diff options
489 files changed, 14871 insertions, 5914 deletions
diff --git a/.gitignore b/.gitignore index 2d5036650..4f342ddca 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,4 @@ libs src/de/danoeh/antennapod/util/flattr/FlattrConfig.java gradle.properties *.keystore +*.p12 diff --git a/.tx/config b/.tx/config index ae7150ecb..5baf71152 100644 --- a/.tx/config +++ b/.tx/config @@ -4,6 +4,7 @@ host = https://www.transifex.com [antennapod.english] source_file = core/src/main/res/values/strings.xml source_lang = en +trans.ast_ES = core/src/main/res/values-b+ast/strings.xml trans.ar = core/src/main/res/values-ar/strings.xml trans.az = core/src/main/res/values-az/strings.xml trans.ca = core/src/main/res/values-ca/strings.xml @@ -14,18 +15,23 @@ trans.de = core/src/main/res/values-de/strings.xml trans.el = core/src/main/res/values-el/strings.xml trans.es = core/src/main/res/values-es/strings.xml trans.es_ES = core/src/main/res/values-es-rES/strings.xml +trans.et = core/src/main/res/values-et/strings.xml +trans.fa = core/src/main/res/values-fa/strings.xml trans.fi = core/src/main/res/values-fi/strings.xml trans.fr = core/src/main/res/values-fr/strings.xml +trans.gl = core/src/main/res/values-gl-rES/strings.xml trans.he_IL = core/src/main/res/values-iw-rIL/strings.xml trans.hi_IN = core/src/main/res/values-hi-rIN/strings.xml trans.hu = core/src/main/res/values-hu/strings.xml trans.id = core/src/main/res/values-id/strings.xml trans.it = core/src/main/res/values-it/strings.xml trans.it_IT = core/src/main/res/values-it-rIT/strings.xml +trans.is = core/src/main/res/values-is-rIS/strings.xml trans.ja = core/src/main/res/values-ja/strings.xml trans.kn_IN = core/src/main/res/values-kn-rIN/strings.xml trans.ko = core/src/main/res/values-ko/strings.xml trans.ko_KR = core/src/main/res/values-ko-rKR/strings.xml +trans.lt = core/src/main/res/values-lt/strings.xml trans.nb = core/src/main/res/values-nb/strings.xml trans.no = core/src/main/res/values-no/strings.xml trans.nl = core/src/main/res/values-nl/strings.xml @@ -38,20 +44,29 @@ trans.ro_RO = core/src/main/res/values-ro-rRO/strings.xml trans.ru = core/src/main/res/values-ru/strings.xml trans.ru-RU = core/src/main/res/values-ru/strings.xml trans.ru_RU = core/src/main/res/values-ru/strings.xml -trans.uk_UA = core/src/main/res/values-uk-rUA/strings.xml -trans.zh_CN = core/src/main/res/values-zh-rCN/strings.xml trans.sv_SE = core/src/main/res/values-sv-rSE/strings.xml +trans.sw_KE = core/src/main/res/values-sw-rKE/strings.xml +trans.te = core/src/main/res/values-te/strings.xml trans.tr = core/src/main/res/values-tr/strings.xml +trans.uk_UA = core/src/main/res/values-uk-rUA/strings.xml trans.vi = core/src/main/res/values-vi/strings.xml trans.vi_VN = core/src/main/res/values-vi-rVN/strings.xml +trans_zh = core/src/main/res/values-zh/strings.xml +trans.zh_CN = core/src/main/res/values-zh-rCN/strings.xml +trans.zh_TW = core/src/main/res/values-zh-rTW/strings.xml +trans.zh_HK = core/src/main/res/values-zh-rHK/strings.xml [antennapod.description] -file_filter = description/<lang>.txt -source_file = description/en.txt +file_filter = app/src/main/play/<lang>/listing/fulldescription +source_file = app/src/main/play/en-US/listing/fulldescription source_lang = en -[antennapod.changelog] -file_filter = changelog/<lang>.md -source_file = CHANGELOG.md +[antennapod.shortdescription] +file_filter = app/src/main/play/<lang>/listing/shortdescription +source_file = app/src/main/play/en-US/listing/shortdescription source_lang = en +[antennapod.changelog] +file_filter = app/src/main/play/<lang>/whatsnew +source_file = app/src/main/play/en-US/whatsnew +source_lang = en diff --git a/CHANGELOG.md b/CHANGELOG.md index 932a53696..ef72e5a45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,20 +1,62 @@ Change Log ========== +Version 1.6.3 +------------- + +* New features: + * Support for Android Auto + * Sort feeds by number of played episodes + * Statistics modes + * Setting: Enqueue downloaded + * Launch screen +* Improvements + * Chapter duration + * Feed title in deletion confirmation +* Fixes: + * Episodes refresh spinner + * Publication date parsing + * Unknown mime type + +Version 1.6.2 +------------- + +* New features: + * Integration of fyyd Podcast Search Engine + * Export subscriptions as HTML + * Rename feeds + * Auto-enable sleep timer + * "has media" filter + * Force gpodder full sync +* Improvements: + * Better support for Atom feeds, e.g. summary tag + * Confirmation dialog on mark all as seen + * Number of downloaded episodes in subscription counter + * Gpodder sync error optional + * Search results + * MRSS support + * Sanitize HTML from Atom feed +* Fixes: + * Reset sleep timer on shake to current waiting time + * Cast dialog image + * Mini player not showing up + * Audio player cover fragment + * Prevent out of memory and casting crashes + Version 1.6.0 ------------- * New features: - * Experimental Chromecast support - * Subscription overview - * Proxy support - * Statistics - * Manual gpodder.net sync + * Experimental Chromecast support + * Subscription overview + * Proxy support + * Statistics + * Manual gpodder.net sync * Fixes: - * Audioplayer controls - * Audio ducking - * Video control fade-out - * External media controls - * Feed parsing + * Audioplayer controls + * Audio ducking + * Video control fade-out + * External media controls + * Feed parsing Version 1.5.0 ------------- diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md index e7b99c56d..dc02f85f4 100644 --- a/ISSUE_TEMPLATE.md +++ b/ISSUE_TEMPLATE.md @@ -7,11 +7,11 @@ In particular, please not only tell us that you want something (*what*), but als --- -**App version:** 1.x (from Google Play/F-Store/Custom build) +**App version:** 1.x (from Google Play/F-Droid/Custom build) **Android version**: 5.x [Please mention if you are using a custom rom!] -**Devide model**: +**Device model**: **Expected behaviour**: @@ -2,8 +2,12 @@ This is the official repository of AntennaPod, the easy-to-use, flexible and open-source podcast manager for Android. -[](https://play.google.com/store/apps/details?id=de.danoeh.antennapod) -[](https://f-droid.org/repository/browse/?fdid=de.danoeh.antennapod) +[<img src="https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png" + alt="Get it on Google Play" + height="90">](https://play.google.com/store/apps/details?id=de.danoeh.antennapod) +[<img src="https://f-droid.org/badge/get-it-on.png" + alt="Get it on F-Droid" + height="90">](https://f-droid.org/app/de.danoeh.antennapod) ## Feedback You can use the [AntennaPod Google Group](https://groups.google.com/forum/#!forum/antennapod) for discussions about the app. @@ -17,7 +21,7 @@ AntennaPod has many users and we don't want them to run into trouble when we add There are APKs available for every branch that is actively worked on. Please note that these might be very unstable versions of the app, which can break your current installation. Install them at your own risk! -Click [here](https://www.dropbox.com/sh/4h2kfa2d2jesnu8/AABF7u5QsOn8Lg8MDie4Z4Ama?dl=0) to get to the nightly builds folder. +Click [here](https://www.dropbox.com/sh/lzfd640z63qz3fr/AACyxTF1ygR9wMlPLPwVGIUKa?dl=0) to get to the nightly builds folder. ## License diff --git a/app/build.gradle b/app/build.gradle index cd3fb7aa1..09763fdbb 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -2,50 +2,13 @@ import org.apache.tools.ant.filters.ReplaceTokens apply plugin: "com.android.application" apply plugin: "me.tatarka.retrolambda" +apply plugin: 'com.github.triplet.play' repositories { maven { url "https://jitpack.io" } mavenCentral() } -dependencies { - compile project(":core") - compile "com.android.support:support-v4:$supportVersion" - compile "com.android.support:appcompat-v7:$supportVersion" - compile "com.android.support:design:$supportVersion" - compile "com.android.support:gridlayout-v7:$supportVersion" - compile "com.android.support:percent:$supportVersion" - compile "com.android.support:recyclerview-v7:$supportVersion" - compile "org.apache.commons:commons-lang3:$commonslangVersion" - compile("org.shredzone.flattr4j:flattr4j-core:$flattr4jVersion") { - exclude group: "org.json", module: "json" - } - compile "commons-io:commons-io:$commonsioVersion" - compile "org.jsoup:jsoup:$jsoupVersion" - compile "com.github.bumptech.glide:glide:$glideVersion" - compile "com.squareup.okhttp:okhttp:$okhttpVersion" - compile "com.squareup.okhttp:okhttp-urlconnection:$okhttpVersion" - compile "com.squareup.okio:okio:$okioVersion" - compile "de.greenrobot:eventbus:$eventbusVersion" - compile "io.reactivex:rxandroid:$rxAndroidVersion" - compile "io.reactivex:rxjava:$rxJavaVersion" - // And ProGuard rules for RxJava! - compile "com.artemzin.rxjava:proguard-rules:$rxJavaRulesVersion" - compile "com.joanzapata.iconify:android-iconify-fontawesome:$iconifyVersion" - compile "com.joanzapata.iconify:android-iconify-material:$iconifyVersion" - compile("com.github.afollestad.material-dialogs:commons:$materialDialogsVersion") { - transitive = true - } - compile "com.yqritc:recyclerview-flexibledivider:$recyclerviewFlexibledividerVersion" - compile("com.githang:viewpagerindicator:2.5@aar") { - exclude module: "support-v4" - } - - compile "com.github.shts:TriangleLabelView:$triangleLabelViewVersion" - - compile "com.github.AntennaPod:AntennaPod-AudioPlayer:$audioPlayerVersion" -} - def getMyVersionName() { def parsedManifestXml = (new XmlSlurper()) .parse("${projectDir}/src/main/AndroidManifest.xml") @@ -67,6 +30,7 @@ android { defaultConfig { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion + multiDexEnabled true versionCode getMyVersionCode() versionName "${getMyVersionName()}" testApplicationId "de.test.antennapod" @@ -137,6 +101,78 @@ android { aaptOptions { additionalParameters "--no-version-vectors" } + + productFlavors { + free { + } + play { + } + } + + dexOptions { + jumboMode true + } +} + +configurations { + freeDebugCompile + freeReleaseCompile + playDebugCompile + playReleaseCompile +} + +dependencies { + freeDebugCompile project(path: ":core", configuration: "freeDebug") + freeReleaseCompile project(path: ":core", configuration: "freeRelease") + // free build hack: skip some dependencies + if (!doFreeBuild()) { + playDebugCompile project(path: ":core", configuration: "playDebug") + playReleaseCompile project(path: ":core", configuration: "playRelease") + } else { + System.out.println("app: free build hack, skipping some dependencies") + } + compile 'com.android.support:multidex:1.0.1' + compile "com.android.support:support-v4:$supportVersion" + compile "com.android.support:appcompat-v7:$supportVersion" + compile "com.android.support:design:$supportVersion" + compile "com.android.support:gridlayout-v7:$supportVersion" + compile "com.android.support:percent:$supportVersion" + compile "com.android.support:recyclerview-v7:$supportVersion" + compile "org.apache.commons:commons-lang3:$commonslangVersion" + compile("org.shredzone.flattr4j:flattr4j-core:$flattr4jVersion") { + exclude group: "org.json", module: "json" + } + compile "commons-io:commons-io:$commonsioVersion" + compile "org.jsoup:jsoup:$jsoupVersion" + compile "com.github.bumptech.glide:glide:$glideVersion" + compile "com.squareup.okhttp3:okhttp:$okhttpVersion" + compile "com.squareup.okhttp3:okhttp-urlconnection:$okhttpVersion" + compile "com.squareup.okio:okio:$okioVersion" + compile "de.greenrobot:eventbus:$eventbusVersion" + compile "io.reactivex:rxandroid:$rxAndroidVersion" + compile "io.reactivex:rxjava:$rxJavaVersion" + // And ProGuard rules for RxJava! + compile "com.artemzin.rxjava:proguard-rules:$rxJavaRulesVersion" + compile "com.joanzapata.iconify:android-iconify-fontawesome:$iconifyVersion" + compile "com.joanzapata.iconify:android-iconify-material:$iconifyVersion" + compile("com.afollestad.material-dialogs:commons:$materialDialogsVersion") { + transitive = true + } + compile "com.yqritc:recyclerview-flexibledivider:$recyclerviewFlexibledividerVersion" + compile("com.githang:viewpagerindicator:2.5@aar") { + exclude module: "support-v4" + } + + compile "com.github.shts:TriangleLabelView:$triangleLabelViewVersion" + + compile "com.github.AntennaPod:AntennaPod-AudioPlayer:$audioPlayerVersion" + + compile 'com.github.mfietz:fyydlin:v0.1' +} + +play { + serviceAccountEmail = '522080222319-compute@developer.gserviceaccount.com' + pk12File = file('../serviceaccount-c3d7d0f61387.p12') } // about.html is templatized so that we can automatically insert @@ -145,12 +181,13 @@ task filterAbout { inputs.files files(["src/main/templates/about.html", "src/main/AndroidManifest.xml"]) outputs.file "src/main/assets/about.html" -} << { +} doLast { copy { from "src/main/templates/about.html" into "src/main/assets" filter(ReplaceTokens, tokens: [versionname: android.defaultConfig.versionName, - commit : "git rev-parse --short HEAD".execute().text]) + commit : "git rev-parse --short HEAD".execute().text, + year : new Date().format('yyyy')]) } } @@ -164,3 +201,11 @@ task copyTextFiles(type: Copy) { } preBuild.dependsOn filterAbout, copyTextFiles + +allprojects { + gradle.projectsEvaluated { + tasks.withType(JavaCompile) { + options.compilerArgs << "-Xlint" << "-Xlint:-deprecation" << "-Xlint:-serial" + } + } +} diff --git a/app/proguard.cfg b/app/proguard.cfg index a25664490..769079bd8 100644 --- a/app/proguard.cfg +++ b/app/proguard.cfg @@ -53,7 +53,7 @@ public *; } --dontwarn com.squareup.okhttp.** +-dontwarn okhttp3.** -dontwarn okio.** # for RxJava: @@ -66,8 +66,10 @@ -keep interface android.support.v4.** { *; } -keep class !android.support.v7.internal.view.menu.**,android.support.v7.** {*;} -keep interface android.support.v7.** { *; } +-keep class com.google.android.wearable.** { *; } -dontwarn android.support.v4.** -dontwarn android.support.v7.** +-dontwarn com.google.android.wearable.** -keepattributes *Annotation* @@ -107,4 +109,19 @@ -dontwarn com.viewpagerindicator.LinePageIndicator # for some reason ProGuard removes this file. Why? Unsure. --keep class de.danoeh.antennapod.core.cast.SwitchableMediaRouteActionProvider { *; }
\ No newline at end of file +-keep class de.danoeh.antennapod.core.cast.SwitchableMediaRouteActionProvider { *; } + +# Retrofit 2.0 +-dontwarn retrofit2.** +-keep class retrofit2.** { *; } +-keepattributes Signature +-keepattributes Exceptions + +-keepclasseswithmembers class * { + @retrofit2.http.* <methods>; +} + +# Moshi +-keep class com.squareup.moshi.** { *; } +-keep interface com.squareup.moshi.** { *; } +-keep public class retrofit2.adapter.rxjava.RxJavaCallAdapterFactory { *; } diff --git a/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java b/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java index 6f8dbcb1a..9ac92c2f9 100644 --- a/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java +++ b/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java @@ -1,6 +1,8 @@ package de.test.antennapod.service.playback; import android.content.Context; +import android.support.annotation.NonNull; +import android.support.annotation.StringRes; import android.test.InstrumentationTestCase; import junit.framework.AssertionFailedError; @@ -20,6 +22,7 @@ import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.FeedPreferences; +import de.danoeh.antennapod.core.feed.MediaType; import de.danoeh.antennapod.core.service.playback.PlaybackServiceMediaPlayer; import de.danoeh.antennapod.core.service.playback.LocalPSMP; import de.danoeh.antennapod.core.service.playback.PlayerStatus; @@ -112,7 +115,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { public void testInit() { final Context c = getInstrumentation().getTargetContext(); - PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, defaultCallback); + PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, new DefaultPSMPCallback()); psmp.shutdown(); } @@ -138,7 +141,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { public void testPlayMediaObjectStreamNoStartNoPrepare() throws InterruptedException { final Context c = getInstrumentation().getTargetContext(); final CountDownLatch countDownLatch = new CountDownLatch(2); - PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() { + PlaybackServiceMediaPlayer.PSMPCallback callback = new DefaultPSMPCallback() { @Override public void statusChanged(LocalPSMP.PSMPInfo newInfo) { try { @@ -159,47 +162,6 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { assertionError = e; } } - - @Override - public void shouldStop() { - - } - - @Override - public void playbackSpeedChanged(float s) { - - } - - @Override - public void setSpeedAbilityChanged() { - - } - - @Override - public void onMediaChanged(boolean reloadUI) { - - } - - @Override - public void onBufferingUpdate(int percent) { - - } - - @Override - public boolean onMediaPlayerInfo(int code, int resourceId) { - return false; - } - - @Override - public boolean onMediaPlayerError(Object inObj, int what, int extra) { - return false; - } - - @Override - public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) { - return false; - } - }; PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback); Playable p = writeTestPlayable(PLAYABLE_FILE_URL, null); @@ -217,7 +179,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { public void testPlayMediaObjectStreamStartNoPrepare() throws InterruptedException { final Context c = getInstrumentation().getTargetContext(); final CountDownLatch countDownLatch = new CountDownLatch(2); - PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() { + PlaybackServiceMediaPlayer.PSMPCallback callback = new DefaultPSMPCallback() { @Override public void statusChanged(LocalPSMP.PSMPInfo newInfo) { try { @@ -238,46 +200,6 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { assertionError = e; } } - - @Override - public void shouldStop() { - - } - - @Override - public void playbackSpeedChanged(float s) { - - } - - @Override - public void setSpeedAbilityChanged() { - - } - - @Override - public void onMediaChanged(boolean reloadUI) { - - } - - @Override - public void onBufferingUpdate(int percent) { - - } - - @Override - public boolean onMediaPlayerInfo(int code, int resourceId) { - return false; - } - - @Override - public boolean onMediaPlayerError(Object inObj, int what, int extra) { - return false; - } - - @Override - public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) { - return false; - } }; PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback); Playable p = writeTestPlayable(PLAYABLE_FILE_URL, null); @@ -296,7 +218,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { public void testPlayMediaObjectStreamNoStartPrepare() throws InterruptedException { final Context c = getInstrumentation().getTargetContext(); final CountDownLatch countDownLatch = new CountDownLatch(4); - PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() { + PlaybackServiceMediaPlayer.PSMPCallback callback = new DefaultPSMPCallback() { @Override public void statusChanged(LocalPSMP.PSMPInfo newInfo) { try { @@ -320,46 +242,6 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { assertionError = e; } } - - @Override - public void shouldStop() { - - } - - @Override - public void playbackSpeedChanged(float s) { - - } - - @Override - public void setSpeedAbilityChanged() { - - } - - @Override - public void onMediaChanged(boolean reloadUI) { - - } - - @Override - public void onBufferingUpdate(int percent) { - - } - - @Override - public boolean onMediaPlayerInfo(int code, int resourceId) { - return false; - } - - @Override - public boolean onMediaPlayerError(Object inObj, int what, int extra) { - return false; - } - - @Override - public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) { - return false; - } }; PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback); Playable p = writeTestPlayable(PLAYABLE_FILE_URL, null); @@ -376,7 +258,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { public void testPlayMediaObjectStreamStartPrepare() throws InterruptedException { final Context c = getInstrumentation().getTargetContext(); final CountDownLatch countDownLatch = new CountDownLatch(5); - PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() { + PlaybackServiceMediaPlayer.PSMPCallback callback = new DefaultPSMPCallback() { @Override public void statusChanged(LocalPSMP.PSMPInfo newInfo) { try { @@ -403,47 +285,6 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { assertionError = e; } } - - @Override - public void shouldStop() { - - } - - @Override - public void playbackSpeedChanged(float s) { - - } - - @Override - public void setSpeedAbilityChanged() { - - } - - @Override - public void onMediaChanged(boolean reloadUI) { - - } - - @Override - public void onBufferingUpdate(int percent) { - - } - - @Override - public boolean onMediaPlayerInfo(int code, int resourceId) { - return false; - } - - @Override - public boolean onMediaPlayerError(Object inObj, int what, int extra) { - return false; - } - - @Override - public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) { - return false; - } - }; PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback); Playable p = writeTestPlayable(PLAYABLE_FILE_URL, null); @@ -459,7 +300,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { public void testPlayMediaObjectLocalNoStartNoPrepare() throws InterruptedException { final Context c = getInstrumentation().getTargetContext(); final CountDownLatch countDownLatch = new CountDownLatch(2); - PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() { + PlaybackServiceMediaPlayer.PSMPCallback callback = new DefaultPSMPCallback() { @Override public void statusChanged(LocalPSMP.PSMPInfo newInfo) { try { @@ -480,47 +321,6 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { assertionError = e; } } - - @Override - public void shouldStop() { - - } - - @Override - public void playbackSpeedChanged(float s) { - - } - - @Override - public void setSpeedAbilityChanged() { - - } - - @Override - public void onMediaChanged(boolean reloadUI) { - - } - - @Override - public void onBufferingUpdate(int percent) { - - } - - @Override - public boolean onMediaPlayerInfo(int code, int resourceId) { - return false; - } - - @Override - public boolean onMediaPlayerError(Object inObj, int what, int extra) { - return false; - } - - @Override - public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) { - return false; - } - }; PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback); Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL); @@ -537,7 +337,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { public void testPlayMediaObjectLocalStartNoPrepare() throws InterruptedException { final Context c = getInstrumentation().getTargetContext(); final CountDownLatch countDownLatch = new CountDownLatch(2); - PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() { + PlaybackServiceMediaPlayer.PSMPCallback callback = new DefaultPSMPCallback() { @Override public void statusChanged(LocalPSMP.PSMPInfo newInfo) { try { @@ -558,46 +358,6 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { assertionError = e; } } - - @Override - public void shouldStop() { - - } - - @Override - public void playbackSpeedChanged(float s) { - - } - - @Override - public void setSpeedAbilityChanged() { - - } - - @Override - public void onMediaChanged(boolean reloadUI) { - - } - - @Override - public void onBufferingUpdate(int percent) { - - } - - @Override - public boolean onMediaPlayerInfo(int code, int resourceId) { - return false; - } - - @Override - public boolean onMediaPlayerError(Object inObj, int what, int extra) { - return false; - } - - @Override - public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) { - return false; - } }; PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback); Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL); @@ -614,7 +374,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { public void testPlayMediaObjectLocalNoStartPrepare() throws InterruptedException { final Context c = getInstrumentation().getTargetContext(); final CountDownLatch countDownLatch = new CountDownLatch(4); - PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() { + PlaybackServiceMediaPlayer.PSMPCallback callback = new DefaultPSMPCallback() { @Override public void statusChanged(LocalPSMP.PSMPInfo newInfo) { try { @@ -638,46 +398,6 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { assertionError = e; } } - - @Override - public void shouldStop() { - - } - - @Override - public void playbackSpeedChanged(float s) { - - } - - @Override - public void setSpeedAbilityChanged() { - - } - - @Override - public void onMediaChanged(boolean reloadUI) { - - } - - @Override - public void onBufferingUpdate(int percent) { - - } - - @Override - public boolean onMediaPlayerInfo(int code, int resourceId) { - return false; - } - - @Override - public boolean onMediaPlayerError(Object inObj, int what, int extra) { - return false; - } - - @Override - public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) { - return false; - } }; PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback); Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL); @@ -693,7 +413,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { public void testPlayMediaObjectLocalStartPrepare() throws InterruptedException { final Context c = getInstrumentation().getTargetContext(); final CountDownLatch countDownLatch = new CountDownLatch(5); - PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() { + PlaybackServiceMediaPlayer.PSMPCallback callback = new DefaultPSMPCallback() { @Override public void statusChanged(LocalPSMP.PSMPInfo newInfo) { try { @@ -721,46 +441,6 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { countDownLatch.countDown(); } } - - @Override - public void shouldStop() { - - } - - @Override - public void playbackSpeedChanged(float s) { - - } - - @Override - public void setSpeedAbilityChanged() { - - } - - @Override - public void onMediaChanged(boolean reloadUI) { - - } - - @Override - public void onBufferingUpdate(int percent) { - - } - - @Override - public boolean onMediaPlayerInfo(int code, int resourceId) { - return false; - } - - @Override - public boolean onMediaPlayerError(Object inObj, int what, int extra) { - return false; - } - - @Override - public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) { - return false; - } }; PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback); Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL); @@ -773,58 +453,12 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { psmp.shutdown(); } - - private final PlaybackServiceMediaPlayer.PSMPCallback defaultCallback = new PlaybackServiceMediaPlayer.PSMPCallback() { - @Override - public void statusChanged(LocalPSMP.PSMPInfo newInfo) { - checkPSMPInfo(newInfo); - } - - @Override - public void shouldStop() { - - } - - @Override - public void playbackSpeedChanged(float s) { - - } - - @Override - public void setSpeedAbilityChanged() { - - } - - @Override - public void onMediaChanged(boolean reloadUI) { - - } - - @Override - public void onBufferingUpdate(int percent) { - - } - - @Override - public boolean onMediaPlayerInfo(int code, int resourceId) { return false; } - - @Override - public boolean onMediaPlayerError(Object inObj, int what, int extra) { - return false; - } - - @Override - public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) { - return false; - } - }; - private void pauseTestSkeleton(final PlayerStatus initialState, final boolean stream, final boolean abandonAudioFocus, final boolean reinit, long timeoutSeconds) throws InterruptedException { final Context c = getInstrumentation().getTargetContext(); final int latchCount = (stream && reinit) ? 2 : 1; final CountDownLatch countDownLatch = new CountDownLatch(latchCount); - PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() { + PlaybackServiceMediaPlayer.PSMPCallback callback = new DefaultPSMPCallback() { @Override public void statusChanged(LocalPSMP.PSMPInfo newInfo) { checkPSMPInfo(newInfo); @@ -864,41 +498,11 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { } @Override - public void playbackSpeedChanged(float s) { - - } - - @Override - public void setSpeedAbilityChanged() { - - } - - @Override - public void onMediaChanged(boolean reloadUI) { - - } - - @Override - public void onBufferingUpdate(int percent) { - - } - - @Override - public boolean onMediaPlayerInfo(int code, int resourceId) { - return false; - } - - @Override public boolean onMediaPlayerError(Object inObj, int what, int extra) { if (assertionError == null) assertionError = new AssertionFailedError("Unexpected call to onMediaPlayerError"); return false; } - - @Override - public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) { - return false; - } }; PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback); Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL); @@ -955,7 +559,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { (initialState == PlayerStatus.PREPARED) ? 1 : 0; final CountDownLatch countDownLatch = new CountDownLatch(latchCount); - PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() { + PlaybackServiceMediaPlayer.PSMPCallback callback = new DefaultPSMPCallback() { @Override public void statusChanged(LocalPSMP.PSMPInfo newInfo) { checkPSMPInfo(newInfo); @@ -974,47 +578,12 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { } @Override - public void shouldStop() { - - } - - @Override - public void playbackSpeedChanged(float s) { - - } - - @Override - public void setSpeedAbilityChanged() { - - } - - @Override - public void onMediaChanged(boolean reloadUI) { - - } - - @Override - public void onBufferingUpdate(int percent) { - - } - - @Override - public boolean onMediaPlayerInfo(int code, int resourceId) { - return false; - } - - @Override public boolean onMediaPlayerError(Object inObj, int what, int extra) { if (assertionError == null) { assertionError = new AssertionFailedError("Unexpected call of onMediaPlayerError"); } return false; } - - @Override - public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) { - return false; - } }; PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback); if (initialState == PlayerStatus.PREPARED || initialState == PlayerStatus.PLAYING || initialState == PlayerStatus.PAUSED) { @@ -1048,7 +617,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { final Context c = getInstrumentation().getTargetContext(); final int latchCount = 1; final CountDownLatch countDownLatch = new CountDownLatch(latchCount); - PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() { + PlaybackServiceMediaPlayer.PSMPCallback callback = new DefaultPSMPCallback() { @Override public void statusChanged(LocalPSMP.PSMPInfo newInfo) { checkPSMPInfo(newInfo); @@ -1062,37 +631,6 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { countDownLatch.countDown(); } } - - } - - @Override - public void shouldStop() { - - } - - @Override - public void playbackSpeedChanged(float s) { - - } - - @Override - public void setSpeedAbilityChanged() { - - } - - @Override - public void onMediaChanged(boolean reloadUI) { - - } - - @Override - public void onBufferingUpdate(int percent) { - - } - - @Override - public boolean onMediaPlayerInfo(int code, int resourceId) { - return false; } @Override @@ -1101,11 +639,6 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { assertionError = new AssertionFailedError("Unexpected call to onMediaPlayerError"); return false; } - - @Override - public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) { - return false; - } }; PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback); Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL); @@ -1153,7 +686,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { final Context c = getInstrumentation().getTargetContext(); final int latchCount = 2; final CountDownLatch countDownLatch = new CountDownLatch(latchCount); - PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() { + PlaybackServiceMediaPlayer.PSMPCallback callback = new DefaultPSMPCallback() { @Override public void statusChanged(LocalPSMP.PSMPInfo newInfo) { checkPSMPInfo(newInfo); @@ -1170,46 +703,11 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { } @Override - public void shouldStop() { - - } - - @Override - public void playbackSpeedChanged(float s) { - - } - - @Override - public void setSpeedAbilityChanged() { - - } - - @Override - public void onMediaChanged(boolean reloadUI) { - - } - - @Override - public void onBufferingUpdate(int percent) { - - } - - @Override - public boolean onMediaPlayerInfo(int code, int resourceId) { - return false; - } - - @Override public boolean onMediaPlayerError(Object inObj, int what, int extra) { if (assertionError == null) assertionError = new AssertionFailedError("Unexpected call to onMediaPlayerError"); return false; } - - @Override - public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) { - return false; - } }; PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback); Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL); @@ -1248,4 +746,71 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { super("Unexpected state change: " + status); } } + + private class DefaultPSMPCallback implements PlaybackServiceMediaPlayer.PSMPCallback { + @Override + public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) { + + } + + @Override + public void shouldStop() { + + } + + @Override + public void playbackSpeedChanged(float s) { + + } + + @Override + public void setSpeedAbilityChanged() { + + } + + @Override + public void onBufferingUpdate(int percent) { + + } + + @Override + public void onMediaChanged(boolean reloadUI) { + + } + + @Override + public boolean onMediaPlayerInfo(int code, @StringRes int resourceId) { + return false; + } + + @Override + public boolean onMediaPlayerError(Object inObj, int what, int extra) { + return false; + } + + @Override + public void onPostPlayback(@NonNull Playable media, boolean ended, boolean skipped, boolean playingNext) { + + } + + @Override + public void onPlaybackStart(@NonNull Playable playable, int position) { + + } + + @Override + public void onPlaybackPause(Playable playable, int position) { + + } + + @Override + public Playable getNextInQueue(Playable currentMedia) { + return null; + } + + @Override + public void onPlaybackEnded(MediaType mediaType, boolean stopPlaying) { + + } + } } diff --git a/app/src/androidTest/java/de/test/antennapod/storage/DBReaderTest.java b/app/src/androidTest/java/de/test/antennapod/storage/DBReaderTest.java index 9386e3bd6..0c5cf10cb 100644 --- a/app/src/androidTest/java/de/test/antennapod/storage/DBReaderTest.java +++ b/app/src/androidTest/java/de/test/antennapod/storage/DBReaderTest.java @@ -218,58 +218,43 @@ public class DBReaderTest extends InstrumentationTestCase { } } - private List<FeedItem> saveUnreadItems(int numItems) { - if (numItems <= 0) { - throw new IllegalArgumentException("numItems<=0"); - } + private List<FeedItem> saveNewItems(int numItems) { List<Feed> feeds = saveFeedlist(numItems, numItems, true); List<FeedItem> items = new ArrayList<>(); for (Feed f : feeds) { items.addAll(f.getItems()); } - List<FeedItem> unread = new ArrayList<>(); + List<FeedItem> newItems = new ArrayList<>(); Random random = new Random(); - while (unread.size() < numItems) { + while (newItems.size() < numItems) { int i = random.nextInt(numItems); - if (!unread.contains(items.get(i))) { + if (!newItems.contains(items.get(i))) { FeedItem item = items.get(i); - item.setPlayed(false); - unread.add(item); + item.setNew(); + newItems.add(item); } } PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - adapter.setFeedItemlist(unread); + adapter.setFeedItemlist(newItems); adapter.close(); - return unread; - } - - public void testGetUnreadItemsList() { - final int numItems = 10; - - List<FeedItem> unread = saveUnreadItems(numItems); - List<FeedItem> unreadSaved = DBReader.getUnreadItemsList(); - assertNotNull(unreadSaved); - assertTrue(unread.size() == unreadSaved.size()); - for (FeedItem item : unreadSaved) { - assertFalse(item.isPlayed()); - } + return newItems; } public void testGetNewItemIds() { final int numItems = 10; - List<FeedItem> unread = saveUnreadItems(numItems); - long[] unreadIds = new long[unread.size()]; - for (int i = 0; i < unread.size(); i++) { - unreadIds[i] = unread.get(i).getId(); + List<FeedItem> newItems = saveNewItems(numItems); + long[] unreadIds = new long[newItems.size()]; + for (int i = 0; i < newItems.size(); i++) { + unreadIds[i] = newItems.get(i).getId(); } - List<FeedItem> unreadSaved = DBReader.getUnreadItemsList(); - assertNotNull(unreadSaved); - assertTrue(unread.size() == unreadSaved.size()); - for(int i=0; i < unreadSaved.size(); i++) { - long savedId = unreadSaved.get(i).getId(); + List<FeedItem> newItemsSaved = DBReader.getNewItemsList(); + assertNotNull(newItemsSaved); + assertTrue(newItems.size() == newItemsSaved.size()); + for(int i=0; i < newItemsSaved.size(); i++) { + long savedId = newItemsSaved.get(i).getId(); boolean found = false; for (long id : unreadIds) { if (id == savedId) { diff --git a/app/src/androidTest/java/de/test/antennapod/storage/DBTestUtils.java b/app/src/androidTest/java/de/test/antennapod/storage/DBTestUtils.java index da164b78e..30f465784 100644 --- a/app/src/androidTest/java/de/test/antennapod/storage/DBTestUtils.java +++ b/app/src/androidTest/java/de/test/antennapod/storage/DBTestUtils.java @@ -45,7 +45,7 @@ public class DBTestUtils { PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); for (int i = 0; i < numFeeds; i++) { - Feed f = new Feed(0, null, "feed " + i, "link" + i, "descr", null, null, + Feed f = new Feed(0, null, "feed " + i, null, "link" + i, "descr", null, null, null, null, "id" + i, null, null, "url" + i, false, new FlattrStatus(), false, null, null, false); f.setItems(new ArrayList<>()); for (int j = 0; j < numItems; j++) { diff --git a/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java b/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java index 9a0e11816..bd9057b47 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java @@ -138,7 +138,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActiv ListView list = (ListView) solo.getView(R.id.nav_list); for (int i = 0; i < uiTestUtils.hostedFeeds.size(); i++) { Feed f = uiTestUtils.hostedFeeds.get(i); - solo.clickOnScreen(50, 50); // open nav drawer + openNavDrawer(); solo.scrollListToLine(list, i); solo.clickOnText(f.getTitle()); solo.waitForView(android.R.id.list); diff --git a/app/src/androidTest/java/de/test/antennapod/ui/PlaybackSonicTest.java b/app/src/androidTest/java/de/test/antennapod/ui/PlaybackSonicTest.java index d4994fb1a..bfbeedd83 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/PlaybackSonicTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/PlaybackSonicTest.java @@ -245,10 +245,10 @@ public class PlaybackSonicTest extends ActivityInstrumentationTestCase2<MainActi }, Timeout.getSmallTimeout()); assertTrue(startedPlaying); - boolean stoppedPlaying = solo.waitForCondition(() -> { - return uiTestUtils.getCurrentMedia(getActivity()) == null - || uiTestUtils.getCurrentMedia(getActivity()).getId() != mediaId; - }, Timeout.getLargeTimeout()); + boolean stoppedPlaying = solo.waitForCondition(() -> + uiTestUtils.getCurrentMedia(getActivity()) == null + || uiTestUtils.getCurrentMedia(getActivity()).getId() != mediaId + , Timeout.getLargeTimeout()); assertTrue(stoppedPlaying); startLocalPlayback(); diff --git a/app/src/androidTest/java/de/test/antennapod/ui/PlaybackTest.java b/app/src/androidTest/java/de/test/antennapod/ui/PlaybackTest.java index 5ce495f9a..661c2200b 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/PlaybackTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/PlaybackTest.java @@ -236,10 +236,9 @@ public class PlaybackTest extends ActivityInstrumentationTestCase2<MainActivity> }, Timeout.getSmallTimeout()); assertTrue(startedPlaying); - boolean stoppedPlaying = solo.waitForCondition(() -> { - return uiTestUtils.getCurrentMedia(getActivity()) == null - || uiTestUtils.getCurrentMedia(getActivity()).getId() != mediaId; - }, Timeout.getLargeTimeout()); + boolean stoppedPlaying = solo.waitForCondition(() -> + uiTestUtils.getCurrentMedia(getActivity()) == null + || uiTestUtils.getCurrentMedia(getActivity()).getId() != mediaId, Timeout.getLargeTimeout()); assertTrue(stoppedPlaying); startLocalPlayback(); diff --git a/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java b/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java index 040f4150b..91928f01e 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java @@ -3,10 +3,12 @@ package de.test.antennapod.ui; import android.content.Context; import android.content.res.Resources; import android.test.ActivityInstrumentationTestCase2; +import android.util.Log; import com.robotium.solo.Solo; import com.robotium.solo.Timeout; +import java.util.Arrays; import java.util.concurrent.TimeUnit; import de.danoeh.antennapod.R; @@ -362,4 +364,48 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference Timeout.getLargeTimeout())); } + + public void testRewindChange() { + int seconds = UserPreferences.getRewindSecs(); + int deltas[] = res.getIntArray(R.array.seek_delta_values); + + solo.clickOnText(solo.getString(R.string.pref_rewind)); + solo.waitForDialogToOpen(); + + int currentIndex = Arrays.binarySearch(deltas, seconds); + assertTrue(currentIndex >= 0 && currentIndex < deltas.length); // found? + + // Find next value (wrapping around to next) + int newIndex = (currentIndex + 1) % deltas.length; + + solo.clickOnText(String.valueOf(deltas[newIndex]) + " seconds"); + solo.clickOnButton("Confirm"); + + solo.waitForDialogToClose(); + assertTrue(solo.waitForCondition(() -> UserPreferences.getRewindSecs() == deltas[newIndex], + Timeout.getLargeTimeout())); + } + + public void testFastForwardChange() { + for (int i = 2; i > 0; i--) { // repeat twice to catch any error where fastforward is tracking rewind + int seconds = UserPreferences.getFastForwardSecs(); + int deltas[] = res.getIntArray(R.array.seek_delta_values); + + solo.clickOnText(solo.getString(R.string.pref_fast_forward)); + solo.waitForDialogToOpen(); + + int currentIndex = Arrays.binarySearch(deltas, seconds); + assertTrue(currentIndex >= 0 && currentIndex < deltas.length); // found? + + // Find next value (wrapping around to next) + int newIndex = (currentIndex + 1) % deltas.length; + + solo.clickOnText(String.valueOf(deltas[newIndex]) + " seconds"); + solo.clickOnButton("Confirm"); + + solo.waitForDialogToClose(); + assertTrue(solo.waitForCondition(() -> UserPreferences.getFastForwardSecs() == deltas[newIndex], + Timeout.getLargeTimeout())); + } + } } diff --git a/app/src/androidTest/java/de/test/antennapod/util/FilenameGeneratorTest.java b/app/src/androidTest/java/de/test/antennapod/util/FilenameGeneratorTest.java index 6d24fa526..13e8b9582 100644 --- a/app/src/androidTest/java/de/test/antennapod/util/FilenameGeneratorTest.java +++ b/app/src/androidTest/java/de/test/antennapod/util/FilenameGeneratorTest.java @@ -34,6 +34,16 @@ public class FilenameGeneratorTest extends AndroidTestCase { createFiles(result); } + public void testFeedTitleContainsApostrophe() { + String result = FileNameGenerator.generateFileName("Feed's Title ..."); + assertEquals("Feeds Title", result); + } + + public void testFeedTitleContainsDash() { + String result = FileNameGenerator.generateFileName("Left - Right"); + assertEquals("Left Right", result); + } + /** * Tests if files can be created. * diff --git a/app/src/free/java/de/danoeh/antennapod/activity/CastEnabledActivity.java b/app/src/free/java/de/danoeh/antennapod/activity/CastEnabledActivity.java new file mode 100644 index 000000000..79d7e02f2 --- /dev/null +++ b/app/src/free/java/de/danoeh/antennapod/activity/CastEnabledActivity.java @@ -0,0 +1,218 @@ +package de.danoeh.antennapod.activity; + +import android.support.v7.app.AppCompatActivity; + +/** + * Activity that allows for showing the MediaRouter button whenever there's a cast device in the + * network. + */ +public abstract class CastEnabledActivity extends AppCompatActivity { +// implements SharedPreferences.OnSharedPreferenceChangeListener { + public static final String TAG = "CastEnabledActivity"; + +// protected CastManager castManager; +// protected SwitchableMediaRouteActionProvider mediaRouteActionProvider; +// private final CastButtonVisibilityManager castButtonVisibilityManager = new CastButtonVisibilityManager(); +// +// @Override +// protected void onCreate(Bundle savedInstanceState) { +// super.onCreate(savedInstanceState); +// +// PreferenceManager.getDefaultSharedPreferences(getApplicationContext()). +// registerOnSharedPreferenceChangeListener(this); +// +// castManager = CastManager.getInstance(); +// castManager.addCastConsumer(castConsumer); +// castButtonVisibilityManager.setPrefEnabled(UserPreferences.isCastEnabled()); +// onCastConnectionChanged(castManager.isConnected()); +// } +// +// @Override +// protected void onDestroy() { +// PreferenceManager.getDefaultSharedPreferences(getApplicationContext()) +// .unregisterOnSharedPreferenceChangeListener(this); +// castManager.removeCastConsumer(castConsumer); +// super.onDestroy(); +// } +// +// @Override +// @CallSuper +// public boolean onCreateOptionsMenu(Menu menu) { +// super.onCreateOptionsMenu(menu); +// getMenuInflater().inflate(R.menu.cast_enabled, menu); +// castButtonVisibilityManager.setMenu(menu); +// return true; +// } +// +// @Override +// @CallSuper +// public boolean onPrepareOptionsMenu(Menu menu) { +// super.onPrepareOptionsMenu(menu); +// mediaRouteActionProvider = castManager +// .addMediaRouterButton(menu.findItem(R.id.media_route_menu_item)); +// mediaRouteActionProvider.setEnabled(castButtonVisibilityManager.shouldEnable()); +// return true; +// } +// +// @Override +// protected void onResume() { +// super.onResume(); +// castButtonVisibilityManager.setResumed(true); +// } +// +// @Override +// protected void onPause() { +// super.onPause(); +// castButtonVisibilityManager.setResumed(false); +// } +// +// @Override +// public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { +// if (UserPreferences.PREF_CAST_ENABLED.equals(key)) { +// boolean newValue = UserPreferences.isCastEnabled(); +// Log.d(TAG, "onSharedPreferenceChanged(), isCastEnabled set to " + newValue); +// castButtonVisibilityManager.setPrefEnabled(newValue); +// // PlaybackService has its own listener, so if it's active we don't have to take action here. +// if (!newValue && !PlaybackService.isRunning) { +// CastManager.getInstance().disconnect(); +// } +// } +// } +// +// CastConsumer castConsumer = new DefaultCastConsumer() { +// @Override +// public void onApplicationConnected(ApplicationMetadata appMetadata, String sessionId, boolean wasLaunched) { +// onCastConnectionChanged(true); +// } +// +// @Override +// public void onDisconnected() { +// onCastConnectionChanged(false); +// } +// }; +// +// private void onCastConnectionChanged(boolean connected) { +// if (connected) { +// castButtonVisibilityManager.onConnected(); +// setVolumeControlStream(AudioManager.USE_DEFAULT_STREAM_TYPE); +// } else { +// castButtonVisibilityManager.onDisconnected(); +// setVolumeControlStream(AudioManager.STREAM_MUSIC); +// } +// } +// +// /** +// * Should be called by any activity or fragment for which the cast button should be shown. +// * +// * @param showAsAction refer to {@link MenuItem#setShowAsAction(int)} +// */ + public final void requestCastButton(int showAsAction) { + // no-op + } + +// private class CastButtonVisibilityManager { +// private volatile boolean prefEnabled = false; +// private volatile boolean viewRequested = false; +// private volatile boolean resumed = false; +// private volatile boolean connected = false; +// private volatile int showAsAction = MenuItem.SHOW_AS_ACTION_IF_ROOM; +// private Menu menu; +// +// public synchronized void setPrefEnabled(boolean newValue) { +// if (prefEnabled != newValue && resumed && (viewRequested || connected)) { +// if (newValue) { +// castManager.incrementUiCounter(); +// } else { +// castManager.decrementUiCounter(); +// } +// } +// prefEnabled = newValue; +// if (mediaRouteActionProvider != null) { +// mediaRouteActionProvider.setEnabled(prefEnabled && (viewRequested || connected)); +// } +// } +// +// public synchronized void setResumed(boolean newValue) { +// if (resumed == newValue) { +// Log.e(TAG, "resumed should never change to the same value"); +// return; +// } +// resumed = newValue; +// if (prefEnabled && (viewRequested || connected)) { +// if (resumed) { +// castManager.incrementUiCounter(); +// } else { +// castManager.decrementUiCounter(); +// } +// } +// } +// +// public synchronized void setViewRequested(boolean newValue) { +// if (viewRequested != newValue && resumed && prefEnabled && !connected) { +// if (newValue) { +// castManager.incrementUiCounter(); +// } else { +// castManager.decrementUiCounter(); +// } +// } +// viewRequested = newValue; +// if (mediaRouteActionProvider != null) { +// mediaRouteActionProvider.setEnabled(prefEnabled && (viewRequested || connected)); +// } +// } +// +// public synchronized void setConnected(boolean newValue) { +// if (connected != newValue && resumed && prefEnabled && !prefEnabled) { +// if (newValue) { +// castManager.incrementUiCounter(); +// } else { +// castManager.decrementUiCounter(); +// } +// } +// connected = newValue; +// if (mediaRouteActionProvider != null) { +// mediaRouteActionProvider.setEnabled(prefEnabled && (viewRequested || connected)); +// } +// } +// +// public synchronized boolean shouldEnable() { +// return prefEnabled && viewRequested; +// } +// +// public void setMenu(Menu menu) { +// setViewRequested(false); +// showAsAction = MenuItem.SHOW_AS_ACTION_IF_ROOM; +// this.menu = menu; +// setShowAsAction(); +// } +// +// public void requestCastButton(int showAsAction) { +// setViewRequested(true); +// this.showAsAction = showAsAction; +// setShowAsAction(); +// } +// +// public void onConnected() { +// setConnected(true); +// setShowAsAction(); +// } +// +// public void onDisconnected() { +// setConnected(false); +// setShowAsAction(); +// } +// +// private void setShowAsAction() { +// if (menu == null) { +// Log.d(TAG, "setShowAsAction() without a menu"); +// return; +// } +// MenuItem item = menu.findItem(R.id.media_route_menu_item); +// if (item == null) { +// Log.e(TAG, "setShowAsAction(), but cast button not inflated"); +// return; +// } +// MenuItemCompat.setShowAsAction(item, connected? MenuItem.SHOW_AS_ACTION_ALWAYS : showAsAction); +// } +// } +} diff --git a/app/src/free/java/de/danoeh/antennapod/config/CastCallbackImpl.java b/app/src/free/java/de/danoeh/antennapod/config/CastCallbackImpl.java new file mode 100644 index 000000000..5e714f02c --- /dev/null +++ b/app/src/free/java/de/danoeh/antennapod/config/CastCallbackImpl.java @@ -0,0 +1,7 @@ +package de.danoeh.antennapod.config; + +import de.danoeh.antennapod.core.CastCallbacks; + +public class CastCallbackImpl implements CastCallbacks { + +} diff --git a/app/src/free/java/de/danoeh/antennapod/preferences/PreferenceControllerFlavorHelper.java b/app/src/free/java/de/danoeh/antennapod/preferences/PreferenceControllerFlavorHelper.java new file mode 100644 index 000000000..de604c7c4 --- /dev/null +++ b/app/src/free/java/de/danoeh/antennapod/preferences/PreferenceControllerFlavorHelper.java @@ -0,0 +1,13 @@ +package de.danoeh.antennapod.preferences; + +import de.danoeh.antennapod.core.preferences.UserPreferences; + +/** + * Implements functions from PreferenceController that are flavor dependent. + */ +public class PreferenceControllerFlavorHelper { + + static void setupFlavoredUI(PreferenceController.PreferenceUI ui) { + ui.findPreference(UserPreferences.PREF_CAST_ENABLED).setEnabled(false); + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d441baf83..288e289d5 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,8 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="de.danoeh.antennapod" - android:versionCode="1060009" - android:versionName="1.6.0.9"> + android:installLocation="auto" + android:versionCode="1060400" + android:versionName="1.6.4.0"> <!-- Version code schema: "1.2.3-SNAPSHOT" -> 1020300 @@ -37,23 +38,35 @@ android:backupAgent=".core.backup.OpmlBackupAgent" android:restoreAnyVersion="true" android:logo="@drawable/ic_launcher"> + <meta-data android:name="com.google.android.gms.car.notification.SmallIcon" + android:resource="@drawable/ic_notification" /> <meta-data android:name="com.google.android.backup.api_key" android:value="AEdPqrEAAAAI3a05VToCTlqBymJrbFGaKQMvF-bBAuLsOdavBA"/> - <meta-data - android:name="com.google.android.gms.version" - android:value="@integer/google_play_services_version" /> - <activity - android:name=".activity.MainActivity" - android:configChanges="keyboardHidden|orientation" + android:name=".activity.SplashActivity" + android:configChanges="keyboardHidden|orientation|screenSize" android:launchMode="singleTask" - android:label="@string/app_name"> + android:label="@string/app_name" + android:theme="@style/Theme.AntennaPod.Dark.Splash"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> + + <intent-filter> + <action android:name= + "android.media.action.MEDIA_PLAY_FROM_SEARCH" /> + <category android:name= + "android.intent.category.DEFAULT" /> + </intent-filter> + </activity> + <activity + android:name=".activity.MainActivity" + android:configChanges="keyboardHidden|orientation|screenSize" + android:launchMode="singleTask" + android:label="@string/app_name"> </activity> <activity android:name=".activity.AudioplayerActivity" @@ -85,7 +98,7 @@ <activity android:name=".activity.PreferenceActivityGingerbread" - android:configChanges="keyboardHidden|orientation" + android:configChanges="keyboardHidden|orientation|screenSize" android:label="@string/settings_label"> <meta-data android:name="android.support.PARENT_ACTIVITY" @@ -94,7 +107,7 @@ <activity android:name=".activity.PreferenceActivity" - android:configChanges="keyboardHidden|orientation" + android:configChanges="keyboardHidden|orientation|screenSize" android:label="@string/settings_label"> <meta-data android:name="android.support.PARENT_ACTIVITY" @@ -150,6 +163,7 @@ </activity> <activity android:name=".activity.AboutActivity" + android:configChanges="keyboardHidden|orientation|screenSize" android:label="@string/about_pref"> <meta-data android:name="android.support.PARENT_ACTIVITY" @@ -164,12 +178,12 @@ </activity> <activity android:name=".activity.OpmlImportFromPathActivity" - android:configChanges="keyboardHidden|orientation" + android:configChanges="keyboardHidden|orientation|screenSize" android:label="@string/opml_import_label"> </activity> <activity android:name=".activity.OpmlImportFromIntentActivity" - android:configChanges="keyboardHidden|orientation" + android:configChanges="keyboardHidden|orientation|screenSize" android:label="@string/opml_import_label"> <intent-filter> <action android:name="android.intent.action.VIEW"/> @@ -177,16 +191,30 @@ <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.BROWSABLE"/> - <data - android:host="*" - android:pathPattern=".*\\.opml" - android:scheme="file" - android:mimeType="*/*"/> - <data - android:host="*" - android:pathPattern=".*\\.opml" - android:scheme="content" - android:mimeType="*/*"/> + <data android:mimeType="text/xml"/> + <data android:mimeType="text/x-opml"/> + <data android:mimeType="application/xml"/> + <data android:mimeType="application/octet-stream"/> + + <data android:scheme="file"/> + <data android:scheme="content"/> + + <data android:host="*"/> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.SEND"/> + + <category android:name="android.intent.category.DEFAULT"/> + <category android:name="android.intent.category.BROWSABLE"/> + + <data android:mimeType="text/xml"/> + <data android:mimeType="text/plain"/> + <data android:mimeType="text/x-opml"/> + <data android:mimeType="application/xml"/> + <data android:mimeType="application/octet-stream"/> + + <data android:scheme="http"/> + <data android:scheme="https"/> </intent-filter> </activity> <activity @@ -221,7 +249,7 @@ <activity android:name=".activity.OnlineFeedViewActivity" - android:configChanges="orientation" + android:configChanges="orientation|screenSize" android:label="@string/add_feed_label"> <meta-data android:name="android.support.PARENT_ACTIVITY" @@ -240,6 +268,7 @@ <data android:host="*"/> <data android:pathPattern=".*\\.xml"/> <data android:pathPattern=".*\\.rss"/> + <data android:pathPattern=".*\\.atom"/> </intent-filter> <!-- Feedburner URLs --> @@ -346,6 +375,10 @@ <meta-data android:name="de.danoeh.antennapod.core.glide.ApGlideModule" android:value="GlideModule" /> + + <meta-data + android:name="com.google.android.gms.car.application" + android:resource="@xml/automotive_app_desc"/> </application> </manifest> diff --git a/app/src/main/java/de/danoeh/antennapod/PodcastApp.java b/app/src/main/java/de/danoeh/antennapod/PodcastApp.java index f6a8db5fb..caa82d725 100644 --- a/app/src/main/java/de/danoeh/antennapod/PodcastApp.java +++ b/app/src/main/java/de/danoeh/antennapod/PodcastApp.java @@ -3,6 +3,7 @@ package de.danoeh.antennapod; import android.app.Application; import android.os.Build; import android.os.StrictMode; +import android.support.multidex.MultiDexApplication; import com.joanzapata.iconify.Iconify; import com.joanzapata.iconify.fonts.FontAwesomeModule; @@ -13,7 +14,7 @@ import de.danoeh.antennapod.core.feed.EventDistributor; import de.danoeh.antennapod.spa.SPAUtil; /** Main application class. */ -public class PodcastApp extends Application { +public class PodcastApp extends MultiDexApplication { // make sure that ClientConfigurator executes its static code static { diff --git a/app/src/main/java/de/danoeh/antennapod/activity/AboutActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/AboutActivity.java index eef2fa4da..1b42b274c 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/AboutActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/AboutActivity.java @@ -124,12 +124,11 @@ public class AboutActivity extends AppCompatActivity { }) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(webviewData -> { - webview.loadDataWithBaseURL("file:///android_asset/", webviewData, "text/html", - "utf-8", "about:blank"); - }, error -> { - Log.e(TAG, Log.getStackTraceString(error)); - }); + .subscribe( + webviewData -> + webview.loadDataWithBaseURL("file:///android_asset/", webviewData, "text/html", "utf-8", "about:blank"), + error -> Log.e(TAG, Log.getStackTraceString(error)) + ); } @Override diff --git a/app/src/main/java/de/danoeh/antennapod/activity/CastplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/CastplayerActivity.java index 1ca4d095f..a7e9b1e70 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/CastplayerActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/CastplayerActivity.java @@ -50,10 +50,10 @@ public class CastplayerActivity extends MediaplayerInfoActivity { if (butPlaybackSpeed != null) { butPlaybackSpeed.setVisibility(View.GONE); } - if (butCastDisconnect != null) { - butCastDisconnect.setOnClickListener(v -> castManager.disconnect()); - butCastDisconnect.setVisibility(View.VISIBLE); - } +// if (butCastDisconnect != null) { +// butCastDisconnect.setOnClickListener(v -> castManager.disconnect()); +// butCastDisconnect.setVisibility(View.VISIBLE); +// } } @Override diff --git a/app/src/main/java/de/danoeh/antennapod/activity/DirectoryChooserActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/DirectoryChooserActivity.java index 5fd69ef6a..390d4cef8 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/DirectoryChooserActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/DirectoryChooserActivity.java @@ -89,9 +89,7 @@ public class DirectoryChooserActivity extends AppCompatActivity { adb.setTitle(R.string.folder_not_empty_dialog_title); adb.setMessage(R.string.folder_not_empty_dialog_msg); adb.setNegativeButton(R.string.cancel_label, - (dialog, which) -> { - dialog.dismiss(); - }); + (dialog, which) -> dialog.dismiss()); adb.setPositiveButton(R.string.confirm_label, (dialog, which) -> { dialog.dismiss(); @@ -291,9 +289,7 @@ public class DirectoryChooserActivity extends AppCompatActivity { builder.setMessage(String.format(getString(R.string.create_folder_msg), CREATE_DIRECTORY_NAME)); builder.setNegativeButton(R.string.cancel_label, - (dialog, which) -> { - dialog.dismiss(); - }); + (dialog, which) -> dialog.dismiss()); builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> { dialog.dismiss(); diff --git a/app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java index d4356719e..2a58d5104 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java @@ -5,10 +5,10 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; -import android.os.AsyncTask; import android.os.Bundle; -import android.support.v7.app.ActionBarActivity; +import android.support.v7.app.AppCompatActivity; import android.text.Editable; +import android.text.TextUtils; import android.text.TextWatcher; import android.util.Log; import android.view.Menu; @@ -28,6 +28,10 @@ import android.widget.Toast; import com.bumptech.glide.Glide; import com.joanzapata.iconify.Iconify; +import org.apache.commons.lang3.StringUtils; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; + import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.dialog.ConfirmationDialog; import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator; @@ -41,23 +45,29 @@ import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.storage.DownloadRequestException; import de.danoeh.antennapod.core.util.IntentUtils; import de.danoeh.antennapod.core.util.LangUtils; +import de.danoeh.antennapod.core.util.syndication.HtmlToPlainText; import de.danoeh.antennapod.menuhandler.FeedMenuHandler; +import rx.Observable; +import rx.Subscription; +import rx.android.schedulers.AndroidSchedulers; +import rx.schedulers.Schedulers; /** * Displays information about a feed. */ -public class FeedInfoActivity extends ActionBarActivity { - private static final String TAG = "FeedInfoActivity"; - private boolean autoDeleteChanged = false; +public class FeedInfoActivity extends AppCompatActivity { public static final String EXTRA_FEED_ID = "de.danoeh.antennapod.extra.feedId"; - + private static final String TAG = "FeedInfoActivity"; + private boolean autoDeleteChanged = false; private Feed feed; private ImageView imgvCover; private TextView txtvTitle; private TextView txtvDescription; + private TextView lblLanguage; private TextView txtvLanguage; + private TextView lblAuthor; private TextView txtvAuthor; private TextView txtvUrl; private EditText etxtUsername; @@ -70,6 +80,9 @@ public class FeedInfoActivity extends ActionBarActivity { private Spinner spnAutoDelete; private boolean filterInclude = true; + private Subscription subscription; + + private final View.OnClickListener copyUrlToClipboard = new View.OnClickListener() { @Override public void onClick(View v) { @@ -91,6 +104,40 @@ public class FeedInfoActivity extends ActionBarActivity { } }; + private boolean authInfoChanged = false; + + private TextWatcher authTextWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable s) { + authInfoChanged = true; + } + }; + + private boolean filterTextChanged = false; + + private TextWatcher filterTextWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable s) { + filterTextChanged = true; + } + }; + @Override protected void onCreate(Bundle savedInstanceState) { setTheme(UserPreferences.getTheme()); @@ -102,7 +149,9 @@ public class FeedInfoActivity extends ActionBarActivity { imgvCover = (ImageView) findViewById(R.id.imgvCover); txtvTitle = (TextView) findViewById(R.id.txtvTitle); txtvDescription = (TextView) findViewById(R.id.txtvDescription); + lblLanguage = (TextView) findViewById(R.id.lblLanguage); txtvLanguage = (TextView) findViewById(R.id.txtvLanguage); + lblAuthor = (TextView) findViewById(R.id.lblAuthor); txtvAuthor = (TextView) findViewById(R.id.txtvAuthor); txtvUrl = (TextView) findViewById(R.id.txtvUrl); cbxAutoDownload = (CheckBox) findViewById(R.id.cbxAutoDownload); @@ -124,48 +173,62 @@ public class FeedInfoActivity extends ActionBarActivity { txtvUrl.setOnClickListener(copyUrlToClipboard); - AsyncTask<Long, Void, Feed> loadTask = new AsyncTask<Long, Void, Feed>() { - - @Override - protected Feed doInBackground(Long... params) { - return DBReader.getFeed(params[0]); - } - - @Override - protected void onPostExecute(Feed result) { - if (result != null) { + subscription = Observable.fromCallable(()-> DBReader.getFeed(feedId)) + .subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(result -> { + if (result == null) { + Log.e(TAG, "Activity was started with invalid arguments"); + finish(); + } feed = result; Log.d(TAG, "Language is " + feed.getLanguage()); Log.d(TAG, "Author is " + feed.getAuthor()); Log.d(TAG, "URL is " + feed.getDownload_url()); FeedPreferences prefs = feed.getPreferences(); - imgvCover.post(() -> Glide.with(FeedInfoActivity.this) - .load(feed.getImageUri()) + Glide.with(FeedInfoActivity.this) + .load(feed.getImageLocation()) .placeholder(R.color.light_gray) .error(R.color.light_gray) .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) .fitCenter() .dontAnimate() - .into(imgvCover)); + .into(imgvCover); txtvTitle.setText(feed.getTitle()); + String description = feed.getDescription(); - txtvDescription.setText((description != null) ? description.trim() : ""); - if (feed.getAuthor() != null) { + if(description != null) { + if(Feed.TYPE_ATOM1.equals(feed.getType())) { + HtmlToPlainText formatter = new HtmlToPlainText(); + Document feedDescription = Jsoup.parse(feed.getDescription()); + description = StringUtils.trim(formatter.getPlainText(feedDescription)); + } + } else { + description = ""; + } + txtvDescription.setText(description); + + if (!TextUtils.isEmpty(feed.getAuthor())) { txtvAuthor.setText(feed.getAuthor()); + } else { + lblAuthor.setVisibility(View.GONE); + txtvAuthor.setVisibility(View.GONE); } - if (feed.getLanguage() != null) { - txtvLanguage.setText(LangUtils - .getLanguageString(feed.getLanguage())); + if (!TextUtils.isEmpty(feed.getLanguage())) { + txtvLanguage.setText(LangUtils.getLanguageString(feed.getLanguage())); + } else { + lblLanguage.setVisibility(View.GONE); + txtvLanguage.setVisibility(View.GONE); } txtvUrl.setText(feed.getDownload_url() + " {fa-paperclip}"); - Iconify.addIcons(txtvUrl); + Iconify.addIcons(txtvUrl); cbxAutoDownload.setEnabled(UserPreferences.isEnableAutodownload()); cbxAutoDownload.setChecked(prefs.getAutoDownload()); cbxAutoDownload.setOnCheckedChangeListener((compoundButton, checked) -> { feed.getPreferences().setAutoDownload(checked); - feed.savePreferences(FeedInfoActivity.this); + feed.savePreferences(); updateAutoDownloadSettings(); ApplyToEpisodesDialog dialog = new ApplyToEpisodesDialog(FeedInfoActivity.this, feed, checked); @@ -174,7 +237,7 @@ public class FeedInfoActivity extends ActionBarActivity { cbxKeepUpdated.setChecked(prefs.getKeepUpdated()); cbxKeepUpdated.setOnCheckedChangeListener((compoundButton, checked) -> { feed.getPreferences().setKeepUpdated(checked); - feed.savePreferences(FeedInfoActivity.this); + feed.savePreferences(); }); spnAutoDelete.setOnItemSelectedListener(new OnItemSelectedListener() { @Override @@ -184,15 +247,12 @@ public class FeedInfoActivity extends ActionBarActivity { case 0: auto_delete_action = FeedPreferences.AutoDeleteAction.GLOBAL; break; - case 1: auto_delete_action = FeedPreferences.AutoDeleteAction.YES; break; - case 2: auto_delete_action = FeedPreferences.AutoDeleteAction.NO; break; - default: // TODO - add exceptions here return; } @@ -234,57 +294,12 @@ public class FeedInfoActivity extends ActionBarActivity { supportInvalidateOptionsMenu(); updateAutoDownloadSettings(); - } else { - Log.e(TAG, "Activity was started with invalid arguments"); - } - } - }; - if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) { - loadTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, feedId); - } else { - loadTask.execute(feedId); - } + }, error -> { + Log.d(TAG, Log.getStackTraceString(error)); + finish(); + }); } - - private boolean authInfoChanged = false; - - private TextWatcher authTextWatcher = new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - - } - - @Override - public void afterTextChanged(Editable s) { - authInfoChanged = true; - } - }; - - private boolean filterTextChanged = false; - - private TextWatcher filterTextWatcher = new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - - } - - @Override - public void afterTextChanged(Editable s) { - filterTextChanged = true; - } - }; - @Override protected void onPause() { super.onPause(); @@ -317,6 +332,14 @@ public class FeedInfoActivity extends ActionBarActivity { } @Override + public void onDestroy() { + super.onDestroy(); + if(subscription != null) { + subscription.unsubscribe(); + } + } + + @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); MenuInflater inflater = getMenuInflater(); @@ -367,7 +390,7 @@ public class FeedInfoActivity extends ActionBarActivity { private final Feed feed; private final boolean autoDownload; - public ApplyToEpisodesDialog(Context context, Feed feed, boolean autoDownload) { + ApplyToEpisodesDialog(Context context, Feed feed, boolean autoDownload) { super(context, R.string.auto_download_apply_to_items_title, R.string.auto_download_apply_to_items_message); this.feed = feed; diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java index b7c7d86c7..f0fcdca90 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java @@ -10,6 +10,7 @@ import android.database.DataSetObserver; import android.os.Build; import android.os.Bundle; import android.os.Handler; +import android.support.design.widget.Snackbar; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; @@ -38,6 +39,7 @@ import de.danoeh.antennapod.R; import de.danoeh.antennapod.adapter.NavListAdapter; import de.danoeh.antennapod.core.asynctask.FeedRemover; import de.danoeh.antennapod.core.dialog.ConfirmationDialog; +import de.danoeh.antennapod.core.event.MessageEvent; import de.danoeh.antennapod.core.event.ProgressEvent; import de.danoeh.antennapod.core.event.QueueEvent; import de.danoeh.antennapod.core.feed.EventDistributor; @@ -46,10 +48,13 @@ import de.danoeh.antennapod.core.preferences.PlaybackPreferences; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.playback.PlaybackService; import de.danoeh.antennapod.core.storage.DBReader; +import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.util.FeedItemUtil; +import de.danoeh.antennapod.core.util.Flavors; import de.danoeh.antennapod.core.util.StorageUtils; import de.danoeh.antennapod.dialog.RatingDialog; +import de.danoeh.antennapod.dialog.RenameFeedDialog; import de.danoeh.antennapod.fragment.AddFeedFragment; import de.danoeh.antennapod.fragment.DownloadsFragment; import de.danoeh.antennapod.fragment.EpisodesFragment; @@ -148,9 +153,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi final FragmentManager fm = getSupportFragmentManager(); - fm.addOnBackStackChangedListener(() -> { - drawerToggle.setDrawerIndicatorEnabled(fm.getBackStackEntryCount() == 0); - }); + fm.addOnBackStackChangedListener(() -> drawerToggle.setDrawerIndicatorEnabled(fm.getBackStackEntryCount() == 0)); getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setHomeButtonEnabled(true); @@ -209,7 +212,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi } else { edit.remove(PREF_LAST_FRAGMENT_TAG); } - edit.commit(); + edit.apply(); } private String getLastNavFragment() { @@ -254,9 +257,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi hiddenDrawerItems.add(NAV_DRAWER_TAGS[which]); } }); - builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> { - UserPreferences.setHiddenDrawerItems(hiddenDrawerItems); - }); + builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> UserPreferences.setHiddenDrawerItems(hiddenDrawerItems)); builder.setNegativeButton(R.string.cancel_label, null); builder.create().show(); } @@ -466,6 +467,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi protected void onResume() { super.onResume(); StorageUtils.checkStorageAvailability(this); + DBTasks.checkShouldRefreshFeeds(getApplicationContext()); Intent intent = getIntent(); if (intent.hasExtra(EXTRA_FEED_ID) || @@ -507,21 +509,24 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi @Override public boolean onCreateOptionsMenu(Menu menu) { boolean retVal = super.onCreateOptionsMenu(menu); - switch (getLastNavFragment()) { - case QueueFragment.TAG: - case EpisodesFragment.TAG: - requestCastButton(MenuItem.SHOW_AS_ACTION_IF_ROOM); - return retVal; - case DownloadsFragment.TAG: - case PlaybackHistoryFragment.TAG: - case AddFeedFragment.TAG: - case SubscriptionFragment.TAG: - return retVal; - default: - requestCastButton(MenuItem.SHOW_AS_ACTION_NEVER); - return retVal; + if (Flavors.FLAVOR == Flavors.PLAY) { + switch (getLastNavFragment()) { + case QueueFragment.TAG: + case EpisodesFragment.TAG: + requestCastButton(MenuItem.SHOW_AS_ACTION_IF_ROOM); + return retVal; + case DownloadsFragment.TAG: + case PlaybackHistoryFragment.TAG: + case AddFeedFragment.TAG: + case SubscriptionFragment.TAG: + return retVal; + default: + requestCastButton(MenuItem.SHOW_AS_ACTION_NEVER); + return retVal; + } + } else { + return retVal; } - } @Override @@ -573,6 +578,9 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi case R.id.mark_all_read_item: DBWriter.markFeedRead(feed.getId()); return true; + case R.id.rename_item: + new RenameFeedDialog(this, feed).show(); + return true; case R.id.remove_item: final FeedRemover remover = new FeedRemover(this, feed) { @Override @@ -585,7 +593,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi }; ConfirmationDialog conDialog = new ConfirmationDialog(this, R.string.remove_feed_label, - R.string.feed_delete_confirmation_msg) { + getString(R.string.feed_delete_confirmation_msg, feed.getTitle())) { @Override public void onConfirmButtonPressed( DialogInterface dialog) { @@ -699,9 +707,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi if (handleIntent) { handleNavIntent(); } - }, error -> { - Log.e(TAG, Log.getStackTraceString(error)); - }); + }, error -> Log.e(TAG, Log.getStackTraceString(error))); } public void onEvent(QueueEvent event) { @@ -733,6 +739,18 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi } } + public void onEventMainThread(MessageEvent event) { + Log.d(TAG, "onEvent(" + event + ")"); + View parentLayout = findViewById(R.id.drawer_layout); + Snackbar snackbar = Snackbar.make(parentLayout, event.message, Snackbar.LENGTH_SHORT); + if(event.action != null) { + snackbar.setAction(getString(R.string.undo), v -> { + event.action.run(); + }); + } + snackbar.show(); + } + private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() { @Override diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java index 71d288725..21a0fa66f 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java @@ -1,6 +1,7 @@ package de.danoeh.antennapod.activity; import android.annotation.TargetApi; +import android.app.Activity; import android.content.Intent; import android.content.SharedPreferences; import android.content.res.TypedArray; @@ -9,6 +10,7 @@ import android.graphics.PixelFormat; import android.net.Uri; import android.os.Build; import android.os.Bundle; +import android.support.annotation.Nullable; import android.support.v7.app.AlertDialog; import android.util.Log; import android.view.Menu; @@ -39,8 +41,10 @@ import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.util.Converter; +import de.danoeh.antennapod.core.util.Flavors; import de.danoeh.antennapod.core.util.ShareUtils; import de.danoeh.antennapod.core.util.StorageUtils; +import de.danoeh.antennapod.core.util.Supplier; import de.danoeh.antennapod.core.util.playback.MediaPlayerError; import de.danoeh.antennapod.core.util.playback.Playable; import de.danoeh.antennapod.core.util.playback.PlaybackController; @@ -48,6 +52,8 @@ import de.danoeh.antennapod.dialog.SleepTimerDialog; import de.danoeh.antennapod.dialog.VariableSpeedDialog; import rx.Observable; import rx.android.schedulers.AndroidSchedulers; +import rx.functions.Action1; +import rx.functions.Func1; import rx.schedulers.Schedulers; @@ -177,6 +183,13 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements }; } + protected static TextView getTxtvFFFromActivity(MediaplayerActivity activity) { + return activity.txtvFF; + } + protected static TextView getTxtvRevFromActivity(MediaplayerActivity activity) { + return activity.txtvRev; + } + protected void onSetSpeedAbilityChanged() { Log.d(TAG, "onSetSpeedAbilityChanged()"); updatePlaybackSpeedButton(); @@ -281,7 +294,9 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); - requestCastButton(MenuItem.SHOW_AS_ACTION_ALWAYS); + if (Flavors.FLAVOR == Flavors.PLAY) { + requestCastButton(MenuItem.SHOW_AS_ACTION_ALWAYS); + } MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.mediaplayer, menu); return true; @@ -294,10 +309,9 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements return false; } Playable media = controller.getMedia(); + boolean isFeedMedia = media != null && (media instanceof FeedMedia); - menu.findItem(R.id.support_item).setVisible( - media != null && media.getPaymentLink() != null && - (media instanceof FeedMedia) && + menu.findItem(R.id.support_item).setVisible(isFeedMedia && media.getPaymentLink() != null && ((FeedMedia) media).getItem() != null && ((FeedMedia) media).getItem().getFlattrStatus().flattrable() ); @@ -305,20 +319,21 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements boolean hasWebsiteLink = media != null && media.getWebsiteLink() != null; menu.findItem(R.id.visit_website_item).setVisible(hasWebsiteLink); - boolean isItemAndHasLink = media != null && (media instanceof FeedMedia) && + boolean isItemAndHasLink = isFeedMedia && ((FeedMedia) media).getItem() != null && ((FeedMedia) media).getItem().getLink() != null; menu.findItem(R.id.share_link_item).setVisible(isItemAndHasLink); menu.findItem(R.id.share_link_with_position_item).setVisible(isItemAndHasLink); - boolean isItemHasDownloadLink = media != null && (media instanceof FeedMedia) && ((FeedMedia) media).getDownload_url() != null; + boolean isItemHasDownloadLink = isFeedMedia && ((FeedMedia) media).getDownload_url() != null; menu.findItem(R.id.share_download_url_item).setVisible(isItemHasDownloadLink); menu.findItem(R.id.share_download_url_with_position_item).setVisible(isItemHasDownloadLink); + menu.findItem(R.id.share_file).setVisible(isFeedMedia && ((FeedMedia) media).fileExists()); menu.findItem(R.id.share_item).setVisible(hasWebsiteLink || isItemAndHasLink || isItemHasDownloadLink); menu.findItem(R.id.add_to_favorites_item).setVisible(false); menu.findItem(R.id.remove_from_favorites_item).setVisible(false); - if(media != null && media instanceof FeedMedia) { + if (isFeedMedia) { menu.findItem(R.id.add_to_favorites_item).setVisible(!isFavorite); menu.findItem(R.id.remove_from_favorites_item).setVisible(isFavorite); } @@ -559,6 +574,11 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements ShareUtils.shareFeedItemDownloadLink(this, ((FeedMedia) media).getItem(), true); } break; + case R.id.share_file: + if (media instanceof FeedMedia) { + ShareUtils.shareFeedItemFile(this, ((FeedMedia) media)); + } + break; default: return false; } @@ -627,17 +647,16 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements */ protected boolean loadMediaInfo() { Log.d(TAG, "loadMediaInfo()"); + if(controller == null || controller.getMedia() == null) { + return false; + } Playable media = controller.getMedia(); SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE); showTimeLeft = prefs.getBoolean(PREF_SHOW_TIME_LEFT, false); - if (media != null) { - onPositionObserverUpdate(); - checkFavorite(); - updatePlaybackSpeedButton(); - return true; - } else { - return false; - } + onPositionObserverUpdate(); + checkFavorite(); + updatePlaybackSpeedButton(); + return true; } protected void updatePlaybackSpeedButton() { @@ -648,6 +667,91 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements // Only meaningful on AudioplayerActivity, where it is overridden. } + /** + * Abstract directions to skip forward or back (rewind) and encapsulates behavior to get or set preference (including update of UI on the skip buttons). + */ + static public enum SkipDirection { + SKIP_FORWARD( + UserPreferences::getFastForwardSecs, + MediaplayerActivity::getTxtvFFFromActivity, + UserPreferences::setFastForwardSecs, + R.string.pref_fast_forward), + SKIP_REWIND(UserPreferences::getRewindSecs, + MediaplayerActivity::getTxtvRevFromActivity, + UserPreferences::setRewindSecs, + R.string.pref_rewind); + + private final Supplier<Integer> getPrefSecsFn; + private final Func1<MediaplayerActivity, TextView> getTextViewFn; + private final Action1<Integer> setPrefSecsFn; + private final int titleResourceID; + + /** + * Constructor for skip direction enum. Stores references to utility functions and resource + * id's that vary dependending on the direction. + * + * @param getPrefSecsFn Handle to function that retrieves current seconds of the skip delta + * @param getTextViewFn Handle to function that gets the TextView which displays the current skip delta value + * @param setPrefSecsFn Handle to function that sets the preference (setting) for the skip delta value (and optionally updates the button label with the current values) + * @param titleResourceID ID of the resource string with the title for a view + */ + SkipDirection(Supplier<Integer> getPrefSecsFn, Func1<MediaplayerActivity, TextView> getTextViewFn, Action1<Integer> setPrefSecsFn, int titleResourceID) { + this.getPrefSecsFn = getPrefSecsFn; + this.getTextViewFn = getTextViewFn; + this.setPrefSecsFn = setPrefSecsFn; + this.titleResourceID = titleResourceID; + } + + + public int getPrefSkipSeconds() { + return(getPrefSecsFn.get()); + } + + /** + * Updates preferences for a forward or backward skip depending on the direction of the instance, optionally updating the UI. + * + * @param seconds Number of seconds to set the preference associated with the direction of the instance. + * @param activity MediaplyerActivity that contains textview to update the display of the skip delta setting (or null if nothing to update) + */ + public void setPrefSkipSeconds(int seconds, @Nullable Activity activity) { + setPrefSecsFn.call(seconds); + + if (activity != null && activity instanceof MediaplayerActivity) { + TextView tv = getTextViewFn.call((MediaplayerActivity)activity); + if (tv != null) tv.setText(String.valueOf(seconds)); + } + } + public int getTitleResourceID() { + return titleResourceID; + } + } + + static public void showSkipPreference(Activity activity, SkipDirection direction) { + int checked = 0; + int skipSecs = direction.getPrefSkipSeconds(); + final int[] values = activity.getResources().getIntArray(R.array.seek_delta_values); + final String[] choices = new String[values.length]; + for (int i = 0; i < values.length; i++) { + if (skipSecs == values[i]) { + checked = i; + } + choices[i] = String.valueOf(values[i]) + " " + activity.getString(R.string.time_seconds); + } + + AlertDialog.Builder builder = new AlertDialog.Builder(activity); + builder.setTitle(direction.getTitleResourceID()); + builder.setSingleChoiceItems(choices, checked, null); + builder.setNegativeButton(R.string.cancel_label, null); + builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> { + int choice = ((AlertDialog)dialog).getListView().getCheckedItemPosition(); + if (choice < 0 || choice >= values.length) { + System.err.printf("Choice in showSkipPreference is out of bounds %d", choice); + } else { + direction.setPrefSkipSeconds(values[choice], activity); + } + }); + builder.create().show(); + } protected void setupGUI() { setContentView(getContentViewResourceId()); @@ -690,7 +794,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements butFF = (ImageButton) findViewById(R.id.butFF); txtvFF = (TextView) findViewById(R.id.txtvFF); if (txtvFF != null) { - txtvFF.setText(String.valueOf(UserPreferences.getFastFowardSecs())); + txtvFF.setText(String.valueOf(UserPreferences.getFastForwardSecs())); } butSkip = (ImageButton) findViewById(R.id.butSkip); @@ -702,39 +806,9 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements if (butRev != null) { butRev.setOnClickListener(v -> onRewind()); - butRev.setOnLongClickListener(new View.OnLongClickListener() { - - int choice; - - @Override - public boolean onLongClick(View v) { - int checked = 0; - int rewindSecs = UserPreferences.getRewindSecs(); - final int[] values = getResources().getIntArray(R.array.seek_delta_values); - final String[] choices = new String[values.length]; - for (int i = 0; i < values.length; i++) { - if (rewindSecs == values[i]) { - checked = i; - } - choices[i] = String.valueOf(values[i]) + " " + getString(R.string.time_seconds); - } - choice = values[checked]; - AlertDialog.Builder builder = new AlertDialog.Builder(MediaplayerActivity.this); - builder.setTitle(R.string.pref_rewind); - builder.setSingleChoiceItems(choices, checked, - (dialog, which) -> { - choice = values[which]; - }); - builder.setNegativeButton(R.string.cancel_label, null); - builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> { - UserPreferences.setPrefRewindSecs(choice); - if(txtvRev != null){ - txtvRev.setText(String.valueOf(choice)); - } - }); - builder.create().show(); - return true; - } + butRev.setOnLongClickListener(v -> { + showSkipPreference(MediaplayerActivity.this, SkipDirection.SKIP_REWIND); + return true; }); } @@ -742,39 +816,9 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements if (butFF != null) { butFF.setOnClickListener(v -> onFastForward()); - butFF.setOnLongClickListener(new View.OnLongClickListener() { - - int choice; - - @Override - public boolean onLongClick(View v) { - int checked = 0; - int rewindSecs = UserPreferences.getFastFowardSecs(); - final int[] values = getResources().getIntArray(R.array.seek_delta_values); - final String[] choices = new String[values.length]; - for (int i = 0; i < values.length; i++) { - if (rewindSecs == values[i]) { - checked = i; - } - choices[i] = String.valueOf(values[i]) + " " + getString(R.string.time_seconds); - } - choice = values[checked]; - AlertDialog.Builder builder = new AlertDialog.Builder(MediaplayerActivity.this); - builder.setTitle(R.string.pref_fast_forward); - builder.setSingleChoiceItems(choices, checked, - (dialog, which) -> { - choice = values[which]; - }); - builder.setNegativeButton(R.string.cancel_label, null); - builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> { - UserPreferences.setPrefFastForwardSecs(choice); - if(txtvFF != null) { - txtvFF.setText(String.valueOf(choice)); - } - }); - builder.create().show(); - return true; - } + butFF.setOnLongClickListener(v -> { + showSkipPreference(MediaplayerActivity.this, SkipDirection.SKIP_FORWARD); + return false; }); } @@ -803,7 +847,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements return; } int curr = controller.getPosition(); - controller.seekTo(curr + UserPreferences.getFastFowardSecs() * 1000); + controller.seekTo(curr + UserPreferences.getFastForwardSecs() * 1000); } protected abstract int getContentViewResourceId(); @@ -865,10 +909,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements isFavorite = isFav; invalidateOptionsMenu(); } - }, error -> { - Log.e(TAG, Log.getStackTraceString(error)); - } - ); + }, error -> Log.e(TAG, Log.getStackTraceString(error))); } } } diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerInfoActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerInfoActivity.java index 647745e39..b3cda69d3 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerInfoActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerInfoActivity.java @@ -8,6 +8,7 @@ import android.content.res.Configuration; import android.os.Build; import android.support.annotation.Nullable; import android.support.design.widget.AppBarLayout; +import android.support.design.widget.Snackbar; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentStatePagerAdapter; @@ -36,6 +37,7 @@ import de.danoeh.antennapod.adapter.ChaptersListAdapter; import de.danoeh.antennapod.adapter.NavListAdapter; import de.danoeh.antennapod.core.asynctask.FeedRemover; import de.danoeh.antennapod.core.dialog.ConfirmationDialog; +import de.danoeh.antennapod.core.event.MessageEvent; import de.danoeh.antennapod.core.feed.EventDistributor; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.feed.FeedMedia; @@ -43,9 +45,11 @@ import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.playback.PlaybackService; import de.danoeh.antennapod.core.service.playback.PlayerStatus; import de.danoeh.antennapod.core.storage.DBReader; +import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.util.playback.Playable; import de.danoeh.antennapod.core.util.playback.PlaybackController; +import de.danoeh.antennapod.dialog.RenameFeedDialog; import de.danoeh.antennapod.fragment.AddFeedFragment; import de.danoeh.antennapod.fragment.ChaptersFragment; import de.danoeh.antennapod.fragment.CoverFragment; @@ -57,6 +61,7 @@ import de.danoeh.antennapod.fragment.QueueFragment; import de.danoeh.antennapod.fragment.SubscriptionFragment; import de.danoeh.antennapod.menuhandler.NavDrawerActivity; import de.danoeh.antennapod.preferences.PreferenceController; +import de.greenrobot.event.EventBus; import rx.Observable; import rx.Subscription; import rx.android.schedulers.AndroidSchedulers; @@ -102,6 +107,12 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem private Subscription subscription; @Override + protected void onPause() { + super.onPause(); + EventBus.getDefault().unregister(this); + } + + @Override protected void onStop() { super.onStop(); Log.d(TAG, "onStop()"); @@ -168,8 +179,10 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem pagerAdapter.onMediaChanged(media); pagerAdapter.setController(controller); } + DBTasks.checkShouldRefreshFeeds(getApplicationContext()); EventDistributor.getInstance().register(contentUpdate); + EventBus.getDefault().register(this); loadData(); } @@ -277,7 +290,7 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem if (!super.loadMediaInfo()) { return false; } - if(controller.getMedia() != media) { + if(controller != null && controller.getMedia() != media) { media = controller.getMedia(); pagerAdapter.onMediaChanged(media); } @@ -370,6 +383,9 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem case R.id.mark_all_read_item: DBWriter.markFeedRead(feed.getId()); return true; + case R.id.rename_item: + new RenameFeedDialog(this, feed).show(); + return true; case R.id.remove_item: final FeedRemover remover = new FeedRemover(this, feed) { @Override @@ -379,7 +395,7 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem }; ConfirmationDialog conDialog = new ConfirmationDialog(this, R.string.remove_feed_label, - R.string.feed_delete_confirmation_msg) { + getString(R.string.feed_delete_confirmation_msg, feed.getTitle())) { @Override public void onConfirmButtonPressed( DialogInterface dialog) { @@ -443,9 +459,7 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem hiddenDrawerItems.add(NAV_DRAWER_TAGS[which]); } }); - builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> { - UserPreferences.setHiddenDrawerItems(hiddenDrawerItems); - }); + builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> UserPreferences.setHiddenDrawerItems(hiddenDrawerItems)); builder.setNegativeButton(R.string.cancel_label, null); builder.create().show(); } @@ -461,12 +475,20 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem if (navAdapter != null) { navAdapter.notifyDataSetChanged(); } - }, error -> { - Log.e(TAG, Log.getStackTraceString(error)); - }); + }, error -> Log.e(TAG, Log.getStackTraceString(error))); } - + public void onEventMainThread(MessageEvent event) { + Log.d(TAG, "onEvent(" + event + ")"); + View parentLayout = findViewById(R.id.drawer_layout); + Snackbar snackbar = Snackbar.make(parentLayout, event.message, Snackbar.LENGTH_SHORT); + if (event.action != null) { + snackbar.setAction(getString(R.string.undo), v -> { + event.action.run(); + }); + } + snackbar.show(); + } private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() { diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java index a53f9bdb8..f6bf11e66 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java @@ -29,7 +29,6 @@ import com.bumptech.glide.Glide; import org.apache.commons.lang3.StringUtils; import org.jsoup.Jsoup; -import org.jsoup.examples.HtmlToPlainText; import org.jsoup.nodes.Document; import java.io.File; @@ -63,6 +62,7 @@ import de.danoeh.antennapod.core.util.FileNameGenerator; import de.danoeh.antennapod.core.util.StorageUtils; import de.danoeh.antennapod.core.util.URLChecker; import de.danoeh.antennapod.core.util.syndication.FeedDiscoverer; +import de.danoeh.antennapod.core.util.syndication.HtmlToPlainText; import de.danoeh.antennapod.dialog.AuthenticationDialog; import de.greenrobot.event.EventBus; import rx.Observable; @@ -81,17 +81,12 @@ import rx.schedulers.Schedulers; */ public class OnlineFeedViewActivity extends AppCompatActivity { - private static final String TAG = "OnlineFeedViewActivity"; - public static final String ARG_FEEDURL = "arg.feedurl"; - // Optional argument: specify a title for the actionbar. public static final String ARG_TITLE = "title"; - - private static final int EVENTS = EventDistributor.FEED_LIST_UPDATE; - public static final int RESULT_ERROR = 2; - + private static final String TAG = "OnlineFeedViewActivity"; + private static final int EVENTS = EventDistributor.FEED_LIST_UPDATE; private volatile List<Feed> feeds; private Feed feed; private String selectedDownloadUrl; @@ -106,22 +101,19 @@ public class OnlineFeedViewActivity extends AppCompatActivity { private Subscription download; private Subscription parser; private Subscription updater; - - public void onEventMainThread(DownloadEvent event) { - Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]"); - setSubscribeButtonState(feed); - } - private EventDistributor.EventListener listener = new EventDistributor.EventListener() { @Override public void update(EventDistributor eventDistributor, Integer arg) { if ((arg & EventDistributor.FEED_LIST_UPDATE) != 0) { - updater = Observable.fromCallable(() -> DBReader.getFeedList()) + updater = Observable.fromCallable(DBReader::getFeedList) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(feeds -> { + .subscribe( + feeds -> { OnlineFeedViewActivity.this.feeds = feeds; setSubscribeButtonState(feed); + }, error -> { + Log.e(TAG, Log.getStackTraceString(error)); } ); } else if ((arg & EVENTS) != 0) { @@ -130,6 +122,11 @@ public class OnlineFeedViewActivity extends AppCompatActivity { } }; + public void onEventMainThread(DownloadEvent event) { + Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]"); + setSubscribeButtonState(feed); + } + @Override protected void onCreate(Bundle savedInstanceState) { setTheme(UserPreferences.getTheme()); @@ -149,7 +146,7 @@ public class OnlineFeedViewActivity extends AppCompatActivity { || TextUtils.equals(getIntent().getAction(), Intent.ACTION_VIEW)) { feedUrl = (TextUtils.equals(getIntent().getAction(), Intent.ACTION_SEND)) ? getIntent().getStringExtra(Intent.EXTRA_TEXT) : getIntent().getDataString(); - getSupportActionBar().setTitle(R.string.add_new_feed_label); + getSupportActionBar().setTitle(R.string.add_feed_label); } else { throw new IllegalArgumentException("Activity must be started with feedurl argument!"); } @@ -281,30 +278,33 @@ public class OnlineFeedViewActivity extends AppCompatActivity { }) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(status -> { - if (status != null) { - if (!status.isCancelled()) { - if (status.isSuccessful()) { - parseFeed(); - } else if (status.getReason() == DownloadError.ERROR_UNAUTHORIZED) { - if (!isFinishing() && !isPaused) { - dialog = new FeedViewAuthenticationDialog(OnlineFeedViewActivity.this, - R.string.authentication_notification_title, downloader.getDownloadRequest().getSource()); - dialog.show(); - } - } else { - String errorMsg = status.getReason().getErrorString(OnlineFeedViewActivity.this); - if (errorMsg != null && status.getReasonDetailed() != null) { - errorMsg += " (" + status.getReasonDetailed() + ")"; - } - showErrorDialog(errorMsg); - } - } - } else { - Log.wtf(TAG, "DownloadStatus returned by Downloader was null"); - finish(); - } - }); + .subscribe(this::checkDownloadResult, + error -> Log.e(TAG, Log.getStackTraceString(error))); + } + + private void checkDownloadResult(DownloadStatus status) { + if (status == null) { + Log.wtf(TAG, "DownloadStatus returned by Downloader was null"); + finish(); + } + if (status.isCancelled()) { + return; + } + if (status.isSuccessful()) { + parseFeed(); + } else if (status.getReason() == DownloadError.ERROR_UNAUTHORIZED) { + if (!isFinishing() && !isPaused) { + dialog = new FeedViewAuthenticationDialog(OnlineFeedViewActivity.this, + R.string.authentication_notification_title, downloader.getDownloadRequest().getSource()); + dialog.show(); + } + } else { + String errorMsg = status.getReason().getErrorString(OnlineFeedViewActivity.this); + if (errorMsg != null && status.getReasonDetailed() != null) { + errorMsg += " (" + status.getReasonDetailed() + ")"; + } + showErrorDialog(errorMsg); + } } private void parseFeed() { @@ -354,14 +354,19 @@ public class OnlineFeedViewActivity extends AppCompatActivity { * This method is executed on a background thread */ private void beforeShowFeedInformation(Feed feed) { - // remove HTML tags from descriptions + final HtmlToPlainText formatter = new HtmlToPlainText(); + if(Feed.TYPE_ATOM1.equals(feed.getType()) && feed.getDescription() != null) { + // remove HTML tags from descriptions + Log.d(TAG, "Removing HTML from feed description"); + Document feedDescription = Jsoup.parse(feed.getDescription()); + feed.setDescription(StringUtils.trim(formatter.getPlainText(feedDescription))); + } Log.d(TAG, "Removing HTML from shownotes"); if (feed.getItems() != null) { - HtmlToPlainText formatter = new HtmlToPlainText(); for (FeedItem item : feed.getItems()) { if (item.getDescription() != null) { - Document description = Jsoup.parse(item.getDescription()); - item.setDescription(StringUtils.trim(formatter.getPlainText(description))); + Document itemDescription = Jsoup.parse(item.getDescription()); + item.setDescription(StringUtils.trim(formatter.getPlainText(itemDescription))); } } } @@ -514,9 +519,7 @@ public class OnlineFeedViewActivity extends AppCompatActivity { builder.setMessage(R.string.error_msg_prefix); } builder.setNeutralButton(android.R.string.ok, - (dialog, which) -> { - dialog.cancel(); - } + (dialog, which) -> dialog.cancel() ); builder.setOnCancelListener(dialog -> { setResult(RESULT_ERROR); @@ -585,7 +588,7 @@ public class OnlineFeedViewActivity extends AppCompatActivity { private String feedUrl; - public FeedViewAuthenticationDialog(Context context, int titleRes, String feedUrl) { + FeedViewAuthenticationDialog(Context context, int titleRes, String feedUrl) { super(context, titleRes, true, false, null, null); this.feedUrl = feedUrl; } diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OpmlFeedChooserActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OpmlFeedChooserActivity.java index fce50bd1c..cd375a65a 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/OpmlFeedChooserActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/OpmlFeedChooserActivity.java @@ -15,7 +15,7 @@ import java.util.ArrayList; import java.util.List; import de.danoeh.antennapod.R; -import de.danoeh.antennapod.core.opml.OpmlElement; +import de.danoeh.antennapod.core.export.opml.OpmlElement; import de.danoeh.antennapod.core.preferences.UserPreferences; /** @@ -23,10 +23,8 @@ import de.danoeh.antennapod.core.preferences.UserPreferences; * which feeds he wants to import. */ public class OpmlFeedChooserActivity extends AppCompatActivity { - private static final String TAG = "OpmlFeedChooserActivity"; - public static final String EXTRA_SELECTED_ITEMS = "de.danoeh.antennapod.selectedItems"; - + private static final String TAG = "OpmlFeedChooserActivity"; private Button butConfirm; private Button butCancel; private ListView feedlist; diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportBaseActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportBaseActivity.java index 8726af281..07b0b3cdb 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportBaseActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportBaseActivity.java @@ -3,6 +3,7 @@ package de.danoeh.antennapod.activity; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; +import android.os.Build; import android.os.Environment; import android.support.annotation.Nullable; import android.support.v4.app.ActivityCompat; @@ -20,7 +21,7 @@ import java.util.ArrayList; import de.danoeh.antennapod.R; import de.danoeh.antennapod.asynctask.OpmlFeedQueuer; import de.danoeh.antennapod.asynctask.OpmlImportWorker; -import de.danoeh.antennapod.core.opml.OpmlElement; +import de.danoeh.antennapod.core.export.opml.OpmlElement; import de.danoeh.antennapod.core.util.LangUtils; /** @@ -29,9 +30,8 @@ import de.danoeh.antennapod.core.util.LangUtils; public class OpmlImportBaseActivity extends AppCompatActivity { private static final String TAG = "OpmlImportBaseActivity"; - private OpmlImportWorker importWorker; - private static final int PERMISSION_REQUEST_READ_EXTERNAL_STORAGE = 5; + private OpmlImportWorker importWorker; @Nullable private Uri uri; /** @@ -77,7 +77,8 @@ public class OpmlImportBaseActivity extends AppCompatActivity { return; } this.uri = uri; - if(uri.toString().contains(Environment.getExternalStorageDirectory().toString())) { + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && + uri.toString().contains(Environment.getExternalStorageDirectory().toString())) { int permission = ActivityCompat.checkSelfPermission(this, android.Manifest.permission.READ_EXTERNAL_STORAGE); if (permission != PackageManager.PERMISSION_GRANTED) { requestPermission(); diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromIntentActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromIntentActivity.java index 02e16a7b5..4c94e2b76 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromIntentActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromIntentActivity.java @@ -1,25 +1,30 @@ package de.danoeh.antennapod.activity; +import android.content.Intent; import android.net.Uri; import android.os.Bundle; import de.danoeh.antennapod.core.preferences.UserPreferences; -/** Lets the user start the OPML-import process. */ +/** + * Lets the user start the OPML-import process. + */ public class OpmlImportFromIntentActivity extends OpmlImportBaseActivity { private static final String TAG = "OpmlImportFromIntentAct"; @Override - protected void onCreate(Bundle savedInstanceState) { - setTheme(UserPreferences.getTheme()); - super.onCreate(savedInstanceState); + protected void onCreate(Bundle savedInstanceState) { + setTheme(UserPreferences.getTheme()); + super.onCreate(savedInstanceState); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); Uri uri = getIntent().getData(); - if(uri.toString().startsWith("/")) { + if (uri != null && uri.toString().startsWith("/")) { uri = Uri.parse("file://" + uri.toString()); + } else { + uri = Uri.parse(getIntent().getStringExtra(Intent.EXTRA_TEXT)); } importUri(uri); } diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromPathActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromPathActivity.java index b2dab7f68..eb6b473d2 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromPathActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromPathActivity.java @@ -135,7 +135,7 @@ public class OpmlImportFromPathActivity extends OpmlImportBaseActivity { super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK && requestCode == CHOOSE_OPML_FILE) { Uri uri = data.getData(); - if(uri.toString().startsWith("/")) { + if(uri != null && uri.toString().startsWith("/")) { uri = Uri.parse("file://" + uri.toString()); } importUri(uri); diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportHolder.java b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportHolder.java index 3a1a7be05..dc5570dc0 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportHolder.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportHolder.java @@ -1,9 +1,9 @@ package de.danoeh.antennapod.activity; -import de.danoeh.antennapod.core.opml.OpmlElement; - import java.util.ArrayList; +import de.danoeh.antennapod.core.export.opml.OpmlElement; + /** * Hold infos gathered by Ompl-Import * <p/> diff --git a/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java index ba22a42b4..dd932814f 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java @@ -26,11 +26,9 @@ import de.danoeh.antennapod.preferences.PreferenceController; */ public class PreferenceActivity extends AppCompatActivity { + private static WeakReference<PreferenceActivity> instance; private PreferenceController preferenceController; private MainFragment prefFragment; - private static WeakReference<PreferenceActivity> instance; - - private final PreferenceController.PreferenceUI preferenceUI = new PreferenceController.PreferenceUI() { @TargetApi(Build.VERSION_CODES.HONEYCOMB) @Override @@ -103,6 +101,7 @@ public class PreferenceActivity extends AppCompatActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + setRetainInstance(true); addPreferencesFromResource(R.xml.preferences); PreferenceActivity activity = instance.get(); if(activity != null && activity.preferenceController != null) { @@ -118,5 +117,23 @@ public class PreferenceActivity extends AppCompatActivity { activity.preferenceController.onResume(); } } + + @Override + public void onPause() { + PreferenceActivity activity = instance.get(); + if(activity != null && activity.preferenceController != null) { + activity.preferenceController.onPause(); + } + super.onPause(); + } + + @Override + public void onStop() { + PreferenceActivity activity = instance.get(); + if(activity != null && activity.preferenceController != null) { + activity.preferenceController.onStop(); + } + super.onStop(); + } } } diff --git a/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivityGingerbread.java b/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivityGingerbread.java index 633f8d66d..390bec15c 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivityGingerbread.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivityGingerbread.java @@ -18,9 +18,6 @@ import de.danoeh.antennapod.preferences.PreferenceController; */ public class PreferenceActivityGingerbread extends android.preference.PreferenceActivity { private static final String TAG = "PreferenceActivity"; - - private PreferenceController preferenceController; - private final PreferenceController.PreferenceUI preferenceUI = new PreferenceController.PreferenceUI() { @SuppressWarnings("deprecation") @@ -34,6 +31,7 @@ public class PreferenceActivityGingerbread extends android.preference.Preference return PreferenceActivityGingerbread.this; } }; + private PreferenceController preferenceController; @SuppressLint("NewApi") @SuppressWarnings("deprecation") @@ -55,6 +53,18 @@ public class PreferenceActivityGingerbread extends android.preference.Preference } @Override + protected void onPause() { + preferenceController.onPause(); + super.onPause(); + } + + @Override + protected void onStop() { + preferenceController.onStop(); + super.onStop(); + } + + @Override protected void onApplyThemeResource(Theme theme, int resid, boolean first) { theme.applyStyle(UserPreferences.getTheme(), true); } diff --git a/app/src/main/java/de/danoeh/antennapod/activity/SplashActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/SplashActivity.java new file mode 100644 index 000000000..b92ac8577 --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/activity/SplashActivity.java @@ -0,0 +1,23 @@ +package de.danoeh.antennapod.activity; + +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.app.AppCompatActivity; + +/** + * Creator: vbarad + * Date: 2016-12-03 + * Project: AntennaPod + */ + +public class SplashActivity extends AppCompatActivity { + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Intent intent = new Intent(this, MainActivity.class); + startActivity(intent); + finish(); + } +} diff --git a/app/src/main/java/de/danoeh/antennapod/activity/StatisticsActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/StatisticsActivity.java index 0254617e4..b2ff43c43 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/StatisticsActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/StatisticsActivity.java @@ -1,14 +1,18 @@ package de.danoeh.antennapod.activity; +import android.content.SharedPreferences; import android.os.Bundle; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.util.Log; +import android.view.Menu; +import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.ListView; import android.widget.ProgressBar; +import android.widget.RadioButton; import android.widget.TextView; import de.danoeh.antennapod.R; @@ -28,12 +32,16 @@ public class StatisticsActivity extends AppCompatActivity implements AdapterView.OnItemClickListener { private static final String TAG = StatisticsActivity.class.getSimpleName(); + private static final String PREF_NAME = "StatisticsActivityPrefs"; + private static final String PREF_COUNT_ALL = "countAll"; private Subscription subscription; private TextView totalTimeTextView; private ListView feedStatisticsList; private ProgressBar progressBar; private StatisticsListAdapter listAdapter; + private boolean countAll = false; + private SharedPreferences prefs; @Override protected void onCreate(Bundle savedInstanceState) { @@ -42,10 +50,14 @@ public class StatisticsActivity extends AppCompatActivity getSupportActionBar().setDisplayShowHomeEnabled(true); setContentView(R.layout.statistics_activity); + prefs = getSharedPreferences(PREF_NAME, MODE_PRIVATE); + countAll = prefs.getBoolean(PREF_COUNT_ALL, false); + totalTimeTextView = (TextView) findViewById(R.id.total_time); feedStatisticsList = (ListView) findViewById(R.id.statistics_list); progressBar = (ProgressBar) findViewById(R.id.progressBar); listAdapter = new StatisticsListAdapter(this); + listAdapter.setCountAll(countAll); feedStatisticsList.setAdapter(listAdapter); feedStatisticsList.setOnItemClickListener(this); } @@ -53,10 +65,15 @@ public class StatisticsActivity extends AppCompatActivity @Override public void onResume() { super.onResume(); - progressBar.setVisibility(View.VISIBLE); - totalTimeTextView.setVisibility(View.GONE); - feedStatisticsList.setVisibility(View.GONE); - loadStats(); + refreshStatistics(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + super.onCreateOptionsMenu(menu); + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.statistics, menu); + return true; } @Override @@ -64,30 +81,60 @@ public class StatisticsActivity extends AppCompatActivity if (item.getItemId() == android.R.id.home) { finish(); return true; + } else if (item.getItemId() == R.id.statistics_mode) { + selectStatisticsMode(); + return true; } else { return super.onOptionsItemSelected(item); } } - private void loadStats() { - if(subscription != null) { + private void selectStatisticsMode() { + View contentView = View.inflate(this, R.layout.statistics_mode_select_dialog, null); + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setView(contentView); + builder.setTitle(R.string.statistics_mode); + + if (countAll) { + ((RadioButton) contentView.findViewById(R.id.statistics_mode_count_all)).setChecked(true); + } else { + ((RadioButton) contentView.findViewById(R.id.statistics_mode_normal)).setChecked(true); + } + + builder.setPositiveButton(android.R.string.ok, (dialog, which) -> { + countAll = ((RadioButton) contentView.findViewById(R.id.statistics_mode_count_all)).isChecked(); + listAdapter.setCountAll(countAll); + prefs.edit().putBoolean(PREF_COUNT_ALL, countAll).apply(); + refreshStatistics(); + }); + + builder.show(); + } + + private void refreshStatistics() { + progressBar.setVisibility(View.VISIBLE); + totalTimeTextView.setVisibility(View.GONE); + feedStatisticsList.setVisibility(View.GONE); + loadStatistics(); + } + + private void loadStatistics() { + if (subscription != null) { subscription.unsubscribe(); } - subscription = Observable.fromCallable(() -> DBReader.getStatistics()) + subscription = Observable.fromCallable(() -> DBReader.getStatistics(countAll)) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(result -> { if (result != null) { totalTimeTextView.setText(Converter - .shortLocalizedDuration(this, result.totalTime)); + .shortLocalizedDuration(this, countAll ? result.totalTimeCountAll : result.totalTime)); listAdapter.update(result.feedTime); progressBar.setVisibility(View.GONE); totalTimeTextView.setVisibility(View.VISIBLE); feedStatisticsList.setVisibility(View.VISIBLE); } - }, error -> { - Log.e(TAG, Log.getStackTraceString(error)); - }); + }, error -> Log.e(TAG, Log.getStackTraceString(error))); } @Override @@ -97,9 +144,10 @@ public class StatisticsActivity extends AppCompatActivity AlertDialog.Builder dialog = new AlertDialog.Builder(this); dialog.setTitle(stats.feed.getTitle()); dialog.setMessage(getString(R.string.statistics_details_dialog, - stats.episodesStarted, + countAll ? stats.episodesStartedIncludingMarked : stats.episodesStarted, stats.episodes, - Converter.shortLocalizedDuration(this, stats.timePlayed), + Converter.shortLocalizedDuration(this, countAll ? + stats.timePlayedCountAll : stats.timePlayed), Converter.shortLocalizedDuration(this, stats.time))); dialog.setPositiveButton(android.R.string.ok, null); dialog.show(); diff --git a/app/src/main/java/de/danoeh/antennapod/activity/StorageErrorActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/StorageErrorActivity.java index 81d727283..62bff0891 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/StorageErrorActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/StorageErrorActivity.java @@ -55,7 +55,7 @@ public class StorageErrorActivity extends AppCompatActivity { openDirectoryChooser(); } }); - if (Build.VERSION.SDK_INT == Build.VERSION_CODES.M) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { int readPermission = ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE); int writePermission = ActivityCompat.checkSelfPermission(this, diff --git a/app/src/main/java/de/danoeh/antennapod/activity/gpoddernet/GpodnetAuthenticationActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/gpoddernet/GpodnetAuthenticationActivity.java index d46a3d6c2..8ede947c5 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/gpoddernet/GpodnetAuthenticationActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/gpoddernet/GpodnetAuthenticationActivity.java @@ -6,11 +6,13 @@ import android.content.res.Configuration; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; -import android.support.v7.app.ActionBarActivity; +import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; @@ -40,7 +42,7 @@ import de.danoeh.antennapod.core.service.GpodnetSyncService; * Step 2: Choose device from a list of available devices or create a new one * Step 3: Choose from a list of actions */ -public class GpodnetAuthenticationActivity extends ActionBarActivity { +public class GpodnetAuthenticationActivity extends AppCompatActivity { private static final String TAG = "GpodnetAuthActivity"; private static final String CURRENT_STEP = "current_step"; @@ -113,6 +115,9 @@ public class GpodnetAuthenticationActivity extends ActionBarActivity { final TextView txtvError = (TextView) view.findViewById(R.id.txtvError); final ProgressBar progressBar = (ProgressBar) view.findViewById(R.id.progBarLogin); + password.setOnEditorActionListener((v, actionID, event) -> + actionID == EditorInfo.IME_ACTION_GO && login.performClick()); + login.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -131,6 +136,11 @@ public class GpodnetAuthenticationActivity extends ActionBarActivity { login.setEnabled(false); progressBar.setVisibility(View.VISIBLE); txtvError.setVisibility(View.GONE); + // hide the keyboard + InputMethodManager inputManager = (InputMethodManager) + getSystemService(Context.INPUT_METHOD_SERVICE); + inputManager.hideSoftInputFromWindow(login.getWindowToken(), + InputMethodManager.HIDE_NOT_ALWAYS); } diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonCallback.java b/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonCallback.java index 66e6f9a00..c18564351 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonCallback.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonCallback.java @@ -1,8 +1,9 @@ package de.danoeh.antennapod.adapter; import de.danoeh.antennapod.core.feed.FeedItem; +import de.danoeh.antennapod.core.util.LongList; public interface ActionButtonCallback { /** Is called when the action button of a list item has been pressed. */ - void onActionButtonPressed(FeedItem item); + void onActionButtonPressed(FeedItem item, LongList queueIds); } diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonUtils.java b/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonUtils.java index 1a8f0a67a..f0210f983 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonUtils.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonUtils.java @@ -47,6 +47,7 @@ public class ActionButtonUtils { * Sets the displayed bitmap and content description of the given * action button so that it matches the state of the FeedItem. */ + @SuppressWarnings("ResourceType") public void configureActionButton(ImageButton butSecondary, FeedItem item, boolean isInQueue) { Validate.isTrue(butSecondary != null && item != null, "butSecondary or item was null"); @@ -57,8 +58,7 @@ public class ActionButtonUtils { if (isDownloadingMedia) { // item is being downloaded butSecondary.setVisibility(View.VISIBLE); - butSecondary.setImageDrawable(drawables - .getDrawable(1)); + butSecondary.setImageDrawable(drawables.getDrawable(1)); butSecondary.setContentDescription(context.getString(labels[1])); } else { // item is not downloaded and not being downloaded diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/AdapterUtils.java b/app/src/main/java/de/danoeh/antennapod/adapter/AdapterUtils.java index 8aaf0055a..5c58d00f2 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/AdapterUtils.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/AdapterUtils.java @@ -15,7 +15,7 @@ import de.danoeh.antennapod.core.util.NetworkUtils; /** * Utility methods for adapters */ -public class AdapterUtils { +class AdapterUtils { private static final String TAG = AdapterUtils.class.getSimpleName(); @@ -26,7 +26,7 @@ public class AdapterUtils { /** * Updates the contents of the TextView that shows the current playback position and the ProgressBar. */ - public static void updateEpisodePlaybackProgress(FeedItem item, TextView txtvPos, ProgressBar episodeProgress) { + static void updateEpisodePlaybackProgress(FeedItem item, TextView txtvPos, ProgressBar episodeProgress) { FeedMedia media = item.getMedia(); episodeProgress.setVisibility(View.GONE); if (media == null) { @@ -47,7 +47,6 @@ public class AdapterUtils { - media.getPosition())); } } else if (!media.isDownloaded()) { - Log.d(TAG, "size: " + media.getSize()); if (media.getSize() > 0) { txtvPos.setText(Converter.byteToString(media.getSize())); } else if(NetworkUtils.isDownloadAllowed() && !media.checkedOnSizeButUnknown()) { diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java index 43a00f7c5..3e8bbc488 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java @@ -200,11 +200,11 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR holder.butSecondary.setOnClickListener(secondaryActionListener); Glide.with(mainActivityRef.get()) - .load(item.getImageUri()) + .load(item.getImageLocation()) .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) .fitCenter() .dontAnimate() - .into(new CoverTarget(item.getFeed().getImageUri(), holder.placeholder, holder.cover, mainActivityRef.get())); + .into(new CoverTarget(item.getFeed().getImageLocation(), holder.placeholder, holder.cover, mainActivityRef.get())); } @Override @@ -232,7 +232,7 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR @Override public void onClick(View v) { FeedItem item = (FeedItem) v.getTag(); - actionButtonCallback.onActionButtonPressed(item); + actionButtonCallback.onActionButtonPressed(item, itemAccess.getQueueIds()); } }; @@ -319,6 +319,8 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR boolean isInQueue(FeedItem item); + LongList getQueueIds(); + } /** diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java index 37e00ab74..d7bebb672 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java @@ -60,6 +60,7 @@ public class ChaptersListAdapter extends ArrayAdapter<Chapter> { defaultTextColor = holder.title.getTextColors().getDefaultColor(); holder.start = (TextView) convertView.findViewById(R.id.txtvStart); holder.link = (TextView) convertView.findViewById(R.id.txtvLink); + holder.duration = (TextView) convertView.findViewById(R.id.txtvDuration); holder.butPlayChapter = (ImageButton) convertView.findViewById(R.id.butPlayChapter); convertView.setTag(holder); } else { @@ -70,6 +71,16 @@ public class ChaptersListAdapter extends ArrayAdapter<Chapter> { holder.title.setText(sc.getTitle()); holder.start.setText(Converter.getDurationStringLong((int) sc .getStart())); + + long duration; + if (position + 1 < media.getChapters().size()) { + duration = media.getChapters().get(position + 1).getStart() - sc.getStart(); + } else { + duration = media.getDuration() - sc.getStart(); + } + holder.duration.setText(getContext().getString(R.string.chapter_duration, + Converter.getDurationStringLong((int) duration))); + if (sc.getLink() != null) { holder.link.setVisibility(View.VISIBLE); holder.link.setText(sc.getLink()); @@ -155,6 +166,7 @@ public class ChaptersListAdapter extends ArrayAdapter<Chapter> { TextView title; TextView start; TextView link; + TextView duration; ImageButton butPlayChapter; } diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/CoverTarget.java b/app/src/main/java/de/danoeh/antennapod/adapter/CoverTarget.java index ed0c08086..538af8c79 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/CoverTarget.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/CoverTarget.java @@ -18,12 +18,12 @@ import de.danoeh.antennapod.core.glide.ApGlideSettings; class CoverTarget extends GlideDrawableImageViewTarget { - private final WeakReference<Uri> fallback; + private final WeakReference<String> fallback; private final WeakReference<TextView> placeholder; private final WeakReference<ImageView> cover; private final WeakReference<MainActivity> mainActivity; - public CoverTarget(Uri fallbackUri, TextView txtvPlaceholder, ImageView imgvCover, MainActivity activity) { + public CoverTarget(String fallbackUri, TextView txtvPlaceholder, ImageView imgvCover, MainActivity activity) { super(imgvCover); fallback = new WeakReference<>(fallbackUri); placeholder = new WeakReference<>(txtvPlaceholder); @@ -33,7 +33,7 @@ class CoverTarget extends GlideDrawableImageViewTarget { @Override public void onLoadFailed(Exception e, Drawable errorDrawable) { - Uri fallbackUri = fallback.get(); + String fallbackUri = fallback.get(); TextView txtvPlaceholder = placeholder.get(); ImageView imgvCover = cover.get(); if (fallbackUri != null && txtvPlaceholder != null && imgvCover != null) { @@ -48,7 +48,7 @@ class CoverTarget extends GlideDrawableImageViewTarget { } @Override - public void onResourceReady(GlideDrawable drawable, GlideAnimation anim) { + public void onResourceReady(GlideDrawable drawable, GlideAnimation<? super GlideDrawable> anim) { super.onResourceReady(drawable, anim); TextView txtvPlaceholder = placeholder.get(); if (txtvPlaceholder != null) { diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java b/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java index 00ab96f6c..4a53be9dc 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java @@ -51,13 +51,12 @@ public class DefaultActionButtonCallback implements ActionButtonCallback { } @Override - public void onActionButtonPressed(final FeedItem item) { + public void onActionButtonPressed(final FeedItem item, final LongList queueIds) { if (item.hasMedia()) { final FeedMedia media = item.getMedia(); boolean isDownloading = DownloadRequester.getInstance().isDownloadingFile(media); if (!isDownloading && !media.isDownloaded()) { - LongList queueIds = DBReader.getQueueIDList(); if (NetworkUtils.isDownloadAllowed() || userAllowedMobileDownloads()) { try { DBTasks.downloadFeedItems(context, item); diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java index 6d0beff9e..6907e467b 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java @@ -12,6 +12,7 @@ import android.widget.ImageView; import android.widget.TextView; import com.bumptech.glide.Glide; +import com.nineoldandroids.view.ViewHelper; import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.feed.FeedItem; @@ -77,7 +78,7 @@ public class DownloadedEpisodesListAdapter extends BaseAdapter { } Glide.with(context) - .load(item.getImageUri()) + .load(item.getImageLocation()) .placeholder(R.color.light_gray) .error(R.color.light_gray) .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) @@ -85,6 +86,12 @@ public class DownloadedEpisodesListAdapter extends BaseAdapter { .dontAnimate() .into(holder.imageView); + if(item.isPlayed()) { + ViewHelper.setAlpha(convertView, 0.5f); + } else { + ViewHelper.setAlpha(convertView, 1.0f); + } + holder.title.setText(item.getTitle()); holder.txtvSize.setText(Converter.byteToString(item.getMedia().getSize())); holder.queueStatus.setVisibility(item.isTagged(FeedItem.TAG_QUEUE) ? View.VISIBLE : View.GONE); diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java index 4e9c5d71b..35c42725c 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java @@ -26,6 +26,7 @@ import de.danoeh.antennapod.core.feed.MediaType; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.storage.DownloadRequester; import de.danoeh.antennapod.core.util.DateUtils; +import de.danoeh.antennapod.core.util.LongList; import de.danoeh.antennapod.core.util.ThemeUtils; /** @@ -86,6 +87,7 @@ public class FeedItemlistAdapter extends BaseAdapter { } @Override + @SuppressWarnings("ResourceType") public View getView(final int position, View convertView, ViewGroup parent) { Holder holder; final FeedItem item = getItem(position); @@ -219,7 +221,7 @@ public class FeedItemlistAdapter extends BaseAdapter { @Override public void onClick(View v) { FeedItem item = (FeedItem) v.getTag(); - callback.onActionButtonPressed(item); + callback.onActionButtonPressed(item, itemAccess.getQueueIds()); } }; @@ -243,6 +245,8 @@ public class FeedItemlistAdapter extends BaseAdapter { FeedItem getItem(int position); + LongList getQueueIds(); + } } diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java index 75c858ec6..465497b55 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java @@ -1,5 +1,6 @@ package de.danoeh.antennapod.adapter; +import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.content.res.TypedArray; @@ -21,6 +22,7 @@ import com.joanzapata.iconify.widget.IconTextView; import org.apache.commons.lang3.ArrayUtils; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -45,6 +47,7 @@ import de.danoeh.antennapod.fragment.SubscriptionFragment; */ public class NavListAdapter extends BaseAdapter implements SharedPreferences.OnSharedPreferenceChangeListener { + public static final int VIEW_TYPE_COUNT = 3; public static final int VIEW_TYPE_NAV = 0; public static final int VIEW_TYPE_SECTION_DIVIDER = 1; @@ -60,12 +63,12 @@ public class NavListAdapter extends BaseAdapter private static String[] titles; private ItemAccess itemAccess; - private Context context; + private WeakReference<Activity> activity; private boolean showSubscriptionList = true; - public NavListAdapter(ItemAccess itemAccess, Context context) { + public NavListAdapter(ItemAccess itemAccess, Activity context) { this.itemAccess = itemAccess; - this.context = context; + this.activity = new WeakReference<>(context); titles = context.getResources().getStringArray(R.array.nav_drawer_titles); loadItems(); @@ -108,6 +111,10 @@ public class NavListAdapter extends BaseAdapter } private Drawable getDrawable(String tag) { + Activity context = activity.get(); + if(context == null) { + return null; + } int icon; switch (tag) { case QueueFragment.TAG: @@ -218,6 +225,10 @@ public class NavListAdapter extends BaseAdapter } private View getNavView(String title, int position, View convertView, ViewGroup parent) { + Activity context = activity.get(); + if(context == null) { + return null; + } NavHolder holder; if (convertView == null) { holder = new NavHolder(); @@ -236,30 +247,28 @@ public class NavListAdapter extends BaseAdapter holder.title.setText(title); + // reset for re-use + holder.count.setVisibility(View.GONE); + holder.count.setOnClickListener(null); + String tag = tags.get(position); if (tag.equals(QueueFragment.TAG)) { int queueSize = itemAccess.getQueueSize(); if (queueSize > 0) { - holder.count.setVisibility(View.VISIBLE); holder.count.setText(String.valueOf(queueSize)); - } else { - holder.count.setVisibility(View.GONE); + holder.count.setVisibility(View.VISIBLE); } } else if (tag.equals(EpisodesFragment.TAG)) { int unreadItems = itemAccess.getNumberOfNewItems(); if (unreadItems > 0) { - holder.count.setVisibility(View.VISIBLE); holder.count.setText(String.valueOf(unreadItems)); - } else { - holder.count.setVisibility(View.GONE); + holder.count.setVisibility(View.VISIBLE); } } else if (tag.equals(SubscriptionFragment.TAG)) { int sum = itemAccess.getFeedCounterSum(); if (sum > 0) { - holder.count.setVisibility(View.VISIBLE); holder.count.setText(String.valueOf(sum)); - } else { - holder.count.setVisibility(View.GONE); + holder.count.setVisibility(View.VISIBLE); } } else if(tag.equals(DownloadsFragment.TAG) && UserPreferences.isEnableAutodownload()) { int epCacheSize = UserPreferences.getEpisodeCacheSize(); @@ -278,11 +287,7 @@ public class NavListAdapter extends BaseAdapter .setPositiveButton(android.R.string.ok, (dialog, which) -> {}) .show() ); - } else { - holder.count.setVisibility(View.GONE); } - } else { - holder.count.setVisibility(View.GONE); } holder.image.setImageDrawable(getDrawable(tags.get(position))); @@ -291,6 +296,10 @@ public class NavListAdapter extends BaseAdapter } private View getSectionDividerView(View convertView, ViewGroup parent) { + Activity context = activity.get(); + if(context == null) { + return null; + } LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); @@ -303,6 +312,10 @@ public class NavListAdapter extends BaseAdapter } private View getFeedView(int position, View convertView, ViewGroup parent) { + Activity context = activity.get(); + if(context == null) { + return null; + } int feedPos = position - getSubscriptionOffset(); Feed feed = itemAccess.getItem(feedPos); @@ -324,7 +337,7 @@ public class NavListAdapter extends BaseAdapter } Glide.with(context) - .load(feed.getImageUri()) + .load(feed.getImageLocation()) .placeholder(R.color.light_gray) .error(R.color.light_gray) .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java index 796ac4184..c6ddc6c86 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java @@ -296,11 +296,11 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap butSecondary.setOnClickListener(secondaryActionListener); Glide.with(mainActivity.get()) - .load(item.getImageUri()) + .load(item.getImageLocation()) .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) .fitCenter() .dontAnimate() - .into(new CoverTarget(item.getFeed().getImageUri(), placeholder, cover, mainActivity.get())); + .into(new CoverTarget(item.getFeed().getImageLocation(), placeholder, cover, mainActivity.get())); } } @@ -309,7 +309,7 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap @Override public void onClick(View v) { FeedItem item = (FeedItem) v.getTag(); - actionButtonCallback.onActionButtonPressed(item); + actionButtonCallback.onActionButtonPressed(item, itemAccess.getQueueIds()); } }; diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/SearchlistAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/SearchlistAdapter.java index a68ef01d9..8e1aa24e0 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/SearchlistAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/SearchlistAdapter.java @@ -11,6 +11,7 @@ import android.widget.ImageView; import android.widget.TextView; import com.bumptech.glide.Glide; +import com.nineoldandroids.view.ViewHelper; import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.feed.Feed; @@ -80,7 +81,7 @@ public class SearchlistAdapter extends BaseAdapter { holder.subtitle.setVisibility(View.GONE); Glide.with(context) - .load(feed.getImageUri()) + .load(feed.getImageLocation()) .placeholder(R.color.light_gray) .error(R.color.light_gray) .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) @@ -96,8 +97,10 @@ public class SearchlistAdapter extends BaseAdapter { holder.subtitle.setText(result.getSubtitle()); } + ViewHelper.setAlpha(convertView, item.isPlayed() ? 0.5f : 1.0f); + Glide.with(context) - .load(item.getFeed().getImageUri()) + .load(item.getFeed().getImageLocation()) .placeholder(R.color.light_gray) .error(R.color.light_gray) .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/StatisticsListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/StatisticsListAdapter.java index 7fb1472ad..c060083a6 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/StatisticsListAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/StatisticsListAdapter.java @@ -9,11 +9,9 @@ import android.widget.ImageView; import android.widget.TextView; import com.bumptech.glide.Glide; -import com.joanzapata.iconify.widget.IconTextView; import java.util.ArrayList; import java.util.List; -import java.util.Locale; import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.feed.Feed; @@ -27,11 +25,15 @@ import de.danoeh.antennapod.core.util.Converter; public class StatisticsListAdapter extends BaseAdapter { private Context context; List<DBReader.StatisticsItem> feedTime = new ArrayList<>(); + private boolean countAll = true; public StatisticsListAdapter(Context context) { this.context = context; } + public void setCountAll(boolean countAll) { + this.countAll = countAll; + } @Override public int getCount() { @@ -69,7 +71,7 @@ public class StatisticsListAdapter extends BaseAdapter { } Glide.with(context) - .load(feed.getImageUri()) + .load(feed.getImageLocation()) .placeholder(R.color.light_gray) .error(R.color.light_gray) .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) @@ -79,7 +81,8 @@ public class StatisticsListAdapter extends BaseAdapter { holder.title.setText(feed.getTitle()); holder.time.setText(Converter.shortLocalizedDuration(context, - feedTime.get(position).timePlayed)); + countAll ? feedTime.get(position).timePlayedCountAll + : feedTime.get(position).timePlayed)); return convertView; } diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsAdapter.java index e2561804e..6d19bfa6c 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsAdapter.java @@ -1,9 +1,7 @@ package de.danoeh.antennapod.adapter; import android.content.Context; -import android.net.Uri; import android.support.v4.app.Fragment; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -32,8 +30,8 @@ public class SubscriptionsAdapter extends BaseAdapter implements AdapterView.OnI /** placeholder object that indicates item should be added */ public static final Object ADD_ITEM_OBJ = new Object(); - /** the position in the view that holds the add item */ - private static final int ADD_POSITION = 0; + /** the position in the view that holds the add item; 0 is the first, -1 is the last position */ + private static final int ADD_POSITION = -1; private static final String TAG = "SubscriptionsAdapter"; private final WeakReference<MainActivity> mainActivityRef; @@ -44,8 +42,16 @@ public class SubscriptionsAdapter extends BaseAdapter implements AdapterView.OnI this.itemAccess = itemAccess; } + private int getAddTilePosition() { + if(ADD_POSITION < 0) { + return ADD_POSITION + getCount(); + } + return ADD_POSITION; + } + private int getAdjustedPosition(int origPosition) { - return origPosition - 1; + assert(origPosition != getAddTilePosition()); + return origPosition < getAddTilePosition() ? origPosition : origPosition - 1; } @Override @@ -55,15 +61,20 @@ public class SubscriptionsAdapter extends BaseAdapter implements AdapterView.OnI @Override public Object getItem(int position) { - if (position == ADD_POSITION) { + if (position == getAddTilePosition()) { return ADD_ITEM_OBJ; } return itemAccess.getItem(getAdjustedPosition(position)); } @Override + public boolean hasStableIds() { + return true; + } + + @Override public long getItemId(int position) { - if (position == ADD_POSITION) { + if (position == getAddTilePosition()) { return 0; } return itemAccess.getItem(getAdjustedPosition(position)).getId(); @@ -89,13 +100,17 @@ public class SubscriptionsAdapter extends BaseAdapter implements AdapterView.OnI holder = (Holder) convertView.getTag(); } - if (position == ADD_POSITION) { + if (position == getAddTilePosition()) { holder.feedTitle.setText("{md-add 500%}\n\n" + mainActivityRef.get().getString(R.string.add_feed_label)); holder.feedTitle.setVisibility(View.VISIBLE); // prevent any accidental re-use of old values (not sure how that would happen...) holder.count.setPrimaryText(""); // make it go away, we don't need it for add feed holder.count.setVisibility(View.INVISIBLE); + + // when this holder is reused, we could else end up with a cover image + Glide.clear(holder.imageView); + return convertView; } @@ -104,10 +119,15 @@ public class SubscriptionsAdapter extends BaseAdapter implements AdapterView.OnI holder.feedTitle.setText(feed.getTitle()); holder.feedTitle.setVisibility(View.VISIBLE); - holder.count.setPrimaryText(String.valueOf(itemAccess.getFeedCounter(feed.getId()))); - holder.count.setVisibility(View.VISIBLE); + int count = itemAccess.getFeedCounter(feed.getId()); + if(count > 0) { + holder.count.setPrimaryText(String.valueOf(itemAccess.getFeedCounter(feed.getId()))); + holder.count.setVisibility(View.VISIBLE); + } else { + holder.count.setVisibility(View.GONE); + } Glide.with(mainActivityRef.get()) - .load(feed.getImageUri()) + .load(feed.getImageLocation()) .error(R.color.light_gray) .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) .fitCenter() @@ -119,7 +139,7 @@ public class SubscriptionsAdapter extends BaseAdapter implements AdapterView.OnI @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { - if (position == ADD_POSITION) { + if (position == getAddTilePosition()) { mainActivityRef.get().loadChildFragment(new AddFeedFragment()); } else { Fragment fragment = ItemlistFragment.newInstance(getItemId(position)); diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java index e9756b467..f1f8be559 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java @@ -1,6 +1,8 @@ package de.danoeh.antennapod.adapter.itunes; import android.content.Context; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; @@ -18,6 +20,7 @@ import java.util.List; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; +import de.mfietz.fyydlin.SearchHit; public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> { /** @@ -42,8 +45,9 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> { this.context = context; } + @NonNull @Override - public View getView(int position, View convertView, ViewGroup parent) { + public View getView(int position, View convertView, @NonNull ViewGroup parent) { //Current podcast Podcast podcast = data.get(position); @@ -66,7 +70,7 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> { //Set the title viewHolder.titleView.setText(podcast.title); - if(!podcast.feedUrl.contains("itunes.apple.com")) { + if(podcast.feedUrl != null && !podcast.feedUrl.contains("itunes.apple.com")) { viewHolder.urlView.setText(podcast.feedUrl); viewHolder.urlView.setVisibility(View.VISIBLE); } else { @@ -87,35 +91,6 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> { } /** - * View holder object for the GridView - */ - class PodcastViewHolder { - - /** - * ImageView holding the Podcast image - */ - public final ImageView coverView; - - /** - * TextView holding the Podcast title - */ - public final TextView titleView; - - public final TextView urlView; - - - /** - * Constructor - * @param view GridView cell - */ - PodcastViewHolder(View view){ - coverView = (ImageView) view.findViewById(R.id.imgvCover); - titleView = (TextView) view.findViewById(R.id.txtvTitle); - urlView = (TextView) view.findViewById(R.id.txtvUrl); - } - } - - /** * Represents an individual podcast on the iTunes Store. */ public static class Podcast { //TODO: Move this out eventually. Possibly to core.itunes.model @@ -128,14 +103,16 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> { /** * URL of the podcast image */ + @Nullable public final String imageUrl; /** * URL of the podcast feed */ + @Nullable public final String feedUrl; - private Podcast(String title, String imageUrl, String feedUrl) { + private Podcast(String title, @Nullable String imageUrl, @Nullable String feedUrl) { this.title = title; this.imageUrl = imageUrl; this.feedUrl = feedUrl; @@ -148,12 +125,16 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> { * @throws JSONException */ public static Podcast fromSearch(JSONObject json) throws JSONException { - String title = json.getString("collectionName"); - String imageUrl = json.getString("artworkUrl100"); - String feedUrl = json.getString("feedUrl"); + String title = json.optString("collectionName", ""); + String imageUrl = json.optString("artworkUrl100", null); + String feedUrl = json.optString("feedUrl", null); return new Podcast(title, imageUrl, feedUrl); } + public static Podcast fromSearch(SearchHit searchHit) { + return new Podcast(searchHit.getTitle(), searchHit.getImageUrl(), searchHit.getXmlUrl()); + } + /** * Constructs a Podcast instance from iTunes toplist entry * @@ -177,4 +158,33 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> { } } + + /** + * View holder object for the GridView + */ + class PodcastViewHolder { + + /** + * ImageView holding the Podcast image + */ + final ImageView coverView; + + /** + * TextView holding the Podcast title + */ + final TextView titleView; + + final TextView urlView; + + + /** + * Constructor + * @param view GridView cell + */ + PodcastViewHolder(View view){ + coverView = (ImageView) view.findViewById(R.id.imgvCover); + titleView = (TextView) view.findViewById(R.id.txtvTitle); + urlView = (TextView) view.findViewById(R.id.txtvUrl); + } + } } diff --git a/app/src/main/java/de/danoeh/antennapod/asynctask/ExportWorker.java b/app/src/main/java/de/danoeh/antennapod/asynctask/ExportWorker.java new file mode 100644 index 000000000..192df8ca5 --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/asynctask/ExportWorker.java @@ -0,0 +1,65 @@ +package de.danoeh.antennapod.asynctask; + +import android.support.annotation.NonNull; +import android.util.Log; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; + +import de.danoeh.antennapod.core.export.ExportWriter; +import de.danoeh.antennapod.core.preferences.UserPreferences; +import de.danoeh.antennapod.core.storage.DBReader; +import de.danoeh.antennapod.core.util.LangUtils; +import rx.Observable; + +/** + * Writes an OPML file into the export directory in the background. + */ +public class ExportWorker { + + private static final String EXPORT_DIR = "export/"; + private static final String TAG = "ExportWorker"; + private static final String DEFAULT_OUTPUT_NAME = "antennapod-feeds"; + + private ExportWriter exportWriter; + private File output; + + public ExportWorker(ExportWriter exportWriter) { + this(exportWriter, new File(UserPreferences.getDataFolder(EXPORT_DIR), + DEFAULT_OUTPUT_NAME + "." + exportWriter.fileExtension())); + } + + public ExportWorker(ExportWriter exportWriter, @NonNull File output) { + this.exportWriter = exportWriter; + this.output = output; + } + + public Observable<File> exportObservable() { + if (output.exists()) { + Log.w(TAG, "Overwriting previously exported file."); + output.delete(); + } + return Observable.create(subscriber -> { + OutputStreamWriter writer = null; + try { + writer = new OutputStreamWriter(new FileOutputStream(output), LangUtils.UTF_8); + exportWriter.writeDocument(DBReader.getFeedList(), writer); + subscriber.onNext(output); + } catch (IOException e) { + subscriber.onError(e); + } finally { + if (writer != null) { + try { + writer.close(); + } catch (IOException e) { + subscriber.onError(e); + } + } + subscriber.onCompleted(); + } + }); + } + +} diff --git a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlExportWorker.java b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlExportWorker.java deleted file mode 100644 index 13abb26ea..000000000 --- a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlExportWorker.java +++ /dev/null @@ -1,122 +0,0 @@ -package de.danoeh.antennapod.asynctask; - -import android.annotation.SuppressLint; -import android.app.ProgressDialog; -import android.content.Context; -import android.content.Intent; -import android.net.Uri; -import android.os.AsyncTask; -import android.support.v7.app.AlertDialog; -import android.util.Log; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStreamWriter; - -import de.danoeh.antennapod.core.R; -import de.danoeh.antennapod.core.opml.OpmlWriter; -import de.danoeh.antennapod.core.preferences.UserPreferences; -import de.danoeh.antennapod.core.storage.DBReader; -import de.danoeh.antennapod.core.util.LangUtils; - -/** - * Writes an OPML file into the export directory in the background. - */ -public class OpmlExportWorker extends AsyncTask<Void, Void, Void> { - private static final String TAG = "OpmlExportWorker"; - private static final String DEFAULT_OUTPUT_NAME = "antennapod-feeds.opml"; - public static final String EXPORT_DIR = "export/"; - - private Context context; - private File output; - - private ProgressDialog progDialog; - private Exception exception; - - public OpmlExportWorker(Context context, File output) { - this.context = context; - this.output = output; - } - - public OpmlExportWorker(Context context) { - this.context = context; - } - - @Override - protected Void doInBackground(Void... params) { - OpmlWriter opmlWriter = new OpmlWriter(); - if (output == null) { - output = new File( - UserPreferences.getDataFolder(EXPORT_DIR), - DEFAULT_OUTPUT_NAME); - if (output.exists()) { - Log.w(TAG, "Overwriting previously exported file."); - output.delete(); - } - } - OutputStreamWriter writer = null; - try { - writer = new OutputStreamWriter(new FileOutputStream(output), LangUtils.UTF_8); - opmlWriter.writeDocument(DBReader.getFeedList(), writer); - } catch (IOException e) { - e.printStackTrace(); - exception = e; - } finally { - if (writer != null) { - try { - writer.close(); - } catch (IOException ioe) { - exception = ioe; - } - } - } - return null; - } - - @Override - protected void onPostExecute(Void result) { - progDialog.dismiss(); - AlertDialog.Builder alert = new AlertDialog.Builder(context) - .setNeutralButton(android.R.string.ok, - (dialog, which) -> dialog.dismiss()); - if (exception != null) { - alert.setTitle(R.string.export_error_label); - alert.setMessage(exception.getMessage()); - } else { - alert.setTitle(R.string.opml_export_success_title); - alert.setMessage(context - .getString(R.string.opml_export_success_sum) - + output.toString()) - .setPositiveButton(R.string.send_label, (dialog, which) -> { - Uri outputUri = Uri.fromFile(output); - Intent sendIntent = new Intent(Intent.ACTION_SEND); - sendIntent.putExtra(Intent.EXTRA_SUBJECT, - context.getResources().getText(R.string.opml_export_label)); - sendIntent.putExtra(Intent.EXTRA_STREAM, outputUri); - sendIntent.setType("text/plain"); - context.startActivity(Intent.createChooser(sendIntent, - context.getResources().getText(R.string.send_label))); - }); - } - alert.create().show(); - } - - @Override - protected void onPreExecute() { - progDialog = new ProgressDialog(context); - progDialog.setMessage(context.getString(R.string.exporting_label)); - progDialog.setIndeterminate(true); - progDialog.show(); - } - - @SuppressLint("NewApi") - public void executeAsync() { - if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) { - executeOnExecutor(THREAD_POOL_EXECUTOR); - } else { - execute(); - } - } - -} diff --git a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java index 1cb653f01..4449d82c2 100644 --- a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java +++ b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java @@ -9,8 +9,8 @@ import java.util.Arrays; import de.danoeh.antennapod.activity.OpmlImportHolder; import de.danoeh.antennapod.core.R; +import de.danoeh.antennapod.core.export.opml.OpmlElement; import de.danoeh.antennapod.core.feed.Feed; -import de.danoeh.antennapod.core.opml.OpmlElement; import de.danoeh.antennapod.core.storage.DownloadRequestException; import de.danoeh.antennapod.core.storage.DownloadRequester; diff --git a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlImportWorker.java b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlImportWorker.java index 45ec6c5fa..62ea85811 100644 --- a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlImportWorker.java +++ b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlImportWorker.java @@ -14,8 +14,8 @@ import java.io.Reader; import java.util.ArrayList; import de.danoeh.antennapod.core.R; -import de.danoeh.antennapod.core.opml.OpmlElement; -import de.danoeh.antennapod.core.opml.OpmlReader; +import de.danoeh.antennapod.core.export.opml.OpmlElement; +import de.danoeh.antennapod.core.export.opml.OpmlReader; public class OpmlImportWorker extends AsyncTask<Void, Void, ArrayList<OpmlElement>> { @@ -75,9 +75,7 @@ public class OpmlImportWorker extends alert.setTitle(R.string.error_label); alert.setMessage(context.getString(R.string.opml_reader_error) + exception.getMessage()); - alert.setNeutralButton(android.R.string.ok, (dialog, which) -> { - dialog.dismiss(); - }); + alert.setNeutralButton(android.R.string.ok, (dialog, which) -> dialog.dismiss()); alert.create().show(); } } diff --git a/app/src/main/java/de/danoeh/antennapod/config/ClientConfigurator.java b/app/src/main/java/de/danoeh/antennapod/config/ClientConfigurator.java index 691eccdd9..538abd4c7 100644 --- a/app/src/main/java/de/danoeh/antennapod/config/ClientConfigurator.java +++ b/app/src/main/java/de/danoeh/antennapod/config/ClientConfigurator.java @@ -18,5 +18,6 @@ public class ClientConfigurator { ClientConfig.playbackServiceCallbacks = new PlaybackServiceCallbacksImpl(); ClientConfig.flattrCallbacks = new FlattrCallbacksImpl(); ClientConfig.dbTasksCallbacks = new DBTasksCallbacksImpl(); + ClientConfig.castCallbacks = new CastCallbackImpl(); } } diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java index 577a3ecbe..ac073141d 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java @@ -225,6 +225,10 @@ public class EpisodesApplyActionFragment extends Fragment { checkQueued(false); resId = R.string.selected_not_queued_label; break; + case R.id.check_has_media: + checkWithMedia(); + resId = R.string.selected_has_media_label; + break; case R.id.sort_title_a_z: sortByTitle(false); return true; @@ -357,6 +361,17 @@ public class EpisodesApplyActionFragment extends Fragment { refreshCheckboxes(); } + private void checkWithMedia() { + for (FeedItem episode : episodes) { + if(episode.hasMedia()) { + checkedIds.add(episode.getId()); + } else { + checkedIds.remove(episode.getId()); + } + } + refreshCheckboxes(); + } + private void refreshTitles() { titles.clear(); for(FeedItem episode : episodes) { diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/GpodnetSetHostnameDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/GpodnetSetHostnameDialog.java index b875eaf62..a4e71c249 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/GpodnetSetHostnameDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/GpodnetSetHostnameDialog.java @@ -35,9 +35,7 @@ public class GpodnetSetHostnameDialog { } dialog1.dismiss(); }) - .setNegativeButton(R.string.cancel_label, (dialog1, which) -> { - dialog1.cancel(); - }) + .setNegativeButton(R.string.cancel_label, (dialog1, which) -> dialog1.cancel()) .setNeutralButton(R.string.pref_gpodnet_sethostname_use_default_host, (dialog1, which) -> { GpodnetPreferences.setHostname(GpodnetService.DEFAULT_BASE_HOST); dialog1.dismiss(); diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java index 98a4b5356..0bd75b5b0 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java @@ -18,10 +18,6 @@ import android.widget.TextView; import com.afollestad.materialdialogs.DialogAction; import com.afollestad.materialdialogs.MaterialDialog; import com.afollestad.materialdialogs.internal.MDButton; -import com.squareup.okhttp.Credentials; -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.Request; -import com.squareup.okhttp.Response; import java.io.IOException; import java.net.InetSocketAddress; @@ -33,6 +29,10 @@ import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; import de.danoeh.antennapod.core.service.download.ProxyConfig; +import okhttp3.Credentials; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; import rx.Observable; import rx.Subscriber; import rx.Subscription; @@ -258,10 +258,11 @@ public class ProxyDialog { SocketAddress address = InetSocketAddress.createUnresolved(host, portValue); Proxy.Type proxyType = Proxy.Type.valueOf(type.toUpperCase()); Proxy proxy = new Proxy(proxyType, address); - OkHttpClient client = AntennapodHttpClient.newHttpClient(); - client.setConnectTimeout(10, TimeUnit.SECONDS); - client.setProxy(proxy); - client.interceptors().clear(); + OkHttpClient.Builder builder = AntennapodHttpClient.newBuilder() + .connectTimeout(10, TimeUnit.SECONDS) + .proxy(proxy); + builder.interceptors().clear(); + OkHttpClient client = builder.build(); if(!TextUtils.isEmpty(username)) { String credentials = Credentials.basic(username, password); client.interceptors().add(chain -> { diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/RenameFeedDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/RenameFeedDialog.java new file mode 100644 index 000000000..31a544582 --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/dialog/RenameFeedDialog.java @@ -0,0 +1,44 @@ +package de.danoeh.antennapod.dialog; + +import android.app.Activity; +import android.text.InputType; + +import com.afollestad.materialdialogs.MaterialDialog; + +import java.lang.ref.WeakReference; + +import de.danoeh.antennapod.core.feed.Feed; +import de.danoeh.antennapod.core.storage.DBWriter; + +public class RenameFeedDialog { + + private final WeakReference<Activity> activityRef; + private final Feed feed; + + public RenameFeedDialog(Activity activity, Feed feed) { + this.activityRef = new WeakReference<>(activity); + this.feed = feed; + } + + public void show() { + Activity activity = activityRef.get(); + if(activity == null) { + return; + } + new MaterialDialog.Builder(activity) + .title(de.danoeh.antennapod.core.R.string.rename_feed_label) + .inputType(InputType.TYPE_CLASS_TEXT) + .input(feed.getTitle(), feed.getTitle(), true, (dialog, input) -> { + feed.setCustomTitle(input.toString()); + DBWriter.setFeedCustomTitle(feed); + dialog.dismiss(); + }) + .neutralText(de.danoeh.antennapod.core.R.string.reset) + .onNeutral((dialog, which) -> dialog.getInputEditText().setText(feed.getFeedTitle())) + .negativeText(de.danoeh.antennapod.core.R.string.cancel_label) + .onNegative((dialog, which) -> dialog.dismiss()) + .autoDismiss(false) + .show(); + } + +} diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java index 8a13a75d9..7d6a66a54 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java @@ -1,7 +1,7 @@ package de.danoeh.antennapod.dialog; import android.content.Context; -import android.content.SharedPreferences; +import android.support.design.widget.Snackbar; import android.text.Editable; import android.text.TextWatcher; import android.util.Log; @@ -9,6 +9,7 @@ import android.view.View; import android.view.inputmethod.InputMethodManager; import android.widget.ArrayAdapter; import android.widget.CheckBox; +import android.widget.CompoundButton; import android.widget.EditText; import android.widget.Spinner; import android.widget.Toast; @@ -16,36 +17,27 @@ import android.widget.Toast; import com.afollestad.materialdialogs.DialogAction; import com.afollestad.materialdialogs.MaterialDialog; -import java.util.concurrent.TimeUnit; - import de.danoeh.antennapod.R; +import de.danoeh.antennapod.core.event.MessageEvent; +import de.danoeh.antennapod.core.preferences.SleepTimerPreferences; +import de.greenrobot.event.EventBus; public abstract class SleepTimerDialog { private static final String TAG = SleepTimerDialog.class.getSimpleName(); - private static final int DEFAULT_SPINNER_POSITION = 1; - private Context context; - private String PREF_NAME = "SleepTimerDialog"; - private String PREF_VALUE = "LastValue"; - private String PREF_TIME_UNIT = "LastTimeUnit"; - private String PREF_VIBRATE = "Vibrate"; - private String PREF_SHAKE_TO_RESET = "ShakeToReset"; - private SharedPreferences prefs; private MaterialDialog dialog; private EditText etxtTime; private Spinner spTimeUnit; private CheckBox cbShakeToReset; private CheckBox cbVibrate; + private CheckBox chAutoEnable; - private TimeUnit[] units = { TimeUnit.SECONDS, TimeUnit.MINUTES, TimeUnit.HOURS }; - - public SleepTimerDialog(Context context) { + protected SleepTimerDialog(Context context) { this.context = context; - prefs = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE); } public MaterialDialog createNewDialog() { @@ -58,7 +50,7 @@ public abstract class SleepTimerDialog { builder.onPositive((dialog, which) -> { try { savePreferences(); - long input = readTimeMillis(); + long input = SleepTimerPreferences.timerMillis(); onTimerSet(input, cbShakeToReset.isChecked(), cbVibrate.isChecked()); dialog.dismiss(); } catch (NumberFormatException e) { @@ -75,8 +67,9 @@ public abstract class SleepTimerDialog { spTimeUnit = (Spinner) view.findViewById(R.id.spTimeUnit); cbShakeToReset = (CheckBox) view.findViewById(R.id.cbShakeToReset); cbVibrate = (CheckBox) view.findViewById(R.id.cbVibrate); + chAutoEnable = (CheckBox) view.findViewById(R.id.chAutoEnable); - etxtTime.setText(prefs.getString(PREF_VALUE, "15")); + etxtTime.setText(SleepTimerPreferences.lastTimerValue()); etxtTime.addTextChangedListener(new TextWatcher() { @Override public void afterTextChanged(Editable s) { @@ -104,12 +97,17 @@ public abstract class SleepTimerDialog { android.R.layout.simple_spinner_item, spinnerContent); spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spTimeUnit.setAdapter(spinnerAdapter); - int selection = prefs.getInt(PREF_TIME_UNIT, DEFAULT_SPINNER_POSITION); - spTimeUnit.setSelection(selection); + spTimeUnit.setSelection(SleepTimerPreferences.lastTimerTimeUnit()); - cbShakeToReset.setChecked(prefs.getBoolean(PREF_SHAKE_TO_RESET, true)); - cbVibrate.setChecked(prefs.getBoolean(PREF_VIBRATE, true)); + cbShakeToReset.setChecked(SleepTimerPreferences.shakeToReset()); + cbVibrate.setChecked(SleepTimerPreferences.vibrate()); + chAutoEnable.setChecked(SleepTimerPreferences.autoEnable()); + chAutoEnable.setOnCheckedChangeListener((compoundButton, isChecked) -> { + SleepTimerPreferences.setAutoEnable(isChecked); + int messageString = isChecked ? R.string.sleep_timer_enabled_label : R.string.sleep_timer_disabled_label; + EventBus.getDefault().post(new MessageEvent(context.getString(messageString))); + }); return dialog; } @@ -125,19 +123,12 @@ public abstract class SleepTimerDialog { public abstract void onTimerSet(long millis, boolean shakeToReset, boolean vibrate); - private long readTimeMillis() { - TimeUnit selectedUnit = units[spTimeUnit.getSelectedItemPosition()]; - long value = Long.parseLong(etxtTime.getText().toString()); - return selectedUnit.toMillis(value); - } - private void savePreferences() { - prefs.edit() - .putString(PREF_VALUE, etxtTime.getText().toString()) - .putInt(PREF_TIME_UNIT, spTimeUnit.getSelectedItemPosition()) - .putBoolean(PREF_SHAKE_TO_RESET, cbShakeToReset.isChecked()) - .putBoolean(PREF_VIBRATE, cbVibrate.isChecked()) - .apply(); + SleepTimerPreferences.setLastTimer(etxtTime.getText().toString(), + spTimeUnit.getSelectedItemPosition()); + SleepTimerPreferences.setShakeToReset(cbShakeToReset.isChecked()); + SleepTimerPreferences.setVibrate(cbVibrate.isChecked()); + SleepTimerPreferences.setAutoEnable(chAutoEnable.isChecked()); } } diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java index 2bf9c4e7a..6a975fe49 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java @@ -95,9 +95,7 @@ public class VariableSpeedDialog { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(R.string.set_playback_speed_label); builder.setMultiChoiceItems(R.array.playback_speed_values, - speedChecked, (dialog, which, isChecked) -> { - speedChecked[which] = isChecked; - }); + speedChecked, (dialog, which, isChecked) -> speedChecked[which] = isChecked); builder.setNegativeButton(android.R.string.cancel, null); builder.setPositiveButton(android.R.string.ok, (dialog, which) -> { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java index 45364ca07..f14ebbdaf 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java @@ -39,10 +39,11 @@ public class AddFeedFragment extends Fragment { etxtFeedurl.setText(args.getString(ARG_FEED_URL)); } + Button butSearchITunes = (Button) root.findViewById(R.id.butSearchItunes); Button butBrowserGpoddernet = (Button) root.findViewById(R.id.butBrowseGpoddernet); + Button butSearchFyyd = (Button) root.findViewById(R.id.butSearchFyyd); Button butOpmlImport = (Button) root.findViewById(R.id.butOpmlImport); Button butConfirm = (Button) root.findViewById(R.id.butConfirm); - Button butSearchITunes = (Button) root.findViewById(R.id.butSearchItunes); final MainActivity activity = (MainActivity) getActivity(); activity.getSupportActionBar().setTitle(R.string.add_feed_label); @@ -51,6 +52,8 @@ public class AddFeedFragment extends Fragment { butBrowserGpoddernet.setOnClickListener(v -> activity.loadChildFragment(new GpodnetMainFragment())); + butSearchFyyd.setOnClickListener(v -> activity.loadChildFragment(new FyydSearchFragment())); + butOpmlImport.setOnClickListener(v -> startActivity(new Intent(getActivity(), OpmlImportFromPathActivity.class))); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java index 8ae7f1cf9..bbfd1688d 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java @@ -80,6 +80,7 @@ public class AllEpisodesFragment extends Fragment { private boolean viewsCreated = false; private boolean isUpdatingFeeds; + protected boolean isMenuInvalidationAllowed = false; protected Subscription subscription; private LinearLayoutManager layoutManager; @@ -180,7 +181,7 @@ public class AllEpisodesFragment extends Fragment { } super.onCreateOptionsMenu(menu, inflater); if (itemsLoaded) { - inflater.inflate(R.menu.new_episodes, menu); + inflater.inflate(R.menu.episodes, menu); MenuItem searchItem = menu.findItem(R.id.action_search); final SearchView sv = (SearchView) MenuItemCompat.getActionView(searchItem); @@ -206,11 +207,13 @@ public class AllEpisodesFragment extends Fragment { @Override public void onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); - if (itemsLoaded) { - MenuItem menuItem = menu.findItem(R.id.mark_all_read_item); - if (menuItem != null) { - menuItem.setVisible(episodes != null && !episodes.isEmpty()); - } + MenuItem markAllRead = menu.findItem(R.id.mark_all_read_item); + if (markAllRead != null) { + markAllRead.setVisible(!showOnlyNewEpisodes() && episodes != null && !episodes.isEmpty()); + } + MenuItem markAllSeen = menu.findItem(R.id.mark_all_seen_item); + if(markAllSeen != null) { + markAllSeen.setVisible(showOnlyNewEpisodes() && episodes != null && !episodes.isEmpty()); } } @@ -225,19 +228,32 @@ public class AllEpisodesFragment extends Fragment { } return true; case R.id.mark_all_read_item: - ConfirmationDialog conDialog = new ConfirmationDialog(getActivity(), + ConfirmationDialog markAllReadConfirmationDialog = new ConfirmationDialog(getActivity(), R.string.mark_all_read_label, R.string.mark_all_read_confirmation_msg) { @Override - public void onConfirmButtonPressed( - DialogInterface dialog) { + public void onConfirmButtonPressed(DialogInterface dialog) { dialog.dismiss(); DBWriter.markAllItemsRead(); Toast.makeText(getActivity(), R.string.mark_all_read_msg, Toast.LENGTH_SHORT).show(); } }; - conDialog.createNewDialog().show(); + markAllReadConfirmationDialog.createNewDialog().show(); + return true; + case R.id.mark_all_seen_item: + ConfirmationDialog markAllSeenConfirmationDialog = new ConfirmationDialog(getActivity(), + R.string.mark_all_seen_label, + R.string.mark_all_seen_confirmation_msg) { + + @Override + public void onConfirmButtonPressed(DialogInterface dialog) { + dialog.dismiss(); + DBWriter.markNewItemsSeen(); + Toast.makeText(getActivity(), R.string.mark_all_seen_msg, Toast.LENGTH_SHORT).show(); + } + }; + markAllSeenConfirmationDialog.createNewDialog().show(); return true; default: return false; @@ -378,6 +394,20 @@ public class AllEpisodesFragment extends Fragment { return item != null && item.isTagged(FeedItem.TAG_QUEUE); } + @Override + public LongList getQueueIds() { + LongList queueIds = new LongList(); + if(episodes == null) { + return queueIds; + } + for(FeedItem item : episodes) { + if(item.isTagged(FeedItem.TAG_QUEUE)) { + queueIds.add(item.getId()); + } + } + return queueIds; + } + }; public void onEventMainThread(FeedItemEvent event) { @@ -401,7 +431,7 @@ public class AllEpisodesFragment extends Fragment { Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]"); DownloaderUpdate update = event.update; downloaderList = update.downloaders; - if (isUpdatingFeeds != update.feedIds.length > 0) { + if (isMenuInvalidationAllowed && isUpdatingFeeds != update.feedIds.length > 0) { getActivity().supportInvalidateOptionsMenu(); } if(listAdapter != null && update.mediaIds.length > 0) { @@ -450,9 +480,7 @@ public class AllEpisodesFragment extends Fragment { onFragmentLoaded(); } } - }, error -> { - Log.e(TAG, Log.getStackTraceString(error)); - }); + }, error -> Log.e(TAG, Log.getStackTraceString(error))); } protected List<FeedItem> loadData() { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java index 77e66f3b0..4d34d076d 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java @@ -69,16 +69,18 @@ public class ChaptersFragment extends ListFragment implements MediaplayerInfoCon @Override public void onMediaChanged(Playable media) { - if(this.media == media || adapter == null) { + if(this.media == media) { return; } this.media = media; - adapter.setMedia(media); - adapter.notifyDataSetChanged(); - if(media == null || media.getChapters() == null || media.getChapters().size() == 0) { - setEmptyText(getString(R.string.no_items_label)); - } else { - setEmptyText(null); + if (adapter != null) { + adapter.setMedia(media); + adapter.notifyDataSetChanged(); + if(media == null || media.getChapters() == null || media.getChapters().size() == 0) { + setEmptyText(getString(R.string.no_items_label)); + } else { + setEmptyText(null); + } } } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java index d14265f70..1ba7ed557 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java @@ -215,9 +215,7 @@ public class CompletedDownloadsFragment extends ListFragment { onFragmentLoaded(); } } - }, error -> { - Log.e(TAG, Log.getStackTraceString(error)); - }); + }, error -> Log.e(TAG, Log.getStackTraceString(error))); } } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java index 943ddeec7..1d3fcefba 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java @@ -33,22 +33,15 @@ public class CoverFragment extends Fragment implements MediaplayerInfoContentFra public static CoverFragment newInstance(Playable item) { CoverFragment f = new CoverFragment(); - if (item != null) { - Bundle args = new Bundle(); - args.putParcelable(ARG_PLAYABLE, item); - f.setArguments(args); - } + f.media = item; return f; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - Bundle args = getArguments(); - if (args != null) { - media = args.getParcelable(ARG_PLAYABLE); - } else { - Log.e(TAG, TAG + " was called with invalid arguments"); + if (media == null) { + Log.e(TAG, TAG + " was called without media"); } } @@ -67,7 +60,7 @@ public class CoverFragment extends Fragment implements MediaplayerInfoContentFra txtvPodcastTitle.setText(media.getFeedTitle()); txtvEpisodeTitle.setText(media.getEpisodeTitle()); Glide.with(this) - .load(media.getImageUri()) + .load(media.getImageLocation()) .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) .dontAnimate() .fitCenter() @@ -98,11 +91,13 @@ public class CoverFragment extends Fragment implements MediaplayerInfoContentFra @Override public void onMediaChanged(Playable media) { - if(!isAdded() || this.media == media) { + if(this.media == media) { return; } this.media = media; - loadMediaInfo(); + if (isAdded()) { + loadMediaInfo(); + } } } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java index 93527b149..0a710196a 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java @@ -165,9 +165,7 @@ public class DownloadLogFragment extends ListFragment { onFragmentLoaded(); } } - }, error -> { - Log.e(TAG, Log.getStackTraceString(error)); - }); + }, error -> Log.e(TAG, Log.getStackTraceString(error))); } } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java index f23981935..e2fbd91f3 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java @@ -79,6 +79,11 @@ public class EpisodesFragment extends Fragment { public static class EpisodesPagerAdapter extends FragmentPagerAdapter { private final Resources resources; + private AllEpisodesFragment[] fragments = { + new NewEpisodesFragment(), + new AllEpisodesFragment(), + new FavoriteEpisodesFragment() + }; public EpisodesPagerAdapter(FragmentManager fm, Resources resources) { super(fm); @@ -87,15 +92,7 @@ public class EpisodesFragment extends Fragment { @Override public Fragment getItem(int position) { - switch (position) { - case POS_ALL_EPISODES: - return new AllEpisodesFragment(); - case POS_NEW_EPISODES: - return new NewEpisodesFragment(); - case POS_FAV_EPISODES: - return new FavoriteEpisodesFragment(); - } - return null; + return fragments[position]; } @Override @@ -116,5 +113,14 @@ public class EpisodesFragment extends Fragment { return super.getPageTitle(position); } } + + @Override + public void setPrimaryItem(ViewGroup container, int position, Object object) { + super.setPrimaryItem(container, position, object); + for (int i = 0; i < TOTAL_COUNT; i++) { + // Invalidating the OptionsMenu is only allowed for the currently active fragment + fragments[i].isMenuInvalidationAllowed = (i == position); + } + } } } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java index 758f8095d..1e385728a 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java @@ -163,7 +163,7 @@ public class ExternalPlayerFragment extends Fragment { ((double) controller.getPosition() / controller.getDuration() * 100)); Glide.with(getActivity()) - .load(media.getImageUri()) + .load(media.getImageLocation()) .placeholder(R.color.light_gray) .error(R.color.light_gray) .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java index 65305df3d..234c8377d 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java @@ -71,9 +71,7 @@ public class FavoriteEpisodesFragment extends AllEpisodesFragment { Snackbar snackbar = Snackbar.make(root, getString(R.string.removed_item), Snackbar.LENGTH_LONG); - snackbar.setAction(getString(R.string.undo), v -> { - DBWriter.addFavoriteItem(item); - }); + snackbar.setAction(getString(R.string.undo), v -> DBWriter.addFavoriteItem(item)); snackbar.show(); } } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FyydSearchFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FyydSearchFragment.java new file mode 100644 index 000000000..7c1ec5ec1 --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/fragment/FyydSearchFragment.java @@ -0,0 +1,192 @@ +package de.danoeh.antennapod.fragment; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.view.MenuItemCompat; +import android.support.v7.widget.SearchView; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.GridView; +import android.widget.ProgressBar; +import android.widget.TextView; + +import java.util.ArrayList; +import java.util.List; + +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.activity.OnlineFeedViewActivity; +import de.danoeh.antennapod.adapter.itunes.ItunesAdapter; +import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; +import de.danoeh.antennapod.menuhandler.MenuItemUtils; +import de.mfietz.fyydlin.FyydClient; +import de.mfietz.fyydlin.FyydResponse; +import de.mfietz.fyydlin.SearchHit; +import rx.Subscription; +import rx.android.schedulers.AndroidSchedulers; +import rx.schedulers.Schedulers; + +import static de.danoeh.antennapod.adapter.itunes.ItunesAdapter.Podcast; +import static java.util.Collections.emptyList; + +public class FyydSearchFragment extends Fragment { + + private static final String TAG = "FyydSearchFragment"; + + /** + * Adapter responsible with the search results + */ + private ItunesAdapter adapter; + private GridView gridView; + private ProgressBar progressBar; + private TextView txtvError; + private Button butRetry; + private TextView txtvEmpty; + + private FyydClient client = new FyydClient(AntennapodHttpClient.getHttpClient()); + + /** + * List of podcasts retreived from the search + */ + private List<Podcast> searchResults; + private Subscription subscription; + + /** + * Constructor + */ + public FyydSearchFragment() { + // Required empty public constructor + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setHasOptionsMenu(true); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + View root = inflater.inflate(R.layout.fragment_itunes_search, container, false); + gridView = (GridView) root.findViewById(R.id.gridView); + adapter = new ItunesAdapter(getActivity(), new ArrayList<>()); + gridView.setAdapter(adapter); + + //Show information about the podcast when the list item is clicked + gridView.setOnItemClickListener((parent, view1, position, id) -> { + Podcast podcast = searchResults.get(position); + Intent intent = new Intent(getActivity(), OnlineFeedViewActivity.class); + intent.putExtra(OnlineFeedViewActivity.ARG_FEEDURL, podcast.feedUrl); + intent.putExtra(OnlineFeedViewActivity.ARG_TITLE, podcast.title); + startActivity(intent); + }); + progressBar = (ProgressBar) root.findViewById(R.id.progressBar); + txtvError = (TextView) root.findViewById(R.id.txtvError); + butRetry = (Button) root.findViewById(R.id.butRetry); + txtvEmpty = (TextView) root.findViewById(android.R.id.empty); + + return root; + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (subscription != null) { + subscription.unsubscribe(); + } + adapter = null; + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + super.onCreateOptionsMenu(menu, inflater); + inflater.inflate(R.menu.itunes_search, menu); + MenuItem searchItem = menu.findItem(R.id.action_search); + final SearchView sv = (SearchView) MenuItemCompat.getActionView(searchItem); + MenuItemUtils.adjustTextColor(getActivity(), sv); + sv.setQueryHint(getString(R.string.search_fyyd_label)); + sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() { + @Override + public boolean onQueryTextSubmit(String s) { + sv.clearFocus(); + search(s); + return true; + } + + @Override + public boolean onQueryTextChange(String s) { + return false; + } + }); + MenuItemCompat.setOnActionExpandListener(searchItem, new MenuItemCompat.OnActionExpandListener() { + @Override + public boolean onMenuItemActionExpand(MenuItem item) { + return true; + } + + @Override + public boolean onMenuItemActionCollapse(MenuItem item) { + getActivity().getSupportFragmentManager().popBackStack(); + return true; + } + }); + MenuItemCompat.expandActionView(searchItem); + } + + private void search(String query) { + if (subscription != null) { + subscription.unsubscribe(); + } + showOnlyProgressBar(); + subscription = client.searchPodcasts(query) + .subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(result -> { + progressBar.setVisibility(View.GONE); + processSearchResult(result); + }, error -> { + Log.e(TAG, Log.getStackTraceString(error)); + progressBar.setVisibility(View.GONE); + txtvError.setText(error.toString()); + txtvError.setVisibility(View.VISIBLE); + butRetry.setOnClickListener(v -> search(query)); + butRetry.setVisibility(View.VISIBLE); + }); + } + + private void showOnlyProgressBar() { + gridView.setVisibility(View.GONE); + txtvError.setVisibility(View.GONE); + butRetry.setVisibility(View.GONE); + txtvEmpty.setVisibility(View.GONE); + progressBar.setVisibility(View.VISIBLE); + } + + void processSearchResult(FyydResponse response) { + adapter.clear(); + if (!response.getData().isEmpty()) { + adapter.clear(); + searchResults = new ArrayList<>(); + for (SearchHit searchHit : response.getData().values()) { + Podcast podcast = Podcast.fromSearch(searchHit); + searchResults.add(podcast); + } + } else { + searchResults = emptyList(); + } + for(Podcast podcast : searchResults) { + adapter.add(podcast); + } + adapter.notifyDataSetInvalidated(); + gridView.setVisibility(!searchResults.isEmpty() ? View.VISIBLE : View.GONE); + txtvEmpty.setVisibility(searchResults.isEmpty() ? View.VISIBLE : View.GONE); + } + +} diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java index 55d28cadb..a0586fe16 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java @@ -185,8 +185,10 @@ public class ItemDescriptionFragment extends Fragment implements MediaplayerInfo super.onViewCreated(view, savedInstanceState); Bundle args = getArguments(); if (args.containsKey(ARG_PLAYABLE)) { - media = args.getParcelable(ARG_PLAYABLE); - shownotesProvider = media; + if (media == null) { + media = args.getParcelable(ARG_PLAYABLE); + shownotesProvider = media; + } load(); } else if (args.containsKey(ARG_FEEDITEM_ID)) { long id = getArguments().getLong(ARG_FEEDITEM_ID); @@ -196,9 +198,7 @@ public class ItemDescriptionFragment extends Fragment implements MediaplayerInfo .subscribe(feedItem -> { shownotesProvider = feedItem; load(); - }, error -> { - Log.e(TAG, Log.getStackTraceString(error)); - }); + }, error -> Log.e(TAG, Log.getStackTraceString(error))); } } @@ -311,9 +311,7 @@ public class ItemDescriptionFragment extends Fragment implements MediaplayerInfo webvDescription.loadDataWithBaseURL(null, data, "text/html", "utf-8", "about:blank"); Log.d(TAG, "Webview loaded"); - }, error -> { - Log.e(TAG, Log.getStackTraceString(error)); - }); + }, error -> Log.e(TAG, Log.getStackTraceString(error))); } private String loadData() { @@ -348,7 +346,7 @@ public class ItemDescriptionFragment extends Fragment implements MediaplayerInfo } private boolean restoreFromPreference() { - if (!saveState) { + if (saveState) { Log.d(TAG, "Restoring from preferences"); Activity activity = getActivity(); if (activity != null) { @@ -381,12 +379,14 @@ public class ItemDescriptionFragment extends Fragment implements MediaplayerInfo @Override public void onMediaChanged(Playable media) { - if(this.media == media || webvDescription == null) { + if(this.media == media) { return; } this.media = media; this.shownotesProvider = media; - load(); + if (webvDescription != null) { + load(); + } } } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java index e721af47d..7939dcb23 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java @@ -44,9 +44,7 @@ import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.adapter.DefaultActionButtonCallback; import de.danoeh.antennapod.core.event.DownloadEvent; import de.danoeh.antennapod.core.event.DownloaderUpdate; -import de.danoeh.antennapod.core.event.FavoritesEvent; import de.danoeh.antennapod.core.event.FeedItemEvent; -import de.danoeh.antennapod.core.event.QueueEvent; import de.danoeh.antennapod.core.feed.EventDistributor; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; @@ -60,7 +58,9 @@ import de.danoeh.antennapod.core.storage.DownloadRequestException; import de.danoeh.antennapod.core.storage.DownloadRequester; import de.danoeh.antennapod.core.util.Converter; import de.danoeh.antennapod.core.util.DateUtils; +import de.danoeh.antennapod.core.util.Flavors; import de.danoeh.antennapod.core.util.IntentUtils; +import de.danoeh.antennapod.core.util.LongList; import de.danoeh.antennapod.core.util.ShareUtils; import de.danoeh.antennapod.core.util.playback.Timeline; import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler; @@ -222,7 +222,8 @@ public class ItemFragment extends Fragment implements OnSwipeGesture { return; } DefaultActionButtonCallback actionButtonCallback = new DefaultActionButtonCallback(getActivity()); - actionButtonCallback.onActionButtonPressed(item); + actionButtonCallback.onActionButtonPressed(item, item.isTagged(FeedItem.TAG_QUEUE) ? + LongList.of(item.getId()) : new LongList(0)); FeedMedia media = item.getMedia(); if (media != null && media.isDownloaded()) { // playback was started, dialog should close itself @@ -312,7 +313,10 @@ public class ItemFragment extends Fragment implements OnSwipeGesture { if(!isAdded() || item == null) { return; } - ((CastEnabledActivity) getActivity()).requestCastButton(MenuItem.SHOW_AS_ACTION_ALWAYS); + super.onCreateOptionsMenu(menu, inflater); + if (Flavors.FLAVOR == Flavors.PLAY) { + ((CastEnabledActivity) getActivity()).requestCastButton(MenuItem.SHOW_AS_ACTION_ALWAYS); + } inflater.inflate(R.menu.feeditem_options, menu); popupMenu = menu; if (item.hasMedia()) { @@ -374,7 +378,7 @@ public class ItemFragment extends Fragment implements OnSwipeGesture { } Glide.with(getActivity()) - .load(item.getImageUri()) + .load(item.getImageLocation()) .placeholder(R.color.light_gray) .error(R.color.light_gray) .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) @@ -417,7 +421,7 @@ public class ItemFragment extends Fragment implements OnSwipeGesture { butAction2Text = R.string.stream_label; } else { butAction2Icon = "{md-delete 24sp}"; - butAction2Text = R.string.remove_label; + butAction2Text = R.string.delete_label; } if (isDownloading) { butAction1Icon = "{md-cancel 24sp}"; @@ -576,9 +580,7 @@ public class ItemFragment extends Fragment implements OnSwipeGesture { item = result; itemsLoaded = true; onFragmentLoaded(); - }, error -> { - Log.e(TAG, Log.getStackTraceString(error)); - }); + }, error -> Log.e(TAG, Log.getStackTraceString(error))); } private FeedItem loadInBackground() { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java index 3194d7cab..a118673a6 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java @@ -64,8 +64,10 @@ import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.storage.DownloadRequestException; import de.danoeh.antennapod.core.storage.DownloadRequester; import de.danoeh.antennapod.core.util.FeedItemUtil; +import de.danoeh.antennapod.core.util.LongList; import de.danoeh.antennapod.core.util.gui.MoreContentListFooterUtil; import de.danoeh.antennapod.dialog.EpisodesApplyActionFragment; +import de.danoeh.antennapod.dialog.RenameFeedDialog; import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler; import de.danoeh.antennapod.menuhandler.FeedMenuHandler; import de.danoeh.antennapod.menuhandler.MenuItemUtils; @@ -98,6 +100,7 @@ public class ItemlistFragment extends ListFragment { private boolean itemsLoaded = false; private boolean viewsCreated = false; + private boolean headerCreated = false; private List<Downloader> downloaderList; @@ -105,7 +108,10 @@ public class ItemlistFragment extends ListFragment { private boolean isUpdatingFeed; + private TextView txtvTitle; private IconTextView txtvFailure; + private ImageView imgvBackground; + private ImageView imgvCover; private TextView txtvInformation; @@ -247,6 +253,9 @@ public class ItemlistFragment extends ListFragment { .newInstance(feed.getItems()); ((MainActivity)getActivity()).loadChildFragment(fragment); return true; + case R.id.rename_item: + new RenameFeedDialog(getActivity(), feed).show(); + return true; case R.id.remove_item: final FeedRemover remover = new FeedRemover( getActivity(), feed) { @@ -258,7 +267,7 @@ public class ItemlistFragment extends ListFragment { }; ConfirmationDialog conDialog = new ConfirmationDialog(getActivity(), R.string.remove_feed_label, - R.string.feed_delete_confirmation_msg) { + getString(R.string.feed_delete_confirmation_msg, feed.getTitle())) { @Override public void onConfirmButtonPressed( @@ -414,6 +423,7 @@ public class ItemlistFragment extends ListFragment { public void update(EventDistributor eventDistributor, Integer arg) { if ((EVENTS & arg) != 0) { Log.d(TAG, "Received contentUpdate Intent. arg " + arg); + refreshHeaderView(); loadItems(); updateProgressBarVisibility(); } @@ -459,15 +469,17 @@ public class ItemlistFragment extends ListFragment { } private void refreshHeaderView() { - if (getListView() == null || feed == null) { - Log.e(TAG, "Unable to setup listview: recyclerView = null or feed = null"); + if (getListView() == null || feed == null || !headerCreated) { + Log.e(TAG, "Unable to refresh header view"); return; } + loadFeedImage(); if(feed.hasLastUpdateFailed()) { txtvFailure.setVisibility(View.VISIBLE); } else { txtvFailure.setVisibility(View.GONE); } + txtvTitle.setText(feed.getTitle()); if(feed.getItemFilter() != null) { FeedItemFilter filter = feed.getItemFilter(); if(filter.getValues().length > 0) { @@ -497,10 +509,10 @@ public class ItemlistFragment extends ListFragment { View header = inflater.inflate(R.layout.feeditemlist_header, lv, false); lv.addHeaderView(header); - TextView txtvTitle = (TextView) header.findViewById(R.id.txtvTitle); + txtvTitle = (TextView) header.findViewById(R.id.txtvTitle); TextView txtvAuthor = (TextView) header.findViewById(R.id.txtvAuthor); - ImageView imgvBackground = (ImageView) header.findViewById(R.id.imgvBackground); - ImageView imgvCover = (ImageView) header.findViewById(R.id.imgvCover); + imgvBackground = (ImageView) header.findViewById(R.id.imgvBackground); + imgvCover = (ImageView) header.findViewById(R.id.imgvCover); ImageButton butShowInfo = (ImageButton) header.findViewById(R.id.butShowInfo); txtvInformation = (TextView) header.findViewById(R.id.txtvInformation); txtvFailure = (IconTextView) header.findViewById(R.id.txtvFailure); @@ -512,8 +524,22 @@ public class ItemlistFragment extends ListFragment { // https://github.com/bumptech/glide/issues/529 imgvBackground.setColorFilter(new LightingColorFilter(0xff828282, 0x000000)); + loadFeedImage(); + + butShowInfo.setOnClickListener(v -> { + if (viewsCreated && itemsLoaded) { + Intent startIntent = new Intent(getActivity(), FeedInfoActivity.class); + startIntent.putExtra(FeedInfoActivity.EXTRA_FEED_ID, + feed.getId()); + startActivity(startIntent); + } + }); + headerCreated = true; + } + + private void loadFeedImage() { Glide.with(getActivity()) - .load(feed.getImageUri()) + .load(feed.getImageLocation()) .placeholder(R.color.image_readability_tint) .error(R.color.image_readability_tint) .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) @@ -522,22 +548,13 @@ public class ItemlistFragment extends ListFragment { .into(imgvBackground); Glide.with(getActivity()) - .load(feed.getImageUri()) + .load(feed.getImageLocation()) .placeholder(R.color.light_gray) .error(R.color.light_gray) .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) .fitCenter() .dontAnimate() .into(imgvCover); - - butShowInfo.setOnClickListener(v -> { - if (viewsCreated && itemsLoaded) { - Intent startIntent = new Intent(getActivity(), FeedInfoActivity.class); - startIntent.putExtra(FeedInfoActivity.EXTRA_FEED_ID, - feed.getId()); - startActivity(startIntent); - } - }); } @@ -578,6 +595,20 @@ public class ItemlistFragment extends ListFragment { } @Override + public LongList getQueueIds() { + LongList queueIds = new LongList(); + if(feed == null) { + return queueIds; + } + for(FeedItem item : feed.getItems()) { + if(item.isTagged(FeedItem.TAG_QUEUE)) { + queueIds.add(item.getId()); + } + } + return queueIds; + } + + @Override public int getCount() { return (feed != null) ? feed.getNumOfItems() : 0; } @@ -612,9 +643,7 @@ public class ItemlistFragment extends ListFragment { onFragmentLoaded(); } } - }, error -> { - Log.e(TAG, Log.getStackTraceString(error)); - }); + }, error -> Log.e(TAG, Log.getStackTraceString(error))); } private Feed loadData() { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java index b736688b9..db88c070d 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java @@ -18,9 +18,6 @@ import android.widget.ProgressBar; import android.widget.TextView; import com.afollestad.materialdialogs.MaterialDialog; -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.Request; -import com.squareup.okhttp.Response; import org.json.JSONArray; import org.json.JSONException; @@ -39,6 +36,9 @@ import de.danoeh.antennapod.adapter.itunes.ItunesAdapter; import de.danoeh.antennapod.core.ClientConfig; import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; import de.danoeh.antennapod.menuhandler.MenuItemUtils; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; import rx.Observable; import rx.Subscription; import rx.android.schedulers.AndroidSchedulers; diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java index 7ef070f21..183c10f3d 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java @@ -7,6 +7,8 @@ import android.support.v7.widget.RecyclerView; import android.support.v7.widget.helper.ItemTouchHelper; import android.util.Log; import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; @@ -92,7 +94,7 @@ public class NewEpisodesFragment extends AllEpisodesFragment { } }; - Snackbar snackbar = Snackbar.make(root, getString(R.string.marked_as_read_label), + Snackbar snackbar = Snackbar.make(root, getString(R.string.marked_as_seen_label), Snackbar.LENGTH_LONG); snackbar.setAction(getString(R.string.undo), v -> { DBWriter.markItemPlayed(FeedItem.NEW, item.getId()); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java index 49c68c732..441f0096c 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java @@ -28,6 +28,7 @@ import de.danoeh.antennapod.core.service.download.Downloader; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.util.FeedItemUtil; +import de.danoeh.antennapod.core.util.LongList; import de.greenrobot.event.EventBus; import rx.Observable; import rx.Subscription; @@ -251,6 +252,20 @@ public class PlaybackHistoryFragment extends ListFragment { return null; } } + + @Override + public LongList getQueueIds() { + LongList queueIds = new LongList(); + if(playbackHistory == null) { + return queueIds; + } + for (FeedItem item : playbackHistory) { + if (item.isTagged(FeedItem.TAG_QUEUE)) { + queueIds.add(item.getId()); + } + } + return queueIds; + } }; private void loadItems() { @@ -268,9 +283,7 @@ public class PlaybackHistoryFragment extends ListFragment { onFragmentLoaded(); } } - }, error -> { - Log.e(TAG, Log.getStackTraceString(error)); - }); + }, error -> Log.e(TAG, Log.getStackTraceString(error))); } private List<FeedItem> loadData() { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java index 08e681c99..d7f25c134 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java @@ -304,11 +304,11 @@ public class QueueFragment extends Fragment { }; conDialog.createNewDialog().show(); return true; - case R.id.queue_sort_alpha_asc: - QueueSorter.sort(getActivity(), QueueSorter.Rule.ALPHA_ASC, true); + case R.id.queue_sort_episode_title_asc: + QueueSorter.sort(getActivity(), QueueSorter.Rule.EPISODE_TITLE_ASC, true); return true; - case R.id.queue_sort_alpha_desc: - QueueSorter.sort(getActivity(), QueueSorter.Rule.ALPHA_DESC, true); + case R.id.queue_sort_episode_title_desc: + QueueSorter.sort(getActivity(), QueueSorter.Rule.EPISODE_TITLE_DESC, true); return true; case R.id.queue_sort_date_asc: QueueSorter.sort(getActivity(), QueueSorter.Rule.DATE_ASC, true); @@ -322,6 +322,12 @@ public class QueueFragment extends Fragment { case R.id.queue_sort_duration_desc: QueueSorter.sort(getActivity(), QueueSorter.Rule.DURATION_DESC, true); return true; + case R.id.queue_sort_feed_title_asc: + QueueSorter.sort(getActivity(), QueueSorter.Rule.FEED_TITLE_ASC, true); + return true; + case R.id.queue_sort_feed_title_desc: + QueueSorter.sort(getActivity(), QueueSorter.Rule.FEED_TITLE_DESC, true); + return true; default: return false; } @@ -605,9 +611,7 @@ public class QueueFragment extends Fragment { recyclerAdapter.notifyDataSetChanged(); } } - }, error -> { - Log.e(TAG, Log.getStackTraceString(error)); - }); + }, error -> Log.e(TAG, Log.getStackTraceString(error))); } } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java index 510909379..f64b4c20a 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java @@ -182,6 +182,9 @@ public class SearchFragment extends ListFragment { } searchAdapter.notifyDataSetChanged(); setListShown(true); + + String query = getArguments().getString(ARG_QUERY); + setEmptyText(getString(R.string.no_results_for_query, query)); } private final SearchlistAdapter.ItemAccess itemAccess = new SearchlistAdapter.ItemAccess() { @@ -219,9 +222,7 @@ public class SearchFragment extends ListFragment { onFragmentLoaded(); } } - }, error -> { - Log.e(TAG, Log.getStackTraceString(error)); - }); + }, error -> Log.e(TAG, Log.getStackTraceString(error))); } private List<SearchResult> performSearch() { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java index a314419ac..9626e6c2e 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java @@ -26,7 +26,9 @@ import de.danoeh.antennapod.core.service.playback.PlaybackService; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.util.FeedItemUtil; +import de.danoeh.antennapod.dialog.RenameFeedDialog; import rx.Observable; +import rx.Subscription; import rx.android.schedulers.AndroidSchedulers; import rx.schedulers.Schedulers; @@ -46,6 +48,7 @@ public class SubscriptionFragment extends Fragment { private int mPosition = -1; + private Subscription subscription; public SubscriptionFragment() { } @@ -88,16 +91,25 @@ public class SubscriptionFragment extends Fragment { EventDistributor.getInstance().register(contentUpdate); } + @Override + public void onDestroy() { + super.onDestroy(); + if(subscription != null) { + subscription.unsubscribe(); + } + } + private void loadSubscriptions() { - Observable.fromCallable(() -> DBReader.getNavDrawerData()) + if(subscription != null) { + subscription.unsubscribe(); + } + subscription = Observable.fromCallable(DBReader::getNavDrawerData) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(result -> { navDrawerData = result; subscriptionAdapter.notifyDataSetChanged(); - }, error -> { - Log.e(TAG, Log.getStackTraceString(error)); - }); + }, error -> Log.e(TAG, Log.getStackTraceString(error))); } @Override @@ -143,21 +155,18 @@ public class SubscriptionFragment extends Fragment { Observable.fromCallable(() -> DBWriter.markFeedSeen(feed.getId())) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(result -> { - loadSubscriptions(); - }, error -> { - Log.e(TAG, Log.getStackTraceString(error)); - }); + .subscribe(result -> loadSubscriptions(), + error -> Log.e(TAG, Log.getStackTraceString(error))); return true; case R.id.mark_all_read_item: Observable.fromCallable(() -> DBWriter.markFeedRead(feed.getId())) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(result -> { - loadSubscriptions(); - }, error -> { - Log.e(TAG, Log.getStackTraceString(error)); - }); + .subscribe(result -> loadSubscriptions(), + error -> Log.e(TAG, Log.getStackTraceString(error))); + return true; + case R.id.rename_item: + new RenameFeedDialog(getActivity(), feed).show(); return true; case R.id.remove_item: final FeedRemover remover = new FeedRemover(getContext(), feed) { @@ -169,7 +178,7 @@ public class SubscriptionFragment extends Fragment { }; ConfirmationDialog conDialog = new ConfirmationDialog(getContext(), R.string.remove_feed_label, - R.string.feed_delete_confirmation_msg) { + getString(R.string.feed_delete_confirmation_msg, feed.getTitle())) { @Override public void onConfirmButtonPressed( DialogInterface dialog) { diff --git a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java index b80213459..57b7c359c 100644 --- a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java +++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java @@ -80,7 +80,7 @@ public class FeedItemMenuHandler { if(queueAccess == null || queueAccess.size() == 0 || queueAccess.get(queueAccess.size()-1) == selectedItem.getId()) { mi.setItemVisibility(R.id.move_to_bottom_item, false); } - if (!isInQueue || isPlaying) { + if (!isInQueue) { mi.setItemVisibility(R.id.remove_from_queue_item, false); } if (!(!isInQueue && selectedItem.getMedia() != null)) { @@ -101,6 +101,8 @@ public class FeedItemMenuHandler { mi.setItemVisibility(R.id.share_download_url_with_position_item, false); } + mi.setItemVisibility(R.id.share_file, hasMedia && selectedItem.getMedia().fileExists()); + if (selectedItem.isPlayed()) { mi.setItemVisibility(R.id.mark_read_item, false); } else { @@ -239,6 +241,9 @@ public class FeedItemMenuHandler { case R.id.share_download_url_with_position_item: ShareUtils.shareFeedItemDownloadLink(context, selectedItem, true); break; + case R.id.share_file: + ShareUtils.shareFeedItemFile(context, selectedItem.getMedia()); + break; default: Log.d(TAG, "Unknown menuItemId: " + menuItemId); return false; diff --git a/app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java b/app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java index 4c28b197d..ac703e13e 100644 --- a/app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java +++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java @@ -28,6 +28,7 @@ public class MenuItemUtils extends de.danoeh.antennapod.core.menuhandler.MenuIte } } + @SuppressWarnings("ResourceType") public static void refreshLockItem(Context context, Menu menu) { final MenuItem queueLock = menu.findItem(de.danoeh.antennapod.R.id.queue_lock); int[] lockIcons = new int[] { de.danoeh.antennapod.R.attr.ic_lock_open, de.danoeh.antennapod.R.attr.ic_lock_closed }; diff --git a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java index 6c03dc7ae..2ca7dd029 100644 --- a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java +++ b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java @@ -3,6 +3,7 @@ package de.danoeh.antennapod.preferences; import android.Manifest; import android.annotation.SuppressLint; import android.app.Activity; +import android.app.ProgressDialog; import android.app.TimePickerDialog; import android.content.ActivityNotFoundException; import android.content.Context; @@ -28,14 +29,13 @@ import android.text.Editable; import android.text.Html; import android.text.TextWatcher; import android.text.format.DateFormat; +import android.text.format.DateUtils; import android.util.Log; import android.widget.EditText; -import android.widget.Toast; import android.widget.ListView; +import android.widget.Toast; import com.afollestad.materialdialogs.MaterialDialog; -import com.google.android.gms.common.ConnectionResult; -import com.google.android.gms.common.GoogleApiAvailability; import org.apache.commons.lang3.ArrayUtils; @@ -43,6 +43,8 @@ import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; +import java.util.Collections; +import java.util.Comparator; import java.util.GregorianCalendar; import java.util.List; import java.util.concurrent.TimeUnit; @@ -52,10 +54,14 @@ import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.AboutActivity; import de.danoeh.antennapod.activity.DirectoryChooserActivity; import de.danoeh.antennapod.activity.MainActivity; +import de.danoeh.antennapod.activity.MediaplayerActivity; import de.danoeh.antennapod.activity.PreferenceActivity; import de.danoeh.antennapod.activity.PreferenceActivityGingerbread; import de.danoeh.antennapod.activity.StatisticsActivity; -import de.danoeh.antennapod.asynctask.OpmlExportWorker; +import de.danoeh.antennapod.asynctask.ExportWorker; +import de.danoeh.antennapod.core.export.ExportWriter; +import de.danoeh.antennapod.core.export.html.HtmlWriter; +import de.danoeh.antennapod.core.export.opml.OpmlWriter; import de.danoeh.antennapod.core.preferences.GpodnetPreferences; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.GpodnetSyncService; @@ -67,6 +73,10 @@ import de.danoeh.antennapod.dialog.AutoFlattrPreferenceDialog; import de.danoeh.antennapod.dialog.GpodnetSetHostnameDialog; import de.danoeh.antennapod.dialog.ProxyDialog; import de.danoeh.antennapod.dialog.VariableSpeedDialog; +import rx.Observable; +import rx.Subscription; +import rx.android.schedulers.AndroidSchedulers; +import rx.schedulers.Schedulers; /** * Sets up a preference UI that lets the user change user preferences. @@ -76,35 +86,45 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc private static final String TAG = "PreferenceController"; - public static final String PREF_FLATTR_SETTINGS = "prefFlattrSettings"; - public static final String PREF_FLATTR_AUTH = "pref_flattr_authenticate"; - public static final String PREF_FLATTR_REVOKE = "prefRevokeAccess"; - public static final String PREF_AUTO_FLATTR_PREFS = "prefAutoFlattrPrefs"; - public static final String PREF_OPML_EXPORT = "prefOpmlExport"; - public static final String STATISTICS = "statistics"; - public static final String PREF_ABOUT = "prefAbout"; - public static final String PREF_CHOOSE_DATA_DIR = "prefChooseDataDir"; - public static final String AUTO_DL_PREF_SCREEN = "prefAutoDownloadSettings"; - public static final String PREF_PLAYBACK_SPEED_LAUNCHER = "prefPlaybackSpeedLauncher"; - public static final String PREF_GPODNET_LOGIN = "pref_gpodnet_authenticate"; - public static final String PREF_GPODNET_SETLOGIN_INFORMATION = "pref_gpodnet_setlogin_information"; - public static final String PREF_GPODNET_SYNC = "pref_gpodnet_sync"; - public static final String PREF_GPODNET_LOGOUT = "pref_gpodnet_logout"; - public static final String PREF_GPODNET_HOSTNAME = "pref_gpodnet_hostname"; - public static final String PREF_EXPANDED_NOTIFICATION = "prefExpandNotify"; - public static final String PREF_PROXY = "prefProxy"; - public static final String PREF_KNOWN_ISSUES = "prefKnownIssues"; - public static final String PREF_FAQ = "prefFaq"; - public static final String PREF_SEND_CRASH_REPORT = "prefSendCrashReport"; - - private final PreferenceUI ui; - - private CheckBoxPreference[] selectedNetworks; - + private static final String PREF_FLATTR_SETTINGS = "prefFlattrSettings"; + private static final String PREF_FLATTR_AUTH = "pref_flattr_authenticate"; + private static final String PREF_FLATTR_REVOKE = "prefRevokeAccess"; + private static final String PREF_AUTO_FLATTR_PREFS = "prefAutoFlattrPrefs"; + private static final String PREF_OPML_EXPORT = "prefOpmlExport"; + private static final String PREF_HTML_EXPORT = "prefHtmlExport"; + private static final String STATISTICS = "statistics"; + private static final String PREF_ABOUT = "prefAbout"; + private static final String PREF_CHOOSE_DATA_DIR = "prefChooseDataDir"; + private static final String AUTO_DL_PREF_SCREEN = "prefAutoDownloadSettings"; + private static final String PREF_PLAYBACK_SPEED_LAUNCHER = "prefPlaybackSpeedLauncher"; + public static final String PREF_PLAYBACK_REWIND_DELTA_LAUNCHER = "prefPlaybackRewindDeltaLauncher"; + public static final String PREF_PLAYBACK_FAST_FORWARD_DELTA_LAUNCHER = "prefPlaybackFastForwardDeltaLauncher"; + private static final String PREF_GPODNET_LOGIN = "pref_gpodnet_authenticate"; + private static final String PREF_GPODNET_SETLOGIN_INFORMATION = "pref_gpodnet_setlogin_information"; + private static final String PREF_GPODNET_SYNC = "pref_gpodnet_sync"; + private static final String PREF_GPODNET_FORCE_FULL_SYNC = "pref_gpodnet_force_full_sync"; + private static final String PREF_GPODNET_LOGOUT = "pref_gpodnet_logout"; + private static final String PREF_GPODNET_HOSTNAME = "pref_gpodnet_hostname"; + private static final String PREF_GPODNET_NOTIFICATIONS = "pref_gpodnet_notifications"; + private static final String PREF_EXPANDED_NOTIFICATION = "prefExpandNotify"; + private static final String PREF_PROXY = "prefProxy"; + private static final String PREF_KNOWN_ISSUES = "prefKnownIssues"; + private static final String PREF_FAQ = "prefFaq"; + private static final String PREF_SEND_CRASH_REPORT = "prefSendCrashReport"; private static final String[] EXTERNAL_STORAGE_PERMISSIONS = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE }; private static final int PERMISSION_REQUEST_EXTERNAL_STORAGE = 41; + private final PreferenceUI ui; + private final SharedPreferences.OnSharedPreferenceChangeListener gpoddernetListener = + (sharedPreferences, key) -> { + if (GpodnetPreferences.PREF_LAST_SYNC_ATTEMPT_TIMESTAMP.equals(key)) { + updateLastGpodnetSyncReport(GpodnetPreferences.getLastSyncAttemptResult(), + GpodnetPreferences.getLastSyncAttemptTimestamp()); + } + }; + private CheckBoxPreference[] selectedNetworks; + private Subscription subscription; public PreferenceController(PreferenceUI ui) { this.ui = ui; @@ -112,22 +132,12 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc .registerOnSharedPreferenceChangeListener(this); } - @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - if(key.equals(UserPreferences.PREF_SONIC)) { - CheckBoxPreference prefSonic = (CheckBoxPreference) ui.findPreference(UserPreferences.PREF_SONIC); - if(prefSonic != null) { - prefSonic.setChecked(sharedPreferences.getBoolean(UserPreferences.PREF_SONIC, false)); - } - } - } - /** * Returns the preference activity that should be used on this device. * * @return PreferenceActivity if the API level is greater than 10, PreferenceActivityGingerbread otherwise. */ - public static Class getPreferenceActivity() { + public static Class<? extends Activity> getPreferenceActivity() { if (Build.VERSION.SDK_INT > 10) { return PreferenceActivity.class; } else { @@ -135,6 +145,16 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc } } + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + if(key.equals(UserPreferences.PREF_SONIC)) { + CheckBoxPreference prefSonic = (CheckBoxPreference) ui.findPreference(UserPreferences.PREF_SONIC); + if(prefSonic != null) { + prefSonic.setChecked(sharedPreferences.getBoolean(UserPreferences.PREF_SONIC, false)); + } + } + } + public void onCreate() { final Activity activity = ui.getActivity(); @@ -170,11 +190,9 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc } ); ui.findPreference(PreferenceController.PREF_OPML_EXPORT).setOnPreferenceClickListener( - preference -> { - new OpmlExportWorker(activity).executeAsync(); - return true; - } - ); + preference -> export(new OpmlWriter())); + ui.findPreference(PreferenceController.PREF_HTML_EXPORT).setOnPreferenceClickListener( + preference -> export(new HtmlWriter())); ui.findPreference(PreferenceController.PREF_CHOOSE_DATA_DIR).setOnPreferenceClickListener( preference -> { if (Build.VERSION_CODES.KITKAT <= Build.VERSION.SDK_INT && @@ -318,6 +336,16 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc VariableSpeedDialog.showDialog(activity); return true; }); + ui.findPreference(PreferenceController.PREF_PLAYBACK_REWIND_DELTA_LAUNCHER) + .setOnPreferenceClickListener(preference -> { + MediaplayerActivity.showSkipPreference(activity, MediaplayerActivity.SkipDirection.SKIP_REWIND); + return true; + }); + ui.findPreference(PreferenceController.PREF_PLAYBACK_FAST_FORWARD_DELTA_LAUNCHER) + .setOnPreferenceClickListener(preference -> { + MediaplayerActivity.showSkipPreference(activity, MediaplayerActivity.SkipDirection.SKIP_FORWARD); + return true; + }); ui.findPreference(PreferenceController.PREF_GPODNET_SETLOGIN_INFORMATION) .setOnPreferenceClickListener(preference -> { AuthenticationDialog dialog = new AuthenticationDialog(activity, @@ -340,6 +368,18 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc toast.show(); return true; }); + ui.findPreference(PreferenceController.PREF_GPODNET_FORCE_FULL_SYNC). + setOnPreferenceClickListener(preference -> { + GpodnetPreferences.setLastSubscriptionSyncTimestamp(0L); + GpodnetPreferences.setLastEpisodeActionsSyncTimestamp(0L); + GpodnetPreferences.setLastSyncAttempt(false, 0); + updateLastGpodnetSyncReport(false, 0); + GpodnetSyncService.sendSyncIntent(ui.getActivity().getApplicationContext()); + Toast toast = Toast.makeText(ui.getActivity(), R.string.pref_gpodnet_sync_started, + Toast.LENGTH_SHORT); + toast.show(); + return true; + }); ui.findPreference(PreferenceController.PREF_GPODNET_LOGOUT).setOnPreferenceClickListener( preference -> { GpodnetPreferences.logout(); @@ -412,28 +452,47 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc ui.getActivity().startActivity(Intent.createChooser(emailIntent, intentTitle)); return true; }); - //checks whether Google Play Services is installed on the device (condition necessary for Cast support) - ui.findPreference(UserPreferences.PREF_CAST_ENABLED).setOnPreferenceChangeListener((preference, o) -> { - if (o instanceof Boolean && ((Boolean) o)) { - final int googlePlayServicesCheck = GoogleApiAvailability.getInstance() - .isGooglePlayServicesAvailable(ui.getActivity()); - if (googlePlayServicesCheck == ConnectionResult.SUCCESS) { - return true; - } else { - GoogleApiAvailability.getInstance() - .getErrorDialog(ui.getActivity(), googlePlayServicesCheck, 0) - .show(); - return false; - } - } - return true; - }); + PreferenceControllerFlavorHelper.setupFlavoredUI(ui); buildEpisodeCleanupPreference(); buildSmartMarkAsPlayedPreference(); buildAutodownloadSelectedNetworsPreference(); setSelectedNetworksEnabled(UserPreferences.isEnableAutodownloadWifiFilter()); } + private boolean export(ExportWriter exportWriter) { + Context context = ui.getActivity(); + final ProgressDialog progressDialog = new ProgressDialog(context); + progressDialog.setMessage(context.getString(R.string.exporting_label)); + progressDialog.setIndeterminate(true); + progressDialog.show(); + final AlertDialog.Builder alert = new AlertDialog.Builder(context) + .setNeutralButton(android.R.string.ok, (dialog, which) -> dialog.dismiss()); + Observable<File> observable = new ExportWorker(exportWriter).exportObservable(); + subscription = observable.subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(output -> { + alert.setTitle(R.string.opml_export_success_title); + String message = context.getString(R.string.opml_export_success_sum) + output.toString(); + alert.setMessage(message); + alert.setPositiveButton(R.string.send_label, (dialog, which) -> { + Uri outputUri = Uri.fromFile(output); + Intent sendIntent = new Intent(Intent.ACTION_SEND); + sendIntent.putExtra(Intent.EXTRA_SUBJECT, + context.getResources().getText(R.string.opml_export_label)); + sendIntent.putExtra(Intent.EXTRA_STREAM, outputUri); + sendIntent.setType("text/plain"); + context.startActivity(Intent.createChooser(sendIntent, + context.getResources().getText(R.string.send_label))); + }); + alert.create().show(); + }, error -> { + alert.setTitle(R.string.export_error_label); + alert.setMessage(error.getMessage()); + alert.show(); + }, () -> progressDialog.dismiss()); + return true; + } + private void openInBrowser(String url) { try { Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); @@ -450,9 +509,20 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc setParallelDownloadsText(UserPreferences.getParallelDownloads()); setEpisodeCacheSizeText(UserPreferences.getEpisodeCacheSize()); setDataFolderText(); + GpodnetPreferences.registerOnSharedPreferenceChangeListener(gpoddernetListener); updateGpodnetPreferenceScreen(); } + public void onPause() { + GpodnetPreferences.unregisterOnSharedPreferenceChangeListener(gpoddernetListener); + } + + public void onStop() { + if(subscription != null) { + subscription.unsubscribe(); + } + } + @SuppressLint("NewApi") public void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode == Activity.RESULT_OK && @@ -494,18 +564,41 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc ui.findPreference(PreferenceController.PREF_GPODNET_LOGIN).setEnabled(!loggedIn); ui.findPreference(PreferenceController.PREF_GPODNET_SETLOGIN_INFORMATION).setEnabled(loggedIn); ui.findPreference(PreferenceController.PREF_GPODNET_SYNC).setEnabled(loggedIn); + ui.findPreference(PreferenceController.PREF_GPODNET_FORCE_FULL_SYNC).setEnabled(loggedIn); ui.findPreference(PreferenceController.PREF_GPODNET_LOGOUT).setEnabled(loggedIn); + ui.findPreference(PREF_GPODNET_NOTIFICATIONS).setEnabled(loggedIn); if(loggedIn) { String format = ui.getActivity().getString(R.string.pref_gpodnet_login_status); String summary = String.format(format, GpodnetPreferences.getUsername(), GpodnetPreferences.getDeviceID()); ui.findPreference(PreferenceController.PREF_GPODNET_LOGOUT).setSummary(Html.fromHtml(summary)); + updateLastGpodnetSyncReport(GpodnetPreferences.getLastSyncAttemptResult(), + GpodnetPreferences.getLastSyncAttemptTimestamp()); } else { ui.findPreference(PreferenceController.PREF_GPODNET_LOGOUT).setSummary(null); + updateLastGpodnetSyncReport(false, 0); } ui.findPreference(PreferenceController.PREF_GPODNET_HOSTNAME).setSummary(GpodnetPreferences.getHostname()); } + private void updateLastGpodnetSyncReport(boolean successful, long lastTime) { + Preference sync = ui.findPreference(PREF_GPODNET_SYNC); + if (lastTime != 0) { + sync.setSummary(ui.getActivity().getString(R.string.pref_gpodnet_sync_changes_sum) + "\n" + + ui.getActivity().getString(R.string.pref_gpodnet_sync_sum_last_sync_line, + ui.getActivity().getString(successful ? + R.string.gpodnetsync_pref_report_successful : + R.string.gpodnetsync_pref_report_failed), + DateUtils.getRelativeDateTimeString(ui.getActivity(), + lastTime, + DateUtils.MINUTE_IN_MILLIS, + DateUtils.WEEK_IN_MILLIS, + DateUtils.FORMAT_SHOW_TIME))); + } else { + sync.setSummary(ui.getActivity().getString(R.string.pref_gpodnet_sync_changes_sum)); + } + } + private String[] getUpdateIntervalEntries(final String[] values) { final Resources res = ui.getActivity().getResources(); String[] entries = new String[values.length]; @@ -621,7 +714,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc val = String.format(context.getString(R.string.pref_autoUpdateIntervallOrTime_at), timeOfDayStr); } else { - val = context.getString(R.string.pref_smart_mark_as_played_disabled); + val = context.getString(R.string.pref_smart_mark_as_played_disabled); // TODO: Is this a bug? Otherwise document why is this related to smart mark??? } } String summary = context.getString(R.string.pref_autoUpdateIntervallOrTime_sum) + "\n" @@ -666,10 +759,16 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc clearAutodownloadSelectedNetworsPreference(); } // get configured networks - WifiManager wifiservice = (WifiManager) activity.getSystemService(Context.WIFI_SERVICE); + WifiManager wifiservice = (WifiManager) activity.getApplicationContext().getSystemService(Context.WIFI_SERVICE); List<WifiConfiguration> networks = wifiservice.getConfiguredNetworks(); if (networks != null) { + Collections.sort(networks, new Comparator<WifiConfiguration>() { + @Override + public int compare(WifiConfiguration x, WifiConfiguration y) { + return x.SSID.compareTo(y.SSID); + } + }); selectedNetworks = new CheckBoxPreference[networks.size()]; List<String> prefValues = Arrays.asList(UserPreferences .getAutodownloadSelectedNetworks()); @@ -754,9 +853,8 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc hiddenDrawerItems.add(NAV_DRAWER_TAGS[which]); } }); - builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> { - UserPreferences.setHiddenDrawerItems(hiddenDrawerItems); - }); + builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> + UserPreferences.setHiddenDrawerItems(hiddenDrawerItems)); builder.setNegativeButton(R.string.cancel_label, null); builder.create().show(); } @@ -800,9 +898,8 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc preferredButtons.remove((Integer) which); } }); - builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> { - UserPreferences.setCompactNotificationButtons(preferredButtons); - }); + builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> + UserPreferences.setCompactNotificationButtons(preferredButtons)); builder.setNegativeButton(R.string.cancel_label, null); builder.create().show(); } diff --git a/description/az.txt b/app/src/main/play/ar/listing/fulldescription index b4955d18a..87b477fdc 100644 --- a/description/az.txt +++ b/app/src/main/play/ar/listing/fulldescription @@ -1,5 +1,3 @@ -Easy-to-use, flexible and open-source podcast manager and player - AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. @@ -35,6 +33,9 @@ https://www.github.com/AntennaPod/AntennaPod Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> https://groups.google.com/forum/#!forum/antennapod +Have a question or want to give us feedback? +https://twitter.com/@AntennaPod + Transifex is the place to help with translations:<br> https://www.transifex.com/antennapod/antennapod diff --git a/changelog/ar.md b/app/src/main/play/ar/whatsnew index 8f2618b8f..8f2618b8f 100644 --- a/changelog/ar.md +++ b/app/src/main/play/ar/whatsnew diff --git a/description/ar.txt b/app/src/main/play/ast_ES/listing/fulldescription index b4955d18a..87b477fdc 100644 --- a/description/ar.txt +++ b/app/src/main/play/ast_ES/listing/fulldescription @@ -1,5 +1,3 @@ -Easy-to-use, flexible and open-source podcast manager and player - AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. @@ -35,6 +33,9 @@ https://www.github.com/AntennaPod/AntennaPod Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> https://groups.google.com/forum/#!forum/antennapod +Have a question or want to give us feedback? +https://twitter.com/@AntennaPod + Transifex is the place to help with translations:<br> https://www.transifex.com/antennapod/antennapod diff --git a/description/ca_ES.txt b/app/src/main/play/az/listing/fulldescription index b4955d18a..87b477fdc 100644 --- a/description/ca_ES.txt +++ b/app/src/main/play/az/listing/fulldescription @@ -1,5 +1,3 @@ -Easy-to-use, flexible and open-source podcast manager and player - AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. @@ -35,6 +33,9 @@ https://www.github.com/AntennaPod/AntennaPod Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> https://groups.google.com/forum/#!forum/antennapod +Have a question or want to give us feedback? +https://twitter.com/@AntennaPod + Transifex is the place to help with translations:<br> https://www.transifex.com/antennapod/antennapod diff --git a/changelog/az.md b/app/src/main/play/az/whatsnew index 8f2618b8f..8f2618b8f 100644 --- a/changelog/az.md +++ b/app/src/main/play/az/whatsnew diff --git a/description/ca.txt b/app/src/main/play/ca/listing/fulldescription index b4955d18a..87b477fdc 100644 --- a/description/ca.txt +++ b/app/src/main/play/ca/listing/fulldescription @@ -1,5 +1,3 @@ -Easy-to-use, flexible and open-source podcast manager and player - AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. @@ -35,6 +33,9 @@ https://www.github.com/AntennaPod/AntennaPod Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> https://groups.google.com/forum/#!forum/antennapod +Have a question or want to give us feedback? +https://twitter.com/@AntennaPod + Transifex is the place to help with translations:<br> https://www.transifex.com/antennapod/antennapod diff --git a/app/src/main/play/ca/listing/shortdescription b/app/src/main/play/ca/listing/shortdescription new file mode 100644 index 000000000..4eceefbb7 --- /dev/null +++ b/app/src/main/play/ca/listing/shortdescription @@ -0,0 +1 @@ +Easy-to-use, flexible and open-source podcast manager and player
\ No newline at end of file diff --git a/app/src/main/play/ca/listing/title b/app/src/main/play/ca/listing/title new file mode 100644 index 000000000..31552f353 --- /dev/null +++ b/app/src/main/play/ca/listing/title @@ -0,0 +1 @@ +AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/ca/listing/video b/app/src/main/play/ca/listing/video new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/app/src/main/play/ca/listing/video diff --git a/app/src/main/play/ca/whatsnew b/app/src/main/play/ca/whatsnew new file mode 100644 index 000000000..a65bddbbb --- /dev/null +++ b/app/src/main/play/ca/whatsnew @@ -0,0 +1,11 @@ +* New features: + * Subscription overview + * Proxy support + * Statistics + * Manual gpodder.net sync +* Fixes: + * Audioplayer controls + * Audio ducking + * Video control fade-out + * External media controls + * Feed parsing
\ No newline at end of file diff --git a/app/src/main/play/ca_ES/listing/fulldescription b/app/src/main/play/ca_ES/listing/fulldescription new file mode 100644 index 000000000..87b477fdc --- /dev/null +++ b/app/src/main/play/ca_ES/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> +But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. + +Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. + +<b>All features:</b><br> +IMPORT, ORGANIZE AND PLAY<br> +• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> +• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> +• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> +• Access password-protected feeds and episodes<br> +• Take advantage of paged feeds (www.podlove.org/paged-feeds) + +KEEP TRACK, SHARE & APPRECIATE<br> +• Keep track of the best of the best by marking episodes as favourites<br> +• Find that one episode through the playback history or by searching (titles and shownotes)<br> +• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> +• Support content creators with Flattr integration including automatic flattring + +CONTROL THE SYSTEM<br> +• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> +• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> +• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adapt to your environment using the light and dark theme<br> +• Back-up your subscriptions with the gPodder.net integration and OPML export + +<b>Join the AntennaPod community!</b><br> +AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! + +GitHub is the place to go for feature requests, bug reports and code contributions:<br> +https://www.github.com/AntennaPod/AntennaPod + +Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> +https://groups.google.com/forum/#!forum/antennapod + +Have a question or want to give us feedback? +https://twitter.com/@AntennaPod + +Transifex is the place to help with translations:<br> +https://www.transifex.com/antennapod/antennapod + +Check out our Beta Testing programme to get the latest features first:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/ca_ES.md b/app/src/main/play/ca_ES/whatsnew index 8f2618b8f..8f2618b8f 100644 --- a/changelog/ca_ES.md +++ b/app/src/main/play/ca_ES/whatsnew diff --git a/app/src/main/play/contactEmail b/app/src/main/play/contactEmail new file mode 100644 index 000000000..d4543c6e0 --- /dev/null +++ b/app/src/main/play/contactEmail @@ -0,0 +1 @@ +antennapod@googlegroups.com
\ No newline at end of file diff --git a/app/src/main/play/contactPhone b/app/src/main/play/contactPhone new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/app/src/main/play/contactPhone diff --git a/app/src/main/play/contactWebsite b/app/src/main/play/contactWebsite new file mode 100644 index 000000000..cb1c2f641 --- /dev/null +++ b/app/src/main/play/contactWebsite @@ -0,0 +1 @@ +https://github.com/AntennaPod/AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/cs-CZ/listing/fulldescription b/app/src/main/play/cs-CZ/listing/fulldescription new file mode 100644 index 000000000..204c521f2 --- /dev/null +++ b/app/src/main/play/cs-CZ/listing/fulldescription @@ -0,0 +1,20 @@ +AntennaPod je open-source správce podcastů pro Android 2.3.3 a novÄ›jÅ¡Ã. NabÃzà vÅ¡echny základnà funkce, které můžete oÄekávat od podcast klienta, jako jsou pÅ™ehrávánà streamu a stahovánà epizod, automatické sledovánà jednotlivých podcastů nebo pÅ™idávánà nových epizod do fronty pro pozdÄ›jÅ¡Ã poslech. NavÃc AntennaPod umožňuje podpoÅ™it podcasty pÅ™Ãmo z aplikace pomocà služby flattr. + +ZatÃm jsou zavedeny tyto možnosti: + +* Stahovánà a streamovaný poslech epizod +* Různé rychlosti pÅ™ehrávánà (vyžaduje knihovnu Presto Sound nebo Prestissimo) +* Podpora Atom a RSS zdrojů +* Podpora pro zdroje a epizody chránÄ›né heslem +* Support for searching iTunes listings +* OPML import a export +* Integrace pro Flattr vÄetnÄ› automatického flattrovánà +* Widget pÅ™ehrávaÄe na domácà obrazovku +* Vyhledávánà +* Automatické sledovánà zdrojů +* Automatické stahovánà nových epizod +* ÄŒasovaÄ vypnutà +* PÅ™Ãstup do seznamu podcastů na gpodder.net +* Synchronizace pÅ™ihlášené služby na gpodder.net +* Podporuje MP3 kapitoly, VorbisComment kapitoly a Podlove Simple Chapters +* Podporuje stránkované kanály (http://podlove.org/paged-feeds/)
\ No newline at end of file diff --git a/app/src/main/play/cs-CZ/listing/shortdescription b/app/src/main/play/cs-CZ/listing/shortdescription new file mode 100644 index 000000000..5f700bd93 --- /dev/null +++ b/app/src/main/play/cs-CZ/listing/shortdescription @@ -0,0 +1 @@ +Open-source správce podcastu pro Android
\ No newline at end of file diff --git a/app/src/main/play/cs-CZ/listing/title b/app/src/main/play/cs-CZ/listing/title new file mode 100644 index 000000000..31552f353 --- /dev/null +++ b/app/src/main/play/cs-CZ/listing/title @@ -0,0 +1 @@ +AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/cs-CZ/listing/video b/app/src/main/play/cs-CZ/listing/video new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/app/src/main/play/cs-CZ/listing/video diff --git a/app/src/main/play/cs-CZ/whatsnew b/app/src/main/play/cs-CZ/whatsnew new file mode 100644 index 000000000..a65bddbbb --- /dev/null +++ b/app/src/main/play/cs-CZ/whatsnew @@ -0,0 +1,11 @@ +* New features: + * Subscription overview + * Proxy support + * Statistics + * Manual gpodder.net sync +* Fixes: + * Audioplayer controls + * Audio ducking + * Video control fade-out + * External media controls + * Feed parsing
\ No newline at end of file diff --git a/app/src/main/play/cs_CZ/listing/fulldescription b/app/src/main/play/cs_CZ/listing/fulldescription new file mode 100644 index 000000000..4e15342ee --- /dev/null +++ b/app/src/main/play/cs_CZ/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> +But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. + +Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. + +<b>All features:</b><br> +IMPORT, ORGANIZE AND PLAY<br> +• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> +• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> +• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> +• Access password-protected feeds and episodes<br> +• Take advantage of paged feeds (www.podlove.org/paged-feeds) + +KEEP TRACK, SHARE & APPRECIATE<br> +• Keep track of the best of the best by marking episodes as favourites<br> +• Find that one episode through the playback history or by searching (titles and shownotes)<br> +• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> +• Support content creators with Flattr integration including automatic flattring + +CONTROL THE SYSTEM<br> +• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> +• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> +• PoužÃvejte AntennaPod ve vlastnÃm jazyce (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adapt to your environment using the light and dark theme<br> +• Back-up your subscriptions with the gPodder.net integration and OPML export + +<b>PÅ™idejte se ke komunitÄ› AntennaPod!</b><br> +AntennaPod je aktivnÄ› vyvÃjen dobrovolnÃky. Můžete pÅ™ispÄ›t také svým kódem nebo komentáři! + +GitHub is the place to go for feature requests, bug reports and code contributions:<br> +https://www.github.com/AntennaPod/AntennaPod + +Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> +https://groups.google.com/forum/#!forum/antennapod + +Máte dotaz nebo chcete poslat svůj názor? +https://twitter.com/@AntennaPod + +PÅ™eklady jsou spravovány pomocà služby Transifex:<br> +https://www.transifex.com/antennapod/antennapod + +Check out our Beta Testing programme to get the latest features first:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/cs_CZ.md b/app/src/main/play/cs_CZ/whatsnew index bf852d3cc..bf852d3cc 100644 --- a/changelog/cs_CZ.md +++ b/app/src/main/play/cs_CZ/whatsnew diff --git a/app/src/main/play/da-DK/listing/fulldescription b/app/src/main/play/da-DK/listing/fulldescription new file mode 100644 index 000000000..1d19da2e8 --- /dev/null +++ b/app/src/main/play/da-DK/listing/fulldescription @@ -0,0 +1,20 @@ +AntennaPod er en open-source podcast afspiller for Android 2.3.3 og nyere. Den tilbyder alle basale features du forventer fra en podcastafspiller, som streaming og download af episoder, opdaterer automatisk feeds eller tilføjer dem automatisk i en kø så du kan høre dem senere. Derudover lader AntennaPod dig flattr podcasts og episoder inde i appen. + +Indtil nu er følgende features blevet implementeret: + +* Download og Streaming af episoder +* Variabel afspilningshastighed (kræver Presto Sound Library eller Prestissimo) +* Understøttelse af Atom og RSS feeds +* Understøttelse af password-beskyttede feeds og episoder +* Support for searching iTunes listings +* OPML import og eksport +* Flattr integration inkluderer automatisk flattring +* Afspiller widget +* Søg +* Automatisk opdatering af feeds +* Automatisk download af nye episoder +* Sleep timer +* Adgang til gpodder.net's podcast bibliotek +* Synkronisering af abonnementer med gpodder.net's service +* Understøtter af MP3 kapitler, VorbisComment kapitler and Podlove Simple Chapters +* Understøtter side-delte feeds (http://podlove.org/paged-feeds/)
\ No newline at end of file diff --git a/app/src/main/play/da-DK/listing/shortdescription b/app/src/main/play/da-DK/listing/shortdescription new file mode 100644 index 000000000..4eceefbb7 --- /dev/null +++ b/app/src/main/play/da-DK/listing/shortdescription @@ -0,0 +1 @@ +Easy-to-use, flexible and open-source podcast manager and player
\ No newline at end of file diff --git a/app/src/main/play/da-DK/listing/title b/app/src/main/play/da-DK/listing/title new file mode 100644 index 000000000..31552f353 --- /dev/null +++ b/app/src/main/play/da-DK/listing/title @@ -0,0 +1 @@ +AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/da-DK/listing/video b/app/src/main/play/da-DK/listing/video new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/app/src/main/play/da-DK/listing/video diff --git a/app/src/main/play/da-DK/whatsnew b/app/src/main/play/da-DK/whatsnew new file mode 100644 index 000000000..a65bddbbb --- /dev/null +++ b/app/src/main/play/da-DK/whatsnew @@ -0,0 +1,11 @@ +* New features: + * Subscription overview + * Proxy support + * Statistics + * Manual gpodder.net sync +* Fixes: + * Audioplayer controls + * Audio ducking + * Video control fade-out + * External media controls + * Feed parsing
\ No newline at end of file diff --git a/app/src/main/play/da/listing/fulldescription b/app/src/main/play/da/listing/fulldescription new file mode 100644 index 000000000..241066fd4 --- /dev/null +++ b/app/src/main/play/da/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod er en app til hÃ¥ndtering og afspilning af podcasts. Den giver dig øjeblikkelig adgang til millioner af gratis og betalte podcasts, fra uafhængige podcastere til store udgivere som BBC, NPR, CNN og DR. Tilføj, importer og eksporter deres feeds problemfrit ved hjælp af iTunes-podcastdatabasen, OPML-filer eller enkle RSS-webadresser. Spar kræfter, batteristrøm og mobilt dataforbrug med kraftfulde automatiske styringsværktøjer til at hente udsendelser (angiv tidspunkter, tidsintervaller og udvalgte wi-fi-netværk) og sletning af episoder (baseret pÃ¥ dine foretrukne udsendelser og forsinkelsesindstillinger).<br> +Men vigtigst af alt: Hent, stream eller sæt udsendelser i kø og nyd dem pÃ¥ den mÃ¥de du kan lide med justerbare hastigheder, kapitelunderstøttelse og en søvntimer. Du kan endda vise din pÃ¥skønnelse over for indholdsskaberne med vores Flattr-integration. + +AntennaPod er lavet af en podcast-entusiast og er gratis og fri i alle betydninger: open source, ingen udgifter, ingen reklamer. + +<b>Alle funktioner:</b><br> +IMPORTER, ORGANISER OG AFSPIL<br> +• Tilføj og importer feeds via iTunes- og gpodder.net-oversigterne, OPML-filer og RSS- eller Atom-links<br> +• HÃ¥ndter afspilning fra hvor som helst: widget pÃ¥ startskærmen, systemnotifikation, samt hovedtelefon- og bluetooth-styring<br> +• Lyt pÃ¥ din egen mÃ¥de med justerbar afspilningshastighed, kapitelunderstøttelse (MP3, VorbisComment og Podlove), erindring af afspilningsposition og en avanceret søvntimer (ryst for at nulstille, sænke lydstyrken og afspille langsommere)<br> +• TilgÃ¥ feeds og udsendelser beskyttet med adgangskode<br> +• Brug sideinddelte feeds (www.podlove.org/paged-feeds) + +HOLD STYR PÃ…, DEL OG ANERKEND<br> +• Hold styr pÃ¥ det bedste af det bedste ved at markere udsendelser som foretrukne<br> +• Find en bestemt udsendelse via afspilningshistorikken eller ved at søge (titler og beskrivelser)<br> +• Del udsendelser og feeds via avancerede valgmuligheder for sociale medier, gpodder.net-tjenesterne og OPML-eksport<br> +• Støt indholdsskabere med Flattr-integration, inklusive automatisk flattring + +STYR SYSTEMET<br> +• Tag styring over automatiseret hentning: vælg feeds, udeluk mobile netværk, vælg specifikke wi-fi-netvæk, kræv at telefonen oplader og indstil tidspunkter eller tidsintervaller +• HÃ¥ndter lagerforbruget ved at indstille antallet af udsendelser, der skal gemmes, smart sletning (baseret pÃ¥ dine foretrukne og afspilningsstatus) og ved at vælge den lagerplacering, du foretrækker<br> +• Brug AntennaPod pÃ¥ dit eget sprog (EN, DE, DA, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Tilpas appen til dit miljø med det lyse og mørke tema<br> +• Sikkerhedskopier dine abonnementer med gpodder.net-integrationen og OPML-eksport + +<b>Bliv en del af AntennaPod-fællesskabet!</b><br> +AntennaPod er under aktiv udvikling af frivillige. Du kan ogsÃ¥ bidrage, med kode eller kommentarer! + +GitHub er stedet for forslag tli ny funktionalitet, fejlrapporter og kodebidrag:<br> +https://www.github.com/AntennaPod/AntennaPod + +Vores Google-gruppe er stedet til at dele dine ideer, foretrukne podcast-øjeblikke og taknemmelighed til alle de frivillige:<br> +https://groups.google.com/forum/#!forum/antennapod + +Har du et spørgsmÃ¥l eller vil du give os en tilbagemelding? +https://twitter.com/@AntennaPod + +Transifex er stedet, hvis du vil hjælpe med oversættelser:<br> +https://www.transifex.com/antennapod/antennapod + +Prøv vores beta-testprogram for at fÃ¥ de nyeste funktioner først:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/da.md b/app/src/main/play/da/whatsnew index 21935a8d9..21935a8d9 100644 --- a/changelog/da.md +++ b/app/src/main/play/da/whatsnew diff --git a/app/src/main/play/de-DE/listing/fulldescription b/app/src/main/play/de-DE/listing/fulldescription new file mode 100644 index 000000000..c2299c44f --- /dev/null +++ b/app/src/main/play/de-DE/listing/fulldescription @@ -0,0 +1,20 @@ +AntennaPod ist ein Open-Source Podcastmanager für Android 2.3.3+. Er bietet alle grundlegenden Funktionen, die Sie von einem Podcatcher erwarten. Dazu gehören das Streaming und Herunterladen von Episoden, alle Feeds automatisch zu aktualisieren oder sie einer Warteschlange hinzuzufügen, um sie später zu hören. Darüber hinaus können Sie mit AntennaPod Podcasts und Episoden aus der App heraus flattrn. + +Bisher sind folgende Funktionen eingebaut: + +* Herunterladen und Streamen von Episoden +Variable Abspielgeschwindigkeit (benötigt Presto Sound Library oder Prestissimo) +* Unterstützung von Atom- und RSS-Feeds +* Unterstützung für Passwort-geschützte Feeds und Episoden +* Unterstützung für Auflistungen die in iTunes gesucht werden +* OPML-Import und -Export +* Flattr-Integration, einschließlich automatischem Flattrn +* Player-Homescreen-Widget +* Suche +* Automatische Feed-Aktualisierungen +* Automatisches Herunterladen von neuen Episoden +* Schlummerfunktion +* Zugang zum gpodder.net-Verzeichnis hinzugefügt +* Option zum Synchronisieren der Podcast-Abonnements mit dem gpodder.net-Service hinzugefügt +* Unterstützt Kapitelmarken in MP3 und VorbisComment, sowie Podlove Simple Chapters +* Unterstützt Paged Feeds (http://podlove.org/paged-feeds/)
\ No newline at end of file diff --git a/app/src/main/play/de-DE/listing/shortdescription b/app/src/main/play/de-DE/listing/shortdescription new file mode 100644 index 000000000..cc5ca9df6 --- /dev/null +++ b/app/src/main/play/de-DE/listing/shortdescription @@ -0,0 +1 @@ +Einfach zu benutzender und anpassbarer Open-Source Podcast-Manager
\ No newline at end of file diff --git a/app/src/main/play/de-DE/listing/title b/app/src/main/play/de-DE/listing/title new file mode 100644 index 000000000..31552f353 --- /dev/null +++ b/app/src/main/play/de-DE/listing/title @@ -0,0 +1 @@ +AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/de-DE/listing/video b/app/src/main/play/de-DE/listing/video new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/app/src/main/play/de-DE/listing/video diff --git a/app/src/main/play/de-DE/whatsnew b/app/src/main/play/de-DE/whatsnew new file mode 100644 index 000000000..094c56808 --- /dev/null +++ b/app/src/main/play/de-DE/whatsnew @@ -0,0 +1,12 @@ +* Neue Funktionen: + * Unterstützung von Chromecast (experimentell) + * Abonnement Übersicht + * Unterstützung von Proxies + * Statistiken + * Manuelle Synchronization mit gpodder.net +* Behobene Fehler: + * Wiedergabesteuerung + * Ducking (Absenken der Lautstärke bei anderen Signalen) + * Ausblenden der Video-Steuerelemente + * Externe Steuerelemente + * Einlesen von Feeds
\ No newline at end of file diff --git a/description/de.txt b/app/src/main/play/de/listing/fulldescription index 84f6c388b..e5d7ec72a 100644 --- a/description/de.txt +++ b/app/src/main/play/de/listing/fulldescription @@ -1,6 +1,4 @@ -Einfach zu benutzender und anpassbarer Open-Source Podcast-Manager - -AntennaPod ist ein Podcast-Manager und -Player, der dir unmittelbar Zugriff auf Millionen von freien und bezahlten Podcasts ermöglicht, angefangen von unabhängigen Podcastern zu großen Rundfunkanstalten oder Hörfunksendern wie BBC, NPR und CNN. Abonniere, importiere und exportiere deine Feeds mühelos mit Hilfe des iTunes-Verzeichnisses, OPML-Dateien oder einfachen RSS-URLs. Reduziere Aufwand, Stromverbrauch und Datenverbrauch durch die Kontrolle der Downloads (bestimmte Uhrzeiten, Intervalle, WiFi-Netze) und des Löschens (basierend auf deinen Favoriten und weiteren Einstellungen). +AntennaPod ist ein Podcast-Manager und -Player, der Dir unmittelbar Zugriff auf Millionen von freien und bezahlten Podcasts ermöglicht, angefangen von unabhängigen Podcastern zu großen Rundfunkanstalten oder Hörfunksendern wie BBC, NPR und CNN. Abonniere, importiere und exportiere deine Feeds mühelos mit Hilfe des iTunes-Verzeichnisses, OPML-Dateien oder einfachen RSS-URLs. Reduziere Aufwand, Stromverbrauch und Datenverbrauch durch die Kontrolle der Downloads (bestimmte Uhrzeiten, Intervalle, WiFi-Netze) und des Löschens von Episoden (basierend auf deinen Favoriten und weiteren Einstellungen).<br> Aber am wichtigsten: Downloade, streame oder füge Episoden zur Abspielliste hinzu und genieße sie mit einstellbarer Abspielgeschwindigkeit, Unterstützung von Kapiteln und Schlummerfunktion. Mit Flattr kannst du den Podcastern sogar deine Wertschätzung zeigen. AntennaPod ist, von Podcast-Enthusiasten gemacht, frei im Sinne des Wortes: Open Source, keine Kosten, keine Werbung. @@ -14,32 +12,32 @@ IMPORTIERE, ORGANISIERE UND HÖRE<br> • Nutze den Vorteil von Paged Feeds (http://www.podlove.org/paged-feeds) ORDNE, TEILE & GENIEßE -• Behalten den Ãœberblück über die Besten der Besten, indem du Episoden als Favoriten markierst +• Bleib an den Besten der Besten dran, indem Du Episoden als Favoriten markierst<br> • Finde Episoden durch die Liste zuletzt gespielter Episoden oder durch Suche in Titel und Shownotes • Teile Episoden and Feeds über soziale Medien, E-Mail, den gPodder.net-Dienst oder als OPML-Export • Unterstütze die Autoren von Inhalten mit Flattr (inklusive automatischem Flattren) STEUER DAS SYSTEM<br> -• Kontrolliere automatisches Herunterladen: Wähle Feeds aus, filtere Episodes durch Schlüsselwörter, schließe mobile Netze aus, suche bestimmte WiFi-Netze aus, setze voraus, dass das Smartphone geladen wird und lege Zeitpunkt oder Intervalle fest<br> +• Kontrolliere automatisches Herunterladen: Wähle Feeds aus, schließe mobile Netze aus, suche bestimmte WiFi-Netze aus, setze voraus, dass das Smartphone geladen wird und lege Zeitpunkte oder Intervalle fest<br> • Verwalte deinen Speicherplatz durch das Festlegen der Anzahl gespeicherter Episoden, schlaues Löschen und durch Auswahl des Speicherortes<br> • Benutze AntennaPod in deiner Sprache (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> • Passe das Aussehen mit dem hellen oder dunklen Theme an<br> • Sichere deine Abonnements mit gPodder.net oder über den OPML-Export -<b>Trete der AntennaPod-Community bei!</b> +<b>Trete der AntennaPod-Community bei!</b><br> AntennaPod wird aktiv von Freiwilligen weiterentwickelt. Auch du kannst bei der Entwicklung mit Quellcode oder Kommentaren mitwirken! -Stelle uns über Twitter Fragen oder gebe uns Feedback: -https://twitter.com/@AntennaPod +Wir verwenden GitHub für Funktionswünsche (Feature Requests), Fehlerberichte (Bug Reports) und zum Beisteuern von Code (Code Contributions). +https://www.github.com/AntennaPod/AntennaPod -Teile deine Idee und Lieblingspodcastmomente und äußere deine Dankbarkeit gegenüber allen Freiwilligen in unserer Google Group: +Teile deine Idee und Lieblingspodcastmomente und äußere Deine Dankbarkeit gegenüber allen Freiwilligen in unserer Google Group:<br> https://groups.google.com/forum/#!forum/antennapod (Englisch) -Helfe auf Transifex, die App in deine Muttersprache zu übersetzen: -https://www.transifex.com/antennapod/antennapod +Du hast eine Frage oder willst uns Feedback geben? +https://twitter.com/@AntennaPod -Probiere unser Beta-Testing-Programm aus, um die neusten Funktionen als Erster zu erhalten: -https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod +Mit Transifex kannst du uns beim Ãœbersetzen helfen:<br> +https://www.transifex.com/antennapod/antennapod -Wir verwenden GitHub für Funktionswünsche (Feature Requests), Fehlerberichte und zur Beteiligung an der Entwicklung. -https://www.github.com/AntennaPod/AntennaPod
\ No newline at end of file +Probiere unser Beta-Testing-Programm aus, um die neusten Funktionen als Erster zu erhalten:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/de.md b/app/src/main/play/de/whatsnew index 131b30954..131b30954 100644 --- a/changelog/de.md +++ b/app/src/main/play/de/whatsnew diff --git a/app/src/main/play/defaultLanguage b/app/src/main/play/defaultLanguage new file mode 100644 index 000000000..f2b0341fe --- /dev/null +++ b/app/src/main/play/defaultLanguage @@ -0,0 +1 @@ +en-US
\ No newline at end of file diff --git a/app/src/main/play/el/listing/fulldescription b/app/src/main/play/el/listing/fulldescription new file mode 100644 index 000000000..87b477fdc --- /dev/null +++ b/app/src/main/play/el/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> +But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. + +Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. + +<b>All features:</b><br> +IMPORT, ORGANIZE AND PLAY<br> +• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> +• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> +• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> +• Access password-protected feeds and episodes<br> +• Take advantage of paged feeds (www.podlove.org/paged-feeds) + +KEEP TRACK, SHARE & APPRECIATE<br> +• Keep track of the best of the best by marking episodes as favourites<br> +• Find that one episode through the playback history or by searching (titles and shownotes)<br> +• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> +• Support content creators with Flattr integration including automatic flattring + +CONTROL THE SYSTEM<br> +• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> +• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> +• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adapt to your environment using the light and dark theme<br> +• Back-up your subscriptions with the gPodder.net integration and OPML export + +<b>Join the AntennaPod community!</b><br> +AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! + +GitHub is the place to go for feature requests, bug reports and code contributions:<br> +https://www.github.com/AntennaPod/AntennaPod + +Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> +https://groups.google.com/forum/#!forum/antennapod + +Have a question or want to give us feedback? +https://twitter.com/@AntennaPod + +Transifex is the place to help with translations:<br> +https://www.transifex.com/antennapod/antennapod + +Check out our Beta Testing programme to get the latest features first:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/el.md b/app/src/main/play/el/whatsnew index 359acd3cf..359acd3cf 100644 --- a/changelog/el.md +++ b/app/src/main/play/el/whatsnew diff --git a/app/src/main/play/en-US/listing/fulldescription b/app/src/main/play/en-US/listing/fulldescription new file mode 100644 index 000000000..87b477fdc --- /dev/null +++ b/app/src/main/play/en-US/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> +But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. + +Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. + +<b>All features:</b><br> +IMPORT, ORGANIZE AND PLAY<br> +• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> +• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> +• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> +• Access password-protected feeds and episodes<br> +• Take advantage of paged feeds (www.podlove.org/paged-feeds) + +KEEP TRACK, SHARE & APPRECIATE<br> +• Keep track of the best of the best by marking episodes as favourites<br> +• Find that one episode through the playback history or by searching (titles and shownotes)<br> +• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> +• Support content creators with Flattr integration including automatic flattring + +CONTROL THE SYSTEM<br> +• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> +• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> +• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adapt to your environment using the light and dark theme<br> +• Back-up your subscriptions with the gPodder.net integration and OPML export + +<b>Join the AntennaPod community!</b><br> +AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! + +GitHub is the place to go for feature requests, bug reports and code contributions:<br> +https://www.github.com/AntennaPod/AntennaPod + +Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> +https://groups.google.com/forum/#!forum/antennapod + +Have a question or want to give us feedback? +https://twitter.com/@AntennaPod + +Transifex is the place to help with translations:<br> +https://www.transifex.com/antennapod/antennapod + +Check out our Beta Testing programme to get the latest features first:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/en-US/listing/shortdescription b/app/src/main/play/en-US/listing/shortdescription new file mode 100644 index 000000000..7afb5a62d --- /dev/null +++ b/app/src/main/play/en-US/listing/shortdescription @@ -0,0 +1 @@ +Easy-to-use, flexible and open-source podcast & radio manager and player
\ No newline at end of file diff --git a/app/src/main/play/en-US/listing/title b/app/src/main/play/en-US/listing/title new file mode 100644 index 000000000..31552f353 --- /dev/null +++ b/app/src/main/play/en-US/listing/title @@ -0,0 +1 @@ +AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/en-US/listing/video b/app/src/main/play/en-US/listing/video new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/app/src/main/play/en-US/listing/video diff --git a/app/src/main/play/en-US/whatsnew b/app/src/main/play/en-US/whatsnew new file mode 100644 index 000000000..a65bddbbb --- /dev/null +++ b/app/src/main/play/en-US/whatsnew @@ -0,0 +1,11 @@ +* New features: + * Subscription overview + * Proxy support + * Statistics + * Manual gpodder.net sync +* Fixes: + * Audioplayer controls + * Audio ducking + * Video control fade-out + * External media controls + * Feed parsing
\ No newline at end of file diff --git a/app/src/main/play/es-ES/listing/fulldescription b/app/src/main/play/es-ES/listing/fulldescription new file mode 100644 index 000000000..5cc6c5bf5 --- /dev/null +++ b/app/src/main/play/es-ES/listing/fulldescription @@ -0,0 +1,40 @@ +AntennaPod is un gestor y reproductor de podcast que te da acceso instantáneo a millones de podcast gratuitos y de pago, desde podcasters independientes a grandes estaciones como la BBC, NPR y CNN. Agrega, importa y exporta las fuentes de manera sencilla usando el listado de iTunes, archivos OPML o las URL de tipo RSS. Ahorra esfuerzo, baterÃa y datos con los controles de descarga (a horas o intervalos especÃficos, o redes WiFi) y de borrado de episodios (basado en favoritos y ajustes de tiempo).<br> +Y lo más importante: descarga, escucha en stream y disfrutalos como quieras con velocidad de reproducción variable, soporte para capÃtulos y temporizador de sueño. Incluso puedes mostrar tu gratitud a los creadores de contenido mediante Flattr. + +Hecho por entusiastas del podcasting, AntennaPod es libre, gratuito y sin publicidad. + +<b>CaracterÃsticas:</b><br> +IMPORTAR, ORGANIZAR Y REPRODUCIR<br> +• Añadir e importar feeds mediante los directorios iTunes o gPodder.net, archivos OPML y los enlaces RSS y Atom<br> +• Gestiona la reproducción desde cualquier parte: widget, notificación del sistema y controles de auricular y bluetooth<br> +• Disfruta escuchando a tu manera ajustando la velocidad de reproducción, con soporte para capÃtulos (MP3, VorbisComment y Podlove), recordando la posición de reproducción y un temporizador de sueño (agita para reiniciar, bajada de volumen y ralentización)<br> +• Accede a feeds y episodios protegidos con contraseña<br> +• Accede a feeds paginados (www.podlove.org/paged-feeds) + +RECUERDA, COMPARTE Y APRECIA +• Ten localizado lo mejor de lo mejor marcando episodios como favoritos<br> +• Encuentra ese episodio consultando el histórico o buscándolo (por tÃtulo o por notas de episodio)<br> +• Comparte episodios feeds con opciones avanzadas de redes sociales, email, servicios gPodder.net y exportación OPML<br> +• Ayuda a los creadores de contenido con la integración Flatter, siendo posible hacer Flattr automático + +CONTROLA EL SISTEMA<br> +• Toma el control de la descarga automática: elige los feeds, excluye las redes móviles, elige redes WiFi especÃficas, hazlo sólo si el teléfono está cargando o a ciertas horas o intervalos<br> +• Gestiona el almacenamiento configurando la cantidad de episodios en caché, configura borrado inteligente (basado en favoritos y el estado de reproducción) y eligiendo tu ubicación favorita<br> +• Usa AntennaPod en tu idioma (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adáptate a tu entorno usando el tema claro u oscuro<br> +• Haz backup de tus suscripciones usando gPodder.net o exportando a OPML + +<b>¡Únete a la comunidad AntennaPod!</b><br> +AntennaPod está en continuo desarrollo por voluntarios. ¡Tú también puedes contribuir, con tu código o con tus comentarios! + +GitHub es el sitio que debes visitar para solicitar caracterÃsticas nuevas, reportar fallos y contribuir con código<br> +www.github.com/AntennaPod/AntennaPod + +Nuestro Grupo de Google es el sitio para compartir tus ideas, tus momentos favoritos de podcasting y tu gratitud a los voluntarios:<br> +https://groups.google.com/forum/#!forum/antennapod + +Transifex es el sitio para ayudar con las traducciones:<br> +www.transifex.com/antennapod/antennapod + +Echa un vistazo a nuestro programa de Beta Testing para ser el primero en usar las nuevas caracterÃsticas:<br> +www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/es-ES/listing/shortdescription b/app/src/main/play/es-ES/listing/shortdescription new file mode 100644 index 000000000..e5b6ace85 --- /dev/null +++ b/app/src/main/play/es-ES/listing/shortdescription @@ -0,0 +1 @@ +Reproductor y gestor de podcast de código abierto, flexible y fácil de usar
\ No newline at end of file diff --git a/app/src/main/play/es-ES/listing/title b/app/src/main/play/es-ES/listing/title new file mode 100644 index 000000000..31552f353 --- /dev/null +++ b/app/src/main/play/es-ES/listing/title @@ -0,0 +1 @@ +AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/es-ES/listing/video b/app/src/main/play/es-ES/listing/video new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/app/src/main/play/es-ES/listing/video diff --git a/app/src/main/play/es-ES/whatsnew b/app/src/main/play/es-ES/whatsnew new file mode 100644 index 000000000..008d3d44c --- /dev/null +++ b/app/src/main/play/es-ES/whatsnew @@ -0,0 +1,12 @@ +* Nuevas funciones: + * Soporte Experimental de Chromecast + * Subscription overview + * Soporte para proxy + * EstadÃsticas + * Sincronización manual a gpodder.net +* Correcciones: + * Controles del reproductor de audio + * Reducción de audio por canal (audio ducking) + * Desvanecimiento del control de video + * Controles para medios externos + * Feed parsing
\ No newline at end of file diff --git a/description/es.txt b/app/src/main/play/es/listing/fulldescription index 3ebde6ef6..2f1c8861a 100644 --- a/description/es.txt +++ b/app/src/main/play/es/listing/fulldescription @@ -1,6 +1,4 @@ -Reproductor y gestor de podcast de código abierto, flexible y fácil de usar - -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (episode filtering, specify times, intervals and WiFi networks) and deleting episodes (based your favorites and delay settings).<br> +AntennaPod is un gestor y reproductor de podcast que te da acceso instantáneo a millones de podcast gratuitos y de pago, desde podcasters independientes a grandes estaciones como la BBC, NPR y CNN. Agrega, importa y exporta las fuentes de manera sencilla usando el listado de iTunes, archivos OPML o las URL de tipo RSS. Ahorra esfuerzo, baterÃa y datos con los controles de descarga (a horas o intervalos especÃficos, o redes WiFi) y de borrado de episodios (basado en favoritos y ajustes de tiempo).<br> Y lo más importante: descarga, escucha en stream y disfrutalos como quieras con velocidad de reproducción variable, soporte para capÃtulos y temporizador de sueño. Incluso puedes mostrar tu gratitud a los creadores de contenido mediante Flattr. Hecho por entusiastas del podcasting, AntennaPod es libre, gratuito y sin publicidad. @@ -20,26 +18,26 @@ RECUERDA, COMPARTE Y APRECIA • Ayuda a los creadores de contenido con la integración Flatter, siendo posible hacer Flattr automático CONTROLA EL SISTEMA<br> -• Take control over automated downloading: choose feeds, filter episodes based on keywords, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> -• Manage storage by setting the amount of cached episodes, smart deletion (based on your favorites and play status) and selecting your preferred location<br> +• Toma el control de la descarga automática: elige los feeds, excluye las redes móviles, elige redes WiFi especÃficas, hazlo sólo si el teléfono está cargando o a ciertas horas o intervalos<br> +• Gestiona el almacenamiento configurando la cantidad de episodios en caché, configura borrado inteligente (basado en favoritos y el estado de reproducción) y eligiendo tu ubicación favorita<br> • Usa AntennaPod en tu idioma (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> • Adáptate a tu entorno usando el tema claro u oscuro<br> • Haz backup de tus suscripciones usando gPodder.net o exportando a OPML -<b>¡Únete a la comunidad AntennaPod!</b> +<b>¡Únete a la comunidad AntennaPod!</b><br> AntennaPod está en continuo desarrollo por voluntarios. ¡Tú también puedes contribuir, con tu código o con tus comentarios! -Haz tu pregunta o danos tu opinión vÃa Twitter: -https://twitter.com/@AntennaPod +GitHub es el sitio que debes visitar para solicitar caracterÃsticas nuevas, reportar fallos y contribuir con código<br> +https://www.github.com/AntennaPod/AntennaPod -Comparte tus ideas, tus momentos favoritos de podcasting y tu gratitud a los voluntarios en nuestro Grupo de Google: +Nuestro Grupo de Google es el sitio para compartir tus ideas, tus momentos favoritos de podcasting y tu gratitud a los voluntarios:<br> https://groups.google.com/forum/#!forum/antennapod -Ayuda a traducir la app a tu idioma en Transifex: -https://www.transifex.com/antennapod/antennapod +¿Tienes una pregunta o quieres darnos tu opinión? +https://twitter.com/@AntennaPod -Check out our Beta Testing programme to get the latest features first: -https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod +Transifex es el sitio para ayudar con las traducciones:<br> +https://www.transifex.com/antennapod/antennapod -Visita GitHub para enviar sugerencias, informes de fallos y aportes de código: -https://www.github.com/AntennaPod/AntennaPod
\ No newline at end of file +Echa un vistazo a nuestro programa de Beta Testing para ser el primero en usar las nuevas caracterÃsticas:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/es.md b/app/src/main/play/es/whatsnew index 8bf611c06..8bf611c06 100644 --- a/changelog/es.md +++ b/app/src/main/play/es/whatsnew diff --git a/app/src/main/play/es_ES/listing/fulldescription b/app/src/main/play/es_ES/listing/fulldescription new file mode 100644 index 000000000..1ce12e3b4 --- /dev/null +++ b/app/src/main/play/es_ES/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> +But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. + +Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. + +<b>All features:</b><br> +IMPORT, ORGANIZE AND PLAY<br> +• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> +• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> +• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> +• Access password-protected feeds and episodes<br> +• Take advantage of paged feeds (www.podlove.org/paged-feeds) + +KEEP TRACK, SHARE & APPRECIATE<br> +• Keep track of the best of the best by marking episodes as favourites<br> +• Find that one episode through the playback history or by searching (titles and shownotes)<br> +• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> +• Support content creators with Flattr integration including automatic flattring + +CONTROL THE SYSTEM<br> +• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> +• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> +• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adapt to your environment using the light and dark theme<br> +• Back-up your subscriptions with the gPodder.net integration and OPML export + +<b>¡Únete a la comunidad de AntennaPod!</b><br> +AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! + +GitHub is the place to go for feature requests, bug reports and code contributions:<br> +https://www.github.com/AntennaPod/AntennaPod + +Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> +https://groups.google.com/forum/#!forum/antennapod + +Have a question or want to give us feedback? +https://twitter.com/@AntennaPod + +Transifex is the place to help with translations:<br> +https://www.transifex.com/antennapod/antennapod + +Check out our Beta Testing programme to get the latest features first:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/es_ES.md b/app/src/main/play/es_ES/whatsnew index 8f2618b8f..8f2618b8f 100644 --- a/changelog/es_ES.md +++ b/app/src/main/play/es_ES/whatsnew diff --git a/app/src/main/play/et/listing/fulldescription b/app/src/main/play/et/listing/fulldescription new file mode 100644 index 000000000..d33e8f4e8 --- /dev/null +++ b/app/src/main/play/et/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> +But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. + +Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. + +<b>Kõik omadused:</b><br> +IMPORDI, ORGANISEERI JA ESITA<br> +• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> +• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> +• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> +• Access password-protected feeds and episodes<br> +• Kasuta ära lehekülgedeks jagatud voogusid (www.podlove.org/paged-feeds) + +JÄLGI, JAGA JA HINDA<br> +• Keep track of the best of the best by marking episodes as favourites<br> +• Find that one episode through the playback history or by searching (titles and shownotes)<br> +• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> +• Support content creators with Flattr integration including automatic flattring + +KONTROLLI SÃœSTEEMI<br> +• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> +• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> +• Kasuta AntennaPodi omaenda keeles (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH, ET)<br> +• Kohandu oma keskkonnale valides heleda ja tumeda ekraani vahet<br> +• Back-up your subscriptions with the gPodder.net integration and OPML export + +<b>Liitu AntennaPodi kogukonnaga!</b> +AntennaPod on vabatahtlike poolt aktiivselt arendamisel. Ka sina võid anda oma osa kirjutades koodi või andes oma kommentaare! + +GitHub is the place to go for feature requests, bug reports and code contributions:<br> +https://www.github.com/AntennaPod/AntennaPod + +Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> +https://groups.google.com/forum/#!forum/antennapod + +Kas sul on küsimus või soovid anda meile tagasisidet? +https://twitter.com/@AntennaPod + +Transifex on koht, kus saad abiks olla tõlkimisega:<br> +https://www.transifex.com/antennapod/antennapod + +Vaata meie beeta testide programmi, et saada esimesena osa värskeimatest omadustest: +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/et/whatsnew b/app/src/main/play/et/whatsnew new file mode 100644 index 000000000..d19253cac --- /dev/null +++ b/app/src/main/play/et/whatsnew @@ -0,0 +1,363 @@ +Muudatuste nimekiri +========== + +Version 1.6.0 +------------- +* New features: + * Experimental Chromecast support + * Subscription overview + * Proxy support + * Statistics + * Manual gpodder.net sync +* Fixes: + * Audioplayer controls + * Audio ducking + * Video control fade-out + * External media controls + * Feed parsing + +Versioon 1.5.0 +------------- +* Exclude episodes from auto download by keyword +* Configure feeds to prevent them from refreshing automatically +* Parandasime helipleierit +* Täiendasime kasutajaliidest +* Veaparandused + +Versioon 1.4.1 +------------- +* Kiiruse täiendused +* Hardware buttons now ff and rewind instead of skipping +* Option to have forward button skip +* Option to send crash reports directly to developers +* Tõsta kuulatav saade esile +* Vidina täiendused + +Versioon 1.4.0.12 +---------------- +* Kokkujooksmine Huawei seadmetel on parandatud (meedia nupud ei pruugi töötada) + +Versioon 1.4 +----------- +* BLUETOOTH PERMISSION: Needed to be able to resume playback when a Bluetooth device reconnects with your phone +* VIBRATE PERMISSION: Used optionally with the sleep timer +* Native variable speed playback (experimental via options) +* Improved sleep timer +* Märgi saateid 'Lemmikuks' +* Saateid saab vahele jätta teavitustest +* Kui saade jäetakse vahele, siis seda ei kustutata +* Saate pilt lukustutekraanil +* Paindlik saadete kustutamine +* Keri pärast pausi tagasi +* Kasutusmugavuse täiendused +* Veaparandused + +Versioon 1.3 +----------- +* Uudisvoo saadete hulgitöötlemine (allalaadimine, järjekorda panemine, kustutamine) +* Piltide poolt kasutatavat ruumi vähendatakse +* Automaatne värskendamine kindlal ajal päevas +* Kohanda indikaatoreid ja uudisvoogude sorteerimist +* Võimalus uudisvooge salvestada +* Autmaatse allalaadimise parandamine +* Paljud parandused ka kasutusmugavuse täiendused + +Versioon 1.2 +----------- +* Optionally disable swiping and dragging in the queue +* Jätka kuulamist pärast telefonikõnet +* Filter episodes in the Podcast feed +* Peida kirjed menüüs +* Customize times for fast forward and rewind +* Parandatud on mõningate OPML failide avamisega seotud probleemid +* Mitmed muud veaparandused ja kasutusmugavuse täiendused + +Versioon 1.1 +----------- +* iTunes podcastide tugi +* Swipe to remove items from the queue +* Set the number of parallel downloads +* Fix for gpodder.net on old devices +* Fixed date problems for some feeds +* Välimuse täiendused +* Kasutusmugavuse täiendused +* Mitmed muud veaparandused + +Versioon 1.0 +----------- +* Järjekorda saab nüüd sorteerida +* Lisatud on võimalus kustutada osa pärast selle esitamist +* Parandatud on viga, mille tõttu näidati peatükke mitu korda +* Mitmed muud veaparandused ja täiendused + + +Versioon 0.9.9.6 +--------------- +* Fixed problems related to variable playback speed plugins +* Automaatse uudisvoo uuendamise probleemide lahendamine +* Mitmed muud veaparandused ja täiendused + +Versioon 0.9.9.5 +--------------- +* Lisatud on lehekülgedeks jagatud uudisvoogude tugi +* Kasutajaliidese täiendused +* Lisasime jaapani ja türgi tõlked +* Lahendasime veel pldilaadimise probleeme +* Mitmed muud veaparandused ja täiendused + +Versioon 0.9.9.4 +--------------- +* Lisatud on võimalus hoida teavitusribal ja lukustusekraanil nupud alles ka siis, kui esitamine on peatatud +* Parandatud on viga, kus saadete pilte ei laadita korrektselt +* Akukasutusprobleemide lahendamine + +Versioon 0.9.9.3 +--------------- +* Video esitamise probleemide lahendamine +* Pildi laadimise täiustamine +* Mitmed muud veaparandused ja täiendused + +Versioon 0.9.9.2 +--------------- +* Added support for feed discovery if a website URL is entered +* Added support for 'next'/'previous' media keys +* Improved sleep timer +* Timestamps in shownotes can now be used to jump to a specific position +* Automatic Flattring is now configurable +* Erinevad veaparandused ja täiendused + +Versioon 0.9.9.1 +--------------- +* Erinevad veaparandused ja täiendused + +Versioon 0.9.9.0 +--------------- +* Uus kasutajaliides +* Ebaõnnestunud allalaadimised taastatakse pärast taaskäivitamist +* Podlove Alternate Feeds toe lisamine +* "pcast"-protokoli toe lisamine +* Added backup & restore functionality. This feature has to be enabled in the Android settings in order to work +* Erinevad veaparandused ja täiendused + +Versioon 0.9.8.3 +--------------- +* Added support for password-protected feeds and episodes +* Added support for more types of episode images +* Lisasime heebrea keele tõlke +* Erinevad veaparandused ja täiendused + +Versioon 0.9.8.2 +--------------- +* Erinevad veaparandused ja täiendused +* Lisasime korea keele tõlke + +Versioon 0.9.8.1 +--------------- +* Added option to flattr an episode automatically after 80 percent of the episode have been played +* Lisasime poola keele tõlke +* Erinevad veaparandused ja täiendused + +Versioon 0.9.8.0 +--------------- +* Lisatud on ligipääs gpodder.net kataloogile +* Added ability to sync podcast subscriptions with the gpodder.net service +* Automatic download can now be turned on or off for specific podcasts +* Added option to pause playback when another app is playing sounds +* Lisasime hollandi ja hindi tõlked +* Lahendatud on probleemid automaatsete taskuhäälingute uuendamisega +* Resolved a problem with the buttons' visibility in the episode screen +* Resolved a problem where episodes would be re-downloaded unnecessarily +* Mitmed muud veaparandused ja kasutusmugavuse täiendused + +Versioon 0.9.7.5 +--------------- +* Rakenduse käivitusaega on kiirendatud +* Mälukasutuse vähendamine +* Lisatud on võimalusi muuta esituskiirust +* Lisasime rootsi keele tõlke +* Erinevad veaparandused ja täiendused + +Versioon 0.9.7.4 +--------------- +* Osade vahemälu suurust saab määrata nüüd piiramatuks +* Removing an episode in the queue via sliding can now be undone +* Lisatud on linkide tugi MP3 peatükkides +* Lisasime tšehhi, azerbaidžaani ja portugali tõlked +* Erinevad veaparandused ja täiendused + +Versioon 0.9.7.3 +--------------- +* Bluetooth devices now display metadata during playback (requires AVRCP 1.3 or higher) +* kasutajaliidese täiendused +* Erinevad veaparandused + +Versioon 0.9.7.2 +--------------- +* Automaatse allalaadimise saab nüüd keelata +* Lisasime itaalia keele tõlke +* Erinevad veaparandused + +Versioon 0.9.7.1 +--------------- +* Lisasime nüüd uute osade automaatse allalaadimise +* Added option to specify the number of downloaded episodes to keep on the device +* Lisasime väliste failide esitamise toe +* Mitmed muud veaparandused ja täiendused +* Lisasime katalaani tõlke + +Versioon 0.9.7 +------------- +* Kasutajaliidese täiendused +* OPML files can now be imported by selecting them in a file browser +* Järjekorda saab nüüd muuta kirjete lohistamisega +* Added expandable notifications (only supported on Android 4.1 and above) +* Lisasime taani, prantuse, rumeenia ja ukraina tõlked (tänud kõigile tõlkijatele!) +* Mitmed muud veaparandused ja väiksemad täiendused + +Versioon 0.9.6.4 +--------------- +* Lisasime hiina keele tõlke (Tänud tupunco!) +* Lisasime portugali (Brasiilia) tõlke (Täname mbaltar!) +* Erinevad veaparandused + +Versioon 0.9.6.3 +--------------- +* Lisatud on võimalus muuta AntennaPodi andmete kaust +* Lisasime hispaania tõlke (Täname frandavid100!) +* Parandasime probleemid mitmete uudisvoogudega + +Version 0.9.6.2 +--------------- +* Parandatud on mõningate OPML failide importimisega seotud probleemid +* Allalaadimise probleemide lahendamine +* AntennaPod tunneb nüüd ära muudatused saadete infos +* Muud veaparandused ja täiendused + +Versioon 0.9.6.1 +--------------- +* Lisasime tumeda teema +* Erinevad veaparandused ja täiendused + +Versioon 0.9.6 +------------- +* Added support for VorbisComment chapters +* AntennaPod now shows items as 'in progress' when playback has started +* Mälukasutuse vähendamine +* Added support for more feed types +* Erinevad veaparandused + + +Versioon 0.9.5.3 +--------------- +* Fixed crash when trying to start playback on some devices +* Fixed problems with some feeds +* Mitmed muud veaparandused ja täiendused + +Versioon 0.9.5.2 +--------------- +* Media player now doesn't use network bandwidth anymore if not in use +* Muud veaparandused ja täiendused + +Versioon 0.9.5.1 +--------------- +* Lisasime esitamise ajaloo +* Improved behavior of download report notifications +* Improved support for headset controls +* Veaparandused uudisvoo lugejas +* Moved 'OPML import' button into the 'add feed' screen and the 'OPML export' button into the settings screen + +Versioon 0.9.5 +------------- +* Experimental support for MP3 chapters +* New menu options for the 'new' list and the queue +* Automaatse kustutamise funktsioon +* Better Download error reports +* Erinevad veaparandused + +Versioon 0.9.4.6 +--------------- +* Enabled support for small-screen devices +* Disabling the sleep timer should now work again + +Versioon 0.9.4.5 +--------------- +* Lisasime vene keele tõlke (Tänud older!) +* Lisasime saksa keele tõlke +* Erinevad veaparandused + +Versioon 0.9.4.4 +--------------- +* Added player controls at the bottom of the main screen and the feedlist screens +* Improved media playback + +Versioon 0.9.4.3 +--------------- +* Fixed several bugs in the feed parser +* Allalaadimise aruannete täiustatud käitumine + +Versioon 0.9.4.2 +--------------- +* Parandasime vea OPML importijas +* Piltide puhul mälukasutuse vähendamine +* Parandasime allalaadimise probleeme mõningatel seadmetel + +Versioon 0.9.4.1 +--------------- +* Changed behavior of download notifications + +Versioon 0.9.4 +------------- +* Kiiremad ja stabiilsemad allalaadimised +* Added lockscreen player controls for Android 4.x devices +* Erinevad veaparandused + +Versioon 0.9.3.1 +--------------- +* Added preference to hide feed items which don't have an episode +* Improved image size for some some screen sizes +* Suurtele ekraanidele võrgustikuvaate lisamine +* Erinevad veaparandused + +Versioon 0.9.3 +------------- +* MiroGuide toe lisamine +* Veaparandused heli- ja videopleieris +* Lisa vood automaatselt järjekorda, kui nad on alla laaditud + +Versioon 0.9.2 +------------- +* Kasutajaliidese veaparandused +* GUID and ID attributes are now recognized by the Feedparser +* Stabiilsuse parndused mitme uudisvoo samaaegsel lisamisel +* Parandatud ono probleemid, mis ilmnesid teatud uudisvoogude lisamisel + +Versioon 0.9.1.1 +-------------------- +* Changed Flattr credentials +* Uudisvoo info lehe paigutust on täiendatud +* AntennaPod on nüüd avatud koodiga! Lähtekood on saadaval aadressil https://github.com/danieloeh/AntennaPod + +Versioon 0.9.1 +----------------- +* SimpleChapters sees olevate linkide toe lisamine +* Bugfix: Current Chapter wasn't always displayed correctly + +Versioon 0.9 +-------------- + +* OPML eksport +* Flattr toe lisamine +* Sleep timer + +Versioon 0.8.2 +------------- + +* lisasime otsingu +* Täiendatud OPML importimise kasutuskogemus +* Erinevad veaparandused + +Versioon 0.8.1 +------------ + +* SimpleChapters toe lisamine +* OPML import
\ No newline at end of file diff --git a/app/src/main/play/fa/listing/fulldescription b/app/src/main/play/fa/listing/fulldescription new file mode 100644 index 000000000..87b477fdc --- /dev/null +++ b/app/src/main/play/fa/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> +But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. + +Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. + +<b>All features:</b><br> +IMPORT, ORGANIZE AND PLAY<br> +• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> +• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> +• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> +• Access password-protected feeds and episodes<br> +• Take advantage of paged feeds (www.podlove.org/paged-feeds) + +KEEP TRACK, SHARE & APPRECIATE<br> +• Keep track of the best of the best by marking episodes as favourites<br> +• Find that one episode through the playback history or by searching (titles and shownotes)<br> +• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> +• Support content creators with Flattr integration including automatic flattring + +CONTROL THE SYSTEM<br> +• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> +• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> +• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adapt to your environment using the light and dark theme<br> +• Back-up your subscriptions with the gPodder.net integration and OPML export + +<b>Join the AntennaPod community!</b><br> +AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! + +GitHub is the place to go for feature requests, bug reports and code contributions:<br> +https://www.github.com/AntennaPod/AntennaPod + +Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> +https://groups.google.com/forum/#!forum/antennapod + +Have a question or want to give us feedback? +https://twitter.com/@AntennaPod + +Transifex is the place to help with translations:<br> +https://www.transifex.com/antennapod/antennapod + +Check out our Beta Testing programme to get the latest features first:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/fi/listing/fulldescription b/app/src/main/play/fi/listing/fulldescription new file mode 100644 index 000000000..87b477fdc --- /dev/null +++ b/app/src/main/play/fi/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> +But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. + +Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. + +<b>All features:</b><br> +IMPORT, ORGANIZE AND PLAY<br> +• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> +• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> +• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> +• Access password-protected feeds and episodes<br> +• Take advantage of paged feeds (www.podlove.org/paged-feeds) + +KEEP TRACK, SHARE & APPRECIATE<br> +• Keep track of the best of the best by marking episodes as favourites<br> +• Find that one episode through the playback history or by searching (titles and shownotes)<br> +• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> +• Support content creators with Flattr integration including automatic flattring + +CONTROL THE SYSTEM<br> +• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> +• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> +• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adapt to your environment using the light and dark theme<br> +• Back-up your subscriptions with the gPodder.net integration and OPML export + +<b>Join the AntennaPod community!</b><br> +AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! + +GitHub is the place to go for feature requests, bug reports and code contributions:<br> +https://www.github.com/AntennaPod/AntennaPod + +Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> +https://groups.google.com/forum/#!forum/antennapod + +Have a question or want to give us feedback? +https://twitter.com/@AntennaPod + +Transifex is the place to help with translations:<br> +https://www.transifex.com/antennapod/antennapod + +Check out our Beta Testing programme to get the latest features first:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/fi.md b/app/src/main/play/fi/whatsnew index 8f2618b8f..8f2618b8f 100644 --- a/changelog/fi.md +++ b/app/src/main/play/fi/whatsnew diff --git a/app/src/main/play/fr-FR/listing/fulldescription b/app/src/main/play/fr-FR/listing/fulldescription new file mode 100644 index 000000000..61177b28a --- /dev/null +++ b/app/src/main/play/fr-FR/listing/fulldescription @@ -0,0 +1,40 @@ +AntennaPod est un lecteur et gestionnaire de podcast permettant l'accès à des millions de podcast gratuits ou payants produit aussi bien par des podcasters indépendants que de gros éditeurs comme la BBC, NPR ou CNN. Ajoutez, importez et exportez leurs flux facilement à partir d'ITunes, de fichiers OPML ou simplement à partir de liens RSS. Économisez votre temps, votre batterie et votre consommation internet grâce à une automatisation puissante des téléchargements (quand, à quel rythme et à partir de quel réseau wifi) et de la suppression des épisodes (à partir d'un certains temps ou des favoris)<br> +Encore plus important : téléchargez, streamez ou mettez dans votre liste de lecture vos épisodes et écoutez les à votre manière grâce à une vitesse de lecture réglable, au support des chapitres et une fonction de mise en veille automatique. Vous pouvez même montrer votre appréciation aux créateurs de contenu avec notre intégration de Flattr. + +Programmé par des fans de podcast, AntennaPod est gratuit dans tous les sens du terme : open source, aucun cout et pas de publicité. + +<b>Caractéristiques complètes :</b><br> +Importer, gérer et écouter<br> +• Ajouter et importer à partir d'iTunes, gPodder.net, de fichiers OPML ou de liens RSS ou Atom<br> +• Gérez la lecture de n'importe où : widget sur l'écran d'accueil, notification système, commande casque ou bluetooth<br> +• Ecoutez à votre façon grâce à une vitesse de lecture réglable, au support des chapitres (MP3, VorbisComment et Podlove), enregistrement de la position de lecture et une mise en veille automatique puissante (secouer pour prolonger le minuteur, baisse du volume et ralentissement de la lecture)<br> +• Accès aux flux et épisodes protégés par mot de passe<br> +• Tirez profit des flux à plusieurs pages (www.podlove.org/paged-feeds) + +GARDEZ TRACE, PARTAGEZ & APPRECIEZ<br> +• Gardez trace des meilleurs épisodes en les marquant comme favoris<br> +• Retrouvez un épisode à partir de l'historique de lecture ou en cherchant (les titres et les commentaires des épisodes)<br> +• Partagez vos épisodes ou flux à travers des options de réseaux sociaux et email avancées, du service gPodder.net ou par des exports OPML<br> +• Soutenez les créateurs de contenu avec l'intégration à Flattr et la possibilité de flatter automatiquement + +CONTRÔLER LE SYSTÈME<br> +• Prenez le contrôle avec l'automatisation des téléchargements : choisissez les flux, empêchez l'utilisation du réseau mobile, sélectionnez les réseaux WIFI à utiliser, exigez que le téléphone soit en train de charger et spécifiez quand ou à quel rythme<br> +• Gérez l'espace de stockage en paramétrant le nombre d'épisodes à garder, de leurs suppressions automatique (à partir de vos favoris et du statut de lecture) et de l'emplacement où les enregistrer<br> +• Utilisez AntennaPod dans votre langue (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adaptez à votre environnement avec un thème clair ou sombre<br> +• Sauvegardez vos abonnements avec l'intération à gPodder.net ou des exports OPML + +<b>Rejoignez la communauté d'AntennaPod !</b><br> +AntennaPod est développé activement par des volontaires. Vous pouvez aussi contribuer avec du code ou des commentaires ! + +GitHub est l'endroit où aller pour demander de nouvelles options, faire part de bug ou pour contribuer au code :<br> +www.github.com/AntennaPod/AntennaPod + +Notre groupe Google est l'endroit où aller pour partager vos idées, moments préférés de podcast et vos remerciements aux volontaires :<br> +https://groups.google.com/forum/#!forum/antennapod + +Transifex est le lieu où vous pouvez aider à la traduction :<br> +www.transifex.com/antennapod/antennapod + +Jetez un coup d’œil à notre programme de version Beta pour bénéficier des dernières options :<br> +www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/fr-FR/listing/shortdescription b/app/src/main/play/fr-FR/listing/shortdescription new file mode 100644 index 000000000..61c3c7e20 --- /dev/null +++ b/app/src/main/play/fr-FR/listing/shortdescription @@ -0,0 +1 @@ +Un lecteur et gestionnaire de podcast facile à utiliser et flexible
\ No newline at end of file diff --git a/app/src/main/play/fr-FR/listing/title b/app/src/main/play/fr-FR/listing/title new file mode 100644 index 000000000..31552f353 --- /dev/null +++ b/app/src/main/play/fr-FR/listing/title @@ -0,0 +1 @@ +AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/fr-FR/listing/video b/app/src/main/play/fr-FR/listing/video new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/app/src/main/play/fr-FR/listing/video diff --git a/app/src/main/play/fr-FR/whatsnew b/app/src/main/play/fr-FR/whatsnew new file mode 100644 index 000000000..938b14a2e --- /dev/null +++ b/app/src/main/play/fr-FR/whatsnew @@ -0,0 +1,12 @@ +* Nouvelles fonctionnalités : + * Support expérimental de Chromecast + * Vue d'ensemble des abonnements + * Support des proxy + * Statistiques + * Synchronisation manuelle à gpodder.net +* Corrections de bugs : + * Contrôles du lecteur audio + * Baisse du son + * Contrôle vidéo du fade-out + * Contrôles externes des médias + * Lecture de flux
\ No newline at end of file diff --git a/description/fr.txt b/app/src/main/play/fr/listing/fulldescription index 6fc861f86..372e1da60 100644 --- a/description/fr.txt +++ b/app/src/main/play/fr/listing/fulldescription @@ -1,9 +1,7 @@ -Un lecteur et gestionnaire de podcast facile à utiliser et flexible +AntennaPod est un lecteur et gestionnaire de podcast permettant l'accès à des millions de podcast gratuits ou payants produit aussi bien par des podcasters indépendants que de gros éditeurs comme la BBC, NPR ou CNN. Ajoutez, importez et exportez leurs flux facilement à partir d'ITunes, de fichiers OPML ou simplement à partir de liens RSS. Gagnez du temps, préservez votre batterie et consommation internet grâce à une automatisation puissante des téléchargements (date, fréquence, choix du réseau WiFi, etc...) et des suppressions d’épisodes écoutés (selon vos critères)<br> +Avant tout : téléchargez, streamez ou ajoutez à la liste de lecture vos épisodes et écoutez les comme vous voulez grâce au réglage de vitesse de lecture, au support des chapitres et au minuteur d'arrêt. Vous pouvez même montrer votre appréciation aux créateurs de contenu avec notre intégration de Flattr. -AntennaPod est un lecteur et gestionnaire de podcast permettant l'accès à des millions de podcast gratuits ou payants produit aussi bien par des podcasters indépendants que de gros éditeurs comme la BBC, NPR ou CNN. Ajoutez, importez et exportez leurs flux facilement à partir d'ITunes, de fichiers OPML ou simplement à partir de liens RSS. Gagnez du temps, préservez votre batterie et consommation internet grâce à une automatisation puissante des téléchargements (filtrage des épisodes, date, fréquence, choix du réseau WiFi, etc...) et des suppressions d’épisodes écoutés (selon vos critères).<br> -Plus important : téléchargez, streamez ou ajoutez à la liste de lecture vos épisodes et écoutez les comme vous voulez grâce au réglage de vitesse de lecture, au support des chapitres et au minuteur d'arrêt automatique. Vous pouvez même montrer votre appréciation aux créateurs de contenu avec notre intégration de Flattr. - -Programmé par des fans de podcast, AntennaPod est gratuit dans tous les sens du terme : open source, gratuit et sans publicité. +Conçu par des fans de podcast, AntennaPod est gratuit dans tous les sens du terme : open source, gratuit et sans publicité. <b>Caractéristiques complètes :</b><br> IMPORTER, GÉRER ET ÉCOUTER<br> @@ -14,32 +12,32 @@ IMPORTER, GÉRER ET ÉCOUTER<br> • Tirez profit des flux paginés (www.podlove.org/paged-feeds) SUIVEZ, PARTAGEZ & PROFITEZ<br> -• Gardez trace des meilleurs épisodes en les marquant comme favoris<br> +• Marquer les meilleurs épisodes en tant que favoris<br> • Retrouvez un épisode à partir de l'historique de lecture ou en recherchant parmi les titres et commentaires des épisodes précédents<br> • Partagez vos épisodes et flux sur les réseaux sociaux, par email, sur gPodder.net ou en les exportant au format OPML<br> • Soutenez les créateurs de contenu avec l'intégration à Flattr et la possibilité de flatter automatiquement CONTRÔLER LE SYSTÈME<br> -• Prenez le contrôle en automatisant vos téléchargements : choix des flux, filtrage des épisodes, restriction de la connexion mobile, sélection du réseau WIFI à utiliser, uniquement durant la recharge et spécifiez la fréquence de mise à jour vous-même<br> +• Prenez le contrôle en automatisant vos téléchargements : choix des flux, restriction de la connexion mobile, sélection du réseau WIFI à utiliser, uniquement durant la recharge et spécifiez la fréquence de mise à jour vous-même<br> • Gérez l'espace de stockage en paramétrant le nombre d'épisodes à garder, leur suppression automatique (en fonction de vos favoris et de leur statut) et leur emplacement sur le disque<br> • Utilisez AntennaPod dans votre langue (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> • Choix d'un thème clair ou sombre selon vos préférences<br> • Sauvegardez vos abonnements avec l’intégration à gPodder.net et les exports OPML -<b>Rejoignez la communauté d'AntennaPod !</b> +<b>Rejoignez la communauté d'AntennaPod !</b><br> AntennaPod est développé activement par des volontaires. Vous pouvez aussi contribuer avec du code, des traductions ou des commentaires ! -Posez vos questions ou donnez votre avis sur Twitter : -https://twitter.com/@AntennaPod +GitHub est l'endroit où aller pour demander de nouvelles options, faire part de bug ou pour contribuer au code :<br> +https://www.github.com/AntennaPod/AntennaPod -Partager vos idées, podcast préférés et adressez vos remerciements à tous les bénévoles dans notre groupe Google : +Rejoignez notre Google Group pour partager vos idées, podcast préférés et vos remerciements à tous les bénévoles :<br> https://groups.google.com/forum/#!forum/antennapod -Aider à traduire l'application dans votre langue sur Transifex : -https://www.transifex.com/antennapod/antennapod +Vous avez une question ou des suggestions ? +https://twitter.com/@AntennaPod -Jetez un coup d’œil à la version Beta pour bénéficier des dernières nouveautés : -https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod +Retrouvez nous sur Transifex pour contribuer à la traduction de cette app :<br> +https://www.transifex.com/antennapod/antennapod -Allez sur GitHub pour demander de nouvelles options, faire part de bugs et pour contribuer au code : -https://www.github.com/AntennaPod/AntennaPod
\ No newline at end of file +Jetez un coup d’œil à notre programme de version Beta pour bénéficier des dernières options :<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/fr.md b/app/src/main/play/fr/whatsnew index e6cb479a9..e6cb479a9 100644 --- a/changelog/fr.md +++ b/app/src/main/play/fr/whatsnew diff --git a/app/src/main/play/gl/listing/fulldescription b/app/src/main/play/gl/listing/fulldescription new file mode 100644 index 000000000..c26d4078c --- /dev/null +++ b/app/src/main/play/gl/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod é un xestor e repordutor de podcast que lle permite acceder a millóns de podcast gratuÃtos e de pago, desde emisións independentes a grandes produtores como BBC, NPR e CNN. Engadir, importar e exportar as súas fontes sen problemas utilizando a base de datos de iTunes, fiecheiros OPML o simples URLs de RSS. Aforre esforzos, consumo de baterÃa e datos móbiles con un control total e automático das descargas de episodios (indique horarios, intervalos e redes WIFI) e eliminación de episodios (basándose nas preferencias de favoritos e retardo).<br> +Mais o máis importante: Descargue, envÃe ou poña na cola os episodios e disfrúteos do xeito en que máis lle conveña, axustando a velocidade de reprodución, xestión de capÃtulos e apagado automático. Poderá tamén mostrarlle aos creadores canto lle gustan os seus contidos gracias a integración con Flattr. + +Escrito por namorados dos podcast, AntennaPod é gratuÃto e libre: open source, sen custos, sen publicidade. + +<b>CaracterÃsticas:</b><br> +IMPORTAR, ORGANIZAR E REPRODUCIR<br> +• Engada e importe fontes a través dos directorios de iTunes e gPodder.net, ficheiros OPML e RSS ou ligazóns Atom<br> +• Xestione as opcións de reprodución desde calquer lugar: widget na pantalla de inicio, barra de notificacións e tamén desde os controis de auriculares e bluetooth<br> +• Goce escoitando ao seu xeito coa velocidade de reprodución axustable, soporte de capÃtulos (MP3, VorbisComment e Podlove), recordo da posición de reprodución e apagado configurable (axitar para reiniciar, baixar volume e diminuir velocidade de reprodución)<br> +• Acceso protexido con contrasinal a episodios e fontes<br> +• BenefÃciese das fontes paxinadas (www.podlove.org/paged-feeds) + +SIGA, COMPARTA E VALORE <br> +• Garde o melloriño de cada casa marcando episodios como favoritos<br> +• Atope ese episodio especial no historial de reprodución ou buscando (tÃtulos e notas do episodio)<br> +• Comparta episodios e fontes a través das opcións de redes sociais e correro electrónico, os servizos de gPodder.net e exportando a OPML<br> +• Axude aos creadores de contido coa integración con Flattr incluÃndo o flattring automático + +CONTROL DO SISTEMA <br> +• Tome control sobre as descargas automáticas: escolla fontes, exclúa redes móbiles, redes WIFI concretas, requerir que o móbil esté a cargar e horarios e intervalos<br> +• Xestione o almacenamento establecendo o volume almacenado de episodios, borrado intelixente (baseándose nos favoritos e situación de reprodución) e selecionando a localización preferida<br> +• Utilice AntennaPod no seu idioma (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH, GL)<br> +• Adápteo a contorna utilizando o decorado claro ou oscuro<br> +• Respalde as súas suscricións coa integración en gPodder.net e exportando a OPML + +<b>Únase a comunidade AntennaPod!</b><br> +AntennaPod está baixo continuo desenvolvemento grazas a voluntarios. Vostede tamén pode contribuir, con código ou con comentarios! + +En GitHub pode solicitar novas caracterÃsticas, informar de erros e contribuir ao código:<br> +https://www.github.com/AntennaPod/AntennaPod + +No noso Google Group pode compartir ideas, momentos favoritos dos podcast e agradecer o traballo dos voluntarios:<br> +https://groups.google.com/forum/#!forum/antennapod + +Ten algunha pregunta ou quere facernos algún comentario? +https://twitter.com/@AntennaPod + +Para axudar na tradución vaia a Transifex:<br> +https://www.transifex.com/antennapod/antennapod + +Mire o noso programa Beta de Probas para ter os últimos avances:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/he_IL/listing/fulldescription b/app/src/main/play/he_IL/listing/fulldescription new file mode 100644 index 000000000..b4ac8ca6c --- /dev/null +++ b/app/src/main/play/he_IL/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> +But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. + +מיוצרת על ידי חובבי פודק×סטי×, ×× ×˜× ×”×¤×•×“ ×”×™× ×” ×ª×•×›× ×” ×—×™× ×ž×™×ª בכל מובן המילה: קוד פתוח, ×œ×œ× ×¢×œ×•×ª ×•×œ×œ× ×¤×¨×¡×•×ž×•×ª. + +<b>All features:</b><br> +IMPORT, ORGANIZE AND PLAY<br> +• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> +• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> +• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> +• Access password-protected feeds and episodes<br> +• Take advantage of paged feeds (www.podlove.org/paged-feeds) + +KEEP TRACK, SHARE & APPRECIATE<br> +• Keep track of the best of the best by marking episodes as favourites<br> +• Find that one episode through the playback history or by searching (titles and shownotes)<br> +• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> +• Support content creators with Flattr integration including automatic flattring + +CONTROL THE SYSTEM<br> +• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> +• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> +• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adapt to your environment using the light and dark theme<br> +• Back-up your subscriptions with the gPodder.net integration and OPML export + +<b>Join the AntennaPod community!</b><br> +AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! + +GitHub is the place to go for feature requests, bug reports and code contributions:<br> +https://www.github.com/AntennaPod/AntennaPod + +Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> +https://groups.google.com/forum/#!forum/antennapod + +Have a question or want to give us feedback? +https://twitter.com/@AntennaPod + +Transifex is the place to help with translations:<br> +https://www.transifex.com/antennapod/antennapod + +Check out our Beta Testing programme to get the latest features first:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/he_IL.md b/app/src/main/play/he_IL/whatsnew index 8f2618b8f..8f2618b8f 100644 --- a/changelog/he_IL.md +++ b/app/src/main/play/he_IL/whatsnew diff --git a/app/src/main/play/hi-IN/listing/fulldescription b/app/src/main/play/hi-IN/listing/fulldescription new file mode 100644 index 000000000..f4687b885 --- /dev/null +++ b/app/src/main/play/hi-IN/listing/fulldescription @@ -0,0 +1,20 @@ +à¤à¤¨à¥à¤Ÿà¥‡à¤¨à¤¾à¤ªà¥‰à¤¡ à¤à¤‚डà¥à¤°à¥‰à¤¯à¤¡ 2.3.3 और ऊपर के लिठà¤à¤• खà¥à¤²à¤¾ सà¥à¤°à¥‹à¤¤ पॉडकासà¥à¤Ÿ पà¥à¤°à¤¬à¤‚धक है. यह आपको सà¥à¤µà¤šà¤¾à¤²à¤¿à¤¤ रूप से सà¤à¥€ फ़ीड ताज़ा या बाद में उनà¥à¤¹à¥‡à¤‚ सà¥à¤¨à¤¨à¥‡ के लिठà¤à¤• कतार में जोड़ने, à¤à¤ªà¤¿à¤¸à¥‹à¤¡ सà¥à¤Ÿà¥à¤°à¥€à¤®à¤¿à¤‚ग और डाउनलोड करने, à¤à¤• पॉडकैचर से उमà¥à¤®à¥€à¤¦ रखने वाली सà¤à¥€ बà¥à¤¨à¤¿à¤¯à¤¾à¤¦à¥€ सà¥à¤µà¤¿à¤§à¤¾à¤à¤ पà¥à¤°à¤¦à¤¾à¤¨ करता है. इसके अलावा, à¤à¤¨à¥à¤Ÿà¥‡à¤¨à¤¾à¤ªà¥‰à¤¡ आपको अनà¥à¤ªà¥à¤°à¤¯à¥‹à¤— के à¤à¥€à¤¤à¤° से फà¥à¤²à¥‡à¤Ÿà¤° पॉडकासà¥à¤Ÿ और पà¥à¤°à¤•à¤°à¤£à¥‹à¤‚ की सà¥à¤µà¤¿à¤§à¤¾ देता है. + +So far the following features are implemented: + +* डाउनलोड और à¤à¤ªà¤¿à¤¸à¥‹à¤¡ के सà¥à¤Ÿà¥à¤°à¥€à¤®à¤¿à¤‚ग +* चर गति पà¥à¤²à¥‡à¤¬à¥ˆà¤• (सफ़ाई धà¥à¤µà¤¨à¤¿ पà¥à¤¸à¥à¤¤à¤•à¤¾à¤²à¤¯ या पà¥à¤°à¥‡à¤¸à¥à¤Ÿà¤¿à¤¸à¥€à¤®à¥‹ कि आवशà¥à¤¯à¤•à¤¤à¤¾ है) + * à¤à¤Ÿà¤® और आरà¤à¤¸à¤à¤¸ फ़ीड के लिठसहायता +* Support for password-protected feeds and episodes +* Support for searching iTunes listings +* ओà¤à¤®à¤ªà¥€à¤à¤² आयात और निरà¥à¤¯à¤¾à¤¤ +* Flattr integration including automatic flattring +* पà¥à¤²à¥‡à¤¯à¤° होमसà¥à¤•à¥à¤°à¥€à¤¨ विजेट +* खोज +* सà¥à¤µà¤šà¤¾à¤²à¤¿à¤¤ फ़ीड अदà¥à¤¯à¤¤à¤¨ +* नठà¤à¤ªà¤¿à¤¸à¥‹à¤¡ की सà¥à¤µà¤šà¤¾à¤²à¤¿à¤¤ डाउनलोड +* सà¥à¤²à¥€à¤ª टाइमर +* Gpodder.net podcast निरà¥à¤¦à¥‡à¤¶à¤¿à¤•à¤¾ के लिठपà¥à¤°à¤µà¥‡à¤¶ +* gpodder.net सेवा के साथ सदसà¥à¤¯à¤¤à¤¾ सिंकà¥à¤°à¤¨à¤¾à¤‡à¤œà¤¼ +* Supports MP3 chapters, VorbisComment chapters and Podlove Simple Chapters +* Supports paged feeds (http://podlove.org/paged-feeds/)
\ No newline at end of file diff --git a/app/src/main/play/hi-IN/listing/shortdescription b/app/src/main/play/hi-IN/listing/shortdescription new file mode 100644 index 000000000..4eceefbb7 --- /dev/null +++ b/app/src/main/play/hi-IN/listing/shortdescription @@ -0,0 +1 @@ +Easy-to-use, flexible and open-source podcast manager and player
\ No newline at end of file diff --git a/app/src/main/play/hi-IN/listing/title b/app/src/main/play/hi-IN/listing/title new file mode 100644 index 000000000..31552f353 --- /dev/null +++ b/app/src/main/play/hi-IN/listing/title @@ -0,0 +1 @@ +AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/hi-IN/listing/video b/app/src/main/play/hi-IN/listing/video new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/app/src/main/play/hi-IN/listing/video diff --git a/app/src/main/play/hi-IN/whatsnew b/app/src/main/play/hi-IN/whatsnew new file mode 100644 index 000000000..a65bddbbb --- /dev/null +++ b/app/src/main/play/hi-IN/whatsnew @@ -0,0 +1,11 @@ +* New features: + * Subscription overview + * Proxy support + * Statistics + * Manual gpodder.net sync +* Fixes: + * Audioplayer controls + * Audio ducking + * Video control fade-out + * External media controls + * Feed parsing
\ No newline at end of file diff --git a/app/src/main/play/hi_IN/listing/fulldescription b/app/src/main/play/hi_IN/listing/fulldescription new file mode 100644 index 000000000..87b477fdc --- /dev/null +++ b/app/src/main/play/hi_IN/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> +But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. + +Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. + +<b>All features:</b><br> +IMPORT, ORGANIZE AND PLAY<br> +• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> +• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> +• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> +• Access password-protected feeds and episodes<br> +• Take advantage of paged feeds (www.podlove.org/paged-feeds) + +KEEP TRACK, SHARE & APPRECIATE<br> +• Keep track of the best of the best by marking episodes as favourites<br> +• Find that one episode through the playback history or by searching (titles and shownotes)<br> +• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> +• Support content creators with Flattr integration including automatic flattring + +CONTROL THE SYSTEM<br> +• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> +• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> +• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adapt to your environment using the light and dark theme<br> +• Back-up your subscriptions with the gPodder.net integration and OPML export + +<b>Join the AntennaPod community!</b><br> +AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! + +GitHub is the place to go for feature requests, bug reports and code contributions:<br> +https://www.github.com/AntennaPod/AntennaPod + +Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> +https://groups.google.com/forum/#!forum/antennapod + +Have a question or want to give us feedback? +https://twitter.com/@AntennaPod + +Transifex is the place to help with translations:<br> +https://www.transifex.com/antennapod/antennapod + +Check out our Beta Testing programme to get the latest features first:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/hi_IN.md b/app/src/main/play/hi_IN/whatsnew index 6a057082a..6a057082a 100644 --- a/changelog/hi_IN.md +++ b/app/src/main/play/hi_IN/whatsnew diff --git a/app/src/main/play/hu/listing/fulldescription b/app/src/main/play/hu/listing/fulldescription new file mode 100644 index 000000000..87b477fdc --- /dev/null +++ b/app/src/main/play/hu/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> +But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. + +Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. + +<b>All features:</b><br> +IMPORT, ORGANIZE AND PLAY<br> +• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> +• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> +• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> +• Access password-protected feeds and episodes<br> +• Take advantage of paged feeds (www.podlove.org/paged-feeds) + +KEEP TRACK, SHARE & APPRECIATE<br> +• Keep track of the best of the best by marking episodes as favourites<br> +• Find that one episode through the playback history or by searching (titles and shownotes)<br> +• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> +• Support content creators with Flattr integration including automatic flattring + +CONTROL THE SYSTEM<br> +• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> +• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> +• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adapt to your environment using the light and dark theme<br> +• Back-up your subscriptions with the gPodder.net integration and OPML export + +<b>Join the AntennaPod community!</b><br> +AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! + +GitHub is the place to go for feature requests, bug reports and code contributions:<br> +https://www.github.com/AntennaPod/AntennaPod + +Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> +https://groups.google.com/forum/#!forum/antennapod + +Have a question or want to give us feedback? +https://twitter.com/@AntennaPod + +Transifex is the place to help with translations:<br> +https://www.transifex.com/antennapod/antennapod + +Check out our Beta Testing programme to get the latest features first:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/hu.md b/app/src/main/play/hu/whatsnew index 8f2618b8f..8f2618b8f 100644 --- a/changelog/hu.md +++ b/app/src/main/play/hu/whatsnew diff --git a/app/src/main/play/id/listing/fulldescription b/app/src/main/play/id/listing/fulldescription new file mode 100644 index 000000000..87b477fdc --- /dev/null +++ b/app/src/main/play/id/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> +But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. + +Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. + +<b>All features:</b><br> +IMPORT, ORGANIZE AND PLAY<br> +• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> +• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> +• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> +• Access password-protected feeds and episodes<br> +• Take advantage of paged feeds (www.podlove.org/paged-feeds) + +KEEP TRACK, SHARE & APPRECIATE<br> +• Keep track of the best of the best by marking episodes as favourites<br> +• Find that one episode through the playback history or by searching (titles and shownotes)<br> +• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> +• Support content creators with Flattr integration including automatic flattring + +CONTROL THE SYSTEM<br> +• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> +• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> +• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adapt to your environment using the light and dark theme<br> +• Back-up your subscriptions with the gPodder.net integration and OPML export + +<b>Join the AntennaPod community!</b><br> +AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! + +GitHub is the place to go for feature requests, bug reports and code contributions:<br> +https://www.github.com/AntennaPod/AntennaPod + +Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> +https://groups.google.com/forum/#!forum/antennapod + +Have a question or want to give us feedback? +https://twitter.com/@AntennaPod + +Transifex is the place to help with translations:<br> +https://www.transifex.com/antennapod/antennapod + +Check out our Beta Testing programme to get the latest features first:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/id.md b/app/src/main/play/id/whatsnew index 8f2618b8f..8f2618b8f 100644 --- a/changelog/id.md +++ b/app/src/main/play/id/whatsnew diff --git a/app/src/main/play/is/listing/fulldescription b/app/src/main/play/is/listing/fulldescription new file mode 100644 index 000000000..87b477fdc --- /dev/null +++ b/app/src/main/play/is/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> +But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. + +Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. + +<b>All features:</b><br> +IMPORT, ORGANIZE AND PLAY<br> +• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> +• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> +• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> +• Access password-protected feeds and episodes<br> +• Take advantage of paged feeds (www.podlove.org/paged-feeds) + +KEEP TRACK, SHARE & APPRECIATE<br> +• Keep track of the best of the best by marking episodes as favourites<br> +• Find that one episode through the playback history or by searching (titles and shownotes)<br> +• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> +• Support content creators with Flattr integration including automatic flattring + +CONTROL THE SYSTEM<br> +• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> +• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> +• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adapt to your environment using the light and dark theme<br> +• Back-up your subscriptions with the gPodder.net integration and OPML export + +<b>Join the AntennaPod community!</b><br> +AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! + +GitHub is the place to go for feature requests, bug reports and code contributions:<br> +https://www.github.com/AntennaPod/AntennaPod + +Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> +https://groups.google.com/forum/#!forum/antennapod + +Have a question or want to give us feedback? +https://twitter.com/@AntennaPod + +Transifex is the place to help with translations:<br> +https://www.transifex.com/antennapod/antennapod + +Check out our Beta Testing programme to get the latest features first:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/it-IT/listing/fulldescription b/app/src/main/play/it-IT/listing/fulldescription new file mode 100644 index 000000000..a88d693e0 --- /dev/null +++ b/app/src/main/play/it-IT/listing/fulldescription @@ -0,0 +1,40 @@ +AntennaPod è un riproduttore e gestore di podcast che ti da accesso immediato a milioni di podcast gratuiti e a pagamento, dai podcaster indipendenti alle più grandi case editrici come BBC, NPR e CNN. Aggiungi, importa e esporta in modo semplici usando il database di podcast di iTunes, da file OPML o da semplici URL RSS. Risparmia fatica, batteria e dati con il potente controllo automatizzato per il download di episodi (orari specifici, intervalli e reti WiFi) e l'eliminazione degli episodi.<br> +But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. + +Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. + +<b>Funzioni:</b><br> +IMPORTA, ORGANIZZA E RIPRODUCI<br> +• Aggiungi e importa feed via iTunes, gPodder.net, file OPML e link RSS o Atom<br> +• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> +• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> +• Accedi a feed e episodi protetti da password<br> +• Take advantage of paged feeds (www.podlove.org/paged-feeds) + +TIENI TRACCIA, CONDIVIDI & APPREZZA<br> +• Tieni traccia del meglio del meglio segnando i tuoi episodi preferiti<br> +• Find that one episode through the playback history or by searching (titles and shownotes)<br> +• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> +• Support content creators with Flattr integration including automatic flattring + +CONTROLLA IL SISTEMA<br> +• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> +• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> +• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adapt to your environment using the light and dark theme<br> +• Back-up your subscriptions with the gPodder.net integration and OPML export + +<b>Entra nella community di AntennaPod!</b><br> +AntennaPod è sviluppato da volontari. Anche tu puoi contribuire, con il codice o con dei commenti! + +GitHub è il posto nel quale fare richieste, segnalare bug e contribuire allo sviluppo:<br> +www.github.com/AntennaPod/AntennaPod + +Il nostro Gruppo Google è il posto dove condividere le tue idee, podcast preferiti e gratitudine a tutti i nostri volontari:<br> +https://groups.google.com/forum/#!forum/antennapod + +Transifex è il posto dove puoi aiutare a tradurre AntennaPod:<br> +www.transifex.com/antennapod/antennapod + +Check out our Beta Testing programme to get the latest features first:<br> +www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/it-IT/listing/shortdescription b/app/src/main/play/it-IT/listing/shortdescription new file mode 100644 index 000000000..bbc1e1f84 --- /dev/null +++ b/app/src/main/play/it-IT/listing/shortdescription @@ -0,0 +1 @@ +Un riproduttore e gestore di podcast open-source, flessibile e facile da usare
\ No newline at end of file diff --git a/app/src/main/play/it-IT/listing/title b/app/src/main/play/it-IT/listing/title new file mode 100644 index 000000000..31552f353 --- /dev/null +++ b/app/src/main/play/it-IT/listing/title @@ -0,0 +1 @@ +AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/it-IT/listing/video b/app/src/main/play/it-IT/listing/video new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/app/src/main/play/it-IT/listing/video diff --git a/app/src/main/play/it-IT/whatsnew b/app/src/main/play/it-IT/whatsnew new file mode 100644 index 000000000..a65bddbbb --- /dev/null +++ b/app/src/main/play/it-IT/whatsnew @@ -0,0 +1,11 @@ +* New features: + * Subscription overview + * Proxy support + * Statistics + * Manual gpodder.net sync +* Fixes: + * Audioplayer controls + * Audio ducking + * Video control fade-out + * External media controls + * Feed parsing
\ No newline at end of file diff --git a/description/it.txt b/app/src/main/play/it/listing/fulldescription index ba94d94ee..307f86117 100644 --- a/description/it.txt +++ b/app/src/main/play/it/listing/fulldescription @@ -1,5 +1,3 @@ -Easy-to-use, flexible and open-source podcast manager and player - AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. @@ -10,7 +8,7 @@ IMPORTA, ORGANIZZA E RIPRODUCI<br> • Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> • Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> • Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> -• Access password-protected feeds and episodes<br> +• Accedi a feed ed episodi protetti da password<br> • Take advantage of paged feeds (www.podlove.org/paged-feeds) TIENI TRACCIA, CONDIVIDI & APPREZZA<br> @@ -22,7 +20,7 @@ TIENI TRACCIA, CONDIVIDI & APPREZZA<br> CONTROLLA IL SISTEMA<br> • Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> • Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> -• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Utilizza AntennaPod nella tua lingua (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> • Adapt to your environment using the light and dark theme<br> • Back-up your subscriptions with the gPodder.net integration and OPML export @@ -35,8 +33,11 @@ https://www.github.com/AntennaPod/AntennaPod Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> https://groups.google.com/forum/#!forum/antennapod -Transifex è il luogo con cui aiutare con le traduzioni:<br> +Hai una domanda o vuoi fornirci un feedback? +https://twitter.com/@AntennaPod + +Transifex è il posto in cui aiutare con le traduzioni:<br> https://www.transifex.com/antennapod/antennapod -Check out our Beta Testing programme to get the latest features first:<br> +Dai un'occhiata al nostro programma di beta testing per ricevere per primo le funzioni più recenti:<br> https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/it.md b/app/src/main/play/it/whatsnew index 3e73d3068..3e73d3068 100644 --- a/changelog/it.md +++ b/app/src/main/play/it/whatsnew diff --git a/description/it_IT.txt b/app/src/main/play/it_IT/listing/fulldescription index 772d41dff..eb2abb40d 100644 --- a/description/it_IT.txt +++ b/app/src/main/play/it_IT/listing/fulldescription @@ -1,6 +1,4 @@ -Un riproduttore e gestore di podcast open-source, flessibile e facile da usare - -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (episode filtering, specify times, intervals and WiFi networks) and deleting episodes (based your favorites and delay settings).<br> +AntennaPod è un riproduttore e gestore di podcast che ti da accesso immediato a milioni di podcast gratuiti e a pagamento, dai podcaster indipendenti alle più grandi emittenti come BBC, NPR e CNN. Aggiungi, importa e esporta in modo semplici usando il database di podcast di iTunes, da file OPML o da semplici URL RSS. Risparmia fatica, batteria e dati con il potente controllo automatizzato per il download di episodi (orari specifici, intervalli e reti WiFi) e l'eliminazione degli episodi.<br> But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. Creato da amanti dei podcast, AntennaPod è libero in tutti i sensi: open source, gratis, senza pubblicità . @@ -14,32 +12,32 @@ IMPORTA, ORGANIZZA E RIPRODUCI<br> • Take advantage of paged feeds (www.podlove.org/paged-feeds) TIENI TRACCIA, CONDIVIDI & APPREZZA<br> -• Keep track of the best of the best by marking episodes as favorites<br> +• Keep track of the best of the best by marking episodes as favourites<br> • Find that one episode through the playback history or by searching (titles and shownotes)<br> • Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> • Supporta i creatori di contenuti tramite l'integrazione con Flattr e il flattring automatico CONTROLLA IL SISTEMA<br> -• Take control over automated downloading: choose feeds, filter episodes based on keywords, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> -• Manage storage by setting the amount of cached episodes, smart deletion (based on your favorites and play status) and selecting your preferred location<br> +• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> +• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> • Usa AntennaPod nella tua lingua (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> • Adapt to your environment using the light and dark theme<br> • Back-up your subscriptions with the gPodder.net integration and OPML export -<b>Entra nella community di AntennaPod!</b> +<b>Entra nella community di AntennaPod!</b><br> AntennaPod è sviluppato da volontari. Anche tu puoi contribuire, con il codice o con dei commenti! -Fai le tue domande o invia un feedback via Twitter: -https://twitter.com/@AntennaPod +GitHub è il posto nel quale fare richieste, segnalare bug e contribuire allo sviluppo:<br> +https://www.github.com/AntennaPod/AntennaPod -Condividi le tue idee, podcast preferiti o esprimi la tua gratitudine a tutti i volontari nel nostro gruppo Google: +Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> https://groups.google.com/forum/#!forum/antennapod -Aiuta a tradurre l'app nella tua lingua su Transifex: -https://www.transifex.com/antennapod/antennapod +Hai una domanda o vuoi darci un feedback? +https://twitter.com/@AntennaPod -Dai un'occhiata al nostro programma di Beta Testing per provare le nuove features in anticipo: -https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod +Transifex è il posto dove puoi contribuire alla traduzione di AntennaPod:<br> +https://www.transifex.com/antennapod/antennapod -Visita GitHub per inviare le ture richieste per nuove funzionalità , segnalare bug e contribuire allo sviluppo: -https://www.github.com/AntennaPod/AntennaPod
\ No newline at end of file +Dai un'occhiata al nostro programma di Beta Testing per avere accesso in anticipo alle nuove features:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/it_IT.md b/app/src/main/play/it_IT/whatsnew index 2a4ba6b2f..2a4ba6b2f 100644 --- a/changelog/it_IT.md +++ b/app/src/main/play/it_IT/whatsnew diff --git a/app/src/main/play/iw-IL/listing/fulldescription b/app/src/main/play/iw-IL/listing/fulldescription new file mode 100644 index 000000000..cbbf5de28 --- /dev/null +++ b/app/src/main/play/iw-IL/listing/fulldescription @@ -0,0 +1,23 @@ +×× ×˜× ×”-פוד ×”×•× ×ž× ×”×œ פודק×סט בקוד פתוח עבור ×× ×“×¨×•×™×“ 2.3.3 ומעלה. ×”×•× ×ž×¦×™×¢ ×ת כל ×ª×›×•× ×•×ª הבסיסיות ש×תה מצפה ×ž×ž× ×”×œ פודק×סטי×, כמו הזרמה והורדה של פרקי×, ×¨×™×¢× ×•×Ÿ ×”×–× ×•×ª ×וטומטי ×ו הוספת ×¤×¨×§×™× ×œ×ª×•×¨ לה××–× ×” בהמשך. כמו כן, ×× ×˜× ×”-פוד מ×פשר לך ×œ×ª×¨×•× ×“×¨×š flattr פודק××¡×˜×™× ×•×¤×¨×§×™× ×ž×‘×ª×•×š ×”×פליקציה. + +עד ×›×” ×”×ª×›×•× ×•×ª הב×ות מיושמות: + +* הורדה והזרמה של ×¤×¨×§×™× +* השמעה במהירות ×ž×©×ª× ×” (דורש ספריית ס××•× ×“ Presto ×ו Prestissimo) +* תמיכה ×‘×”×–× ×•×ª RSS ו-Atom +* תמיכה ×‘×”×–× ×•×ª ×•×¤×¨×§×™× ×ž×•×’× ×™ ססמה +* ×™×‘×•× ×•×™×¦×•× OMPL +××™× ×˜×’×¨×¦×™×” ×¢× flattr כולל flattr ×וטומ×טי +* יישומון × ×’×Ÿ למסך הבית +* חיפוש +* ×¢×™×“×›×•× ×™ ×”×–× ×•×ª ××•×˜×•×ž×˜×™× +* הורדה ×וטמטית של ×¤×¨×§×™× ×—×“×©×™× +* טיימר ×©×™× ×” +*גישה ל××™× ×“×§×¡ הפודק××¡×˜×™× gpodder.net +* ×¡×™× ×›×¨×•×Ÿ ×¨×™×©×•×ž×™× ×¢× ×©×™×¨×•×ª gpodder.net +* תמיכה בפרקי MP3, פרקי VorbisComment ופרקי Podlove Simple +* תמיכה ×‘×”×–× ×•×ª מרובות ×“×¤×™× (http://podlove.org/paged-feeds/) + +לדווח ב××’×™× ×ו משוב, × ×™×ª×Ÿ ליצור סוגיה (issue) בעמוד פרויקט Github (https://github.com/danieloeh/AntennaPod) ×ו לשלוח דו×ר ××œ×§×˜×¨×•× ×™ לfeedback@antennapod.com. × ×™×ª×Ÿ ×’× ×œ×™×¦×•×¨ קשר antennapod@ בטוויטר. + +×™×™×©×•× ×–×” ×”×•× ×œ×œ× ×ª×©×œ×•× ×•×œ×œ× ×¤×¨×¡×•×ž×•×ª. ×× ×תה רוצה לתמוך ב×× ×˜× ×”-פוד, ×תה יכול ×œ×ª×¨×•× ×‘-flattr ×›×ן: flattr.com/thing/745609
\ No newline at end of file diff --git a/app/src/main/play/iw-IL/listing/shortdescription b/app/src/main/play/iw-IL/listing/shortdescription new file mode 100644 index 000000000..ad3ccb1f8 --- /dev/null +++ b/app/src/main/play/iw-IL/listing/shortdescription @@ -0,0 +1 @@ +An open-source podcast manager for Android
\ No newline at end of file diff --git a/app/src/main/play/iw-IL/listing/title b/app/src/main/play/iw-IL/listing/title new file mode 100644 index 000000000..31552f353 --- /dev/null +++ b/app/src/main/play/iw-IL/listing/title @@ -0,0 +1 @@ +AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/iw-IL/listing/video b/app/src/main/play/iw-IL/listing/video new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/app/src/main/play/iw-IL/listing/video diff --git a/app/src/main/play/iw-IL/whatsnew b/app/src/main/play/iw-IL/whatsnew new file mode 100644 index 000000000..a65bddbbb --- /dev/null +++ b/app/src/main/play/iw-IL/whatsnew @@ -0,0 +1,11 @@ +* New features: + * Subscription overview + * Proxy support + * Statistics + * Manual gpodder.net sync +* Fixes: + * Audioplayer controls + * Audio ducking + * Video control fade-out + * External media controls + * Feed parsing
\ No newline at end of file diff --git a/app/src/main/play/ja-JP/listing/fulldescription b/app/src/main/play/ja-JP/listing/fulldescription new file mode 100644 index 000000000..38f6deffb --- /dev/null +++ b/app/src/main/play/ja-JP/listing/fulldescription @@ -0,0 +1,41 @@ +AntennaPodã¯ã€ç‹¬è‡ªã®ãƒãƒƒãƒ‰ã‚ャスターã‹ã‚‰ã€BBCã€NPRã€CNNãªã©ã®å¤§è¦æ¨¡ãªæ”¾é€ã¾ã§ã€æ•°ç™¾ä¸‡ã®ç„¡æ–™ã‚„有料ãƒãƒƒãƒ‰ã‚ャストã«çž¬æ™‚ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã“ã¨ãŒã§ãã‚‹ã€ãƒãƒƒãƒ‰ã‚ャストマãƒãƒ¼ã‚¸ãƒ£ãƒ¼ãŠã‚ˆã³ãƒ—レーヤーã§ã™ã€‚フィードã¯æ‰‹é–“ã®ã‹ã‹ã‚‰ãªã„iTunesã®Podcastã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã€OPMLファイルや簡å˜ãªRSSã®URLを使用ã—ã¦è¿½åŠ ã€ã‚¤ãƒ³ãƒãƒ¼ãƒˆã€ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã—ã¾ã™ã€‚エピソードã®ãƒ€ã‚¦ãƒ³ãƒãƒ¼ãƒ‰ (時間ã€é–“éš”ãŠã‚ˆã³WiFiãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚’指定) ã¨ã‚¨ãƒ”ソードã®å‰Šé™¤ (ãŠæ°—ã«å…¥ã‚Šã¨é…延è¨å®šã«åŸºã¥ã„ã¦) ã‚’ã™ã‚‹ãŸã‚ã«å¼·åŠ›ãªè‡ªå‹•ã‚³ãƒ³ãƒˆãƒãƒ¼ãƒ«ã§ã€æ‰‹é–“ã€ãƒãƒƒãƒ†ãƒªæ¶ˆè²»ã€ãƒ¢ãƒã‚¤ãƒ«ãƒ‡ãƒ¼ã‚¿ä½¿ç”¨é‡ã‚’節約ã—ã¾ã™ã€‚<br> +ã—ã‹ã—最もé‡è¦ãªã“ã¨: エピソードをダウンãƒãƒ¼ãƒ‰ã€ã‚¹ãƒˆãƒªãƒ¼ãƒ å†ç”Ÿã€ã¾ãŸã¯ã‚ューã«å…¥ã‚Œã¦ã€ãã—ã¦å†ç”Ÿé€Ÿåº¦ã®èª¿æ•´ã€ãƒãƒ£ãƒ—ターã®ã‚µãƒãƒ¼ãƒˆã€ã‚¹ãƒªãƒ¼ãƒ—タイマーã§å¥½ããªã‚ˆã†ã«æ¥½ã—ã‚“ã§ãã ã•ã„。Flattrçµ±åˆã§ã‚³ãƒ³ãƒ†ãƒ³ãƒ„作æˆè€…ã«ã‚ãªãŸã®æ„›ã‚’示ã™ã“ã¨ãŒã§ãã¾ã™ã€‚ + +ãƒãƒƒãƒ‰ã‚ャスト愛好家ãŒä½œæˆã—㟠AntennaPod ã¯ã™ã¹ã¦ã®æ„味ã§ãƒ•ãƒªãƒ¼è‡ªç”±ã§ã™: オープンソースã€ã‚³ã‚¹ãƒˆä¸è¦ã€åºƒå‘Šã¯ã‚ã‚Šã¾ã›ã‚“。 + +<b>ã™ã¹ã¦ã®æ©Ÿèƒ½:</b><br> +インãƒãƒ¼ãƒˆã€æ•´ç†ã€å†ç”Ÿ<br> +• iTunesã‚„ã€gPodder.netディレクトリã€OPMLファイルã€RSSã¾ãŸã¯Atom経由ã§ãƒ•ã‚£ãƒ¼ãƒ‰ã‚’è¿½åŠ ãŠã‚ˆã³ã‚¤ãƒ³ãƒãƒ¼ãƒˆã—ã¾ã™<br> +• 様々ãªå ´æ‰€ã§å†ç”Ÿã‚’管ç†ã—ã¾ã™: ホーム画é¢ã‚¦ã‚£ã‚¸ã‚§ãƒƒãƒˆã€ã‚·ã‚¹ãƒ†ãƒ 通知ã€ã‚¤ãƒ¤ãƒ›ãƒ³ã€Bluetoothコントãƒãƒ¼ãƒ«<br> +• å†ç”Ÿé€Ÿåº¦ã®èª¿æ•´ã€ãƒãƒ£ãƒ—ターã®ã‚µãƒãƒ¼ãƒˆ (MP3ã€VorbisCommentã¨Podlove)ã€å†ç”Ÿä½ç½®ã®ä¿å˜ã€é«˜åº¦ãªã‚¹ãƒªãƒ¼ãƒ—タイマー (シェイクã—ã¦ãƒªã‚»ãƒƒãƒˆã€éŸ³é‡ã‚’å°ã•ãã€å†ç”Ÿé€Ÿåº¦ã‚’é…ã) ã§ã€ãŠå¥½ã¿ã® +èžãæ–¹ã§ãŠæ¥½ã—ã¿ãã ã•ã„<br> +• アクセスパスワードã§ä¿è·ã•ã‚ŒãŸãƒ•ã‚£ãƒ¼ãƒ‰ã¨ã‚¨ãƒ”ソード<br> +• ページフィードをã”利用ãã ã•ã„ (www.podlove.org/paged-feeds) + +記録ã€å…±æœ‰ & æ„Ÿè¬<br> +• エピソードをãŠæ°—ã«å…¥ã‚Šã¨ã—ã¦ãƒžãƒ¼ã‚¯ã—ã¦ã€ä¸€ç•ªã®ä¸ã®ä¸€ç•ªã‚’記録ã—ã¦ãã ã•ã„<br> +• å†ç”Ÿå±¥æ´ã‹ã‚‰ã€ã¾ãŸã¯æ¤œç´¢ (タイトルã¨ã‚·ãƒ§ãƒ¼ãƒŽãƒ¼ãƒˆ) ã—ã¦ç›®çš„ã®ã‚¨ãƒ”ソードを見ã¤ã‘ã¦ãã ã•ã„<br> +• 高度ãªã‚½ãƒ¼ã‚·ãƒ£ãƒ«ãƒ¡ãƒ‡ã‚£ã‚¢ã¨ãƒ¡ãƒ¼ãƒ«ã‚ªãƒ—ションã€gPodder.netサービスã€OPMLエクスãƒãƒ¼ãƒˆã‹ã‚‰ã‚¨ãƒ”ソードやフィードを共有ã—ã¦ãã ã•ã„<br> +• 自動Flattrã‚’å«ã‚€Flattrã®çµ±åˆã§ã‚³ãƒ³ãƒ†ãƒ³ãƒ„クリエイターをサãƒãƒ¼ãƒˆã—ã¾ã™ + +システムã®ã‚³ãƒ³ãƒˆãƒãƒ¼ãƒ« +• 自動ダウンãƒãƒ¼ãƒ‰ã®åˆ¶å¾¡: フィードをé¸æŠžã€ãƒ¢ãƒã‚¤ãƒ«ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚’除外ã€ç‰¹å®šã®WiFiãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚’é¸æŠžã€é›»è©±ã‚’å……é›»ã™ã‚‹å¿…è¦ã€æ™‚間や間隔をè¨å®š<br> +• ã‚ャッシュã•ã‚Œã‚‹ã‚¨ãƒ”ソードã®é‡ã®è¨å®šã€ã‚¹ãƒžãƒ¼ãƒˆå‰Šé™¤ (ãŠæ°—ã«å…¥ã‚Šã‚„プレイ状æ³ã«åŸºã¥ã„ã¦) ã¨ã€ãŠå¥½ã¿ã®å ´æ‰€ã‚’é¸æŠžã—ã¦ã€ã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸ã‚’管ç†ã—ã¾ã™<br> +• AntennaPod ã‚’ã‚ãªãŸã®è¨€èªžã§ã”利用ãã ã•ã„ (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• ライトã¨ãƒ€ãƒ¼ã‚¯ テーマを使用ã—ã¦ç’°å¢ƒã«é©å¿œã—ã¾ã™<br> +• gPodder.netçµ±åˆã¨OPMLã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã§ã€è³¼èªã‚’ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—ã—ã¾ã™ + +<b>AntennaPod ã®ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ã«å‚åŠ ã—ã¦ãã ã•ã„!</b><br> +AntennaPod ã¯ãƒœãƒ©ãƒ³ãƒ†ã‚£ã‚¢ã«ã‚ˆã£ã¦æ´»ç™ºã«é–‹ç™ºä¸ã§ã™ã€‚コードやコメントã§ã€ã‚ãªãŸã‚‚も貢献ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™! + +GitHubã¯ã€æ©Ÿèƒ½ã®ãƒªã‚¯ã‚¨ã‚¹ãƒˆã€ãƒã‚°ã®å ±å‘Šã€ã‚³ãƒ¼ãƒ‰ã®è²¢çŒ®ã®ãŸã‚ã®å ´æ‰€ã§ã™:<br> +www.github.com/AntennaPod/AntennaPod + +ç§ãŸã¡ã®Googleグループã¯ã€ã‚ãªãŸã®ã‚¢ã‚¤ãƒ‡ã‚¢ã€ãŠæ°—ã«å…¥ã‚Šã®ãƒãƒƒãƒ‰ã‚ャスティングモーメントã€æ„Ÿè¬ã‚’ã€ã™ã¹ã¦ã®ãƒœãƒ©ãƒ³ãƒ†ã‚£ã‚¢ã¨å…±æœ‰ã™ã‚‹ãŸã‚ã®å ´æ‰€ã§:<br> +https://groups.google.com/forum/#!forum/antennapod + +Transifexã¯ç¿»è¨³ã‚’支æ´ã™ã‚‹ãŸã‚ã®å ´æ‰€ã§ã™:<br> +www.transifex.com/antennapod/antennapod + +ç§ãŸã¡ã®ãƒ™ãƒ¼ã‚¿ãƒ†ã‚¹ãƒˆãƒ—ãƒã‚°ãƒ©ãƒ ã‚’ãƒã‚§ãƒƒã‚¯ã—ã¦ã€æœ€æ–°æ©Ÿèƒ½ã‚’最åˆã«å…¥æ‰‹ã—ã¦ãã ã•ã„:<br> +www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/ja-JP/listing/shortdescription b/app/src/main/play/ja-JP/listing/shortdescription new file mode 100644 index 000000000..6872efb2b --- /dev/null +++ b/app/src/main/play/ja-JP/listing/shortdescription @@ -0,0 +1 @@ +使ã„ã‚„ã™ãã¦æŸ”軟ãªã€ã‚ªãƒ¼ãƒ—ンソース ãƒãƒƒãƒ‰ã‚ャスト マãƒãƒ¼ã‚¸ãƒ£ãƒ¼/プレイヤーã§ã™ã€‚
\ No newline at end of file diff --git a/app/src/main/play/ja-JP/listing/title b/app/src/main/play/ja-JP/listing/title new file mode 100644 index 000000000..31552f353 --- /dev/null +++ b/app/src/main/play/ja-JP/listing/title @@ -0,0 +1 @@ +AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/ja-JP/listing/video b/app/src/main/play/ja-JP/listing/video new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/app/src/main/play/ja-JP/listing/video diff --git a/app/src/main/play/ja-JP/whatsnew b/app/src/main/play/ja-JP/whatsnew new file mode 100644 index 000000000..08d63a3b6 --- /dev/null +++ b/app/src/main/play/ja-JP/whatsnew @@ -0,0 +1,12 @@ +* 新機能: + * 実験的㪠Chromecast サãƒãƒ¼ãƒˆ + * è³¼èªæ¦‚è¦ + * プãƒã‚シサãƒãƒ¼ãƒˆ + * çµ±è¨ˆæƒ…å ± + * 手動 gpodder.net åŒæœŸ +* ä¿®æ£: + * オーディオプレイヤー コントãƒãƒ¼ãƒ« + * オーディオ ダッã‚ング + * ビデオ コントãƒãƒ¼ãƒ« フェードアウト + * 外部メディアコントãƒãƒ¼ãƒ« + * フィードã®è§£æž
\ No newline at end of file diff --git a/description/ja.txt b/app/src/main/play/ja/listing/fulldescription index 8d84248ae..b85f6787e 100644 --- a/description/ja.txt +++ b/app/src/main/play/ja/listing/fulldescription @@ -1,6 +1,4 @@ -使ã„ã‚„ã™ãã¦æŸ”軟ãªã€ã‚ªãƒ¼ãƒ—ンソース ãƒãƒƒãƒ‰ã‚ャスト マãƒãƒ¼ã‚¸ãƒ£ãƒ¼/プレイヤーã§ã™ã€‚ - -AntennaPodã¯ã€ç‹¬è‡ªã®ãƒãƒƒãƒ‰ã‚ャスターã‹ã‚‰ã€BBCã€NPRã€CNNãªã©ã®å¤§è¦æ¨¡ãªæ”¾é€ã¾ã§ã€æ•°ç™¾ä¸‡ã®ç„¡æ–™ã‚„有料ãƒãƒƒãƒ‰ã‚ャストã«çž¬æ™‚ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã“ã¨ãŒã§ãã‚‹ã€ãƒãƒƒãƒ‰ã‚ャストマãƒãƒ¼ã‚¸ãƒ£ãƒ¼ãŠã‚ˆã³ãƒ—レーヤーã§ã™ã€‚フィードã¯æ‰‹é–“ã®ã‹ã‹ã‚‰ãªã„iTunesã®Podcastã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã€OPMLファイルや簡å˜ãªRSSã®URLを使用ã—ã¦è¿½åŠ ã€ã‚¤ãƒ³ãƒãƒ¼ãƒˆã€ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã—ã¾ã™ã€‚エピソードã®ãƒ€ã‚¦ãƒ³ãƒãƒ¼ãƒ‰ (エピソードã®ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼ã€æ™‚é–“ã€é–“éš”ãŠã‚ˆã³WiFiãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚’指定) ã¨ã‚¨ãƒ”ソードã®å‰Šé™¤ (ãŠæ°—ã«å…¥ã‚Šã¨é…延è¨å®šã«åŸºã¥ã„ã¦) ã‚’ã™ã‚‹å¼·åŠ›ãªè‡ªå‹•ã‚³ãƒ³ãƒˆãƒãƒ¼ãƒ«ã§ã€æ‰‹é–“ã€ãƒãƒƒãƒ†ãƒªæ¶ˆè²»ã€ãƒ¢ãƒã‚¤ãƒ«ãƒ‡ãƒ¼ã‚¿ä½¿ç”¨é‡ã‚’節約ã—ã¾ã™ã€‚<br> +AntennaPodã¯ã€ç‹¬è‡ªã®ãƒãƒƒãƒ‰ã‚ャスターã‹ã‚‰ã€BBCã€NPRã€CNNãªã©ã®å¤§è¦æ¨¡ãªæ”¾é€ã¾ã§ã€æ•°ç™¾ä¸‡ã®ç„¡æ–™ã‚„有料ãƒãƒƒãƒ‰ã‚ャストã«çž¬æ™‚ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã“ã¨ãŒã§ãã‚‹ã€ãƒãƒƒãƒ‰ã‚ャストマãƒãƒ¼ã‚¸ãƒ£ãƒ¼ãŠã‚ˆã³ãƒ—レーヤーã§ã™ã€‚フィードã¯æ‰‹é–“ã®ã‹ã‹ã‚‰ãªã„iTunesã®Podcastã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã€OPMLファイルや簡å˜ãªRSSã®URLを使用ã—ã¦è¿½åŠ ã€ã‚¤ãƒ³ãƒãƒ¼ãƒˆã€ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã—ã¾ã™ã€‚エピソードã®ãƒ€ã‚¦ãƒ³ãƒãƒ¼ãƒ‰ (時間ã€é–“éš”ãŠã‚ˆã³WiFiãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚’指定) ã¨ã‚¨ãƒ”ソードã®å‰Šé™¤ (ãŠæ°—ã«å…¥ã‚Šã¨é…延è¨å®šã«åŸºã¥ã„ã¦) ã‚’ã™ã‚‹ãŸã‚ã«å¼·åŠ›ãªè‡ªå‹•ã‚³ãƒ³ãƒˆãƒãƒ¼ãƒ«ã§ã€æ‰‹é–“ã€ãƒãƒƒãƒ†ãƒªæ¶ˆè²»ã€ãƒ¢ãƒã‚¤ãƒ«ãƒ‡ãƒ¼ã‚¿ä½¿ç”¨é‡ã‚’節約ã—ã¾ã™ã€‚<br> ã—ã‹ã—最もé‡è¦ãªã“ã¨: エピソードをダウンãƒãƒ¼ãƒ‰ã€ã‚¹ãƒˆãƒªãƒ¼ãƒ å†ç”Ÿã€ã¾ãŸã¯ã‚ューã«å…¥ã‚Œã¦ã€ãã—ã¦å†ç”Ÿé€Ÿåº¦ã®èª¿æ•´ã€ãƒãƒ£ãƒ—ターã®ã‚µãƒãƒ¼ãƒˆã€ã‚¹ãƒªãƒ¼ãƒ—タイマーã§å¥½ããªã‚ˆã†ã«æ¥½ã—ã‚“ã§ãã ã•ã„。Flattrçµ±åˆã§ã‚³ãƒ³ãƒ†ãƒ³ãƒ„作æˆè€…ã«ã‚ãªãŸã®æ„›ã‚’示ã™ã“ã¨ãŒã§ãã¾ã™ã€‚ ãƒãƒƒãƒ‰ã‚ャスト愛好家ãŒä½œæˆã—㟠AntennaPod ã¯ã™ã¹ã¦ã®æ„味ã§ãƒ•ãƒªãƒ¼è‡ªç”±ã§ã™: オープンソースã€ã‚³ã‚¹ãƒˆä¸è¦ã€åºƒå‘Šã¯ã‚ã‚Šã¾ã›ã‚“。 @@ -14,32 +12,32 @@ AntennaPodã¯ã€ç‹¬è‡ªã®ãƒãƒƒãƒ‰ã‚ャスターã‹ã‚‰ã€BBCã€NPRã€CNNãªã©ã • ページフィードをã”利用ãã ã•ã„ (www.podlove.org/paged-feeds) 記録ã€å…±æœ‰ & æ„Ÿè¬<br> -• エピソードをãŠæ°—ã«å…¥ã‚Šã¨ã—ã¦ãƒžãƒ¼ã‚¯ã—ã¦ã€ä¸€ç•ªã®ä¸ã®ä¸€ç•ªã‚’記録ã—ã¦ãã ã•ã„<br> +• エピソードをãŠæ°—ã«å…¥ã‚Šã¨ã—ã¦ãƒžãƒ¼ã‚¯ã—ã¦ã€ä¸€ç•ªã®ä¸ã®ä¸€ç•ªã‚’ä¿å˜ã—ã¦ãã ã•ã„<br> • å†ç”Ÿå±¥æ´ã‹ã‚‰ã€ã¾ãŸã¯æ¤œç´¢ (タイトルã¨ã‚·ãƒ§ãƒ¼ãƒŽãƒ¼ãƒˆ) ã—ã¦ç›®çš„ã®ã‚¨ãƒ”ソードを見ã¤ã‘ã¦ãã ã•ã„<br> • 高度ãªã‚½ãƒ¼ã‚·ãƒ£ãƒ«ãƒ¡ãƒ‡ã‚£ã‚¢ã¨ãƒ¡ãƒ¼ãƒ«ã‚ªãƒ—ションã€gPodder.netサービスã€OPMLエクスãƒãƒ¼ãƒˆã‹ã‚‰ã‚¨ãƒ”ソードやフィードを共有ã—ã¦ãã ã•ã„<br> • 自動Flattrã‚’å«ã‚€Flattrã®çµ±åˆã§ã‚³ãƒ³ãƒ†ãƒ³ãƒ„クリエイターをサãƒãƒ¼ãƒˆã—ã¾ã™ システムã®ã‚³ãƒ³ãƒˆãƒãƒ¼ãƒ« -• 自動ダウンãƒãƒ¼ãƒ‰ã®åˆ¶å¾¡: フィードをé¸æŠžã€ã‚ーワードã«åŸºã¥ã„ã¦ã‚¨ãƒ”ソードをフィルターã€ãƒ¢ãƒã‚¤ãƒ«ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚’除外ã€ç‰¹å®šã®WiFiãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚’é¸æŠžã€é›»è©±ã‚’å……é›»ã™ã‚‹å¿…è¦æ€§ã€æ™‚間や間隔をè¨å®š<br> +• 自動ダウンãƒãƒ¼ãƒ‰ã®åˆ¶å¾¡: フィードをé¸æŠžã€ãƒ¢ãƒã‚¤ãƒ«ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚’除外ã€ç‰¹å®šã®WiFiãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚’é¸æŠžã€é›»è©±ã‚’å……é›»ã™ã‚‹å¿…è¦ã€æ™‚間や間隔をè¨å®š<br> • ã‚ャッシュã•ã‚Œã‚‹ã‚¨ãƒ”ソードã®é‡ã®è¨å®šã€ã‚¹ãƒžãƒ¼ãƒˆå‰Šé™¤ (ãŠæ°—ã«å…¥ã‚Šã‚„プレイ状æ³ã«åŸºã¥ã„ã¦) ã¨ã€ãŠå¥½ã¿ã®å ´æ‰€ã‚’é¸æŠžã—ã¦ã€ã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸ã‚’管ç†ã—ã¾ã™<br> • AntennaPod ã‚’ã‚ãªãŸã®è¨€èªžã§ã”利用ãã ã•ã„ (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> • ライトã¨ãƒ€ãƒ¼ã‚¯ テーマを使用ã—ã¦ç’°å¢ƒã«é©å¿œã—ã¾ã™<br> • gPodder.netçµ±åˆã¨OPMLã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã§ã€è³¼èªã‚’ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—ã—ã¾ã™ -<b>AntennaPod ã®ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ã«å‚åŠ ã—ã¦ãã ã•ã„!</b> +<b>AntennaPod ã®ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ã«å‚åŠ ã—ã¦ãã ã•ã„!</b><br> AntennaPod ã¯ãƒœãƒ©ãƒ³ãƒ†ã‚£ã‚¢ã«ã‚ˆã£ã¦æ´»ç™ºã«é–‹ç™ºä¸ã§ã™ã€‚コードやコメントã§ã€ã‚ãªãŸã‚‚も貢献ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™! -Twitterã§è³ªå•ã‚„ã€ãƒ•ã‚£ãƒ¼ãƒ‰ãƒãƒƒã‚¯ã‚’ã—ã¦ãã ã•ã„: -https://twitter.com/@AntennaPod +GitHubã¯ã€æ©Ÿèƒ½ã®ãƒªã‚¯ã‚¨ã‚¹ãƒˆã€ãƒã‚°ã®å ±å‘Šã€ã‚³ãƒ¼ãƒ‰ã®è²¢çŒ®ã®ãŸã‚ã®å ´æ‰€ã§ã™:<br> +https://www.github.com/AntennaPod/AntennaPod -ç§ãŸã¡ã®Googleグループã§ã€ã‚ãªãŸã®ã‚¢ã‚¤ãƒ‡ã‚¢ã€ãŠæ°—ã«å…¥ã‚Šã®ãƒãƒƒãƒ‰ã‚ャスティングモーメントã€æ„Ÿè¬ã‚’ã€ã™ã¹ã¦ã®ãƒœãƒ©ãƒ³ãƒ†ã‚£ã‚¢ã¨å…±æœ‰ã—ã¦ãã ã•ã„: +ç§ãŸã¡ã®Googleグループã¯ã€ã‚ãªãŸã®ã‚¢ã‚¤ãƒ‡ã‚¢ã€ãŠæ°—ã«å…¥ã‚Šã®ãƒãƒƒãƒ‰ã‚ャスティングモーメントã€æ„Ÿè¬ã‚’ã€ã™ã¹ã¦ã®ãƒœãƒ©ãƒ³ãƒ†ã‚£ã‚¢ã¨å…±æœ‰ã™ã‚‹ãŸã‚ã®å ´æ‰€ã§ã™:<br> https://groups.google.com/forum/#!forum/antennapod -Transifexã§ã‚ãªãŸã®æ¯å›½èªžã¸ã®ã‚¢ãƒ—リã®ç¿»è¨³ã‚’手ä¼ã£ã¦ãã ã•ã„: -https://www.transifex.com/antennapod/antennapod +質å•ã‚„ã€ç§ãŸã¡ã¸ã®ãƒ•ã‚£ãƒ¼ãƒ‰ãƒãƒƒã‚¯ãŒã‚ã‚Šã¾ã›ã‚“ã‹? +https://twitter.com/@AntennaPod -ç§ãŸã¡ã®ãƒ™ãƒ¼ã‚¿ãƒ†ã‚¹ãƒˆãƒ—ãƒã‚°ãƒ©ãƒ ã‚’ãƒã‚§ãƒƒã‚¯ã—ã¦ã€æœ€æ–°æ©Ÿèƒ½ã‚’最åˆã«å…¥æ‰‹ã—ã¦ãã ã•ã„: -https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod +Transifexã¯ç¿»è¨³ã‚’支æ´ã™ã‚‹ãŸã‚ã®å ´æ‰€ã§ã™:<br> +https://www.transifex.com/antennapod/antennapod -GitHubを訪å•ã—ã¦ã€æ©Ÿèƒ½ã®ãƒªã‚¯ã‚¨ã‚¹ãƒˆã€ãƒã‚°ã®å ±å‘Šã€ã‚³ãƒ¼ãƒ‰ã®è²¢çŒ®ã‚’ã—ã¦ãã ã•ã„: -https://www.github.com/AntennaPod/AntennaPod
\ No newline at end of file +ç§ãŸã¡ã®ãƒ™ãƒ¼ã‚¿ãƒ†ã‚¹ãƒˆãƒ—ãƒã‚°ãƒ©ãƒ ã‚’ãƒã‚§ãƒƒã‚¯ã—ã¦ã€æœ€æ–°æ©Ÿèƒ½ã‚’最åˆã«å…¥æ‰‹ã—ã¦ãã ã•ã„:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/ja.md b/app/src/main/play/ja/whatsnew index 79e6fb005..79e6fb005 100644 --- a/changelog/ja.md +++ b/app/src/main/play/ja/whatsnew diff --git a/app/src/main/play/kn_IN/listing/fulldescription b/app/src/main/play/kn_IN/listing/fulldescription new file mode 100644 index 000000000..87b477fdc --- /dev/null +++ b/app/src/main/play/kn_IN/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> +But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. + +Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. + +<b>All features:</b><br> +IMPORT, ORGANIZE AND PLAY<br> +• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> +• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> +• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> +• Access password-protected feeds and episodes<br> +• Take advantage of paged feeds (www.podlove.org/paged-feeds) + +KEEP TRACK, SHARE & APPRECIATE<br> +• Keep track of the best of the best by marking episodes as favourites<br> +• Find that one episode through the playback history or by searching (titles and shownotes)<br> +• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> +• Support content creators with Flattr integration including automatic flattring + +CONTROL THE SYSTEM<br> +• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> +• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> +• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adapt to your environment using the light and dark theme<br> +• Back-up your subscriptions with the gPodder.net integration and OPML export + +<b>Join the AntennaPod community!</b><br> +AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! + +GitHub is the place to go for feature requests, bug reports and code contributions:<br> +https://www.github.com/AntennaPod/AntennaPod + +Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> +https://groups.google.com/forum/#!forum/antennapod + +Have a question or want to give us feedback? +https://twitter.com/@AntennaPod + +Transifex is the place to help with translations:<br> +https://www.transifex.com/antennapod/antennapod + +Check out our Beta Testing programme to get the latest features first:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/kn_IN.md b/app/src/main/play/kn_IN/whatsnew index 8f2618b8f..8f2618b8f 100644 --- a/changelog/kn_IN.md +++ b/app/src/main/play/kn_IN/whatsnew diff --git a/app/src/main/play/ko-KR/listing/fulldescription b/app/src/main/play/ko-KR/listing/fulldescription new file mode 100644 index 000000000..7f04d4e7b --- /dev/null +++ b/app/src/main/play/ko-KR/listing/fulldescription @@ -0,0 +1,20 @@ +ì•ˆí…Œë‚˜íŒŸì€ ì˜¤í”ˆì†ŒìŠ¤ 팟ìºìŠ¤íŠ¸ 관리 프로그램입니다. 안드로ì´ë“œ 2.2.3 ì´ìƒì—ì„œ ë™ìž‘합니다. ì—í”¼ì†Œë“œì˜ ìŠ¤íŠ¸ë¦¬ë° ë° ë‹¤ìš´ë¡œë“œ, ìžë™ìœ¼ë¡œ 피드를 새로 확ì¸í•˜ê³ ë‚˜ì¤‘ì— ë“¤ì„ ìˆ˜ 있게 ëŒ€ê¸°ì—´ì— ì¶”ê°€í•˜ëŠ” 등 팟ìºìŠ¤íŠ¸ 프로그램ì—ì„œ ìƒê°í• 수 있는 ëª¨ë“ ê¸°ë³¸ ê¸°ëŠ¥ì„ ì§€ì›í•©ë‹ˆë‹¤. ë˜ ì•ˆí…Œë‚˜íŒŸ 앱 안ì—ì„œ 팟ìºìŠ¤íŠ¸ì— 대해 Flattr 기부 ê¸°ëŠ¥ì„ ì‚¬ìš©í• ìˆ˜ 있습니다. + +지금까지 ë‹¤ìŒ ê¸°ëŠ¥ì´ êµ¬í˜„ë˜ì—ˆìŠµë‹ˆë‹¤: + +* ì—피소드 다운로드 ë° ìŠ¤íŠ¸ë¦¬ë° +* 여러가지 ë°°ì† ìž¬ìƒ(Presto 사운드 ë¼ì´ë¸ŒëŸ¬ë¦¬ ë˜ëŠ” Prestissimo í•„ìš”) +* Atom ë° RSS 피드 ì§€ì› +* 암호로 ë³´í˜¸ëœ í”¼ë“œì™€ ì—피소드 ì§€ì› +* iTunes ëª©ë¡ ê²€ìƒ‰ 기능 +* OPML ê°€ì ¸ì˜¤ê¸° ë° ë‚´ë³´ë‚´ê¸° +* Flattr 통합, ìžë™ìœ¼ë¡œ Flattr하기 기능 í¬í•¨ +* 홈스í¬ë¦° ìž¬ìƒ ìœ„ì ¯ +* 검색 +* ìžë™ 피드 ì—…ë°ì´íŠ¸ +* 새 ì—피소드 ìžë™ 다운로드 +* 취침 타ì´ë¨¸ +* gpodder.net 팟ìºìŠ¤íŠ¸ ë””ë ‰í„°ë¦¬ 찾아보기 +* gpodder.net 서비스와 êµ¬ë… ì •ë³´ ë™ê¸°í™” +* MP3 챕터, VorbisComment 챕터, Podlove Simple Chapters 기능 +* 페ì´ì§€ 피드 (http://podlove.org/paged-feeds/) 지ì›
\ No newline at end of file diff --git a/app/src/main/play/ko-KR/listing/shortdescription b/app/src/main/play/ko-KR/listing/shortdescription new file mode 100644 index 000000000..9baa9eb11 --- /dev/null +++ b/app/src/main/play/ko-KR/listing/shortdescription @@ -0,0 +1 @@ +안드로ì´ë“œìš© 오픈소스 팟ìºìŠ¤íŠ¸ 관리 앱
\ No newline at end of file diff --git a/app/src/main/play/ko-KR/listing/title b/app/src/main/play/ko-KR/listing/title new file mode 100644 index 000000000..31552f353 --- /dev/null +++ b/app/src/main/play/ko-KR/listing/title @@ -0,0 +1 @@ +AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/ko-KR/listing/video b/app/src/main/play/ko-KR/listing/video new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/app/src/main/play/ko-KR/listing/video diff --git a/app/src/main/play/ko-KR/whatsnew b/app/src/main/play/ko-KR/whatsnew new file mode 100644 index 000000000..a65bddbbb --- /dev/null +++ b/app/src/main/play/ko-KR/whatsnew @@ -0,0 +1,11 @@ +* New features: + * Subscription overview + * Proxy support + * Statistics + * Manual gpodder.net sync +* Fixes: + * Audioplayer controls + * Audio ducking + * Video control fade-out + * External media controls + * Feed parsing
\ No newline at end of file diff --git a/description/ko.txt b/app/src/main/play/ko/listing/fulldescription index 566c0f289..65f20d943 100644 --- a/description/ko.txt +++ b/app/src/main/play/ko/listing/fulldescription @@ -1,6 +1,4 @@ -사용하기 ì‰½ê³ ìœ ì—°í•˜ê³ ì˜¤í”ˆì†ŒìŠ¤ì¸ íŒŸìºìŠ¤íŠ¸ 관리 ë° í”Œë ˆì´ì–´ - -ì•ˆí…Œë‚˜íŒŸì„ ì‚¬ìš©í•´ 소규모 ë…립 ì œìž‘ìžë“¤ë¶€í„° BBC, NPR, CNN ë“±ì˜ ëŒ€í˜• ì–¸ë¡ ì‚¬ê¹Œì§€ ìˆ˜ë§Žì€ ë¬´ë£Œ ë° ìœ ë£Œ 팟ìºìŠ¤íŠ¸ì— ì ‘ê·¼í• ìˆ˜ 있습니다. iTunes 팟ìºìŠ¤íŠ¸ ë°ì´í„°ë² ì´ìŠ¤, OPML 파ì¼, RSS 주소를 사용해 팟ìºìŠ¤íŠ¸ 피드를 간편하게 ì¶”ê°€í•˜ê³ ë‚´ë³´ë‚´ê³ ê°€ì ¸ì˜¬ 수 있습니다. ê°•ë ¥í•œ ìžë™ 다운로드 ì œì–´(íŠ¹ì • 시간 간격 ë° Wi-Fi ë„¤íŠ¸ì›Œí¬ ì§€ì •)와 ì‚ì œ ì œì–´(ì¦ê²¨ì°¾ê¸° ë° ì§€ì—° ì„¤ì •ì— ê¸°ë°˜í•œ)를 통해 편리하게 배터리와 ëª¨ë°”ì¼ ë°ì´í„° ì‚¬ìš©ëŸ‰ì„ ì¤„ì´ì„¸ìš”. +ì•ˆí…Œë‚˜íŒŸì„ ì‚¬ìš©í•´ 소규모 ë…립 ì œìž‘ìžë“¤ë¶€í„° BBC, NPR, CNN ë“±ì˜ ëŒ€í˜• ì–¸ë¡ ì‚¬ê¹Œì§€ ìˆ˜ë§Žì€ ë¬´ë£Œ ë° ìœ ë£Œ 팟ìºìŠ¤íŠ¸ì— ì ‘ê·¼í• ìˆ˜ 있습니다. iTunes 팟ìºìŠ¤íŠ¸ ë°ì´í„°ë² ì´ìŠ¤, OPML 파ì¼, RSS 주소를 사용해 팟ìºìŠ¤íŠ¸ 피드를 간편하게 ì¶”ê°€í•˜ê³ ë‚´ë³´ë‚´ê³ ê°€ì ¸ì˜¬ 수 있습니다. ê°•ë ¥í•œ ìžë™ 다운로드 ì œì–´(íŠ¹ì • 시간 간격 ë° Wi-Fi ë„¤íŠ¸ì›Œí¬ ì§€ì •)와 ì‚ì œ ì œì–´(ì¦ê²¨ì°¾ê¸° ë° ì§€ì—° ì„¤ì •ì— ê¸°ë°˜í•œ)를 통해 편리하게 배터리와 ëª¨ë°”ì¼ ë°ì´í„° ì‚¬ìš©ëŸ‰ì„ ì¤„ì´ì„¸ìš”.<br> 하지만 가장 중요한 기능ì€: ì—피소드를 다운로드하거나 스트리ë°í•˜ê±°ë‚˜ ëŒ€ê¸°ì—´ì„ ë§Œë“¤ê³ , ìž¬ìƒ ì†ë„ ì¡°ì ˆ, 챕터 지ì›, 취침 타ì´ë¨¸ë¥¼ 통해 ì›í•˜ëŠ”대로 ì¦ê¸¸ 수 있다는 ì 입니다. ë‚´ìž¥ëœ Flattr 지ì›ì„ 통해 팟ìºìŠ¤íŠ¸ ì œìž‘ìžë“¤ì—게 호ì‘ì„ ë³´ë‚¼ ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤. 팟ìºìŠ¤íŠ¸ ì• í˜¸ê°€ì— ì˜í•´ 만들어진, ì•ˆí…Œë‚˜íŒŸì€ ëª¨ë“ ë©´ì—ì„œ ìžìœ ë¡ìŠµë‹ˆë‹¤: 소스 코드가 공개ë˜ì–´ ìžˆê³ , 무료ì¸ë°ë‹¤ê°€ ê´‘ê³ ë„ ì—†ìŠµë‹ˆë‹¤. @@ -35,6 +33,9 @@ https://www.github.com/AntennaPod/AntennaPod 구글 그룹ì—ì„œ ì•„ì´ë””어와 ì¢‹ì€ íŒŸìºìŠ¤íŠ¸ë¥¼ ê³µìœ í•˜ê³ ëª¨ë“ ì§€ì›ìžë“¤ì—게 ê°ì‚¬í• 수 있습니다:<br> https://groups.google.com/forum/#!forum/antennapod +ì§ˆë¬¸ì´ ìžˆìœ¼ì‹ ê°€ìš”? 아니면 ì˜ê²¬ì´ ìžˆìœ¼ì‹ ê°€ìš”? +https://twitter.com/@AntennaPod + Transifexì—ì„œ 번ì—ì„ ë„울 수 있습니다:<br> https://www.transifex.com/antennapod/antennapod diff --git a/changelog/ko.md b/app/src/main/play/ko/whatsnew index 6149e9f23..6149e9f23 100644 --- a/changelog/ko.md +++ b/app/src/main/play/ko/whatsnew diff --git a/app/src/main/play/ko_KR/listing/fulldescription b/app/src/main/play/ko_KR/listing/fulldescription new file mode 100644 index 000000000..87b477fdc --- /dev/null +++ b/app/src/main/play/ko_KR/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> +But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. + +Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. + +<b>All features:</b><br> +IMPORT, ORGANIZE AND PLAY<br> +• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> +• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> +• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> +• Access password-protected feeds and episodes<br> +• Take advantage of paged feeds (www.podlove.org/paged-feeds) + +KEEP TRACK, SHARE & APPRECIATE<br> +• Keep track of the best of the best by marking episodes as favourites<br> +• Find that one episode through the playback history or by searching (titles and shownotes)<br> +• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> +• Support content creators with Flattr integration including automatic flattring + +CONTROL THE SYSTEM<br> +• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> +• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> +• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adapt to your environment using the light and dark theme<br> +• Back-up your subscriptions with the gPodder.net integration and OPML export + +<b>Join the AntennaPod community!</b><br> +AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! + +GitHub is the place to go for feature requests, bug reports and code contributions:<br> +https://www.github.com/AntennaPod/AntennaPod + +Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> +https://groups.google.com/forum/#!forum/antennapod + +Have a question or want to give us feedback? +https://twitter.com/@AntennaPod + +Transifex is the place to help with translations:<br> +https://www.transifex.com/antennapod/antennapod + +Check out our Beta Testing programme to get the latest features first:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/ko_KR.md b/app/src/main/play/ko_KR/whatsnew index 8f2618b8f..8f2618b8f 100644 --- a/changelog/ko_KR.md +++ b/app/src/main/play/ko_KR/whatsnew diff --git a/app/src/main/play/lt/listing/fulldescription b/app/src/main/play/lt/listing/fulldescription new file mode 100644 index 000000000..3f9f50a90 --- /dev/null +++ b/app/src/main/play/lt/listing/fulldescription @@ -0,0 +1,43 @@ +„AntennaPod“ yra tinklalaidžių tvarkytuvÄ— ir leistuvÄ—, įgalinanti momentinÄ™ prieigÄ… prie milijonų nemokamų bei mokamų tinklalaidžių, nuo nepriklausomų tinklalaidžių kÅ«rÄ—jų iki didžiųjų leidyklų, tokių kaip „BBC“, „NPR“ ir „CNN“. Be vargo pridÄ—kite, importuokite ir eksportuokite jų sklaidos kanalus naudodamiesi „iTunes“ tinklalaidžių duomenų baze, OPML failais ar tiesiogiai iÅ¡ RSS kanalo adreso. Sutaupykite laiko, baterijos energijos ir suvartojamų mobiliųjų duomenų iÅ¡naudodami galingas automatinio epizodų atsiuntimo priemones (nurodykite atsiuntimo metÄ…, laiko intervalÄ… ir belaidžius tinklus) ir iÅ¡trindami epizodus (remiantis mÄ—giamųjų sÄ…raÅ¡u ir laikymo nustatymais).<br> +Bet svarbiausia: atsisiųskite, klausykitÄ—s iÅ¡ karto ar pridÄ—kite epizodus į eilÄ™ ir mÄ—gaukitÄ—s jais pasirinkdami atkÅ«rimo spartÄ…, naudodamiesi skyrių palaikymu bei miego laikmaÄiu. JÅ«s netgi galite iÅ¡reikÅ¡ti savo meilÄ™ turinio kÅ«rÄ—jams naudodamiesi mÅ«sų „Flattr“ integracija. + +Sukurtas tinklalaidžių entuziasto, „AntennaPod“ yra laisvas visomis Å¡io žodžio prasmÄ—mis: atvirojo kodo, jokių mokesÄių, jokių reklamų. + +<b>Visos funkcijos:</b><br> +IMPORTUOKITE, TVARKYKITE BEI KLAUSYKITÄ–S<br> +• PridÄ—kite bei importuokite sklaidos kanalus iÅ¡ „iTunes“ bei „gPodder.net“ paslaugų, OPML failų ir RSS ar Atom nuorodų<br> +• Valdykite atkÅ«rimÄ… bet kur: pradžios ekrano valdyklyje, programos praneÅ¡imuose, ausinių ar „Bluetooth“ valdikliu<br> +• MÄ—gaukitÄ—s klausydamiesi taip, kaip Jums patinka, naudodamiesi derinama atkÅ«rimo sparta, skyrių palaikymu (MP3, „VorbisComment“ ir „Podlove“), iÅ¡saugota paskutinio atkÅ«rimo pozicija ir miego laikmaÄiu (mažinamas garsis bei lÄ—tinama atkÅ«rimo sparta, pakraÄius nustatomas iÅ¡ naujo)<br> +• Pasiekite slaptažodžiu apsaugotus sklaidos kanalus bei epizodus<br> +• IÅ¡naudokite puslapiuotus sklaidos kanalus (www.podlove.org/paged-feeds) + +STEBÄ–KITE, DALINKITÄ–S IR MÄ–GAUKITÄ–S<br> +• Kaupkite geriausius iÅ¡ geriausiųjų pažymÄ—dami epizodus kaip mÄ—gstamiausius<br> +• Raskite tÄ… vienintelį epizodÄ… naudodamiesi atkÅ«rimo istorija arba paieÅ¡ka (pavadinimuose ir laidų užraÅ¡uose)<br> +• DalinkitÄ—s epizodais bei sklaidos kanalais per socialinius tinklus, el. paÅ¡tu, „gPodder.net“ paslaugÄ… bei eksportuotus OPML failus<br> +• Remkite turinio kÅ«rÄ—jus naudodamiesi „Flattr“ integracija bei automatiniu rÄ—mimu + +VALDYKITE SISTEMÄ„<br> +• Valdykite automatinį atsiuntimÄ…: pasirinkite sklaidos kanalus, neleiskite atsiuntimų mobiliuoju duomenų ryÅ¡iu, apibrėžkite leidžiamus belaidžio ryÅ¡io tinklus, reikalaukite, jog atsiuntimai bÅ«tų vykdomi telefono įkrovos metu ir nurodykite atsiuntimų dienos metÄ… ar intervalÄ…<br> +• Valdykite atmintinÄ—s naudojimÄ… nurodydami podÄ—lyje laikomų epizodų kiekį, iÅ¡manų iÅ¡trynimÄ… (remiantis atkÅ«rimo bÅ«sena bei mÄ—giamųjų sÄ…raÅ¡u) ir nurodykite saugojimo vietÄ…<br> +• NaudokitÄ—s „AntennaPod“ savo kalba (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH, LT)<br> +• Pritaikykite savo aplinkai pasirinkdami Å¡viesiÄ… arba tamsiÄ… temÄ…<br> +• Sukurkite savo prenumeratų atsarginÄ™ kopijÄ… pasinaudodami „gPodder.net“ integracija arba OPML eksportu + +<b>Prisijunkite prie AntennaPod bendruomenÄ—s!</b><br> +„AntennaPod“ aplikacijÄ… aktyviai vysto savanoriai. JÅ«s taip pat galite prisidÄ—ti, nuo atsiliepimų iki programinio kodo! + +„GitHub“ yra ta vieta, kur galite pageidauti naujų funkcijų, praneÅ¡ti apie riktÄ… arba prisidÄ—ti programiniu kodu:<br> +https://www.github.com/AntennaPod/AntennaPod + +MÅ«sų „Google“ grupÄ— yra puiki vieta pasidalinti idÄ—jomis, mÄ—gstamiausiais tinklalaidžių sklaidos momentais ar iÅ¡reikÅ¡ti padÄ—kÄ… visiems savanoriams:<br> +https://groups.google.com/forum/#!forum/antennapod + +Turite klausimų ar norite palikti atsiliepimÄ…? +https://twitter.com/@AntennaPod + +„Transifex“ yra ta vieta, kur galite prisidÄ—ti prie aplikacijos vertimo:<br> +https://www.transifex.com/antennapod/antennapod + +IÅ¡bandykite mÅ«sų Beta Testavimo programÄ…, jei norite pirmieji gauti naujausias funkcijas:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/nb/listing/fulldescription b/app/src/main/play/nb/listing/fulldescription new file mode 100644 index 000000000..87b477fdc --- /dev/null +++ b/app/src/main/play/nb/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> +But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. + +Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. + +<b>All features:</b><br> +IMPORT, ORGANIZE AND PLAY<br> +• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> +• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> +• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> +• Access password-protected feeds and episodes<br> +• Take advantage of paged feeds (www.podlove.org/paged-feeds) + +KEEP TRACK, SHARE & APPRECIATE<br> +• Keep track of the best of the best by marking episodes as favourites<br> +• Find that one episode through the playback history or by searching (titles and shownotes)<br> +• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> +• Support content creators with Flattr integration including automatic flattring + +CONTROL THE SYSTEM<br> +• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> +• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> +• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adapt to your environment using the light and dark theme<br> +• Back-up your subscriptions with the gPodder.net integration and OPML export + +<b>Join the AntennaPod community!</b><br> +AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! + +GitHub is the place to go for feature requests, bug reports and code contributions:<br> +https://www.github.com/AntennaPod/AntennaPod + +Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> +https://groups.google.com/forum/#!forum/antennapod + +Have a question or want to give us feedback? +https://twitter.com/@AntennaPod + +Transifex is the place to help with translations:<br> +https://www.transifex.com/antennapod/antennapod + +Check out our Beta Testing programme to get the latest features first:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/nb.md b/app/src/main/play/nb/whatsnew index 8f2618b8f..8f2618b8f 100644 --- a/changelog/nb.md +++ b/app/src/main/play/nb/whatsnew diff --git a/description/nb_NO.txt b/app/src/main/play/nb_NO/listing/fulldescription index e8edc03c1..11bc6fd9f 100644 --- a/description/nb_NO.txt +++ b/app/src/main/play/nb_NO/listing/fulldescription @@ -1,6 +1,4 @@ -En podcast-behandler for Android basert pÃ¥ Ã¥pen kildekode. - -AntennaPod er en podkast-behandler og -spiller som gir deg umiddelbar tilgang til millioner av gratis og betalte podkaster, fra uavhengige podkastere til store forlagshus som BBC, NPR og CNN. Legg til, importer og eksporter deres strømmer uten problemer ved hjelp av iTunes' podkast-database, OPML-filer eller enkle RSS URLer. Spar anstrengelser, batterikapasitet og mobildata-bruk med kraftfulle automatiseringskontroller for nedlasting av episoder (spesifiser tider, intervaller og WiFi-nettverk) og sletting av episoder (basert pÃ¥ dine favoritter og delay-instillinger).<br> +AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> Men viktigst av alt: Last ned, strøm eller legg episoder i kø og nyt dem slik du ønsker med regulerbar avspillingshasitghet, kapittelstøtte og en tidtaker for automatisk avslÃ¥ing. Du kan til og med vise din takknemlighet til innholdets skapere med vÃ¥r Flattr-integrasjon. Laget av podkast-entusiaster er AntennaPod gratis i ordets rette forstand: Ã¥pen kildekode, ingen kostnader, ingen reklame. @@ -14,29 +12,32 @@ IMPORTER, ORGANISER OG SPILL AV<br> • Støtte for «paged feeds» (www.podlove.org/paged-feeds) FØLG MED, DEL OG SETT PRIS PÃ…<br> -• Følg med pÃ¥ det beste av det beste ved Ã¥ markere episoder som favoritter<br> +• Keep track of the best of the best by marking episodes as favourites<br> • Find den ene episoden gjennom avspillingshistorien eller ved Ã¥ søke (titler og shownotater)<br> • Del episoder og strømmer gjennom avanserte sosiale medier- og e-postinstillinger, gPodder.net-tjenester og via OPML-eksportering<br> • Støtt innholdsskapere med Flattr-integrasjon gjennom automatisk «flattring» KONTROLLER SYSTEMET<br> -• Ta kontroll over automatisk nedlasting: velg strømmer, ekskluder mobile nettverk, velg spesifikke WiFi-nettverk, krev av telefonen er til lading og sett klokkeslett eller intervaller<br> -• Behandle lagring ved Ã¥ sette en øvre grense for «cachede» episoder, smart sletting (basert pÃ¥ dine favoritter og avspillingsstatus) og velg din foretrukne lokasjon<br> +• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> +• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> • Bruk AntennaPod i ditt sprÃ¥k (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> • Tilpass appens stil ved Ã¥ bruke det mørke eller lyse temaet<br> • Lag back-up av dine abonnement med gPodder.net-integrasjon og OPML-eksport -<b>Bli med i AntennaPod-samfunnet!</b></br> +<b>Join the AntennaPod community!</b><br> AntennaPod er under aktiv utvikling av frivillige. Du kan ogsÃ¥ bidra, med kode eller kommentarer! -GitHub er stedet Ã¥ gÃ¥ for Ã¥ etterspørre funksjoner, feilrapportering og kodebidrag:<br> +GitHub is the place to go for feature requests, bug reports and code contributions:<br> https://www.github.com/AntennaPod/AntennaPod -VÃ¥r Google Gruppe er stedet for Ã¥ dele dine ideer, dine podkast-favorittøyeblikk og din takknemlighet til alle frivillige:<br> +Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> https://groups.google.com/forum/#!forum/antennapod -Transifex er stedet for Ã¥ hjelpe til med oversettelser:<br> +Have a question or want to give us feedback? +https://twitter.com/@AntennaPod + +Transifex is the place to help with translations:<br> https://www.transifex.com/antennapod/antennapod -Sjekk ut vÃ¥rt Betatesting-program for Ã¥ fÃ¥ de siste funksjonene først:<br> +Check out our Beta Testing programme to get the latest features first:<br> https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/nb_NO.md b/app/src/main/play/nb_NO/whatsnew index 9fd15b2f8..9fd15b2f8 100644 --- a/changelog/nb_NO.md +++ b/app/src/main/play/nb_NO/whatsnew diff --git a/app/src/main/play/nl-NL/listing/fulldescription b/app/src/main/play/nl-NL/listing/fulldescription new file mode 100644 index 000000000..52a2d4337 --- /dev/null +++ b/app/src/main/play/nl-NL/listing/fulldescription @@ -0,0 +1,20 @@ +AntennaPod is een open-source podcast manager voor Android 2.3.3 en hoger. Het biedt alle basisfuncties die u verwacht van een podcatcher, zoals streaming en downloaden van episodes, alle feeds automatisch verversen of episodes aan een wachtrij toevoegen om ze later te luisteren. Bovendien laat AntennaPod je podcasts en afleveringen vanuit de app flattr'en. + +So far the following features are implemented: + +* Episodes downloaden en streamen +* Variabele afspeelsnelheid (vereist Presto Sound Library of Prestissimo) +* Support voor Atom en RSS feeds +* Ondersteuning voor wachtwoord-beveiligde feeds en afleveringen +* Support for searching iTunes listings +* OPML import en export +* Flattr integration including automatic flattring +* Homescreen widget voor de player +* Zoekfunctie +* Automatische feed updates +* Automatisch downloaden van nieuwe episodes +* Sleep timer +* Toegang tot de gpodder.net podcast gids +* Abonnementen synchroniseren met de gpodder.net dienst +* Supports MP3 chapters, VorbisComment chapters and Podlove Simple Chapters +* Supports paged feeds (http://podlove.org/paged-feeds/)
\ No newline at end of file diff --git a/app/src/main/play/nl-NL/listing/shortdescription b/app/src/main/play/nl-NL/listing/shortdescription new file mode 100644 index 000000000..4eceefbb7 --- /dev/null +++ b/app/src/main/play/nl-NL/listing/shortdescription @@ -0,0 +1 @@ +Easy-to-use, flexible and open-source podcast manager and player
\ No newline at end of file diff --git a/app/src/main/play/nl-NL/listing/title b/app/src/main/play/nl-NL/listing/title new file mode 100644 index 000000000..31552f353 --- /dev/null +++ b/app/src/main/play/nl-NL/listing/title @@ -0,0 +1 @@ +AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/nl-NL/listing/video b/app/src/main/play/nl-NL/listing/video new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/app/src/main/play/nl-NL/listing/video diff --git a/app/src/main/play/nl-NL/whatsnew b/app/src/main/play/nl-NL/whatsnew new file mode 100644 index 000000000..a65bddbbb --- /dev/null +++ b/app/src/main/play/nl-NL/whatsnew @@ -0,0 +1,11 @@ +* New features: + * Subscription overview + * Proxy support + * Statistics + * Manual gpodder.net sync +* Fixes: + * Audioplayer controls + * Audio ducking + * Video control fade-out + * External media controls + * Feed parsing
\ No newline at end of file diff --git a/app/src/main/play/nl/listing/fulldescription b/app/src/main/play/nl/listing/fulldescription new file mode 100644 index 000000000..736a3f3a5 --- /dev/null +++ b/app/src/main/play/nl/listing/fulldescription @@ -0,0 +1,43 @@ +Met AntennaPod speel en beheer je al je podcasts en krijg je directe toegang tot duizenden gratis en betaalde podcasts - van onafhankelijke makers tot grote merken zoals BBC, CNN en NPO. Via de iTunes database, OPML-bestanden en simpele RSS-linkjes voeg je deze podcasts makkelijk toe. Dankzij simpele maar slimme automatische controle van het downloaden en verwijderen van afleveringen spaar je je batterij, hoef je je favoriete podcast niet meer handmatig te volgen en verbruik je geen onnodig mobiele data.<br> +Maar belangrijker: Met een handige wachtrij, aanpasbare afspeelsnelheden, ondersteuning van hoofdstukken en een slaap timer luister je naar podcasts op de manier die jij prettig vindt. Je kunt zelfs je liefde voor de makers uiten met onze Flattr-integratie. + +Gemaakt door podcast-enthousiastelingen, AntennaPod is vrij in de breedste zin van het woord: vrij van advertenties, open source en gratis. + +<b>Alle features:</b><br> +IMPORTEREN, ORGANISEREN, AFSPELEN<br> +• Voeg feeds toe via iTunes and gPodder.net database, OPML-bestanden and RSS of Atom linkjes<br> +• Beheer het afspelen overal: met een homescreen widget, in je Android meldingen en de knoppen op je koptelefoon en bluetooth-apparaat<br> +• Bepaal zelf hoe je luistert met aanpasbare afspeelsnelheden, ondersteuning van hoofdstukken (MP3, VorbisComment en Podlove), afspeelpositie voor elke aflevering en een handige 'slaap timer' (schudden om te resetten, volume langzaam zachter en herstel naar normale afspeelsnelheid)<br> +• Toegang tot wachtwoord-beveiligde podcasts en afleveringen<br> +• Doe je voordeel met 'paged feeds' (www.podlove.org/paged-feeds) + +DEEL & WAARDEER<br> +• Hou het beste van het beste bij door afleveringen als favoriet te markeren<br> +• Vindt die ene aflevering terug in de afspeelgeschiedenis of door te zoeken (in titels, shownotes en makers)<br> +• Deel podcasts en afleveringen via uitgebreide opties voor sociale media, WhatsApp, email en gPodder.net<br> +• Steun makers met Flattr-integratie, inclusief auto-Flattr + +HOUD DE CONTROLE +• Beheer automatische downloads: kies je podcasts, sluit mobiele netwerken uit, selecteer specifieke WiFi-verbindingen, eis dat de telefoon wordt opgeladen and bepaal tijden of intervals<br> +• Controleer geheugengebruik: stel een maximumaantal gedownloade afleveringen in, laat afleveringen automatisch verwijderen (maar sluit je favorieten en niet-afgespeelde afleveringen uit) en selecteer zelf je opslaglocatie<br> +• Gebruik AntennaPod in jouw taal: Nederlands! (Of in het Engels, Zweeds, Frans, Duits, Spaans, enz)<br> +• Voel je een kameleon: kies voor een licht of donker uiterlijk<br> +• Back-up je abonnementen via gPodder.net en geëxporteerde OPML-bestanden + +<b>Doe mee met de AntennaPod gemeenschap!</b><br> +AntennaPod wordt regelmatig geüpdatet door vrijwilligers. En jij kan ook helpen, met code of commentaar! + +GitHub is de beste plek voor foutmeldingen, verzoekjes voor nieuwe functies en bijdragen aan de code:<br> +https://www.github.com/AntennaPod/AntennaPod + +Onze Google Group is de beste plek om je ideeën, favoriete podcast-momenten en waardering naar alle vrijwilligers te delen:<br> +https://groups.google.com/forum/#!forum/antennapod + +Heb je een vraag of wil je feedback geven? +https://twitter.com/@AntennaPod + +Transifex is de beste plek om te helpen met vertalen:<br> +https://www.transifex.com/antennapod/antennapod + +Check het Beta Testprogramma om de laatste features als eerst te krijgen:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/nl.md b/app/src/main/play/nl/whatsnew index 9d61936eb..c9c0af69d 100644 --- a/changelog/nl.md +++ b/app/src/main/play/nl/whatsnew @@ -1,20 +1,20 @@ Changelog ========== -Version 1.6.0 +Versie 1.6.0 ------------- -* New features: - * Experimental Chromecast support - * Subscription overview - * Proxy support - * Statistics - * Manual gpodder.net sync -* Fixes: - * Audioplayer controls - * Audio ducking - * Video control fade-out - * External media controls - * Feed parsing +* Nieuwe functies: + * Experimentele Chromecast-ondersteuning + * Feeds overzicht + * Proxy-ondersteuning + * Statistieken + * Handmatige synchronisatie gpodder.net +* Foutoplossingen: + * Bediening audioplayer + * Ducking (verminderd volume bij oproepen) + * Fade-out van bedieningsknoppen video + * Externe bedieningsknoppen + * Parsen van feeds Versie 1.5.0 ------------- diff --git a/app/src/main/play/no/listing/fulldescription b/app/src/main/play/no/listing/fulldescription new file mode 100644 index 000000000..87b477fdc --- /dev/null +++ b/app/src/main/play/no/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> +But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. + +Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. + +<b>All features:</b><br> +IMPORT, ORGANIZE AND PLAY<br> +• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> +• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> +• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> +• Access password-protected feeds and episodes<br> +• Take advantage of paged feeds (www.podlove.org/paged-feeds) + +KEEP TRACK, SHARE & APPRECIATE<br> +• Keep track of the best of the best by marking episodes as favourites<br> +• Find that one episode through the playback history or by searching (titles and shownotes)<br> +• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> +• Support content creators with Flattr integration including automatic flattring + +CONTROL THE SYSTEM<br> +• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> +• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> +• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adapt to your environment using the light and dark theme<br> +• Back-up your subscriptions with the gPodder.net integration and OPML export + +<b>Join the AntennaPod community!</b><br> +AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! + +GitHub is the place to go for feature requests, bug reports and code contributions:<br> +https://www.github.com/AntennaPod/AntennaPod + +Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> +https://groups.google.com/forum/#!forum/antennapod + +Have a question or want to give us feedback? +https://twitter.com/@AntennaPod + +Transifex is the place to help with translations:<br> +https://www.transifex.com/antennapod/antennapod + +Check out our Beta Testing programme to get the latest features first:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/no.md b/app/src/main/play/no/whatsnew index 8f2618b8f..8f2618b8f 100644 --- a/changelog/no.md +++ b/app/src/main/play/no/whatsnew diff --git a/app/src/main/play/pl-PL/listing/fulldescription b/app/src/main/play/pl-PL/listing/fulldescription new file mode 100644 index 000000000..795addbc5 --- /dev/null +++ b/app/src/main/play/pl-PL/listing/fulldescription @@ -0,0 +1,20 @@ +AntennaPod jest menadżerem podcastów dla Androida 2.3.3 i nowszych na otwartej licencji. Oferuje wszystkie podstawowe funkcje których oczekuje się od podcathera, takie jak strumieniowanie oraz pobieranie odcinków, odświeżanie wszystkich wątków automatycznie i dodawanie ich do kolejki do późniejszego odsłuchania. Oprócz tego AntennaPod pozwala na flattr-owanie podcastów i odcinków z poziomu aplikacji. + +Dotychczas zostały wdrożone następujące funkcjonalności: + +* Pobieranie i strumieniowanie odcinków +* Zmienna prędkość odtwarzania (wymaga Presto Sound Library lub Prestissimo) +* Wsparcie dla wątków Atom i RSS +* Wsparcie dla kanałów i odcinków zabezpieczonych hasłem +* Support for searching iTunes listings +* Import i eksport OPML +Integracja z serwisem Flattr umożliwiająca flattring +* Widget odtwarzacza na home screen +* Wyszukiwanie +* Automatyczne aktualizaje wątków +* Automatyczne pobieranie nowych odcinków +* Timer snu +* Dostęp do katalogu podcastów na gpodder.net +* Synchronizację subskrypcji z gpodder.net +* Obsługuje rodziały MP3, VorbisComment i Podlove Simple. +* Wspiera stronicowane kanały (http://podlove.org/paged-feeds/)
\ No newline at end of file diff --git a/app/src/main/play/pl-PL/listing/shortdescription b/app/src/main/play/pl-PL/listing/shortdescription new file mode 100644 index 000000000..4eceefbb7 --- /dev/null +++ b/app/src/main/play/pl-PL/listing/shortdescription @@ -0,0 +1 @@ +Easy-to-use, flexible and open-source podcast manager and player
\ No newline at end of file diff --git a/app/src/main/play/pl-PL/listing/title b/app/src/main/play/pl-PL/listing/title new file mode 100644 index 000000000..31552f353 --- /dev/null +++ b/app/src/main/play/pl-PL/listing/title @@ -0,0 +1 @@ +AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/pl-PL/listing/video b/app/src/main/play/pl-PL/listing/video new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/app/src/main/play/pl-PL/listing/video diff --git a/app/src/main/play/pl-PL/whatsnew b/app/src/main/play/pl-PL/whatsnew new file mode 100644 index 000000000..a65bddbbb --- /dev/null +++ b/app/src/main/play/pl-PL/whatsnew @@ -0,0 +1,11 @@ +* New features: + * Subscription overview + * Proxy support + * Statistics + * Manual gpodder.net sync +* Fixes: + * Audioplayer controls + * Audio ducking + * Video control fade-out + * External media controls + * Feed parsing
\ No newline at end of file diff --git a/app/src/main/play/pl/listing/fulldescription b/app/src/main/play/pl/listing/fulldescription new file mode 100644 index 000000000..87b477fdc --- /dev/null +++ b/app/src/main/play/pl/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> +But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. + +Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. + +<b>All features:</b><br> +IMPORT, ORGANIZE AND PLAY<br> +• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> +• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> +• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> +• Access password-protected feeds and episodes<br> +• Take advantage of paged feeds (www.podlove.org/paged-feeds) + +KEEP TRACK, SHARE & APPRECIATE<br> +• Keep track of the best of the best by marking episodes as favourites<br> +• Find that one episode through the playback history or by searching (titles and shownotes)<br> +• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> +• Support content creators with Flattr integration including automatic flattring + +CONTROL THE SYSTEM<br> +• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> +• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> +• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adapt to your environment using the light and dark theme<br> +• Back-up your subscriptions with the gPodder.net integration and OPML export + +<b>Join the AntennaPod community!</b><br> +AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! + +GitHub is the place to go for feature requests, bug reports and code contributions:<br> +https://www.github.com/AntennaPod/AntennaPod + +Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> +https://groups.google.com/forum/#!forum/antennapod + +Have a question or want to give us feedback? +https://twitter.com/@AntennaPod + +Transifex is the place to help with translations:<br> +https://www.transifex.com/antennapod/antennapod + +Check out our Beta Testing programme to get the latest features first:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/pl.md b/app/src/main/play/pl/whatsnew index 8f2618b8f..8f2618b8f 100644 --- a/changelog/pl.md +++ b/app/src/main/play/pl/whatsnew diff --git a/app/src/main/play/pl_PL/listing/fulldescription b/app/src/main/play/pl_PL/listing/fulldescription new file mode 100644 index 000000000..c2c8cc597 --- /dev/null +++ b/app/src/main/play/pl_PL/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod jest programem katalogujÄ…cym i odtwarzajÄ…cym który daje możliwość natychmiastowego dostÄ™pu do milionów darmowych i pÅ‚atnych podcastów. Od niezależych twórców po wielkich producentów takich jak BBC, NPR czy CNN. Dodawaj, importuj, eksportuj wÄ…tki bez przeszkód używajÄ…c bazy iTunes, plików OPML czy po prostu przez linki RSS. OszczÄ™dź wysiÅ‚ek, bateriÄ™ oraz pakiety danych mobilnych poprzez zaawansowanÄ… kontrolÄ™ automatycznego pobierania (okreÅ›lone godziny, interwaÅ‚y czy sieci WiFi) oraz inteligentne usuwanie odcinków ( na podstawie ulubionych i ustawieÅ„ opóźnieÅ„).<br> +Najważniejsze: pobieraj , streamuj lub kolejkuj odcinki oraz rozkoszuj siÄ™ nimi jak tylko chcesz z możliwoÅ›ciÄ… zmiany prÄ™dkoÅ›ci odtwarzania, wsparciem rozdziałów i wyÅ‚Ä…cznikiem czasowym. Możesz nawet pokazać jak bardzo doceniach twórców dziÄ™ki integracji z Flattr. + +Stworzone przez entuzjastów podcastów, AntennaPod jest darmowe w każdym sÅ‚owa znaczeniu: otwarty kod, brak opÅ‚at i reklam. + +<b>Wszystkie funkcje:</b><br> +ZAIMPORTUJ, ZORGANIZUJ I ODTWARZAJ<br> +• Dodawaj i importuj kanaÅ‚y poprzez iTunes, gPodder.net, z plików OPML, RSS i linków Atom<br> +• ZarzÄ…dzaj odtwarzaniem zewszÄ…d: widget na ekranie głównym, powiadomienia systemowe i kontrolery bluetooth<br> +• Delektuj siÄ™ sÅ‚uchaniem po swojemu z: zmiennÄ… prÄ™dkoÅ›ciÄ… odtwarzania, wsparciem rozdziałów (MP3, VorbisComment i Podlove), zapamiÄ™tywaniem miejsca zakoÅ„czenia sÅ‚uchania i zaawansowanym wyÅ‚Ä…cznikiem czasowym (potrzÄ…Å›nij aby zrestartować, zmiejszanie gÅ‚oÅ›noÅ›ci i zwalnianie odtwarzania) <br> +• DostÄ™p do odcinków i kanałów chroniony hasÅ‚em<br> +• Wykorzystaj zapisane kanaÅ‚y (www.podlove.org/paged-feeds) + +ÅšLEDŹ, DZIEL SIĘ I DOCENIAJ<br> +• ZapamiÄ™tywanie najlepszych z najlepszych poprzez dodawania odcinków do ulubionych<br> +• Wyszukiwanie odcinów w historii odtwarzania lub poprzez tytuÅ‚/przypisy<br> +• Dzial siÄ™ odcinkami i wÄ…tkami poprzez zaawansowane opcje medii spoÅ‚ecznych oraz emaila, serwisu gPodder.net lub poprzez eksport do OPML<br> +• Wsparcie twórców poprzez integracjÄ™ z Flattr, również poprzez automatyczne flattr-owanie + +Kontroluj system<br> +• Ustaw automatyczne pobieranie zgodnie z wÅ‚asnymi preferencjami: wybieranie wÄ…tków, pobieranie tylko przez WiFi, wybór okreÅ›lonych sieci WiFi, wymaganie Å‚adowania przy pobieraniu oraz ustawienie harmonogramu i interwałów<br> +• ZarzÄ…danie pamiÄ™ciÄ… poprzez ustawienia liczby pobranych odcinków z pomocÄ… inteligentnego kasowania( na podstawie ulubionych i statusu odtwarzania) oraz wyboru lokalizacji<br> +• Używaj AntennaPod w swoim jÄ™zyku (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Dostosowanie wyglÄ…du jasnÄ… i ciemnÄ… skórkÄ…<br> +• Twórz kopie bezpieczeÅ„stwa swoich subskrypcji z pomocÄ… zintegrowanego gPoddder.net oraz plików OPML + +<b>DoÅ‚Ä…cz do spoÅ‚ecznoÅ›ci AntennaPod</b><br> +AntennaPod jest ciÄ…gle rozwijane przez ochotników. Ty też możesz pomóc, kodem lub komentarzem! + +Sugestie ulepszeÅ„, raporty bÅ‚Ä™dów oraz dodatki do kodu prosimy kierować poprzez GitHub<br> +https://www.github.com/AntennaPod/AntennaPod + +Nasza grupa Google jest miejsce do dzielenia siÄ™ pomysÅ‚ami, ulubionymi momentami podcastów oraz miejscem gdzie można podziÄ™kować ochotnikom za ich pracÄ™:<br> +https://groups.google.com/forum/#!forum/antennapod + +Masz pytanie lub chcesz przekazać nam swojÄ… opiniÄ™ ? +https://twitter.com/@AntennaPod + +Pomoc w tÅ‚umaczeniach na Transifex:<br> +https://www.transifex.com/antennapod/antennapod + +JeÅ›li chcesz otrzymywać najnowsze ulepszenia wczeÅ›niej niż inni rozważ doÅ‚Ä…czenie do programu beta testów:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/pl_PL.md b/app/src/main/play/pl_PL/whatsnew index 6b7574152..6b7574152 100644 --- a/changelog/pl_PL.md +++ b/app/src/main/play/pl_PL/whatsnew diff --git a/app/src/main/play/pt-BR/listing/fulldescription b/app/src/main/play/pt-BR/listing/fulldescription new file mode 100644 index 000000000..735334e0c --- /dev/null +++ b/app/src/main/play/pt-BR/listing/fulldescription @@ -0,0 +1,40 @@ +O AntennaPod é um gestor de podcasts que lhe permite aceder a milhões de podcasts (gratuitos ou pagos), a partir de diversas fontes tais como as estações BBC, NPR e CNN. A adição de fontes é muito fácil através das base de dados iTunes ou gPodder, ficheiros OPML ou fontes RSS. Poupe tempo, economize energia e dados móveis através dos mecanismos de controlo de transferência de episódios (possibilidade de especificar intervalos ou horas para as transferências e redes WiFi) e de eliminação de episódios (de acordo com as suas preferências).<br> +Mas ainda mais importante: pode transferir, emitir ou colocar episódios na lista de reprodução ao seu gosto, pode utilizar velocidades variáveis de reprodução, tem suporte a capÃtulos e um temporizador. Pode também mostrar o seu apreço aos disponibilizadores dos episódios através do serviço Flattr. + +Criado por entusiastas de podcasts, o AntennaPod é livre em todos os sentidos da palavra: open source, gratuito e sem publicidade. + +<b>Funcionalidades:</b><br> +Importação, organização e reprodução<br> +• Adicione e importe fontes existentes nos diretórios iTunes e gPodder.net, ficheiros OPML e ligações ATOM e RSS<br> +• Gestão de podcasts através do widget, barra de notificações e controlos de auriculares ou auscultadores<br> +• Velocidade variável de reprodução, suporte a capÃtulos (MP3, VorbisComment e Podlove), memorização da posição de reprodução e um temporizador avançado (agite para repor ou baixar e aumentar o volume)<br> +• Acesso a fontes e episódios protegidos por palavra-passe<br> +• Possibilidade de subscrever fontes paginadas (www.podlove.org/paged-feeds) + +Monitorização, partilha e suporte<br> +• Monitorize os seus podcasts preferidos marcando-os como favoritos<br> +• Localize um episódio através do histórico de reprodução ou através de uma pesquisa (tÃtulos e notas)<br> +• Partilhe episódios e fontes nas redes sociais, por e-mail, no diretório gPodder.net ou através de ficheiros OPML<br> +• Ajude os criadores de conteúdos através do serviço Flattr + +Controlar o sistema<br> +• Controle todas as transferÊncias automáticas: escolha as fontes, exclua redes móveis, especifique as redes WiFi, indique se o telefone deve estar a ser carregado e defina as horas ou intervalos das transferências<br> +• Faça a gestão do armazenamento através da cache de episódios, da eliminação inteligente (de acordo com os seus favoritos e estado de reprodução) e selecionado a localização de armazenamento<br> +• Utilize o AntennaPod no seu idioma (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adapte-se ao seu ambiente através dos temas claro ou escuro<br> +• Salvaguarde as suas subscrições com a integração gPodder.net ou através da exportação OPML + +<b>Integre a comunidade do AntennaPod!</b><br> +O AntennaPod é desenvolvido por voluntários. Você também pode contribuir na programação ou reportando os erros encontrados! + +O GitHub é o local certo para os pedidos de funcionalidades, relatórios de erros e contribuições:<br> +www.github.com/AntennaPod/AntennaPod + +O nosso grupo Google é o local certo para partilhar ideias e agradecer aos nossos voluntários:<br> +https://groups.google.com/forum/#!forum/antennapod + +O Transifex é o local no qual pode ajudar a traduzir a aplicação:<br> +www.transifex.com/antennapod/antennapod + +Junte-se ao nosso programa de testes para obter as funcionalidades mais recentes:<br> +www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/pt-BR/listing/shortdescription b/app/src/main/play/pt-BR/listing/shortdescription new file mode 100644 index 000000000..849436827 --- /dev/null +++ b/app/src/main/play/pt-BR/listing/shortdescription @@ -0,0 +1 @@ +Um gestor de podcasts de código livre para Android.
\ No newline at end of file diff --git a/app/src/main/play/pt-BR/listing/title b/app/src/main/play/pt-BR/listing/title new file mode 100644 index 000000000..31552f353 --- /dev/null +++ b/app/src/main/play/pt-BR/listing/title @@ -0,0 +1 @@ +AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/pt-BR/listing/video b/app/src/main/play/pt-BR/listing/video new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/app/src/main/play/pt-BR/listing/video diff --git a/app/src/main/play/pt-BR/whatsnew b/app/src/main/play/pt-BR/whatsnew new file mode 100644 index 000000000..7d59ed9a6 --- /dev/null +++ b/app/src/main/play/pt-BR/whatsnew @@ -0,0 +1,12 @@ +* Novas funcionalidades + * Suporte Chromecast (experimental) + * Visão geral de subscrições + * Suporte a proxy + * EstatÃsticas + * Sincronização manual com gpodder.net +* Correções: + * Controlos de reprodução áudio + * 'Ducking' de áudio + * Controlos de desvanecimento de vÃdeo + * Controlos multimédia externos + * Processamento de fontes
\ No newline at end of file diff --git a/app/src/main/play/pt-PT/listing/fulldescription b/app/src/main/play/pt-PT/listing/fulldescription new file mode 100644 index 000000000..735334e0c --- /dev/null +++ b/app/src/main/play/pt-PT/listing/fulldescription @@ -0,0 +1,40 @@ +O AntennaPod é um gestor de podcasts que lhe permite aceder a milhões de podcasts (gratuitos ou pagos), a partir de diversas fontes tais como as estações BBC, NPR e CNN. A adição de fontes é muito fácil através das base de dados iTunes ou gPodder, ficheiros OPML ou fontes RSS. Poupe tempo, economize energia e dados móveis através dos mecanismos de controlo de transferência de episódios (possibilidade de especificar intervalos ou horas para as transferências e redes WiFi) e de eliminação de episódios (de acordo com as suas preferências).<br> +Mas ainda mais importante: pode transferir, emitir ou colocar episódios na lista de reprodução ao seu gosto, pode utilizar velocidades variáveis de reprodução, tem suporte a capÃtulos e um temporizador. Pode também mostrar o seu apreço aos disponibilizadores dos episódios através do serviço Flattr. + +Criado por entusiastas de podcasts, o AntennaPod é livre em todos os sentidos da palavra: open source, gratuito e sem publicidade. + +<b>Funcionalidades:</b><br> +Importação, organização e reprodução<br> +• Adicione e importe fontes existentes nos diretórios iTunes e gPodder.net, ficheiros OPML e ligações ATOM e RSS<br> +• Gestão de podcasts através do widget, barra de notificações e controlos de auriculares ou auscultadores<br> +• Velocidade variável de reprodução, suporte a capÃtulos (MP3, VorbisComment e Podlove), memorização da posição de reprodução e um temporizador avançado (agite para repor ou baixar e aumentar o volume)<br> +• Acesso a fontes e episódios protegidos por palavra-passe<br> +• Possibilidade de subscrever fontes paginadas (www.podlove.org/paged-feeds) + +Monitorização, partilha e suporte<br> +• Monitorize os seus podcasts preferidos marcando-os como favoritos<br> +• Localize um episódio através do histórico de reprodução ou através de uma pesquisa (tÃtulos e notas)<br> +• Partilhe episódios e fontes nas redes sociais, por e-mail, no diretório gPodder.net ou através de ficheiros OPML<br> +• Ajude os criadores de conteúdos através do serviço Flattr + +Controlar o sistema<br> +• Controle todas as transferÊncias automáticas: escolha as fontes, exclua redes móveis, especifique as redes WiFi, indique se o telefone deve estar a ser carregado e defina as horas ou intervalos das transferências<br> +• Faça a gestão do armazenamento através da cache de episódios, da eliminação inteligente (de acordo com os seus favoritos e estado de reprodução) e selecionado a localização de armazenamento<br> +• Utilize o AntennaPod no seu idioma (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adapte-se ao seu ambiente através dos temas claro ou escuro<br> +• Salvaguarde as suas subscrições com a integração gPodder.net ou através da exportação OPML + +<b>Integre a comunidade do AntennaPod!</b><br> +O AntennaPod é desenvolvido por voluntários. Você também pode contribuir na programação ou reportando os erros encontrados! + +O GitHub é o local certo para os pedidos de funcionalidades, relatórios de erros e contribuições:<br> +www.github.com/AntennaPod/AntennaPod + +O nosso grupo Google é o local certo para partilhar ideias e agradecer aos nossos voluntários:<br> +https://groups.google.com/forum/#!forum/antennapod + +O Transifex é o local no qual pode ajudar a traduzir a aplicação:<br> +www.transifex.com/antennapod/antennapod + +Junte-se ao nosso programa de testes para obter as funcionalidades mais recentes:<br> +www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/pt-PT/listing/shortdescription b/app/src/main/play/pt-PT/listing/shortdescription new file mode 100644 index 000000000..849436827 --- /dev/null +++ b/app/src/main/play/pt-PT/listing/shortdescription @@ -0,0 +1 @@ +Um gestor de podcasts de código livre para Android.
\ No newline at end of file diff --git a/app/src/main/play/pt-PT/listing/title b/app/src/main/play/pt-PT/listing/title new file mode 100644 index 000000000..31552f353 --- /dev/null +++ b/app/src/main/play/pt-PT/listing/title @@ -0,0 +1 @@ +AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/pt-PT/listing/video b/app/src/main/play/pt-PT/listing/video new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/app/src/main/play/pt-PT/listing/video diff --git a/app/src/main/play/pt-PT/whatsnew b/app/src/main/play/pt-PT/whatsnew new file mode 100644 index 000000000..7d59ed9a6 --- /dev/null +++ b/app/src/main/play/pt-PT/whatsnew @@ -0,0 +1,12 @@ +* Novas funcionalidades + * Suporte Chromecast (experimental) + * Visão geral de subscrições + * Suporte a proxy + * EstatÃsticas + * Sincronização manual com gpodder.net +* Correções: + * Controlos de reprodução áudio + * 'Ducking' de áudio + * Controlos de desvanecimento de vÃdeo + * Controlos multimédia externos + * Processamento de fontes
\ No newline at end of file diff --git a/description/pt.txt b/app/src/main/play/pt/listing/fulldescription index 3a24b8884..58d88eb24 100644 --- a/description/pt.txt +++ b/app/src/main/play/pt/listing/fulldescription @@ -1,6 +1,4 @@ -Gestor e reprodutor de podcasts simples, flexÃvel e open souce - -O AntennaPod é um gestor e reprodutor de podcasts que lhe permite aceder a milhões de podcasts gratuitos ou pagos, a partir de fontes independentes ou de grandes editoras, tais como as estações BBC, NPR e CNN. Adicione, importe e exporte as fontes facilmente através das base de dados iTunes, ficheiros OPML ou fontes RSS. Poupe tempo, economize bateria e dados móveis através dos mecanismos de controlo de descarga de episódios (possibilidade de especificar intervalos ou horas e redes Wi-Fi) e de eliminação de episódios (de acordo com as suas preferências).<br> +O AntennaPod é um gestor de podcasts que lhe permite aceder a milhões de podcasts, gratuitos ou pagos, a partir de diversas fontes tais como as estações BBC, NPR e CNN. A adição de fontes é muito fácil através das base de dados iTunes ou gPodder, ficheiros OPML ou fontes RSS. Poupe tempo, economize bateria e dados móveis através dos mecanismos de controlo de descargas de episódios (possibilidade de especificar intervalos ou horas para as descargas e redes WiFi) e de eliminação de episódios (de acordo com as suas preferências).<br> Mas ainda mais importante: pode descarregar, emitir ou colocar episódios na lista de reprodução ao seu gosto, pode utilizar velocidades variáveis de reprodução, tem suporte a capÃtulos e um temporizador. Pode também mostrar o seu apreço aos criadores dos episódios através do serviço Flattr. Criado por entusiastas de podcasts, o AntennaPod é livre em todos os sentidos da palavra: open source, gratuito e sem publicidade. @@ -14,32 +12,32 @@ Importação, organização e reprodução<br> • Possibilidade de subscrever fontes paginadas (www.podlove.org/paged-feeds) Monitorização, partilha e suporte<br> -• Monitorize os seus episódio preferidos marcando-os como favoritos<br> +• Monitorize os seus podcasts preferidos marcando-os como favoritos<br> • Localize um episódio através do histórico de reprodução ou através de uma pesquisa (tÃtulos e notas)<br> • Partilhe episódios e fontes nas redes sociais, por e-mail, no diretório gPodder.net ou através de ficheiros OPML<br> • Ajude os criadores de conteúdos através do serviço Flattr Controlo do sistema<br> -• Controle as descargas automáticas: escolha as fontes, filtre episódios com base em palavras-chave, exclua redes móveis, selecione redes Wi-Fi, indique se o dispositivo deve estar a ser carregado e defina as horas ou intervalos das descargas<br> -• Faça a gestão do armazenamento através da cache de episódios, da eliminação inteligente (de acordo com os seus favoritos e estado de reprodução) e selecionando a localização dos dados<br> +• Controle todas as descargas automáticas: escolha as fontes, exclua redes móveis, especifique as redes Wi-Fi, indique se o telefone deve estar a ser carregado e defina as horas ou intervalos das descargas<br> +• Faça a gestão do armazenamento através da cache de episódios, da eliminação inteligente (de acordo com os seus favoritos e estado de reprodução) e selecionado a localização de armazenamento<br> • Utilize o AntennaPod no seu idioma (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> • Adapte-se ao seu ambiente através dos temas claro ou escuro<br> • Salvaguarde as suas subscrições com a integração gPodder.net ou através da exportação OPML -<b>Junte-se à comunidade do AntennaPod!</b> +<b>Integre a comunidade do AntennaPod!</b><br> O AntennaPod é desenvolvido por voluntários. Você também pode contribuir na programação ou reportando os erros encontrados! -Coloque uma questão ou dê a sua opinião através do Twitter: -https://twitter.com/@AntennaPod +O GitHub é o local certo para os pedidos de funcionalidades, relatórios de erros e contributos:<br> +https://www.github.com/AntennaPod/AntennaPod -Partilhe as suas ideias e os seus momentos favoritos nos podcasts com todos os voluntários do nosso grupo Google: +O nosso grupo Google é o local certo para partilhar ideias e agradecer aos nossos voluntários:<br> https://groups.google.com/forum/#!forum/antennapod -Ajude a traduzir a aplicação para o seu idioma no Transifex: -https://www.transifex.com/antennapod/antennapod +Tem alguma questão ou comentário a fazer? +https://twitter.com/@AntennaPod -Junte-se ao nosso programa de testes para obter as funcionalidades mais recentes: -https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod +O Transifex é o local no qual pode ajudar a traduzir a aplicação:<br> +https://www.transifex.com/antennapod/antennapod -Visite o GitHub para submeter pedidos de funcionalidades, relatórios de erros e contribuições de programação: -https://www.github.com/AntennaPod/AntennaPod
\ No newline at end of file +Junte-se ao nosso programa Beta para obter as funcionalidades mais recentes:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/pt.md b/app/src/main/play/pt/whatsnew index 609334752..609334752 100644 --- a/changelog/pt.md +++ b/app/src/main/play/pt/whatsnew diff --git a/app/src/main/play/pt_BR/listing/fulldescription b/app/src/main/play/pt_BR/listing/fulldescription new file mode 100644 index 000000000..e40d3f450 --- /dev/null +++ b/app/src/main/play/pt_BR/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod é um gerenciador e reprodutor de <i>podcasts</i> que te dá acesso instantâneo a milhões de <i>podcasts</i> gratuitos e pagos, desde <i>podcasters</i> independentes até grandes editores como BBC, NPR e CNN. Adicione, importe e exporte seus <i>feeds</i> sem complicações utilizando a base de dados do iTunes, arquivos OPML ou simples URLs RSS. Economize esforços, bateria e uso de dados móveis com poderosos controles de automação para baixar episódios (especifique horários, intervalos e redes WiFi) e excluir episódios (baseado nos seus favoritos e configurações de adiamento).<br> +Mas o mais importante: Baixe, realize <i>streaming</i> ou enfilere episódios e desfrute deles da maneira que quiser com velocidades de reprodução ajustáveis, suporte para capÃtulos e cronômetro. Você pode até mostrar o seu apreço aos criadores de conteúdo com a integração com o Flattr. + +Desenvolvido por fãs de podcasts, AntennaPod é livre em todos os sentidos da palavra; <i>open source</i>, sem custos, sem propagandas. + +<b>Recursos disponÃveis:</b><br> +IMPORTE, ORGANIZE E TOQUE <br> +• Adicione and importe feeds pelo iTunes e diretorios gPodder.net, arquivos OPML e links RSS ou Atom<br> +• Gerencie suas reproduções de qualquer lugar: widget da tela inicial, notificações de sistema e fone de ouvido e controles bluetooth<br> +• Ouça do seu jeito com velocidade de reprodução ajustável, suporte a capÃtulos (MP3, VorbisComment e Podlove), marcador da posição de reprodução e um despertador avançado (chacoalhe para reiniciar, volume reduzido e reprodução desacelerada)<br> +• Acesse feeds e episódios protegidos por senha +• Faça uso de <i>feeds</i> paginados (www.podlove.org/paged-feeds) + +MANTENHA-SE ATUALIZADO, COMPARTILHE E APRECIE<br> +• Guarde o melhor do melhor marcando episódios como favoritos<br> +• Encontre aquele episódio especÃfico através do histórico de execução ou pelo sistema de busca (através de tÃtulos e anotações)<br> +• Compartilhe episódios e <i>feeds</i> através de opções em redes sociais, email, os serviços da gPodder.net e exportação OPML<br> +• Apoie os criadores de conteúdo com a integração com o Flattr + +CONTROLE O SISTEMA +• Tenha controle sobre a automação dos <i>downloads</i>: escolha <i>feeds</i>, exclua redes móveis, selecione redes especÃficas de WiFi, exija que o telefone esteja sendo carregado e defina horários ou intervalos<br> +• Gerencie o armazenamento configurando a quantidade de episódios em cache, exclusão inteligente dos episódios (baseada nos seus favoritos e status de reprodução)<br> +• Use o AntennaPod no seu idioma (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adapte-se ao ambiente utilizando os temas claro ou escuro<br> +• Faça <i>backup</i> das suas inscrições com a integração ao gPodder.net e exportação de OPML + +<b>Junte-se à comunidade AntennaPod!</b><br> +O AntennaPod está sob constante desenvolvimento através de voluntários. Você também pode contribuir, com código ou um comentário! + +Vá ao GitHub para solicitar funcionalidades, reportar bugs e contribuir com código:<br> +https://www.github.com/AntennaPod/AntennaPod + +Nosso grupo no Google é o lugar para compartilhar suas idéias, momentos de podcasts favoritos e agradecer aos voluntários:<br> +https://groups.google.com/forum/#!forum/antennapod + +Tem uma dúvida ou um comentário? +https://twitter.com/@AntennaPod + +Transifex é o lugar para ajudar com as traduções:<br> +https://www.transifex.com/antennapod/antennapod + +Cheque nosso programa de beta testing para receber as atualizações mais recentes primeiro:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/pt_BR.md b/app/src/main/play/pt_BR/whatsnew index 6ece7128f..6ece7128f 100644 --- a/changelog/pt_BR.md +++ b/app/src/main/play/pt_BR/whatsnew diff --git a/app/src/main/play/ro/listing/fulldescription b/app/src/main/play/ro/listing/fulldescription new file mode 100644 index 000000000..7fdbfa355 --- /dev/null +++ b/app/src/main/play/ro/listing/fulldescription @@ -0,0 +1,20 @@ +AntennaPod este un podcast manager open-source pentru Android 2.3.3 sau mai nou. Oferă toate funcțiile de bază la care vă așteptați de la un podcatcher, precum streaming și descărcare de episoade, actualizarea tuturor feedurilor automat sau adăugarea lor la o coadă pentru a le asculta mai târziu. De asemenea, AntennaPod vă permite să flattr podcasturi și episoade direct din aplicație. + +So far the following features are implemented: + +* Descărcarea și Streamingul episoadelor +* Variable speed playback (requires Presto Sound Library or Prestissimo) +* Suport pentru feeduri Atom și RSS +* Support for password-protected feeds and episodes +* Support for searching iTunes listings +* Import și export OPML +* Flattr integration including automatic flattring +* Widget player +* Căutare +* Update automat de feeduri +* Descărcare automată a episoadelor noi +* Cronometru somn +* Access to the gpodder.net podcast directory +* Subscription syncing with the gpodder.net service +* Supports MP3 chapters, VorbisComment chapters and Podlove Simple Chapters +* Supports paged feeds (http://podlove.org/paged-feeds/)
\ No newline at end of file diff --git a/app/src/main/play/ro/listing/shortdescription b/app/src/main/play/ro/listing/shortdescription new file mode 100644 index 000000000..4eceefbb7 --- /dev/null +++ b/app/src/main/play/ro/listing/shortdescription @@ -0,0 +1 @@ +Easy-to-use, flexible and open-source podcast manager and player
\ No newline at end of file diff --git a/app/src/main/play/ro/listing/title b/app/src/main/play/ro/listing/title new file mode 100644 index 000000000..31552f353 --- /dev/null +++ b/app/src/main/play/ro/listing/title @@ -0,0 +1 @@ +AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/ro/listing/video b/app/src/main/play/ro/listing/video new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/app/src/main/play/ro/listing/video diff --git a/app/src/main/play/ro/whatsnew b/app/src/main/play/ro/whatsnew new file mode 100644 index 000000000..a65bddbbb --- /dev/null +++ b/app/src/main/play/ro/whatsnew @@ -0,0 +1,11 @@ +* New features: + * Subscription overview + * Proxy support + * Statistics + * Manual gpodder.net sync +* Fixes: + * Audioplayer controls + * Audio ducking + * Video control fade-out + * External media controls + * Feed parsing
\ No newline at end of file diff --git a/app/src/main/play/ro_RO/listing/fulldescription b/app/src/main/play/ro_RO/listing/fulldescription new file mode 100644 index 000000000..87b477fdc --- /dev/null +++ b/app/src/main/play/ro_RO/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> +But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. + +Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. + +<b>All features:</b><br> +IMPORT, ORGANIZE AND PLAY<br> +• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> +• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> +• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> +• Access password-protected feeds and episodes<br> +• Take advantage of paged feeds (www.podlove.org/paged-feeds) + +KEEP TRACK, SHARE & APPRECIATE<br> +• Keep track of the best of the best by marking episodes as favourites<br> +• Find that one episode through the playback history or by searching (titles and shownotes)<br> +• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> +• Support content creators with Flattr integration including automatic flattring + +CONTROL THE SYSTEM<br> +• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> +• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> +• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adapt to your environment using the light and dark theme<br> +• Back-up your subscriptions with the gPodder.net integration and OPML export + +<b>Join the AntennaPod community!</b><br> +AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! + +GitHub is the place to go for feature requests, bug reports and code contributions:<br> +https://www.github.com/AntennaPod/AntennaPod + +Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> +https://groups.google.com/forum/#!forum/antennapod + +Have a question or want to give us feedback? +https://twitter.com/@AntennaPod + +Transifex is the place to help with translations:<br> +https://www.transifex.com/antennapod/antennapod + +Check out our Beta Testing programme to get the latest features first:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/ro_RO.md b/app/src/main/play/ro_RO/whatsnew index 2798b3aa5..2798b3aa5 100644 --- a/changelog/ro_RO.md +++ b/app/src/main/play/ro_RO/whatsnew diff --git a/app/src/main/play/ru-RU/listing/fulldescription b/app/src/main/play/ru-RU/listing/fulldescription new file mode 100644 index 000000000..e3e1635ff --- /dev/null +++ b/app/src/main/play/ru-RU/listing/fulldescription @@ -0,0 +1,20 @@ +AntennaPod — Ñто open-source менеджер подкаÑтов Ð´Ð»Ñ Android 2.3.3 и выше. Он предлагает вÑе оÑновные функции подкаÑÑ‚-менеджера, такие как воÑпроизведение из Ñети, загрузка выпуÑков, автоматичеÑкое обновление каналов и добавление выпуÑков в очередь. Кроме того, AntennaPod позволÑет Ñовершать Ð¿Ð¾Ð¶ÐµÑ€Ñ‚Ð²Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ð¾Ð´ÐºÐ°ÑÑ‚-каналам, поÑредÑтвом Flattr, прÑмо из приложениÑ. + +Были реализованы Ñледующие возможноÑти: + +* Загрузка и потоковое воÑпроизведение выпуÑков +* Изменение ÑкороÑти воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ (требует Presto Sound Library или Prestissimo) +* Поддержка каналов в форматах Atom и RSS +* Поддержка защищенных паролем каналов и выпуÑков +* Поддержка поиÑка по каталогу iTunes +* Импорт и ÑкÑпорт OPML +* Ð˜Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ð¸Ñ Ñ Flattr, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑкую поддержку через него +* Виджет Ð´Ð»Ñ Ð´Ð¾Ð¼Ð°ÑˆÐ½ÐµÐ³Ð¾ Ñкрана +* ПоиÑк +* ÐвтоматичеÑкое обновление каналов +* ÐвтоматичеÑÐºÐ°Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ° новых выпуÑков +* Таймер Ñна +* ДоÑтуп к каталогу подкаÑтов на gpodder.net +* Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð¿Ð¾Ð´Ð¿Ð¸Ñок Ñ ÑервиÑом gpodder.net +* Поддержка Ð¾Ð³Ð»Ð°Ð²Ð»ÐµÐ½Ð¸Ñ MP3, VorbisComment и Podlove Simple Chapters +* Поддержка поÑтраничных лент (http://podlove.org/paged-feeds/)
\ No newline at end of file diff --git a/app/src/main/play/ru-RU/listing/shortdescription b/app/src/main/play/ru-RU/listing/shortdescription new file mode 100644 index 000000000..64e181e6b --- /dev/null +++ b/app/src/main/play/ru-RU/listing/shortdescription @@ -0,0 +1 @@ +Менеджер подкаÑтов Ð´Ð»Ñ Android Ñ Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ñ‹Ð¼ иÑходным кодом
\ No newline at end of file diff --git a/app/src/main/play/ru-RU/listing/title b/app/src/main/play/ru-RU/listing/title new file mode 100644 index 000000000..31552f353 --- /dev/null +++ b/app/src/main/play/ru-RU/listing/title @@ -0,0 +1 @@ +AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/ru-RU/listing/video b/app/src/main/play/ru-RU/listing/video new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/app/src/main/play/ru-RU/listing/video diff --git a/app/src/main/play/ru-RU/whatsnew b/app/src/main/play/ru-RU/whatsnew new file mode 100644 index 000000000..a65bddbbb --- /dev/null +++ b/app/src/main/play/ru-RU/whatsnew @@ -0,0 +1,11 @@ +* New features: + * Subscription overview + * Proxy support + * Statistics + * Manual gpodder.net sync +* Fixes: + * Audioplayer controls + * Audio ducking + * Video control fade-out + * External media controls + * Feed parsing
\ No newline at end of file diff --git a/app/src/main/play/ru_RU/listing/fulldescription b/app/src/main/play/ru_RU/listing/fulldescription new file mode 100644 index 000000000..9b68a06c0 --- /dev/null +++ b/app/src/main/play/ru_RU/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod — менеджер и проигрыватель подкаÑтов, который обеÑпечит Ð’Ð°Ñ Ð¼Ð³Ð½Ð¾Ð²ÐµÐ½Ð½Ñ‹Ð¼ доÑтупом к миллионам беÑплатных и платных подкаÑтов, как от незавиÑимых подкаÑтеров, так и крупных издательÑких домов, например, BBC, NPR и CNN. С лёгкоÑтью добавлÑйте, импортируйте и ÑкÑпортируйте их каналы иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ ÐºÐ°Ñ‚Ð°Ð»Ð¾Ð³ подкаÑтов iTunes, файлы OPML или адреÑа каналов RSS. Сберегите уÑилиÑ, зарÑд батареи и мобильный трафик при помощи мощных ÑредÑтв автоматизации загрузки выпуÑков (фильтрациÑ, указание времени и интервалов, а также Ñетей WiFi) и их ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ (в ÑоответÑтвии Ñ Ð½Ð°Ñтройками избранного и ожиданиÑ).<br> +Ðо Ñамое главное: Загружайте, Ñлушайте Ñ Ñфира или Ñтавьте в очередь и получайте удовольÑтвие от их проÑÐ»ÑƒÑˆÐ¸Ð²Ð°Ð½Ð¸Ñ Ð¿Ñ€Ð¸Ð¼ÐµÐ½ÑÑ Ñ€ÐµÐ³ÑƒÐ»Ð¸Ñ€ÑƒÐµÐ¼ÑƒÑŽ ÑкороÑÑ‚ÑŒ воÑпроизведениÑ, Ð¾Ð³Ð»Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¸ таймер Ñна. Ð’Ñ‹ даже можете выразить Ñвою благодарноÑÑ‚ÑŒ ÑоздателÑм аудио поÑредÑтвом интеграции Ñ Flattr. + +Созданное поклонниками подкаÑтов, AntennaPod — беÑплатное и Ñвободное приложение без рекламы и платежей. + +<b>Ð’Ñе возможноÑти:</b><br> +Импортируйте, ÑиÑтематизируйте и проÑлушивайте<br> +• Добавление и импорт каналов через каталоги iTunes и gPodder.net, файлы OPML и ÑÑылки на каналы RSS или Atom<br> +• Ð’Ñевозможное управление воÑпроизведением: виджетом, ÑиÑтемным уведомлением и кнопками проводных и беÑпроводных гарнитур<br> +• ПриÑтное, по вашему вкуÑу, проÑлушивание применÑÑ Ñ€ÐµÐ³ÑƒÐ»Ð¸Ñ€Ð¾Ð²ÐºÑƒ ÑкороÑти воÑпроизведениÑ, Ð¾Ð³Ð»Ð°Ð²Ð»ÐµÐ½Ð¸Ñ (MP3, VorbisComment и Podlove), запоминание меÑта воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð¸ продвинутый таймер Ñна (ÑÐ±Ñ€Ð¾Ñ Ð¿Ñ€Ð¸ вÑÑ‚Ñ€Ñхивание, Ñнижение громкоÑти и замедление воÑпроизведениÑ)<br> +• ДоÑтуп к каналам и выпуÑкам защищенным паролем<br> +• ИÑпользует преимущеÑтва поÑтраничных лент (www.podlove.org/paged-feeds) + +ОтÑлеживайте, делитеÑÑŒ и благодарите<br> +• ОтÑлеживайте лучших из лучших, Ð¿Ð¾Ð¼ÐµÑ‰Ð°Ñ Ð²Ñ‹Ð¿ÑƒÑки в избранное<br> +• ПоиÑк того Ñамого выпуÑка в иÑтории воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð¸Ð»Ð¸ по контекÑту (заголовки и заметки к выпуÑку)<br> +• Разнообразные возможноÑти поделитьÑÑ Ð²Ñ‹Ð¿ÑƒÑками и каналами через Ñоциальные Ñлужбы и e-mail, уÑлуги gPodder.net и ÑкÑпорт в OPML<br> +• Поддержка Ñоздателей аудио при помощи интеграции Ñ Flattr, в том чиÑле и автоматичеÑки + +УправлÑйте ÑиÑтемой<br> +• Управление автоматичеÑкой загрузкой: выбор отдельных каналов, отбор выпуÑков на оÑнове ключевых Ñлов, запрет на иÑпользование мобильных Ñетей, выбор отдельных точек доÑтупа WiFi, только во Ð²Ñ€ÐµÐ¼Ñ Ð·Ð°Ñ€Ñдки телефона и задание времени и интервалов<br> +• Управление хранением путём Ð·Ð°Ð´Ð°Ð½Ð¸Ñ ÐºÐ¾Ð»Ð¸Ñ‡ÐµÑтва выпуÑков в кÑше, автоудаление (на оÑновании наÑтроек избранного и ÑтатуÑа проÑлушиваниÑ) и выбор предпочитаемого раÑположениÑ<br> +• AntennaPod на родном Вам Ñзыке (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH, RU)<br> +• ПриÑпоÑабливаетÑÑ Ðº Вашему окружению поÑредÑтвом Ñветлой или тёмной темы<br> +• Резервирование Ваших подпиÑок путём интеграции Ñ gPodder.net и Ñкпорта в OPML + +<b>ПриÑоединÑйтеÑÑŒ к ÑообщеÑтву AntennaPod!</b><br> +AntennaPod поÑтоÑнно развиваетÑÑ Ñилами добровольцев. Ð’Ñ‹ тоже можете Ñделать Ñвой вклад при помощи кода или комментариÑ! + +ПоÑещайте GitHub Ð´Ð»Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñа новых возможноÑтей, ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¾Ð± ошибках и внеÑÐµÐ½Ð¸Ñ ÐºÐ¾Ð´Ð°:<br> +https://www.github.com/AntennaPod/AntennaPod + +ПоделитеÑÑŒ идеÑми, любимыми мгновениÑми проÑÐ»ÑƒÑˆÐ¸Ð²Ð°Ð½Ð¸Ñ Ð¸ благодарноÑтью Ñо вÑеми добровольцами из нашей группы Google:<br> +https://groups.google.com/forum/#!forum/antennapod + +ПоÑвилиÑÑŒ вопроÑÑ‹ и Ð¾Ð±Ñ€Ð°Ñ‚Ð½Ð°Ñ ÑвÑзь? +https://twitter.com/@AntennaPod + +Помогайте Ñ Ð¿ÐµÑ€ÐµÐ²Ð¾Ð´Ð¾Ð¼ Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð½Ð° Transifex:<br> +https://www.transifex.com/antennapod/antennapod + +Попробуйте ÑÐµÐ±Ñ Ð² программе Бета теÑÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¸ получите доÑтуп к раÑпоÑледним возможноÑÑ‚Ñм в чиÑле первых:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/ru_RU.md b/app/src/main/play/ru_RU/whatsnew index eb4677c7c..eb4677c7c 100644 --- a/changelog/ru_RU.md +++ b/app/src/main/play/ru_RU/whatsnew diff --git a/description/sv_SE.txt b/app/src/main/play/sv-SE/listing/fulldescription index 5455c7d78..bdf641cf2 100644 --- a/description/sv_SE.txt +++ b/app/src/main/play/sv-SE/listing/fulldescription @@ -1,5 +1,3 @@ -Användarvänlig och flexibel podcasthanterare och spelare med öppen källkod - AntennaPod är en podcasthanterare och spelare som ger dig omedelbar tillgång till millioner av gratis och betalda podcasts, allt ifrån oberoende podcasters till publiceringsjättar som BBC, NPR och CNN. Lägg till, importera och exportera enkelt deras flöden med hjälp av iTunes podcastdatabas, OPML filer eller enkla RSS URL:er. Spara tid, batterikraft och mobildata med kraftfull automatisering för nedladdning (specifiera tider, intervall och WiFi-nätverk) och borttagning av episoder (baserat på dina favoriter och fördröjningsinställningar).<br> Men viktigast: Ladda ner, strömma eller köa episoder och avnjut dem på ditt sätt med justerbar uppspelningshastighet, kapitelstöd och en sovtimer. Du kan till och med visa din uppskattning av innehållsskaparna med vår integrering av Flattr. @@ -30,13 +28,13 @@ KONTROLLERA SYSTEMET<br> AntennaPod är under aktiv utveckling av volontärer. Du kan också bidra, med kod eller kommentarer! GitHub är platsen att gå till för att be om funktioner, skapa buggrapporter eller bidra med kod:<br> -https://www.github.com/AntennaPod/AntennaPod +www.github.com/AntennaPod/AntennaPod Vår Google Group är platsen för att dela idéer, dina favoritögonblick med podcasting och din uppskattning till volontärerna:<br> https://groups.google.com/forum/#!forum/antennapod Transifex är platsen att gå till för att hjälpa till med översättningen:<br> -https://www.transifex.com/antennapod/antennapod +www.transifex.com/antennapod/antennapod Kolla in vårat Beta Testing program för att få de senaste funktionerna först:<br> -https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file +www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/sv-SE/listing/shortdescription b/app/src/main/play/sv-SE/listing/shortdescription new file mode 100644 index 000000000..26b3b106a --- /dev/null +++ b/app/src/main/play/sv-SE/listing/shortdescription @@ -0,0 +1 @@ +Användarvänlig, flexibel podcasthanterare och spelare med öppen källkod
\ No newline at end of file diff --git a/app/src/main/play/sv-SE/listing/title b/app/src/main/play/sv-SE/listing/title new file mode 100644 index 000000000..31552f353 --- /dev/null +++ b/app/src/main/play/sv-SE/listing/title @@ -0,0 +1 @@ +AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/sv-SE/listing/video b/app/src/main/play/sv-SE/listing/video new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/app/src/main/play/sv-SE/listing/video diff --git a/app/src/main/play/sv-SE/whatsnew b/app/src/main/play/sv-SE/whatsnew new file mode 100644 index 000000000..c7b7f1aa6 --- /dev/null +++ b/app/src/main/play/sv-SE/whatsnew @@ -0,0 +1,12 @@ +* Nya funktioner: + * Experimentellt stöd för Chromecast + * Prenumerationsöversikt + * Proxystöd + * Statistik + * Manuell gpodder.net synkronisering +* Fixar: + * Ljuduppspelningskontroller + * Ljudduckning + * Fade-out på videokontroller + * Externa mediakontroller + * Flödestolkning
\ No newline at end of file diff --git a/app/src/main/play/sv_SE/listing/fulldescription b/app/src/main/play/sv_SE/listing/fulldescription new file mode 100644 index 000000000..84b7d9681 --- /dev/null +++ b/app/src/main/play/sv_SE/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod är en podcasthanterare och spelare som ger dig omedelbar tillgÃ¥ng till millioner av gratis och betalda podcasts, allt ifrÃ¥n oberoende podcasters till publiceringsjättar som BBC, NPR och CNN. Lägg till, importera och exportera enkelt deras flöden med hjälp av iTunes podcastdatabas, OPML filer eller enkla RSS URL:er. Spara tid, batterikraft och mobildata med kraftfull automatisering för nedladdning (specifiera tider, intervall och WiFi-nätverk) och borttagning av episoder (baserat pÃ¥ dina favoriter och fördröjningsinställningar).<br> +Men viktigast: Ladda ner, strömma eller köa episoder och avnjut dem pÃ¥ ditt sätt med justerbar uppspelningshastighet, kapitelstöd och en sovtimer. Du kan till och med visa din uppskattning av innehÃ¥llsskaparna med vÃ¥r integrering av Flattr. + +Gjord av podcastenthusiaster, AntennaPod är fri i alla ordets bemärkelser: öppen källkod, inga kostnader, ingen reklam. + +<b>Alla funktioner:</b><br> +IMPORTERA, ORGANISERA OCH SPELA<br> +• Lägg till och importera flöden via iTunes och gPodder.net, OPML filer och RSS eller Atom länkar<br> +• Hantera uppspelningen frÃ¥n vartsomhelst: hemskärmswidget, aviseringsfältet och hörlurs/bluetoth-kontroller<br> +• Njut av att lyssna pÃ¥ ditt sätt med justerbar uppspelningshastighet, kapitelstöd (MP4, VorbisComment och Podlove), ihÃ¥gkommen uppspelningsposition och en avancerad sömntimer (skaka för Ã¥terställaning, sänk volymen och sänk hastigheten)<br> +• Kom Ã¥t lösenordsskyddade flöden och episoder<br> +• Dra nytta av siduppdelade flöden (www.podlove.ord/paged-feeds) + +SPÃ…RA, DELA & UPPSKATTA<br> +• HÃ¥ll ordning pÃ¥ de bästa av de bästa med favoritmarkering av episoder<br> +• Hitta just den där episoden i uppspelningshistoriken eller genom sökning (titel och shownotes)<br> +• Dela episoder och flöden med avancerade vald för social media och och email, tjänsten gPodder.net och via OPML export<br> +• Stöd innehÃ¥llsskaparna via integrering av Flattr och automatisk flattring + +KONTROLLERA SYSTEMET<br> +• Ta kontroll över automatisk nedladdning: välj flöden, exkludera mobilnätverk, välj specifika WiFi nätverk, kräv att telefonen är inkopplad för laddning och sätt tider eller intervall för körning<br> +• Hantera lagringsutrymme genom att välja antalet cachade episoder, smart borttagning (baserat pÃ¥ dina favoriter och uppspelningsstatus) och välj den lagringsplats du föredrar<br> +• Använd AntennaPod pÃ¥ ditt sprÃ¥k (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Anpassa till din omgivning med det ljusa och mörka temat<br> +• Ta backup av dina prenumerationer med integreringen av gPodder.net och OPML exportering + +<b>GÃ¥ med i AntennaPods gemenskap!</b><br> +AntennaPod är under aktiv utveckling av volontärer. Du kan ocksÃ¥ bidra, med kod eller kommentarer! + +GitHub är platsen att gÃ¥ till för att be om funktioner, skapa buggrapporter eller bidra med kod:<br> +https://www.github.com/AntennaPod/AntennaPod + +VÃ¥r Google Group är platsen för att dela idéer, dina favoritögonblick med podcasting och din uppskattning till volontärerna:<br> +https://groups.google.com/forum/#!forum/antennapod + +Har du frÃ¥gor eller vill ge feedback? +https://twitter.com/@AntennaPod + +Transifex är platsen att gÃ¥ till för att hjälpa till med översättningen:<br> +https://www.transifex.com/antennapod/antennapod + +Kolla in vÃ¥rat Beta Testing program för att fÃ¥ de senaste funktionerna först:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/sv_SE.md b/app/src/main/play/sv_SE/whatsnew index 5689c6252..5689c6252 100644 --- a/changelog/sv_SE.md +++ b/app/src/main/play/sv_SE/whatsnew diff --git a/app/src/main/play/sw_KE/listing/fulldescription b/app/src/main/play/sw_KE/listing/fulldescription new file mode 100644 index 000000000..87b477fdc --- /dev/null +++ b/app/src/main/play/sw_KE/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> +But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. + +Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. + +<b>All features:</b><br> +IMPORT, ORGANIZE AND PLAY<br> +• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> +• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> +• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> +• Access password-protected feeds and episodes<br> +• Take advantage of paged feeds (www.podlove.org/paged-feeds) + +KEEP TRACK, SHARE & APPRECIATE<br> +• Keep track of the best of the best by marking episodes as favourites<br> +• Find that one episode through the playback history or by searching (titles and shownotes)<br> +• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> +• Support content creators with Flattr integration including automatic flattring + +CONTROL THE SYSTEM<br> +• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> +• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> +• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adapt to your environment using the light and dark theme<br> +• Back-up your subscriptions with the gPodder.net integration and OPML export + +<b>Join the AntennaPod community!</b><br> +AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! + +GitHub is the place to go for feature requests, bug reports and code contributions:<br> +https://www.github.com/AntennaPod/AntennaPod + +Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> +https://groups.google.com/forum/#!forum/antennapod + +Have a question or want to give us feedback? +https://twitter.com/@AntennaPod + +Transifex is the place to help with translations:<br> +https://www.transifex.com/antennapod/antennapod + +Check out our Beta Testing programme to get the latest features first:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/te/listing/fulldescription b/app/src/main/play/te/listing/fulldescription new file mode 100644 index 000000000..87b477fdc --- /dev/null +++ b/app/src/main/play/te/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> +But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. + +Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. + +<b>All features:</b><br> +IMPORT, ORGANIZE AND PLAY<br> +• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> +• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> +• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> +• Access password-protected feeds and episodes<br> +• Take advantage of paged feeds (www.podlove.org/paged-feeds) + +KEEP TRACK, SHARE & APPRECIATE<br> +• Keep track of the best of the best by marking episodes as favourites<br> +• Find that one episode through the playback history or by searching (titles and shownotes)<br> +• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> +• Support content creators with Flattr integration including automatic flattring + +CONTROL THE SYSTEM<br> +• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> +• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> +• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adapt to your environment using the light and dark theme<br> +• Back-up your subscriptions with the gPodder.net integration and OPML export + +<b>Join the AntennaPod community!</b><br> +AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! + +GitHub is the place to go for feature requests, bug reports and code contributions:<br> +https://www.github.com/AntennaPod/AntennaPod + +Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> +https://groups.google.com/forum/#!forum/antennapod + +Have a question or want to give us feedback? +https://twitter.com/@AntennaPod + +Transifex is the place to help with translations:<br> +https://www.transifex.com/antennapod/antennapod + +Check out our Beta Testing programme to get the latest features first:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/tr-TR/listing/fulldescription b/app/src/main/play/tr-TR/listing/fulldescription new file mode 100644 index 000000000..7ea4d906d --- /dev/null +++ b/app/src/main/play/tr-TR/listing/fulldescription @@ -0,0 +1,20 @@ +AntennaPod, Android 2.3.3 ve üzeri için açık kaynak kodlu cepyayını yöneticisidir. Bölümleri yayınlama ve indirme, beslemelerin otomatik olarak yenilenmesi veya daha sonra dinlemek için sıraya konması gibi bir cepyayını yakalayıcısından beklediğiniz tüm temel özellikleri içerir. Hatta cepyayınlarını ve bölümleri uygulama içinden flattr aracılığıyla desteklemenize olanak verir. + +Şimdiye kadar aşağıdaki özellikler eklenmiştir: + +* Bölümlerin indirilmesi ve yayınlanması +* Değişken çalma hızı (Presto Sound Library veya Prestissimo gerekir) +* Atom ve RSS besleme desteği +* Şifre korumalı besleme ve bölüm desteği +* iTunes listelerinde arama yapma desteği +* OPML içe aktarma ve dışa aktarma +* Otomatik flatter içeren Flattr entegrasyonu +* Ev ekranı oynatıcı widget'ı +* Arama +* Otomatik besleme güncellemeleri +* Yeni bölümlerin otomatik indirilmesi +*Uyku zamanlayıcı +* gpodder.net cepyayını dizinine erişim +* gpodder.net servisi ile üyelik senkronizasyonu +* MP3 kısımları, VorbisComment kısımlar ve Podlove Simple Chapter desteği +* Sayfalanmış beslemeler desteği (http://podlove.org/paged-feeds/)
\ No newline at end of file diff --git a/app/src/main/play/tr-TR/listing/shortdescription b/app/src/main/play/tr-TR/listing/shortdescription new file mode 100644 index 000000000..979342e23 --- /dev/null +++ b/app/src/main/play/tr-TR/listing/shortdescription @@ -0,0 +1 @@ +Android için açık kaynaklı cepyayını yöneticisi
\ No newline at end of file diff --git a/app/src/main/play/tr-TR/listing/title b/app/src/main/play/tr-TR/listing/title new file mode 100644 index 000000000..31552f353 --- /dev/null +++ b/app/src/main/play/tr-TR/listing/title @@ -0,0 +1 @@ +AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/tr-TR/listing/video b/app/src/main/play/tr-TR/listing/video new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/app/src/main/play/tr-TR/listing/video diff --git a/app/src/main/play/tr-TR/whatsnew b/app/src/main/play/tr-TR/whatsnew new file mode 100644 index 000000000..a65bddbbb --- /dev/null +++ b/app/src/main/play/tr-TR/whatsnew @@ -0,0 +1,11 @@ +* New features: + * Subscription overview + * Proxy support + * Statistics + * Manual gpodder.net sync +* Fixes: + * Audioplayer controls + * Audio ducking + * Video control fade-out + * External media controls + * Feed parsing
\ No newline at end of file diff --git a/app/src/main/play/tr/listing/fulldescription b/app/src/main/play/tr/listing/fulldescription new file mode 100644 index 000000000..90bda48af --- /dev/null +++ b/app/src/main/play/tr/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> +But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. + +Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. + +<b>Tüm özellikler:</b><br> +IMPORT, ORGANIZE AND PLAY<br> +• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> +• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> +• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> +• Access password-protected feeds and episodes<br> +• Take advantage of paged feeds (www.podlove.org/paged-feeds) + +KEEP TRACK, SHARE & APPRECIATE<br> +• Keep track of the best of the best by marking episodes as favourites<br> +• Find that one episode through the playback history or by searching (titles and shownotes)<br> +• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> +• Support content creators with Flattr integration including automatic flattring + +SÄ°STEMÄ° KONTROL ET<br> +• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> +• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> +• AntennaPod'u kendi dilinizde kullanın (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adapt to your environment using the light and dark theme<br> +• Back-up your subscriptions with the gPodder.net integration and OPML export + +<b>AntennaPod topluluÄŸuna katılın!</b><br> +AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! + +GitHub is the place to go for feature requests, bug reports and code contributions:<br> +https://www.github.com/AntennaPod/AntennaPod + +Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> +https://groups.google.com/forum/#!forum/antennapod + +Bir sorunuz mu var veya bize geri bildirim bırakmak mı istiyorsunuz? +https://twitter.com/@AntennaPod + +Tercümelere yardım etmenin yeri Transifex:<br> +https://www.transifex.com/antennapod/antennapod + +En son özellikleri ilk önce almak isterseniz Beta Testing programımıza katılın:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/tr.md b/app/src/main/play/tr/whatsnew index 189e7ce56..189e7ce56 100644 --- a/changelog/tr.md +++ b/app/src/main/play/tr/whatsnew diff --git a/app/src/main/play/uk/listing/fulldescription b/app/src/main/play/uk/listing/fulldescription new file mode 100644 index 000000000..877483033 --- /dev/null +++ b/app/src/main/play/uk/listing/fulldescription @@ -0,0 +1,40 @@ +AntennaPod це менеджер подкаÑтів та плейер що дає доÑтуп до мільйонів безкоштовних та комерційних подкаÑтів від незалежних подкаÑтерів та великих корпорацій таких Ñк BBC, NPR та CNN. Є можливіÑÑ‚ÑŒ додавати, імпортувати та екÑпортувати канали за допомогою бази даних подкаÑтів iTunes, файлів OPML або проÑтих поÑилань на RSS. Зберігайте зуÑиллÑ, Ð¶Ð¸Ð²Ð»ÐµÐ½Ð½Ñ Ñ‚Ð° мобільний трафік за допомогою автоматичного Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ ÐµÐ¿Ñ–Ð·Ð¾Ð´Ñ–Ð² (зазначивши чаÑ, інтервали та мережі WiFi) та Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ ÐµÐ¿Ñ–Ð·Ð¾Ð´Ñ–Ð² (з урахуваннÑм ваших побажань та налаштувань).<br> +Ðле найважливіше: завантажуйте, Ñлухайте або додавайте до черги епізоди так, Ñк вам подобаєтьÑÑ Ð· налаштуваннÑм швидкоÑÑ‚Ñ– програваннÑ, підтримкою розділів та таймера Ñну. Можливо навіть фінанÑово заохочувати авторів за допомогою інтергації з ÑервіÑом Flattr. + +Зроблений ентузіаÑтом подкаÑтів, AntennaPod Ñ” вільним в уÑÑ–Ñ… ÑенÑах цього Ñлова: відкриті вихідні текÑти, безкоштовний, без реклами. + +<b>Ð’ÑÑ– можливоÑÑ‚Ñ–:</b><br> +ІМПОРТУЙТЕ, ВПОРЯДКОВУЙТЕ ТРСЛУХÐЙТЕ<br> +• Додавайте та імпортуйте канали з каталогів iTunes та gPodder.net, файлів OPML та з поÑилань на RSS або Atom<br> +• Керуйте програваннÑм будь-де: з віджета, нотифікації, кнопками навушників або через блютуÑ<br> +• Слухайте так Ñк вам подобаєтьÑÑ Ð· налаштуваннÑм швидкоÑÑ‚Ñ– програваннÑ, підтримкой розділів (в форматах MP3, VorbisComment та Podlove), зберіганнÑм момента Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð²Ð°Ð½Ð½Ñ Ñ‚Ð° таймером Ñну (перезапуÑк ÑтруÑом, Ð·Ð½Ð¸Ð¶ÐµÐ½Ð½Ñ Ð³ÑƒÑ‡Ð½Ð¾ÑÑ‚Ñ– та ÑƒÐ¿Ð¾Ð²Ñ–Ð»ÑŒÐ½ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð²Ð°Ð½Ð½Ñ)<br> +• ДоÑтуп до каналів та епізодів що захищені паролем<br> +• ВикориÑтовуйте поÑторінкові канали (www.podlove.org/paged-feeds) + +ВІДСТЕЖУЙТЕ, ДІЛІТЬСЯ ТРОЦІÐЮЙТЕ<br> +• Зберігайте найкраще в улюблених епізодах<br> +• Відшукайте той Ñамий епізод в Ñ–Ñторії Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð²Ð°Ð½Ð½Ñ Ð°Ð±Ð¾ пошуком (в назвах Ñ– нотатках)<br> +• ДілітьÑÑ ÐµÐ¿Ñ–Ð·Ð¾Ð´Ð°Ð¼Ð¸ та каналами за допомогою Ñоцмереж та пошти, ÑервіÑів gPodder.net та через екÑпорт OPML файлів<br> +• Підтримуйте авторів за допомогою інтегрованого ÑервіÑа Flattr з можливіÑÑ‚ÑŽ автоматичной підтримки + +КЕРУЙТЕ СИСТЕМОЙ<br> +• Керуйте автоматичним завантаженнÑм: вибирайте канали, мобільні мережі, мережі WiFi, завантажуйте тільки під Ñ‡Ð°Ñ Ð·Ð°Ñ€Ñдки або у вÑтановлений Ñ‡Ð°Ñ Ñ– інтервали<br> +• Керуйте збереженнÑм, вÑтановлюйте ліміт на кеш епізодів, налагоджуйте розумне Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ (з урахуваннÑм улюблених епізодів Ñ– ÑтатуÑа програваннÑ) та вибирайте міÑце зберіганнÑ<br> +• КориÑтуйтеÑÑŒ AntennaPod вашою мовою (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• ПриÑтоÑовуйтеÑÑŒ до ваших умов, кориÑтуйтеÑÑŒ Ñвітлой або темной темами<br> +• Зберігайте ваші підпиÑки на gPodder.net або екÑпортуйте в файл OPML + +<b>ДолучайтеÑÑŒ до Ñпільноти AntennaPod!</b><br> +AntennaPod швидко розвиваєтьÑÑ Ð²Ð¾Ð»Ð¾Ð½Ñ‚ÐµÑ€Ð°Ð¼Ð¸. Ви також маєте змогу допомогти, кодом або зауваженнÑми! + +ДолучитиÑÑŒ до проекта, повідомити про ваші Ð¿Ð¾Ð±Ð°Ð¶Ð°Ð½Ð½Ñ Ñ‚Ð° про помилки можна на GitHub:<br> +www.github.com/AntennaPod/AntennaPod + +Ð’ нашій групі на Google можна поділитиÑÑŒ ідеÑми, улюбленими моментами з подкаÑтінга та добрими побажаннÑми волонтерам:<br> +https://groups.google.com/forum/#!forum/antennapod + +Допомагайте з перекладом на Transifex:<br> +www.transifex.com/antennapod/antennapod + +Зверніть увагу на нашу програму Ð´Ð»Ñ Ð±ÐµÑ‚Ð° теÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñкщо бажаєте получати найновіші верÑÑ–Ñ— в першу чергу:<br> +www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/uk/listing/shortdescription b/app/src/main/play/uk/listing/shortdescription new file mode 100644 index 000000000..ac638de72 --- /dev/null +++ b/app/src/main/play/uk/listing/shortdescription @@ -0,0 +1 @@ +Менеджер подкаÑтів Ð´Ð»Ñ Android з відкритими вихідними текÑтами.
\ No newline at end of file diff --git a/app/src/main/play/uk/listing/title b/app/src/main/play/uk/listing/title new file mode 100644 index 000000000..31552f353 --- /dev/null +++ b/app/src/main/play/uk/listing/title @@ -0,0 +1 @@ +AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/uk/listing/video b/app/src/main/play/uk/listing/video new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/app/src/main/play/uk/listing/video diff --git a/app/src/main/play/uk/whatsnew b/app/src/main/play/uk/whatsnew new file mode 100644 index 000000000..a65bddbbb --- /dev/null +++ b/app/src/main/play/uk/whatsnew @@ -0,0 +1,11 @@ +* New features: + * Subscription overview + * Proxy support + * Statistics + * Manual gpodder.net sync +* Fixes: + * Audioplayer controls + * Audio ducking + * Video control fade-out + * External media controls + * Feed parsing
\ No newline at end of file diff --git a/description/uk_UA.txt b/app/src/main/play/uk_UA/listing/fulldescription index b3aa64be5..ae8ac2c20 100644 --- a/description/uk_UA.txt +++ b/app/src/main/play/uk_UA/listing/fulldescription @@ -1,5 +1,3 @@ -Легкий у викориÑтанні та гнучкий плейер та менеджер подкаÑтів з відкритим Ñирцевим кодом - AntennaPod це менеджер подкаÑтів та плейер що дає доÑтуп до мільйонів безкоштовних та комерційних подкаÑтів від незалежних подкаÑтерів та великих корпорацій таких Ñк BBC, NPR та CNN. Є можливіÑÑ‚ÑŒ додавати, імпортувати та екÑпортувати канали за допомогою бази даних подкаÑтів iTunes, файлів OPML або проÑтих поÑилань на RSS. Зберігайте зуÑиллÑ, Ð¶Ð¸Ð²Ð»ÐµÐ½Ð½Ñ Ñ‚Ð° мобільний трафік за допомогою автоматичного Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ ÐµÐ¿Ñ–Ð·Ð¾Ð´Ñ–Ð² (зазначивши чаÑ, інтервали та мережі WiFi) та Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ ÐµÐ¿Ñ–Ð·Ð¾Ð´Ñ–Ð² (з урахуваннÑм ваших побажань та налаштувань).<br> Ðле найважливіше: завантажуйте, Ñлухайте або додавайте до черги епізоди так, Ñк вам подобаєтьÑÑ Ð· налаштуваннÑм швидкоÑÑ‚Ñ– програваннÑ, підтримкою розділів та таймера Ñну. Можливо навіть фінанÑово заохочувати авторів за допомогою інтергації з ÑервіÑом Flattr. @@ -20,26 +18,26 @@ AntennaPod це менеджер подкаÑтів та плейер що Ð´Ð°Ñ • Підтримуйте авторів за допомогою інтегрованого ÑервіÑа Flattr з можливіÑÑ‚ÑŽ автоматичной підтримки КЕРУЙТЕ СИСТЕМОЙ<br> -• Керуйте автоматичним завантаженнÑм: вибирайте канали, мобільні мережі, мережі WiFi, фільтруйте епізоди за ключовими Ñловами, завантажуйте тільки під Ñ‡Ð°Ñ Ð·Ð°Ñ€Ñдки або у вÑтановлений Ñ‡Ð°Ñ Ñ– інтервали<br> +• Керуйте автоматичним завантаженнÑм: вибирайте канали, мобільні мережі, мережі WiFi, завантажуйте тільки під Ñ‡Ð°Ñ Ð·Ð°Ñ€Ñдки або у вÑтановлений Ñ‡Ð°Ñ Ñ– інтервали<br> • Керуйте збереженнÑм, вÑтановлюйте ліміт на кеш епізодів, налагоджуйте розумне Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ (з урахуваннÑм улюблених епізодів Ñ– ÑтатуÑа програваннÑ) та вибирайте міÑце зберіганнÑ<br> • КориÑтуйтеÑÑŒ AntennaPod вашою мовою (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> • ПриÑтоÑовуйтеÑÑŒ до ваших умов, кориÑтуйтеÑÑŒ Ñвітлой або темной темами<br> • Зберігайте ваші підпиÑки на gPodder.net або екÑпортуйте в файл OPML -<b>ДолучайтеÑÑŒ до Ñпільноти AntennaPod!</b> +<b>ДолучайтеÑÑŒ до Ñпільноти AntennaPod!</b><br> AntennaPod швидко розвиваєтьÑÑ Ð²Ð¾Ð»Ð¾Ð½Ñ‚ÐµÑ€Ð°Ð¼Ð¸. Ви також маєте змогу допомогти, кодом або зауваженнÑми! -Запитуйте, та ÑпілкуйтеÑÑŒ за допомогую твітера: -https://twitter.com/@AntennaPod +ДолучитиÑÑŒ до проекта, повідомити про ваші Ð¿Ð¾Ð±Ð°Ð¶Ð°Ð½Ð½Ñ Ñ‚Ð° про помилки можна на GitHub:<br> +https://www.github.com/AntennaPod/AntennaPod -Ð’ нашій групі на Google можна поділитиÑÑŒ ідеÑми, улюбленими моментами з подкаÑтінга та добрими побажаннÑми волонтерам: +Ð’ нашій групі на Google можна поділитиÑÑŒ ідеÑми, улюбленими моментами з подкаÑтінга та добрими побажаннÑми волонтерам:<br> https://groups.google.com/forum/#!forum/antennapod -Допоможіть з перекладом на рідну мову на Transifex: -https://www.transifex.com/antennapod/antennapod +Маєте Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð°Ð±Ð¾ Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð½Ð°Ñ? +https://twitter.com/@AntennaPod -Зверніть увагу на нашу програму Ð´Ð»Ñ Ð±ÐµÑ‚Ð° теÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñкщо бажаєте получати найновіші верÑÑ–Ñ— в першу чергу: -https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod +Допомагайте з перекладом на Transifex:<br> +https://www.transifex.com/antennapod/antennapod -ДолучитиÑÑŒ до проекта, повідомити про ваші Ð¿Ð¾Ð±Ð°Ð¶Ð°Ð½Ð½Ñ Ñ‚Ð° про помилки можна на GitHub: -https://www.github.com/AntennaPod/AntennaPod
\ No newline at end of file +Зверніть увагу на нашу програму Ð´Ð»Ñ Ð±ÐµÑ‚Ð° теÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñкщо бажаєте получати найновіші верÑÑ–Ñ— в першу чергу:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/uk_UA.md b/app/src/main/play/uk_UA/whatsnew index f12ebadf2..f12ebadf2 100644 --- a/changelog/uk_UA.md +++ b/app/src/main/play/uk_UA/whatsnew diff --git a/app/src/main/play/vi/listing/fulldescription b/app/src/main/play/vi/listing/fulldescription new file mode 100644 index 000000000..87b477fdc --- /dev/null +++ b/app/src/main/play/vi/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> +But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. + +Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. + +<b>All features:</b><br> +IMPORT, ORGANIZE AND PLAY<br> +• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> +• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> +• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> +• Access password-protected feeds and episodes<br> +• Take advantage of paged feeds (www.podlove.org/paged-feeds) + +KEEP TRACK, SHARE & APPRECIATE<br> +• Keep track of the best of the best by marking episodes as favourites<br> +• Find that one episode through the playback history or by searching (titles and shownotes)<br> +• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> +• Support content creators with Flattr integration including automatic flattring + +CONTROL THE SYSTEM<br> +• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> +• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> +• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adapt to your environment using the light and dark theme<br> +• Back-up your subscriptions with the gPodder.net integration and OPML export + +<b>Join the AntennaPod community!</b><br> +AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! + +GitHub is the place to go for feature requests, bug reports and code contributions:<br> +https://www.github.com/AntennaPod/AntennaPod + +Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> +https://groups.google.com/forum/#!forum/antennapod + +Have a question or want to give us feedback? +https://twitter.com/@AntennaPod + +Transifex is the place to help with translations:<br> +https://www.transifex.com/antennapod/antennapod + +Check out our Beta Testing programme to get the latest features first:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/vi.md b/app/src/main/play/vi/whatsnew index 8f2618b8f..8f2618b8f 100644 --- a/changelog/vi.md +++ b/app/src/main/play/vi/whatsnew diff --git a/app/src/main/play/vi_VN/listing/fulldescription b/app/src/main/play/vi_VN/listing/fulldescription new file mode 100644 index 000000000..87b477fdc --- /dev/null +++ b/app/src/main/play/vi_VN/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> +But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. + +Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. + +<b>All features:</b><br> +IMPORT, ORGANIZE AND PLAY<br> +• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> +• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> +• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> +• Access password-protected feeds and episodes<br> +• Take advantage of paged feeds (www.podlove.org/paged-feeds) + +KEEP TRACK, SHARE & APPRECIATE<br> +• Keep track of the best of the best by marking episodes as favourites<br> +• Find that one episode through the playback history or by searching (titles and shownotes)<br> +• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> +• Support content creators with Flattr integration including automatic flattring + +CONTROL THE SYSTEM<br> +• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> +• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> +• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adapt to your environment using the light and dark theme<br> +• Back-up your subscriptions with the gPodder.net integration and OPML export + +<b>Join the AntennaPod community!</b><br> +AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! + +GitHub is the place to go for feature requests, bug reports and code contributions:<br> +https://www.github.com/AntennaPod/AntennaPod + +Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> +https://groups.google.com/forum/#!forum/antennapod + +Have a question or want to give us feedback? +https://twitter.com/@AntennaPod + +Transifex is the place to help with translations:<br> +https://www.transifex.com/antennapod/antennapod + +Check out our Beta Testing programme to get the latest features first:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/vi_VN.md b/app/src/main/play/vi_VN/whatsnew index 8f2618b8f..8f2618b8f 100644 --- a/changelog/vi_VN.md +++ b/app/src/main/play/vi_VN/whatsnew diff --git a/app/src/main/play/zh-CN/listing/fulldescription b/app/src/main/play/zh-CN/listing/fulldescription new file mode 100644 index 000000000..932b5ba3a --- /dev/null +++ b/app/src/main/play/zh-CN/listing/fulldescription @@ -0,0 +1,20 @@ +AntennaPod 是一款开æºæ’客管ç†è½¯ä»¶, æä¾› Android 2.3.3 åŠä»¥ä¸Šå¹³å°è¿è¡Œ. 它æä¾›äº†æ‰€æœ‰ä½ æ‰€æœŸæœ›çš„æ’客基本功能, 例如在线æµåª’体和下载收å¬æ›²ç›®, 以åŠè‡ªåŠ¨åˆ·æ–°æ‰€æœ‰è®¢é˜…å’Œæ·»åŠ åˆ°æ’放列表. æ¤å¤–, AntennaPod 支æŒåº”用内 Flattr æ’客和节目表. + +So far the following features are implemented: + +* 在线æµåª’体和下载收å¬æ›²ç›® +* å˜é€Ÿæ’放 (éœ€è¦ Presto 声音库或者 Prestissimo) +* æ”¯æŒ Atom å’Œ RSS 订阅 +* 支æŒåŠ 密的订阅 +* Support for searching iTunes listings +* OPML 文件导入导出 +* Flattr integration including automatic flattring +* æ’放器主å±å¹•çª—å£å°éƒ¨ä»¶ (Widget) +* æœç´¢ +* 自动订阅更新 +* 自动下载新曲目 +* ç¡çœ 计时器 +* 访问 gpodder.net æ’客目录 +* åŒæ¥ gpodder.net 订阅æœåŠ¡ +* Supports MP3 chapters, VorbisComment chapters and Podlove Simple Chapters +* Supports paged feeds (http://podlove.org/paged-feeds/)
\ No newline at end of file diff --git a/app/src/main/play/zh-CN/listing/shortdescription b/app/src/main/play/zh-CN/listing/shortdescription new file mode 100644 index 000000000..4eceefbb7 --- /dev/null +++ b/app/src/main/play/zh-CN/listing/shortdescription @@ -0,0 +1 @@ +Easy-to-use, flexible and open-source podcast manager and player
\ No newline at end of file diff --git a/app/src/main/play/zh-CN/listing/title b/app/src/main/play/zh-CN/listing/title new file mode 100644 index 000000000..31552f353 --- /dev/null +++ b/app/src/main/play/zh-CN/listing/title @@ -0,0 +1 @@ +AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/zh-CN/listing/video b/app/src/main/play/zh-CN/listing/video new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/app/src/main/play/zh-CN/listing/video diff --git a/app/src/main/play/zh-CN/whatsnew b/app/src/main/play/zh-CN/whatsnew new file mode 100644 index 000000000..a65bddbbb --- /dev/null +++ b/app/src/main/play/zh-CN/whatsnew @@ -0,0 +1,11 @@ +* New features: + * Subscription overview + * Proxy support + * Statistics + * Manual gpodder.net sync +* Fixes: + * Audioplayer controls + * Audio ducking + * Video control fade-out + * External media controls + * Feed parsing
\ No newline at end of file diff --git a/app/src/main/play/zh/listing/fulldescription b/app/src/main/play/zh/listing/fulldescription new file mode 100644 index 000000000..87b477fdc --- /dev/null +++ b/app/src/main/play/zh/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> +But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. + +Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. + +<b>All features:</b><br> +IMPORT, ORGANIZE AND PLAY<br> +• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> +• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> +• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> +• Access password-protected feeds and episodes<br> +• Take advantage of paged feeds (www.podlove.org/paged-feeds) + +KEEP TRACK, SHARE & APPRECIATE<br> +• Keep track of the best of the best by marking episodes as favourites<br> +• Find that one episode through the playback history or by searching (titles and shownotes)<br> +• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> +• Support content creators with Flattr integration including automatic flattring + +CONTROL THE SYSTEM<br> +• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> +• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> +• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adapt to your environment using the light and dark theme<br> +• Back-up your subscriptions with the gPodder.net integration and OPML export + +<b>Join the AntennaPod community!</b><br> +AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! + +GitHub is the place to go for feature requests, bug reports and code contributions:<br> +https://www.github.com/AntennaPod/AntennaPod + +Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> +https://groups.google.com/forum/#!forum/antennapod + +Have a question or want to give us feedback? +https://twitter.com/@AntennaPod + +Transifex is the place to help with translations:<br> +https://www.transifex.com/antennapod/antennapod + +Check out our Beta Testing programme to get the latest features first:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/zh_CN/listing/fulldescription b/app/src/main/play/zh_CN/listing/fulldescription new file mode 100644 index 000000000..6f2a6209e --- /dev/null +++ b/app/src/main/play/zh_CN/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod 是æ’客管ç†å’Œæ’æ”¾å·¥å…·ï¼Œä½¿å¾—ä½ å³åˆ»æ”¶å¬åˆ°æ•°ç™¾ä¸‡æ¥è‡ªä»Žä¸ªäººæ’客制作者到类似BBCã€NPRå’ŒCNNç‰å¤§åž‹å‡ºç‰ˆæœºæž„çš„å…费或付费æ’客。通过 iTunes æ•°æ®åº“ã€OPML 文件或简å•çš„ RSS 地å€ï¼Œä½ å¯ä»¥è‡ªç”±åœ°æ·»åŠ ã€å¯¼å…¥å’Œå¯¼å‡ºæ’客订阅æµã€‚通过指定次数ã€é—´éš”时间和 WIFI 网络的下载以åŠåŸºäºŽä¸ªäººå–œå¥½å’Œå»¶è¿Ÿåˆ 除的设置,功能强大的智能控制åšåˆ°äº†çœåŠ›ã€çœç”µå’Œçœæµé‡ã€‚<br> +但最é‡è¦çš„åœ¨äºŽï¼Œä½ å¯ä»¥é€‰æ‹©ä¸‹è½½ã€ä¸²æµæˆ–åŠ å…¥é˜Ÿåˆ—ç‰æ–¹å¼æ”¶å¬èŠ‚目,并使用调节回放速度ã€ç« 节跳转和定时ç¡çœ çš„è¾…åŠ©åŠŸèƒ½ã€‚ä½ ç”šè‡³å¯ä»¥é€šè¿‡ Flattr 集æˆåŠŸèƒ½å‘å†…å®¹åˆ›ä½œè€…è¡¨è¾¾ä½ è¡·å¿ƒçš„æ„Ÿè°¢ã€‚ + +AntennaPod 是一个由æ’客爱好者开å‘,在多ç§æ„义下“自由â€çš„软件——开æºã€å…费并且没有广告。 + +<b>特性包括:</b><br> +导入,组织和æ’放<br> +• 通过 iTunes,gPodder.net,OPML文件,RSS或Atomé“¾æŽ¥æ·»åŠ å’Œå¯¼å…¥è®¢é˜… +• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> +• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> +• Access password-protected feeds and episodes<br> +• Take advantage of paged feeds (www.podlove.org/paged-feeds) + +KEEP TRACK, SHARE & APPRECIATE<br> +• Keep track of the best of the best by marking episodes as favourites<br> +• Find that one episode through the playback history or by searching (titles and shownotes)<br> +• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> +• Support content creators with Flattr integration including automatic flattring + +CONTROL THE SYSTEM<br> +• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> +• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> +• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adapt to your environment using the light and dark theme<br> +• Back-up your subscriptions with the gPodder.net integration and OPML export + +<b>Join the AntennaPod community!</b><br> +AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! + +GitHub is the place to go for feature requests, bug reports and code contributions:<br> +https://www.github.com/AntennaPod/AntennaPod + +Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> +https://groups.google.com/forum/#!forum/antennapod + +Have a question or want to give us feedback? +https://twitter.com/@AntennaPod + +Transifex is the place to help with translations:<br> +https://www.transifex.com/antennapod/antennapod + +Check out our Beta Testing programme to get the latest features first:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/changelog/zh_CN.md b/app/src/main/play/zh_CN/whatsnew index 6ecca532c..6ecca532c 100644 --- a/changelog/zh_CN.md +++ b/app/src/main/play/zh_CN/whatsnew diff --git a/app/src/main/play/zh_HK/listing/fulldescription b/app/src/main/play/zh_HK/listing/fulldescription new file mode 100644 index 000000000..87b477fdc --- /dev/null +++ b/app/src/main/play/zh_HK/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> +But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. + +Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. + +<b>All features:</b><br> +IMPORT, ORGANIZE AND PLAY<br> +• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> +• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> +• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> +• Access password-protected feeds and episodes<br> +• Take advantage of paged feeds (www.podlove.org/paged-feeds) + +KEEP TRACK, SHARE & APPRECIATE<br> +• Keep track of the best of the best by marking episodes as favourites<br> +• Find that one episode through the playback history or by searching (titles and shownotes)<br> +• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> +• Support content creators with Flattr integration including automatic flattring + +CONTROL THE SYSTEM<br> +• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> +• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> +• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adapt to your environment using the light and dark theme<br> +• Back-up your subscriptions with the gPodder.net integration and OPML export + +<b>Join the AntennaPod community!</b><br> +AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! + +GitHub is the place to go for feature requests, bug reports and code contributions:<br> +https://www.github.com/AntennaPod/AntennaPod + +Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> +https://groups.google.com/forum/#!forum/antennapod + +Have a question or want to give us feedback? +https://twitter.com/@AntennaPod + +Transifex is the place to help with translations:<br> +https://www.transifex.com/antennapod/antennapod + +Check out our Beta Testing programme to get the latest features first:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/app/src/main/play/zh_TW/listing/fulldescription b/app/src/main/play/zh_TW/listing/fulldescription new file mode 100644 index 000000000..87b477fdc --- /dev/null +++ b/app/src/main/play/zh_TW/listing/fulldescription @@ -0,0 +1,43 @@ +AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> +But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. + +Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. + +<b>All features:</b><br> +IMPORT, ORGANIZE AND PLAY<br> +• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> +• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> +• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> +• Access password-protected feeds and episodes<br> +• Take advantage of paged feeds (www.podlove.org/paged-feeds) + +KEEP TRACK, SHARE & APPRECIATE<br> +• Keep track of the best of the best by marking episodes as favourites<br> +• Find that one episode through the playback history or by searching (titles and shownotes)<br> +• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> +• Support content creators with Flattr integration including automatic flattring + +CONTROL THE SYSTEM<br> +• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> +• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> +• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> +• Adapt to your environment using the light and dark theme<br> +• Back-up your subscriptions with the gPodder.net integration and OPML export + +<b>Join the AntennaPod community!</b><br> +AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! + +GitHub is the place to go for feature requests, bug reports and code contributions:<br> +https://www.github.com/AntennaPod/AntennaPod + +Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> +https://groups.google.com/forum/#!forum/antennapod + +Have a question or want to give us feedback? +https://twitter.com/@AntennaPod + +Transifex is the place to help with translations:<br> +https://www.transifex.com/antennapod/antennapod + +Check out our Beta Testing programme to get the latest features first:<br> +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/app/src/main/res/layout-v14/time_dialog.xml b/app/src/main/res/layout-v14/time_dialog.xml index 06c2cce14..ba4249268 100644 --- a/app/src/main/res/layout-v14/time_dialog.xml +++ b/app/src/main/res/layout-v14/time_dialog.xml @@ -33,26 +33,34 @@ </LinearLayout> <LinearLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="vertical"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:text="@string/timer_about_to_expire_label" + android:textSize="16sp" /> + + <CheckBox + android:id="@+id/cbShakeToReset" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/shake_to_reset_label" /> + + <CheckBox + android:id="@+id/cbVibrate" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/timer_vibration_label" /> + + <CheckBox + android:id="@+id/chAutoEnable" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:orientation="vertical"> - - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginTop="8dp" - android:textSize="16sp" - android:text="@string/timer_about_to_expire_label"/> - - <CheckBox android:id="@+id/cbShakeToReset" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/shake_to_reset_label"/> - - <CheckBox android:id="@+id/cbVibrate" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/timer_vibration_label"/> + android:text="@string/auto_enable_label" /> </LinearLayout> diff --git a/app/src/main/res/layout/addfeed.xml b/app/src/main/res/layout/addfeed.xml index dff24c650..33951e060 100644 --- a/app/src/main/res/layout/addfeed.xml +++ b/app/src/main/res/layout/addfeed.xml @@ -7,18 +7,18 @@ <LinearLayout android:layout_width="match_parent" - android:layout_height="match_parent" - android:paddingTop="8dp" + android:layout_height="wrap_content" + android:orientation="vertical" + android:paddingBottom="8dp" android:paddingLeft="16dp" android:paddingRight="16dp" - android:paddingBottom="8dp" - android:orientation="vertical"> + android:paddingTop="8dp"> <TextView android:id="@+id/txtvPodcastDirectories" + style="@style/AntennaPod.TextView.Heading" android:layout_width="match_parent" android:layout_height="wrap_content" - style="@style/AntennaPod.TextView.Heading" android:text="@string/podcastdirectories_label"/> <TextView @@ -26,83 +26,73 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/podcastdirectories_descr" - android:textSize="@dimen/text_size_medium" - android:layout_marginTop="4dp"/> + android:textSize="@dimen/text_size_medium"/> <Button android:id="@+id/butSearchItunes" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginTop="8dp" + android:layout_marginTop="4dp" android:text="@string/search_itunes_label"/> <Button + android:id="@+id/butSearchFyyd" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/search_fyyd_label"/> + + <Button android:id="@+id/butBrowseGpoddernet" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginTop="8dp" android:text="@string/browse_gpoddernet_label"/> - <View - android:id="@+id/divider1" - android:layout_width="match_parent" - android:layout_height="1dp" - android:layout_margin="16dp" - android:background="?android:attr/listDivider"/> + <View style="@style/Divider"/> <TextView android:id="@+id/txtvFeedurl" + style="@style/AntennaPod.TextView.Heading" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_below="@id/divider1" - style="@style/AntennaPod.TextView.Heading" android:text="@string/txtvfeedurl_label"/> <EditText android:id="@+id/etxtFeedurl" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginTop="4dp" - android:hint="@string/etxtFeedurlHint" - android:inputType="textUri" + android:cursorVisible="true" android:focusable="true" android:focusableInTouchMode="true" - android:cursorVisible="true"/> + android:hint="@string/etxtFeedurlHint" + android:inputType="textUri"/> <Button android:id="@+id/butConfirm" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginTop="8dp" android:text="@string/confirm_label"/> - <View - android:id="@+id/divider2" - android:layout_width="match_parent" - android:layout_height="1dp" - android:layout_margin="16dp" - android:background="?android:attr/listDivider"/> + <View style="@style/Divider"/> <TextView android:id="@+id/txtvOpmlImport" + style="@style/AntennaPod.TextView.Heading" android:layout_width="match_parent" android:layout_height="wrap_content" - style="@style/AntennaPod.TextView.Heading" android:text="@string/opml_import_label"/> <TextView android:id="@+id/txtvOpmlImportExpl" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginTop="4dp" - android:textSize="@dimen/text_size_medium" - android:text="@string/opml_import_txtv_button_lable"/> + android:text="@string/opml_import_txtv_button_lable" + android:textSize="@dimen/text_size_medium"/> <Button android:id="@+id/butOpmlImport" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginTop="8dp" + android:layout_marginTop="4dp" android:text="@string/opml_import_label"/> </LinearLayout> diff --git a/app/src/main/res/layout/gpodnetauth_credentials.xml b/app/src/main/res/layout/gpodnetauth_credentials.xml index 13c5977f8..a290b682b 100644 --- a/app/src/main/res/layout/gpodnetauth_credentials.xml +++ b/app/src/main/res/layout/gpodnetauth_credentials.xml @@ -33,7 +33,11 @@ android:layout_margin="8dp" android:focusable="true" android:focusableInTouchMode="true" - android:cursorVisible="true"/> + android:cursorVisible="true" + android:maxLines="1" + android:inputType="text" + android:imeOptions="actionNext" + android:nextFocusForward="@id/etxtPassword"/> <EditText android:id="@+id/etxtPassword" @@ -45,7 +49,9 @@ android:layout_margin="8dp" android:focusable="true" android:focusableInTouchMode="true" - android:cursorVisible="true"/> + android:cursorVisible="true" + android:imeOptions="actionGo" + android:imeActionLabel="@string/gpodnetauth_login_butLabel"/> <Button android:id="@+id/butLogin" diff --git a/app/src/main/res/layout/nav_list.xml b/app/src/main/res/layout/nav_list.xml index 9fcf9d9fc..7e72bb39b 100644 --- a/app/src/main/res/layout/nav_list.xml +++ b/app/src/main/res/layout/nav_list.xml @@ -1,7 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?> - -<RelativeLayout - xmlns:android="http://schemas.android.com/apk/res/android" +<?xml version='1.0' encoding='utf-8'?> +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/nav_layout" android:layout_width="@dimen/drawer_width" @@ -23,8 +21,6 @@ android:id="@+id/imgvCover" android:layout_width="@dimen/thumbnail_length_navlist" android:layout_height="@dimen/thumbnail_length_navlist" - android:layout_alignParentLeft="true" - android:layout_centerVertical="true" android:layout_marginBottom="4dp" android:layout_marginLeft="@dimen/listitem_icon_leftpadding" android:layout_marginTop="4dp" @@ -34,8 +30,8 @@ android:padding="8dp" android:scaleType="centerCrop" android:src="?attr/ic_settings" - tools:src="@android:drawable/sym_def_app_icon" - tools:background="@android:color/holo_orange_dark" /> + tools:background="@android:color/holo_orange_dark" + tools:src="@android:drawable/sym_def_app_icon"></ImageView> <TextView android:layout_width="wrap_content" @@ -47,16 +43,15 @@ android:text="@string/settings_label" android:textColor="?android:attr/textColorPrimary" android:textSize="@dimen/text_size_navdrawer" - tools:background="@android:color/holo_green_light"/> - + tools:background="@android:color/holo_green_light" /> </LinearLayout> <View android:id="@+id/divider" android:layout_width="@dimen/drawer_width" android:layout_height="1dp" - android:layout_centerVertical="true" android:layout_above="@id/nav_settings" + android:layout_centerVertical="true" android:background="?android:attr/listDivider" tools:background="@android:color/holo_red_dark" /> @@ -64,7 +59,6 @@ android:id="@+id/nav_list" android:layout_width="@dimen/drawer_width" android:layout_height="wrap_content" - android:layout_weight="1" android:layout_above="@id/divider" android:layout_alignParentTop="true" android:choiceMode="singleChoice" @@ -74,7 +68,6 @@ android:paddingBottom="@dimen/list_vertical_padding" android:paddingTop="@dimen/list_vertical_padding" android:scrollbarStyle="outsideOverlay" - tools:listitem="@layout/nav_listitem" - tools:background="@android:color/holo_purple" /> - + tools:background="@android:color/holo_purple" + tools:listitem="@layout/nav_listitem"></ListView> </RelativeLayout> diff --git a/app/src/main/res/layout/simplechapter_item.xml b/app/src/main/res/layout/simplechapter_item.xml index fae6bac8c..21bbc9545 100644 --- a/app/src/main/res/layout/simplechapter_item.xml +++ b/app/src/main/res/layout/simplechapter_item.xml @@ -53,6 +53,16 @@ tools:text="Link" tools:background="@android:color/holo_green_dark" /> + <TextView + android:id="@+id/txtvDuration" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:focusable="false" + android:focusableInTouchMode="false" + android:maxLines="1" + tools:text="Duration" + tools:background="@android:color/holo_green_dark" /> + </LinearLayout> <include layout="@layout/vertical_list_divider" /> diff --git a/app/src/main/res/layout/statistics_mode_select_dialog.xml b/app/src/main/res/layout/statistics_mode_select_dialog.xml new file mode 100644 index 000000000..8f8e1e657 --- /dev/null +++ b/app/src/main/res/layout/statistics_mode_select_dialog.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<RadioGroup xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:padding="16dp"> + + <TextView + android:text="@string/statistics_speed_not_counted" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="16dp"/> + + <RadioButton + android:id="@+id/statistics_mode_normal" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/statistics_mode_normal"/> + + <RadioButton + android:id="@+id/statistics_mode_count_all" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/statistics_mode_count_all"/> +</RadioGroup> diff --git a/app/src/main/res/layout/subscription_item.xml b/app/src/main/res/layout/subscription_item.xml index 19b9943e4..8f0539dfa 100644 --- a/app/src/main/res/layout/subscription_item.xml +++ b/app/src/main/res/layout/subscription_item.xml @@ -1,7 +1,7 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version='1.0' encoding='utf-8'?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> @@ -10,31 +10,28 @@ android:id="@+id/imgvCover" android:layout_width="fill_parent" android:layout_height="fill_parent" - android:layout_centerHorizontal="true" - android:layout_centerVertical="true" android:scaleType="centerCrop" - tools:src="@drawable/ic_launcher" /> + tools:src="@drawable/ic_launcher"> + </de.danoeh.antennapod.view.SquareImageView> <com.joanzapata.iconify.widget.IconTextView android:id="@+id/txtvTitle" android:layout_width="match_parent" android:layout_height="match_parent" + android:background="@color/light_gray" android:ellipsize="end" android:gravity="center" - android:background="@color/light_gray" tools:text="@string/app_name" /> <jp.shts.android.library.TriangleLabelView android:id="@+id/triangleCountView" android:layout_width="match_parent" android:layout_height="match_parent" - android:layout_alignParentRight="true" - android:layout_alignParentTop="true" + android:layout_gravity="right|top" app:backgroundColor="@color/antennapod_blue" app:corner="rightTop" app:primaryText="Test" app:primaryTextColor="@color/white" - app:primaryTextSize="12sp" - android:layout_gravity="right|top"/> - + app:primaryTextSize="12sp"> + </jp.shts.android.library.TriangleLabelView> </FrameLayout> diff --git a/app/src/main/res/layout/time_dialog.xml b/app/src/main/res/layout/time_dialog.xml index b270e82f7..0290ce708 100644 --- a/app/src/main/res/layout/time_dialog.xml +++ b/app/src/main/res/layout/time_dialog.xml @@ -36,22 +36,30 @@ android:layout_height="wrap_content" android:orientation="vertical"> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginTop="8dp" - android:textSize="16sp" - android:text="@string/timer_about_to_expire_label"/> - - <CheckBox android:id="@+id/cbShakeToReset" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/shake_to_reset_label"/> - - <CheckBox android:id="@+id/cbVibrate" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/timer_vibration_label"/> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:text="@string/timer_about_to_expire_label" + android:textSize="16sp" /> + + <CheckBox + android:id="@+id/cbShakeToReset" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/shake_to_reset_label" /> + + <CheckBox + android:id="@+id/cbVibrate" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/timer_vibration_label" /> + + <CheckBox + android:id="@+id/chAutoEnable" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/auto_enable_label" /> </LinearLayout> diff --git a/app/src/main/res/menu/allepisodes_context.xml b/app/src/main/res/menu/allepisodes_context.xml index c5356535c..7398b9118 100644 --- a/app/src/main/res/menu/allepisodes_context.xml +++ b/app/src/main/res/menu/allepisodes_context.xml @@ -71,6 +71,10 @@ android:id="@+id/share_download_url_with_position_item" android:menuCategory="container" android:title="@string/share_item_url_with_position_label" /> + <item + android:id="@+id/share_file" + android:menuCategory="container" + android:title="@string/share_file_label" /> </menu> </item> diff --git a/app/src/main/res/menu/new_episodes.xml b/app/src/main/res/menu/episodes.xml index 1e1d7ab78..bbaabcd8b 100644 --- a/app/src/main/res/menu/new_episodes.xml +++ b/app/src/main/res/menu/episodes.xml @@ -24,4 +24,11 @@ custom:showAsAction="collapseActionView" android:icon="?attr/navigation_accept"/> -</menu>
\ No newline at end of file + <item + android:id="@+id/mark_all_seen_item" + android:title="@string/mark_all_seen_label" + android:menuCategory="container" + custom:showAsAction="collapseActionView" + android:icon="?attr/navigation_accept"/> + +</menu> diff --git a/app/src/main/res/menu/episodes_apply_action_options.xml b/app/src/main/res/menu/episodes_apply_action_options.xml index 3df88046d..c3f117386 100644 --- a/app/src/main/res/menu/episodes_apply_action_options.xml +++ b/app/src/main/res/menu/episodes_apply_action_options.xml @@ -46,6 +46,8 @@ android:title="@string/queued_label"/> <item android:id="@+id/check_not_queued" android:title="@string/not_queued_label"/> + <item android:id="@+id/check_has_media" + android:title="@string/has_media"/> </menu> </item> diff --git a/app/src/main/res/menu/feeditem_options.xml b/app/src/main/res/menu/feeditem_options.xml index 511758c2e..7e111d816 100644 --- a/app/src/main/res/menu/feeditem_options.xml +++ b/app/src/main/res/menu/feeditem_options.xml @@ -84,6 +84,10 @@ android:id="@+id/share_download_url_with_position_item" android:menuCategory="container" android:title="@string/share_item_url_with_position_label" /> + <item + android:id="@+id/share_file" + android:menuCategory="container" + android:title="@string/share_file_label" /> </menu> </item> diff --git a/app/src/main/res/menu/feeditemlist_context.xml b/app/src/main/res/menu/feeditemlist_context.xml index 271cb96a7..d3ec88bc7 100644 --- a/app/src/main/res/menu/feeditemlist_context.xml +++ b/app/src/main/res/menu/feeditemlist_context.xml @@ -73,6 +73,10 @@ android:id="@+id/share_download_url_with_position_item" android:menuCategory="container" android:title="@string/share_item_url_with_position_label" /> + <item + android:id="@+id/share_file" + android:menuCategory="container" + android:title="@string/share_file_label" /> </menu> </item> diff --git a/app/src/main/res/menu/feedlist.xml b/app/src/main/res/menu/feedlist.xml index ed03c08d6..0646dc70f 100644 --- a/app/src/main/res/menu/feedlist.xml +++ b/app/src/main/res/menu/feedlist.xml @@ -66,6 +66,12 @@ </item> <item + android:id="@+id/rename_item" + android:menuCategory="container" + android:title="@string/rename_feed_label" + custom:showAsAction="never" /> + + <item android:id="@+id/remove_item" android:icon="?attr/content_discard" android:menuCategory="container" diff --git a/app/src/main/res/menu/mediaplayer.xml b/app/src/main/res/menu/mediaplayer.xml index c4086bf5e..530eb3400 100644 --- a/app/src/main/res/menu/mediaplayer.xml +++ b/app/src/main/res/menu/mediaplayer.xml @@ -64,6 +64,10 @@ android:id="@+id/share_download_url_with_position_item" android:menuCategory="container" android:title="@string/share_item_url_with_position_label" /> + <item + android:id="@+id/share_file" + android:menuCategory="container" + android:title="@string/share_file_label" /> </menu> </item> <item diff --git a/app/src/main/res/menu/nav_feed_context.xml b/app/src/main/res/menu/nav_feed_context.xml index 4bf067d25..4da40441f 100644 --- a/app/src/main/res/menu/nav_feed_context.xml +++ b/app/src/main/res/menu/nav_feed_context.xml @@ -12,6 +12,11 @@ android:title="@string/mark_all_read_label" /> <item + android:id="@+id/rename_item" + android:menuCategory="container" + android:title="@string/rename_feed_label" /> + + <item android:id="@+id/remove_item" android:menuCategory="container" android:title="@string/remove_feed_label" /> diff --git a/app/src/main/res/menu/queue.xml b/app/src/main/res/menu/queue.xml index 01a11b10e..a5fe85865 100644 --- a/app/src/main/res/menu/queue.xml +++ b/app/src/main/res/menu/queue.xml @@ -36,47 +36,60 @@ <menu> <item - android:id="@+id/queue_sort_alpha" - android:title="@string/alpha"> + android:id="@+id/queue_sort_date" + android:title="@string/date"> <menu> <item - android:id="@+id/queue_sort_alpha_asc" + android:id="@+id/queue_sort_date_asc" android:title="@string/ascending"/> <item - android:id="@+id/queue_sort_alpha_desc" + android:id="@+id/queue_sort_date_desc" android:title="@string/descending"/> </menu> </item> <item - android:id="@+id/queue_sort_date" - android:title="@string/date"> + android:id="@+id/queue_sort_duration" + android:title="@string/duration"> <menu> <item - android:id="@+id/queue_sort_date_asc" + android:id="@+id/queue_sort_duration_asc" android:title="@string/ascending"/> <item - android:id="@+id/queue_sort_date_desc" + android:id="@+id/queue_sort_duration_desc" android:title="@string/descending"/> </menu> </item> <item - android:id="@+id/queue_sort_duration" - android:title="@string/duration"> + android:id="@+id/queue_sort_episode_title" + android:title="@string/episode_title"> <menu> <item - android:id="@+id/queue_sort_duration_asc" + android:id="@+id/queue_sort_episode_title_asc" android:title="@string/ascending"/> <item - android:id="@+id/queue_sort_duration_desc" + android:id="@+id/queue_sort_episode_title_desc" android:title="@string/descending"/> </menu> </item> + <item + android:id="@+id/queue_sort_feed_title" + android:title="@string/feed_title"> + + <menu> + <item + android:id="@+id/queue_sort_feed_title_asc" + android:title="@string/ascending"/> + <item + android:id="@+id/queue_sort_feed_title_desc" + android:title="@string/descending"/> + </menu> + </item> </menu> </item> diff --git a/app/src/main/res/menu/queue_context.xml b/app/src/main/res/menu/queue_context.xml index 3eb1d9d5e..e93d808c1 100644 --- a/app/src/main/res/menu/queue_context.xml +++ b/app/src/main/res/menu/queue_context.xml @@ -74,6 +74,10 @@ android:id="@+id/share_download_url_with_position_item" android:menuCategory="container" android:title="@string/share_item_url_with_position_label" /> + <item + android:id="@+id/share_file" + android:menuCategory="container" + android:title="@string/share_file_label" /> </menu> </item> <item diff --git a/app/src/main/res/menu/statistics.xml b/app/src/main/res/menu/statistics.xml new file mode 100644 index 000000000..6ecc70707 --- /dev/null +++ b/app/src/main/res/menu/statistics.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<menu xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:custom="http://schemas.android.com/apk/res-auto"> + + <item + android:id="@+id/statistics_mode" + android:icon="?attr/ic_filter" + android:title="@string/statistics_mode" + custom:showAsAction="never"> + </item> + +</menu> diff --git a/app/src/main/res/xml/automotive_app_desc.xml b/app/src/main/res/xml/automotive_app_desc.xml new file mode 100644 index 000000000..8f0a7c59c --- /dev/null +++ b/app/src/main/res/xml/automotive_app_desc.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<automotiveApp xmlns:android="http://schemas.android.com/apk/res/android"> + <uses name="media"/> +</automotiveApp>
\ No newline at end of file diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 57829e3e1..e81115627 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -74,7 +74,6 @@ android:key="prefQueueAddToFront" android:summary="@string/pref_queueAddToFront_sum" android:title="@string/pref_queueAddToFront_title"/> - /> </PreferenceCategory> <PreferenceCategory android:title="@string/playback_pref"> @@ -110,6 +109,20 @@ android:key="prefHardwareForwardButtonSkips" android:summary="@string/pref_hardwareForwardButtonSkips_sum" android:title="@string/pref_hardwareForwardButtonSkips_title"/> + <Preference + android:key="prefPlaybackFastForwardDeltaLauncher" + android:summary="@string/pref_fast_forward_sum" + android:title="@string/pref_fast_forward" /> + <Preference + android:key="prefPlaybackRewindDeltaLauncher" + android:summary="@string/pref_rewind_sum" + android:title="@string/pref_rewind" /> + <de.danoeh.antennapod.preferences.SwitchCompatPreference + android:defaultValue="false" + android:enabled="true" + android:key="prefHardwarePreviousButtonRestarts" + android:summary="@string/pref_hardwarePreviousButtonRestarts_sum" + android:title="@string/pref_hardwarePreviousButtonRestarts_title"/> <de.danoeh.antennapod.preferences.SwitchCompatPreference android:defaultValue="true" android:enabled="true" @@ -123,6 +136,12 @@ android:summary="@string/pref_skip_keeps_episodes_sum" android:title="@string/pref_skip_keeps_episodes_title"/> <de.danoeh.antennapod.preferences.SwitchCompatPreference + android:defaultValue="true" + android:enabled="true" + android:key="prefFavoriteKeepsEpisode" + android:summary="@string/pref_favorite_keeps_episodes_sum" + android:title="@string/pref_favorite_keeps_episodes_title"/> + <de.danoeh.antennapod.preferences.SwitchCompatPreference android:defaultValue="false" android:enabled="true" android:key="prefAutoDelete" @@ -140,7 +159,6 @@ android:key="prefPlaybackSpeedLauncher" android:summary="@string/pref_playback_speed_sum" android:title="@string/pref_playback_speed_title" /> - <de.danoeh.antennapod.preferences.SwitchCompatPreference android:defaultValue="false" android:enabled="true" @@ -156,6 +174,12 @@ </PreferenceCategory> <PreferenceCategory android:title="@string/network_pref"> + <de.danoeh.antennapod.preferences.SwitchCompatPreference + android:defaultValue="true" + android:enabled="true" + android:key="prefEnqueueDownloaded" + android:summary="@string/pref_enqueue_downloaded_summary" + android:title="@string/pref_enqueue_downloaded_title" /> <Preference android:key="prefAutoUpdateIntervall" android:summary="@string/pref_autoUpdateIntervallOrTime_sum" @@ -201,6 +225,11 @@ android:summary="@string/pref_automatic_download_on_battery_sum" android:defaultValue="true"/> <de.danoeh.antennapod.preferences.SwitchCompatPreference + android:key="prefEnableAutoDownloadOnMobile" + android:title="@string/pref_autodl_allow_on_mobile_title" + android:summary="@string/pref_autodl_allow_on_mobile_sum" + android:defaultValue="false"/> + <de.danoeh.antennapod.preferences.SwitchCompatPreference android:key="prefEnableAutoDownloadWifiFilter" android:title="@string/pref_autodl_wifi_filter_title" android:summary="@string/pref_autodl_wifi_filter_sum"/> @@ -233,7 +262,7 @@ android:title="@string/pref_revokeAccess_title"/> </PreferenceScreen> <PreferenceScreen - android:key="prefFlattrSettings" + android:key="prefGpodderSettings" android:title="@string/gpodnet_main_label"> <PreferenceScreen @@ -248,14 +277,23 @@ android:summary="@string/pref_gpodnet_setlogin_information_sum"/> <Preference android:key="pref_gpodnet_sync" - android:title="@string/pref_gpodnet_sync_title" - android:summary="@string/pref_gpodnet_sync_sum"/> + android:title="@string/pref_gpodnet_sync_changes_title" + android:summary="@string/pref_gpodnet_sync_changes_sum"/> + <Preference + android:key="pref_gpodnet_force_full_sync" + android:title="@string/pref_gpodnet_full_sync_title" + android:summary="@string/pref_gpodnet_full_sync_sum"/> <Preference android:key="pref_gpodnet_logout" android:title="@string/pref_gpodnet_logout_title"/> <Preference android:key="pref_gpodnet_hostname" android:title="@string/pref_gpodnet_sethostname_title"/> + <de.danoeh.antennapod.preferences.SwitchCompatPreference + android:key="pref_gpodnet_notifications" + android:title="@string/pref_gpodnet_notifications_title" + android:summary="@string/pref_gpodnet_notifications_sum" + android:defaultValue="true"/> </PreferenceScreen> </PreferenceCategory> <PreferenceCategory android:title="@string/storage_pref"> @@ -275,6 +313,9 @@ android:key="prefOpmlExport" android:title="@string/opml_export_label"/> <Preference + android:key="prefHtmlExport" + android:title="@string/html_export_label"/> + <Preference android:key="statistics" android:title="@string/statistics_label"/> </PreferenceCategory> diff --git a/app/src/main/templates/about.html b/app/src/main/templates/about.html index 5c7a3cbd0..400727c46 100644 --- a/app/src/main/templates/about.html +++ b/app/src/main/templates/about.html @@ -52,7 +52,7 @@ <p>Created by Daniel Oeh</p> - <p>Copyright © 2015 AntennaPod Contributors <a href="CONTRIBUTORS.txt">(View)</a></p> + <p>Copyright © 2012-@year@ AntennaPod Contributors <a href="CONTRIBUTORS.txt">(View)</a></p> <p>Licensed under the MIT License <a href="LICENSE.txt">(View)</a></p> </div> diff --git a/app/src/play/AndroidManifest.xml b/app/src/play/AndroidManifest.xml new file mode 100644 index 000000000..dcf82e44a --- /dev/null +++ b/app/src/play/AndroidManifest.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="de.danoeh.antennapod"> + + <application> + <meta-data + android:name="com.google.android.gms.version" + android:value="@integer/google_play_services_version" /> + </application> + +</manifest> diff --git a/app/src/main/java/de/danoeh/antennapod/activity/CastEnabledActivity.java b/app/src/play/java/de/danoeh/antennapod/activity/CastEnabledActivity.java index b8856c295..87304b3d6 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/CastEnabledActivity.java +++ b/app/src/play/java/de/danoeh/antennapod/activity/CastEnabledActivity.java @@ -67,9 +67,16 @@ public abstract class CastEnabledActivity extends AppCompatActivity @CallSuper public boolean onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); - mediaRouteActionProvider = castManager - .addMediaRouterButton(menu.findItem(R.id.media_route_menu_item)); - mediaRouteActionProvider.setEnabled(castButtonVisibilityManager.shouldEnable()); + MenuItem mediaRouteButton = menu.findItem(R.id.media_route_menu_item); + if (mediaRouteButton == null) { + Log.wtf(TAG, "MediaRoute item could not be found on the menu!", new Exception()); + mediaRouteActionProvider = null; + return true; + } + mediaRouteActionProvider = castManager.addMediaRouterButton(mediaRouteButton); + if (mediaRouteActionProvider != null) { + mediaRouteActionProvider.setEnabled(castButtonVisibilityManager.shouldEnable()); + } return true; } diff --git a/app/src/play/java/de/danoeh/antennapod/config/CastCallbackImpl.java b/app/src/play/java/de/danoeh/antennapod/config/CastCallbackImpl.java new file mode 100644 index 000000000..916b13a38 --- /dev/null +++ b/app/src/play/java/de/danoeh/antennapod/config/CastCallbackImpl.java @@ -0,0 +1,21 @@ +package de.danoeh.antennapod.config; + +import android.support.annotation.NonNull; +import android.support.v7.app.MediaRouteControllerDialogFragment; +import android.support.v7.app.MediaRouteDialogFactory; + +import de.danoeh.antennapod.core.CastCallbacks; +import de.danoeh.antennapod.fragment.CustomMRControllerDialogFragment; + +public class CastCallbackImpl implements CastCallbacks { + @Override + public MediaRouteDialogFactory getMediaRouterDialogFactory() { + return new MediaRouteDialogFactory() { + @NonNull + @Override + public MediaRouteControllerDialogFragment onCreateControllerDialogFragment() { + return new CustomMRControllerDialogFragment(); + } + }; + } +} diff --git a/app/src/play/java/de/danoeh/antennapod/dialog/CustomMRControllerDialog.java b/app/src/play/java/de/danoeh/antennapod/dialog/CustomMRControllerDialog.java new file mode 100644 index 000000000..7b07d3f84 --- /dev/null +++ b/app/src/play/java/de/danoeh/antennapod/dialog/CustomMRControllerDialog.java @@ -0,0 +1,483 @@ +package de.danoeh.antennapod.dialog; + +import android.app.PendingIntent; +import android.content.Context; +import android.content.res.Configuration; +import android.graphics.Bitmap; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.Bundle; +import android.os.RemoteException; +import android.support.annotation.NonNull; +import android.support.v4.media.MediaDescriptionCompat; +import android.support.v4.media.MediaMetadataCompat; +import android.support.v4.media.session.MediaControllerCompat; +import android.support.v4.media.session.MediaSessionCompat; +import android.support.v4.media.session.PlaybackStateCompat; +import android.support.v4.util.Pair; +import android.support.v4.view.MarginLayoutParamsCompat; +import android.support.v4.view.accessibility.AccessibilityEventCompat; +import android.support.v7.app.MediaRouteControllerDialog; +import android.support.v7.graphics.Palette; +import android.support.v7.media.MediaRouter; +import android.text.TextUtils; +import android.util.Log; +import android.util.TypedValue; +import android.view.View; +import android.view.ViewGroup; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityManager; +import android.widget.FrameLayout; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.target.Target; + +import java.util.concurrent.ExecutionException; + +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.core.glide.ApGlideSettings; +import rx.Observable; +import rx.Subscription; +import rx.android.schedulers.AndroidSchedulers; +import rx.schedulers.Schedulers; + +public class CustomMRControllerDialog extends MediaRouteControllerDialog { + public static final String TAG = "CustomMRContrDialog"; + + private MediaRouter mediaRouter; + private MediaSessionCompat.Token token; + + private ImageView artView; + private TextView titleView; + private TextView subtitleView; + private ImageButton playPauseButton; + private LinearLayout rootView; + + private boolean viewsCreated = false; + + private Subscription fetchArtSubscription; + + private MediaControllerCompat mediaController; + private MediaControllerCompat.Callback mediaControllerCallback; + + public CustomMRControllerDialog(Context context) { + this(context, 0); + } + + public CustomMRControllerDialog(Context context, int theme) { + super(context, theme); + mediaRouter = MediaRouter.getInstance(getContext()); + token = mediaRouter.getMediaSessionToken(); + try { + if (token != null) { + mediaController = new MediaControllerCompat(getContext(), token); + } + } catch (RemoteException e) { + Log.e(TAG, "Error creating media controller", e); + } + + if (mediaController != null) { + mediaControllerCallback = new MediaControllerCompat.Callback() { + @Override + public void onSessionDestroyed() { + if (mediaController != null) { + mediaController.unregisterCallback(mediaControllerCallback); + mediaController = null; + } + } + + @Override + public void onMetadataChanged(MediaMetadataCompat metadata) { + updateViews(); + } + + @Override + public void onPlaybackStateChanged(PlaybackStateCompat state) { + updateState(); + } + }; + mediaController.registerCallback(mediaControllerCallback); + } + } + + @Override + public View onCreateMediaControlView(Bundle savedInstanceState) { + boolean landscape = getContext().getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE; + if (landscape) { + /* + * When a horizontal LinearLayout measures itself, it first measures its children and + * settles their widths on the first pass, and only then figures out its height, never + * revisiting the widths measurements. + * When one has a child view that imposes a certain aspect ratio (such as an ImageView), + * then its width and height are related to each other, and so if one allows for a large + * height, then it will request for itself a large width as well. However, on the first + * child measurement, the LinearLayout imposes a very relaxed height bound, that the + * child uses to tell the width it wants, a value which the LinearLayout will interpret + * as final, even though the child will want to change it once a more restrictive height + * bound is imposed later. + * + * Our solution is, given that the heights of the children do not depend on their widths + * in this case, we first figure out the layout's height and only then perform the + * usual sequence of measurements. + * + * Note: this solution does not take into account any vertical paddings nor children's + * vertical margins in determining the height, as this View as well as its children are + * defined in code and no paddings/margins that would influence these computations are + * introduced. + * + * There were no resources online for this type of issue as far as I could gather. + */ + rootView = new LinearLayout(getContext()) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + // We'd like to find the overall height before adjusting the widths within the LinearLayout + int maxHeight = Integer.MIN_VALUE; + if (MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY) { + for (int i = 0; i < getChildCount(); i++) { + int height = Integer.MIN_VALUE; + View child = getChildAt(i); + ViewGroup.LayoutParams lp = child.getLayoutParams(); + // we only measure children whose layout_height is not MATCH_PARENT + if (lp.height >= 0) { + height = lp.height; + } else if (lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) { + child.measure(widthMeasureSpec, heightMeasureSpec); + height = child.getMeasuredHeight(); + } + maxHeight = Math.max(maxHeight, height); + } + } + if (maxHeight > 0) { + super.onMeasure(widthMeasureSpec, + MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.EXACTLY)); + } else { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + } + }; + rootView.setOrientation(LinearLayout.HORIZONTAL); + } else { + rootView = new LinearLayout(getContext()); + rootView.setOrientation(LinearLayout.VERTICAL); + } + FrameLayout.LayoutParams rootParams = new FrameLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT); + rootParams.setMargins(0, 0, 0, + getContext().getResources().getDimensionPixelSize(R.dimen.media_router_controller_bottom_margin)); + rootView.setLayoutParams(rootParams); + + // Start the session activity when a content item (album art, title or subtitle) is clicked. + View.OnClickListener onClickListener = v -> { + if (mediaController != null) { + PendingIntent pi = mediaController.getSessionActivity(); + if (pi != null) { + try { + pi.send(); + dismiss(); + } catch (PendingIntent.CanceledException e) { + Log.e(TAG, pi + " was not sent, it had been canceled."); + } + } + } + }; + + LinearLayout.LayoutParams artParams; + /* + * On portrait orientation, we want to limit the artView's height to 9/16 of the available + * width. Reason is that we need to choose the height wisely otherwise we risk the dialog + * being much larger than the screen, and there doesn't seem to be a good way to know the + * available height beforehand. + * + * On landscape orientation, we want to limit the artView's width to its available height. + * Otherwise, horizontal images would take too much space and severely restrict the space + * for episode title and play/pause button. + * + * Internal implementation of ImageView only uses the source image's aspect ratio, but we + * want to impose our own and fallback to the source image's when it is more favorable. + * Solutions were inspired, among other similar sources, on + * http://stackoverflow.com/questions/18077325/scale-image-to-fill-imageview-width-and-keep-aspect-ratio + */ + if (landscape) { + artView = new ImageView(getContext()) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int desiredWidth = widthMeasureSpec; + int desiredMeasureMode = MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY ? + MeasureSpec.EXACTLY : MeasureSpec.AT_MOST; + if (MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY) { + Drawable drawable = getDrawable(); + if (drawable != null) { + int intrHeight = drawable.getIntrinsicHeight(); + int intrWidth = drawable.getIntrinsicWidth(); + int originalHeight = MeasureSpec.getSize(heightMeasureSpec); + if (intrHeight < intrWidth) { + desiredWidth = MeasureSpec.makeMeasureSpec( + originalHeight, desiredMeasureMode); + } else { + desiredWidth = MeasureSpec.makeMeasureSpec( + Math.round((float) originalHeight * intrWidth / intrHeight), + desiredMeasureMode); + } + } + } + super.onMeasure(desiredWidth, heightMeasureSpec); + } + }; + artParams = new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.MATCH_PARENT); + MarginLayoutParamsCompat.setMarginStart(artParams, + getContext().getResources().getDimensionPixelSize(R.dimen.media_router_controller_playback_control_horizontal_spacing)); + } else { + artView = new ImageView(getContext()) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int desiredHeight = heightMeasureSpec; + if (MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY) { + Drawable drawable = getDrawable(); + if (drawable != null) { + int originalWidth = MeasureSpec.getSize(widthMeasureSpec); + int intrHeight = drawable.getIntrinsicHeight(); + int intrWidth = drawable.getIntrinsicWidth(); + float scale; + if (intrHeight*16 > intrWidth*9) { + // image is taller than 16:9 + scale = (float) originalWidth * 9 / 16 / intrHeight; + } else { + // image is more horizontal than 16:9 + scale = (float) originalWidth / intrWidth; + } + desiredHeight = MeasureSpec.makeMeasureSpec( + Math.round(intrHeight * scale), + MeasureSpec.EXACTLY); + } + } + super.onMeasure(widthMeasureSpec, desiredHeight); + } + }; + artParams = new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT); + } + // When we fetch the bitmap, we want to know if we should set a background color or not. + artView.setTag(landscape); + + artView.setScaleType(ImageView.ScaleType.FIT_CENTER); + artView.setOnClickListener(onClickListener); + + artView.setLayoutParams(artParams); + rootView.addView(artView); + + ViewGroup wrapper = rootView; + + if (landscape) { + // Here we wrap with a frame layout because we want to set different layout parameters + // for landscape orientation. + wrapper = new FrameLayout(getContext()); + wrapper.setLayoutParams(new LinearLayout.LayoutParams( + 0, + ViewGroup.LayoutParams.WRAP_CONTENT, 1f)); + rootView.addView(wrapper); + rootView.setWeightSum(1f); + } + + View playbackControlLayout = View.inflate(getContext(), R.layout.media_router_controller, wrapper); + + titleView = (TextView) playbackControlLayout.findViewById(R.id.mrc_control_title); + subtitleView = (TextView) playbackControlLayout.findViewById(R.id.mrc_control_subtitle); + playbackControlLayout.findViewById(R.id.mrc_control_title_container).setOnClickListener(onClickListener); + playPauseButton = (ImageButton) playbackControlLayout.findViewById(R.id.mrc_control_play_pause); + playPauseButton.setOnClickListener(v -> { + PlaybackStateCompat state; + if (mediaController != null && (state = mediaController.getPlaybackState()) != null) { + boolean isPlaying = state.getState() == PlaybackStateCompat.STATE_PLAYING; + if (isPlaying) { + mediaController.getTransportControls().pause(); + } else { + mediaController.getTransportControls().play(); + } + // Announce the action for accessibility. + AccessibilityManager accessibilityManager = (AccessibilityManager) + getContext().getSystemService(Context.ACCESSIBILITY_SERVICE); + if (accessibilityManager != null && accessibilityManager.isEnabled()) { + AccessibilityEvent event = AccessibilityEvent.obtain( + AccessibilityEventCompat.TYPE_ANNOUNCEMENT); + event.setPackageName(getContext().getPackageName()); + event.setClassName(getClass().getName()); + int resId = isPlaying ? + android.support.v7.mediarouter.R.string.mr_controller_pause : + android.support.v7.mediarouter.R.string.mr_controller_play; + event.getText().add(getContext().getString(resId)); + accessibilityManager.sendAccessibilityEvent(event); + } + } + }); + + viewsCreated = true; + updateViews(); + return rootView; + } + + @Override + public void onDetachedFromWindow() { + if (fetchArtSubscription != null) { + fetchArtSubscription.unsubscribe(); + fetchArtSubscription = null; + } + super.onDetachedFromWindow(); + } + + private void updateViews() { + if (!viewsCreated || token == null || mediaController == null) { + rootView.setVisibility(View.GONE); + return; + } + MediaMetadataCompat metadata = mediaController.getMetadata(); + MediaDescriptionCompat description = metadata == null ? null : metadata.getDescription(); + if (description == null) { + rootView.setVisibility(View.GONE); + return; + } + + PlaybackStateCompat state = mediaController.getPlaybackState(); + MediaRouter.RouteInfo route = MediaRouter.getInstance(getContext()).getSelectedRoute(); + + CharSequence title = description.getTitle(); + boolean hasTitle = !TextUtils.isEmpty(title); + CharSequence subtitle = description.getSubtitle(); + boolean hasSubtitle = !TextUtils.isEmpty(subtitle); + + boolean showTitle = false; + boolean showSubtitle = false; + if (route.getPresentationDisplay() != null && + route.getPresentationDisplay().getDisplayId() != MediaRouter.RouteInfo.PRESENTATION_DISPLAY_ID_NONE) { + // The user is currently casting screen. + titleView.setText(android.support.v7.mediarouter.R.string.mr_controller_casting_screen); + showTitle = true; + } else if (state == null || state.getState() == PlaybackStateCompat.STATE_NONE) { + // Show "No media selected" as we don't yet know the playback state. + // (Only exception is bluetooth where we don't show anything.) + if (!route.isBluetooth()) { + titleView.setText(android.support.v7.mediarouter.R.string.mr_controller_no_media_selected); + showTitle = true; + } + } else if (!hasTitle && !hasSubtitle) { + titleView.setText(android.support.v7.mediarouter.R.string.mr_controller_no_info_available); + showTitle = true; + } else { + if (hasTitle) { + titleView.setText(title); + showTitle = true; + } + if (hasSubtitle) { + subtitleView.setText(subtitle); + showSubtitle = true; + } + } + if (showSubtitle) { + titleView.setSingleLine(); + } else { + titleView.setMaxLines(2); + } + titleView.setVisibility(showTitle ? View.VISIBLE : View.GONE); + subtitleView.setVisibility(showSubtitle ? View.VISIBLE : View.GONE); + + updateState(); + + if(rootView.getVisibility() != View.VISIBLE) { + artView.setVisibility(View.GONE); + rootView.setVisibility(View.VISIBLE); + } + + if (fetchArtSubscription != null) { + fetchArtSubscription.unsubscribe(); + } + + fetchArtSubscription = Observable.fromCallable(() -> fetchArt(description)) + .subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(result -> { + fetchArtSubscription = null; + if (artView == null) { + return; + } + if (result.first != null) { + if (!((Boolean) artView.getTag())) { + artView.setBackgroundColor(result.second); + } + artView.setImageBitmap(result.first); + artView.setVisibility(View.VISIBLE); + } else { + artView.setVisibility(View.GONE); + } + }, error -> Log.e(TAG, Log.getStackTraceString(error))); + + } + + private void updateState() { + PlaybackStateCompat state; + if (!viewsCreated || mediaController == null || + (state = mediaController.getPlaybackState()) == null) { + return; + } + boolean isPlaying = state.getState() == PlaybackStateCompat.STATE_BUFFERING + || state.getState() == PlaybackStateCompat.STATE_PLAYING; + boolean supportsPlay = (state.getActions() & (PlaybackStateCompat.ACTION_PLAY + | PlaybackStateCompat.ACTION_PLAY_PAUSE)) != 0; + boolean supportsPause = (state.getActions() & (PlaybackStateCompat.ACTION_PAUSE + | PlaybackStateCompat.ACTION_PLAY_PAUSE)) != 0; + if (isPlaying && supportsPause) { + playPauseButton.setVisibility(View.VISIBLE); + playPauseButton.setImageResource(getThemeResource(getContext(), + android.support.v7.mediarouter.R.attr.mediaRoutePauseDrawable)); + playPauseButton.setContentDescription(getContext().getResources() + .getText(android.support.v7.mediarouter.R.string.mr_controller_pause)); + } else if (!isPlaying && supportsPlay) { + playPauseButton.setVisibility(View.VISIBLE); + playPauseButton.setImageResource(getThemeResource(getContext(), + android.support.v7.mediarouter.R.attr.mediaRoutePlayDrawable)); + playPauseButton.setContentDescription(getContext().getResources() + .getText(android.support.v7.mediarouter.R.string.mr_controller_play)); + } else { + playPauseButton.setVisibility(View.GONE); + } + } + + private static int getThemeResource(Context context, int attr) { + TypedValue value = new TypedValue(); + return context.getTheme().resolveAttribute(attr, value, true) ? value.resourceId : 0; + } + + private Pair<Bitmap, Integer> fetchArt(@NonNull MediaDescriptionCompat description) { + Bitmap iconBitmap = description.getIconBitmap(); + Uri iconUri = description.getIconUri(); + Bitmap art = null; + if (iconBitmap != null) { + art = iconBitmap; + } else if (iconUri != null) { + try { + art = Glide.with(getContext().getApplicationContext()) + .load(iconUri.toString()) + .asBitmap() + .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) + .into(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) + .get(); + } catch (InterruptedException | ExecutionException e) { + Log.e(TAG, "Image art load failed", e); + } + } + int backgroundColor = 0; + if (art != null && art.getWidth()*9 < art.getHeight()*16) { + // Portrait art requires dominant color as background color. + Palette palette = new Palette.Builder(art).maximumColorCount(1).generate(); + backgroundColor = palette.getSwatches().isEmpty() + ? 0 : palette.getSwatches().get(0).getRgb(); + } + return new Pair<>(art, backgroundColor); + } +} diff --git a/app/src/play/java/de/danoeh/antennapod/fragment/CustomMRControllerDialogFragment.java b/app/src/play/java/de/danoeh/antennapod/fragment/CustomMRControllerDialogFragment.java new file mode 100644 index 000000000..a960ec998 --- /dev/null +++ b/app/src/play/java/de/danoeh/antennapod/fragment/CustomMRControllerDialogFragment.java @@ -0,0 +1,15 @@ +package de.danoeh.antennapod.fragment; + +import android.content.Context; +import android.os.Bundle; +import android.support.v7.app.MediaRouteControllerDialog; +import android.support.v7.app.MediaRouteControllerDialogFragment; + +import de.danoeh.antennapod.dialog.CustomMRControllerDialog; + +public class CustomMRControllerDialogFragment extends MediaRouteControllerDialogFragment { + @Override + public MediaRouteControllerDialog onCreateControllerDialog(Context context, Bundle savedInstanceState) { + return new CustomMRControllerDialog(context); + } +} diff --git a/app/src/play/java/de/danoeh/antennapod/preferences/PreferenceControllerFlavorHelper.java b/app/src/play/java/de/danoeh/antennapod/preferences/PreferenceControllerFlavorHelper.java new file mode 100644 index 000000000..b9b4e891f --- /dev/null +++ b/app/src/play/java/de/danoeh/antennapod/preferences/PreferenceControllerFlavorHelper.java @@ -0,0 +1,31 @@ +package de.danoeh.antennapod.preferences; + +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.GoogleApiAvailability; + +import de.danoeh.antennapod.core.preferences.UserPreferences; + +/** + * Implements functions from PreferenceController that are flavor dependent. + */ +public class PreferenceControllerFlavorHelper { + + static void setupFlavoredUI(PreferenceController.PreferenceUI ui) { + //checks whether Google Play Services is installed on the device (condition necessary for Cast support) + ui.findPreference(UserPreferences.PREF_CAST_ENABLED).setOnPreferenceChangeListener((preference, o) -> { + if (o instanceof Boolean && ((Boolean) o)) { + final int googlePlayServicesCheck = GoogleApiAvailability.getInstance() + .isGooglePlayServicesAvailable(ui.getActivity()); + if (googlePlayServicesCheck == ConnectionResult.SUCCESS) { + return true; + } else { + GoogleApiAvailability.getInstance() + .getErrorDialog(ui.getActivity(), googlePlayServicesCheck, 0) + .show(); + return false; + } + } + return true; + }); + } +} diff --git a/app/src/play/res/layout/media_router_controller.xml b/app/src/play/res/layout/media_router_controller.xml new file mode 100644 index 000000000..9489173a3 --- /dev/null +++ b/app/src/play/res/layout/media_router_controller.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/mrc_playback_control" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingTop="@dimen/media_router_controller_playback_control_vertical_padding" + android:paddingBottom="@dimen/media_router_controller_playback_control_vertical_padding" + android:paddingLeft="@dimen/media_router_controller_playback_control_start_padding" + android:paddingStart="@dimen/media_router_controller_playback_control_start_padding" + android:paddingRight="@dimen/media_router_controller_playback_control_horizontal_spacing" + android:paddingEnd="@dimen/media_router_controller_playback_control_horizontal_spacing"> + <ImageButton android:id="@+id/mrc_control_play_pause" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginLeft="@dimen/media_router_controller_playback_control_horizontal_spacing" + android:layout_marginStart="@dimen/media_router_controller_playback_control_horizontal_spacing" + android:layout_alignParentRight="true" + android:layout_alignParentEnd="true" + android:contentDescription="@string/mr_controller_play" + android:background="?attr/selectableItemBackgroundBorderless"/> + + <LinearLayout android:id="@+id/mrc_control_title_container" + android:orientation="vertical" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" + android:layout_toLeftOf="@id/mrc_control_play_pause" + android:layout_toStartOf="@id/mrc_control_play_pause" + android:layout_centerVertical="true"> + <TextView android:id="@+id/mrc_control_title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="@style/TextAppearance.MediaRouter.PrimaryText"/> + <TextView android:id="@+id/mrc_control_subtitle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="@style/TextAppearance.MediaRouter.SecondaryText" + android:singleLine="true" /> + </LinearLayout> +</RelativeLayout> diff --git a/build.gradle b/build.gradle index 3eace8f8a..d0fee89c9 100644 --- a/build.gradle +++ b/build.gradle @@ -3,12 +3,13 @@ buildscript { repositories { jcenter() + mavenCentral() } dependencies { - classpath "com.android.tools.build:gradle:1.5.0" - classpath "me.tatarka:gradle-retrolambda:3.2.4" + classpath "com.android.tools.build:gradle:2.3.3" + classpath "me.tatarka:gradle-retrolambda:3.7.0" classpath "me.tatarka.retrolambda.projectlombok:lombok.ast:0.2.3.a2" - + classpath "com.github.triplet.gradle:play-publisher:1.1.4" // Exclude the version that the android plugin depends on. configurations.classpath.exclude group: "com.android.tools.external.lombok" } @@ -36,36 +37,42 @@ subprojects { } project.ext { - compileSdkVersion = 23 - buildToolsVersion = "23.0.2" + compileSdkVersion = 25 + buildToolsVersion = "25.0.3" minSdkVersion = 10 - targetSdkVersion = 23 + targetSdkVersion = 25 - supportVersion = "23.2.1" - commonsioVersion = "2.4" - commonslangVersion = "3.4" + supportVersion = "25.3.1" + commonsioVersion = "2.5" + commonslangVersion = "3.6" eventbusVersion = "2.4.0" - flattr4jVersion = "2.13" - glideVersion = "3.7.0" - glideOkhttpIntegrationVersion = "1.4.0" - iconifyVersion = "2.2.1" - jsoupVersion = "1.7.3" - materialDialogsVersion = "0.8.5.6@aar" - okhttpVersion = "2.7.5" - okioVersion = "1.6.0" + flattr4jVersion = "2.14" + glideVersion = "3.8.0" + glideOkhttpIntegrationVersion = "1.5.0" + iconifyVersion = "2.2.2" + jsoupVersion = "1.10.3" + materialDialogsVersion = "0.9.0.2" + okhttpVersion = "3.9.0" + okioVersion = "1.13.0" recyclerviewFlexibledividerVersion = "1.2.6" - robotiumSoloVersion = "5.5.3" - rxAndroidVersion = "1.1.0" - rxJavaVersion = "1.1.0" - rxJavaRulesVersion = "1.1.0.0" + robotiumSoloVersion = "5.6.3" + rxAndroidVersion = "1.2.1" + rxJavaVersion = "1.3.2" + rxJavaRulesVersion = "1.3.2.0" triangleLabelViewVersion = "1.1.0" - audioPlayerVersion = "v1.0.16" + audioPlayerVersion = "v1.0.17" - castCompanionLibVer = "2.8.3" + castCompanionLibVer = "2.9.1" playServicesVersion = "8.4.0" + wearableSupportVersion = "2.0.3" } task wrapper(type: Wrapper) { - gradleVersion = "2.11" + gradleVersion = "4.2" +} + +// free build hack: common functions +def doFreeBuild() { + return hasProperty("freeBuild") } diff --git a/changelog/ca.md b/changelog/ca.md deleted file mode 100644 index b5860ac05..000000000 --- a/changelog/ca.md +++ /dev/null @@ -1,363 +0,0 @@ -Registre de canvis -==================== - -Version 1.6.0 --------------------- -* New features: - * Experimental Chromecast support - * Subscription overview - * Proxy support - * Statistics - * Manual gpodder.net sync -* Fixes: - * Audioplayer controls - * Audio ducking - * Video control fade-out - * External media controls - * Feed parsing - -Version 1.5.0 --------------------- -* Exclude episodes from auto download by keyword -* Configure feeds to prevent them from refreshing automatically -* Improved audio player -* Improved UI -* Bug fixes - -Version 1.4.1 --------------------- -* Performance improvements -* Hardware buttons now ff and rewind instead of skipping -* Option to have forward button skip -* Option to send crash reports directly to developers -* Highlight currently playing episode -* Widget improvements - -Version 1.4.0.12 ----------------- -* Fix for crash on Huawei devices (media buttons may not work) - -Versió 1.4 ------------ -* BLUETOOTH PERMISSION: Needed to be able to resume playback when a Bluetooth device reconnects with your phone -* VIBRATE PERMISSION: Used optionally with the sleep timer -* Native variable speed playback (experimental via options) -* S'ha millorat el temporitzador -* Mark episodes as 'favorite' -* Notification can skip episodes -* Keep episodes when skipping them -* Episode art on lock screen -* Flexible episode cleanup -* Rewind after pause -* Usability improvements -* Bug fixes - -Version 1.3 ------------ -* Bulk actions on feed episodes (download, queue, delete) -* Reduced space used by images -* Automatic refresh at a certain time of day -* Customizable indicators and sorting for feeds -* Ability to share feeds -* Improved auto download -* Many fixes and usability improvements - -Version 1.2 ------------ -* Optionally disable swiping and dragging in the queue -* Resume playback after phone call -* Filter episodes in the Podcast feed -* Hide items in the Nav drawer -* Customize times for fast forward and rewind -* Resolved issues with opening some OPML files -* Various bug fixes and usability improvements - -Version 1.1 ------------ -* iTunes podcast integration -* Swipe to remove items from the queue -* Set the number of parallel downloads -* Fix for gpodder.net on old devices -* Fixed date problems for some feeds -* Display improvements -* Usability improvements -* Several other bugfixes - -Version 1.0 ------------ -* The queue can now be sorted -* Added option to delete episode after playback -* Fixed a bug that caused chapters to be displayed multiple times -* Several other improvements and bugfixes - - -Version 0.9.9.6 --------------------- -* Fixed problems related to variable playback speed plugins -* Fixed automatic feed update problems -* Several other bugfixes and improvements - -Version 0.9.9.5 --------------------- -* Added support for paged feeds -* S'ha millorat la interfÃcie -* Added Japanese and Turkish translations -* Fixed more image loading problems -* Altres correccions i millores - -Version 0.9.9.4 --------------------- -* Added option to keep notification and lockscreen controls when playback is paused -* Fixed a bug where episode images were not loaded correctly -* Fixed battery usage problems - -Versió 0.9.9.3 --------------------- -* S'han corregit problemes en la reproducció de vÃdeo -* S'ha millorat la cà rrega d'imatges -* Altres correccions i millores - -* Versió 0.9.9.2 --------------------- -* S'ha afegit suport per detectar automà ticament canals en introduir l'adreça d'un lloc web -* S'ha afegit suport per als botons de «següent» i «anterior» -* S'ha millorat el temporitzador -* Les marques de temps a les notes es poden emprar per saltar a posicions especÃfiques -* Es pot configurar la compartició automà tica per Flatt -* Algunes millores i correcció d'errors - -Versió 0.9.9.1 --------------------- -* Algunes millores i correcció d'errors - -Versió 0.9.9.0 --------------------- -* Nova interfÃcie d'usuari -* Es reinicien aquelles baixades que hagin fallat -* S'ha afegit suport per als canals Podlove Alternate -* S'ha afegit suport per al protocol «pcast» -* S'ha afegit una nova funcionalitat per a desar i restaurar còpies de seguretat. Per tal que funcioni, cal activar-ho des dels parà metres de configuració d'Android -* Algunes millores i correcció d'errors - -Versió 0.9.8.3 --------------------- -* S'ha afegit suport per a canals i episodis protegits per contrasenya -* S'ha afegit suport per a més tipus d'imatges -* S'ha traduït a l'hebreu -* Algunes millores i correcció d'errors - -Versió 0.9.8.2 --------------------- -* Algunes millores i correcció d'errors -* S'ha traduït al coreà - -Versió 0.9.8.1 --------------------- -* S'ha afegit l'opció de compartir automà ticament per flattr un episodi després d'haver-ne reproduït com a mÃnim el 80% -* S'ha traduït al polonès -* Algunes millores i correcció d'errors - -Versió 0.9.8.0 --------------------- -* S'ha afegit accés al directori gpodder.net -* S'ha afegit l'opció de sincronitzar les subscripcions a podcasts amb el servei de gpodder.net -* Podeu activar o desactivar la baixada automà tica per a podcasts concrets -* S'ha afegit l'opció de pausar la reproducció quan una altra aplicació està reproduint sons -* S'ha traduït al neerlandès i l'hindi -* S'ha resolt un problema amb les actualitzacions automà tiques de podcasts -* S'ha resolt un problema amb la visibilitat dels botons de la pantalla d'episodis -* S'ha resolt el problema pel qual els episodis es tornaven a baixar innecessà riament -* S'han corregit força més errors i s'ha millorat la usabilitat - -Versió 0.9.7.5 --------------------- -* S'ha reduït el temps d'inicialització -* Reducció en l'ús de memòria -* S'ha afegit l'opció de canviar la velocitat de reproducció -* S'ha traduït al suec -* Algunes millores i correcció d'errors - -Versió 0.9.7.4 --------------------- -* Es pot fixar una mida il·limitada per la memòria d'episodis -* Si esborreu un episodi de la cua fent lliscar el dit, ara podeu desfer l'acció -* S'ha afegit suport per a enllaços dins els capÃtols en format MP3 -* S'ha traduït al txec (República Txeca), azerbaidjan i portuguès -* Algunes millores i correcció d'errors - -Versió 0.9.7.3 --------------------- -* Els dispositius Bluetooth mostren metadades durant la reproducció (necessita AVRCP 1.3 o superior) -* Millores en la interfÃcie d'usuari -* S'han corregit diversos errors - -Versió 0.9.7.2 --------------------- -* Es pot desactivar la baixada automà tica -* S'ha traduït a l'italià (Ità lia) -* S'han corregit diversos errors - -Versió 0.9.7.1 --------------------- -* S'ha afegit la baixada automà tica d'episodis nous -* S'ha afegit l'opció d'especificar quants episodis es guarden al dispositiu -* S'ha afegit la reproducció de fitxers multimèdia externs -* Diverses millores i correcció d'errors -* S'ha traduït al català - -Versió 0.9.7 --------------------- -* S'ha millorat la interfÃcie -* Es poden importar fitxers OPML seleccionant-los des d'un explorador de fitxers -* La cua es pot organitzar arrossegant i deixant anar -* S'han afegit notificacions ampliables (només per a Android 4.1 i superior) -* S'ha traduït al danès, francès, rumanès i ucraïnès (grà cies als traductors!) -* S'han corregit força errors i s'han afegit algunes millores - -Versió 0.9.6.4 --------------------- -* S'ha traduït al xinès (grà cies tupunco!) -* S'ha traduït al portuguès (grà cies mbaltar!) -* S'han corregit diversos errors - -Versió 0.9.6.3 --------------------- -* S'ha afegit l'opció de canviar la ubicació de la carpeta de dades d'AntennaPod -* S'ha traduït al castellà (grà cies frandavid100!) -* S'han solucionat els problemes amb diversos canals - -Versió 0.9.6.2 --------------------- -* S'han solucionat alguns problemes en importar fitxers OPML -* S'han solucionat els problemes amb les baixades -* Es reconeixen els canvis en la informació d'un episodi -* Altres millores i correcció d'errors - -Versió 0.9.6.1 --------------------- -* Afegit el tema fosc -* Algunes millores i correcció d'errors - -Versió 0.9.6 --------------------- -* S'ha afegit suport per als capÃtols VorbisComment -* Els elements que s'estan reproduïnt apareixen com «en progrès» -* Reducció en l'ús de memòria -* Se suporten més tipus de canals -* S'han corregit diversos errors - - -Versió 0.9.5.3 --------------------- -* Es corregeix una fallada en reproduir en alguns dispositius -* S'han corregit diversos problemes en alguns canals -* Altres correccions i millores - -Versió 0.9.5.2 --------------------- -* El reproductor ja no utilitza ample de banda mentre no s'utilitza -* Altres millores i correcció d'errors - -Versió 0.9.5.1 --------------------- -* S'ha afegit un historial de reproducció -* S'ha millorat el comportament de les notificacions de baixades -* S'ha millorat el suport per al control d'auriculars -* S'han corregit errors de l'analitzador de canals -* S'ha canviat la ubicació dels botons d'importar i exportar fitxers OPML - -Versió 0.9.5 --------------------- -* S'ha afegit suport experimental per a capÃtols MP3 -* Noves opcions de menú per a la llista de nous i la cua -* Funció d'auto-esborrat -* Millora en la notificació d'errors de baixada -* Correcció d'errors - -Versió 0.9.4.6 --------------------- -* S'ha afegit suport per a dispositius amb una pantalla petita -* S'ha desactivat el temporitzador per dormir (ja hauria de funcionar) - -Versió 0.9.4.5 --------------------- -* S'ha traduït al rus (grà cies older!) -* S'ha traduït a l'alemany -* S'han corregit diversos errors - -Versió 0.9.4.4 --------------------- -* S'han afegit els controls del reproductor a la part inferior de les pantalles principal i llista de canals -* S'ha millorat la reproducció de fitxers - -Versió 0.9.4.3 --------------------- -* S'han corregit diversos errors de l'analitzador de canals -* S'ha millorat el comportament dels informes de baixades - -Versió 0.9.4.2 --------------------- -* S'ha corregit un error en la funció d'importar OPML -* S'ha reduït l'ús de memòria de les imatges -* S'ha corregit un problema amb les baixades en alguns dispositius - -Versió 0.9.4.1 --------------------- -* S'ha canviat el comportament de les notificacions de baixades - -Versió 0.9.4 --------------------- -* Baixades més rà pides i segures -* S'han afegit controls de reproducció a la pantalla de bloqueig per a dispositius Android 4.x -* S'han corregit diversos errors - -Versió 0.9.3.1 --------------------- -* S'ha afegit l'opció d'amagar els canals sense episodis -* S'ha millorat la mida de la imatge per a algunes mides de pantalla -* S'ha afegit una vista en graella per a pantalles més grans -* S'han corregit diversos errors - -Versió 0.9.3 --------------------- -* Integració de la MiroGuide -* Correcció d'errors per al reproductor d'à udio i vÃdeo -* Els canals s'afegeixen a la cua automà ticament un cop baixats - -Versió 0.9.2 --------------------- -* Correcció d'errors de la interfÃcie d'usuari -* L'analitzado de canals reconeix els atributs GUID i ID -* Millores d'estabilitat en afegir diversos canals al mateix moment -* S'han corregit els errors que apareixien en afegir certs canals - -Versió 0.9.1.1 --------------------- -* S'han canviat les credencials de Flattr -* S'ha millorat el disseny de la pantalla d'informació del canal -* AntennaPod esdevé codi obert; podeu trobar el codi a https://github.com/danieloeh/AntennaPod - -Versió 0.9.1 --------------------- -* S'ha afegit suport per a enllaços de SimpleChapters -* Error corregit: el capÃtol actual no sempre es mostrava correctament - -Versió 0.9 --------------------- - -* Exportar a OPML -* Integració amb Flattr -* Temporitzador per dormir - -Versió 0.8.2 --------------------- - -* S'ha millorat la cerca -* S'ha millorat la importació de fitxers OPML -* Diversos errors corregits - -Versió 0.8.1 --------------------- - -* S'ha afegit suport per a SimpleChapters -* Importar d'OPML
\ No newline at end of file diff --git a/circle.yml b/circle.yml index 2f8f17e7a..01055725a 100644 --- a/circle.yml +++ b/circle.yml @@ -2,6 +2,8 @@ general: artifacts: - app/build/outputs/apk machine: + environment: + GRADLE_OPTS: '-Dorg.gradle.jvmargs="-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError"' java: version: oraclejdk8 dependencies: @@ -9,11 +11,12 @@ dependencies: - ~/.android - ~/android pre: - - echo y | android update sdk --no-ui --all --filter "tool,extra-android-m2repository,extra-android-support,extra-google-google_play_services,extra-google-m2repository,android-23" - - echo y | android update sdk --no-ui --all --filter "build-tools-23.0.2" + - echo y | android update sdk --no-ui --all --filter "tool,extra-android-m2repository,extra-android-support,extra-google-google_play_services,extra-google-m2repository,android-25" + - echo y | android update sdk --no-ui --all --filter "build-tools-25.0.3" override: - echo override dependencies test: override: - - ./gradlew assembleDebug -PdisablePreDex
\ No newline at end of file + - ./gradlew assembleDebug -PdisablePreDex: + timeout: 1800 diff --git a/core/build.gradle b/core/build.gradle index 5264e435b..f70083ec1 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -30,6 +30,14 @@ android { targetCompatibility JavaVersion.VERSION_1_8 } + publishNonDefault true + productFlavors { + free { + } + play { + } + } + } repositories { @@ -48,9 +56,9 @@ dependencies { compile "com.jayway.android.robotium:robotium-solo:$robotiumSoloVersion" compile "org.jsoup:jsoup:$jsoupVersion" compile "com.github.bumptech.glide:glide:$glideVersion" - compile "com.github.bumptech.glide:okhttp-integration:$glideOkhttpIntegrationVersion" - compile "com.squareup.okhttp:okhttp:$okhttpVersion" - compile "com.squareup.okhttp:okhttp-urlconnection:$okhttpVersion" + compile "com.github.bumptech.glide:okhttp3-integration:$glideOkhttpIntegrationVersion@aar" + compile "com.squareup.okhttp3:okhttp:$okhttpVersion" + compile "com.squareup.okhttp3:okhttp-urlconnection:$okhttpVersion" compile "com.squareup.okio:okio:$okioVersion" compile "com.nineoldandroids:library:2.4.0" compile "de.greenrobot:eventbus:$eventbusVersion" @@ -59,7 +67,21 @@ dependencies { compile "com.github.AntennaPod:AntennaPod-AudioPlayer:$audioPlayerVersion" // Add casting features - compile "com.google.android.libraries.cast.companionlibrary:ccl:$castCompanionLibVer" - compile "com.android.support:mediarouter-v7:$supportVersion" - compile "com.google.android.gms:play-services-cast:$playServicesVersion" + // free build hack: skip some dependencies + if (!doFreeBuild()) { + playCompile "com.google.android.libraries.cast.companionlibrary:ccl:$castCompanionLibVer" + compile "com.android.support:mediarouter-v7:$supportVersion" + playCompile "com.google.android.gms:play-services-cast:$playServicesVersion" + compile "com.google.android.support:wearable:$wearableSupportVersion" + } else { + System.out.println("core: free build hack, skipping some dependencies") + } +} + +allprojects { + gradle.projectsEvaluated { + tasks.withType(JavaCompile) { + options.compilerArgs << "-Xlint" << "-Xlint:-deprecation" << "-Xlint:-serial" + } + } } diff --git a/core/src/androidTest/java/de/danoeh/antennapod/core/feed/FeedImageMother.java b/core/src/androidTest/java/de/danoeh/antennapod/core/feed/FeedImageMother.java new file mode 100644 index 000000000..f240c870e --- /dev/null +++ b/core/src/androidTest/java/de/danoeh/antennapod/core/feed/FeedImageMother.java @@ -0,0 +1,9 @@ +package de.danoeh.antennapod.core.feed; + +public class FeedImageMother { + + public static FeedImage anyFeedImage() { + return new FeedImage(0, "image", null, "http://example.com/picture", false); + } + +} diff --git a/core/src/androidTest/java/de/danoeh/antennapod/core/feed/FeedItemMother.java b/core/src/androidTest/java/de/danoeh/antennapod/core/feed/FeedItemMother.java new file mode 100644 index 000000000..3d7c4fe5f --- /dev/null +++ b/core/src/androidTest/java/de/danoeh/antennapod/core/feed/FeedItemMother.java @@ -0,0 +1,16 @@ +package de.danoeh.antennapod.core.feed; + +import java.util.Date; + +import static de.danoeh.antennapod.core.feed.FeedImageMother.anyFeedImage; +import static de.danoeh.antennapod.core.feed.FeedMother.anyFeed; + +class FeedItemMother { + + static FeedItem anyFeedItemWithImage() { + FeedItem item = new FeedItem(0, "Item", "Item", "url", new Date(), FeedItem.PLAYED, anyFeed()); + item.setImage(anyFeedImage()); + return item; + } + +} diff --git a/core/src/androidTest/java/de/danoeh/antennapod/core/feed/FeedItemTest.java b/core/src/androidTest/java/de/danoeh/antennapod/core/feed/FeedItemTest.java new file mode 100644 index 000000000..9e12e8ae0 --- /dev/null +++ b/core/src/androidTest/java/de/danoeh/antennapod/core/feed/FeedItemTest.java @@ -0,0 +1,65 @@ +package de.danoeh.antennapod.core.feed; + +import android.test.AndroidTestCase; + +import static de.danoeh.antennapod.core.feed.FeedItemMother.anyFeedItemWithImage; + +public class FeedItemTest extends AndroidTestCase { + + private FeedItem original; + private FeedImage originalImage; + private FeedItem changedFeedItem; + + @Override + protected void setUp() { + original = anyFeedItemWithImage(); + originalImage = original.getImage(); + changedFeedItem = anyFeedItemWithImage(); + } + + public void testUpdateFromOther_feedItemImageDownloadUrlChanged() throws Exception { + setNewFeedItemImageDownloadUrl(); + + original.updateFromOther(changedFeedItem); + + feedItemImageWasUpdated(); + } + + public void testUpdateFromOther_feedItemImageRemoved() throws Exception { + feedItemImageRemoved(); + + original.updateFromOther(changedFeedItem); + + feedItemImageWasNotUpdated(); + } + + public void testUpdateFromOther_feedItemImageAdded() throws Exception { + feedItemHadNoImage(); + setNewFeedItemImageDownloadUrl(); + + original.updateFromOther(changedFeedItem); + + feedItemImageWasUpdated(); + } + + private void feedItemHadNoImage() { + original.setImage(null); + } + + private void setNewFeedItemImageDownloadUrl() { + changedFeedItem.getImage().setDownload_url("http://example.com/new_picture"); + } + + private void feedItemImageRemoved() { + changedFeedItem.setImage(null); + } + + private void feedItemImageWasUpdated() { + assertEquals(original.getImage().getDownload_url(), changedFeedItem.getImage().getDownload_url()); + } + + private void feedItemImageWasNotUpdated() { + assertTrue(originalImage == original.getImage()); + } + +}
\ No newline at end of file diff --git a/core/src/androidTest/java/de/danoeh/antennapod/core/feed/FeedMother.java b/core/src/androidTest/java/de/danoeh/antennapod/core/feed/FeedMother.java new file mode 100644 index 000000000..1cea6b9c9 --- /dev/null +++ b/core/src/androidTest/java/de/danoeh/antennapod/core/feed/FeedMother.java @@ -0,0 +1,14 @@ +package de.danoeh.antennapod.core.feed; + +import static de.danoeh.antennapod.core.feed.FeedImageMother.anyFeedImage; + +public class FeedMother { + + public static Feed anyFeed() { + FeedImage image = anyFeedImage(); + return new Feed(0, null, "title", "http://example.com", "This is the description", + "http://example.com/payment", "Daniel", "en", null, "http://example.com/feed", image, + null, "http://example.com/feed", true); + } + +} diff --git a/core/src/androidTest/java/de/danoeh/antennapod/core/feed/FeedTest.java b/core/src/androidTest/java/de/danoeh/antennapod/core/feed/FeedTest.java new file mode 100644 index 000000000..8067ec93f --- /dev/null +++ b/core/src/androidTest/java/de/danoeh/antennapod/core/feed/FeedTest.java @@ -0,0 +1,92 @@ +package de.danoeh.antennapod.core.feed; + +import android.test.AndroidTestCase; + +import static de.danoeh.antennapod.core.feed.FeedImageMother.anyFeedImage; +import static de.danoeh.antennapod.core.feed.FeedMother.anyFeed; + +public class FeedTest extends AndroidTestCase { + + private Feed original; + private FeedImage originalImage; + private Feed changedFeed; + + @Override + protected void setUp() { + original = anyFeed(); + originalImage = original.getImage(); + changedFeed = anyFeed(); + } + + public void testCompareWithOther_feedImageDownloadUrlChanged() throws Exception { + setNewFeedImageDownloadUrl(); + + feedHasChanged(); + } + + public void testCompareWithOther_sameFeedImage() throws Exception { + changedFeed.setImage(anyFeedImage()); + + feedHasNotChanged(); + } + + public void testCompareWithOther_feedImageRemoved() throws Exception { + feedImageRemoved(); + + feedHasNotChanged(); + } + + public void testUpdateFromOther_feedImageDownloadUrlChanged() throws Exception { + setNewFeedImageDownloadUrl(); + + original.updateFromOther(changedFeed); + + feedImageWasUpdated(); + } + + public void testUpdateFromOther_feedImageRemoved() throws Exception { + feedImageRemoved(); + + original.updateFromOther(changedFeed); + + feedImageWasNotUpdated(); + } + + public void testUpdateFromOther_feedImageAdded() throws Exception { + feedHadNoImage(); + setNewFeedImageDownloadUrl(); + + original.updateFromOther(changedFeed); + + feedImageWasUpdated(); + } + + private void feedHasNotChanged() { + assertFalse(original.compareWithOther(changedFeed)); + } + + private void feedHadNoImage() { + original.setImage(null); + } + + private void setNewFeedImageDownloadUrl() { + changedFeed.getImage().setDownload_url("http://example.com/new_picture"); + } + + private void feedHasChanged() { + assertTrue(original.compareWithOther(changedFeed)); + } + + private void feedImageRemoved() { + changedFeed.setImage(null); + } + + private void feedImageWasUpdated() { + assertEquals(original.getImage().getDownload_url(), changedFeed.getImage().getDownload_url()); + } + + private void feedImageWasNotUpdated() { + assertTrue(originalImage == original.getImage()); + } + +}
\ No newline at end of file diff --git a/core/src/androidTest/java/de/danoeh/antennapod/core/tests/util/DateUtilsTest.java b/core/src/androidTest/java/de/danoeh/antennapod/core/tests/util/DateUtilsTest.java index 2727b1447..8adcc41c5 100644 --- a/core/src/androidTest/java/de/danoeh/antennapod/core/tests/util/DateUtilsTest.java +++ b/core/src/androidTest/java/de/danoeh/antennapod/core/tests/util/DateUtilsTest.java @@ -86,7 +86,7 @@ public class DateUtilsTest extends AndroidTestCase { } public void testAsctime() throws Exception { - GregorianCalendar exp = new GregorianCalendar(2011, 4, 25, 12, 33, 00); + GregorianCalendar exp = new GregorianCalendar(2011, 4, 25, 12, 33, 0); exp.setTimeZone(TimeZone.getTimeZone("UTC")); Date expected = new Date(exp.getTimeInMillis()); Date actual = DateUtils.parse("Wed, 25 May 2011 12:33:00"); @@ -101,4 +101,33 @@ public class DateUtilsTest extends AndroidTestCase { assertEquals(expected, actual); } + public void testParseDateWithNoTimezonePadding() throws Exception { + GregorianCalendar exp = new GregorianCalendar(2017, 1, 22, 22, 28, 0); + exp.setTimeZone(TimeZone.getTimeZone("UTC")); + Date expected = new Date(exp.getTimeInMillis() + 2); + Date actual = DateUtils.parse("2017-02-22T14:28:00.002-08:00"); + assertEquals(expected, actual); + } + + public void testParseDateWithForCest() throws Exception { + GregorianCalendar exp1 = new GregorianCalendar(2017, 0, 28, 22, 0, 0); + exp1.setTimeZone(TimeZone.getTimeZone("UTC")); + Date expected1 = new Date(exp1.getTimeInMillis()); + Date actual1 = DateUtils.parse("Sun, 29 Jan 2017 00:00:00 CEST"); + assertEquals(expected1, actual1); + + GregorianCalendar exp2 = new GregorianCalendar(2017, 0, 28, 23, 0, 0); + exp2.setTimeZone(TimeZone.getTimeZone("UTC")); + Date expected2 = new Date(exp2.getTimeInMillis()); + Date actual2 = DateUtils.parse("Sun, 29 Jan 2017 00:00:00 CET"); + assertEquals(expected2, actual2); + } + + public void testParseDateWithIncorrectWeekday() { + GregorianCalendar exp1 = new GregorianCalendar(2014, 9, 8, 9, 0, 0); + exp1.setTimeZone(TimeZone.getTimeZone("GMT")); + Date expected = new Date(exp1.getTimeInMillis()); + Date actual = DateUtils.parse("Thu, 8 Oct 2014 09:00:00 GMT"); // actually a Wednesday + assertEquals(expected, actual); + } } diff --git a/core/src/androidTest/java/de/danoeh/antennapod/core/tests/util/service/download/DownloadServiceTest.java b/core/src/androidTest/java/de/danoeh/antennapod/core/tests/util/service/download/DownloadServiceTest.java new file mode 100644 index 000000000..94cfb3278 --- /dev/null +++ b/core/src/androidTest/java/de/danoeh/antennapod/core/tests/util/service/download/DownloadServiceTest.java @@ -0,0 +1,35 @@ +package de.danoeh.antennapod.core.tests.util.service.download; + +import android.test.AndroidTestCase; + +import java.util.ArrayList; +import java.util.List; + +import de.danoeh.antennapod.core.feed.Feed; +import de.danoeh.antennapod.core.feed.FeedImage; +import de.danoeh.antennapod.core.feed.FeedItem; +import de.danoeh.antennapod.core.service.download.DownloadService; + +public class DownloadServiceTest extends AndroidTestCase { + + public void testRemoveDuplicateImages() { + List<FeedItem> items = new ArrayList<>(); + for (int i = 0; i < 50; i++) { + FeedItem item = new FeedItem(); + String url = (i % 5 == 0) ? "dupe_url" : String.format("url_%d", i); + item.setImage(new FeedImage(null, url, "")); + items.add(item); + } + Feed feed = new Feed(); + feed.setItems(items); + + DownloadService.removeDuplicateImages(feed); + + assertEquals(50, items.size()); + for (int i = 0; i < items.size(); i++) { + FeedItem item = items.get(i); + String want = (i == 0) ? "dupe_url" : (i % 5 == 0) ? null : String.format("url_%d", i); + assertEquals(want, item.getImageLocation()); + } + } +} diff --git a/core/src/free/java/de/danoeh/antennapod/core/CastCallbacks.java b/core/src/free/java/de/danoeh/antennapod/core/CastCallbacks.java new file mode 100644 index 000000000..2e266c736 --- /dev/null +++ b/core/src/free/java/de/danoeh/antennapod/core/CastCallbacks.java @@ -0,0 +1,7 @@ +package de.danoeh.antennapod.core; + +/** + * Callbacks for Chromecast support on the core module + */ +public interface CastCallbacks { +} diff --git a/core/src/free/java/de/danoeh/antennapod/core/ClientConfig.java b/core/src/free/java/de/danoeh/antennapod/core/ClientConfig.java new file mode 100644 index 000000000..88ae6d6bc --- /dev/null +++ b/core/src/free/java/de/danoeh/antennapod/core/ClientConfig.java @@ -0,0 +1,51 @@ +package de.danoeh.antennapod.core; + +import android.content.Context; + +import de.danoeh.antennapod.core.preferences.PlaybackPreferences; +import de.danoeh.antennapod.core.preferences.SleepTimerPreferences; +import de.danoeh.antennapod.core.preferences.UserPreferences; +import de.danoeh.antennapod.core.storage.PodDBAdapter; +import de.danoeh.antennapod.core.util.NetworkUtils; + +/** + * Stores callbacks for core classes like Services, DB classes etc. and other configuration variables. + * Apps using the core module of AntennaPod should register implementations of all interfaces here. + */ +public class ClientConfig { + + /** + * Should be used when setting User-Agent header for HTTP-requests. + */ + public static String USER_AGENT; + + public static ApplicationCallbacks applicationCallbacks; + + public static DownloadServiceCallbacks downloadServiceCallbacks; + + public static PlaybackServiceCallbacks playbackServiceCallbacks; + + public static GpodnetCallbacks gpodnetCallbacks; + + public static FlattrCallbacks flattrCallbacks; + + public static DBTasksCallbacks dbTasksCallbacks; + + public static CastCallbacks castCallbacks; + + private static boolean initialized = false; + + public static synchronized void initialize(Context context) { + if(initialized) { + return; + } + PodDBAdapter.init(context); + UserPreferences.init(context); + UpdateManager.init(context); + PlaybackPreferences.init(context); + NetworkUtils.init(context); + SleepTimerPreferences.init(context); + initialized = true; + } + +} diff --git a/core/src/free/java/de/danoeh/antennapod/core/feed/FeedMediaFlavorHelper.java b/core/src/free/java/de/danoeh/antennapod/core/feed/FeedMediaFlavorHelper.java new file mode 100644 index 000000000..8818f6b46 --- /dev/null +++ b/core/src/free/java/de/danoeh/antennapod/core/feed/FeedMediaFlavorHelper.java @@ -0,0 +1,11 @@ +package de.danoeh.antennapod.core.feed; + +/** + * Implements methods for FeedMedia that are flavor dependent. + */ +public class FeedMediaFlavorHelper { + private FeedMediaFlavorHelper(){} + static boolean instanceOfRemoteMedia(Object o) { + return false; + } +} diff --git a/core/src/free/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceFlavorHelper.java b/core/src/free/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceFlavorHelper.java new file mode 100644 index 000000000..4e6482fda --- /dev/null +++ b/core/src/free/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceFlavorHelper.java @@ -0,0 +1,54 @@ +package de.danoeh.antennapod.core.service.playback; + +import android.content.Context; +import android.support.annotation.StringRes; +import android.support.v4.media.session.MediaSessionCompat; +import android.support.v4.media.session.PlaybackStateCompat; + +/** + * Class intended to work along PlaybackService and provide support for different flavors. + */ +public class PlaybackServiceFlavorHelper { + + private PlaybackService.FlavorHelperCallback callback; + + PlaybackServiceFlavorHelper(Context context, PlaybackService.FlavorHelperCallback callback) { + this.callback = callback; + } + + void initializeMediaPlayer(Context context) { + callback.setMediaPlayer(new LocalPSMP(context, callback.getMediaPlayerCallback())); + } + + void removeCastConsumer() { + // no-op + } + + boolean castDisconnect(boolean castDisconnect) { + return false; + } + + boolean onMediaPlayerInfo(Context context, int code, @StringRes int resourceId) { + return false; + } + + void registerWifiBroadcastReceiver() { + // no-op + } + + void unregisterWifiBroadcastReceiver() { + // no-op + } + + boolean onSharedPreference(String key) { + return false; + } + + void sessionStateAddActionForWear(PlaybackStateCompat.Builder sessionState, String actionName, CharSequence name, int icon) { + // no-op + } + + void mediaSessionSetExtraForWear(MediaSessionCompat mediaSession) { + // no-op + } +} diff --git a/core/src/free/res/values/strings.xml b/core/src/free/res/values/strings.xml new file mode 100644 index 000000000..579b12e12 --- /dev/null +++ b/core/src/free/res/values/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="pref_cast_message">@string/pref_cast_message_free_flavor</string> +</resources> diff --git a/core/src/main/AndroidManifest.xml b/core/src/main/AndroidManifest.xml index 47bd8b666..ee035c9fa 100644 --- a/core/src/main/AndroidManifest.xml +++ b/core/src/main/AndroidManifest.xml @@ -12,16 +12,19 @@ <application android:allowBackup="true" - android:icon="@drawable/ic_launcher" - android:label="@string/app_name"> + android:icon="@drawable/ic_launcher"> <service android:name=".service.download.DownloadService" android:enabled="true" /> - <service - android:name=".service.playback.PlaybackService" + <service android:name=".service.playback.PlaybackService" + android:label="@string/app_name" android:enabled="true" - android:exported="true" /> + android:exported="true"> + <intent-filter> + <action android:name="android.media.browse.MediaBrowserService"/> + </intent-filter> + </service> <service android:name=".service.GpodnetSyncService" android:enabled="true" /> diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/FeedRemover.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/FeedRemover.java index e475e696c..67c460e78 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/asynctask/FeedRemover.java +++ b/core/src/main/java/de/danoeh/antennapod/core/asynctask/FeedRemover.java @@ -38,10 +38,11 @@ public class FeedRemover extends AsyncTask<Void, Void, Void> { @Override protected void onPostExecute(Void result) { - dialog.dismiss(); + if(dialog != null && dialog.isShowing()) { + dialog.dismiss(); + } if(skipOnCompletion) { - context.sendBroadcast(new Intent( - PlaybackService.ACTION_SKIP_CURRENT_EPISODE)); + context.sendBroadcast(new Intent(PlaybackService.ACTION_SKIP_CURRENT_EPISODE)); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/FlattrClickWorker.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/FlattrClickWorker.java index 3ddaba52e..d991006e5 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/asynctask/FlattrClickWorker.java +++ b/core/src/main/java/de/danoeh/antennapod/core/asynctask/FlattrClickWorker.java @@ -106,7 +106,7 @@ public class FlattrClickWorker extends AsyncTask<Void, Integer, FlattrClickWorke return ExitCode.NO_THINGS; } - List<Future> dbFutures = new LinkedList<>(); + List<Future<?>> dbFutures = new LinkedList<>(); for (FlattrThing thing : flattrQueue) { if (BuildConfig.DEBUG) Log.d(TAG, "Processing " + thing.getTitle()); @@ -131,7 +131,7 @@ public class FlattrClickWorker extends AsyncTask<Void, Integer, FlattrClickWorke } } - for (Future f : dbFutures) { + for (Future<?> f : dbFutures) { try { f.get(); } catch (InterruptedException | ExecutionException e) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/ImageResource.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/ImageResource.java index 992321441..b01e3f3ba 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/asynctask/ImageResource.java +++ b/core/src/main/java/de/danoeh/antennapod/core/asynctask/ImageResource.java @@ -1,7 +1,5 @@ package de.danoeh.antennapod.core.asynctask; -import android.net.Uri; - /** * Classes that implement this interface provide access to an image resource that can * be loaded by the Picasso library. @@ -9,29 +7,9 @@ import android.net.Uri; public interface ImageResource { /** - * This scheme should be used by PicassoImageResources to - * indicate that the image Uri points to a file that is not an image - * (e.g. a media file). This workaround is needed so that the Picasso library - * loads these Uri with a Downloader instead of trying to load it directly. - * <p/> - * For example implementations, see FeedMedia or ExternalMedia. - */ - String SCHEME_MEDIA = "media"; - - - /** - * Parameter key for an encoded fallback Uri. This Uri MUST point to a local image file - */ - String PARAM_FALLBACK = "fallback"; - - /** - * Returns a Uri to the image or null if no image is available. - * <p/> - * The Uri can either be an HTTP-URL, a URL pointing to a local image file or - * a non-image file (see SCHEME_MEDIA for more details). + * Returns the location of the image or null if no image is available. * <p/> - * The Uri can also have an optional fallback-URL if loading the default URL - * failed (see PARAM_FALLBACK). + * The location can either be an URL or a local path */ - Uri getImageUri(); + String getImageLocation(); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java b/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java index 982015314..80ce6cf56 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java +++ b/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java @@ -8,6 +8,7 @@ import android.content.Context; import android.os.ParcelFileDescriptor; import android.util.Log; +import org.apache.commons.io.IOUtils; import org.xmlpull.v1.XmlPullParserException; import java.io.ByteArrayOutputStream; @@ -27,10 +28,10 @@ import java.util.ArrayList; import java.util.Arrays; import de.danoeh.antennapod.core.BuildConfig; +import de.danoeh.antennapod.core.export.opml.OpmlElement; +import de.danoeh.antennapod.core.export.opml.OpmlReader; +import de.danoeh.antennapod.core.export.opml.OpmlWriter; import de.danoeh.antennapod.core.feed.Feed; -import de.danoeh.antennapod.core.opml.OpmlElement; -import de.danoeh.antennapod.core.opml.OpmlReader; -import de.danoeh.antennapod.core.opml.OpmlWriter; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DownloadRequestException; import de.danoeh.antennapod.core.storage.DownloadRequester; @@ -56,7 +57,9 @@ public class OpmlBackupAgent extends BackupAgentHelper { } } - /** Class for backing up and restoring the OPML file. */ + /** + * Class for backing up and restoring the OPML file. + */ private static class OpmlBackupHelper implements BackupHelper { private static final String TAG = "OpmlBackupHelper"; @@ -64,7 +67,9 @@ public class OpmlBackupAgent extends BackupAgentHelper { private final Context mContext; - /** Checksum of restored OPML file */ + /** + * Checksum of restored OPML file + */ private byte[] mChecksum; public OpmlBackupHelper(Context context) { @@ -170,12 +175,7 @@ public class OpmlBackupAgent extends BackupAgentHelper { } catch (IOException e) { Log.e(TAG, "Failed to restore OPML backup", e); } finally { - if (reader != null) { - try { - reader.close(); - } catch (IOException e) { - } - } + IOUtils.closeQuietly(reader); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/dialog/ConfirmationDialog.java b/core/src/main/java/de/danoeh/antennapod/core/dialog/ConfirmationDialog.java index 266526d82..b14803751 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/dialog/ConfirmationDialog.java +++ b/core/src/main/java/de/danoeh/antennapod/core/dialog/ConfirmationDialog.java @@ -16,16 +16,20 @@ public abstract class ConfirmationDialog { private static final String TAG = ConfirmationDialog.class.getSimpleName(); protected Context context; - int titleId; - int messageId; + private int titleId; + private String message; - int positiveText; - int negativeText; + private int positiveText; + private int negativeText; public ConfirmationDialog(Context context, int titleId, int messageId) { + this(context, titleId, context.getString(messageId)); + } + + public ConfirmationDialog(Context context, int titleId, String message) { this.context = context; this.titleId = titleId; - this.messageId = messageId; + this.message = message; } public void onCancelButtonPressed(DialogInterface dialog) { @@ -47,7 +51,7 @@ public abstract class ConfirmationDialog { public final AlertDialog createNewDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(titleId); - builder.setMessage(messageId); + builder.setMessage(message); builder.setPositiveButton(positiveText != 0 ? positiveText : R.string.confirm_label, (dialog, which) -> onConfirmButtonPressed(dialog)); builder.setNegativeButton(negativeText != 0 ? negativeText : R.string.cancel_label, diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/MessageEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/MessageEvent.java new file mode 100644 index 000000000..9fc488fbc --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/event/MessageEvent.java @@ -0,0 +1,21 @@ +package de.danoeh.antennapod.core.event; + +import android.support.annotation.Nullable; + +public class MessageEvent { + + public final String message; + + @Nullable + public final Runnable action; + + public MessageEvent(String message) { + this(message, null); + } + + public MessageEvent(String message, Runnable action) { + this.message = message; + this.action = action; + } + +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/export/CommonSymbols.java b/core/src/main/java/de/danoeh/antennapod/core/export/CommonSymbols.java new file mode 100644 index 000000000..3ed251047 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/export/CommonSymbols.java @@ -0,0 +1,24 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package de.danoeh.antennapod.core.export; + +public class CommonSymbols { + + public static final String HEAD = "head"; + public static final String BODY = "body"; + public static final String TITLE = "title"; + + public static final String XML_FEATURE_INDENT_OUTPUT = "http://xmlpull.org/v1/doc/features.html#indent-output"; + +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/export/ExportWriter.java b/core/src/main/java/de/danoeh/antennapod/core/export/ExportWriter.java new file mode 100644 index 000000000..d6a187b21 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/export/ExportWriter.java @@ -0,0 +1,29 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package de.danoeh.antennapod.core.export; + +import java.io.IOException; +import java.io.Writer; +import java.util.List; + +import de.danoeh.antennapod.core.feed.Feed; + +public interface ExportWriter { + + void writeDocument(List<Feed> feeds, Writer writer) + throws IllegalArgumentException, IllegalStateException, IOException; + + String fileExtension(); + +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlSymbols.java b/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlSymbols.java new file mode 100644 index 000000000..b8807a686 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlSymbols.java @@ -0,0 +1,30 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package de.danoeh.antennapod.core.export.html; + +import de.danoeh.antennapod.core.export.CommonSymbols; + +class HtmlSymbols extends CommonSymbols { + + static final String HTML = "html"; + + static final String ORDERED_LIST = "ol"; + static final String LIST_ITEM = "li"; + + static String HEADING = "h1"; + + static final String LINK = "a"; + static final String LINK_DESTINATION = "href"; + +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlWriter.java b/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlWriter.java new file mode 100644 index 000000000..c24b39812 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlWriter.java @@ -0,0 +1,82 @@ +package de.danoeh.antennapod.core.export.html; + +import android.text.TextUtils; +import android.util.Log; +import android.util.Xml; + +import org.xmlpull.v1.XmlSerializer; + +import java.io.IOException; +import java.io.Writer; +import java.util.List; + +import de.danoeh.antennapod.core.export.ExportWriter; +import de.danoeh.antennapod.core.feed.Feed; + +/** Writes HTML documents. */ +public class HtmlWriter implements ExportWriter { + + private static final String TAG = "HtmlWriter"; + private static final String ENCODING = "UTF-8"; + private static final String HTML_TITLE = "AntennaPod Subscriptions"; + + /** + * Takes a list of feeds and a writer and writes those into an HTML + * document. + * + * @throws IOException + * @throws IllegalStateException + * @throws IllegalArgumentException + */ + @Override + public void writeDocument(List<Feed> feeds, Writer writer) + throws IllegalArgumentException, IllegalStateException, IOException { + Log.d(TAG, "Starting to write document"); + XmlSerializer xs = Xml.newSerializer(); + xs.setFeature(HtmlSymbols.XML_FEATURE_INDENT_OUTPUT, true); + xs.setOutput(writer); + + xs.startDocument(ENCODING, false); + xs.startTag(null, HtmlSymbols.HTML); + xs.startTag(null, HtmlSymbols.HEAD); + xs.startTag(null, HtmlSymbols.TITLE); + xs.text(HTML_TITLE); + xs.endTag(null, HtmlSymbols.TITLE); + xs.endTag(null, HtmlSymbols.HEAD); + + xs.startTag(null, HtmlSymbols.BODY); + xs.startTag(null, HtmlSymbols.HEADING); + xs.text(HTML_TITLE); + xs.endTag(null, HtmlSymbols.HEADING); + xs.startTag(null, HtmlSymbols.ORDERED_LIST); + for (Feed feed : feeds) { + xs.startTag(null, HtmlSymbols.LIST_ITEM); + xs.text(feed.getTitle()); + if (!TextUtils.isEmpty(feed.getLink())) { + xs.text(" ["); + xs.startTag(null, HtmlSymbols.LINK); + xs.attribute(null, HtmlSymbols.LINK_DESTINATION, feed.getLink()); + xs.text("Website"); + xs.endTag(null, HtmlSymbols.LINK); + xs.text("]"); + } + xs.text(" ["); + xs.startTag(null, HtmlSymbols.LINK); + xs.attribute(null, HtmlSymbols.LINK_DESTINATION, feed.getDownload_url()); + xs.text("Feed"); + xs.endTag(null, HtmlSymbols.LINK); + xs.text("]"); + xs.endTag(null, HtmlSymbols.LIST_ITEM); + } + xs.endTag(null, HtmlSymbols.ORDERED_LIST); + xs.endTag(null, HtmlSymbols.BODY); + xs.endTag(null, HtmlSymbols.HTML); + xs.endDocument(); + Log.d(TAG, "Finished writing document"); + } + + public String fileExtension() { + return "html"; + } + +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlElement.java b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlElement.java index 8d0a4a842..61eb4d0c9 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlElement.java +++ b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlElement.java @@ -1,4 +1,4 @@ -package de.danoeh.antennapod.core.opml; +package de.danoeh.antennapod.core.export.opml; /** Represents a single feed in an OPML file. */ public class OpmlElement { diff --git a/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlReader.java b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlReader.java index 17afc7904..a17fedd7d 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlReader.java @@ -1,4 +1,4 @@ -package de.danoeh.antennapod.core.opml; +package de.danoeh.antennapod.core.export.opml; import android.util.Log; diff --git a/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlSymbols.java b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlSymbols.java new file mode 100644 index 000000000..40b0e23b8 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlSymbols.java @@ -0,0 +1,21 @@ +package de.danoeh.antennapod.core.export.opml; + +import de.danoeh.antennapod.core.export.CommonSymbols; + +/** Contains symbols for reading and writing OPML documents. */ +public final class OpmlSymbols extends CommonSymbols { + + public static final String OPML = "opml"; + static final String OUTLINE = "outline"; + static final String TEXT = "text"; + static final String XMLURL = "xmlUrl"; + static final String HTMLURL = "htmlUrl"; + static final String TYPE = "type"; + static final String VERSION = "version"; + static final String DATE_CREATED = "dateCreated"; + + private OpmlSymbols() { + + } + +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlWriter.java b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlWriter.java index 673c602df..fd0922f72 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlWriter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlWriter.java @@ -1,4 +1,4 @@ -package de.danoeh.antennapod.core.opml; +package de.danoeh.antennapod.core.export.opml; import android.util.Log; import android.util.Xml; @@ -10,11 +10,13 @@ import java.io.Writer; import java.util.Date; import java.util.List; +import de.danoeh.antennapod.core.export.ExportWriter; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.util.DateUtils; /** Writes OPML documents. */ -public class OpmlWriter { +public class OpmlWriter implements ExportWriter { + private static final String TAG = "OpmlWriter"; private static final String ENCODING = "UTF-8"; private static final String OPML_VERSION = "2.0"; @@ -28,40 +30,29 @@ public class OpmlWriter { * @throws IllegalStateException * @throws IllegalArgumentException */ + @Override public void writeDocument(List<Feed> feeds, Writer writer) throws IllegalArgumentException, IllegalStateException, IOException { Log.d(TAG, "Starting to write document"); XmlSerializer xs = Xml.newSerializer(); + xs.setFeature(OpmlSymbols.XML_FEATURE_INDENT_OUTPUT, true); xs.setOutput(writer); xs.startDocument(ENCODING, false); - xs.text("\n"); xs.startTag(null, OpmlSymbols.OPML); xs.attribute(null, OpmlSymbols.VERSION, OPML_VERSION); - xs.text("\n"); - xs.text(" "); xs.startTag(null, OpmlSymbols.HEAD); - xs.text("\n"); - xs.text(" "); xs.startTag(null, OpmlSymbols.TITLE); xs.text(OPML_TITLE); xs.endTag(null, OpmlSymbols.TITLE); - xs.text("\n"); - xs.text(" "); xs.startTag(null, OpmlSymbols.DATE_CREATED); xs.text(DateUtils.formatRFC822Date(new Date())); xs.endTag(null, OpmlSymbols.DATE_CREATED); - xs.text("\n"); - xs.text(" "); xs.endTag(null, OpmlSymbols.HEAD); - xs.text("\n"); - xs.text(" "); xs.startTag(null, OpmlSymbols.BODY); - xs.text("\n"); for (Feed feed : feeds) { - xs.text(" "); xs.startTag(null, OpmlSymbols.OUTLINE); xs.attribute(null, OpmlSymbols.TEXT, feed.getTitle()); xs.attribute(null, OpmlSymbols.TITLE, feed.getTitle()); @@ -73,14 +64,15 @@ public class OpmlWriter { xs.attribute(null, OpmlSymbols.HTMLURL, feed.getLink()); } xs.endTag(null, OpmlSymbols.OUTLINE); - xs.text("\n"); } - xs.text(" "); xs.endTag(null, OpmlSymbols.BODY); - xs.text("\n"); xs.endTag(null, OpmlSymbols.OPML); - xs.text("\n"); xs.endDocument(); Log.d(TAG, "Finished writing document"); } + + public String fileExtension() { + return "opml"; + } + } diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/EventDistributor.java b/core/src/main/java/de/danoeh/antennapod/core/feed/EventDistributor.java index dbad084c7..514a79fad 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/EventDistributor.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/EventDistributor.java @@ -96,7 +96,7 @@ public class EventDistributor extends Observable { public void sendPlayerStatusUpdateBroadcast() { addEvent(PLAYER_STATUS_UPDATE); } - public static abstract class EventListener implements Observer { + public abstract static class EventListener implements Observer { @Override public void update(Observable observable, Object data) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java b/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java index 67ac2d280..746dd43c4 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java @@ -1,8 +1,6 @@ package de.danoeh.antennapod.core.feed; -import android.content.Context; import android.database.Cursor; -import android.net.Uri; import android.support.annotation.Nullable; import android.text.TextUtils; @@ -22,12 +20,16 @@ import de.danoeh.antennapod.core.util.flattr.FlattrThing; * @author daniel */ public class Feed extends FeedFile implements FlattrThing, ImageResource { + public static final int FEEDFILETYPE_FEED = 0; public static final String TYPE_RSS2 = "rss"; - public static final String TYPE_RSS091 = "rss"; public static final String TYPE_ATOM1 = "atom"; - private String title; + /* title as defined by the feed */ + private String feedTitle; + /* custom title set by the user */ + private String customTitle; + /** * Contains 'id'-element in Atom feed. */ @@ -93,13 +95,14 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource { /** * This constructor is used for restoring a feed from the database. */ - public Feed(long id, String lastUpdate, String title, String link, String description, String paymentLink, + public Feed(long id, String lastUpdate, String title, String customTitle, String link, String description, String paymentLink, String author, String language, String type, String feedIdentifier, FeedImage image, String fileUrl, String downloadUrl, boolean downloaded, FlattrStatus status, boolean paged, String nextPageLink, String filter, boolean lastUpdateFailed) { super(fileUrl, downloadUrl, downloaded); this.id = id; - this.title = title; + this.feedTitle = title; + this.customTitle = customTitle; this.lastUpdate = lastUpdate; this.link = link; this.description = description; @@ -127,7 +130,7 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource { public Feed(long id, String lastUpdate, String title, String link, String description, String paymentLink, String author, String language, String type, String feedIdentifier, FeedImage image, String fileUrl, String downloadUrl, boolean downloaded) { - this(id, lastUpdate, title, link, description, paymentLink, author, language, type, feedIdentifier, image, + this(id, lastUpdate, title, null, link, description, paymentLink, author, language, type, feedIdentifier, image, fileUrl, downloadUrl, downloaded, new FlattrStatus(), false, null, null, false); } @@ -155,7 +158,7 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource { */ public Feed(String url, String lastUpdate, String title) { this(url, lastUpdate); - this.title = title; + this.feedTitle = title; this.flattrStatus = new FlattrStatus(); } @@ -172,6 +175,7 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource { int indexId = cursor.getColumnIndex(PodDBAdapter.KEY_ID); int indexLastUpdate = cursor.getColumnIndex(PodDBAdapter.KEY_LASTUPDATE); int indexTitle = cursor.getColumnIndex(PodDBAdapter.KEY_TITLE); + int indexCustomTitle = cursor.getColumnIndex(PodDBAdapter.KEY_CUSTOM_TITLE); int indexLink = cursor.getColumnIndex(PodDBAdapter.KEY_LINK); int indexDescription = cursor.getColumnIndex(PodDBAdapter.KEY_DESCRIPTION); int indexPaymentLink = cursor.getColumnIndex(PodDBAdapter.KEY_PAYMENT_LINK); @@ -192,6 +196,7 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource { cursor.getLong(indexId), cursor.getString(indexLastUpdate), cursor.getString(indexTitle), + cursor.getString(indexCustomTitle), cursor.getString(indexLink), cursor.getString(indexDescription), cursor.getString(indexPaymentLink), @@ -215,33 +220,6 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource { return feed; } - - /** - * Returns true if at least one item in the itemlist is unread. - * - */ - public boolean hasNewItems() { - for (FeedItem item : items) { - if (item.isNew()) { - return true; - } - } - return false; - } - - /** - * Returns true if at least one item in the itemlist is unread. - * - */ - public boolean hasUnplayedItems() { - for (FeedItem item : items) { - if (!item.isNew() && !item.isPlayed()) { - return true; - } - } - return false; - } - /** * Returns the number of FeedItems. * @@ -269,8 +247,8 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource { return feedIdentifier; } else if (download_url != null && !download_url.isEmpty()) { return download_url; - } else if (title != null && !title.isEmpty()) { - return title; + } else if (feedTitle != null && !feedTitle.isEmpty()) { + return feedTitle; } else { return link; } @@ -278,8 +256,8 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource { @Override public String getHumanReadableIdentifier() { - if (title != null) { - return title; + if (feedTitle != null) { + return feedTitle; } else { return download_url; } @@ -288,8 +266,11 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource { public void updateFromOther(Feed other) { // don't update feed's download_url, we do that manually if redirected // see AntennapodHttpClient - if (other.title != null) { - title = other.title; + if (other.image != null) { + this.image = other.image; + } + if (other.feedTitle != null) { + feedTitle = other.feedTitle; } if (other.feedIdentifier != null) { feedIdentifier = other.feedIdentifier; @@ -324,7 +305,10 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource { if (super.compareWithOther(other)) { return true; } - if (!TextUtils.equals(title, other.title)) { + if(other.image != null && !TextUtils.equals(image.download_url, other.image.download_url)) { + return true; + } + if (!TextUtils.equals(feedTitle, other.feedTitle)) { return true; } if (other.feedIdentifier != null) { @@ -385,11 +369,28 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource { } public String getTitle() { - return title; + return !TextUtils.isEmpty(customTitle) ? customTitle : feedTitle; } public void setTitle(String title) { - this.title = title; + this.feedTitle = title; + } + + public String getFeedTitle() { + return this.feedTitle; + } + + @Nullable + public String getCustomTitle() { + return this.customTitle; + } + + public void setCustomTitle(String customTitle) { + if(customTitle == null || customTitle.equals(feedTitle)) { + this.customTitle = null; + } else { + this.customTitle = customTitle; + } } public String getLink() { @@ -488,7 +489,7 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource { return preferences; } - public void savePreferences(Context context) { + public void savePreferences() { DBWriter.setFeedPreferences(preferences); } @@ -501,9 +502,9 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource { } @Override - public Uri getImageUri() { + public String getImageLocation() { if (image != null) { - return image.getImageUri(); + return image.getImageLocation(); } else { return null; } diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedImage.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedImage.java index bd7ceb54f..f0c508830 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedImage.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedImage.java @@ -1,7 +1,6 @@ package de.danoeh.antennapod.core.feed; import android.database.Cursor; -import android.net.Uri; import java.io.File; @@ -81,11 +80,11 @@ public class FeedImage extends FeedFile implements ImageResource { } @Override - public Uri getImageUri() { + public String getImageLocation() { if (file_url != null && downloaded) { - return Uri.fromFile(new File(file_url)); + return new File(file_url).getAbsolutePath(); } else if(download_url != null) { - return Uri.parse(download_url); + return download_url; } else { return null; } diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java index 4921c0576..66c4b10d0 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java @@ -1,7 +1,7 @@ package de.danoeh.antennapod.core.feed; import android.database.Cursor; -import android.net.Uri; +import android.support.annotation.Nullable; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; @@ -54,9 +54,9 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr private long feedId; private int state; - public final static int NEW = -1; - public final static int UNPLAYED = 0; - public final static int PLAYED = 1; + public static final int NEW = -1; + public static final int UNPLAYED = 0; + public static final int PLAYED = 1; private String paymentLink; private FlattrStatus flattrStatus; @@ -177,6 +177,9 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr public void updateFromOther(FeedItem other) { super.updateFromOther(other); + if (other.image != null) { + this.image = other.image; + } if (other.title != null) { title = other.title; } @@ -270,6 +273,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr } } + @Nullable public FeedMedia getMedia() { return media; } @@ -374,13 +378,13 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr } @Override - public Uri getImageUri() { + public String getImageLocation() { if(media != null && media.hasEmbeddedPicture()) { - return media.getImageUri(); + return media.getImageLocation(); } else if (image != null) { - return image.getImageUri(); + return image.getImageLocation(); } else if (feed != null) { - return feed.getImageUri(); + return feed.getImageLocation(); } else { return null; } diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java index 9d8f4adf8..200153876 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java @@ -18,6 +18,7 @@ public class FeedItemFilter { private boolean showNotQueued = false; private boolean showDownloaded = false; private boolean showNotDownloaded = false; + private boolean showHasMedia = false; public FeedItemFilter(String properties) { this(TextUtils.split(properties, ",")); @@ -49,6 +50,9 @@ public class FeedItemFilter { case "not_downloaded": showNotDownloaded = true; break; + case "has_media": + showHasMedia = true; + break; } } } @@ -82,6 +86,8 @@ public class FeedItemFilter { if (showDownloaded && !downloaded) continue; if (showNotDownloaded && downloaded) continue; + if (showHasMedia && !item.hasMedia()) continue; + // If the item reaches here, it meets all criteria result.add(item); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java index 7f064fff3..d4414227c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java @@ -1,25 +1,30 @@ package de.danoeh.antennapod.core.feed; +import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.database.Cursor; import android.media.MediaMetadataRetriever; -import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; import android.support.annotation.Nullable; +import android.support.v4.media.MediaBrowserCompat; +import android.support.v4.media.MediaDescriptionCompat; import java.util.Date; import java.util.List; import java.util.concurrent.Callable; -import de.danoeh.antennapod.core.cast.RemoteMedia; +import de.danoeh.antennapod.core.gpoddernet.model.GpodnetEpisodeAction; +import de.danoeh.antennapod.core.preferences.GpodnetPreferences; import de.danoeh.antennapod.core.preferences.PlaybackPreferences; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.storage.DBReader; +import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.storage.PodDBAdapter; import de.danoeh.antennapod.core.util.ChapterUtils; +import de.danoeh.antennapod.core.util.flattr.FlattrUtils; import de.danoeh.antennapod.core.util.playback.Playable; public class FeedMedia extends FeedFile implements Playable { @@ -48,6 +53,8 @@ public class FeedMedia extends FeedFile implements Playable { private String mime_type; @Nullable private volatile FeedItem item; private Date playbackCompletionDate; + private int startPosition = -1; + private int playedDurationWhenStarted; // if null: unknown, will be checked private Boolean hasEmbeddedPicture; @@ -73,6 +80,7 @@ public class FeedMedia extends FeedFile implements Playable { this.duration = duration; this.position = position; this.played_duration = played_duration; + this.playedDurationWhenStarted = played_duration; this.size = size; this.mime_type = mime_type; this.playbackCompletionDate = playbackCompletionDate == null @@ -150,6 +158,21 @@ public class FeedMedia extends FeedFile implements Playable { } /** + * Returns a MediaItem representing the FeedMedia object. + * This is used by the MediaBrowserService + */ + public MediaBrowserCompat.MediaItem getMediaItem() { + Playable p = this; + MediaDescriptionCompat description = new MediaDescriptionCompat.Builder() + .setMediaId(String.valueOf(id)) + .setTitle(p.getEpisodeTitle()) + .setDescription(p.getFeedTitle()) + .setSubtitle(p.getFeedTitle()) + .build(); + return new MediaBrowserCompat.MediaItem(description, MediaBrowserCompat.MediaItem.FLAG_PLAYABLE); + } + + /** * Uses mimetype to determine the type of media. */ public MediaType getMediaType() { @@ -321,12 +344,10 @@ public class FeedMedia extends FeedFile implements Playable { } public boolean hasEmbeddedPicture() { - return false; - // TODO: reenable! - //if(hasEmbeddedPicture == null) { - // checkEmbeddedPicture(); - //} - //return hasEmbeddedPicture; + if(hasEmbeddedPicture == null) { + checkEmbeddedPicture(); + } + return hasEmbeddedPicture; } @Override @@ -459,15 +480,59 @@ public class FeedMedia extends FeedFile implements Playable { } setPosition(newPosition); setLastPlayedTime(timeStamp); + if(startPosition>=0 && position > startPosition) { + setPlayedDuration(playedDurationWhenStarted + position - startPosition); + } DBWriter.setFeedMediaPlaybackInformation(this); } @Override public void onPlaybackStart() { + startPosition = (position > 0) ? position : 0; + playedDurationWhenStarted = played_duration; } + @Override - public void onPlaybackCompleted() { + public void onPlaybackPause(Context context) { + if (position > startPosition) { + played_duration = playedDurationWhenStarted + position - startPosition; + playedDurationWhenStarted = played_duration; + } + postPlaybackTasks(context, false); + startPosition = position; + } + @Override + public void onPlaybackCompleted(Context context) { + postPlaybackTasks(context, true); + startPosition = -1; + } + + private void postPlaybackTasks(Context context, boolean completed) { + if (item != null) { + // gpodder play action + if (startPosition >= 0 && (completed || startPosition < position) && + GpodnetPreferences.loggedIn()) { + GpodnetEpisodeAction action = new GpodnetEpisodeAction.Builder(item, GpodnetEpisodeAction.Action.PLAY) + .currentDeviceId() + .currentTimestamp() + .started(startPosition / 1000) + .position((completed ? duration : position) / 1000) + .total(duration / 1000) + .build(); + GpodnetPreferences.enqueueEpisodeAction(action); + } + // Auto flattr + float autoFlattrThreshold = UserPreferences.getAutoFlattrPlayedDurationThreshold(); + if (FlattrUtils.hasToken() && + UserPreferences.isAutoFlattr() && + item.getPaymentLink() != null && + item.getFlattrStatus().getUnflattred() && + (completed && autoFlattrThreshold <= 1.0f || + played_duration >= autoFlattrThreshold * duration)) { + DBTasks.flattrItemIfLoggedIn(context, item); + } + } } @Override @@ -514,20 +579,11 @@ public class FeedMedia extends FeedFile implements Playable { }; @Override - public Uri getImageUri() { + public String getImageLocation() { if (hasEmbeddedPicture()) { - Uri.Builder builder = new Uri.Builder(); - builder.scheme(SCHEME_MEDIA).encodedPath(getLocalMediaUrl()); - - if (item != null && item.getFeed() != null) { - final Uri feedImgUri = item.getFeed().getImageUri(); - if (feedImgUri != null) { - builder.appendQueryParameter(PARAM_FALLBACK, feedImgUri.toString()); - } - } - return builder.build(); + return getLocalMediaUrl(); } else if(item != null) { - return item.getImageUri(); + return item.getImageLocation(); } else { return null; } @@ -550,7 +606,7 @@ public class FeedMedia extends FeedFile implements Playable { super.setFile_url(file_url); } - private void checkEmbeddedPicture() { + public void checkEmbeddedPicture() { if (!localFileAvailable()) { hasEmbeddedPicture = Boolean.FALSE; return; @@ -572,7 +628,7 @@ public class FeedMedia extends FeedFile implements Playable { @Override public boolean equals(Object o) { - if (o instanceof RemoteMedia) { + if (FeedMediaFlavorHelper.instanceOfRemoteMedia(o)) { return o.equals(this); } return super.equals(o); diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java index e2b5dd7c2..66fc4024b 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java @@ -68,7 +68,7 @@ public class FeedPreferences { /** * @return the filter for this feed */ - public @NonNull FeedFilter getFilter() { + @NonNull public FeedFilter getFilter() { return filter; } diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java index 0baff9723..835dee735 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java +++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java @@ -6,7 +6,6 @@ import com.bumptech.glide.Glide; import com.bumptech.glide.GlideBuilder; import com.bumptech.glide.load.DecodeFormat; import com.bumptech.glide.load.engine.cache.InternalCacheDiskCacheFactory; -import com.bumptech.glide.load.model.GlideUrl; import com.bumptech.glide.module.GlideModule; import java.io.InputStream; @@ -27,7 +26,7 @@ public class ApGlideModule implements GlideModule { @Override public void registerComponents(Context context, Glide glide) { - glide.register(GlideUrl.class, InputStream.class, new ApOkHttpUrlLoader.Factory()); + glide.register(String.class, InputStream.class, new ApOkHttpUrlLoader.Factory()); } -}
\ No newline at end of file +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java index 513264a05..8ca9faa0d 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java @@ -4,15 +4,12 @@ import android.content.Context; import android.text.TextUtils; import android.util.Log; -import com.bumptech.glide.integration.okhttp.OkHttpStreamFetcher; +import com.bumptech.glide.integration.okhttp3.OkHttpStreamFetcher; import com.bumptech.glide.load.data.DataFetcher; import com.bumptech.glide.load.model.GenericLoaderFactory; import com.bumptech.glide.load.model.GlideUrl; import com.bumptech.glide.load.model.ModelLoader; import com.bumptech.glide.load.model.ModelLoaderFactory; -import com.squareup.okhttp.Interceptor; -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.Response; import java.io.IOException; import java.io.InputStream; @@ -22,18 +19,22 @@ import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; import de.danoeh.antennapod.core.service.download.HttpDownloader; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.util.NetworkUtils; +import okhttp3.Interceptor; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; /** - * @see com.bumptech.glide.integration.okhttp.OkHttpUrlLoader + * @see com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader */ -public class ApOkHttpUrlLoader implements ModelLoader<GlideUrl, InputStream> { +public class ApOkHttpUrlLoader implements ModelLoader<String, InputStream> { private static final String TAG = ApOkHttpUrlLoader.class.getSimpleName(); /** * The default factory for {@link ApOkHttpUrlLoader}s. */ - public static class Factory implements ModelLoaderFactory<GlideUrl, InputStream> { + public static class Factory implements ModelLoaderFactory<String, InputStream> { private static volatile OkHttpClient internalClient; private OkHttpClient client; @@ -42,9 +43,10 @@ public class ApOkHttpUrlLoader implements ModelLoader<GlideUrl, InputStream> { if (internalClient == null) { synchronized (Factory.class) { if (internalClient == null) { - internalClient = AntennapodHttpClient.newHttpClient(); - internalClient.interceptors().add(new NetworkAllowanceInterceptor()); - internalClient.interceptors().add(new BasicAuthenticationInterceptor()); + OkHttpClient.Builder builder = AntennapodHttpClient.newBuilder(); + builder.interceptors().add(new NetworkAllowanceInterceptor()); + builder.interceptors().add(new BasicAuthenticationInterceptor()); + internalClient = builder.build(); } } } @@ -66,7 +68,7 @@ public class ApOkHttpUrlLoader implements ModelLoader<GlideUrl, InputStream> { } @Override - public ModelLoader<GlideUrl, InputStream> build(Context context, GenericLoaderFactory factories) { + public ModelLoader<String, InputStream> build(Context context, GenericLoaderFactory factories) { return new ApOkHttpUrlLoader(client); } @@ -83,8 +85,17 @@ public class ApOkHttpUrlLoader implements ModelLoader<GlideUrl, InputStream> { } @Override - public DataFetcher<InputStream> getResourceFetcher(GlideUrl model, int width, int height) { - return new OkHttpStreamFetcher(client, model); + public DataFetcher<InputStream> getResourceFetcher(String model, int width, int height) { + Log.d(TAG, "getResourceFetcher() called with: " + "model = [" + model + "], width = [" + + width + "], height = [" + height + "]"); + if(TextUtils.isEmpty(model)) { + return null; + } else if(model.startsWith("/")) { + return new AudioCoverFetcher(model); + } else { + GlideUrl url = new GlideUrl(model); + return new OkHttpStreamFetcher(client, url); + } } private static class NetworkAllowanceInterceptor implements Interceptor { @@ -104,8 +115,8 @@ public class ApOkHttpUrlLoader implements ModelLoader<GlideUrl, InputStream> { @Override public Response intercept(Chain chain) throws IOException { - com.squareup.okhttp.Request request = chain.request(); - String url = request.urlString(); + Request request = chain.request(); + String url = request.url().toString(); String authentication = DBReader.getImageAuthentication(url); if(TextUtils.isEmpty(authentication)) { @@ -116,7 +127,7 @@ public class ApOkHttpUrlLoader implements ModelLoader<GlideUrl, InputStream> { // add authentication String[] auth = authentication.split(":"); String credentials = HttpDownloader.encodeCredentials(auth[0], auth[1], "ISO-8859-1"); - com.squareup.okhttp.Request newRequest = request + Request newRequest = request .newBuilder() .addHeader("Authorization", credentials) .build(); diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/AudioCoverFetcher.java b/core/src/main/java/de/danoeh/antennapod/core/glide/AudioCoverFetcher.java new file mode 100644 index 000000000..48dadc492 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/glide/AudioCoverFetcher.java @@ -0,0 +1,48 @@ +package de.danoeh.antennapod.core.glide; + +import android.media.MediaMetadataRetriever; +import android.util.Log; + +import com.bumptech.glide.Priority; +import com.bumptech.glide.load.data.DataFetcher; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +// see https://github.com/bumptech/glide/issues/699 +class AudioCoverFetcher implements DataFetcher<InputStream> { + + private static final String TAG = "AudioCoverFetcher"; + + private final String path; + + public AudioCoverFetcher(String path) { + this.path = path; + } + + @Override public String getId() { + return path; + } + + @Override public InputStream loadData(Priority priority) throws Exception { + MediaMetadataRetriever retriever = new MediaMetadataRetriever(); + try { + retriever.setDataSource(path); + byte[] picture = retriever.getEmbeddedPicture(); + if (picture != null) { + return new ByteArrayInputStream(picture); + } + } finally { + retriever.release(); + } + throw new IOException("Loading embedded cover did not work"); + } + + @Override public void cleanup() { + // nothing to clean up + } + @Override public void cancel() { + // cannot cancel + } +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java b/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java index 9f716e546..4459fbd08 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java @@ -1,15 +1,6 @@ package de.danoeh.antennapod.core.gpoddernet; import android.support.annotation.NonNull; - -import com.squareup.okhttp.Credentials; -import com.squareup.okhttp.MediaType; -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.Request; -import com.squareup.okhttp.RequestBody; -import com.squareup.okhttp.Response; -import com.squareup.okhttp.ResponseBody; - import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -38,6 +29,13 @@ import de.danoeh.antennapod.core.gpoddernet.model.GpodnetTag; import de.danoeh.antennapod.core.gpoddernet.model.GpodnetUploadChangesResponse; import de.danoeh.antennapod.core.preferences.GpodnetPreferences; import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; +import okhttp3.Credentials; +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import okhttp3.ResponseBody; /** * Communicates with the gpodder.net service. @@ -570,15 +568,9 @@ public class GpodnetService { e.printStackTrace(); throw new GpodnetServiceException(e); } finally { - if (response != null && body != null) { - try { - body.close(); - } catch (IOException e) { - e.printStackTrace(); - throw new GpodnetServiceException(e); - } + if (body != null) { + body.close(); } - } return responseString; } @@ -605,12 +597,7 @@ public class GpodnetService { throw new GpodnetServiceException(e); } finally { if (body != null) { - try { - body.close(); - } catch (IOException e) { - e.printStackTrace(); - throw new GpodnetServiceException(e); - } + body.close(); } } return result; @@ -619,12 +606,7 @@ public class GpodnetService { private String getStringFromResponseBody(@NonNull ResponseBody body) throws GpodnetServiceException { ByteArrayOutputStream outputStream; - int contentLength = 0; - try { - contentLength = (int) body.contentLength(); - } catch (IOException ignore) { - // ignore - } + int contentLength = (int) body.contentLength(); if (contentLength > 0) { outputStream = new ByteArrayOutputStream(contentLength); } else { diff --git a/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlSymbols.java b/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlSymbols.java deleted file mode 100644 index c973713cb..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlSymbols.java +++ /dev/null @@ -1,22 +0,0 @@ -package de.danoeh.antennapod.core.opml; - -/** Contains symbols for reading and writing OPML documents. */ -public final class OpmlSymbols { - - public static final String OPML = "opml"; - public static final String BODY = "body"; - public static final String OUTLINE = "outline"; - public static final String TEXT = "text"; - public static final String XMLURL = "xmlUrl"; - public static final String HTMLURL = "htmlUrl"; - public static final String TYPE = "type"; - public static final String VERSION = "version"; - public static final String HEAD = "head"; - public static final String TITLE = "title"; - public static final String DATE_CREATED = "dateCreated"; - - private OpmlSymbols() { - - } - -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/GpodnetPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/GpodnetPreferences.java index fa002ae5f..1e7ee0f11 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/preferences/GpodnetPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/GpodnetPreferences.java @@ -39,6 +39,8 @@ public class GpodnetPreferences { public static final String PREF_SYNC_ADDED = "de.danoeh.antennapod.preferences.gpoddernet.sync_added"; public static final String PREF_SYNC_REMOVED = "de.danoeh.antennapod.preferences.gpoddernet.sync_removed"; public static final String PREF_SYNC_EPISODE_ACTIONS = "de.danoeh.antennapod.preferences.gpoddernet.sync_queued_episode_actions"; + public static final String PREF_LAST_SYNC_ATTEMPT_TIMESTAMP = "de.danoeh.antennapod.preferences.gpoddernet.last_sync_attempt_timestamp"; + public static final String PREF_LAST_SYNC_ATTEMPT_RESULT = "de.danoeh.antennapod.preferences.gpoddernet.last_sync_attempt_result"; private static String username; private static String password; @@ -58,12 +60,26 @@ public class GpodnetPreferences { private static long lastEpisodeActionsSyncTimeStamp; + private static long lastSyncAttemptTimestamp; + + private static boolean lastSyncAttemptResult; + private static boolean preferencesLoaded = false; private static SharedPreferences getPreferences() { return ClientConfig.applicationCallbacks.getApplicationInstance().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE); } + public static void registerOnSharedPreferenceChangeListener( + SharedPreferences.OnSharedPreferenceChangeListener listener) { + getPreferences().registerOnSharedPreferenceChangeListener(listener); + } + + public static void unregisterOnSharedPreferenceChangeListener( + SharedPreferences.OnSharedPreferenceChangeListener listener) { + getPreferences().unregisterOnSharedPreferenceChangeListener(listener); + } + private static synchronized void ensurePreferencesLoaded() { if (!preferencesLoaded) { SharedPreferences prefs = getPreferences(); @@ -72,6 +88,8 @@ public class GpodnetPreferences { deviceID = prefs.getString(PREF_GPODNET_DEVICEID, null); lastSubscriptionSyncTimestamp = prefs.getLong(PREF_LAST_SUBSCRIPTION_SYNC_TIMESTAMP, 0); lastEpisodeActionsSyncTimeStamp = prefs.getLong(PREF_LAST_EPISODE_ACTIONS_SYNC_TIMESTAMP, 0); + lastSyncAttemptTimestamp = prefs.getLong(PREF_LAST_SYNC_ATTEMPT_TIMESTAMP, 0); + lastSyncAttemptResult = prefs.getBoolean(PREF_LAST_SYNC_ATTEMPT_RESULT, false); addedFeeds = readListFromString(prefs.getString(PREF_SYNC_ADDED, "")); removedFeeds = readListFromString(prefs.getString(PREF_SYNC_REMOVED, "")); queuedEpisodeActions = readEpisodeActionsFromString(prefs.getString(PREF_SYNC_EPISODE_ACTIONS, "")); @@ -84,19 +102,25 @@ public class GpodnetPreferences { private static void writePreference(String key, String value) { SharedPreferences.Editor editor = getPreferences().edit(); editor.putString(key, value); - editor.commit(); + editor.apply(); } private static void writePreference(String key, long value) { SharedPreferences.Editor editor = getPreferences().edit(); editor.putLong(key, value); - editor.commit(); + editor.apply(); } private static void writePreference(String key, Collection<String> value) { SharedPreferences.Editor editor = getPreferences().edit(); editor.putString(key, writeListToString(value)); - editor.commit(); + editor.apply(); + } + + private static void writePreference(String key, boolean value) { + SharedPreferences.Editor editor = getPreferences().edit(); + editor.putBoolean(key, value); + editor.apply(); } public static String getUsername() { @@ -149,6 +173,23 @@ public class GpodnetPreferences { writePreference(PREF_LAST_EPISODE_ACTIONS_SYNC_TIMESTAMP, timestamp); } + public static long getLastSyncAttemptTimestamp() { + ensurePreferencesLoaded(); + return lastSyncAttemptTimestamp; + } + + public static boolean getLastSyncAttemptResult() { + ensurePreferencesLoaded(); + return lastSyncAttemptResult; + } + + public static void setLastSyncAttempt(boolean result, long timestamp) { + GpodnetPreferences.lastSyncAttemptResult = result; + GpodnetPreferences.lastSyncAttemptTimestamp = timestamp; + writePreference(PREF_LAST_SYNC_ATTEMPT_RESULT, result); + writePreference(PREF_LAST_SYNC_ATTEMPT_TIMESTAMP, timestamp); + } + public static String getHostname() { ensurePreferencesLoaded(); return hostname; @@ -271,6 +312,8 @@ public class GpodnetPreferences { writePreference(PREF_SYNC_EPISODE_ACTIONS, writeEpisodeActionsToString(queuedEpisodeActions)); feedListLock.unlock(); setLastSubscriptionSyncTimestamp(0); + setLastSyncAttempt(false, 0); + UserPreferences.setGpodnetNotificationsEnabled(); } private static Set<String> readListFromString(String s) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/SleepTimerPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/SleepTimerPreferences.java new file mode 100644 index 000000000..b7ed890f5 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/SleepTimerPreferences.java @@ -0,0 +1,80 @@ +package de.danoeh.antennapod.core.preferences; + +import android.content.Context; +import android.content.SharedPreferences; +import android.support.annotation.NonNull; +import android.util.Log; + +import java.util.concurrent.TimeUnit; + +public class SleepTimerPreferences { + + private static final String TAG = "SleepTimerPreferences"; + + private static final String PREF_NAME = "SleepTimerDialog"; + private static final String PREF_VALUE = "LastValue"; + private static final String PREF_TIME_UNIT = "LastTimeUnit"; + private static final String PREF_VIBRATE = "Vibrate"; + private static final String PREF_SHAKE_TO_RESET = "ShakeToReset"; + private static final String PREF_AUTO_ENABLE = "AutoEnable"; + + private static final TimeUnit[] UNITS = { TimeUnit.SECONDS, TimeUnit.MINUTES, TimeUnit.HOURS }; + + private static final String DEFAULT_VALUE = "15"; + private static final int DEFAULT_TIME_UNIT = 1; + + private static Context context; + private static SharedPreferences prefs; + + /** + * Sets up the UserPreferences class. + * + * @throws IllegalArgumentException if context is null + */ + public static void init(@NonNull Context context) { + Log.d(TAG, "Creating new instance of SleepTimerPreferences"); + SleepTimerPreferences.prefs = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE); + } + + public static void setLastTimer(String value, int timeUnit) { + prefs.edit().putString(PREF_VALUE, value).putInt(PREF_TIME_UNIT, timeUnit).apply(); + } + + public static String lastTimerValue() { + return prefs.getString(PREF_VALUE, DEFAULT_VALUE); + } + + public static int lastTimerTimeUnit() { + return prefs.getInt(PREF_TIME_UNIT, DEFAULT_TIME_UNIT); + } + + public static long timerMillis() { + long value = Long.parseLong(lastTimerValue()); + return UNITS[lastTimerTimeUnit()].toMillis(value); + } + + public static void setVibrate(boolean vibrate) { + prefs.edit().putBoolean(PREF_VIBRATE, vibrate).apply(); + } + + public static boolean vibrate() { + return prefs.getBoolean(PREF_VIBRATE, true); + } + + public static void setShakeToReset(boolean shakeToReset) { + prefs.edit().putBoolean(PREF_SHAKE_TO_RESET, shakeToReset).apply(); + } + + public static boolean shakeToReset() { + return prefs.getBoolean(PREF_SHAKE_TO_RESET, true); + } + + public static void setAutoEnable(boolean autoEnable) { + prefs.edit().putBoolean(PREF_AUTO_ENABLE, autoEnable).apply(); + } + + public static boolean autoEnable() { + return prefs.getBoolean(PREF_AUTO_ENABLE, false); + } + +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java index 5c7a6b464..a3eaf187e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java @@ -57,7 +57,6 @@ public class UserPreferences { public static final String PREF_LOCKSCREEN_BACKGROUND = "prefLockscreenBackground"; public static final String PREF_SHOW_DOWNLOAD_REPORT = "prefShowDownloadReport"; - // Queue public static final String PREF_QUEUE_ADD_TO_FRONT = "prefQueueAddToFront"; @@ -66,8 +65,10 @@ public class UserPreferences { public static final String PREF_UNPAUSE_ON_HEADSET_RECONNECT = "prefUnpauseOnHeadsetReconnect"; public static final String PREF_UNPAUSE_ON_BLUETOOTH_RECONNECT = "prefUnpauseOnBluetoothReconnect"; public static final String PREF_HARDWARE_FOWARD_BUTTON_SKIPS = "prefHardwareForwardButtonSkips"; + public static final String PREF_HARDWARE_PREVIOUS_BUTTON_RESTARTS = "prefHardwarePreviousButtonRestarts"; public static final String PREF_FOLLOW_QUEUE = "prefFollowQueue"; public static final String PREF_SKIP_KEEPS_EPISODE = "prefSkipKeepsEpisode"; + public static final String PREF_FAVORITE_KEEPS_EPISODE = "prefFavoriteKeepsEpisode"; public static final String PREF_AUTO_DELETE = "prefAutoDelete"; public static final String PREF_SMART_MARK_AS_PLAYED_SECS = "prefSmartMarkAsPlayedSecs"; public static final String PREF_PLAYBACK_SPEED_ARRAY = "prefPlaybackSpeedArray"; @@ -75,6 +76,7 @@ public class UserPreferences { public static final String PREF_RESUME_AFTER_CALL = "prefResumeAfterCall"; // Network + public static final String PREF_ENQUEUE_DOWNLOADED = "prefEnqueueDownloaded"; public static final String PREF_UPDATE_INTERVAL = "prefAutoUpdateIntervall"; public static final String PREF_MOBILE_UPDATE = "prefMobileUpdate"; public static final String PREF_EPISODE_CLEANUP = "prefEpisodeCleanup"; @@ -83,6 +85,7 @@ public class UserPreferences { public static final String PREF_ENABLE_AUTODL = "prefEnableAutoDl"; public static final String PREF_ENABLE_AUTODL_ON_BATTERY = "prefEnableAutoDownloadOnBattery"; public static final String PREF_ENABLE_AUTODL_WIFI_FILTER = "prefEnableAutoDownloadWifiFilter"; + public static final String PREF_ENABLE_AUTODL_ON_MOBILE = "prefEnableAutoDownloadOnMobile"; public static final String PREF_AUTODL_SELECTED_NETWORKS = "prefAutodownloadSelectedNetworks"; public static final String PREF_PROXY_TYPE = "prefProxyType"; public static final String PREF_PROXY_HOST = "prefProxyHost"; @@ -93,6 +96,7 @@ public class UserPreferences { // Services public static final String PREF_AUTO_FLATTR = "pref_auto_flattr"; public static final String PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD = "prefAutoFlattrPlayedDurationThreshold"; + public static final String PREF_GPODNET_NOTIFICATIONS = "pref_gpodnet_notifications"; // Other public static final String PREF_DATA_FOLDER = "prefDataFolder"; @@ -125,10 +129,12 @@ public class UserPreferences { public static final int FEED_ORDER_COUNTER = 0; public static final int FEED_ORDER_ALPHABETICAL = 1; public static final int FEED_ORDER_LAST_UPDATE = 2; + public static final int FEED_ORDER_MOST_PLAYED = 3; public static final int FEED_COUNTER_SHOW_NEW_UNPLAYED_SUM = 0; public static final int FEED_COUNTER_SHOW_NEW = 1; public static final int FEED_COUNTER_SHOW_UNPLAYED = 2; public static final int FEED_COUNTER_SHOW_NONE = 3; + public static final int FEED_COUNTER_SHOW_DOWNLOADED = 4; private static Context context; private static SharedPreferences prefs; @@ -257,11 +263,10 @@ public class UserPreferences { return prefs.getBoolean(PREF_SHOW_DOWNLOAD_REPORT, true); } - /** - * Returns {@code true} if new queue elements are added to the front - * - * @return {@code true} if new queue elements are added to the front; {@code false} otherwise - */ + public static boolean enqueueDownloadedEpisodes() { + return prefs.getBoolean(PREF_ENQUEUE_DOWNLOADED, true); + } + public static boolean enqueueAtFront() { return prefs.getBoolean(PREF_QUEUE_ADD_TO_FRONT, false); } @@ -282,6 +287,10 @@ public class UserPreferences { return prefs.getBoolean(PREF_HARDWARE_FOWARD_BUTTON_SKIPS, false); } + public static boolean shouldHardwarePreviousButtonRestart() { + return prefs.getBoolean(PREF_HARDWARE_PREVIOUS_BUTTON_RESTARTS, false); + } + public static boolean isFollowQueue() { return prefs.getBoolean(PREF_FOLLOW_QUEUE, true); @@ -289,6 +298,10 @@ public class UserPreferences { public static boolean shouldSkipKeepEpisode() { return prefs.getBoolean(PREF_SKIP_KEEPS_EPISODE, true); } + public static boolean shouldFavoriteKeepEpisode() { + return prefs.getBoolean(PREF_FAVORITE_KEEPS_EPISODE, true); + } + public static boolean isAutoDelete() { return prefs.getBoolean(PREF_AUTO_DELETE, false); } @@ -332,7 +345,10 @@ public class UserPreferences { } - + /* + * Returns update interval in milliseconds; value 0 means that auto update is disabled + * or feeds are updated at a certain time of day + */ public static long getUpdateInterval() { String updateInterval = prefs.getString(PREF_UPDATE_INTERVAL, "0"); if(!updateInterval.contains(":")) { @@ -387,6 +403,11 @@ public class UserPreferences { return prefs.getBoolean(PREF_ENABLE_AUTODL_WIFI_FILTER, false); } + public static boolean isEnableAutodownloadOnMobile() { + return prefs.getBoolean(PREF_ENABLE_AUTODL_ON_MOBILE, false); + } + + public static int getImageCacheSize() { String cacheSizeString = prefs.getString(PREF_IMAGE_CACHE_SIZE, IMAGE_CACHE_DEFAULT_VALUE); int cacheSizeInt = Integer.parseInt(cacheSizeString); @@ -400,7 +421,7 @@ public class UserPreferences { return cacheSizeMB; } - public static int getFastFowardSecs() { + public static int getFastForwardSecs() { return prefs.getInt(PREF_FAST_FORWARD_SECS, 30); } @@ -465,13 +486,13 @@ public class UserPreferences { return prefs.getBoolean(PREF_QUEUE_LOCKED, false); } - public static void setPrefFastForwardSecs(int secs) { + public static void setFastForwardSecs(int secs) { prefs.edit() .putInt(PREF_FAST_FORWARD_SECS, secs) .apply(); } - public static void setPrefRewindSecs(int secs) { + public static void setRewindSecs(int secs) { prefs.edit() .putInt(PREF_REWIND_SECS, secs) .apply(); @@ -547,6 +568,16 @@ public class UserPreferences { .apply(); } + public static boolean gpodnetNotificationsEnabled() { + return prefs.getBoolean(PREF_GPODNET_NOTIFICATIONS, true); + } + + public static void setGpodnetNotificationsEnabled() { + prefs.edit() + .putBoolean(PREF_GPODNET_NOTIFICATIONS, true) + .apply(); + } + public static void setHiddenDrawerItems(List<String> items) { String str = TextUtils.join(",", items); prefs.edit() @@ -744,12 +775,12 @@ public class UserPreferences { if (timeOfDay.length == 2) { restartUpdateTimeOfDayAlarm(timeOfDay[0], timeOfDay[1]); } else { - long hours = getUpdateInterval(); - long startTrigger = hours; + long milliseconds = getUpdateInterval(); + long startTrigger = milliseconds; if (now) { startTrigger = TimeUnit.SECONDS.toMillis(10); } - restartUpdateIntervalAlarm(startTrigger, hours); + restartUpdateIntervalAlarm(startTrigger, milliseconds); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java b/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java index e0abe0efb..9bbeb7c88 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java +++ b/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java @@ -21,7 +21,7 @@ public class FeedUpdateReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { Log.d(TAG, "Received intent"); ClientConfig.initialize(context); - if (NetworkUtils.isDownloadAllowed()) { + if (NetworkUtils.networkAvailable() && NetworkUtils.isDownloadAllowed()) { DBTasks.refreshAllFeeds(context, null); } else { Log.d(TAG, "Blocking automatic update: no wifi available / no mobile updates allowed"); diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java b/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java index 9704d2111..e9312b929 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java @@ -30,6 +30,7 @@ import de.danoeh.antennapod.core.gpoddernet.model.GpodnetEpisodeActionPostRespon import de.danoeh.antennapod.core.gpoddernet.model.GpodnetSubscriptionChange; import de.danoeh.antennapod.core.gpoddernet.model.GpodnetUploadChangesResponse; import de.danoeh.antennapod.core.preferences.GpodnetPreferences; +import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.storage.DBWriter; @@ -107,7 +108,7 @@ public class GpodnetSyncService extends Service { private synchronized void sync() { - if (GpodnetPreferences.loggedIn() == false || NetworkUtils.networkAvailable() == false) { + if (!GpodnetPreferences.loggedIn() || !NetworkUtils.networkAvailable()) { stopSelf(); return; } @@ -161,6 +162,7 @@ public class GpodnetSyncService extends Service { GpodnetPreferences.removeRemovedFeeds(localRemoved); } GpodnetPreferences.setLastSubscriptionSyncTimestamp(newTimeStamp); + GpodnetPreferences.setLastSyncAttempt(true, System.currentTimeMillis()); clearErrorNotifications(); } catch (GpodnetServiceException e) { e.printStackTrace(); @@ -177,15 +179,15 @@ public class GpodnetSyncService extends Service { // local changes are always superior to remote changes! // add subscription if (1) not already subscribed and (2) not just unsubscribed for (String downloadUrl : changes.getAdded()) { - if (false == localSubscriptions.contains(downloadUrl) && - false == localRemoved.contains(downloadUrl)) { + if (!localSubscriptions.contains(downloadUrl) && + !localRemoved.contains(downloadUrl)) { Feed feed = new Feed(downloadUrl, null); DownloadRequester.getInstance().downloadFeed(this, feed); } } // remove subscription if not just subscribed (again) for (String downloadUrl : changes.getRemoved()) { - if(false == localAdded.contains(downloadUrl)) { + if(!localAdded.contains(downloadUrl)) { DBTasks.removeFeedWithDownloadUrl(GpodnetSyncService.this, downloadUrl); } } @@ -215,6 +217,7 @@ public class GpodnetSyncService extends Service { GpodnetPreferences.removeQueuedEpisodeActions(localActions); } GpodnetPreferences.setLastEpisodeActionsSyncTimestamp(lastUpdate); + GpodnetPreferences.setLastSyncAttempt(true, System.currentTimeMillis()); clearErrorNotifications(); } catch (GpodnetServiceException e) { e.printStackTrace(); @@ -232,7 +235,7 @@ public class GpodnetSyncService extends Service { } Map<Pair<String, String>, GpodnetEpisodeAction> localMostRecentPlayAction = new ArrayMap<>(); for(GpodnetEpisodeAction action : localActions) { - Pair key = new Pair(action.getPodcast(), action.getEpisode()); + Pair<String, String> key = new Pair<>(action.getPodcast(), action.getEpisode()); GpodnetEpisodeAction mostRecent = localMostRecentPlayAction.get(key); if (mostRecent == null || mostRecent.getTimestamp() == null) { localMostRecentPlayAction.put(key, action); @@ -256,7 +259,7 @@ public class GpodnetSyncService extends Service { case DOWNLOAD: break; case PLAY: - Pair key = new Pair(action.getPodcast(), action.getEpisode()); + Pair<String, String> key = new Pair<>(action.getPodcast(), action.getEpisode()); GpodnetEpisodeAction localMostRecent = localMostRecentPlayAction.get(key); if(localMostRecent == null || localMostRecent.getTimestamp() == null || @@ -298,8 +301,8 @@ public class GpodnetSyncService extends Service { private void updateErrorNotification(GpodnetServiceException exception) { Log.d(TAG, "Posting error notification"); + GpodnetPreferences.setLastSyncAttempt(false, System.currentTimeMillis()); - NotificationCompat.Builder builder = new NotificationCompat.Builder(this); final String title; final String description; final int id; @@ -308,18 +311,23 @@ public class GpodnetSyncService extends Service { description = getString(R.string.gpodnetsync_auth_error_descr); id = R.id.notification_gpodnet_sync_autherror; } else { - title = getString(R.string.gpodnetsync_error_title); - description = getString(R.string.gpodnetsync_error_descr) + exception.getMessage(); - id = R.id.notification_gpodnet_sync_error; + if (UserPreferences.gpodnetNotificationsEnabled()) { + title = getString(R.string.gpodnetsync_error_title); + description = getString(R.string.gpodnetsync_error_descr) + exception.getMessage(); + id = R.id.notification_gpodnet_sync_error; + } else { + return; + } } PendingIntent activityIntent = ClientConfig.gpodnetCallbacks.getGpodnetSyncServiceErrorNotificationPendingIntent(this); - Notification notification = builder.setContentTitle(title) + Notification notification = new NotificationCompat.Builder(this) + .setContentTitle(title) .setContentText(description) .setContentIntent(activityIntent) .setSmallIcon(R.drawable.stat_notify_sync_error) .setAutoCancel(true) - .setVisibility(Notification.VISIBILITY_PUBLIC) + .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) .build(); NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); nm.notify(id, notification); 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 e255a07ef..300f57be6 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 @@ -5,12 +5,6 @@ import android.support.annotation.NonNull; import android.text.TextUtils; import android.util.Log; -import com.squareup.okhttp.Credentials; -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.Request; -import com.squareup.okhttp.Response; -import com.squareup.okhttp.internal.http.StatusLine; - import java.io.IOException; import java.net.CookieManager; import java.net.CookiePolicy; @@ -20,16 +14,27 @@ import java.net.InetSocketAddress; import java.net.Proxy; import java.net.Socket; import java.net.SocketAddress; -import java.net.URL; import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.util.Arrays; 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 de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.storage.DBWriter; +import okhttp3.Credentials; +import okhttp3.HttpUrl; +import okhttp3.JavaNetCookieJar; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.internal.http.StatusLine; /** * Provides access to a HttpClient singleton. @@ -53,13 +58,13 @@ public class AntennapodHttpClient { */ public static synchronized OkHttpClient getHttpClient() { if (httpClient == null) { - httpClient = newHttpClient(); + httpClient = newBuilder().build(); } return httpClient; } public static synchronized void reinit() { - httpClient = newHttpClient(); + httpClient = newBuilder().build(); } /** @@ -70,33 +75,33 @@ public class AntennapodHttpClient { * @return http client */ @NonNull - public static OkHttpClient newHttpClient() { + public static OkHttpClient.Builder newBuilder() { Log.d(TAG, "Creating new instance of HTTP client"); System.setProperty("http.maxConnections", String.valueOf(MAX_CONNECTIONS)); - OkHttpClient client = new OkHttpClient(); + OkHttpClient.Builder builder = new OkHttpClient.Builder(); // detect 301 Moved permanently and 308 Permanent Redirect - client.networkInterceptors().add(chain -> { + builder.networkInterceptors().add(chain -> { Request request = chain.request(); Response response = chain.proceed(request); if (response.code() == HttpURLConnection.HTTP_MOVED_PERM || response.code() == StatusLine.HTTP_PERM_REDIRECT) { String location = response.header("Location"); if (location.startsWith("/")) { // URL is not absolute, but relative - URL url = request.url(); - location = url.getProtocol() + "://" + url.getHost() + location; + HttpUrl url = request.url(); + location = url.scheme() + "://" + url.host() + location; } else if (!location.toLowerCase().startsWith("http://") && !location.toLowerCase().startsWith("https://")) { // Reference is relative to current path - URL url = request.url(); - String path = url.getPath(); + HttpUrl url = request.url(); + String path = url.encodedPath(); String newPath = path.substring(0, path.lastIndexOf("/") + 1) + location; - location = url.getProtocol() + "://" + url.getHost() + newPath; + location = url.scheme() + "://" + url.host() + newPath; } try { - DBWriter.updateFeedDownloadURL(request.urlString(), location).get(); + DBWriter.updateFeedDownloadURL(request.url().toString(), location).get(); } catch (Exception e) { Log.e(TAG, Log.getStackTraceString(e)); } @@ -107,26 +112,26 @@ public class AntennapodHttpClient { // set cookie handler CookieManager cm = new CookieManager(); cm.setCookiePolicy(CookiePolicy.ACCEPT_ORIGINAL_SERVER); - client.setCookieHandler(cm); + builder.cookieJar(new JavaNetCookieJar(cm)); // set timeouts - client.setConnectTimeout(CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS); - client.setReadTimeout(READ_TIMEOUT, TimeUnit.MILLISECONDS); - client.setWriteTimeout(READ_TIMEOUT, TimeUnit.MILLISECONDS); + builder.connectTimeout(CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS); + builder.readTimeout(READ_TIMEOUT, TimeUnit.MILLISECONDS); + builder.writeTimeout(READ_TIMEOUT, TimeUnit.MILLISECONDS); // configure redirects - client.setFollowRedirects(true); - client.setFollowSslRedirects(true); + builder.followRedirects(true); + builder.followSslRedirects(true); ProxyConfig config = UserPreferences.getProxyConfig(); if (config.type != Proxy.Type.DIRECT) { int port = config.port > 0 ? config.port : ProxyConfig.DEFAULT_PORT; SocketAddress address = InetSocketAddress.createUnresolved(config.host, port); Proxy proxy = new Proxy(config.type, address); - client.setProxy(proxy); + builder.proxy(proxy); if (!TextUtils.isEmpty(config.username)) { String credentials = Credentials.basic(config.username, config.password); - client.interceptors().add(chain -> { + builder.interceptors().add(chain -> { Request request = chain.request().newBuilder() .header("Proxy-Authorization", credentials).build(); return chain.proceed(request); @@ -134,9 +139,9 @@ public class AntennapodHttpClient { } } if(16 <= Build.VERSION.SDK_INT && Build.VERSION.SDK_INT < 21) { - client.setSslSocketFactory(new CustomSslSocketFactory()); + builder.sslSocketFactory(new CustomSslSocketFactory(), trustManager()); } - return client; + return builder; } /** @@ -149,6 +154,23 @@ public class AntennapodHttpClient { } } + 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; + } + } + private static class CustomSslSocketFactory extends SSLSocketFactory { private SSLSocketFactory factory; diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index 00b0e6db3..64f6ec774 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -1,6 +1,5 @@ package de.danoeh.antennapod.core.service.download; -import android.annotation.SuppressLint; import android.app.Notification; import android.app.NotificationManager; import android.app.Service; @@ -15,13 +14,15 @@ import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.support.annotation.NonNull; +import android.support.annotation.VisibleForTesting; import android.support.v4.app.NotificationCompat; -import android.support.v4.util.Pair; import android.text.TextUtils; import android.util.Log; +import android.util.Pair; import android.webkit.URLUtil; import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.StringUtils; import org.xml.sax.SAXException; import java.io.File; @@ -30,8 +31,10 @@ import java.net.HttpURLConnection; import java.util.ArrayList; import java.util.Collections; import java.util.Date; +import java.util.HashSet; import java.util.LinkedList; import java.util.List; +import java.util.Set; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Callable; import java.util.concurrent.CompletionService; @@ -76,7 +79,7 @@ import de.danoeh.antennapod.core.util.InvalidFeedException; import de.greenrobot.event.EventBus; /** - * Manages the download of feedfiles in the app. Downloads can be enqueued viathe startService intent. + * Manages the download of feedfiles in the app. Downloads can be enqueued via the startService intent. * The argument of the intent is an instance of DownloadRequest in the EXTRA_REQUEST field of * the intent. * After the downloads have finished, the downloaded object will be passed on to a specific handler, depending on the @@ -145,7 +148,7 @@ public class DownloadService extends Service { private Handler handler; private NotificationUpdater notificationUpdater; - private ScheduledFuture notificationUpdaterFuture; + private ScheduledFuture<?> notificationUpdaterFuture; private static final int SCHED_EX_POOL_SIZE = 1; private ScheduledThreadPoolExecutor schedExecutor; @@ -196,19 +199,20 @@ public class DownloadService extends Service { saveDownloadStatus(status); handleFailedDownload(status, downloader.getDownloadRequest()); - if(type == FeedMedia.FEEDFILETYPE_FEEDMEDIA) { + if (type == FeedMedia.FEEDFILETYPE_FEEDMEDIA) { long id = status.getFeedfileId(); FeedMedia media = DBReader.getFeedMedia(id); - if(media == null || media.getItem() == null) { + FeedItem item; + if (media == null || (item = media.getItem()) == null) { return; } - FeedItem item = media.getItem(); boolean httpNotFound = status.getReason() == DownloadError.ERROR_HTTP_DATA_ERROR && String.valueOf(HttpURLConnection.HTTP_NOT_FOUND).equals(status.getReasonDetailed()); boolean forbidden = status.getReason() == DownloadError.ERROR_FORBIDDEN && String.valueOf(HttpURLConnection.HTTP_FORBIDDEN).equals(status.getReasonDetailed()); boolean notEnoughSpace = status.getReason() == DownloadError.ERROR_NOT_ENOUGH_SPACE; - if (httpNotFound || forbidden || notEnoughSpace) { + boolean wrongFileType = status.getReason() == DownloadError.ERROR_FILE_TYPE; + if (httpNotFound || forbidden || notEnoughSpace || wrongFileType) { DBWriter.saveFeedItemAutoDownloadFailed(item).get(); } // to make lists reload the failed item, we fake an item update @@ -218,17 +222,21 @@ public class DownloadService extends Service { } else { // if FeedMedia download has been canceled, fake FeedItem update // so that lists reload that it - if(status.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) { + if (status.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) { FeedMedia media = DBReader.getFeedMedia(status.getFeedfileId()); - EventBus.getDefault().post(FeedItemEvent.updated(media.getItem())); + FeedItem item; + if (media == null || (item = media.getItem()) == null) { + return; + } + EventBus.getDefault().post(FeedItemEvent.updated(item)); } } queryDownloadsAsync(); } } catch (InterruptedException e) { - Log.d(TAG, "DownloadCompletionThread was interrupted"); + Log.e(TAG, "DownloadCompletionThread was interrupted"); } catch (ExecutionException e) { - e.printStackTrace(); + Log.e(TAG, "ExecutionException in DownloadCompletionThread: " + e.getMessage()); numberOfDownloads.decrementAndGet(); } } @@ -246,7 +254,6 @@ public class DownloadService extends Service { return Service.START_NOT_STICKY; } - @SuppressLint("NewApi") @Override public void onCreate() { Log.d(TAG, "Service started"); @@ -321,7 +328,7 @@ public class DownloadService extends Service { // if this was the initial gpodder sync, i.e. we just synced the feeds successfully, // it is now time to sync the episode actions - if(GpodnetPreferences.loggedIn() && + if (GpodnetPreferences.loggedIn() && GpodnetPreferences.getLastSubscriptionSyncTimestamp() > 0 && GpodnetPreferences.getLastEpisodeActionsSyncTimestamp() == 0) { GpodnetSyncService.sendSyncActionsIntent(this); @@ -332,16 +339,14 @@ public class DownloadService extends Service { } private void setupNotificationBuilders() { - Bitmap icon = BitmapFactory.decodeResource(getResources(), - R.drawable.stat_notify_sync); - - notificationCompatBuilder = new NotificationCompat.Builder(this) - .setOngoing(true) - .setContentIntent(ClientConfig.downloadServiceCallbacks.getNotificationContentIntent(this)) - .setLargeIcon(icon) - .setSmallIcon(R.drawable.stat_notify_sync) - .setVisibility(Notification.VISIBILITY_PUBLIC); + Bitmap icon = BitmapFactory.decodeResource(getResources(), R.drawable.stat_notify_sync); + notificationCompatBuilder = new NotificationCompat.Builder(this) + .setOngoing(true) + .setContentIntent(ClientConfig.downloadServiceCallbacks.getNotificationContentIntent(this)) + .setLargeIcon(icon) + .setSmallIcon(R.drawable.stat_notify_sync) + .setVisibility(Notification.VISIBILITY_PUBLIC); Log.d(TAG, "Notification set up"); } @@ -351,49 +356,21 @@ public class DownloadService extends Service { * before setupNotificationBuilders. */ private Notification updateNotifications() { - String contentTitle = getString(R.string.download_notification_title); - int numDownloads = requester.getNumberOfDownloads(); - String downloadsLeft; - if (numDownloads > 0) { - downloadsLeft = getResources() - .getQuantityString(R.plurals.downloads_left, numDownloads, numDownloads); - } else { - downloadsLeft = getString(R.string.downloads_processing); + if (notificationCompatBuilder == null) { + return null; } - if (notificationCompatBuilder != null) { - - StringBuilder bigText = new StringBuilder(""); - for (int i = 0; i < downloads.size(); i++) { - Downloader downloader = downloads.get(i); - final DownloadRequest request = downloader - .getDownloadRequest(); - if (request.getFeedfileType() == Feed.FEEDFILETYPE_FEED) { - if (request.getTitle() != null) { - if (i > 0) { - bigText.append("\n"); - } - bigText.append("\u2022 ").append(request.getTitle()); - } - } else if (request.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) { - if (request.getTitle() != null) { - if (i > 0) { - bigText.append("\n"); - } - bigText.append("\u2022 ").append(request.getTitle()) - .append(" (").append(request.getProgressPercent()) - .append("%)"); - } - } - } - notificationCompatBuilder.setContentTitle(contentTitle); - notificationCompatBuilder.setContentText(downloadsLeft); - if (bigText != null) { - notificationCompatBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(bigText.toString())); - } - return notificationCompatBuilder.build(); - } - return null; + String contentTitle = getString(R.string.download_notification_title); + int numDownloads = requester.getNumberOfDownloads(); + String downloadsLeft = (numDownloads > 0) ? + getResources().getQuantityString(R.plurals.downloads_left, numDownloads, numDownloads) : + getString(R.string.downloads_processing); + String bigText = compileNotificationString(downloads); + + notificationCompatBuilder.setContentTitle(contentTitle); + notificationCompatBuilder.setContentText(downloadsLeft); + notificationCompatBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(bigText)); + return notificationCompatBuilder.build(); } private Downloader getDownloader(String downloadUrl) { @@ -411,7 +388,7 @@ public class DownloadService extends Service { public void onReceive(Context context, Intent intent) { if (TextUtils.equals(intent.getAction(), ACTION_CANCEL_DOWNLOAD)) { String url = intent.getStringExtra(EXTRA_DOWNLOAD_URL); - if(url == null) { + if (url == null) { throw new IllegalArgumentException("ACTION_CANCEL_DOWNLOAD intent needs download url extra"); } @@ -448,7 +425,7 @@ public class DownloadService extends Service { if (downloader != null) { numberOfDownloads.incrementAndGet(); // smaller rss feeds before bigger media files - if(request.getFeedfileType() == Feed.FEEDFILETYPE_FEED) { + if (request.getFeedfileType() == Feed.FEEDFILETYPE_FEED) { downloads.add(0, downloader); } else { downloads.add(downloader); @@ -462,15 +439,11 @@ public class DownloadService extends Service { } private Downloader getDownloader(DownloadRequest request) { - if (URLUtil.isHttpUrl(request.getSource()) - || URLUtil.isHttpsUrl(request.getSource())) { - return new HttpDownloader(request); + if (!URLUtil.isHttpUrl(request.getSource()) && !URLUtil.isHttpsUrl(request.getSource())) { + Log.e(TAG, "Could not find appropriate downloader for " + request.getSource()); + return null; } - Log.e(TAG, - "Could not find appropriate downloader for " - + request.getSource() - ); - return null; + return new HttpDownloader(request); } /** @@ -479,8 +452,7 @@ public class DownloadService extends Service { */ private void removeDownload(final Downloader d) { handler.post(() -> { - Log.d(TAG, "Removing downloader: " - + d.getDownloadRequest().getSource()); + Log.d(TAG, "Removing downloader: " + d.getDownloadRequest().getSource()); boolean rc = downloads.remove(d); Log.d(TAG, "Result of downloads.remove: " + rc); DownloadRequester.getInstance().removeDownload(d.getDownloadRequest()); @@ -527,10 +499,8 @@ public class DownloadService extends Service { Log.d(TAG, "Creating report"); // create notification object Notification notification = new NotificationCompat.Builder(this) - .setTicker( - getString(R.string.download_report_title)) - .setContentTitle( - getString(R.string.download_report_content_title)) + .setTicker(getString(R.string.download_report_title)) + .setContentTitle(getString(R.string.download_report_content_title)) .setContentText( String.format( getString(R.string.download_report_content), @@ -580,8 +550,8 @@ public class DownloadService extends Service { private void postAuthenticationNotification(final DownloadRequest downloadRequest) { handler.post(() -> { - final String resourceTitle = (downloadRequest.getTitle() != null) - ? downloadRequest.getTitle() : downloadRequest.getSource(); + final String resourceTitle = (downloadRequest.getTitle() != null) ? + downloadRequest.getTitle() : downloadRequest.getSource(); NotificationCompat.Builder builder = new NotificationCompat.Builder(DownloadService.this); builder.setTicker(getText(R.string.authentication_notification_title)) @@ -606,7 +576,6 @@ public class DownloadService extends Service { private void handleCompletedFeedDownload(DownloadRequest request) { Log.d(TAG, "Handling completed Feed Download"); feedSyncThread.submitCompletedDownload(request); - } /** @@ -655,6 +624,7 @@ public class DownloadService extends Service { parserService.submit(new FeedParserTask(request)); tasks++; } catch (InterruptedException e) { + Log.e(TAG, "FeedSyncThread was interrupted"); return null; } @@ -690,9 +660,10 @@ public class DownloadService extends Service { if (result != null) { results.add(result); } - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - + } catch (InterruptedException e) { + Log.e(TAG, "FeedSyncThread was interrupted"); + } catch (ExecutionException e) { + Log.e(TAG, "ExecutionException in FeedSyncThread: " + e.getMessage()); } } @@ -701,7 +672,7 @@ public class DownloadService extends Service { private int pollCompletedDownloads() { int tasks = 0; - for (int i = 0; i < completedRequests.size(); i++) { + while (!completedRequests.isEmpty()) { parserService.submit(new FeedParserTask(completedRequests.poll())); tasks++; } @@ -727,8 +698,10 @@ public class DownloadService extends Service { if (dbUpdateFuture != null) { try { dbUpdateFuture.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); + } catch (InterruptedException e) { + Log.e(TAG, "FeedSyncThread was interrupted"); + } catch (ExecutionException e) { + Log.e(TAG, "ExecutionException in FeedSyncThread: " + e.getMessage()); } } @@ -765,14 +738,13 @@ public class DownloadService extends Service { try { dbUpdateFuture.get(); } catch (InterruptedException e) { + Log.e(TAG, "interrupted while updating the db"); } catch (ExecutionException e) { - e.printStackTrace(); + Log.e(TAG, "ExecutionException while updating the db: " + e.getMessage()); } } - Log.d(TAG, "Shutting down"); - } /** @@ -837,25 +809,28 @@ public class DownloadService extends Service { successful = false; reason = DownloadError.ERROR_PARSER_EXCEPTION; reasonDetailed = e.getMessage(); + } finally { + File feedFile = new File(request.getDestination()); + if (feedFile.exists()) { + boolean deleted = feedFile.delete(); + Log.d(TAG, "Deletion of file '" + feedFile.getAbsolutePath() + "' " + (deleted ? "successful" : "FAILED")); + } } - // cleanup(); - - if (successful) { // we create a 'successful' download log if the feed's last refresh failed List<DownloadStatus> log = DBReader.getFeedDownloadLog(feed); - if(log.size() > 0 && !log.get(0).isSuccessful()) { - saveDownloadStatus(new DownloadStatus(feed, - feed.getHumanReadableIdentifier(), DownloadError.SUCCESS, successful, - reasonDetailed)); + if (log.size() > 0 && !log.get(0).isSuccessful()) { + saveDownloadStatus( + new DownloadStatus(feed, feed.getHumanReadableIdentifier(), + DownloadError.SUCCESS, successful, reasonDetailed)); } return Pair.create(request, result); } else { numberOfDownloads.decrementAndGet(); - saveDownloadStatus(new DownloadStatus(feed, - feed.getHumanReadableIdentifier(), reason, successful, - reasonDetailed)); + saveDownloadStatus( + new DownloadStatus(feed, feed.getHumanReadableIdentifier(), reason, + successful, reasonDetailed)); return null; } } @@ -876,26 +851,6 @@ public class DownloadService extends Service { return true; } - /** - * Checks if the FeedItems of this feed have images that point - * to the same URL. If two FeedItems have an image that points to - * the same URL, the reference of the second item is removed, so that every image - * reference is unique. - */ - private void removeDuplicateImages(Feed feed) { - for (int x = 0; x < feed.getItems().size(); x++) { - for (int y = x + 1; y < feed.getItems().size(); y++) { - FeedItem item1 = feed.getItems().get(x); - FeedItem item2 = feed.getItems().get(y); - if (item1.hasItemImage() && item2.hasItemImage()) { - if (TextUtils.equals(item1.getImage().getDownload_url(), item2.getImage().getDownload_url())) { - item2.setImage(null); - } - } - } - } - } - private boolean hasValidFeedItems(Feed feed) { for (FeedItem item : feed.getItems()) { if (item.getTitle() == null) { @@ -903,8 +858,7 @@ public class DownloadService extends Service { return false; } if (item.getPubDate() == null) { - Log.e(TAG, - "Item has no pubDate. Using current time as pubDate"); + Log.e(TAG, "Item has no pubDate. Using current time as pubDate"); if (item.getTitle() != null) { Log.e(TAG, "Title of invalid item: " + item.getTitle()); } @@ -966,11 +920,11 @@ public class DownloadService extends Service { @Override public void run() { - if(request.getFeedfileType() == Feed.FEEDFILETYPE_FEED) { + if (request.getFeedfileType() == Feed.FEEDFILETYPE_FEED) { DBWriter.setFeedLastUpdateFailed(request.getFeedfileId(), true); } else if (request.isDeleteOnFailure()) { Log.d(TAG, "Ignoring failed download, deleteOnFailure=true"); - } else { + } else { File dest = new File(request.getDestination()); if (dest.exists() && request.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) { Log.d(TAG, "File has been partially downloaded. Writing file url"); @@ -978,8 +932,10 @@ public class DownloadService extends Service { media.setFile_url(request.getDestination()); try { DBWriter.setFeedMedia(media).get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); + } catch (InterruptedException e) { + Log.e(TAG, "FailedDownloadHandler was interrupted"); + } catch (ExecutionException e) { + Log.e(TAG, "ExecutionException in FailedDownloadHandler: " + e.getMessage()); } } } @@ -1009,56 +965,57 @@ public class DownloadService extends Service { } media.setDownloaded(true); media.setFile_url(request.getDestination()); - media.setHasEmbeddedPicture(null); + media.checkEmbeddedPicture(); // enforce check // check if file has chapters ChapterUtils.loadChaptersFromFileUrl(media); // Get duration - MediaMetadataRetriever mmr = null; + MediaMetadataRetriever mmr = new MediaMetadataRetriever(); + String durationStr = null; try { - mmr = new MediaMetadataRetriever(); mmr.setDataSource(media.getFile_url()); - String durationStr = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION); + durationStr = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION); media.setDuration(Integer.parseInt(durationStr)); Log.d(TAG, "Duration of file is " + media.getDuration()); } catch (NumberFormatException e) { - e.printStackTrace(); - } catch (RuntimeException e) { - e.printStackTrace(); + Log.d(TAG, "Invalid file duration: " + durationStr); + } catch(Exception e) { + Log.e(TAG, "Get duration failed", e); } finally { - if (mmr != null) { - mmr.release(); - } + mmr.release(); } final FeedItem item = media.getItem(); try { // we've received the media, we don't want to autodownload it again - if(item != null) { + if (item != null) { item.setAutoDownload(false); DBWriter.setFeedItem(item).get(); } DBWriter.setFeedMedia(media).get(); - if (item != null && !DBTasks.isInQueue(DownloadService.this, item.getId())) { + if (item != null && UserPreferences.enqueueDownloadedEpisodes() && + !DBTasks.isInQueue(DownloadService.this, item.getId())) { DBWriter.addQueueItem(DownloadService.this, item).get(); } - } catch (ExecutionException | InterruptedException e) { - e.printStackTrace(); + } catch (InterruptedException e) { + Log.e(TAG, "MediaHandlerThread was interrupted"); + } catch (ExecutionException e) { + Log.e(TAG, "ExecutionException in MediaHandlerThread: " + e.getMessage()); status = new DownloadStatus(media, media.getEpisodeTitle(), DownloadError.ERROR_DB_ACCESS_ERROR, false, e.getMessage()); } saveDownloadStatus(status); - if(GpodnetPreferences.loggedIn() && item != null) { - GpodnetEpisodeAction action = new GpodnetEpisodeAction.Builder(item, Action.DOWNLOAD) - .currentDeviceId() - .currentTimestamp() - .build(); - GpodnetPreferences.enqueueEpisodeAction(action); + if (GpodnetPreferences.loggedIn() && item != null) { + GpodnetEpisodeAction action = new GpodnetEpisodeAction.Builder(item, Action.DOWNLOAD) + .currentDeviceId() + .currentTimestamp() + .build(); + GpodnetPreferences.enqueueEpisodeAction(action); } numberOfDownloads.decrementAndGet(); @@ -1098,6 +1055,7 @@ public class DownloadService extends Service { } }); } + } @@ -1114,11 +1072,57 @@ public class DownloadService extends Service { private void postDownloaders() { long now = System.currentTimeMillis(); - if(now - lastPost >= 250) { + if (now - lastPost >= 250) { postHandler.removeCallbacks(postDownloaderTask); postDownloaderTask.run(); lastPost = now; } } + /** + * Checks if the FeedItems of this feed have images that point to the same URL. If two FeedItems + * have an image that points to the same URL, the reference of the second item is removed, so + * that every image reference is unique. + */ + @VisibleForTesting + public static void removeDuplicateImages(Feed feed) { + Set<String> known = new HashSet<String>(); + for (FeedItem item : feed.getItems()) { + String url = item.hasItemImage() ? item.getImage().getDownload_url() : null; + if (url != null) { + if (known.contains(url)) { + item.setImage(null); + } else { + known.add(url); + } + } + } + } + + private static String compileNotificationString(List<Downloader> downloads) { + List<String> lines = new ArrayList<>(downloads.size()); + for (Downloader downloader : downloads) { + StringBuilder line = new StringBuilder("\u2022 "); + DownloadRequest request = downloader.getDownloadRequest(); + switch (request.getFeedfileType()) { + case Feed.FEEDFILETYPE_FEED: + if (request.getTitle() != null) { + line.append(request.getTitle()); + } + break; + case FeedMedia.FEEDFILETYPE_FEEDMEDIA: + if (request.getTitle() != null) { + line.append(request.getTitle()) + .append(" (") + .append(request.getProgressPercent()) + .append("%)"); + } + break; + default: + line.append("Unknown: ").append(request.getFeedfileType()); + } + lines.add(line.toString()); + } + return StringUtils.join(lines, '\n'); + } } 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 94a722da9..b409a419a 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 @@ -3,12 +3,6 @@ package de.danoeh.antennapod.core.service.download; import android.text.TextUtils; import android.util.Log; -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.Protocol; -import com.squareup.okhttp.Request; -import com.squareup.okhttp.Response; -import com.squareup.okhttp.ResponseBody; - import org.apache.commons.io.IOUtils; import java.io.BufferedInputStream; @@ -32,6 +26,12 @@ import de.danoeh.antennapod.core.util.DateUtils; import de.danoeh.antennapod.core.util.DownloadError; import de.danoeh.antennapod.core.util.StorageUtils; import de.danoeh.antennapod.core.util.URIUtil; +import okhttp3.Interceptor; +import okhttp3.OkHttpClient; +import okhttp3.Protocol; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.ResponseBody; import okio.ByteString; public class HttpDownloader extends Downloader { @@ -59,7 +59,9 @@ public class HttpDownloader extends Downloader { } } - OkHttpClient httpClient = AntennapodHttpClient.getHttpClient(); + OkHttpClient.Builder httpClientBuilder = AntennapodHttpClient.newBuilder(); + httpClientBuilder.interceptors().add(new BasicAuthorizationInterceptor(request)); + OkHttpClient httpClient = httpClientBuilder.build(); RandomAccessFile out = null; InputStream connection; ResponseBody responseBody = null; @@ -68,16 +70,16 @@ public class HttpDownloader extends Downloader { final URI uri = URIUtil.getURIFromRequestUrl(request.getSource()); Request.Builder httpReq = new Request.Builder().url(uri.toURL()) .header("User-Agent", ClientConfig.USER_AGENT); - if(request.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) { + if (request.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) { // set header explicitly so that okhttp doesn't do transparent gzip Log.d(TAG, "addHeader(\"Accept-Encoding\", \"identity\")"); httpReq.addHeader("Accept-Encoding", "identity"); } - if(!TextUtils.isEmpty(request.getLastModified())) { + if (!TextUtils.isEmpty(request.getLastModified())) { String lastModified = request.getLastModified(); Date lastModifiedDate = DateUtils.parse(lastModified); - if(lastModifiedDate != null) { + if (lastModifiedDate != null) { long threeDaysAgo = System.currentTimeMillis() - 1000 * 60 * 60 * 24 * 3; if (lastModifiedDate.getTime() > threeDaysAgo) { Log.d(TAG, "addHeader(\"If-Modified-Since\", \"" + lastModified + "\")"); @@ -89,19 +91,6 @@ public class HttpDownloader extends Downloader { } } - // add authentication information - String userInfo = uri.getUserInfo(); - if (userInfo != null) { - String[] parts = userInfo.split(":"); - if (parts.length == 2) { - String credentials = encodeCredentials(parts[0], parts[1], "ISO-8859-1"); - httpReq.header("Authorization", credentials); - } - } else if (!TextUtils.isEmpty(request.getUsername()) && request.getPassword() != null) { - String credentials = encodeCredentials(request.getUsername(), request.getPassword(), - "ISO-8859-1"); - httpReq.header("Authorization", credentials); - } // add range header if necessary if (fileExists) { @@ -111,15 +100,17 @@ public class HttpDownloader extends Downloader { } Response response; + try { response = httpClient.newCall(httpReq.build()).execute(); - } catch(IOException e) { + } catch (IOException e) { Log.e(TAG, e.toString()); - if(e.getMessage().contains("PROTOCOL_ERROR")) { - httpClient.setProtocols(Collections.singletonList(Protocol.HTTP_1_1)); + if (e.getMessage().contains("PROTOCOL_ERROR")) { + httpClient = httpClient.newBuilder() + .protocols(Collections.singletonList(Protocol.HTTP_1_1)) + .build(); response = httpClient.newCall(httpReq.build()).execute(); - } - else { + } else { throw e; } } @@ -127,34 +118,13 @@ public class HttpDownloader extends Downloader { responseBody = response.body(); String contentEncodingHeader = response.header("Content-Encoding"); boolean isGzip = false; - if(!TextUtils.isEmpty(contentEncodingHeader)) { + if (!TextUtils.isEmpty(contentEncodingHeader)) { isGzip = TextUtils.equals(contentEncodingHeader.toLowerCase(), "gzip"); } Log.d(TAG, "Response code is " + response.code()); - if(!response.isSuccessful() && response.code() == HttpURLConnection.HTTP_UNAUTHORIZED) { - Log.d(TAG, "Authorization failed, re-trying with UTF-8 encoding"); - if (userInfo != null) { - String[] parts = userInfo.split(":"); - if (parts.length == 2) { - String credentials = encodeCredentials(parts[0], parts[1], "UTF-8"); - httpReq.header("Authorization", credentials); - } - } else if (!TextUtils.isEmpty(request.getUsername()) && request.getPassword() != null) { - String credentials = encodeCredentials(request.getUsername(), request.getPassword(), - "UTF-8"); - httpReq.header("Authorization", credentials); - } - response = httpClient.newCall(httpReq.build()).execute(); - responseBody = response.body(); - contentEncodingHeader = response.header("Content-Encoding"); - if(!TextUtils.isEmpty(contentEncodingHeader)) { - isGzip = TextUtils.equals(contentEncodingHeader.toLowerCase(), "gzip"); - } - } - - if(!response.isSuccessful() && response.code() == HttpURLConnection.HTTP_NOT_MODIFIED) { + if (!response.isSuccessful() && response.code() == HttpURLConnection.HTTP_NOT_MODIFIED) { Log.d(TAG, "Feed '" + request.getSource() + "' not modified since last update, Download canceled"); onCancelled(); return; @@ -166,7 +136,7 @@ public class HttpDownloader extends Downloader { if (response.code() == HttpURLConnection.HTTP_UNAUTHORIZED) { error = DownloadError.ERROR_UNAUTHORIZED; details = String.valueOf(response.code()); - } else if(response.code() == HttpURLConnection.HTTP_FORBIDDEN) { + } else if (response.code() == HttpURLConnection.HTTP_FORBIDDEN) { error = DownloadError.ERROR_FORBIDDEN; details = String.valueOf(response.code()); } else { @@ -182,10 +152,22 @@ public class HttpDownloader extends Downloader { return; } - if(request.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) { + // fail with a file type error when the content type is text and + // the reported content length is less than 100kb (or no length is given) + if (request.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) { + int contentLength = -1; + String contentLen = response.header("Content-Length"); + if (contentLen != null) { + try { + contentLength = Integer.parseInt(contentLen); + } catch (NumberFormatException e) { + } + } + Log.d(TAG, "content length: " + contentLength); String contentType = response.header("Content-Type"); Log.d(TAG, "content type: " + contentType); - if(contentType.startsWith("text/")) { + if (contentType != null && contentType.startsWith("text/") && + contentLength < 100 * 1024) { onFail(DownloadError.ERROR_FILE_TYPE, null); return; } @@ -233,10 +215,10 @@ public class HttpDownloader extends Downloader { while (!cancelled && (count = connection.read(buffer)) != -1) { out.write(buffer, 0, count); request.setSoFar(request.getSoFar() + count); - int progressPercent = (int)(100.0 * request.getSoFar() / request.getSize()); + int progressPercent = (int) (100.0 * request.getSoFar() / request.getSize()); request.setProgressPercent(progressPercent); } - } catch(IOException e) { + } catch (IOException e) { Log.e(TAG, Log.getStackTraceString(e)); } if (cancelled) { @@ -249,12 +231,12 @@ public class HttpDownloader extends Downloader { onFail(DownloadError.ERROR_IO_ERROR, "Download completed but size: " + request.getSoFar() + " does not equal expected size " + request.getSize()); return; - } else if(request.getSize() > 0 && request.getSoFar() == 0){ + } else if (request.getSize() > 0 && request.getSoFar() == 0) { onFail(DownloadError.ERROR_IO_ERROR, "Download completed, but nothing was read"); return; } String lastModified = response.header("Last-Modified"); - if(lastModified != null) { + if (lastModified != null) { request.setLastModified(lastModified); } else { request.setLastModified(response.header("ETag")); @@ -314,7 +296,7 @@ public class HttpDownloader extends Downloader { if (dest.exists()) { boolean rc = dest.delete(); Log.d(TAG, "Deleted file " + dest.getName() + "; Result: " - + rc); + + rc); } else { Log.d(TAG, "cleanup() didn't delete file: does not exist."); } @@ -332,4 +314,62 @@ public class HttpDownloader extends Downloader { } } + private class BasicAuthorizationInterceptor implements Interceptor { + + private DownloadRequest downloadRequest; + + public BasicAuthorizationInterceptor(DownloadRequest downloadRequest) { + this.downloadRequest = downloadRequest; + } + + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + String userInfo = URIUtil.getURIFromRequestUrl(downloadRequest.getSource()).getUserInfo(); + + Response response = chain.proceed(request); + + if (response.code() != HttpURLConnection.HTTP_UNAUTHORIZED) { + return response; + } + + Request.Builder newRequest = request.newBuilder(); + + Log.d(TAG, "Authorization failed, re-trying with ISO-8859-1 encoded credentials"); + if (userInfo != null) { + String[] parts = userInfo.split(":"); + if (parts.length == 2) { + String credentials = encodeCredentials(parts[0], parts[1], "ISO-8859-1"); + newRequest.header("Authorization", credentials); + } + } else if (!TextUtils.isEmpty(downloadRequest.getUsername()) && downloadRequest.getPassword() != null) { + String credentials = encodeCredentials(downloadRequest.getUsername(), downloadRequest.getPassword(), + "ISO-8859-1"); + newRequest.header("Authorization", credentials); + } + + response = chain.proceed(newRequest.build()); + + if (response.code() != HttpURLConnection.HTTP_UNAUTHORIZED) { + return response; + } + + Log.d(TAG, "Authorization failed, re-trying with UTF-8 encoded credentials"); + if (userInfo != null) { + String[] parts = userInfo.split(":"); + if (parts.length == 2) { + String credentials = encodeCredentials(parts[0], parts[1], "UTF-8"); + newRequest.header("Authorization", credentials); + } + } else if (!TextUtils.isEmpty(downloadRequest.getUsername()) && downloadRequest.getPassword() != null) { + String credentials = encodeCredentials(downloadRequest.getUsername(), downloadRequest.getPassword(), + "UTF-8"); + newRequest.header("Authorization", credentials); + } + + return chain.proceed(newRequest.build()); + } + + } + } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/ProxyConfig.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/ProxyConfig.java index 6eb1f4118..619b58471 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/ProxyConfig.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/ProxyConfig.java @@ -12,7 +12,7 @@ public class ProxyConfig { @Nullable public final String username; @Nullable public final String password; - public final static int DEFAULT_PORT = 8080; + public static final int DEFAULT_PORT = 8080; public static ProxyConfig direct() { return new ProxyConfig(Proxy.Type.DIRECT, null, 0, null, null); diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java index 8bacac1ef..11cd21db5 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java @@ -13,6 +13,7 @@ import org.antennapod.audio.MediaPlayer; import java.io.IOException; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -140,10 +141,13 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { } // set temporarily to pause in order to update list with current position if (playerStatus == PlayerStatus.PLAYING) { - setPlayerStatus(PlayerStatus.PAUSED, media); + callback.onPlaybackPause(media, getPosition()); } - smartMarkAsPlayed(media); + if (!media.getIdentifier().equals(playable.getIdentifier())) { + final Playable oldMedia = media; + executor.submit(() -> callback.onPostPlayback(oldMedia, false, false, true)); + } setPlayerStatus(PlayerStatus.INDETERMINATE, null); } @@ -199,6 +203,8 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { audioFocusChangeListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); if (focusGained == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { + Log.d(TAG, "Audiofocus successfully requested"); + Log.d(TAG, "Resuming/Starting playback"); acquireWifiLockIfNecessary(); float speed = 1.0f; try { @@ -220,8 +226,6 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { setPlayerStatus(PlayerStatus.PLAYING, media); pausedBecauseOfTransientAudiofocusLoss = false; - media.onPlaybackStart(); - } else { Log.e(TAG, "Failed to request audio focus"); } @@ -249,7 +253,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { if (playerStatus == PlayerStatus.PLAYING) { Log.d(TAG, "Pausing playback."); mediaPlayer.pause(); - setPlayerStatus(PlayerStatus.PAUSED, media); + setPlayerStatus(PlayerStatus.PAUSED, media, getPosition()); if (abandonFocus) { audioManager.abandonAudioFocus(audioFocusChangeListener); @@ -296,7 +300,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { /** * Called after media player has been prepared. This method is executed on the caller's thread. */ - void onPrepared(final boolean startWhenPrepared) { + private void onPrepared(final boolean startWhenPrepared) { playerLock.lock(); if (playerStatus != PlayerStatus.PREPARING) { @@ -311,11 +315,12 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { videoSize = new Pair<>(vp.getVideoWidth(), vp.getVideoHeight()); } + // TODO this call has no effect! if (media.getPosition() > 0) { seekToSync(media.getPosition()); } - if (media.getDuration() == 0) { + if (media.getDuration() <= 0) { Log.d(TAG, "Setting duration of media"); media.setDuration(mediaPlayer.getDuration()); } @@ -367,10 +372,6 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { if (playerStatus == PlayerStatus.PLAYING || playerStatus == PlayerStatus.PAUSED || playerStatus == PlayerStatus.PREPARED) { - if (!stream) { - statusBeforeSeeking = playerStatus; - setPlayerStatus(PlayerStatus.SEEKING, media); - } if(seekLatch != null && seekLatch.getCount() > 0) { try { seekLatch.await(3, TimeUnit.SECONDS); @@ -379,7 +380,12 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { } } seekLatch = new CountDownLatch(1); + statusBeforeSeeking = playerStatus; + setPlayerStatus(PlayerStatus.SEEKING, media, getPosition()); mediaPlayer.seekTo(t); + if (statusBeforeSeeking == PlayerStatus.PREPARED) { + media.setPosition(t); + } try { seekLatch.await(3, TimeUnit.SECONDS); } catch (InterruptedException e) { @@ -682,18 +688,22 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { media = playable; } - private IPlayer createMediaPlayer() { + private void createMediaPlayer() { if (mediaPlayer != null) { mediaPlayer.release(); } - if (media == null || media.getMediaType() == MediaType.VIDEO) { + if(media == null) { + mediaPlayer = null; + return; + } + if (media.getMediaType() == MediaType.VIDEO) { mediaPlayer = new VideoPlayer(); } else { mediaPlayer = new AudioPlayer(context); } mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mediaPlayer.setWakeMode(context, PowerManager.PARTIAL_WAKE_LOCK); - return setMediaPlayerListeners(mediaPlayer); + setMediaPlayerListeners(mediaPlayer); } private final AudioManager.OnAudioFocusChangeListener audioFocusChangeListener = new AudioManager.OnAudioFocusChangeListener() { @@ -752,8 +762,9 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { @Override - public void endPlayback(final boolean wasSkipped, boolean switchingPlayers) { - executor.submit(() -> { + protected Future<?> endPlayback(final boolean hasEnded, final boolean wasSkipped, + final boolean shouldContinue, final boolean toStoppedState) { + return executor.submit(() -> { playerLock.lock(); releaseWifiLockIfNecessary(); @@ -762,13 +773,58 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { if (playerStatus != PlayerStatus.INDETERMINATE) { setPlayerStatus(PlayerStatus.INDETERMINATE, media); } + // we're relying on the position stored in the Playable object for post-playback processing + if (media != null) { + int position = getPosition(); + if (position >= 0) { + media.setPosition(position); + } + } + if (mediaPlayer != null) { mediaPlayer.reset(); - } audioManager.abandonAudioFocus(audioFocusChangeListener); - callback.endPlayback(media, isPlaying, wasSkipped, switchingPlayers); + final Playable currentMedia = media; + Playable nextMedia = null; + + if (shouldContinue) { + // Load next episode if previous episode was in the queue and if there + // is an episode in the queue left. + // Start playback immediately if continuous playback is enabled + nextMedia = callback.getNextInQueue(currentMedia); + + boolean playNextEpisode = isPlaying && + nextMedia != null && + UserPreferences.isFollowQueue(); + + if (playNextEpisode) { + Log.d(TAG, "Playback of next episode will start immediately."); + } else if (nextMedia == null){ + Log.d(TAG, "No more episodes available to play"); + } else { + Log.d(TAG, "Loading next episode, but not playing automatically."); + } + + if (nextMedia != null) { + callback.onPlaybackEnded(nextMedia.getMediaType(), !playNextEpisode); + // setting media to null signals to playMediaObject() that we're taking care of post-playback processing + media = null; + playMediaObject(nextMedia, false, !nextMedia.localFileAvailable(), playNextEpisode, playNextEpisode); + } + } + if (shouldContinue || toStoppedState) { + if (nextMedia == null) { + callback.onPlaybackEnded(null, true); + stop(); + } + final boolean hasNext = nextMedia != null; + + executor.submit(() -> callback.onPostPlayback(currentMedia, hasEnded, wasSkipped, hasNext)); + } else if (isPlaying) { + callback.onPlaybackPause(currentMedia, currentMedia.getPosition()); + } playerLock.unlock(); }); } @@ -779,8 +835,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { * This method will only take care of changing the PlayerStatus of this object! Other tasks like * abandoning audio focus have to be done with other methods. */ - @Override - public void stop() { + private void stop() { executor.submit(() -> { playerLock.lock(); releaseWifiLockIfNecessary(); @@ -801,27 +856,32 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { } private IPlayer setMediaPlayerListeners(IPlayer mp) { - if (mp != null && media != null) { - if (media.getMediaType() == MediaType.AUDIO) { - ((AudioPlayer) mp) - .setOnCompletionListener(audioCompletionListener); - ((AudioPlayer) mp) - .setOnSeekCompleteListener(audioSeekCompleteListener); - ((AudioPlayer) mp).setOnErrorListener(audioErrorListener); - ((AudioPlayer) mp) - .setOnBufferingUpdateListener(audioBufferingUpdateListener); - ((AudioPlayer) mp).setOnInfoListener(audioInfoListener); - ((AudioPlayer) mp).setOnSpeedAdjustmentAvailableChangedListener(audioSetSpeedAbilityListener); - } else { - ((VideoPlayer) mp) - .setOnCompletionListener(videoCompletionListener); - ((VideoPlayer) mp) - .setOnSeekCompleteListener(videoSeekCompleteListener); - ((VideoPlayer) mp).setOnErrorListener(videoErrorListener); - ((VideoPlayer) mp) - .setOnBufferingUpdateListener(videoBufferingUpdateListener); - ((VideoPlayer) mp).setOnInfoListener(videoInfoListener); + if (mp == null || media == null) { + return mp; + } + if (mp instanceof VideoPlayer) { + if (media.getMediaType() != MediaType.VIDEO) { + Log.w(TAG, "video player, but media type is " + media.getMediaType()); + } + VideoPlayer vp = (VideoPlayer) mp; + vp.setOnCompletionListener(videoCompletionListener); + vp.setOnSeekCompleteListener(videoSeekCompleteListener); + vp.setOnErrorListener(videoErrorListener); + vp.setOnBufferingUpdateListener(videoBufferingUpdateListener); + vp.setOnInfoListener(videoInfoListener); + } else if (mp instanceof AudioPlayer) { + if (media.getMediaType() != MediaType.AUDIO) { + Log.w(TAG, "audio player, but media type is " + media.getMediaType()); } + AudioPlayer ap = (AudioPlayer) mp; + ap.setOnCompletionListener(audioCompletionListener); + ap.setOnSeekCompleteListener(audioSeekCompleteListener); + ap.setOnErrorListener(audioErrorListener); + ap.setOnBufferingUpdateListener(audioBufferingUpdateListener); + ap.setOnInfoListener(audioInfoListener); + ap.setOnSpeedAdjustmentAvailableChangedListener(audioSetSpeedAbilityListener); + } else { + Log.w(TAG, "Unknown media player: " + mp); } return mp; } @@ -833,7 +893,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { mp -> genericOnCompletion(); private void genericOnCompletion() { - endPlayback(false, false); + endPlayback(true, false, true, true); } private final MediaPlayer.OnBufferingUpdateListener audioBufferingUpdateListener = @@ -889,8 +949,11 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { seekLatch.countDown(); } playerLock.lock(); + if (playerStatus == PlayerStatus.PLAYING) { + callback.onPlaybackStart(media, getPosition()); + } if (playerStatus == PlayerStatus.SEEKING) { - setPlayerStatus(statusBeforeSeeking, media); + setPlayerStatus(statusBeforeSeeking, media, getPosition()); } playerLock.unlock(); }); diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java index e6d41879c..b8ab70ed4 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java @@ -15,66 +15,65 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.media.AudioManager; import android.media.MediaPlayer; -import android.net.NetworkInfo; -import android.net.wifi.WifiManager; +import android.net.Uri; import android.os.Binder; import android.os.Build; +import android.os.Bundle; import android.os.IBinder; import android.os.Vibrator; import android.preference.PreferenceManager; import android.support.annotation.NonNull; import android.support.annotation.StringRes; +import android.support.v4.media.MediaBrowserCompat; +import android.support.v4.media.MediaBrowserServiceCompat; +import android.support.v4.media.MediaDescriptionCompat; import android.support.v4.media.MediaMetadataCompat; import android.support.v4.media.session.MediaSessionCompat; import android.support.v4.media.session.PlaybackStateCompat; +import android.support.v4.view.InputDeviceCompat; import android.support.v7.app.NotificationCompat; -import android.support.v7.media.MediaRouter; import android.text.TextUtils; import android.util.Log; import android.util.Pair; -import android.view.Display; import android.view.InputDevice; import android.view.KeyEvent; import android.view.SurfaceHolder; -import android.view.WindowManager; import android.widget.Toast; import com.bumptech.glide.Glide; import com.bumptech.glide.request.target.Target; -import com.google.android.gms.cast.ApplicationMetadata; -import com.google.android.libraries.cast.companionlibrary.cast.BaseCastManager; +import java.util.ArrayList; import java.util.List; import de.danoeh.antennapod.core.ClientConfig; import de.danoeh.antennapod.core.R; -import de.danoeh.antennapod.core.cast.CastConsumer; -import de.danoeh.antennapod.core.cast.CastManager; -import de.danoeh.antennapod.core.cast.DefaultCastConsumer; +import de.danoeh.antennapod.core.event.MessageEvent; import de.danoeh.antennapod.core.feed.Chapter; +import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.MediaType; +import de.danoeh.antennapod.core.feed.SearchResult; import de.danoeh.antennapod.core.glide.ApGlideSettings; -import de.danoeh.antennapod.core.gpoddernet.model.GpodnetEpisodeAction; -import de.danoeh.antennapod.core.gpoddernet.model.GpodnetEpisodeAction.Action; -import de.danoeh.antennapod.core.preferences.GpodnetPreferences; import de.danoeh.antennapod.core.preferences.PlaybackPreferences; +import de.danoeh.antennapod.core.preferences.SleepTimerPreferences; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.receiver.MediaButtonReceiver; +import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.storage.DBWriter; +import de.danoeh.antennapod.core.storage.FeedSearcher; import de.danoeh.antennapod.core.util.IntList; -import de.danoeh.antennapod.core.util.NetworkUtils; import de.danoeh.antennapod.core.util.QueueAccess; -import de.danoeh.antennapod.core.util.flattr.FlattrUtils; import de.danoeh.antennapod.core.util.playback.ExternalMedia; import de.danoeh.antennapod.core.util.playback.Playable; +import de.greenrobot.event.EventBus; /** * Controls the MediaPlayer that plays a FeedMedia-file */ -public class PlaybackService extends Service { +public class PlaybackService extends MediaBrowserServiceCompat { public static final String FORCE_WIDGET_UPDATE = "de.danoeh.antennapod.FORCE_WIDGET_UPDATE"; public static final String STOP_WIDGET_UPDATE = "de.danoeh.antennapod.STOP_WIDGET_UPDATE"; /** @@ -134,6 +133,12 @@ public class PlaybackService extends Service { */ public static final String ACTION_RESUME_PLAY_CURRENT_EPISODE = "action.de.danoeh.antennapod.core.service.resumePlayCurrentEpisode"; + /** + * Custom action used by Android Wear + */ + private static final String CUSTOM_ACTION_FAST_FORWARD = "action.de.danoeh.antennapod.core.service.fastForward"; + private static final String CUSTOM_ACTION_REWIND = "action.de.danoeh.antennapod.core.service.rewind"; + /** * Used in NOTIFICATION_TYPE_RELOAD. @@ -183,12 +188,6 @@ public class PlaybackService extends Service { public static final int INVALID_TIME = -1; /** - * Time in seconds during which the CastManager will try to reconnect to the Cast Device after - * the Wifi Connection is regained. - */ - private static final int RECONNECTION_ATTEMPT_PERIOD_S = 15; - - /** * Is true if service is running. */ public static boolean isRunning = false; @@ -204,28 +203,18 @@ public class PlaybackService extends Service { * Is true if a Cast Device is connected to the service. */ private static volatile boolean isCasting = false; - /** - * Stores the state of the cast playback just before it disconnects. - */ - private volatile PlaybackServiceMediaPlayer.PSMPInfo infoBeforeCastDisconnection; - - private boolean wifiConnectivity = true; - private BroadcastReceiver wifiBroadcastReceiver; private static final int NOTIFICATION_ID = 1; private PlaybackServiceMediaPlayer mediaPlayer; private PlaybackServiceTaskManager taskManager; + private PlaybackServiceFlavorHelper flavorHelper; - private CastManager castManager; - private MediaRouter mediaRouter; /** - * Only used for Lollipop notifications. + * Used for Lollipop notifications, Android Wear, and Android Auto. */ private MediaSessionCompat mediaSession; - private int startPosition; - private static volatile MediaType currentMediaType = MediaType.UNKNOWN; private final IBinder mBinder = new LocalBinder(); @@ -274,6 +263,8 @@ public class PlaybackService extends Service { Log.d(TAG, "Service created."); isRunning = true; + registerReceiver(autoStateUpdated, new IntentFilter( + "com.google.android.gms.car.media.STATUS")); registerReceiver(headsetDisconnected, new IntentFilter( Intent.ACTION_HEADSET_PLUG)); registerReceiver(shutdownReceiver, new IntentFilter( @@ -292,7 +283,7 @@ public class PlaybackService extends Service { ACTION_RESUME_PLAY_CURRENT_EPISODE)); taskManager = new PlaybackServiceTaskManager(this, taskManagerCallback); - mediaRouter = MediaRouter.getInstance(getApplicationContext()); + flavorHelper = new PlaybackServiceFlavorHelper(PlaybackService.this, flavorHelperCallback); PreferenceManager.getDefaultSharedPreferences(this) .registerOnSharedPreferenceChangeListener(prefListener); @@ -303,6 +294,7 @@ public class PlaybackService extends Service { PendingIntent buttonReceiverIntent = PendingIntent.getBroadcast(this, 0, mediaButtonIntent, PendingIntent.FLAG_UPDATE_CURRENT); mediaSession = new MediaSessionCompat(getApplicationContext(), TAG, eventReceiver, buttonReceiverIntent); + setSessionToken(mediaSession.getSessionToken()); try { mediaSession.setCallback(sessionCallback); @@ -316,19 +308,21 @@ public class PlaybackService extends Service { npe.printStackTrace(); } - castManager = CastManager.getInstance(); - castManager.addCastConsumer(castConsumer); - isCasting = castManager.isConnected(); - if (isCasting) { - if (UserPreferences.isCastEnabled()) { - onCastAppConnected(false); - } else { - castManager.disconnect(); + List<MediaSessionCompat.QueueItem> queueItems = new ArrayList<>(); + try { + for (FeedItem feedItem : taskManager.getQueue()) { + if(feedItem.getMedia() != null) { + MediaDescriptionCompat mediaDescription = feedItem.getMedia().getMediaItem().getDescription(); + queueItems.add(new MediaSessionCompat.QueueItem(mediaDescription, feedItem.getId())); + } } - } else { - mediaPlayer = new LocalPSMP(this, mediaPlayerCallback); + mediaSession.setQueue(queueItems); + } catch (InterruptedException e) { + e.printStackTrace(); } + flavorHelper.initializeMediaPlayer(PlaybackService.this); + mediaSession.setActive(true); } @@ -345,6 +339,7 @@ public class PlaybackService extends Service { if (mediaSession != null) { mediaSession.release(); } + unregisterReceiver(autoStateUpdated); unregisterReceiver(headsetDisconnected); unregisterReceiver(shutdownReceiver); if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { @@ -354,16 +349,94 @@ public class PlaybackService extends Service { unregisterReceiver(skipCurrentEpisodeReceiver); unregisterReceiver(pausePlayCurrentEpisodeReceiver); unregisterReceiver(pauseResumeCurrentEpisodeReceiver); - castManager.removeCastConsumer(castConsumer); - unregisterWifiBroadcastReceiver(); + flavorHelper.removeCastConsumer(); + flavorHelper.unregisterWifiBroadcastReceiver(); mediaPlayer.shutdown(); taskManager.shutdown(); } @Override + public BrowserRoot onGetRoot(@NonNull String clientPackageName, int clientUid, Bundle rootHints) { + Log.d(TAG, "OnGetRoot: clientPackageName=" + clientPackageName + + "; clientUid=" + clientUid + " ; rootHints=" + rootHints); + return new BrowserRoot( + getResources().getString(R.string.app_name), // Name visible in Android Auto + null); // Bundle of optional extras + } + + private MediaBrowserCompat.MediaItem createBrowsableMediaItemForRoot() { + MediaDescriptionCompat description = new MediaDescriptionCompat.Builder() + .setMediaId(getResources().getString(R.string.queue_label)) + .setTitle(getResources().getString(R.string.queue_label)) + .build(); + return new MediaBrowserCompat.MediaItem(description, + MediaBrowserCompat.MediaItem.FLAG_BROWSABLE); + } + + private MediaBrowserCompat.MediaItem createBrowsableMediaItemForFeed(Feed feed) { + MediaDescriptionCompat.Builder builder = new MediaDescriptionCompat.Builder() + .setMediaId("FeedId:" + Long.toString(feed.getId())) + .setTitle(feed.getTitle()) + .setDescription(feed.getDescription()) + .setSubtitle(feed.getCustomTitle()); + if(feed.getImageLocation() != null) { + builder.setIconUri(Uri.parse(feed.getImageLocation())); + } + if(feed.getLink() != null) { + builder.setMediaUri(Uri.parse(feed.getLink())); + } + MediaDescriptionCompat description = builder.build(); + return new MediaBrowserCompat.MediaItem(description, + MediaBrowserCompat.MediaItem.FLAG_BROWSABLE); + } + + @Override + public void onLoadChildren(@NonNull String parentId, + @NonNull Result<List<MediaBrowserCompat.MediaItem>> result) { + Log.d(TAG, "OnLoadChildren: parentMediaId=" + parentId); + List<MediaBrowserCompat.MediaItem> mediaItems = new ArrayList<>(); + if (parentId.equals(getResources().getString(R.string.app_name))) { + // Root List + try { + if (!(taskManager.getQueue().isEmpty())) { + mediaItems.add(createBrowsableMediaItemForRoot()); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + List<Feed> feeds = DBReader.getFeedList(); + for (Feed feed: feeds) { + mediaItems.add(createBrowsableMediaItemForFeed(feed)); + } + } else if (parentId.equals(getResources().getString(R.string.queue_label))){ + // Child List + try { + for (FeedItem feedItem: taskManager.getQueue()) { + mediaItems.add(feedItem.getMedia().getMediaItem()); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } else if (parentId.startsWith("FeedId:")) { + Long feedId = Long.parseLong(parentId.split(":")[1]); + List<FeedItem> feedItems = DBReader.getFeedItemList(DBReader.getFeed(feedId)); + for (FeedItem feedItem: feedItems) { + if(feedItem.getMedia() != null && feedItem.getMedia().getMediaItem() != null) { + mediaItems.add(feedItem.getMedia().getMediaItem()); + } + } + } + result.sendResult(mediaItems); + } + + @Override public IBinder onBind(Intent intent) { Log.d(TAG, "Received onBind event"); - return mBinder; + if(intent.getAction() != null && TextUtils.equals(intent.getAction(), MediaBrowserServiceCompat.SERVICE_INTERFACE)) { + return super.onBind(intent); + } else { + return mBinder; + } } @Override @@ -388,10 +461,8 @@ public class PlaybackService extends Service { if (keycode != -1) { Log.d(TAG, "Received media button event"); handleKeycode(keycode, intent.getIntExtra(MediaButtonReceiver.EXTRA_SOURCE, - InputDevice.SOURCE_CLASS_NONE)); - } else if (castDisconnect) { - castManager.disconnect(); - } else { + InputDeviceCompat.SOURCE_CLASS_NONE)); + } else if (!flavorHelper.castDisconnect(castDisconnect)) { started = true; boolean stream = intent.getBooleanExtra(EXTRA_SHOULD_STREAM, true); @@ -399,9 +470,7 @@ public class PlaybackService extends Service { boolean prepareImmediately = intent.getBooleanExtra(EXTRA_PREPARE_IMMEDIATELY, false); sendNotificationBroadcast(NOTIFICATION_TYPE_RELOAD, 0); //If the user asks to play External Media, the casting session, if on, should end. - if (playable instanceof ExternalMedia) { - castManager.disconnect(); - } + flavorHelper.castDisconnect(playable instanceof ExternalMedia); mediaPlayer.playMediaObject(playable, stream, startWhenPrepared, prepareImmediately); } } @@ -449,17 +518,25 @@ public class PlaybackService extends Service { UserPreferences.shouldHardwareButtonSkip()) { // assume the skip command comes from a notification or the lockscreen // a >| skip button should actually skip - mediaPlayer.endPlayback(true, false); + mediaPlayer.skip(); } else { // assume skip command comes from a (bluetooth) media button // user actually wants to fast-forward - seekDelta(UserPreferences.getFastFowardSecs() * 1000); + seekDelta(UserPreferences.getFastForwardSecs() * 1000); } break; case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: - mediaPlayer.seekDelta(UserPreferences.getFastFowardSecs() * 1000); + mediaPlayer.seekDelta(UserPreferences.getFastForwardSecs() * 1000); break; case KeyEvent.KEYCODE_MEDIA_PREVIOUS: + if(UserPreferences.shouldHardwarePreviousButtonRestart()) { + // user wants to restart current episode + mediaPlayer.seekTo(0); + } else { + // user wants to rewind current episode + mediaPlayer.seekDelta(-UserPreferences.getRewindSecs() * 1000); + } + break; case KeyEvent.KEYCODE_MEDIA_REWIND: mediaPlayer.seekDelta(-UserPreferences.getRewindSecs() * 1000); break; @@ -506,7 +583,7 @@ public class PlaybackService extends Service { private final PlaybackServiceTaskManager.PSTMCallback taskManagerCallback = new PlaybackServiceTaskManager.PSTMCallback() { @Override public void positionSaverTick() { - saveCurrentPosition(true, PlaybackServiceTaskManager.POSITION_SAVER_WAITING_INTERVAL); + saveCurrentPosition(true, null, PlaybackServiceMediaPlayer.INVALID_TIME); } @Override @@ -558,9 +635,6 @@ public class PlaybackService extends Service { break; case PAUSED: - taskManager.cancelPositionSaver(); - saveCurrentPosition(false, 0); - taskManager.cancelWidgetUpdater(); if ((UserPreferences.isPersistNotify() || isCasting) && android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { // do not remove notification on pause based on user pref and whether android version supports expanded notifications @@ -571,22 +645,6 @@ public class PlaybackService extends Service { stopForeground(true); } writePlayerStatusPlaybackPreferences(); - - final Playable playable = newInfo.playable; - - // Gpodder: send play action - if(GpodnetPreferences.loggedIn() && playable instanceof FeedMedia) { - FeedMedia media = (FeedMedia) playable; - FeedItem item = media.getItem(); - GpodnetEpisodeAction action = new GpodnetEpisodeAction.Builder(item, Action.PLAY) - .currentDeviceId() - .currentTimestamp() - .started(startPosition / 1000) - .position(getCurrentPosition() / 1000) - .total(getDuration() / 1000) - .build(); - GpodnetPreferences.enqueueEpisodeAction(action); - } break; case STOPPED: @@ -595,15 +653,15 @@ public class PlaybackService extends Service { break; case PLAYING: - Log.d(TAG, "Audiofocus successfully requested"); - Log.d(TAG, "Resuming/Starting playback"); - - taskManager.startPositionSaver(); - taskManager.startWidgetUpdater(); writePlayerStatusPlaybackPreferences(); setupNotification(newInfo); started = true; - startPosition = mediaPlayer.getPosition(); + // set sleep timer if auto-enabled + if(newInfo.oldPlayerStatus != null && newInfo.oldPlayerStatus != PlayerStatus.SEEKING && + SleepTimerPreferences.autoEnable() && !sleepTimerActive()) { + setSleepTimer(SleepTimerPreferences.timerMillis(), SleepTimerPreferences.shakeToReset(), + SleepTimerPreferences.vibrate()); + } break; case ERROR: @@ -657,14 +715,8 @@ public class PlaybackService extends Service { case MediaPlayer.MEDIA_INFO_BUFFERING_END: sendNotificationBroadcast(NOTIFICATION_TYPE_BUFFER_END, 0); return true; - case RemotePSMP.CAST_ERROR: - sendNotificationBroadcast(NOTIFICATION_TYPE_SHOW_TOAST, resourceId); - return true; - case RemotePSMP.CAST_ERROR_PRIORITY_HIGH: - Toast.makeText(PlaybackService.this, resourceId, Toast.LENGTH_SHORT).show(); - return true; default: - return false; + return flavorHelper.onMediaPlayerInfo(PlaybackService.this, code, resourceId); } } @@ -682,121 +734,174 @@ public class PlaybackService extends Service { } @Override - public boolean endPlayback(Playable media, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) { - PlaybackService.this.endPlayback(media, playNextEpisode, wasSkipped, switchingPlayers); - return true; + public void onPostPlayback(@NonNull Playable media, boolean ended, boolean skipped, + boolean playingNext) { + PlaybackService.this.onPostPlayback(media, ended, skipped, playingNext); + } + + @Override + public void onPlaybackStart(@NonNull Playable playable, int position) { + taskManager.startWidgetUpdater(); + if (position != PlaybackServiceMediaPlayer.INVALID_TIME) { + playable.setPosition(position); + } + playable.onPlaybackStart(); + taskManager.startPositionSaver(); + } + + @Override + public void onPlaybackPause(Playable playable, int position) { + taskManager.cancelPositionSaver(); + saveCurrentPosition(position == PlaybackServiceMediaPlayer.INVALID_TIME || playable == null, + playable, position); + taskManager.cancelWidgetUpdater(); + if (playable != null) { + playable.onPlaybackPause(getApplicationContext()); + } + } + + @Override + public Playable getNextInQueue(Playable currentMedia) { + return PlaybackService.this.getNextInQueue(currentMedia); + } + + @Override + public void onPlaybackEnded(MediaType mediaType, boolean stopPlaying) { + PlaybackService.this.onPlaybackEnded(mediaType, stopPlaying); } }; - private void endPlayback(final Playable playable, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) { - Log.d(TAG, "Playback ended" + (switchingPlayers ? " from switching players": "")); + private Playable getNextInQueue(final Playable currentMedia) { + if (!(currentMedia instanceof FeedMedia)) { + Log.d(TAG, "getNextInQueue(), but playable not an instance of FeedMedia, so not proceeding"); + return null; + } + if (!ClientConfig.playbackServiceCallbacks.useQueue()) { + Log.d(TAG, "getNextInQueue(), but queue not in use by this app"); + return null; + } + Log.d(TAG, "getNextInQueue()"); + FeedMedia media = (FeedMedia) currentMedia; + try { + media.loadMetadata(); + } catch (Playable.PlayableException e) { + Log.e(TAG, "Unable to load metadata to get next in queue", e); + return null; + } + FeedItem item = media.getItem(); + if (item == null) { + Log.w(TAG, "getNextInQueue() with FeedMedia object whose FeedItem is null"); + return null; + } + FeedItem nextItem; + try { + final List<FeedItem> queue = taskManager.getQueue(); + nextItem = DBTasks.getQueueSuccessorOfItem(item.getId(), queue); + } catch (InterruptedException e) { + Log.e(TAG, "Error handling the queue in order to retrieve the next item", e); + return null; + } + return (nextItem != null)? nextItem.getMedia() : null; + + } + + /** + * Set of instructions to be performed when playback ends. + */ + private void onPlaybackEnded(MediaType mediaType, boolean stopPlaying) { + Log.d(TAG, "Playback ended"); + if (stopPlaying) { + taskManager.cancelPositionSaver(); + writePlaybackPreferencesNoMediaPlaying(); + if (!isCasting) { + stopForeground(true); + } + stopWidgetUpdater(); + } + if (mediaType == null) { + sendNotificationBroadcast(NOTIFICATION_TYPE_PLAYBACK_END, 0); + } else { + sendNotificationBroadcast(NOTIFICATION_TYPE_RELOAD, + isCasting ? EXTRA_CODE_CAST : + (mediaType == MediaType.VIDEO) ? EXTRA_CODE_VIDEO : EXTRA_CODE_AUDIO); + } + } + /** + * This method processes the media object after its playback ended, either because it completed + * or because a different media object was selected for playback. + * + * Even though these tasks aren't supposed to be resource intensive, a good practice is to + * usually call this method on a background thread. + * + * @param playable the media object that was playing. It is assumed that its position + * property was updated before this method was called. + * @param ended if true, it signals that {@param playable} was played until its end. + * In such case, the position property of the media becomes irrelevant for + * most of the tasks (although it's still a good practice to keep it + * accurate). + * @param skipped if the user pressed a skip >| button. + * @param playingNext if true, it means another media object is being loaded in place of this + * one. + * Instances when we'd set it to false would be when we're not following the + * queue or when the queue has ended. + */ + private void onPostPlayback(final Playable playable, boolean ended, boolean skipped, + boolean playingNext) { if (playable == null) { - Log.e(TAG, "Cannot end playback: media was null"); + Log.e(TAG, "Cannot do post-playback processing: media was null"); return; } + Log.d(TAG, "onPostPlayback(): media=" + playable.getEpisodeTitle()); - taskManager.cancelPositionSaver(); - - boolean isInQueue = false; - FeedItem nextItem = null; + if (!(playable instanceof FeedMedia)) { + Log.d(TAG, "Not doing post-playback processing: media not of type FeedMedia"); + if (ended) { + playable.onPlaybackCompleted(getApplicationContext()); + } else { + playable.onPlaybackPause(getApplicationContext()); + } + return; + } + FeedMedia media = (FeedMedia) playable; + FeedItem item = media.getItem(); + boolean smartMarkAsPlayed = playingNext && media.hasAlmostEnded(); + if (!ended && smartMarkAsPlayed) { + Log.d(TAG, "smart mark as played"); + } - if (playable instanceof FeedMedia && ((FeedMedia) playable).getItem() != null) { - FeedMedia media = (FeedMedia) playable; - FeedItem item = media.getItem(); + if (ended || smartMarkAsPlayed) { + media.onPlaybackCompleted(getApplicationContext()); + } else { + media.onPlaybackPause(getApplicationContext()); + } - if (!switchingPlayers) { + if (item != null) { + if (ended || smartMarkAsPlayed || + (skipped && !UserPreferences.shouldSkipKeepEpisode())) { + // only mark the item as played if we're not keeping it anyways + DBWriter.markItemPlayed(item, FeedItem.PLAYED, ended); try { final List<FeedItem> queue = taskManager.getQueue(); - isInQueue = QueueAccess.ItemListAccess(queue).contains(item.getId()); - nextItem = DBTasks.getQueueSuccessorOfItem(item.getId(), queue); + if (QueueAccess.ItemListAccess(queue).contains(item.getId())) { + // don't know if it actually matters to not autodownload when smart mark as played is triggered + DBWriter.removeQueueItem(PlaybackService.this, item, ended); + } } catch (InterruptedException e) { e.printStackTrace(); // isInQueue remains false } - - boolean shouldKeep = wasSkipped && UserPreferences.shouldSkipKeepEpisode(); - - if (!shouldKeep) { - // only mark the item as played if we're not keeping it anyways - DBWriter.markItemPlayed(item, FeedItem.PLAYED, true); - - if (isInQueue) { - DBWriter.removeQueueItem(PlaybackService.this, item, true); - } - - // Delete episode if enabled - if (item.getFeed().getPreferences().getCurrentAutoDelete()) { - DBWriter.deleteFeedMediaOfItem(PlaybackService.this, media.getId()); - Log.d(TAG, "Episode Deleted"); - } + // Delete episode if enabled + if (item.getFeed().getPreferences().getCurrentAutoDelete() && + !(item.isTagged(FeedItem.TAG_FAVORITE) && UserPreferences.shouldFavoriteKeepEpisode())) { + DBWriter.deleteFeedMediaOfItem(PlaybackService.this, media.getId()); + Log.d(TAG, "Episode Deleted"); } } - - - DBWriter.addItemToPlaybackHistory(media); - - // auto-flattr if enabled - if (isAutoFlattrable(media) && UserPreferences.getAutoFlattrPlayedDurationThreshold() == 1.0f) { - DBTasks.flattrItemIfLoggedIn(PlaybackService.this, item); - } - - // gpodder play action - if(GpodnetPreferences.loggedIn()) { - GpodnetEpisodeAction action = new GpodnetEpisodeAction.Builder(item, Action.PLAY) - .currentDeviceId() - .currentTimestamp() - .started(startPosition / 1000) - .position(getDuration() / 1000) - .total(getDuration() / 1000) - .build(); - GpodnetPreferences.enqueueEpisodeAction(action); - } } - if (!switchingPlayers) { - // Load next episode if previous episode was in the queue and if there - // is an episode in the queue left. - // Start playback immediately if continuous playback is enabled - Playable nextMedia = null; - boolean loadNextItem = ClientConfig.playbackServiceCallbacks.useQueue() && - isInQueue && - nextItem != null; - - playNextEpisode = playNextEpisode && - loadNextItem && - UserPreferences.isFollowQueue(); - - if (loadNextItem) { - Log.d(TAG, "Loading next item in queue"); - nextMedia = nextItem.getMedia(); - } - final boolean prepareImmediately; - final boolean startWhenPrepared; - final boolean stream; - - if (playNextEpisode) { - Log.d(TAG, "Playback of next episode will start immediately."); - prepareImmediately = startWhenPrepared = true; - } else { - Log.d(TAG, "No more episodes available to play"); - prepareImmediately = startWhenPrepared = false; - stopForeground(true); - stopWidgetUpdater(); - } - - writePlaybackPreferencesNoMediaPlaying(); - if (nextMedia != null) { - stream = !nextMedia.localFileAvailable(); - mediaPlayer.playMediaObject(nextMedia, stream, startWhenPrepared, prepareImmediately); - sendNotificationBroadcast(NOTIFICATION_TYPE_RELOAD, - isCasting ? EXTRA_CODE_CAST : - (nextMedia.getMediaType() == MediaType.VIDEO) ? EXTRA_CODE_VIDEO : EXTRA_CODE_AUDIO); - } else { - sendNotificationBroadcast(NOTIFICATION_TYPE_PLAYBACK_END, 0); - mediaPlayer.stop(); - //stopSelf(); - } + if (ended || skipped || playingNext) { + DBWriter.addItemToPlaybackHistory(media); } } @@ -804,11 +909,14 @@ public class PlaybackService extends Service { Log.d(TAG, "Setting sleep timer to " + Long.toString(waitingTime) + " milliseconds"); taskManager.setSleepTimer(waitingTime, shakeToReset, vibrate); sendNotificationBroadcast(NOTIFICATION_TYPE_SLEEPTIMER_UPDATE, 0); + EventBus.getDefault().post(new MessageEvent(getString(R.string.sleep_timer_enabled_label), + () -> disableSleepTimer())); } public void disableSleepTimer() { taskManager.disableSleepTimer(); sendNotificationBroadcast(NOTIFICATION_TYPE_SLEEPTIMER_UPDATE, 0); + EventBus.getDefault().post(new MessageEvent(getString(R.string.sleep_timer_disabled_label))); } private void writePlaybackPreferencesNoMediaPlaying() { @@ -962,13 +1070,45 @@ public class PlaybackService extends Service { state = PlaybackStateCompat.STATE_NONE; } sessionState.setState(state, mediaPlayer.getPosition(), mediaPlayer.getPlaybackSpeed()); - sessionState.setActions(PlaybackStateCompat.ACTION_PLAY_PAUSE + long capabilities = PlaybackStateCompat.ACTION_PLAY_PAUSE | PlaybackStateCompat.ACTION_REWIND | PlaybackStateCompat.ACTION_FAST_FORWARD - | PlaybackStateCompat.ACTION_SKIP_TO_NEXT); + | PlaybackStateCompat.ACTION_SKIP_TO_NEXT; + + if (useSkipToPreviousForRewindInLockscreen()) { + // Workaround to fool Android so that Lockscreen will expose a skip-to-previous button, + // which will be used for rewind. + // The workaround is used for pre Lollipop (Androidv5) devices. + // For Androidv5+, lockscreen widges are really notifications (compact), + // with an independent codepath + // + // @see #sessionCallback in the backing callback, skipToPrevious implementation + // is actually the same as rewind. So no new inconsistency is created. + // @see #setupNotification() for the method to create Androidv5+ lockscreen UI + // with notification (compact) + capabilities = capabilities | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS; + } + + sessionState.setActions(capabilities); + + flavorHelper.sessionStateAddActionForWear(sessionState, + CUSTOM_ACTION_REWIND, getString(R.string.rewind_label), android.R.drawable.ic_media_rew); + flavorHelper.sessionStateAddActionForWear(sessionState, + CUSTOM_ACTION_FAST_FORWARD, getString(R.string.fast_forward_label), android.R.drawable.ic_media_ff); + + flavorHelper.mediaSessionSetExtraForWear(mediaSession); + mediaSession.setPlaybackState(sessionState.build()); } + private static boolean useSkipToPreviousForRewindInLockscreen() { + // showRewindOnCompactNotification() corresponds to the "Set Lockscreen Buttons" + // Settings in UI. + // Hence, from user perspective, he/she is setting the buttons for Lockscreen + return ( UserPreferences.showRewindOnCompactNotification() && + (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) ); + } + /** * Used by updateMediaSessionMetadata to load notification data in another thread. */ @@ -986,39 +1126,43 @@ public class PlaybackService extends Service { MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder(); builder.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, p.getFeedTitle()); builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, p.getEpisodeTitle()); + builder.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, p.getFeedTitle()); builder.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, p.getDuration()); builder.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, p.getEpisodeTitle()); - builder.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, p.getFeedTitle()); + builder.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_SUBTITLE, p.getFeedTitle()); - if (p.getImageUri() != null && UserPreferences.setLockscreenBackground()) { - builder.putString(MediaMetadataCompat.METADATA_KEY_ART_URI, p.getImageUri().toString()); - try { - if (isCasting) { + String imageLocation = p.getImageLocation(); + + if (!TextUtils.isEmpty(imageLocation)) { + if (UserPreferences.setLockscreenBackground()) { + builder.putString(MediaMetadataCompat.METADATA_KEY_ART_URI, imageLocation); + try { Bitmap art = Glide.with(this) - .load(p.getImageUri()) + .load(imageLocation) .asBitmap() .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) .into(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) .get(); builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ART, art); - } else { - WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE); - Display display = wm.getDefaultDisplay(); - Bitmap art = Glide.with(this) - .load(p.getImageUri()) - .asBitmap() - .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) - .centerCrop() - .into(display.getWidth(), display.getHeight()) - .get(); - builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ART, art); + } catch (Throwable tr) { + Log.e(TAG, Log.getStackTraceString(tr)); } - } catch (Throwable tr) { - Log.e(TAG, Log.getStackTraceString(tr)); + } else if (isCasting) { + // In the absence of metadata art, the controller dialog takes care of creating it. + builder.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON_URI, imageLocation); } } if (!Thread.currentThread().isInterrupted() && started) { - mediaSession.setMetadata(builder.build()); + mediaSession.setSessionActivity(PendingIntent.getActivity(this, 0, + PlaybackService.getPlayerActivityIntent(this), + PendingIntent.FLAG_UPDATE_CURRENT)); + try { + mediaSession.setMetadata(builder.build()); + } catch (OutOfMemoryError e) { + Log.e(TAG, "Setting media session metadata", e); + builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ART, null); + mediaSession.setMetadata(builder.build()); + } } }; @@ -1054,7 +1198,7 @@ public class PlaybackService extends Service { android.R.dimen.notification_large_icon_width); try { icon = Glide.with(PlaybackService.this) - .load(info.playable.getImageUri()) + .load(info.playable.getImageLocation()) .asBitmap() .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) .centerCrop() @@ -1164,8 +1308,8 @@ public class PlaybackService extends Service { .setShowActionsInCompactView(compactActionList.toArray()) .setShowCancelButton(true) .setCancelButtonIntent(stopButtonPendingIntent)) - .setVisibility(Notification.VISIBILITY_PUBLIC) - .setColor(Notification.COLOR_DEFAULT); + .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) + .setColor(NotificationCompat.COLOR_DEFAULT); notification = notificationBuilder.build(); @@ -1202,28 +1346,23 @@ public class PlaybackService extends Service { /** * Persists the current position and last played time of the media file. * - * @param updatePlayedDuration true if played_duration should be updated. This applies only to FeedMedia objects - * @param deltaPlayedDuration value by which played_duration should be increased. + * @param fromMediaPlayer if true, the information is gathered from the current Media Player + * and {@param playable} and {@param position} become irrelevant. + * @param playable the playable for which the current position should be saved, unless + * {@param fromMediaPlayer} is true. + * @param position the position that should be saved, unless {@param fromMediaPlayer} is true. */ - private synchronized void saveCurrentPosition(boolean updatePlayedDuration, int deltaPlayedDuration) { - int position = getCurrentPosition(); - int duration = getDuration(); - float playbackSpeed = getCurrentPlaybackSpeed(); - final Playable playable = mediaPlayer.getPlayable(); + private synchronized void saveCurrentPosition(boolean fromMediaPlayer, Playable playable, int position) { + int duration; + if (fromMediaPlayer) { + position = getCurrentPosition(); + duration = getDuration(); + playable = mediaPlayer.getPlayable(); + } else { + duration = playable.getDuration(); + } if (position != INVALID_TIME && duration != INVALID_TIME && playable != null) { Log.d(TAG, "Saving current position to " + position); - if (updatePlayedDuration && playable instanceof FeedMedia) { - FeedMedia media = (FeedMedia) playable; - FeedItem item = media.getItem(); - media.setPlayedDuration(media.getPlayedDuration() + ((int) (deltaPlayedDuration * playbackSpeed))); - // Auto flattr - if (isAutoFlattrable(media) && - (media.getPlayedDuration() > UserPreferences.getAutoFlattrPlayedDurationThreshold() * duration)) { - Log.d(TAG, "saveCurrentPosition: performing auto flattr since played duration " + Integer.toString(media.getPlayedDuration()) - + " is " + UserPreferences.getAutoFlattrPlayedDurationThreshold() * 100 + "% of file duration " + Integer.toString(duration)); - DBTasks.flattrItemIfLoggedIn(this, item); - } - } playable.saveCurrentPosition( PreferenceManager.getDefaultSharedPreferences(getApplicationContext()), position, @@ -1258,7 +1397,7 @@ public class PlaybackService extends Service { if (info.playable != null) { Intent i = new Intent(whatChanged); - i.putExtra("id", 1); + i.putExtra("id", 1L); i.putExtra("artist", ""); i.putExtra("album", info.playable.getFeedTitle()); i.putExtra("track", info.playable.getEpisodeTitle()); @@ -1267,12 +1406,35 @@ public class PlaybackService extends Service { if (queue != null) { i.putExtra("ListSize", queue.size()); } - i.putExtra("duration", info.playable.getDuration()); - i.putExtra("position", info.playable.getPosition()); + i.putExtra("duration", (long) info.playable.getDuration()); + i.putExtra("position", (long) info.playable.getPosition()); sendBroadcast(i); } } + private final BroadcastReceiver autoStateUpdated = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String status = intent.getStringExtra("media_connection_status"); + boolean isConnectedToCar = "media_connected".equals(status); + Log.d(TAG, "Received Auto Connection update: " + status); + if(!isConnectedToCar) { + Log.d(TAG, "Car was unplugged during playback."); + pauseIfPauseOnDisconnect(); + } else { + PlayerStatus playerStatus = mediaPlayer.getPlayerStatus(); + if (playerStatus == PlayerStatus.PAUSED || playerStatus == PlayerStatus.PREPARED) { + mediaPlayer.resume(); + } else if (playerStatus == PlayerStatus.PREPARING) { + mediaPlayer.setStartWhenPrepared(!mediaPlayer.isStartWhenPrepared()); + } else if (playerStatus == PlayerStatus.INITIALIZED) { + mediaPlayer.setStartWhenPrepared(true); + mediaPlayer.prepare(); + } + } + } + }; + /** * Pauses playback when the headset is disconnected and the preference is * set @@ -1332,7 +1494,7 @@ public class PlaybackService extends Service { * Pauses playback if PREF_PAUSE_ON_HEADSET_DISCONNECT was set to true. */ private void pauseIfPauseOnDisconnect() { - if (UserPreferences.isPauseOnHeadsetDisconnect()) { + if (UserPreferences.isPauseOnHeadsetDisconnect() && !isCasting()) { if (mediaPlayer.getPlayerStatus() == PlayerStatus.PLAYING) { transientPause = true; } @@ -1375,7 +1537,7 @@ public class PlaybackService extends Service { public void onReceive(Context context, Intent intent) { if (TextUtils.equals(intent.getAction(), ACTION_SKIP_CURRENT_EPISODE)) { Log.d(TAG, "Received SKIP_CURRENT_EPISODE intent"); - mediaPlayer.endPlayback(true, false); + mediaPlayer.skip(); } } }; @@ -1468,26 +1630,7 @@ public class PlaybackService extends Service { public void seekTo(final int t) { - if(mediaPlayer.getPlayerStatus() == PlayerStatus.PLAYING - && GpodnetPreferences.loggedIn()) { - final Playable playable = mediaPlayer.getPlayable(); - if (playable instanceof FeedMedia) { - FeedMedia media = (FeedMedia) playable; - FeedItem item = media.getItem(); - GpodnetEpisodeAction action = new GpodnetEpisodeAction.Builder(item, Action.PLAY) - .currentDeviceId() - .currentTimestamp() - .started(startPosition / 1000) - .position(getCurrentPosition() / 1000) - .total(getDuration() / 1000) - .build(); - GpodnetPreferences.enqueueEpisodeAction(action); - } - } mediaPlayer.seekTo(t); - if(mediaPlayer.getPlayerStatus() == PlayerStatus.PLAYING ) { - startPosition = t; - } } @@ -1496,10 +1639,10 @@ public class PlaybackService extends Service { } /** - * @see LocalPSMP#seekToChapter(de.danoeh.antennapod.core.feed.Chapter) + * Seek to the start of the specified chapter. */ public void seekToChapter(Chapter c) { - mediaPlayer.seekToChapter(c); + seekTo((int) c.getStart()); } /** @@ -1526,76 +1669,6 @@ public class PlaybackService extends Service { return mediaPlayer.getVideoSize(); } - private boolean isAutoFlattrable(FeedMedia media) { - if (media != null) { - FeedItem item = media.getItem(); - return item != null && FlattrUtils.hasToken() && UserPreferences.isAutoFlattr() && item.getPaymentLink() != null && item.getFlattrStatus().getUnflattred(); - } else { - return false; - } - } - - private CastConsumer castConsumer = new DefaultCastConsumer() { - @Override - public void onApplicationConnected(ApplicationMetadata appMetadata, String sessionId, boolean wasLaunched) { - PlaybackService.this.onCastAppConnected(wasLaunched); - } - - @Override - public void onDisconnectionReason(int reason) { - Log.d(TAG, "onDisconnectionReason() with code " + reason); - // This is our final chance to update the underlying stream position - // In onDisconnected(), the underlying CastPlayback#mVideoCastConsumer - // is disconnected and hence we update our local value of stream position - // to the latest position. - if (mediaPlayer != null) { - saveCurrentPosition(false, 0); - infoBeforeCastDisconnection = mediaPlayer.getPSMPInfo(); - if (reason != BaseCastManager.DISCONNECT_REASON_EXPLICIT && - infoBeforeCastDisconnection.playerStatus == PlayerStatus.PLAYING) { - // If it's NOT based on user action, we shouldn't automatically resume local playback - infoBeforeCastDisconnection.playerStatus = PlayerStatus.PAUSED; - } - } - } - - @Override - public void onDisconnected() { - Log.d(TAG, "onDisconnected()"); - isCasting = false; - PlaybackServiceMediaPlayer.PSMPInfo info = infoBeforeCastDisconnection; - infoBeforeCastDisconnection = null; - if (info == null && mediaPlayer != null) { - info = mediaPlayer.getPSMPInfo(); - } - if (info == null) { - info = new PlaybackServiceMediaPlayer.PSMPInfo(PlayerStatus.STOPPED, null); - } - switchMediaPlayer(new LocalPSMP(PlaybackService.this, mediaPlayerCallback), - info, true); - if (info.playable != null) { - sendNotificationBroadcast(NOTIFICATION_TYPE_RELOAD, - info.playable.getMediaType() == MediaType.AUDIO ? EXTRA_CODE_AUDIO : EXTRA_CODE_VIDEO); - } else { - Log.d(TAG, "Cast session disconnected, but no current media"); - sendNotificationBroadcast(NOTIFICATION_TYPE_PLAYBACK_END, 0); - } - // hardware volume buttons control the local device volume - mediaRouter.setMediaSessionCompat(null); - unregisterWifiBroadcastReceiver(); - PlayerStatus status = info.playerStatus; - if ((status == PlayerStatus.PLAYING || - status == PlayerStatus.SEEKING || - status == PlayerStatus.PREPARING || - UserPreferences.isPersistNotify()) && - android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - setupNotification(info); - } else if (!UserPreferences.isPersistNotify()){ - stopForeground(true); - } - } - }; - private final MediaSessionCompat.Callback sessionCallback = new MediaSessionCompat.Callback() { private static final String TAG = "MediaSessionCompat"; @@ -1613,22 +1686,46 @@ public class PlaybackService extends Service { } @Override + public void onPlayFromMediaId(String mediaId, Bundle extras) { + Log.d(TAG, "onPlayFromMediaId: mediaId: " + mediaId + " extras: " + extras.toString()); + FeedMedia p = DBReader.getFeedMedia(Long.parseLong(mediaId)); + if(p != null) { + mediaPlayer.playMediaObject(p, !p.localFileAvailable(), true, true); + } + } + + @Override + public void onPlayFromSearch (String query, Bundle extras) { + Log.d(TAG, "onPlayFromSearch query=" + query + " extras=" + extras.toString()); + + List<SearchResult> results = FeedSearcher.performSearch(getBaseContext(),query,0); + for( SearchResult result : results) { + try { + FeedMedia p = ((FeedItem)(result.getComponent())).getMedia(); + mediaPlayer.playMediaObject(p, !p.localFileAvailable(), true, true); + return; + } catch (Exception e) { + Log.d(TAG, e.getMessage()); + e.printStackTrace(); + continue; + } + } + onPlay(); + return; + } + + @Override public void onPause() { Log.d(TAG, "onPause()"); if (getStatus() == PlayerStatus.PLAYING) { - pause(false, true); - } - if (UserPreferences.isPersistNotify()) { - pause(false, true); - } else { - pause(true, true); + pause(!UserPreferences.isPersistNotify(), true); } } @Override public void onStop() { Log.d(TAG, "onStop()"); - mediaPlayer.stop(); + mediaPlayer.stopPlayback(true); } @Override @@ -1646,16 +1743,16 @@ public class PlaybackService extends Service { @Override public void onFastForward() { Log.d(TAG, "onFastForward()"); - seekDelta(UserPreferences.getFastFowardSecs() * 1000); + seekDelta(UserPreferences.getFastForwardSecs() * 1000); } @Override public void onSkipToNext() { Log.d(TAG, "onSkipToNext()"); if(UserPreferences.shouldHardwareButtonSkip()) { - mediaPlayer.endPlayback(true, false); + mediaPlayer.skip(); } else { - seekDelta(UserPreferences.getFastFowardSecs() * 1000); + seekDelta(UserPreferences.getFastForwardSecs() * 1000); } } @@ -1679,102 +1776,102 @@ public class PlaybackService extends Service { } return false; } - }; - private void onCastAppConnected(boolean wasLaunched) { - Log.d(TAG, "A cast device application was " + (wasLaunched ? "launched" : "joined")); - isCasting = true; - PlaybackServiceMediaPlayer.PSMPInfo info = null; - if (mediaPlayer != null) { - info = mediaPlayer.getPSMPInfo(); - if (info.playerStatus == PlayerStatus.PLAYING) { - // could be pause, but this way we make sure the new player will get the correct position, - // since pause runs asynchronously and we could be directing the new player to play even before - // the old player gives us back the position. - saveCurrentPosition(false, 0); + @Override + public void onCustomAction(String action, Bundle extra) { + Log.d(TAG, "onCustomAction(" + action + ")"); + if (CUSTOM_ACTION_FAST_FORWARD.equals(action)) { + onFastForward(); + } else if (CUSTOM_ACTION_REWIND.equals(action)) { + onRewind(); } } - if (info == null) { - info = new PlaybackServiceMediaPlayer.PSMPInfo(PlayerStatus.STOPPED, null); - } - sendNotificationBroadcast(NOTIFICATION_TYPE_RELOAD, EXTRA_CODE_CAST); - switchMediaPlayer(new RemotePSMP(PlaybackService.this, mediaPlayerCallback), - info, - wasLaunched); - // hardware volume buttons control the remote device volume - mediaRouter.setMediaSessionCompat(mediaSession); - registerWifiBroadcastReceiver(); - setupNotification(info); - } - - private void switchMediaPlayer(@NonNull PlaybackServiceMediaPlayer newPlayer, - @NonNull PlaybackServiceMediaPlayer.PSMPInfo info, - boolean wasLaunched) { - if (mediaPlayer != null) { - mediaPlayer.endPlayback(true, true); - mediaPlayer.shutdownQuietly(); - } - mediaPlayer = newPlayer; - Log.d(TAG, "switched to " + mediaPlayer.getClass().getSimpleName()); - if (!wasLaunched) { - PlaybackServiceMediaPlayer.PSMPInfo candidate = mediaPlayer.getPSMPInfo(); - if (candidate.playable != null && - candidate.playerStatus.isAtLeast(PlayerStatus.PREPARING)) { - // do not automatically send new media to cast device - info.playable = null; - } + }; + + private SharedPreferences.OnSharedPreferenceChangeListener prefListener = + (sharedPreferences, key) -> { + if (UserPreferences.PREF_LOCKSCREEN_BACKGROUND.equals(key)) { + updateMediaSessionMetadata(getPlayable()); + } else { + flavorHelper.onSharedPreference(key); + } + }; + + interface FlavorHelperCallback { + PlaybackServiceMediaPlayer.PSMPCallback getMediaPlayerCallback(); + void setMediaPlayer(PlaybackServiceMediaPlayer mediaPlayer); + PlaybackServiceMediaPlayer getMediaPlayer(); + void setIsCasting(boolean isCasting); + void sendNotificationBroadcast(int type, int code); + void saveCurrentPosition(boolean fromMediaPlayer, Playable playable, int position); + void setupNotification(boolean connected, PlaybackServiceMediaPlayer.PSMPInfo info); + MediaSessionCompat getMediaSession(); + Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter); + void unregisterReceiver(BroadcastReceiver receiver); + } + + private FlavorHelperCallback flavorHelperCallback = new FlavorHelperCallback() { + @Override + public PlaybackServiceMediaPlayer.PSMPCallback getMediaPlayerCallback() { + return PlaybackService.this.mediaPlayerCallback; } - if (info.playable != null) { - mediaPlayer.playMediaObject(info.playable, - !info.playable.localFileAvailable(), - info.playerStatus == PlayerStatus.PLAYING, - info.playerStatus.isAtLeast(PlayerStatus.PREPARING)); + + @Override + public void setMediaPlayer(PlaybackServiceMediaPlayer mediaPlayer) { + PlaybackService.this.mediaPlayer = mediaPlayer; } - } - private void registerWifiBroadcastReceiver() { - if (wifiBroadcastReceiver != null) { - return; + @Override + public PlaybackServiceMediaPlayer getMediaPlayer() { + return PlaybackService.this.mediaPlayer; } - wifiBroadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { - NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); - boolean isConnected = info.isConnected(); - //apparently this method gets called twice when a change happens, but one run is enough. - if (isConnected && !wifiConnectivity) { - wifiConnectivity = true; - castManager.startCastDiscovery(); - castManager.reconnectSessionIfPossible(RECONNECTION_ATTEMPT_PERIOD_S, NetworkUtils.getWifiSsid()); - } else { - wifiConnectivity = isConnected; - } + + @Override + public void setIsCasting(boolean isCasting) { + PlaybackService.isCasting = isCasting; + } + + @Override + public void sendNotificationBroadcast(int type, int code) { + PlaybackService.this.sendNotificationBroadcast(type, code); + } + + @Override + public void saveCurrentPosition(boolean fromMediaPlayer, Playable playable, int position) { + PlaybackService.this.saveCurrentPosition(fromMediaPlayer, playable, position); + } + + @Override + public void setupNotification(boolean connected, PlaybackServiceMediaPlayer.PSMPInfo info) { + if (connected) { + PlaybackService.this.setupNotification(info); + } else { + PlayerStatus status = info.playerStatus; + if ((status == PlayerStatus.PLAYING || + status == PlayerStatus.SEEKING || + status == PlayerStatus.PREPARING || + UserPreferences.isPersistNotify()) && + android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + PlaybackService.this.setupNotification(info); + } else if (!UserPreferences.isPersistNotify()){ + PlaybackService.this.stopForeground(true); } } - }; - registerReceiver(wifiBroadcastReceiver, - new IntentFilter(WifiManager.NETWORK_STATE_CHANGED_ACTION)); - } + } - private void unregisterWifiBroadcastReceiver() { - if (wifiBroadcastReceiver != null) { - unregisterReceiver(wifiBroadcastReceiver); - wifiBroadcastReceiver = null; + @Override + public MediaSessionCompat getMediaSession() { + return PlaybackService.this.mediaSession; } - } - private SharedPreferences.OnSharedPreferenceChangeListener prefListener = - (sharedPreferences, key) -> { - if (UserPreferences.PREF_CAST_ENABLED.equals(key)) { - if (!UserPreferences.isCastEnabled()) { - if (castManager.isConnecting() || castManager.isConnected()) { - Log.d(TAG, "Disconnecting cast device due to a change in user preferences"); - castManager.disconnect(); - } - } - } else if (UserPreferences.PREF_LOCKSCREEN_BACKGROUND.equals(key)) { - updateMediaSessionMetadata(getPlayable()); - } + @Override + public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { + return PlaybackService.this.registerReceiver(receiver, filter); + } + + @Override + public void unregisterReceiver(BroadcastReceiver receiver) { + PlaybackService.this.unregisterReceiver(receiver); + } }; } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java index 206eccb65..393019fd1 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java @@ -8,11 +8,9 @@ import android.util.Log; import android.util.Pair; import android.view.SurfaceHolder; -import de.danoeh.antennapod.core.feed.Chapter; -import de.danoeh.antennapod.core.feed.FeedItem; -import de.danoeh.antennapod.core.feed.FeedMedia; +import java.util.concurrent.Future; + import de.danoeh.antennapod.core.feed.MediaType; -import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.util.playback.Playable; @@ -31,9 +29,10 @@ public abstract class PlaybackServiceMediaPlayer { /** * Return value of some PSMP methods if the method call failed. */ - public static final int INVALID_TIME = -1; + static final int INVALID_TIME = -1; - protected volatile PlayerStatus playerStatus; + volatile PlayerStatus oldPlayerStatus; + volatile PlayerStatus playerStatus; /** * A wifi-lock that is acquired if the media file is being streamed. @@ -43,8 +42,8 @@ public abstract class PlaybackServiceMediaPlayer { protected final PSMPCallback callback; protected final Context context; - public PlaybackServiceMediaPlayer(@NonNull Context context, - @NonNull PSMPCallback callback){ + PlaybackServiceMediaPlayer(@NonNull Context context, + @NonNull PSMPCallback callback){ this.context = context; this.callback = callback; @@ -130,13 +129,6 @@ public abstract class PlaybackServiceMediaPlayer { public abstract void seekDelta(int d); /** - * Seek to the start of the specified chapter. - */ - public void seekToChapter(@NonNull Chapter c) { - seekTo((int) c.getStart()); - } - - /** * Returns the duration of the current media object or INVALID_TIME if the duration could not be retrieved. */ public abstract int getDuration(); @@ -213,7 +205,7 @@ public abstract class PlaybackServiceMediaPlayer { * @return The PSMPInfo object. */ public final synchronized PSMPInfo getPSMPInfo() { - return new PSMPInfo(playerStatus, getPlayable()); + return new PSMPInfo(oldPlayerStatus, playerStatus, getPlayable()); } /** @@ -236,22 +228,55 @@ public abstract class PlaybackServiceMediaPlayer { protected abstract void setPlayable(Playable playable); - public abstract void endPlayback(boolean wasSkipped, boolean switchingPlayers); + public void skip() { + endPlayback(false, true, true, true); + } + + /** + * Ends playback of current media (if any) and moves into INDETERMINATE state, unless + * {@param toStoppedState} is set to true, in which case it moves into STOPPED state. + * + * @see #endPlayback(boolean, boolean, boolean, boolean) + */ + public Future<?> stopPlayback(boolean toStoppedState) { + return endPlayback(false, false, false, toStoppedState); + } /** - * Moves the PSMP into STOPPED state. This call is only valid if the player is currently in - * INDETERMINATE state, for example after a call to endPlayback. - * This method will only take care of changing the PlayerStatus of this object! Other tasks like - * abandoning audio focus have to be done with other methods. + * Internal method that handles end of playback. + * + * Currently, it has 5 use cases: + * <ul> + * <li>Media playback has completed: call with (true, false, true, true)</li> + * <li>User asks to skip to next episode: call with (false, true, true, true)</li> + * <li>Skipping to next episode due to playback error: call with (false, false, true, true)</li> + * <li>Stopping the media player: call with (false, false, false, true)</li> + * <li>We want to change the media player implementation: call with (false, false, false, false)</li> + * </ul> + * + * @param hasEnded If true, we assume the current media's playback has ended, for + * purposes of post playback processing. + * @param wasSkipped Whether the user chose to skip the episode (by pressing the skip + * button). + * @param shouldContinue If true, the media player should try to load, and possibly play, + * the next item, based on the user preferences and whether such item + * exists. + * @param toStoppedState If true, the playback state gets set to STOPPED if the media player + * is not loading/playing after this call, and the UI will reflect that. + * Only relevant if {@param shouldContinue} is set to false, otherwise + * this method's behavior defaults as if this parameter was true. + * + * @return a Future, just for the purpose of tracking its execution. */ - public abstract void stop(); + protected abstract Future<?> endPlayback(boolean hasEnded, boolean wasSkipped, + boolean shouldContinue, boolean toStoppedState); /** * @return {@code true} if the WifiLock feature should be used, {@code false} otherwise. */ protected abstract boolean shouldLockWifi(); - protected final synchronized void acquireWifiLockIfNecessary() { + final synchronized void acquireWifiLockIfNecessary() { if (shouldLockWifi()) { if (wifiLock == null) { wifiLock = ((WifiManager) context.getSystemService(Context.WIFI_SERVICE)) @@ -262,7 +287,7 @@ public abstract class PlaybackServiceMediaPlayer { } } - protected final synchronized void releaseWifiLockIfNecessary() { + final synchronized void releaseWifiLockIfNecessary() { if (wifiLock != null && wifiLock.isHeld()) { wifiLock.release(); } @@ -274,41 +299,38 @@ public abstract class PlaybackServiceMediaPlayer { * <p/> * This method will notify the callback about the change of the player status (even if the new status is the same * as the old one). + * <p/> + * It will also call {@link PSMPCallback#onPlaybackPause(Playable, int)} or {@link PSMPCallback#onPlaybackStart(Playable, int)} + * depending on the status change. * * @param newStatus The new PlayerStatus. This must not be null. * @param newMedia The new playable object of the PSMP object. This can be null. + * @param position The position to be set to the current Playable object in case playback started or paused. + * Will be ignored if given the value of {@link #INVALID_TIME}. */ - protected synchronized final void setPlayerStatus(@NonNull PlayerStatus newStatus, Playable newMedia) { + final synchronized void setPlayerStatus(@NonNull PlayerStatus newStatus, Playable newMedia, int position) { Log.d(TAG, this.getClass().getSimpleName() + ": Setting player status to " + newStatus); + this.oldPlayerStatus = playerStatus; this.playerStatus = newStatus; setPlayable(newMedia); - if (playerStatus != null) { - Log.d(TAG, "playerStatus: " + playerStatus.toString()); + if (newMedia != null && newStatus != PlayerStatus.INDETERMINATE) { + if (oldPlayerStatus == PlayerStatus.PLAYING && newStatus != PlayerStatus.PLAYING) { + callback.onPlaybackPause(newMedia, position); + } else if (oldPlayerStatus != PlayerStatus.PLAYING && newStatus == PlayerStatus.PLAYING) { + callback.onPlaybackStart(newMedia, position); + } } - callback.statusChanged(new PSMPInfo(playerStatus, getPlayable())); + callback.statusChanged(new PSMPInfo(oldPlayerStatus, playerStatus, getPlayable())); } - protected void smartMarkAsPlayed(Playable media) { - if(media != null && media instanceof FeedMedia) { - FeedMedia oldMedia = (FeedMedia) media; - if(oldMedia.hasAlmostEnded()) { - Log.d(TAG, "smart mark as read"); - FeedItem item = oldMedia.getItem(); - if (item == null) { - return; - } - DBWriter.markItemPlayed(item, FeedItem.PLAYED, false); - DBWriter.removeQueueItem(context, item, false); - DBWriter.addItemToPlaybackHistory(oldMedia); - if (item.getFeed().getPreferences().getCurrentAutoDelete()) { - Log.d(TAG, "Delete " + oldMedia.toString()); - DBWriter.deleteFeedMediaOfItem(context, oldMedia.getId()); - } - } - } + /** + * @see #setPlayerStatus(PlayerStatus, Playable, int) + */ + final void setPlayerStatus(@NonNull PlayerStatus newStatus, Playable newMedia) { + setPlayerStatus(newStatus, newMedia, INVALID_TIME); } public interface PSMPCallback { @@ -328,17 +350,27 @@ public abstract class PlaybackServiceMediaPlayer { boolean onMediaPlayerError(Object inObj, int what, int extra); - boolean endPlayback(Playable media, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers); + void onPostPlayback(@NonNull Playable media, boolean ended, boolean skipped, boolean playingNext); + + void onPlaybackStart(@NonNull Playable playable, int position); + + void onPlaybackPause(Playable playable, int position); + + Playable getNextInQueue(Playable currentMedia); + + void onPlaybackEnded(MediaType mediaType, boolean stopPlaying); } /** * Holds information about a PSMP object. */ public static class PSMPInfo { + public PlayerStatus oldPlayerStatus; public PlayerStatus playerStatus; public Playable playable; - public PSMPInfo(PlayerStatus playerStatus, Playable playable) { + PSMPInfo(PlayerStatus oldPlayerStatus, PlayerStatus playerStatus, Playable playable) { + this.oldPlayerStatus = oldPlayerStatus; this.playerStatus = playerStatus; this.playable = playable; } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java index 8a0964d36..0c7d5e718 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java @@ -42,11 +42,11 @@ public class PlaybackServiceTaskManager { private static final int SCHED_EX_POOL_SIZE = 2; private final ScheduledThreadPoolExecutor schedExecutor; - private ScheduledFuture positionSaverFuture; - private ScheduledFuture widgetUpdaterFuture; - private ScheduledFuture sleepTimerFuture; + private ScheduledFuture<?> positionSaverFuture; + private ScheduledFuture<?> widgetUpdaterFuture; + private ScheduledFuture<?> sleepTimerFuture; private volatile Future<List<FeedItem>> queueFuture; - private volatile Future chapterLoaderFuture; + private volatile Future<?> chapterLoaderFuture; private SleepTimer sleepTimer; @@ -299,7 +299,8 @@ public class PlaybackServiceTaskManager { private static final String TAG = "SleepTimer"; private static final long UPDATE_INTERVAL = 1000L; private static final long NOTIFICATION_THRESHOLD = 10000; - private long waitingTime; + private final long waitingTime; + private long timeLeft; private final boolean shakeToReset; private final boolean vibrate; private ShakeListener shakeListener; @@ -307,6 +308,7 @@ public class PlaybackServiceTaskManager { public SleepTimer(long waitingTime, boolean shakeToReset, boolean vibrate) { super(); this.waitingTime = waitingTime; + this.timeLeft = waitingTime; this.shakeToReset = shakeToReset; this.vibrate = vibrate; } @@ -316,14 +318,14 @@ public class PlaybackServiceTaskManager { Log.d(TAG, "Starting"); boolean notifiedAlmostExpired = false; long lastTick = System.currentTimeMillis(); - while (waitingTime > 0) { + while (timeLeft > 0) { try { Thread.sleep(UPDATE_INTERVAL); long now = System.currentTimeMillis(); - waitingTime -= now - lastTick; + timeLeft -= now - lastTick; lastTick = now; - if(waitingTime < NOTIFICATION_THRESHOLD && !notifiedAlmostExpired) { + if(timeLeft < NOTIFICATION_THRESHOLD && !notifiedAlmostExpired) { Log.d(TAG, "Sleep timer is about to expire"); if(vibrate) { Vibrator v = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); @@ -337,7 +339,7 @@ public class PlaybackServiceTaskManager { callback.onSleepTimerAlmostExpired(); notifiedAlmostExpired = true; } - if (waitingTime <= 0) { + if (timeLeft <= 0) { Log.d(TAG, "Sleep timer expired"); if(shakeListener != null) { shakeListener.pause(); @@ -358,11 +360,11 @@ public class PlaybackServiceTaskManager { } public long getWaitingTime() { - return waitingTime; + return timeLeft; } public void onShake() { - setSleepTimer(15 * 60 * 1000, shakeToReset, vibrate); + setSleepTimer(waitingTime, shakeToReset, vibrate); callback.onSleepTimerReset(); shakeListener.pause(); shakeListener = null; diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index 869ec5f9d..a2ecd0a52 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -4,7 +4,6 @@ import android.database.Cursor; import android.support.v4.util.ArrayMap; import android.util.Log; -import java.util.Arrays; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -66,23 +65,28 @@ public final class DBReader { PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - List<Feed> result = getFeedList(adapter); - adapter.close(); - return result; + try { + return getFeedList(adapter); + } finally { + adapter.close(); + } } private static List<Feed> getFeedList(PodDBAdapter adapter) { - Cursor feedlistCursor = adapter.getAllFeedsCursor(); - List<Feed> feeds = new ArrayList<>(feedlistCursor.getCount()); - - if (feedlistCursor.moveToFirst()) { - do { - Feed feed = extractFeedFromCursorRow(adapter, feedlistCursor); + Cursor cursor = null; + try { + cursor = adapter.getAllFeedsCursor(); + List<Feed> feeds = new ArrayList<>(cursor.getCount()); + while (cursor.moveToNext()) { + Feed feed = extractFeedFromCursorRow(adapter, cursor); feeds.add(feed); - } while (feedlistCursor.moveToNext()); + } + return feeds; + } finally { + if (cursor != null) { + cursor.close(); + } } - feedlistCursor.close(); - return feeds; } /** @@ -92,23 +96,26 @@ public final class DBReader { */ public static List<String> getFeedListDownloadUrls() { PodDBAdapter adapter = PodDBAdapter.getInstance(); - List<String> result = new ArrayList<>(); adapter.open(); - Cursor feeds = adapter.getFeedCursorDownloadUrls(); - if (feeds.moveToFirst()) { - do { - result.add(feeds.getString(1)); - } while (feeds.moveToNext()); + Cursor cursor = null; + try { + cursor = adapter.getFeedCursorDownloadUrls(); + List<String> result = new ArrayList<>(cursor.getCount()); + while (cursor.moveToNext()) { + result.add(cursor.getString(1)); + } + return result; + } finally { + if (cursor != null) { + cursor.close(); + } + adapter.close(); } - feeds.close(); - adapter.close(); - - return result; } - /** * Loads additional data in to the feed items from other database queries + * * @param items the FeedItems who should have other data loaded */ public static void loadAdditionalFeedItemListData(List<FeedItem> items) { @@ -135,20 +142,21 @@ public final class DBReader { * The feedID-attribute of a FeedItem must be set to the ID of its feed or the method will * not find the correct feed of an item. * - * @param items The FeedItems whose Feed-objects should be loaded. + * @param items The FeedItems whose Feed-objects should be loaded. */ public static void loadFeedDataOfFeedItemList(List<FeedItem> items) { List<Feed> feeds = getFeedList(); + + Map<Long, Feed> feedIndex = new ArrayMap<>(feeds.size()); + for (Feed feed : feeds) { + feedIndex.put(feed.getId(), feed); + } for (FeedItem item : items) { - for (Feed feed : feeds) { - if (feed.getId() == item.getFeedId()) { - item.setFeed(feed); - break; - } - } - if (item.getFeed() == null) { + Feed feed = feedIndex.get(item.getFeedId()); + if (feed == null) { Log.w(TAG, "No match found for item with ID " + item.getId() + ". Feed ID was " + item.getFeedId()); } + item.setFeed(feed); } } @@ -156,7 +164,7 @@ public final class DBReader { * Loads the list of FeedItems for a certain Feed-object. This method should NOT be used if the FeedItems are not * used. In order to get information ABOUT the list of FeedItems, consider using {@link #getFeedStatisticsList()} instead. * - * @param feed The Feed whose items should be loaded + * @param feed The Feed whose items should be loaded * @return A list with the FeedItems of the Feed. The Feed-attribute of the FeedItems will already be set correctly. * The method does NOT change the items-attribute of the feed. */ @@ -165,33 +173,35 @@ public final class DBReader { PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - - Cursor itemlistCursor = adapter.getAllItemsOfFeedCursor(feed); - List<FeedItem> items = extractItemlistFromCursor(adapter, - itemlistCursor); - itemlistCursor.close(); - adapter.close(); - - Collections.sort(items, new FeedItemPubdateComparator()); - - for (FeedItem item : items) { - item.setFeed(feed); + Cursor cursor = null; + try { + cursor = adapter.getAllItemsOfFeedCursor(feed); + List<FeedItem> items = extractItemlistFromCursor(adapter, cursor); + Collections.sort(items, new FeedItemPubdateComparator()); + for (FeedItem item : items) { + item.setFeed(feed); + } + return items; + } finally { + if (cursor != null) { + cursor.close(); + } + adapter.close(); } - - return items; } public static List<FeedItem> extractItemlistFromCursor(Cursor itemlistCursor) { Log.d(TAG, "extractItemlistFromCursor() called with: " + "itemlistCursor = [" + itemlistCursor + "]"); PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - List<FeedItem> result = extractItemlistFromCursor(adapter, itemlistCursor); - adapter.close(); - return result; + try { + return extractItemlistFromCursor(adapter, itemlistCursor); + } finally { + adapter.close(); + } } - private static List<FeedItem> extractItemlistFromCursor(PodDBAdapter adapter, - Cursor cursor) { + private static List<FeedItem> extractItemlistFromCursor(PodDBAdapter adapter, Cursor cursor) { List<FeedItem> result = new ArrayList<>(cursor.getCount()); LongList imageIds = new LongList(cursor.getCount()); @@ -206,16 +216,16 @@ public final class DBReader { result.add(item); itemIds.add(item.getId()); } while (cursor.moveToNext()); - Map<Long,FeedImage> images = getFeedImages(adapter, imageIds.toArray()); - Map<Long,FeedMedia> medias = getFeedMedia(adapter, itemIds.toArray()); - for(int i=0; i < result.size(); i++) { + Map<Long, FeedImage> images = getFeedImages(adapter, imageIds.toArray()); + Map<Long, FeedMedia> medias = getFeedMedia(adapter, itemIds); + for (int i = 0; i < result.size(); i++) { FeedItem item = result.get(i); long imageId = imageIds.get(i); FeedImage image = images.get(imageId); item.setImage(image); FeedMedia media = medias.get(item.getId()); item.setMedia(media); - if(media != null) { + if (media != null) { media.setItem(item); } } @@ -223,15 +233,14 @@ public final class DBReader { return result; } - private static Map<Long,FeedMedia> getFeedMedia(PodDBAdapter adapter, - long... itemIds) { - - String[] ids = new String[itemIds.length]; - for(int i=0, len=itemIds.length; i < len; i++) { - ids[i] = String.valueOf(itemIds[i]); + private static Map<Long, FeedMedia> getFeedMedia(PodDBAdapter adapter, LongList itemIds) { + List<String> ids = new ArrayList<>(itemIds.size()); + for (long item : itemIds.toArray()) { + ids.add(String.valueOf(item)); } - Map<Long,FeedMedia> result = new ArrayMap<>(itemIds.length); - Cursor cursor = adapter.getFeedMediaCursor(ids); + + Map<Long, FeedMedia> result = new ArrayMap<>(itemIds.size()); + Cursor cursor = adapter.getFeedMediaCursor(ids.toArray(new String[0])); try { if (cursor.moveToFirst()) { do { @@ -247,8 +256,7 @@ public final class DBReader { return result; } - private static Feed extractFeedFromCursorRow(PodDBAdapter adapter, - Cursor cursor) { + private static Feed extractFeedFromCursorRow(PodDBAdapter adapter, Cursor cursor) { final FeedImage image; int indexImage = cursor.getColumnIndex(PodDBAdapter.KEY_IMAGE); long imageId = cursor.getLong(indexImage); @@ -272,11 +280,17 @@ public final class DBReader { static List<FeedItem> getQueue(PodDBAdapter adapter) { Log.d(TAG, "getQueue()"); - Cursor itemlistCursor = adapter.getQueueCursor(); - List<FeedItem> items = extractItemlistFromCursor(adapter, itemlistCursor); - itemlistCursor.close(); - loadAdditionalFeedItemListData(items); - return items; + Cursor cursor = null; + try { + cursor = adapter.getQueueCursor(); + List<FeedItem> items = extractItemlistFromCursor(adapter, cursor); + loadAdditionalFeedItemListData(items); + return items; + } finally { + if (cursor != null) { + cursor.close(); + } + } } /** @@ -290,22 +304,27 @@ public final class DBReader { Log.d(TAG, "getQueueIDList() called"); PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - LongList result = getQueueIDList(adapter); - adapter.close(); - return result; + try { + return getQueueIDList(adapter); + } finally { + adapter.close(); + } } - static LongList getQueueIDList(PodDBAdapter adapter) { - Cursor queueCursor = adapter.getQueueIDCursor(); - - LongList queueIds = new LongList(queueCursor.getCount()); - if (queueCursor.moveToFirst()) { - do { - queueIds.add(queueCursor.getLong(0)); - } while (queueCursor.moveToNext()); + private static LongList getQueueIDList(PodDBAdapter adapter) { + Cursor cursor = null; + try { + cursor = adapter.getQueueIDCursor(); + LongList queueIds = new LongList(cursor.getCount()); + while (cursor.moveToNext()) { + queueIds.add(cursor.getLong(0)); + } + return queueIds; + } finally { + if (cursor != null) { + cursor.close(); + } } - queueCursor.close(); - return queueIds; } /** @@ -316,13 +335,15 @@ public final class DBReader { * list in a {@link de.danoeh.antennapod.core.util.QueueAccess} object for easier access to the queue's properties. */ public static List<FeedItem> getQueue() { - Log.d(TAG, "getQueue() called with: " + ""); + Log.d(TAG, "getQueue() called"); PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - List<FeedItem> items = getQueue(adapter); - adapter.close(); - return items; + try { + return getQueue(adapter); + } finally { + adapter.close(); + } } /** @@ -331,48 +352,29 @@ public final class DBReader { * @return A list of FeedItems whose episdoe has been downloaded. */ public static List<FeedItem> getDownloadedItems() { - Log.d(TAG, "getDownloadedItems() called with: " + ""); - - PodDBAdapter adapter = PodDBAdapter.getInstance(); - adapter.open(); - - Cursor itemlistCursor = adapter.getDownloadedItemsCursor(); - List<FeedItem> items = extractItemlistFromCursor(adapter, - itemlistCursor); - itemlistCursor.close(); - loadAdditionalFeedItemListData(items); - adapter.close(); - - Collections.sort(items, new FeedItemPubdateComparator()); - - return items; - - } - - /** - * Loads a list of FeedItems whose 'read'-attribute is set to false. - * - * @return A list of FeedItems whose 'read'-attribute it set to false. - */ - public static List<FeedItem> getUnreadItemsList() { - Log.d(TAG, "getUnreadItemsList() called"); + Log.d(TAG, "getDownloadedItems() called"); PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - Cursor itemlistCursor = adapter.getUnreadItemsCursor(); - List<FeedItem> items = extractItemlistFromCursor(adapter, itemlistCursor); - itemlistCursor.close(); - - loadAdditionalFeedItemListData(items); - - adapter.close(); - - return items; + Cursor cursor = null; + try { + cursor = adapter.getDownloadedItemsCursor(); + List<FeedItem> items = extractItemlistFromCursor(adapter, cursor); + loadAdditionalFeedItemListData(items); + Collections.sort(items, new FeedItemPubdateComparator()); + return items; + } finally { + if (cursor != null) { + cursor.close(); + } + adapter.close(); + } } /** * Loads a list of FeedItems that are considered new. * Excludes items from feeds that do not have keep updated enabled. + * * @return A list of FeedItems that are considered new. */ public static List<FeedItem> getNewItemsList() { @@ -380,16 +382,18 @@ public final class DBReader { PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - - Cursor itemlistCursor = adapter.getNewItemsCursor(); - List<FeedItem> items = extractItemlistFromCursor(adapter, itemlistCursor); - itemlistCursor.close(); - - loadAdditionalFeedItemListData(items); - - adapter.close(); - - return items; + Cursor cursor = null; + try { + cursor = adapter.getNewItemsCursor(); + List<FeedItem> items = extractItemlistFromCursor(adapter, cursor); + loadAdditionalFeedItemListData(items); + return items; + } finally { + if (cursor != null) { + cursor.close(); + } + adapter.close(); + } } public static List<FeedItem> getFavoriteItemsList() { @@ -397,55 +401,63 @@ public final class DBReader { PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - - Cursor itemlistCursor = adapter.getFavoritesCursor(); - List<FeedItem> items = extractItemlistFromCursor(adapter, itemlistCursor); - itemlistCursor.close(); - - loadAdditionalFeedItemListData(items); - - adapter.close(); - - return items; + Cursor cursor = null; + try { + cursor = adapter.getFavoritesCursor(); + List<FeedItem> items = extractItemlistFromCursor(adapter, cursor); + loadAdditionalFeedItemListData(items); + return items; + } finally { + if (cursor != null) { + cursor.close(); + } + adapter.close(); + } } public static LongList getFavoriteIDList() { Log.d(TAG, "getFavoriteIDList() called"); + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - Cursor favoritesCursor = adapter.getFavoritesCursor(); - - LongList favoriteIDs = new LongList(favoritesCursor.getCount()); - if (favoritesCursor.moveToFirst()) { - do { - favoriteIDs.add(favoritesCursor.getLong(0)); - } while (favoritesCursor.moveToNext()); + Cursor cursor = null; + try { + cursor = adapter.getFavoritesCursor(); + LongList favoriteIDs = new LongList(cursor.getCount()); + while (cursor.moveToNext()) { + favoriteIDs.add(cursor.getLong(0)); + } + return favoriteIDs; + } finally { + if (cursor != null) { + cursor.close(); + } + adapter.close(); } - favoritesCursor.close(); - adapter.close(); - return favoriteIDs; } /** * Loads a list of FeedItems sorted by pubDate in descending order. * - * @param limit The maximum number of episodes that should be loaded. + * @param limit The maximum number of episodes that should be loaded. */ public static List<FeedItem> getRecentlyPublishedEpisodes(int limit) { Log.d(TAG, "getRecentlyPublishedEpisodes() called with: " + "limit = [" + limit + "]"); PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - - Cursor itemlistCursor = adapter.getRecentlyPublishedItemsCursor(limit); - List<FeedItem> items = extractItemlistFromCursor(adapter, itemlistCursor); - itemlistCursor.close(); - - loadAdditionalFeedItemListData(items); - - adapter.close(); - - return items; + Cursor cursor = null; + try { + cursor = adapter.getRecentlyPublishedItemsCursor(limit); + List<FeedItem> items = extractItemlistFromCursor(adapter, cursor); + loadAdditionalFeedItemListData(items); + return items; + } finally { + if (cursor != null) { + cursor.close(); + } + adapter.close(); + } } /** @@ -461,21 +473,29 @@ public final class DBReader { PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - Cursor mediaCursor = adapter.getCompletedMediaCursor(PLAYBACK_HISTORY_SIZE); - String[] itemIds = new String[mediaCursor.getCount()]; - for (int i = 0; i < itemIds.length && mediaCursor.moveToPosition(i); i++) { - int index = mediaCursor.getColumnIndex(PodDBAdapter.KEY_FEEDITEM); - itemIds[i] = Long.toString(mediaCursor.getLong(index)); + Cursor mediaCursor = null; + Cursor itemCursor = null; + try { + mediaCursor = adapter.getCompletedMediaCursor(PLAYBACK_HISTORY_SIZE); + String[] itemIds = new String[mediaCursor.getCount()]; + for (int i = 0; i < itemIds.length && mediaCursor.moveToPosition(i); i++) { + int index = mediaCursor.getColumnIndex(PodDBAdapter.KEY_FEEDITEM); + itemIds[i] = Long.toString(mediaCursor.getLong(index)); + } + itemCursor = adapter.getFeedItemCursor(itemIds); + List<FeedItem> items = extractItemlistFromCursor(adapter, itemCursor); + loadAdditionalFeedItemListData(items); + Collections.sort(items, new PlaybackCompletionDateComparator()); + return items; + } finally { + if (mediaCursor != null) { + mediaCursor.close(); + } + if (itemCursor != null) { + itemCursor.close(); + } + adapter.close(); } - mediaCursor.close(); - Cursor itemCursor = adapter.getFeedItemCursor(itemIds); - List<FeedItem> items = extractItemlistFromCursor(adapter, itemCursor); - loadAdditionalFeedItemListData(items); - itemCursor.close(); - adapter.close(); - - Collections.sort(items, new PlaybackCompletionDateComparator()); - return items; } /** @@ -489,19 +509,21 @@ public final class DBReader { PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - Cursor logCursor = adapter.getDownloadLogCursor(DOWNLOAD_LOG_SIZE); - List<DownloadStatus> downloadLog = new ArrayList<>(logCursor.getCount()); - - if (logCursor.moveToFirst()) { - do { - DownloadStatus status = DownloadStatus.fromCursor(logCursor); - downloadLog.add(status); - } while (logCursor.moveToNext()); + Cursor cursor = null; + try { + cursor = adapter.getDownloadLogCursor(DOWNLOAD_LOG_SIZE); + List<DownloadStatus> downloadLog = new ArrayList<>(cursor.getCount()); + while (cursor.moveToNext()) { + downloadLog.add(DownloadStatus.fromCursor(cursor)); + } + Collections.sort(downloadLog, new DownloadStatusComparator()); + return downloadLog; + } finally { + if (cursor != null) { + cursor.close(); + } + adapter.close(); } - logCursor.close(); - adapter.close(); - Collections.sort(downloadLog, new DownloadStatusComparator()); - return downloadLog; } /** @@ -509,26 +531,28 @@ public final class DBReader { * * @param feed Feed for which the download log is loaded * @return A list with DownloadStatus objects that represent the feed's download log, - * newest events first. + * newest events first. */ public static List<DownloadStatus> getFeedDownloadLog(Feed feed) { Log.d(TAG, "getFeedDownloadLog() called with: " + "feed = [" + feed + "]"); PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - Cursor cursor = adapter.getDownloadLog(Feed.FEEDFILETYPE_FEED, feed.getId()); - List<DownloadStatus> downloadLog = new ArrayList<>(cursor.getCount()); - - if (cursor.moveToFirst()) { - do { - DownloadStatus status = DownloadStatus.fromCursor(cursor); - downloadLog.add(status); - } while (cursor.moveToNext()); + Cursor cursor = null; + try { + cursor = adapter.getDownloadLog(Feed.FEEDFILETYPE_FEED, feed.getId()); + List<DownloadStatus> downloadLog = new ArrayList<>(cursor.getCount()); + while (cursor.moveToNext()) { + downloadLog.add(DownloadStatus.fromCursor(cursor)); + } + Collections.sort(downloadLog, new DownloadStatusComparator()); + return downloadLog; + } finally { + if (cursor != null) { + cursor.close(); + } + adapter.close(); } - cursor.close(); - adapter.close(); - Collections.sort(downloadLog, new DownloadStatusComparator()); - return downloadLog; } /** @@ -542,103 +566,91 @@ public final class DBReader { Log.d(TAG, "getFeedStatisticsList() called"); PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - List<FeedItemStatistics> result = new ArrayList<>(); - Cursor cursor = adapter.getFeedStatisticsCursor(); - if (cursor.moveToFirst()) { - do { + Cursor cursor = null; + try { + cursor = adapter.getFeedStatisticsCursor(); + List<FeedItemStatistics> result = new ArrayList<>(cursor.getCount()); + while (cursor.moveToNext()) { FeedItemStatistics fis = FeedItemStatistics.fromCursor(cursor); result.add(fis); - } while (cursor.moveToNext()); + } + return result; + } finally { + if (cursor != null) { + cursor.close(); + } + adapter.close(); } - - cursor.close(); - adapter.close(); - return result; } /** * Loads a specific Feed from the database. * - * @param feedId The ID of the Feed + * @param feedId The ID of the Feed * @return The Feed or null if the Feed could not be found. The Feeds FeedItems will also be loaded from the * database and the items-attribute will be set correctly. */ public static Feed getFeed(final long feedId) { Log.d(TAG, "getFeed() called with: " + "feedId = [" + feedId + "]"); + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - Feed result = getFeed(feedId, adapter); - adapter.close(); - return result; + try { + return getFeed(feedId, adapter); + } finally { + adapter.close(); + } } static Feed getFeed(final long feedId, PodDBAdapter adapter) { Feed feed = null; - - Cursor feedCursor = adapter.getFeedCursor(feedId); - if (feedCursor.moveToFirst()) { - feed = extractFeedFromCursorRow(adapter, feedCursor); - feed.setItems(getFeedItemList(feed)); - } else { - Log.e(TAG, "getFeed could not find feed with id " + feedId); - } - feedCursor.close(); - return feed; - } - - static FeedItem getFeedItem(final long itemId, PodDBAdapter adapter) { - Log.d(TAG, "Loading feeditem with id " + itemId); - FeedItem item = null; - - Cursor itemCursor = adapter.getFeedItemCursor(Long.toString(itemId)); - if (!itemCursor.moveToFirst()) { - itemCursor.close(); - return null; - } - List<FeedItem> list = extractItemlistFromCursor(adapter, itemCursor); - itemCursor.close(); - if (list.size() > 0) { - item = list.get(0); - loadAdditionalFeedItemListData(list); - if (item.hasChapters()) { - loadChaptersOfFeedItem(adapter, item); + Cursor cursor = null; + try { + cursor = adapter.getFeedCursor(feedId); + if (cursor.moveToNext()) { + feed = extractFeedFromCursorRow(adapter, cursor); + feed.setItems(getFeedItemList(feed)); + } else { + Log.e(TAG, "getFeed could not find feed with id " + feedId); + } + return feed; + } finally { + if (cursor != null) { + cursor.close(); } } - return item; } - static List<FeedItem> getFeedItems(PodDBAdapter adapter, final long... itemIds) { - - String[] ids = new String[itemIds.length]; - for(int i = 0; i < itemIds.length; i++) { - long itemId = itemIds[i]; - ids[i] = Long.toString(itemId); - } - - List<FeedItem> result; + private static FeedItem getFeedItem(final long itemId, PodDBAdapter adapter) { + Log.d(TAG, "Loading feeditem with id " + itemId); - Cursor itemCursor = adapter.getFeedItemCursor(ids); - if (itemCursor.moveToFirst()) { - result = extractItemlistFromCursor(adapter, itemCursor); - loadAdditionalFeedItemListData(result); - for(FeedItem item : result) { - if (item.hasChapters()) { - loadChaptersOfFeedItem(adapter, item); + FeedItem item = null; + Cursor cursor = null; + try { + cursor = adapter.getFeedItemCursor(Long.toString(itemId)); + if (cursor.moveToNext()) { + List<FeedItem> list = extractItemlistFromCursor(adapter, cursor); + if (!list.isEmpty()) { + item = list.get(0); + loadAdditionalFeedItemListData(list); + if (item.hasChapters()) { + loadChaptersOfFeedItem(adapter, item); + } } } - } else { - result = Collections.emptyList(); + return item; + } finally { + if (cursor != null) { + cursor.close(); + } } - itemCursor.close(); - return result; - } /** * Loads a specific FeedItem from the database. This method should not be used for loading more * than one FeedItem because this method might query the database several times for each item. * - * @param itemId The ID of the FeedItem + * @param itemId The ID of the FeedItem * @return The FeedItem or null if the FeedItem could not be found. All FeedComponent-attributes * as well as chapter marks of the FeedItem will also be loaded from the database. */ @@ -647,51 +659,42 @@ public final class DBReader { PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - FeedItem item = getFeedItem(itemId, adapter); - adapter.close(); - return item; + try { + return getFeedItem(itemId, adapter); + } finally { + adapter.close(); + } } static FeedItem getFeedItem(final String podcastUrl, final String episodeUrl, PodDBAdapter adapter) { Log.d(TAG, "Loading feeditem with podcast url " + podcastUrl + " and episode url " + episodeUrl); - FeedItem item = null; - Cursor itemCursor = adapter.getFeedItemCursor(podcastUrl, episodeUrl); - if (itemCursor.moveToFirst()) { - List<FeedItem> list = extractItemlistFromCursor(adapter, itemCursor); - if (list.size() > 0) { + Cursor cursor = null; + try { + cursor = adapter.getFeedItemCursor(podcastUrl, episodeUrl); + if (!cursor.moveToNext()) { + return null; + } + List<FeedItem> list = extractItemlistFromCursor(adapter, cursor); + FeedItem item = null; + if (!list.isEmpty()) { item = list.get(0); loadAdditionalFeedItemListData(list); if (item.hasChapters()) { loadChaptersOfFeedItem(adapter, item); } } + return item; + } finally { + if (cursor != null) { + cursor.close(); + } } - itemCursor.close(); - return item; } /** - * Loads specific FeedItems from the database. This method canbe used for loading more - * than one FeedItem - * - * @param itemIds The IDs of the FeedItems - * @return The FeedItems or an empty list if none of the FeedItems could be found. All FeedComponent-attributes - * as well as chapter marks of the FeedItems will also be loaded from the database. - */ - public static List<FeedItem> getFeedItems(final long... itemIds) { - Log.d(TAG, "getFeedItems() called with: " + "itemIds = [" + Arrays.toString(itemIds) + "]"); - PodDBAdapter adapter = PodDBAdapter.getInstance(); - adapter.open(); - List<FeedItem> items = getFeedItems(adapter, itemIds); - adapter.close(); - return items; - } - - - /** * Returns credentials based on image URL * - * @param imageUrl The URL of the image + * @param imageUrl The URL of the image * @return Credentials in format "<Username>:<Password>", empty String if no authorization given */ public static String getImageAuthentication(final String imageUrl) { @@ -699,20 +702,22 @@ public final class DBReader { PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - String credentials = getImageAuthentication(imageUrl, adapter); - adapter.close(); - return credentials; - + try { + return getImageAuthentication(imageUrl, adapter); + } finally { + adapter.close(); + } } - static String getImageAuthentication(final String imageUrl, PodDBAdapter adapter) { + private static String getImageAuthentication(final String imageUrl, PodDBAdapter adapter) { String credentials = null; - Cursor cursor = adapter.getImageAuthenticationCursor(imageUrl); + Cursor cursor = null; try { + cursor = adapter.getImageAuthenticationCursor(imageUrl); if (cursor.moveToFirst()) { String username = cursor.getString(0); String password = cursor.getString(1); - if(username != null && password != null) { + if (username != null && password != null) { credentials = username + ":" + password; } else { credentials = ""; @@ -721,7 +726,9 @@ public final class DBReader { credentials = ""; } } finally { - cursor.close(); + if (cursor != null) { + cursor.close(); + } } return credentials; } @@ -739,31 +746,39 @@ public final class DBReader { PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - FeedItem item = getFeedItem(podcastUrl, episodeUrl, adapter); - adapter.close(); - return item; + try { + return getFeedItem(podcastUrl, episodeUrl, adapter); + } finally { + adapter.close(); + } } /** * Loads additional information about a FeedItem, e.g. shownotes * - * @param item The FeedItem + * @param item The FeedItem */ public static void loadExtraInformationOfFeedItem(final FeedItem item) { Log.d(TAG, "loadExtraInformationOfFeedItem() called with: " + "item = [" + item + "]"); PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - Cursor extraCursor = adapter.getExtraInformationOfItem(item); - if (extraCursor.moveToFirst()) { - int indexDescription = extraCursor.getColumnIndex(PodDBAdapter.KEY_DESCRIPTION); - String description = extraCursor.getString(indexDescription); - int indexContentEncoded = extraCursor.getColumnIndex(PodDBAdapter.KEY_CONTENT_ENCODED); - String contentEncoded = extraCursor.getString(indexContentEncoded); - item.setDescription(description); - item.setContentEncoded(contentEncoded); + Cursor cursor = null; + try { + cursor = adapter.getExtraInformationOfItem(item); + if (cursor.moveToFirst()) { + int indexDescription = cursor.getColumnIndex(PodDBAdapter.KEY_DESCRIPTION); + String description = cursor.getString(indexDescription); + int indexContentEncoded = cursor.getColumnIndex(PodDBAdapter.KEY_CONTENT_ENCODED); + String contentEncoded = cursor.getString(indexContentEncoded); + item.setDescription(description); + item.setContentEncoded(contentEncoded); + } + } finally { + if (cursor != null) { + cursor.close(); + } + adapter.close(); } - extraCursor.close(); - adapter.close(); } /** @@ -771,56 +786,64 @@ public final class DBReader { * any chapters that this FeedItem has. If no chapters were found in the database, the chapters * reference of the FeedItem will be set to null. * - * @param item The FeedItem + * @param item The FeedItem */ public static void loadChaptersOfFeedItem(final FeedItem item) { Log.d(TAG, "loadChaptersOfFeedItem() called with: " + "item = [" + item + "]"); + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - loadChaptersOfFeedItem(adapter, item); - adapter.close(); + try { + loadChaptersOfFeedItem(adapter, item); + } finally { + adapter.close(); + } } static void loadChaptersOfFeedItem(PodDBAdapter adapter, FeedItem item) { - Cursor chapterCursor = adapter.getSimpleChaptersOfFeedItemCursor(item); - if (chapterCursor.moveToFirst()) { - item.setChapters(new ArrayList<>()); - do { - int indexType = chapterCursor.getColumnIndex(PodDBAdapter.KEY_CHAPTER_TYPE); - int indexStart = chapterCursor.getColumnIndex(PodDBAdapter.KEY_START); - int indexTitle = chapterCursor.getColumnIndex(PodDBAdapter.KEY_TITLE); - int indexLink = chapterCursor.getColumnIndex(PodDBAdapter.KEY_LINK); - - int chapterType = chapterCursor.getInt(indexType); + Cursor cursor = null; + try { + cursor = adapter.getSimpleChaptersOfFeedItemCursor(item); + int chaptersCount = cursor.getCount(); + if (chaptersCount == 0) { + item.setChapters(null); + return; + } + item.setChapters(new ArrayList<>(chaptersCount)); + while (cursor.moveToNext()) { + int indexType = cursor.getColumnIndex(PodDBAdapter.KEY_CHAPTER_TYPE); + int indexStart = cursor.getColumnIndex(PodDBAdapter.KEY_START); + int indexTitle = cursor.getColumnIndex(PodDBAdapter.KEY_TITLE); + int indexLink = cursor.getColumnIndex(PodDBAdapter.KEY_LINK); + + int chapterType = cursor.getInt(indexType); Chapter chapter = null; - long start = chapterCursor.getLong(indexStart); - String title = chapterCursor.getString(indexTitle); - String link = chapterCursor.getString(indexLink); + long start = cursor.getLong(indexStart); + String title = cursor.getString(indexTitle); + String link = cursor.getString(indexLink); switch (chapterType) { case SimpleChapter.CHAPTERTYPE_SIMPLECHAPTER: - chapter = new SimpleChapter(start, title, item, - link); + chapter = new SimpleChapter(start, title, item, link); break; case ID3Chapter.CHAPTERTYPE_ID3CHAPTER: - chapter = new ID3Chapter(start, title, item, - link); + chapter = new ID3Chapter(start, title, item, link); break; case VorbisCommentChapter.CHAPTERTYPE_VORBISCOMMENT_CHAPTER: - chapter = new VorbisCommentChapter(start, - title, item, link); + chapter = new VorbisCommentChapter(start, title, item, link); break; } if (chapter != null) { - int indexId = chapterCursor.getColumnIndex(PodDBAdapter.KEY_ID); - chapter.setId(chapterCursor.getLong(indexId)); + int indexId = cursor.getColumnIndex(PodDBAdapter.KEY_ID); + chapter.setId(cursor.getLong(indexId)); item.getChapters().add(chapter); } - } while (chapterCursor.moveToNext()); - } else { - item.setChapters(null); + } + } finally { + if (cursor != null) { + cursor.close(); + } } - chapterCursor.close(); } /** @@ -828,13 +851,17 @@ public final class DBReader { * * @return The number of downloaded episodes. */ + public static int getNumberOfDownloadedEpisodes() { Log.d(TAG, "getNumberOfDownloadedEpisodes() called with: " + ""); + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - final int result = adapter.getNumberOfDownloadedEpisodes(); - adapter.close(); - return result; + try { + return adapter.getNumberOfDownloadedEpisodes(); + } finally { + adapter.close(); + } } /** @@ -847,9 +874,11 @@ public final class DBReader { Log.d(TAG, "getFeedImage() called with: " + "imageId = [" + imageId + "]"); PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - FeedImage result = getFeedImage(adapter, imageId); - adapter.close(); - return result; + try { + return getFeedImage(adapter, imageId); + } finally { + adapter.close(); + } } /** @@ -868,21 +897,23 @@ public final class DBReader { * @param imageIds The ids of the images * @return Map that associates the id of an image with the image itself */ - private static Map<Long,FeedImage> getFeedImages(PodDBAdapter adapter, final long... imageIds) { + private static Map<Long, FeedImage> getFeedImages(PodDBAdapter adapter, final long... imageIds) { String[] ids = new String[imageIds.length]; - for(int i=0, len=imageIds.length; i < len; i++) { + for (int i = 0, len = imageIds.length; i < len; i++) { ids[i] = String.valueOf(imageIds[i]); } Cursor cursor = adapter.getImageCursor(ids); - Map<Long, FeedImage> result = new ArrayMap<>(cursor.getCount()); + int imageCount = cursor.getCount(); + if (imageCount == 0) { + cursor.close(); + return Collections.emptyMap(); + } + Map<Long, FeedImage> result = new ArrayMap<>(imageCount); try { - if ((cursor.getCount() == 0) || !cursor.moveToFirst()) { - return Collections.emptyMap(); - } - do { + while (cursor.moveToNext()) { FeedImage image = FeedImage.fromCursor(cursor); result.put(image.getId(), image); - } while(cursor.moveToNext()); + } } finally { cursor.close(); } @@ -899,88 +930,137 @@ public final class DBReader { PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - Cursor mediaCursor = adapter.getSingleFeedMediaCursor(mediaId); - - if (!mediaCursor.moveToFirst()) { - mediaCursor.close(); - return null; - } + Cursor mediaCursor = null; + try { + mediaCursor = adapter.getSingleFeedMediaCursor(mediaId); + if (!mediaCursor.moveToFirst()) { + return null; + } - int indexFeedItem = mediaCursor.getColumnIndex(PodDBAdapter.KEY_FEEDITEM); - long itemId = mediaCursor.getLong(indexFeedItem); - FeedMedia media = FeedMedia.fromCursor(mediaCursor); - mediaCursor.close(); + int indexFeedItem = mediaCursor.getColumnIndex(PodDBAdapter.KEY_FEEDITEM); + long itemId = mediaCursor.getLong(indexFeedItem); + FeedMedia media = FeedMedia.fromCursor(mediaCursor); + if (media != null) { + FeedItem item = getFeedItem(itemId); + if (item != null) { + media.setItem(item); + item.setMedia(media); + } + } + return media; - if(media != null) { - FeedItem item = getFeedItem(itemId); - if (item != null) { - media.setItem(item); - item.setMedia(media); + } finally { + if (mediaCursor != null) { + mediaCursor.close(); } + adapter.close(); } - - adapter.close(); - - return media; } /** * Searches the DB for statistics * + * @param sortByCountAll If true, the statistic items will be sorted according to the + * countAll calculation time * @return The StatisticsInfo object */ - public static StatisticsData getStatistics() { + public static StatisticsData getStatistics(boolean sortByCountAll) { PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); + long totalTimeCountAll = 0; long totalTime = 0; List<StatisticsItem> feedTime = new ArrayList<>(); List<Feed> feeds = getFeedList(); for (Feed feed : feeds) { + long feedPlayedTimeCountAll = 0; long feedPlayedTime = 0; long feedTotalTime = 0; long episodes = 0; long episodesStarted = 0; + long episodesStartedIncludingMarked = 0; List<FeedItem> items = getFeed(feed.getId()).getItems(); - for(FeedItem item : items) { + for (FeedItem item : items) { FeedMedia media = item.getMedia(); - if(media == null) { + if (media == null) { continue; } + // played duration used to be reset when the item is added to the playback history + if (media.getPlaybackCompletionDate() != null) { + feedPlayedTime += media.getDuration() / 1000; + } feedPlayedTime += media.getPlayedDuration() / 1000; - if(media.getPlayedDuration() > 0) { + + if (item.isPlayed()) { + feedPlayedTimeCountAll += media.getDuration() / 1000; + } else { + feedPlayedTimeCountAll += media.getPosition() / 1000; + } + + if (media.getPlaybackCompletionDate() != null || media.getPlayedDuration() > 0) { episodesStarted++; } + + if (item.isPlayed() || media.getPosition() != 0) { + episodesStartedIncludingMarked++; + } + feedTotalTime += media.getDuration() / 1000; episodes++; } feedTime.add(new StatisticsItem( - feed, feedTotalTime, feedPlayedTime, episodes, episodesStarted)); + feed, feedTotalTime, feedPlayedTime, feedPlayedTimeCountAll, episodes, + episodesStarted, episodesStartedIncludingMarked)); totalTime += feedPlayedTime; + totalTimeCountAll += feedPlayedTimeCountAll; } - Collections.sort(feedTime, (item1, item2) -> { - if(item1.timePlayed > item2.timePlayed) { - return -1; - } else if(item1.timePlayed < item2.timePlayed) { - return 1; - } else { - return 0; - } - }); + if (sortByCountAll) { + Collections.sort(feedTime, (item1, item2) -> + compareLong(item1.timePlayedCountAll, item2.timePlayedCountAll)); + } else { + Collections.sort(feedTime, (item1, item2) -> + compareLong(item1.timePlayed, item2.timePlayed)); + } adapter.close(); - return new StatisticsData(totalTime, feedTime); + return new StatisticsData(totalTime, totalTimeCountAll, feedTime); + } + + /** + * Compares two {@code long} values. Long.compare() is not available before API 19 + * + * @return 0 if long1 = long2, less than 0 if long1 < long2, + * and greater than 0 if long1 > long2. + */ + private static int compareLong(long long1, long long2) { + if (long1 > long2) { + return -1; + } else if (long1 < long2) { + return 1; + } else { + return 0; + } } public static class StatisticsData { + /** + * Simply sums up time of podcasts that are marked as played + */ + public long totalTimeCountAll; + + /** + * Respects speed, listening twice, ... + */ public long totalTime; + public List<StatisticsItem> feedTime; - public StatisticsData(long totalTime, List<StatisticsItem> feedTime) { + public StatisticsData(long totalTime, long totalTimeCountAll, List<StatisticsItem> feedTime) { this.totalTime = totalTime; + this.totalTimeCountAll = totalTimeCountAll; this.feedTime = feedTime; } } @@ -988,17 +1068,34 @@ public final class DBReader { public static class StatisticsItem { public Feed feed; public long time; + + /** + * Respects speed, listening twice, ... + */ public long timePlayed; + /** + * Simply sums up time of podcasts that are marked as played + */ + public long timePlayedCountAll; public long episodes; + /** + * Episodes that are actually played + */ public long episodesStarted; + /** + * All episodes that are marked as played (or have position != 0) + */ + public long episodesStartedIncludingMarked; - public StatisticsItem(Feed feed, long time, long timePlayed, - long episodes, long episodesStarted) { + public StatisticsItem(Feed feed, long time, long timePlayed, long timePlayedCountAll, + long episodes, long episodesStarted, long episodesStartedIncludingMarked) { this.feed = feed; this.time = time; this.timePlayed = timePlayed; + this.timePlayedCountAll = timePlayedCountAll; this.episodes = episodes; this.episodesStarted = episodesStarted; + this.episodesStartedIncludingMarked = episodesStartedIncludingMarked; } } @@ -1036,7 +1133,6 @@ public final class DBReader { * Returns data necessary for displaying the navigation drawer. This includes * the list of subscriptions, the number of items in the queue and the number of unread * items. - * */ public static NavDrawerData getNavDrawerData() { Log.d(TAG, "getNavDrawerData() called with: " + ""); @@ -1044,51 +1140,66 @@ public final class DBReader { adapter.open(); List<Feed> feeds = getFeedList(adapter); long[] feedIds = new long[feeds.size()]; - for(int i=0; i < feeds.size(); i++) { + for (int i = 0; i < feeds.size(); i++) { feedIds[i] = feeds.get(i).getId(); } final LongIntMap feedCounters = adapter.getFeedCounters(feedIds); Comparator<Feed> comparator; int feedOrder = UserPreferences.getFeedOrder(); - if(feedOrder == UserPreferences.FEED_ORDER_COUNTER) { + if (feedOrder == UserPreferences.FEED_ORDER_COUNTER) { comparator = (lhs, rhs) -> { long counterLhs = feedCounters.get(lhs.getId()); long counterRhs = feedCounters.get(rhs.getId()); - if(counterLhs > counterRhs) { + if (counterLhs > counterRhs) { // reverse natural order: podcast with most unplayed episodes first return -1; - } else if(counterLhs == counterRhs) { - return lhs.getTitle().compareTo(rhs.getTitle()); + } else if (counterLhs == counterRhs) { + return lhs.getTitle().compareToIgnoreCase(rhs.getTitle()); } else { return 1; } }; - } else if(feedOrder == UserPreferences.FEED_ORDER_ALPHABETICAL) { + } else if (feedOrder == UserPreferences.FEED_ORDER_ALPHABETICAL) { comparator = (lhs, rhs) -> { String t1 = lhs.getTitle(); String t2 = rhs.getTitle(); - if(t1 == null) { + if (t1 == null) { return 1; - } else if(t2 == null) { + } else if (t2 == null) { return -1; } else { - return t1.toLowerCase().compareTo(t2.toLowerCase()); + return t1.compareToIgnoreCase(t2); + } + }; + } else if (feedOrder == UserPreferences.FEED_ORDER_MOST_PLAYED) { + final LongIntMap playedCounters = adapter.getPlayedEpisodesCounters(feedIds); + + comparator = (lhs, rhs) -> { + long counterLhs = playedCounters.get(lhs.getId()); + long counterRhs = playedCounters.get(rhs.getId()); + if (counterLhs > counterRhs) { + // podcast with most played episodes first + return -1; + } else if (counterLhs == counterRhs) { + return lhs.getTitle().compareToIgnoreCase(rhs.getTitle()); + } else { + return 1; } }; } else { comparator = (lhs, rhs) -> { - if(lhs.getItems() == null || lhs.getItems().size() == 0) { + if (lhs.getItems() == null || lhs.getItems().size() == 0) { List<FeedItem> items = DBReader.getFeedItemList(lhs); lhs.setItems(items); } - if(rhs.getItems() == null || rhs.getItems().size() == 0) { + if (rhs.getItems() == null || rhs.getItems().size() == 0) { List<FeedItem> items = DBReader.getFeedItemList(rhs); rhs.setItems(items); } - if(lhs.getMostRecentItem() == null) { + if (lhs.getMostRecentItem() == null) { return 1; - } else if(rhs.getMostRecentItem() == null) { + } else if (rhs.getMostRecentItem() == null) { return -1; } else { Date d1 = lhs.getMostRecentItem().getPubDate(); diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java index 75bbd4adc..148b530a7 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java @@ -2,6 +2,7 @@ package de.danoeh.antennapod.core.storage; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.database.Cursor; import android.util.Log; @@ -16,7 +17,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; -import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import de.danoeh.antennapod.core.ClientConfig; @@ -27,21 +28,29 @@ import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.FeedPreferences; +import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.GpodnetSyncService; import de.danoeh.antennapod.core.service.download.DownloadStatus; import de.danoeh.antennapod.core.service.playback.PlaybackService; +import de.danoeh.antennapod.core.util.Converter; import de.danoeh.antennapod.core.util.DownloadError; import de.danoeh.antennapod.core.util.LongList; import de.danoeh.antennapod.core.util.comparator.FeedItemPubdateComparator; import de.danoeh.antennapod.core.util.exception.MediaFileNotFoundException; import de.danoeh.antennapod.core.util.flattr.FlattrUtils; +import static android.content.Context.MODE_PRIVATE; +import static android.provider.Contacts.SettingsColumns.KEY; + /** * Provides methods for doing common tasks that use DBReader and DBWriter. */ public final class DBTasks { private static final String TAG = "DBTasks"; + public static final String PREF_NAME = "dbtasks"; + private static final String PREF_LAST_REFRESH = "last_refresh"; + /** * Executor service used by the autodownloadUndownloadedEpisodes method. */ @@ -162,6 +171,9 @@ public final class DBTasks { } isRefreshing.set(false); + SharedPreferences prefs = context.getSharedPreferences(PREF_NAME, MODE_PRIVATE); + prefs.edit().putLong(PREF_LAST_REFRESH, System.currentTimeMillis()).apply(); + if (FlattrUtils.hasToken()) { Log.d(TAG, "Flattring all pending things."); new FlattrClickWorker(context).executeAsync(); // flattr pending things @@ -313,6 +325,31 @@ public final class DBTasks { DownloadRequester.getInstance().downloadFeed(context, f, loadAllPages, force); } + /* + * Checks if the app should refresh all feeds, i.e. if the last auto refresh failed. + * + * The feeds are only refreshed if an update interval or time of day is set and the last + * (successful) refresh was before the last interval or more than a day ago, respectively. + */ + public static void checkShouldRefreshFeeds(Context context) { + long interval = 0; + if(UserPreferences.getUpdateInterval() > 0) { + interval = UserPreferences.getUpdateInterval(); + } else if(UserPreferences.getUpdateTimeOfDay().length > 0){ + interval = TimeUnit.DAYS.toMillis(1); + } + if(interval == 0) { // auto refresh is disabled + return; + } + SharedPreferences prefs = context.getSharedPreferences(PREF_NAME, MODE_PRIVATE); + long lastRefresh = prefs.getLong(PREF_LAST_REFRESH, 0); + Log.d(TAG, "last refresh: " + Converter.getDurationStringLocalized(context, + System.currentTimeMillis() - lastRefresh) + " ago"); + if(lastRefresh <= System.currentTimeMillis() - interval) { + DBTasks.refreshAllFeeds(context, null); + } + } + /** * Notifies the database about a missing FeedMedia file. This method will correct the FeedMedia object's values in the * DB and send a FeedUpdateBroadcast. @@ -641,6 +678,54 @@ public final class DBTasks { } /** + * Searches the authors of FeedItems of a specific Feed for a given + * string. + * + * @param context Used for accessing the DB. + * @param feedID The id of the feed whose items should be searched. + * @param query The search string. + * @return A FutureTask object that executes the search request and returns the search result as a List of FeedItems. + */ + public static FutureTask<List<FeedItem>> searchFeedItemAuthor(final Context context, + final long feedID, final String query) { + return new FutureTask<>(new QueryTask<List<FeedItem>>(context) { + @Override + public void execute(PodDBAdapter adapter) { + Cursor searchResult = adapter.searchItemAuthors(feedID, + query); + List<FeedItem> items = DBReader.extractItemlistFromCursor(searchResult); + DBReader.loadAdditionalFeedItemListData(items); + setResult(items); + searchResult.close(); + } + }); + } + + /** + * Searches the feed identifiers of FeedItems of a specific Feed for a given + * string. + * + * @param context Used for accessing the DB. + * @param feedID The id of the feed whose items should be searched. + * @param query The search string. + * @return A FutureTask object that executes the search request and returns the search result as a List of FeedItems. + */ + public static FutureTask<List<FeedItem>> searchFeedItemFeedIdentifier(final Context context, + final long feedID, final String query) { + return new FutureTask<>(new QueryTask<List<FeedItem>>(context) { + @Override + public void execute(PodDBAdapter adapter) { + Cursor searchResult = adapter.searchItemFeedIdentifiers(feedID, + query); + List<FeedItem> items = DBReader.extractItemlistFromCursor(searchResult); + DBReader.loadAdditionalFeedItemListData(items); + setResult(items); + searchResult.close(); + } + }); + } + + /** * Searches the descriptions of FeedItems of a specific Feed for a given * string. * @@ -717,7 +802,7 @@ public final class DBTasks { * This class automatically creates a PodDBAdapter object and closes it when * it is no longer in use. */ - static abstract class QueryTask<T> implements Callable<T> { + abstract static class QueryTask<T> implements Callable<T> { private T result; private Context context; diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java index 6f299ee35..49ec07004 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java @@ -4,10 +4,11 @@ import android.app.backup.BackupManager; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; -import android.database.Cursor; import android.preference.PreferenceManager; import android.util.Log; +import de.danoeh.antennapod.core.R; +import de.danoeh.antennapod.core.event.MessageEvent; import org.shredzone.flattr4j.model.Flattr; import java.io.File; @@ -85,12 +86,13 @@ public class DBWriter { if (media != null) { Log.i(TAG, String.format("Requested to delete FeedMedia [id=%d, title=%s, downloaded=%s", media.getId(), media.getEpisodeTitle(), String.valueOf(media.isDownloaded()))); - boolean result = false; if (media.isDownloaded()) { // delete downloaded media file File mediaFile = new File(media.getFile_url()); - if (mediaFile.exists()) { - result = mediaFile.delete(); + if (mediaFile.exists() && !mediaFile.delete()) { + MessageEvent evt = new MessageEvent(context.getString(R.string.delete_failed)); + EventBus.getDefault().post(evt); + return; } media.setDownloaded(false); media.setFile_url(null); @@ -130,7 +132,6 @@ public class DBWriter { GpodnetPreferences.enqueueEpisodeAction(action); } } - Log.d(TAG, "Deleting File. Result: " + result); EventBus.getDefault().post(FeedItemEvent.deletedMedia(Collections.singletonList(media.getItem()))); EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); } @@ -272,8 +273,6 @@ public class DBWriter { return dbExec.submit(() -> { Log.d(TAG, "Adding new item to playback history"); media.setPlaybackCompletionDate(new Date()); - // reset played_duration to 0 so that it behaves correctly when the episode is played again - media.setPlayedDuration(0); PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); @@ -651,7 +650,7 @@ public class DBWriter { } /** - * Sets the 'read'-attribute of all FeedItems of a specific Feed to true. + * Sets the 'read'-attribute of all NEW FeedItems of a specific Feed to UNPLAYED. * * @param feedId ID of the Feed. */ @@ -659,15 +658,7 @@ public class DBWriter { return dbExec.submit(() -> { final PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - Cursor itemCursor = adapter.getNewItemsIdsCursor(feedId); - long[] ids = new long[itemCursor.getCount()]; - itemCursor.moveToFirst(); - for (int i = 0; i < ids.length; i++) { - ids[i] = itemCursor.getLong(0); - itemCursor.moveToNext(); - } - itemCursor.close(); - adapter.setFeedItemRead(FeedItem.UNPLAYED, ids); + adapter.setFeedItems(FeedItem.NEW, FeedItem.UNPLAYED, feedId); adapter.close(); EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); @@ -675,7 +666,7 @@ public class DBWriter { } /** - * Sets the 'read'-attribute of all FeedItems of a specific Feed to true. + * Sets the 'read'-attribute of all FeedItems of a specific Feed to PLAYED. * * @param feedId ID of the Feed. */ @@ -683,16 +674,7 @@ public class DBWriter { return dbExec.submit(() -> { final PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - Cursor itemCursor = adapter.getAllItemsOfFeedCursor(feedId); - long[] itemIds = new long[itemCursor.getCount()]; - itemCursor.moveToFirst(); - for (int i = 0; i < itemIds.length; i++) { - int indexId = itemCursor.getColumnIndex(PodDBAdapter.KEY_ID); - itemIds[i] = itemCursor.getLong(indexId); - itemCursor.moveToNext(); - } - itemCursor.close(); - adapter.setFeedItemRead(FeedItem.PLAYED, itemIds); + adapter.setFeedItems(FeedItem.PLAYED, feedId); adapter.close(); EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); @@ -700,27 +682,31 @@ public class DBWriter { } /** - * Sets the 'read'-attribute of all FeedItems to true. + * Sets the 'read'-attribute of all FeedItems to PLAYED. */ public static Future<?> markAllItemsRead() { return dbExec.submit(() -> { final PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - Cursor itemCursor = adapter.getUnreadItemsCursor(); - long[] itemIds = new long[itemCursor.getCount()]; - itemCursor.moveToFirst(); - for (int i = 0; i < itemIds.length; i++) { - int indexId = itemCursor.getColumnIndex(PodDBAdapter.KEY_ID); - itemIds[i] = itemCursor.getLong(indexId); - itemCursor.moveToNext(); - } - itemCursor.close(); - adapter.setFeedItemRead(FeedItem.PLAYED, itemIds); + adapter.setFeedItems(FeedItem.PLAYED); adapter.close(); EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); }); + } + + /** + * Sets the 'read'-attribute of all NEW FeedItems to UNPLAYED. + */ + public static Future<?> markNewItemsSeen() { + return dbExec.submit(() -> { + final PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + adapter.setFeedItems(FeedItem.NEW, FeedItem.UNPLAYED); + adapter.close(); + EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); + }); } static Future<?> addNewFeed(final Context context, final Feed... feeds) { @@ -900,6 +886,17 @@ public class DBWriter { }); } + public static Future<?> setFeedCustomTitle(Feed feed) { + return dbExec.submit(() -> { + PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + adapter.setFeedCustomTitle(feed.getId(), feed.getCustomTitle()); + adapter.close(); + EventDistributor.getInstance().sendFeedUpdateBroadcast(); + }); + } + + /** * format an url for querying the database * (postfix a / and apply percent-encoding) diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java index 04afc504b..7051d7f4d 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java @@ -345,9 +345,7 @@ public class DownloadRequester { // Try to generate the filename by the item title if (media.getItem() != null && media.getItem().getTitle() != null) { String title = media.getItem().getTitle(); - // Delete reserved characters - titleBaseFilename = title.replaceAll("[^a-zA-Z0-9 ._()-]", ""); - titleBaseFilename = titleBaseFilename.trim(); + titleBaseFilename = FileNameGenerator.generateFileName(title); } String URLBaseFilename = URLUtil.guessFileName(media.getDownload_url(), diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java b/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java index 9aa3012b3..f91e2ad08 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java @@ -4,7 +4,9 @@ import android.content.Context; import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; @@ -23,31 +25,51 @@ public class FeedSearcher { /** - * Performs a search in all feeds or one specific feed. + * Search through a feed, or all feeds, for episodes that match the query in either the title, + * chapter, or show notes. The search is first performed on titles, then chapters, and finally + * show notes. The list of resulting episodes also describes where the first match occurred + * (title, chapters, or show notes). + * + * @param context + * @param query search query + * @param selectedFeed feed to search, 0 to search through all feeds + * @return list of episodes containing the query */ public static List<SearchResult> performSearch(final Context context, final String query, final long selectedFeed) { - final int values[] = {0, 0, 1, 2}; - final String[] subtitles = {context.getString(R.string.found_in_shownotes_label), - context.getString(R.string.found_in_shownotes_label), + final int values[] = {2, 1, 0, 0, 0, 0}; + final String[] subtitles = {context.getString(R.string.found_in_title_label), context.getString(R.string.found_in_chapters_label), - context.getString(R.string.found_in_title_label)}; + context.getString(R.string.found_in_shownotes_label), + context.getString(R.string.found_in_shownotes_label), + context.getString(R.string.found_in_authors_label), + context.getString(R.string.found_in_feeds_label)}; List<SearchResult> result = new ArrayList<>(); - FutureTask<List<FeedItem>>[] tasks = new FutureTask[4]; - (tasks[0] = DBTasks.searchFeedItemContentEncoded(context, selectedFeed, query)).run(); - (tasks[1] = DBTasks.searchFeedItemDescription(context, selectedFeed, query)).run(); - (tasks[2] = DBTasks.searchFeedItemChapters(context, selectedFeed, query)).run(); - (tasks[3] = DBTasks.searchFeedItemTitle(context, selectedFeed, query)).run(); + List<FutureTask<List<FeedItem>>> tasks = new ArrayList<>(); + tasks.add(DBTasks.searchFeedItemTitle(context, selectedFeed, query)); + tasks.add(DBTasks.searchFeedItemChapters(context, selectedFeed, query)); + tasks.add(DBTasks.searchFeedItemDescription(context, selectedFeed, query)); + tasks.add(DBTasks.searchFeedItemContentEncoded(context, selectedFeed, query)); + tasks.add(DBTasks.searchFeedItemAuthor(context, selectedFeed, query)); + tasks.add(DBTasks.searchFeedItemFeedIdentifier(context, selectedFeed, query)); + + for (FutureTask<List<FeedItem>> task : tasks) { + task.run(); + } try { - for (int i = 0; i < tasks.length; i++) { - FutureTask task = tasks[i]; - List<FeedItem> items = (List<FeedItem>) task.get(); + Set<Long> set = new HashSet<>(); + + for (int i = 0; i < tasks.size(); i++) { + FutureTask<List<FeedItem>> task = tasks.get(i); + List<FeedItem> items = task.get(); for (FeedItem item : items) { - result.add(new SearchResult(item, values[i], subtitles[i])); + if (!set.contains(item.getId())) { // to prevent duplicate results + result.add(new SearchResult(item, values[i], subtitles[i])); + set.add(item.getId()); + } } - } } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index 92d1e790c..dc8692866 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -15,9 +15,12 @@ import android.text.TextUtils; import android.util.Log; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import de.danoeh.antennapod.core.R; import de.danoeh.antennapod.core.event.ProgressEvent; @@ -40,14 +43,14 @@ import de.greenrobot.event.EventBus; * Implements methods for accessing the database */ public class PodDBAdapter { - + private static final String TAG = "PodDBAdapter"; - public static final String DATABASE_NAME = "Antennapod.db"; + private static final String DATABASE_NAME = "Antennapod.db"; /** * Maximum number of arguments for IN-operator. */ - public static final int IN_OPERATOR_MAXIMUM = 800; + private static final int IN_OPERATOR_MAXIMUM = 800; /** * Maximum number of entries per search request. @@ -57,6 +60,7 @@ public class PodDBAdapter { // Key-constants public static final String KEY_ID = "id"; public static final String KEY_TITLE = "title"; + public static final String KEY_CUSTOM_TITLE = "custom_title"; public static final String KEY_NAME = "name"; public static final String KEY_LINK = "link"; public static final String KEY_DESCRIPTION = "description"; @@ -109,14 +113,14 @@ public class PodDBAdapter { public static final String KEY_EXCLUDE_FILTER = "exclude_filter"; // Table names - public static final String TABLE_NAME_FEEDS = "Feeds"; - public static final String TABLE_NAME_FEED_ITEMS = "FeedItems"; - public static final String TABLE_NAME_FEED_IMAGES = "FeedImages"; - public static final String TABLE_NAME_FEED_MEDIA = "FeedMedia"; - public static final String TABLE_NAME_DOWNLOAD_LOG = "DownloadLog"; - public static final String TABLE_NAME_QUEUE = "Queue"; - public static final String TABLE_NAME_SIMPLECHAPTERS = "SimpleChapters"; - public static final String TABLE_NAME_FAVORITES = "Favorites"; + private static final String TABLE_NAME_FEEDS = "Feeds"; + private static final String TABLE_NAME_FEED_ITEMS = "FeedItems"; + private static final String TABLE_NAME_FEED_IMAGES = "FeedImages"; + private static final String TABLE_NAME_FEED_MEDIA = "FeedMedia"; + private static final String TABLE_NAME_DOWNLOAD_LOG = "DownloadLog"; + private static final String TABLE_NAME_QUEUE = "Queue"; + private static final String TABLE_NAME_SIMPLECHAPTERS = "SimpleChapters"; + private static final String TABLE_NAME_FAVORITES = "Favorites"; // SQL Statements for creating new tables private static final String TABLE_PRIMARY_KEY = KEY_ID @@ -124,7 +128,7 @@ public class PodDBAdapter { public static final String CREATE_TABLE_FEEDS = "CREATE TABLE " + TABLE_NAME_FEEDS + " (" + TABLE_PRIMARY_KEY + KEY_TITLE - + " TEXT," + KEY_FILE_URL + " TEXT," + KEY_DOWNLOAD_URL + " TEXT," + + " TEXT," + KEY_CUSTOM_TITLE + " TEXT," + KEY_FILE_URL + " TEXT," + KEY_DOWNLOAD_URL + " TEXT," + KEY_DOWNLOADED + " INTEGER," + KEY_LINK + " TEXT," + KEY_DESCRIPTION + " TEXT," + KEY_PAYMENT_LINK + " TEXT," + KEY_LASTUPDATE + " TEXT," + KEY_LANGUAGE + " TEXT," + KEY_AUTHOR @@ -218,13 +222,14 @@ public class PodDBAdapter { public static final String CREATE_TABLE_FAVORITES = "CREATE TABLE " + TABLE_NAME_FAVORITES + "(" + KEY_ID + " INTEGER PRIMARY KEY," + KEY_FEEDITEM + " INTEGER," + KEY_FEED + " INTEGER)"; - + /** * Select all columns from the feed-table */ private static final String[] FEED_SEL_STD = { TABLE_NAME_FEEDS + "." + KEY_ID, TABLE_NAME_FEEDS + "." + KEY_TITLE, + TABLE_NAME_FEEDS + "." + KEY_CUSTOM_TITLE, TABLE_NAME_FEEDS + "." + KEY_FILE_URL, TABLE_NAME_FEEDS + "." + KEY_DOWNLOAD_URL, TABLE_NAME_FEEDS + "." + KEY_DOWNLOADED, @@ -250,7 +255,7 @@ public class PodDBAdapter { TABLE_NAME_FEEDS + "." + KEY_INCLUDE_FILTER, TABLE_NAME_FEEDS + "." + KEY_EXCLUDE_FILTER }; - + /** * Select all columns from the feeditems-table except description and * content-encoded. @@ -301,59 +306,87 @@ public class PodDBAdapter { private static final String[] SEL_FI_EXTRA = {KEY_ID, KEY_DESCRIPTION, KEY_CONTENT_ENCODED, KEY_FEED}; - - private static SQLiteDatabase db; private static Context context; private static PodDBHelper dbHelper; + + private static volatile SQLiteDatabase db; + private static Lock dbLock = new ReentrantLock(); private static AtomicInteger counter = new AtomicInteger(0); public static void init(Context context) { PodDBAdapter.context = context.getApplicationContext(); } - public static synchronized PodDBAdapter getInstance() { - if(dbHelper == null) { - dbHelper = new PodDBHelper(PodDBAdapter.context, DATABASE_NAME, null); - } + private static class PodDBHelperholder { + public static final PodDBHelper dbHelper = new PodDBHelper(PodDBAdapter.context, DATABASE_NAME, null); + } + + public static PodDBAdapter getInstance() { + dbHelper = PodDBHelperholder.dbHelper; return new PodDBAdapter(); } - private PodDBAdapter() {} + private PodDBAdapter() { + } - public synchronized PodDBAdapter open() { + public PodDBAdapter open() { int adapters = counter.incrementAndGet(); Log.v(TAG, "Opening DB #" + adapters); - if (db == null || !db.isOpen() || db.isReadOnly()) { + + if ((db == null) || (!db.isOpen()) || (db.isReadOnly())) { try { - db = dbHelper.getWritableDatabase(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - db.enableWriteAheadLogging(); + dbLock.lock(); + if ((db == null) || (!db.isOpen()) || (db.isReadOnly())) { + db = openDb(); } - } catch (SQLException ex) { - Log.e(TAG, Log.getStackTraceString(ex)); - db = dbHelper.getReadableDatabase(); + } finally { + dbLock.unlock(); } } return this; } - public synchronized void close() { + private SQLiteDatabase openDb() { + SQLiteDatabase newDb = null; + try { + newDb = dbHelper.getWritableDatabase(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + newDb.enableWriteAheadLogging(); + } + } catch (SQLException ex) { + Log.e(TAG, Log.getStackTraceString(ex)); + newDb = dbHelper.getReadableDatabase(); + } + return newDb; + } + + public void close() { int adapters = counter.decrementAndGet(); Log.v(TAG, "Closing DB #" + adapters); - if(adapters == 0) { + + if (adapters == 0) { Log.v(TAG, "Closing DB, really"); - db.close(); + try { + dbLock.lock(); + db.close(); + db = null; + } finally { + dbLock.unlock(); + } } } public static boolean deleteDatabase() { PodDBAdapter adapter = getInstance(); adapter.open(); - for (String tableName : ALL_TABLES) { - db.delete(tableName, "1", null); + try { + for (String tableName : ALL_TABLES) { + db.delete(tableName, "1", null); + } + return true; + } finally { + adapter.close(); } - adapter.close(); - return true; } /** @@ -363,7 +396,7 @@ public class PodDBAdapter { */ public long setFeed(Feed feed) { ContentValues values = new ContentValues(); - values.put(KEY_TITLE, feed.getTitle()); + values.put(KEY_TITLE, feed.getFeedTitle()); values.put(KEY_LINK, feed.getLink()); values.put(KEY_DESCRIPTION, feed.getDescription()); values.put(KEY_PAYMENT_LINK, feed.getPaymentLink()); @@ -388,8 +421,8 @@ public class PodDBAdapter { values.put(KEY_FLATTR_STATUS, feed.getFlattrStatus().toLong()); values.put(KEY_IS_PAGED, feed.isPaged()); values.put(KEY_NEXT_PAGE_LINK, feed.getNextPageLink()); - if(feed.getItemFilter() != null && feed.getItemFilter().getValues().length > 0) { - values.put(KEY_HIDE, TextUtils.join( ",", feed.getItemFilter().getValues())); + if (feed.getItemFilter() != null && feed.getItemFilter().getValues().length > 0) { + values.put(KEY_HIDE, TextUtils.join(",", feed.getItemFilter().getValues())); } else { values.put(KEY_HIDE, ""); } @@ -413,7 +446,7 @@ public class PodDBAdapter { ContentValues values = new ContentValues(); values.put(KEY_AUTO_DOWNLOAD, prefs.getAutoDownload()); values.put(KEY_KEEP_UPDATED, prefs.getKeepUpdated()); - values.put(KEY_AUTO_DELETE_ACTION,prefs.getAutoDeleteAction().ordinal()); + values.put(KEY_AUTO_DELETE_ACTION, prefs.getAutoDeleteAction().ordinal()); values.put(KEY_USERNAME, prefs.getUsername()); values.put(KEY_PASSWORD, prefs.getPassword()); values.put(KEY_INCLUDE_FILTER, prefs.getFilter().getIncludeFilter()); @@ -422,10 +455,11 @@ public class PodDBAdapter { } public void setFeedItemFilter(long feedId, Set<String> filterValues) { - Log.d(TAG, "setFeedItemFilter() called with: " + "feedId = [" + feedId + "], " + - "filterValues = [" + TextUtils.join(",", filterValues) + "]"); + String valuesList = TextUtils.join(",", filterValues); + Log.d(TAG, String.format( + "setFeedItemFilter() called with: feedId = [%d], filterValues = [%s]", feedId, valuesList)); ContentValues values = new ContentValues(); - values.put(KEY_HIDE, TextUtils.join(",", filterValues)); + values.put(KEY_HIDE, valuesList); db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(feedId)}); } @@ -456,7 +490,7 @@ public class PodDBAdapter { image.setId(db.insert(TABLE_NAME_FEED_IMAGES, null, values)); } else { db.update(TABLE_NAME_FEED_IMAGES, values, KEY_ID + "=?", - new String[]{String.valueOf(image.getId())}); + new String[]{String.valueOf(image.getId())}); } final FeedComponent owner = image.getOwner(); @@ -744,9 +778,9 @@ public class PodDBAdapter { setFeed(item.getFeed()); } values.put(KEY_FEED, item.getFeed().getId()); - if(item.isNew()) { + if (item.isNew()) { values.put(KEY_READ, FeedItem.NEW); - } else if(item.isPlayed()) { + } else if (item.isPlayed()) { values.put(KEY_READ, FeedItem.PLAYED); } else { values.put(KEY_READ, FeedItem.UNPLAYED); @@ -806,7 +840,8 @@ public class PodDBAdapter { /** * Sets the 'read' attribute of the item. - * @param read must be one of FeedItem.PLAYED, FeedItem.NEW, FeedItem.UNPLAYED + * + * @param read must be one of FeedItem.PLAYED, FeedItem.NEW, FeedItem.UNPLAYED * @param itemIds items to change the value of */ public void setFeedItemRead(int read, long... itemIds) { @@ -849,11 +884,17 @@ public class PodDBAdapter { public void setFeedLastUpdateFailed(long feedId, boolean failed) { final String sql = "UPDATE " + TABLE_NAME_FEEDS - + " SET " + KEY_LAST_UPDATE_FAILED+ "=" + (failed ? "1" : "0") - + " WHERE " + KEY_ID + "="+ feedId; + + " SET " + KEY_LAST_UPDATE_FAILED + "=" + (failed ? "1" : "0") + + " WHERE " + KEY_ID + "=" + feedId; db.execSQL(sql); } + void setFeedCustomTitle(long feedId, String customTitle) { + ContentValues values = new ContentValues(); + values.put(KEY_CUSTOM_TITLE, customTitle); + db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(feedId)}); + } + /** * Inserts or updates a download status. */ @@ -884,7 +925,7 @@ public class PodDBAdapter { public void setFeedsItemsAutoDownload(Feed feed, boolean autoDownload) { final String sql = "UPDATE " + TABLE_NAME_FEED_ITEMS - + " SET " + KEY_AUTO_DOWNLOAD + "="+ (autoDownload ? "1" : "0") + + " SET " + KEY_AUTO_DOWNLOAD + "=" + (autoDownload ? "1" : "0") + " WHERE " + KEY_FEED + "=" + feed.getId(); db.execSQL(sql); } @@ -986,8 +1027,8 @@ public class PodDBAdapter { public void removeFeedMedia(FeedMedia media) { // delete download log entries for feed media - db.delete(TABLE_NAME_DOWNLOAD_LOG, KEY_FEEDFILE + "=? AND " + KEY_FEEDFILETYPE +"=?", - new String[] { String.valueOf(media.getId()), String.valueOf(FeedMedia.FEEDFILETYPE_FEEDMEDIA) }); + db.delete(TABLE_NAME_DOWNLOAD_LOG, KEY_FEEDFILE + "=? AND " + KEY_FEEDFILETYPE + "=?", + new String[]{String.valueOf(media.getId()), String.valueOf(FeedMedia.FEEDFILETYPE_FEEDMEDIA)}); db.delete(TABLE_NAME_FEED_MEDIA, KEY_ID + "=?", new String[]{String.valueOf(media.getId())}); @@ -1040,10 +1081,10 @@ public class PodDBAdapter { } // delete download log entries for feed db.delete(TABLE_NAME_DOWNLOAD_LOG, KEY_FEEDFILE + "=? AND " + KEY_FEEDFILETYPE + "=?", - new String[]{String.valueOf(feed.getId()), String.valueOf(Feed.FEEDFILETYPE_FEED)}); + new String[]{String.valueOf(feed.getId()), String.valueOf(Feed.FEEDFILETYPE_FEED)}); db.delete(TABLE_NAME_FEEDS, KEY_ID + "=?", - new String[]{String.valueOf(feed.getId())}); + new String[]{String.valueOf(feed.getId())}); db.setTransactionSuccessful(); } catch (SQLException e) { Log.e(TAG, Log.getStackTraceString(e)); @@ -1148,7 +1189,9 @@ public class PodDBAdapter { + TABLE_NAME_FEED_IMAGES + " WHERE " + KEY_ID + " IN " + buildInOperator(neededLength), parts); } - return new MergeCursor(cursors); + Cursor result = new MergeCursor(cursors); + result.moveToFirst(); + return result; } else { return db.query(TABLE_NAME_FEED_IMAGES, null, KEY_ID + " IN " + buildInOperator(length), imageIds, null, null, null); @@ -1180,12 +1223,12 @@ public class PodDBAdapter { * cursor uses the FEEDITEM_SEL_FI_SMALL selection. */ public final Cursor getQueueCursor() { - Object[] args = new String[] { + Object[] args = new String[]{ SEL_FI_SMALL_STR, TABLE_NAME_FEED_ITEMS, TABLE_NAME_QUEUE, TABLE_NAME_FEED_ITEMS + "." + KEY_ID, TABLE_NAME_QUEUE + "." + KEY_FEEDITEM, - TABLE_NAME_QUEUE + "." + KEY_ID }; + TABLE_NAME_QUEUE + "." + KEY_ID}; String query = String.format("SELECT %s FROM %s INNER JOIN %s ON %s=%s ORDER BY %s", args); return db.rawQuery(query, null); } @@ -1196,36 +1239,38 @@ public class PodDBAdapter { public final Cursor getFavoritesCursor() { - Object[] args = new String[] { + Object[] args = new String[]{ SEL_FI_SMALL_STR, TABLE_NAME_FEED_ITEMS, TABLE_NAME_FAVORITES, TABLE_NAME_FEED_ITEMS + "." + KEY_ID, TABLE_NAME_FAVORITES + "." + KEY_FEEDITEM, - TABLE_NAME_FEED_ITEMS + "." + KEY_PUBDATE }; + TABLE_NAME_FEED_ITEMS + "." + KEY_PUBDATE}; String query = String.format("SELECT %s FROM %s INNER JOIN %s ON %s=%s ORDER BY %s DESC", args); return db.rawQuery(query, null); } - /** - * Returns a cursor which contains all feed items in the unread items list. - * The returned cursor uses the FEEDITEM_SEL_FI_SMALL selection. - */ - public final Cursor getUnreadItemsCursor() { - return db.query(TABLE_NAME_FEED_ITEMS, FEEDITEM_SEL_FI_SMALL, KEY_READ - + "<" + FeedItem.PLAYED, null, null, null, KEY_PUBDATE + " DESC"); + public void setFeedItems(int state) { + setFeedItems(Integer.MIN_VALUE, state, 0); } - /** - * Returns a cursor which contains all items of a feed that are considered new. - * The returned cursor uses the FEEDITEM_SEL_FI_SMALL selection. - */ - public final Cursor getNewItemsIdsCursor(long feedId) { - final String query = "SELECT " + KEY_ID - + " FROM " + TABLE_NAME_FEED_ITEMS - + " WHERE " + KEY_FEED + "=" + feedId - + " AND " + KEY_READ + "=" + FeedItem.NEW - + " ORDER BY " + KEY_PUBDATE + " DESC"; - return db.rawQuery(query, null); + public void setFeedItems(int oldState, int newState) { + setFeedItems(oldState, newState, 0); + } + + public void setFeedItems(int state, long feedId) { + setFeedItems(Integer.MIN_VALUE, state, feedId); + } + + public void setFeedItems(int oldState, int newState, long feedId) { + String sql = "UPDATE " + TABLE_NAME_FEED_ITEMS + " SET " + KEY_READ + "=" + newState; + if (feedId > 0) { + sql += " WHERE " + KEY_FEED + "=" + feedId; + } + if (FeedItem.NEW <= oldState && oldState <= FeedItem.PLAYED) { + sql += feedId > 0 ? " AND " : " WHERE "; + sql += KEY_READ + "=" + oldState; + } + db.execSQL(sql); } /** @@ -1234,7 +1279,7 @@ public class PodDBAdapter { * The returned cursor uses the FEEDITEM_SEL_FI_SMALL selection. */ public final Cursor getNewItemsCursor() { - Object[] args = new String[] { + Object[] args = new String[]{ SEL_FI_SMALL_STR, TABLE_NAME_FEED_ITEMS, TABLE_NAME_FEEDS, @@ -1268,7 +1313,7 @@ public class PodDBAdapter { * @throws IllegalArgumentException if limit < 0 */ public final Cursor getCompletedMediaCursor(int limit) { - if(limit < 0) { + if (limit < 0) { throw new IllegalArgumentException("Limit must be >= 0"); } @@ -1309,7 +1354,9 @@ public class PodDBAdapter { + TABLE_NAME_FEED_MEDIA + " WHERE " + KEY_FEEDITEM + " IN " + buildInOperator(neededLength), parts); } - return new MergeCursor(cursors); + Cursor result = new MergeCursor(cursors); + result.moveToFirst(); + return result; } else { return db.query(TABLE_NAME_FEED_MEDIA, null, KEY_FEEDITEM + " IN " + buildInOperator(length), itemIds, null, null, null); @@ -1323,11 +1370,10 @@ public class PodDBAdapter { if (size == 1) { return "(?)"; } - StringBuilder builder = new StringBuilder("("); - for (int i = 0; i < size - 1; i++) { - builder.append("?,"); - } - builder.append("?)"); + StringBuilder builder = + new StringBuilder("(") + .append(TextUtils.join(",", Collections.nCopies(size, "?"))) + .append(")"); return builder.toString(); } @@ -1361,7 +1407,7 @@ public class PodDBAdapter { + " INNER JOIN " + TABLE_NAME_FEEDS + " ON " + TABLE_NAME_FEED_ITEMS + "." + KEY_FEED + "=" + TABLE_NAME_FEEDS + "." + KEY_ID + " INNER JOIN " + TABLE_NAME_FEED_MEDIA - + " ON " + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM + "=" + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + + " ON " + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM + "=" + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + " WHERE " + TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOAD_URL + "=" + escapedEpisodeUrl + " AND " + TABLE_NAME_FEEDS + "." + KEY_DOWNLOAD_URL + "=" + escapedPodcastUrl; Log.d(TAG, "SQL: " + query); @@ -1412,17 +1458,29 @@ public class PodDBAdapter { public final LongIntMap getFeedCounters(long... feedIds) { int setting = UserPreferences.getFeedCounterSetting(); String whereRead; - if(setting == UserPreferences.FEED_COUNTER_SHOW_NEW_UNPLAYED_SUM) { - whereRead = "(" + KEY_READ + "=" + FeedItem.NEW - + " OR " + KEY_READ + "=" + FeedItem.UNPLAYED + ")"; - } else if(setting == UserPreferences.FEED_COUNTER_SHOW_NEW) { - whereRead = KEY_READ + "=" + FeedItem.NEW; - } else if(setting == UserPreferences.FEED_COUNTER_SHOW_UNPLAYED) { - whereRead = KEY_READ + "=" + FeedItem.UNPLAYED; - } else { // NONE - return new LongIntMap(0); + switch (setting) { + case UserPreferences.FEED_COUNTER_SHOW_NEW_UNPLAYED_SUM: + whereRead = "(" + KEY_READ + "=" + FeedItem.NEW + + " OR " + KEY_READ + "=" + FeedItem.UNPLAYED + ")"; + break; + case UserPreferences.FEED_COUNTER_SHOW_NEW: + whereRead = KEY_READ + "=" + FeedItem.NEW; + break; + case UserPreferences.FEED_COUNTER_SHOW_UNPLAYED: + whereRead = KEY_READ + "=" + FeedItem.UNPLAYED; + break; + case UserPreferences.FEED_COUNTER_SHOW_DOWNLOADED: + whereRead = KEY_DOWNLOADED + "=1"; + break; + case UserPreferences.FEED_COUNTER_SHOW_NONE: + // deliberate fall-through + default: // NONE + return new LongIntMap(0); } + return conditionalFeedCounterRead(whereRead, feedIds); + } + private LongIntMap conditionalFeedCounterRead(String whereRead, long... feedIds) { // work around TextUtils.join wanting only boxed items // and StringUtils.join() causing NoSuchMethodErrors on MIUI StringBuilder builder = new StringBuilder(); @@ -1435,8 +1493,10 @@ public class PodDBAdapter { builder.deleteCharAt(builder.length() - 1); } - final String query = "SELECT " + KEY_FEED + ", COUNT(" + KEY_ID + ") AS count " + final String query = "SELECT " + KEY_FEED + ", COUNT(" + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + ") AS count " + " FROM " + TABLE_NAME_FEED_ITEMS + + " LEFT JOIN " + TABLE_NAME_FEED_MEDIA + " ON " + + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "=" + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM + " WHERE " + KEY_FEED + " IN (" + builder.toString() + ") " + " AND " + whereRead + " GROUP BY " + KEY_FEED; @@ -1447,12 +1507,17 @@ public class PodDBAdapter { long feedId = c.getLong(0); int count = c.getInt(1); result.put(feedId, count); - } while(c.moveToNext()); + } while (c.moveToNext()); } c.close(); return result; } + public final LongIntMap getPlayedEpisodesCounters(long... feedIds) { + String whereRead = KEY_READ + "=" + FeedItem.PLAYED; + return conditionalFeedCounterRead(whereRead, feedIds); + } + public final int getNumberOfDownloadedEpisodes() { final String query = "SELECT COUNT(DISTINCT " + KEY_ID + ") AS count FROM " + TABLE_NAME_FEED_MEDIA + " WHERE " + KEY_DOWNLOADED + " > 0"; @@ -1546,6 +1611,52 @@ public class PodDBAdapter { } } + public Cursor searchItemAuthors(long feedID, String query) { + if (feedID != 0) { + // search items in specific feed + return db.rawQuery("SELECT " + TextUtils.join(", ", FEEDITEM_SEL_FI_SMALL) + " FROM " + TABLE_NAME_FEED_ITEMS + + " JOIN " + TABLE_NAME_FEEDS + " ON " + TABLE_NAME_FEED_ITEMS + "." + KEY_FEED + "=" + TABLE_NAME_FEEDS + "." + KEY_ID + + " WHERE " + KEY_FEED + + "=? AND " + KEY_AUTHOR + " LIKE '%" + + prepareSearchQuery(query) + "%' ORDER BY " + + TABLE_NAME_FEED_ITEMS + "." + KEY_PUBDATE + " DESC", + new String[]{String.valueOf(feedID)} + ); + } else { + // search through all items + return db.rawQuery("SELECT " + TextUtils.join(", ", FEEDITEM_SEL_FI_SMALL) + " FROM " + TABLE_NAME_FEED_ITEMS + + " JOIN " + TABLE_NAME_FEEDS + " ON " + TABLE_NAME_FEED_ITEMS + "." + KEY_FEED + "=" + TABLE_NAME_FEEDS + "." + KEY_ID + + " WHERE " + KEY_AUTHOR + " LIKE '%" + + prepareSearchQuery(query) + "%' ORDER BY " + + TABLE_NAME_FEED_ITEMS + "." + KEY_PUBDATE + " DESC", + null + ); + } + } + + public Cursor searchItemFeedIdentifiers(long feedID, String query) { + if (feedID != 0) { + // search items in specific feed + return db.rawQuery("SELECT " + TextUtils.join(", ", FEEDITEM_SEL_FI_SMALL) + " FROM " + TABLE_NAME_FEED_ITEMS + + " JOIN " + TABLE_NAME_FEEDS + " ON " + TABLE_NAME_FEED_ITEMS + "." + KEY_FEED + "=" + TABLE_NAME_FEEDS + "." + KEY_ID + + " WHERE " + KEY_FEED + + "=? AND " + KEY_FEED_IDENTIFIER + " LIKE '%" + + prepareSearchQuery(query) + "%' ORDER BY " + + TABLE_NAME_FEED_ITEMS + "." + KEY_PUBDATE + " DESC", + new String[]{String.valueOf(feedID)} + ); + } else { + // search through all items + return db.rawQuery("SELECT " + TextUtils.join(", ", FEEDITEM_SEL_FI_SMALL) + " FROM " + TABLE_NAME_FEED_ITEMS + + " JOIN " + TABLE_NAME_FEEDS + " ON " + TABLE_NAME_FEED_ITEMS + "." + KEY_FEED + "=" + TABLE_NAME_FEEDS + "." + KEY_ID + + " WHERE " + KEY_FEED_IDENTIFIER + " LIKE '%" + + prepareSearchQuery(query) + "%' ORDER BY " + + TABLE_NAME_FEED_ITEMS + "." + KEY_PUBDATE + " DESC", + null + ); + } + } + public Cursor searchItemChapters(long feedID, String searchQuery) { final String query; if (feedID != 0) { @@ -1593,7 +1704,7 @@ public class PodDBAdapter { */ private static class PodDBHelper extends SQLiteOpenHelper { - private final static int VERSION = 1050004; + private static final int VERSION = 1060200; private Context context; @@ -1741,7 +1852,7 @@ public class PodDBAdapter { KEY_LINK, KEY_CHAPTER_TYPE)); } - if(oldVersion <= 14) { + if (oldVersion <= 14) { db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + " ADD COLUMN " + KEY_AUTO_DOWNLOAD + " INTEGER"); db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS @@ -1764,7 +1875,7 @@ public class PodDBAdapter { db.execSQL(PodDBAdapter.CREATE_INDEX_QUEUE_FEEDITEM); db.execSQL(PodDBAdapter.CREATE_INDEX_SIMPLECHAPTERS_FEEDITEM); } - if(oldVersion <= 15) { + if (oldVersion <= 15) { db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + " ADD COLUMN " + KEY_HAS_EMBEDDED_PICTURE + " INTEGER DEFAULT -1"); db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA @@ -1774,7 +1885,7 @@ public class PodDBAdapter { + " FROM " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + " WHERE " + KEY_DOWNLOADED + "=1 " + " AND " + KEY_HAS_EMBEDDED_PICTURE + "=-1", null); - if(c.moveToFirst()) { + if (c.moveToFirst()) { MediaMetadataRetriever mmr = new MediaMetadataRetriever(); do { String fileUrl = c.getString(0); @@ -1784,20 +1895,20 @@ public class PodDBAdapter { if (image != null) { db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + " SET " + KEY_HAS_EMBEDDED_PICTURE + "=1" - + " WHERE " + KEY_FILE_URL + "='"+ fileUrl + "'"); + + " WHERE " + KEY_FILE_URL + "='" + fileUrl + "'"); } else { db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + " SET " + KEY_HAS_EMBEDDED_PICTURE + "=0" - + " WHERE " + KEY_FILE_URL + "='"+ fileUrl + "'"); + + " WHERE " + KEY_FILE_URL + "='" + fileUrl + "'"); } - } catch(Exception e) { + } catch (Exception e) { e.printStackTrace(); } - } while(c.moveToNext()); + } while (c.moveToNext()); } c.close(); } - if(oldVersion <= 16) { + if (oldVersion <= 16) { String selectNew = "SELECT " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + KEY_ID + " FROM " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + " INNER JOIN " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + " ON " @@ -1811,29 +1922,29 @@ public class PodDBAdapter { + PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + " = 0 AND " // undownloaded + PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + KEY_POSITION + " = 0 AND " // not partially played + PodDBAdapter.TABLE_NAME_QUEUE + "." + KEY_ID + " IS NULL"; // not in queue - String sql = "UPDATE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + String sql = "UPDATE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + " SET " + KEY_READ + "=" + FeedItem.NEW + " WHERE " + KEY_ID + " IN (" + selectNew + ")"; Log.d("Migration", "SQL: " + sql); db.execSQL(sql); } - if(oldVersion <= 17) { + if (oldVersion <= 17) { db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + " ADD COLUMN " + PodDBAdapter.KEY_AUTO_DELETE_ACTION + " INTEGER DEFAULT 0"); } - if(oldVersion < 1030005) { + if (oldVersion < 1030005) { db.execSQL("UPDATE FeedItems SET auto_download=0 WHERE " + "(read=1 OR id IN (SELECT feeditem FROM FeedMedia WHERE position>0 OR downloaded=1)) " + "AND id NOT IN (SELECT feeditem FROM Queue)"); } - if(oldVersion < 1040001) { + if (oldVersion < 1040001) { db.execSQL(CREATE_TABLE_FAVORITES); } - if (oldVersion < 1040002) { + if (oldVersion < 1040002) { db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + " ADD COLUMN " + PodDBAdapter.KEY_LAST_PLAYED_TIME + " INTEGER DEFAULT 0"); } - if(oldVersion < 1040013) { + if (oldVersion < 1040013) { db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_PUBDATE); db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_READ); } @@ -1887,7 +1998,11 @@ public class PodDBAdapter { if (oldVersion < 1050004) { // prevent old timestamps to be misinterpreted as ETags db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEEDS - +" SET " + PodDBAdapter.KEY_LASTUPDATE + "=NULL"); + + " SET " + PodDBAdapter.KEY_LASTUPDATE + "=NULL"); + } + if (oldVersion < 1060200) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + + " ADD COLUMN " + PodDBAdapter.KEY_CUSTOM_TITLE + " TEXT"); } EventBus.getDefault().post(ProgressEvent.end()); diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/SyndHandler.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/SyndHandler.java index 47503dee4..ae91c0743 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/SyndHandler.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/SyndHandler.java @@ -6,7 +6,6 @@ import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; -import de.danoeh.antennapod.core.BuildConfig; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.syndication.namespace.NSContent; import de.danoeh.antennapod.core.syndication.namespace.NSDublinCore; @@ -86,34 +85,28 @@ public class SyndHandler extends DefaultHandler { state.defaultNamespaces.push(new NSAtom()); } else if (prefix.equals(NSAtom.NSTAG)) { state.namespaces.put(uri, new NSAtom()); - if (BuildConfig.DEBUG) - Log.d(TAG, "Recognized Atom namespace"); + Log.d(TAG, "Recognized Atom namespace"); } } else if (uri.equals(NSContent.NSURI) && prefix.equals(NSContent.NSTAG)) { state.namespaces.put(uri, new NSContent()); - if (BuildConfig.DEBUG) - Log.d(TAG, "Recognized Content namespace"); + Log.d(TAG, "Recognized Content namespace"); } else if (uri.equals(NSITunes.NSURI) && prefix.equals(NSITunes.NSTAG)) { state.namespaces.put(uri, new NSITunes()); - if (BuildConfig.DEBUG) - Log.d(TAG, "Recognized ITunes namespace"); + Log.d(TAG, "Recognized ITunes namespace"); } else if (uri.equals(NSSimpleChapters.NSURI) && prefix.matches(NSSimpleChapters.NSTAG)) { state.namespaces.put(uri, new NSSimpleChapters()); - if (BuildConfig.DEBUG) - Log.d(TAG, "Recognized SimpleChapters namespace"); + Log.d(TAG, "Recognized SimpleChapters namespace"); } else if (uri.equals(NSMedia.NSURI) && prefix.equals(NSMedia.NSTAG)) { state.namespaces.put(uri, new NSMedia()); - if (BuildConfig.DEBUG) - Log.d(TAG, "Recognized media namespace"); + Log.d(TAG, "Recognized media namespace"); } else if (uri.equals(NSDublinCore.NSURI) && prefix.equals(NSDublinCore.NSTAG)) { state.namespaces.put(uri, new NSDublinCore()); - if (BuildConfig.DEBUG) - Log.d(TAG, "Recognized DublinCore namespace"); + Log.d(TAG, "Recognized DublinCore namespace"); } } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/TypeGetter.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/TypeGetter.java index f84d6ee96..ee0a71f30 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/TypeGetter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/TypeGetter.java @@ -45,6 +45,12 @@ public class TypeGetter { case ATOM_ROOT: feed.setType(Feed.TYPE_ATOM1); Log.d(TAG, "Recognized type Atom"); + + String strLang = xpp.getAttributeValue("http://www.w3.org/XML/1998/namespace", "lang"); + if (strLang != null) { + feed.setLanguage(strLang); + } + return Type.ATOM; case RSS_ROOT: String strVersion = xpp.getAttributeValue(null, "version"); @@ -78,9 +84,8 @@ public class TypeGetter { } } catch (IOException e1) { e1.printStackTrace(); - } finally { - throw new UnsupportedFeedtypeException(Type.INVALID, rootElement); } + throw new UnsupportedFeedtypeException(Type.INVALID, rootElement); } catch (IOException e) { e.printStackTrace(); diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java index 1c424c6b5..7d60566b2 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java @@ -101,7 +101,10 @@ public class NSITunes extends Namespace { if (TextUtils.isEmpty(summary)) { return; } - if (state.getCurrentItem() != null) { + if (state.getCurrentItem() != null && + (TextUtils.isEmpty(state.getCurrentItem().getDescription()) || + state.getCurrentItem().getDescription().length() * 1.25 < summary.length()) + ) { state.getCurrentItem().setDescription(summary); } else if (state.getFeed() != null) { state.getFeed().setDescription(summary); diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSMedia.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSMedia.java index 7a8b2bc03..f2cfc2e57 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSMedia.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSMedia.java @@ -7,8 +7,10 @@ import org.xml.sax.Attributes; import java.util.concurrent.TimeUnit; +import de.danoeh.antennapod.core.feed.FeedImage; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.syndication.handler.HandlerState; +import de.danoeh.antennapod.core.syndication.namespace.atom.AtomText; import de.danoeh.antennapod.core.syndication.util.SyndTypeUtils; /** Processes tags from the http://search.yahoo.com/mrss/ namespace. */ @@ -23,22 +25,51 @@ public class NSMedia extends Namespace { private static final String SIZE = "fileSize"; private static final String MIME_TYPE = "type"; private static final String DURATION = "duration"; + private static final String DEFAULT = "isDefault"; + private static final String MEDIUM = "medium"; + + private static final String MEDIUM_IMAGE = "image"; + private static final String MEDIUM_AUDIO = "audio"; + private static final String MEDIUM_VIDEO = "video"; + + private static final String IMAGE = "thumbnail"; + private static final String IMAGE_URL = "url"; + + private static final String DESCRIPTION = "description"; + private static final String DESCRIPTION_TYPE = "type"; @Override public SyndElement handleElementStart(String localName, HandlerState state, - Attributes attributes) { + Attributes attributes) { if (CONTENT.equals(localName)) { String url = attributes.getValue(DOWNLOAD_URL); String type = attributes.getValue(MIME_TYPE); - boolean validType; - if(SyndTypeUtils.enclosureTypeValid(type)) { - validType = true; - } else { - type = SyndTypeUtils.getValidMimeTypeFromUrl(url); - validType = type != null; - } - if (state.getCurrentItem() != null && state.getCurrentItem().getMedia() == null && - url != null && validType) { + String defaultStr = attributes.getValue(DEFAULT); + String medium = attributes.getValue(MEDIUM); + boolean validTypeMedia = false; + boolean validTypeImage = false; + + boolean isDefault = "true".equals(defaultStr); + + if (MEDIUM_AUDIO.equals(medium) || MEDIUM_VIDEO.equals(medium)) { + validTypeMedia = true; + } else if (MEDIUM_IMAGE.equals(medium)) { + validTypeImage = true; + } else { + if (type == null) { + type = SyndTypeUtils.getMimeTypeFromUrl(url); + } + + if (SyndTypeUtils.enclosureTypeValid(type)) { + validTypeMedia = true; + } else if (SyndTypeUtils.imageTypeValid(type)) { + validTypeImage = true; + } + } + + if (state.getCurrentItem() != null && + (state.getCurrentItem().getMedia() == null || isDefault) && + url != null && validTypeMedia) { long size = 0; String sizeStr = attributes.getValue(SIZE); try { @@ -51,25 +82,56 @@ public class NSMedia extends Namespace { String durationStr = attributes.getValue(DURATION); if (!TextUtils.isEmpty(durationStr)) { try { - long duration = Long.parseLong(durationStr); + long duration = Long.parseLong(durationStr); durationMs = (int) TimeUnit.MILLISECONDS.convert(duration, TimeUnit.SECONDS); } catch (NumberFormatException e) { Log.e(TAG, "Duration \"" + durationStr + "\" could not be parsed"); } } FeedMedia media = new FeedMedia(state.getCurrentItem(), url, size, type); - if(durationMs > 0) { + if (durationMs > 0) { media.setDuration(durationMs); } state.getCurrentItem().setMedia(media); + } else if (state.getCurrentItem() != null && url != null && validTypeImage) { + FeedImage image = new FeedImage(); + image.setDownload_url(url); + image.setOwner(state.getCurrentItem()); + + state.getCurrentItem().setImage(image); + } + } else if (IMAGE.equals(localName)) { + String url = attributes.getValue(IMAGE_URL); + if (url != null) { + FeedImage image = new FeedImage(); + image.setDownload_url(url); + + if (state.getCurrentItem() != null) { + image.setOwner(state.getCurrentItem()); + state.getCurrentItem().setImage(image); + } else { + if (state.getFeed().getImage() == null) { + image.setOwner(state.getFeed()); + state.getFeed().setImage(image); + } + } } + } else if (DESCRIPTION.equals(localName)) { + String type = attributes.getValue(DESCRIPTION_TYPE); + return new AtomText(localName, this, type); } return new SyndElement(localName, this); } @Override public void handleElementEnd(String localName, HandlerState state) { - + if (DESCRIPTION.equals(localName)) { + String content = state.getContentBuf().toString(); + if (state.getCurrentItem() != null && content != null && + state.getCurrentItem().getDescription() == null) { + state.getCurrentItem().setDescription(content); + } + } } - } + diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java index 1c7952a56..3d752df76 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java @@ -20,25 +20,27 @@ import de.danoeh.antennapod.core.util.DateUtils; * */ public class NSRSS20 extends Namespace { - private static final String TAG = "NSRSS20"; - public static final String NSTAG = "rss"; - public static final String NSURI = ""; - - public final static String CHANNEL = "channel"; - public final static String ITEM = "item"; - public final static String GUID = "guid"; - public final static String TITLE = "title"; - public final static String LINK = "link"; - public final static String DESCR = "description"; - public final static String PUBDATE = "pubDate"; - public final static String ENCLOSURE = "enclosure"; - public final static String IMAGE = "image"; - public final static String URL = "url"; - public final static String LANGUAGE = "language"; - - public final static String ENC_URL = "url"; - public final static String ENC_LEN = "length"; - public final static String ENC_TYPE = "type"; + + private static final String TAG = "NSRSS20"; + + private static final String NSTAG = "rss"; + private static final String NSURI = ""; + + public static final String CHANNEL = "channel"; + public static final String ITEM = "item"; + private static final String GUID = "guid"; + private static final String TITLE = "title"; + private static final String LINK = "link"; + private static final String DESCR = "description"; + private static final String PUBDATE = "pubDate"; + private static final String ENCLOSURE = "enclosure"; + private static final String IMAGE = "image"; + private static final String URL = "url"; + private static final String LANGUAGE = "language"; + + private static final String ENC_URL = "url"; + private static final String ENC_LEN = "length"; + private static final String ENC_TYPE = "type"; @Override public SyndElement handleElementStart(String localName, HandlerState state, @@ -51,15 +53,16 @@ public class NSRSS20 extends Namespace { } else if (ENCLOSURE.equals(localName)) { String type = attributes.getValue(ENC_TYPE); String url = attributes.getValue(ENC_URL); - boolean validType; - if(SyndTypeUtils.enclosureTypeValid(type)) { - validType = true; - } else { - type = type = SyndTypeUtils.getValidMimeTypeFromUrl(url); - validType = type != null; - } - if (state.getCurrentItem() != null && state.getCurrentItem().getMedia() == null && - validType) { + + boolean validType = SyndTypeUtils.enclosureTypeValid(type); + if(!validType) { + type = SyndTypeUtils.getMimeTypeFromUrl(url); + validType = SyndTypeUtils.enclosureTypeValid(type); + } + + boolean validUrl = !TextUtils.isEmpty(url); + if (state.getCurrentItem() != null && state.getCurrentItem().getMedia() == null && + validType && validUrl) { long size = 0; try { size = Long.parseLong(attributes.getValue(ENC_LEN)); @@ -70,8 +73,8 @@ public class NSRSS20 extends Namespace { } catch (NumberFormatException e) { Log.d(TAG, "Length attribute could not be parsed."); } - state.getCurrentItem().setMedia( - new FeedMedia(state.getCurrentItem(), url, size, type)); + FeedMedia media = new FeedMedia(state.getCurrentItem(), url, size, type); + state.getCurrentItem().setMedia(media); } } else if (IMAGE.equals(localName)) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java index 7b5abf053..cfb20d578 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java @@ -28,8 +28,11 @@ public class NSAtom extends Namespace { private static final String LINK = "link"; private static final String UPDATED = "updated"; private static final String AUTHOR = "author"; + private static final String AUTHOR_NAME = "name"; private static final String CONTENT = "content"; - private static final String IMAGE = "logo"; + private static final String SUMMARY = "summary"; + private static final String IMAGE_LOGO = "logo"; + private static final String IMAGE_ICON = "icon"; private static final String SUBTITLE = "subtitle"; private static final String PUBLISHED = "published"; @@ -42,6 +45,7 @@ public class NSAtom extends Namespace { private static final String LINK_LENGTH = "length"; // rel-values private static final String LINK_REL_ALTERNATE = "alternate"; + private static final String LINK_REL_ARCHIVES = "archives"; private static final String LINK_REL_ENCLOSURE = "enclosure"; private static final String LINK_REL_PAYMENT = "payment"; private static final String LINK_REL_RELATED = "related"; @@ -57,8 +61,8 @@ public class NSAtom extends Namespace { /** * Regexp to test whether an Element is a Text Element. */ - private static final String isText = TITLE + "|" + CONTENT + "|" + "|" - + SUBTITLE; + private static final String isText = TITLE + "|" + CONTENT + "|" + + SUBTITLE + "|" + SUMMARY; public static final String isFeed = FEED + "|" + NSRSS20.CHANNEL; public static final String isFeedItem = ENTRY + "|" + NSRSS20.ITEM; @@ -91,14 +95,12 @@ public class NSAtom extends Namespace { Log.d(TAG, "Length attribute could not be parsed."); } String type = attributes.getValue(LINK_TYPE); - boolean validType; - if(SyndTypeUtils.enclosureTypeValid(type)) { - validType = true; - } else { - type = SyndTypeUtils.getValidMimeTypeFromUrl(href); - validType = type != null; + + if (type == null) { + type = SyndTypeUtils.getMimeTypeFromUrl(href); } - if (validType) { + + if(SyndTypeUtils.enclosureTypeValid(type)) { FeedItem currItem = state.getCurrentItem(); if(currItem != null && !currItem.hasMedia()) { currItem.setMedia(new FeedMedia(currItem, href, size, type)); @@ -127,6 +129,17 @@ public class NSAtom extends Namespace { } state.addAlternateFeedUrl(title, href); } + } else if (LINK_REL_ARCHIVES.equals(rel) && state.getFeed() != null) { + String type = attributes.getValue(LINK_TYPE); + if (LINK_TYPE_ATOM.equals(type) || LINK_TYPE_RSS.equals(type)) { + String title = attributes.getValue(LINK_TITLE); + if (TextUtils.isEmpty(title)) { + title = href; + } + state.addAlternateFeedUrl(title, href); + } else if (LINK_TYPE_HTML.equals(type) || LINK_TYPE_XHTML.equals(type)) { + //A Link such as to a directory such as iTunes + } } else if (LINK_REL_PAYMENT.equals(rel) && state.getFeed() != null) { state.getFeed().setPaymentLink(href); } else if (LINK_REL_NEXT.equals(rel) && state.getFeed() != null) { @@ -189,15 +202,27 @@ public class NSAtom extends Namespace { } else if (CONTENT.equals(top) && ENTRY.equals(second) && textElement != null && state.getCurrentItem() != null) { state.getCurrentItem().setDescription(textElement.getProcessedContent()); + } else if (SUMMARY.equals(top) && ENTRY.equals(second) && textElement != null && + state.getCurrentItem() != null && state.getCurrentItem().getDescription() == null) { + state.getCurrentItem().setDescription(textElement.getProcessedContent()); } else if (UPDATED.equals(top) && ENTRY.equals(second) && state.getCurrentItem() != null && state.getCurrentItem().getPubDate() == null) { state.getCurrentItem().setPubDate(DateUtils.parse(content)); } else if (PUBLISHED.equals(top) && ENTRY.equals(second) && state.getCurrentItem() != null) { state.getCurrentItem().setPubDate(DateUtils.parse(content)); - } else if (IMAGE.equals(top) && state.getFeed() != null && state.getFeed().getImage() == null) { + } else if (IMAGE_LOGO.equals(top) && state.getFeed() != null && state.getFeed().getImage() == null) { state.getFeed().setImage(new FeedImage(state.getFeed(), content, null)); + } else if (IMAGE_ICON.equals(top) && state.getFeed() != null) { + state.getFeed().setImage(new FeedImage(state.getFeed(), content, null)); + } else if (AUTHOR_NAME.equals(top) && AUTHOR.equals(second) && + state.getFeed() != null && state.getCurrentItem() == null) { + String currentName = state.getFeed().getAuthor(); + if (currentName == null) { + state.getFeed().setAuthor(content); + } else { + state.getFeed().setAuthor(currentName + ", " + content); + } } } } - } diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/util/SyndTypeUtils.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/util/SyndTypeUtils.java index e84361fb2..1d564ab0e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/util/SyndTypeUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/util/SyndTypeUtils.java @@ -1,13 +1,22 @@ package de.danoeh.antennapod.core.syndication.util; +import android.text.TextUtils; import android.webkit.MimeTypeMap; + import org.apache.commons.io.FilenameUtils; +import java.util.Arrays; + /** Utility class for handling MIME-Types of enclosures */ public class SyndTypeUtils { - private final static String VALID_MIMETYPE = "audio/.*" + "|" + "video/.*" - + "|" + "application/ogg"; + private static final String VALID_MEDIA_MIMETYPE = TextUtils.join("|", Arrays.asList( + "audio/.*", + "video/.*", + "application/ogg", + "application/octet-stream")); + + private static final String VALID_IMAGE_MIMETYPE = "image/.*"; private SyndTypeUtils() { @@ -17,9 +26,17 @@ public class SyndTypeUtils { if (type == null) { return false; } else { - return type.matches(VALID_MIMETYPE); + return type.matches(VALID_MEDIA_MIMETYPE); } } + public static boolean imageTypeValid(String type) { + if (type == null) { + return false; + } else { + return type.matches(VALID_IMAGE_MIMETYPE); + } + } + /** * Should be used if mime-type of enclosure tag is not supported. This @@ -27,15 +44,27 @@ public class SyndTypeUtils { * the type is not supported, this method will return null. */ public static String getValidMimeTypeFromUrl(String url) { - if (url != null) { - String extension = FilenameUtils.getExtension(url); - if (extension != null) { - String type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); - if (type != null && enclosureTypeValid(type)) { - return type; - } - } + String type = getMimeTypeFromUrl(url); + if (enclosureTypeValid(type)) { + return type; + } else { + return null; } - return null; + } + + /** + * Should be used if mime-type of enclosure tag is not supported. This + * method will return the mime-type of the file extension. + */ + public static String getMimeTypeFromUrl(String url) { + if (url == null) { + return null; + } + String extension = FilenameUtils.getExtension(url); + if (extension == null) { + return null; + } + + return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java index a8c78ed9a..ead897136 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java @@ -16,42 +16,47 @@ import java.util.TimeZone; * Parses several date formats. */ public class DateUtils { + private DateUtils(){} - + private static final String TAG = "DateUtils"; private static final TimeZone defaultTimezone = TimeZone.getTimeZone("GMT"); public static Date parse(final String input) { - if(input == null) { + if (input == null) { throw new IllegalArgumentException("Date must not be null"); } String date = input.trim().replace('/', '-').replaceAll("( ){2,}+", " "); + // CEST is widely used but not in the "ISO 8601 Time zone" list. Let's hack around. + date = date.replaceAll("CEST$", "+02:00"); + date = date.replaceAll("CET$", "+01:00"); + // if datetime is more precise than seconds, make sure the value is in ms - if(date.contains(".")) { + if (date.contains(".")) { int start = date.indexOf('.'); - int current = start+1; - while(current < date.length() && Character.isDigit(date.charAt(current))) { + int current = start + 1; + while (current < date.length() && Character.isDigit(date.charAt(current))) { current++; } // even more precise than microseconds: discard further decimal places - if(current - start > 4) { - if(current < date.length()-1) { + if (current - start > 4) { + if (current < date.length() - 1) { date = date.substring(0, start + 4) + date.substring(current); } else { date = date.substring(0, start + 4); } - // less than 4 decimal places: pad to have a consistent format for the parser - } else if(current - start < 4) { - if(current < date.length()-1) { - date = date.substring(0, current) + StringUtils.repeat("0", 4-(current-start)) + date.substring(current); + // less than 4 decimal places: pad to have a consistent format for the parser + } else if (current - start < 4) { + if (current < date.length() - 1) { + date = date.substring(0, current) + StringUtils.repeat("0", 4 - (current - start)) + date.substring(current); } else { - date = date.substring(0, current) + StringUtils.repeat("0", 4-(current-start)); + date = date.substring(0, current) + StringUtils.repeat("0", 4 - (current - start)); } } } - String[] patterns = { + final String[] patterns = { "dd MMM yy HH:mm:ss Z", "dd MMM yy HH:mm Z", "EEE, dd MMM yyyy HH:mm:ss Z", @@ -77,6 +82,7 @@ public class DateUtils { "yyyy-MM-dd'T'HH:mm:ss.SSS", "yyyy-MM-dd'T'HH:mm:ssZ", "yyyy-MM-dd'T'HH:mm:ss'Z'", + "yyyy-MM-dd'T'HH:mm:ss.SSSZ", "yyyy-MM-ddZ", "yyyy-MM-dd" }; @@ -86,7 +92,7 @@ public class DateUtils { parser.setTimeZone(defaultTimezone); ParsePosition pos = new ParsePosition(0); - for(String pattern : patterns) { + for (String pattern : patterns) { parser.applyPattern(pattern); pos.setIndex(0); try { @@ -94,11 +100,16 @@ public class DateUtils { if (result != null && pos.getIndex() == date.length()) { return result; } - } catch(Exception e) { + } catch (Exception e) { Log.e(TAG, Log.getStackTraceString(e)); } } + // if date string starts with a weekday, try parsing date string without it + if(date.matches("^\\w+, .*$")) { + return parse(date.substring(date.indexOf(',') + 1)); + } + Log.d(TAG, "Could not parse date string \"" + input + "\" [" + date + "]"); return null; } @@ -144,7 +155,7 @@ public class DateUtils { } public static String formatAbbrev(final Context context, final Date date) { - if(date == null) { + if (date == null) { return ""; } GregorianCalendar cal = new GregorianCalendar(); @@ -153,7 +164,7 @@ public class DateUtils { cal.add(GregorianCalendar.DAY_OF_MONTH, 10); boolean withinLastYear = date.after(cal.getTime()); int format = android.text.format.DateUtils.FORMAT_ABBREV_ALL; - if(withinLastYear) { + if (withinLastYear) { format |= android.text.format.DateUtils.FORMAT_NO_YEAR; } return android.text.format.DateUtils.formatDateTime(context, date.getTime(), format); diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/FileNameGenerator.java b/core/src/main/java/de/danoeh/antennapod/core/util/FileNameGenerator.java index 30c2e62f2..8da176c82 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/FileNameGenerator.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/FileNameGenerator.java @@ -1,18 +1,21 @@ package de.danoeh.antennapod.core.util; +import org.apache.commons.lang3.ArrayUtils; + import java.util.Arrays; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** Generates valid filenames for a given string. */ public class FileNameGenerator { - private static final char[] ILLEGAL_CHARACTERS = { '/', '\\', '?', '%', - '*', ':', '|', '"', '<', '>', '\n' }; - static { - Arrays.sort(ILLEGAL_CHARACTERS); - } + private static final char[] validChars = ( + "abcdefghijklmnopqrstuvwxyz" + + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + + "0123456789" + + " _-").toCharArray(); private FileNameGenerator() { - } /** @@ -20,17 +23,17 @@ public class FileNameGenerator { * characters of the given string. */ public static String generateFileName(String string) { - StringBuilder builder = new StringBuilder(); + StringBuilder buf = new StringBuilder(); for (int i = 0; i < string.length(); i++) { char c = string.charAt(i); - if (Arrays.binarySearch(ILLEGAL_CHARACTERS, c) < 0) { - builder.append(c); + if(Character.isSpaceChar(c) && (buf.length() == 0 || Character.isSpaceChar(buf.charAt(buf.length()-1)))) { + continue; + } + if (ArrayUtils.contains(validChars, c)) { + buf.append(c); } } - return builder.toString().replaceFirst(" *$",""); + return buf.toString().trim(); } - public static long generateLong(final String str) { - return str.hashCode(); - } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/Flavors.java b/core/src/main/java/de/danoeh/antennapod/core/util/Flavors.java new file mode 100644 index 000000000..5feb232e7 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/util/Flavors.java @@ -0,0 +1,24 @@ +package de.danoeh.antennapod.core.util; + +import de.danoeh.antennapod.core.BuildConfig; + +/** + * Helper class to handle the different build flavors. + */ +public enum Flavors { + FREE, + PLAY, + UNKNOWN; + + public static final Flavors FLAVOR; + + static { + if (BuildConfig.FLAVOR.equals("free")) { + FLAVOR = FREE; + } else if (BuildConfig.FLAVOR.equals("play")) { + FLAVOR = PLAY; + } else { + FLAVOR = UNKNOWN; + } + } +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/IntentUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/IntentUtils.java index 9e5e41b6c..9e35833da 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/IntentUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/IntentUtils.java @@ -10,10 +10,18 @@ import java.util.List; public class IntentUtils { private IntentUtils(){} + /* + * Checks if there is at least one exported activity that can be performed for the intent + */ public static boolean isCallable(final Context context, final Intent intent) { List<ResolveInfo> list = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); - return list.size() > 0; + for(ResolveInfo info : list) { + if(info.activityInfo.exported) { + return true; + } + } + return false; } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/NetworkUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/NetworkUtils.java index 57647a576..34ad8b8a2 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/NetworkUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/NetworkUtils.java @@ -5,13 +5,9 @@ import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; +import android.support.v4.net.ConnectivityManagerCompat; import android.text.TextUtils; import android.util.Log; - -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.Request; -import com.squareup.okhttp.Response; - import java.io.File; import java.io.IOException; import java.util.Arrays; @@ -21,6 +17,9 @@ import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; import de.danoeh.antennapod.core.storage.DBWriter; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; import rx.Observable; import rx.Subscriber; import rx.android.schedulers.AndroidSchedulers; @@ -68,6 +67,16 @@ public class NetworkUtils { } } } + } else { + if (!UserPreferences.isEnableAutodownloadOnMobile()) { + Log.d(TAG, "Auto Download not enabled on Mobile"); + return false; + } + if (networkInfo.isRoaming()) { + Log.d(TAG, "Roaming on foreign network"); + return false; + } + return true; } } Log.d(TAG, "Network for auto-dl is not available"); @@ -81,16 +90,13 @@ public class NetworkUtils { } public static boolean isDownloadAllowed() { - return UserPreferences.isAllowMobileUpdate() || NetworkUtils.connectedToWifi(); + return UserPreferences.isAllowMobileUpdate() || !NetworkUtils.isNetworkMetered(); } - public static boolean connectedToWifi() { + public static boolean isNetworkMetered() { ConnectivityManager connManager = (ConnectivityManager) context .getSystemService(Context.CONNECTIVITY_SERVICE); - NetworkInfo mWifi = connManager - .getNetworkInfo(ConnectivityManager.TYPE_WIFI); - - return mWifi.isConnected(); + return ConnectivityManagerCompat.isActiveNetworkMetered(connManager); } /** diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/QueueSorter.java b/core/src/main/java/de/danoeh/antennapod/core/util/QueueSorter.java index 5dc194dbd..c3b4c0e15 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/QueueSorter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/QueueSorter.java @@ -13,22 +13,24 @@ import de.danoeh.antennapod.core.storage.DBWriter; */ public class QueueSorter { public enum Rule { - ALPHA_ASC, - ALPHA_DESC, + EPISODE_TITLE_ASC, + EPISODE_TITLE_DESC, DATE_ASC, DATE_DESC, DURATION_ASC, - DURATION_DESC + DURATION_DESC, + FEED_TITLE_ASC, + FEED_TITLE_DESC } public static void sort(final Context context, final Rule rule, final boolean broadcastUpdate) { Comparator<FeedItem> comparator = null; switch (rule) { - case ALPHA_ASC: + case EPISODE_TITLE_ASC: comparator = (f1, f2) -> f1.getTitle().compareTo(f2.getTitle()); break; - case ALPHA_DESC: + case EPISODE_TITLE_DESC: comparator = (f1, f2) -> f2.getTitle().compareTo(f1.getTitle()); break; case DATE_ASC: @@ -59,6 +61,13 @@ public class QueueSorter { return -1 * (duration1 - duration2); }; + break; + case FEED_TITLE_ASC: + comparator = (f1, f2) -> f1.getFeed().getTitle().compareTo(f2.getFeed().getTitle()); + break; + case FEED_TITLE_DESC: + comparator = (f1, f2) -> f2.getFeed().getTitle().compareTo(f1.getFeed().getTitle()); + break; default: } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java index 35916a604..887c0055c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java @@ -3,9 +3,13 @@ package de.danoeh.antennapod.core.util; import android.content.Context; import android.content.Intent; +import android.net.Uri; import de.danoeh.antennapod.core.R; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.feed.FeedItem; +import de.danoeh.antennapod.core.feed.FeedMedia; + +import java.io.File; /** Utility methods for sharing data */ public class ShareUtils { @@ -58,4 +62,11 @@ public class ShareUtils { shareLink(context, text); } + public static void shareFeedItemFile(Context context, FeedMedia media) { + Intent i = new Intent(Intent.ACTION_SEND); + i.setType(media.getMime_type()); + i.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(media.getLocalMediaUrl()))); + i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + context.startActivity(Intent.createChooser(i, context.getString(R.string.share_file_label))); + } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/URLChecker.java b/core/src/main/java/de/danoeh/antennapod/core/util/URLChecker.java index 415a1d3a2..40faa1dd2 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/URLChecker.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/URLChecker.java @@ -37,6 +37,9 @@ public final class URLChecker { } else if (url.startsWith("pcast://")) { if (BuildConfig.DEBUG) Log.d(TAG, "Removing pcast://"); return prepareURL(url.substring("pcast://".length())); + } else if (url.startsWith("pcast:")) { + if (BuildConfig.DEBUG) Log.d(TAG, "Removing pcast:"); + return prepareURL(url.substring("pcast:".length())); } else if (url.startsWith("itpc")) { if (BuildConfig.DEBUG) Log.d(TAG, "Replacing itpc:// with http://"); return url.replaceFirst("itpc://", "http://"); diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/comparator/SearchResultValueComparator.java b/core/src/main/java/de/danoeh/antennapod/core/util/comparator/SearchResultValueComparator.java index b16e0949d..d23901a45 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/comparator/SearchResultValueComparator.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/comparator/SearchResultValueComparator.java @@ -1,14 +1,27 @@ package de.danoeh.antennapod.core.util.comparator; +import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.SearchResult; import java.util.Comparator; public class SearchResultValueComparator implements Comparator<SearchResult> { + /** + * Compare items based, first, on where they were found (ie. title, chapters, or show notes). + * If they were found in the same section, then compare based on the title, in lexicographic + * order. This is still not ideal since, for example, "#12 Example A" would be considered + * before "#8 Example B" due to the fact that "8" has a larger unicode value than "1" + */ @Override public int compare(SearchResult lhs, SearchResult rhs) { - return rhs.getValue() - lhs.getValue(); + int value = rhs.getValue() - lhs.getValue(); + if (value == 0 && lhs.getComponent() instanceof FeedItem && rhs.getComponent() instanceof FeedItem) { + String lhsTitle = ((FeedItem) lhs.getComponent()).getTitle(); + String rhsTitle = ((FeedItem) rhs.getComponent()).getTitle(); + return lhsTitle.compareTo(rhsTitle); + } + return value; } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrServiceCreator.java b/core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrServiceCreator.java index d3a1e3e14..2103ae3b2 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrServiceCreator.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrServiceCreator.java @@ -17,14 +17,14 @@ public class FlattrServiceCreator { private static volatile FlattrService flattrService; - public synchronized static FlattrService getService(AccessToken token) { + public static synchronized FlattrService getService(AccessToken token) { if (flattrService == null) { flattrService = FlattrFactory.getInstance().createFlattrService(token); } return flattrService; } - public synchronized static void deleteFlattrService() { + public static synchronized void deleteFlattrService() { if (BuildConfig.DEBUG) Log.d(TAG, "Deleting service instance"); flattrService = null; } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/ExternalMedia.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/ExternalMedia.java index 412a27b95..c4acdb65e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/ExternalMedia.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/ExternalMedia.java @@ -1,9 +1,9 @@ package de.danoeh.antennapod.core.util.playback; +import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.media.MediaMetadataRetriever; -import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; @@ -206,7 +206,12 @@ public class ExternalMedia implements Playable { } @Override - public void onPlaybackCompleted() { + public void onPlaybackPause(Context context) { + + } + + @Override + public void onPlaybackCompleted(Context context) { } @@ -242,9 +247,9 @@ public class ExternalMedia implements Playable { }; @Override - public Uri getImageUri() { + public String getImageLocation() { if (localFileAvailable()) { - return new Uri.Builder().scheme(SCHEME_MEDIA).encodedPath(getLocalMediaUrl()).build(); + return getLocalMediaUrl(); } else { return null; } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java index 90cd53b64..cb0757522 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java @@ -8,7 +8,6 @@ import android.util.Log; import java.util.List; import de.danoeh.antennapod.core.asynctask.ImageResource; -import de.danoeh.antennapod.core.cast.RemoteMedia; import de.danoeh.antennapod.core.feed.Chapter; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.MediaType; @@ -139,14 +138,27 @@ public interface Playable extends Parcelable, void setLastPlayedTime(long lastPlayedTimestamp); /** - * Is called by the PlaybackService when playback starts. + * This method should be called every time playback starts on this object. + * <p/> + * Position held by this Playable should be set accurately before a call to this method is made. */ void onPlaybackStart(); /** - * Is called by the PlaybackService when playback is completed. + * This method should be called every time playback pauses or stops on this object, + * including just before a seeking operation is performed, after which a call to + * {@link #onPlaybackStart()} should be made. If playback completes, calling this method is not + * necessary, as long as a call to {@link #onPlaybackCompleted(Context)} is made. + * <p/> + * Position held by this Playable should be set accurately before a call to this method is made. */ - void onPlaybackCompleted(); + void onPlaybackPause(Context context); + + /** + * This method should be called when playback completes for this object. + * @param context + */ + void onPlaybackCompleted(Context context); /** * Returns an integer that must be unique among all Playable classes. The @@ -186,9 +198,6 @@ public interface Playable extends Parcelable, case ExternalMedia.PLAYABLE_TYPE_EXTERNAL_MEDIA: result = createExternalMediaInstance(pref); break; - case RemoteMedia.PLAYABLE_TYPE_REMOTE_MEDIA: - result = createRemoteMediaInstance(pref); - break; } if (result == null) { Log.e(TAG, "Could not restore Playable object from preferences"); @@ -217,12 +226,6 @@ public interface Playable extends Parcelable, } return result; } - - private static Playable createRemoteMediaInstance(SharedPreferences pref) { - //TODO there's probably no point in restoring RemoteMedia from preferences, because we - //only care about it while it's playing on the cast device. - return null; - } } class PlayableException extends Exception { diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java index 041831e80..9d3854f41 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java @@ -65,7 +65,7 @@ public abstract class PlaybackController { private static final int SCHED_EX_POOLSIZE = 1; private MediaPositionObserver positionObserver; - private ScheduledFuture positionObserverFuture; + private ScheduledFuture<?> positionObserverFuture; private boolean mediaInfoLoaded = false; private boolean released = false; @@ -197,9 +197,7 @@ public abstract class PlaybackController { mConnection, 0); } Log.d(TAG, "Result for service binding: " + bound); - }, error -> { - Log.e(TAG, Log.getStackTraceString(error)); - }); + }, error -> Log.e(TAG, Log.getStackTraceString(error))); } /** @@ -218,7 +216,7 @@ public abstract class PlaybackController { Intent serviceIntent = new Intent(activity, PlaybackService.class); serviceIntent.putExtra(PlaybackService.EXTRA_PLAYABLE, media); serviceIntent.putExtra(PlaybackService.EXTRA_START_WHEN_PREPARED, false); - serviceIntent.putExtra(PlaybackService.EXTRA_PREPARE_IMMEDIATELY, false); + serviceIntent.putExtra(PlaybackService.EXTRA_PREPARE_IMMEDIATELY, true); boolean fileExists = media.localFileAvailable(); boolean lastIsStream = PlaybackPreferences.getCurrentEpisodeIsStream(); if (!fileExists && !lastIsStream && media instanceof FeedMedia) { @@ -463,6 +461,7 @@ public abstract class PlaybackController { checkMediaInfoLoaded(); postStatusMsg(R.string.player_ready_msg, false); updatePlayButtonAppearance(playResource, playText); + onPositionObserverUpdate(); break; case SEEKING: onPositionObserverUpdate(); diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/syndication/HtmlToPlainText.java b/core/src/main/java/de/danoeh/antennapod/core/util/syndication/HtmlToPlainText.java new file mode 100644 index 000000000..bd40f398d --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/util/syndication/HtmlToPlainText.java @@ -0,0 +1,89 @@ +package de.danoeh.antennapod.core.util.syndication; + +import org.jsoup.helper.StringUtil; +import org.jsoup.nodes.Element; +import org.jsoup.nodes.Node; +import org.jsoup.nodes.TextNode; +import org.jsoup.select.NodeTraversor; +import org.jsoup.select.NodeVisitor; + +/** + * This class is based on <code>HtmlToPlainText</code> from jsoup's examples package. + * + * HTML to plain-text. This example program demonstrates the use of jsoup to convert HTML input to lightly-formatted + * plain-text. That is divergent from the general goal of jsoup's .text() methods, which is to get clean data from a + * scrape. + * <p> + * Note that this is a fairly simplistic formatter -- for real world use you'll want to embrace and extend. + * </p> + * <p> + * To invoke from the command line, assuming you've downloaded the jsoup jar to your current directory:</p> + * <p><code>java -cp jsoup.jar org.jsoup.examples.HtmlToPlainText url [selector]</code></p> + * where <i>url</i> is the URL to fetch, and <i>selector</i> is an optional CSS selector. + * + * @author Jonathan Hedley, jonathan@hedley.net + * @author AntennaPod open source community + */ +public class HtmlToPlainText { + + /** + * Format an Element to plain-text + * @param element the root element to format + * @return formatted text + */ + public String getPlainText(Element element) { + FormattingVisitor formatter = new FormattingVisitor(); + NodeTraversor traversor = new NodeTraversor(formatter); + traversor.traverse(element); // walk the DOM, and call .head() and .tail() for each node + + return formatter.toString(); + } + + // the formatting rules, implemented in a breadth-first DOM traverse + private class FormattingVisitor implements NodeVisitor { + + private StringBuilder accum = new StringBuilder(); // holds the accumulated text + + // hit when the node is first seen + public void head(Node node, int depth) { + String name = node.nodeName(); + if (node instanceof TextNode) { + append(((TextNode) node).text()); // TextNodes carry all user-readable text in the DOM. + } + else if (name.equals("li")) { + append("\n * "); + } + else if (name.equals("dt")) { + append(" "); + } + else if (StringUtil.in(name, "p", "h1", "h2", "h3", "h4", "h5", "tr")) { + append("\n"); + } + } + + // hit when all of the node's children (if any) have been visited + public void tail(Node node, int depth) { + String name = node.nodeName(); + if (StringUtil.in(name, "br", "dd", "dt", "p", "h1", "h2", "h3", "h4", "h5")) { + append("\n"); + } else if (name.equals("a")) { + append(String.format(" <%s>", node.absUrl("href"))); + } + } + + // appends text to the string builder with a simple word wrap method + private void append(String text) { + if (text.equals(" ") && + (accum.length() == 0 || StringUtil.in(accum.substring(accum.length() - 1), " ", "\n"))) { + return; // don't accumulate long runs of empty spaces + } + + accum.append(text); + } + + @Override + public String toString() { + return accum.toString(); + } + } +} diff --git a/core/src/main/res/drawable/bg_splash.xml b/core/src/main/res/drawable/bg_splash.xml new file mode 100644 index 000000000..dd66e3083 --- /dev/null +++ b/core/src/main/res/drawable/bg_splash.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> + + <item + android:drawable="@color/overlay_dark"/> + + <item> + <bitmap + android:gravity="center" + android:src="@drawable/ic_launcher"/> + </item> + +</layer-list>
\ No newline at end of file diff --git a/core/src/main/res/drawable/ic_notification.png b/core/src/main/res/drawable/ic_notification.png Binary files differnew file mode 100644 index 000000000..8bd22b54a --- /dev/null +++ b/core/src/main/res/drawable/ic_notification.png diff --git a/core/src/main/res/values-az/strings.xml b/core/src/main/res/values-az/strings.xml index 10771d8f8..bde3d8393 100644 --- a/core/src/main/res/values-az/strings.xml +++ b/core/src/main/res/values-az/strings.xml @@ -1,17 +1,13 @@ <?xml version='1.0' encoding='UTF-8'?> <resources xmlns:tools="http://schemas.android.com/tools"> <!--Activitiy and fragment titles--> - <string name="app_name">AntennaPod</string> <string name="feeds_label">Kanallar</string> - <string name="podcasts_label">PODKASTLAR</string> <string name="new_label">Yeni</string> - <string name="waiting_list_label">GözlÉ™mÉ™dÉ™</string> <string name="settings_label">ParametrlÉ™r</string> <string name="downloads_label">YüklÉ™mÉ™lÉ™r</string> <string name="cancel_download_label">YüklÉ™mÉ™yi ləğv et</string> <string name="playback_history_label">Oynatma tarixiçəsi</string> <string name="gpodnet_main_label">gpodder.net</string> - <!--New episodes fragment--> <!--Statistics fragment--> <!--Main activity--> <!--Webview actions--> @@ -45,7 +41,6 @@ <string name="mark_all_read_label">Hamısını oxunmuÅŸ kimi iÅŸarÉ™lÉ™</string> <string name="show_info_label">MÉ™lumatı göstÉ™r</string> <string name="share_link_label">Web-sÉ™hifÉ™yi paylaÅŸ</string> - <string name="feed_delete_confirmation_msg">Bütün kanallar vÉ™ epizodlar silinəçək.</string> <!--actions on feeditems--> <string name="download_label">YüklÉ™</string> <string name="play_label">Oynat</string> @@ -58,8 +53,6 @@ <string name="remove_from_queue_label">NövbÉ™dÉ™n sil</string> <string name="visit_website_label">Web-sÉ™hifÉ™sini aç</string> <string name="support_label">Flattrla</string> - <string name="enqueue_all_new">Hamsını növbÉ™yÉ™ É™lavÉ™ et</string> - <string name="download_all">Hamısını yüklÉ™</string> <string name="skip_episode_label">Epizodu burax</string> <!--Download messages and labels--> <string name="download_pending">YüklÉ™mÉ™ gözlÉ™nir</string> @@ -95,7 +88,6 @@ <string name="playback_error_server_died">Server iÅŸtÉ™mir</string> <string name="playback_error_unknown">NamÉ™lum xÉ™ta</string> <string name="no_media_playing_label">Heç nÉ™ oynadılmır</string> - <string name="position_default_label">00:00:00</string> <string name="player_buffering_msg">BuferləşmÉ™</string> <string name="playbackservice_notification_title">Podkast oynadılır</string> <!--Queue operations--> @@ -160,8 +152,6 @@ <string name="pref_update_interval_hours_manual">Æl ilÉ™</string> <!--Auto-Flattr dialog--> <!--Search--> - <string name="search_hint">Kanalları vÉ™ ya epizodları axtar</string> - <string name="found_in_shownotes_label">TÉ™svirlÉ™rdÉ™ tapıldı</string> <string name="found_in_chapters_label">FÉ™sillÉ™rdÉ™ tapıldı</string> <string name="search_status_no_results">Heç nÉ™ tapılmadı</string> <string name="search_label">Axtar</string> @@ -202,7 +192,11 @@ <!--Feed information screen--> <!--Progress information--> <!--AntennaPodSP--> + <!--Episodes apply actions--> + <!--Sort--> <!--Rating dialog--> <!--Audio controls--> <!--proxy settings--> + <!--Casting--> + <!--<string name="cast_failed_to_connect">Could not connect to the device</string>--> </resources> diff --git a/core/src/main/res/values-b+ast/strings.xml b/core/src/main/res/values-b+ast/strings.xml new file mode 100644 index 000000000..87ca9ed3e --- /dev/null +++ b/core/src/main/res/values-b+ast/strings.xml @@ -0,0 +1,381 @@ +<?xml version='1.0' encoding='UTF-8'?> +<resources xmlns:tools="http://schemas.android.com/tools"> + <!--Activitiy and fragment titles--> + <string name="feeds_label">Feeds</string> + <string name="statistics_label">EstadÃstiques</string> + <string name="add_feed_label">Amestar podcast</string> + <string name="episodes_label">Episodios</string> + <string name="all_episodes_short_label">Too</string> + <string name="favorite_episodes_label">Favoritos</string> + <string name="new_label">Nuevo</string> + <string name="settings_label">Axustes</string> + <string name="add_new_feed_label">Amestar podcast</string> + <string name="downloads_label">Descargues</string> + <string name="downloads_running_label">N\'execución</string> + <string name="downloads_completed_label">Completóse</string> + <string name="downloads_log_label">Rexistru</string> + <string name="subscriptions_label">Soscripciones</string> + <string name="subscriptions_list_label">Llistáu de soscripciones</string> + <string name="cancel_download_label">Encaboxar\ndescarga</string> + <string name="playback_history_label">Historial de reproducción</string> + <string name="gpodnet_main_label">gpodder.net</string> + <string name="gpodnet_auth_label">Aniciu de sesión de gpodder.net</string> + <string name="free_space_label">%1$s llibres</string> + <string name="episode_cache_full_title">Enllenóse la caché d\'episodios</string> + <string name="episode_cache_full_message">Algamóse la llende de la caché d\'episodios. Pues aumentar el tamañu de la caché n\'Axustes.</string> + <!--Statistics fragment--> + <string name="total_time_listened_to_podcasts">Tiempu total de podcasts reproducÃos.</string> + <string name="statistics_details_dialog">%1$d de %2$d episodios aniciaos.\n\nReproducÃos %3$s de %4$s.</string> + <!--Main activity--> + <string name="drawer_open">Abrir menú</string> + <string name="drawer_close">Zarrar menú</string> + <string name="drawer_preferences">Preferencies del caxón</string> + <string name="drawer_feed_order_unplayed_episodes">Ordenar pel contador</string> + <string name="drawer_feed_order_alphabetical">Ordenar alfabéticamente</string> + <string name="drawer_feed_order_last_update">Ordenar pela data d\'espublización</string> + <string name="drawer_feed_counter_new_unplayed">Númberu de episodios nuevos ensin reproducir</string> + <string name="drawer_feed_counter_new">Númberu d\'episodios nuevos</string> + <string name="drawer_feed_counter_unplayed">Númberos d\'episodios ensin reproducir</string> + <string name="drawer_feed_counter_downloaded">Númberu d\'episodios baxaos</string> + <string name="drawer_feed_counter_none">Dengún</string> + <!--Webview actions--> + <string name="open_in_browser_label">Abrir nel restolador</string> + <string name="copy_url_label">Copiar URL</string> + <string name="share_url_label">Compartir URL</string> + <string name="copied_url_msg">Copióse la URL al cartafueyu</string> + <string name="go_to_position_label">Dir a esta posición</string> + <!--Playback history--> + <string name="clear_history_label">Llimpiar historial</string> + <!--Other--> + <string name="confirm_label">Confirmar</string> + <string name="cancel_label">Encaboxar</string> + <string name="yes">SÃ</string> + <string name="no">Non</string> + <string name="reset">Reafitar</string> + <string name="author_label">Autor</string> + <string name="language_label">Llingua</string> + <string name="url_label">URL</string> + <string name="podcast_settings_label">Axustes</string> + <string name="cover_label">Semeya</string> + <string name="error_label">Fallu</string> + <string name="error_msg_prefix">Asocedió un fallu:</string> + <string name="refresh_label">Refrescar</string> + <string name="external_storage_error_msg">Nun hai disponible dengún almacenamientu esternu. Asegúrate que ta montáu pa que l\'aplicación puea furrular afayadizamente.</string> + <string name="chapters_label">CapÃtulos</string> + <string name="description_label">Descripción</string> + <string name="most_recent_prefix">Episodiu más recién:\u0020</string> + <string name="episodes_suffix">\u0020episodios</string> + <string name="length_prefix">Llargor:\u0020</string> + <string name="size_prefix">Tamañu:\u0020</string> + <string name="processing_label">Procesando</string> + <string name="loading_label">Cargando...</string> + <string name="save_username_password_label">Guardar nome d\'usuariu y contraseña</string> + <string name="close_label">Zarrar</string> + <string name="retry_label">Retentar</string> + <string name="auto_download_label">Incluyir en descargues automátiques</string> + <string name="auto_download_apply_to_items_title">Aplicar a episodios previos</string> + <string name="parallel_downloads_suffix">\u0020descargues paraleles</string> + <string name="feed_auto_download_always">Siempres</string> + <string name="feed_auto_download_never">Enxamás</string> + <string name="send_label">Unviar...</string> + <string name="episode_cleanup_never">Enxamás</string> + <string name="episode_cleanup_queue_removal">Al nun tar na cola</string> + <string name="episode_cleanup_after_listening">Dempués de finar</string> + <plurals name="episode_cleanup_days_after_listening"> + <item quantity="one">1 dÃa dempués de finar</item> + <item quantity="other">%d dÃes dempués de finar</item> + </plurals> + <!--'Add Feed' Activity labels--> + <string name="feedurl_label">URL del feed</string> + <string name="etxtFeedurlHint">www.exemplu.com/feed</string> + <string name="txtvfeedurl_label">Amestar podcast pola URL</string> + <string name="podcastdirectories_label">Alcontrar podcast nel direutoriu</string> + <string name="podcastdirectories_descr">Pa podcasts nuevos, pues guetar n\'iTunes o fyyd, o restolar gpodder.net per nome, estaya o sonadÃa.</string> + <string name="browse_gpoddernet_label">Restolar gpodder.net</string> + <!--Actions on feeds--> + <string name="mark_all_read_label">Marcar too ccomo reproducÃo</string> + <string name="mark_all_read_msg">Conseñáronse tolos episodios como reproducÃos</string> + <string name="mark_all_read_confirmation_msg">Confirma que quies conseñar tolos episodios como reproducÃos, por favor.</string> + <string name="mark_all_read_feed_confirmation_msg">Confirma que quies conseñar tolos episodios nesti feed como reproducÃos, por favor.</string> + <string name="mark_all_seen_label">Conseñar too como visto</string> + <string name="mark_all_seen_msg">Conseñáronse tolos episodios como vistos</string> + <string name="mark_all_seen_confirmation_msg">Confirma que quies conseñar tolos episodios como vistos.</string> + <string name="show_info_label">Amosar información</string> + <string name="rename_feed_label">Renomar podcast</string> + <string name="remove_feed_label">Desaniciar podcast</string> + <string name="share_label">Compartir...</string> + <string name="share_link_label">Compartir enllaz</string> + <string name="share_feed_url_label">Compartir URL del feed</string> + <string name="share_item_url_label">Compatir URL del ficheru del episodiu</string> + <string name="feed_remover_msg">Desaniciando fees</string> + <string name="load_complete_feed">Completóse\'l refrescu\'l feed</string> + <string name="hide_episodes_title">Anubrir episodios</string> + <string name="episode_actions">Aplicar aiciones</string> + <string name="hide_unplayed_episodes_label">Ensin reproducir</string> + <string name="hide_paused_episodes_label">Posóse</string> + <string name="hide_played_episodes_label">Reprodúxose</string> + <string name="hide_queued_episodes_label">Na cola</string> + <string name="hide_downloaded_episodes_label">Baxóse</string> + <string name="hide_not_downloaded_episodes_label">Nun se baxó</string> + <string name="hide_has_media_label">Tien medios</string> + <string name="filtered_label">Peñéróse</string> + <string name="open_podcast">Abrir podcast</string> + <!--actions on feeditems--> + <string name="download_label">Baxar</string> + <string name="play_label">Reproducir</string> + <string name="pause_label">Posar</string> + <string name="stop_label">Parar</string> + <string name="remove_label">Desaniciar</string> + <string name="delete_label">Desaniciar</string> + <string name="remove_episode_lable">Desaniciar episodiu</string> + <string name="marked_as_seen_label">Conseñóse como vistu</string> + <string name="mark_read_label">Conseñar como reproducÃu</string> + <string name="marked_as_read_label">Conseñóse como reproducÃu</string> + <string name="mark_unread_label">Conseñar como non reproducÃu</string> + <string name="add_to_queue_label">Amestar a la cola</string> + <string name="added_to_queue_label">Amestóse a la cola</string> + <string name="remove_from_queue_label">Desaniciar de la cola</string> + <string name="add_to_favorite_label">Amestar a favoritos</string> + <string name="added_to_favorites">Amestóse a favoritos</string> + <string name="remove_from_favorite_label">Desaniciar de favoritos</string> + <string name="removed_from_favorites">Desanicióse de favoritos</string> + <string name="visit_website_label">Visitar sitiu web</string> + <string name="skip_episode_label">Saltar episodiu</string> + <string name="activate_auto_download">Activar descarga automática</string> + <string name="deactivate_auto_download">Desactivar descarga automática</string> + <string name="reset_position">Reaniciar posición de reproducción</string> + <string name="removed_item">Desanicióse l\'elementu</string> + <!--Download messages and labels--> + <string name="download_failed">falló</string> + <string name="download_pending">Descarga pendiente</string> + <string name="download_running">Descarga n\'execución</string> + <string name="download_error_device_not_found">Nun s\'alcontró\'l preséu d\'almacenamientu</string> + <string name="download_error_insufficient_space">Espaciu insuficiente</string> + <string name="download_error_file_error">Fallu de ficheru</string> + <string name="download_error_http_data_error">Fallu de datos HTTP</string> + <string name="download_error_error_unknown">Fallu desconocÃu</string> + <string name="download_error_parser_exception">Esceición del analizador</string> + <string name="download_error_unsupported_type">Triba non sofitada de feed</string> + <string name="download_error_connection_error">Fallu de conexón</string> + <string name="download_error_unknown_host">Agospiu desconocÃu</string> + <string name="download_error_unauthorized">Fallu d\'autenticación</string> + <string name="download_error_file_type_type">Fallu de triba de ficheru</string> + <string name="download_error_forbidden">ProhibÃo</string> + <string name="cancel_all_downloads_label">Encaboxar toles descargues</string> + <string name="download_canceled_msg">Encaboxóse la descarga</string> + <string name="download_canceled_autodownload_enabled_msg">Encaboxóse la descarga\nDesabilitóse la <i>auto-descarga</i> pa esti elementu</string> + <string name="download_report_title">Les descargues completáronse con fallos</string> + <string name="download_report_content_title">Informe de descarga</string> + <string name="download_error_malformed_url">URL mal formada</string> + <string name="download_error_io_error">Fallu d\'ES</string> + <string name="download_error_request_error">Fallu de solicitú</string> + <string name="download_error_db_access">Fallu d\'accesu a la base de datos</string> + <plurals name="downloads_left"> + <item quantity="one">%d descarga restante</item> + <item quantity="other">%d descargues restantes</item> + </plurals> + <string name="downloads_processing">Procesando descargues</string> + <string name="download_notification_title">Baxando datos del podcast</string> + <string name="download_report_content">%1$d descargues esitoses, %2$d fallaron</string> + <string name="download_log_title_unknown">TÃtulu desconocÃu</string> + <string name="download_type_feed">Feed</string> + <string name="download_type_media">Triba de mediu</string> + <string name="download_type_image">Imaxe</string> + <string name="download_request_error_dialog_message_prefix">Asocedió un fallu al tentar de baxar el ficheru:\u0020</string> + <string name="authentication_notification_title">RÃquese l\'autenticación</string> + <string name="authentication_notification_msg">El recursu que solicitesti rique un nome d\'usuariu y una contraseña</string> + <string name="confirm_mobile_download_dialog_title">Confirmar descarga móvil</string> + <string name="confirm_mobile_download_dialog_message_not_in_queue">Deshabilitóse n\'axustes la descarga pente datos móviles.\n\nPues escoyer ente amestar l\'episodiu a la cola o permitir la descarga temporal.\n\n<small>La to escoyeta recordaráse 10 minutos</small></string> + <string name="confirm_mobile_download_dialog_message">Deshabilitóse n\'axustes la descarga pente datos móviles.\n\n¿Quies permitir la descarga temporal?\n\n<small>La to escoyeta recordaráse 10 minutos</small></string> + <string name="confirm_mobile_download_dialog_only_add_to_queue">Poner na cola</string> + <string name="confirm_mobile_download_dialog_enable_temporarily">Pemitir temporalmente</string> + <!--Mediaplayer messages--> + <string name="player_error_msg">¡Fallu!</string> + <string name="player_stopped_msg">Nun hai medios en reproducción</string> + <string name="player_preparing_msg">Tresnando</string> + <string name="player_ready_msg">Preparáu</string> + <string name="playback_error_server_died">Morrió\'l servidor</string> + <string name="playback_error_unknown">Fallu desconocÃu</string> + <string name="no_media_playing_label">Nun hai medios en reproducción</string> + <string name="player_buffering_msg">Atroxando nel búfer</string> + <string name="playbackservice_notification_title">Reproduciendo podcast</string> + <string name="unknown_media_key">AntennaPod - Clave desconocida de medios: %1$d</string> + <!--Queue operations--> + <string name="lock_queue">Bloquiar cola</string> + <string name="unlock_queue">Desbloquiar cola</string> + <string name="queue_locked">Bloquióse la cola</string> + <string name="queue_unlocked">Desbloquióse la cola</string> + <string name="clear_queue_label">Llimpiar cola</string> + <string name="undo">Desfacer</string> + <string name="removed_from_queue">Desanicióse l\'elementu</string> + <string name="move_to_top_label">Xubir</string> + <string name="move_to_bottom_label">Baxar</string> + <string name="sort">Ordenar</string> + <string name="date">Data</string> + <string name="duration">Duración</string> + <string name="episode_title">TÃtulu d\'episodiu</string> + <string name="feed_title">TÃtulu del feed</string> + <string name="ascending">Ascendente</string> + <string name="descending">Descendente</string> + <string name="clear_queue_confirmation_msg">Confirma que quies llimpiar la tola de TOLO episodios nella, por favor.</string> + <!--Flattr--> + <string name="flattr_auth_label">Aniciu de sesión de Flattr</string> + <string name="flattr_auth_explanation">Primi\'l botón d\'embaxo pa entamar el procesu d\'autenticación. Amosaráse la pantalla d\'aniciu de sesión de Flattr y pidirásete que-y deas permisu a AntennaPod pa facer flattr a coses. Dempués d\'eso, volverás a esta pantalla automáticamente.</string> + <string name="authenticate_label">Autenticar</string> + <string name="return_home_label">Volver al aniciu</string> + <string name="flattr_auth_success">¡L\'autenticación tuvo ésitu! Agora pues facer flattr a coses dientro l\'aplicación.</string> + <string name="no_flattr_token_title">Nun s\'alcontró\'l pase de Flattr</string> + <string name="no_flattr_token_notification_msg">La to cuenta Flattr nun paez tar coneutada con AntennaPod. Calca equà p\'autenticar.</string> + <string name="no_flattr_token_msg">La to cuenta Flattr nun paez tar coneutada con AntennaPod. Pues o coneutar la cuenta con AntennaPod pa facer Flattr a coses dientro l\'aplicación, o pues visitar el sitiu web de la cosa a facer Flattr.</string> + <string name="authenticate_now_label">Autenticar</string> + <string name="action_forbidden_title">Torgóse la aición</string> + <string name="action_forbidden_msg">AntennaPod nun tien permisu pa esta aición. La razón quiciabes seya que se revocare\'l pase d\'accesu d\'AntennaPod a la to cuenta. Pues o reautenticate, o visitar el sitiu web de la cosa.</string> + <string name="access_revoked_title">Revocóse l\'accesu</string> + <string name="access_revoked_info">Revoquesti con ésitu\'l pase d\'accesu AntennaPod a la to cuenta. Pa completar el procesu, tienes de desaniciar esta aplicación del llistáu d\'aplicaciones aprobaes nos axustes de la to cuenta nel sitiu web de Flattr.</string> + <!--Flattr--> + <!--Variable Speed--> + <string name="download_plugin_label">Baxar complementu</string> + <string name="no_playback_plugin_title">Nun s\'instaló\'l complementu</string> + <string name="set_playback_speed_label">Velocidaes de reproducción</string> + <!--Empty list labels--> + <string name="no_items_label">Nun hai elementos nesti llistáu.</string> + <string name="no_feeds_label">Entá nun tas soscritu a feed dalu.</string> + <string name="no_chapters_label">Esti episodiu nun tien capÃtulos.</string> + <!--Preferences--> + <string name="storage_pref">Almacenamientu</string> + <string name="project_pref">Proyeutu</string> + <string name="services_label">Servicios</string> + <string name="flattr_label">Flattr</string> + <string name="pref_episode_cleanup_title">Llimpieza d\'episodios</string> + <string name="pref_pauseOnDisconnect_sum">Posa la reproducción al desconeutase los auriculares o Bluetooth</string> + <string name="pref_unpauseOnHeadsetReconnect_sum">Sigue la reproducción al coneutar los auriculares</string> + <string name="pref_unpauseOnBluetoothReconnect_sum">Sigue la reproducción al reconeutar el Bluetooth</string> + <string name="pref_auto_delete_sum">Desanicia l\'episodiu al completase la reproducción</string> + <string name="pref_skip_keeps_episodes_sum">Caltién los episodios al saltalos</string> + <string name="pref_skip_keeps_episodes_title">Caltener episodios saltaos</string> + <string name="playback_pref">Reproducción</string> + <string name="network_pref">Rede</string> + <string name="pref_autoUpdateIntervallOrTime_sum">Especifica un intervalu o una hora especÃfica del dÃa pa refrescar automáticamente los feeds</string> + <string name="pref_autoUpdateIntervallOrTime_Interval">Afitar intervalu</string> + <string name="pref_autoUpdateIntervallOrTime_every">cada %1$s</string> + <string name="pref_downloadMediaOnWifiOnly_sum">Baxa los ficheros de medios namái na WiFi</string> + <string name="pref_followQueue_title">Reproducción continua</string> + <string name="pref_mobileUpdate_sum">Permite los anovamientos pente la conexón de datos móviles</string> + <string name="refreshing_label">Refrescando</string> + <string name="flattr_settings_label">Axustes de Flattr</string> + <string name="pref_flattr_auth_title">Aniciu de sesión de Flattr</string> + <string name="pref_revokeAccess_sum">Revoca\'l permisu d\'accesu a la to cuenta Flatrr pa esta aplicación.</string> + <string name="pref_nav_drawer_sum">Personaliza l\'aspeutu del caxón de navegación.</string> + <string name="pref_nav_drawer_items_sum">Camuda qué elementos apaecen nel caxón de navegación.</string> + <string name="pref_nav_drawer_feed_order_sum">Camuda l\'orde de les tos soscripciones</string> + <string name="pref_nav_drawer_feed_counter_sum">Camuda la información amosada pol contador de soscripciones</string> + <string name="pref_set_theme_sum">Camuda l\'aspeutu d\'AntennaPod</string> + <string name="pref_automatic_download_sum">Configura la descarga automática d\'episodios.</string> + <string name="pref_autodl_wifi_filter_sum">Permite la descarga namái dende les redes Wi-Fi esbillaes.</string> + <string name="pref_automatic_download_on_battery_sum">Permite la descarga automárica cuando la baterÃa nun tea cargando.</string> + <string name="pref_episode_cache_title">Caché d\'episodios</string> + <string name="pref_update_interval_hours_plural">hores</string> + <string name="pref_update_interval_hours_singular">hora</string> + <string name="pref_update_interval_hours_manual">Manual</string> + <string name="pref_gpodnet_authenticate_sum">Anicia sesión cola to cuenta de gpodder.net pa sincronizar les tos soscripciones.</string> + <string name="pref_gpodnet_setlogin_information_sum">Camuda la información d\'aniciu de sesión de la to cuenta de gpodder.net.</string> + <string name="pref_gpodnet_notifications_sum">Esti axuste nun s\'aplica a los fallos d\'autenticación.</string> + <string name="pref_playback_speed_title">Velocidaes de reproducción</string> + <string name="pref_expandNotify_title">Espander avisu</string> + <string name="pref_expandNotify_sum">Siempres espande l\'avisu p\'amosar los botones de reproducción.</string> + <string name="pref_showDownloadReport_title">Amosar informe de descarga</string> + <string name="pref_showDownloadReport_sum">SI falla la descarga, xenera un informe qu\'amuesa los detalles del fallu.</string> + <string name="pref_image_cache_size_sum">Tamañu del discu pa la caché d\'imáxenes.</string> + <string name="crash_report_title">Informe de casque</string> + <string name="experimental_pref">Esperimental</string> + <string name="pref_proxy_sum">Afita un proxy de rede</string> + <string name="pref_faq">FAQ</string> + <string name="pref_known_issues">Problemes conocÃos</string> + <string name="pref_no_browser_found">Nun s\'alcontró un restolador web.</string> + <string name="pref_cast_title">Sofitu de Chromecast</string> + <!--Auto-Flattr dialog--> + <!--Search--> + <!--OPML import and export--> + <string name="start_import_label">Aniciar importación</string> + <string name="opml_import_label">Importación d\'OPML</string> + <string name="opml_directory_error">¡Fallu!</string> + <string name="reading_opml_label">Lleendo\'l ficheru OPML</string> + <string name="opml_reader_error">Asocedió un fallu entrÃn se lleÃa\'l documentu OPML:</string> + <string name="opml_import_error_no_file">¡Nun s\'esbillaron ficheros!</string> + <string name="select_all_label">Esbillar too</string> + <string name="deselect_all_label">Nun esbillar nada</string> + <string name="select_options_label">Esbillar...</string> + <string name="opml_export_label">Esportación d\'OPML</string> + <string name="html_export_label">Esportación de HTML</string> + <string name="exporting_label">Esportando...</string> + <string name="export_error_label">Fallu d\'esportación</string> + <string name="opml_import_ask_read_permission">RÃquese l\'accesu al almacenamientu internu pa lleer el ficheru OPML</string> + <!--Sleep timer--> + <string name="timer_vibration_label">Vibrar</string> + <string name="time_seconds">segundos</string> + <string name="time_minutes">minutos</string> + <string name="time_hours">hores</string> + <!--gpodder.net--> + <string name="gpodnet_taglist_header">ESTAYES</string> + <string name="gpodnet_toplist_header">DESTACAO</string> + <string name="gpodnet_suggestions_header">SUXERENCIES</string> + <string name="username_label">Nome d\'usuariu</string> + <string name="password_label">Contraseña</string> + <string name="gpodnetauth_device_title">Esbilla de preséu</string> + <string name="gpodnetauth_device_descr">Crea un preséu nuevu pa usalu cola to cuente de gpodder.net o escueyi ún esistente:</string> + <string name="gpodnetauth_device_deviceID">ID de preséu:\u0020</string> + <string name="gpodnetauth_device_butCreateNewDevice">Crear preséu nuevu</string> + <string name="gpodnetauth_device_chooseExistingDevice">Escoyer preséu esistente:</string> + <string name="gpodnetauth_device_errorEmpty">La ID del preséu nun ha tar balera</string> + <string name="gpodnetauth_device_errorAlreadyUsed">La ID del preséu yá ta n\'usu</string> + <string name="gpodnetauth_device_butChoose">Escoyer</string> + <string name="gpodnetauth_finish_butgomainscreen">Dir a la pantalla principal</string> + <string name="gpodnetsync_auth_error_title">Fallu d\'autenticación de gpodder.net</string> + <string name="gpodnetsync_error_descr">Asocedió un fallu na sincronización:\u0020</string> + <!--Directory chooser--> + <string name="selected_folder_label">Carpeta esbillada:</string> + <string name="create_folder_label">Crear carpeta</string> + <string name="choose_data_directory_permission_rationale">RÃquese l\'accesu al almacenamientu esternu pa camudar la carpeta de datos</string> + <string name="create_folder_msg">¿Crear carpeta nueva col nome «%1$s»?</string> + <string name="create_folder_success">Creóse la carpeta nueva</string> + <string name="create_folder_error_no_write_access">Nun pue escribise a esta carpeta</string> + <string name="create_folder_error_already_exists">Yá esiste la carpeta</string> + <string name="create_folder_error">Nun pudo crease la carpeta</string> + <string name="folder_not_empty_dialog_title">La carpeta nun ta balera</string> + <!--Online feed view--> + <string name="downloading_label">Baxando...</string> + <!--Content descriptions for image buttons--> + <string name="rewind_label">Rebobinar</string> + <string name="fast_forward_label">Avance rápidu</string> + <string name="media_type_audio_label">Audiu</string> + <string name="media_type_video_label">Videu</string> + <!--Feed information screen--> + <string name="authentication_label">Autenticación</string> + <!--Progress information--> + <!--AntennaPodSP--> + <!--Episodes apply actions--> + <string name="all_label">Too</string> + <string name="selected_all_label">Esbilláronse tolos episodios</string> + <!--Sort--> + <!--Rating dialog--> + <string name="rating_title">¿Préstate AntennaPod?</string> + <string name="rating_message">Agradeceriemos que valores a AntennaPod si pues y quies.</string> + <string name="rating_never_label">Dexáime solu</string> + <string name="rating_later_label">Recordáimelo más sero</string> + <string name="rating_now_label">¡SÃ, vamos facelo!</string> + <!--Audio controls--> + <string name="audio_controls">Controles d\'audiu</string> + <string name="playback_speed">Velocidá de reproducción</string> + <string name="volume">Volume</string> + <string name="left_short">I</string> + <string name="right_short">D</string> + <string name="audio_effects">Efeutos d\'audiu</string> + <!--proxy settings--> + <string name="proxy_type_label">Triba</string> + <string name="host_label">Agospiu</string> + <string name="port_label">Puertu</string> + <string name="optional_hint">(Opcional)</string> + <string name="proxy_checking">Comprobando...</string> + <!--Casting--> + <!--<string name="cast_failed_to_connect">Could not connect to the device</string>--> +</resources> diff --git a/core/src/main/res/values-ca-rES/strings.xml b/core/src/main/res/values-ca-rES/strings.xml index 28dfeb6e8..4b0bf218c 100644 --- a/core/src/main/res/values-ca-rES/strings.xml +++ b/core/src/main/res/values-ca-rES/strings.xml @@ -1,8 +1,31 @@ <?xml version='1.0' encoding='UTF-8'?> <resources xmlns:tools="http://schemas.android.com/tools"> <!--Activitiy and fragment titles--> + <string name="statistics_label">EstadÃstiques</string> + <string name="add_feed_label">Afegir Podcast</string> + <string name="episodes_label">Episodis</string> + <string name="all_episodes_short_label">Tots</string> + <string name="favorite_episodes_label">Preferits</string> + <string name="new_label">Nous</string> + <string name="settings_label">Ajustaments</string> + <string name="add_new_feed_label">Afegir Podcast</string> + <string name="downloads_label">Descà rregues</string> + <string name="downloads_running_label">Actius</string> + <string name="downloads_completed_label">Finalitzats</string> + <string name="downloads_log_label">Log</string> + <string name="subscriptions_label">Subscripcions</string> + <string name="subscriptions_list_label">Llista de subscripcions</string> + <string name="playback_history_label">Historial de Reproducció</string> + <string name="gpodnet_main_label">gpodder.net</string> + <string name="gpodnet_auth_label">gpodder.net Login</string> + <string name="free_space_label">%1$s lliures</string> + <string name="episode_cache_full_title">Cache d´episodis ple</string> <!--Statistics fragment--> <!--Main activity--> + <string name="drawer_feed_order_alphabetical">Ordenar alfabeticament</string> + <string name="drawer_feed_order_last_update">Ordenar per data de publicacio</string> + <string name="drawer_feed_counter_new_unplayed">Nombre d´episodis nous mes nombre d´episodis no reproduits</string> + <string name="drawer_feed_counter_new">Nombre de episodis nous</string> <!--Webview actions--> <!--Playback history--> <!--Other--> diff --git a/core/src/main/res/values-ca/strings.xml b/core/src/main/res/values-ca/strings.xml index b8516001f..349dde72c 100644 --- a/core/src/main/res/values-ca/strings.xml +++ b/core/src/main/res/values-ca/strings.xml @@ -2,6 +2,7 @@ <resources xmlns:tools="http://schemas.android.com/tools"> <!--Activitiy and fragment titles--> <string name="feeds_label">Canals</string> + <string name="statistics_label">EstadÃstiques</string> <string name="add_feed_label">Afegeix podcast</string> <string name="episodes_label">Episodis</string> <string name="all_episodes_short_label">Tot</string> @@ -13,14 +14,22 @@ <string name="downloads_running_label">En execució</string> <string name="downloads_completed_label">Completat</string> <string name="downloads_log_label">Registre</string> + <string name="subscriptions_label">Subscripcions</string> + <string name="subscriptions_list_label">Llista de subscripcions</string> <string name="cancel_download_label">Cancel·la la baixada</string> <string name="playback_history_label">Historial de reproducció</string> <string name="gpodnet_main_label">gpodder.net</string> <string name="gpodnet_auth_label">Inici de sessió a gpodder.net</string> - <string name="free_space_label">%1$s lliures</string> + <string name="free_space_label">%1$s lliure</string> <string name="episode_cache_full_title">Caché d\'episodi completa</string> <string name="episode_cache_full_message">S\'ha arribat al lÃmit de la caché. Pots incrementar la capacitat de la caché a les Opcions</string> <!--Statistics fragment--> + <string name="total_time_listened_to_podcasts">Temps total de podcasts reproduïts</string> + <string name="statistics_details_dialog">%1$d de %2$depisodis començats.\n\nReproduïts %3$s de %4$s.</string> + <string name="statistics_mode">Mode d\'estadÃstiques</string> + <string name="statistics_mode_normal">Calcula el temps que realment s\'ha reproduït. La reproducció repetida es comptarà repetides vegades, mentre que no es tindrà en compte si s\'ha marcat com a reproduït. </string> + <string name="statistics_mode_count_all">Suma tots els podcasts marcats com a reproduïts</string> + <string name="statistics_speed_not_counted">AvÃs: la velocitat de reproducció mai no es té en compte.</string> <!--Main activity--> <string name="drawer_open">Obre menú</string> <string name="drawer_close">Tanca menú</string> @@ -28,9 +37,11 @@ <string name="drawer_feed_order_unplayed_episodes">Ordre per durada</string> <string name="drawer_feed_order_alphabetical">Ordre alfabètic</string> <string name="drawer_feed_order_last_update">Ordre per data de publicació</string> + <string name="drawer_feed_order_most_played">Ordre per número d\'episodis reproduïts</string> <string name="drawer_feed_counter_new_unplayed">Número d\'episodis nous i per reproduir</string> <string name="drawer_feed_counter_new">Número de episodis nous</string> <string name="drawer_feed_counter_unplayed">Número de episodis per reproduir</string> + <string name="drawer_feed_counter_downloaded">Número d\'episodis descarregats</string> <string name="drawer_feed_counter_none">Cap</string> <!--Webview actions--> <string name="open_in_browser_label">Obre en un navegador</string> @@ -45,6 +56,7 @@ <string name="cancel_label">Cancel·la</string> <string name="yes">SÃ</string> <string name="no">No</string> + <string name="reset">Reiniciar</string> <string name="author_label">Autor</string> <string name="language_label">Llengua</string> <string name="url_label">Adreça web</string> @@ -55,6 +67,7 @@ <string name="refresh_label">Actualitza</string> <string name="external_storage_error_msg">L\'emmagatzemament extern no està disponible. Assegureu-vos que està muntat per què l\'aplicació funcioni correctament.</string> <string name="chapters_label">CapÃtols</string> + <string name="chapter_duration">Durada: %1$s</string> <string name="shownotes_label">Notes del programa</string> <string name="description_label">Descripció</string> <string name="most_recent_prefix">Episodi més recent: \u0020</string> @@ -69,7 +82,9 @@ <string name="auto_download_label">Inclou a baixades automà tiques</string> <string name="auto_download_apply_to_items_title">Aplica als episodis previs</string> <string name="auto_download_apply_to_items_message">El nou ajustament de <i>baixada automà tica</i> s\'aplicarà als nous episodis.\nVols que també sigui aplicat als episodis publicats prèviament?</string> + <string name="auto_delete_label">Esborra episodi automà ticament</string> <string name="parallel_downloads_suffix">\u0020baixades paral·leles</string> + <string name="feed_auto_download_global">Valor predeterminat global</string> <string name="feed_auto_download_always">Sempre</string> <string name="feed_auto_download_never">Mai</string> <string name="send_label">Enviar...</string> @@ -85,7 +100,7 @@ <string name="etxtFeedurlHint">URL, canal o lloc web</string> <string name="txtvfeedurl_label">Afegeix podcast amb l\'URL</string> <string name="podcastdirectories_label">Cerca podcast al directori</string> - <string name="podcastdirectories_descr">Podeu cercar nous podcasts al directori de gpodder.net mitjançant el seu nom, categoria o popularitat.</string> + <string name="podcastdirectories_descr">Per trobar podcasts nous, podeu cercar a iTunes o fyyd, o bé navegar per gpodder.net per nom, categoria o popularitat.</string> <string name="browse_gpoddernet_label">Navega gpodder.net</string> <!--Actions on feeds--> <string name="mark_all_read_label">Marca-ho tot com a llegit</string> @@ -93,13 +108,18 @@ <string name="mark_all_read_confirmation_msg">Si us plau confirma que vols marcar tots els episodis com reproduits.</string> <string name="mark_all_read_feed_confirmation_msg">Si us plau confirma que vols marcar tots els episodis d\'aquest canal com reproduits.</string> <string name="mark_all_seen_label">Marca tot com a llegit</string> + <string name="mark_all_seen_msg">S\'han marcat tots els episodis com a vistos</string> + <string name="mark_all_seen_confirmation_msg">Si us plau confirma que vols marcar tots els episodis com vistos.</string> <string name="show_info_label">Mostra informació</string> + <string name="rename_feed_label">Renombra podcast</string> <string name="remove_feed_label">Esborra podcast</string> <string name="share_label">Compartir...</string> <string name="share_link_label">Comparteix l\'enllaç</string> <string name="share_link_with_position_label">Comparteix enllaç amb posició</string> <string name="share_feed_url_label">Comparteix adreça del canal</string> - <string name="feed_delete_confirmation_msg">Confirmeu que, efectivament, voleu suprimir aquest canal i tots els episodis que us n\'heu baixat.</string> + <string name="share_item_url_label">Comparteix adreça del fitxer del canal</string> + <string name="share_item_url_with_position_label">Comparteix adreça del fitxer del canal amb posició</string> + <string name="feed_delete_confirmation_msg">Confirmeu que voleu suprimir el canal \"%1$s\" i TOTS els episodis que n\'heu descarregat.</string> <string name="feed_remover_msg">S\'està esborrant el canal</string> <string name="load_complete_feed">S\'ha actualitzat el canal</string> <string name="hide_episodes_title">Amaga Episodis</string> @@ -111,8 +131,10 @@ <string name="hide_not_queued_episodes_label">No en cua</string> <string name="hide_downloaded_episodes_label">Baixat</string> <string name="hide_not_downloaded_episodes_label">No baixat</string> + <string name="hide_has_media_label">Conté medis</string> <string name="filtered_label">Filtrat</string> <string name="refresh_failed_msg">{fa-exclamation-circle} Darrera actualització fallida</string> + <string name="open_podcast">Obrir podcast</string> <!--actions on feeditems--> <string name="download_label">Baixa</string> <string name="play_label">Reprodueix</string> @@ -120,7 +142,9 @@ <string name="stop_label">Atura</string> <string name="stream_label">Reprodueix sense baixar</string> <string name="remove_label">Suprimeix</string> + <string name="delete_label">Esborrar</string> <string name="remove_episode_lable">Esborra episodi</string> + <string name="marked_as_seen_label">Marcat com a vist</string> <string name="mark_read_label">Marca com a llegit</string> <string name="marked_as_read_label">Marcats com llegits</string> <string name="mark_unread_label">Marca com a pendent</string> @@ -153,6 +177,8 @@ <string name="download_error_connection_error">Error de connexió</string> <string name="download_error_unknown_host">Amfitrió desconegut</string> <string name="download_error_unauthorized">Error d\'autenticació</string> + <string name="download_error_file_type_type">Error de tipus de fitxer</string> + <string name="download_error_forbidden">Prohibit</string> <string name="cancel_all_downloads_label">Cancel·la totes les baixades</string> <string name="download_canceled_msg">S\'ha cancel·lat la baixada</string> <string name="download_canceled_autodownload_enabled_msg">Baixada cancel·lada\nDesactivada les <i>baixades automà tiques</i> per aquest element</string> @@ -177,8 +203,8 @@ <string name="authentication_notification_title">Cal autenticar-se</string> <string name="authentication_notification_msg">Es necessita un usuari i una contrasenya per accedir al recurs</string> <string name="confirm_mobile_download_dialog_title">Confirma baixada mòvil</string> - <string name="confirm_mobile_download_dialog_message_not_in_queue">La baixada amb conexió de dades mòvils està desactivada.\n\nPots escollir ja sigui només afegir l\'episodi a la cua o pot permetre la descà rrega de forma temporal.\n\n<small>La seva elecció serà recordada durant 10 minuts.</small></string> - <string name="confirm_mobile_download_dialog_message">La baixada amb conexió de dades mòvils està desactivada.\n\nVols permetre la descà rrega de forma temporal?\n\n<small>La seva elecció serà recordada durant 10 minuts.</small></string> + <string name="confirm_mobile_download_dialog_message_not_in_queue">La baixada amb connexió de dades mòbils està desactivada.\n\nPots escollir entre afegir l\'episodi a la cua, o permetre la descà rrega de forma temporal.\n\n<small>La teva tria es recordarà durant 10 minuts.</small></string> + <string name="confirm_mobile_download_dialog_message">La baixada amb connexió de dades mòbils està desactivada.\n\nVols permetre la descà rrega de forma temporal?\n\n<small>La teva tria es recordarà durant 10 minuts.</small></string> <string name="confirm_mobile_download_dialog_only_add_to_queue">En cua</string> <string name="confirm_mobile_download_dialog_enable_temporarily">Permetre temporalment</string> <!--Mediaplayer messages--> @@ -204,12 +230,13 @@ <string name="move_to_top_label">Mou al principi</string> <string name="move_to_bottom_label">Mou al final</string> <string name="sort">Ordena</string> - <string name="alpha">Alfabèticament</string> <string name="date">Data</string> <string name="duration">Durada</string> + <string name="episode_title">TÃtol de l\'episodi</string> + <string name="feed_title">TÃtol del feed</string> <string name="ascending">Ascendent</string> <string name="descending">Descendent</string> - <string name="clear_queue_confirmation_msg">Si us plau confirma que vols suprimir tots els episodis de la cua</string> + <string name="clear_queue_confirmation_msg">Si us plau, confirma que vols suprimir tots els episodis de la cua</string> <!--Flattr--> <string name="flattr_auth_label">Inici de sessió a Flattr</string> <string name="flattr_auth_explanation">Premeu el botó per iniciar el procés d\'autenticació. Quan s\'obri la pantalla d\'inici de sessió de Flattr al vostre navegador, introduïu les vostres credencials i concediu a AntennaPod els permisos de compartir mitjançant Flattr. En finalitzar el procés, tornareu automà ticament a aquesta pantalla.</string> @@ -239,38 +266,43 @@ <!--Variable Speed--> <string name="download_plugin_label">Baixa el connector</string> <string name="no_playback_plugin_title">Connector no instal·lat</string> - <string name="no_playback_plugin_or_sonic_msg">Per a què funcioni la velocitat de reproducció variable, recomanem activar el Sonic Media Player integrat [Android 4.1+].\n\nPer una altra banda, pots baixar el plugin de tercers <i>Prestissimo</i> de la Play Store.\nQualsevol problema amb Prestissimo no és responsabilitat d\'AntennaPod i no haurà de ser reportat al seu propietari.</string> + <string name="no_playback_plugin_or_sonic_msg">Per a què funcioni la velocitat de reproducció variable, recomanem activar el Sonic Media Player integrat [Android 4.1+].\n\nAltra opció és baixar el connector de tercers <i>Prestissimo</i> de la Play Store.\nQualsevol problema amb Prestissimo no és responsabilitat d\'AntennaPod i haurà d\'informar-ne al seu propietari.</string> <string name="set_playback_speed_label">Velocitats de reproducció</string> <string name="enable_sonic">Activa Sonic</string> <!--Empty list labels--> <string name="no_items_label">No hi ha elements a la llista.</string> <string name="no_feeds_label">No us heu subscrit a cap canal.</string> <string name="no_chapters_label">Aquest episodi no té capÃtols</string> + <string name="no_shownotes_label">Aquest episodi no té notes.</string> <!--Preferences--> + <string name="storage_pref">Emmagatzematge</string> + <string name="project_pref">Projecte</string> <string name="other_pref">Altres</string> <string name="about_pref">Quant a</string> <string name="queue_label">Cua</string> <string name="services_label">Serveis</string> <string name="flattr_label">Flattr</string> <string name="pref_episode_cleanup_title">Neteja l\'episodi</string> - <string name="pref_episode_cleanup_summary">Episodis que no es troben a la cua i no són favorits haurien de ser candidats per ser esborrats si Auto Descà rrega necessita espai per nous episodis</string> + <string name="pref_episode_cleanup_summary">Els episodis que no es troben a la cua i no són favorits haurien de ser candidats a ser esborrats si l\'Auto Descà rrega necessita espai per a nous episodis</string> <string name="pref_pauseOnDisconnect_sum">Pausa la reproducció en desconnectar els auriculars o el bluetooth</string> <string name="pref_unpauseOnHeadsetReconnect_sum">Continua la reproducció en connectar novament els auriculars</string> <string name="pref_unpauseOnBluetoothReconnect_sum">Continua la reproducció en connectar novament el bluetooth</string> - <string name="pref_hardwareForwardButtonSkips_title">Botó \'Endavant\' passa al següent</string> - <string name="pref_hardwareForwardButtonSkips_sum">Al prémer el botó de hardware \'Endavant\' passar al següent episodi en comptes d\'avançar a la reproducció</string> + <string name="pref_hardwareForwardButtonSkips_title">Endavant per saltar</string> + <string name="pref_hardwareForwardButtonSkips_sum">En prémer el botó fÃsic d\'Endavant, passar al següent episodi en comptes d\'avançar a la reproducció</string> + <string name="pref_hardwarePreviousButtonRestarts_title">Endarrere per reiniciar</string> + <string name="pref_hardwarePreviousButtonRestarts_sum">En prémer un botó fÃsic, reinicieu l\'episodi actual en lloc de rebobinar-lo</string> <string name="pref_followQueue_sum">Salta al següent element de la cua en acabar la reproducció</string> <string name="pref_auto_delete_sum">Suprimeix l\'episodi quan s\'acabi de reproduir</string> <string name="pref_auto_delete_title">Esborrat automà tic</string> <string name="pref_smart_mark_as_played_sum">Marca episodis com com reproduits, encara que quedi menys d\'una certa quantitat de segons de temps</string> - <string name="pref_smart_mark_as_played_title">Marcació intel·ligent com a reproduit</string> + <string name="pref_smart_mark_as_played_title">Marca intel·ligent com a reproduït</string> <string name="pref_skip_keeps_episodes_sum">Mantenir episodis quan són passats de llarg</string> <string name="pref_skip_keeps_episodes_title">Mantenir els episodis passats de llarg</string> <string name="playback_pref">Reproducció</string> <string name="network_pref">Xarxa</string> <string name="pref_autoUpdateIntervallOrTime_title">Actualitza interval o horari del dia</string> - <string name="pref_autoUpdateIntervallOrTime_sum">Especifica un interval o una hora especÃfica del dia per refrescar els canals de forma automà tica</string> - <string name="pref_autoUpdateIntervallOrTime_message">Pots establir un <i>interval</i> com \"cada 2 hores\", establir una <i>hora del dia</i> com \"7:00 AM\" o <i>disactiva</i> l\'actualització automà tica del conjunt.\n\n<small>Pren nota: Les actualitzacions de vegades són inexactes. Es pot trobar una breu demora.</small></string> + <string name="pref_autoUpdateIntervallOrTime_sum">Especifica un interval o una hora concreta del dia per actualitzar els canals de forma automà tica</string> + <string name="pref_autoUpdateIntervallOrTime_message">Pots establir un <i>interval</i> com ara \"cada 2 hores\", establir una <i>hora del dia</i> com ara \"7:00 AM\" o <i>disactiva</i> l\'actualització automà tica del conjunt.\n\n<small>Tingues en compte que les actualitzacions no són exactes i pot donar-se una breu demora.</small></string> <string name="pref_autoUpdateIntervallOrTime_Disable">Desactivar</string> <string name="pref_autoUpdateIntervallOrTime_Interval">Establir interval</string> <string name="pref_autoUpdateIntervallOrTime_TimeOfDay">Establir hora del dia</string> @@ -288,22 +320,22 @@ <string name="flattr_settings_label">Configuració de Flattr</string> <string name="pref_flattr_auth_title">Inici de sessió Flattr</string> <string name="pref_flattr_auth_sum">Inicieu sessió al vostre compte Flattr per compartir continguts directament des de l\'aplicació.</string> - <string name="pref_flattr_this_app_title">Compartiu aquesta aplicació amb Flattr</string> + <string name="pref_flattr_this_app_title">Recolza aquesta aplicació amb Flattr</string> <string name="pref_flattr_this_app_sum">Doneu suport al desenvolupament d\'AntennaPod compartint l\'aplicació a través de Flattr. Grà cies!</string> <string name="pref_revokeAccess_title">Revoca l\'accés</string> <string name="pref_revokeAccess_sum">Revoqueu el permÃs d\'accés d\'aquesta aplicació al vostre compte Flattr.</string> <string name="pref_auto_flattr_title">Flattr automà tic</string> <string name="pref_auto_flattr_sum">Configura la compartició automà tica per Flattr</string> <string name="user_interface_label">InterfÃcie d\'usuari</string> - <string name="pref_set_theme_title">Selecció de tema</string> - <string name="pref_nav_drawer_title">Personalitzar navegació del calaix</string> + <string name="pref_set_theme_title">Selecciona el tema</string> + <string name="pref_nav_drawer_title">Personalitza el calaix de navegació</string> <string name="pref_nav_drawer_sum">Personalitza l\'aparença del calaix de navegació.</string> - <string name="pref_nav_drawer_items_title">Establir els elements del calaix de navegació</string> - <string name="pref_nav_drawer_items_sum">Canviar els elements que apareixen al calaix de navegació.</string> - <string name="pref_nav_drawer_feed_order_title">Establir ordre de subscripció</string> - <string name="pref_nav_drawer_feed_order_sum">Canviar l\'ordre de les subscripcions</string> - <string name="pref_nav_drawer_feed_counter_title">Establir contador de subscripció</string> - <string name="pref_nav_drawer_feed_counter_sum">Canviar la informació mostrada pel comptador de subscripció</string> + <string name="pref_nav_drawer_items_title">Estableix els elements del calaix de navegació</string> + <string name="pref_nav_drawer_items_sum">Canvia els elements que apareixen al calaix de navegació.</string> + <string name="pref_nav_drawer_feed_order_title">Estableix l\'ordre de les subscripcions</string> + <string name="pref_nav_drawer_feed_order_sum">Canvia l\'ordre de les subscripcions</string> + <string name="pref_nav_drawer_feed_counter_title">Estableix el comptador de les subscripcions</string> + <string name="pref_nav_drawer_feed_counter_sum">Canvia la informació mostrada pel comptador de les subscripcions</string> <string name="pref_set_theme_sum">Canvieu l\'aparença d\'AntennaPod.</string> <string name="pref_automatic_download_title">Baixada automà tica</string> <string name="pref_automatic_download_sum">Configureu la baixada automà tica d\'episodis.</string> @@ -325,61 +357,93 @@ <string name="pref_gpodnet_logout_toast">Heu sortit de la sessió</string> <string name="pref_gpodnet_setlogin_information_title">Dades d\'inici de sessió</string> <string name="pref_gpodnet_setlogin_information_sum">Canvia les dades d\'inici de sessió del vostre compte de gpodder.net</string> + <string name="pref_gpodnet_sync_changes_title">Sincronitza els canvis ara</string> + <string name="pref_gpodnet_sync_changes_sum">Sincronitza amb gpodder.net les subscripcions i els estats dels episodis.</string> + <string name="pref_gpodnet_full_sync_title">Sincronitza per complet ara mateix</string> + <string name="pref_gpodnet_full_sync_sum">Sincronitza amb gpodder.net totes les subscripcions i els estats dels episodis.</string> + <string name="pref_gpodnet_sync_sum_last_sync_line">Darrer intent de sincronització: %1$s (%2$s)</string> + <string name="pref_gpodnet_sync_started">Sincronització en marxa</string> + <string name="pref_gpodnet_full_sync_started">Sincronització completa en marxa</string> + <string name="pref_gpodnet_login_status"><![CDATA[Connectat com a <i>%1$s</i> amb el dispositiu <i>%2$s</i>]]></string> + <string name="pref_gpodnet_notifications_title">Notifica els errors de sincronització</string> + <string name="pref_gpodnet_notifications_sum">Aquest parà metre no s\'aplica als errors d\'autenticació. </string> <string name="pref_playback_speed_title">Velocitats de reproducció</string> <string name="pref_playback_speed_sum">Personalitzeu les velocitats disponibles per a una velocitat de reproducció d\'à udio variable</string> - <string name="pref_fast_forward">Temps d\'avançada rà pida</string> - <string name="pref_rewind">Temps de rebobinat</string> + <string name="pref_fast_forward">Temps de salt de l\'Avanç rà pid</string> + <string name="pref_fast_forward_sum">Personalitzar el nombre de segons del salt endavant quan es prem el botó d\'Avanç rà pid.</string> + <string name="pref_rewind">Temps de salt del Rebobinat</string> + <string name="pref_rewind_sum">Personalitza el nombre de segons del salt endarrere quan es prem el botó de Rebobinat</string> <string name="pref_gpodnet_sethostname_title">Definex nom del servidor</string> <string name="pref_gpodnet_sethostname_use_default_host">Utilitza el servidor per defecte</string> <string name="pref_expandNotify_title">Amplia la notificació</string> <string name="pref_expandNotify_sum">Amplia sempre les notificacions per mostrar els botons de reproducció.</string> <string name="pref_persistNotify_title">Botons de reproducció persistents</string> - <string name="pref_persistNotify_sum">Mantén els controls a l\'à rea de notificacions i pantalla de bloqueig quan la reproducció estigui aturada</string> - <string name="pref_lockscreen_background_title">Establir fons de la pantalla de bloqueig</string> - <string name="pref_lockscreen_background_sum">Establir el fons de pantalla de bloqueig a la imatge de l\'episodi actual. Com efecte secundari, això també mostrarà la imatge en aplicacions de tercers.</string> + <string name="pref_persistNotify_sum">Manté els controls a l\'à rea de notificacions i pantalla de bloqueig quan la reproducció estigui aturada</string> + <string name="pref_compact_notification_buttons_title">Estableix els botons del bloqueig de pantalla</string> + <string name="pref_compact_notification_buttons_sum">Canvia els botons de reproducció al bloqueig de pantalla. Els de pausa i reproducció sempre estan inclosos. </string> + <string name="pref_compact_notification_buttons_dialog_title">Selecciona un mà xim de %1$d elements.</string> + <string name="pref_compact_notification_buttons_dialog_error">Només pots seleccionar un mà xim de %1$d elements.</string> + <string name="pref_lockscreen_background_title">Estableix el fons del bloqueig de pantalla</string> + <string name="pref_lockscreen_background_sum">Estableix el fons del bloqueig de pantalla a la imatge de l\'episodi actual. Com a efecte secundari, això també mostrarà la imatge en aplicacions de tercers.</string> <string name="pref_showDownloadReport_title">Mostra informació de baixades</string> - <string name="pref_showDownloadReport_sum">Si les descà rregues fallen, genera un informe que mostra els detalls de la falla.</string> + <string name="pref_showDownloadReport_sum">Si les descà rregues fallen, genera un informe que mostra els detalls de la fallada.</string> <string name="pref_expand_notify_unsupport_toast">Les versions d\'Android anteriors a la 4.1 no suporten les notificacions ampliades.</string> - <string name="pref_queueAddToFront_sum">Afegir nous episodis a la part davantera de la cua.</string> - <string name="pref_queueAddToFront_title">Cua al davant</string> - <string name="pref_smart_mark_as_played_disabled">Desactivar</string> + <string name="pref_queueAddToFront_sum">Afegeix nous episodis al principi de la cua.</string> + <string name="pref_queueAddToFront_title">Posa en cua al davant</string> + <string name="pref_smart_mark_as_played_disabled">Desactivat</string> <string name="pref_image_cache_size_title">Mida de la memòria cau de les imatges</string> <string name="pref_image_cache_size_sum">Mida de la memòria cau en el disc de les imatges.</string> - <string name="crash_report_title">Reportar tancament abrupte</string> - <string name="crash_report_sum">Enviar l\'últim report de tancament abrupte per e-mail</string> + <string name="crash_report_title">Informa d\'un tancament abrupte</string> + <string name="crash_report_sum">Envia l\'últim informe de tancament abrupte per e-mail</string> <string name="send_email">Envia e-mail</string> <string name="experimental_pref">Experimental</string> - <string name="pref_sonic_title">Reproductor multimèdia Sonic</string> - <string name="pref_sonic_message">Fer servir el reproductor Sonic Media integrat en comptes del reproductor natiu d\'Android i Prestissimo</string> + <string name="pref_sonic_title">Reproductor Sonic Media Player</string> + <string name="pref_sonic_message">Fes servir el reproductor Sonic Media Player integrat en comptes del reproductor natiu d\'Android i Prestissimo</string> <string name="pref_current_value">Valor actual: %1$s</string> + <string name="pref_proxy_title">Servidor intermediari</string> + <string name="pref_proxy_sum">Estableix un servidor intermediari</string> + <string name="pref_faq">PMF</string> + <string name="pref_known_issues">Problemes coneguts</string> + <string name="pref_no_browser_found">No s\'ha trobat cap navegador web.</string> + <string name="pref_cast_title">Suport per a Chromecast</string> + <string name="pref_cast_message_play_flavor">Habilita el suport per la reproducció remota en dispositius de difusió (com ara Chromecast, Audio Speakers o Android TV). </string> + <string name="pref_cast_message_free_flavor">Chromecast requereix de llibreries propietà ries de terceres parts que estan inhabilitades en aquesta versió d\'AntennaPod</string> + <string name="pref_enqueue_downloaded_title">Posa a la cua els descarregats</string> + <string name="pref_enqueue_downloaded_summary">Afegeix els episodis descarregats a la cua</string> <!--Auto-Flattr dialog--> <string name="auto_flattr_enable">Activa la compartició automà tica per Flattr</string> <string name="auto_flattr_after_percent">Comparteix per Flattr l\'episodi en haver-ne reproduït el %d per cent</string> <string name="auto_flattr_ater_beginning">Comparteix per Flattr l\'episodi en haver-ne iniciat la reproducció</string> <string name="auto_flattr_ater_end">Comparteix per Flattr l\'episodi en acabar-se\'n la reproducció</string> <!--Search--> - <string name="search_hint">Cerca canals o episodis</string> - <string name="found_in_shownotes_label">Trobat a notes del programa</string> + <string name="search_hint">Cerca episodis</string> + <string name="found_in_shownotes_label">Troba a les notes dels canals</string> <string name="found_in_chapters_label">Trobat als capÃtols</string> + <string name="found_in_authors_label">Troba als autors</string> + <string name="found_in_feeds_label">Troba als canals</string> <string name="search_status_no_results">No s\'ha trobat cap resultat</string> <string name="search_label">Cerca</string> <string name="found_in_title_label">Trobat al tÃtol</string> + <string name="no_results_for_query">No s\'han trobat resultats per \"%1$s\"</string> <!--OPML import and export--> <string name="opml_import_txtv_button_lable">Els fitxers OPML us permeten moure els podcasts d\'un gestor de podcasts a un altre.</string> <string name="opml_import_option">Opció %1$d</string> - <string name="opml_import_explanation_1">Trieu una ruta de fitxer especÃfic del sistema de fitxers local.</string> - <string name="opml_import_explanation_2">Utilitzeu una aplicació externa com Dropbox, Google Drive o el seu gestor de fitxers preferit per obrir un fitxer OPML.</string> + <string name="opml_import_explanation_1">Tria una ruta de fitxer especÃfic del sistema de fitxers local.</string> + <string name="opml_import_explanation_2">Utilitza una aplicació externa com Dropbox, Google Drive o el seu gestor de fitxers preferit per obrir un fitxer OPML.</string> <string name="opml_import_explanation_3">Algunes aplicacions com Google Mail, Dropbox, Google Drive i la majoria dels administradors d\'arxius pot <i>obrir</i> arxius OPML <i>amb</i> AntennaPod.</string> <string name="start_import_label">Inicia la importació</string> - <string name="opml_import_label">Importació OPML</string> + <string name="opml_import_label">Importació d\'OPML</string> <string name="opml_directory_error">Error!</string> <string name="reading_opml_label">S\'està llegint el fitxer OPML</string> + <string name="opml_reader_error">S\'ha produït un error en llegir el document OPML: </string> + <string name="opml_import_error_no_file">Cap fitxer seleccionat!</string> <string name="select_all_label">Selecciona-ho tot</string> <string name="deselect_all_label">Deselecciona-ho tot</string> <string name="select_options_label">Selecciona...</string> <string name="choose_file_from_filesystem">Des de sistema d\'arxius local</string> <string name="choose_file_from_external_application">Utilitza aplicació externa</string> <string name="opml_export_label">Exportació OPML</string> + <string name="html_export_label">Exporta HTML</string> <string name="exporting_label">Exportant...</string> <string name="export_error_label">Error d\'exportació</string> <string name="opml_export_success_title">S\'ha exportat l\'OPML correctament.</string> @@ -393,8 +457,8 @@ <string name="time_left_label">Temps restant:\u0020</string> <string name="time_dialog_invalid_input">L\'entrada no és và lida, ja que el temps ha de ser un nombre i no ho és</string> <string name="timer_about_to_expire_label"><b>Quan el temporitzador està a punt d\'expirar:</b></string> - <string name="shake_to_reset_label">Agitar per reiniciar el temporitzador</string> - <string name="timer_vibration_label">Vibrar</string> + <string name="shake_to_reset_label">Agita per reiniciar el temporitzador</string> + <string name="timer_vibration_label">Vibra</string> <string name="time_seconds">segons</string> <string name="time_minutes">minuts</string> <string name="time_hours">hores</string> @@ -410,6 +474,9 @@ <item quantity="one">1 hora</item> <item quantity="other">%d hores</item> </plurals> + <string name="auto_enable_label">Autohabilita</string> + <string name="sleep_timer_enabled_label">Temporitzador habilitat</string> + <string name="sleep_timer_disabled_label">Temporitzador deshabilitat</string> <!--gpodder.net--> <string name="gpodnet_taglist_header">CATEGORIES</string> <string name="gpodnet_toplist_header">TOP PODCASTS</string> @@ -429,6 +496,7 @@ <string name="gpodnetauth_device_chooseExistingDevice">Seleccioneu un dispositiu existent:</string> <string name="gpodnetauth_device_errorEmpty">L\'ID de dispositiu no pot ser buit</string> <string name="gpodnetauth_device_errorAlreadyUsed">L\'ID de dispositiu ja existeix</string> + <string name="gpodnetauth_device_caption_errorEmpty">El tÃtol no pot estar buit </string> <string name="gpodnetauth_device_butChoose">Selecciona</string> <string name="gpodnetauth_finish_title">Heu iniciat la sessió!</string> <string name="gpodnetauth_finish_descr">Felicitats! El vostre compte de gpodder.net s\'ha enllaçat amb el dispositiu. D\'ara endavant, AntennaPod sincronitzarà automà ticament les subscripcions del dispositiu al vostre compte.</string> @@ -438,6 +506,8 @@ <string name="gpodnetsync_auth_error_descr">Nom d\'usuari o contrasenya incorrectes</string> <string name="gpodnetsync_error_title">Error de sincronització a gpodder.net</string> <string name="gpodnetsync_error_descr">S\'ha produït un error durant la sincronització:\u0020</string> + <string name="gpodnetsync_pref_report_successful">Correcte</string> + <string name="gpodnetsync_pref_report_failed">Ha fallat</string> <!--Directory chooser--> <string name="selected_folder_label">Carpeta seleccionada:</string> <string name="create_folder_label">Crea una carpeta</string> @@ -457,8 +527,8 @@ <string name="set_to_default_folder">Selecciona la carpeta per defecte</string> <string name="pref_pausePlaybackForFocusLoss_sum">Pausa la reproducció en lloc de baixar el volum quan una altra app necessiti reproduir sons</string> <string name="pref_pausePlaybackForFocusLoss_title">Pausa en interrompre</string> - <string name="pref_resumeAfterCall_sum">Reprendre la reproducció després d\'una trucada telefònica</string> - <string name="pref_resumeAfterCall_title">Reprendre després d\'una trucada</string> + <string name="pref_resumeAfterCall_sum">Reprén la reproducció després d\'una trucada telefònica</string> + <string name="pref_resumeAfterCall_title">Reprén després d\'una trucada</string> <string name="pref_restart_required">AntennaPod s\'ha de reiniciar perquè aquest canvi tingui efecte.</string> <!--Online feed view--> <string name="subscribe_label">Subscriu</string> @@ -480,16 +550,17 @@ <string name="auto_download_settings_label">Opcions d\'Auto Descà rrega</string> <string name="episode_filters_label">Filtre d\'episodis</string> <string name="episode_filters_description">Llistat de termes usats per decidir si un episodi s\'ha d\'incloure o excloure en descarregar automà ticament</string> - <string name="episode_filters_include">Incloure</string> - <string name="episode_filters_exclude">Excloure</string> + <string name="episode_filters_include">Inclou</string> + <string name="episode_filters_exclude">Exclou</string> <string name="episode_filters_hint">Una paraula \n\"Diverses paraules\"</string> - <string name="keep_updated">Mantenir actualitzat</string> + <string name="keep_updated">Manté actualitzat</string> <!--Progress information--> - <string name="progress_upgrading_database">Actualització de la base de dades</string> + <string name="progress_upgrading_database">Actualitzant la base de dades</string> <!--AntennaPodSP--> <string name="sp_apps_importing_feeds_msg">S\'estan important les subscripcions des de les apps de propòsit únic...</string> <string name="search_itunes_label">Cerca a iTunes</string> - <string name="filter">Filtrar</string> + <string name="filter">Filtra</string> + <string name="search_fyyd_label">Cerca a fyyd</string> <!--Episodes apply actions--> <string name="all_label">Tot</string> <string name="selected_all_label">Selecciona tots els episodis</string> @@ -497,7 +568,7 @@ <string name="deselected_all_label">Deselecciona tots els episodis</string> <string name="played_label">Reproduit</string> <string name="selected_played_label">Selecciona episodis reproduits</string> - <string name="unplayed_label">Per reproduir</string> + <string name="unplayed_label">No reproduïts</string> <string name="selected_unplayed_label">Selecciona episodis sense reproduir</string> <string name="downloaded_label">Baixat</string> <string name="selected_downloaded_label">Selecciona episodis descarregats</string> @@ -505,8 +576,10 @@ <string name="selected_not_downloaded_label">Selecciona episodis sense descarregar</string> <string name="queued_label">En cua</string> <string name="selected_queued_label">Episodis en cua seleccionats</string> - <string name="not_queued_label">No a la cua</string> + <string name="not_queued_label">No encuat</string> <string name="selected_not_queued_label">Episodis seleccionats i no a la cua</string> + <string name="has_media">Té mitjans</string> + <string name="selected_has_media_label">Episodis amb mitjans seleccionats</string> <!--Sort--> <string name="sort_title_a_z">TÃtol (A \u2192 Z)</string> <string name="sort_title_z_a">TÃtol (Z \u2192 A)</string> @@ -530,6 +603,31 @@ <string name="stereo_to_mono">Downmix: D\'estereo a mono</string> <string name="sonic_only">Només Sonic</string> <!--proxy settings--> + <string name="proxy_type_label">Tipus</string> + <string name="host_label">Host</string> + <string name="port_label">Port</string> + <string name="optional_hint">(Opcional)</string> + <string name="proxy_test_label">Test</string> + <string name="proxy_checking">Comprovant...</string> + <string name="proxy_test_successful">Test correcte</string> + <string name="proxy_test_failed">Test fallit</string> + <string name="proxy_host_empty_error">El host no pot estar buit</string> + <string name="proxy_host_invalid_error">El host no és una adreça IP o domini và lid</string> + <string name="proxy_port_invalid_error">El port no és và lid</string> <!--Casting--> + <string name="cast_media_route_menu_title">Reproduir a...</string> + <string name="cast_disconnect_label">Desconnectar la sessió de difusió </string> + <string name="cast_not_castable">Els mitjans seleccionats no són compatibles amb el dispositiu de difusió</string> + <string name="cast_failed_to_play">Error en començar la reproducció del medi</string> + <string name="cast_failed_to_stop">Error en aturar la reproducció del medi</string> + <string name="cast_failed_to_pause">Error en pausar la reproducció del medi</string> <!--<string name="cast_failed_to_connect">Could not connect to the device</string>--> + <string name="cast_failed_setting_volume">Error en establir el volum</string> + <string name="cast_failed_no_connection">No hi ha cap connexió amb el dispositiu de difusió </string> + <string name="cast_failed_no_connection_trans">S\'ha perdut la connexió amb el dispositiu de difusió. L\'aplicació està tractant de restablir la connexió, si això és possible. Espereu uns segons i torneu-ho a provar.</string> + <string name="cast_failed_perform_action">No s\'ha pogut dur a terme l\'acció</string> + <string name="cast_failed_status_request">No s\'ha pogut sincronitzar amb el dispositiu de difusió</string> + <string name="cast_failed_seek">No s\'ha pogut cercar la nova posició al dispositiu de difusió</string> + <string name="cast_failed_receiver_player_error">El reproductor receptor ha trobat un error greu</string> + <string name="cast_failed_media_error_skipping">Error en la reproducció. Saltant...</string> </resources> diff --git a/core/src/main/res/values-cs-rCZ/strings.xml b/core/src/main/res/values-cs-rCZ/strings.xml index 127ba6675..9eb2ccb7f 100644 --- a/core/src/main/res/values-cs-rCZ/strings.xml +++ b/core/src/main/res/values-cs-rCZ/strings.xml @@ -1,24 +1,21 @@ <?xml version='1.0' encoding='UTF-8'?> <resources xmlns:tools="http://schemas.android.com/tools"> <!--Activitiy and fragment titles--> - <string name="app_name">AntennaPod</string> <string name="feeds_label">Kanály</string> <string name="statistics_label">Statistiky</string> <string name="add_feed_label">PÅ™idat podcast</string> - <string name="podcasts_label">PODCASTY</string> <string name="episodes_label">Epizody</string> - <string name="new_episodes_label">Nové epizody</string> - <string name="all_episodes_label">VÅ¡echny epizody</string> <string name="all_episodes_short_label">VÅ¡e</string> <string name="favorite_episodes_label">OblÃbené</string> <string name="new_label">Nový</string> - <string name="waiting_list_label">Seznam nepÅ™eÄtených</string> <string name="settings_label">NastavenÃ</string> <string name="add_new_feed_label">PÅ™idat podcast</string> <string name="downloads_label">StahovánÃ</string> <string name="downloads_running_label">PrávÄ› běžÃ</string> <string name="downloads_completed_label">DokonÄeno</string> <string name="downloads_log_label">Log</string> + <string name="subscriptions_label">SbÃrky</string> + <string name="subscriptions_list_label">Seznam sbÃrek</string> <string name="cancel_download_label">ZruÅ¡it stahovánÃ</string> <string name="playback_history_label">Historie pÅ™ehrávánÃ</string> <string name="gpodnet_main_label">gpodder.net</string> @@ -26,9 +23,6 @@ <string name="free_space_label">%1$s volné</string> <string name="episode_cache_full_title">Odkládacà prostor pro epizody je plný</string> <string name="episode_cache_full_message">DoÅ¡lo k zaplnÄ›nà limitu odkládacÃho prostoru pro epizody. Můžete navýšit vyhrazený prostor v NastavenÃ.</string> - <!--New episodes fragment--> - <string name="recently_published_episodes_label">Nedávno zveÅ™ejnÄ›né</string> - <string name="episode_filter_label">Zobrazit pouze nové epizody</string> <!--Statistics fragment--> <string name="total_time_listened_to_podcasts">Celkový Äas poslechnutých podcastů:</string> <string name="statistics_details_dialog">%1$d z %2$d zapoÄatých epizod.\n\nPÅ™ehraných %3$s z %4$s.</string> @@ -42,6 +36,7 @@ <string name="drawer_feed_counter_new_unplayed">PoÄet nových a nepÅ™ehraných epizod</string> <string name="drawer_feed_counter_new">PoÄet nových epizod</string> <string name="drawer_feed_counter_unplayed">PoÄet nepÅ™ehraných epizod</string> + <string name="drawer_feed_counter_downloaded">PoÄet stažených epizod</string> <string name="drawer_feed_counter_none">Žádné</string> <!--Webview actions--> <string name="open_in_browser_label">OtevÅ™Ãt v prohlÞeÄi</string> @@ -57,6 +52,7 @@ <string name="yes">Ano</string> <string name="no">Ne </string> + <string name="reset">Reset</string> <string name="author_label">Autor</string> <string name="language_label">Jazyk</string> <string name="url_label">URL</string> @@ -81,9 +77,9 @@ <string name="auto_download_label">Zahrnout do automaticky stahovaných</string> <string name="auto_download_apply_to_items_title">PoužÃt na pÅ™edchozà epizody</string> <string name="auto_download_apply_to_items_message">Nové nastavenà <i>automatického stahovánÃ</i> bude použito pro nové epizody.\nChcete ho použÃt také na epizody zveÅ™ejnÄ›né dÅ™Ãve?</string> - <string name="auto_delete_label">Automaticky smazat epizodu\n(pÅ™eskoÄit globálnà nastavenÃ)</string> + <string name="auto_delete_label">Automatické mazánà epizod</string> <string name="parallel_downloads_suffix">\u0020paralelnÃch stahovánÃ</string> - <string name="feed_auto_download_global">GlobálnÃ</string> + <string name="feed_auto_download_global">Globálnà nastavenÃ</string> <string name="feed_auto_download_always">Vždy</string> <string name="feed_auto_download_never">Nikdy</string> <string name="send_label">Odeslat</string> @@ -100,23 +96,25 @@ <string name="etxtFeedurlHint">URL nebo webová stránka kanálu</string> <string name="txtvfeedurl_label">PÅ™idat podcast pomocà URL</string> <string name="podcastdirectories_label">NajÃt podcast v seznamu</string> - <string name="podcastdirectories_descr">Můžete vyhledávat nové podcasty podle jména, kategorie nebo popularity v seznamu gpodder.net.</string> + <string name="podcastdirectories_descr">Nové podcasty můžete hledat pomocà iTunes nebo fyyd, nebo hledat na gpodder.net podle jména, kategorie Äi popularity.</string> <string name="browse_gpoddernet_label">Prohledávat gpodder.net</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">ProsÃm potvrÄte, že chcete oznaÄit vÅ¡echny vybrané epizody jako poslechnuté.</string> - <string name="mark_all_read_feed_confirmation_msg">ProsÃm potvrÄte, že chcete oznaÄit vÅ¡echny epizody z tohoto zdroje 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 z tohoto zdroje jako poslechnuté.</string> <string name="mark_all_seen_label">OznaÄit vÅ¡e jako zobrazené</string> + <string name="mark_all_seen_msg">OznaÄit vÅ¡echny epizody jako shlédnuté</string> + <string name="mark_all_seen_confirmation_msg">PotvrÄte prosÃm, že chcete oznaÄit vÅ¡echny epizody jako shlédnuté.</string> <string name="show_info_label">Informace o zdroji</string> + <string name="rename_feed_label">PÅ™ejmenovat podcast</string> <string name="remove_feed_label">Odstranit podcast</string> <string name="share_label">SdÃlet</string> <string name="share_link_label">SdÃlet odkaz</string> <string name="share_link_with_position_label">SdÃlet odkaz s pozicÃ</string> <string name="share_feed_url_label">SdÃlet URL kanálu</string> - <string name="share_item_url_label">SdÃlet URL epizody</string> - <string name="share_item_url_with_position_label">SdÃlet URL epizody s pozicÃ</string> - <string name="feed_delete_confirmation_msg">ProsÃm potvrÄte, že chcete smazat tento kanál vÄetnÄ› vÅ¡ech stažených epizod.</string> + <string name="share_item_url_label">SdÃlet URL souboru epizody</string> + <string name="share_item_url_with_position_label">SdÃlet URL souboru epizody s pozicÃ</string> <string name="feed_remover_msg">Odstranit kanál</string> <string name="load_complete_feed">Obnovit kompletnà kanál</string> <string name="hide_episodes_title">Skrýt epizody</string> @@ -128,6 +126,7 @@ <string name="hide_not_queued_episodes_label">Mimo frontu</string> <string name="hide_downloaded_episodes_label">Stažené</string> <string name="hide_not_downloaded_episodes_label">Nestažené</string> + <string name="hide_has_media_label">Obsahuje média</string> <string name="filtered_label">Filtrované</string> <string name="refresh_failed_msg">{fa-exclamation-circle} Poslednà aktualizace selhala</string> <string name="open_podcast">OtevÅ™Ãt podcast</string> @@ -138,7 +137,9 @@ <string name="stop_label">Zastavit</string> <string name="stream_label">VysÃlat</string> <string name="remove_label">Odstranit</string> + <string name="delete_label">Smazat</string> <string name="remove_episode_lable">Odstranit epizodu</string> + <string name="marked_as_seen_label">OznaÄit jako shlédnuté</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_unread_label">OznaÄit jako neposlechnuté</string> @@ -151,8 +152,6 @@ <string name="removed_from_favorites">Odebráno z oblÃbených</string> <string name="visit_website_label">NavÅ¡tÃvit stránku</string> <string name="support_label">Flattrovat</string> - <string name="enqueue_all_new">VÅ¡e do fronty</string> - <string name="download_all">Stáhnout vÅ¡e</string> <string name="skip_episode_label">PÅ™eskoÄit epizodu</string> <string name="activate_auto_download">Aktivovat automatické stahovánÃ</string> <string name="deactivate_auto_download">Deaktivovat automatické stahovánÃ</string> @@ -174,6 +173,7 @@ <string name="download_error_unknown_host">Neznámý host</string> <string name="download_error_unauthorized">Chyba pÅ™ihlášenÃ</string> <string name="download_error_file_type_type">Chyba typu souboru</string> + <string name="download_error_forbidden">Zákázáno</string> <string name="cancel_all_downloads_label">ZruÅ¡it vÅ¡echna stahovánÃ</string> <string name="download_canceled_msg">Stahovánà zruÅ¡eno</string> <string name="download_canceled_autodownload_enabled_msg">Stahovánà zruÅ¡eno\nVypnuto <i>automatické stahovánÃ</i> této položky</string> @@ -212,7 +212,6 @@ <string name="playback_error_server_died">Server nereaguje</string> <string name="playback_error_unknown">Neznámá chyba</string> <string name="no_media_playing_label">Žádné probÃhajÃcà pÅ™ehrávánÃ</string> - <string name="position_default_label">00:00:00</string> <string name="player_buffering_msg">NaÄÃtánÃ</string> <string name="playbackservice_notification_title">PÅ™ehrávaný podcast</string> <string name="unknown_media_key">AntennaPod - Neznámý klÃÄ médiÃ: %1$d</string> @@ -227,12 +226,13 @@ <string name="move_to_top_label">Posunout na zaÄátek</string> <string name="move_to_bottom_label">Posunout na konec</string> <string name="sort">ŘazenÃ</string> - <string name="alpha">AbecednÄ›</string> <string name="date">Datum</string> <string name="duration">Délka</string> + <string name="episode_title">Název epizody</string> + <string name="feed_title">Název kanálu</string> <string name="ascending">VzestupnÄ›</string> <string name="descending">SestupnÄ›</string> - <string name="clear_queue_confirmation_msg">ProsÃm potvrÄte, že chcete vyÄistit tuto frontu a VÅ ECHNY v nà obsažené epizody</string> + <string name="clear_queue_confirmation_msg">PotvrÄte prosÃm, že chcete vyÄistit tuto frontu a VÅ ECHNY v nà obsažené epizody</string> <!--Flattr--> <string name="flattr_auth_label">Flattr pÅ™ihlášenÃ</string> <string name="flattr_auth_explanation">StisknÄ›te následujÃcà tlaÄÃtko pro spuÅ¡tÄ›nà autentizaÄnÃho procesu. Budete pÅ™esmÄ›rováni na pÅ™ihlaÅ¡ovacà obrazovku flattru a vyzváni k potvrzenà udÄ›lenà práv pro použità flattru aplikacà AntennaPod. Po udÄ›lenà práv se automaticky vrátÃte na tuto obrazovku.</string> @@ -271,6 +271,8 @@ <string name="no_chapters_label">Tato epizoda nemá žádné kapitoly.</string> <string name="no_shownotes_label">Tato epizoda neobsahuje žádné poznámky.</string> <!--Preferences--> + <string name="storage_pref">ÚložiÅ¡tÄ›</string> + <string name="project_pref">Projekt</string> <string name="other_pref">OstatnÃ</string> <string name="about_pref">O aplikaci</string> <string name="queue_label">Fronta</string> @@ -281,13 +283,13 @@ <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">PÅ™eskoÄit tlaÄÃtkem vpÅ™ed</string> <string name="pref_hardwareForwardButtonSkips_sum">Po stlaÄenà hardwarového tlaÄÃtka pro posun vpÅ™ed mÃsto pÅ™etoÄenà vpÅ™ed pÅ™eskoÄit na dalÅ¡Ã epizodu</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> <string name="pref_auto_delete_sum">Smazat dÃl po jeho pÅ™ehránÃ</string> <string name="pref_auto_delete_title">Automatické mazánÃ</string> <string name="pref_smart_mark_as_played_sum">OznaÄit epizody jako poslechnuté i pokud jeÅ¡tÄ› zbývá urÄitý poÄet sekund pÅ™ehrávánà do jejich konce</string> - <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="playback_pref">PÅ™ehrávánÃ</string> @@ -349,20 +351,28 @@ <string name="pref_gpodnet_logout_toast">ÚspěšnÄ› odhlášeno</string> <string name="pref_gpodnet_setlogin_information_title">ZmÄ›na pÅ™ihlaÅ¡ovacÃch údajů</string> <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_title">Synchronizovat nynÃ</string> - <string name="pref_gpodnet_sync_sum">Synchronizovat odbÄ›ry a stav epizod s gpodder.net</string> + <string name="pref_gpodnet_sync_changes_title">Synchronizovat zmÄ›ny</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">Plná synchronizace</string> + <string name="pref_gpodnet_full_sync_sum">Synchronizovat vÅ¡echny odbÄ›ry a stav epizod s gpodder.net.</string> + <string name="pref_gpodnet_sync_sum_last_sync_line">Poslednà pokus o synchronizaci: %1$s (%2$s)</string> <string name="pref_gpodnet_sync_started">Synchronizace spuÅ¡tÄ›na</string> + <string name="pref_gpodnet_full_sync_started">SpuÅ¡tÄ›na plná synchronizace</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_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> - <string name="pref_fast_forward">ÄŒas rychlého posunu</string> - <string name="pref_rewind">ÄŒas pÅ™etoÄenÃ</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">RozÅ¡ÃÅ™ené upozornÄ›nÃ</string> <string name="pref_expandNotify_sum">Vždy zobrazovat tlaÄÃtka pro pÅ™ehrávánà 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_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> + <string name="pref_compact_notification_buttons_dialog_error">Lze vybrat maximálnÄ› %1$d položek.</string> <string name="pref_lockscreen_background_title">Nastavit pozadà uzamÄené obrazovky</string> <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> @@ -377,25 +387,29 @@ <string name="crash_report_sum">OdesÃlat hlášenà o poslednÃm pádu aplikace emailem</string> <string name="send_email">Poslat email</string> <string name="experimental_pref">ExperimentálnÃ</string> - <string name="pref_sonic_title">PÅ™ehrávaÄ médià Sonic</string> <string name="pref_sonic_message">PoužÃt pÅ™ipojený sonic media player jako náhradu za výchozà pÅ™ehrávaÄ médià pro Android a Prestissimo</string> <string name="pref_current_value">Aktuálnà hodnota: %1$s</string> <string name="pref_proxy_title">Proxy</string> <string name="pref_proxy_sum">Nastavit sÃÅ¥ovou proxy</string> + <string name="pref_faq">FAQ</string> <string name="pref_known_issues">Známé chyby</string> - <string name="pref_no_browser_found">Nebyl nalezen webový prohlÞeÄ.\"</string> + <string name="pref_no_browser_found">Webový prohlÞeÄ nenalezen.</string> + <string name="pref_cast_title">Chromecast podpora</string> + <string name="pref_cast_message_play_flavor">Povolit podporu vzdáleného pÅ™ehrávánà médià na Cast pÅ™ÃstrojÃch (jako tÅ™eba Chromecast, Audio Speakers nebo Android TV)</string> + <string name="pref_cast_message_free_flavor">Chromecast vyžaduje proprietárnà knihovny tÅ™etÃch stran, které jsou vypnuty v této verzi AntennaPod</string> <!--Auto-Flattr dialog--> <string name="auto_flattr_enable">Povolit automatické flattrovánÃ</string> <string name="auto_flattr_after_percent">Flattrovat dÃl jakmile bude odehráno %d procent</string> <string name="auto_flattr_ater_beginning">Flattrovat dÃl po zaÄátku pÅ™ehrávánÃ</string> <string name="auto_flattr_ater_end">Flattrovat dÃl po konci pÅ™ehrávánÃ</string> <!--Search--> - <string name="search_hint">Hledat kanály a epizody</string> - <string name="found_in_shownotes_label">Nalezeno v poznámkách k show</string> + <string name="search_hint">Hledat epizody</string> + <string name="found_in_shownotes_label">Nalezeno v poznámkách poÅ™adu</string> <string name="found_in_chapters_label">Nalezeno v kapitolách</string> <string name="search_status_no_results">Žádné výsledky</string> <string name="search_label">Vyhledat</string> <string name="found_in_title_label">Nalezeno v názvu</string> + <string name="no_results_for_query">Nebyly nalezeny žádné výsledky pro \"%1$s\"</string> <!--OPML import and export--> <string name="opml_import_txtv_button_lable">OPML soubory umožňujà pÅ™enést vaÅ¡e podcasty z jednoho pÅ™ehrávaÄe na jiný.</string> <string name="opml_import_option">Možnost %1$d</string> @@ -414,6 +428,7 @@ <string name="choose_file_from_filesystem">Z mÃstnÃho souborového systému</string> <string name="choose_file_from_external_application">PoužÃt externà aplikaci</string> <string name="opml_export_label">OPML export</string> + <string name="html_export_label">HTML export</string> <string name="exporting_label">Export</string> <string name="export_error_label">Chyba exportu</string> <string name="opml_export_success_title">OPML export byl úspěšný.</string> @@ -447,6 +462,9 @@ <item quantity="few">%d hodiny</item> <item quantity="other">%d hodin</item> </plurals> + <string name="auto_enable_label">Automaticky zapnout</string> + <string name="sleep_timer_enabled_label">ÄŒasovaÄ vypnutà povolen</string> + <string name="sleep_timer_disabled_label">ÄŒasovaÄ vypnutà zakázán</string> <!--gpodder.net--> <string name="gpodnet_taglist_header">KATEGORIE</string> <string name="gpodnet_toplist_header">TOP PODCASTY</string> @@ -466,6 +484,7 @@ <string name="gpodnetauth_device_chooseExistingDevice">Vybrat existujÃcà zaÅ™ÃzenÃ:</string> <string name="gpodnetauth_device_errorEmpty">ID zaÅ™Ãzenà nesmà být prázdné</string> <string name="gpodnetauth_device_errorAlreadyUsed">ID zaÅ™Ãzenà je již obsazeno</string> + <string name="gpodnetauth_device_caption_errorEmpty">Titulek nesmà být prázdný</string> <string name="gpodnetauth_device_butChoose">Vybrat</string> <string name="gpodnetauth_finish_title">ÚspěšnÄ› pÅ™ihlášeno!</string> <string name="gpodnetauth_finish_descr">Gratulujeme! Váš gpodder.net úÄet je nynà úspěšnÄ› propojen s vaÅ¡Ãm zaÅ™ÃzenÃm. AntennaPod bude automaticky synchronizovat odebÃrané podcasty s nastaveným úÄtem na gpodder.net.</string> @@ -475,6 +494,8 @@ <string name="gpodnetsync_auth_error_descr">Å patné pÅ™ihlaÅ¡ovacà jméno nebo heslo</string> <string name="gpodnetsync_error_title">gpodder.net synchronizace selhala</string> <string name="gpodnetsync_error_descr">V průbÄ›hu synchronizace nastala chyba:\u0020</string> + <string name="gpodnetsync_pref_report_successful">Úspěšné</string> + <string name="gpodnetsync_pref_report_failed">Selhalo</string> <!--Directory chooser--> <string name="selected_folder_label">Vybraný adresář:</string> <string name="create_folder_label">VytvoÅ™it adresář</string> @@ -502,22 +523,13 @@ <string name="subscribed_label">OdebÃráno</string> <string name="downloading_label">StahovánÃ</string> <!--Content descriptions for image buttons--> - <string name="show_chapters_label">Zobrazit kapitoly</string> - <string name="show_shownotes_label">Zobrazit poznámky o poÅ™adu</string> - <string name="show_cover_label">Zobrazit obrázek</string> <string name="rewind_label">Posunout zpÄ›t</string> <string name="fast_forward_label">Posunout vpÅ™ed</string> <string name="media_type_audio_label">Audio</string> <string name="media_type_video_label">Video</string> <string name="navigate_upwards_label">Navigovat vzhůru</string> - <string name="butAction_label">VÃce možnostÃ</string> - <string name="status_playing_label">Epizoda se právÄ› pÅ™ehrává</string> <string name="status_downloading_label">Epizoda je právÄ› stahována</string> - <string name="status_downloaded_label">Epizoda je stažena</string> - <string name="status_unread_label">Nová položka</string> <string name="in_queue_label">Epizoda je ve frontÄ›</string> - <string name="new_episodes_count_label">PoÄet nových epizod</string> - <string name="in_progress_episodes_count_label">PoÄet epizod u kterých byl zapoÄat poslech</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> <!--Feed information screen--> @@ -535,8 +547,9 @@ <!--AntennaPodSP--> <string name="sp_apps_importing_feeds_msg">Importuji odbÄ›ry z jednoúÄelových aplikacÃ...</string> <string name="search_itunes_label">Prohledat iTunes</string> - <string name="select_label"><b>Vybrat…</b></string> <string name="filter">Filtr</string> + <string name="search_fyyd_label">Prohledat fyyd</string> + <!--Episodes apply actions--> <string name="all_label">VÅ¡e</string> <string name="selected_all_label">Vybrány vÅ¡echny epizody</string> <string name="none_label">Žádné</string> @@ -553,7 +566,9 @@ <string name="selected_queued_label">Vybrané epizody ve frontÄ›</string> <string name="not_queued_label">Mimo frontu</string> <string name="selected_not_queued_label">Vybrané epizody mimo frontu</string> - <string name="sort_title"><b>Řadit dle</b></string> + <string name="has_media">Obsahuje média</string> + <string name="selected_has_media_label">Vybrané epizody s médii</string> + <!--Sort--> <string name="sort_title_a_z">Názvu (A \u2192 Z)</string> <string name="sort_title_z_a">Názvu (Z \u2192 A)</string> <string name="sort_date_new_old">Data (Nové \u2192 Staré)</string> @@ -584,7 +599,23 @@ <string name="proxy_checking">Kontrola...</string> <string name="proxy_test_successful">Test úspěšný</string> <string name="proxy_test_failed">Test selhal</string> - <string name="proxy_host_empty_error">Host nesmà být nevyplnÄ›ný</string> + <string name="proxy_host_empty_error">Host nesmà být prázdný</string> <string name="proxy_host_invalid_error">Host nenà platná IP nebo doména</string> <string name="proxy_port_invalid_error">Neplatný port</string> + <!--Casting--> + <string name="cast_media_route_menu_title">PÅ™ehrát na...</string> + <string name="cast_disconnect_label">Odpojit sezenà vysÃlánÃ</string> + <string name="cast_not_castable">Vybraná média nejsou kompatibilnà s pÅ™ehrávacÃm pÅ™Ãstrojem</string> + <string name="cast_failed_to_play">Selhalo spuÅ¡tÄ›nà pÅ™ehrávánà média</string> + <string name="cast_failed_to_stop">Selhalo zastavenà pÅ™ehrávánà média</string> + <string name="cast_failed_to_pause">Selhalo pozastavenà pÅ™ehrávánà média</string> + <!--<string name="cast_failed_to_connect">Could not connect to the device</string>--> + <string name="cast_failed_setting_volume">Selhalo nastavenà hlasitosti</string> + <string name="cast_failed_no_connection">Nenà dostupné pÅ™ipojenà k pÅ™ehrávacÃmu pÅ™Ãstroji</string> + <string name="cast_failed_no_connection_trans">DoÅ¡lo ke ztrátÄ› pÅ™ipojenà k pÅ™ehrávacÃmu pÅ™Ãstroji. Aplikace se pokouÅ¡Ã znovu pÅ™ipojit, pokud to bude možné. PoÄkejte nÄ›kolik sekund a zkuste znovu.</string> + <string name="cast_failed_perform_action">Selhalo provedenà akce</string> + <string name="cast_failed_status_request">Selhala synchronizace s vysÃlaÄem</string> + <string name="cast_failed_seek">Selhal posun na novou pozici na vysÃlaÄi</string> + <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> </resources> diff --git a/core/src/main/res/values-da/strings.xml b/core/src/main/res/values-da/strings.xml index ca144c17f..f1eb85f7a 100644 --- a/core/src/main/res/values-da/strings.xml +++ b/core/src/main/res/values-da/strings.xml @@ -1,347 +1,634 @@ <?xml version='1.0' encoding='UTF-8'?> <resources xmlns:tools="http://schemas.android.com/tools"> <!--Activitiy and fragment titles--> - <string name="app_name">AntennaPod</string> <string name="feeds_label">Feeds</string> + <string name="statistics_label">Statistik</string> <string name="add_feed_label">Tilføj podcast</string> - <string name="podcasts_label">PODCASTS</string> - <string name="new_episodes_label">Nye episoder</string> - <string name="all_episodes_label">Alle episoder</string> - <string name="new_label">Nye</string> - <string name="waiting_list_label">Venteliste</string> + <string name="episodes_label">Udsendelser</string> + <string name="all_episodes_short_label">Alle</string> + <string name="favorite_episodes_label">Foretrukne</string> + <string name="new_label">Ny(e)</string> <string name="settings_label">Indstillinger</string> <string name="add_new_feed_label">Tilføj podcast</string> - <string name="downloads_label">Downloads</string> - <string name="downloads_running_label">Kører</string> - <string name="downloads_completed_label">Fuldført</string> + <string name="downloads_label">Overførsler</string> + <string name="downloads_running_label">I gang</string> + <string name="downloads_completed_label">Færdige</string> <string name="downloads_log_label">Log</string> - <string name="cancel_download_label">Annuller Download</string> + <string name="subscriptions_label">Abonnementer</string> + <string name="subscriptions_list_label">Liste over abonnementer</string> + <string name="cancel_download_label">Annuller\noverførsel</string> <string name="playback_history_label">Afspilningshistorik</string> <string name="gpodnet_main_label">gpodder.net</string> - <string name="gpodnet_auth_label">gpodder.net login</string> - <!--New episodes fragment--> - <string name="recently_published_episodes_label">Nyligt udgivet</string> - <string name="episode_filter_label">Hvis kun nye episoder</string> + <string name="gpodnet_auth_label">Login til gpodder.net</string> + <string name="free_space_label">%1$s ledig</string> + <string name="episode_cache_full_title">Mellemlageret for udsendelser er fuldt</string> + <string name="episode_cache_full_message">Grænsen for størrelsen pÃ¥ udsendelsesmellemlageret er nÃ¥et. Du kan øge størrelsen pÃ¥ mellemlageret i Indstillinger.</string> <!--Statistics fragment--> + <string name="total_time_listened_to_podcasts">Samlet varighed for afspillede podcasts:</string> + <string name="statistics_details_dialog">%1$d af %2$d udsendelser startet.\n\nAfspillet %3$s af %4$s.</string> + <string name="statistics_mode">Statistiktilstand</string> + <string name="statistics_mode_normal">Beregn den varighed som faktisk blev afspillet. Afspilning af en udsendelse to gange tæller dobbelt, mens en markering som værende afspillet ikke tælles med.</string> + <string name="statistics_mode_count_all">Opsummer alle podcasts markeret som afspillet</string> + <string name="statistics_speed_not_counted">Bemærk: Afspilningshastigheden har ingen betydning</string> <!--Main activity--> - <string name="drawer_open">Ã…ben menu</string> + <string name="drawer_open">Ã…bn menu</string> <string name="drawer_close">Luk menu</string> + <string name="drawer_preferences">Indstillinger for panel</string> + <string name="drawer_feed_order_unplayed_episodes">Sorter efter tæller</string> + <string name="drawer_feed_order_alphabetical">Sorter alfabetisk</string> + <string name="drawer_feed_order_last_update">Sorter efter udgivelsesdato</string> + <string name="drawer_feed_order_most_played">Sorter efter antal afspillede udsendelser</string> + <string name="drawer_feed_counter_new_unplayed">Antal nye og uafspillede udsendelser</string> + <string name="drawer_feed_counter_new">Antal nye udsendelser</string> + <string name="drawer_feed_counter_unplayed">Antal uafspillede udsendelser</string> + <string name="drawer_feed_counter_downloaded">Antal overførte udsendelser</string> + <string name="drawer_feed_counter_none">Ingen</string> <!--Webview actions--> - <string name="open_in_browser_label">Ã…ben i browser</string> - <string name="copy_url_label">Kopier URL</string> - <string name="share_url_label">Del URL</string> - <string name="copied_url_msg">URL kopieret til udklipsholderen.</string> + <string name="open_in_browser_label">Ã…bn i browser</string> + <string name="copy_url_label">Kopier webadresse</string> + <string name="share_url_label">Del webadresse</string> + <string name="copied_url_msg">Webadresse kopieret til udklipsholderen</string> <string name="go_to_position_label">GÃ¥ til denne position</string> <!--Playback history--> <string name="clear_history_label">Fjern historik</string> <!--Other--> <string name="confirm_label">Bekræft</string> <string name="cancel_label">Annuller</string> + <string name="yes">Ja</string> + <string name="no">Nej</string> + <string name="reset">Nulstil</string> <string name="author_label">Forfatter</string> <string name="language_label">Sprog</string> + <string name="url_label">Webadresse</string> <string name="podcast_settings_label">Indstillinger </string> - <string name="cover_label">Billed</string> + <string name="cover_label">Billede</string> <string name="error_label">Fejl</string> <string name="error_msg_prefix">En fejl er opstÃ¥et:</string> <string name="refresh_label">Opdater</string> <string name="external_storage_error_msg">Ingen ekstern harddisk er tilgængelig. Vær venlig at sørge for at den eksterne hukommelse er monteret sÃ¥ app\'en kan fungere korrekt.</string> <string name="chapters_label">Kapitler</string> - <string name="shownotes_label">Afsnitsnoter</string> + <string name="chapter_duration">Varighed: %1$s</string> + <string name="shownotes_label">Beskrivelse</string> <string name="description_label">Beskrivelse</string> - <string name="most_recent_prefix">Seneste episoder:\u0020</string> - <string name="episodes_suffix">\u0020episoder</string> + <string name="most_recent_prefix">Seneste udsendelse:\u0020</string> + <string name="episodes_suffix">\u0020udsendelser</string> <string name="length_prefix">Længde:\u0020</string> <string name="size_prefix">Størrelse:\u0020</string> <string name="processing_label">Behandler</string> - <string name="save_username_password_label">Gem brugernavn og kodeord</string> + <string name="loading_label">Indlæser...</string> + <string name="save_username_password_label">Gem brugernavn og adgangskode</string> <string name="close_label">Luk</string> <string name="retry_label">Prøv igen</string> - <string name="auto_download_label">Inkluder i automatiske downloads</string> + <string name="auto_download_label">Inkluder i Automatisk overførsel</string> + <string name="auto_download_apply_to_items_title">Anvend pÃ¥ tidligere udsendelser</string> + <string name="auto_download_apply_to_items_message">Den nye <i>Automatisk overførsel</i>-indstilling vil automatisk blive anvendt pÃ¥ nye udsendelser.\nVil du ogsÃ¥ anvende den pÃ¥ tidligere udsendelser?</string> + <string name="auto_delete_label">Slet udsendelser automatisk</string> + <string name="parallel_downloads_suffix">\u0020parallelle overførsler</string> + <string name="feed_auto_download_global">Global standard</string> + <string name="feed_auto_download_always">Altid</string> + <string name="feed_auto_download_never">Aldrig</string> + <string name="send_label">Send…</string> + <string name="episode_cleanup_never">Aldrig</string> + <string name="episode_cleanup_queue_removal">NÃ¥r ikke i kø</string> + <string name="episode_cleanup_after_listening">Efter færdig afspilning</string> + <plurals name="episode_cleanup_days_after_listening"> + <item quantity="one">1 dag efter færdig afspilning</item> + <item quantity="other">%d dage efter færdig afspilning</item> + </plurals> <!--'Add Feed' Activity labels--> - <string name="feedurl_label">Feed URL</string> - <string name="etxtFeedurlHint">URL af feed eller webside</string> - <string name="txtvfeedurl_label">Tilføj Podcast med URL</string> - <string name="podcastdirectories_label">Find podcast i mappen</string> - <string name="podcastdirectories_descr">Du kan søge efter nye podcasts efter navn, kategori eller popularitet i gpodder.net biblioteket</string> + <string name="feedurl_label">Webadresse for feed</string> + <string name="etxtFeedurlHint">www.example.com/feed</string> + <string name="txtvfeedurl_label">Tilføj podcast via webadresse</string> + <string name="podcastdirectories_label">Find podcast i mappe</string> + <string name="podcastdirectories_descr">For at finde nye podcasts kan du søge pÃ¥ iTunes eller fyyd, eller du kan bladre pÃ¥ gpodder.net efter navn, kategori eller popularitet.</string> <string name="browse_gpoddernet_label">Gennemse gpodder.net</string> <!--Actions on feeds--> - <string name="mark_all_read_label">Marker alle som læst</string> - <string name="mark_all_read_msg">Marker alle episoder som læst</string> + <string name="mark_all_read_label">Marker alle som afspillet</string> + <string name="mark_all_read_msg">Marker alle udsendelser som afspillet</string> + <string name="mark_all_read_confirmation_msg">Bekræft venligst at du ønsker at markere alle udsendelser som værende afspillet.</string> + <string name="mark_all_read_feed_confirmation_msg">Bekræft venligst at du ønsker at markere alle udsendelser i denne feed som værende afspillet.</string> + <string name="mark_all_seen_label">Marker alle som set</string> + <string name="mark_all_seen_msg">Markerede alle udsendelser som set</string> + <string name="mark_all_seen_confirmation_msg">Bekræft venligst at du ønsker at markere alle udsendelser som set.</string> <string name="show_info_label">Vis information</string> + <string name="rename_feed_label">Omdøb podcast</string> <string name="remove_feed_label">Fjern podcast</string> - <string name="share_link_label">Del webside link</string> - <string name="feed_delete_confirmation_msg">Bekræft venligst at du vil fjerne dette feed og ALLE episoder du har downloadet fra dette feed.</string> + <string name="share_label">Del…</string> + <string name="share_link_label">Del link</string> + <string name="share_link_with_position_label">Del link med position</string> + <string name="share_feed_url_label">Del webadresse for feedet</string> + <string name="share_item_url_label">Del webadresse for udsendelsen</string> + <string name="share_item_url_with_position_label">Del webadresse for udsendelsen med position</string> + <string name="feed_delete_confirmation_msg">Bekræft venligst at du ønsker at slette feedet \"%1$s\" og ALLE overførte udsendelser i dette feed.</string> <string name="feed_remover_msg">Fjerner feed</string> - <string name="load_complete_feed">Opdater hele feed\'et</string> + <string name="load_complete_feed">Opdater hele feedet</string> + <string name="hide_episodes_title">Skjul udsendelser</string> + <string name="episode_actions">Anvend handlinger</string> + <string name="hide_unplayed_episodes_label">Uafspillede</string> + <string name="hide_paused_episodes_label">Sat pÃ¥ pause</string> + <string name="hide_played_episodes_label">Afspillede</string> + <string name="hide_queued_episodes_label">Sat i kø</string> + <string name="hide_not_queued_episodes_label">Ikke sat i kø</string> + <string name="hide_downloaded_episodes_label">Overførte</string> + <string name="hide_not_downloaded_episodes_label">Ikke overførte</string> + <string name="hide_has_media_label">Har medier</string> + <string name="filtered_label">Filtrerede</string> + <string name="refresh_failed_msg">{fa-exclamation-circle} Sidste opdatering fejlede</string> + <string name="open_podcast">Ã…bn podcast</string> <!--actions on feeditems--> <string name="download_label">Hent</string> <string name="play_label">Afspil</string> - <string name="pause_label">Pause</string> + <string name="pause_label">Sæt pÃ¥ pause</string> <string name="stop_label">Stop</string> <string name="stream_label">Stream</string> <string name="remove_label">Fjern</string> - <string name="remove_episode_lable">Fjern episode</string> + <string name="delete_label">Slet</string> + <string name="remove_episode_lable">Fjern udsendelse</string> + <string name="marked_as_seen_label">Markeret som set</string> <string name="mark_read_label">Marker som læst</string> - <string name="mark_unread_label">Marker som ulæst</string> - <string name="add_to_queue_label">Tilføj til kø</string> + <string name="marked_as_read_label">Markeret som afspillet</string> + <string name="mark_unread_label">Marker som uafspillet</string> + <string name="add_to_queue_label">Føj til kø</string> + <string name="added_to_queue_label">Føjet til kø</string> <string name="remove_from_queue_label">Fjern fra kø</string> + <string name="add_to_favorite_label">Føj til foretrukne</string> + <string name="added_to_favorites">Føjet til foretrukne</string> + <string name="remove_from_favorite_label">Fjern fra foretrukne</string> + <string name="removed_from_favorites">Fjernet fra foretrukne</string> <string name="visit_website_label">Besøg webside</string> <string name="support_label">Flattr dette</string> - <string name="enqueue_all_new">Sæt alle i kø</string> - <string name="download_all">Download alle</string> - <string name="skip_episode_label">Spring episode over</string> + <string name="skip_episode_label">Spring udsendelse over</string> + <string name="activate_auto_download">SlÃ¥ Automatisk overførsel til</string> + <string name="deactivate_auto_download">SlÃ¥ Automatisk overførsel fra</string> + <string name="reset_position">Nulstil afspilningsposition</string> + <string name="removed_item">Element fjernet</string> <!--Download messages and labels--> - <string name="download_successful">succesfuld</string> - <string name="download_failed">fejlet</string> - <string name="download_pending">Download afventer</string> - <string name="download_running">Download kører</string> - <string name="download_error_device_not_found">Kan ikke finde lager-enhed</string> + <string name="download_successful">lykkedes</string> + <string name="download_failed">fejlede</string> + <string name="download_pending">Afventer overførsel</string> + <string name="download_running">Overfører</string> + <string name="download_error_device_not_found">Kan ikke finde lagerenhed</string> <string name="download_error_insufficient_space">Ikke nok plads</string> - <string name="download_error_file_error">Fil fejl</string> - <string name="download_error_http_data_error">HTTP data fejl</string> + <string name="download_error_file_error">Filfejl</string> + <string name="download_error_http_data_error">HTTP-datafejl</string> <string name="download_error_error_unknown">Ukendt fejl</string> - <string name="download_error_parser_exception">Parser undtagelse</string> - <string name="download_error_unsupported_type">Feed type er ikke understøttet</string> + <string name="download_error_parser_exception">Parser-undtagelse</string> + <string name="download_error_unsupported_type">Feedets type er ikke understøttet</string> <string name="download_error_connection_error">Forbindelsesfejl</string> <string name="download_error_unknown_host">Ukendt vært</string> - <string name="download_error_unauthorized">Godkendelses fejl</string> - <string name="cancel_all_downloads_label">Annuller alle downloads</string> - <string name="download_canceled_msg">Download afbrudt</string> - <string name="download_report_title">Downloads afsluttet</string> - <string name="download_error_malformed_url">Misdannet URL</string> - <string name="download_error_io_error">IO fejl</string> - <string name="download_error_request_error">Anmode fejl</string> - <string name="download_error_db_access">Adgangsfejl i database</string> - <string name="downloads_processing">Bearbejder downloads</string> - <string name="download_notification_title">Downloader podcast data</string> - <string name="download_report_content">%1$d downloads lykkedes, %2$d fejlet</string> + <string name="download_error_unauthorized">Godkendelsesfejl</string> + <string name="download_error_file_type_type">Filtypefejl</string> + <string name="download_error_forbidden">Adgang nægtet</string> + <string name="cancel_all_downloads_label">Annuller alle overførsler</string> + <string name="download_canceled_msg">Overførsel annulleret</string> + <string name="download_canceled_autodownload_enabled_msg">Overførsel annulleret\n<i>Automatisk overførsel</i> blev slÃ¥et fra for dette element</string> + <string name="download_report_title">Overførsler afsluttet med fejl</string> + <string name="download_report_content_title">Rapport over overførsler</string> + <string name="download_error_malformed_url">Webadresse er forkert udformet</string> + <string name="download_error_io_error">Læse- eller skrivefejl</string> + <string name="download_error_request_error">Fejl i anmodning</string> + <string name="download_error_db_access">Databaseadgangsfejl</string> + <plurals name="downloads_left"> + <item quantity="one">%d overførsel mangler</item> + <item quantity="other">%d overførsler mangler</item> + </plurals> + <string name="downloads_processing">Bearbejder overførte data</string> + <string name="download_notification_title">Henter podcast-data</string> + <string name="download_report_content">%1$d overførsler lykkedes, %2$d fejlede</string> <string name="download_log_title_unknown">Ukendt titel</string> <string name="download_type_feed">Feed</string> - <string name="download_type_media">Medie fil</string> + <string name="download_type_media">Mediefil</string> <string name="download_type_image">Billede</string> - <string name="download_request_error_dialog_message_prefix">En fejl opstod under download af filen:\u0020</string> - <string name="authentication_notification_title">Godkendelses krævet</string> - <string name="authentication_notification_msg">Den ressource du efterspurgte kræver et brugernavn og et password</string> + <string name="download_request_error_dialog_message_prefix">En fejl opstod ved overførsel af filen:\u0020</string> + <string name="authentication_notification_title">Godkendelse kræves</string> + <string name="authentication_notification_msg">Ressourcen du efterspurgte kræver brugernavn og adgangskode</string> + <string name="confirm_mobile_download_dialog_title">Bekræft brug af mobildata</string> + <string name="confirm_mobile_download_dialog_message_not_in_queue">Overførsel over mobil dataforbindelse er slÃ¥et fra i indstillingerne.\n\nDu kan vælge blot at føje udsendelsen til køen eller du kan tillade overførsel midlertidigt.\n\n<small>Dit valg vil blive husket i 10 minutter.</small></string> + <string name="confirm_mobile_download_dialog_message">Overførsel over mobil dataforbindelse er slÃ¥et fra i indstillingerne.\n\nVil du tillade overførsel midlertidigt?\n\n<small>Dit valg vil blive husket i 10 minutter.</small></string> + <string name="confirm_mobile_download_dialog_only_add_to_queue">Sæt i kø</string> + <string name="confirm_mobile_download_dialog_enable_temporarily">Tillad midlertidigt</string> <!--Mediaplayer messages--> <string name="player_error_msg">Fejl!</string> - <string name="player_stopped_msg">Ingen medier afspiller</string> + <string name="player_stopped_msg">Ingen medier afspilles</string> <string name="player_preparing_msg">Forbereder</string> <string name="player_ready_msg">Klar</string> <string name="player_seeking_msg">Søger</string> <string name="playback_error_server_died">Server døde</string> <string name="playback_error_unknown">Ukendt fejl</string> <string name="no_media_playing_label">Ingen medier afspiller</string> - <string name="position_default_label">00:00:00</string> - <string name="player_buffering_msg">Buffering</string> + <string name="player_buffering_msg">Henter data til buffer</string> <string name="playbackservice_notification_title">Afspiller podcast</string> - <string name="unknown_media_key">AntennaPod - ukendt medie nøgle: %1$d</string> + <string name="unknown_media_key">AntennaPod - Ukendt medienøgle: %1$d</string> <!--Queue operations--> - <string name="clear_queue_label">Fjern kø</string> + <string name="lock_queue">LÃ¥s kø</string> + <string name="unlock_queue">LÃ¥s kø op</string> + <string name="queue_locked">Kø lÃ¥st</string> + <string name="queue_unlocked">Kø lÃ¥st op</string> + <string name="clear_queue_label">Ryd kø</string> <string name="undo">Fortryd</string> - <string name="removed_from_queue">Emne slettet</string> + <string name="removed_from_queue">Element slettet</string> <string name="move_to_top_label">Flyt til toppen</string> <string name="move_to_bottom_label">Flyt til bunden</string> <string name="sort">Sorter</string> - <string name="alpha">Alfabetisk</string> <string name="date">Dato</string> <string name="duration">Varighed</string> + <string name="episode_title">Titel pÃ¥ udsendelse</string> + <string name="feed_title">Titel pÃ¥ feed</string> <string name="ascending">Stigende</string> <string name="descending">Faldende</string> + <string name="clear_queue_confirmation_msg">Bekræft venligst at du vil rydde ALLE udsendelser fra køen</string> <!--Flattr--> - <string name="flattr_auth_label">Flattr log ind</string> - <string name="flattr_auth_explanation">Tryk pÃ¥ knappen nedenfor for at starte godkendelsesprocessen. Du vil blive ført til flattr log ind siden i din browser og bedt om at give AntennaPod tilladelse til at flattr emner. Efter at du har givet tilladelsen vil du automatisk vende tilbage til denne side.</string> - <string name="authenticate_label">Godkender</string> - <string name="return_home_label">Retuner hjem</string> - <string name="flattr_auth_success">Godkendelse lykkedes! Du kan nu flattr emner inde i app\'en.</string> - <string name="no_flattr_token_title">Ingen flattr polet fundet</string> - <string name="no_flattr_token_notification_msg">Din flattr konto ser ikke ud til at være forbundet med AntennaPod. Tryk her for at forbinde.</string> - <string name="no_flattr_token_msg">Din flattr konto er vidst ikke forbundet til AntennaPod. Du kan forbinde din konto til AntennaPod for at flattr emner inde i app\'en, eller besøge websiden af mediet for at flattr det der.</string> - <string name="authenticate_now_label">Godkender</string> - <string name="action_forbidden_title">Forbudt handling</string> - <string name="action_forbidden_msg">AntennaPod har ikke tilladelse til denne handling. Ã…rsagen kunne være at adgangspoletten for AntennaPod til din konto er blevet tilbagekaldt. Du kan enten godkende den igen eller besøge websiden for mediet istedet.</string> + <string name="flattr_auth_label">Log ind pÃ¥ Flattr</string> + <string name="flattr_auth_explanation">Tryk pÃ¥ knappen nedenfor for at starte godkendelsesprocessen. Du vil blive ført til flattr\'s log ind-side i din browser og bedt om at give AntennaPod tilladelse til at flattre emner. Efter at du har givet tilladelsen, vil du automatisk vende tilbage til denne side.</string> + <string name="authenticate_label">Godkend</string> + <string name="return_home_label">GÃ¥ tilbage hjem</string> + <string name="flattr_auth_success">Godkendelse lykkedes! Du kan nu flattre ting inde fra appen.</string> + <string name="no_flattr_token_title">Ingen flattr-polet (token) fundet</string> + <string name="no_flattr_token_notification_msg">Din flattr-konto ser ikke ud til at være forbundet med AntennaPod. Tryk her for at forbinde.</string> + <string name="no_flattr_token_msg">Din flattr konto ser ikke ud til at være forbundet til AntennaPod. Du kan enten forbinde din konto til AntennaPod for at flattre emner inde fra appen, eller du kan besøge websiden for det du vil flattre for at gøre det dér.</string> + <string name="authenticate_now_label">Godkend</string> + <string name="action_forbidden_title">Handling ikke tilladt</string> + <string name="action_forbidden_msg">AntennaPod har ikke tilladelse til denne handling. Ã…rsagen kunne være at adgangspoletten for AntennaPod til din konto er blevet tilbagekaldt. Du kan enten godkende igen eller alternativt besøge websiden for det du vil flattre.</string> <string name="access_revoked_title">Adgang tilbagekaldt</string> - <string name="access_revoked_info">Du har succesfuldt tilbagekaldt AntennaPods adgangs polet til din konto. For at fuldføre processen skal du fjerne denne app fra listen af godkendte applikationer i din kontos indstillinger pÃ¥ flattr\'s hjemmeside.</string> + <string name="access_revoked_info">Du har nu tilbagekaldt AntennaPods adgangspolet (\'access token\') til din konto. For at fuldføre processen skal du fjerne denne app fra listen over godkendte applikationer i dine kontoindstillinger pÃ¥ flattr\'s hjemmeside.</string> <!--Flattr--> - <string name="flattr_click_success">Flattr\'et en ting!</string> - <string name="flattr_click_success_count">Flattr\'et %d ting!</string> + <string name="flattr_click_success">Flattret en ting!</string> + <string name="flattr_click_success_count">Flattret %d ting!</string> <string name="flattr_click_success_queue">Flattr\'et: %s.</string> - <string name="flattr_click_failure_count">Det mislykkedes at flattr %d ting!</string> + <string name="flattr_click_failure_count">Det lykkedes ikke at flattre %d ting!</string> <string name="flattr_click_failure">Ikke flattr\'et: %s.</string> - <string name="flattr_click_enqueued">Ting vil blive flattr\'et senere</string> + <string name="flattr_click_enqueued">Tingen vil blive flattret senere</string> <string name="flattring_thing">Flattr\'er %s</string> - <string name="flattring_label">AntennaPod flatttr\'er</string> + <string name="flattring_label">AntennaPod flattrer</string> <string name="flattrd_label">AntennaPod har flattr\'et</string> - <string name="flattrd_failed_label">AntennaPod flattr mislykkedes</string> - <string name="flattr_retrieving_status">Hent flatt\'rede ting</string> + <string name="flattrd_failed_label">AntennaPod-flattring mislykkedes</string> + <string name="flattr_retrieving_status">Henter flattrede ting</string> <!--Variable Speed--> - <string name="download_plugin_label">Hent Plugin</string> + <string name="download_plugin_label">Hent plugin</string> <string name="no_playback_plugin_title">Plugin er ikke installeret</string> + <string name="no_playback_plugin_or_sonic_msg">For at afspilning med variabel hastighed skal fungere, anbefaler vi at slÃ¥ den indbyggede Sonic-medieafspiller til (Android 4.1+).\n\nAlternativt kan du hente tredjeparts-pluginnet <i>Prestissimo</i> fra Play Store.\nProblemer med Prestissimo er ikke AntennaPods ansvar og skal rapporteres til pluginnets ejer.</string> <string name="set_playback_speed_label">Afspilningshastigheder</string> + <string name="enable_sonic">SlÃ¥ Sonic til</string> <!--Empty list labels--> - <string name="no_items_label">Der er ingen emner i denne liste.</string> - <string name="no_feeds_label">Du har endnu ikke abonneret til nogle feeds.</string> + <string name="no_items_label">Der er ingen elementer i denne liste.</string> + <string name="no_feeds_label">Du har endnu ikke abonneret pÃ¥ nogen feeds.</string> + <string name="no_chapters_label">Denne udsendelse har ingen kapitler.</string> + <string name="no_shownotes_label">Denne udsendelse har ingen beskrivelse.</string> <!--Preferences--> + <string name="storage_pref">Lagring</string> + <string name="project_pref">Projekt</string> <string name="other_pref">Andre</string> <string name="about_pref">Om</string> <string name="queue_label">Kø</string> <string name="services_label">Tjenester</string> <string name="flattr_label">Flattr</string> - <string name="pref_unpauseOnHeadsetReconnect_sum">Genoptag afspilning nÃ¥r hovedtelefoner tilsluttes igen</string> - <string name="pref_followQueue_sum">Hop til næste medie i køen nÃ¥r afspilning er færdig</string> - <string name="pref_auto_delete_sum">Slet episode nÃ¥r afspilningen er færdig</string> - <string name="pref_auto_delete_title">Slet Automatisk</string> + <string name="pref_episode_cleanup_title">Oprydning i udsendelser</string> + <string name="pref_episode_cleanup_summary">Tillad at udsendelser, som ikke er i køen og som ikke er markeret som foretrukne, kan fjernes, hvis Automatisk overførsel har brug for plads til nye udsendelser</string> + <string name="pref_pauseOnDisconnect_sum">Sæt afspilning pÃ¥ pause, hvis hovedtelefoner eller bluetooth afkobles</string> + <string name="pref_unpauseOnHeadsetReconnect_sum">Genoptag afspilning nÃ¥r hovedtelefonerne tilsluttes igen</string> + <string name="pref_unpauseOnBluetoothReconnect_sum">Genoptag afspilning nÃ¥r bluetooth forbinder igen</string> + <string name="pref_hardwareForwardButtonSkips_title">Fremadknap springer over</string> + <string name="pref_hardwareForwardButtonSkips_sum">NÃ¥r der trykkes pÃ¥ en fysisk fremadknap, skal der springes til den næste udsendelse i stedet for at spoles fremad.</string> + <string name="pref_hardwarePreviousButtonRestarts_title">Tilbageknap genstarter</string> + <string name="pref_hardwarePreviousButtonRestarts_sum">NÃ¥r der trykkes pÃ¥ en fysisk tilbageknap, skal den aktuelle udsendelse afspilles forfra i stedet for at der spoles tilbage.</string> + <string name="pref_followQueue_sum">Spring til næste element i køen nÃ¥r afspilningen er færdig</string> + <string name="pref_auto_delete_sum">Slet udsendelsen nÃ¥r afspilningen er færdig</string> + <string name="pref_auto_delete_title">Slet automatisk</string> + <string name="pref_smart_mark_as_played_sum">Marker udsendelser som værende afspillet, selv om op til et angivet antal sekunders spilletid stadig mangler</string> + <string name="pref_smart_mark_as_played_title">Smart markering af afspillet</string> + <string name="pref_skip_keeps_episodes_sum">Behold udsendelser nÃ¥r de bliver sprunget over</string> + <string name="pref_skip_keeps_episodes_title">Behold oversprungne udsendelser</string> <string name="playback_pref">Afspilning</string> <string name="network_pref">Netværk</string> - <string name="pref_downloadMediaOnWifiOnly_sum">Download kun medie filer over WiFi</string> + <string name="pref_autoUpdateIntervallOrTime_title">Opdateringsinterval eller -klokkeslæt</string> + <string name="pref_autoUpdateIntervallOrTime_sum">Angiv et tidsinterval eller et bestemt klokkeslæt hvor feedene skal opdateres automatisk</string> + <string name="pref_autoUpdateIntervallOrTime_message">Du kan indstille et <i>interval</i> som \"hver anden time\", indstille et bestemt <i>klokkeslæt</i> som \"7:00\", eller <i>slÃ¥</i> automatiske opdateringer helt <i>fra</i>.\n\n<small>Bemærk: Opdateringstider er ikke eksakte. Du kan opleve en kort forsinkelse.</small></string> + <string name="pref_autoUpdateIntervallOrTime_Disable">SlÃ¥ fra</string> + <string name="pref_autoUpdateIntervallOrTime_Interval">Indstil interval</string> + <string name="pref_autoUpdateIntervallOrTime_TimeOfDay">Indstil klokkeslæt</string> + <string name="pref_autoUpdateIntervallOrTime_every">hver %1$s</string> + <string name="pref_autoUpdateIntervallOrTime_at">kl. %1$s</string> + <string name="pref_downloadMediaOnWifiOnly_sum">Overfør mediefiler kun via wi-fi</string> <string name="pref_followQueue_title">Kontinuerlig afspilning</string> - <string name="pref_downloadMediaOnWifiOnly_title">WiFi medie download</string> - <string name="pref_pauseOnHeadsetDisconnect_title">Hovedtelefoner afbrudt</string> - <string name="pref_unpauseOnHeadsetReconnect_title">Hovedtelefoner tilsluttes igen</string> + <string name="pref_downloadMediaOnWifiOnly_title">Overførsel af mediefiler over wi-fi</string> + <string name="pref_pauseOnHeadsetDisconnect_title">Afbrydelse af hovedtelefoner</string> + <string name="pref_unpauseOnHeadsetReconnect_title">Tilslutning af hovedtelefoner igen</string> + <string name="pref_unpauseOnBluetoothReconnect_title">Bluetooth forbundet igen</string> <string name="pref_mobileUpdate_title">Mobile opdateringer</string> - <string name="pref_mobileUpdate_sum">Tillad opdateringer over mobil data forbindelse</string> + <string name="pref_mobileUpdate_sum">Tillad opdateringer over mobildataforbindelsen</string> <string name="refreshing_label">Opdaterer</string> - <string name="flattr_settings_label">Flattr indstillinger</string> - <string name="pref_flattr_auth_title">Flattr log ind</string> - <string name="pref_flattr_auth_sum">Log ind til din flattr konto for at flattr emner direkte fra app\'en</string> + <string name="flattr_settings_label">Flattr-indstillinger</string> + <string name="pref_flattr_auth_title">Log ind pÃ¥ Flattr</string> + <string name="pref_flattr_auth_sum">Log ind pÃ¥ din flattr-konto for at flattre emner direkte fra appen.</string> <string name="pref_flattr_this_app_title">Flattr denne app</string> - <string name="pref_flattr_this_app_sum">Støt udviklingen af AntennaPod ved at flattr den. Tak!</string> + <string name="pref_flattr_this_app_sum">Støt udviklingen af AntennaPod ved at flattre den. Tak!</string> <string name="pref_revokeAccess_title">Tilbagekald adgang</string> - <string name="pref_revokeAccess_sum">Tilbagekald adgangen til din flattr konto fra denne app.</string> - <string name="pref_auto_flattr_title">Flattr\'er automatisk</string> - <string name="pref_auto_flattr_sum">Konfigurer automatisk flattering</string> - <string name="user_interface_label">Brugerflade</string> + <string name="pref_revokeAccess_sum">Tilbagekald adgangstilladelsen til din flattr-konto fra denne app.</string> + <string name="pref_auto_flattr_title">Automatisk flattring</string> + <string name="pref_auto_flattr_sum">Konfigurer automatisk flattring</string> + <string name="user_interface_label">Brugergrænseflade</string> <string name="pref_set_theme_title">Vælg tema</string> - <string name="pref_set_theme_sum">Skift AntennaPods udseende.</string> - <string name="pref_automatic_download_title">Download automatisk</string> - <string name="pref_automatic_download_sum">Konfigurer automatisk download af episoder</string> - <string name="pref_autodl_wifi_filter_title">Sæt Wi-Fi filter til</string> - <string name="pref_autodl_wifi_filter_sum">Tillad kun automatisk download for de valgte Wi-Fi netværk</string> - <string name="pref_automatic_download_on_battery_title">Download nÃ¥r der ikke oplades</string> - <string name="pref_automatic_download_on_battery_sum">Tillad automatisk download nÃ¥r batteriet ikke oplades</string> - <string name="pref_episode_cache_title">Episode cache</string> + <string name="pref_nav_drawer_title">Tilpas navigationspanel</string> + <string name="pref_nav_drawer_sum">Tilpas udseendet af navigationspanelet</string> + <string name="pref_nav_drawer_items_title">Vælg elementer i navigationspanelet</string> + <string name="pref_nav_drawer_items_sum">Vælg hvilke elementer, der skal vises i navigationspanelet.</string> + <string name="pref_nav_drawer_feed_order_title">Vælg abonnementsorden</string> + <string name="pref_nav_drawer_feed_order_sum">Ændr rækkefølgen af dine abonnementer</string> + <string name="pref_nav_drawer_feed_counter_title">Indstil abonnementstæller</string> + <string name="pref_nav_drawer_feed_counter_sum">Vælg den information, som abonnementstælleren viser</string> + <string name="pref_set_theme_sum">Ændr AntennaPods udseende.</string> + <string name="pref_automatic_download_title">Automatisk overførsel</string> + <string name="pref_automatic_download_sum">Konfigurer automatisk overførsel af udsendelser</string> + <string name="pref_autodl_wifi_filter_title">SlÃ¥ wi-fi-filter til</string> + <string name="pref_autodl_wifi_filter_sum">Tillad automatisk overførsel kun pÃ¥ de valgte wi-fi-netværk</string> + <string name="pref_automatic_download_on_battery_title">Tillad overførsel ved batteridrift</string> + <string name="pref_automatic_download_on_battery_sum">Tillad automatisk overførsel, nÃ¥r batteriet ikke oplades</string> + <string name="pref_parallel_downloads_title">Parallelle overførsler</string> + <string name="pref_episode_cache_title">Mellemlager for udsendelser</string> <string name="pref_theme_title_light">Lys</string> <string name="pref_theme_title_dark">Mørk</string> - <string name="pref_episode_cache_unlimited">Uendelig</string> + <string name="pref_episode_cache_unlimited">Ubegrænset</string> <string name="pref_update_interval_hours_plural">timer</string> <string name="pref_update_interval_hours_singular">time</string> <string name="pref_update_interval_hours_manual">Manuelt</string> <string name="pref_gpodnet_authenticate_title">Log ind</string> - <string name="pref_gpodnet_authenticate_sum">Log ind med din gpodder.net konto for at synkronisere dine abonnementer.</string> + <string name="pref_gpodnet_authenticate_sum">Log ind pÃ¥ din gpodder.net-konto for at synkronisere dine abonnementer.</string> <string name="pref_gpodnet_logout_title">Log ud</string> - <string name="pref_gpodnet_logout_toast">Logget ud</string> - <string name="pref_gpodnet_setlogin_information_title">Skift login information</string> - <string name="pref_gpodnet_setlogin_information_sum">Skift din gpodder.net kontos login information.</string> + <string name="pref_gpodnet_logout_toast">Loggede ud</string> + <string name="pref_gpodnet_setlogin_information_title">Ændr loginoplysninger</string> + <string name="pref_gpodnet_setlogin_information_sum">Ændr din gpodder.net-kontos loginoplysninger.</string> + <string name="pref_gpodnet_sync_changes_title">Synkroniser ændringer nu</string> + <string name="pref_gpodnet_sync_changes_sum">Synkroniser tilstandsændringer for abonnementer og udsendelser med gpodder.net.</string> + <string name="pref_gpodnet_full_sync_title">Fuld synkronisering nu</string> + <string name="pref_gpodnet_full_sync_sum">Synkroniser tilstande for alle abonnementer og udsendelser med gpodder.net.</string> + <string name="pref_gpodnet_sync_sum_last_sync_line">Sidste synkroniseringsforsøg: %1$s (%2$s)</string> + <string name="pref_gpodnet_sync_started">Synkronisering startet</string> + <string name="pref_gpodnet_full_sync_started">Fuld synkronisering startet</string> + <string name="pref_gpodnet_login_status"><![CDATA[Logget ind som <i>%1$s</i> med enheden <i>%2$s</i>]]></string> + <string name="pref_gpodnet_notifications_title">Vis notifikationer med synkroniseringsfejl</string> + <string name="pref_gpodnet_notifications_sum">Denne indstilling vedrører ikke godkendelsesfejl.</string> <string name="pref_playback_speed_title">Afspilningshastigheder</string> - <string name="pref_playback_speed_sum">Tilpas tilgængelige hastigheder for variabelt afspilningshastigheds plugin</string> + <string name="pref_playback_speed_sum">Tilpas tilgængelige hastigheder for lydafspilning med variabel hastighed</string> + <string name="pref_fast_forward">Tidshop for fremadspoling</string> + <string name="pref_fast_forward_sum">Indstil antallet af sekunder, der skal springes fremad, nÃ¥r der trykkes pÃ¥ fremadspolingsknappen</string> + <string name="pref_rewind">Tidshop for tilbagespoling</string> + <string name="pref_rewind_sum">Indstil antallet af sekunder, der skal springes tilbage, nÃ¥r der trykkes pÃ¥ tilbagespolingsknappen</string> <string name="pref_gpodnet_sethostname_title">Indstil værtsnavn</string> <string name="pref_gpodnet_sethostname_use_default_host">Brug standard vært</string> - <string name="pref_expandNotify_title">Udvid notifikation</string> - <string name="pref_expandNotify_sum">Altid udvid notifikationen for at vise afspilningsknapper.</string> - <string name="pref_persistNotify_title">Afspilningskontrol forbliver altid</string> - <string name="pref_persistNotify_sum">Behold notifikation og lÃ¥seskærmskontrol nÃ¥r afspilningen pauses.</string> - <string name="pref_expand_notify_unsupport_toast">Android versioner før 4.1 understøtter ikke udvidede notifikationer.</string> + <string name="pref_expandNotify_title">Udvidelse af notifikation</string> + <string name="pref_expandNotify_sum">Udvid altid notifikationen for at vise afspilningsknapper.</string> + <string name="pref_persistNotify_title">Vedholdende afspilningsknapper</string> + <string name="pref_persistNotify_sum">Behold notifikation og knapper pÃ¥ lÃ¥seskærmen, nÃ¥r afspilningen sættes pÃ¥ pause.</string> + <string name="pref_compact_notification_buttons_title">Indstil knapper pÃ¥ lÃ¥seskærm</string> + <string name="pref_compact_notification_buttons_sum">Vælg afspilningsknapper pÃ¥ lÃ¥seskærmen. Afspil/pause-knappen medtages altid.</string> + <string name="pref_compact_notification_buttons_dialog_title">Vælg højst %1$d knapper</string> + <string name="pref_compact_notification_buttons_dialog_error">Du kan højst vælge %1$d knapper.</string> + <string name="pref_lockscreen_background_title">Indstil baggrund pÃ¥ lÃ¥seskærmen</string> + <string name="pref_lockscreen_background_sum">Sæt baggrunden pÃ¥ lÃ¥seskærmen til billedet for den aktuelle udsendelse. Som en sidevirkning vil det ogsÃ¥ vise billedet i tredjepartsapps.</string> + <string name="pref_showDownloadReport_title">Vis rapport over overførsler</string> + <string name="pref_showDownloadReport_sum">Lav en rapport, som viser detaljer om fejlene, hvis overførsler fejler</string> + <string name="pref_expand_notify_unsupport_toast">Android-versioner før 4.1 understøtter ikke udvidede notifikationer.</string> + <string name="pref_queueAddToFront_sum">Føj nye udsendelser til starten af køen.</string> + <string name="pref_queueAddToFront_title">Føj til starten af køen</string> + <string name="pref_smart_mark_as_played_disabled">SlÃ¥et fra</string> + <string name="pref_image_cache_size_title">Størrelse pÃ¥ mellemlager (cache) for billeder</string> + <string name="pref_image_cache_size_sum">Størrelse pÃ¥ diskmellemlageret (disk cache) for billeder</string> + <string name="crash_report_title">Nedbrudsrapport</string> + <string name="crash_report_sum">Send den seneste nedbrudsrapport via e-mail</string> + <string name="send_email">Send e-mail</string> + <string name="experimental_pref">Eksperimentelt</string> + <string name="pref_sonic_title">Sonic-medieafspiller</string> + <string name="pref_sonic_message">Brug indbygget Sonic-medieafspiller i stedet for Androids indbyggede medieafspiller og Prestissimo</string> + <string name="pref_current_value">Nuværende værdi: %1$s</string> + <string name="pref_proxy_title">Proxy</string> + <string name="pref_proxy_sum">Indstil en netværksproxy</string> + <string name="pref_faq">Ofte spurgte spørgsmÃ¥l</string> + <string name="pref_known_issues">Kendte problemer</string> + <string name="pref_no_browser_found">Ingen webbrowser fundet</string> + <string name="pref_cast_title">Chromecast-understøttelse</string> + <string name="pref_cast_message_play_flavor">Aktiver understøttelse af fjernafspilning pÃ¥ Cast-enheder (sÃ¥som Chromecast, højttalere med indbygget Chromecast, eller Android TV)</string> + <string name="pref_cast_message_free_flavor">Chromecast kræver tredjeparts proprietære biblioteker, som er slÃ¥et fra i denne version af AntennaPod</string> + <string name="pref_enqueue_downloaded_title">Sæt overførte udsendelser i kø</string> + <string name="pref_enqueue_downloaded_summary">Føj udsendelser til køen, sÃ¥ snart de er overført</string> <!--Auto-Flattr dialog--> <string name="auto_flattr_enable">Aktiver automatisk flattring</string> - <string name="auto_flattr_after_percent">Flattr episoder sÃ¥ snart %d procent er blevet afspillet</string> - <string name="auto_flattr_ater_beginning">Flattr episoder nÃ¥r afspilning starter</string> - <string name="auto_flattr_ater_end">Flattr episoder nÃ¥r afspilning slutter</string> + <string name="auto_flattr_after_percent">Flattr udsendelser sÃ¥ snart %d procent er blevet afspillet</string> + <string name="auto_flattr_ater_beginning">Flattr udsendelse nÃ¥r afspilning starter</string> + <string name="auto_flattr_ater_end">Flattr udsendelse nÃ¥r afspilning slutter</string> <!--Search--> - <string name="search_hint">Søg efter feeds eller episoder</string> - <string name="found_in_shownotes_label">Funder i showets noter</string> + <string name="search_hint">Søg efter udsendelser</string> + <string name="found_in_shownotes_label">Fundet i beskrivelse</string> <string name="found_in_chapters_label">Fundet i kapitler</string> + <string name="found_in_authors_label">Fundet i forfattere</string> + <string name="found_in_feeds_label">Fundet i feeds</string> <string name="search_status_no_results">Fandt ingen resultater</string> <string name="search_label">Søg</string> <string name="found_in_title_label">Fundet i titel</string> + <string name="no_results_for_query">Ingen resultater fundet for \"%1$s\"</string> <!--OPML import and export--> - <string name="opml_import_txtv_button_lable">OPML filer lader dig flytte dine podcasts fra en podcastafspiller til en anden.</string> + <string name="opml_import_txtv_button_lable">OPML-filer lader dig flytte dine podcasts fra én podcastafspiller til en anden.</string> + <string name="opml_import_option">Valgmulighed %1$d</string> + <string name="opml_import_explanation_1">Vælg en bestemt filsti fra det lokale filsystem.</string> + <string name="opml_import_explanation_2">Brug en ekstern app som Dropbox, Google Drive eller dit foretrukne filhÃ¥ndteringsprogram til at Ã¥bne en OPML-fil.</string> + <string name="opml_import_explanation_3">Mange apps som Gmail, Dropbox, Google Drive og de fleste filhÃ¥ndteringsprogrammer kan <i>Ã¥bne</i> OPML-filer <i>med</i> AntennaPod.</string> <string name="start_import_label">Start import</string> - <string name="opml_import_label">OPML import</string> + <string name="opml_import_label">OPML-import</string> <string name="opml_directory_error">FEJL!</string> - <string name="reading_opml_label">Indlæser OPML fil</string> - <string name="select_all_label">Vælg alt</string> - <string name="deselect_all_label">Fravælg alt</string> + <string name="reading_opml_label">Indlæser OPML-fil</string> + <string name="opml_reader_error">Der opstod en fejl, da OPML-dokumentet blev forsøgt indlæst</string> + <string name="opml_import_error_no_file">Ingen fil valgt!</string> + <string name="select_all_label">Vælg alle</string> + <string name="deselect_all_label">Fravælg alle</string> + <string name="select_options_label">Vælg…</string> + <string name="choose_file_from_filesystem">Fra lokalt filsystem</string> + <string name="choose_file_from_external_application">Brug ekstern app</string> <string name="opml_export_label">OPML eksport</string> - <string name="export_error_label">Eksport fejl</string> - <string name="opml_export_success_title">Opml eksport lykkedes.</string> - <string name="opml_export_success_sum">.opml filen var skrevet til:\u0020</string> + <string name="html_export_label">HTML-eksport</string> + <string name="exporting_label">Eksporterer…</string> + <string name="export_error_label">Eksportfejl</string> + <string name="opml_export_success_title">OPML-eksport lykkedes.</string> + <string name="opml_export_success_sum">.opml-filen blev skrevet til:\u0020</string> + <string name="opml_import_ask_read_permission">Adgang til eksternt lager er pÃ¥krævet for at læse OPML-filen</string> <!--Sleep timer--> - <string name="set_sleeptimer_label">Sæt søvn timer</string> - <string name="disable_sleeptimer_label">Fjern søvn timer</string> - <string name="enter_time_here_label">Indtast tid</string> + <string name="set_sleeptimer_label">Indstil søvntimer</string> + <string name="disable_sleeptimer_label">SlÃ¥ søvntimer fra</string> + <string name="enter_time_here_label">Vælg tid</string> <string name="sleep_timer_label">Søvn timer</string> <string name="time_left_label">Tid tilbage:\u0020</string> - <string name="time_dialog_invalid_input">Ugyldig indtastning, tid skal være et heltal</string> + <string name="time_dialog_invalid_input">Ugyldig indtastning: tid skal være et heltal</string> + <string name="timer_about_to_expire_label"><b>NÃ¥r timeren er ved at udløbe:</b></string> + <string name="shake_to_reset_label">Ryst for at nulstille timer</string> + <string name="timer_vibration_label">Vibrer</string> + <string name="time_seconds">sekunder</string> + <string name="time_minutes">minutter</string> + <string name="time_hours">timer</string> + <plurals name="time_seconds_quantified"> + <item quantity="one">1 sekund</item> + <item quantity="other">%d sekunder</item> + </plurals> + <plurals name="time_minutes_quantified"> + <item quantity="one">1 minut</item> + <item quantity="other">%d minutter</item> + </plurals> + <plurals name="time_hours_quantified"> + <item quantity="one">1 time</item> + <item quantity="other">%d timer</item> + </plurals> + <string name="auto_enable_label">SlÃ¥ automatisk til</string> + <string name="sleep_timer_enabled_label">Søvntimer slÃ¥et til</string> + <string name="sleep_timer_disabled_label">Søvntimer slÃ¥et fra</string> <!--gpodder.net--> - <string name="gpodnet_taglist_header">KATEGORIER </string> - <string name="gpodnet_toplist_header">TOP PODCASTS</string> + <string name="gpodnet_taglist_header">KATEGORIER</string> + <string name="gpodnet_toplist_header">TOP-PODCASTS</string> <string name="gpodnet_suggestions_header">FORSLAG</string> <string name="gpodnet_search_hint">Søg pÃ¥ gpodder.net</string> <string name="gpodnetauth_login_title">Log ind</string> - <string name="gpodnetauth_login_descr">Velkommen til gpodder.nets login proces. Indsæt dine login informationer:</string> + <string name="gpodnetauth_login_descr">Velkommen til gpodder.nets loginproces. Skriv først dine loginoplysninger:</string> <string name="gpodnetauth_login_butLabel">Log ind</string> - <string name="gpodnetauth_login_register">Hvis du ikke har en konto endnu, sÃ¥ kan du oprette en her:\nhttps://gpodder.net/register/</string> + <string name="gpodnetauth_login_register">Hvis du ikke har en konto endnu, kan du oprette en her:\nhttps://gpodder.net/register/</string> <string name="username_label">Brugernavn</string> - <string name="password_label">Kodeord</string> - <string name="gpodnetauth_device_title">Enheds valg</string> - <string name="gpodnetauth_device_descr">Tilføj en ny enhed for at bruge din gpodder.net konto eller vælg en eksisterende:</string> - <string name="gpodnetauth_device_deviceID">Enhed ID:\u0020</string> - <string name="gpodnetauth_device_caption">Billedtekst</string> + <string name="password_label">Adgangskode</string> + <string name="gpodnetauth_device_title">Valg af enhed</string> + <string name="gpodnetauth_device_descr">Opret en ny enhed til at bruge med din gpodder.net-konto eller vælg en eksisterende:</string> + <string name="gpodnetauth_device_deviceID">Enheds-id:\u0020</string> + <string name="gpodnetauth_device_caption">Enhedsnavn</string> <string name="gpodnetauth_device_butCreateNewDevice">Opret en ny enhed</string> <string name="gpodnetauth_device_chooseExistingDevice">Vælg en eksisterende enhed:</string> - <string name="gpodnetauth_device_errorEmpty">Enheds ID mÃ¥ ikke være tomt</string> - <string name="gpodnetauth_device_errorAlreadyUsed">Enheds ID er allerede i brug</string> + <string name="gpodnetauth_device_errorEmpty">Enheds-id mÃ¥ ikke være tomt</string> + <string name="gpodnetauth_device_errorAlreadyUsed">Enheds-id er allerede i brug</string> + <string name="gpodnetauth_device_caption_errorEmpty">Enhedsnavn mÃ¥ ikke være tomt</string> <string name="gpodnetauth_device_butChoose">Vælg</string> <string name="gpodnetauth_finish_title">Login lykkedes!</string> - <string name="gpodnetauth_finish_descr">Tillykke! Din gpodder.net konto er nu forbundet med din enhed. AntennaPod vil fra nu af automatisk synkronisere dine abonnementer pÃ¥ din enhed med din gpodder.net konto.</string> + <string name="gpodnetauth_finish_descr">Tillykke! Din gpodder.net-konto er nu forbundet med din enhed. AntennaPod vil fra nu af automatisk synkronisere dine abonnementer pÃ¥ din enhed med din gpodder.net-konto.</string> <string name="gpodnetauth_finish_butsyncnow">Start synkronisering nu</string> <string name="gpodnetauth_finish_butgomainscreen">GÃ¥ til hovedskærmen</string> - <string name="gpodnetsync_auth_error_title">gpodder.net autentificeringfejl</string> - <string name="gpodnetsync_auth_error_descr">Forkert brugernavn eller kodeord</string> - <string name="gpodnetsync_error_title">gpodder.net synkroniseringsfejl</string> + <string name="gpodnetsync_auth_error_title">gpodder.net-autentificeringfejl</string> + <string name="gpodnetsync_auth_error_descr">Forkert brugernavn eller adgangskode</string> + <string name="gpodnetsync_error_title">gpodder.net-synkroniseringsfejl</string> <string name="gpodnetsync_error_descr">En fejl opstod under synkronisering:\u0020</string> + <string name="gpodnetsync_pref_report_successful">Lykkedes</string> + <string name="gpodnetsync_pref_report_failed">Fejlede</string> <!--Directory chooser--> - <string name="selected_folder_label">Valgte mappe:</string> + <string name="selected_folder_label">Valgt mappe:</string> <string name="create_folder_label">Opret mappe</string> - <string name="choose_data_directory">Vælg data mappe</string> + <string name="choose_data_directory">Vælg datamappe</string> + <string name="choose_data_directory_message">Vælg venligst roden af din datamappe. AntennaPod vil oprette passende undermapper.</string> + <string name="choose_data_directory_permission_rationale">Adgang til eksternt lager er kræver for at ændre datamappen</string> <string name="create_folder_msg">Opret en ny mappe med navnet \"%1$s\"?</string> - <string name="create_folder_success">Opret en ny mappe</string> + <string name="create_folder_success">Oprettede ny mappe</string> <string name="create_folder_error_no_write_access">Kan ikke skrive til denne mappe</string> <string name="create_folder_error_already_exists">Mappen eksisterer allerede</string> - <string name="create_folder_error">Kunne ikke oprette ny mappe</string> + <string name="create_folder_error">Kunne ikke oprette mappe</string> + <string name="folder_does_not_exist_error">\"%1$s\" findes ikke</string> + <string name="folder_not_readable_error">\"%1$s\" er ikke læsbar</string> + <string name="folder_not_writable_error">\"%1$s\" er ikke skrivbar</string> <string name="folder_not_empty_dialog_title">Mappen er ikke tom</string> - <string name="folder_not_empty_dialog_msg">Mappen du har valgt er ikke tom. Medie downloads og andre filer vil blive placeret i denne mappe. Forsæt alligevel?</string> - <string name="set_to_default_folder">Vælg standard mappe</string> - <string name="pref_pausePlaybackForFocusLoss_sum">Sæt afspilning pÃ¥ pause i stedet for at sænke lydniveauet nÃ¥r en anden app vil afspille lyde</string> - <string name="pref_pausePlaybackForFocusLoss_title">Pause for afbrydelser</string> + <string name="folder_not_empty_dialog_msg">Mappen du har valgt er ikke tom. Overførte medier og andre filer vil blive placeret direkte i denne mappe. Fortsæt alligevel?</string> + <string name="set_to_default_folder">Vælg standardmappe</string> + <string name="pref_pausePlaybackForFocusLoss_sum">Sæt afspilning pÃ¥ pause i stedet for at sænke lydniveauet, nÃ¥r en anden app vil afspille lyde</string> + <string name="pref_pausePlaybackForFocusLoss_title">Sæt pÃ¥ pause ved afbrydelser</string> + <string name="pref_resumeAfterCall_sum">Genoptag afspilning nÃ¥r et telefonkald afsluttes</string> + <string name="pref_resumeAfterCall_title">Genoptag efter opkald</string> + <string name="pref_restart_required">AntennaPod skal genstartes for at denne indstilling kan træde i kraft</string> <!--Online feed view--> <string name="subscribe_label">Abonner</string> <string name="subscribed_label">Abonneret</string> + <string name="downloading_label">Overfører…</string> <!--Content descriptions for image buttons--> - <string name="show_chapters_label">Vis kapitler</string> - <string name="show_shownotes_label">Vis shownoter</string> - <string name="show_cover_label">Vis billede</string> <string name="rewind_label">Spol tilbage</string> - <string name="fast_forward_label">Hurtigt fremad</string> + <string name="fast_forward_label">Spol frem</string> <string name="media_type_audio_label">Lyd</string> <string name="media_type_video_label">Video</string> <string name="navigate_upwards_label">Naviger opad</string> - <string name="butAction_label">Flere handlinger</string> - <string name="status_playing_label">Episode afspilles</string> - <string name="status_downloading_label">Episode downloades</string> - <string name="status_downloaded_label">Episode er downloadet</string> - <string name="status_unread_label">Nyt emne</string> - <string name="in_queue_label">Episode er i køen</string> - <string name="new_episodes_count_label">Antal nye episoder</string> - <string name="in_progress_episodes_count_label">Antallet af episoder du er begyndt at lytte til</string> - <string name="drag_handle_content_description">Træk for at skifte denne tings position</string> + <string name="status_downloading_label">Udsendelse overføres</string> + <string name="in_queue_label">Udsendelse er i køen</string> + <string name="drag_handle_content_description">Træk for at ændre dette elements placering</string> <string name="load_next_page_label">Indlæs næste side</string> <!--Feed information screen--> <string name="authentication_label">Godkendelse</string> - <string name="authentication_descr">Skift dit brugernavn og kodeord for denne podcast og dets episoder.</string> + <string name="authentication_descr">Ændr dit brugernavn og adgangskode for denne podcast og dets udsendelser.</string> + <string name="auto_download_settings_label">Indstillinger for Automatisk overførsel</string> + <string name="episode_filters_label">Udsendelsesfilter</string> + <string name="episode_filters_description">Liste af ord, der bliver brugt til at beslutte, om en udsendelse skal medtages eller udelades ved automatisk overførsel</string> + <string name="episode_filters_include">Medtag</string> + <string name="episode_filters_exclude">Udelad</string> + <string name="episode_filters_hint">Enkeltord \n +\"Flere ord\"</string> + <string name="keep_updated">Hold opdateret</string> <!--Progress information--> + <string name="progress_upgrading_database">Opgraderer databasen</string> <!--AntennaPodSP--> - <string name="sp_apps_importing_feeds_msg">Importerer abonnementer fra single-purpose apps…</string> + <string name="sp_apps_importing_feeds_msg">Importerer abonnementer fra enkeltformÃ¥lsapps…</string> + <string name="search_itunes_label">Søg i iTunes</string> + <string name="filter">Filtrér</string> + <string name="search_fyyd_label">Søg i fyyd</string> + <!--Episodes apply actions--> + <string name="all_label">Alle</string> + <string name="selected_all_label">Markerede alle udsendelser</string> + <string name="none_label">Ingen</string> + <string name="deselected_all_label">Afmarkerede alle udsendelser</string> + <string name="played_label">Afspillede</string> + <string name="selected_played_label">Markerede afspillede udsendelser</string> + <string name="unplayed_label">Uafspillede</string> + <string name="selected_unplayed_label">Markerede uafspillede udsendelser</string> + <string name="downloaded_label">Overførte</string> + <string name="selected_downloaded_label">Markerede overførte udsendelser</string> + <string name="not_downloaded_label">Ikke-overførte</string> + <string name="selected_not_downloaded_label">Markerede ikke-overførte udsendelser</string> + <string name="queued_label">Sat i kø</string> + <string name="selected_queued_label">Markerede udsendelser, der er sat i kø</string> + <string name="not_queued_label">Ikke sat i kø</string> + <string name="selected_not_queued_label">Markerede udsendelser, der ikke er sat i kø</string> + <string name="has_media">Har medier</string> + <string name="selected_has_media_label">Markerede udsendelser med medier</string> + <!--Sort--> + <string name="sort_title_a_z">Titel (A \u2192 Ã…)</string> + <string name="sort_title_z_a">Titel (Ã… \u2192 A)</string> + <string name="sort_date_new_old">Dato (ny \u2192 gammel)</string> + <string name="sort_date_old_new">Dato (gammel \u2192 ny)</string> + <string name="sort_duration_short_long">Varighed (kort \u2192 lang)</string> + <string name="sort_duration_long_short">Varighed (lang \u2192 kort)</string> <!--Rating dialog--> + <string name="rating_title">Kan du lide AntennaPod?</string> + <string name="rating_message">Vi vil sætte pris pÃ¥, hvis du vil bedømme AntennaPod.</string> + <string name="rating_never_label">Lad mig være</string> + <string name="rating_later_label">PÃ¥mind mig senere</string> + <string name="rating_now_label">Klart, lad os gøre det!</string> <!--Audio controls--> + <string name="audio_controls">Lydknapper</string> + <string name="playback_speed">Afspilningshastighed</string> + <string name="volume">Lydstyrke</string> + <string name="left_short">V</string> + <string name="right_short">H</string> + <string name="audio_effects">Lydeffekter</string> + <string name="stereo_to_mono">Gør stereo til mono</string> + <string name="sonic_only">Kun Sonic</string> <!--proxy settings--> + <string name="proxy_type_label">Type</string> + <string name="host_label">Vært</string> + <string name="port_label">Port</string> + <string name="optional_hint">(Valgfrit)</string> + <string name="proxy_test_label">Afprøv</string> + <string name="proxy_checking">Kontrollerer…</string> + <string name="proxy_test_successful">Afprøvning lykkedes</string> + <string name="proxy_test_failed">Afprøvning fejlede</string> + <string name="proxy_host_empty_error">Vært kan ikke være tom</string> + <string name="proxy_host_invalid_error">Vært er ikke en gyldig IP-adresse eller et gyldigt domæne</string> + <string name="proxy_port_invalid_error">Port ikke gyldig</string> + <!--Casting--> + <string name="cast_media_route_menu_title">Afspil pÃ¥ …</string> + <string name="cast_disconnect_label">Afbryd cast-sessionen</string> + <string name="cast_not_castable">Det valgte medie er ikke kompatibelt med cast-enheden</string> + <string name="cast_failed_to_play">Kunne ikke starte afspilning af medie</string> + <string name="cast_failed_to_stop">Kunne ikke stoppe afspilning af medie</string> + <string name="cast_failed_to_pause">Kunne ikke sætte afspilning af medie pÃ¥ pause</string> + <!--<string name="cast_failed_to_connect">Could not connect to the device</string>--> + <string name="cast_failed_setting_volume">Kunne ikke indstille lydstyrken</string> + <string name="cast_failed_no_connection">Der er ingen forbindelse til cast-enheden</string> + <string name="cast_failed_no_connection_trans">Forbindelsen til cast-enheden er mistet. Appen forsøger at genskabe forbindelsen, om muligt. Vent venligst et par sekunder og prøv igen.</string> + <string name="cast_failed_perform_action">Det lykkedes ikke at udføre handlingen</string> + <string name="cast_failed_status_request">Det lykkedes ikke at synkronisere med cast-enheden</string> + <string name="cast_failed_seek">Det lykkedes ikke at søge til den nye position pÃ¥ cast-enheden</string> + <string name="cast_failed_receiver_player_error">Modtagerafspilleren er stødt pÃ¥ en alvorlig fejl</string> + <string name="cast_failed_media_error_skipping">Fejl ved afspilning af medie. Springer over…</string> </resources> diff --git a/core/src/main/res/values-de/strings.xml b/core/src/main/res/values-de/strings.xml index 3f3daff52..c7da72961 100644 --- a/core/src/main/res/values-de/strings.xml +++ b/core/src/main/res/values-de/strings.xml @@ -26,21 +26,27 @@ <!--Statistics fragment--> <string name="total_time_listened_to_podcasts">Gesamtzeit gespielter Podcasts:</string> <string name="statistics_details_dialog">%1$d von %2$d Episoden gestartet.\n\n%3$s von %4$s Episoden gespielt.</string> + <string name="statistics_mode">Statistik-Modus</string> + <string name="statistics_mode_normal">Berechne die tatsächlich gespielte Dauer. Zweimaliges Abspielen wird auch zwei Mal gezählt, als gespielt markierte Episoden jedoch gar nicht</string> + <string name="statistics_mode_count_all">Aufsummieren aller als gespielt markierter Episoden</string> + <string name="statistics_speed_not_counted">Hinweis: Die Abspielgeschwindigkeit wird nicht berücksichtigt.</string> <!--Main activity--> <string name="drawer_open">Menü öffnen</string> <string name="drawer_close">Menü schließen</string> <string name="drawer_preferences">Seitenleisten-Einstellungen</string> - <string name="drawer_feed_order_unplayed_episodes">Sortieren nach Zähler</string> + <string name="drawer_feed_order_unplayed_episodes">Nach Zähler sortieren </string> <string name="drawer_feed_order_alphabetical">Alphabetisch sortieren</string> - <string name="drawer_feed_order_last_update">Sortiere nach Veröffentlichungsdatum</string> + <string name="drawer_feed_order_last_update">Nach Veröffentlichungsdatum sortieren</string> + <string name="drawer_feed_order_most_played">Nach Anzahl gespielter Episoden sortieren</string> <string name="drawer_feed_counter_new_unplayed">Anzahl neuer und ungespielter Episoden</string> <string name="drawer_feed_counter_new">Anzahl neuer Episoden</string> <string name="drawer_feed_counter_unplayed">Anzahl ungespielter Episoden</string> + <string name="drawer_feed_counter_downloaded">Anzahl heruntergeladener Episoden</string> <string name="drawer_feed_counter_none">Keine</string> <!--Webview actions--> <string name="open_in_browser_label">Im Browser öffnen</string> <string name="copy_url_label">URL kopieren</string> - <string name="share_url_label">URL teilen</string> + <string name="share_url_label">Teile URL</string> <string name="copied_url_msg">URL wurde in die Zwischenablage kopiert.</string> <string name="go_to_position_label">Gehe zu dieser Position</string> <!--Playback history--> @@ -50,6 +56,7 @@ <string name="cancel_label">Abbrechen</string> <string name="yes">Ja</string> <string name="no">Nein</string> + <string name="reset">Reset</string> <string name="author_label">Autor</string> <string name="language_label">Sprache</string> <string name="url_label">URL</string> @@ -60,7 +67,8 @@ <string name="refresh_label">Aktualisieren</string> <string name="external_storage_error_msg">Der externe Speicher ist nicht verfügbar. Bitte stelle sicher, dass das externe Speichermedium eingelegt ist, damit die Anwendung funktioniert.</string> <string name="chapters_label">Kapitel</string> - <string name="shownotes_label">Notizen</string> + <string name="chapter_duration">Dauer: %1$s</string> + <string name="shownotes_label">Shownotizen</string> <string name="description_label">Beschreibung</string> <string name="most_recent_prefix">Letzte Episode:\u0020</string> <string name="episodes_suffix">\u0020Episoden</string> @@ -82,7 +90,7 @@ <string name="send_label">Senden…</string> <string name="episode_cleanup_never">Nie</string> <string name="episode_cleanup_queue_removal">Wenn nicht in der Abspielliste</string> - <string name="episode_cleanup_after_listening">wenn fertig gespielt gespielt</string> + <string name="episode_cleanup_after_listening">Wenn fertig gespielt</string> <plurals name="episode_cleanup_days_after_listening"> <item quantity="one">1 Tag nachdem fertig gespielt</item> <item quantity="other">%d Tage nachdem fertig gespielt</item> @@ -92,23 +100,26 @@ <string name="etxtFeedurlHint">URL des Feeds oder der Webseite</string> <string name="txtvfeedurl_label">Podcast per URL hinzufügen</string> <string name="podcastdirectories_label">Podcast in Verzeichnis finden</string> - <string name="podcastdirectories_descr">Bei gpodder.net kannst du neue Podcasts nach Name, Kategorie oder Popularität suchen. Oder suche bei iTunes.</string> + <string name="podcastdirectories_descr">Für neue Podcasts kannst du iTunes oder fyyd durchsuchen, oder gpodder.net nach Name, Kategorie oder Popularität durchstöbern</string> <string name="browse_gpoddernet_label">gpodder.net durchsuchen</string> <!--Actions on feeds--> <string name="mark_all_read_label">Alle als gespielt markieren</string> - <string name="mark_all_read_msg">Alle Episoden als gespielt markieren</string> + <string name="mark_all_read_msg">Alle Episoden als gespielt markiert</string> <string name="mark_all_read_confirmation_msg">Bitte bestätige, dass alle Episoden als gespielt markiert werden sollen.</string> <string name="mark_all_read_feed_confirmation_msg">Bitte bestätige, dass alle Episoden in diesem Feed als gespielt markiert werden sollen.</string> <string name="mark_all_seen_label">Alle als gesehen markieren</string> + <string name="mark_all_seen_msg">Alle Episoden als gesehen markiert</string> + <string name="mark_all_seen_confirmation_msg">Bitte bestätige, dass alle Episoden als gesehen markiert werden sollen.</string> <string name="show_info_label">Informationen anzeigen</string> + <string name="rename_feed_label">Podcast umbenennen</string> <string name="remove_feed_label">Podcast entfernen</string> <string name="share_label">Teilen…</string> - <string name="share_link_label">Webseiten-Link teilen</string> + <string name="share_link_label">Teile Link</string> <string name="share_link_with_position_label">Teile Link mit Zeitmarke</string> <string name="share_feed_url_label">Teile URL des Podcasts</string> - <string name="share_item_url_label">URL zur Datei teilen</string> - <string name="share_item_url_with_position_label">URL zur Datei und Zeitmarke teilen</string> - <string name="feed_delete_confirmation_msg">Bitte bestätige, dass du diesen Feed und ALLE heruntergeladenen Episoden dieses Feeds entfernen möchtest.</string> + <string name="share_item_url_label">Teile URL der Episode</string> + <string name="share_item_url_with_position_label">Teile URL der Episode mit Zeitmarke</string> + <string name="feed_delete_confirmation_msg">Bitte bestätige, dass du den Feed \"%1$s\" und ALLE heruntergeladenen Episoden löschen möchtest.</string> <string name="feed_remover_msg">Entferne Feed</string> <string name="load_complete_feed">Kompletten Feed aktualisieren</string> <string name="hide_episodes_title">Episoden verbergen</string> @@ -120,9 +131,10 @@ <string name="hide_not_queued_episodes_label">Nicht in Abspielliste</string> <string name="hide_downloaded_episodes_label">Heruntergeladen</string> <string name="hide_not_downloaded_episodes_label">Nicht heruntergeladen</string> + <string name="hide_has_media_label">Hat Medien</string> <string name="filtered_label">Gefiltert</string> <string name="refresh_failed_msg">{fa-exclamation-circle} Aktualisierung fehlgeschlagen</string> - <string name="open_podcast">Öffne Podcast</string> + <string name="open_podcast">Podcast öffnen</string> <!--actions on feeditems--> <string name="download_label">Herunterladen</string> <string name="play_label">Abspielen</string> @@ -130,7 +142,9 @@ <string name="stop_label">Stop</string> <string name="stream_label">Streamen</string> <string name="remove_label">Entfernen</string> + <string name="delete_label">Löschen</string> <string name="remove_episode_lable">Episode entfernen</string> + <string name="marked_as_seen_label">Als gesehen markiert</string> <string name="mark_read_label">Als gespielt markieren</string> <string name="marked_as_read_label">Als gespielt markiert</string> <string name="mark_unread_label">Als ungespielt markieren</string> @@ -216,12 +230,13 @@ <string name="move_to_top_label">Zum Anfang verschieben</string> <string name="move_to_bottom_label">Zum Ende verschieben</string> <string name="sort">Sortieren</string> - <string name="alpha">Alphabetisch</string> <string name="date">Datum</string> <string name="duration">Dauer</string> + <string name="episode_title">Episodentitel</string> + <string name="feed_title">Podcastname</string> <string name="ascending">Aufsteigend</string> <string name="descending">Absteigend</string> - <string name="clear_queue_confirmation_msg">Bitte bestätige, dass alle Episoden in der Warteschlange gelöscht werden sollen</string> + <string name="clear_queue_confirmation_msg">Bitte bestätige, dass ALLE Episoden aus der Abspielliste entfernt werden sollen</string> <!--Flattr--> <string name="flattr_auth_label">Flattr Anmeldung</string> <string name="flattr_auth_explanation">Drücke den Button unten, um den Authentifizierungsprozess zu starten. Du wirst zur Flattr-Anmeldeseite weitergeleitet. Hier wirst du gefragt, AntennaPod die Erlaubnis zu geben, Dinge zu flattrn. Nachdem du die Erlaubnis erteilt hast, kehrst du automatisch zu diesem Bildschirm zurück.</string> @@ -258,7 +273,7 @@ <string name="no_items_label">Es sind keine Einträge in dieser Liste.</string> <string name="no_feeds_label">Du hast noch keine Feeds abonniert.</string> <string name="no_chapters_label">Diese Episode hat keine Kapitel.</string> - <string name="no_shownotes_label">Episode hat keine Shownotes.</string> + <string name="no_shownotes_label">Episode hat keine Shownotizen.</string> <!--Preferences--> <string name="storage_pref">Speicher</string> <string name="project_pref">Projekt</string> @@ -268,17 +283,19 @@ <string name="services_label">Dienste</string> <string name="flattr_label">Flattr</string> <string name="pref_episode_cleanup_title">Automatisches Löschen</string> - <string name="pref_episode_cleanup_summary">Episoden, die weder in Abspielliste noch favorisiert sind, können gelöscht werden, wenn beim automatischen Herunterladen Speicherplatz für neue Episoden gebraucht wird</string> + <string name="pref_episode_cleanup_summary">Episoden, die weder in der Abspielliste noch Favoriten sind, können gelöscht werden, wenn beim automatischen Herunterladen Speicherplatz für neue Episoden gebraucht wird</string> <string name="pref_pauseOnDisconnect_sum">Wiedergabe pausieren, wenn Kopfhörer ausgesteckt oder Bluetooth getrennt wird</string> <string name="pref_unpauseOnHeadsetReconnect_sum">Wiedergabe fortsetzen, wenn Kopfhörer wieder eingesteckt werden</string> <string name="pref_unpauseOnBluetoothReconnect_sum">Wiedergabe fortsetzen, wenn Bluetooth wieder verbunden ist</string> - <string name="pref_hardwareForwardButtonSkips_title">Nächster-Taste überspringt</string> - <string name="pref_hardwareForwardButtonSkips_sum">Springe zur nächsten Episode (statt Vorspulen), wenn die \"Nächster\"-Taste gedrückt wird</string> - <string name="pref_followQueue_sum">Springe zur nächsten Episode, wenn die vorherige Episode endet</string> + <string name="pref_hardwareForwardButtonSkips_title">\"Nächster\"-Taste springt zur nächsten Episode</string> + <string name="pref_hardwareForwardButtonSkips_sum">Zur nächsten Episode springen, wenn die \"Nächster\"-Taste gedrückt wird (statt vorzuspulen)</string> + <string name="pref_hardwarePreviousButtonRestarts_title">Vorheriger-Taste startet neu</string> + <string name="pref_hardwarePreviousButtonRestarts_sum">Die Wiedergabe der aktuellen Episode neu starten, wenn die \"Vorheriger\"-Taste gedrückt wird (statt zurückzuspulen)</string> + <string name="pref_followQueue_sum">Springe zur nächsten Episode in der Abspielliste, wenn die Wiedergabe endet</string> <string name="pref_auto_delete_sum">Episode löschen, wenn die Wiedergabe endet</string> <string name="pref_auto_delete_title">Automatisches Löschen</string> - <string name="pref_smart_mark_as_played_sum">Episoden werden als gespielt markiert, wenn weniger als eine bestimmte Anzahl Sekunden Restspielzeit übrig sind</string> - <string name="pref_smart_mark_as_played_title">Schlaues als gespielt markieren</string> + <string name="pref_smart_mark_as_played_sum">Episoden werden bereits als gespielt markiert, wenn weniger als eine bestimmte Anzahl Sekunden Restspielzeit übrig sind</string> + <string name="pref_smart_mark_as_played_title">Schlau als gespielt markieren</string> <string name="pref_skip_keeps_episodes_sum">Behalte Episoden beim Ãœberspringen</string> <string name="pref_skip_keeps_episodes_title">Behalte übersprungene Episoden</string> <string name="playback_pref">Wiedergabe</string> @@ -340,14 +357,22 @@ <string name="pref_gpodnet_logout_toast">Abmeldung war erfolgreich</string> <string name="pref_gpodnet_setlogin_information_title">Anmeldeinformationen ändern</string> <string name="pref_gpodnet_setlogin_information_sum">Ändere die Anmeldeinformationen deines gpodder.net Profils</string> - <string name="pref_gpodnet_sync_title">Jetzt synchronisieren</string> - <string name="pref_gpodnet_sync_sum">Synchronisiere Abonnements und Episodenstatus mit gpodder.net</string> + <string name="pref_gpodnet_sync_changes_title">Jetzt Änderungen synchronisieren</string> + <string name="pref_gpodnet_sync_changes_sum">Änderungen an Abonnement- und Episoden-Status mit gpodder.net synchronisieren.</string> + <string name="pref_gpodnet_full_sync_title">Jetzt komplett synchronisieren</string> + <string name="pref_gpodnet_full_sync_sum">Kompletten Abonnement- und Episoden-Status mit gpodder.net synchronisieren.</string> + <string name="pref_gpodnet_sync_sum_last_sync_line">Letzter Synchronisierungsversuch: %1$s (%2$s)</string> <string name="pref_gpodnet_sync_started">Synchronisation starten</string> + <string name="pref_gpodnet_full_sync_started">Komplette Synchronisierung gestartet</string> <string name="pref_gpodnet_login_status"><![CDATA[Eingeloggt als <i>%1$s</i> mit dem Gerät <i>%2$s</i>]]></string> + <string name="pref_gpodnet_notifications_title">Zeige Benachrichtungen bei Synchronisierungsfehlern</string> + <string name="pref_gpodnet_notifications_sum">Diese Einstellung gilt nicht für Authentifizierungsfehler.</string> <string name="pref_playback_speed_title">Wiedergabegeschwindigkeiten</string> <string name="pref_playback_speed_sum">Lege die verfügbaren Werte für die Veränderung der Wiedergabeschwindigkeit fest</string> <string name="pref_fast_forward">Vorspulzeit</string> + <string name="pref_fast_forward_sum">Passe an, wie viele Sekunden vorgespult wird, wenn die entsprechende Hardware-Taste gedrückt wird</string> <string name="pref_rewind">Rückspulzeit</string> + <string name="pref_rewind_sum">Passe an, wie viele Sekunden zurückgespult wird, wenn die entsprechende Hardware-Taste gedrückt wird</string> <string name="pref_gpodnet_sethostname_title">Hostname ändern</string> <string name="pref_gpodnet_sethostname_use_default_host">Standard-Host verwenden</string> <string name="pref_expandNotify_title">Benachrichtigung erweitern</string> @@ -358,15 +383,13 @@ <string name="pref_compact_notification_buttons_sum">Verändere die Wiedergabetasten auf dem Lockscreen. Die Abspielen-/Pause-Taste wird immer angezeigt.</string> <string name="pref_compact_notification_buttons_dialog_title">Wähle bis zu %1$d Elemente aus</string> <string name="pref_compact_notification_buttons_dialog_error">Du kannst maximal %1$d Elemente auswählen.</string> - <string name="pref_show_subscriptions_in_drawer_title">Zeige Abonnements</string> - <string name="pref_show_subscriptions_in_drawer_sum">Liste von Abonnements in Seitenleiste anzeigen</string> <string name="pref_lockscreen_background_title">Lockscreen-Hintergrund einstellen</string> <string name="pref_lockscreen_background_sum">Verwende das aktuelle Episodenbild als Lockscreen-Hintergrund. Es wird als Nebeneffekt auch in anderen Apps gezeigt.</string> <string name="pref_showDownloadReport_title">Zeige Download-Bericht</string> <string name="pref_showDownloadReport_sum">Wenn Downloads fehlschlagen, erstelle einen Bericht, der die Details des Fehlschlages beschreibt.</string> <string name="pref_expand_notify_unsupport_toast">Android-Versionen vor 4.1 unterstützen keine erweiterten Benachrichtigungen.</string> - <string name="pref_queueAddToFront_sum">Fügen Sie neue Folgen auf den Anfang der Warteschlange.</string> - <string name="pref_queueAddToFront_title">Vorne in Abspielliste einreihen</string> + <string name="pref_queueAddToFront_sum">Neue Folgen zum Anfang der Abspielliste hinzufügen.</string> + <string name="pref_queueAddToFront_title">Zum Anfang der Abspielliste hinzufügen</string> <string name="pref_smart_mark_as_played_disabled">Deaktiviert</string> <string name="pref_image_cache_size_title">Größe des Bilder-Zwischenspeichers</string> <string name="pref_image_cache_size_sum">Größe des Zwischenspeichers für Bilder</string> @@ -374,7 +397,7 @@ <string name="crash_report_sum">Sende den aktuellen Absturzbericht per E-Mail</string> <string name="send_email">E-Mail senden</string> <string name="experimental_pref">Experimentell</string> - <string name="pref_sonic_title">Sonic Mediaplayer</string> + <string name="pref_sonic_title">Sonic Media Player</string> <string name="pref_sonic_message">Benutze den integrierten Sonic Mediaplayer als Ersatz für Androids eigenen Mediaplayer und Prestissimo</string> <string name="pref_current_value">Aktueller Wert: %1$s</string> <string name="pref_proxy_title">Proxy</string> @@ -383,19 +406,25 @@ <string name="pref_known_issues">Bekannte Probleme</string> <string name="pref_no_browser_found">Kein Browser gefunden.</string> <string name="pref_cast_title">Chromecast-Unterstützung</string> - <string name="pref_cast_message">Aktiviere Wiedergabe auf Chromecast-Geräten (unter anderem Lautsprecher, Android TV)</string> + <string name="pref_cast_message_play_flavor">Aktiviere die Unterstützung von Cast-Geräten (Chromecast, Lautsprecher oder Android TV) zum entfernten Abspielen</string> + <string name="pref_cast_message_free_flavor">Chromecast benötigt proprietäre Bibliotheken von Drittanbietern, die in dieser Version von AntennaPod deaktiviert sind</string> + <string name="pref_enqueue_downloaded_title">Downloads zur Abspielliste hinzufügen</string> + <string name="pref_enqueue_downloaded_summary">Füge heruntergeladene Episoden zur Abspielliste hinzu</string> <!--Auto-Flattr dialog--> <string name="auto_flattr_enable">Automatisches Flattrn aktivieren</string> <string name="auto_flattr_after_percent">Flattr eine Episode, sobald %d Prozent gespielt worden sind</string> <string name="auto_flattr_ater_beginning">Flattr Episode, sobald die Wiedergabe beginnt</string> <string name="auto_flattr_ater_end">Flattr Episode, sobald die Wiedergabe endet</string> <!--Search--> - <string name="search_hint">Suche nach Feeds oder Episoden</string> - <string name="found_in_shownotes_label">In Sendungsnotizen gefunden</string> + <string name="search_hint">Suche nach Episoden</string> + <string name="found_in_shownotes_label">In Shownotizen gefunden</string> <string name="found_in_chapters_label">In Kapiteln gefunden</string> + <string name="found_in_authors_label">In Autoren gefunden</string> + <string name="found_in_feeds_label">In Feeds gefunden</string> <string name="search_status_no_results">Keine Ergebnisse gefunden</string> - <string name="search_label">Suche</string> + <string name="search_label">Suchen</string> <string name="found_in_title_label">In Titel gefunden</string> + <string name="no_results_for_query">Es wurden keine Ergebnisse für \"%1$s\" gefunden</string> <!--OPML import and export--> <string name="opml_import_txtv_button_lable">Mit OPML Dateien kannst du deine Podcasts von einem Podcatcher auf einen anderen übertragen</string> <string name="opml_import_option">Option %1$d</string> @@ -414,21 +443,22 @@ <string name="choose_file_from_filesystem">Vom lokalen Dateisystem</string> <string name="choose_file_from_external_application">Verwende externe Anwendung</string> <string name="opml_export_label">OPML Export</string> + <string name="html_export_label">HTML Export</string> <string name="exporting_label">Exportiere…</string> <string name="export_error_label">Exportfehler</string> <string name="opml_export_success_title">OPML Export erfolgreich</string> <string name="opml_export_success_sum">Die OPML Datei wurde unter dem folgenden Pfad gespeichert:\u0020</string> <string name="opml_import_ask_read_permission">Zugriff auf externen Speicher wird benötigt, um die OPML Datei zu lesen</string> <!--Sleep timer--> - <string name="set_sleeptimer_label">Schlummerfunktion</string> + <string name="set_sleeptimer_label">Timer einstellen</string> <string name="disable_sleeptimer_label">Schlummerfunktion deaktivieren</string> <string name="enter_time_here_label">Zeit eingeben</string> <string name="sleep_timer_label">Schlummerfunktion</string> <string name="time_left_label">Zeit übrig:\u0020</string> <string name="time_dialog_invalid_input">Ungültige Eingabe, Zeit muss eine Ganzzahl sein</string> - <string name="timer_about_to_expire_label"><b>Wenn der Timer gleich abläuft:</b></string> + <string name="timer_about_to_expire_label"><b>Kurz bevor der Timer abläuft:</b></string> <string name="shake_to_reset_label">Timer durch Schütteln zurücksetzen</string> - <string name="timer_vibration_label">Vibriere</string> + <string name="timer_vibration_label">Vibrieren</string> <string name="time_seconds">Sekunden</string> <string name="time_minutes">Minuten</string> <string name="time_hours">Stunden</string> @@ -444,6 +474,9 @@ <item quantity="one">1 Stunde</item> <item quantity="other">%d Stunden</item> </plurals> + <string name="auto_enable_label">Automatisch aktivieren</string> + <string name="sleep_timer_enabled_label">Schlummerfunktion aktiviert</string> + <string name="sleep_timer_disabled_label">Schlummerfunktion deaktiviert</string> <!--gpodder.net--> <string name="gpodnet_taglist_header">KATEGORIEN</string> <string name="gpodnet_toplist_header">BESTE PODCASTS</string> @@ -473,8 +506,10 @@ <string name="gpodnetsync_auth_error_descr">Falscher Benutzername oder falsches Passwort</string> <string name="gpodnetsync_error_title">gpodder.net Synchronisierungsfehler</string> <string name="gpodnetsync_error_descr">Ein Fehler ist beim Synchronisieren aufgetreten:\u0020</string> + <string name="gpodnetsync_pref_report_successful">Erfolgreich</string> + <string name="gpodnetsync_pref_report_failed">Fehlgeschlagen</string> <!--Directory chooser--> - <string name="selected_folder_label">Ausgewählter Ordner</string> + <string name="selected_folder_label">Ausgewählter Ordner:</string> <string name="create_folder_label">Neuer Ordner</string> <string name="choose_data_directory">Datenordner auswählen</string> <string name="choose_data_directory_message">Bitte wähle eine Basis für deinen Datenordner. AntennaPod erstellt automatisch die richtigen Unterverzeichnisse.</string> @@ -525,6 +560,7 @@ <string name="sp_apps_importing_feeds_msg">Importiere Abonnements aus Single-Purpose Apps</string> <string name="search_itunes_label">iTunes durchsuchen</string> <string name="filter">Filtern</string> + <string name="search_fyyd_label">fyyd durchsuchen</string> <!--Episodes apply actions--> <string name="all_label">Alle</string> <string name="selected_all_label">Alle Episoden ausgewählt</string> @@ -542,6 +578,8 @@ <string name="selected_queued_label">Episoden in Abspielliste ausgewählt</string> <string name="not_queued_label">Nicht in Abspielliste</string> <string name="selected_not_queued_label">Episoden nicht in Abspielliste ausgewählt</string> + <string name="has_media">Hat Medien</string> + <string name="selected_has_media_label">Episoden mit Medien ausgewählt</string> <!--Sort--> <string name="sort_title_a_z">Titel (A \u2192 Z)</string> <string name="sort_title_z_a">Titel (Z \u2192 A)</string> @@ -590,5 +628,6 @@ <string name="cast_failed_perform_action">Aktion konnte nicht ausgeführt werden</string> <string name="cast_failed_status_request">Synchronization mit Cast-Gerät fehlgeschlagen</string> <string name="cast_failed_seek">Spulen zur neuen Position fehlgeschlagen</string> + <string name="cast_failed_receiver_player_error">Es wurde ein schwerer Fehler beim Empfangsgerät festgestellt</string> <string name="cast_failed_media_error_skipping">Fehler bei Wiedergabe. Ãœberspringe...</string> </resources> diff --git a/core/src/main/res/values-el/strings.xml b/core/src/main/res/values-el/strings.xml index 56c6d98ec..9768efa59 100644 --- a/core/src/main/res/values-el/strings.xml +++ b/core/src/main/res/values-el/strings.xml @@ -2,15 +2,21 @@ <resources xmlns:tools="http://schemas.android.com/tools"> <!--Activitiy and fragment titles--> <string name="feeds_label">ΡοÎÏ‚</string> + <string name="statistics_label">Στατιστικά</string> + <string name="add_feed_label">Î Ïοσθήκη Podcast</string> <string name="episodes_label">Επεισόδια</string> <string name="all_episodes_short_label">Όλα</string> <string name="favorite_episodes_label">ΑγαπημÎνα</string> <string name="new_label">ÎÎα</string> <string name="settings_label">Ρυθμίσεις</string> + <string name="add_new_feed_label">Î Ïοσθήκη Podcast</string> <string name="downloads_label">Λήψεις</string> <string name="downloads_running_label">ΕκτÎλεση</string> <string name="downloads_completed_label">ΟλοκληÏώθηκε</string> <string name="downloads_log_label">Είσοδος</string> + <string name="subscriptions_label">ΣυνδÏομÎÏ‚</string> + <string name="subscriptions_list_label">Λίστα ΣυνδÏομών</string> + <string name="cancel_download_label">ΑκÏÏωση\nΛήψης</string> <string name="playback_history_label">ΙστοÏικό ΑναπαÏαγωγής</string> <string name="gpodnet_main_label">gpodder.net</string> <string name="gpodnet_auth_label">gpodder.net ΣÏνδεση</string> @@ -58,12 +64,10 @@ <string name="feedurl_label">URL της Ροής</string> <string name="etxtFeedurlHint">www.example.com/feed</string> <string name="txtvfeedurl_label">Î Ïοσθήκη Podcast με τη διεÏθυνση URL</string> - <string name="podcastdirectories_descr">ΜποÏείτε να ψάξετε για νÎα podcast από το όνομα, κατηγοÏία ή δημοτικότητα στον κατάλογο του iTunes.</string> <string name="browse_gpoddernet_label">ΠεÏιήγηση στο gpodder.net</string> <!--Actions on feeds--> <string name="show_info_label">Εμφάνιση πληÏοφοÏιών</string> <string name="remove_feed_label">ΚατάÏγηση Podcast</string> - <string name="feed_delete_confirmation_msg">ΠαÏακαλοÏμε επιβεβαιώστε ότι θÎλετε να διαγÏάφθουν αυτες οι Ï„Ïοφοδοσιες και όλα τα επεισόδια του Ï…Î»Î¹ÎºÎ¿Ï Î±Ï…Ï„Î¿Ï Ï€Î¿Ï… Îχετε κανει λήψη.</string> <string name="hide_episodes_title">ΑπόκÏυψη Επεισοδίων</string> <string name="hide_downloaded_episodes_label">ΕιλημμÎνα</string> <string name="refresh_failed_msg">{fa-exclamation-circle} Η Τελευταία ΑνανÎωση ΑπÎτυχε</string> @@ -135,7 +139,6 @@ <string name="move_to_top_label">Μετακίνηση στην κοÏυφή</string> <string name="move_to_bottom_label">Μετακίνηση Ï€Ïος τα κάτω</string> <string name="sort">Ταξινόμηση</string> - <string name="alpha">Αλφαβητικά</string> <string name="date">ΗμεÏομηνία</string> <string name="duration">ΔάÏκεια</string> <string name="ascending">ΑÏξουσα</string> @@ -234,8 +237,6 @@ <string name="auto_flattr_ater_beginning">Flattr επεισόδιο όταν αÏχίζει η αναπαÏαγωγή</string> <string name="auto_flattr_ater_end">Flattr επεισόδιο όταν ολοκληÏωθεί η αναπαÏαγωγή του</string> <!--Search--> - <string name="search_hint">Αναζήτηση για ΤÏοφοδοσίες ή Επεισόδια</string> - <string name="found_in_shownotes_label">Î’ÏÎθηκε στις σημειώσεις</string> <string name="found_in_chapters_label">Î’ÏÎθηκε σε κεφάλαια</string> <string name="search_status_no_results">Δεν βÏÎθηκαν αποτελÎσματα</string> <string name="search_label">Αναζήτηση</string> @@ -320,7 +321,7 @@ <string name="media_type_audio_label">Ήχος</string> <string name="media_type_video_label">Βίντεο</string> <string name="navigate_upwards_label">Πλοήγηση Ï€Ïος τα πάνω</string> - <string name="status_downloading_label">Το επεισόδιο γίνεται λήφθετε</string> + <string name="status_downloading_label">Λήψη επεισοδίου</string> <string name="in_queue_label">Το επεισόδιο είναι στη σειÏά αναμονής</string> <string name="drag_handle_content_description">ΣÏÏετε για να αλλάξετε τη θÎση Î±Ï…Ï„Î¿Ï Ï„Î¿Ï… στοιχείου</string> <string name="load_next_page_label">ΤοποθÎτηση επόμενης σελίδας</string> @@ -333,7 +334,7 @@ <string name="search_itunes_label">iTunes Αναζήτηση</string> <!--Episodes apply actions--> <string name="all_label">Όλα</string> - <string name="downloaded_label">ΕιλημμÎνα</string> + <string name="downloaded_label">Λήψεις</string> <!--Sort--> <!--Rating dialog--> <!--Audio controls--> diff --git a/core/src/main/res/values-es-rES/strings.xml b/core/src/main/res/values-es-rES/strings.xml index cd6eb01cf..f183c8028 100644 --- a/core/src/main/res/values-es-rES/strings.xml +++ b/core/src/main/res/values-es-rES/strings.xml @@ -1,17 +1,12 @@ <?xml version='1.0' encoding='UTF-8'?> <resources xmlns:tools="http://schemas.android.com/tools"> <!--Activitiy and fragment titles--> - <string name="app_name">AntennaPod</string> <string name="feeds_label">Canales</string> - <string name="add_feed_label">Añadir podcast</string> - <string name="podcasts_label">PODCASTS</string> + <string name="add_feed_label">Añadir Podcast</string> <string name="episodes_label">Episodios</string> - <string name="new_episodes_label">Nuevos episodios</string> - <string name="all_episodes_label">Todos los episodios</string> <string name="all_episodes_short_label">Todos</string> <string name="favorite_episodes_label">Favoritos</string> <string name="new_label">Nuevos</string> - <string name="waiting_list_label">Lista de espera</string> <string name="settings_label">Ajustes</string> <string name="add_new_feed_label">Añadir podcast</string> <string name="downloads_label">Descargas</string> @@ -20,13 +15,10 @@ <string name="gpodnet_main_label">gpodder.net</string> <string name="gpodnet_auth_label">gpodder.net Login</string> <string name="free_space_label">%1$s disponible</string> - <!--New episodes fragment--> - <string name="recently_published_episodes_label">Publicado recientemente</string> - <string name="episode_filter_label">Mostrar solo episodios nuevos</string> <!--Statistics fragment--> <!--Main activity--> - <string name="drawer_open">Abrir menu</string> - <string name="drawer_close">Cerrar menu</string> + <string name="drawer_open">Abrir menú</string> + <string name="drawer_close">Cerrar menú</string> <string name="drawer_feed_order_unplayed_episodes">Ordenar por contador</string> <string name="drawer_feed_order_alphabetical">Ordenar alfabéticamente</string> <string name="drawer_feed_order_last_update">Ordenar por fecha de publicación</string> @@ -67,7 +59,6 @@ <string name="retry_label">Intentar de nuevo</string> <string name="auto_download_label">Incluir en descargas automaticas</string> <string name="auto_download_apply_to_items_title">Aplicar a los previos episodios</string> - <string name="feed_auto_download_global">Global</string> <string name="feed_auto_download_always">Siempre</string> <string name="feed_auto_download_never">Nunca</string> <string name="episode_cleanup_never">Nunca</string> @@ -89,7 +80,7 @@ <string name="show_info_label">Información del programa</string> <string name="remove_feed_label">Eliminar podcast</string> <string name="share_link_label">Compartir el enlace de la web</string> - <string name="feed_delete_confirmation_msg">Confirme que quiere eliminar este canal y TODOS los episodios descargados del mismo.</string> + <string name="hide_queued_episodes_label">En cola</string> <!--actions on feeditems--> <string name="download_label">Descargar</string> <string name="play_label">Reproducir</string> @@ -102,8 +93,6 @@ <string name="remove_from_queue_label">Quitar de la cola</string> <string name="visit_website_label">Visitar el sitio web</string> <string name="support_label">Añadir a Flattr</string> - <string name="enqueue_all_new">Ponerlos todos en cola</string> - <string name="download_all">Descargarlos todos</string> <string name="skip_episode_label">Saltar episodio</string> <!--Download messages and labels--> <string name="download_pending">Descarga pendiente</string> @@ -139,7 +128,6 @@ <string name="playback_error_server_died">El servidor está inactivo</string> <string name="playback_error_unknown">Error desconocido</string> <string name="no_media_playing_label">No hay medios en reproducción</string> - <string name="position_default_label">00:00:00</string> <string name="player_buffering_msg">Almacenando</string> <string name="playbackservice_notification_title">Reproduciendo el podcast</string> <!--Queue operations--> @@ -193,8 +181,6 @@ <string name="pref_episode_cache_title">Caché de episodios</string> <!--Auto-Flattr dialog--> <!--Search--> - <string name="search_hint">Buscar canales o episodios</string> - <string name="found_in_shownotes_label">Encontrado en las notas del programa</string> <string name="found_in_chapters_label">Encontrado en los capÃtulos</string> <string name="search_status_no_results">No se han encontrado resultados</string> <string name="search_label">Buscar</string> @@ -231,13 +217,16 @@ <string name="set_to_default_folder">Elegir carpeta predeterminada</string> <!--Online feed view--> <!--Content descriptions for image buttons--> - <string name="new_episodes_count_label">Numero de nuevos episodios</string> <!--Feed information screen--> <!--Progress information--> <!--AntennaPodSP--> + <!--Episodes apply actions--> <string name="all_label">Todos</string> <string name="none_label">Ningun</string> + <!--Sort--> <!--Rating dialog--> <!--Audio controls--> <!--proxy settings--> + <!--Casting--> + <!--<string name="cast_failed_to_connect">Could not connect to the device</string>--> </resources> diff --git a/core/src/main/res/values-es/strings.xml b/core/src/main/res/values-es/strings.xml index 0eda43051..eb2343f28 100644 --- a/core/src/main/res/values-es/strings.xml +++ b/core/src/main/res/values-es/strings.xml @@ -26,6 +26,8 @@ <!--Statistics fragment--> <string name="total_time_listened_to_podcasts">Tiempo total reproducido:</string> <string name="statistics_details_dialog">Empezados %1$d episodios de %2$d.\n\nReproducidos %3$s de %4$s.</string> + <string name="statistics_mode">Modo de estadÃsticas</string> + <string name="statistics_mode_count_all">Resumir todos los podcasts marcados como reproducidos</string> <!--Main activity--> <string name="drawer_open">Abrir menú</string> <string name="drawer_close">Cerrar menú</string> @@ -33,9 +35,11 @@ <string name="drawer_feed_order_unplayed_episodes">Ordenar por cuenta</string> <string name="drawer_feed_order_alphabetical">Ordenar alfabéticamente</string> <string name="drawer_feed_order_last_update">Ordenar por fecha de publicación</string> + <string name="drawer_feed_order_most_played">Ordenar por número de episodios reproducidos</string> <string name="drawer_feed_counter_new_unplayed">Cantidad de episodios nuevos y no escuchados</string> <string name="drawer_feed_counter_new">Cantidad de episodios nuevos</string> <string name="drawer_feed_counter_unplayed">Cantidad de episodios no escuchados</string> + <string name="drawer_feed_counter_downloaded">Cantidad de episodios descargados</string> <string name="drawer_feed_counter_none">Ninguno</string> <!--Webview actions--> <string name="open_in_browser_label">Abrir en el navegador</string> @@ -50,6 +54,7 @@ <string name="cancel_label">Cancelar</string> <string name="yes">SÃ</string> <string name="no">No</string> + <string name="reset">Resetear</string> <string name="author_label">Autor</string> <string name="language_label">Idioma</string> <string name="url_label">URL</string> @@ -60,6 +65,7 @@ <string name="refresh_label">Actualizar</string> <string name="external_storage_error_msg">No se encuentra un almacenamiento externo. Asegúrese de que su almacenamiento externo esté montado para que la aplicación funcione correctamente.</string> <string name="chapters_label">CapÃtulos</string> + <string name="chapter_duration">Duración: %1$s</string> <string name="shownotes_label">Notas del programa</string> <string name="description_label">Descripción</string> <string name="most_recent_prefix">Episodio más reciente:\u0020</string> @@ -92,7 +98,7 @@ <string name="etxtFeedurlHint">www.ejemplo.com/feed</string> <string name="txtvfeedurl_label">Añadir podcast por URL</string> <string name="podcastdirectories_label">Buscar podcast en directorio</string> - <string name="podcastdirectories_descr">Es posible buscar podcasts nuevos por nombre, categorÃa o popularidad en el directorio de gpodder.net.</string> + <string name="podcastdirectories_descr">Para podcasts nuevos, puedes buscar en iTunes o fyyd, o explorar gpodder.net por nombre, categorÃa o popularidad.</string> <string name="browse_gpoddernet_label">Explorar gpodder.net</string> <!--Actions on feeds--> <string name="mark_all_read_label">Marcar todos como escuchado</string> @@ -100,7 +106,10 @@ <string name="mark_all_read_confirmation_msg">Confirme que quiere marcar todos los episodios como escuchados.</string> <string name="mark_all_read_feed_confirmation_msg">Confirme que quiere marcar todos los episodios de este canal como escuchados.</string> <string name="mark_all_seen_label">Marcar todos como vistos</string> + <string name="mark_all_seen_msg">Marcar todos los episodios como vistos</string> + <string name="mark_all_seen_confirmation_msg">Por favor confirma que quieres marcar todos los episodios como vistos.</string> <string name="show_info_label">Información del programa</string> + <string name="rename_feed_label">Renombrar Podcast</string> <string name="remove_feed_label">Eliminar podcast</string> <string name="share_label">Compartir…</string> <string name="share_link_label">Compartir el enlace de la web</string> @@ -108,7 +117,6 @@ <string name="share_feed_url_label">Compartir URL del canal</string> <string name="share_item_url_label">Compartir URL del archivo del episodio</string> <string name="share_item_url_with_position_label">Compartir URL del episodio con posición</string> - <string name="feed_delete_confirmation_msg">Confirme que quiere eliminar este canal y TODOS los episodios descargados del mismo.</string> <string name="feed_remover_msg">Quitando el canal</string> <string name="load_complete_feed">Actualizar el canal completo</string> <string name="hide_episodes_title">Ocultar episodios</string> @@ -120,6 +128,7 @@ <string name="hide_not_queued_episodes_label">No en cola</string> <string name="hide_downloaded_episodes_label">Descargados</string> <string name="hide_not_downloaded_episodes_label">No descargados</string> + <string name="hide_has_media_label">Tiene multimedia</string> <string name="filtered_label">Filtrados</string> <string name="refresh_failed_msg">{fa-exclamation-circle} Error en última actualización</string> <string name="open_podcast">Abrir Podcast</string> @@ -130,7 +139,9 @@ <string name="stop_label">Detener</string> <string name="stream_label">Transmitir</string> <string name="remove_label">Quitar</string> + <string name="delete_label">Borrar</string> <string name="remove_episode_lable">Quitar episodio</string> + <string name="marked_as_seen_label">Marcar como visto</string> <string name="mark_read_label">Marcar como escuchado</string> <string name="marked_as_read_label">Marcado como escuchado</string> <string name="mark_unread_label">Marcar como no escuchado</string> @@ -216,9 +227,10 @@ <string name="move_to_top_label">Mover al principio</string> <string name="move_to_bottom_label">Mover al final</string> <string name="sort">Ordenar</string> - <string name="alpha">Alfabéticamente</string> <string name="date">Fecha</string> <string name="duration">Duración</string> + <string name="episode_title">TÃtulo del episodio</string> + <string name="feed_title">TÃtulo del feed</string> <string name="ascending">Ascendente</string> <string name="descending">Descendente</string> <string name="clear_queue_confirmation_msg">Confirme que quiere borrar TODOS los episodios de la cola</string> @@ -272,13 +284,13 @@ <string name="pref_pauseOnDisconnect_sum">Pausar la reproducción al desconectar los auriculares o el bluetooth</string> <string name="pref_unpauseOnHeadsetReconnect_sum">Reanudar reproducción cuando se reconecten los auriculares</string> <string name="pref_unpauseOnBluetoothReconnect_sum">Reanudar reproducción cuando se reconecte el bluetooth</string> - <string name="pref_hardwareForwardButtonSkips_title">Saltar episodio con botón</string> <string name="pref_hardwareForwardButtonSkips_sum">Al pulsar el botón fÃsico de avanzar se saltará al siguiente episodio en lugar de sólo avanzar</string> + <string name="pref_hardwarePreviousButtonRestarts_title">Botón anterior reinicia</string> + <string name="pref_hardwarePreviousButtonRestarts_sum">Al pulsar el botón fÃsico de retroceder se comenzará el episodio de nuevo, en lugar de rebobinar</string> <string name="pref_followQueue_sum">Saltar al siguiente elemento de la cola al acabar la reproducción</string> <string name="pref_auto_delete_sum">Borrar episodio cuando finalice la reproducción</string> <string name="pref_auto_delete_title">Eliminar automáticamente</string> <string name="pref_smart_mark_as_played_sum">Marcar episodios como escuchados incluso si todavÃa quedan unos segundos por escuchar</string> - <string name="pref_smart_mark_as_played_title">Marcar como escuchado inteligente</string> <string name="pref_skip_keeps_episodes_sum">Conservar episodios al saltarlos</string> <string name="pref_skip_keeps_episodes_title">Conservar episodios saltados</string> <string name="playback_pref">Reproducción</string> @@ -340,14 +352,18 @@ <string name="pref_gpodnet_logout_toast">Ha cerrado la sesión correctamente.</string> <string name="pref_gpodnet_setlogin_information_title">Cambiar información de acceso</string> <string name="pref_gpodnet_setlogin_information_sum">Modificar datos de inicio de sesión en gpodder.net.</string> - <string name="pref_gpodnet_sync_title">Sincronizar ahora</string> - <string name="pref_gpodnet_sync_sum">Sincronizar suscripciones y estados con gpodder.net</string> + <string name="pref_gpodnet_sync_changes_title">Sincronizar cambios ahora</string> + <string name="pref_gpodnet_sync_changes_sum">Sincronizar cambios del estado de subscripción y episodio con gpodder.net.</string> + <string name="pref_gpodnet_full_sync_title">Sincronización completa ahora</string> + <string name="pref_gpodnet_full_sync_sum">Sincronizar el estado de todas las suscripciones y estados de episodio con gpodder.net.</string> + <string name="pref_gpodnet_sync_sum_last_sync_line">Último intento de sincronización: %1$s (%2$s)</string> <string name="pref_gpodnet_sync_started">Comenzó sincronización</string> + <string name="pref_gpodnet_full_sync_started">Comenzó sincronización completa</string> <string name="pref_gpodnet_login_status"><![CDATA[Autenticado como <i>%1$s</i> con dispositivo <i>%2$s</i>]]></string> + <string name="pref_gpodnet_notifications_title">Mostrar notificaciones de errores de sincronización</string> + <string name="pref_gpodnet_notifications_sum">Este ajuste no afecta a errores de autenticación.</string> <string name="pref_playback_speed_title">Velocidades de reproducción</string> <string name="pref_playback_speed_sum">Personalice las velocidades disponibles para la reproducción de audio a velocidad variable</string> - <string name="pref_fast_forward">Intervalo de avance</string> - <string name="pref_rewind">Intervalo de retroceso</string> <string name="pref_gpodnet_sethostname_title">Definir nombre de equipo</string> <string name="pref_gpodnet_sethostname_use_default_host">Usar nombre de equipo por defecto</string> <string name="pref_expandNotify_title">Expandir Notificación</string> @@ -358,8 +374,6 @@ <string name="pref_compact_notification_buttons_sum">Cambiar los botones de la pantalla de bloqueo. El botón play/pausa siempre está incluido.</string> <string name="pref_compact_notification_buttons_dialog_title">Seleccionar un máximo de %1$d elementos</string> <string name="pref_compact_notification_buttons_dialog_error">Sólo puedes seleccionar un máximo de %1$d elementos.</string> - <string name="pref_show_subscriptions_in_drawer_title">Mostrar Subscripciones</string> - <string name="pref_show_subscriptions_in_drawer_sum">Mostrar la lista de suscripción directamente en el cajón de navegación</string> <string name="pref_lockscreen_background_title">Establecer fondo de pantalla de bloqueo</string> <string name="pref_lockscreen_background_sum">Establecer el fondo de pantalla de bloqueo desde la imagen del episodio. Como efecto lateral, esto también mostrará la imagen en aplicaciones de terceros.</string> <string name="pref_showDownloadReport_title">Mostrar informe de descarga</string> @@ -383,19 +397,24 @@ <string name="pref_known_issues">Problemas conocidos</string> <string name="pref_no_browser_found">No se ha encontrado navegador web.</string> <string name="pref_cast_title">Soporte para Chromecast</string> - <string name="pref_cast_message">Habilitar soporte para reproducción remota en dispositivos Cast (como Chromecast, altavoces o Android TV)</string> + <string name="pref_cast_message_play_flavor">Habilitar soporte para reproducción remota en dispositivos Cast (como Chromecast, altavoces o Android TV)</string> + <string name="pref_cast_message_free_flavor">Chromecast requiere librerÃas propietarias de terceros que están deshabilitadas en esta versión de AntennaPod</string> + <string name="pref_enqueue_downloaded_title">Descargados en cola</string> + <string name="pref_enqueue_downloaded_summary">Agregar episodios descargados a la cola</string> <!--Auto-Flattr dialog--> <string name="auto_flattr_enable">Habilitar Flattr automático</string> <string name="auto_flattr_after_percent">Hacer Flattr del episodio en cuanto se haya reproducido el %d por ciento</string> <string name="auto_flattr_ater_beginning">Hacer Flattr del episodio al comenzar la reproducción</string> <string name="auto_flattr_ater_end">Hacer Flattr del episodio al terminar la reproducción</string> <!--Search--> - <string name="search_hint">Buscar canales o episodios</string> - <string name="found_in_shownotes_label">Encontrado en las notas del programa</string> + <string name="search_hint">Buscar episodios</string> + <string name="found_in_shownotes_label">Encontrado en las notas del show</string> <string name="found_in_chapters_label">Encontrado en los capÃtulos</string> + <string name="found_in_authors_label">Encontrado en los autores</string> <string name="search_status_no_results">No se han encontrado resultados</string> <string name="search_label">Buscar</string> <string name="found_in_title_label">Encontrado en el tÃtulo</string> + <string name="no_results_for_query">No se han encontrado resultados para \"%1$s\"</string> <!--OPML import and export--> <string name="opml_import_txtv_button_lable">Los archivos OPML le permiten migrar sus podcasts de una aplicación a otra.</string> <string name="opml_import_option">Opción %1$d</string> @@ -414,6 +433,7 @@ <string name="choose_file_from_filesystem">Desde el sistema de ficheros local</string> <string name="choose_file_from_external_application">Usar aplicación externa</string> <string name="opml_export_label">Exportar a OPML</string> + <string name="html_export_label">Exportar a HTML</string> <string name="exporting_label">Exportando…</string> <string name="export_error_label">Error en la exportación</string> <string name="opml_export_success_title">Exportación a OPML exitosa</string> @@ -444,6 +464,9 @@ <item quantity="one">1 hora</item> <item quantity="other">%d horas</item> </plurals> + <string name="auto_enable_label">Auto-habilitar</string> + <string name="sleep_timer_enabled_label">Temporizador de sueño habilitado</string> + <string name="sleep_timer_disabled_label">Temporizador de sueño deshabilitado</string> <!--gpodder.net--> <string name="gpodnet_taglist_header">CATEGORÃAS</string> <string name="gpodnet_toplist_header">MEJORES PODCASTS</string> @@ -473,6 +496,8 @@ <string name="gpodnetsync_auth_error_descr">Usuario o contraseña incorrectos</string> <string name="gpodnetsync_error_title">Error de sincronización de gpodder.net</string> <string name="gpodnetsync_error_descr">Ocurrió un error de sincronización:\u0020</string> + <string name="gpodnetsync_pref_report_successful">Exitoso</string> + <string name="gpodnetsync_pref_report_failed">Fallido</string> <!--Directory chooser--> <string name="selected_folder_label">Carpeta seleccionada</string> <string name="create_folder_label">Crear carpeta</string> @@ -525,6 +550,7 @@ <string name="sp_apps_importing_feeds_msg">Importando subscripciones de aplicaciones de uso especÃfico...</string> <string name="search_itunes_label">Buscar en iTunes</string> <string name="filter">Filtro</string> + <string name="search_fyyd_label">Buscar fyyd</string> <!--Episodes apply actions--> <string name="all_label">Todo</string> <string name="selected_all_label">Seleccionados todos los episodios</string> @@ -542,6 +568,8 @@ <string name="selected_queued_label">Seleccionados episodios en cola</string> <string name="not_queued_label">No en cola</string> <string name="selected_not_queued_label">Seleccionados episodios no en cola</string> + <string name="has_media">Tiene multimedia</string> + <string name="selected_has_media_label">Seleccionar episodios con multimedia</string> <!--Sort--> <string name="sort_title_a_z">TÃtulo (A \u2192 Z)</string> <string name="sort_title_z_a">TÃtulo (Z \u2192 A)</string> diff --git a/core/src/main/res/values-et/strings.xml b/core/src/main/res/values-et/strings.xml new file mode 100644 index 000000000..629fd4654 --- /dev/null +++ b/core/src/main/res/values-et/strings.xml @@ -0,0 +1,498 @@ +<?xml version='1.0' encoding='UTF-8'?> +<resources xmlns:tools="http://schemas.android.com/tools"> + <!--Activitiy and fragment titles--> + <string name="feeds_label">Uudisvood</string> + <string name="statistics_label">Statistika</string> + <string name="add_feed_label">Lisa taskuhääling</string> + <string name="episodes_label">Saated</string> + <string name="all_episodes_short_label">Kõik</string> + <string name="favorite_episodes_label">Lemmikud</string> + <string name="new_label">Uus</string> + <string name="settings_label">Seaded</string> + <string name="add_new_feed_label">Lisa taskuhääling</string> + <string name="downloads_label">Allalaadimised</string> + <string name="downloads_running_label">Käimas</string> + <string name="downloads_completed_label">Lõpetatud</string> + <string name="downloads_log_label">Logi</string> + <string name="subscriptions_label">Tellimused</string> + <string name="subscriptions_list_label">Tellimuste nimekiri</string> + <string name="cancel_download_label">Tühista\nLaadi alla</string> + <string name="playback_history_label">Esitamise ajalugu</string> + <string name="gpodnet_main_label">gpodder.net</string> + <string name="gpodnet_auth_label">gpodder.net kasutajanimi</string> + <string name="free_space_label">%1$s vaba</string> + <string name="episode_cache_full_title">Saadete vahemälu on täis</string> + <!--Statistics fragment--> + <string name="total_time_listened_to_podcasts">Kuulatud taskuhäälingute kogupikkus:</string> + <!--Main activity--> + <string name="drawer_open">Ava menüü</string> + <string name="drawer_close">Sulge menüü</string> + <string name="drawer_preferences">Sahtli eelistused</string> + <string name="drawer_feed_order_unplayed_episodes">Sorteeri arvu järgi</string> + <string name="drawer_feed_order_alphabetical">Sorteeri tähestiku järgi</string> + <string name="drawer_feed_order_last_update">Sorteeri avaldamise kuupäeva järgi</string> + <string name="drawer_feed_counter_new_unplayed">Uute ja kuulamata osade arv</string> + <string name="drawer_feed_counter_new">Uute saadete arv</string> + <string name="drawer_feed_counter_unplayed">Kuulamata saadete arv</string> + <string name="drawer_feed_counter_none">Pole</string> + <!--Webview actions--> + <string name="open_in_browser_label">Ava veebisirvijas</string> + <string name="copy_url_label">Kopeeri URL</string> + <string name="share_url_label">Jaga URL-i</string> + <string name="copied_url_msg">URL on kopeeritud lõikelauale</string> + <string name="go_to_position_label">Mine sellele asukohale</string> + <!--Playback history--> + <string name="clear_history_label">Tühjenda ajalugu</string> + <!--Other--> + <string name="confirm_label">Kinnita</string> + <string name="cancel_label">Loobu</string> + <string name="yes">Jah</string> + <string name="no">Ei</string> + <string name="reset">Nulli</string> + <string name="author_label">Autor</string> + <string name="language_label">Keel</string> + <string name="url_label">URL</string> + <string name="podcast_settings_label">Seaded</string> + <string name="cover_label">Pilt</string> + <string name="error_label">Viga</string> + <string name="error_msg_prefix">Tekkis viga:</string> + <string name="refresh_label">Värskenda</string> + <string name="chapters_label">Peatükid</string> + <string name="shownotes_label">Saate märkmed</string> + <string name="description_label">Kirjeldus</string> + <string name="most_recent_prefix">Kõige värskem saade:\u0020</string> + <string name="episodes_suffix">\u0020saadet</string> + <string name="length_prefix">Pikkus:\u0020</string> + <string name="size_prefix">Suurus:\u0020</string> + <string name="processing_label">Töötlemine</string> + <string name="loading_label">Laadimine...</string> + <string name="save_username_password_label">Salvesta kasutajanimi ja parool</string> + <string name="close_label">Sulge</string> + <string name="retry_label">Proovi uuesti</string> + <string name="auto_download_label">Kaasa heli allalaadimises</string> + <string name="auto_download_apply_to_items_title">Rakenda eelmistele saadetele</string> + <string name="auto_delete_label">Saadeta automaatne kustutamine</string> + <string name="parallel_downloads_suffix">\u0020samaaegset allalaadimist</string> + <string name="feed_auto_download_global">Ãœldine vaikeväärtus</string> + <string name="feed_auto_download_always">Alati</string> + <string name="feed_auto_download_never">Mitte kunagi</string> + <string name="send_label">Saada...</string> + <string name="episode_cleanup_never">Mitte kunagi</string> + <string name="episode_cleanup_queue_removal">Kui pole järjekorras</string> + <string name="episode_cleanup_after_listening">Pärast lõpetamist</string> + <plurals name="episode_cleanup_days_after_listening"> + <item quantity="one">1 päev pärast lõpetamist</item> + <item quantity="other">%d päeva pärast lõpetamist</item> + </plurals> + <!--'Add Feed' Activity labels--> + <string name="feedurl_label">Uudisvoo URL</string> + <string name="etxtFeedurlHint">www.example.com/feed</string> + <string name="txtvfeedurl_label">Lisa taskuhääling URL-iga</string> + <string name="podcastdirectories_label">Leia taskuhääling kaustast</string> + <string name="browse_gpoddernet_label">Sirvi gpodder.net-i</string> + <!--Actions on feeds--> + <string name="mark_all_read_label">Märgi kuulatuks</string> + <string name="mark_all_read_msg">Märgi kõik saated esitatuks</string> + <string name="mark_all_seen_label">Märgi kõik nähtuks</string> + <string name="mark_all_seen_msg">Märgi kõik saated nähtuks</string> + <string name="show_info_label">Näita infot</string> + <string name="rename_feed_label">Nimeta taskuhääling ümber</string> + <string name="remove_feed_label">Eemalda taskuhääling</string> + <string name="share_label">Jaga...</string> + <string name="share_link_label">Jaga linki</string> + <string name="share_link_with_position_label">Jaga linki koos asukohaga</string> + <string name="share_feed_url_label">Jaga uudisvoo URL-i</string> + <string name="feed_remover_msg">Uudisvoo eemaldamine</string> + <string name="load_complete_feed">Värskenda kogu uudisvoogu</string> + <string name="hide_episodes_title">Peida saated</string> + <string name="episode_actions">Rakenda tegevused</string> + <string name="hide_unplayed_episodes_label">Esitamata</string> + <string name="hide_paused_episodes_label">Peatatud</string> + <string name="hide_played_episodes_label">Esitatud</string> + <string name="hide_queued_episodes_label">Järjekorras</string> + <string name="hide_not_queued_episodes_label">Pole järjekorras</string> + <string name="hide_downloaded_episodes_label">Alla laaditud</string> + <string name="hide_not_downloaded_episodes_label">Pole alla laaditud</string> + <string name="hide_has_media_label">On meediafaile</string> + <string name="filtered_label">Filtreeritud</string> + <string name="refresh_failed_msg">{fa-exclamation-circle} Viimane värskendamine ebaõnnestus</string> + <string name="open_podcast">Ava taskuhääling</string> + <!--actions on feeditems--> + <string name="download_label">Laadi alla</string> + <string name="play_label">Esita</string> + <string name="pause_label">Peata</string> + <string name="stop_label">Stopp</string> + <string name="stream_label">Voogedastusena</string> + <string name="remove_label">Eemalda</string> + <string name="delete_label">Kustuta</string> + <string name="remove_episode_lable">Eemalda saade</string> + <string name="marked_as_seen_label">Märgitud nähtuks</string> + <string name="mark_read_label">Märgi esitatuks</string> + <string name="marked_as_read_label">Märgitud kuulatuks</string> + <string name="mark_unread_label">Märgitud kui kuulamata</string> + <string name="add_to_queue_label">Lisa järjekorda</string> + <string name="added_to_queue_label">Lisatud järjekorda</string> + <string name="remove_from_queue_label">Eemalda järjekorrast</string> + <string name="add_to_favorite_label">Lisa lemmikuks</string> + <string name="added_to_favorites">Lisatud lemmikuks</string> + <string name="remove_from_favorite_label">Eemalda lemmikutest</string> + <string name="removed_from_favorites">Eemaldatud lemmikutest</string> + <string name="visit_website_label">Külasta veebilehte</string> + <string name="skip_episode_label">Jäda saade vahele</string> + <string name="activate_auto_download">Lülita automaatne allalaadimine sisse</string> + <string name="deactivate_auto_download">Lülita automaatne allalaadimine välja</string> + <string name="reset_position">Nulli esitamise asukoht</string> + <string name="removed_item">Kirje on eemaldatud</string> + <!--Download messages and labels--> + <string name="download_successful">korras</string> + <string name="download_failed">ebaõnnestus</string> + <string name="download_pending">Ootel allalaadimine</string> + <string name="download_running">Allalaadimine on käimas</string> + <string name="download_error_device_not_found">Salvestuskohta ei leitud</string> + <string name="download_error_insufficient_space">Pole piisavalt ruumi</string> + <string name="download_error_file_error">Faili viga</string> + <string name="download_error_http_data_error">HTTP andmete viga</string> + <string name="download_error_error_unknown">Tundmatu tõrge</string> + <string name="download_error_parser_exception">Parsimise järjekord</string> + <string name="download_error_unsupported_type">Toetamata uudisvoo tüüp</string> + <string name="download_error_connection_error">Ãœhenduse viga</string> + <string name="download_error_unknown_host">Tundmatu host</string> + <string name="download_error_unauthorized">Autentimise viga</string> + <string name="download_error_file_type_type">Failitüübi viga</string> + <string name="download_error_forbidden">Keelatud</string> + <string name="cancel_all_downloads_label">Tühista kõik allalaadimised</string> + <string name="download_canceled_msg">Allalaadimine on tühistatud</string> + <string name="download_report_title">Allalaadimised lõpetati veaga (vigadega)</string> + <string name="download_report_content_title">Allalaadimise aruanne</string> + <string name="download_error_malformed_url">Vigane URL-i vorming</string> + <string name="download_error_io_error">IO viga</string> + <string name="download_error_request_error">Päringu viga</string> + <string name="download_error_db_access">Andmebaasile ligipääsu viga</string> + <plurals name="downloads_left"> + <item quantity="one">%d allalaadimine järgi</item> + <item quantity="other">%d allalaadimisi järgi</item> + </plurals> + <string name="downloads_processing">Allalaadimiste töötlemine</string> + <string name="download_notification_title">Taskuhäälingu andmete allalaadimine</string> + <string name="download_log_title_unknown">Tundmatu pealkiri</string> + <string name="download_type_feed">Uudisvoog</string> + <string name="download_type_media">Meediafail</string> + <string name="download_type_image">Pilt</string> + <string name="authentication_notification_title">Autentimine on nõutud</string> + <string name="confirm_mobile_download_dialog_title">Kinnita üle mobiili allalaadimine</string> + <string name="confirm_mobile_download_dialog_only_add_to_queue">Järjekorda</string> + <string name="confirm_mobile_download_dialog_enable_temporarily">Luba ajutiselt</string> + <!--Mediaplayer messages--> + <string name="player_error_msg">Viga!</string> + <string name="player_stopped_msg">Mingit faili ei esitata</string> + <string name="player_preparing_msg">Ettevalmistamine</string> + <string name="player_ready_msg">Valmis</string> + <string name="player_seeking_msg">Otsimine</string> + <string name="playback_error_server_died">Server suri ära</string> + <string name="playback_error_unknown">Tundmatu tõrge</string> + <string name="no_media_playing_label">Mingit faili ei esitata</string> + <string name="player_buffering_msg">Puhverdamine</string> + <string name="playbackservice_notification_title">Taskuhäälingu esitamine</string> + <string name="unknown_media_key">AntennaPod - Tundmatu meedia võti: %1$d</string> + <!--Queue operations--> + <string name="lock_queue">Lukusta järjekord</string> + <string name="unlock_queue">Eemalda järjekorra lukustus</string> + <string name="queue_locked">Järjekord on lukustatud</string> + <string name="queue_unlocked">Järjekorra lukustus on eemaldatud</string> + <string name="clear_queue_label">Tühjenda järjekord</string> + <string name="undo">Tühista</string> + <string name="removed_from_queue">Kirje on eemaldatud</string> + <string name="move_to_top_label">Liiguta üles</string> + <string name="move_to_bottom_label">Liiguta alla</string> + <string name="sort">Sorteeri</string> + <string name="date">Kuupäeva järgi</string> + <string name="duration">Kestuse järgi</string> + <string name="episode_title">Saate pealkiri</string> + <string name="feed_title">Uudisvoo pealkiri</string> + <string name="ascending">Kasvavalt</string> + <string name="descending">Kahanevalt</string> + <!--Flattr--> + <string name="authenticate_label">Autendi</string> + <string name="return_home_label">Tagasi koju</string> + <string name="authenticate_now_label">Autendi</string> + <string name="action_forbidden_title">Tegevus on keelatud</string> + <string name="access_revoked_title">Ligipääs on eemaldatud</string> + <!--Flattr--> + <!--Variable Speed--> + <string name="download_plugin_label">Laadi plugin alla</string> + <string name="no_playback_plugin_title">Pluginat pole paigaldatud</string> + <string name="set_playback_speed_label">Esitamise kiirused</string> + <string name="enable_sonic">Luba Sonicu kasutamine</string> + <!--Empty list labels--> + <string name="no_items_label">Selles nimekirjas pole midagi.</string> + <string name="no_feeds_label">Sa pole veel ühtegi uusidvoogi tellinud.</string> + <string name="no_chapters_label">Saatel pole peatükke.</string> + <string name="no_shownotes_label">Sellel saatel pole mingeid märkusi.</string> + <!--Preferences--> + <string name="storage_pref">Salvestusruum</string> + <string name="project_pref">Projekt</string> + <string name="other_pref">Muud</string> + <string name="about_pref">Info</string> + <string name="queue_label">Järjekord</string> + <string name="services_label">Teenused</string> + <string name="flattr_label">Flattr</string> + <string name="pref_episode_cleanup_title">Saadete kustutamien</string> + <string name="pref_followQueue_sum">Kui saade lõpeb, siis esita kohe järgmine järjekorras olev saade.</string> + <string name="pref_auto_delete_sum">Kustuta saated, kui need on kuulatud</string> + <string name="pref_auto_delete_title">Automaatne kustutamine</string> + <string name="pref_skip_keeps_episodes_sum">Hoia saated alles, kui need jäetakse vahele</string> + <string name="pref_skip_keeps_episodes_title">Hoia vahelejäetud osad alles</string> + <string name="playback_pref">Esitamine</string> + <string name="network_pref">Võrk</string> + <string name="pref_autoUpdateIntervallOrTime_title">Uuendamise intervall või kellaaeg</string> + <string name="pref_autoUpdateIntervallOrTime_Disable">Lülita välja</string> + <string name="pref_autoUpdateIntervallOrTime_Interval">Määra intervall</string> + <string name="pref_autoUpdateIntervallOrTime_TimeOfDay">Määra aeg päevades</string> + <string name="pref_autoUpdateIntervallOrTime_every">iga %1$s</string> + <string name="pref_autoUpdateIntervallOrTime_at">kell %1$s</string> + <string name="pref_downloadMediaOnWifiOnly_sum">Laadi meediafaile alla ainult üle Wifi</string> + <string name="pref_followQueue_title">Pidev esitamine</string> + <string name="pref_downloadMediaOnWifiOnly_title">Meedia allalaadimine üle Wifi</string> + <string name="pref_pauseOnHeadsetDisconnect_title">Kõrvaklappide eemaldmine</string> + <string name="pref_unpauseOnHeadsetReconnect_title">Kõrvaklappide uuesti ühendamine</string> + <string name="pref_unpauseOnBluetoothReconnect_title">Bloetoothi uuesti ühendamin</string> + <string name="pref_mobileUpdate_title">Uuendamine üle andmeside</string> + <string name="pref_mobileUpdate_sum">Luba uuendamised kasutades mobiilset andmesidet</string> + <string name="refreshing_label">Värskendamine</string> + <string name="flattr_settings_label">Flattri seaded</string> + <string name="pref_revokeAccess_title">Eemalda ligipääs</string> + <string name="user_interface_label">Kasutajalidies</string> + <string name="pref_set_theme_title">Vali teema</string> + <string name="pref_nav_drawer_title">Kohanda peamenüüd</string> + <string name="pref_nav_drawer_sum">Kohanda peamenüü välimust</string> + <string name="pref_nav_drawer_items_title">Määra peamenüü osad</string> + <string name="pref_nav_drawer_items_sum">Määra, mis osad on peamenüüs nähtaval.</string> + <string name="pref_nav_drawer_feed_order_title">Määra tellimuste järjekord</string> + <string name="pref_nav_drawer_feed_order_sum">Muuda oma tellimuste järjekorda</string> + <string name="pref_nav_drawer_feed_counter_title">Määra tellimuste loendur</string> + <string name="pref_automatic_download_title">Automaatne allalaadimine</string> + <string name="pref_autodl_wifi_filter_title">Luba Wifi filter</string> + <string name="pref_autodl_wifi_filter_sum">Luba automaatne allalaadimine ainult valitud Wifi võrkudes.</string> + <string name="pref_automatic_download_on_battery_title">Allalaadmiine kui seade ei laadi</string> + <string name="pref_automatic_download_on_battery_sum">Luba automaatne allalaadimine ka siis, kui seade pole laadimas</string> + <string name="pref_parallel_downloads_title">Samaaegsed allalaadimised</string> + <string name="pref_episode_cache_title">Saadete vahemälu</string> + <string name="pref_theme_title_light">Hele</string> + <string name="pref_theme_title_dark">Tume</string> + <string name="pref_episode_cache_unlimited">Piiramatult</string> + <string name="pref_update_interval_hours_plural">tundi</string> + <string name="pref_update_interval_hours_singular">tund</string> + <string name="pref_update_interval_hours_manual">Käsitsi</string> + <string name="pref_gpodnet_authenticate_title">Logi sisse</string> + <string name="pref_gpodnet_logout_title">Logi välja</string> + <string name="pref_gpodnet_logout_toast">Väljalogimine oli edukas</string> + <string name="pref_gpodnet_setlogin_information_title">Muuda kasutajakonto infot</string> + <string name="pref_gpodnet_sync_changes_title">Sünkrooni muudatused kohe</string> + <string name="pref_gpodnet_full_sync_title">Täielik sünkroonimine kohe</string> + <string name="pref_gpodnet_sync_started">Sünkroonimine on käivitatud</string> + <string name="pref_gpodnet_login_status"><![CDATA[Sisseloginud kui <i>%1$s</i> seadmega <i>%2$s</i>]]></string> + <string name="pref_playback_speed_title">Esitamise kiirused</string> + <string name="pref_gpodnet_sethostname_title">Määra hostinimi</string> + <string name="pref_gpodnet_sethostname_use_default_host">Kasuta vaikimisi hosti</string> + <string name="pref_expandNotify_title">Teavituste laiendamine</string> + <string name="pref_expandNotify_sum">Näita alati teavitustes pleieri nuppe.</string> + <string name="pref_persistNotify_title">Püsivad taasesitamise nupud</string> + <string name="pref_compact_notification_buttons_title">Määra lukustutekraani nupud</string> + <string name="pref_lockscreen_background_title">Määra lukustusekraani taustapilt</string> + <string name="pref_showDownloadReport_title">Näita allalaadimise aruannet</string> + <string name="pref_queueAddToFront_title">Pane järjekorra algusesse</string> + <string name="pref_smart_mark_as_played_disabled">Välja lülitatud</string> + <string name="pref_image_cache_size_title">Pildi vahemälu suurus</string> + <string name="pref_image_cache_size_sum">Piltide jaoks kasutatava vahemälu suurus</string> + <string name="crash_report_title">Veateated</string> + <string name="crash_report_sum">Saada veateated e-postiga</string> + <string name="send_email">Saata e-post</string> + <string name="experimental_pref">Katsetamisel</string> + <string name="pref_current_value">Praegune väärtus: %1$s</string> + <string name="pref_proxy_title">Vaheserver</string> + <string name="pref_proxy_sum">Määra võrgu vaheserver</string> + <string name="pref_faq">KKK</string> + <string name="pref_known_issues">Teadaolevad probleemid</string> + <string name="pref_no_browser_found">Veebilehitsejat ei leitud.</string> + <string name="pref_cast_title">Chromecasti tugi</string> + <!--Auto-Flattr dialog--> + <!--Search--> + <string name="search_hint">Otsi saateid</string> + <string name="found_in_shownotes_label">Leitud saate märkmetest</string> + <string name="found_in_chapters_label">Leitud peatükkidest</string> + <string name="search_status_no_results">ei leitud midagi</string> + <string name="search_label">Otsi</string> + <string name="found_in_title_label">Leitud pealkirjast</string> + <!--OPML import and export--> + <string name="opml_import_txtv_button_lable">OPML failid võimaldavad sul liigutada oma taskuhäälinguid ühest rakendusest teise.</string> + <string name="opml_import_option">Valik %1$d</string> + <string name="opml_import_explanation_1">Vali failisüsteemist konktreetne kaust.</string> + <string name="opml_import_explanation_2">Kasuta OPML-faili avamiseks väliseid rakendusi nagu Dropbox, Google Drive või sinu lemmik failihaldur.</string> + <string name="start_import_label">Alusta importimist</string> + <string name="opml_import_label">OPML import</string> + <string name="opml_directory_error">VIGA!</string> + <string name="reading_opml_label">OPML faili lugemine</string> + <string name="opml_reader_error">OPML dokumendi lugemisel tekkis tõrge:</string> + <string name="opml_import_error_no_file">Ãœhtegi faili pole avatud!</string> + <string name="select_all_label">Vali kõik</string> + <string name="deselect_all_label">Ära vali midagi</string> + <string name="select_options_label">Vali...</string> + <string name="choose_file_from_filesystem">Kohalikust failisüsteemist</string> + <string name="choose_file_from_external_application">Kasuta välist rakendust</string> + <string name="opml_export_label">OPML eksport</string> + <string name="html_export_label">HTML eksport</string> + <string name="exporting_label">Eksportimine...</string> + <string name="export_error_label">Viga eksportimisel</string> + <string name="opml_export_success_title">OPML eksport oli edukas.</string> + <string name="opml_export_success_sum">.opml fail kirjutati kausta:\u0020</string> + <!--Sleep timer--> + <string name="set_sleeptimer_label">Määra unetaimer</string> + <string name="disable_sleeptimer_label">Keela unetaimer</string> + <string name="enter_time_here_label">Sisesta aeg</string> + <string name="sleep_timer_label">Unetaimer</string> + <string name="time_left_label">Aega järgi:\u0020</string> + <string name="time_dialog_invalid_input">Vigane sisend, aeg peab olema arvuna</string> + <string name="shake_to_reset_label">Raputa taimeri nullimiseks</string> + <string name="timer_vibration_label">Vibreeri</string> + <string name="time_seconds">sekundit</string> + <string name="time_minutes">inutit</string> + <string name="time_hours">tundi</string> + <plurals name="time_seconds_quantified"> + <item quantity="one">1 sekund</item> + <item quantity="other">%d sekundit</item> + </plurals> + <plurals name="time_minutes_quantified"> + <item quantity="one">1 minut</item> + <item quantity="other">%d minutit</item> + </plurals> + <plurals name="time_hours_quantified"> + <item quantity="one">1 tund</item> + <item quantity="other">%d tundi</item> + </plurals> + <!--gpodder.net--> + <string name="gpodnet_taglist_header">KATEGOORIAD</string> + <string name="gpodnet_toplist_header">POPIMAD TASKUHÄÄLINGUD</string> + <string name="gpodnet_suggestions_header">SOOVITUSED</string> + <string name="gpodnet_search_hint">Otsi gpodder.net-ist</string> + <string name="gpodnetauth_login_title">Logi sisse</string> + <string name="gpodnetauth_login_butLabel">Logi välja</string> + <string name="gpodnetauth_login_register">Kui sul pole veel kontot, siis sa saad selle endale registreerida siin:\nhttps://gpodder.net/register/</string> + <string name="username_label">Kasutajanimi</string> + <string name="password_label">Parool</string> + <string name="gpodnetauth_device_title">Seadme valimine</string> + <string name="gpodnetauth_device_deviceID">Seadme ID:\u0020</string> + <string name="gpodnetauth_device_caption">Pealkiri</string> + <string name="gpodnetauth_device_butCreateNewDevice">Loo uus seade</string> + <string name="gpodnetauth_device_chooseExistingDevice">Vali olemasolev seade:</string> + <string name="gpodnetauth_device_errorEmpty">Seadme ID ei tohi olla tühi</string> + <string name="gpodnetauth_device_errorAlreadyUsed">Seadme ID on juba kasutuses</string> + <string name="gpodnetauth_device_butChoose">Vali</string> + <string name="gpodnetauth_finish_title">Sisse logitud!</string> + <string name="gpodnetauth_finish_butsyncnow">Alusta kohe sünkroonimist</string> + <string name="gpodnetauth_finish_butgomainscreen">Mine peaekraanile</string> + <string name="gpodnetsync_auth_error_title">gpodder.net autentimise viga</string> + <string name="gpodnetsync_auth_error_descr">Vale kasutajanimi või parool</string> + <string name="gpodnetsync_error_title">gpodder.net sünkroonimise viga</string> + <string name="gpodnetsync_error_descr">Sünkroonimise ajal tekkis viga:\u0020</string> + <string name="gpodnetsync_pref_report_successful">Korras</string> + <string name="gpodnetsync_pref_report_failed">Ebaõnnestus</string> + <!--Directory chooser--> + <string name="selected_folder_label">Vali kaust:</string> + <string name="create_folder_label">Loo kaust</string> + <string name="choose_data_directory">Vali andmete kaust</string> + <string name="create_folder_msg">Loo uus kaust nimega \"%1$s\"?</string> + <string name="create_folder_success">Uus kaust on loodud</string> + <string name="create_folder_error_no_write_access">Sellesse kausta ei saa kirjutada</string> + <string name="create_folder_error_already_exists">Kaust on juba olemas</string> + <string name="create_folder_error">Kausta loomine ebaõnnestus</string> + <string name="folder_does_not_exist_error">\"%1$s\" pole olemas</string> + <string name="folder_not_readable_error">\"%1$s\" pole loetav</string> + <string name="folder_not_writable_error">\"%1$s\" pole kirjutatav</string> + <string name="folder_not_empty_dialog_title">Kaust pole tühi</string> + <string name="set_to_default_folder">Vali vaikimisi kaust</string> + <string name="pref_pausePlaybackForFocusLoss_title">Peata kõne korral</string> + <string name="pref_resumeAfterCall_sum">Taasta esitamine pärast telefonikõne lõppu</string> + <string name="pref_resumeAfterCall_title">Taasta pärast kõne lõppu</string> + <string name="pref_restart_required">Selle muudatuse mõjumiseks tuleb AntennaPod taaskäivitada.</string> + <!--Online feed view--> + <string name="subscribe_label">Telli</string> + <string name="subscribed_label">Tellitud</string> + <string name="downloading_label">Allalaadimine...</string> + <!--Content descriptions for image buttons--> + <string name="rewind_label">Keri tagasi</string> + <string name="fast_forward_label">Keri edasi</string> + <string name="media_type_audio_label">Heli</string> + <string name="media_type_video_label">Video</string> + <string name="navigate_upwards_label">Liigu ülespoole</string> + <string name="status_downloading_label">Saadet laaditakse alla</string> + <string name="in_queue_label">Saade on järjekorras</string> + <string name="load_next_page_label">Laadi järgmine lehekülg</string> + <!--Feed information screen--> + <string name="authentication_label">Autentimine</string> + <string name="auto_download_settings_label">Automaatse allalaadimise seaded</string> + <string name="episode_filters_label">Saadete filter</string> + <string name="episode_filters_include">Kaasa</string> + <string name="episode_filters_exclude">Jäta välja</string> + <string name="episode_filters_hint">Ãœksikud sõnad \n\"Mitu sõna\"</string> + <string name="keep_updated">Hoia uuendatuna</string> + <!--Progress information--> + <string name="progress_upgrading_database">Andmebaasi uuendamine</string> + <!--AntennaPodSP--> + <string name="search_itunes_label">Otsi iTunest</string> + <string name="filter">Filter</string> + <!--Episodes apply actions--> + <string name="all_label">Kõik</string> + <string name="selected_all_label">Vali kõik saated</string> + <string name="none_label">Pole</string> + <string name="deselected_all_label">Tühista kõigi saadete valik</string> + <string name="played_label">Esitatud</string> + <string name="selected_played_label">Valitud kuulatud saated</string> + <string name="unplayed_label">Esitamata</string> + <string name="selected_unplayed_label">Valitud kuulamata saated</string> + <string name="downloaded_label">Alla laaditud</string> + <string name="selected_downloaded_label">Valitud allalaaditud saated</string> + <string name="not_downloaded_label">Pole alla laaditud</string> + <string name="selected_not_downloaded_label">Valitud allalaadimata saated</string> + <string name="queued_label">Järjekorras</string> + <string name="selected_queued_label">Valitud järjekorras olevad saated</string> + <string name="not_queued_label">Pole järjekorras</string> + <string name="selected_not_queued_label">Valitud järjekorras mitte olevad saated</string> + <string name="has_media">On meediafaile</string> + <string name="selected_has_media_label">Valitud saated meediafailidega</string> + <!--Sort--> + <string name="sort_title_a_z">Pealkiri (A \u2192 Z)</string> + <string name="sort_title_z_a">Pealkiri (Z \u2192 A)</string> + <string name="sort_date_new_old">Kuupäev (uus \u2192 vana)</string> + <string name="sort_date_old_new">Kuupäev (vana \u2192 uus)</string> + <string name="sort_duration_short_long">Kestus (lühike \u2192 pikk)</string> + <string name="sort_duration_long_short">Kestus (pikk \u2192 lühike)</string> + <!--Rating dialog--> + <string name="rating_title">Kas sulle meeldib AntennaPod?</string> + <string name="rating_message">Me hindame, kui sa saaksid võtta aega, et hinnata AntennaPodi.</string> + <string name="rating_never_label">Jäta mind rahule</string> + <string name="rating_later_label">Tuleta hiljem meelde</string> + <string name="rating_now_label">Jah, otseloomulikult!</string> + <!--Audio controls--> + <string name="audio_controls">Audiopleieri nupud</string> + <string name="playback_speed">Esitamise kiirus</string> + <string name="volume">Helitugevus</string> + <string name="left_short">L</string> + <string name="right_short">R</string> + <string name="audio_effects">Heliefektid</string> + <string name="stereo_to_mono">Downmix: Stereo monoks</string> + <string name="sonic_only">Ainult Sonic</string> + <!--proxy settings--> + <string name="proxy_type_label">Tüüp</string> + <string name="host_label">Hostinimi</string> + <string name="port_label">Port</string> + <string name="optional_hint">(valikuline)</string> + <string name="proxy_test_label">Proovi</string> + <string name="proxy_checking">Kontrollimine...</string> + <string name="proxy_test_successful">Kontroll oli edukas</string> + <string name="proxy_test_failed">Kontroll ebaõnnestus</string> + <string name="proxy_host_empty_error">Hostinimi ei saa olla tühi</string> + <string name="proxy_port_invalid_error">Port pole korrektne</string> + <!--Casting--> + <string name="cast_media_route_menu_title">Esita...</string> + <!--<string name="cast_failed_to_connect">Could not connect to the device</string>--> +</resources> diff --git a/core/src/main/res/values-fa/strings.xml b/core/src/main/res/values-fa/strings.xml new file mode 100644 index 000000000..28dfeb6e8 --- /dev/null +++ b/core/src/main/res/values-fa/strings.xml @@ -0,0 +1,38 @@ +<?xml version='1.0' encoding='UTF-8'?> +<resources xmlns:tools="http://schemas.android.com/tools"> + <!--Activitiy and fragment titles--> + <!--Statistics fragment--> + <!--Main activity--> + <!--Webview actions--> + <!--Playback history--> + <!--Other--> + <!--'Add Feed' Activity labels--> + <!--Actions on feeds--> + <!--actions on feeditems--> + <!--Download messages and labels--> + <!--Mediaplayer messages--> + <!--Queue operations--> + <!--Flattr--> + <!--Flattr--> + <!--Variable Speed--> + <!--Empty list labels--> + <!--Preferences--> + <!--Auto-Flattr dialog--> + <!--Search--> + <!--OPML import and export--> + <!--Sleep timer--> + <!--gpodder.net--> + <!--Directory chooser--> + <!--Online feed view--> + <!--Content descriptions for image buttons--> + <!--Feed information screen--> + <!--Progress information--> + <!--AntennaPodSP--> + <!--Episodes apply actions--> + <!--Sort--> + <!--Rating dialog--> + <!--Audio controls--> + <!--proxy settings--> + <!--Casting--> + <!--<string name="cast_failed_to_connect">Could not connect to the device</string>--> +</resources> diff --git a/core/src/main/res/values-fr/strings.xml b/core/src/main/res/values-fr/strings.xml index 623476f8f..4b17fed06 100644 --- a/core/src/main/res/values-fr/strings.xml +++ b/core/src/main/res/values-fr/strings.xml @@ -26,6 +26,10 @@ <!--Statistics fragment--> <string name="total_time_listened_to_podcasts">Temps d\'écoute total</string> <string name="statistics_details_dialog">%1$d épisodes sur %2$d commencés.\n\nLu %3$s sur %4$s.</string> + <string name="statistics_mode">Type de statistiques</string> + <string name="statistics_mode_normal">Calculer la durée réellement écoutée. Les épisodes écoutés deux fois comptent double alors que ceux simplement marqués lus ne sont pas comptés</string> + <string name="statistics_mode_count_all">Additionner tous les podcasts marqués comme lus</string> + <string name="statistics_speed_not_counted">Note : la vitesse de lecture n\'est jamais prise en compte.</string> <!--Main activity--> <string name="drawer_open">Ouvrir le menu</string> <string name="drawer_close">Fermer le menu</string> @@ -33,9 +37,11 @@ <string name="drawer_feed_order_unplayed_episodes">Trier par compteur</string> <string name="drawer_feed_order_alphabetical">Trier alphabétiquement</string> <string name="drawer_feed_order_last_update">Trier par date de publication</string> + <string name="drawer_feed_order_most_played">Trier par nombre d\'épisodes lus</string> <string name="drawer_feed_counter_new_unplayed">Nombre de nouveaux épisodes non-lus</string> <string name="drawer_feed_counter_new">Nombre de nouveaux épisodes</string> <string name="drawer_feed_counter_unplayed">Nombre d\'épisodes non-lus</string> + <string name="drawer_feed_counter_downloaded">Nombre d\'épisodes téléchargés</string> <string name="drawer_feed_counter_none">Aucun</string> <!--Webview actions--> <string name="open_in_browser_label">Ouvrir dans le navigateur</string> @@ -50,6 +56,7 @@ <string name="cancel_label">Annuler</string> <string name="yes">Oui</string> <string name="no">Non</string> + <string name="reset">Réinitialiser</string> <string name="author_label">Auteur</string> <string name="language_label">Langue</string> <string name="url_label">URL</string> @@ -60,6 +67,7 @@ <string name="refresh_label">Rafraîchir</string> <string name="external_storage_error_msg">Aucun stockage externe n\'est disponible. Merci de connecter un volume de stockage externe pour que l\'application puisse fonctionner correctement.</string> <string name="chapters_label">Chapitres</string> + <string name="chapter_duration">Durée : %1$s</string> <string name="shownotes_label">Notes d\'épisode</string> <string name="description_label">Description</string> <string name="most_recent_prefix">Épisode le plus récent :\u0020</string> @@ -81,7 +89,7 @@ <string name="feed_auto_download_never">Jamais</string> <string name="send_label">Envoyer...</string> <string name="episode_cleanup_never">Jamais</string> - <string name="episode_cleanup_queue_removal">Quand l’épisode n\'est pas dans la liste</string> + <string name="episode_cleanup_queue_removal">Quand l’épisode n\'est pas dans la liste de lecture</string> <string name="episode_cleanup_after_listening">Après avoir terminé</string> <plurals name="episode_cleanup_days_after_listening"> <item quantity="one">1 jour après avoir été écouté</item> @@ -92,15 +100,18 @@ <string name="etxtFeedurlHint">URL du flux</string> <string name="txtvfeedurl_label">Ajouter un podcast par son URL</string> <string name="podcastdirectories_label">Trouver le podcast dans la bibliothèque</string> - <string name="podcastdirectories_descr">Vous pouvez chercher de nouveaux podcasts en filtrant par nom, catégorie ou popularité dans la bibliothèque gpodder.net, ou sur l\'iTunes Store.</string> + <string name="podcastdirectories_descr">Pour de nouveaux podcasts vous pouvez chercher iTunes ou fyyd ou parcourir gpodder.net par nom, catégorie ou popularité.</string> <string name="browse_gpoddernet_label">Chercher sur gpodder.net</string> <!--Actions on feeds--> <string name="mark_all_read_label">Marquer tous les épisodes comme lus</string> <string name="mark_all_read_msg">Tous les épisodes ont été marqués comme lus</string> <string name="mark_all_read_confirmation_msg">Confirmer le marquage de tous les épisode comme lus</string> <string name="mark_all_read_feed_confirmation_msg">Confirmer le marquage de tous les épisode de ce flux comme lus</string> - <string name="mark_all_seen_label">Marquer tout les épisodes comme vus</string> + <string name="mark_all_seen_label">Marquer tous les épisodes comme vus</string> + <string name="mark_all_seen_msg">Tous les épisodes ont été marqués vus</string> + <string name="mark_all_seen_confirmation_msg">Merci de confirmer que vous voulez marquer tous les épisodes comme vus.</string> <string name="show_info_label">Voir les détails</string> + <string name="rename_feed_label">Renommer le podcast</string> <string name="remove_feed_label">Supprimer le podcast</string> <string name="share_label">Partager...</string> <string name="share_link_label">Partager un lien vers le site</string> @@ -108,7 +119,7 @@ <string name="share_feed_url_label">Partager lien du flux</string> <string name="share_item_url_label">Partager le lien de l\'épisode</string> <string name="share_item_url_with_position_label">Partager le lien de l\'épisode avec la position</string> - <string name="feed_delete_confirmation_msg">Veuillez confirmer que vous voulez bien supprimer ce flux et TOUS ses épisodes que vous avez téléchargés.</string> + <string name="feed_delete_confirmation_msg">Confirmer que vous voulez supprimer le flux \"%1$s\" et TOUS les épisodes que vous avez téléchargés.</string> <string name="feed_remover_msg">Flux en cours de suppression</string> <string name="load_complete_feed">Mettre à jour tout le flux</string> <string name="hide_episodes_title">Cacher épisodes</string> @@ -116,10 +127,11 @@ <string name="hide_unplayed_episodes_label">Non joués</string> <string name="hide_paused_episodes_label">En pause</string> <string name="hide_played_episodes_label">Joués</string> - <string name="hide_queued_episodes_label">Rajouté à la liste d\'attente</string> - <string name="hide_not_queued_episodes_label">Pas rajouté à la liste d\'attente</string> + <string name="hide_queued_episodes_label">Rajouté à la liste de lecture</string> + <string name="hide_not_queued_episodes_label">Non rajouté à la liste de lecture</string> <string name="hide_downloaded_episodes_label">Téléchargé</string> <string name="hide_not_downloaded_episodes_label">Non téléchargé</string> + <string name="hide_has_media_label">À des médias</string> <string name="filtered_label">Filtré</string> <string name="refresh_failed_msg">{fa-exclamation-circle} La dernière mise à jour a échoué</string> <string name="open_podcast">Ouvrir Podcast</string> @@ -130,13 +142,15 @@ <string name="stop_label">Stop</string> <string name="stream_label">Lire en ligne</string> <string name="remove_label">Supprimer</string> + <string name="delete_label">Effacer</string> <string name="remove_episode_lable">Supprimer cet épisode</string> + <string name="marked_as_seen_label">Marqué comme vu</string> <string name="mark_read_label">Marquer comme lu</string> <string name="marked_as_read_label">Les épisodes ont été marqués comme lus</string> <string name="mark_unread_label">Marquer comme non lu</string> - <string name="add_to_queue_label">Ajouter à la liste</string> - <string name="added_to_queue_label">Ajouté à la liste</string> - <string name="remove_from_queue_label">Supprimer de la liste</string> + <string name="add_to_queue_label">Ajouter à la liste de lecture</string> + <string name="added_to_queue_label">Ajouté à la liste de lecture</string> + <string name="remove_from_queue_label">Supprimer de la liste de lecture</string> <string name="add_to_favorite_label">Ajouter aux Favoris</string> <string name="added_to_favorites">Ajouté aux Favoris</string> <string name="remove_from_favorite_label">Supprimer des Favoris</string> @@ -146,7 +160,7 @@ <string name="skip_episode_label">Passer cet épisode</string> <string name="activate_auto_download">Activer téléchargement automatique</string> <string name="deactivate_auto_download">Désactiver téléchargement automatique</string> - <string name="reset_position">Remettre a zéro la position de lecture actuelle</string> + <string name="reset_position">Réinitialiser la position de lecture</string> <string name="removed_item">Élément retiré</string> <!--Download messages and labels--> <string name="download_successful">terminé</string> @@ -189,9 +203,9 @@ <string name="authentication_notification_title">Authentification requise</string> <string name="authentication_notification_msg">La ressource que vous avez demandé nécessite un nom d\'utilisateur et un mot de passe</string> <string name="confirm_mobile_download_dialog_title">Confirmer le téléchargement mobile</string> - <string name="confirm_mobile_download_dialog_message_not_in_queue">Le téléchargement sur la connexion mobile est désactivé dans les options.\n\nVous pouvez choisir d\'ajouter seulement l\'épisode à la liste ou vous pouvez autoriser temporairement le téléchargement.\n\n<small>Votre choix sera retenu pour les 10 prochaines minutes.</small></string> + <string name="confirm_mobile_download_dialog_message_not_in_queue">Le téléchargement sur la connexion mobile est désactivé dans les options.\n\nVous pouvez choisir d\'ajouter seulement l\'épisode à la liste de lecture ou vous pouvez autoriser temporairement le téléchargement.\n\n<small>Votre choix sera retenu pour les 10 prochaines minutes.</small></string> <string name="confirm_mobile_download_dialog_message">Le téléchargement sur la connexion mobile est désactivé dans les options.\n\nVoulez-vous autoriser temporairement le téléchargement?\n\n<small>Votre choix sera retenu pour les 10 prochaines minutes.</small></string> - <string name="confirm_mobile_download_dialog_only_add_to_queue">Rajouter à la liste</string> + <string name="confirm_mobile_download_dialog_only_add_to_queue">Rajouter à la liste de lecture</string> <string name="confirm_mobile_download_dialog_enable_temporarily">Autoriser temporairement</string> <!--Mediaplayer messages--> <string name="player_error_msg">Erreur !</string> @@ -206,22 +220,23 @@ <string name="playbackservice_notification_title">Lecture de podcast en cours</string> <string name="unknown_media_key">AntennaPod - Touche média inconnue : %1$d</string> <!--Queue operations--> - <string name="lock_queue">Bloquer la liste</string> - <string name="unlock_queue">Débloquer la liste</string> + <string name="lock_queue">Bloquer la liste de lecture</string> + <string name="unlock_queue">Débloquer la liste de lecture</string> <string name="queue_locked">Liste de lecture verrouillée</string> <string name="queue_unlocked">Liste de lecture déverrouillée</string> - <string name="clear_queue_label">Effacer la liste</string> + <string name="clear_queue_label">Effacer la liste de lecture</string> <string name="undo">Annuler</string> <string name="removed_from_queue">Élément retiré</string> - <string name="move_to_top_label">Déplacer vers le haut de la liste</string> - <string name="move_to_bottom_label">Déplacer vers le bas de la liste</string> + <string name="move_to_top_label">Déplacer en haut de la liste</string> + <string name="move_to_bottom_label">Déplacer en bas de la liste</string> <string name="sort">Trier</string> - <string name="alpha">Ordre alphabétique</string> <string name="date">Date</string> <string name="duration">Durée</string> + <string name="episode_title">Titre de l\'épisode</string> + <string name="feed_title">Nom du flux</string> <string name="ascending">Ordre croissant</string> <string name="descending">Ordre décroissant</string> - <string name="clear_queue_confirmation_msg">Veuillez confirmer que vous voulez bien supprimer TOUS les épisodes de la file d\'attente</string> + <string name="clear_queue_confirmation_msg">Veuillez confirmer que vous voulez bien supprimer TOUS les épisodes de la liste de lecture</string> <!--Flattr--> <string name="flattr_auth_label">Connecter à Flattr</string> <string name="flattr_auth_explanation">Appuyez sur le bouton ci-dessous pour vous authentifier. Voter navigateur va s\'ouvrir et vous serez envoyés vers l\'écran de connexion Flattr afin de donner à AntennaPod la permission de flattr. Une fois fait, vous reviendrez automatiquement à cet écran.</string> @@ -272,13 +287,15 @@ <string name="pref_pauseOnDisconnect_sum">Interrompre la lecture lorsque le casque ou le bluetooth sont déconnectés</string> <string name="pref_unpauseOnHeadsetReconnect_sum">Reprendre la lecture quand les écouteurs sont reconnectés</string> <string name="pref_unpauseOnBluetoothReconnect_sum">Reprendre la lecture quand le Bluetooth se reconnecte</string> - <string name="pref_hardwareForwardButtonSkips_title">Le bouton piste suivante saute l\'épisode</string> - <string name="pref_hardwareForwardButtonSkips_sum">Passer à l\'épisode suivant au lieu de faire un saut avant quand il est pressé un bouton physique pour avancer à la piste suivante</string> + <string name="pref_hardwareForwardButtonSkips_title">Le bouton \"saut avant\" saute l\'épisode</string> + <string name="pref_hardwareForwardButtonSkips_sum">Passer à l\'épisode suivant au lieu de faire un saut avant quand un bouton physique \"saut avant\" est pressé</string> + <string name="pref_hardwarePreviousButtonRestarts_title">Le bouton \"saut arrière\" redémarre l\'épisode</string> + <string name="pref_hardwarePreviousButtonRestarts_sum">Repartir de zéro au lieu de faire un saut arrière quand un bouton physique \"saut arrière\" est pressé</string> <string name="pref_followQueue_sum">Après la fin d\'un épisode, passer au suivant</string> <string name="pref_auto_delete_sum">Supprimer l\'épisode quand la lecture est finie</string> <string name="pref_auto_delete_title">Suppression automatique</string> - <string name="pref_smart_mark_as_played_sum">Marquer les épisodes comme lus même s\'il reste encore un certain nombre de secondes à jouer</string> - <string name="pref_smart_mark_as_played_title">Marquer comme lu de manière intelligente</string> + <string name="pref_smart_mark_as_played_sum">Les épisodes seront marqués comme lus même s\'il reste quelques secondes à jouer</string> + <string name="pref_smart_mark_as_played_title">Marquer comme lu intelligemment</string> <string name="pref_skip_keeps_episodes_sum">Garder les épisodes quand ils sont passés</string> <string name="pref_skip_keeps_episodes_title">Garder les épisodes passés</string> <string name="playback_pref">Lecture</string> @@ -340,33 +357,39 @@ <string name="pref_gpodnet_logout_toast">Vous êtes maintenant déconnecté</string> <string name="pref_gpodnet_setlogin_information_title">Modifier les informations de connexion</string> <string name="pref_gpodnet_setlogin_information_sum">Modifier les information de connexion pour votre compte gpodder.net</string> - <string name="pref_gpodnet_sync_title">Synchroniser maintenant</string> - <string name="pref_gpodnet_sync_sum">Synchroniser les abonnements et l\'état de lecture avec gpodder.net</string> + <string name="pref_gpodnet_sync_changes_title">Synchroniser maintenant</string> + <string name="pref_gpodnet_sync_changes_sum">Synchroniser l\'état des abonnements et des épisodes avec gpodder.net</string> + <string name="pref_gpodnet_full_sync_title">Tout synchroniser maintenant</string> + <string name="pref_gpodnet_full_sync_sum">Synchroniser tous les abonnements et tous les états des épisodes avec gpodder.net.</string> + <string name="pref_gpodnet_sync_sum_last_sync_line">Dernière tentative de synchronisation : %1$s (%2$s)</string> <string name="pref_gpodnet_sync_started">Synchronisation démarrée</string> + <string name="pref_gpodnet_full_sync_started">Synchronisation totale commencée</string> <string name="pref_gpodnet_login_status"><![CDATA[Connecté comme <i>%1$s</i> avec l\'appareil <i>%2$s</i>]]></string> + <string name="pref_gpodnet_notifications_title">Notification des erreurs de synchronisation</string> + <string name="pref_gpodnet_notifications_sum">Ce paramètre ne s\'applique pas aux erreurs d\'authentification.</string> <string name="pref_playback_speed_title">Vitesses de lecture</string> - <string name="pref_playback_speed_sum">Modifier la liste des vitesses disponibles pour la lecture audio</string> - <string name="pref_fast_forward">Avance rapide</string> - <string name="pref_rewind">Retour en arrière</string> + <string name="pref_playback_speed_sum">Définir les vitesses disponibles lors de la lecture audio</string> + <string name="pref_fast_forward">Durée du saut avant</string> + <string name="pref_fast_forward_sum">Nombre de secondes à sauter quand le bouton \"saut avant\" est cliqué</string> + <string name="pref_rewind">Durée du saut arrière</string> + <string name="pref_rewind_sum">Nombre de secondes à sauter quand le bouton \"saut arrière\" est cliqué</string> <string name="pref_gpodnet_sethostname_title">Choisir un nom de domaine</string> <string name="pref_gpodnet_sethostname_use_default_host">Utiliser le nom de domaine par défaut</string> <string name="pref_expandNotify_title">Etendre la notification</string> - <string name="pref_expandNotify_sum">Toujours étendre les notifications pour montrer les boutons de lecture</string> + <string name="pref_expandNotify_sum">Toujours étendre la notification pour montrer tous les boutons de lecture </string> <string name="pref_persistNotify_title">Boutons de lecture permanents</string> <string name="pref_persistNotify_sum">Garder les notifications et les boutons de lecture sur l\'écran de verouillage quand la lecture est en pause</string> <string name="pref_compact_notification_buttons_title">Définir les boutons de l\'écran de verrouillage</string> <string name="pref_compact_notification_buttons_sum">Change les boutons de lecture sur l\'écran de verrouillage. Le bouton de lecture/pause est toujours affiché.</string> <string name="pref_compact_notification_buttons_dialog_title">Choisir un maximum de %1$d éléments</string> <string name="pref_compact_notification_buttons_dialog_error">Vous ne pouvez pas choisir plus de %1$d éléments.</string> - <string name="pref_show_subscriptions_in_drawer_title">Montrer Abonnements</string> - <string name="pref_show_subscriptions_in_drawer_sum">Montrer la liste des abonnements directement dans le volet de navigation</string> <string name="pref_lockscreen_background_title">Changer l’arrière plan de l\'écran de déverrouillage</string> - <string name="pref_lockscreen_background_sum">Placer l\'image de l’épisode en arrière plan de l\'écran de déverrouillage. Cela a pour effet secondaire de montrer l\'image dans les apps tierces.</string> + <string name="pref_lockscreen_background_sum">Placer l\'image de l’épisode en arrière plan de l\'écran de déverrouillage. Cela aura aussi pour effet de montrer l\'image dans les autres applications.</string> <string name="pref_showDownloadReport_title">Afficher le rapport de téléchargements</string> - <string name="pref_showDownloadReport_sum">Si les téléchargements échouent, générer un rapport des détails des échecs.</string> + <string name="pref_showDownloadReport_sum">Si les téléchargements échouent, générer un rapport détaillé des échecs.</string> <string name="pref_expand_notify_unsupport_toast">Les versions d\'Android antérieures à 4.1 ne sont pas compatibles avec les notifications élargies</string> - <string name="pref_queueAddToFront_sum">Ajouter de nouveaux épisodes en tête de file</string> - <string name="pref_queueAddToFront_title">Mettre au début de la file d\'attente</string> + <string name="pref_queueAddToFront_sum">Ajouter les nouveaux épisodes au début de la liste de lecture.</string> + <string name="pref_queueAddToFront_title">Mettre au début de la liste de lecture</string> <string name="pref_smart_mark_as_played_disabled">Désactivé</string> <string name="pref_image_cache_size_title">Taille du cache de l\'image</string> <string name="pref_image_cache_size_sum">Taille de l’espace de stockage temporaire des images.</string> @@ -375,27 +398,33 @@ <string name="send_email">Envoyer e-mail</string> <string name="experimental_pref">Expérimental</string> <string name="pref_sonic_title">Lecteur multimédia Sonic</string> - <string name="pref_sonic_message">Utiliser le lecteur multimédia interne Sonic au lieu du natif d\'Android ou de Prestissimo</string> + <string name="pref_sonic_message">Utiliser le lecteur multimédia interne Sonic au lieu du lecteur natif d\'Android ou Prestissimo</string> <string name="pref_current_value">Valeur actuelle : %1$s</string> <string name="pref_proxy_title">Proxy</string> <string name="pref_proxy_sum">Paramétrer un réseau proxy</string> <string name="pref_faq">FAQ</string> <string name="pref_known_issues">Problèmes connus</string> <string name="pref_no_browser_found">Aucun navigateur trouvé.</string> - <string name="pref_cast_title">Chromecast support</string> - <string name="pref_cast_message">Activer le support de lecture de médias à distance pour les appareils Cast (comme Chromecast, haut parleurs ou Android Tv) </string> + <string name="pref_cast_title">Support Chromecast</string> + <string name="pref_cast_message_play_flavor">Activer la lecture à distance sur les appareils Cast (comme Chromecast, Audio Speaker ou Android TV)</string> + <string name="pref_cast_message_free_flavor">Chromecast nécessite des bibliothèques tierces qui sont désactivées dans cette version d\'AntennaPod</string> + <string name="pref_enqueue_downloaded_title">Ajouter à la liste après téléchargement</string> + <string name="pref_enqueue_downloaded_summary">Mettre les épisodes dans la la liste de lecture après téléchargement</string> <!--Auto-Flattr dialog--> <string name="auto_flattr_enable">Activer le paiement flattr automatique</string> <string name="auto_flattr_after_percent">Lancer un paiement flattr pour un épisode dès que %d de l\'épisode a été joué</string> <string name="auto_flattr_ater_beginning">Lancer le paiement flattr d\'un épisode dès que la lecture commence</string> <string name="auto_flattr_ater_end">Lancer le paiement flattr d\'un épisode à la fin de la lecture</string> <!--Search--> - <string name="search_hint">Chercher des flux ou épisodes</string> - <string name="found_in_shownotes_label">Trouvé dans les notes</string> + <string name="search_hint">Chercher les épisodes</string> + <string name="found_in_shownotes_label">Trouvé dans les notes d\'épisodes</string> <string name="found_in_chapters_label">Trouvé dans les titres de chapitre</string> + <string name="found_in_authors_label">Trouvés en tant qu\'auteur</string> + <string name="found_in_feeds_label">Trouvés dans les flux</string> <string name="search_status_no_results">Aucun résultat trouvé</string> <string name="search_label">Recherche</string> <string name="found_in_title_label">Trouvé dans le titre</string> + <string name="no_results_for_query">Aucun résultat trouvé pour \"%1$s\"</string> <!--OPML import and export--> <string name="opml_import_txtv_button_lable">Les fichiers OPML vous permettent d\'exporter vos podcasts d\'un logiciel à un autre.</string> <string name="opml_import_option">Option %1$d</string> @@ -414,20 +443,21 @@ <string name="choose_file_from_filesystem">Depuis le système de fichier local</string> <string name="choose_file_from_external_application">Utiliser une application tierce</string> <string name="opml_export_label">Exportation OPML</string> + <string name="html_export_label">Export HTML</string> <string name="exporting_label">Export en cours...</string> <string name="export_error_label">Erreur d\'exportation</string> <string name="opml_export_success_title">Exportation OPML réussie.</string> <string name="opml_export_success_sum">Le fichier .opml a été écrit ici :\u0020</string> <string name="opml_import_ask_read_permission">L\'accès au stockage externe est requis pour lire le fichier OPML</string> <!--Sleep timer--> - <string name="set_sleeptimer_label">Définir le minuteur d\'arrêt automatique</string> - <string name="disable_sleeptimer_label">Désactiver le minuteur d\'arrêt automatique</string> + <string name="set_sleeptimer_label">Activation du minuteur d\'arrêt</string> + <string name="disable_sleeptimer_label">Désactiver le minuteur d\'arrêt</string> <string name="enter_time_here_label">Entrer l\'heure</string> - <string name="sleep_timer_label">Minuteur de mise en veille</string> + <string name="sleep_timer_label">Minuteur d\'arrêt</string> <string name="time_left_label">Durée restante :\u0020</string> <string name="time_dialog_invalid_input">Entrée invalide, la durée doit être un nombre entier</string> - <string name="timer_about_to_expire_label"><b>Quand le minuteur est sur le point de se terminer:</b></string> - <string name="shake_to_reset_label">Secouer afin de remettre le minuteur a zéro</string> + <string name="timer_about_to_expire_label"><b>Quand le minuteur se termine :</b></string> + <string name="shake_to_reset_label">Secouer pour redémarrer le minuteur</string> <string name="timer_vibration_label">Vibrer</string> <string name="time_seconds">secondes</string> <string name="time_minutes">minutes</string> @@ -444,6 +474,9 @@ <item quantity="one">1 heure</item> <item quantity="other">%d heures</item> </plurals> + <string name="auto_enable_label">Activation automatique</string> + <string name="sleep_timer_enabled_label">Arrêt automatique activé</string> + <string name="sleep_timer_disabled_label">Arrêt automatique désactivé</string> <!--gpodder.net--> <string name="gpodnet_taglist_header">CATEGORIES</string> <string name="gpodnet_toplist_header">PODCASTS POPULAIRES</string> @@ -473,6 +506,8 @@ <string name="gpodnetsync_auth_error_descr">Problème d\'identifiant et/ou de mot de passe</string> <string name="gpodnetsync_error_title">Problème de synchronisation avec gpodder.net</string> <string name="gpodnetsync_error_descr">Une erreur est apparue lors de la synchronisation :\u0020</string> + <string name="gpodnetsync_pref_report_successful">Réussie</string> + <string name="gpodnetsync_pref_report_failed">Échoué</string> <!--Directory chooser--> <string name="selected_folder_label">Répertoire choisi :</string> <string name="create_folder_label">Créer répertoire</string> @@ -490,7 +525,7 @@ <string name="folder_not_empty_dialog_title">Le répertoire n\'est pas vide</string> <string name="folder_not_empty_dialog_msg">Le répertoire que vous avez choisi n\'est pas vide. Les fichiers téléchargés seront ajoutés à ce répertoire. Continuer malgré tout ?</string> <string name="set_to_default_folder">Choisir le répertoire par défaut</string> - <string name="pref_pausePlaybackForFocusLoss_sum">Mettre la lecture en pause au lieu de baisser le volume quand une autre application veut jouer un son</string> + <string name="pref_pausePlaybackForFocusLoss_sum">Pauser la lecture au lieu de baisser le volume quand une autre application joue un son</string> <string name="pref_pausePlaybackForFocusLoss_title">Mettre en pause lors d\'interruptions</string> <string name="pref_resumeAfterCall_sum">Reprendre la lecture après un appel téléphonique</string> <string name="pref_resumeAfterCall_title">Reprendre après appel</string> @@ -500,13 +535,13 @@ <string name="subscribed_label">Abonné</string> <string name="downloading_label">En cours de téléchargement...</string> <!--Content descriptions for image buttons--> - <string name="rewind_label">Retour en arrière</string> - <string name="fast_forward_label">Avance rapide</string> + <string name="rewind_label">Saut arrière</string> + <string name="fast_forward_label">Saut avant</string> <string name="media_type_audio_label">Audio</string> <string name="media_type_video_label">Vidéo</string> <string name="navigate_upwards_label">Naviguer vers le haut</string> <string name="status_downloading_label">L\'épisode est en train d\'être téléchargé</string> - <string name="in_queue_label">L\'épisode est dans la liste</string> + <string name="in_queue_label">L\'épisode est dans la liste de lecture</string> <string name="drag_handle_content_description">Faire glisser pour changer la position de cet élément</string> <string name="load_next_page_label">Charger la page suivante</string> <!--Feed information screen--> @@ -525,6 +560,7 @@ <string name="sp_apps_importing_feeds_msg">Importation des abonnements à partir d\'applications à usage unique...</string> <string name="search_itunes_label">Chercher sur iTunes</string> <string name="filter">Filtrer</string> + <string name="search_fyyd_label">Chercher fyyd</string> <!--Episodes apply actions--> <string name="all_label">Tout</string> <string name="selected_all_label">Tous les épisodes ont été sélectionné</string> @@ -540,8 +576,10 @@ <string name="selected_not_downloaded_label">Épisodes non téléchargés sélectionnés</string> <string name="queued_label">Dans liste de lecture</string> <string name="selected_queued_label">Episodes présents dans la liste de lecture sélectionnés</string> - <string name="not_queued_label">Hors liste de lecture</string> + <string name="not_queued_label">En dehors de la liste de lecture</string> <string name="selected_not_queued_label">Episodes absents de la liste de lecture sélectionnés</string> + <string name="has_media">À des médias</string> + <string name="selected_has_media_label">Sélectionner les épisodes avec des médias</string> <!--Sort--> <string name="sort_title_a_z">Titre (A \u2192 Z)</string> <string name="sort_title_z_a">Titre (Z \u2192 A)</string> @@ -585,11 +623,11 @@ <string name="cast_failed_to_pause">Échec de mise en pause du média</string> <!--<string name="cast_failed_to_connect">Could not connect to the device</string>--> <string name="cast_failed_setting_volume">Échec de réglage du volume</string> - <string name="cast_failed_no_connection">Aucune connexion à l\'appareil Cast existe</string> + <string name="cast_failed_no_connection">Aucune connexion à l\'appareil Cast n\'existe</string> <string name="cast_failed_no_connection_trans">La connexion à l\'appareil cast a été perdu. L\'application tente de rétablir la connexion. Veuillez patienter quelques secondes et réessayer.</string> <string name="cast_failed_perform_action">Échec de l\'action</string> <string name="cast_failed_status_request">Échec de la synchronisation avec l\'appareil cast</string> <string name="cast_failed_seek">Échec de la recherche de la nouvelle position sur l\'appareil cast</string> - <string name="cast_failed_receiver_player_error">Le lecteur de réception à rencontrer une grave erreur</string> + <string name="cast_failed_receiver_player_error">Le lecteur de réception a rencontré une grave erreur</string> <string name="cast_failed_media_error_skipping">Erreur de lecture du média. Passage au suivant...</string> </resources> diff --git a/core/src/main/res/values-gl-rES/strings.xml b/core/src/main/res/values-gl-rES/strings.xml new file mode 100644 index 000000000..995687fa2 --- /dev/null +++ b/core/src/main/res/values-gl-rES/strings.xml @@ -0,0 +1,633 @@ +<?xml version='1.0' encoding='UTF-8'?> +<resources xmlns:tools="http://schemas.android.com/tools"> + <!--Activitiy and fragment titles--> + <string name="feeds_label">Fontes</string> + <string name="statistics_label">EstatÃsticas</string> + <string name="add_feed_label">Engadir Podcast</string> + <string name="episodes_label">Episodios</string> + <string name="all_episodes_short_label">Todo</string> + <string name="favorite_episodes_label">Favoritos</string> + <string name="new_label">Novo</string> + <string name="settings_label">Axustes</string> + <string name="add_new_feed_label">Engadir Podcast</string> + <string name="downloads_label">Descargas</string> + <string name="downloads_running_label">Descargando</string> + <string name="downloads_completed_label">Completado</string> + <string name="downloads_log_label">Rexistro</string> + <string name="subscriptions_label">Suscricións</string> + <string name="subscriptions_list_label">Lista de suscricións</string> + <string name="cancel_download_label">Cancelar\nDescarga</string> + <string name="playback_history_label">Historial de reprodución</string> + <string name="gpodnet_main_label">gpodder.net</string> + <string name="gpodnet_auth_label">gpodder.net Conexión</string> + <string name="free_space_label">%1$s gratis</string> + <string name="episode_cache_full_title">Caché de episodios chea</string> + <string name="episode_cache_full_message">Acadouse o lÃmite de espazo na caché de episodios. Pode incrementalo nos Axustes do tamaño da caché.</string> + <!--Statistics fragment--> + <string name="total_time_listened_to_podcasts">Tempo total dos podcast reproducidos:</string> + <string name="statistics_details_dialog">%1$d de %2$d episodios iniciados.\n\nReproducidos %3$s de %4$s.</string> + <string name="statistics_mode">Modo de estatÃsticas</string> + <string name="statistics_mode_normal">Calcular a duración que foi realmente reproducida. Reproducir dúas veces conta dobre, mentras que marcar como lido non conta</string> + <string name="statistics_mode_count_all">Sumar todos os podcast marcados como reproducidos</string> + <string name="statistics_speed_not_counted">Aviso: A velocidade de reprodución non se ten en conta en ningún caso.</string> + <!--Main activity--> + <string name="drawer_open">Abrir menú</string> + <string name="drawer_close">Pechar menú</string> + <string name="drawer_preferences">Preferencias da caixa</string> + <string name="drawer_feed_order_unplayed_episodes">Ordenar polo contador</string> + <string name="drawer_feed_order_alphabetical">Ordenar alfabéticamente</string> + <string name="drawer_feed_order_last_update">Ordenar por data de publicación</string> + <string name="drawer_feed_order_most_played">Ordenar por número de episodios reproducidos</string> + <string name="drawer_feed_counter_new_unplayed">Número de episodios novos e non reproducidos</string> + <string name="drawer_feed_counter_new">Número de episodios novos</string> + <string name="drawer_feed_counter_unplayed">Número de episodios non reproducidos</string> + <string name="drawer_feed_counter_downloaded">Número de episodios descargados</string> + <string name="drawer_feed_counter_none">Ningún</string> + <!--Webview actions--> + <string name="open_in_browser_label">Abrir en navegador</string> + <string name="copy_url_label">Copiar URL</string> + <string name="share_url_label">Compartir URL</string> + <string name="copied_url_msg">Copiar URL ao portapapeis</string> + <string name="go_to_position_label">Ir a esta posición</string> + <!--Playback history--> + <string name="clear_history_label">Limpar historial</string> + <!--Other--> + <string name="confirm_label">Confirmar</string> + <string name="cancel_label">Cancelar</string> + <string name="yes">Si</string> + <string name="no">Non</string> + <string name="reset">Restablecer</string> + <string name="author_label">Autor</string> + <string name="language_label">Idioma</string> + <string name="url_label">URL</string> + <string name="podcast_settings_label">Axustes</string> + <string name="cover_label">Imaxe</string> + <string name="error_label">Fallo</string> + <string name="error_msg_prefix">Houbo un fallo:</string> + <string name="refresh_label">Actualizar</string> + <string name="external_storage_error_msg">Non se dispón de almacenamento externo. Por favor asegúrese de que o almacenamento externo está montado e asà o app poderá funcionar correctamente.</string> + <string name="chapters_label">CapÃtulos</string> + <string name="chapter_duration">Duración: %1$s</string> + <string name="shownotes_label">Notas do episodio</string> + <string name="description_label">Descrición</string> + <string name="most_recent_prefix">Episodio máis recente:\u0020</string> + <string name="episodes_suffix">\u0020episodios</string> + <string name="length_prefix">Duración:\u0020</string> + <string name="size_prefix">Tamaño:\u0020</string> + <string name="processing_label">Procesando</string> + <string name="loading_label">Cargando...</string> + <string name="save_username_password_label">Gardar nome de usuario e contrasinal</string> + <string name="close_label">Pechar</string> + <string name="retry_label">Reintentar</string> + <string name="auto_download_label">IncluÃr en descargas automáticas</string> + <string name="auto_download_apply_to_items_title">Aplicar a episodios previos</string> + <string name="auto_download_apply_to_items_message">A nova función <i>Descarga automática</i> aplicarase automáticamente aos novos episodios.\nQuere que tamén se aplique aos episodios publicados con anterioridade?</string> + <string name="auto_delete_label">Borrado automático do episodio</string> + <string name="parallel_downloads_suffix">\u0020descargas paralelas</string> + <string name="feed_auto_download_global">Valor xeral por omisión</string> + <string name="feed_auto_download_always">Sempre</string> + <string name="feed_auto_download_never">Nunca</string> + <string name="send_label">Enviar...</string> + <string name="episode_cleanup_never">Nunca</string> + <string name="episode_cleanup_queue_removal">Cando non esté na cola</string> + <string name="episode_cleanup_after_listening">Tras rematar</string> + <plurals name="episode_cleanup_days_after_listening"> + <item quantity="one">1 dÃa despois de rematar</item> + <item quantity="other">%d dÃas despois de rematar</item> + </plurals> + <!--'Add Feed' Activity labels--> + <string name="feedurl_label">URL da fonte</string> + <string name="etxtFeedurlHint">www.example.com/feed</string> + <string name="txtvfeedurl_label">Engadir Podcast por URL</string> + <string name="podcastdirectories_label">Buscar Podcast nun directorio</string> + <string name="podcastdirectories_descr">Para novos podcasts, pode buscar en iTunes ou fyyd, ou tamén en gpodder.net por nome, categorÃa ou popularidade.</string> + <string name="browse_gpoddernet_label">Buscar en gpodder.net</string> + <!--Actions on feeds--> + <string name="mark_all_read_label">Marcar todo como reproducido</string> + <string name="mark_all_read_msg">Marcáronse todos como reproducidos</string> + <string name="mark_all_read_confirmation_msg">Por favor confirme que quere marcar todos os episodios como reproducidos.</string> + <string name="mark_all_read_feed_confirmation_msg">Por favor confirme que quere marcar todos os episodios de esta fonte como reproducidos.</string> + <string name="mark_all_seen_label">Marcar como visto</string> + <string name="mark_all_seen_msg">Marcáronse todos os episodios como vistos</string> + <string name="mark_all_seen_confirmation_msg">Por favor confirme que quere marcar todos os episodios como vistos.</string> + <string name="show_info_label">Mostrar información</string> + <string name="rename_feed_label">Mudar nome do podcast</string> + <string name="remove_feed_label">Quitar podcast</string> + <string name="share_label">Compartir...</string> + <string name="share_link_label">Compartir ligazón</string> + <string name="share_link_with_position_label">Compartir ligazón con posición</string> + <string name="share_feed_url_label">Compartir URL da fonte</string> + <string name="share_item_url_label">Compartir a URL do ficheiro do episodio</string> + <string name="share_item_url_with_position_label">Compartir a URL do ficheiro do episodio con posición</string> + <string name="feed_delete_confirmation_msg">Por favor confirme que quere eliminar a fonte \"%1$s\" e TODOS os episodios de esta fonte anteriormente descargados.</string> + <string name="feed_remover_msg">Eliminando a fonte</string> + <string name="load_complete_feed">Actualizar completamente a fonte</string> + <string name="hide_episodes_title">Ocultar episodios</string> + <string name="episode_actions">Aplicar accións</string> + <string name="hide_unplayed_episodes_label">Non reproducido</string> + <string name="hide_paused_episodes_label">En pausa</string> + <string name="hide_played_episodes_label">Reproducido</string> + <string name="hide_queued_episodes_label">Na cola</string> + <string name="hide_not_queued_episodes_label">Fora da cola</string> + <string name="hide_downloaded_episodes_label">Descargado</string> + <string name="hide_not_downloaded_episodes_label">Non descargado</string> + <string name="hide_has_media_label">Ten medios</string> + <string name="filtered_label">Filtrado</string> + <string name="refresh_failed_msg">{fa-exclamation-circle} Erro na última actualización</string> + <string name="open_podcast">Abrir podcast</string> + <!--actions on feeditems--> + <string name="download_label">Descargar</string> + <string name="play_label">Reproducir</string> + <string name="pause_label">Pausar</string> + <string name="stop_label">Parar</string> + <string name="stream_label">Enviar</string> + <string name="remove_label">Eliminar</string> + <string name="delete_label">Borrar</string> + <string name="remove_episode_lable">Eliminar episodio</string> + <string name="marked_as_seen_label">Marcar como visto</string> + <string name="mark_read_label">Marcar como reproducido</string> + <string name="marked_as_read_label">Marcado como reproducido</string> + <string name="mark_unread_label">Marcar como non reproducido</string> + <string name="add_to_queue_label">Engadir a cola</string> + <string name="added_to_queue_label">Engadido a cola</string> + <string name="remove_from_queue_label">Quitar da cola</string> + <string name="add_to_favorite_label">Engadir a favoritos</string> + <string name="added_to_favorites">Engadido a favoritos</string> + <string name="remove_from_favorite_label">Quitar dos favoritos</string> + <string name="removed_from_favorites">Eliminado dos favoritos</string> + <string name="visit_website_label">Visitar sitio web</string> + <string name="support_label">Publicar en Flattr</string> + <string name="skip_episode_label">Saltar episodio</string> + <string name="activate_auto_download">Activar a descarga automática</string> + <string name="deactivate_auto_download">Desactivar a descarga automática</string> + <string name="reset_position">Reiniciar a posición de reprodución</string> + <string name="removed_item">Elmento eleminado</string> + <!--Download messages and labels--> + <string name="download_successful">exitoso</string> + <string name="download_failed">fallou</string> + <string name="download_pending">Descarga pendente</string> + <string name="download_running">Descarga en proceso</string> + <string name="download_error_device_not_found">Non se atopou dispositivo de almacenamento</string> + <string name="download_error_insufficient_space">Non hai suficiente espacio</string> + <string name="download_error_file_error">Fallo de ficheiro</string> + <string name="download_error_http_data_error">Fallo de datos HTTP</string> + <string name="download_error_error_unknown">Fallo descoñecido</string> + <string name="download_error_parser_exception">Excepción no procesador</string> + <string name="download_error_unsupported_type">Tipo de fonte non admitida</string> + <string name="download_error_connection_error">Fallo na conexión</string> + <string name="download_error_unknown_host">Servidor descoñecido</string> + <string name="download_error_unauthorized">Fallo na autenticación</string> + <string name="download_error_file_type_type">Fallo no tipo de ficheiro</string> + <string name="download_error_forbidden">Non admitido</string> + <string name="cancel_all_downloads_label">Cancelar todas as descargas</string> + <string name="download_canceled_msg">Descarga cancelada</string> + <string name="download_canceled_autodownload_enabled_msg">Descarga cancelada\nDeshabilitouse <i>Descarga automática</i> para este elemento</string> + <string name="download_report_title">Descargas completadas con erro(s)</string> + <string name="download_report_content_title">Informe da descarga</string> + <string name="download_error_malformed_url">URL mal formada</string> + <string name="download_error_io_error">Fallo IO</string> + <string name="download_error_request_error">Fallo na petición</string> + <string name="download_error_db_access">Fallo no acceso a base de datos</string> + <plurals name="downloads_left"> + <item quantity="one">%d descarga restante</item> + <item quantity="other">%d descargas restantes</item> + </plurals> + <string name="downloads_processing">Procesando as descargas</string> + <string name="download_notification_title">Descargando datos do podcast</string> + <string name="download_report_content">%1$ddescargas exitosas, %2$d fallaron</string> + <string name="download_log_title_unknown">TÃtulo descoñecido</string> + <string name="download_type_feed">Fonte</string> + <string name="download_type_media">Ficheiro de medios</string> + <string name="download_type_image">Imaxe</string> + <string name="download_request_error_dialog_message_prefix">Houbo un fallo intentando descargar o ficheiro:\u0020</string> + <string name="authentication_notification_title">PrecÃsase autenticación</string> + <string name="authentication_notification_msg">O recurso solicitado require un usuario e contrasinal</string> + <string name="confirm_mobile_download_dialog_title">Confirme a descarga con datos do móbil</string> + <string name="confirm_mobile_download_dialog_message_not_in_queue">Descargar coa conexión de datos do móbil está deshabilitada nos axustes.\n\nPode escoller ben só engadir o episodio a cola ou pode permitir a descarga temporalmente.\n\n<small> A súa elección lembrarase durante 10 minutos.</small></string> + <string name="confirm_mobile_download_dialog_message">A descarga con datos móbiles está deshabilitada nos axustes.\n\nQuere permitir a descarga temporalmente?\n\n <small>A súa decisión lembrarase durante 10 minutos.</small></string> + <string name="confirm_mobile_download_dialog_only_add_to_queue">Engadir a cola</string> + <string name="confirm_mobile_download_dialog_enable_temporarily">Permitir temporalmente</string> + <!--Mediaplayer messages--> + <string name="player_error_msg">Fallo!</string> + <string name="player_stopped_msg">Non está a reproducir</string> + <string name="player_preparing_msg">Preparando</string> + <string name="player_ready_msg">Listo</string> + <string name="player_seeking_msg">Buscando</string> + <string name="playback_error_server_died">Servidor desconectado</string> + <string name="playback_error_unknown">Fallo descoñecido</string> + <string name="no_media_playing_label">Non reproducindo</string> + <string name="player_buffering_msg">Almacenando</string> + <string name="playbackservice_notification_title">Reproducindo podcast</string> + <string name="unknown_media_key">AntennaPod - chave de medios descoñecida: %1$d</string> + <!--Queue operations--> + <string name="lock_queue">Pechar a cola</string> + <string name="unlock_queue">Despechar a cola</string> + <string name="queue_locked">Cola pechada</string> + <string name="queue_unlocked">Cola despechada</string> + <string name="clear_queue_label">Limpar cola</string> + <string name="undo">Desfacer</string> + <string name="removed_from_queue">Elemento eliminado</string> + <string name="move_to_top_label">Mover arriba</string> + <string name="move_to_bottom_label">Mover abaixo</string> + <string name="sort">Ordenar</string> + <string name="date">Data</string> + <string name="duration">Duración</string> + <string name="episode_title">TÃtulo do episodio</string> + <string name="feed_title">TÃtulo da fonte</string> + <string name="ascending">Ascendente</string> + <string name="descending">Descendente</string> + <string name="clear_queue_confirmation_msg">Por favor confirme que quere limpar a cola e TODOS os episodios nela</string> + <!--Flattr--> + <string name="flattr_auth_label">conectar Flattr</string> + <string name="flattr_auth_explanation">Pulse o botón inferior para iniciar o proceso de autenticación. Será redireccionado a pantalla de conexión en Flattr no seu navegador e pediralle permiso para que AntennaPod poida acceder. Despois de dar permiso, voltará a esta pantalla de xeito automático.</string> + <string name="authenticate_label">Autenticar</string> + <string name="return_home_label">Voltar ao inicio</string> + <string name="flattr_auth_success">Autenticouse correctamente! Xa pode enviar valoracións a Flattr desde o app.</string> + <string name="no_flattr_token_title">Non se atopou o testemuño de Flattr</string> + <string name="no_flattr_token_notification_msg">A súa conta de Flattr non semella estar conectada a AntennaPod. Toque aquà para autenticarse.</string> + <string name="no_flattr_token_msg">A súa conta de Flattr non semella estar conectada a AntennaPod. Ben pode conectar a súa conta a AntennaPod para interactuar en Flattr desde o app ou ben pode visitar o sitio web do elemento e darlle ao flattr desde alÃ.</string> + <string name="authenticate_now_label">Autenticar</string> + <string name="action_forbidden_title">Acción non permitida</string> + <string name="action_forbidden_msg">AntennaPod non ten permiso para esta acción. A razón poderÃa ser que o testemuño de acceso de AntennaPod ou a súa conta fosen rexeitados. Pode voltar a autenticarse ou visitar o sitio web do elemento.</string> + <string name="access_revoked_title">Acceso rexeitado</string> + <string name="access_revoked_info">Eliminou correctamente o testemuño de acceso de AntennaPod a súa conta. Para completar o proceso deberá eliminar este aplicativo da lista de aplicativos autorizados nos axustes da súa conta na web de Flattr.</string> + <!--Flattr--> + <string name="flattr_click_success">Flateraches algo!</string> + <string name="flattr_click_success_count">Flateraches %d cousas!</string> + <string name="flattr_click_success_queue">Flattr\'ed: %s.</string> + <string name="flattr_click_failure_count">Failed to flattr %d things!</string> + <string name="flattr_click_failure">Not flattr\'ed: %s.</string> + <string name="flattr_click_enqueued">A cousa esta será flaterada máis tarde</string> + <string name="flattring_thing">Flattring %s</string> + <string name="flattring_label">AntennaPod está enviando a Flattr</string> + <string name="flattrd_label">AntennaPod enviou a Flattr</string> + <string name="flattrd_failed_label">Fallou o envÃo a Flattr</string> + <string name="flattr_retrieving_status">Obtendo cousas de Flattr</string> + <!--Variable Speed--> + <string name="download_plugin_label">Descargar engadido</string> + <string name="no_playback_plugin_title">Engadido non instalado</string> + <string name="no_playback_plugin_or_sonic_msg">Para que funcione a velocidade de reprodución variable recomendamos utilizar o reproductor Sonic incluÃdo[Android 4.1+].\n\nAlternativamente tamén pode descargar o engadido de terceiros de nome <i>Prestissimo</i>desde a Play Store.\nCalquer problema con Prestissimo non é responsabilidade de AntennaPod e deberÃa informar ao responsable do engadido.</string> + <string name="set_playback_speed_label">Velocidade de reproducións</string> + <string name="enable_sonic">Habilitar Sonic</string> + <!--Empty list labels--> + <string name="no_items_label">Non hai elementos na lista.</string> + <string name="no_feeds_label">AÃnda non está suscrito a ningunha fonte.</string> + <string name="no_chapters_label">Este episodio non ten capÃtulos.</string> + <string name="no_shownotes_label">Este episodio non ten notas de episodio.</string> + <!--Preferences--> + <string name="storage_pref">Almacenamento</string> + <string name="project_pref">Proxecto</string> + <string name="other_pref">Outro</string> + <string name="about_pref">Sobre</string> + <string name="queue_label">Cola</string> + <string name="services_label">Servizos</string> + <string name="flattr_label">Flattr</string> + <string name="pref_episode_cleanup_title">Limpeza de episodios</string> + <string name="pref_episode_cleanup_summary">Os episodios que non están na cola e tampouco son favoritos deberÃan poder ser candidatos a ser eliminados si a función Descarga Automática precisa espazo para novos episodios.</string> + <string name="pref_pauseOnDisconnect_sum">Deter a reprodución cando se desconectan os auriculares ou bluetooth</string> + <string name="pref_unpauseOnHeadsetReconnect_sum">Retomar a reprodución cando se conectan os auriculares</string> + <string name="pref_unpauseOnBluetoothReconnect_sum">Retomar a reprodución cando se reconecta o bluetooth</string> + <string name="pref_hardwareForwardButtonSkips_title">O botón Adiante salta</string> + <string name="pref_hardwareForwardButtonSkips_sum">Cando se presiona o botón Adiante no dispositivo salta ao seguinte episodio en lugar de reproducir de xeito acelerado</string> + <string name="pref_hardwarePreviousButtonRestarts_title">O botón Anterior reinicia</string> + <string name="pref_hardwarePreviousButtonRestarts_sum">Cando se presiona Anterior no dispositivo reinicia o episodio no lugar de ir cara atrás</string> + <string name="pref_followQueue_sum">Saltar ao seguinte elemento na cola cando remata o episodio</string> + <string name="pref_auto_delete_sum">Eliminar o episodio cando remata a súa reprodución</string> + <string name="pref_auto_delete_title">Borrado automático</string> + <string name="pref_smart_mark_as_played_sum">Marcar episodios como reproducidos si aÃnda quedan un determinado número de segundos por reproducir</string> + <string name="pref_smart_mark_as_played_title">Marcar como Reproducido automático</string> + <string name="pref_skip_keeps_episodes_sum">Manter os episodios cando son saltados</string> + <string name="pref_skip_keeps_episodes_title">Manter episodios saltados</string> + <string name="playback_pref">Reprodución</string> + <string name="network_pref">Rede</string> + <string name="pref_autoUpdateIntervallOrTime_title">Intervalo de actualización ou Hora do dÃa</string> + <string name="pref_autoUpdateIntervallOrTime_sum">Indicar un intervalo ou unha hora en concreto para actualizar automáticamente as fontes</string> + <string name="pref_autoUpdateIntervallOrTime_message">Pode establecer un <i>intervalo</i> como \"2 horas\", unha <i>hora do dÃa</i> en concreto como \"7:00 AM\" ou <i>deshabilitar</i>totalmente a actualización automática.\n\n<small>Aviso: indicar que pode haber un lixeiro retardo do momento da actualización.</small></string> + <string name="pref_autoUpdateIntervallOrTime_Disable">Deshabilitar</string> + <string name="pref_autoUpdateIntervallOrTime_Interval">Establecer intervalo</string> + <string name="pref_autoUpdateIntervallOrTime_TimeOfDay">Establecer hora do dÃa</string> + <string name="pref_autoUpdateIntervallOrTime_every">cada %1$s</string> + <string name="pref_autoUpdateIntervallOrTime_at">as %1$s</string> + <string name="pref_downloadMediaOnWifiOnly_sum">Descargar ficheiros de medios so cando rede WiFi</string> + <string name="pref_followQueue_title">Reprodución continua</string> + <string name="pref_downloadMediaOnWifiOnly_title">Descarga de medios WiFi</string> + <string name="pref_pauseOnHeadsetDisconnect_title">Desconexión de auriculares</string> + <string name="pref_unpauseOnHeadsetReconnect_title">Reconexión de auriculares</string> + <string name="pref_unpauseOnBluetoothReconnect_title">Reconexión bluetooth</string> + <string name="pref_mobileUpdate_title">Actualizacións Móbil</string> + <string name="pref_mobileUpdate_sum">Permitir actualizacións sobre a rede de datos do móbil</string> + <string name="refreshing_label">Actualizando</string> + <string name="flattr_settings_label">Axustes Flattr</string> + <string name="pref_flattr_auth_title">Conexión Flattr</string> + <string name="pref_flattr_auth_sum">Conéctese a súa conta Flattr para interactuar desde o aplicativo.</string> + <string name="pref_flattr_this_app_title">Flattr este aplicativo</string> + <string name="pref_flattr_this_app_sum">Axude ao desenvolvemento de AntennaPod comentandoo en Flattr. Grazas!</string> + <string name="pref_revokeAccess_title">Retirar acceso</string> + <string name="pref_revokeAccess_sum">Retirar o permiso de acceso a súa conta Flattr en este aplicativo.</string> + <string name="pref_auto_flattr_title">Flattr automático</string> + <string name="pref_auto_flattr_sum">Configure o flattr automático</string> + <string name="user_interface_label">Interface de usuaria</string> + <string name="pref_set_theme_title">Escolla o decorado</string> + <string name="pref_nav_drawer_title">Personalice a Caixa de navegación</string> + <string name="pref_nav_drawer_sum">Personalice o aspecto da caixa de navegación</string> + <string name="pref_nav_drawer_items_title">Estableza os elementos da Caixa de navegación</string> + <string name="pref_nav_drawer_items_sum">Cambie os elementos que aparecerán na Caixa de navegación</string> + <string name="pref_nav_drawer_feed_order_title">Estableza a orde de suscrición</string> + <string name="pref_nav_drawer_feed_order_sum">Cambie a orde das súas suscricións</string> + <string name="pref_nav_drawer_feed_counter_title">Establecer o contador de suscricións</string> + <string name="pref_nav_drawer_feed_counter_sum">Cambie a información mostrada polo contador de suscricións</string> + <string name="pref_set_theme_sum">Cambiar o aspecto de AntennaPod.</string> + <string name="pref_automatic_download_title">Descarga automática</string> + <string name="pref_automatic_download_sum">Axuste a descarga automática de episodios.</string> + <string name="pref_autodl_wifi_filter_title">Habilitar o filtro WiFi</string> + <string name="pref_autodl_wifi_filter_sum">Permitir a descarga automática só en redes WiFi selecionadas.</string> + <string name="pref_automatic_download_on_battery_title">Descargar elementos cando non esté cargando</string> + <string name="pref_automatic_download_on_battery_sum">Permitir a descarga automática cando a baterÃa non está a cargar</string> + <string name="pref_parallel_downloads_title">Descargas simultáneas</string> + <string name="pref_episode_cache_title">Caché de episodios</string> + <string name="pref_theme_title_light">Claro</string> + <string name="pref_theme_title_dark">Oscuro</string> + <string name="pref_episode_cache_unlimited">Ilimitado</string> + <string name="pref_update_interval_hours_plural">horas</string> + <string name="pref_update_interval_hours_singular">hora</string> + <string name="pref_update_interval_hours_manual">Manual</string> + <string name="pref_gpodnet_authenticate_title">Conexión</string> + <string name="pref_gpodnet_authenticate_sum">Conectar coa súa conta gpodder.net para sincronizar as súas suscricións.</string> + <string name="pref_gpodnet_logout_title">Desconectar</string> + <string name="pref_gpodnet_logout_toast">Desconectouse correctamente</string> + <string name="pref_gpodnet_setlogin_information_title">Cambiar a información de conexión</string> + <string name="pref_gpodnet_setlogin_information_sum">Cambiar a información de conexión da súa conta gpodder.net</string> + <string name="pref_gpodnet_sync_changes_title">Sincronizar os cambios agora</string> + <string name="pref_gpodnet_sync_changes_sum">Sincronizar os datos de suscrición e estado dos episodios con gpodder.net</string> + <string name="pref_gpodnet_full_sync_title">Sincronice todo agora</string> + <string name="pref_gpodnet_full_sync_sum">Sincronizar todas as suscricións e estados de episodios con gpodder.net</string> + <string name="pref_gpodnet_sync_sum_last_sync_line">Último intento de sincronización: %1$s (%2$s)</string> + <string name="pref_gpodnet_sync_started">Sincronización iniciada</string> + <string name="pref_gpodnet_full_sync_started">Sincronización completa iniciada</string> + <string name="pref_gpodnet_login_status"><![CDATA[Conectada como <i>%1$s</i> co dispositivo <i>%2$s</i>]]></string> + <string name="pref_gpodnet_notifications_title">Mostrar notificacións de erros na sincronización.</string> + <string name="pref_gpodnet_notifications_sum">Esta preferencia non se aplica a fallos na autenticación.</string> + <string name="pref_playback_speed_title">Velocidades de reprodución</string> + <string name="pref_playback_speed_sum">Personalice a velocidade variable de reprodución de audio</string> + <string name="pref_fast_forward">Avance rápido Salta tempo</string> + <string name="pref_fast_forward_sum">Personalice o número de segundos a avanzar cando o se pulsa o botón de avance rápido</string> + <string name="pref_rewind">Retroceso Salta tempo</string> + <string name="pref_rewind_sum">Personalice o número de segundos que se retrocede na reprodución cando se pulsa o botón retroceso</string> + <string name="pref_gpodnet_sethostname_title">Establecer servidor</string> + <string name="pref_gpodnet_sethostname_use_default_host">Utilizar servidor por omisión</string> + <string name="pref_expandNotify_title">Expandir notificación</string> + <string name="pref_expandNotify_sum">Expandir sempre a notificación para mostrar os botóns de reprodución</string> + <string name="pref_persistNotify_title">Controles persistentes de reprodución</string> + <string name="pref_persistNotify_sum">Manter notificación e controles na pantalla de bloqueo cando a reprodución está pausada.</string> + <string name="pref_compact_notification_buttons_title">Establecer botóns de pantalla de bloqueo</string> + <string name="pref_compact_notification_buttons_sum">Cambiar os botóns de reprodución na pantalla de bloqueo. O botón reproducir/pausa sempre se inclúe.</string> + <string name="pref_compact_notification_buttons_dialog_title">Escolla un máximo de %1$d elementos</string> + <string name="pref_compact_notification_buttons_dialog_error">Só pode selecionar un máximo de %1$d elementos.</string> + <string name="pref_lockscreen_background_title">Establecer fondo da pantalla de bloqueo</string> + <string name="pref_lockscreen_background_sum">Establecer o fondo de pantalla de bloqueo coa imaxe do episodio actual. Como consecuencia, esto tamén mostrará a imaxe en aplicativos de terceiros.</string> + <string name="pref_showDownloadReport_title">Mostrar informe de descarga</string> + <string name="pref_showDownloadReport_sum">Si falla a descarga, xerar un informe que informe dos detalles do fallo.</string> + <string name="pref_expand_notify_unsupport_toast">As versións de Android anteriores a 4.1 non teñen soporte para notificacións expandidas.</string> + <string name="pref_queueAddToFront_sum">Engadir os novos episodios ao inicio da cola.</string> + <string name="pref_queueAddToFront_title">Por no inicio da cola</string> + <string name="pref_smart_mark_as_played_disabled">Deshabilitado</string> + <string name="pref_image_cache_size_title">Tamaño da caché de imaxes</string> + <string name="pref_image_cache_size_sum">Tamaño da caché en disco para as imaxes.</string> + <string name="crash_report_title">Informe de Desgracias</string> + <string name="crash_report_sum">Enviar por email o informe de fallo xeral no aplicativo</string> + <string name="send_email">Enviar email</string> + <string name="experimental_pref">En probas</string> + <string name="pref_sonic_title">Sonic Media Player</string> + <string name="pref_sonic_message">Utilizar o sonic media player incluÃdo no lugar do reprodutor nativo de Android e Prestissimo</string> + <string name="pref_current_value">Valor actual: %1$s</string> + <string name="pref_proxy_title">Proxy</string> + <string name="pref_proxy_sum">Establecer un proxy para a rede</string> + <string name="pref_faq">PMF</string> + <string name="pref_known_issues">Problemas coñecidos</string> + <string name="pref_no_browser_found">Non se atopou un navegador web</string> + <string name="pref_cast_title">Soporte Chromecast</string> + <string name="pref_cast_message_play_flavor">Habilitar o soporte de reprodución remota nun dispositivo Cast (como o Chromecast, Altofalantes ou Android TV)</string> + <string name="pref_cast_message_free_flavor">Chromecast precisa software propietario de terceiras partes que están deshabilitadas en esta versión de AntennaPod</string> + <string name="pref_enqueue_downloaded_title">Descargas engadidas a cola</string> + <string name="pref_enqueue_downloaded_summary">Engadir os episodios descargados a cola</string> + <!--Auto-Flattr dialog--> + <string name="auto_flattr_enable">Hablitar o flattring automático</string> + <string name="auto_flattr_after_percent">Flattr o episodio tan pronto como o %d por cento foi reproducido</string> + <string name="auto_flattr_ater_beginning">Flattr o episodio cando se inicia a reprodución</string> + <string name="auto_flattr_ater_end">Flattr o episodio cando remata a reprodución</string> + <!--Search--> + <string name="search_hint">Buscar episodios</string> + <string name="found_in_shownotes_label">Atopado nas notas do episodio</string> + <string name="found_in_chapters_label">Atopado en capÃtulos</string> + <string name="found_in_authors_label">Atopado en autores</string> + <string name="found_in_feeds_label">Atopado en fontes</string> + <string name="search_status_no_results">Non se atoparon resultados</string> + <string name="search_label">Buscar</string> + <string name="found_in_title_label">Atopado no tÃtulo</string> + <string name="no_results_for_query">Non hai resultados para \"%1$s\"</string> + <!--OPML import and export--> + <string name="opml_import_txtv_button_lable">Os ficheiros OPML permÃtenlle mover os seus podcast de un xestor a outro.</string> + <string name="opml_import_option">Opción %1$d</string> + <string name="opml_import_explanation_1">Escolla unha ruta de ficheiro concreta no sistema de ficheiros local.</string> + <string name="opml_import_explanation_2">Utilice unha aplicación externa como Dropbox, Google Drive ou o seu xestor de ficheiros para abrir un ficheiro OPML.</string> + <string name="opml_import_explanation_3">Moitos aplicativos como Google Mail, Dropbox, Google Drive e a maiorÃa dos xestores de ficheiros poden <i>abrir</i> ficheiros OPML <i>con</i> AntennaPod.</string> + <string name="start_import_label">Iniciar a importación</string> + <string name="opml_import_label">Importar OPML</string> + <string name="opml_directory_error">FALLO!</string> + <string name="reading_opml_label">Lendo ficheiro OPML</string> + <string name="opml_reader_error">Houbo un fallo ao ler o documento OPML:</string> + <string name="opml_import_error_no_file">Non hai ficheiro seleccionado!</string> + <string name="select_all_label">Seleccionar todo</string> + <string name="deselect_all_label">Deseleccionar todo</string> + <string name="select_options_label">Seleccionar...</string> + <string name="choose_file_from_filesystem">Desde sistema local de ficheiros</string> + <string name="choose_file_from_external_application">Utilizar aplicativo externo</string> + <string name="opml_export_label">Exportar OPML</string> + <string name="html_export_label">Exportar HTML</string> + <string name="exporting_label">Exportando...</string> + <string name="export_error_label">Fallo ao exportar</string> + <string name="opml_export_success_title">Exportación OPML exitosa.</string> + <string name="opml_export_success_sum">O ficheiro .opml foi gardado en:\u0020</string> + <string name="opml_import_ask_read_permission">PrecÃsase acceso ao almacenamento externo para ler o ficheiro OPML</string> + <!--Sleep timer--> + <string name="set_sleeptimer_label">Establecer apagado automático</string> + <string name="disable_sleeptimer_label">Deshabilitar o apagado automático</string> + <string name="enter_time_here_label">Introducir tempo</string> + <string name="sleep_timer_label">Apagado automático</string> + <string name="time_left_label">Tempo restante:\u0020</string> + <string name="time_dialog_invalid_input">Entrada incorrecta, o tempo ten que ser un número enteiro</string> + <string name="timer_about_to_expire_label"><b>Cando está a piques de rematar o temporizador:</b></string> + <string name="shake_to_reset_label">Axitar para reiniciar o temporizador</string> + <string name="timer_vibration_label">Vibrar</string> + <string name="time_seconds">segundos</string> + <string name="time_minutes">minutos</string> + <string name="time_hours">horas</string> + <plurals name="time_seconds_quantified"> + <item quantity="one">1 segundo</item> + <item quantity="other">%d segundos</item> + </plurals> + <plurals name="time_minutes_quantified"> + <item quantity="one">1 minuto</item> + <item quantity="other">%d minutos</item> + </plurals> + <plurals name="time_hours_quantified"> + <item quantity="one">1 hora</item> + <item quantity="other">%d horas</item> + </plurals> + <string name="auto_enable_label">Habilitar automáticamente</string> + <string name="sleep_timer_enabled_label">Apagado automático habilitado</string> + <string name="sleep_timer_disabled_label">Apagado automático deshabilitado</string> + <!--gpodder.net--> + <string name="gpodnet_taglist_header">CATEGORÃAS</string> + <string name="gpodnet_toplist_header">PODCASTS TOP</string> + <string name="gpodnet_suggestions_header">SUXESTIÓNS</string> + <string name="gpodnet_search_hint">Buscar en gpodder.net</string> + <string name="gpodnetauth_login_title">Conexión</string> + <string name="gpodnetauth_login_descr">Benvida ao proceso de conexión a gpodder.net. Primeiro, escriba os seus datos de conexión:</string> + <string name="gpodnetauth_login_butLabel">Conexión</string> + <string name="gpodnetauth_login_register">Se aÃnda non ten unha conta, pode crear unha aquÃ:\nhttps://gpodder.net/register/</string> + <string name="username_label">Nome de usuaria</string> + <string name="password_label">Contrasinal</string> + <string name="gpodnetauth_device_title">Selección de dispositivo</string> + <string name="gpodnetauth_device_descr">Crear un novo dispositivo para usar coa sua conta gpodder.net ou escoller un existente:</string> + <string name="gpodnetauth_device_deviceID">ID de dispositivo:\u0020</string> + <string name="gpodnetauth_device_caption">TÃtulo</string> + <string name="gpodnetauth_device_butCreateNewDevice">Crear un novo dispositivo</string> + <string name="gpodnetauth_device_chooseExistingDevice">Escolle un novo dispositivo:</string> + <string name="gpodnetauth_device_errorEmpty">O ID do dispositivo non pode quedar baldeiro</string> + <string name="gpodnetauth_device_errorAlreadyUsed">ID de dispositivo xa en uso</string> + <string name="gpodnetauth_device_caption_errorEmpty">Non pode quedar baldeiro o titulo</string> + <string name="gpodnetauth_device_butChoose">Escoller</string> + <string name="gpodnetauth_finish_title">Conexión correcta!</string> + <string name="gpodnetauth_finish_descr">Parabéns! A súa conta gpodder.net está conectada ao dispositivo. AntennaPod poderá agora sincronizar automáticamente as súas suscricións no dispositivo na conta de gpodder.net</string> + <string name="gpodnetauth_finish_butsyncnow">Iniciar a sincronización</string> + <string name="gpodnetauth_finish_butgomainscreen">Ir a pantalla principal</string> + <string name="gpodnetsync_auth_error_title">fallo na autenticación en gpodder.net</string> + <string name="gpodnetsync_auth_error_descr">Nome de usuaria o contrasinal incorrectos</string> + <string name="gpodnetsync_error_title">fallo na sincronización con gpodder.net</string> + <string name="gpodnetsync_error_descr">Houbo un fallo durante a sincronización:\u0020</string> + <string name="gpodnetsync_pref_report_successful">Con éxito</string> + <string name="gpodnetsync_pref_report_failed">Fallou</string> + <!--Directory chooser--> + <string name="selected_folder_label">Cartafol escollido:</string> + <string name="create_folder_label">Crear cartafol</string> + <string name="choose_data_directory">Escoller cartafol de datos</string> + <string name="choose_data_directory_message">Por favor escolla a base do cartafol dos seus datos. AntennaPod creará os subcartafoles axeitados.</string> + <string name="choose_data_directory_permission_rationale">PrecÃsase o acceso ao almacenamento externo para mudar o cartafol de datos</string> + <string name="create_folder_msg">Crear un novo cartafol de nome \"%1$s\"?</string> + <string name="create_folder_success">Novo cartafol creado</string> + <string name="create_folder_error_no_write_access">Non se pode escribir en este cartafol</string> + <string name="create_folder_error_already_exists">O cartafol xa existe</string> + <string name="create_folder_error">Non se creou o cartafol</string> + <string name="folder_does_not_exist_error">\"%1$s\" non existe</string> + <string name="folder_not_readable_error">\"%1$s\" non se pode ler</string> + <string name="folder_not_writable_error">non se pode escribir en \"%1$s\"</string> + <string name="folder_not_empty_dialog_title">O cartafol non está baldeiro</string> + <string name="folder_not_empty_dialog_msg">O cartafol escollido non está baldeiro. As descargas de medios e outros ficheiros situaranse directamente en este cartafol. Proceder de todos xeitos?</string> + <string name="set_to_default_folder">Escolla o cartafol por omisión</string> + <string name="pref_pausePlaybackForFocusLoss_sum">Pausar a reprodución en lugar de baixar o volume cando outro app quere reproducir un son.</string> + <string name="pref_pausePlaybackForFocusLoss_title">Pausa para interrupcións</string> + <string name="pref_resumeAfterCall_sum">Retomar a reprodución despois de rematar a chamada telefónica</string> + <string name="pref_resumeAfterCall_title">Retomar despois da chamada</string> + <string name="pref_restart_required">AntennaPod debe reiniciarse para que esta opción se aplique.</string> + <!--Online feed view--> + <string name="subscribe_label">Suscribir</string> + <string name="subscribed_label">Suscrito</string> + <string name="downloading_label">Descargando...</string> + <!--Content descriptions for image buttons--> + <string name="rewind_label">Rebobinar</string> + <string name="fast_forward_label">Avance rápido</string> + <string name="media_type_audio_label">Son</string> + <string name="media_type_video_label">VÃdeo</string> + <string name="navigate_upwards_label">Navegar hacia arriba</string> + <string name="status_downloading_label">Estase a descargar o episodio</string> + <string name="in_queue_label">O episodio está na cola</string> + <string name="drag_handle_content_description">Arrastre para mudar a posición de este elemento</string> + <string name="load_next_page_label">Cargar a seguinte páxina</string> + <!--Feed information screen--> + <string name="authentication_label">Autenticación</string> + <string name="authentication_descr">Cambiar o seu nome de usuaria e contrasinal para este podcast e os seus episodios.</string> + <string name="auto_download_settings_label">Axustes de descarga automática</string> + <string name="episode_filters_label">Fitro de episodios</string> + <string name="episode_filters_description">Lista dos termos utilizados para decidir si un episodio debe ser incluÃdo ou excluÃdo das descargas automáticas</string> + <string name="episode_filters_include">IncluÃr</string> + <string name="episode_filters_exclude">ExcluÃr</string> + <string name="episode_filters_hint">Palabras simples \n\"Varias palabras\"</string> + <string name="keep_updated">Manter actualizado</string> + <!--Progress information--> + <string name="progress_upgrading_database">Actualizando a base de datos</string> + <!--AntennaPodSP--> + <string name="sp_apps_importing_feeds_msg">Importando as suscricións desde apps de propósito único...</string> + <string name="search_itunes_label">Buscar en iTunes</string> + <string name="filter">Filtrado</string> + <string name="search_fyyd_label">Buscar fyyd</string> + <!--Episodes apply actions--> + <string name="all_label">Todo</string> + <string name="selected_all_label">Seleccionar todos os episodios</string> + <string name="none_label">Ningún</string> + <string name="deselected_all_label">Todos os episodios deseleccionados</string> + <string name="played_label">Reproducidos</string> + <string name="selected_played_label">Episodios reproducidos seleccionados</string> + <string name="unplayed_label">Non reproducidos</string> + <string name="selected_unplayed_label">Episodios non reproducidos seleccionados</string> + <string name="downloaded_label">Descargados</string> + <string name="selected_downloaded_label">Episodios descargados seleccionados</string> + <string name="not_downloaded_label">Non descargados</string> + <string name="selected_not_downloaded_label">Episodios non descargados seleccionados</string> + <string name="queued_label">Na cola</string> + <string name="selected_queued_label">Seleccionados os episodios na cola</string> + <string name="not_queued_label">Fora da cola</string> + <string name="selected_not_queued_label">Seleccionados os episodios fora da cola</string> + <string name="has_media">Teñen medios</string> + <string name="selected_has_media_label">Seleccionados episodios que inclúen medios</string> + <!--Sort--> + <string name="sort_title_a_z">TÃtulo (A \u2192 Z)</string> + <string name="sort_title_z_a">TÃtulo (Z \u2192 A)</string> + <string name="sort_date_new_old">Data (Novo \u2192 Vello)</string> + <string name="sort_date_old_new">Data (Vello \u2192 Novo)</string> + <string name="sort_duration_short_long">Duración (Curto \u2192 Longo)</string> + <string name="sort_duration_long_short">Duración (Longo \u2192 Curto)</string> + <!--Rating dialog--> + <string name="rating_title">Gosta de AntennaPod?</string> + <string name="rating_message">AgradecerÃamos que dedicase un intre a valorar AntennaPod.</string> + <string name="rating_never_label">Pasa de min oh!</string> + <string name="rating_later_label">Lembrar máis tarde</string> + <string name="rating_now_label">Trato, fagámolo!</string> + <!--Audio controls--> + <string name="audio_controls">Controis de audio</string> + <string name="playback_speed">Velocidade de reprodución</string> + <string name="volume">Volume</string> + <string name="left_short">L</string> + <string name="right_short">R</string> + <string name="audio_effects">Efectos de son</string> + <string name="stereo_to_mono">Comprimir: stereo a mono</string> + <string name="sonic_only">Só Sonic</string> + <!--proxy settings--> + <string name="proxy_type_label">Tipo</string> + <string name="host_label">Servidor</string> + <string name="port_label">Porto</string> + <string name="optional_hint">(Optativo)</string> + <string name="proxy_test_label">Proba</string> + <string name="proxy_checking">Comprobando...</string> + <string name="proxy_test_successful">Proba exitosa</string> + <string name="proxy_test_failed">Fallo na proba</string> + <string name="proxy_host_empty_error">Servidor non pode quedar baldeiro</string> + <string name="proxy_host_invalid_error">O servidor indicado non é un dominio ou IP válidos</string> + <string name="proxy_port_invalid_error">Porto non válido</string> + <!--Casting--> + <string name="cast_media_route_menu_title">Reproducir en...</string> + <string name="cast_disconnect_label">Desconectar a sesión de emisión</string> + <string name="cast_not_castable">O medio seleccionado non é compatible co dispositivo de emisión</string> + <string name="cast_failed_to_play">Fallo no inicio da reprodución de medios</string> + <string name="cast_failed_to_stop">Non se puido deter a reprodución de medios</string> + <string name="cast_failed_to_pause">Non se puido pausar a reprodución de medios</string> + <!--<string name="cast_failed_to_connect">Could not connect to the device</string>--> + <string name="cast_failed_setting_volume">Non se puido establecer o volume</string> + <string name="cast_failed_no_connection">Non hai conexión ao dispositivo de emisión</string> + <string name="cast_failed_no_connection_trans">Perdeuse a conexión ao dispositivo de emisión. O aplicativo está a intentar restablecela se fose posible. Por favor, agarde uns segundos e inténteo de novo.</string> + <string name="cast_failed_perform_action">Non se puido completar a acción</string> + <string name="cast_failed_status_request">Fallo de sincronización co dispositivo de emisión</string> + <string name="cast_failed_seek">Non se puido cambiar a posición no dispositivo de emisión</string> + <string name="cast_failed_receiver_player_error">O reprodutor receptor atopou un fallo grave</string> + <string name="cast_failed_media_error_skipping">Fallo na reprodución de medios. Saltando...</string> +</resources> diff --git a/core/src/main/res/values-hi-rIN/strings.xml b/core/src/main/res/values-hi-rIN/strings.xml index 2d3bfb539..9e30ff59d 100644 --- a/core/src/main/res/values-hi-rIN/strings.xml +++ b/core/src/main/res/values-hi-rIN/strings.xml @@ -1,11 +1,8 @@ <?xml version='1.0' encoding='UTF-8'?> <resources xmlns:tools="http://schemas.android.com/tools"> <!--Activitiy and fragment titles--> - <string name="app_name"> à¤à¤¨à¥à¤Ÿà¥‡à¤¨à¤¾à¤ªà¥‰à¤¡</string> <string name="feeds_label">फिडà¥à¤¸</string> - <string name="podcasts_label">पॉडकासà¥à¤Ÿ</string> <string name="new_label">नया</string> - <string name="waiting_list_label">वेटिंग लिसà¥à¤Ÿ</string> <string name="settings_label">सेटिंगà¥à¤¸</string> <string name="add_new_feed_label">पॉडकासà¥à¤Ÿ जोड़ें</string> <string name="downloads_label">डाउनलोड</string> @@ -13,7 +10,6 @@ <string name="playback_history_label">पà¥à¤²à¥‡à¤¬à¥ˆà¤• इतिहास</string> <string name="gpodnet_main_label">gpodder.net</string> <string name="gpodnet_auth_label">gpodder.net login</string> - <!--New episodes fragment--> <!--Statistics fragment--> <!--Main activity--> <!--Webview actions--> @@ -56,7 +52,6 @@ <string name="remove_feed_label">पॉडकासà¥à¤Ÿ हटाà¤à¤ </string> <string name="share_link_label">शेयर वेबसाइट लिंक</string> - <string name="feed_delete_confirmation_msg">इसकी पà¥à¤·à¥à¤Ÿà¤¿ करें कि आप इस फ़ीड और इस फ़ीड के सà¤à¥€ पà¥à¤°à¤•à¤°à¤£à¥‹à¤‚ को हटाना चाहते हैं जिनà¥à¤¹à¥‡à¤‚ आपने डाउनलोड किया है.</string> <string name="feed_remover_msg">फ़ीड निकाल रहा है</string> <!--actions on feeditems--> <string name="download_label">डाउनलोड</string> @@ -70,8 +65,6 @@ <string name="remove_from_queue_label">क़तार से हटाà¤à¤</string> <string name="visit_website_label">वेबसाइट पर जाà¤à¤</string> <string name="support_label">इसे Flattr करें</string> - <string name="enqueue_all_new">पंकà¥à¤¤à¤¿ में सà¤à¥€ को डालें</string> - <string name="download_all">सà¤à¥€ डाउनलोड</string> <string name="skip_episode_label">à¤à¤ªà¤¿à¤¸à¥‹à¤¡ छोङें</string> <!--Download messages and labels--> <string name="download_successful">सफल @@ -111,7 +104,6 @@ <string name="playback_error_server_died">सरà¥à¤µà¤° निरसà¥à¤¤</string> <string name="playback_error_unknown">अजà¥à¤žà¤¾à¤¤ तà¥à¤°à¥à¤Ÿà¤¿</string> <string name="no_media_playing_label">मीडिया नहीं चल रहा</string> - <string name="position_default_label">00:00:00</string> <string name="player_buffering_msg">बफरिंग</string> <string name="playbackservice_notification_title">पà¥à¤²à¥‡à¤ˆà¤‚ग पॉडकासà¥à¤Ÿ</string> <!--Queue operations--> @@ -194,8 +186,6 @@ <string name="pref_gpodnet_sethostname_use_default_host">डिफ़ॉलà¥à¤Ÿ होसà¥à¤Ÿ का पà¥à¤°à¤¯à¥‹à¤— करें</string> <!--Auto-Flattr dialog--> <!--Search--> - <string name="search_hint">फ़ीड या à¤à¤ªà¤¿à¤¸à¥‹à¤¡ के लिठखोज</string> - <string name="found_in_shownotes_label">Shownotes में मिला</string> <string name="found_in_chapters_label">अधà¥à¤¯à¤¾à¤¯à¥‹à¤‚ में मिला</string> <string name="search_status_no_results">कोई परिणाम नहीं मिले</string> <string name="search_label">खोज</string> @@ -266,7 +256,11 @@ <!--Feed information screen--> <!--Progress information--> <!--AntennaPodSP--> + <!--Episodes apply actions--> + <!--Sort--> <!--Rating dialog--> <!--Audio controls--> <!--proxy settings--> + <!--Casting--> + <!--<string name="cast_failed_to_connect">Could not connect to the device</string>--> </resources> diff --git a/core/src/main/res/values-hu/strings.xml b/core/src/main/res/values-hu/strings.xml index 28dfeb6e8..91eef6144 100644 --- a/core/src/main/res/values-hu/strings.xml +++ b/core/src/main/res/values-hu/strings.xml @@ -1,15 +1,179 @@ <?xml version='1.0' encoding='UTF-8'?> <resources xmlns:tools="http://schemas.android.com/tools"> <!--Activitiy and fragment titles--> + <string name="feeds_label">IdÅ‘vonalak</string> + <string name="statistics_label">Statisztika</string> + <string name="add_feed_label">Podcast hozzáadása</string> + <string name="episodes_label">Epizódok</string> + <string name="all_episodes_short_label">Mind</string> + <string name="favorite_episodes_label">Kedvencek</string> + <string name="new_label">Új</string> + <string name="settings_label">BeállÃtások</string> + <string name="add_new_feed_label">Podcast hozzáadása</string> + <string name="downloads_label">Letöltések</string> + <string name="downloads_running_label">Futó</string> + <string name="downloads_completed_label">Befejezett</string> + <string name="downloads_log_label">Napló</string> + <string name="subscriptions_label">Feliratkozások</string> + <string name="subscriptions_list_label">Feliratkozások listája</string> + <string name="cancel_download_label">Letöltés megállÃtása</string> + <string name="playback_history_label">Lejátszási Napló</string> + <string name="gpodnet_main_label">gpodder.net</string> + <string name="gpodnet_auth_label">gpodder.net Bejelentkezés</string> + <string name="free_space_label">%1$s szabad</string> + <string name="episode_cache_full_title">Epizód tárhely megtelt</string> + <string name="episode_cache_full_message">Az epizódok tárolására megadott maximális tárhely megtelt. A méretét a \"BeállÃtások\" menüpontban tudod megnövelni.</string> <!--Statistics fragment--> + <string name="total_time_listened_to_podcasts">A lejátszott podcast-ok összideje:</string> + <string name="statistics_details_dialog">%1$d-ból %2$d epizód elindÃtva.\n\n%3$s-ból %4$s lejátszva.</string> <!--Main activity--> + <string name="drawer_open">Menü megnyitása</string> + <string name="drawer_close">Menü bezárása</string> + <string name="drawer_preferences">Oldalsáv beállÃtásai</string> + <string name="drawer_feed_order_unplayed_episodes">Rendezés számláló szerint</string> + <string name="drawer_feed_order_alphabetical">Rendezés ABC rendben</string> + <string name="drawer_feed_order_last_update">Rendezés megjelenés dátuma szerint</string> + <string name="drawer_feed_counter_new_unplayed">Új és nem játszott epizódok száma</string> + <string name="drawer_feed_counter_new">Új epizódok száma</string> + <string name="drawer_feed_counter_unplayed">Nem játszott epizódok száma</string> + <string name="drawer_feed_counter_downloaded">Letöltött epizódok száma</string> + <string name="drawer_feed_counter_none">Nincs</string> <!--Webview actions--> + <string name="open_in_browser_label">Megnyitás böngészÅ‘ben</string> + <string name="copy_url_label">URL másolása</string> + <string name="share_url_label">URL megosztása</string> + <string name="copied_url_msg">URL másolva a vásólapra</string> + <string name="go_to_position_label">Ugrás ehhez a pozÃcióhoz</string> <!--Playback history--> + <string name="clear_history_label">Napló törlése</string> <!--Other--> + <string name="confirm_label">MegerÅ‘sÃt</string> + <string name="cancel_label">Mégsem</string> + <string name="yes">Igen</string> + <string name="no">Nem</string> + <string name="reset">VisszaállÃtás</string> + <string name="author_label">SzerzÅ‘</string> + <string name="language_label">Nyelv</string> + <string name="url_label">URL</string> + <string name="podcast_settings_label">BeállÃtások</string> + <string name="cover_label">Kép</string> + <string name="error_label">Hiba</string> + <string name="error_msg_prefix">Hiba történt:</string> + <string name="refresh_label">FrissÃtés</string> + <string name="external_storage_error_msg">Nem található külsÅ‘ tárhely. BiztosÃts egy külsÅ‘ tárhelyet hogy az alkalmazás működni tudjon.</string> + <string name="chapters_label">Fejezetek</string> + <string name="shownotes_label">Jegyzetek</string> + <string name="description_label">LeÃrás</string> + <string name="most_recent_prefix">Legfrissebb epizód:\u0020</string> + <string name="episodes_suffix">\u0020epizód</string> + <string name="length_prefix">Hossz:\u0020</string> + <string name="size_prefix">Méret:\u0020</string> + <string name="processing_label">Feldolgozás</string> + <string name="loading_label">Betöltés...</string> + <string name="save_username_password_label">Felhasználónév és jelszó mentése</string> + <string name="close_label">Bezárás</string> + <string name="retry_label">Újra</string> + <string name="auto_download_label">Automatikus letöltésekhez hozzáfűzés</string> + <string name="auto_download_apply_to_items_title">Alkalmazás elÅ‘zÅ‘ epizódokra</string> + <string name="auto_download_apply_to_items_message">A beállÃtott <i>Automatikus letöltés</i> az új epizódokra érvényes.\nVonatkozzon a korábban kibocsátott epizódokra is?</string> + <string name="auto_delete_label">Epizód automatikus törlése</string> + <string name="parallel_downloads_suffix">\u0020párhuzamos letöltés</string> + <string name="feed_auto_download_global">Globális alapértelmezett</string> + <string name="feed_auto_download_always">Mindig</string> + <string name="feed_auto_download_never">Soha</string> + <string name="send_label">Küldés…</string> + <string name="episode_cleanup_never">Soha</string> + <string name="episode_cleanup_queue_removal">Ha nem várakozik</string> + <string name="episode_cleanup_after_listening">Befejezés után</string> + <plurals name="episode_cleanup_days_after_listening"> + <item quantity="one">1 nappal a befejezés után</item> + <item quantity="other">%d nappal a befejezés után</item> + </plurals> <!--'Add Feed' Activity labels--> + <string name="feedurl_label">IdÅ‘vonal URL</string> + <string name="etxtFeedurlHint">www.example.com/feed</string> + <string name="txtvfeedurl_label">Podcast hozzáadása URL alapján</string> + <string name="podcastdirectories_label">Podcast keresése mappában</string> + <string name="podcastdirectories_descr">Új podcastokat kereshetsz iTunes-on vagy fyyd-en, vagy a gpodder.net-en név, kategória vagy cÃm alapján.</string> + <string name="browse_gpoddernet_label">gpodder.net böngészése</string> <!--Actions on feeds--> + <string name="mark_all_read_label">Az összes megjelölése lejátszottként</string> + <string name="mark_all_read_msg">Az összes epizód lejátszottként megjelölve</string> + <string name="mark_all_read_confirmation_msg">Biztosan megjelölöd az összes epizódot lejátszottként?</string> + <string name="mark_all_read_feed_confirmation_msg">Biztosan megjelölöd az összes epizódot az idÅ‘vonalon lejátszottként?</string> + <string name="mark_all_seen_label">Az összes megjelölése megnézettként</string> + <string name="mark_all_seen_msg">Az összes epizód megnézettként megjelölve</string> + <string name="mark_all_seen_confirmation_msg">Biztosan megjelölöd az összes epizódott megnézettként?</string> + <string name="show_info_label">Információ mutatása</string> + <string name="rename_feed_label">Podcast átnevezése</string> + <string name="remove_feed_label">Podcast eltávolÃtása</string> + <string name="share_label">Megosztás…</string> + <string name="share_link_label">Link megosztása</string> + <string name="share_link_with_position_label">Link megosztása pozÃcióval</string> + <string name="share_feed_url_label">IdÅ‘vonal URL megosztása</string> + <string name="share_item_url_label">Epizód fájl URL megosztása</string> + <string name="share_item_url_with_position_label">Epizód fájl URL megosztása pozÃcióval</string> + <string name="feed_remover_msg">IdÅ‘vonal eltávolÃtása</string> + <string name="load_complete_feed">Teljes idÅ‘vonal frissÃtése</string> + <string name="hide_episodes_title">Epizódok elrejtése</string> + <string name="episode_actions">Műveletek alkalmazása</string> + <string name="hide_unplayed_episodes_label">Nem lejátszott</string> + <string name="hide_paused_episodes_label">Szüneteltetett</string> + <string name="hide_played_episodes_label">Lejátszott</string> + <string name="hide_queued_episodes_label">Várakozó</string> + <string name="hide_not_queued_episodes_label">Nem várakozó</string> + <string name="hide_downloaded_episodes_label">Letöltött</string> + <string name="hide_not_downloaded_episodes_label">Nem letöltött</string> + <string name="hide_has_media_label">További tartalma van</string> + <string name="filtered_label">Szűrt</string> + <string name="refresh_failed_msg">{fa-exclamation-circle} A legutóbbi frissÃtés sikertelen</string> + <string name="open_podcast">Podcast megnyitása</string> <!--actions on feeditems--> + <string name="download_label">Letöltés</string> + <string name="play_label">Lejátszás</string> + <string name="pause_label">Szüneteltetés</string> + <string name="stop_label">MegállÃtás</string> + <string name="stream_label">Stream-elés</string> + <string name="remove_label">EltávolÃtás</string> + <string name="delete_label">Törlés</string> + <string name="remove_episode_lable">Epizód eltávolÃtása</string> + <string name="marked_as_seen_label">Megtekintettként megjelölve</string> + <string name="mark_read_label">Lejátszottként megjelölés</string> + <string name="marked_as_read_label">Lejátszottként megjelölve</string> + <string name="mark_unread_label">Nem lejátszottként megjelölés</string> + <string name="add_to_queue_label">Várakozási sorhoz adás</string> + <string name="added_to_queue_label">Várakozási sorhoz adva</string> + <string name="remove_from_queue_label">Várakozási sorból eltávolÃtás</string> + <string name="add_to_favorite_label">Kedvencekhez adás</string> + <string name="added_to_favorites">Kedvencekhez adva</string> + <string name="remove_from_favorite_label">KedvencekbÅ‘l eltávolÃtás</string> + <string name="removed_from_favorites">KedvencekbÅ‘l eltávolÃtva</string> + <string name="visit_website_label">Honlap megtekintése</string> + <string name="support_label">Flattr-ezés</string> + <string name="skip_episode_label">Epizód átugrása</string> + <string name="activate_auto_download">Automatikus letöltés bekapcsolása</string> + <string name="deactivate_auto_download">Automatikus letöltés kikapcsolása</string> + <string name="reset_position">Lejátszási pozÃció visszaállÃtása</string> + <string name="removed_item">Elem eltávolÃtva</string> <!--Download messages and labels--> + <string name="download_successful">sikeres</string> + <string name="download_failed">sikertelen</string> + <string name="download_pending">Letöltés várakozik</string> + <string name="download_running">Letöltés fut</string> + <string name="download_error_device_not_found">Táreszköz nem található</string> + <string name="download_error_insufficient_space">Túl kevés tárhely</string> + <string name="download_error_file_error">Fájl Hiba</string> + <string name="download_error_http_data_error">HTTP Adat Hiba</string> + <string name="download_error_error_unknown">Ismeretlen Hiba</string> + <string name="download_error_parser_exception">ÉrtelmezÅ‘ Kivétel</string> + <string name="download_error_unsupported_type">Nem Támogatott IdÅ‘vonal TÃpus</string> + <string name="download_error_connection_error">Kapcsolódási Hiba</string> + <string name="download_error_unknown_host">Ismeretlen Hoszt</string> + <string name="download_error_unauthorized">AzonosÃtási Hiba</string> + <string name="download_error_file_type_type">Fájl TÃpus Hiba</string> + <string name="download_error_forbidden">Tiltott</string> + <string name="cancel_all_downloads_label">Az összes letöltés visszavonása</string> + <string name="download_canceled_msg">Letöltés visszavonva</string> <!--Mediaplayer messages--> <!--Queue operations--> <!--Flattr--> diff --git a/core/src/main/res/values-id/strings.xml b/core/src/main/res/values-id/strings.xml index 383605ded..743812a58 100644 --- a/core/src/main/res/values-id/strings.xml +++ b/core/src/main/res/values-id/strings.xml @@ -95,7 +95,6 @@ <string name="pref_update_interval_hours_singular">jam</string> <string name="pref_gpodnet_authenticate_title">Masuk</string> <string name="pref_gpodnet_logout_title">Keluar</string> - <string name="pref_gpodnet_sync_title">Sinkronkan sekarang</string> <string name="pref_gpodnet_sync_started">Sinkronkan dimulai</string> <!--Auto-Flattr dialog--> <!--Search--> diff --git a/core/src/main/res/values-is-rIS/strings.xml b/core/src/main/res/values-is-rIS/strings.xml new file mode 100644 index 000000000..28dfeb6e8 --- /dev/null +++ b/core/src/main/res/values-is-rIS/strings.xml @@ -0,0 +1,38 @@ +<?xml version='1.0' encoding='UTF-8'?> +<resources xmlns:tools="http://schemas.android.com/tools"> + <!--Activitiy and fragment titles--> + <!--Statistics fragment--> + <!--Main activity--> + <!--Webview actions--> + <!--Playback history--> + <!--Other--> + <!--'Add Feed' Activity labels--> + <!--Actions on feeds--> + <!--actions on feeditems--> + <!--Download messages and labels--> + <!--Mediaplayer messages--> + <!--Queue operations--> + <!--Flattr--> + <!--Flattr--> + <!--Variable Speed--> + <!--Empty list labels--> + <!--Preferences--> + <!--Auto-Flattr dialog--> + <!--Search--> + <!--OPML import and export--> + <!--Sleep timer--> + <!--gpodder.net--> + <!--Directory chooser--> + <!--Online feed view--> + <!--Content descriptions for image buttons--> + <!--Feed information screen--> + <!--Progress information--> + <!--AntennaPodSP--> + <!--Episodes apply actions--> + <!--Sort--> + <!--Rating dialog--> + <!--Audio controls--> + <!--proxy settings--> + <!--Casting--> + <!--<string name="cast_failed_to_connect">Could not connect to the device</string>--> +</resources> diff --git a/core/src/main/res/values-it-rIT/strings.xml b/core/src/main/res/values-it-rIT/strings.xml index b52ccc5fa..4d4e44bff 100644 --- a/core/src/main/res/values-it-rIT/strings.xml +++ b/core/src/main/res/values-it-rIT/strings.xml @@ -20,6 +20,7 @@ <string name="playback_history_label">Cronologia delle riproduzioni</string> <string name="gpodnet_main_label">gpodder.net</string> <string name="gpodnet_auth_label">gpodder.net login</string> + <string name="free_space_label">%1$s disponibili</string> <string name="episode_cache_full_title">Cache degli episodi piena</string> <string name="episode_cache_full_message">Il limite della cache degli episodi è stato raggiunto. Puoi incrementare la dimensione della cache nelle Impostazioni.</string> <!--Statistics fragment--> @@ -28,11 +29,13 @@ <!--Main activity--> <string name="drawer_open">Apri il menù</string> <string name="drawer_close">Chiudi il menù</string> + <string name="drawer_preferences">Preferenze Cassetto</string> <string name="drawer_feed_order_alphabetical">Ordina alfabeticamente</string> <string name="drawer_feed_order_last_update">Ordina per data di pubblicazione</string> <string name="drawer_feed_counter_new_unplayed">Numero di episodi nuovi e non riprodotti</string> <string name="drawer_feed_counter_new">Numero di episodi nuovi</string> <string name="drawer_feed_counter_unplayed">Numero di episodi non riprodotti</string> + <string name="drawer_feed_counter_downloaded">Numero di episodi scaricati</string> <string name="drawer_feed_counter_none">Nessuno</string> <!--Webview actions--> <string name="open_in_browser_label">Apri nel browser</string> @@ -70,6 +73,7 @@ <string name="retry_label">Riprova</string> <string name="auto_download_label">Includi nei download automatici</string> <string name="auto_download_apply_to_items_title">Applica ai Precedenti Episodi</string> + <string name="auto_download_apply_to_items_message">La nuova funzione <i>Auto Download</i> sarà applicata automaticamente ai nuovi episodi.\nVuoi attivarla anche per gli episodi pubblicati precedentemente?</string> <string name="auto_delete_label">Elimina Episodi Automaticamente</string> <string name="parallel_downloads_suffix">\u0020download paralleli</string> <string name="feed_auto_download_always">Sempre</string> @@ -86,7 +90,6 @@ <string name="etxtFeedurlHint">www.example.com/feed</string> <string name="txtvfeedurl_label">Aggiungi un Podcast tramite URL</string> <string name="podcastdirectories_label">Trova un podcast nella directory</string> - <string name="podcastdirectories_descr">Puoi cercare dei nuovi podcast in base al nome, alla categoria o alla popolarità nella directory di gpodder.net.</string> <string name="browse_gpoddernet_label">Esplora gpodder.net</string> <!--Actions on feeds--> <string name="mark_all_read_label">Segna tutti come riprodotti</string> @@ -95,14 +98,14 @@ <string name="mark_all_read_feed_confirmation_msg">Per favore conferma che vuoi segnare tutti gli episodi di questo feed come riprodotti.</string> <string name="mark_all_seen_label">Segna tutti come visti</string> <string name="show_info_label">Informazioni</string> - <string name="remove_feed_label">Rimuovi un podcast</string> + <string name="rename_feed_label">Rinomina Podcast</string> + <string name="remove_feed_label">Rimuovi podcast</string> <string name="share_label">Condividi...</string> <string name="share_link_label">Condividi il link al sito</string> <string name="share_link_with_position_label">Condividi il Link con la Posizione</string> <string name="share_feed_url_label">Condividi URL del Feed</string> <string name="share_item_url_label">Condividi URL del File dell\'episodio</string> <string name="share_item_url_with_position_label">Condividi l\'URL del File dell\'epsiodio con la Posizione</string> - <string name="feed_delete_confirmation_msg">Per favore conferma la cancellazione di questo feed e di TUTTI gli episodi collegati che sono stati precedentemente scaricati.</string> <string name="feed_remover_msg">Rimozione feed</string> <string name="load_complete_feed">Ricarica il feed completo</string> <string name="hide_episodes_title">Nascondi gli episodi</string> @@ -124,7 +127,9 @@ <string name="stop_label">Ferma</string> <string name="stream_label">Stream</string> <string name="remove_label">Rimuovi</string> + <string name="delete_label">Elimina</string> <string name="remove_episode_lable">Rimuovi l\'episodio</string> + <string name="marked_as_seen_label">Segna come visto</string> <string name="mark_read_label">Segna come riprodotto</string> <string name="marked_as_read_label">Segnato come riprodotto</string> <string name="mark_unread_label">Segna come non riprodotto</string> @@ -207,11 +212,13 @@ <string name="move_to_top_label">Sposta all\'inizio</string> <string name="move_to_bottom_label">Sposta in fondo</string> <string name="sort">Ordina</string> - <string name="alpha">Alfabeticamente</string> <string name="date">Per data</string> <string name="duration">Per durata</string> + <string name="episode_title">Titolo episodio</string> + <string name="feed_title">Titolo feed</string> <string name="ascending">In ordine crescente</string> <string name="descending">In ordine decrescente</string> + <string name="clear_queue_confirmation_msg">Per favore conferma che vuoi rimuovere dalla coda TUTTI gli episodi in essa presenti.</string> <!--Flattr--> <string name="flattr_auth_label">Accesso a Flattr</string> <string name="flattr_auth_explanation">Premi il tasto seguente per iniziare il processo di autenticazione. Sarai trasferito alla pagina di login di flattr sul tuo browser e ti sarà richiesto di garantire ad AntennaPod il permesso di effettuare microdonazioni. Dopo la tua autorizzazione, sarai riportato alla seguente schermata in modo automatico.</string> @@ -248,6 +255,7 @@ <string name="no_feeds_label">Non sei ancora abbonato a nessun feed.</string> <string name="no_chapters_label">Questo episodio non ha capitoli.</string> <!--Preferences--> + <string name="storage_pref">Memoria</string> <string name="project_pref">Progetto</string> <string name="other_pref">Altro</string> <string name="about_pref">Informazioni</string> @@ -258,6 +266,7 @@ <string name="pref_followQueue_sum">Passa al prossimo episodio in coda quanto si completa una riproduzione</string> <string name="pref_auto_delete_sum">Elimina l\'episodio quando viene completata la riproduzione</string> <string name="pref_auto_delete_title">Elimina automaticamente</string> + <string name="pref_skip_keeps_episodes_title">Manteni gli Episodi Saltati</string> <string name="playback_pref">Riproduzione</string> <string name="network_pref">Rete</string> <string name="pref_autoUpdateIntervallOrTime_Disable">Disabilita</string> @@ -269,6 +278,7 @@ <string name="pref_downloadMediaOnWifiOnly_title">Download dei media su WiFi</string> <string name="pref_pauseOnHeadsetDisconnect_title">Disconnessione cuffie</string> <string name="pref_unpauseOnHeadsetReconnect_title">Riconnetti le cuffie</string> + <string name="pref_unpauseOnBluetoothReconnect_title">Riconnessione Bluetooth</string> <string name="pref_mobileUpdate_title">Update su rete mobile</string> <string name="pref_mobileUpdate_sum">Permetti gli aggiornamenti tramite connessione dati mobile</string> <string name="refreshing_label">Aggiornamento</string> @@ -283,6 +293,7 @@ <string name="pref_auto_flattr_sum">Configura l\'esecuzione automatica di Flattr</string> <string name="user_interface_label">Interfaccia utente</string> <string name="pref_set_theme_title">Seleziona il tema</string> + <string name="pref_nav_drawer_feed_order_title">Imposta l\'ordine delle Iscrizioni</string> <string name="pref_set_theme_sum">Cambia l\'aspetto di AntennaPod</string> <string name="pref_automatic_download_title">Download automatico</string> <string name="pref_automatic_download_sum">Configura il download automatico degli episodi</string> @@ -304,7 +315,6 @@ <string name="pref_gpodnet_logout_toast">Logout effettuato</string> <string name="pref_gpodnet_setlogin_information_title">Cambia le informazioni di login</string> <string name="pref_gpodnet_setlogin_information_sum">Cambia le informazioni di login per il tuo account gpodder.net.</string> - <string name="pref_gpodnet_sync_title">Sincronizza ora</string> <string name="pref_gpodnet_sync_started">Sincronizzazione avviata</string> <string name="pref_playback_speed_title">Velocità di riproduzione</string> <string name="pref_playback_speed_sum">Personalizza le velocità disponibili per la riproduzione audio a velocità variabile</string> @@ -331,8 +341,6 @@ <string name="auto_flattr_ater_beginning">Carica l\'episodio su Flattr appena comincia la riproduzione</string> <string name="auto_flattr_ater_end">Carica l\'episodio su Flattr appena finisce la riproduzione</string> <!--Search--> - <string name="search_hint">Cerca dei feed o degli episodi</string> - <string name="found_in_shownotes_label">Trovato nelle note dell\'episodio</string> <string name="found_in_chapters_label">Trovato nei capitoli</string> <string name="search_status_no_results">Nessun risultato trovato</string> <string name="search_label">Ricerca</string> @@ -468,6 +476,8 @@ <string name="rating_later_label">Ricordamelo più tardi</string> <!--Audio controls--> <string name="volume">Volume</string> + <string name="left_short">L</string> + <string name="right_short">R</string> <string name="audio_effects">Effetti Audio</string> <!--proxy settings--> <string name="proxy_type_label">Tipo</string> diff --git a/core/src/main/res/values-it/strings.xml b/core/src/main/res/values-it/strings.xml index 52f84a143..2549a5bac 100644 --- a/core/src/main/res/values-it/strings.xml +++ b/core/src/main/res/values-it/strings.xml @@ -2,6 +2,7 @@ <resources xmlns:tools="http://schemas.android.com/tools"> <!--Activitiy and fragment titles--> <string name="feeds_label">Feed</string> + <string name="statistics_label">Statistiche</string> <string name="add_feed_label">Aggiungi un podcast</string> <string name="episodes_label">Episodi</string> <string name="all_episodes_short_label">Tutto</string> @@ -13,10 +14,13 @@ <string name="downloads_running_label">In corso</string> <string name="downloads_completed_label">Completati</string> <string name="downloads_log_label">Registro</string> + <string name="subscriptions_label">Sottoscrizioni</string> + <string name="subscriptions_list_label">Elenco delle sottoscrizioni</string> <string name="cancel_download_label">Annulla\nil download</string> <string name="playback_history_label">Cronologia delle riproduzioni</string> <string name="gpodnet_main_label">gpodder.net</string> <string name="gpodnet_auth_label">Accesso a gpodder.net</string> + <string name="free_space_label">%1$s liberi</string> <!--Statistics fragment--> <!--Main activity--> <string name="drawer_open">Apri il menù</string> @@ -29,7 +33,9 @@ <string name="open_in_browser_label">Apri nel browser</string> <string name="copy_url_label">Copia l\'URL</string> <string name="share_url_label">Condividi l\'URL</string> + <string name="go_to_position_label">Vai a questa posizione</string> <!--Playback history--> + <string name="clear_history_label">Pulisci la cronologia</string> <!--Other--> <string name="confirm_label">Conferma</string> <string name="cancel_label">Annulla</string> @@ -44,11 +50,13 @@ <string name="error_msg_prefix">È avvenuto un errore:</string> <string name="refresh_label">Ricarica</string> <string name="chapters_label">Capitoli</string> + <string name="chapter_duration">Durata: %1$s</string> <string name="description_label">Descrizione</string> <string name="episodes_suffix">\u0020episodi</string> <string name="length_prefix">Lunghezza:\u0020</string> <string name="size_prefix">Dimensione:\u0020</string> <string name="processing_label">Processando</string> + <string name="loading_label">Caricamento in corso...</string> <string name="save_username_password_label">Salva il nome utente e la password</string> <string name="close_label">Chiudi</string> <string name="retry_label">Riprova</string> @@ -57,6 +65,7 @@ <string name="parallel_downloads_suffix">\u0020download paralleli</string> <string name="feed_auto_download_always">Sempre</string> <string name="feed_auto_download_never">Mai</string> + <string name="send_label">Invia...</string> <string name="episode_cleanup_never">Mai</string> <string name="episode_cleanup_after_listening">Dopo il completamento</string> <plurals name="episode_cleanup_days_after_listening"> @@ -67,14 +76,12 @@ <string name="feedurl_label">URL del feed</string> <string name="etxtFeedurlHint">www.example.com/feed</string> <string name="txtvfeedurl_label">Aggiungi un podcast inserendo un URL</string> - <string name="podcastdirectories_descr">Puoi cercare nuovi podcast per nome, categoria o popolarità su gpodder.net, oppure sull\'iTunes store.</string> <string name="browse_gpoddernet_label">Esplora gpodder.net</string> <!--Actions on feeds--> <string name="mark_all_read_label">Segna tutti come riprodotti</string> <string name="mark_all_read_confirmation_msg">Conferma che desideri segnare tutti gli episodi come riprodotti.</string> <string name="mark_all_read_feed_confirmation_msg">Conferma che desideri segnare tutti gli episodi in questo feed come riprodotti.</string> <string name="show_info_label">Mostra delle informazioni</string> - <string name="feed_delete_confirmation_msg">Conferma che desideri cancellare questo feed e TUTTI gli episodi di questo feed che hai scaricato.</string> <string name="hide_episodes_title">Nascondi gli episodi</string> <string name="episode_actions">Applica le azioni</string> <string name="hide_unplayed_episodes_label">Non riprodotti</string> @@ -137,7 +144,6 @@ <string name="move_to_top_label">Sposta in cima</string> <string name="move_to_bottom_label">Sposta in fondo</string> <string name="sort">Ordina</string> - <string name="alpha">In ordine alfabetico</string> <string name="date">Data</string> <string name="duration">Durata</string> <string name="ascending">Ascendente</string> @@ -195,7 +201,6 @@ <string name="pref_smart_mark_as_played_disabled">Disabilitato</string> <!--Auto-Flattr dialog--> <!--Search--> - <string name="search_hint">Cerca dei feed o degli episodi</string> <string name="found_in_chapters_label">Trovato nei capitoli</string> <string name="search_status_no_results">Nessun risultato trovato</string> <string name="search_label">Cerca</string> @@ -214,6 +219,19 @@ <string name="sleep_timer_label">Timer per lo spegnimento</string> <string name="time_left_label">Tempo rimasto:\u0020</string> <string name="time_dialog_invalid_input">Input non valido, il tempo deve essere un numero intero</string> + <plurals name="time_seconds_quantified"> + <item quantity="one">1 secondo</item> + <item quantity="other">%d secondi</item> + </plurals> + <plurals name="time_minutes_quantified"> + <item quantity="one">1 minuto</item> + <item quantity="other">%d minuti</item> + </plurals> + <plurals name="time_hours_quantified"> + <item quantity="one">1 ora</item> + <item quantity="other">%d ore</item> + </plurals> + <string name="auto_enable_label">Abilita automaticamente</string> <!--gpodder.net--> <string name="gpodnet_taglist_header">CATEGORIE</string> <string name="gpodnet_toplist_header">PODCAST PIÙ POPOLARI</string> @@ -247,11 +265,15 @@ <string name="create_folder_error_no_write_access">Non è possibile scrivere in questa cartella</string> <string name="create_folder_error_already_exists">La cartella esiste già </string> <string name="create_folder_error">Non è stato possibile creare la cartella</string> + <string name="folder_does_not_exist_error">\"%1$s\" non esiste</string> + <string name="folder_not_readable_error">\"%1$s\" non è leggibile</string> + <string name="folder_not_writable_error">\"%1$s\" non è scrivibile</string> <string name="folder_not_empty_dialog_title">La cartella non è vuota</string> <string name="set_to_default_folder">Scegli la cartella predefinita</string> <!--Online feed view--> <string name="subscribe_label">Abbonati</string> <string name="subscribed_label">Abbonato</string> + <string name="downloading_label">Download in corso...</string> <!--Content descriptions for image buttons--> <string name="rewind_label">Riavvolgi</string> <string name="fast_forward_label">Avanti veloce</string> @@ -262,15 +284,47 @@ <string name="load_next_page_label">Carica la pagina successiva</string> <!--Feed information screen--> <string name="authentication_label">Autenticazione</string> + <string name="episode_filters_include">Includi</string> + <string name="episode_filters_exclude">Escludi</string> + <string name="keep_updated">Tieni aggiornato</string> <!--Progress information--> <!--AntennaPodSP--> <string name="search_itunes_label">Cerca su iTunes</string> <!--Episodes apply actions--> <string name="all_label">Tutto</string> + <string name="none_label">Nessuno</string> + <string name="deselected_all_label">De-seleziona tutti gli episodi</string> + <string name="played_label">Riprodotti</string> + <string name="selected_played_label">Selezionati gli episodi riprodotti</string> + <string name="unplayed_label">Non riprodotti</string> + <string name="selected_unplayed_label">Selezionati gli episodi non riprodotti</string> + <string name="downloaded_label">Scaricati</string> + <string name="selected_downloaded_label">Selezionati gli episodi scaricati</string> + <string name="not_downloaded_label">Non scaricati</string> + <string name="selected_not_downloaded_label">Selezionati gli episodi non scaricati</string> + <string name="queued_label">In coda</string> + <string name="selected_queued_label">Selezionati gli episodi in coda</string> + <string name="not_queued_label">Non in coda</string> + <string name="selected_not_queued_label">Selezionati gli episodi non in coda</string> + <string name="selected_has_media_label">Selezionati gli episodi con elementi multimediali</string> <!--Sort--> + <string name="sort_title_a_z">Titolo (A \u2192 Z)</string> + <string name="sort_title_z_a">Titolo (Z \u2192 A)</string> + <string name="sort_date_new_old">Data (Nuovi \u2192 Vecchi)</string> + <string name="sort_date_old_new">Data (Vecchi \u2192 Nuovi)</string> <!--Rating dialog--> + <string name="rating_title">Ti piace AntennaPod?</string> + <string name="rating_later_label">Ricordamelo più tardi</string> <!--Audio controls--> + <string name="audio_controls">Controlli audio</string> + <string name="playback_speed">Velocità di riproduzione</string> + <string name="volume">Volume</string> <!--proxy settings--> + <string name="proxy_type_label">Tipo</string> + <string name="proxy_test_label">Test</string> + <string name="proxy_checking">Controllo in corso...</string> + <string name="proxy_test_successful">Test avvenuto con successo</string> + <string name="proxy_test_failed">Test fallito</string> <!--Casting--> <!--<string name="cast_failed_to_connect">Could not connect to the device</string>--> </resources> diff --git a/core/src/main/res/values-iw-rIL/strings.xml b/core/src/main/res/values-iw-rIL/strings.xml index a8d1ddfc5..9a835b9f0 100644 --- a/core/src/main/res/values-iw-rIL/strings.xml +++ b/core/src/main/res/values-iw-rIL/strings.xml @@ -1,16 +1,13 @@ <?xml version='1.0' encoding='UTF-8'?> <resources xmlns:tools="http://schemas.android.com/tools"> <!--Activitiy and fragment titles--> - <string name="app_name">×× ×˜× ×”-פוד</string> <string name="feeds_label">×”×–× ×•×ª</string> + <string name="statistics_label">סטטיסטיקות</string> <string name="add_feed_label">הוסף פודק×סט</string> - <string name="podcasts_label">פודק×סטי×</string> <string name="episodes_label">פרקי×</string> - <string name="new_episodes_label">×¤×¨×§×™× ×—×“×©×™×</string> - <string name="all_episodes_label">כל הפרקי×</string> + <string name="all_episodes_short_label">הכל</string> <string name="favorite_episodes_label">מועדפי×</string> <string name="new_label">חדש</string> - <string name="waiting_list_label">רשימת ×”×ž×ª× ×”</string> <string name="settings_label">הגדרות</string> <string name="add_new_feed_label">הוסף פודק×סט</string> <string name="downloads_label">הורדות</string> @@ -21,13 +18,13 @@ <string name="playback_history_label">היסטוריית × ×™×’×•×Ÿ</string> <string name="gpodnet_main_label">gpodder.net</string> <string name="gpodnet_auth_label">התחברות ×ל gpodder.net</string> - <!--New episodes fragment--> - <string name="recently_published_episodes_label">×¤×•×¨×¡× ×œ××—×¨×•× ×”</string> - <string name="episode_filter_label">הצג רק ×¤×¨×§×™× ×—×“×©×™×</string> <!--Statistics fragment--> <!--Main activity--> <string name="drawer_open">פתח תפריט</string> <string name="drawer_close">סגור תפריט</string> + <string name="drawer_feed_order_alphabetical">מיין בסדר ×לפביתי</string> + <string name="drawer_feed_order_last_update">מיין לפי ת×ריך פרסו×</string> + <string name="drawer_feed_order_most_played">מיין לפי מספר ×¤×¨×§×™× ×©×”×•×©×ž×¢×• </string> <!--Webview actions--> <string name="open_in_browser_label">פתח בדפדפן</string> <string name="copy_url_label">העתק כתובת ×תר</string> @@ -43,6 +40,7 @@ <string name="no">ל×</string> <string name="author_label">מחבר</string> <string name="language_label">שפה</string> + <string name="url_label">כתובת</string> <string name="podcast_settings_label">הגדרות</string> <string name="cover_label">×ª×ž×•× ×”</string> <string name="error_label">שגי××”</string> @@ -57,34 +55,43 @@ <string name="length_prefix">×ורך:\u0020</string> <string name="size_prefix">גודל:\u0020</string> <string name="processing_label">מעבד</string> + <string name="loading_label">טוען...</string> <string name="save_username_password_label">שמור ×©× ×ž×©×ª×ž×© וססמה</string> <string name="close_label">סגור</string> <string name="retry_label">× ×¡×” שוב</string> <string name="auto_download_label">כלול בהורדות ×וטומטיות</string> - <string name="auto_delete_label">מחק ל×חר ההשמעה\n(גובר על ההגדרה הגלובלית)</string> <string name="parallel_downloads_suffix">\u0020הורדות במקביל</string> - <string name="feed_auto_download_global">לפי הגדרה גלובלית</string> <string name="feed_auto_download_always">תמיד</string> <string name="feed_auto_download_never">××£ פע×</string> + <string name="send_label">שלח...</string> <string name="episode_cleanup_never">××£ פע×</string> + <string name="episode_cleanup_after_listening">×חרי סיו×</string> + <plurals name="episode_cleanup_days_after_listening"> + <item quantity="one">×™×•× ×חרי סיו×</item> + <item quantity="other">%d ×™×ž×™× ×œ×חר ×¡×™×•× </item> + </plurals> <!--'Add Feed' Activity labels--> <string name="feedurl_label">כתובת ×”×–× ×”</string> <string name="etxtFeedurlHint">כתובת של ×”×–× ×” ×ו ×תר ××™× ×˜×¨× ×˜</string> <string name="txtvfeedurl_label">הוסף פודק×סט לפי כתובת ×תר</string> <string name="podcastdirectories_label">חפש פודק×סט בספריה</string> - <string name="podcastdirectories_descr">×פשר לחפש ×¤×•×“×§×¡×˜×™× ×—×“×©×™× ×œ×¤×™ בש×, קטגוריה ×ו פופולריות בספריית gpodder.net.</string> <string name="browse_gpoddernet_label">עיין בgpodder.net</string> <!--Actions on feeds--> <string name="mark_all_read_label">סמן הכל ×›× ×§×¨×</string> <string name="mark_all_read_msg">סמן ×ת כל ×”×¤×¨×§×™× ×›× ×§×¨×</string> <string name="mark_all_read_confirmation_msg">×× × ×שר ש×תה רוצה לסמן ×ת כל ×¤×¨×§×™× ×›× ×§×¨××™×.</string> <string name="mark_all_read_feed_confirmation_msg">×× × ×שר ש×תה רוצה לסמן ×ת כל ×¤×¨×§×™× ×‘×”×–× ×” זו ×›× ×§×¨××™×.</string> + <string name="mark_all_seen_label">סמן ×ת ×›×•×œ× ×›× ×¨×ו</string> + <string name="mark_all_seen_msg">סמן ×ת כל ×”×¤×¨×§×™× ×›× ×¨×ו</string> + <string name="mark_all_seen_confirmation_msg">×× × ×שר ש×תה רוצה לסמן ×ת כל ×¤×¨×§×™× ×›× ×¨×ו.</string> <string name="show_info_label">הצג מידע</string> + <string name="rename_feed_label">×©× ×” ×©× ×¤×•×“×§×סט</string> <string name="remove_feed_label">הסר פודק×סט</string> + <string name="share_label">שתף...</string> <string name="share_link_label">שתף קישור ×תר</string> - <string name="feed_delete_confirmation_msg">×שר מחיקת ×”×–× ×” זו ו×ת כל פרקי ×”×”×–× ×” שהורדת.</string> <string name="feed_remover_msg">הסר ×”×–× ×”</string> <string name="load_complete_feed">×¨×¢× ×Ÿ ×ת כל ×”×”×–× ×”</string> + <string name="hide_episodes_title">הסתר פרקי×</string> <!--actions on feeditems--> <string name="download_label">הורד</string> <string name="play_label">× ×’×Ÿ</string> @@ -102,8 +109,6 @@ <string name="add_to_favorite_label">התווסף למועדפי×</string> <string name="visit_website_label">בקר ב×תר</string> <string name="support_label">×ª×¨×•× ×‘×מצעות Flattr</string> - <string name="enqueue_all_new">×”×›× ×¡ לתור הכל</string> - <string name="download_all">הורד הכל</string> <string name="skip_episode_label">דלג על הפרק</string> <!--Download messages and labels--> <string name="download_successful">הצלחה</string> @@ -146,7 +151,6 @@ <string name="playback_error_server_died">שרת מת</string> <string name="playback_error_unknown">שגי××” ×œ× ×™×“×•×¢×”</string> <string name="no_media_playing_label">מדיה ×œ× ×ž×ª× ×’× ×ª</string> - <string name="position_default_label">00:00:00</string> <string name="player_buffering_msg">×ž×ž×œ× ×—×•×¦×¥</string> <string name="playbackservice_notification_title">×ž× ×’×Ÿ פודק×סט</string> <string name="unknown_media_key">×× ×˜× ×”-פוד - מפתח מדיה ×œ× ×™×“×•×¢: %1$d</string> @@ -157,7 +161,6 @@ <string name="move_to_top_label">העבר למעלה</string> <string name="move_to_bottom_label">העבר למטה</string> <string name="sort">מיין</string> - <string name="alpha">בסדר ×לפביתי</string> <string name="date">ת×ריך</string> <string name="duration">משך</string> <string name="ascending">בסדר עולה</string> @@ -265,8 +268,6 @@ <string name="auto_flattr_ater_beginning">×ª×¨×•× ×‘×מצעות flattr ×›×©× ×™×’×•×Ÿ פרק מתחיל</string> <string name="auto_flattr_ater_end">×ª×¨×•× ×‘×מצעות flattr ×›×©× ×™×’×•×Ÿ פרק מסתיי×</string> <!--Search--> - <string name="search_hint">חפש ×”×–× ×•×ª ×ו פרקי×</string> - <string name="found_in_shownotes_label">× ×ž×¦× ×‘×”×¢×¨×•×ª פרק</string> <string name="found_in_chapters_label">× ×ž×¦× ×‘×¤×¨×§×™×</string> <string name="search_status_no_results">×ין תוצ×ות</string> <string name="search_label">חיפוש</string> @@ -341,22 +342,13 @@ <string name="subscribe_label">הרש×</string> <string name="subscribed_label">× ×¨×©×</string> <!--Content descriptions for image buttons--> - <string name="show_chapters_label">הצג פרקי×</string> - <string name="show_shownotes_label">הצג הערות פרק</string> - <string name="show_cover_label">הצג ×ª×ž×•× ×”</string> <string name="rewind_label">דלג ל×חור</string> <string name="fast_forward_label">הרץ קדימה</string> <string name="media_type_audio_label">שמע</string> <string name="media_type_video_label">ויד×ו</string> <string name="navigate_upwards_label">× ×•×•×˜ למעלה</string> - <string name="butAction_label">עוד פעולות</string> - <string name="status_playing_label">הפרק ×ž×ª× ×’×Ÿ</string> <string name="status_downloading_label">הפרק יורד</string> - <string name="status_downloaded_label">הפרק ירד</string> - <string name="status_unread_label">פריט חדש</string> <string name="in_queue_label">הפרק בתור</string> - <string name="new_episodes_count_label">מספר ×”×¤×¨×§×™× ×”×—×“×©×™×</string> - <string name="in_progress_episodes_count_label">מספר ×”×¤×¨×§×™× ×©×”×ª×—×œ×ª לה×זין לה×</string> <string name="drag_handle_content_description">גרור ×œ×©×™× ×•×™ ×ž×™×§×•× ×¤×¨×™×˜ ×–×”</string> <string name="load_next_page_label">טען ×ת הדף הב×</string> <!--Feed information screen--> @@ -366,7 +358,11 @@ <!--AntennaPodSP--> <string name="sp_apps_importing_feeds_msg">×ž×™×™×‘× ×¨×™×©×•× ×ž×פליקציות יעודיות...</string> <string name="search_itunes_label">חפש בiTunes</string> + <!--Episodes apply actions--> + <!--Sort--> <!--Rating dialog--> <!--Audio controls--> <!--proxy settings--> + <!--Casting--> + <!--<string name="cast_failed_to_connect">Could not connect to the device</string>--> </resources> diff --git a/core/src/main/res/values-ja/strings.xml b/core/src/main/res/values-ja/strings.xml index a892a957d..2e70594ec 100644 --- a/core/src/main/res/values-ja/strings.xml +++ b/core/src/main/res/values-ja/strings.xml @@ -26,6 +26,10 @@ <!--Statistics fragment--> <string name="total_time_listened_to_podcasts">ãƒãƒƒãƒ‰ã‚ャストをå†ç”Ÿã—ãŸåˆè¨ˆæ™‚é–“:</string> <string name="statistics_details_dialog">%2$d ã‹ã‚‰ %1$d ã®ã‚¨ãƒ”ソードãŒé–‹å§‹ã—ã¾ã—ãŸã€‚\n\n%4$s ã‹ã‚‰%3$s ã‚’å†ç”Ÿã—ã¾ã—ãŸã€‚</string> + <string name="statistics_mode">çµ±è¨ˆæƒ…å ±ãƒ¢ãƒ¼ãƒ‰</string> + <string name="statistics_mode_normal">実際ã«å†ç”Ÿã•ã‚ŒãŸæ™‚間を計算ã—ã¾ã™ã€‚ 2回å†ç”Ÿã™ã‚‹ã¨2回カウントã•ã‚Œã€å†ç”Ÿæ¸ˆã®ãƒžãƒ¼ã‚¯ã¯ã‚«ã‚¦ãƒ³ãƒˆã•ã‚Œã¾ã›ã‚“</string> + <string name="statistics_mode_count_all">å†ç”Ÿæ¸ˆã¿ã¨ãƒžãƒ¼ã‚¯ã•ã‚ŒãŸã™ã¹ã¦ã®ãƒãƒƒãƒ‰ã‚ャストを集計ã™ã‚‹</string> + <string name="statistics_speed_not_counted">注æ„: å†ç”Ÿé€Ÿåº¦ã¯è€ƒæ…®ã•ã‚Œã¾ã›ã‚“。</string> <!--Main activity--> <string name="drawer_open">メニューを開ã</string> <string name="drawer_close">メニューを閉ã˜ã‚‹</string> @@ -33,9 +37,11 @@ <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> <string name="drawer_feed_counter_new">æ–°ã—ã„エピソードã®æ•°</string> <string name="drawer_feed_counter_unplayed">未å†ç”Ÿã®ã‚¨ãƒ”ソードã®æ•°</string> + <string name="drawer_feed_counter_downloaded">ダウンãƒãƒ¼ãƒ‰æ¸ˆã®ã‚¨ãƒ”ソードã®æ•°</string> <string name="drawer_feed_counter_none">ãªã—</string> <!--Webview actions--> <string name="open_in_browser_label">ブラウザーã§é–‹ã</string> @@ -50,6 +56,7 @@ <string name="cancel_label">ã‚ャンセル</string> <string name="yes">ã¯ã„</string> <string name="no">ã„ã„ãˆ</string> + <string name="reset">リセット</string> <string name="author_label">作者</string> <string name="language_label">言語</string> <string name="url_label">URL</string> @@ -60,6 +67,7 @@ <string name="refresh_label">æ›´æ–°</string> <string name="external_storage_error_msg">外部ストレージãŒåˆ©ç”¨ã§ãã¾ã›ã‚“。アプリãŒæ£å¸¸ã«å‹•ä½œã§ãるよã†ã«ã€å¤–部ストレージãŒãƒžã‚¦ãƒ³ãƒˆã•ã‚Œã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。</string> <string name="chapters_label">ãƒãƒ£ãƒ—ター</string> + <string name="chapter_duration">時間: %1$s</string> <string name="shownotes_label">ショーノート</string> <string name="description_label">説明</string> <string name="most_recent_prefix">最も最近ã®ã‚¨ãƒ”ソード:\u0020</string> @@ -91,15 +99,18 @@ <string name="etxtFeedurlHint">フィードã¾ãŸã¯Webサイトã®URL</string> <string name="txtvfeedurl_label">URLã§ãƒãƒƒãƒ‰ã‚ãƒ£ã‚¹ãƒˆã‚’è¿½åŠ </string> <string name="podcastdirectories_label">ディレクトリã§ãƒãƒƒãƒ‰ã‚ャストを検索</string> - <string name="podcastdirectories_descr">åå‰ã€ã‚«ãƒ†ã‚´ãƒªã‚„人気ã§ã€gpodder.netディレクトリ内ã®æ–°ã—ã„ãƒãƒƒãƒ‰ã‚ャストを検索ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚</string> + <string name="podcastdirectories_descr">æ–°ã—ã„ãƒãƒƒãƒ‰ã‚ャストã§ã¯ã€åå‰ã€ã‚«ãƒ†ã‚´ãƒªãƒ¼ã€äººæ°—ã§iTunesã‚„fyydを検索ã—ãŸã‚Šã€gpodder.netã‚’å‚ç…§ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚</string> <string name="browse_gpoddernet_label">gpodder.netã‚’å‚ç…§</string> <!--Actions on feeds--> <string name="mark_all_read_label">ã™ã¹ã¦å†ç”Ÿæ¸ˆã¨ã—ã¦ãƒžãƒ¼ã‚¯</string> <string name="mark_all_read_msg">ã™ã¹ã¦ã®ã‚¨ãƒ”ソードをå†ç”Ÿæ¸ˆã«ã—ã¾ã—ãŸ</string> <string name="mark_all_read_confirmation_msg">å†ç”Ÿæ¸ˆã¨ã—ã¦ãƒžãƒ¼ã‚¯ã™ã‚‹ã™ã¹ã¦ã®ã‚¨ãƒ”ソードを確èªã—ã¦ãã ã•ã„。</string> <string name="mark_all_read_feed_confirmation_msg">å†ç”Ÿæ¸ˆã¨ã—ã¦ãƒžãƒ¼ã‚¯ã™ã‚‹ã“ã®ãƒ•ã‚£ãƒ¼ãƒ‰ã®ã™ã¹ã¦ã®ã‚¨ãƒ”ソードを確èªã—ã¦ãã ã•ã„。</string> - <string name="mark_all_seen_label">å‚照済ã¨ã—ã¦ãƒžãƒ¼ã‚¯</string> + <string name="mark_all_seen_label">ã™ã¹ã¦å‚照済ã¨ã—ã¦ãƒžãƒ¼ã‚¯</string> + <string name="mark_all_seen_msg">ã™ã¹ã¦ã®ã‚¨ãƒ”ソードをå‚照済ã«ã—ã¾ã—ãŸ</string> + <string name="mark_all_seen_confirmation_msg">å‚照済ã¨ã—ã¦ãƒžãƒ¼ã‚¯ã™ã‚‹ã™ã¹ã¦ã®ã‚¨ãƒ”ソードを確èªã—ã¦ãã ã•ã„。</string> <string name="show_info_label">æƒ…å ±ã‚’è¡¨ç¤º</string> + <string name="rename_feed_label">ãƒãƒƒãƒ‰ã‚ャストã®åå‰ã‚’変更</string> <string name="remove_feed_label">ãƒãƒƒãƒ‰ã‚ャストを削除</string> <string name="share_label">共有…</string> <string name="share_link_label">Webサイトã®ãƒªãƒ³ã‚¯ã‚’共有</string> @@ -107,7 +118,7 @@ <string name="share_feed_url_label">フィード URLを共有</string> <string name="share_item_url_label">エピソードファイル URLを共有</string> <string name="share_item_url_with_position_label">エピソードファイル URL ã‚’ä½ç½®ã¨å…±ã«å…±æœ‰</string> - <string name="feed_delete_confirmation_msg">ã“ã®ãƒ•ã‚£ãƒ¼ãƒ‰ã¨ã€ã“ã®ãƒ•ã‚£ãƒ¼ãƒ‰ã®ãƒ€ã‚¦ãƒ³ãƒãƒ¼ãƒ‰ã—ãŸã™ã¹ã¦ã®ã‚¨ãƒ”ソードを削除ã™ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。</string> + <string name="feed_delete_confirmation_msg">フィード \"%1$s\" ã¨ã€ã“ã®ãƒ•ã‚£ãƒ¼ãƒ‰ã®ã™ã¹ã¦ã®ãƒ€ã‚¦ãƒ³ãƒãƒ¼ãƒ‰ã—ãŸã‚¨ãƒ”ソードを削除ã™ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。</string> <string name="feed_remover_msg">フィードã®å‰Šé™¤ä¸</string> <string name="load_complete_feed">フィードをã™ã¹ã¦æ›´æ–°</string> <string name="hide_episodes_title">エピソードをéžè¡¨ç¤ºã«ã™ã‚‹</string> @@ -119,6 +130,7 @@ <string name="hide_not_queued_episodes_label">ã‚ューã«å…¥ã£ã¦ã„ã¾ã›ã‚“</string> <string name="hide_downloaded_episodes_label">ダウンãƒãƒ¼ãƒ‰ã—ã¾ã—ãŸ</string> <string name="hide_not_downloaded_episodes_label">ダウンãƒãƒ¼ãƒ‰ã—ã¦ã„ã¾ã›ã‚“</string> + <string name="hide_has_media_label">メディアã‚ã‚Š</string> <string name="filtered_label">フィルターã—ã¾ã—ãŸ</string> <string name="refresh_failed_msg">{fa-exclamation-circle} å‰å›žæ›´æ–°ã«å¤±æ•—ã—ã¾ã—ãŸ</string> <string name="open_podcast">ãƒãƒƒãƒ‰ã‚ャストを開ã</string> @@ -129,7 +141,9 @@ <string name="stop_label">åœæ¢</string> <string name="stream_label">ストリーム</string> <string name="remove_label">削除</string> + <string name="delete_label">削除</string> <string name="remove_episode_lable">エピソードを削除</string> + <string name="marked_as_seen_label">å‚照済ã¨ã—ã¦ãƒžãƒ¼ã‚¯</string> <string name="mark_read_label">å†ç”Ÿæ¸ˆã¨ã—ã¦ãƒžãƒ¼ã‚¯</string> <string name="marked_as_read_label">å†ç”Ÿæ¸ˆã¨ã—ã¦ãƒžãƒ¼ã‚¯ã—ã¾ã—ãŸ</string> <string name="mark_unread_label">未å†ç”Ÿã¨ã—ã¦ãƒžãƒ¼ã‚¯</string> @@ -214,9 +228,10 @@ <string name="move_to_top_label">å…ˆé ã«ç§»å‹•</string> <string name="move_to_bottom_label">最後ã«ç§»å‹•</string> <string name="sort">並ã¹æ›¿ãˆ</string> - <string name="alpha">ã‚¢ãƒ«ãƒ•ã‚¡ãƒ™ãƒƒãƒˆé †</string> <string name="date">日付</string> <string name="duration">継続時間</string> + <string name="episode_title">エピソード タイトル</string> + <string name="feed_title">フィード タイトル</string> <string name="ascending">æ˜‡é †</string> <string name="descending">é™é †</string> <string name="clear_queue_confirmation_msg">クリアã™ã‚‹ã€ã‚ューã«å«ã¾ã‚Œã‚‹ã™ã¹ã¦ã®ã‚¨ãƒ”ソードを確èªã—ã¦ãã ã•ã„。</string> @@ -272,6 +287,8 @@ <string name="pref_unpauseOnBluetoothReconnect_sum">BluetoothãŒå†æŽ¥ç¶šã•ã‚ŒãŸæ™‚ã«å†ç”Ÿã‚’å†é–‹ã—ã¾ã™</string> <string name="pref_hardwareForwardButtonSkips_title">æ—©é€ã‚Šãƒœã‚¿ãƒ³ã§ã‚¹ã‚ップ</string> <string name="pref_hardwareForwardButtonSkips_sum">ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ã®æ—©é€ã‚Šãƒœã‚¿ãƒ³ã‚’押ã—ãŸã¨ãã«ã€æ—©é€ã‚Šã®ä»£ã‚ã‚Šã«æ¬¡ã®ã‚¨ãƒ”ソードã«ã‚¹ã‚ップã—ã¾ã™</string> + <string name="pref_hardwarePreviousButtonRestarts_title">戻るボタンã§å†é–‹</string> + <string name="pref_hardwarePreviousButtonRestarts_sum">ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ã®æˆ»ã‚‹ãƒœã‚¿ãƒ³ã‚’押ã—ãŸã¨ãã«ã€å·»ã戻ã—ã®ä»£ã‚ã‚Šã«ç¾åœ¨ã®ã‚¨ãƒ”ソードã®å†ç”Ÿã‚’å†é–‹ã—ã¾ã™</string> <string name="pref_followQueue_sum">å†ç”ŸãŒå®Œäº†ã—ãŸæ™‚ã«æ¬¡ã®ã‚ューã®ã‚¢ã‚¤ãƒ†ãƒ ã«ç§»å‹•ã—ã¾ã™</string> <string name="pref_auto_delete_sum">å†ç”ŸãŒå®Œäº†ã—ãŸæ™‚ã«ã‚¨ãƒ”ソードを削除ã—ã¾ã™</string> <string name="pref_auto_delete_title">自動削除</string> @@ -338,14 +355,22 @@ <string name="pref_gpodnet_logout_toast">ãƒã‚°ã‚¢ã‚¦ãƒˆã—ã¾ã—ãŸ</string> <string name="pref_gpodnet_setlogin_information_title">ãƒã‚°ã‚¤ãƒ³æƒ…å ±ã‚’å¤‰æ›´</string> <string name="pref_gpodnet_setlogin_information_sum">gpodder.netアカウントã®ãƒã‚°ã‚¤ãƒ³æƒ…å ±ã‚’å¤‰æ›´ã—ã¾ã™ã€‚</string> - <string name="pref_gpodnet_sync_title">今ã™ãåŒæœŸ</string> - <string name="pref_gpodnet_sync_sum">è³¼èªã¨ã‚¨ãƒ”ソードã®çŠ¶æ…‹ã‚’ gpodder.net ã§åŒæœŸ</string> + <string name="pref_gpodnet_sync_changes_title">今ã™ã変更をåŒæœŸ</string> + <string name="pref_gpodnet_sync_changes_sum">è³¼èªã¨ã‚¨ãƒ”ソードã®çŠ¶æ…‹ã®å¤‰æ›´ã‚’ gpodder.net ã§åŒæœŸã—ã¾ã™ã€‚</string> + <string name="pref_gpodnet_full_sync_title">今ã™ã完全ã«åŒæœŸ</string> + <string name="pref_gpodnet_full_sync_sum">ã™ã¹ã¦ã®è³¼èªã¨ã‚¨ãƒ”ソードã®çŠ¶æ…‹ã‚’ gpodder.net ã§åŒæœŸã—ã¾ã™ã€‚</string> + <string name="pref_gpodnet_sync_sum_last_sync_line">最後ã«åŒæœŸã‚’試行: %1$s (%2$s)</string> <string name="pref_gpodnet_sync_started">åŒæœŸã‚’開始ã—ã¾ã—ãŸ</string> + <string name="pref_gpodnet_full_sync_started">完全ãªåŒæœŸã‚’開始ã—ã¾ã—ãŸ</string> <string name="pref_gpodnet_login_status"><![CDATA[<i>%1$s</i> ã¨ã—ã¦ãƒ‡ãƒã‚¤ã‚¹ <i>%2$s</i> ã§ãƒã‚°ã‚¤ãƒ³ã—ã¾ã—ãŸ]]></string> + <string name="pref_gpodnet_notifications_title">åŒæœŸã‚¨ãƒ©ãƒ¼ã®é€šçŸ¥ã‚’表示</string> + <string name="pref_gpodnet_notifications_sum">ã“ã®è¨å®šã¯ã€èªè¨¼ã‚¨ãƒ©ãƒ¼ã«ã¯é©ç”¨ã•ã‚Œã¾ã›ã‚“。</string> <string name="pref_playback_speed_title">å†ç”Ÿé€Ÿåº¦</string> <string name="pref_playback_speed_sum">å¯å¤‰é€Ÿåº¦éŸ³å£°å†ç”Ÿã«ä½¿ç”¨å¯èƒ½ãªé€Ÿåº¦ã‚’カスタマイズã—ã¾ã™</string> - <string name="pref_fast_forward">æ—©é€ã‚Šæ™‚é–“</string> - <string name="pref_rewind">å·»ã戻ã—時間</string> + <string name="pref_fast_forward">æ—©é€ã‚Šã®ã‚¹ã‚ップ時間</string> + <string name="pref_fast_forward_sum">æ—©é€ã‚Šãƒœã‚¿ãƒ³ãŒã‚¯ãƒªãƒƒã‚¯ã•ã‚ŒãŸã¨ãã«ã‚¸ãƒ£ãƒ³ãƒ—ã™ã‚‹ç§’数をカスタマイズã—ã¾ã™</string> + <string name="pref_rewind">å·»ã戻ã—スã‚ップ時間</string> + <string name="pref_rewind_sum">å·»ã戻ã—ボタンãŒã‚¯ãƒªãƒƒã‚¯ã•ã‚ŒãŸã¨ãã«å¾Œæ–¹ã«ã‚¸ãƒ£ãƒ³ãƒ—ã™ã‚‹ç§’数をカスタマイズã—ã¾ã™</string> <string name="pref_gpodnet_sethostname_title">ホストåをセット</string> <string name="pref_gpodnet_sethostname_use_default_host">デフォルトホストを使用</string> <string name="pref_expandNotify_title">拡張通知</string> @@ -356,8 +381,6 @@ <string name="pref_compact_notification_buttons_sum">ãƒãƒƒã‚¯ç”»é¢ã®å†ç”Ÿãƒœã‚¿ãƒ³ã‚’変更ã—ã¾ã™ã€‚å†ç”Ÿ/一時åœæ¢ãƒœã‚¿ãƒ³ã‚’常ã«å«ã¿ã¾ã™ã€‚</string> <string name="pref_compact_notification_buttons_dialog_title">最大 %1$d ã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’é¸æŠž</string> <string name="pref_compact_notification_buttons_dialog_error">最大 %1$d ã®ã‚¢ã‚¤ãƒ†ãƒ ã®ã¿ã‚’é¸æŠžã§ãã¾ã™ã€‚</string> - <string name="pref_show_subscriptions_in_drawer_title">è³¼èªã‚’表示</string> - <string name="pref_show_subscriptions_in_drawer_sum">ナビゲーションドãƒãƒ¯ãƒ¼ã«ç›´æŽ¥è³¼èªãƒªã‚¹ãƒˆã‚’表示ã—ã¾ã™</string> <string name="pref_lockscreen_background_title">ãƒãƒƒã‚¯ç”»é¢ã®èƒŒæ™¯ã‚’è¨å®š</string> <string name="pref_lockscreen_background_sum">ãƒãƒƒã‚¯ç”»é¢ã®èƒŒæ™¯ã‚’ã€ç¾åœ¨ã®ã‚¨ãƒ”ソードã®ç”»åƒã«è¨å®šã—ã¾ã™ã€‚副作用ã¨ã—ã¦ã€ã“ã‚Œã¯ã‚µãƒ¼ãƒ‰ãƒ‘ーティã®ã‚¢ãƒ—リケーションã§ã‚‚ç”»åƒã‚’表示ã—ã¾ã™ã€‚</string> <string name="pref_showDownloadReport_title">ダウンãƒãƒ¼ãƒ‰ レãƒãƒ¼ãƒˆã‚’表示</string> @@ -381,19 +404,25 @@ <string name="pref_known_issues">既知ã®å•é¡Œ</string> <string name="pref_no_browser_found">WebブラウザーãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。</string> <string name="pref_cast_title">Chromecast サãƒãƒ¼ãƒˆ</string> - <string name="pref_cast_message">(Chromecastã€ã‚ªãƒ¼ãƒ‡ã‚£ã‚ªã‚¹ãƒ”ーカーã€Android TV ãªã©) ã‚ャストデãƒã‚¤ã‚¹ä¸Šã§ãƒªãƒ¢ãƒ¼ãƒˆãƒ¡ãƒ‡ã‚£ã‚¢å†ç”Ÿã®ã‚µãƒãƒ¼ãƒˆã‚’有効ã«ã—ã¾ã™</string> + <string name="pref_cast_message_play_flavor">(Chromecastã€ã‚ªãƒ¼ãƒ‡ã‚£ã‚ªã‚¹ãƒ”ーカーã€Android TV ãªã©) ã‚ャストデãƒã‚¤ã‚¹ä¸Šã§ãƒªãƒ¢ãƒ¼ãƒˆãƒ¡ãƒ‡ã‚£ã‚¢å†ç”Ÿã®ã‚µãƒãƒ¼ãƒˆã‚’有効ã«ã—ã¾ã™</string> + <string name="pref_cast_message_free_flavor">Chromecast 㯠AntennaPod ã®ã“ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã§ç„¡åŠ¹ã«ãªã£ã¦ã„るサードパーティ独自ã®ãƒ©ã‚¤ãƒ–ラリーãŒå¿…è¦ã§ã™</string> + <string name="pref_enqueue_downloaded_title">ダウンãƒãƒ¼ãƒ‰æ¸ˆã¿ã‚’ã‚ューã«å…¥ã‚Œã‚‹</string> + <string name="pref_enqueue_downloaded_summary">ダウンãƒãƒ¼ãƒ‰ã—ãŸã‚¨ãƒ”ソードをã‚ューã«è¿½åŠ ã—ã¾ã™</string> <!--Auto-Flattr dialog--> <string name="auto_flattr_enable">自動Flattrを有効ã«ã™ã‚‹</string> <string name="auto_flattr_after_percent">%d ï¼…å†ç”Ÿã—ãŸã‚‰ã‚¨ãƒ”ソードをFlattr </string> <string name="auto_flattr_ater_beginning">å†ç”Ÿã‚’開始ã—ãŸæ™‚ã«ã‚¨ãƒ”ソードをFlattr</string> <string name="auto_flattr_ater_end">å†ç”ŸãŒçµ‚了ã—ãŸæ™‚ã«ã‚¨ãƒ”ソードをFlattr</string> <!--Search--> - <string name="search_hint">フィードã¾ãŸã¯ã‚¨ãƒ”ソードを検索</string> + <string name="search_hint">エピソードã®æ¤œç´¢</string> <string name="found_in_shownotes_label">ショーノートã§è¦‹ã¤ã‹ã‚Šã¾ã—ãŸ</string> <string name="found_in_chapters_label">ãƒãƒ£ãƒ—ターã§è¦‹ã¤ã‹ã‚Šã¾ã—ãŸ</string> + <string name="found_in_authors_label">作者ã§è¦‹ã¤ã‹ã‚Šã¾ã—ãŸ</string> + <string name="found_in_feeds_label">フィードã§è¦‹ã¤ã‹ã‚Šã¾ã—ãŸ</string> <string name="search_status_no_results">見ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ</string> <string name="search_label">検索</string> <string name="found_in_title_label">タイトルã§è¦‹ã¤ã‹ã‚Šã¾ã—ãŸ</string> + <string name="no_results_for_query">\"%1$s\" ã®çµæžœã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ</string> <!--OPML import and export--> <string name="opml_import_txtv_button_lable">OPMLファイルã§ã€ã‚ã‚‹ãƒãƒƒãƒ‰ã‚ャッãƒãƒ£ãƒ¼ã‹ã‚‰åˆ¥ã®ã‚‚ã®ã«ãƒãƒƒãƒ‰ã‚ャストを移動ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚</string> <string name="opml_import_option">オプション %1$d</string> @@ -412,6 +441,7 @@ <string name="choose_file_from_filesystem">ãƒãƒ¼ã‚«ãƒ« ファイルシステムã‹ã‚‰</string> <string name="choose_file_from_external_application">外部アプリケーションを使用ã™ã‚‹</string> <string name="opml_export_label">OPMLエクスãƒãƒ¼ãƒˆ</string> + <string name="html_export_label">HTML エクスãƒãƒ¼ãƒˆ</string> <string name="exporting_label">エクスãƒãƒ¼ãƒˆä¸â€¦</string> <string name="export_error_label">エクスãƒãƒ¼ãƒˆã‚¨ãƒ©ãƒ¼</string> <string name="opml_export_success_title">OPMLをエクスãƒãƒ¼ãƒˆã—ã¾ã—ãŸã€‚</string> @@ -439,6 +469,9 @@ <plurals name="time_hours_quantified"> <item quantity="other">%d 時間</item> </plurals> + <string name="auto_enable_label">自動有効化</string> + <string name="sleep_timer_enabled_label">スリープタイマーを有効ã«ã—ã¾ã—ãŸ</string> + <string name="sleep_timer_disabled_label">スリープタイマーを無効ã«ã—ã¾ã—ãŸ</string> <!--gpodder.net--> <string name="gpodnet_taglist_header">カテゴリー</string> <string name="gpodnet_toplist_header">トップ ボッドã‚ャスト</string> @@ -468,6 +501,8 @@ <string name="gpodnetsync_auth_error_descr">ユーザーåã¾ãŸã¯ãƒ‘スワードãŒé–“é•ã£ã¦ã„ã¾ã™</string> <string name="gpodnetsync_error_title">gpodder.net åŒæœŸã‚¨ãƒ©ãƒ¼</string> <string name="gpodnetsync_error_descr">åŒæœŸä¸ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ:\u0020</string> + <string name="gpodnetsync_pref_report_successful">æˆåŠŸã—ã¾ã—ãŸ</string> + <string name="gpodnetsync_pref_report_failed">失敗ã—ã¾ã—ãŸ</string> <!--Directory chooser--> <string name="selected_folder_label">é¸æŠžã—ãŸãƒ•ã‚©ãƒ«ãƒ€ãƒ¼:</string> <string name="create_folder_label">フォルダーを作æˆ</string> @@ -520,6 +555,7 @@ <string name="sp_apps_importing_feeds_msg">å˜ä¸€ç›®çš„ã®ã‚¢ãƒ—リã‹ã‚‰è³¼èªã‚’インãƒãƒ¼ãƒˆä¸â€¦</string> <string name="search_itunes_label">iTunes を検索</string> <string name="filter">フィルター</string> + <string name="search_fyyd_label">fyydを検索</string> <!--Episodes apply actions--> <string name="all_label">ã™ã¹ã¦</string> <string name="selected_all_label">ã™ã¹ã¦ã®ã‚¨ãƒ”ソードをé¸æŠžã—ã¾ã—ãŸ</string> @@ -537,6 +573,8 @@ <string name="selected_queued_label">ã‚ューã«å…¥ã£ãŸã‚¨ãƒ”ソードをé¸æŠžã—ã¾ã—ãŸ</string> <string name="not_queued_label">ã‚ューã«å…¥ã£ã¦ã„ã¾ã›ã‚“</string> <string name="selected_not_queued_label">ã‚ューã«å…¥ã£ã¦ã„ãªã„エピソードをé¸æŠžã—ã¾ã—ãŸ</string> + <string name="has_media">メディアã‚ã‚Š</string> + <string name="selected_has_media_label">メディアã®ã‚るエピソードをé¸æŠžã—ã¾ã—ãŸ</string> <!--Sort--> <string name="sort_title_a_z">タイトル (A \u2192 Z)</string> <string name="sort_title_z_a">タイトル (Z \u2192 A)</string> diff --git a/core/src/main/res/values-kn-rIN/strings.xml b/core/src/main/res/values-kn-rIN/strings.xml index 26de5a2fb..3d24900c9 100644 --- a/core/src/main/res/values-kn-rIN/strings.xml +++ b/core/src/main/res/values-kn-rIN/strings.xml @@ -28,7 +28,6 @@ <string name="feedurl_label">ಫೀಡೠಯà³.ಆರà³.ಎಲà³</string> <!--Actions on feeds--> <string name="show_info_label">ಮಾಹಿತಿ ತೋರಿಸà³</string> - <string name="feed_delete_confirmation_msg">ನೀವೠಈ ಫೀಡೠಮತà³à²¤à³ ನೀವೠಡೌನà³à²²à³†à³‚ೕಡೠಮಾಡಿದ ಈ ಫೀಡà³à²¨ ಎಲà³à²²à²¾ ಕಂತà³à²—ಳೠಅಳಿಸಲೠಬಯಸà³à²¤à³à²¤à³€à²°à²¿ ಎಂಬà³à²¦à²¨à³à²¨à³ ದಯವಿಟà³à²Ÿà³ ದೃಢಪಡಿಸಿ.</string> <!--actions on feeditems--> <string name="download_label">ಡೌನà³à²²à³†à³‚ೕಡà³</string> <string name="play_label">ಚಾಲನೆಗೊಳಿಸà³</string> @@ -82,8 +81,6 @@ <string name="user_interface_label">ಬಳಕೆದಾರ ಸಂಪರà³à²•à²¸à²¾à²§à²¨</string> <!--Auto-Flattr dialog--> <!--Search--> - <string name="search_hint">ಫೀಡà³à²¸à³ ಅಥವಾ ಸಂಚಿಕೆಗಳಿಗಾಗಿ ಹà³à²¡à³à²•à²¿</string> - <string name="found_in_shownotes_label">ಪà³à²°à²¦à²°à³à²¶à²¨ ಟಿಪà³à²ªà²£à²¿à²—ಳಲà³à²²à²¿ ಕಂಡà³à²¬à²°à³à²¤à³à²¤à²µà³†</string> <string name="found_in_chapters_label">ಅಧà³à²¯à²¾à²¯à²—ಳಲà³à²²à²¿ ಕಂಡà³à²¬à²°à³à²¤à³à²¤à²µà³†</string> <string name="search_status_no_results">ಯಾವà³à²¦à³†à³• ಫಲಿತಾಂಶಗಳೠಕಂಡà³à²¬à²‚ದಿಲà³à²²</string> <string name="search_label">ಹà³à²¡à³à²•à³</string> diff --git a/core/src/main/res/values-ko/strings.xml b/core/src/main/res/values-ko/strings.xml index 29ddd7e73..b472db1a7 100644 --- a/core/src/main/res/values-ko/strings.xml +++ b/core/src/main/res/values-ko/strings.xml @@ -26,6 +26,10 @@ <!--Statistics fragment--> <string name="total_time_listened_to_podcasts">재ìƒí•œ 팟ìºìŠ¤íŠ¸ì˜ ì „ì²´ 시간</string> <string name="statistics_details_dialog">ì—피소드 %1$dê°œ (ì „ì²´ %2$dê°œ) 시작.\n\n%3$sê°œ ìž¬ìƒ (ì „ì²´ %4$sê°œ).</string> + <string name="statistics_mode">통계 모드</string> + <string name="statistics_mode_normal">ì‹¤ì œ 재ìƒí•œ ì‹œê°„ì„ ê³„ì‚°í•©ë‹ˆë‹¤. ë‘ ë²ˆ 재ìƒí•˜ë©´ ë‘ ë²ˆ 계산ë˜ê³ , 재ìƒí•œ 것으로 표시하면 ê³„ì‚°ì— ì•ˆ 들어갑니다.</string> + <string name="statistics_mode_count_all">재ìƒí•œ 것으로 표시한 ëª¨ë“ íŒŸìºìŠ¤íŠ¸ 합계</string> + <string name="statistics_speed_not_counted">주ì˜: ìž¬ìƒ ì†ë„는 ê³ ë ¤í•˜ì§€ 않습니다</string> <!--Main activity--> <string name="drawer_open">메뉴 열기</string> <string name="drawer_close">메뉴 닫기</string> @@ -33,9 +37,11 @@ <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> <string name="drawer_feed_counter_new">새로운 ì—피소드 수</string> <string name="drawer_feed_counter_unplayed">재ìƒí•˜ì§€ ì•Šì€ ì—피소드 수</string> + <string name="drawer_feed_counter_downloaded">다운로드한 ì—피소드 수</string> <string name="drawer_feed_counter_none">ì—†ìŒ</string> <!--Webview actions--> <string name="open_in_browser_label">브ë¼ìš°ì €ì—ì„œ 열기</string> @@ -50,6 +56,7 @@ <string name="cancel_label">취소</string> <string name="yes">예</string> <string name="no">아니요</string> + <string name="reset">초기화</string> <string name="author_label">ì €ìž</string> <string name="language_label">언어</string> <string name="url_label">URL</string> @@ -60,6 +67,7 @@ <string name="refresh_label">새로 ê³ ì¹¨</string> <string name="external_storage_error_msg">외부 ì €ìž¥ 장치가 없습니다. ì•±ì´ ì œëŒ€ë¡œ ë™ìž‘í•˜ë ¤ë©´ 외부 ì €ìž¥ìž¥ì¹˜ë¥¼ 마운트하ì‹ì‹œì˜¤.</string> <string name="chapters_label">챕터</string> + <string name="chapter_duration">길ì´: %1$s</string> <string name="shownotes_label">프로그램 메모</string> <string name="description_label">설명</string> <string name="most_recent_prefix">가장 최근 ì—피소드:\u0020</string> @@ -91,7 +99,7 @@ <string name="etxtFeedurlHint">í”¼ë“œì˜ URL ë˜ëŠ” 홈페ì´ì§€</string> <string name="txtvfeedurl_label">URLë¡œ 팟ìºìŠ¤íŠ¸ë¥¼ 추가</string> <string name="podcastdirectories_label">ë””ë ‰í„°ë¦¬ì—ì„œ 팟ìºìŠ¤íŠ¸ 찾기</string> - <string name="podcastdirectories_descr">gpodder.net ë””ë ‰í„°ë¦¬ì—ì„œ ì´ë¦„, 분류, ì¸ê¸°ì— ë”°ë¼ ìƒˆ 팟ìºìŠ¤íŠ¸ë¥¼ ê²€ìƒ‰í• ìˆ˜ ìžˆê³ , iTunes ìŠ¤í† ì–´ì—ì„œ ê²€ìƒ‰í• ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤.</string> + <string name="podcastdirectories_descr">새 팟ìºìŠ¤íŠ¸ëŠ” iTunes, fyyd, gpodder.netì—ì„œ ì´ë¦„, 분류, ì¸ê¸°ë¡œ ê²€ìƒ‰í• ìˆ˜ 있습니다.</string> <string name="browse_gpoddernet_label">gpodder.net 둘러보기</string> <!--Actions on feeds--> <string name="mark_all_read_label">ëª¨ë‘ ìž¬ìƒí–ˆë‹¤ê³ 표시</string> @@ -99,7 +107,10 @@ <string name="mark_all_read_confirmation_msg">ëª¨ë“ ì—피소드를 재ìƒí–ˆë‹¤ê³ í‘œì‹œí• ì§€ 확ì¸í•˜ì‹ì‹œì˜¤.</string> <string name="mark_all_read_feed_confirmation_msg">ì´ í”¼ë“œì— ë“¤ì–´ 있는 ëª¨ë“ ì—피소드를 재ìƒí–ˆë‹¤ê³ í‘œì‹œí• ì§€ 확ì¸í•˜ì‹ì‹œì˜¤.</string> <string name="mark_all_seen_label">ëª¨ë‘ ë´¤ë‹¤ê³ í‘œì‹œ</string> + <string name="mark_all_seen_msg">ëª¨ë“ ì—피소드를 ë´¤ë‹¤ê³ í‘œì‹œí–ˆìŠµë‹ˆë‹¤</string> + <string name="mark_all_seen_confirmation_msg">ëª¨ë“ ì—피소드를 본 것으로 표시하는지 확ì¸í•˜ì‹ì‹œì˜¤.</string> <string name="show_info_label">ì •ë³´ 표시</string> + <string name="rename_feed_label">팟ìºìŠ¤íŠ¸ ì´ë¦„ 바꾸기</string> <string name="remove_feed_label">팟ìºìŠ¤íŠ¸ ì œê±°</string> <string name="share_label">ê³µìœ â€¦</string> <string name="share_link_label">홈페ì´ì§€ ë§í¬ ê³µìœ </string> @@ -107,7 +118,7 @@ <string name="share_feed_url_label">피드 URL ê³µìœ </string> <string name="share_item_url_label">ì—피소드 íŒŒì¼ URL ê³µìœ </string> <string name="share_item_url_with_position_label">ì—피소드 íŒŒì¼ URLê³¼ ìž¬ìƒ ìœ„ì¹˜ ê³µìœ </string> - <string name="feed_delete_confirmation_msg">ì´ í”¼ë“œì™€ ì´ í”¼ë“œì—ì„œ 다운로드한 ëª¨ë“ ì—피소드를 ì‚ì œí•˜ì‹œë ¤ë©´ 확ì¸ì„ 누르ì‹ì‹œì˜¤.</string> + <string name="feed_delete_confirmation_msg">확ì¸í•˜ë©´ \"%1$s\" 피드를 ì‚ì œí•˜ê³ ì´ í”¼ë“œì—ì„œ 다운로드한 ëª¨ë“ ì—피소드를 ì‚ì œí•©ë‹ˆë‹¤.</string> <string name="feed_remover_msg">피드 ì‚ì œí•˜ëŠ” 중</string> <string name="load_complete_feed">ì „ì²´ 피드 ìƒˆë¡œê³ ì¹¨</string> <string name="hide_episodes_title">ì—피소드 ê°ì¶”기</string> @@ -119,6 +130,7 @@ <string name="hide_not_queued_episodes_label">대기열 추가 안 함</string> <string name="hide_downloaded_episodes_label">다운로드함</string> <string name="hide_not_downloaded_episodes_label">다운로드 안 함</string> + <string name="hide_has_media_label">미디어 있ìŒ</string> <string name="filtered_label">í•„í„°ë§í•¨</string> <string name="refresh_failed_msg">{fa-exclamation-circle} 최근 새로 ê³ ì¹¨ 실패</string> <string name="open_podcast">팟ìºìŠ¤íŠ¸ 열기</string> @@ -129,9 +141,11 @@ <string name="stop_label">중지</string> <string name="stream_label">스트리ë°</string> <string name="remove_label">ì œê±°</string> + <string name="delete_label">ì‚ì œ</string> <string name="remove_episode_lable">ì—피소드 ì œê±°</string> + <string name="marked_as_seen_label">ë´¤ë‹¤ê³ í‘œì‹œí–ˆìŠµë‹ˆë‹¤</string> <string name="mark_read_label">재ìƒí–ˆë‹¤ê³ 표시</string> - <string name="marked_as_read_label">재ìƒí–ˆë‹¤ê³ 표시함</string> + <string name="marked_as_read_label">재ìƒí–ˆë‹¤ê³ 표시했습니다</string> <string name="mark_unread_label">재ìƒí•˜ì§€ ì•ŠìŒìœ¼ë¡œ 표시</string> <string name="add_to_queue_label">ëŒ€ê¸°ì—´ì— ì¶”ê°€</string> <string name="added_to_queue_label">ëŒ€ê¸°ì—´ì— ì¶”ê°€í•¨</string> @@ -214,9 +228,10 @@ <string name="move_to_top_label">맨 위로 ì´ë™</string> <string name="move_to_bottom_label">맨 아래로 ì´ë™</string> <string name="sort">ì •ë ¬</string> - <string name="alpha">ì‚¬ì „ìˆœ</string> <string name="date">ë‚ ì§œ</string> <string name="duration">기간</string> + <string name="episode_title">ì—피소드 ì œëª©</string> + <string name="feed_title">피드 ì œëª©</string> <string name="ascending">오름차순</string> <string name="descending">내림차순</string> <string name="clear_queue_confirmation_msg">ë‚´ë¶€ì˜ ëª¨ë“ ì—피소드 ëŒ€ê¸°ì—´ì„ ì§€ìš¸ì§€ 확ì¸í•˜ì‹ì‹œì˜¤.</string> @@ -270,8 +285,10 @@ <string name="pref_pauseOnDisconnect_sum">헤드í°ì´ë‚˜ 블루투스가 ì—°ê²° í•´ì œë˜ì—ˆì„ 경우 ì¼ì‹œì •ì§€í•©ë‹ˆë‹¤.</string> <string name="pref_unpauseOnHeadsetReconnect_sum">í—¤ë“œí° ë‹¤ì‹œ ì—°ê²°í• ë•Œ 재ìƒì„ 계ì†í•©ë‹ˆë‹¤.</string> <string name="pref_unpauseOnBluetoothReconnect_sum">블루투스가 다시 ì—°ê²°ë˜ë©´ 재ìƒì„ 계ì†í•©ë‹ˆë‹¤.</string> - <string name="pref_hardwareForwardButtonSkips_title">빨리ê°ê¸° ë²„íŠ¼ì„ ë„˜ê¹€ 버튼으로</string> + <string name="pref_hardwareForwardButtonSkips_title">ë¹ ë¥´ê²Œ ê°ê¸° 버튼 건너뛰기</string> <string name="pref_hardwareForwardButtonSkips_sum">빨리ê°ê¸° 하드웨어 ë²„íŠ¼ì„ ëˆŒë €ì„ ê²½ìš° 빨리ê°ê¸° ëŒ€ì‹ ë‹¤ìŒ ì—피소드로 넘ê¹ë‹ˆë‹¤.</string> + <string name="pref_hardwarePreviousButtonRestarts_title">ì´ì „ ë²„íŠ¼ì„ ëˆ„ë¥´ë©´ 재시작</string> + <string name="pref_hardwarePreviousButtonRestarts_sum">하드웨어 ì´ì „ ë²„íŠ¼ì„ ëˆ„ë¥´ë©´ 뒤로ê°ê¸° ëŒ€ì‹ í˜„ìž¬ ì—피소드를 재시작합니다</string> <string name="pref_followQueue_sum">재ìƒì„ ë§ˆì³¤ì„ ë•Œ ë‹¤ìŒ ëŒ€ê¸°ì—´ë¡œ ì´ë™</string> <string name="pref_auto_delete_sum">재ìƒì´ ë나면 ì—피소드를 ì‚ì œí•©ë‹ˆë‹¤.</string> <string name="pref_auto_delete_title">ìžë™ ì‚ì œ</string> @@ -338,14 +355,22 @@ <string name="pref_gpodnet_logout_toast">로그아웃 성공</string> <string name="pref_gpodnet_setlogin_information_title">ë¡œê·¸ì¸ ì •ë³´ 바꾸기</string> <string name="pref_gpodnet_setlogin_information_sum">gpodder.net ê³„ì •ì˜ ë¡œê·¸ì¸ ì •ë³´ë¥¼ 바꿉니다.</string> - <string name="pref_gpodnet_sync_title">지금 ë™ê¸°í™”</string> - <string name="pref_gpodnet_sync_sum">gpodder.netì˜ êµ¬ë…ê³¼ ì—피소드 ìƒíƒœ ë™ê¸°í™”</string> + <string name="pref_gpodnet_sync_changes_title">변경 ì‚¬í• ì§€ê¸ˆ ë™ê¸°í™”</string> + <string name="pref_gpodnet_sync_changes_sum">gpodder.netì˜ êµ¬ë…ê³¼ ì—피소드 ìƒíƒœ 변화를 ë™ê¸°í™”합니다.</string> + <string name="pref_gpodnet_full_sync_title">지금 ì „ì²´ ë™ê¸°í™”</string> + <string name="pref_gpodnet_full_sync_sum">gpodder.netì˜ ëª¨ë“ êµ¬ë…ê³¼ ì—피소드 ìƒíƒœë¥¼ ë™ê¸°í™”합니다.</string> + <string name="pref_gpodnet_sync_sum_last_sync_line">최근 ë™ê¸°í™” ì‹œë„: %1$s (%2$s)</string> <string name="pref_gpodnet_sync_started">ë™ê¸°í™” 시작함</string> + <string name="pref_gpodnet_full_sync_started">ì „ì²´ ë™ê¸°í™” 시작함</string> <string name="pref_gpodnet_login_status"><![CDATA[<i>%1$s</i> 사용ìžë¡œ 로그ì¸, <i>%2$s</i> 장치]]></string> + <string name="pref_gpodnet_notifications_title">ë™ê¸°í™” 오류 알림 표시</string> + <string name="pref_gpodnet_notifications_sum">ì´ ì„¤ì •ì€ ì¸ì¦ 오류ì—는 ì ìš©ë˜ì§€ 않습니다.</string> <string name="pref_playback_speed_title">ìž¬ìƒ ì†ë„</string> <string name="pref_playback_speed_sum">여러가지 오디오 ìž¬ìƒ ì†ë„ ì§ì ‘ ì„¤ì •</string> - <string name="pref_fast_forward">ë¹ ë¥´ê²Œ ê°ê¸° 시간</string> - <string name="pref_rewind">뒤로 ê°ê¸° 시간</string> + <string name="pref_fast_forward">ë¹ ë¥´ê²Œ ê°ê¸° 건너뛰기 시간</string> + <string name="pref_fast_forward_sum">앞으로 ê°ê¸° ë²„íŠ¼ì„ ëˆŒë €ì„ ë•Œ 앞으로 넘어갈 초를 ì§€ì •í•©ë‹ˆë‹¤.</string> + <string name="pref_rewind">뒤로 건너뛰기 시간</string> + <string name="pref_rewind_sum">뒤로 ê°ê¸° ë²„íŠ¼ì„ ëˆŒë €ì„ ë•Œ 뒤로 넘어갈 초를 ì§€ì •í•©ë‹ˆë‹¤.</string> <string name="pref_gpodnet_sethostname_title">호스트 ì´ë¦„ ì„¤ì •</string> <string name="pref_gpodnet_sethostname_use_default_host">기본 호스트 사용</string> <string name="pref_expandNotify_title">알림 확장</string> @@ -356,8 +381,6 @@ <string name="pref_compact_notification_buttons_sum">ìž ê¸ˆí™”ë©´ì˜ ì¡°ìž‘ ë²„íŠ¼ì„ ë°”ê¿‰ë‹ˆë‹¤. 재ìƒ/ì¼ì‹œì¤‘지 ë²„íŠ¼ì€ í•ìƒ í¬í•¨ë©ë‹ˆë‹¤.</string> <string name="pref_compact_notification_buttons_dialog_title">최대 %1$dê°œ í•ëª© ì„ íƒ</string> <string name="pref_compact_notification_buttons_dialog_error">최대 %1$dê°œ í•ëª¨ë§Œ ì„ íƒí• 수 있습니다.</string> - <string name="pref_show_subscriptions_in_drawer_title">êµ¬ë… í‘œì‹œ</string> - <string name="pref_show_subscriptions_in_drawer_sum">네비게ì´ì…˜ ë“œë¡œì–´ì— ì§ì ‘ êµ¬ë… ëª©ë¡ì„ 표시</string> <string name="pref_lockscreen_background_title">ìž ê¸ˆ 화면 ë°°ê²½ ì„¤ì •</string> <string name="pref_lockscreen_background_sum">현재 ì—í”¼ì†Œë“œì˜ ì´ë¯¸ì§€ë¥¼ ìž ê¸ˆ í™”ë©´ì˜ ë°°ê²½ìœ¼ë¡œ ì„¤ì •í•©ë‹ˆë‹¤. ëŒ€ì‹ ì´ëŠ” ì œ3ìž ì•±ì˜ ì´ë¯¸ì§€ë„ 표시하게 ë©ë‹ˆë‹¤.</string> <string name="pref_showDownloadReport_title">다운로드 ë³´ê³ ì„œ 보기</string> @@ -381,19 +404,25 @@ <string name="pref_known_issues">ì•Œë ¤ì§„ ë¬¸ì œì </string> <string name="pref_no_browser_found">웹브ë¼ìš°ì €ê°€ 없습니다.</string> <string name="pref_cast_title">í¬ë¡¬ìºìŠ¤íŠ¸ 지ì›</string> - <string name="pref_cast_message">ìºìŠ¤íŠ¸ ìž¥ì¹˜ì˜ ì›ê²© 미디어 ìž¬ìƒ ê¸°ëŠ¥ 사용 (예: í¬ë¡¬ìºìŠ¤íŠ¸, 안드로ì´ë“œ TVì˜ ì˜¤ë””ì˜¤ 스피커)</string> + <string name="pref_cast_message_play_flavor">ìºìŠ¤íŠ¸ ìž¥ì¹˜ì˜ ì›ê²© 미디어 ìž¬ìƒ ê¸°ëŠ¥ 사용 (예: í¬ë¡¬ìºìŠ¤íŠ¸, 안드로ì´ë“œ TVì˜ ì˜¤ë””ì˜¤ 스피커)</string> + <string name="pref_cast_message_free_flavor">í¬ë¡¬ìºìŠ¤íŠ¸ëŠ” 서드파티 ë¼ì´ë¸ŒëŸ¬ë¦¬ê°€ 필요하지만, ì´ ë²„ì „ì˜ ì•ˆí…Œë‚˜íŒŸì—서는 사용하지 않게 ë˜ì–´ 있습니다.</string> + <string name="pref_enqueue_downloaded_title">다운로드 í•ëª© 대기열 넣기</string> + <string name="pref_enqueue_downloaded_summary">다운로드한 ì—피소드를 ëŒ€ê¸°ì—´ì— ì¶”ê°€</string> <!--Auto-Flattr dialog--> <string name="auto_flattr_enable">ìžë™ flattr 사용</string> <string name="auto_flattr_after_percent">%d í¼ì„¼íŠ¸ë¥¼ 재ìƒí•˜ë©´ ì—í”¼ì†Œë“œì— flattr합니다</string> <string name="auto_flattr_ater_beginning">재ìƒì´ 시작하면 ì—피소드 flattr</string> <string name="auto_flattr_ater_end">재ìƒì´ ë나면 ì—피소드 flattr</string> <!--Search--> - <string name="search_hint">피드나 ì—피소드 검색</string> - <string name="found_in_shownotes_label">프로그램 메모ì—ì„œ 발견</string> + <string name="search_hint">ì—피소드 검색</string> + <string name="found_in_shownotes_label">프로그램 메모ì—ì„œ </string> <string name="found_in_chapters_label">챕터ì—ì„œ 발견</string> + <string name="found_in_authors_label">작성ìžì—ì„œ 발견</string> + <string name="found_in_feeds_label">피드ì—ì„œ 발견</string> <string name="search_status_no_results">검색 결과가 없습니다</string> <string name="search_label">검색</string> <string name="found_in_title_label">ì œëª©ì—ì„œ 발견</string> + <string name="no_results_for_query">\"%1$s\" 검색 결과가 없습니다</string> <!--OPML import and export--> <string name="opml_import_txtv_button_lable">OPML 파ì¼ì„ ì´ìš©í•˜ë©´ 팟ìºìŠ¤íŠ¸ 목ë¡ì„ í•œ 팟ìºìŠ¤íŠ¸ 프로그램ì—ì„œ 다른 팟ìºìŠ¤íŠ¸ 프로그램으로 옮길 수 있습니다.</string> <string name="opml_import_option">옵션 %1$d</string> @@ -412,6 +441,7 @@ <string name="choose_file_from_filesystem">로컬 파ì¼ì‹œìŠ¤í…œì—ì„œ</string> <string name="choose_file_from_external_application">외부 앱 사용</string> <string name="opml_export_label">OPML 내보내기</string> + <string name="html_export_label">HTML 내보내기</string> <string name="exporting_label">내보내는 중…</string> <string name="export_error_label">내보내기 오류</string> <string name="opml_export_success_title">OPML 내보내기가 성공했습니다.</string> @@ -439,6 +469,9 @@ <plurals name="time_hours_quantified"> <item quantity="other">%d시간</item> </plurals> + <string name="auto_enable_label">ìžë™ 사용</string> + <string name="sleep_timer_enabled_label">취침 타ì´ë¨¸ 사용함</string> + <string name="sleep_timer_disabled_label">취침 타ì´ë¨¸ í•´ì œí•¨</string> <!--gpodder.net--> <string name="gpodnet_taglist_header">분류</string> <string name="gpodnet_toplist_header">ìƒìœ„ 팟ìºìŠ¤íŠ¸</string> @@ -468,6 +501,8 @@ <string name="gpodnetsync_auth_error_descr">ìž˜ëª»ëœ ì‚¬ìš©ìž ì´ë¦„ ë˜ëŠ” 암호</string> <string name="gpodnetsync_error_title">gpodder.net ë™ê¸°í™” 오류</string> <string name="gpodnetsync_error_descr">ë™ê¸°í™” ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤:\u0020</string> + <string name="gpodnetsync_pref_report_successful">성공</string> + <string name="gpodnetsync_pref_report_failed">실패</string> <!--Directory chooser--> <string name="selected_folder_label">ì„ íƒí•œ í´ë”:</string> <string name="create_folder_label">í´ë” 만들기</string> @@ -520,23 +555,26 @@ <string name="sp_apps_importing_feeds_msg">ë‹¨ì¼ ìš©ë„ ì•±ì—ì„œ êµ¬ë… ì •ë³´ë¥¼ ê°€ì ¸ì˜µë‹ˆë‹¤...</string> <string name="search_itunes_label">iTunes 검색</string> <string name="filter">í•„í„°</string> + <string name="search_fyyd_label">fyyd 검색</string> <!--Episodes apply actions--> <string name="all_label">모ë‘</string> - <string name="selected_all_label">ëª¨ë“ ì—피소드 ì„ íƒ</string> + <string name="selected_all_label">ëª¨ë“ ì—피소드 ì„ íƒí•¨</string> <string name="none_label">ì—†ìŒ</string> - <string name="deselected_all_label">ëª¨ë“ ì—피소드 ì„ íƒ í•´ì œ</string> + <string name="deselected_all_label">ëª¨ë“ ì—피소드 ì„ íƒ í•´ì œí•¨</string> <string name="played_label">재ìƒí•¨</string> - <string name="selected_played_label">ìž¬ìƒ ì—피소드 ì„ íƒ</string> + <string name="selected_played_label">재ìƒí•œ ì—피소드 ì„ íƒí•¨</string> <string name="unplayed_label">ìž¬ìƒ ì•ˆ 함</string> - <string name="selected_unplayed_label">ìž¬ìƒ ì•ˆ í•œ ì—피소드 ì„ íƒ</string> + <string name="selected_unplayed_label">ìž¬ìƒ ì•ˆ í•œ ì—피소드 ì„ íƒí•¨</string> <string name="downloaded_label">다운로드함</string> - <string name="selected_downloaded_label">다운로드한 ì—피소드 ì„ íƒ</string> + <string name="selected_downloaded_label">다운로드한 ì—피소드 ì„ íƒí•¨</string> <string name="not_downloaded_label">다운로드 안 함</string> - <string name="selected_not_downloaded_label">다운로드 안 í•œ ì—피소드 ì„ íƒ</string> + <string name="selected_not_downloaded_label">다운로드 안 í•œ ì—피소드 ì„ íƒí•¨</string> <string name="queued_label">ëŒ€ê¸°ì—´ì— ìžˆìŒ</string> - <string name="selected_queued_label">ì„ íƒí•œ ëŒ€ê¸°ì—´ì˜ ì—피소드</string> + <string name="selected_queued_label">ëŒ€ê¸°ì—´ì˜ ì—피소드 ì„ íƒí•¨</string> <string name="not_queued_label">ëŒ€ê¸°ì—´ì— ì—†ìŒ</string> - <string name="selected_not_queued_label">ì„ íƒí•œ 대기열 ì™¸ì˜ ì—피소드</string> + <string name="selected_not_queued_label">대기열 ì™¸ì˜ ì—피소드 ì„ íƒí•¨</string> + <string name="has_media">미디어 있ìŒ</string> + <string name="selected_has_media_label">미디어가 있는 ì—피소드 ì„ íƒí•¨</string> <!--Sort--> <string name="sort_title_a_z">ì œëª© (A \u2192 Z)</string> <string name="sort_title_z_a">ì œëª© (Z \u2192 A)</string> diff --git a/core/src/main/res/values-land/dimens.xml b/core/src/main/res/values-land/dimens.xml new file mode 100644 index 000000000..73b2b2e98 --- /dev/null +++ b/core/src/main/res/values-land/dimens.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <dimen name="media_router_controller_playback_control_start_padding">@dimen/media_router_controller_playback_control_horizontal_spacing</dimen> +</resources> diff --git a/core/src/main/res/values-lt/strings.xml b/core/src/main/res/values-lt/strings.xml new file mode 100644 index 000000000..73d1d90a8 --- /dev/null +++ b/core/src/main/res/values-lt/strings.xml @@ -0,0 +1,638 @@ +<?xml version='1.0' encoding='UTF-8'?> +<resources xmlns:tools="http://schemas.android.com/tools"> + <!--Activitiy and fragment titles--> + <string name="feeds_label">Sklaidos kanalai</string> + <string name="statistics_label">Statistika</string> + <string name="add_feed_label">PridÄ—ti tinklalaidÄ™</string> + <string name="episodes_label">Epizodai</string> + <string name="all_episodes_short_label">Visi</string> + <string name="favorite_episodes_label">MÄ—giami</string> + <string name="new_label">Nauji</string> + <string name="settings_label">Nustatymai</string> + <string name="add_new_feed_label">PridÄ—ti tinklalaidÄ™</string> + <string name="downloads_label">Atsiuntimai</string> + <string name="downloads_running_label">Vykdomi</string> + <string name="downloads_completed_label">Užbaigti</string> + <string name="downloads_log_label">Žurnalas</string> + <string name="subscriptions_label">Prenumeratos</string> + <string name="subscriptions_list_label">Prenumeratų sÄ…raÅ¡as</string> + <string name="cancel_download_label">AtÅ¡aukti\natsiuntimÄ…</string> + <string name="playback_history_label">AtkÅ«rimo istorija</string> + <string name="gpodnet_main_label">gpodder.net</string> + <string name="gpodnet_auth_label">gpodder.net prisijungimas</string> + <string name="free_space_label">%1$s laisva</string> + <string name="episode_cache_full_title">Epizodų podÄ—lis pilnas</string> + <string name="episode_cache_full_message">Pasiektas epizodų podÄ—lio dydžio limitas. Nustatymuose galite padidinti podÄ—lio dydį.</string> + <!--Statistics fragment--> + <string name="total_time_listened_to_podcasts">Bendra perklausytų tinklalaidžių trukmÄ—:</string> + <string name="statistics_details_dialog">Paleisti %1$d iÅ¡ %2$d epizodų.\n\nPerklausyta %3$s iÅ¡ %4$s.</string> + <string name="statistics_mode">Statistikos režimas</string> + <string name="statistics_mode_normal">ApskaiÄiuoti tikrÄ…jÄ… atkÅ«rimo trukmÄ™. Perklausa dukart skaiÄiuojama dvigubai, o pažymÄ—jimas perklausytu neskaiÄiuojamas</string> + <string name="statistics_mode_count_all">Sumuoti visas tinklalaides, pažymÄ—tas kaip perklausytas</string> + <string name="statistics_speed_not_counted">Atkreipkite dÄ—mesį: į atkÅ«rimo spartÄ… neatsižvelgiama.</string> + <!--Main activity--> + <string name="drawer_open">Atverti meniu</string> + <string name="drawer_close">Uždaryti meniu</string> + <string name="drawer_preferences">StalÄiaus parinktys</string> + <string name="drawer_feed_order_unplayed_episodes">Rikiuoti pagal skaitliuko reikÅ¡mÄ™</string> + <string name="drawer_feed_order_alphabetical">Rikiuoti pagal abÄ—cÄ—lÄ™</string> + <string name="drawer_feed_order_last_update">Rikiuoti pagal publikavimo datÄ…</string> + <string name="drawer_feed_order_most_played">Rikiuoti pagal perklausytų epizodų kiekį</string> + <string name="drawer_feed_counter_new_unplayed">Naujų, dar neperklausytų epizodų skaiÄius</string> + <string name="drawer_feed_counter_new">Naujų epizodų skaiÄius</string> + <string name="drawer_feed_counter_unplayed">Neperklausytų epizodų skaiÄius</string> + <string name="drawer_feed_counter_downloaded">Atsisiųstų epizodų skaiÄius</string> + <string name="drawer_feed_counter_none">Nieko</string> + <!--Webview actions--> + <string name="open_in_browser_label">Atverti narÅ¡yklÄ—je</string> + <string name="copy_url_label">Kopijuoti URL</string> + <string name="share_url_label">Dalintis URL</string> + <string name="copied_url_msg">URL nukopijuotas į iÅ¡karpinÄ™</string> + <string name="go_to_position_label">PerÅ¡okti į Å¡iÄ… pozicijÄ…</string> + <!--Playback history--> + <string name="clear_history_label">IÅ¡valyti istorijÄ…</string> + <!--Other--> + <string name="confirm_label">Patvirtinti</string> + <string name="cancel_label">AtÅ¡aukti</string> + <string name="yes">Taip</string> + <string name="no">Ne</string> + <string name="reset">Nustatyti iÅ¡ naujo</string> + <string name="author_label">Autorius</string> + <string name="language_label">Kalba</string> + <string name="url_label">URL</string> + <string name="podcast_settings_label">Nustatymai</string> + <string name="cover_label">PaveikslÄ—lis</string> + <string name="error_label">Klaida</string> + <string name="error_msg_prefix">Ä®vyko klaida:</string> + <string name="refresh_label">Atnaujinti</string> + <string name="external_storage_error_msg">NÄ—ra prieinamų iÅ¡orinių atmintinių. Patikrinkite, jog iÅ¡orinÄ—s atmintinÄ—s yra prijungtos, kad programÄ—lÄ— tinkamai veiktų.</string> + <string name="chapters_label">Skyriai</string> + <string name="chapter_duration">TrukmÄ—: %1$s</string> + <string name="shownotes_label">Laidos užraÅ¡ai</string> + <string name="description_label">ApraÅ¡ymas</string> + <string name="most_recent_prefix">Naujausias epizodas:\u0020</string> + <string name="episodes_suffix">\u0020epizodai</string> + <string name="length_prefix">TrukmÄ—:\u0020</string> + <string name="size_prefix">Dydis:\u0020</string> + <string name="processing_label">Apdorojama</string> + <string name="loading_label">Kraunama...</string> + <string name="save_username_password_label">IÅ¡saugoti vartotojo vardÄ… ir slaptažodį</string> + <string name="close_label">Užverti</string> + <string name="retry_label">Bandyti vÄ—l</string> + <string name="auto_download_label">Ä®traukti į automatinius atsiuntimus</string> + <string name="auto_download_apply_to_items_title">Pritaikyti ankstesniems epizodams</string> + <string name="auto_download_apply_to_items_message">Naujieji <i>Automatinio atsiuntimo</i> nustatymai bus automatiÅ¡kai pritaikyti naujiems epizodams.\nAr norite Å¡iuos nustatymus taip pat pritaikyti ir anksÄiau iÅ¡leistiems epizodams?</string> + <string name="auto_delete_label">AutomatiÅ¡kai trinti epizodus</string> + <string name="parallel_downloads_suffix">\u0020lygiagretÅ«s atsiuntimai</string> + <string name="feed_auto_download_global">Globali numatytoji</string> + <string name="feed_auto_download_always">Visada</string> + <string name="feed_auto_download_never">Niekada</string> + <string name="send_label">Siųsti...</string> + <string name="episode_cleanup_never">Niekada</string> + <string name="episode_cleanup_queue_removal">Jei nÄ—ra eilÄ—je</string> + <string name="episode_cleanup_after_listening">Pabaigus klausyti</string> + <plurals name="episode_cleanup_days_after_listening"> + <item quantity="one">PraÄ—jus 1 dienai nuo perklausymo</item> + <item quantity="few">PraÄ—jus %d dienoms nuo perklausymo</item> + <item quantity="other">PraÄ—jus %d dienų nuo perklausymo</item> + </plurals> + <!--'Add Feed' Activity labels--> + <string name="feedurl_label">Sklaidos kanalo URL</string> + <string name="etxtFeedurlHint">www.example.com/feed</string> + <string name="txtvfeedurl_label">PridÄ—ti tinklalaidÄ™ pagal URL adresÄ…</string> + <string name="podcastdirectories_label">Rasti tinklalaidÄ™ aplanke</string> + <string name="podcastdirectories_descr">Naujų tinklalaidžių atrasti galite ieÅ¡kodami „iTunes“ ar „fyyd“ arba narÅ¡ydami „gpodder.net“ kataloge pagal pavadinimÄ…, kategorijÄ… ar populiarumÄ….</string> + <string name="browse_gpoddernet_label">NarÅ¡yti gpodder.net svetainÄ—je</string> + <!--Actions on feeds--> + <string name="mark_all_read_label">PažymÄ—ti visus kaip perklausytus</string> + <string name="mark_all_read_msg">Visi epizodai pažymÄ—ti kaip perklausyti</string> + <string name="mark_all_read_confirmation_msg">Patvirtinkite, jog norite pažymÄ—ti visus epizodus kaip perklausytus.</string> + <string name="mark_all_read_feed_confirmation_msg">Patvirtinkite, jog norite pažymÄ—ti visus Å¡io sklaidos kanalo epizodus kaip perklausytus.</string> + <string name="mark_all_seen_label">PažymÄ—ti visus kaip matytus</string> + <string name="mark_all_seen_msg">Visi epizodai pažymÄ—ti kaip matyti</string> + <string name="mark_all_seen_confirmation_msg">Patvirtinkite, jog norite pažymÄ—ti visus epizodus kaip matytus.</string> + <string name="show_info_label">Rodyti informacijÄ…</string> + <string name="rename_feed_label">Pervadinti tinklalaidÄ™</string> + <string name="remove_feed_label">PaÅ¡alinti tinklalaidÄ™</string> + <string name="share_label">Dalintis...</string> + <string name="share_link_label">Dalintis nuoroda</string> + <string name="share_link_with_position_label">Dalintis nuoroda su pozicija</string> + <string name="share_feed_url_label">Dalintis sklaidos kanalo URL</string> + <string name="share_item_url_label">Dalintis epizodo failo URL</string> + <string name="share_item_url_with_position_label">Dalintis epizodo failo adresu su pozicija</string> + <string name="feed_delete_confirmation_msg">Patvirtinkite, jog norite iÅ¡trinti sklaidos kanalÄ… „%1$s“ bei VISUS atsisiųstus Å¡io sklaidos kanalo epizodus.</string> + <string name="feed_remover_msg">Å alinamas sklaidos kanalas</string> + <string name="load_complete_feed">Atnaujinti visÄ… sklaidos kanalÄ…</string> + <string name="hide_episodes_title">SlÄ—pti epizodus</string> + <string name="episode_actions">Pritaikyti veiksmus</string> + <string name="hide_unplayed_episodes_label">Neperklausyti</string> + <string name="hide_paused_episodes_label">Pristabdyti</string> + <string name="hide_played_episodes_label">Perklausyti</string> + <string name="hide_queued_episodes_label">Esantys eilÄ—je</string> + <string name="hide_not_queued_episodes_label">Nesantys eilÄ—je</string> + <string name="hide_downloaded_episodes_label">Atsiųsti</string> + <string name="hide_not_downloaded_episodes_label">Neatsiųsti</string> + <string name="hide_has_media_label">Turintys medijos failų</string> + <string name="filtered_label">Filtruota</string> + <string name="refresh_failed_msg">{fa-exclamation-circle} Paskutinis atnaujinimas nepavyko</string> + <string name="open_podcast">Atverti tinklalaidÄ™</string> + <!--actions on feeditems--> + <string name="download_label">Atsisiųsti</string> + <string name="play_label">Atkurti</string> + <string name="pause_label">Pristabdyti</string> + <string name="stop_label">Sustabdyti</string> + <string name="stream_label">Klausytis tiesiogiai</string> + <string name="remove_label">PaÅ¡alinti</string> + <string name="delete_label">IÅ¡trinti</string> + <string name="remove_episode_lable">PaÅ¡alinti epizodÄ…</string> + <string name="marked_as_seen_label">PažymÄ—tas kaip matytas</string> + <string name="mark_read_label">PažymÄ—ti kaip perklausytÄ…</string> + <string name="marked_as_read_label">PažymÄ—tas kaip perklausytas</string> + <string name="mark_unread_label">PažymÄ—ti kaip neperklausytÄ…</string> + <string name="add_to_queue_label">PridÄ—ti į eilÄ™</string> + <string name="added_to_queue_label">PridÄ—tas į eilÄ™</string> + <string name="remove_from_queue_label">PaÅ¡alinti iÅ¡ eilÄ—s</string> + <string name="add_to_favorite_label">PridÄ—ti prie mÄ—giamų</string> + <string name="added_to_favorites">PridÄ—tas prie mÄ—giamų</string> + <string name="remove_from_favorite_label">PaÅ¡alinti iÅ¡ mÄ—giamų</string> + <string name="removed_from_favorites">PaÅ¡alintas iÅ¡ mÄ—giamų</string> + <string name="visit_website_label">Aplankyti svetainÄ™</string> + <string name="support_label">Paremti „Flattr“</string> + <string name="skip_episode_label">Praleisti epizodÄ…</string> + <string name="activate_auto_download">Ä®jungti automatinį atsiuntimÄ…</string> + <string name="deactivate_auto_download">IÅ¡jungti automatinį atsiuntimÄ…</string> + <string name="reset_position">Nustatyti atkÅ«rimo pozicijÄ… iÅ¡ naujo</string> + <string name="removed_item">Elementas paÅ¡alintas</string> + <!--Download messages and labels--> + <string name="download_successful">sÄ—kmingi</string> + <string name="download_failed">nepavyko</string> + <string name="download_pending">Laukia atsiuntimo</string> + <string name="download_running">Atsiuntimas vyksta</string> + <string name="download_error_device_not_found">Nerastas atmintinÄ—s įrenginys</string> + <string name="download_error_insufficient_space">TrÅ«ksta laisvos vietos</string> + <string name="download_error_file_error">Failo klaida</string> + <string name="download_error_http_data_error">HTTP duomenų klaida</string> + <string name="download_error_error_unknown">Nežinoma klaida</string> + <string name="download_error_parser_exception">IÅ¡imtinÄ— situacija analizatoriuje</string> + <string name="download_error_unsupported_type">Nepalaikomas sklaidos kanalo tipas</string> + <string name="download_error_connection_error">Susijungimo klaida</string> + <string name="download_error_unknown_host">Nežinomas serveris</string> + <string name="download_error_unauthorized">Tapatumo nustatymo klaida</string> + <string name="download_error_file_type_type">Failo tipo klaida</string> + <string name="download_error_forbidden">Uždrausta</string> + <string name="cancel_all_downloads_label">AtÅ¡aukti visus atsiuntimus</string> + <string name="download_canceled_msg">Atsiuntimas atÅ¡auktas</string> + <string name="download_canceled_autodownload_enabled_msg">Atsiuntimas atÅ¡auktas\n<i>Automatinis atsiuntimas</i> Å¡iam elementui iÅ¡jungtas</string> + <string name="download_report_title">Atsiuntimai užbaigti su klaida (-omis)</string> + <string name="download_report_content_title">Atsiuntimų ataskaita</string> + <string name="download_error_malformed_url">Netvarkingas URL</string> + <string name="download_error_io_error">Ä®vesties/iÅ¡vesties klaida</string> + <string name="download_error_request_error">Užklausos klaida</string> + <string name="download_error_db_access">Duomenų bazÄ—s prieigos klaida</string> + <plurals name="downloads_left"> + <item quantity="one">Liko %d atsiuntimas</item> + <item quantity="few">Liko %d atsiuntimai</item> + <item quantity="other">Liko %d atsiuntimų</item> + </plurals> + <string name="downloads_processing">Apdorojami atsiuntimai</string> + <string name="download_notification_title">AtsiunÄiami tinklalaidÄ—s duomenys</string> + <string name="download_report_content">%1$d atsiuntimai sÄ—kmingi, %2$d nepavyko</string> + <string name="download_log_title_unknown">Nežinomas pavadinimas</string> + <string name="download_type_feed">Sklaidos kanalas</string> + <string name="download_type_media">Medijos failas</string> + <string name="download_type_image">PaveikslÄ—lis</string> + <string name="download_request_error_dialog_message_prefix">Ä®vyko klaida bandant atsisiųsti failÄ…:\u0020</string> + <string name="authentication_notification_title">Reikalingas tapatumo nustatymas</string> + <string name="authentication_notification_msg">Å is iÅ¡teklius reikalauja vartotojo vardo bei slaptažodžio</string> + <string name="confirm_mobile_download_dialog_title">Patvirtinkite atsiuntimÄ… mobiliuoju internetu</string> + <string name="confirm_mobile_download_dialog_message_not_in_queue">Atsiuntimas mobiliuoju internetu iÅ¡jungtas nustatymuose.\n\nGalite pasirinkti tik pridÄ—ti epizodÄ… į eilÄ™ arba laikinai leisti atsiuntimÄ….\n\n<small>JÅ«sų pasirinkimas bus prisimenamas 10 minuÄių.</small></string> + <string name="confirm_mobile_download_dialog_message">Atsiuntimas mobiliuoju internetu iÅ¡jungtas nustatymuose.\n\nAr norite laikinai leisti atsiuntimÄ…?\n\n<small>JÅ«sų pasirinkimas bus prisimenamas 10 minuÄių.</small></string> + <string name="confirm_mobile_download_dialog_only_add_to_queue">PridÄ—ti į eilÄ™</string> + <string name="confirm_mobile_download_dialog_enable_temporarily">Laikinai leisti</string> + <!--Mediaplayer messages--> + <string name="player_error_msg">Klaida!</string> + <string name="player_stopped_msg">AtkÅ«rimas nevyksta</string> + <string name="player_preparing_msg">RuoÅ¡iamasi</string> + <string name="player_ready_msg">PasiruoÅ¡Ä™s</string> + <string name="player_seeking_msg">IeÅ¡koma</string> + <string name="playback_error_server_died">Serveris nepasiekiamas</string> + <string name="playback_error_unknown">Nežinoma klaida</string> + <string name="no_media_playing_label">AtkÅ«rimas nevyksta</string> + <string name="player_buffering_msg">Buferizuojama</string> + <string name="playbackservice_notification_title">Atkuriama tinklalaidÄ—</string> + <string name="unknown_media_key">„AntennaPod“ – nežinomas medijos klaviÅ¡as: %1$d</string> + <!--Queue operations--> + <string name="lock_queue">Užrakinti eilÄ™</string> + <string name="unlock_queue">Atrakinti eilÄ™</string> + <string name="queue_locked">EilÄ— užrakinta</string> + <string name="queue_unlocked">EilÄ— atrakinta</string> + <string name="clear_queue_label">IÅ¡valyti eilÄ™</string> + <string name="undo">AtÅ¡aukti</string> + <string name="removed_from_queue">Elementas paÅ¡alintas</string> + <string name="move_to_top_label">Perkelti į viršų</string> + <string name="move_to_bottom_label">Perkelti į apaÄiÄ…</string> + <string name="sort">Rikiuoti</string> + <string name="date">Data</string> + <string name="duration">TrukmÄ—</string> + <string name="episode_title">Epizodo pavadinimas</string> + <string name="feed_title">Sklaidos kanalo pavadinimas</string> + <string name="ascending">DidÄ—janÄia tvarka</string> + <string name="descending">MažėjanÄia tvarka</string> + <string name="clear_queue_confirmation_msg">Patvirtinkite, jog norite paÅ¡alinti VISUS epizodus iÅ¡ perklausos eilÄ—s</string> + <!--Flattr--> + <string name="flattr_auth_label">„Flattr“ prisijungimas</string> + <string name="flattr_auth_explanation">Jei norite pradÄ—ti tapatumo nustatymo procesÄ…, paspauskite žemiau esantį mygtukÄ…. BÅ«site nukreipti į „Flattr“ prisijungimo langÄ… narÅ¡yklÄ—je ir papraÅ¡yti suteikti „AntennaPod“ programÄ—lei leidimÄ… paremti turinį. Kai suteiksite leidimÄ…, bÅ«site automatiÅ¡kai sugrąžinti į šį ekranÄ….</string> + <string name="authenticate_label">Nustatyti tapatumÄ…</string> + <string name="return_home_label">Grįžti atgal</string> + <string name="flattr_auth_success">Tapatumas patvirtintas! Nuo Å¡iol programÄ—lÄ—je galÄ—site paremti epizodus naudodami „Flattr“ paslaugÄ….</string> + <string name="no_flattr_token_title">Nerastas „Flattr“ žetonas</string> + <string name="no_flattr_token_notification_msg">PanaÅ¡u, jog JÅ«sų „Flattr“ paskyra nesusieta su „AntennaPod“. SpustelÄ—kite Äia, jei norite nustatyti tapatybÄ™.</string> + <string name="no_flattr_token_msg">PanaÅ¡u, jog JÅ«sų „Flattr“ paskyra nÄ—ra susieta su „AntennaPod“. Galite susieti savo paskyrÄ… su „AntennaPod“, jei norite paremti turinį naudodamiesi programÄ—le, arba paremkite elementÄ… apsilankÄ™ jo svetainÄ—je.</string> + <string name="authenticate_now_label">Tikrinti tapatumÄ…</string> + <string name="action_forbidden_title">Veiksmas uždraustas</string> + <string name="action_forbidden_msg">„AntennaPod“ neturi leidimo Å¡iam veiksmui atlikti. Gali bÅ«ti, jog „AntennaPod“ prieigos žetono galiojimas buvo sustabdytas. Galite iÅ¡ naujo patvirtinti tapatybÄ™ arba aplankyti elemento svetainÄ™.</string> + <string name="access_revoked_title">Prieiga panaikinta</string> + <string name="access_revoked_info">SÄ—kmingai sustabdÄ—te „AntennaPod“ prieigos prie JÅ«sų paskyros žetono galiojimÄ…. Jei norite užbaigti šį procesÄ…, paÅ¡alinkite Å¡iÄ… programÄ—lÄ™ iÅ¡ patvirtintų programÄ—lių sÄ…raÅ¡o paskyros nustatymuose „Flattr“ svetainÄ—je.</string> + <!--Flattr--> + <string name="flattr_click_success">Vienas elementas paremtas „Flattr“!</string> + <string name="flattr_click_success_count">%d elementai paremti „Flattr“!</string> + <string name="flattr_click_success_queue">Paremta „Flattr“: %s.</string> + <string name="flattr_click_failure_count">„Flattr“ nepavyko paremti %d elementų!</string> + <string name="flattr_click_failure">„Flattr“ neparemta: %s.</string> + <string name="flattr_click_enqueued">Å is elementas bus paremtas „Flattr“ vÄ—liau</string> + <string name="flattring_thing">Remiama „Flattr“: %s</string> + <string name="flattring_label">„AntennaPod“ Å¡iuo metu paremia „Flattr“</string> + <string name="flattrd_label">„AntennaPod“ parama „Flattr“ pavyko</string> + <string name="flattrd_failed_label">„AntennaPod“ parama „Flattr“ nepavyko</string> + <string name="flattr_retrieving_status">Nuskaitomi „Flattr“ paremti elementai</string> + <!--Variable Speed--> + <string name="download_plugin_label">Atsiųsti įskiepį</string> + <string name="no_playback_plugin_title">Ä®skiepis neįdiegtas</string> + <string name="no_playback_plugin_or_sonic_msg">Jei norite, jog kintamos atkÅ«rimo spartos funkcija veiktų, patartina įjungti įtaisytÄ…jÄ… „Sonic“ medijos leistuvÄ™ [„Android“ 4.1+].\n\nKaip pakaitalÄ…, naudodamiesi „Play Store“, galite atsisiųsti treÄiųjų Å¡alių įskiepį <i>Prestissimo</i>.\nBet kokie nesklandumai dÄ—l „Prestissimo“ veikimo yra ne „AntennaPod“ atsakomybÄ—, todÄ—l apie juos reikÄ—tų praneÅ¡ti įskiepio autoriams.</string> + <string name="set_playback_speed_label">AtkÅ«rimo spartos</string> + <string name="enable_sonic">Ä®jungti „Sonic“</string> + <!--Empty list labels--> + <string name="no_items_label">Å iame sÄ…raÅ¡e nÄ—ra elementų.</string> + <string name="no_feeds_label">Kol kas neprenumeruojate jokio sklaidos kanalo.</string> + <string name="no_chapters_label">Å is epizodas neturi skyrių.</string> + <string name="no_shownotes_label">Å is epizodas neturi užrašų.</string> + <!--Preferences--> + <string name="storage_pref">AtmintinÄ—</string> + <string name="project_pref">Projektas</string> + <string name="other_pref">Kita</string> + <string name="about_pref">Apie</string> + <string name="queue_label">EilÄ—</string> + <string name="services_label">Paslaugos</string> + <string name="flattr_label">Flattr</string> + <string name="pref_episode_cleanup_title">Epizodų valymas</string> + <string name="pref_episode_cleanup_summary">Epizodai, nesantys eilÄ—je ar tarp mÄ—giamųjų, gali bÅ«ti iÅ¡trinti automatinio atsiuntimo metu pritrÅ«kus laisvos vietos naujiems epizodams </string> + <string name="pref_pauseOnDisconnect_sum">Pristabdyti atkÅ«rimÄ…, kai atjungiamos ausinÄ—s ar „Bluetooth“</string> + <string name="pref_unpauseOnHeadsetReconnect_sum">PratÄ™sti atkÅ«rimÄ…, kai ausinÄ—s pakartotinai prijungiamos</string> + <string name="pref_unpauseOnBluetoothReconnect_sum">PratÄ™sti atkÅ«rimÄ…, kai pakartotinai prisijungiama prie „Bluetooth“</string> + <string name="pref_hardwareForwardButtonSkips_title">Mygtukas „pirmyn“ perÅ¡oka epizodÄ…</string> + <string name="pref_hardwareForwardButtonSkips_sum">Paspaudus aparatinį mygtukÄ… „pirmyn“ perÅ¡okti į kitÄ… epizodÄ… vietoje greito persukimo į priekį.</string> + <string name="pref_hardwarePreviousButtonRestarts_title">Mygtukas „ankstesnis“ paleidžia iÅ¡ naujo</string> + <string name="pref_hardwarePreviousButtonRestarts_sum">Paspaudus aparatinį mygtukÄ… „ankstesnis“ paleisti dabartinį epizodÄ… nuo pradžių vietoj epizodo perÅ¡okimo</string> + <string name="pref_followQueue_sum">AtkÅ«rimui pasibaigus perÅ¡okti į kitÄ… eilÄ—s elementÄ…</string> + <string name="pref_auto_delete_sum">IÅ¡trinti epizodÄ… pasibaigus atkÅ«rimui</string> + <string name="pref_auto_delete_title">Automatinis iÅ¡trynimas</string> + <string name="pref_smart_mark_as_played_sum">ŽymÄ—ti epizodus kaip perklausytus iki pilnos perklausos likus nurodytam sekundžių kiekiui.</string> + <string name="pref_smart_mark_as_played_title">IÅ¡manus perklausų žymÄ—jimas</string> + <string name="pref_skip_keeps_episodes_sum">Palikti epizodus, kai Å¡ie praleidžiami</string> + <string name="pref_skip_keeps_episodes_title">Palikti praleistus epizodus</string> + <string name="playback_pref">AtkÅ«rimas</string> + <string name="network_pref">Tinklas</string> + <string name="pref_autoUpdateIntervallOrTime_title">Atnaujinimų intervalas ar dienos metas</string> + <string name="pref_autoUpdateIntervallOrTime_sum">Apibrėžkite automatinio sklaidos kanalų atnaujinimo laiko intervalÄ… ar tikslų dienos metÄ….</string> + <string name="pref_autoUpdateIntervallOrTime_message">Galite nustatyti <i>intervalÄ…</i>, pvz. „kas 2 valandas“, nurodyti tikslų <i>dienos metÄ…</i>, pvz. „07:00“ arba visiÅ¡kai <i>iÅ¡jungti</i> automatinius atnaujinimus.\n\n<small>Atkreipkite dÄ—mesį: atnaujinimo laikas nÄ—ra tikslus, galimas trumpas uždelsimas.</small></string> + <string name="pref_autoUpdateIntervallOrTime_Disable">IÅ¡jungti</string> + <string name="pref_autoUpdateIntervallOrTime_Interval">Nustatyti intervalÄ…</string> + <string name="pref_autoUpdateIntervallOrTime_TimeOfDay">Nustatyti dienos metÄ…</string> + <string name="pref_autoUpdateIntervallOrTime_every">kas %1$s</string> + <string name="pref_autoUpdateIntervallOrTime_at">lygiai %1$s</string> + <string name="pref_downloadMediaOnWifiOnly_sum">Medijos failus atsiųsti tik naudojantis belaidžiu tinklu</string> + <string name="pref_followQueue_title">NenutrÅ«kstamas atkÅ«rimas</string> + <string name="pref_downloadMediaOnWifiOnly_title">Atsisiųsti tik belaidžiu tinklu</string> + <string name="pref_pauseOnHeadsetDisconnect_title">Ausinių atjungimas</string> + <string name="pref_unpauseOnHeadsetReconnect_title">Pakartotinai prijungus ausines</string> + <string name="pref_unpauseOnBluetoothReconnect_title">Pakartotinai prisijungus prie „Bluetooth“</string> + <string name="pref_mobileUpdate_title">Atnaujinimai mobiliuoju internetu</string> + <string name="pref_mobileUpdate_sum">Leisti atnaujinimus mobiliuoju internetu</string> + <string name="refreshing_label">Atnaujinama</string> + <string name="flattr_settings_label">„Flattr“ nustatymai</string> + <string name="pref_flattr_auth_title">„Flattr“ prisijungimas</string> + <string name="pref_flattr_auth_sum">Prisijunkite prie savo „Flattr“ paskyros ir remkite turinį tiesiai iÅ¡ programÄ—lÄ—s</string> + <string name="pref_flattr_this_app_title">Paremti Å¡iÄ… programÄ—lÄ™ per „Flattr“</string> + <string name="pref_flattr_this_app_sum">Paskatinkite „AntennaPod“ tobulinimÄ… paremdami jÄ… per „Flattr“. AÄiÅ«!</string> + <string name="pref_revokeAccess_title">Panaikinti prieigÄ…</string> + <string name="pref_revokeAccess_sum">Panaikinti Å¡ios programÄ—lÄ—s prieigos prie JÅ«sų „Flattr“ paskyros leidimÄ…. </string> + <string name="pref_auto_flattr_title">Automatinis rÄ—mimas per „Flattr“</string> + <string name="pref_auto_flattr_sum">KonfigÅ«ruoti automatinį rÄ—mimÄ… per „Flattr“</string> + <string name="user_interface_label">Vartotojo sÄ…saja</string> + <string name="pref_set_theme_title">Pasirinkti temÄ…</string> + <string name="pref_nav_drawer_title">Derinti narÅ¡ymo stalÄių</string> + <string name="pref_nav_drawer_sum">Derinti narÅ¡ymo stalÄiaus iÅ¡vaizdÄ….</string> + <string name="pref_nav_drawer_items_title">Nustatyti narÅ¡ymo stalÄiaus elementus</string> + <string name="pref_nav_drawer_items_sum">Keisti narÅ¡ymo stalÄiuje rodomus elementus.</string> + <string name="pref_nav_drawer_feed_order_title">Nustatyti prenumeratų tvarkÄ…</string> + <string name="pref_nav_drawer_feed_order_sum">Keiskite prenumeratų tvarkÄ…</string> + <string name="pref_nav_drawer_feed_counter_title">Nustatyti prenumeratų skaitliukÄ…</string> + <string name="pref_nav_drawer_feed_counter_sum">Keisti prenumeratų skaitliuko rodomÄ… informacijÄ…</string> + <string name="pref_set_theme_sum">Keisti AntennaPod iÅ¡vaizdÄ….</string> + <string name="pref_automatic_download_title">Automatinis atsiuntimas</string> + <string name="pref_automatic_download_sum">KonfigÅ«ruoti automatinį epizodų atsiuntimÄ….</string> + <string name="pref_autodl_wifi_filter_title">Ä®jungti belaidžių tinklų filtrÄ…</string> + <string name="pref_autodl_wifi_filter_sum">Leisti automatinį atsiuntimÄ… tik prisijungus prie nurodytų belaidžių tinklų.</string> + <string name="pref_automatic_download_on_battery_title">Atsiuntimas ne įkrovimo metu</string> + <string name="pref_automatic_download_on_battery_sum">Leisti automatinį atsiuntimÄ… kai baterija nÄ—ra įkraunama</string> + <string name="pref_parallel_downloads_title">LygiagretÅ«s atsiuntimai</string> + <string name="pref_episode_cache_title">Epizodų podÄ—lis</string> + <string name="pref_theme_title_light">Å viesi</string> + <string name="pref_theme_title_dark">Tamsi</string> + <string name="pref_episode_cache_unlimited">Neribojamas</string> + <string name="pref_update_interval_hours_plural">valandos</string> + <string name="pref_update_interval_hours_singular">valanda</string> + <string name="pref_update_interval_hours_manual">Rankinis</string> + <string name="pref_gpodnet_authenticate_title">Prisijungimas</string> + <string name="pref_gpodnet_authenticate_sum">NorÄ—dami sinchronizuoti prenumeratas, prisijunkite prie savo „gpodder.net“ paskyros.</string> + <string name="pref_gpodnet_logout_title">Atsijungti</string> + <string name="pref_gpodnet_logout_toast">SÄ—kmingai atsijungta</string> + <string name="pref_gpodnet_setlogin_information_title">Keisti prisijungimo duomenis</string> + <string name="pref_gpodnet_setlogin_information_sum">Keisti prisijungimo prie „gpodder.net“ paskyros duomenis.</string> + <string name="pref_gpodnet_sync_changes_title">Sinchronizuoti pakeitimus dabar</string> + <string name="pref_gpodnet_sync_changes_sum">Sinchronizuoti prenumeratų bei epizodų bÅ«senų pasikeitimus su „gpodder.net“.</string> + <string name="pref_gpodnet_full_sync_title">PradÄ—ti pilnÄ… sinchronizavimÄ… dabar</string> + <string name="pref_gpodnet_full_sync_sum">Sinchronizuoti visas prenumeratas bei epizodų bÅ«senas su „gpodder.net“.</string> + <string name="pref_gpodnet_sync_sum_last_sync_line">Paskutinis sinchronizavimo bandymas: %1$s (%2$s)</string> + <string name="pref_gpodnet_sync_started">PradÄ—tas sinchronizavimas</string> + <string name="pref_gpodnet_full_sync_started">PradÄ—tas pilnas sinchronizavimas</string> + <string name="pref_gpodnet_login_status"><![CDATA[Prisijungta kaip <i>%1$s</i> naudojant įrenginį <i>%2$s</i>]]></string> + <string name="pref_gpodnet_notifications_title">Rodyti sinchronizavimo klaidų praneÅ¡imus</string> + <string name="pref_gpodnet_notifications_sum">Å is nustatymas negalioja tapatumo nustatymo klaidoms.</string> + <string name="pref_playback_speed_title">AtkÅ«rimo sparta</string> + <string name="pref_playback_speed_sum">Derinkite prieinamas garso atkÅ«rimo spartas</string> + <string name="pref_fast_forward">Persukimo į priekį trukmÄ—</string> + <string name="pref_fast_forward_sum">Derinkite, per kiek sekundžių Å¡oktelÄ—ti į priekį kai paspaudžiamas persukimo į priekį mygtukas</string> + <string name="pref_rewind">Atsukimo atgal trukmÄ—</string> + <string name="pref_rewind_sum">Derinkite, per kiek sekundžių Å¡oktelÄ—ti atgal kai paspaudžiamas atsukimo atgal mygtukas</string> + <string name="pref_gpodnet_sethostname_title">Nustatyti serverį</string> + <string name="pref_gpodnet_sethostname_use_default_host">Naudoti numatytÄ…jį serverį</string> + <string name="pref_expandNotify_title">IÅ¡plÄ—sti praneÅ¡imus</string> + <string name="pref_expandNotify_sum">IÅ¡plÄ—sti programos praneÅ¡imus, kad bÅ«tų atvaizduojami atkÅ«rimo valdymo mygtukai.</string> + <string name="pref_persistNotify_title">PastovÅ«s atkÅ«rimo valdikliai</string> + <string name="pref_persistNotify_sum">Pristabdžius atkÅ«rimÄ… palikti valdiklius ekrano užrakte bei programų praneÅ¡imuose. </string> + <string name="pref_compact_notification_buttons_title">Nustatyti ekrano užrakto mygtukus</string> + <string name="pref_compact_notification_buttons_sum">Keisti ekrano užrakte matomus atkÅ«rimo valdymo mygtukus. AtkÅ«rimo/pristabdymo mygtukas matomas visada.</string> + <string name="pref_compact_notification_buttons_dialog_title">Pasirinkite daugiausiai %1$d elementus</string> + <string name="pref_compact_notification_buttons_dialog_error">Galite pasirinkti daugiausiai %1$d elementus.</string> + <string name="pref_lockscreen_background_title">Nustatyti ekrano užrakto fonÄ…</string> + <string name="pref_lockscreen_background_sum">Atkuriamo epizodo paveikslÄ—lį naudoti kaip ekrano užrakto fonÄ…. PaveikslÄ—lis taip pat bus matomas treÄiųjų Å¡alių programÄ—lÄ—se.</string> + <string name="pref_showDownloadReport_title">Rodyti atsiuntimų ataskaitÄ…</string> + <string name="pref_showDownloadReport_sum">Atsiuntimui nepavykus, sukurti ataskaitÄ… su iÅ¡samiu klaidų apraÅ¡ymu.</string> + <string name="pref_expand_notify_unsupport_toast">AnkstesnÄ—s nei 4.1 „Android“ versijos nepalaiko iÅ¡plÄ—stų programos praneÅ¡imų.</string> + <string name="pref_queueAddToFront_sum">Naujus epizodus dÄ—ti į eilÄ—s priekį.</string> + <string name="pref_queueAddToFront_title">DÄ—ti į eilÄ—s priekį</string> + <string name="pref_smart_mark_as_played_disabled">IÅ¡jungtas</string> + <string name="pref_image_cache_size_title">PaveikslÄ—lių podÄ—lio dydis</string> + <string name="pref_image_cache_size_sum">PaveikslÄ—lių podÄ—lio diske dydis.</string> + <string name="crash_report_title">Strigties praneÅ¡imas</string> + <string name="crash_report_sum">Siųsti paskiausios strigties praneÅ¡imÄ… el. paÅ¡tu</string> + <string name="send_email">Siųsti el. laiÅ¡kÄ…</string> + <string name="experimental_pref">Eksperimentinis</string> + <string name="pref_sonic_title">„Sonic“ medijos leistuvÄ—</string> + <string name="pref_sonic_message">Naudoti įtaisytÄ…jÄ… „Sonic“ medijos leistuvÄ™ vietoje savosios „Android“ medijos leistuvÄ—s ir „Prestissimo“ </string> + <string name="pref_current_value">DabartinÄ— reikÅ¡mÄ—: %1$s</string> + <string name="pref_proxy_title">Ä®galiotasis serveris</string> + <string name="pref_proxy_sum">Nustatyti įgaliotÄ…jį tinklo serverį</string> + <string name="pref_faq">DUK</string> + <string name="pref_known_issues">Žinomos problemos</string> + <string name="pref_no_browser_found">Nerasta jokia interneto narÅ¡yklÄ—.</string> + <string name="pref_cast_title">„Chromecast“ palaikymas</string> + <string name="pref_cast_message_play_flavor">Ä®jungti nuotolinio medijos atkÅ«rimo „Cast“ įrenginiuose (pvz. „Chromecast“, garso kolonÄ—lÄ—s ar „Android TV“) palaikymÄ…</string> + <string name="pref_cast_message_free_flavor">„Chromecast“ palaikymui reikalingos nuosavybinÄ—s treÄiųjų Å¡alių bibliotekos, kurios yra negalimos Å¡ioje „AntennaPod“ versijoje.</string> + <string name="pref_enqueue_downloaded_title">Atsiuntimus pridÄ—ti į eilÄ™</string> + <string name="pref_enqueue_downloaded_summary">Parsiuntus epizodus, pridÄ—ti juos į eilÄ™</string> + <!--Auto-Flattr dialog--> + <string name="auto_flattr_enable">Ä®jungti automatinį rÄ—mimÄ… „Flattr“</string> + <string name="auto_flattr_after_percent">Paremti epizodÄ… „Flattr“ perklausius %d procentus jo trukmÄ—s</string> + <string name="auto_flattr_ater_beginning">Paremti epizodÄ… „Flattr“ atkÅ«rimui prasidÄ—jus</string> + <string name="auto_flattr_ater_end">Paremti epizodÄ… „Flattr“ atkÅ«rimui pasibaigus</string> + <!--Search--> + <string name="search_hint">IeÅ¡koti epizodų</string> + <string name="found_in_shownotes_label">Rasta laidos užraÅ¡uose</string> + <string name="found_in_chapters_label">Rasta skyriuose</string> + <string name="found_in_authors_label">Rasta autoriuose</string> + <string name="found_in_feeds_label">Rasta sklaidos kanaluose</string> + <string name="search_status_no_results">Nieko nerasta</string> + <string name="search_label">PaieÅ¡ka</string> + <string name="found_in_title_label">Rasta pavadinime</string> + <string name="no_results_for_query">Rezultatų paieÅ¡kai \"%1$s\" nÄ—ra.</string> + <!--OPML import and export--> + <string name="opml_import_txtv_button_lable">OPML failai leidžia perkelti tinklalaides iÅ¡ vienos tvarkytuvÄ—s į kitÄ….</string> + <string name="opml_import_option">Parinktis %1$d</string> + <string name="opml_import_explanation_1">Pasirinkite tikslų keliÄ… iki failo vietinÄ—je failų sistemoje.</string> + <string name="opml_import_explanation_2">Naudokite iÅ¡orinÄ™ programÄ—lÄ™, pvz. „Dropbox“, „Google Drive“ ar mÄ—giamÄ… failų tvarkytuvÄ™ OPML failui atverti.</string> + <string name="opml_import_explanation_3">Dauguma programÄ—lių, pvz. „Google Mail“, „Dropbox“, „Google Drive“ ir dauguma failų tvarkytuvių leidžia <i>atverti</i> OPML failus <i>naudojant</i> „AntennaPod“.</string> + <string name="start_import_label">PradÄ—ti importÄ…</string> + <string name="opml_import_label">OPML importas</string> + <string name="opml_directory_error">KLAIDA!</string> + <string name="reading_opml_label">Skaitomas OPML failas</string> + <string name="opml_reader_error">Skaitant OPML failÄ… įvyko klaida:</string> + <string name="opml_import_error_no_file">Nepasirinktas failas!</string> + <string name="select_all_label">PažymÄ—ti visus</string> + <string name="deselect_all_label">NepažymÄ—ti nieko</string> + <string name="select_options_label">Pasirinkti...</string> + <string name="choose_file_from_filesystem">IÅ¡ vietinÄ—s failų sistemos</string> + <string name="choose_file_from_external_application">Naudoti iÅ¡orinÄ™ programÄ—lÄ™</string> + <string name="opml_export_label">OPML eksportas</string> + <string name="html_export_label">HTML eksportas</string> + <string name="exporting_label">Eksportuojama...</string> + <string name="export_error_label">Eksporto klaida</string> + <string name="opml_export_success_title">OPML eksportas sÄ—kmingas.</string> + <string name="opml_export_success_sum">.opml failas iÅ¡saugotas į:\u0020</string> + <string name="opml_import_ask_read_permission">Norint nuskaityti OPML failÄ… reikalinga prieiga prie neÅ¡iojamos atmintinÄ—s</string> + <!--Sleep timer--> + <string name="set_sleeptimer_label">Nustatyti miego laikmatį</string> + <string name="disable_sleeptimer_label">IÅ¡jungti miego laikmatį</string> + <string name="enter_time_here_label">Ä®veskite laikÄ…</string> + <string name="sleep_timer_label">Miego laikmatis</string> + <string name="time_left_label">Liko laiko:\u0020</string> + <string name="time_dialog_invalid_input">Netinkama įvestis, laikas turi bÅ«ti sveikasis skaiÄius</string> + <string name="timer_about_to_expire_label"><b>PrieÅ¡ pat laikmaÄiui pasibaigiant:</b></string> + <string name="shake_to_reset_label">PakraÄius nustatyti laikmatį iÅ¡ naujo</string> + <string name="timer_vibration_label">Vibruoti</string> + <string name="time_seconds">sekundÄ—s</string> + <string name="time_minutes">minutÄ—s</string> + <string name="time_hours">valandos</string> + <plurals name="time_seconds_quantified"> + <item quantity="one">1 sekundÄ—</item> + <item quantity="few">%d sekundÄ—s</item> + <item quantity="other">%d sekundžių</item> + </plurals> + <plurals name="time_minutes_quantified"> + <item quantity="one">1 minutÄ—</item> + <item quantity="few">%d minutÄ—s</item> + <item quantity="other">%d minuÄių</item> + </plurals> + <plurals name="time_hours_quantified"> + <item quantity="one">1 valanda</item> + <item quantity="few">%d valandos</item> + <item quantity="other">%d valandų</item> + </plurals> + <string name="auto_enable_label">Ä®jungti automatiÅ¡kai</string> + <string name="sleep_timer_enabled_label">Miego laikmatis įjungtas</string> + <string name="sleep_timer_disabled_label">Miego laikmatis iÅ¡jungtas</string> + <!--gpodder.net--> + <string name="gpodnet_taglist_header">KATEGORIJOS</string> + <string name="gpodnet_toplist_header">POPULIARIAUSIOS TINKLALAIDÄ–S</string> + <string name="gpodnet_suggestions_header">PASIŪLYMAI</string> + <string name="gpodnet_search_hint">IeÅ¡koti „gpodder.net“ svetainÄ—je</string> + <string name="gpodnetauth_login_title">Prisijungti</string> + <string name="gpodnetauth_login_descr">Sveiki! Tai prisijungimo prie „gpodder.net“ vedlys. Visų pirma, įveskite savo prisijungimo duomenis:</string> + <string name="gpodnetauth_login_butLabel">Prisijungti</string> + <string name="gpodnetauth_login_register">Jei dar neturite paskyros, galite susikurti jÄ… Äia:\nhttps://gpodder.net/register/</string> + <string name="username_label">Vartotojo vardas</string> + <string name="password_label">Slaptažodis</string> + <string name="gpodnetauth_device_title">Ä®renginio pasirinkimas</string> + <string name="gpodnetauth_device_descr">Sukurkite naujÄ… įrenginį savo „gpodder.net“ paskyrai arba pasirinkite esamÄ…:</string> + <string name="gpodnetauth_device_deviceID">Ä®renginio ID:\u0020</string> + <string name="gpodnetauth_device_caption">Pavadinimas</string> + <string name="gpodnetauth_device_butCreateNewDevice">Sukurti naujÄ… įrenginį</string> + <string name="gpodnetauth_device_chooseExistingDevice">Pasirinkti esamÄ… įrenginį:</string> + <string name="gpodnetauth_device_errorEmpty">Ä®renginio ID laukelis negali bÅ«ti tuÅ¡Äias</string> + <string name="gpodnetauth_device_errorAlreadyUsed">Toks įrenginio ID jau naudojamas</string> + <string name="gpodnetauth_device_caption_errorEmpty">Pavadinimas negali bÅ«ti tuÅ¡Äias</string> + <string name="gpodnetauth_device_butChoose">Pasirinkti</string> + <string name="gpodnetauth_finish_title">SÄ—kmingai prisijungta!</string> + <string name="gpodnetauth_finish_descr">Sveikiname! JÅ«sų „gpodder.net“ paskyra susieta su Å¡iuo įrenginiu. Nuo Å¡iol „AntennaPod“ automatiÅ¡kai sinchronizuos prenumeratas Å¡iame įrenginyje su JÅ«sų „gpodder.net“ paskyra.</string> + <string name="gpodnetauth_finish_butsyncnow">PradÄ—ti sinchronizavimÄ… dabar</string> + <string name="gpodnetauth_finish_butgomainscreen">Eiti į pagrindinį ekranÄ…</string> + <string name="gpodnetsync_auth_error_title">„gpodder.net“ tapatumo nustatymo klaida</string> + <string name="gpodnetsync_auth_error_descr">Neteisingas vartotojo vardas ar slaptažodis</string> + <string name="gpodnetsync_error_title">„gpodder.net“ sinchronizavimo klaida</string> + <string name="gpodnetsync_error_descr">Sinchronizavimo metu įvyko klaida:\u0020</string> + <string name="gpodnetsync_pref_report_successful">Pavyko</string> + <string name="gpodnetsync_pref_report_failed">Nepavyko</string> + <!--Directory chooser--> + <string name="selected_folder_label">Pasirinktas aplankas:</string> + <string name="create_folder_label">Sukurti aplankÄ…</string> + <string name="choose_data_directory">Pasirinkite duomenų aplankÄ…</string> + <string name="choose_data_directory_message">PraÅ¡ome pasirinkti pamatinį duomenų aplankÄ…. „AntennaPod“ sukurs reikiamus poaplankius.</string> + <string name="choose_data_directory_permission_rationale">Norinti pakeisti duomenų aplankÄ… reikalinga prieiga prie neÅ¡iojamos atmintinÄ—s</string> + <string name="create_folder_msg">Sukurti naujÄ… aplankÄ… pavadinimu \"%1$s\"?</string> + <string name="create_folder_success">Sukurtas naujas aplankas</string> + <string name="create_folder_error_no_write_access">Nepavyksta raÅ¡yti Å¡iame aplanke</string> + <string name="create_folder_error_already_exists">Aplankas jau egzistuoja</string> + <string name="create_folder_error">Nepavyko sukurti aplanko</string> + <string name="folder_does_not_exist_error">„%1$s“ neegzistuoja</string> + <string name="folder_not_readable_error">„%1$s“ negalima skaityti</string> + <string name="folder_not_writable_error">Ä® „%1$s“ negalima raÅ¡yti</string> + <string name="folder_not_empty_dialog_title">Aplankas nÄ—ra tuÅ¡Äias</string> + <string name="folder_not_empty_dialog_msg">JÅ«sų pasirinktas aplankas nÄ—ra tuÅ¡Äias. Atsiųsti medijos ir kiti failai bus saugomi bÅ«tent Å¡iame aplanke. Ar norite tÄ™sti?</string> + <string name="set_to_default_folder">Pasirinkite numatytÄ…jį aplankÄ…</string> + <string name="pref_pausePlaybackForFocusLoss_sum">Kai kita programÄ—lÄ— nori atkurti garsus, pristabdyti atkÅ«rimÄ… vietoje garsio sumažinimo</string> + <string name="pref_pausePlaybackForFocusLoss_title">Pristabdyti pertraukus</string> + <string name="pref_resumeAfterCall_sum">PratÄ™sti atkÅ«rimÄ… užbaigus pokalbį telefonu</string> + <string name="pref_resumeAfterCall_title">PratÄ™sti po skambuÄio</string> + <string name="pref_restart_required">Kad pakeitimas įsigaliotų, reikia paleisti „AntennaPod“ iÅ¡ naujo.</string> + <!--Online feed view--> + <string name="subscribe_label">Prenumeruoti</string> + <string name="subscribed_label">Prenumeruojama</string> + <string name="downloading_label">AtsiunÄiama...</string> + <!--Content descriptions for image buttons--> + <string name="rewind_label">Atsukti</string> + <string name="fast_forward_label">Persukti į priekį</string> + <string name="media_type_audio_label">Garsas</string> + <string name="media_type_video_label">Vaizdas</string> + <string name="navigate_upwards_label">Eiti aukÅ¡tyn</string> + <string name="status_downloading_label">Epizodas atsiunÄiamas</string> + <string name="in_queue_label">Epizodas yra eilÄ—je</string> + <string name="drag_handle_content_description">Tempkite norÄ—dami pakeisti Å¡io elemento pozicijÄ…</string> + <string name="load_next_page_label">Ä®kelti kitÄ… puslapį</string> + <!--Feed information screen--> + <string name="authentication_label">Tapatumo nustatymas</string> + <string name="authentication_descr">Keisti vartotojo vardÄ… ir slaptažodį Å¡iai tinklalaidei ir jos epizodams.</string> + <string name="auto_download_settings_label">Automatinio atsiuntimo nustatymai</string> + <string name="episode_filters_label">Epizodų filtras</string> + <string name="episode_filters_description">Žodžių ar frazių sÄ…raÅ¡as, kuriuo remiantis sprendžiama, ar epizodas turÄ—tų bÅ«ti įtrauktas ar iÅ¡brauktas iÅ¡ automatiÅ¡kai atsiunÄiamų epizodų</string> + <string name="episode_filters_include">Ä®traukti</string> + <string name="episode_filters_exclude">IÅ¡braukti</string> + <string name="episode_filters_hint">Pavieniai žodžiai\n\"frazÄ—s kabutÄ—se\"</string> + <string name="keep_updated">Pastoviai atnaujinti</string> + <!--Progress information--> + <string name="progress_upgrading_database">Atnaujinama duomenų bazÄ—</string> + <!--AntennaPodSP--> + <string name="sp_apps_importing_feeds_msg">Ä®keliamos prenumeratos iÅ¡ specializuotų programÄ—lių...</string> + <string name="search_itunes_label">IeÅ¡koti „iTunes“</string> + <string name="filter">Filtruoti</string> + <string name="search_fyyd_label">IeÅ¡koti „fyyd“</string> + <!--Episodes apply actions--> + <string name="all_label">Visi</string> + <string name="selected_all_label">PažymÄ—ti visi epizodai</string> + <string name="none_label">Jokie</string> + <string name="deselected_all_label">Panaikintas visų epizodų žymÄ—jimas</string> + <string name="played_label">Perklausyti</string> + <string name="selected_played_label">PažymÄ—ti perklausyti epizodai</string> + <string name="unplayed_label">Neperklausyti</string> + <string name="selected_unplayed_label">PažymÄ—ti neperklausyti epizodai</string> + <string name="downloaded_label">Atsiųsti</string> + <string name="selected_downloaded_label">PažymÄ—ti atsiųsti epizodai</string> + <string name="not_downloaded_label">Neatsiųsti</string> + <string name="selected_not_downloaded_label">PažymÄ—ti neatsiųsti epizodai</string> + <string name="queued_label">EilÄ—je</string> + <string name="selected_queued_label">PažymÄ—ti epizodai, esantys eilÄ—je</string> + <string name="not_queued_label">Ne eilÄ—je</string> + <string name="selected_not_queued_label">PažymÄ—ti epizodai, nesantys eilÄ—je</string> + <string name="has_media">Turintys medijos failų</string> + <string name="selected_has_media_label">PažymÄ—ti epizodai, turintys medijos failų</string> + <!--Sort--> + <string name="sort_title_a_z">Pavadinimas (A \u2192 Z)</string> + <string name="sort_title_z_a">Pavadinimas (Z \u2192 A)</string> + <string name="sort_date_new_old">Data (Nauji \u2192 Seni)</string> + <string name="sort_date_old_new">Data (Seni \u2192 Nauji)</string> + <string name="sort_duration_short_long">TrukmÄ— (Trumpi \u2192 Ilgi)</string> + <string name="sort_duration_long_short">TrukmÄ— (Ilgi \u2192 Trumpi)</string> + <!--Rating dialog--> + <string name="rating_title">Patinka „AntennaPod“?</string> + <string name="rating_message">BÅ«tume dÄ—kingi, jei skirtumÄ—te laiko įvertinti „AntennaPod“.</string> + <string name="rating_never_label">Palikite mane ramybÄ—je</string> + <string name="rating_later_label">Priminti vÄ—liau</string> + <string name="rating_now_label">Žinoma, padarykime tai!</string> + <!--Audio controls--> + <string name="audio_controls">Garso valdikliai</string> + <string name="playback_speed">AtkÅ«rimo sparta</string> + <string name="volume">Garsis</string> + <string name="left_short">K</string> + <string name="right_short">D</string> + <string name="audio_effects">Garso efektai</string> + <string name="stereo_to_mono">Kanalų mažinimas: iÅ¡ stereo į mono</string> + <string name="sonic_only">Tik „Sonic“</string> + <!--proxy settings--> + <string name="proxy_type_label">Tipas</string> + <string name="host_label">Serveris</string> + <string name="port_label">Prievadas</string> + <string name="optional_hint">(neprivalomas)</string> + <string name="proxy_test_label">IÅ¡bandyti</string> + <string name="proxy_checking">Tikrinama...</string> + <string name="proxy_test_successful">Bandymas sÄ—kmingas</string> + <string name="proxy_test_failed">Bandymas nesÄ—kmingas</string> + <string name="proxy_host_empty_error">Serverio laukelis negali bÅ«ti tuÅ¡Äias</string> + <string name="proxy_host_invalid_error">Serverio laukelyje nurodytas netaisyklingas IP adresas ar sritis</string> + <string name="proxy_port_invalid_error">Netinkamas prievadas</string> + <!--Casting--> + <string name="cast_media_route_menu_title">Atkurti naudojant...</string> + <string name="cast_disconnect_label">Atjungti „Chromecast“ sesijÄ…</string> + <string name="cast_not_castable">Pasirinktas medijos failas nesuderinamas su „Chromecast“ įrenginiu</string> + <string name="cast_failed_to_play">Nepavyko pradÄ—ti medijos atkÅ«rimo</string> + <string name="cast_failed_to_stop">Nepavyko sustabdyti medijos atkÅ«rimo</string> + <string name="cast_failed_to_pause">Nepavyko pristabdyti medijos atkÅ«rimo</string> + <!--<string name="cast_failed_to_connect">Could not connect to the device</string>--> + <string name="cast_failed_setting_volume">Nepavyko nustatyti garsio</string> + <string name="cast_failed_no_connection">NÄ—ra ryÅ¡io su „Chromecast“ įrenginiu</string> + <string name="cast_failed_no_connection_trans">Prarastas ryÅ¡ys su „Chromecast“ įrenginiu. Jei įmanoma, programÄ—lÄ— pabandys atkurti ryšį. Palaukite keletÄ… sekundžių ir pabandykite dar kartÄ….</string> + <string name="cast_failed_perform_action">Nepavyko atlikti veiksmo.</string> + <string name="cast_failed_status_request">Sinchronizavimas su „Chromecast“ įrenginiu nepavyko</string> + <string name="cast_failed_seek">PerÅ¡okti į naujÄ… pozicijÄ… „Chromecast“ įrenginyje nepavyko</string> + <string name="cast_failed_receiver_player_error">Imtuvo leistuvÄ™ iÅ¡tiko rimta klaida</string> + <string name="cast_failed_media_error_skipping">Ä®vyko medijos atkÅ«rimo klaida. Praleidžiama...</string> +</resources> diff --git a/core/src/main/res/values-nb/strings.xml b/core/src/main/res/values-nb/strings.xml index 537bd49d6..13f9274ae 100644 --- a/core/src/main/res/values-nb/strings.xml +++ b/core/src/main/res/values-nb/strings.xml @@ -1,17 +1,12 @@ <?xml version='1.0' encoding='UTF-8'?> <resources xmlns:tools="http://schemas.android.com/tools"> <!--Activitiy and fragment titles--> - <string name="app_name">AntennaPod</string> <string name="feeds_label">Strømmer</string> <string name="add_feed_label">Legg til podcast</string> - <string name="podcasts_label">PODCASTER</string> <string name="episodes_label">Episoder</string> - <string name="new_episodes_label">Nye episoder</string> - <string name="all_episodes_label">Alle episoder</string> <string name="all_episodes_short_label">Alle</string> <string name="favorite_episodes_label">Favoritter</string> <string name="new_label">Nye</string> - <string name="waiting_list_label">Venteliste</string> <string name="settings_label">Innstillinger</string> <string name="add_new_feed_label">Legg til podcast</string> <string name="downloads_label">Nedlastninger</string> @@ -23,9 +18,6 @@ <string name="gpodnet_main_label">gpodder.net</string> <string name="gpodnet_auth_label">gpodder.net-innlogging</string> <string name="free_space_label">%1$s ledig</string> - <!--New episodes fragment--> - <string name="recently_published_episodes_label">Nylig publisert</string> - <string name="episode_filter_label">Vis kun nye episoder</string> <!--Statistics fragment--> <!--Main activity--> <string name="drawer_open">Ã…pne menyen</string> @@ -74,9 +66,7 @@ <string name="auto_download_label">Inkluder i automatiske nedlastninger</string> <string name="auto_download_apply_to_items_title">Angi for tidligere episoder</string> <string name="auto_download_apply_to_items_message">Den nye <i>Automatisk nedlasting</i>-innstillingen vil automatisk aktiveres for nye episoder.\nØnsker du Ã¥ aktivere den for tidligere utgitte episoder ogsÃ¥?</string> - <string name="auto_delete_label">Automatisk sletting av episode\n(overstyr den globale standarden)</string> <string name="parallel_downloads_suffix">\u0020samtidige nedlastinger</string> - <string name="feed_auto_download_global">Global</string> <string name="feed_auto_download_always">Alltid</string> <string name="feed_auto_download_never">Aldri</string> <string name="episode_cleanup_never">AldriAldri</string> @@ -91,7 +81,6 @@ <string name="etxtFeedurlHint">www.example.com/feed</string> <string name="txtvfeedurl_label">Legg til en podcast via URL</string> <string name="podcastdirectories_label">Finn podcast i katalog</string> - <string name="podcastdirectories_descr">Du kan søke etter nye podcaster pÃ¥ navn, kategori eller popularitet i gpodder.nets katalog eller pÃ¥ iTunes.</string> <string name="browse_gpoddernet_label">Bla gjennom gpodder.net</string> <!--Actions on feeds--> <string name="mark_all_read_label">Marker alle som avspilt</string> @@ -104,9 +93,6 @@ <string name="share_link_label">Del lenke</string> <string name="share_link_with_position_label">Del lenke med plassering</string> <string name="share_feed_url_label">Del strømmens URL</string> - <string name="share_item_url_label">Del episodens URL</string> - <string name="share_item_url_with_position_label">Del episodens URL med posisjon</string> - <string name="feed_delete_confirmation_msg">Vil du virkelig slette denne strømmen og alle episodene av denne strømmen du har lastet ned?</string> <string name="feed_remover_msg">Fjerner strøm</string> <string name="load_complete_feed">Oppdater hele strømmen</string> <string name="hide_episodes_title">Skjul episoder</string> @@ -138,8 +124,6 @@ <string name="remove_from_favorite_label">Fjern fra favoritter</string> <string name="visit_website_label">Besøk nettside</string> <string name="support_label">Flattr\'e dette</string> - <string name="enqueue_all_new">Legg alle til queue</string> - <string name="download_all">Last ned alle</string> <string name="skip_episode_label">Skip episode</string> <string name="activate_auto_download">Aktiver automatisk nedlasting</string> <string name="deactivate_auto_download">Deaktiver automatisk nedlasting</string> @@ -193,7 +177,6 @@ <string name="playback_error_server_died">Serveren døde</string> <string name="playback_error_unknown">Ukjent feil</string> <string name="no_media_playing_label">Ingen media spillende for øyeblikket.</string> - <string name="position_default_label">00:00:00</string> <string name="player_buffering_msg">Bufrer</string> <string name="playbackservice_notification_title">Spiller podcast</string> <string name="unknown_media_key">AntennaPod - Ukjent medienøkkel: %1$d</string> @@ -206,7 +189,6 @@ <string name="move_to_top_label">GÃ¥ til toppen</string> <string name="move_to_bottom_label">GÃ¥ til bunnen</string> <string name="sort">Sortér</string> - <string name="alpha">Alfabetisk</string> <string name="date">PÃ¥ dato</string> <string name="duration">PÃ¥ varighet</string> <string name="ascending">Økende</string> @@ -256,13 +238,11 @@ <string name="pref_pauseOnDisconnect_sum">Sett playback pÃ¥ pause nÃ¥r hodetelefoner eller bluetooth er frakoblet</string> <string name="pref_unpauseOnHeadsetReconnect_sum">Gjenoppta avspilling nÃ¥r hodetelefoner gjeninnkoples</string> <string name="pref_unpauseOnBluetoothReconnect_sum">Fortsett avspilling nÃ¥r bluetooth er tilkoblet igjen</string> - <string name="pref_hardwareForwardButtonSkips_title">Forover-knapp hopper</string> <string name="pref_hardwareForwardButtonSkips_sum">Ved pressing av hardware forover-knapp hopp til neste episode istedenfor forover-spoling</string> <string name="pref_followQueue_sum">Hopp til neste element i køen nÃ¥r avspillingen er ferdig</string> <string name="pref_auto_delete_sum">Slett episode nÃ¥r avspillingen er ferdig</string> <string name="pref_auto_delete_title">Automatisk sletting</string> <string name="pref_smart_mark_as_played_sum">Marker episoder som avspilt selv om det er X antall sekunder igjen av avspillingen</string> - <string name="pref_smart_mark_as_played_title">Smart markering av avspilt</string> <string name="pref_skip_keeps_episodes_sum">Behold episoder nÃ¥r de hoppes over</string> <string name="pref_skip_keeps_episodes_title">Behold episoder som er hoppet over</string> <string name="playback_pref">Avspilling</string> @@ -324,8 +304,6 @@ <string name="pref_gpodnet_setlogin_information_sum">Endre innlogginsinformasjonen til din gpodder.net konto</string> <string name="pref_playback_speed_title">Avspillingshastigheter</string> <string name="pref_playback_speed_sum">Egendefiner hastighetene tilgjengelig for variabel avspillingshastighet</string> - <string name="pref_fast_forward">Spoling fremover</string> - <string name="pref_rewind">Spoling bakover</string> <string name="pref_gpodnet_sethostname_title">Sett vertsnavn</string> <string name="pref_gpodnet_sethostname_use_default_host">Bruk standard vert</string> <string name="pref_expandNotify_title">Utvid varsel</string> @@ -346,15 +324,12 @@ <string name="crash_report_sum">Send den siste kræsj-rapporten via e-post</string> <string name="send_email">Send e-post</string> <string name="experimental_pref">Eksperimentell</string> - <string name="pref_sonic_title">Sonic medieavspiller</string> <!--Auto-Flattr dialog--> <string name="auto_flattr_enable">Aktiver automatisk flattring</string> <string name="auto_flattr_after_percent">Flattre episode sÃ¥ snart %d prosent er avspilt</string> <string name="auto_flattr_ater_beginning">Flattre episode nÃ¥r avspillingen starter</string> <string name="auto_flattr_ater_end">Flattre episode nÃ¥r avspillingen tar slutt</string> <!--Search--> - <string name="search_hint">Søk etter strømmer eller episoder</string> - <string name="found_in_shownotes_label">Funnet i shownotater</string> <string name="found_in_chapters_label">Funnet i kapitler</string> <string name="search_status_no_results">Ingen resultater ble funnet</string> <string name="search_label">Søk</string> @@ -456,22 +431,13 @@ <string name="subscribe_label">Abonner</string> <string name="subscribed_label">Abonnert</string> <!--Content descriptions for image buttons--> - <string name="show_chapters_label">Vis kapitler</string> - <string name="show_shownotes_label">Vis notater</string> - <string name="show_cover_label">Vis bilde</string> <string name="rewind_label">Spol tilbake</string> <string name="fast_forward_label">Spol fremover</string> <string name="media_type_audio_label">Lyd</string> <string name="media_type_video_label">Video</string> <string name="navigate_upwards_label">Naviger oppover</string> - <string name="butAction_label">Flere handlinger</string> - <string name="status_playing_label">Episode spilles nÃ¥</string> <string name="status_downloading_label">Episode lastes ned nÃ¥</string> - <string name="status_downloaded_label">Episode har blitt lastet ned</string> - <string name="status_unread_label">Objekt er nytt</string> <string name="in_queue_label">Episoden er i queue</string> - <string name="new_episodes_count_label">Antall nye episoder</string> - <string name="in_progress_episodes_count_label">Antall episoder du har begynt Ã¥ høre pÃ¥</string> <string name="drag_handle_content_description">Dra for Ã¥ endre posisjonen til dette objektet</string> <string name="load_next_page_label">Last inn neste side</string> <!--Feed information screen--> @@ -482,6 +448,7 @@ <!--AntennaPodSP--> <string name="sp_apps_importing_feeds_msg">Importerer abbonementer fra enkeltstÃ¥ende applikasjoner ...</string> <string name="search_itunes_label">Søk pÃ¥ iTunes</string> + <!--Episodes apply actions--> <string name="all_label">Alle</string> <string name="selected_all_label">Valgte alle episoder</string> <string name="none_label">Ingen</string> @@ -496,6 +463,7 @@ <string name="selected_not_downloaded_label">Valgte ikke-nedlastede episoder</string> <string name="queued_label">I kø</string> <string name="not_queued_label">Ikke i kø</string> + <!--Sort--> <string name="sort_title_a_z">Tittel (A \u2192 Z)</string> <string name="sort_title_z_a">Tittel (Z \u2192 A)</string> <string name="sort_date_new_old">Dato (Ny \u2192 Gammel)</string> @@ -510,4 +478,6 @@ <string name="rating_now_label">Naturligvis, kom igjen!</string> <!--Audio controls--> <!--proxy settings--> + <!--Casting--> + <!--<string name="cast_failed_to_connect">Could not connect to the device</string>--> </resources> diff --git a/core/src/main/res/values-nl/strings.xml b/core/src/main/res/values-nl/strings.xml index d7c5d4a97..ce80569e4 100644 --- a/core/src/main/res/values-nl/strings.xml +++ b/core/src/main/res/values-nl/strings.xml @@ -26,16 +26,22 @@ <!--Statistics fragment--> <string name="total_time_listened_to_podcasts">Totale duur van afgespeelde podcasts:</string> <string name="statistics_details_dialog">%1$d van de %2$d afleveringen gestart.\n\n%3$s van de %4$s afgespeeld.</string> + <string name="statistics_mode">Rekenmethode</string> + <string name="statistics_mode_normal">Bereken de daadwerkelijke speeltijd. Tweemaal afspelen wordt twee keer gerekend; als \'afgespeeld\' markeren wordt niet meegeteld.</string> + <string name="statistics_mode_count_all">Duur van de podcasts optelle die als \'afgespeeld\' zijn gemarkeerd.</string> + <string name="statistics_speed_not_counted">Let op: Met de afspeelsnelheid wordt geen rekening gehouden.</string> <!--Main activity--> <string name="drawer_open">Menu openen</string> <string name="drawer_close">Menu sluiten</string> <string name="drawer_preferences">Menu voorkeuren</string> <string name="drawer_feed_order_unplayed_episodes">Op aantal afleveringen</string> <string name="drawer_feed_order_alphabetical">Op alfabetische volgorde</string> - <string name="drawer_feed_order_last_update">Op datum van feed-update</string> + <string name="drawer_feed_order_last_update">Op datum van publicatie</string> + <string name="drawer_feed_order_most_played">Op aantal afgespeelde afleveringen</string> <string name="drawer_feed_counter_new_unplayed">Aantal nieuwe plus onbeluisterde afleveringen</string> <string name="drawer_feed_counter_new">Aantal nieuwe afleveringen</string> <string name="drawer_feed_counter_unplayed">Aantal onbeluisterde afleveringen</string> + <string name="drawer_feed_counter_downloaded">Aantal gedownloade afleveringen</string> <string name="drawer_feed_counter_none">Geen (alfabetisch sorteren)</string> <!--Webview actions--> <string name="open_in_browser_label">In de browser openen</string> @@ -50,6 +56,7 @@ <string name="cancel_label">Annuleren</string> <string name="yes">Ja</string> <string name="no">Nee</string> + <string name="reset">Reset</string> <string name="author_label">Auteur</string> <string name="language_label">Taal</string> <string name="url_label">URL</string> @@ -60,6 +67,7 @@ <string name="refresh_label">Verversen</string> <string name="external_storage_error_msg">Geen externe opslag beschikbaar. Zorg ervoor dat de externe opslag gemonteerd is, zodat de app goed kan werken.</string> <string name="chapters_label">Hoofdstukken</string> + <string name="chapter_duration">Duur: %1$s</string> <string name="shownotes_label">Shownotes</string> <string name="description_label">Beschrijving</string> <string name="most_recent_prefix">Meest recente aflevering:\u0020</string> @@ -100,7 +108,10 @@ <string name="mark_all_read_confirmation_msg">Bevestig aub dat u alle afleveringen als afgespeeld wilt markeren.</string> <string name="mark_all_read_feed_confirmation_msg">Bevestig aub dat u alle afleveringen van deze feed als afgespeeld wilt markeren.</string> <string name="mark_all_seen_label">\'Nieuw\' label van alle afleveringen verwijderen.</string> + <string name="mark_all_seen_msg">\'Nieuw\' label van alle afleveringen verwijderend</string> + <string name="mark_all_seen_confirmation_msg">Bevestig aub dat u het \'nieuw\' label van alle afleveringen wilt verwijderen.</string> <string name="show_info_label">Toon informatie</string> + <string name="rename_feed_label">Podcast hernoemen</string> <string name="remove_feed_label">Podcast verwijderen</string> <string name="share_label">Delen…</string> <string name="share_link_label">Link van de aflevering delen</string> @@ -108,7 +119,7 @@ <string name="share_feed_url_label">URL van de feed delen</string> <string name="share_item_url_label">URL van het mediabestand delen</string> <string name="share_item_url_with_position_label">URL van mediabestand met tijdstip delen</string> - <string name="feed_delete_confirmation_msg">Bevestig dat u deze feed en ALLE afleveringen van deze feed die u heeft gedownload wilt verwijderen.</string> + <string name="feed_delete_confirmation_msg">Bevestig dat u de feed <i>%1$s</i> en ALLE (ook gedownloade) afleveringen van deze podcast wilt verwijderen.</string> <string name="feed_remover_msg">Feed verwijderen</string> <string name="load_complete_feed">Hele feed vernieuwen</string> <string name="hide_episodes_title">Afleveringen verbergen</string> @@ -120,6 +131,7 @@ <string name="hide_not_queued_episodes_label">Niet in de wachtrij</string> <string name="hide_downloaded_episodes_label">Gedownload</string> <string name="hide_not_downloaded_episodes_label">Niet gedownload</string> + <string name="hide_has_media_label">Bevat media</string> <string name="filtered_label">Gefilterd</string> <string name="refresh_failed_msg">{fa-exclamation-circle} Laatste vernieuwing mislukt</string> <string name="open_podcast">Open podcast</string> @@ -130,7 +142,9 @@ <string name="stop_label">Stop</string> <string name="stream_label">Stream</string> <string name="remove_label">Verwijderen</string> + <string name="delete_label">Verwijderen</string> <string name="remove_episode_lable">Aflevering(en) verwijderen</string> + <string name="marked_as_seen_label">Verwijder \'nieuw\' label</string> <string name="mark_read_label">Als afgespeeld markeren</string> <string name="marked_as_read_label">Als afgespeeld gemarkeerd</string> <string name="mark_unread_label">Als niet afgespeeld markeren</string> @@ -216,9 +230,10 @@ <string name="move_to_top_label">Naar boven verplaatsen</string> <string name="move_to_bottom_label">Naar beneden verplaatsen</string> <string name="sort">Sorteren</string> - <string name="alpha">Alfabetisch</string> <string name="date">Datum</string> <string name="duration">Lengte</string> + <string name="episode_title">Afleveringtitel</string> + <string name="feed_title">Feed-titel</string> <string name="ascending">Oplopend</string> <string name="descending">Aflopend</string> <string name="clear_queue_confirmation_msg">Bevestig aub dat u alle afleveringen uit de wachtrij wilt verwijderen</string> @@ -274,6 +289,8 @@ <string name="pref_unpauseOnBluetoothReconnect_sum">Afspelen hervatten wanneer de bluetooth verbinding hervat wordt</string> <string name="pref_hardwareForwardButtonSkips_title">\'Volgende\' knop voor overslaan</string> <string name="pref_hardwareForwardButtonSkips_sum">Aflevering overslaan ipv vooruitspoelen wanneer op een fysieke \'volgende\' knop wordt gedrukt</string> + <string name="pref_hardwarePreviousButtonRestarts_title">Vorige voor opnieuw afspelen</string> + <string name="pref_hardwarePreviousButtonRestarts_sum">Aflevering afspelen vanaf het begin ipv terugspoelen wanneer op een fysieke \'vorige\' knop wordt gedrukt</string> <string name="pref_followQueue_sum">Volgende item in de wachtrij afspelen als de aflevering voltooid is</string> <string name="pref_auto_delete_sum">Afleveringen verwijderen als ze zijn afgespeeld</string> <string name="pref_auto_delete_title">Automatisch verwijderen</string> @@ -285,7 +302,7 @@ <string name="network_pref">Netwerk</string> <string name="pref_autoUpdateIntervallOrTime_title">Feed update interval of tijdstip</string> <string name="pref_autoUpdateIntervallOrTime_sum">Specificeer een interval of tijdstip waarop feeds automatisch vernieuwd moeten worden</string> - <string name="pref_autoUpdateIntervallOrTime_message">U kunt een <i>interval</i> zoals \'elke twee uur\' of een specifiek <i>tijdstip</i> zoals \'07:00 uur\' instellen, of het automatisch verversen van feeds uitzetten.\n\n<small>Nota bene: tijdstippen voor updates zijn niet precies. Er kan een kleine vertraging plaatsvinden.</small></string> + <string name="pref_autoUpdateIntervallOrTime_message">U kunt een <i>interval</i> zoals \'elke twee uur\' of een specifiek <i>tijdstip</i> zoals \'07:00 uur\' instellen, of het automatisch verversen van feeds uitzetten.\n\n<small>Let op: tijdstippen voor updates zijn niet precies. Er kan een kleine vertraging plaatsvinden.</small></string> <string name="pref_autoUpdateIntervallOrTime_Disable">Uitschakelen</string> <string name="pref_autoUpdateIntervallOrTime_Interval">Interval instellen</string> <string name="pref_autoUpdateIntervallOrTime_TimeOfDay">Tijdstip instellen</string> @@ -340,14 +357,22 @@ <string name="pref_gpodnet_logout_toast">Uitlog was succesvol</string> <string name="pref_gpodnet_setlogin_information_title">Aanmeldingsgegevens wijzigen</string> <string name="pref_gpodnet_setlogin_information_sum">Wijzig de aanmeldingsgegevens van je gpodder.net account.</string> - <string name="pref_gpodnet_sync_title">Nu synchroniseren</string> - <string name="pref_gpodnet_sync_sum">Synchroniseer abonnementen en aflevering-status met gpodder.net</string> + <string name="pref_gpodnet_sync_changes_title">Wijzigingen nu synchroniseren</string> + <string name="pref_gpodnet_sync_changes_sum">Synchroniseer veranderde abonnementen en aflevering-statussen met gpodder.net</string> + <string name="pref_gpodnet_full_sync_title">Nu alles synchroniseren</string> + <string name="pref_gpodnet_full_sync_sum">Synchroniseer alle abonnementen en aflevering-statussen met gpodder.net</string> + <string name="pref_gpodnet_sync_sum_last_sync_line">Laatste synchronisatie: %1$s (%2$s)</string> <string name="pref_gpodnet_sync_started">Synchroniseren gestart</string> + <string name="pref_gpodnet_full_sync_started">Volledige synchronisatie gestart</string> <string name="pref_gpodnet_login_status"><![CDATA[Ingelogd als <i>%1$s</i> met apparaat <i>%2$s</i>]]></string> + <string name="pref_gpodnet_notifications_title">Toon synchronisatiefouten in melding</string> + <string name="pref_gpodnet_notifications_sum">Deze instelling is niet van toepassing op inlogfouten.</string> <string name="pref_playback_speed_title">Afspeelsnelheden</string> <string name="pref_playback_speed_sum">Pas de beschikbare snelheden aan voor de variabele audio afspeelsnelheid</string> <string name="pref_fast_forward">Snelheid van vooruitspoelen</string> + <string name="pref_fast_forward_sum">Pas het aantal seconden aan waarmee wordt vooruitgespoeld per klik op de knop</string> <string name="pref_rewind">Snelheid terugspoelen</string> + <string name="pref_rewind_sum">Pas het aantal seconden aan waarmee wordt teruggespoeld per klik op de knop</string> <string name="pref_gpodnet_sethostname_title">Definieer hostname</string> <string name="pref_gpodnet_sethostname_use_default_host">Gebruik standaard host</string> <string name="pref_expandNotify_title">Bedienen via melding</string> @@ -381,19 +406,25 @@ <string name="pref_known_issues">Reeds bekende bugs</string> <string name="pref_no_browser_found">Geen browser gevonden</string> <string name="pref_cast_title">Chromecast</string> - <string name="pref_cast_message">Ondersteuning voor \'Cast\' apparaten (zoals Chromecast, Audio Speakers en Android TV) inschakelen</string> + <string name="pref_cast_message_play_flavor">Ondersteuning activeren voor draadloos afspelen via Cast apparaten (zoals Chromecast, Audio speakers en Android TV)</string> + <string name="pref_cast_message_free_flavor">Voor Chromecast is software van derden vereist die niet beschikbaar zijn in deze versie van AntennaPod</string> + <string name="pref_enqueue_downloaded_title">Downloads in de wachtrij</string> + <string name="pref_enqueue_downloaded_summary">Voeg gedownloade afleveringen toe aan de wachtrij</string> <!--Auto-Flattr dialog--> <string name="auto_flattr_enable">Automatisch flattr\'en aanzetten</string> <string name="auto_flattr_after_percent">Flattr een aflevering zodra %d procent is afgespeeld</string> <string name="auto_flattr_ater_beginning">Flattr de aflevering bij afspelen</string> <string name="auto_flattr_ater_end">Flattr aflevering als afspelen is gestopt</string> <!--Search--> - <string name="search_hint">Feeds of afleveringen zoeken</string> + <string name="search_hint">Zoeken naar afleveringen</string> <string name="found_in_shownotes_label">Gevonden in de shownotes</string> - <string name="found_in_chapters_label">Gevonden in hoofdstukken</string> + <string name="found_in_chapters_label">Gevonden in de hoofdstukken</string> + <string name="found_in_authors_label">Gevonden in de makers</string> + <string name="found_in_feeds_label">Gevonden in de feeds</string> <string name="search_status_no_results">Er zijn geen resultaten gevonden</string> <string name="search_label">Zoeken</string> <string name="found_in_title_label">Gevonden in de titel</string> + <string name="no_results_for_query">Geen resultaten gevonden voor \"%1$s\"</string> <!--OPML import and export--> <string name="opml_import_txtv_button_lable">Met OPML-bestanden kan je podcasts van de ene naar de andere podcatcher verplaatsen.</string> <string name="opml_import_option">Optie %1$d</string> @@ -412,6 +443,7 @@ <string name="choose_file_from_filesystem">Via bestandsbeheer</string> <string name="choose_file_from_external_application">Via externe app</string> <string name="opml_export_label">OPML export</string> + <string name="html_export_label">HTML export</string> <string name="exporting_label">Exporteren…</string> <string name="export_error_label">Export fout</string> <string name="opml_export_success_title">OPML bestand succesvol geëxporteerd.</string> @@ -442,6 +474,9 @@ <item quantity="one">1 uur</item> <item quantity="other">%d uur</item> </plurals> + <string name="auto_enable_label">Automatisch inschakelen</string> + <string name="sleep_timer_enabled_label">Slaap timer ingeschakeld</string> + <string name="sleep_timer_disabled_label">Slaap timer uitgeschakeld</string> <!--gpodder.net--> <string name="gpodnet_taglist_header">CATEGORIEËN</string> <string name="gpodnet_toplist_header">TOP PODCASTS</string> @@ -471,6 +506,8 @@ <string name="gpodnetsync_auth_error_descr">Ongeldig gebruikersnaam of wachtwoord</string> <string name="gpodnetsync_error_title">gpodder.net synchronisatie fout</string> <string name="gpodnetsync_error_descr">Er is een fout opgetreden tijdens het synchroniseren:\u0020</string> + <string name="gpodnetsync_pref_report_successful">Succesvol</string> + <string name="gpodnetsync_pref_report_failed">Gefaald</string> <!--Directory chooser--> <string name="selected_folder_label">Geselecteerde map:</string> <string name="create_folder_label">Map aanmaken</string> @@ -523,6 +560,7 @@ <string name="sp_apps_importing_feeds_msg">Abonnementen aan het importeren vanuit single-purpose apps...</string> <string name="search_itunes_label">Zoeken in iTunes</string> <string name="filter">Filter</string> + <string name="search_fyyd_label">Fyyd doorzoeken</string> <!--Episodes apply actions--> <string name="all_label">Alle</string> <string name="selected_all_label">Alle afleveringen selecteren</string> @@ -540,6 +578,8 @@ <string name="selected_queued_label">Afleveringen in de wachtrij selecteren</string> <string name="not_queued_label">Niet in de wachtrij</string> <string name="selected_not_queued_label">Afleveringen geselecteerd die niet in de wachtrij staan</string> + <string name="has_media">Bevat media</string> + <string name="selected_has_media_label">Geselecteerde afleveringen met media</string> <!--Sort--> <string name="sort_title_a_z">Titel (A \u2192 Z)</string> <string name="sort_title_z_a">Titel (A \u2192 A)</string> @@ -576,6 +616,7 @@ <string name="proxy_port_invalid_error">Poortnummer ongeldig</string> <!--Casting--> <string name="cast_media_route_menu_title">Afspelen op…</string> + <string name="cast_disconnect_label">Cast loskoppelen</string> <string name="cast_not_castable">Dit bestand kan niet afgespeeld woorden door het Cast apparaat</string> <string name="cast_failed_to_play">Starten van afspelen is mislukt</string> <string name="cast_failed_to_stop">Stoppen van afspelen is mislukt</string> @@ -587,5 +628,6 @@ <string name="cast_failed_perform_action">Het uitvoeren van de actie is mislukt</string> <string name="cast_failed_status_request">Het synchroniseren met het Cast apparaat is mislukt</string> <string name="cast_failed_seek">Het opzoeken van het nieuwe tijdstip op het Cast apparaat is mislukt</string> + <string name="cast_failed_receiver_player_error">Ernstige fout opgetreden bij het afspelende Cast apparaat</string> <string name="cast_failed_media_error_skipping">Er was een fout bij het afspelen; de aflevering wordt overgeslagen…</string> </resources> diff --git a/core/src/main/res/values-no-rNB/strings.xml b/core/src/main/res/values-no-rNB/strings.xml index 58e8d9891..56bff080b 100644 --- a/core/src/main/res/values-no-rNB/strings.xml +++ b/core/src/main/res/values-no-rNB/strings.xml @@ -81,7 +81,6 @@ <string name="etxtFeedurlHint">www.example.com/feed</string> <string name="txtvfeedurl_label">Legg til en podcast via URL</string> <string name="podcastdirectories_label">Finn podcast i katalog</string> - <string name="podcastdirectories_descr">Du kan søke etter nye podcaster pÃ¥ navn, kategori eller popularitet i gpodder.nets katalog eller pÃ¥ iTunes.</string> <string name="browse_gpoddernet_label">Bla gjennom gpodder.net</string> <!--Actions on feeds--> <string name="mark_all_read_label">Marker alle som avspilt</string> @@ -94,7 +93,6 @@ <string name="share_link_label">Del lenke</string> <string name="share_link_with_position_label">Del lenke med plassering</string> <string name="share_feed_url_label">Del strømmens URL</string> - <string name="feed_delete_confirmation_msg">Vil du virkelig slette denne strømmen og alle episodene av denne strømmen du har lastet ned?</string> <string name="feed_remover_msg">Fjerner strøm</string> <string name="load_complete_feed">Oppdater hele strømmen</string> <string name="hide_episodes_title">Skjul episoder</string> @@ -191,7 +189,6 @@ <string name="move_to_top_label">GÃ¥ til toppen</string> <string name="move_to_bottom_label">GÃ¥ til bunnen</string> <string name="sort">Sortér</string> - <string name="alpha">Alfabetisk</string> <string name="date">PÃ¥ dato</string> <string name="duration">PÃ¥ varighet</string> <string name="ascending">Økende</string> @@ -241,13 +238,11 @@ <string name="pref_pauseOnDisconnect_sum">Sett playback pÃ¥ pause nÃ¥r hodetelefoner eller bluetooth er frakoblet</string> <string name="pref_unpauseOnHeadsetReconnect_sum">Gjenoppta avspilling nÃ¥r hodetelefoner gjeninnkoples</string> <string name="pref_unpauseOnBluetoothReconnect_sum">Fortsett avspilling nÃ¥r bluetooth er tilkoblet igjen</string> - <string name="pref_hardwareForwardButtonSkips_title">Forover-knapp hopper</string> <string name="pref_hardwareForwardButtonSkips_sum">Ved pressing av hardware forover-knapp hopp til neste episode istedenfor forover-spoling</string> <string name="pref_followQueue_sum">Hopp til neste element i køen nÃ¥r avspillingen er ferdig</string> <string name="pref_auto_delete_sum">Slett episode nÃ¥r avspillingen er ferdig</string> <string name="pref_auto_delete_title">Automatisk sletting</string> <string name="pref_smart_mark_as_played_sum">Marker episoder som avspilt selv om det er X antall sekunder igjen av avspillingen</string> - <string name="pref_smart_mark_as_played_title">Smart markering av avspilt</string> <string name="pref_skip_keeps_episodes_sum">Behold episoder nÃ¥r de hoppes over</string> <string name="pref_skip_keeps_episodes_title">Behold episoder som er hoppet over</string> <string name="playback_pref">Avspilling</string> @@ -309,8 +304,6 @@ <string name="pref_gpodnet_setlogin_information_sum">Endre innlogginsinformasjonen til din gpodder.net konto</string> <string name="pref_playback_speed_title">Avspillingshastigheter</string> <string name="pref_playback_speed_sum">Egendefiner hastighetene tilgjengelig for variabel avspillingshastighet</string> - <string name="pref_fast_forward">Spoling fremover</string> - <string name="pref_rewind">Spoling bakover</string> <string name="pref_gpodnet_sethostname_title">Sett vertsnavn</string> <string name="pref_gpodnet_sethostname_use_default_host">Bruk standard vert</string> <string name="pref_expandNotify_title">Utvid varsel</string> @@ -331,15 +324,12 @@ <string name="crash_report_sum">Send den siste kræsj-rapporten via e-post</string> <string name="send_email">Send e-post</string> <string name="experimental_pref">Eksperimentell</string> - <string name="pref_sonic_title">Sonic medieavspiller</string> <!--Auto-Flattr dialog--> <string name="auto_flattr_enable">Aktiver automatisk flattring</string> <string name="auto_flattr_after_percent">Flattre episode sÃ¥ snart %d prosent er avspilt</string> <string name="auto_flattr_ater_beginning">Flattre episode nÃ¥r avspillingen starter</string> <string name="auto_flattr_ater_end">Flattre episode nÃ¥r avspillingen tar slutt</string> <!--Search--> - <string name="search_hint">Søk etter strømmer eller episoder</string> - <string name="found_in_shownotes_label">Funnet i shownotater</string> <string name="found_in_chapters_label">Funnet i kapitler</string> <string name="search_status_no_results">Ingen resultater ble funnet</string> <string name="search_label">Søk</string> diff --git a/core/src/main/res/values-pl-rPL/strings.xml b/core/src/main/res/values-pl-rPL/strings.xml index 51def2c0e..194f387bd 100644 --- a/core/src/main/res/values-pl-rPL/strings.xml +++ b/core/src/main/res/values-pl-rPL/strings.xml @@ -1,31 +1,35 @@ <?xml version='1.0' encoding='UTF-8'?> <resources xmlns:tools="http://schemas.android.com/tools"> <!--Activitiy and fragment titles--> - <string name="app_name">AntennaPod</string> <string name="feeds_label">KanaÅ‚y</string> + <string name="statistics_label">Statystyki</string> <string name="add_feed_label">Dodaj podcast</string> - <string name="podcasts_label">PODCASTY</string> <string name="episodes_label">Odcinki</string> - <string name="new_episodes_label">Nowe odcinki</string> - <string name="all_episodes_label">Wszystkie odcinki</string> <string name="all_episodes_short_label">Wszystkie</string> <string name="favorite_episodes_label">Ulubione</string> <string name="new_label">Nowy</string> - <string name="waiting_list_label">Lista oczekujÄ…cych</string> <string name="settings_label">Ustawienia</string> <string name="add_new_feed_label">Dodaj podcast</string> <string name="downloads_label">Pobrane</string> <string name="downloads_running_label">W toku</string> <string name="downloads_completed_label">UkoÅ„czone</string> <string name="downloads_log_label">Dziennik</string> + <string name="subscriptions_label">Subskrypcje</string> + <string name="subscriptions_list_label">Lista subskrypcji</string> <string name="cancel_download_label">Anuluj pobieranie</string> <string name="playback_history_label">Historia odtwarzania</string> <string name="gpodnet_main_label">gpodder.net</string> <string name="gpodnet_auth_label">gpodder.net login</string> - <!--New episodes fragment--> - <string name="recently_published_episodes_label">Ostatnio opublikowane</string> - <string name="episode_filter_label">Pokaż tylko nowe odcinki</string> + <string name="free_space_label">%1$s wolnego miejsca</string> + <string name="episode_cache_full_title">PeÅ‚na pamięć cache</string> + <string name="episode_cache_full_message">Limit pamiÄ™ci cache zostaÅ‚ osiÄ…gniÄ™ty. Możesz zwiÄ™kszyć pojemność cache w ustawieniach aplikacji.</string> <!--Statistics fragment--> + <string name="total_time_listened_to_podcasts">CaÅ‚kowity czas trwania podcastów:</string> + <string name="statistics_details_dialog">%1$d z %2$d odcinków rozpoczÄ™to.\n\nZagrano %3$s z %4$s.</string> + <string name="statistics_mode">Tryb statystyk</string> + <string name="statistics_mode_normal">Oblicz Å‚Ä…czny czas rzeczywistego odtwarzania. Dwukrotne odtworzenie bÄ™dzie policzone ale zaznaczenie jako odtworzone nie bÄ™dzie policzone.</string> + <string name="statistics_mode_count_all">Podsumuj wszystkie podcasty oznaczone jako odtworzone</string> + <string name="statistics_speed_not_counted">Powiadomienie: PrÄ™dkość odtwarzania nigdy nie jest uwzglÄ™dniana.</string> <!--Main activity--> <string name="drawer_open">Otwórz menu</string> <string name="drawer_close">Zamknij menu</string> @@ -33,9 +37,11 @@ <string name="drawer_feed_order_unplayed_episodes">Sortuj wg liczby</string> <string name="drawer_feed_order_alphabetical">Sortuj alfabetycznie</string> <string name="drawer_feed_order_last_update">Sortuj wg daty publikacji</string> + <string name="drawer_feed_order_most_played">Sortuj po liczbie odtworzonych odcinków</string> <string name="drawer_feed_counter_new_unplayed">Liczba nowych i nieodtworzonych odcinków</string> <string name="drawer_feed_counter_new">Liczba nowych odcinków</string> <string name="drawer_feed_counter_unplayed">Liczba nieodtworzonych odcinków</string> + <string name="drawer_feed_counter_downloaded">Liczba pobranych odcinków</string> <string name="drawer_feed_counter_none">Brak</string> <!--Webview actions--> <string name="open_in_browser_label">Otwórz w przeglÄ…darce</string> @@ -50,8 +56,10 @@ <string name="cancel_label">Anuluj</string> <string name="yes">Tak</string> <string name="no">Nie</string> + <string name="reset">Reset</string> <string name="author_label">Autor</string> <string name="language_label">JÄ™zyk</string> + <string name="url_label">URL</string> <string name="podcast_settings_label">Ustawienia</string> <string name="cover_label">Obraz</string> <string name="error_label">BÅ‚Ä…d</string> @@ -59,6 +67,7 @@ <string name="refresh_label">OdÅ›wież</string> <string name="external_storage_error_msg">Brak zewnÄ™trznej pamiÄ™ci. Sprawdź czy jest ona podÅ‚Ä…czona żeby aplikacja mogÅ‚a pracować poprawnie.</string> <string name="chapters_label">RozdziaÅ‚y</string> + <string name="chapter_duration">Czas trwania: %1$s</string> <string name="shownotes_label">Opis odcinka</string> <string name="description_label">Opis</string> <string name="most_recent_prefix">Najnowszy odcinek:\u0020</string> @@ -66,23 +75,26 @@ <string name="length_prefix">DÅ‚ugość:\u0020</string> <string name="size_prefix">Rozmiar:\u0020</string> <string name="processing_label">Przetwarzanie</string> + <string name="loading_label">Åadowanie</string> <string name="save_username_password_label">Zapisz nazwÄ™ użytkownika i hasÅ‚o</string> <string name="close_label">Zamknij</string> <string name="retry_label">Spróbuj ponownie</string> <string name="auto_download_label">DoÅ‚Ä…cz do automatycznego pobierania</string> <string name="auto_download_apply_to_items_title">Zastosuj do poprzednich odcinków</string> <string name="auto_download_apply_to_items_message">Nowe ustawienie <i>automatycznego pobierania</i> zostanie zastosowane do nowych odcinków.\n Czy chcesz zastosować je także do odcinków opublikowanych wczeÅ›niej?</string> - <string name="auto_delete_label">Automatyczne usuwanie odcinków\n(nadpisz ustawienia globalne)</string> + <string name="auto_delete_label">Automatyczne usuwanie odcinków</string> <string name="parallel_downloads_suffix">\u0020równolegÅ‚ych pobieraÅ„</string> - <string name="feed_auto_download_global">Globalnie</string> + <string name="feed_auto_download_global">Globalnie domyÅ›lnie</string> <string name="feed_auto_download_always">Zawsze</string> <string name="feed_auto_download_never">Nigdy</string> + <string name="send_label">WyÅ›lij...</string> <string name="episode_cleanup_never">Nigdy</string> <string name="episode_cleanup_queue_removal">Kiedy nie sÄ… w kolejce</string> <string name="episode_cleanup_after_listening">Po odtworzeniu</string> <plurals name="episode_cleanup_days_after_listening"> <item quantity="one">1 dzieÅ„ po odtworzeniu</item> <item quantity="few">%d dni po odtworzeniu</item> + <item quantity="many">%d dni po odtworzeniu</item> <item quantity="other">%d dni po odtworzeniu</item> </plurals> <!--'Add Feed' Activity labels--> @@ -90,23 +102,30 @@ <string name="etxtFeedurlHint">Adres URL kanaÅ‚u lub strony internetowej</string> <string name="txtvfeedurl_label">Dodaj podcast przez adres</string> <string name="podcastdirectories_label">Znajdź podcast w folderze</string> - <string name="podcastdirectories_descr">Możesz wyszukiwać nowe podcasty ze wzglÄ™du na nazwÄ™, kategoriÄ™ lub popularność na gpodder.net</string> + <string name="podcastdirectories_descr">Możesz wyszukiwać nowe podcasty ze wzglÄ™du na nazwÄ™, kategoriÄ™ lub popularność na gpodder.net, Itunes lub fyyd</string> <string name="browse_gpoddernet_label">PrzeglÄ…daj gpodder.net</string> <!--Actions on feeds--> <string name="mark_all_read_label">Oznacz wszystkie jako odtworzone</string> <string name="mark_all_read_msg">Wszystkie odcinki zaznaczono jako odtworzone</string> + <string name="mark_all_read_confirmation_msg">ProszÄ™ potwierdzić, że chcesz zaznaczyć wszystkie odcinki do odtworzenia.</string> + <string name="mark_all_read_feed_confirmation_msg">ProszÄ™ potwierdzić, że chcesz zaznaczyć wszystkie odcinki na tym kanale do odtworzenia.</string> <string name="mark_all_seen_label">Oznacz wszystkie jako widziane</string> + <string name="mark_all_seen_msg">Zaznacz wszystkie Odcinki jako obejrzane</string> + <string name="mark_all_seen_confirmation_msg">ProszÄ™ potwierdzić chęć zaznaczenia wszystkich odcinków jako obejrzanych.</string> <string name="show_info_label">Pokaż informacje</string> + <string name="rename_feed_label">ZmieÅ„ nazwÄ™ podcast-u</string> <string name="remove_feed_label">UsuÅ„ podcast</string> + <string name="share_label">UdostÄ™pnij...</string> <string name="share_link_label">UdostÄ™pnij stronÄ™</string> <string name="share_link_with_position_label">UdostÄ™pnij link z aktualnÄ… pozycjÄ…</string> <string name="share_feed_url_label">UdostÄ™pnij adres kanaÅ‚u</string> - <string name="share_item_url_label">UdostÄ™pnij adres URL odcinka</string> - <string name="share_item_url_with_position_label">UdostÄ™pnij adres URL odcinka z aktualnÄ… pozycjÄ…</string> - <string name="feed_delete_confirmation_msg">Potwierdź chęć usuniÄ™cia tego kanaÅ‚u wraz ze WSZYSTKIMI odcinkami, które zostaÅ‚y pobrane.</string> + <string name="share_item_url_label">UdostÄ™pnij plik URL odcinka</string> + <string name="share_item_url_with_position_label">UdostÄ™pnik plik URL odcinka z pozycjÄ…</string> + <string name="feed_delete_confirmation_msg">Potwierdź chęć usuniÄ™cia kanaÅ‚u \"%1$s\" wraz ze WSZYSTKIMI odcinkami, które zostaÅ‚y pobrane.</string> <string name="feed_remover_msg">Usuwanie kanaÅ‚u</string> <string name="load_complete_feed">OdÅ›wież caÅ‚y kanaÅ‚</string> <string name="hide_episodes_title">Ukryj odcinki</string> + <string name="episode_actions">Zatwierdź czynnoÅ›ci</string> <string name="hide_unplayed_episodes_label">Nieodtworzone</string> <string name="hide_paused_episodes_label">Zatrzymane</string> <string name="hide_played_episodes_label">Odtworzone</string> @@ -114,6 +133,10 @@ <string name="hide_not_queued_episodes_label">Nie w kolejce</string> <string name="hide_downloaded_episodes_label">Pobrane</string> <string name="hide_not_downloaded_episodes_label">Nie pobrane</string> + <string name="hide_has_media_label">Ma media</string> + <string name="filtered_label">Przefiltrowany</string> + <string name="refresh_failed_msg">{fa-exclamation-circle} Ostatnie odÅ›wierzanie nie powiodÅ‚o siÄ™</string> + <string name="open_podcast">Otwarty Podcast</string> <!--actions on feeditems--> <string name="download_label">Pobierz</string> <string name="play_label">Odtwórz</string> @@ -121,7 +144,9 @@ <string name="stop_label">Stop</string> <string name="stream_label">StrumieÅ„</string> <string name="remove_label">UsuÅ„</string> + <string name="delete_label">UsuÅ„</string> <string name="remove_episode_lable">UsuÅ„ odcinek</string> + <string name="marked_as_seen_label">Zaznaczono jako wyÅ›wietlone</string> <string name="mark_read_label">Oznacz jako odtworzone</string> <string name="marked_as_read_label">Oznaczone jako odtworzone</string> <string name="mark_unread_label">Oznacz jako nieodtworzone</string> @@ -129,14 +154,15 @@ <string name="added_to_queue_label">Dodano do Kolejki</string> <string name="remove_from_queue_label">UsuÅ„ z kolejki</string> <string name="add_to_favorite_label">Dodaj do Ulubionych</string> + <string name="added_to_favorites">Dodaj do ulubionych</string> <string name="remove_from_favorite_label">UsuÅ„ z Ulubionych</string> + <string name="removed_from_favorites">UsuniÄ™to z ulubionych</string> <string name="visit_website_label">Odwiedź stronÄ™</string> <string name="support_label">Wspomóż na Flattr</string> - <string name="enqueue_all_new">Dodaj wszystko do kolejki</string> - <string name="download_all">Pobierz wszystkie</string> <string name="skip_episode_label">PomiÅ„ odcinek</string> <string name="activate_auto_download">WÅ‚Ä…cz automatyczne pobieranie</string> <string name="deactivate_auto_download">WyÅ‚Ä…cz automatyczne pobieranie</string> + <string name="reset_position">Zresetowano pozycjÄ™ odtwarzania</string> <string name="removed_item">Pozycja usuniÄ™ta</string> <!--Download messages and labels--> <string name="download_successful">Operacja zakoÅ„czona sukcesem</string> @@ -153,14 +179,23 @@ <string name="download_error_connection_error">BÅ‚Ä…d poÅ‚Ä…czenia</string> <string name="download_error_unknown_host">Nieznany host</string> <string name="download_error_unauthorized">BÅ‚Ä…d autoryzacji</string> + <string name="download_error_file_type_type">BÅ‚Ä…d rodzaju pliku</string> + <string name="download_error_forbidden">Zabronione</string> <string name="cancel_all_downloads_label">Anuluj wszystkie pobierania</string> <string name="download_canceled_msg">Pobieranie anulowane</string> + <string name="download_canceled_autodownload_enabled_msg">Pobieranie zatrzymane\nWyÅ‚Ä…czone <i>Automatyczne pobieranie</i> dla tego elementu</string> <string name="download_report_title">Pobieranie ukoÅ„czone</string> <string name="download_report_content_title">Raport pobierania</string> <string name="download_error_malformed_url">Niepoprawny adres</string> <string name="download_error_io_error">BÅ‚Ä…d wejÅ›cia/wyjÅ›cia</string> <string name="download_error_request_error">BÅ‚Ä…d żądania</string> <string name="download_error_db_access">BÅ‚Ä…d dostÄ™pu do bazy danych</string> + <plurals name="downloads_left"> + <item quantity="one">%d element zostaÅ‚ do pobrania</item> + <item quantity="few">%d elementów zostaÅ‚o do pobrania</item> + <item quantity="many">%d elementów zostaÅ‚o do pobrania</item> + <item quantity="other">%d elementów zostaÅ‚o do pobrania</item> + </plurals> <string name="downloads_processing">Przetwarzanie pobranych</string> <string name="download_notification_title">Pobieranie danych podcastu</string> <string name="download_report_content">%1$d pobierania poprawne, %2$d nieudane</string> @@ -185,22 +220,24 @@ <string name="playback_error_server_died">Serwer zdechÅ‚</string> <string name="playback_error_unknown">Nieznany bÅ‚Ä…d</string> <string name="no_media_playing_label">Å»adne media nie odtwarzane </string> - <string name="position_default_label">00:00:00</string> <string name="player_buffering_msg">Buferowanie</string> <string name="playbackservice_notification_title">Odtwarzenie podcastu </string> <string name="unknown_media_key">AntennaPod - Nieznany klawisz: %1$d</string> <!--Queue operations--> <string name="lock_queue">Zablokuj KolejkÄ™</string> <string name="unlock_queue">Odblokuj KolejkÄ™</string> + <string name="queue_locked">Kolejka zablokowana</string> + <string name="queue_unlocked">Kolejka odblokowana</string> <string name="clear_queue_label">Wyczyść kolejkÄ™</string> <string name="undo">Cofnij</string> <string name="removed_from_queue">Element usuniÄ™ty</string> <string name="move_to_top_label">PrzesuÅ„ na górÄ™</string> <string name="move_to_bottom_label">PrzesuÅ„ na dół</string> <string name="sort">Sortuj</string> - <string name="alpha">Alfabetycznie</string> <string name="date">WedÅ‚ug daty</string> <string name="duration">WedÅ‚ug dÅ‚ugoÅ›ci</string> + <string name="episode_title">TytuÅ‚ odcinka</string> + <string name="feed_title">TytuÅ‚ kanaÅ‚u</string> <string name="ascending">RosnÄ…co</string> <string name="descending">MalejÄ…co</string> <string name="clear_queue_confirmation_msg">Potwierdź usuniÄ™cie WSZYSTKICH pozycji z kolejki</string> @@ -233,22 +270,31 @@ <!--Variable Speed--> <string name="download_plugin_label">Pobierz wtyczkÄ™</string> <string name="no_playback_plugin_title">Wtyczka nie zainstalowana</string> + <string name="no_playback_plugin_or_sonic_msg">Dla odtwarzania w różnych prÄ™dkoÅ›ciach zalecamy odblokowania wbudowanego odtwarzacza Sonic [Android 4.1+].\n\nW innym przypadku możesz użycz zewnÄ™trznego dodatku. <i>Prestissimo</i> ze Sklepu Play.\nAntennaPod nie ponosi odpowiedzialnoÅ›ci za problemy z Prestissimo, powinny one być zgÅ‚aszane do wÅ‚aÅ›ciciela dodatku.</string> <string name="set_playback_speed_label">PrÄ™dkość odtwarzania</string> + <string name="enable_sonic">WÅ‚Ä…cz Sonic</string> <!--Empty list labels--> <string name="no_items_label">Brak elementów na tej liÅ›cie.</string> <string name="no_feeds_label">Nie subskrybowaÅ‚eÅ› jeszcze żadnego kanaÅ‚u.</string> + <string name="no_chapters_label">Ten odcinek nie ma rozdziałów.</string> + <string name="no_shownotes_label">Ten epizod nie ma notatek.</string> <!--Preferences--> + <string name="storage_pref">Pamięć</string> + <string name="project_pref">Projekt</string> <string name="other_pref">Inne</string> <string name="about_pref">O...</string> <string name="queue_label">Kolejka</string> <string name="services_label">UsÅ‚ugi</string> <string name="flattr_label">Flattr</string> <string name="pref_episode_cleanup_title">Usuwanie odcinków</string> + <string name="pref_episode_cleanup_summary">Odcinki niebÄ™dÄ…ce w kolejce i niebÄ™dÄ…ce na liÅ›cie ulubiobych powinny nadawać siÄ™ do usuniÄ™cia, jeÅ›li Automatyczne Pobieranie potrzebuje miejsca na nowe odcinki.</string> <string name="pref_pauseOnDisconnect_sum">Wstrzymaj odtwarzanie po rozÅ‚Ä…czeniu sÅ‚uchawek lub Bluetooth</string> <string name="pref_unpauseOnHeadsetReconnect_sum">Wznów odtwarzanie kiedy sÅ‚uchawki zostanÄ… podÅ‚Ä…czone ponownie</string> <string name="pref_unpauseOnBluetoothReconnect_sum">Wznów odtwarzanie po przywróceniu poÅ‚Ä…czenia Bluetooth</string> <string name="pref_hardwareForwardButtonSkips_title">Przycisk \'Do przodu\' pomija odcinek</string> <string name="pref_hardwareForwardButtonSkips_sum">PrzyciÅ›niÄ™cie fizycznego przycisku \'Do przodu\' przeskakuje do nastÄ™pnego odcinka zamiast przewijania</string> + <string name="pref_hardwarePreviousButtonRestarts_title">Przycisk wstecz restartuje</string> + <string name="pref_hardwarePreviousButtonRestarts_sum">Podczas odtwarzania przycisk wstecz restartuje zamiast przewijać</string> <string name="pref_followQueue_sum">Przeskocz do nastÄ™pnego elementu kolejki po zakoÅ„czeniu odtwarzania</string> <string name="pref_auto_delete_sum">UsuÅ„ odcinek kiedy jego odtwarzanie zostanie zakoÅ„czone</string> <string name="pref_auto_delete_title">Automatyczne usuwanie</string> @@ -258,6 +304,14 @@ <string name="pref_skip_keeps_episodes_title">Zachowaj pominiÄ™te odcinki</string> <string name="playback_pref">Odtwarzanie</string> <string name="network_pref">Sieć</string> + <string name="pref_autoUpdateIntervallOrTime_title">CzÄ™stotliwość aktualizacji lub Czas dnia</string> + <string name="pref_autoUpdateIntervallOrTime_sum">OkreÅ›l czÄ™stotliwość albo konkretny czas dnia automatycznego odÅ›wieżania kanałów lub je wyÅ‚Ä…cz</string> + <string name="pref_autoUpdateIntervallOrTime_message">Możesz ustawić <i>czÄ™stotliwość</i> na przykÅ‚ad \"co 2 godziny\", ustawić konretny <i>czas dnia</i> na przykÅ‚ad \"7:00\" albo <i>wyÅ‚Ä…czyć</i> automatyczne aktualizacje.\n\n<small>Uwaga: Czas aktualizacji nie jest Å›cisÅ‚y. Możesz napotkać maÅ‚e opóźnienia.</small></string> + <string name="pref_autoUpdateIntervallOrTime_Disable">Zablokuj</string> + <string name="pref_autoUpdateIntervallOrTime_Interval">Ustaw czÄ™stotliwość</string> + <string name="pref_autoUpdateIntervallOrTime_TimeOfDay">Ustaw czas dnia</string> + <string name="pref_autoUpdateIntervallOrTime_every">każdy %1$s</string> + <string name="pref_autoUpdateIntervallOrTime_at">o %1$s</string> <string name="pref_downloadMediaOnWifiOnly_sum">Pobieraj pliki tylko przez WiFi</string> <string name="pref_followQueue_title">Odtwarzanie ciÄ…gÅ‚e</string> <string name="pref_downloadMediaOnWifiOnly_title">WiFi media pobrane</string> @@ -307,15 +361,34 @@ <string name="pref_gpodnet_logout_toast">Wylogowanie siÄ™ powiodÅ‚o</string> <string name="pref_gpodnet_setlogin_information_title">ZmieÅ„ informacje logowania</string> <string name="pref_gpodnet_setlogin_information_sum">ZmieÅ„ dane logowania konta gpodder.net.</string> + <string name="pref_gpodnet_sync_changes_title">Zsynchronizuj zmiany teraz</string> + <string name="pref_gpodnet_sync_changes_sum">Synchronizuj subskrypcje oraz stan odcinków z pomocÄ… gpodder.net.</string> + <string name="pref_gpodnet_full_sync_title">Wykonaj peÅ‚nÄ… synchronizacjÄ™ teraz</string> + <string name="pref_gpodnet_full_sync_sum">Synchronizuj wszystkie subskrypcje oraz stan odcinków z pomocÄ… gpodder.net.</string> + <string name="pref_gpodnet_sync_sum_last_sync_line">Ostatnia próba synchronizacji: %1$s (%2$s)</string> + <string name="pref_gpodnet_sync_started">Synchronizacja uruchomiona</string> + <string name="pref_gpodnet_full_sync_started">PeÅ‚na synchronizacja rozpoczÄ™ta</string> + <string name="pref_gpodnet_login_status"><![CDATA[Zalogowano jako <i>%1$s</i> na urzÄ…dzeniu <i>%2$s</i>]]></string> + <string name="pref_gpodnet_notifications_title">Pokaż powiadomienia bÅ‚Ä™dów synchronizacji</string> + <string name="pref_gpodnet_notifications_sum">To ustawienie nie dotyczy bÅ‚Ä™dów autoryzacji.</string> <string name="pref_playback_speed_title">PrÄ™dkość odtwarzania</string> <string name="pref_playback_speed_sum">Dostosuj prÄ™dkoÅ›ci dostÄ™pne dla odtwarzania audio o zmiennej prÄ™dkoÅ›ci</string> + <string name="pref_fast_forward">Szybkie przewijanie do przodu</string> + <string name="pref_fast_forward_sum">Dostosuj liczbÄ™ sekund do przeskoczenia przy klikniÄ™ciu szybkiego przewijania do przodu</string> + <string name="pref_rewind">Przewijanie do tyÅ‚u</string> + <string name="pref_rewind_sum">Dostosuj liczbÄ™ sekund do przeskoczenia przy klikniÄ™ciu przewijania do tyÅ‚u</string> <string name="pref_gpodnet_sethostname_title">Ustaw nazwÄ™ hosta</string> <string name="pref_gpodnet_sethostname_use_default_host">Użyj domyÅ›lnego hosta</string> <string name="pref_expandNotify_title">RozwiÅ„ Powiadomienia</string> <string name="pref_expandNotify_sum">Zawsze rozwijaj powiadomienie żeby pokazać przyciski odtwarzacza.</string> <string name="pref_persistNotify_title">StaÅ‚e przyciski odtwarzacza</string> <string name="pref_persistNotify_sum">Utrzymuj powiadomienie i przyciski odtwarzania na ekranie blokady gdy odtwarzanie jest wstrzymane.</string> + <string name="pref_compact_notification_buttons_title">Ustaw przyciski ekranu blokowania</string> + <string name="pref_compact_notification_buttons_sum">ZmieÅ„ przyciski odtwarzania na ekranie blokowania. Przyciski odtwórz/zatrzymaj sÄ… zawsze uwzglÄ™dnione.</string> + <string name="pref_compact_notification_buttons_dialog_title">Wybierz maksimum z %1$d przedmiotów</string> + <string name="pref_compact_notification_buttons_dialog_error">Możesz tylko wybrać maksimum z %1$d przedmiotów.</string> <string name="pref_lockscreen_background_title">Ustaw tÅ‚o ekranu blokady</string> + <string name="pref_lockscreen_background_sum">Ustaw tÅ‚o ekranu blokowania na aktualny obraz odcinka. W efekcie bÄ™dzie zawsze pokazywaÅ‚ obraz w innych aplikacjach.</string> <string name="pref_showDownloadReport_title">Pokaż raport z pobierania</string> <string name="pref_showDownloadReport_sum">Jeżeli pobieranie siÄ™ nie powiedzie, pokaż raport ze szczegółami bÅ‚Ä™du.</string> <string name="pref_expand_notify_unsupport_toast">Android starszy niż 4.1 nie wspiera rozszerzonych powiadomieÅ„.</string> @@ -329,32 +402,57 @@ <string name="send_email">WyÅ›lij e-mail</string> <string name="experimental_pref">Eksperymentalne</string> <string name="pref_sonic_title">Odtwarzacz mediów Sonic</string> + <string name="pref_sonic_message">Użyj wbudowanego odtwarzacza Sonic jako oprogramowanie zastÄ™pcze do natywnego odtwarzacza Android i Prestissimo</string> + <string name="pref_current_value">Aktualna wartość: %1$s</string> + <string name="pref_proxy_title">Proxy</string> + <string name="pref_proxy_sum">Ustaw proxy sieciowe</string> + <string name="pref_faq">Najczęściej zadawane pytania</string> + <string name="pref_known_issues">Znane problemy</string> + <string name="pref_no_browser_found">Nie znaleziono przeglÄ…darki.</string> + <string name="pref_cast_title">ObsÅ‚uga Chromecast</string> + <string name="pref_cast_message_play_flavor">Uruchom obsÅ‚ugÄ™ dla zdalnego odtwarzania mediów na innych urzÄ…dzeniach (takich jak Chromecast, Audio Speakers albo Android TV)</string> + <string name="pref_cast_message_free_flavor">Chromecast wymagadodatkowych bibliotek, które sÄ… zablokowane w tej wersji AntennaPod</string> + <string name="pref_enqueue_downloaded_title">Rzeczy z kolejki zostaÅ‚y pobrane</string> + <string name="pref_enqueue_downloaded_summary">Dodaj pobrane odcinki do kolejki</string> <!--Auto-Flattr dialog--> <string name="auto_flattr_enable">WÅ‚Ä…cz automatyczne wspieranie na flattr.</string> <string name="auto_flattr_after_percent">Z-flattr-uj odcinki odegrane %d procentach.</string> <string name="auto_flattr_ater_beginning">Z-flattr-uj odcinek gdy odtawarzanie zostanie rozpoczÄ™te</string> <string name="auto_flattr_ater_end">Z-flattr-uj odcinek gdy odtwarzanie zostanie zakoÅ„czone</string> <!--Search--> - <string name="search_hint">Szukaj kanałów lub odcinków</string> - <string name="found_in_shownotes_label">Znaleziono w notatkach</string> + <string name="search_hint">Szukaj odcinków</string> + <string name="found_in_shownotes_label">Znalezione w notatkach dotyczÄ…cych show</string> <string name="found_in_chapters_label">Znaleziono w rozdziaÅ‚ach</string> + <string name="found_in_authors_label">Znaleziono wÅ›ród autorów</string> + <string name="found_in_feeds_label">Znaleziono wÅ›ród kanałów</string> <string name="search_status_no_results">Brak wyników</string> <string name="search_label">Szukaj</string> <string name="found_in_title_label">Znaleziono w tytuÅ‚ach</string> + <string name="no_results_for_query">Brak wyników dla \"%1$s\"</string> <!--OPML import and export--> <string name="opml_import_txtv_button_lable">Pliki OPML pozwalajÄ… na przenoszenie podcastów miÄ™dzy aplikacjami.</string> + <string name="opml_import_option">Opcja %1$d</string> + <string name="opml_import_explanation_1">Wybierz konkretÄ… Å›cieżkÄ™ z lokalnego systemu plików.</string> <string name="opml_import_explanation_2">Użyj zewnÄ™trznej aplikacji takiej jak Dropbox, Google Drive lub ulubionego menedżera plików, aby otworzyć plik OPML.</string> + <string name="opml_import_explanation_3">Wiele aplikacji takich jak Google Mail, Dropbox, Google Drive i wiÄ™kszość menedżerów plików potrafi <i>otworzyć</i>pliki OPML <i>przy użyciu</i>AntennaPod</string> <string name="start_import_label">Rozpocznij import</string> <string name="opml_import_label">Import OPML</string> <string name="opml_directory_error">BÅÄ„D!</string> <string name="reading_opml_label">OdczytujÄ™ plik OPML</string> + <string name="opml_reader_error">WystÄ…piÅ‚ bÅ‚Ä…d podczas odczytywania pliku OPML:</string> + <string name="opml_import_error_no_file">Nie wbrano pliku!</string> <string name="select_all_label">Zaznacz wszystko</string> <string name="deselect_all_label">Odznacz wszystko</string> + <string name="select_options_label">Wybierz...</string> + <string name="choose_file_from_filesystem">Z lokalnego systemu plików</string> <string name="choose_file_from_external_application">Użyj zewnÄ™trznej aplikacji</string> <string name="opml_export_label">Eksport OPML</string> + <string name="html_export_label">Eksport HTML</string> + <string name="exporting_label">Eksportowanie...</string> <string name="export_error_label">BÅ‚Ä…d eksportu</string> <string name="opml_export_success_title">Eksport OPML udany.</string> <string name="opml_export_success_sum">Plik .opml zostaÅ‚ zapisany do:\u0020</string> + <string name="opml_import_ask_read_permission">DostÄ™p do zewnÄ™trznej pamiÄ™ci jest potrzebny do odczytywania plików OPML</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> @@ -371,18 +469,24 @@ <plurals name="time_seconds_quantified"> <item quantity="one">1 sekunda</item> <item quantity="few">%d sekundy</item> + <item quantity="many">%d sekund</item> <item quantity="other">%d sekund</item> </plurals> <plurals name="time_minutes_quantified"> <item quantity="one">1 minuta</item> <item quantity="few">%d minuty</item> + <item quantity="many">%d minut</item> <item quantity="other">%d minut</item> </plurals> <plurals name="time_hours_quantified"> <item quantity="one">1 godzina</item> <item quantity="few">%d godziny</item> + <item quantity="many">%d godzin</item> <item quantity="other">%d godzin</item> </plurals> + <string name="auto_enable_label">Automaczyne wÅ‚Ä…czenie</string> + <string name="sleep_timer_enabled_label">WyÅ‚Ä…cznik czasowy wÅ‚Ä…czony</string> + <string name="sleep_timer_disabled_label">WyÅ‚Ä…cznik czasowy wyÅ‚Ä…czony</string> <!--gpodder.net--> <string name="gpodnet_taglist_header">KATEGORIE</string> <string name="gpodnet_toplist_header">TOP PODCASTY</string> @@ -403,6 +507,7 @@ https://gpodder.net/register/</string> <string name="gpodnetauth_device_chooseExistingDevice">Wybierz istniejÄ…ce urzÄ…dzenie:</string> <string name="gpodnetauth_device_errorEmpty">Identyfikator urzÄ…dzenia nie może być pusty</string> <string name="gpodnetauth_device_errorAlreadyUsed">Identyfikator urzÄ…dzenia w użyciu</string> + <string name="gpodnetauth_device_caption_errorEmpty">Pole nie może być puste</string> <string name="gpodnetauth_device_butChoose">Wybierz</string> <string name="gpodnetauth_finish_title">Logowanie zakoÅ„czone sukcesem!</string> <string name="gpodnetauth_finish_descr">Gratulacje! Twoje konto na gpodder.net jest poÅ‚Ä…czone z urzÄ…dzeniem. AntennaPod bÄ™dzie automatycznie synchronizować subskrypcje na urzÄ…dzeniu z kontem na gpodder.net. </string> @@ -412,11 +517,14 @@ https://gpodder.net/register/</string> <string name="gpodnetsync_auth_error_descr">Niepoprawna nazwa użytkownika lub hasÅ‚o</string> <string name="gpodnetsync_error_title">BÅ‚Ä…d synchronizacji z gpodder.net</string> <string name="gpodnetsync_error_descr">WystÄ…piÅ‚ bÅ‚Ä…d podczas synchronizacji:\u0020</string> + <string name="gpodnetsync_pref_report_successful">Sukces</string> + <string name="gpodnetsync_pref_report_failed">Porażka</string> <!--Directory chooser--> <string name="selected_folder_label">Wybrany folder:</string> <string name="create_folder_label">Utwórz folder</string> <string name="choose_data_directory">Wybierz folder danych</string> <string name="choose_data_directory_message">Wybierz główny folder dla danych. AntennaPod utworzy odpowiednie podkatalogi.</string> + <string name="choose_data_directory_permission_rationale">DostÄ™p do pamiÄ™ci zewnÄ™trznej jest wymagany do zmiany folderu danych.</string> <string name="create_folder_msg">Utworzyć nowy folder o nazwie \"%1$s\"?</string> <string name="create_folder_success">Utworzono nowy folder</string> <string name="create_folder_error_no_write_access">Nie można zapisać do tego folderu</string> @@ -436,33 +544,35 @@ https://gpodder.net/register/</string> <!--Online feed view--> <string name="subscribe_label">Subskrybuj</string> <string name="subscribed_label">Subskrybowane</string> + <string name="downloading_label">Pobieranie...</string> <!--Content descriptions for image buttons--> - <string name="show_chapters_label">Pokaż rozdziaÅ‚y</string> - <string name="show_shownotes_label">Pokaż opis odcinka</string> - <string name="show_cover_label">Pokaż obraz</string> <string name="rewind_label">Cofnij</string> <string name="fast_forward_label">PrzewiÅ„</string> <string name="media_type_audio_label">Audio</string> <string name="media_type_video_label">Wideo</string> <string name="navigate_upwards_label">PrzesuÅ„ w górÄ™</string> - <string name="butAction_label">WiÄ™cej akcji</string> - <string name="status_playing_label">Odcinek jest odtwarzany</string> <string name="status_downloading_label">Odcinek jest pobierany</string> - <string name="status_downloaded_label">Odcinek pobrany</string> - <string name="status_unread_label">Nowa pozycja</string> <string name="in_queue_label">Odcinek jest w kolejce</string> - <string name="new_episodes_count_label">Liczba nowych odcinków</string> - <string name="in_progress_episodes_count_label">Liczba odcinków, których zaczÄ…Å‚eÅ› sÅ‚uchać</string> <string name="drag_handle_content_description">PrzeciÄ…gnij aby zmienić pozycjÄ™ elementu</string> <string name="load_next_page_label">ZaÅ‚aduj nastÄ™pnÄ… stronÄ™</string> <!--Feed information screen--> <string name="authentication_label">Autoryzacja</string> <string name="authentication_descr">ZmieÅ„ swojÄ… nazwÄ™ użytkownika oraz hasÅ‚o dla tego podcastu i jego odcinków</string> + <string name="auto_download_settings_label">Ustawienia automatycznego pobierania</string> + <string name="episode_filters_label">Filtr odcinków</string> + <string name="episode_filters_description">Wykaz terminów używanych aby zdecydować, czy odcinek powinien być wÅ‚Ä…czony lub wyÅ‚Ä…czony podczas automatycznego pobierania.</string> + <string name="episode_filters_include">WÅ‚Ä…czajÄ…c</string> + <string name="episode_filters_exclude">WyÅ‚Ä…czajÄ…c</string> + <string name="episode_filters_hint">Pojedyncze sÅ‚owa \n\"Kilka słów\"</string> + <string name="keep_updated">Utrzymuj zaktualizowane</string> <!--Progress information--> <string name="progress_upgrading_database">Aktualizacja bazy danych</string> <!--AntennaPodSP--> <string name="sp_apps_importing_feeds_msg">Importowanie subskrybcji z jednozadaniowych aplikacji</string> <string name="search_itunes_label">Szukaj w iTunes</string> + <string name="filter">Filtruj</string> + <string name="search_fyyd_label">Szukaj w fyyd</string> + <!--Episodes apply actions--> <string name="all_label">Wszystkie</string> <string name="selected_all_label">Zaznaczono wszystkie odcinki</string> <string name="none_label">Brak</string> @@ -475,6 +585,13 @@ https://gpodder.net/register/</string> <string name="selected_downloaded_label">Zaznaczono pobrane odcinki</string> <string name="not_downloaded_label">Nie pobrane</string> <string name="selected_not_downloaded_label">Zaznaczono niepobrane odcinki</string> + <string name="queued_label">W kolejce</string> + <string name="selected_queued_label">Wybierz odcinki w kolejce</string> + <string name="not_queued_label">Nie w kolejce</string> + <string name="selected_not_queued_label">Wybierz odcinki, które nie sÄ… w kolejce</string> + <string name="has_media">Ma media</string> + <string name="selected_has_media_label">Wybrane odcinki z mediami</string> + <!--Sort--> <string name="sort_title_a_z">TytuÅ‚ (A \u2192 Z)</string> <string name="sort_title_z_a">TytuÅ‚ (Z \u2192 A)</string> <string name="sort_date_new_old">Data (Nowe \u2192 Stare)</string> @@ -488,5 +605,40 @@ https://gpodder.net/register/</string> <string name="rating_later_label">Przypomnij później</string> <string name="rating_now_label">Pewnie, zróbmy to!</string> <!--Audio controls--> + <string name="audio_controls">Sterowanie audio</string> + <string name="playback_speed">PrÄ™dkość odtwarzania</string> + <string name="volume">GÅ‚oÅ›ność</string> + <string name="left_short">Lewy</string> + <string name="right_short">Prawy</string> + <string name="audio_effects">Efekty audio</string> + <string name="stereo_to_mono">Downmix: Stereo na mono</string> + <string name="sonic_only">Tylko Sonic</string> <!--proxy settings--> + <string name="proxy_type_label">Typ</string> + <string name="host_label">Host</string> + <string name="port_label">Port</string> + <string name="optional_hint">(Dodatkowe)</string> + <string name="proxy_test_label">Test</string> + <string name="proxy_checking">Sprawdzanie...</string> + <string name="proxy_test_successful">Test zakoÅ„czony powodzeniem</string> + <string name="proxy_test_failed">Test zakoÅ„czony niepowodzeniem</string> + <string name="proxy_host_empty_error">Host nie może być pusty!</string> + <string name="proxy_host_invalid_error">Host nie jest prawidÅ‚owym adresem IP albo domenÄ…</string> + <string name="proxy_port_invalid_error">BÅ‚Ä™dny port</string> + <!--Casting--> + <string name="cast_media_route_menu_title">Odtwarzaj na...</string> + <string name="cast_disconnect_label">RozÅ‚Ä…cz sesjÄ™</string> + <string name="cast_not_castable">Wybrane media nie sÄ… kompatybilne z urzÄ…dzeniem nadajÄ…cym.</string> + <string name="cast_failed_to_play">WystÄ…piÅ‚ bÅ‚Ä…d podczas uruchamiania odtwarzania</string> + <string name="cast_failed_to_stop">WystÄ…piÅ‚ bÅ‚Ä…d podczas zatrzymywania odtwarzania</string> + <string name="cast_failed_to_pause">WystÄ…piÅ‚ bÅ‚Ä…d podczas pauzowania odtwarzania</string> + <!--<string name="cast_failed_to_connect">Could not connect to the device</string>--> + <string name="cast_failed_setting_volume">WystÄ…piÅ‚ bÅ‚Ä…d podczas zmiany poziomu gÅ‚oÅ›noÅ›ci</string> + <string name="cast_failed_no_connection">Brak poÅ‚Ä…czenia z urzÄ…dzeniem nadajÄ…cym</string> + <string name="cast_failed_no_connection_trans">PoÅ‚Ä…czenie z urzÄ…dzeniem nadajÄ…cym zostaÅ‚o przerwane. Aplikacja próbuje przywrócić poÅ‚Ä…czenie, jeÅ›li jest to możliwe. ProszÄ™ poczekać kilka sekund i spróbować ponownie.</string> + <string name="cast_failed_perform_action">BÅ‚Ä…d podczas wykonywania akcji.</string> + <string name="cast_failed_status_request">WystÄ…piÅ‚ bÅ‚Ä…d podczas synchronizacji z urzÄ…dzeniem nadajÄ…cym.</string> + <string name="cast_failed_seek">WystÄ…piÅ‚ bÅ‚Ä…d podczas szukania nowej pozycji na urzÄ…dzeniu nadajÄ…cym.</string> + <string name="cast_failed_receiver_player_error">UrzÄ…dzenie odbierajÄ…ce napotkaÅ‚o poważny problem</string> + <string name="cast_failed_media_error_skipping">BÅ‚Ä…d podczas odtwarzania, pomijanie...</string> </resources> diff --git a/core/src/main/res/values-pt-rBR/strings.xml b/core/src/main/res/values-pt-rBR/strings.xml index 271f23459..7606f99f3 100644 --- a/core/src/main/res/values-pt-rBR/strings.xml +++ b/core/src/main/res/values-pt-rBR/strings.xml @@ -12,20 +12,24 @@ <string name="add_new_feed_label">Adicionar podcast</string> <string name="downloads_label">Downloads</string> <string name="downloads_running_label">Rodando</string> - <string name="downloads_completed_label">Completado</string> + <string name="downloads_completed_label">Finalizado</string> <string name="downloads_log_label">Log</string> <string name="subscriptions_label">Assinaturas</string> <string name="subscriptions_list_label">Lista de Assinaturas</string> - <string name="cancel_download_label">Cancelar Download</string> + <string name="cancel_download_label">Cancelar\nDownload</string> <string name="playback_history_label">Histórico de reprodução</string> <string name="gpodnet_main_label">gpodder.net</string> <string name="gpodnet_auth_label">gpodder.net login</string> - <string name="free_space_label">%1$s livre</string> - <string name="episode_cache_full_title">Cache de episódio completo</string> + <string name="free_space_label">%1$s livre(s)</string> + <string name="episode_cache_full_title">Cache de episódios cheio</string> <string name="episode_cache_full_message">O limite de cache de episódios foi alcançado. Você pode aumentar o tamanho do cache em Configurações.</string> <!--Statistics fragment--> - <string name="total_time_listened_to_podcasts">Tempo total de podcasts escutados:</string> - <string name="statistics_details_dialog">%1$d de %2$d episódios iniciados.\n\nEscutados %3$s de %4$s.</string> + <string name="total_time_listened_to_podcasts">Tempo total de podcasts reproduzidos:</string> + <string name="statistics_details_dialog">%1$d de %2$d episódios iniciados.\n\nReproduzidos %3$s de %4$s.</string> + <string name="statistics_mode">Modo EstatÃstica</string> + <string name="statistics_mode_normal">Calcular a duração que já foi tocada. Tocar das vezes é contado o dobro, enquanto marcar como tocada não é contado</string> + <string name="statistics_mode_count_all">Somar todos os podcasts marcados como tocados</string> + <string name="statistics_speed_not_counted">Nota: A velocidade de reprodução nunca é levada em conta.</string> <!--Main activity--> <string name="drawer_open">Abrir menu</string> <string name="drawer_close">Fechar menu</string> @@ -33,9 +37,11 @@ <string name="drawer_feed_order_unplayed_episodes">Ordenar por contador</string> <string name="drawer_feed_order_alphabetical">Ordenar alfabeticamente</string> <string name="drawer_feed_order_last_update">Ordenar por data de publicação</string> - <string name="drawer_feed_counter_new_unplayed">Número de episódios novos e não escutados ainda</string> + <string name="drawer_feed_order_most_played">Ordenar pelo número de episódios reproduzidos</string> + <string name="drawer_feed_counter_new_unplayed">Número de episódios novos e não reproduzidos</string> <string name="drawer_feed_counter_new">Numero de novos episódios</string> - <string name="drawer_feed_counter_unplayed">Número de episódios não escutados</string> + <string name="drawer_feed_counter_unplayed">Número de episódios não reproduzidos</string> + <string name="drawer_feed_counter_downloaded">Número de episódios baixados</string> <string name="drawer_feed_counter_none">Nenhum</string> <!--Webview actions--> <string name="open_in_browser_label">Abrir no navegador</string> @@ -50,6 +56,7 @@ <string name="cancel_label">Cancelar</string> <string name="yes">Sim</string> <string name="no">Não</string> + <string name="reset">Resetar</string> <string name="author_label">Autor</string> <string name="language_label">Idioma</string> <string name="url_label">URL</string> @@ -60,6 +67,7 @@ <string name="refresh_label">Atualizar</string> <string name="external_storage_error_msg">Não há dispositivos de armazenamento externo disponÃveis. Por favor, certifique-se de que um dispositivo de armazenamento externo está montado para que o aplicativo possa funcionar adequadamente.</string> <string name="chapters_label">CapÃtulos</string> + <string name="chapter_duration">Duração: %1$s</string> <string name="shownotes_label">Notas do podcast</string> <string name="description_label">Descrição</string> <string name="most_recent_prefix">Episódio mais recente:\u0020</string> @@ -72,11 +80,11 @@ <string name="close_label">Fechar</string> <string name="retry_label">Tentar novamente</string> <string name="auto_download_label">Incluir em downloads automáticos</string> - <string name="auto_download_apply_to_items_title">Aplicar a episódios anteriores</string> - <string name="auto_download_apply_to_items_message">A nova <i>Download Automático</i> configuração irá se aplicar automaticamente a novos episódios.\nVocê quer aplicá-la a aos episódios anteriores?</string> + <string name="auto_download_apply_to_items_title">Aplicar aos episódios anteriores</string> + <string name="auto_download_apply_to_items_message">A nova configuração de <i>Download Automático</i> será aplicada automaticamente a novos episódios.\nVocê deseja aplicá-la aos episódios anteriores?</string> <string name="auto_delete_label">Apagar episódio automaticamente</string> <string name="parallel_downloads_suffix">\u0020 downloads paralelos</string> - <string name="feed_auto_download_global">configurações globais</string> + <string name="feed_auto_download_global">Padrão global</string> <string name="feed_auto_download_always">Sempre</string> <string name="feed_auto_download_never">Nunca</string> <string name="send_label">Enviar...</string> @@ -89,40 +97,44 @@ </plurals> <!--'Add Feed' Activity labels--> <string name="feedurl_label">URL do Feed</string> - <string name="etxtFeedurlHint">www.example.com/feed</string> + <string name="etxtFeedurlHint">www.exemplo.com/feed</string> <string name="txtvfeedurl_label">Adicionar podcast por URL</string> <string name="podcastdirectories_label">Procurar Podcast na Pasta</string> - <string name="podcastdirectories_descr">Você pode buscar novos episódios por nome, categoria ou popularidade no gpodder.net, ou buscar no iTunes.</string> - <string name="browse_gpoddernet_label">Listar no gpodder.net</string> + <string name="podcastdirectories_descr">Você pode procurar novos episódios no iTunes ou fyyd, ou buscar no gpodder.net pelo nome, categoria ou popularidade.</string> + <string name="browse_gpoddernet_label">Pesquisar no gpodder.net</string> <!--Actions on feeds--> - <string name="mark_all_read_label">Marcar todos como lido</string> - <string name="mark_all_read_msg">Marcar todos Episódios como lidos</string> - <string name="mark_all_read_confirmation_msg">Por favor, confirme que você quer marcar todos os episódios como já tocados.</string> - <string name="mark_all_read_feed_confirmation_msg">Por favor confirme se você quer marcar todos os episódios deste feed como já tocados.</string> - <string name="mark_all_seen_label">Marcar todos como lido</string> + <string name="mark_all_read_label">Marcar todos como reproduzidos</string> + <string name="mark_all_read_msg">Marcar todos Episódios como reproduzidos</string> + <string name="mark_all_read_confirmation_msg">Por favor, confirme que você deseja marcar todos os episódios como já reproduzidos.</string> + <string name="mark_all_read_feed_confirmation_msg">Por favor confirme se você deseja marcar todos os episódios deste feed como já reproduzidos.</string> + <string name="mark_all_seen_label">Marcar todos como vistos</string> + <string name="mark_all_seen_msg">Todos os episódios marcados como vistos</string> + <string name="mark_all_seen_confirmation_msg">Confirme se deseja marcar todos os episódios como vistos.</string> <string name="show_info_label">Mostrar informação</string> + <string name="rename_feed_label">Renomear o Podcast</string> <string name="remove_feed_label">Remover Podcast</string> <string name="share_label">Compartilhar...</string> - <string name="share_link_label">Compartilhar link do site</string> - <string name="share_link_with_position_label">Compartilhar link com posição</string> + <string name="share_link_label">Compartilhar Link</string> + <string name="share_link_with_position_label">Compartilhar Link com posição</string> <string name="share_feed_url_label">Compartilhar Link do Feed</string> - <string name="share_item_url_label">Compartilhar Link do arquivo do episódio</string> - <string name="share_item_url_with_position_label">Compartilhar url do arquivo do episódio com posição</string> - <string name="feed_delete_confirmation_msg">Por favor confirme que você deseja apagar este feed e TODOS os episódios que você fez download deste feed.</string> + <string name="share_item_url_label">Compartilhar URL do arquivo do episódio</string> + <string name="share_item_url_with_position_label">Compartilhar URL do arquivo do episódio com posição</string> + <string name="feed_delete_confirmation_msg">Confirme se deseja deletar o feed \"%1$s\" e todos os episódios baixados desse feed.</string> <string name="feed_remover_msg">Removendo feed</string> <string name="load_complete_feed">Atualizar feed completamente</string> <string name="hide_episodes_title">Ocultar Episódios</string> <string name="episode_actions">Aplicar ações</string> - <string name="hide_unplayed_episodes_label">Não lido</string> + <string name="hide_unplayed_episodes_label">Não reproduzido</string> <string name="hide_paused_episodes_label">Pausado</string> - <string name="hide_played_episodes_label">Lido</string> + <string name="hide_played_episodes_label">Reproduzido</string> <string name="hide_queued_episodes_label">Enfileirado</string> <string name="hide_not_queued_episodes_label">Não enfileirado</string> <string name="hide_downloaded_episodes_label">Baixado</string> <string name="hide_not_downloaded_episodes_label">Não baixado</string> + <string name="hide_has_media_label">Possui mÃdia</string> <string name="filtered_label">Filtrado</string> <string name="refresh_failed_msg">{fa-exclamation-circle} Última Atualização falhou</string> - <string name="open_podcast">Podcast Aberto</string> + <string name="open_podcast">Abrir Podcast</string> <!--actions on feeditems--> <string name="download_label">Download</string> <string name="play_label">Reproduzir</string> @@ -130,10 +142,12 @@ <string name="stop_label">Parar</string> <string name="stream_label">Stream</string> <string name="remove_label">Remover</string> + <string name="delete_label">Deletar</string> <string name="remove_episode_lable">Remover Episódio</string> - <string name="mark_read_label">Marcar como lido</string> - <string name="marked_as_read_label">Marcado como lido</string> - <string name="mark_unread_label">Marcar como não lido</string> + <string name="marked_as_seen_label">Marcar como visto</string> + <string name="mark_read_label">Marcar como reproduzido</string> + <string name="marked_as_read_label">Marcado como reproduzido</string> + <string name="mark_unread_label">Marcar como não reproduzido</string> <string name="add_to_queue_label">Adicionar à fila</string> <string name="added_to_queue_label">Adicionado à fila</string> <string name="remove_from_queue_label">Remover da fila</string> @@ -168,7 +182,7 @@ <string name="cancel_all_downloads_label">Cancelar todos os downloads</string> <string name="download_canceled_msg">Download cancelado</string> <string name="download_canceled_autodownload_enabled_msg">Download cancelado\nDesabilitado <i>Download Automático</i> para este item</string> - <string name="download_report_title">Downloads finalizados</string> + <string name="download_report_title">Downloads finalizados com erro(s)</string> <string name="download_report_content_title">Reportar Download</string> <string name="download_error_malformed_url">URL inválida</string> <string name="download_error_io_error">Erro de IO</string> @@ -187,11 +201,11 @@ <string name="download_type_image">Imagem</string> <string name="download_request_error_dialog_message_prefix">Ocorreu um erro durante download do arquivo:\u0020</string> <string name="authentication_notification_title">Autenticação requerida</string> - <string name="authentication_notification_msg">O recurso que você requisitou requer um usuário e uma senha</string> - <string name="confirm_mobile_download_dialog_title">Confirmar Download Mobile</string> - <string name="confirm_mobile_download_dialog_message_not_in_queue">Baixar sobre plano de dados foi desabilitado nas configurações.\n\nVocê pode escolher entre apenas adicionar o episódio na fila ou você pode permitir o download temporáriamente.\n\n<small>Sua escolha será lembrada por 10 minutos.</small></string> - <string name="confirm_mobile_download_dialog_message">Baixar sobre plano de dados foi desabilitado em configurações.\n\n Você quer permitir o download temporáriamente?\n\n<small>Sua escolha será lembrada por 10 minutos</small></string> - <string name="confirm_mobile_download_dialog_only_add_to_queue">Enfileirados</string> + <string name="authentication_notification_msg">O recurso que você solicitou requer um usuário e uma senha</string> + <string name="confirm_mobile_download_dialog_title">Confirmar Download utilizando dados móveis</string> + <string name="confirm_mobile_download_dialog_message_not_in_queue">O download utilizando plano de dados foi desabilitado nas configurações.\n\nVocê pode escolher entre apenas adicionar o episódio na fila ou você pode permitir o download temporáriamente.\n\n<small>Sua escolha será lembrada por 10 minutos.</small></string> + <string name="confirm_mobile_download_dialog_message">O download sobre plano de dados foi desabilitado nas configurações.\n\n Você deseja permitir o download temporáriamente?\n\n<small>Sua escolha será lembrada por 10 minutos</small></string> + <string name="confirm_mobile_download_dialog_only_add_to_queue">Adicionar à fila</string> <string name="confirm_mobile_download_dialog_enable_temporarily">Permitir temporariamente</string> <!--Mediaplayer messages--> <string name="player_error_msg">Erro!</string> @@ -216,12 +230,13 @@ <string name="move_to_top_label">Mover para o topo</string> <string name="move_to_bottom_label">Mover para o fim</string> <string name="sort">Ordenar</string> - <string name="alpha">Alfabeticamente</string> <string name="date">Data</string> <string name="duration">Duração</string> + <string name="episode_title">Titulo do Episodio</string> + <string name="feed_title">Titulo do Feed</string> <string name="ascending">Crescente</string> <string name="descending">Decrescente</string> - <string name="clear_queue_confirmation_msg">Por favor confirme que você quer limpar a fila de TODOS eposódios</string> + <string name="clear_queue_confirmation_msg">Por favor confirme que você deseja limpar TODOS episódios da fila</string> <!--Flattr--> <string name="flattr_auth_label">Logar no Flattr</string> <string name="flattr_auth_explanation">Pressione o botão abaixo para iniciar o processo de autenticação. Você será direcionado para a tela de login do Flattr, que pedirá autorização para que o AntennaPod utilize o Flattr. Após conceder a permissão, você retornará a esta tela automaticamente.</string> @@ -258,7 +273,7 @@ <string name="no_items_label">Não existem itens nesta lista.</string> <string name="no_feeds_label">Você ainda não assinou nenhum feed.</string> <string name="no_chapters_label">Este episódio não possui capÃtulos</string> - <string name="no_shownotes_label">Este episódio não possui notas de apresentação</string> + <string name="no_shownotes_label">Este episódio não possui notas.</string> <!--Preferences--> <string name="storage_pref">Armazenamento</string> <string name="project_pref">Projeto</string> @@ -268,24 +283,26 @@ <string name="services_label">Serviços</string> <string name="flattr_label">Flattr</string> <string name="pref_episode_cleanup_title">Limpar Episódio</string> - <string name="pref_episode_cleanup_summary">Episódios que não foram enfileirados e não foram favoritados deveriam ser elegÃdos para remoção se o Auto Download precisar de espaço para novos episódios</string> - <string name="pref_pauseOnDisconnect_sum">Pausar a exibição quando phones de ouvidos ou bluetooth forem disconectados</string> - <string name="pref_unpauseOnHeadsetReconnect_sum">Continuar a exibição quando os fones de ouvido forem reconectados</string> - <string name="pref_unpauseOnBluetoothReconnect_sum">Continuar a exibição quando o bluetooth reconectar</string> + <string name="pref_episode_cleanup_summary">Episódios que não estão na fila e não estão nos favoritos podem ser removidos se o Download Automático precisar de espaço para novos episódios</string> + <string name="pref_pauseOnDisconnect_sum">Pausar a reprodução quando o fone de ouvido ou bluetooth forem disconectados</string> + <string name="pref_unpauseOnHeadsetReconnect_sum">Continuar a reprodução quando os fones de ouvido forem reconectados</string> + <string name="pref_unpauseOnBluetoothReconnect_sum">Continuar a reprodução quando o bluetooth reconectar</string> <string name="pref_hardwareForwardButtonSkips_title">Botão avançar pula</string> - <string name="pref_hardwareForwardButtonSkips_sum">Quando pressionar um botão fÃsico, avançar para o próximo episódio ao invés de avançar rápido</string> + <string name="pref_hardwareForwardButtonSkips_sum">Quando pressionar um botão fÃsico, avançar para o próximo episódio ao invés de avançar a reprodução</string> + <string name="pref_hardwarePreviousButtonRestarts_title">Botão anterior reinicia</string> + <string name="pref_hardwarePreviousButtonRestarts_sum">Reinicia a reprodução atual ao pressionar o botão fÃsico anterior ao invés de retroceder</string> <string name="pref_followQueue_sum">Pular para próximo item da fila quando a reprodução terminar</string> - <string name="pref_auto_delete_sum">Apagar os episódios quando a exibição for concluÃda</string> + <string name="pref_auto_delete_sum">Apagar os episódios quando a reprodução for concluÃda</string> <string name="pref_auto_delete_title">Deletar automaticamente</string> - <string name="pref_smart_mark_as_played_sum">Marcar episódios como escutados </string> - <string name="pref_smart_mark_as_played_title">Inteligentemente marcar como escutado </string> + <string name="pref_smart_mark_as_played_sum">Marcar episódios como reproduzidos mesmo que restem alguns segundos de reprodução</string> + <string name="pref_smart_mark_as_played_title">Marcar automaticamente como reproduzido</string> <string name="pref_skip_keeps_episodes_sum">Manter os episódios quando eles forem avançados</string> <string name="pref_skip_keeps_episodes_title">Manter episódios avançados</string> <string name="playback_pref">Reprodução</string> <string name="network_pref">Rede</string> - <string name="pref_autoUpdateIntervallOrTime_title">Intervado de atualização ou Tempo do dia</string> - <string name="pref_autoUpdateIntervallOrTime_sum">Especifique um intervalo ou um tempo especÃfico do dia para atualizar os seus feed automaticamente</string> - <string name="pref_autoUpdateIntervallOrTime_message">Você pode configurar um <i>intervalo</i> como \"cada 2 horas\", configurar um especÃfico <i>horário do dia</i> como \"7:00 AM\" ou <i>desabilitar</i> atualizações automaticas completamente.\n\n<small>Observe: Horários de atualização não são precisos. Você deve considar um possÃvel atraso.</small></string> + <string name="pref_autoUpdateIntervallOrTime_title">Atualizar intervalo ou momento do dia</string> + <string name="pref_autoUpdateIntervallOrTime_sum">Especificar um intervalo ou um momento especÃfico do dia para atualizar os seus feeds automaticamente</string> + <string name="pref_autoUpdateIntervallOrTime_message">Você pode configurar um <i>intervalo</i> como \"cada 2 horas\", configurar um <i>horário do dia</i> especÃfico como \"7:00 AM\" ou <i>desabilitar</i> atualizações automaticas completamente.\n\n<small>Observe: Horários de atualização não são precisos. Você deve considar um possÃvel atraso.</small></string> <string name="pref_autoUpdateIntervallOrTime_Disable">Desabilitar</string> <string name="pref_autoUpdateIntervallOrTime_Interval">Configurar Intervalo</string> <string name="pref_autoUpdateIntervallOrTime_TimeOfDay">Configurar Tempo do dia</string> @@ -296,7 +313,7 @@ <string name="pref_downloadMediaOnWifiOnly_title">Download de mÃdia via WiFi</string> <string name="pref_pauseOnHeadsetDisconnect_title">Fones de ouvido desconectados</string> <string name="pref_unpauseOnHeadsetReconnect_title">Fones de ouvido reconectados</string> - <string name="pref_unpauseOnBluetoothReconnect_title">Bluetooth reconectados</string> + <string name="pref_unpauseOnBluetoothReconnect_title">Bluetooth reconectado</string> <string name="pref_mobileUpdate_title">Atualizações via Rede de Dados Celular</string> <string name="pref_mobileUpdate_sum">Permite atualizações quando conectado na rede de dados celular</string> <string name="refreshing_label">Atualizando</string> @@ -313,8 +330,8 @@ <string name="pref_set_theme_title">Selecionar tema</string> <string name="pref_nav_drawer_title">Customizar Gaveta de Navegação</string> <string name="pref_nav_drawer_sum">Customizar a aparencia da gaveta de navegação.</string> - <string name="pref_nav_drawer_items_title">Configurar items a Gaveta de Navegação</string> - <string name="pref_nav_drawer_items_sum">Escolher quais items irão aparecer na gaveta de navegação.</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> <string name="pref_nav_drawer_feed_order_title">Configurar Ordem de Assinaturas</string> <string name="pref_nav_drawer_feed_order_sum">Mudar a ordem de suas assinaturas</string> <string name="pref_nav_drawer_feed_counter_title">Configurar um contador de assinaturas</string> @@ -340,14 +357,22 @@ <string name="pref_gpodnet_logout_toast">Saiu com sucesso</string> <string name="pref_gpodnet_setlogin_information_title">Alterar informações de login</string> <string name="pref_gpodnet_setlogin_information_sum">Alterar informações de login da sua conta gpodder.net</string> - <string name="pref_gpodnet_sync_title">Sincronizar agora</string> - <string name="pref_gpodnet_sync_sum">Sincronizar assinaturas e estados dos episódios com gpodder.net</string> + <string name="pref_gpodnet_sync_changes_title">Sincronizar alterações 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">Sincronização total agora</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_sync_sum_last_sync_line">Última tentativa de sincronização: %1$s (%2$s)</string> <string name="pref_gpodnet_sync_started">Sincronização iniciada</string> + <string name="pref_gpodnet_full_sync_started">Sincronização total iniciada</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_fast_forward">Avançar o tempo</string> - <string name="pref_rewind">Voltar o tempo</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> + <string name="pref_rewind_sum">Personalize os segundos para voltar quando o botão retroceder for clicado</string> <string name="pref_gpodnet_sethostname_title">Configurar hostname</string> <string name="pref_gpodnet_sethostname_use_default_host">Usar host padrão</string> <string name="pref_expandNotify_title">Expandir Notificação</string> @@ -358,15 +383,13 @@ <string name="pref_compact_notification_buttons_sum">Mudar os botões de reprodução na tela de bloqueio. O botão tocar/pausar sempre é incluso.</string> <string name="pref_compact_notification_buttons_dialog_title">Selecione no máximo %1$d itens</string> <string name="pref_compact_notification_buttons_dialog_error">Você só pode selecionar no máximo %1$d itens.</string> - <string name="pref_show_subscriptions_in_drawer_title">Mostrar Assinaturas</string> - <string name="pref_show_subscriptions_in_drawer_sum">Mostrar lista de assinaturas diretamente da gaveta de navegação</string> <string name="pref_lockscreen_background_title">Configurar plano de fundo da tela de bloqueio</string> <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_expand_notify_unsupport_toast">Versões do Android inferiores a 4.1 não suportam notificações expansÃveis</string> <string name="pref_queueAddToFront_sum">Adicionar um novo episódio para a frente da fila.</string> - <string name="pref_queueAddToFront_title">Enfileirar para a frente</string> + <string name="pref_queueAddToFront_title">Adicionar ao topo da fila</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> @@ -374,28 +397,34 @@ <string name="crash_report_sum">Enviar o relatório da última falha por e-mail</string> <string name="send_email">Enviar e-mail</string> <string name="experimental_pref">Experimental</string> - <string name="pref_sonic_title">Reprodutor de mÃdia Sonic</string> + <string name="pref_sonic_title">Sonic Media Player</string> <string name="pref_sonic_message">Utilizar o reprodutor de mÃdia Sonic no lugar do reprodutor de mÃdia nativo do Android e do Prestissimo</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">FAQ</string> + <string name="pref_faq">Perguntas Frequentes</string> <string name="pref_known_issues">Problemas conhecidos</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">Abilitar o suporte de reprodução de mÃdia remota em dispositivos Cast ( assim como Chromecast, Caixas de som ou Android TV)</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> + <string name="pref_cast_message_free_flavor">O Chromecast necessita de bibliotecas proprietárias de terceiros que estão desativadas nesta versão do AntennaPod</string> + <string name="pref_enqueue_downloaded_title">Adicionar baixado à fila</string> + <string name="pref_enqueue_downloaded_summary">Adicionar episódios baixados à fila</string> <!--Auto-Flattr dialog--> <string name="auto_flattr_enable">Abilitar automaticamente o flattr</string> <string name="auto_flattr_after_percent">Episódio Flattr assim que %d porcento for tocado</string> <string name="auto_flattr_ater_beginning">Episódio Flattr quando a repodução iniciar</string> <string name="auto_flattr_ater_end">Episódio Flattr quando a reprodução finalizar</string> <!--Search--> - <string name="search_hint">Procurar por Feeds ou Episódios</string> - <string name="found_in_shownotes_label">Encontrado nas notas do podcast</string> + <string name="search_hint">Buscar por episódios</string> + <string name="found_in_shownotes_label">Encontrados em exibir descrição</string> <string name="found_in_chapters_label">Encontrado nos capÃtulos</string> + <string name="found_in_authors_label">Encontrados em autores</string> + <string name="found_in_feeds_label">Encontrados em feeds</string> <string name="search_status_no_results">Nenhum resultado encontrado</string> <string name="search_label">Pesquisar</string> <string name="found_in_title_label">Encontrado no tÃtulo</string> + <string name="no_results_for_query">Nenhum resultado para \"%1$s\"</string> <!--OPML import and export--> <string name="opml_import_txtv_button_lable">Arquivos OPML permitem que você mova seus podcasts de um programa de podcasts para outro.</string> <string name="opml_import_option">Opção %1$d</string> @@ -414,6 +443,7 @@ <string name="choose_file_from_filesystem">Dos arquivos locais do sistema</string> <string name="choose_file_from_external_application">Utilizar aplicação externa</string> <string name="opml_export_label">Exportar OPML</string> + <string name="html_export_label">Exportar HTML</string> <string name="exporting_label">Exportando...</string> <string name="export_error_label">Erro na exportação</string> <string name="opml_export_success_title">Exportação do OPML realizada com sucesso.</string> @@ -444,6 +474,9 @@ <item quantity="one">1 hora</item> <item quantity="other">%d horas</item> </plurals> + <string name="auto_enable_label">Auto habilitar</string> + <string name="sleep_timer_enabled_label">Temporizador habilitado</string> + <string name="sleep_timer_disabled_label">Temporizador desabilitado</string> <!--gpodder.net--> <string name="gpodnet_taglist_header">CATEGORIAS</string> <string name="gpodnet_toplist_header">TOP PODCASTS</string> @@ -473,11 +506,13 @@ <string name="gpodnetsync_auth_error_descr">Nome do usuário ou senha incorreta</string> <string name="gpodnetsync_error_title">gpodder.net: erro de sincronização</string> <string name="gpodnetsync_error_descr">Ocorreu um erro durante a sincronização:\u0020</string> + <string name="gpodnetsync_pref_report_successful">Sucesso</string> + <string name="gpodnetsync_pref_report_failed">Falhou</string> <!--Directory chooser--> <string name="selected_folder_label">Selecionar pasta:</string> <string name="create_folder_label">Criar pasta</string> <string name="choose_data_directory">Escolher pasta de dados</string> - <string name="choose_data_directory_message">Por favor escolha a base do seu repositório de dados. O AntennaPode irá criar os sub-diretórios apropriados.</string> + <string name="choose_data_directory_message">Por favor escolha a raiz da sua pasta de dados. O AntennaPod irá criar os sub-diretórios apropriados.</string> <string name="choose_data_directory_permission_rationale">Acesso ao armazenamento externo é necessário para mudar o repositório de dados</string> <string name="create_folder_msg">Criar nova pasta com o nome \"%1$s\"?</string> <string name="create_folder_success">Nova pasta criada</string> @@ -494,7 +529,7 @@ <string name="pref_pausePlaybackForFocusLoss_title">Pausar em interrupções</string> <string name="pref_resumeAfterCall_sum">Continuar a reprodução depois que uma ligação telefonica for concluida</string> <string name="pref_resumeAfterCall_title">Continuar após ligação</string> - <string name="pref_restart_required">AntennaPode deve ser reiniciado para que esta mudanças tenha efeito.</string> + <string name="pref_restart_required">AntennaPod deve ser reiniciado para que esta mudanças tenha efeito.</string> <!--Online feed view--> <string name="subscribe_label">Assinar</string> <string name="subscribed_label">Assinado</string> @@ -507,7 +542,7 @@ <string name="navigate_upwards_label">Navegar para cima</string> <string name="status_downloading_label">O epÃsódio está sendo baixado</string> <string name="in_queue_label">Episódio está na fila</string> - <string name="drag_handle_content_description">Arrastar para mudar a posição deste item</string> + <string name="drag_handle_content_description">Arraste para mudar a posição deste item</string> <string name="load_next_page_label">Carregar a próxima página</string> <!--Feed information screen--> <string name="authentication_label">Autenticação</string> @@ -520,28 +555,31 @@ <string name="episode_filters_hint">Única palavra \n\"Múltiplas palavras\"</string> <string name="keep_updated">Manter Atualizado</string> <!--Progress information--> - <string name="progress_upgrading_database">Atualizar o banco de dados</string> + <string name="progress_upgrading_database">Atualizando o banco de dados</string> <!--AntennaPodSP--> - <string name="sp_apps_importing_feeds_msg">Importar assinaturas de aplicativos de finalidade única...</string> + <string name="sp_apps_importing_feeds_msg">Importando assinaturas de aplicativos de finalidade única...</string> <string name="search_itunes_label">Procurar no iTunes</string> <string name="filter">Filtrar</string> + <string name="search_fyyd_label">Pesquisar em fyyd</string> <!--Episodes apply actions--> <string name="all_label">Todos</string> <string name="selected_all_label">Selecionar todos Episódios</string> <string name="none_label">Nenhum</string> <string name="deselected_all_label">Desmarcar todos Episódios</string> - <string name="played_label">Tocado</string> - <string name="selected_played_label">Selecionar episódios tocados</string> - <string name="unplayed_label">Não tocado</string> - <string name="selected_unplayed_label">Selecionar episódios não tocados</string> + <string name="played_label">Reproduzido</string> + <string name="selected_played_label">Selecionar episódios reproduzidos</string> + <string name="unplayed_label">Não reproduzido</string> + <string name="selected_unplayed_label">Selecionar episódios não reproduzidos</string> <string name="downloaded_label">Baixados</string> - <string name="selected_downloaded_label">Selecionar episódios baixados</string> - <string name="not_downloaded_label">Não baixado</string> - <string name="selected_not_downloaded_label">Selecionar episÃdios não baixados</string> + <string name="selected_downloaded_label">Episódios baixados selecionados</string> + <string name="not_downloaded_label">Não baixados</string> + <string name="selected_not_downloaded_label">EpisÃdios não baixados selecionados</string> <string name="queued_label">Enfileirado</string> - <string name="selected_queued_label">Selecionar episódios enfileirados</string> + <string name="selected_queued_label">Episódios enfileirados selecionados</string> <string name="not_queued_label">Não enfileirado</string> - <string name="selected_not_queued_label">Selecionar episódios não enfileirados</string> + <string name="selected_not_queued_label">Episódios não enfileirados selecionados</string> + <string name="has_media">Possui mÃdia</string> + <string name="selected_has_media_label">Episódios selecionados com mÃdia</string> <!--Sort--> <string name="sort_title_a_z">TÃtulo (A \u2192 Z)</string> <string name="sort_title_z_a">TÃtulo (Z \u2192 A)</string> @@ -554,7 +592,7 @@ <string name="rating_message">Nós gostarÃamos que você dedicasse um tempo para avaliar o AntennaPod.</string> <string name="rating_never_label">Me deixe em paz</string> <string name="rating_later_label">Lembre-me mais tarde</string> - <string name="rating_now_label">Claro, deixe-me fazer isso!</string> + <string name="rating_now_label">Claro, vamos fazer isso!</string> <!--Audio controls--> <string name="audio_controls">Controles de Àudio</string> <string name="playback_speed">Velocidade da Reprodução</string> @@ -574,22 +612,22 @@ <string name="proxy_test_successful">Teste realizado com sucesso</string> <string name="proxy_test_failed">Teste falhou</string> <string name="proxy_host_empty_error">Host não pode ser vazio</string> - <string name="proxy_host_invalid_error">Host não possui um endereço de IP válido ou dominio</string> + <string name="proxy_host_invalid_error">Host não possui um endereço de IP ou domÃnio válidos</string> <string name="proxy_port_invalid_error">Porta inválida</string> <!--Casting--> - <string name="cast_media_route_menu_title">Tocar em...</string> + <string name="cast_media_route_menu_title">Reproduzir em...</string> <string name="cast_disconnect_label">Desconectar a sessão do cast</string> - <string name="cast_not_castable">A mÃdia selecionada não é compatÃvel com o dispositivo cast</string> + <string name="cast_not_castable">A mÃdia selecionada não é compatÃvel com o dispositivo em cast</string> <string name="cast_failed_to_play">Falha ao iniciar a reprodução da mÃdia</string> <string name="cast_failed_to_stop">Falha ao parar a reprodução da mÃdia</string> <string name="cast_failed_to_pause">Falha ao pausar a reprodução da mÃdia</string> <!--<string name="cast_failed_to_connect">Could not connect to the device</string>--> <string name="cast_failed_setting_volume">Falha ao configurar o volume</string> <string name="cast_failed_no_connection">Sem conexão com o dispositivo cast</string> - <string name="cast_failed_no_connection_trans">A conexão com o dispositivo cast foi perdida. A aplicação está tentando re-estabelecer a coneção, se possivel. Por favor espere por alguns segundos e tente novamente.</string> + <string name="cast_failed_no_connection_trans">A conexão com o dispositivo cast foi perdida. A aplicação está tentando reestabelecer a conexão. Por favor espere por alguns segundos e tente novamente.</string> <string name="cast_failed_perform_action">Falha ao executar a ação</string> <string name="cast_failed_status_request">Falha ao sincronizar com o dispositivo cast</string> <string name="cast_failed_seek">Falha ao buscar uma nova posição no dispositivo cast</string> - <string name="cast_failed_receiver_player_error">O receptor de reprodução encontrou um erro no servidor</string> - <string name="cast_failed_media_error_skipping">Erro ao tocar a mÃdia. Pulando...</string> + <string name="cast_failed_receiver_player_error">O receptor de reprodução encontrou um erro grave</string> + <string name="cast_failed_media_error_skipping">Erro ao reproduzir mÃdia. Pulando...</string> </resources> diff --git a/core/src/main/res/values-pt/strings.xml b/core/src/main/res/values-pt/strings.xml index fb5bc533e..154b451b6 100644 --- a/core/src/main/res/values-pt/strings.xml +++ b/core/src/main/res/values-pt/strings.xml @@ -26,6 +26,10 @@ <!--Statistics fragment--> <string name="total_time_listened_to_podcasts">Tempo total dos podcasts reproduzidos:</string> <string name="statistics_details_dialog">%1$d de %2$d episódios iniciados.\n\nReproduzidos %3$s de %4$s.</string> + <string name="statistics_mode">Modo estatÃstico</string> + <string name="statistics_mode_normal">Calcula a duração dos podcasts reproduzidos. Se os reproduzir duas vezes, serão contados duas vezes mas se os marcar como reproduzidos não serão contados.</string> + <string name="statistics_mode_count_all">Somar todos os podcasts marcados como reproduzidos</string> + <string name="statistics_speed_not_counted">Aviso: a velocidade de reprodução nunca será considerada.</string> <!--Main activity--> <string name="drawer_open">Abrir menu</string> <string name="drawer_close">Fechar menu</string> @@ -33,9 +37,11 @@ <string name="drawer_feed_order_unplayed_episodes">Ordenar por contador</string> <string name="drawer_feed_order_alphabetical">Ordenar alfabeticamente</string> <string name="drawer_feed_order_last_update">Ordenar por data de publicação</string> + <string name="drawer_feed_order_most_played">Ordenar por número de episódios reproduzidos</string> <string name="drawer_feed_counter_new_unplayed">Número de episódios novos ou por reproduzir</string> <string name="drawer_feed_counter_new">Número de novos episódios</string> <string name="drawer_feed_counter_unplayed">Número de episódios por reproduzir</string> + <string name="drawer_feed_counter_downloaded">Número de episódios descarregados</string> <string name="drawer_feed_counter_none">Nenhum</string> <!--Webview actions--> <string name="open_in_browser_label">Abrir no navegador</string> @@ -50,6 +56,7 @@ <string name="cancel_label">Cancelar</string> <string name="yes">Sim</string> <string name="no">Não</string> + <string name="reset">Repor</string> <string name="author_label">Autor</string> <string name="language_label">Idioma</string> <string name="url_label">URL</string> @@ -60,6 +67,7 @@ <string name="refresh_label">Atualizar</string> <string name="external_storage_error_msg">Cartão SD não disponÃvel. Certifique-se de que inseriu o cartão corretamente para que a aplicação funcione corretamente.</string> <string name="chapters_label">CapÃtulos</string> + <string name="chapter_duration">Duração: %1$s</string> <string name="shownotes_label">Notas</string> <string name="description_label">Descrição</string> <string name="most_recent_prefix">Episódio mais recente:\u0020</string> @@ -92,7 +100,7 @@ <string name="etxtFeedurlHint">URL da fonte ou do sÃtio web</string> <string name="txtvfeedurl_label">Adicionar podcast via URL</string> <string name="podcastdirectories_label">Localizar podcasts no diretório</string> - <string name="podcastdirectories_descr">Pode procurar por novos podcasts no gPodder.net e também na loja iTunes. Pode pesquisar por nome, categoria e popularidade.</string> + <string name="podcastdirectories_descr">Para novos podcasts, pode pesquisar no iTunes ou no fyyd. Também pode explorar no gpoder.net por nome, categoria ou popularidade.</string> <string name="browse_gpoddernet_label">Procurar no gPodder.net</string> <!--Actions on feeds--> <string name="mark_all_read_label">Marcar tudo como reproduzido</string> @@ -100,7 +108,10 @@ <string name="mark_all_read_confirmation_msg">Tem a certeza de que deseja marcar todos os episódios como reproduzidos?</string> <string name="mark_all_read_feed_confirmation_msg">Tem a certeza de que deseja marcar todos os episódios desta fonte como reproduzidos?</string> <string name="mark_all_seen_label">Marcar tudo como visto</string> + <string name="mark_all_seen_msg">Marcar todos os episódios como vistos</string> + <string name="mark_all_seen_confirmation_msg">Confirma de que deseja marcar todos os episódios como vistos?</string> <string name="show_info_label">Mostrar informações</string> + <string name="rename_feed_label">Renomear podcast</string> <string name="remove_feed_label">Remover podcast</string> <string name="share_label">Partilhar...</string> <string name="share_link_label">Partilhar ligação</string> @@ -108,7 +119,7 @@ <string name="share_feed_url_label">Partilhar URL da fonte</string> <string name="share_item_url_label">Partilhar URL do episódio</string> <string name="share_item_url_with_position_label">Partilhar URL do episódio com posição</string> - <string name="feed_delete_confirmation_msg">Tem a certeza de que deseja remover esta fonte e todos os episódios descarregados?</string> + <string name="feed_delete_confirmation_msg">Tem a certeza de que deseja remover a fonte \"%1$s\" e TODOS os episódios descarregados?</string> <string name="feed_remover_msg">Remover fonte</string> <string name="load_complete_feed">Atualizar todas as páginas da fonte</string> <string name="hide_episodes_title">Ocultar episódios</string> @@ -120,6 +131,7 @@ <string name="hide_not_queued_episodes_label">Não na fila</string> <string name="hide_downloaded_episodes_label">Descarregados</string> <string name="hide_not_downloaded_episodes_label">Não descarregados</string> + <string name="hide_has_media_label">Tem ficheiro</string> <string name="filtered_label">Filtrados</string> <string name="refresh_failed_msg">{fa-exclamation-circle} Última atualização falhada</string> <string name="open_podcast">Abrir podcast</string> @@ -130,7 +142,9 @@ <string name="stop_label">Parar</string> <string name="stream_label">Emitir</string> <string name="remove_label">Remover</string> + <string name="delete_label">Apagar</string> <string name="remove_episode_lable">Remover episódio</string> + <string name="marked_as_seen_label">Marcar como visto</string> <string name="mark_read_label">Marcar como reproduzido</string> <string name="marked_as_read_label">Marcado como reproduzido</string> <string name="mark_unread_label">Marcar como não reproduzido</string> @@ -216,9 +230,10 @@ <string name="move_to_top_label">Mover para o topo</string> <string name="move_to_bottom_label">Mover para o fundo</string> <string name="sort">Organização</string> - <string name="alpha">Alfabética</string> <string name="date">Data</string> <string name="duration">Duração</string> + <string name="episode_title">TÃtulo do episódio</string> + <string name="feed_title">TÃtulo da fonte</string> <string name="ascending">Crescente</string> <string name="descending">Decrescente</string> <string name="clear_queue_confirmation_msg">Tem a certeza de que deseja remover todos os episódios da fila de reprodução?</string> @@ -274,6 +289,8 @@ <string name="pref_unpauseOnBluetoothReconnect_sum">Continuar reprodução ao estabelecer a ligação bluetooth</string> <string name="pref_hardwareForwardButtonSkips_title">Botão para avançar</string> <string name="pref_hardwareForwardButtonSkips_sum">Ao premir o botão Avançar, ir para o episódio seguinte em vez de avançar a reprodução</string> + <string name="pref_hardwarePreviousButtonRestarts_title">Botão Anterior para reiniciar</string> + <string name="pref_hardwarePreviousButtonRestarts_sum">Ao premir o botão do telefone, reiniciar o episódio atual em vez de recuar para o episódio anterior</string> <string name="pref_followQueue_sum">Ir para a episódio seguinte ao terminar a reprodução</string> <string name="pref_auto_delete_sum">Apagar episódio ao terminar a reprodução</string> <string name="pref_auto_delete_title">Eliminação automática</string> @@ -340,14 +357,22 @@ <string name="pref_gpodnet_logout_toast">Sessão terminada</string> <string name="pref_gpodnet_setlogin_information_title">Alterar informação de acesso</string> <string name="pref_gpodnet_setlogin_information_sum">Alterar a informação de acesso à sua conta gpodder.net</string> - <string name="pref_gpodnet_sync_title">Sincronizar agora</string> - <string name="pref_gpodnet_sync_sum">Sincronizar subscrições e estado dos episódios com o gpodder.net</string> + <string name="pref_gpodnet_sync_changes_title">Sincronizar alterações</string> + <string name="pref_gpodnet_sync_changes_sum">Sincronizar subscrição e estado do episódio com o gpodder.net.</string> + <string name="pref_gpodnet_full_sync_title">Sincronização total</string> + <string name="pref_gpodnet_full_sync_sum">Sincronizar todas as subscrições e estados dos episódios com o gpodder.net.</string> + <string name="pref_gpodnet_sync_sum_last_sync_line">Última tentativa de sincronização: %1$s (%2$s)</string> <string name="pref_gpodnet_sync_started">Sincronização iniciada</string> + <string name="pref_gpodnet_full_sync_started">Sincronização iniciada</string> <string name="pref_gpodnet_login_status"><![CDATA[Sessão iniciada como <i>%1$s</i> com o dispositivo <i>%2$s</i>]]></string> + <string name="pref_gpodnet_notifications_title">Mostrar erros de sincronização</string> + <string name="pref_gpodnet_notifications_sum">Esta definição não é aplicável aos erros de autenticação.</string> <string name="pref_playback_speed_title">Velocidades de reprodução</string> <string name="pref_playback_speed_sum">Personalizar as velocidades de reprodução disponÃveis</string> <string name="pref_fast_forward">Tempo a avançar</string> + <string name="pref_fast_forward_sum">Personalizar o número de segundos a avançar ao clicar no botão de avanço rápido</string> <string name="pref_rewind">Tempo a recuar</string> + <string name="pref_rewind_sum">Personalizar o número de segundos a recuar ao clicar no botão de recuo rápido</string> <string name="pref_gpodnet_sethostname_title">Definir nome de servidor</string> <string name="pref_gpodnet_sethostname_use_default_host">Utilizar predefinições</string> <string name="pref_expandNotify_title">Expansão de notificação</string> @@ -358,8 +383,6 @@ <string name="pref_compact_notification_buttons_sum">Alterar botões de reprodução do ecrã de bloqueio. Os botões Reproduzir/Pausa serão sempre incluÃdos.</string> <string name="pref_compact_notification_buttons_dialog_title">Selecione no máximo %1$d itens</string> <string name="pref_compact_notification_buttons_dialog_error">Apenas pode selecionar um máximo de %1$d itens.</string> - <string name="pref_show_subscriptions_in_drawer_title">Mostrar subscrições</string> - <string name="pref_show_subscriptions_in_drawer_sum">Mostrar lista de subscrições no menu de navegação</string> <string name="pref_lockscreen_background_title">Definir fundo do ecrã de bloqueio</string> <string name="pref_lockscreen_background_sum">Define a imagem do episódio como fundo do ecrã de bloqueio. Efeito colateral: também será mostrada em outras aplicações</string> <string name="pref_showDownloadReport_title">Mostrar relatório de erros</string> @@ -374,7 +397,7 @@ <string name="crash_report_sum">Enviar o relatório de erros por e-mail</string> <string name="send_email">Enviar e-mail</string> <string name="experimental_pref">Experimental</string> - <string name="pref_sonic_title">Reprodutor Sonic</string> + <string name="pref_sonic_title">Reprodutor multimédia Sonic</string> <string name="pref_sonic_message">Utilizar o Sonic Media Player como substituto do reprodutor nativo do Android e do Prestissimo</string> <string name="pref_current_value">Valor atual: %1$s</string> <string name="pref_proxy_title">Proxy</string> @@ -383,19 +406,25 @@ <string name="pref_known_issues">Problemas conhecidos</string> <string name="pref_no_browser_found">Navegador web não encontrado</string> <string name="pref_cast_title">Suporte Chromecast</string> - <string name="pref_cast_message">Ativar suporte a reprodução multimédia remota em dispositivos Cast (tais como Chromecast, colunas áudio ou Android TV)</string> + <string name="pref_cast_message_play_flavor">Ativar suporte a reprodução multimédia em dispositivos Cast (tais como Chromecast, Android TV...)</string> + <string name="pref_cast_message_free_flavor">O Chromecast necessita de bibliotecas proprietárias de terceiros que estão desativadas nesta versão do AntennaPod</string> + <string name="pref_enqueue_downloaded_title">Colocar descarregados na fila</string> + <string name="pref_enqueue_downloaded_summary">Adicionar à fila os episódios descarregados</string> <!--Auto-Flattr dialog--> <string name="auto_flattr_enable">Ativar flattr automático</string> <string name="auto_flattr_after_percent">Flattr de episódios ao atingir %d porcento de reprodução</string> <string name="auto_flattr_ater_beginning">Flattr de episodios ao iniciar a reprodução</string> <string name="auto_flattr_ater_end">Flattr de episódios ao terminar a reprodução</string> <!--Search--> - <string name="search_hint">Pesquisar fontes ou episódios</string> + <string name="search_hint">Pesquisar por episódios</string> <string name="found_in_shownotes_label">Encontrado nas notas</string> <string name="found_in_chapters_label">Encontrado nos capÃtulos</string> + <string name="found_in_authors_label">Encontrado em autores</string> + <string name="found_in_feeds_label">Encontrado em fontes</string> <string name="search_status_no_results">Nenhum resultado</string> <string name="search_label">Pesquisar</string> <string name="found_in_title_label">Encontrado no tÃtulo</string> + <string name="no_results_for_query">Não existem resultados para \"%1$s\"</string> <!--OPML import and export--> <string name="opml_import_txtv_button_lable">Os ficheiros OPML permitem-lhe mover os podcasts entre aplicações</string> <string name="opml_import_option">Opção %1$d</string> @@ -414,6 +443,7 @@ <string name="choose_file_from_filesystem">Do sistema local de ficheiros</string> <string name="choose_file_from_external_application">Utilizar aplicação externa</string> <string name="opml_export_label">Exportação OPML</string> + <string name="html_export_label">Exportação HTML</string> <string name="exporting_label">A exportar...</string> <string name="export_error_label">Erro de exportação</string> <string name="opml_export_success_title">Exportação efetuada</string> @@ -444,6 +474,9 @@ <item quantity="one">1 hora</item> <item quantity="other">%d horas</item> </plurals> + <string name="auto_enable_label">Ativar automaticamente</string> + <string name="sleep_timer_enabled_label">Temporizador ativado</string> + <string name="sleep_timer_disabled_label">Temporizador desativado</string> <!--gpodder.net--> <string name="gpodnet_taglist_header">Categorias</string> <string name="gpodnet_toplist_header">Melhores</string> @@ -473,6 +506,8 @@ <string name="gpodnetsync_auth_error_descr">Utilizador ou palavra-passe inválida</string> <string name="gpodnetsync_error_title">Erro de sincronização gpodder.net</string> <string name="gpodnetsync_error_descr">Ocorreu um erro ao sincronizar:\u0020</string> + <string name="gpodnetsync_pref_report_successful">Sucesso</string> + <string name="gpodnetsync_pref_report_failed">Falha</string> <!--Directory chooser--> <string name="selected_folder_label">Diretório escolhido:</string> <string name="create_folder_label">Criar pasta</string> @@ -525,6 +560,7 @@ <string name="sp_apps_importing_feeds_msg">Importar subscrições de aplicações single-purpose...</string> <string name="search_itunes_label">Pesquisar no iTunes</string> <string name="filter">Filtro</string> + <string name="search_fyyd_label">Pesquisar no fyyd</string> <!--Episodes apply actions--> <string name="all_label">Todos</string> <string name="selected_all_label">Marcar todos os episódios</string> @@ -542,6 +578,8 @@ <string name="selected_queued_label">Episódios selecionados na fila</string> <string name="not_queued_label">Não na fila</string> <string name="selected_not_queued_label">Episódios não selecionados na fila</string> + <string name="has_media">Tem ficheiro</string> + <string name="selected_has_media_label">Episódios selecionados com ficheiros</string> <!--Sort--> <string name="sort_title_a_z">TÃtulo (A \u2192 Z)</string> <string name="sort_title_z_a">TÃtulo (Z \u2192 A)</string> diff --git a/core/src/main/res/values-ro-rRO/strings.xml b/core/src/main/res/values-ro-rRO/strings.xml index 0a8eb83ee..ba3f0ed4c 100644 --- a/core/src/main/res/values-ro-rRO/strings.xml +++ b/core/src/main/res/values-ro-rRO/strings.xml @@ -1,18 +1,14 @@ <?xml version='1.0' encoding='UTF-8'?> <resources xmlns:tools="http://schemas.android.com/tools"> <!--Activitiy and fragment titles--> - <string name="app_name">AntennaPod</string> <string name="feeds_label">Feeduri</string> - <string name="podcasts_label">PODCASTURI</string> <string name="new_label">Nou</string> - <string name="waiting_list_label">Listă de aÈ™teptare</string> <string name="settings_label">Setări</string> <string name="downloads_label">Descărcări</string> <string name="cancel_download_label">Anulează descărcare</string> <string name="playback_history_label">Istorie ascultare</string> <string name="gpodnet_main_label">gpodder.net</string> <string name="gpodnet_auth_label">autentificare gpodder.net</string> - <!--New episodes fragment--> <!--Statistics fragment--> <!--Main activity--> <!--Webview actions--> @@ -49,7 +45,6 @@ <string name="mark_all_read_label">Marchează toate ca citite</string> <string name="show_info_label">Arată informaÈ›ii</string> <string name="share_link_label">ÃŽmparte adresă website</string> - <string name="feed_delete_confirmation_msg">ConfirmaÈ›i È™tergerea feedului È™i a TUTUROR episoadelor pe care le-aÈ›i descărcat.</string> <!--actions on feeditems--> <string name="download_label">Descarcă</string> <string name="play_label">Play</string> @@ -62,8 +57,6 @@ <string name="remove_from_queue_label">Șterge din Coadă</string> <string name="visit_website_label">Vizitează Website</string> <string name="support_label">Flattr aceasta</string> - <string name="enqueue_all_new">Adaugă toate în coadă</string> - <string name="download_all">Descarcă toate</string> <string name="skip_episode_label">Sari peste episod</string> <!--Download messages and labels--> <string name="download_pending">Descărcare în aÈ™teptare</string> @@ -99,7 +92,6 @@ <string name="playback_error_server_died">Server mort</string> <string name="playback_error_unknown">Eroare necuonscută</string> <string name="no_media_playing_label">Nu se ascultă nimic</string> - <string name="position_default_label">00:00:00</string> <string name="player_buffering_msg">Buffering</string> <string name="playbackservice_notification_title">Cântă podcast</string> <!--Queue operations--> @@ -169,8 +161,6 @@ <string name="pref_playback_speed_sum">Modifică vitezele disponibile pentru viteza de ascultare.</string> <!--Auto-Flattr dialog--> <!--Search--> - <string name="search_hint">Caută feeduri sau episoade</string> - <string name="found_in_shownotes_label">Găsit în notiÈ›e</string> <string name="found_in_chapters_label">Găsit în capitole</string> <string name="search_status_no_results">Nu s-a găsit nici un rezultat</string> <string name="search_label">Caută</string> @@ -229,7 +219,11 @@ <!--Feed information screen--> <!--Progress information--> <!--AntennaPodSP--> + <!--Episodes apply actions--> + <!--Sort--> <!--Rating dialog--> <!--Audio controls--> <!--proxy settings--> + <!--Casting--> + <!--<string name="cast_failed_to_connect">Could not connect to the device</string>--> </resources> diff --git a/core/src/main/res/values-ru/strings.xml b/core/src/main/res/values-ru/strings.xml index c6ca5285a..57a801304 100644 --- a/core/src/main/res/values-ru/strings.xml +++ b/core/src/main/res/values-ru/strings.xml @@ -26,6 +26,10 @@ <!--Statistics fragment--> <string name="total_time_listened_to_podcasts">Общее Ð²Ñ€ÐµÐ¼Ñ Ð¿Ñ€Ð¾ÑÐ»ÑƒÑˆÐ¸Ð²Ð°Ð½Ð¸Ñ Ð¿Ð¾Ð´ÐºÐ°Ñтов:</string> <string name="statistics_details_dialog">%1$d из %2$d выпуÑков начато.\n\nПроÑлушано %3$s из %4$s.</string> + <string name="statistics_mode">Режим подÑчёта ÑтатиÑтики</string> + <string name="statistics_mode_normal">РаÑÑчитывать длительноÑÑ‚ÑŒ воÑпроизведённого на Ñамом деле. Повторное воÑпроизведение заÑчитываетÑÑ, а отметка о проÑлушивании — нет</string> + <string name="statistics_mode_count_all">ПрибавлÑÑ‚ÑŒ также вÑе подкаÑÑ‚Ñ‹, отмеченные как проÑлушанные</string> + <string name="statistics_speed_not_counted">Замечание: СкороÑÑ‚ÑŒ воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð½Ðµ учитываетÑÑ Ð½Ð¸ÐºÐ¾Ð³Ð´Ð°.</string> <!--Main activity--> <string name="drawer_open">Открыть меню</string> <string name="drawer_close">Закрыть меню</string> @@ -33,9 +37,11 @@ <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> <string name="drawer_feed_counter_new">КоличеÑтво новых выпуÑков</string> <string name="drawer_feed_counter_unplayed">КоличеÑтво непроÑлушанных выпуÑков</string> + <string name="drawer_feed_counter_downloaded">КоличеÑтво загруженных выпуÑков</string> <string name="drawer_feed_counter_none">Ðичего</string> <!--Webview actions--> <string name="open_in_browser_label">Открыть в браузере</string> @@ -50,6 +56,7 @@ <string name="cancel_label">Отмена</string> <string name="yes">Да</string> <string name="no">Ðет</string> + <string name="reset">СброÑ</string> <string name="author_label">Ðвтор</string> <string name="language_label">Язык</string> <string name="url_label">ÐдреÑ</string> @@ -60,6 +67,7 @@ <string name="refresh_label">Обновить</string> <string name="external_storage_error_msg">Внешний ноÑитель недоÑтупен. УбедитеÑÑŒ что внешний ноÑитель уÑтановлен, иначе приложение не Ñможет нормально работать.</string> <string name="chapters_label">Главы</string> + <string name="chapter_duration">ДлительноÑÑ‚ÑŒ: %1$s</string> <string name="shownotes_label">ÐŸÑ€Ð¸Ð¼ÐµÑ‡Ð°Ð½Ð¸Ñ Ðº выпуÑку</string> <string name="description_label">ОпиÑание</string> <string name="most_recent_prefix">ПоÑледний выпуÑк:\u0020</string> @@ -94,15 +102,18 @@ <string name="etxtFeedurlHint">www.example.com/feed</string> <string name="txtvfeedurl_label">Добавить подкаÑÑ‚ по URL</string> <string name="podcastdirectories_label">Ðайти подкаÑÑ‚ в каталоге</string> - <string name="podcastdirectories_descr">Ð’Ñ‹ можете иÑкать новые подкаÑÑ‚Ñ‹ по имени, категории или популÑрноÑти в каталоге gpodder.net и в магазине iTunes.</string> + <string name="podcastdirectories_descr">Ð’Ñ‹ можете иÑкать новые подкаÑÑ‚Ñ‹ в каталогах iTunes, fyyd или gpodder.net по имени, категории или популÑрноÑти.</string> <string name="browse_gpoddernet_label">ПроÑмотр gpodder.net</string> <!--Actions on feeds--> <string name="mark_all_read_label">Отметить как проÑлушанное</string> <string name="mark_all_read_msg">Отметить вÑе выпуÑки как проÑлушанные</string> <string name="mark_all_read_confirmation_msg">Подтвердите, что хотите пометить вÑе Ñпизоды как проÑлушанные.</string> <string name="mark_all_read_feed_confirmation_msg">Подтвердите, что хотите пометить вÑе Ñпизоды в Ñтом канале как проÑлушанные.</string> - <string name="mark_all_seen_label">Отметить вÑе как замеченное</string> + <string name="mark_all_seen_label">Отметить вÑе как проÑмотренное</string> + <string name="mark_all_seen_msg">Ð’Ñе выпуÑки отмечены как проÑмотренные</string> + <string name="mark_all_seen_confirmation_msg">ПожалуйÑта, подтвердите намерение отметить вÑе выпуÑки как проÑмотренные.</string> <string name="show_info_label">Показать информацию</string> + <string name="rename_feed_label">Переименовать подкаÑÑ‚</string> <string name="remove_feed_label">Удалить подкаÑÑ‚</string> <string name="share_label">ПоделитьÑÑ…</string> <string name="share_link_label">ПоделитьÑÑ ÑÑылкой</string> @@ -110,7 +121,7 @@ <string name="share_feed_url_label">ПоделитьÑÑ ÑÑылкой на канал</string> <string name="share_item_url_label">ПоделитьÑÑ ÑÑылкой на файл выпуÑка</string> <string name="share_item_url_with_position_label">ПоделитьÑÑ ÑÑылкой на файл выпуÑка Ñ Ð¾Ñ‚Ð¼ÐµÑ‚ÐºÐ¾Ð¹ времени</string> - <string name="feed_delete_confirmation_msg">Подтвердите удаление канала и вÑех выпуÑков, загруженных Ñ Ñтого канала.</string> + <string name="feed_delete_confirmation_msg">Подтвердите, что хотите удалить канал \"%1$s\" и ВСЕ Ñкачанные Ñпизоды Ñтого канала.</string> <string name="feed_remover_msg">Удаление канала</string> <string name="load_complete_feed">Обновить веÑÑŒ канал</string> <string name="hide_episodes_title">Скрыть выпуÑки</string> @@ -122,6 +133,7 @@ <string name="hide_not_queued_episodes_label">Ðе в очереди</string> <string name="hide_downloaded_episodes_label">Загружено</string> <string name="hide_not_downloaded_episodes_label">Ðе загружено</string> + <string name="hide_has_media_label">С файлами</string> <string name="filtered_label">Отфильтровано</string> <string name="refresh_failed_msg">{fa-exclamation-circle} ПоÑледнее обновление не удалоÑÑŒ</string> <string name="open_podcast">Открыть подкаÑÑ‚</string> @@ -132,7 +144,9 @@ <string name="stop_label">ОÑтановить</string> <string name="stream_label">ВоÑпроизвеÑти из Ñети</string> <string name="remove_label">Удалить</string> + <string name="delete_label">Удалить</string> <string name="remove_episode_lable">Удалить выпуÑк</string> + <string name="marked_as_seen_label">Отмечено как проÑмотренное</string> <string name="mark_read_label">Отметить как проÑлушанное</string> <string name="marked_as_read_label">Помечено как проÑлушанное</string> <string name="mark_unread_label">Отметить как непроÑлушанное</string> @@ -165,7 +179,7 @@ <string name="download_error_connection_error">Ошибка ÑоединениÑ</string> <string name="download_error_unknown_host">ÐеизвеÑтный узел</string> <string name="download_error_unauthorized">Ошибка авторизации</string> - <string name="download_error_file_type_type">Ошибка в типе файла</string> + <string name="download_error_file_type_type">Ошибка типа файла</string> <string name="download_error_forbidden">ДоÑтуп запрещён</string> <string name="cancel_all_downloads_label">Отменить вÑе загрузки</string> <string name="download_canceled_msg">Загрузка отменена</string> @@ -177,10 +191,10 @@ <string name="download_error_request_error">Ошибка запроÑа</string> <string name="download_error_db_access">Ошибка доÑтупа к базе данных</string> <plurals name="downloads_left"> - <item quantity="one">оÑталаÑÑŒ %d загрузка</item> - <item quantity="few">оÑталоÑÑŒ %d загрузки</item> - <item quantity="many">оÑталоÑÑŒ %d загрузок</item> - <item quantity="other">оÑталоÑÑŒ %d загрузок</item> + <item quantity="one">ОÑталаÑÑŒ %d загрузка</item> + <item quantity="few">ОÑталоÑÑŒ %d загрузки</item> + <item quantity="many">ОÑталоÑÑŒ %d загрузок</item> + <item quantity="other">ОÑталоÑÑŒ %d загрузок</item> </plurals> <string name="downloads_processing">ПроизводитÑÑ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ°</string> <string name="download_notification_title">Получение данных подкаÑта</string> @@ -189,7 +203,7 @@ <string name="download_type_feed">Канал</string> <string name="download_type_media">Медиафайл</string> <string name="download_type_image">Изображение</string> - <string name="download_request_error_dialog_message_prefix">Ошибка при загрузки файла:\u0020</string> + <string name="download_request_error_dialog_message_prefix">Ошибка при загрузке файла:\u0020</string> <string name="authentication_notification_title">Ðеобходима авторизациÑ</string> <string name="authentication_notification_msg">Ð”Ð»Ñ Ð´Ð¾Ñтупа к реÑурÑу необходимо ввеÑти Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸ пароль</string> <string name="confirm_mobile_download_dialog_title">Подтвердите загрузку через мобильное Ñоединение</string> @@ -220,9 +234,10 @@ <string name="move_to_top_label">ПеремеÑтить вверх</string> <string name="move_to_bottom_label">ПеремеÑтить вниз</string> <string name="sort">Сортировать</string> - <string name="alpha">По алфавиту</string> <string name="date">По дате</string> <string name="duration">По продолжительноÑти</string> + <string name="episode_title">Ðазвание выпуÑка</string> + <string name="feed_title">Ðазвание канала</string> <string name="ascending">По возраÑтанию</string> <string name="descending">По убыванию</string> <string name="clear_queue_confirmation_msg">Подтвердите, что хотите очиÑтить очередь от ВСЕХ Ñпизодов.</string> @@ -260,7 +275,7 @@ <string name="enable_sonic">Включить Sonic</string> <!--Empty list labels--> <string name="no_items_label">СпиÑок пуÑÑ‚</string> - <string name="no_feeds_label">Ð’Ñ‹ еще не подпиÑаны ни на один канал</string> + <string name="no_feeds_label">Ð’Ñ‹ ещё не подпиÑаны ни на один канал.</string> <string name="no_chapters_label">Ðтот выпуÑк не Ñодержит оглавлениÑ.</string> <string name="no_shownotes_label">Ðтот выпуÑк не Ñодержит примечаний.</string> <!--Preferences--> @@ -275,13 +290,15 @@ <string name="pref_episode_cleanup_summary">ВыпуÑки, которые не ÑтоÑÑ‚ в очереди и не отмечены как избранные могут быть удалены Ð´Ð»Ñ Ð¾ÑÐ²Ð¾Ð±Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ Ð¼ÐµÑта под Ðвтозагрузку.</string> <string name="pref_pauseOnDisconnect_sum">ПриоÑтановить воÑпроизведение, когда наушники или bluetooth отключены</string> <string name="pref_unpauseOnHeadsetReconnect_sum">Продолжать воÑпроизведение поÑле Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð½Ð°ÑƒÑˆÐ½Ð¸ÐºÐ¾Ð²</string> - <string name="pref_unpauseOnBluetoothReconnect_sum">Продолжать воÑпроизведение поÑле Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð½Ð°ÑƒÑˆÐ½Ð¸ÐºÐ¾Ð² или воÑÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ bluetooth-ÑоединениÑ</string> + <string name="pref_unpauseOnBluetoothReconnect_sum">Продолжать воÑпроизведение поÑле воÑÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ bluetooth-ÑоединениÑ</string> <string name="pref_hardwareForwardButtonSkips_title">ПропуÑкать кнопкой перемотки вперёд</string> <string name="pref_hardwareForwardButtonSkips_sum">При нажатии на физичеÑкую кнопку перемотки вперёд переходить к Ñледующему выпуÑку вмеÑто перемотки</string> + <string name="pref_hardwarePreviousButtonRestarts_title">Ð’ начало кнопкой перемотки назад</string> + <string name="pref_hardwarePreviousButtonRestarts_sum">При нажатии на физичеÑкую кнопку перемотки назад переходить к началу выпуÑка вмеÑто перемотки назад</string> <string name="pref_followQueue_sum">ПоÑле Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ð²Ð¾ÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð¿ÐµÑ€ÐµÐ¹Ñ‚Ð¸ к Ñледующему в очереди</string> <string name="pref_auto_delete_sum">УдалÑÑ‚ÑŒ Ñпизод поÑле Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ð²Ð¾ÑпроизведениÑ</string> <string name="pref_auto_delete_title">ÐвтоматичеÑкое удаление</string> - <string name="pref_smart_mark_as_played_sum">Отмечать выпуÑк как проÑлушанный, даже еÑли до Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ð¾ÑтаетÑÑ Ð½ÐµÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ðµ времÑ</string> + <string name="pref_smart_mark_as_played_sum">Отмечать выпуÑки как проÑлушанные, даже еÑли до Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ð¾ÑтаётÑÑ Ð½ÐµÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ðµ времÑ</string> <string name="pref_smart_mark_as_played_title">ÐŸÑ€ÐµÐ´Ð²Ð°Ñ€Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¾Ñ‚Ð¼ÐµÑ‚ÐºÐ° \"проÑлушано\"</string> <string name="pref_skip_keeps_episodes_sum">СохранÑÑ‚ÑŒ выпуÑки, помеченные как пропущенные</string> <string name="pref_skip_keeps_episodes_title">СохранÑÑ‚ÑŒ пропущенные выпуÑки</string> @@ -299,7 +316,7 @@ <string name="pref_followQueue_title">Ðепрерывное воÑпроизведение</string> <string name="pref_downloadMediaOnWifiOnly_title">Загрузка по Wi-Fi</string> <string name="pref_pauseOnHeadsetDisconnect_title">Ðаушники отÑоединены</string> - <string name="pref_unpauseOnHeadsetReconnect_title">Ðаушники отÑоединены</string> + <string name="pref_unpauseOnHeadsetReconnect_title">Ðаушники подключены обратно</string> <string name="pref_unpauseOnBluetoothReconnect_title">Bluetooth-Ñоединение воÑÑтановлено</string> <string name="pref_mobileUpdate_title">Мобильные обновлениÑ</string> <string name="pref_mobileUpdate_sum">Позволить Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ñ‡ÐµÑ€ÐµÐ· мобильное интернет-подключение</string> @@ -318,11 +335,11 @@ <string name="pref_nav_drawer_title">ÐаÑтроить боковую панель</string> <string name="pref_nav_drawer_sum">ÐаÑтроить вид боковой панели</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_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_counter_title">Счетчик подпиÑок</string> - <string name="pref_nav_drawer_feed_counter_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> <string name="pref_automatic_download_title">ÐвтоматичеÑÐºÐ°Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ°</string> <string name="pref_automatic_download_sum">ÐаÑтроить автоматичеÑкую загрузку выпуÑков.</string> @@ -344,33 +361,39 @@ <string name="pref_gpodnet_logout_toast">Выход произведён уÑпешно</string> <string name="pref_gpodnet_setlogin_information_title">Изменить информацию авторизации</string> <string name="pref_gpodnet_setlogin_information_sum">Изменить информацию авторизации Ð´Ð»Ñ Ð°ÐºÐºÐ°ÑƒÐ½Ñ‚Ð° gpodder.net</string> - <string name="pref_gpodnet_sync_title">Синхронизировать</string> - <string name="pref_gpodnet_sync_sum">Синхронизировать подпиÑки и ÑÑ‚Ð°Ñ‚ÑƒÑ Ð²Ñ‹Ð¿ÑƒÑков Ñ ÑервиÑом gpodder.net</string> + <string name="pref_gpodnet_sync_changes_title">Синхронизировать изменениÑ</string> + <string name="pref_gpodnet_sync_changes_sum">Синхронизировать Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð´Ð¿Ð¸Ñок и выпуÑков при помощи gpodder.net.</string> + <string name="pref_gpodnet_full_sync_title">Синхронизировать полноÑтью</string> + <string name="pref_gpodnet_full_sync_sum">Синхронизировать ÑоÑтоÑÐ½Ð¸Ñ Ð²Ñех подпиÑок и выпуÑков при помощи gpodder.net.</string> + <string name="pref_gpodnet_sync_sum_last_sync_line">ÐŸÑ€ÐµÐ´Ñ‹Ð´ÑƒÑ‰Ð°Ñ Ð¿Ð¾Ð¿Ñ‹Ñ‚ÐºÐ° Ñинхронизации: %1$s (%2$s)</string> <string name="pref_gpodnet_sync_started">Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð·Ð°Ð¿ÑƒÑ‰ÐµÐ½Ð°</string> + <string name="pref_gpodnet_full_sync_started">Запущена Ð¿Ð¾Ð»Ð½Ð°Ñ ÑинхронизациÑ</string> <string name="pref_gpodnet_login_status"><![CDATA[Вход как <i>%1$s</i> Ñ ÑƒÑтройÑтва <i>%2$s</i>]]></string> + <string name="pref_gpodnet_notifications_title">Показывать ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¾Ð± ошибках Ñинхронизации</string> + <string name="pref_gpodnet_notifications_sum">Ðе затрагивает ошибки авторизации.</string> <string name="pref_playback_speed_title">СкороÑÑ‚ÑŒ воÑпроизведениÑ</string> <string name="pref_playback_speed_sum">ÐаÑтроить ÑкороÑти воÑпроизведениÑ</string> <string name="pref_fast_forward">Интервал быÑтрой перемотки вперед</string> + <string name="pref_fast_forward_sum">ÐаÑтройте длину шага в Ñекундах при нажатии кнопки перемотки вперёд</string> <string name="pref_rewind">Интервал быÑтрой перемотки назад</string> + <string name="pref_rewind_sum">ÐаÑтройте длину шага в Ñекундах при нажатии кнопки перемотки назад</string> <string name="pref_gpodnet_sethostname_title">Задать Ð¸Ð¼Ñ ÑƒÐ·Ð»Ð°</string> <string name="pref_gpodnet_sethostname_use_default_host">ИÑпользовать узел по умолчанию</string> - <string name="pref_expandNotify_title">РаÑширенное уведомление</string> - <string name="pref_expandNotify_sum">Ð’Ñегда показывать в уведомлении кнопки ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð²Ð¾Ð¿Ñпроизведением</string> - <string name="pref_persistNotify_title">ПоÑтоÑнный контрооль воÑпроизведениÑ</string> + <string name="pref_expandNotify_title">Развёрнутое уведомление</string> + <string name="pref_expandNotify_sum">Ð’Ñегда разворачивать уведомление, Ð¿Ð¾ÐºÐ°Ð·Ñ‹Ð²Ð°Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸ ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð²Ð¾Ñпроизведением.</string> + <string name="pref_persistNotify_title">ПоÑтоÑнные кнопки воÑпроизведениÑ</string> <string name="pref_persistNotify_sum">СохранÑÑ‚ÑŒ уведомление и кнопки воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð½Ð° Ñкране блокировки во Ð²Ñ€ÐµÐ¼Ñ Ð¿Ð°ÑƒÐ·Ñ‹.</string> <string name="pref_compact_notification_buttons_title">Выбрать кнопки Ñкрана блокировки</string> <string name="pref_compact_notification_buttons_sum">ПоменÑÑ‚ÑŒ кнопки ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð½Ð° Ñкране блокировки. Кнопка воÑпроизведениÑ/паузы приÑутÑтвует поÑтоÑнно.</string> <string name="pref_compact_notification_buttons_dialog_title">Выберите не более %1$d Ñлементов</string> <string name="pref_compact_notification_buttons_dialog_error">ÐÐµÐ»ÑŒÐ·Ñ Ð²Ñ‹Ð±Ñ€Ð°Ñ‚ÑŒ больше %1$d Ñлементов.</string> - <string name="pref_show_subscriptions_in_drawer_title">Показать подпиÑки</string> - <string name="pref_show_subscriptions_in_drawer_sum">Показывать перечень подпиÑок в боковой панели</string> - <string name="pref_lockscreen_background_title">Выбрать фон Ñкрана блокировки</string> + <string name="pref_lockscreen_background_title">МенÑÑ‚ÑŒ фон Ñкрана блокировки</string> <string name="pref_lockscreen_background_sum">ИзменÑет фон Ñкрана блокировки на обложку выпуÑка. Кроме того показывает обложку в Ñторонних приложениÑÑ….</string> <string name="pref_showDownloadReport_title">Показывать отчёт о загрузках</string> - <string name="pref_showDownloadReport_sum">ЕÑли загрузка не удаетÑÑ, показывать отчет Ñ Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ð¾ÑÑ‚Ñми об ошибке.</string> + <string name="pref_showDownloadReport_sum">ЕÑли загрузка не удаётÑÑ, показывать отчёт Ñ Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ð¾ÑÑ‚Ñми об ошибке.</string> <string name="pref_expand_notify_unsupport_toast">ВерÑии Android ниже 4.1 не поддерживают раÑширенные уведомлениÑ.</string> - <string name="pref_queueAddToFront_sum">ДобавлÑÑ‚ÑŒ новые выпуÑки в начало очереди.</string> - <string name="pref_queueAddToFront_title">Ð’ начало очереди.</string> + <string name="pref_queueAddToFront_sum">ДобавлÑÑ‚ÑŒ новые выпуÑки в начало очереди</string> + <string name="pref_queueAddToFront_title">Ð’ начало очереди</string> <string name="pref_smart_mark_as_played_disabled">Отключено</string> <string name="pref_image_cache_size_title">Размер кÑша Ð´Ð»Ñ Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ð¹</string> <string name="pref_image_cache_size_sum">Размер диÑкового кÑша Ð´Ð»Ñ Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ð¹</string> @@ -378,7 +401,7 @@ <string name="crash_report_sum">ОтоÑлать поÑледний отчёт о Ñбое по e-mail</string> <string name="send_email">Отправить Email</string> <string name="experimental_pref">ÐкÑпериментальные наÑтройки</string> - <string name="pref_sonic_title">Проигрыватель Sonic</string> + <string name="pref_sonic_title">Проигрывать через Sonic</string> <string name="pref_sonic_message">ЗадейÑтвовать вÑтроенный медиа проигрыватель Sonic вмеÑто Ñтандартного из ОС Android и Prestissimo</string> <string name="pref_current_value">Текущее значение: %1$s</string> <string name="pref_proxy_title">ПрокÑи</string> @@ -387,19 +410,25 @@ <string name="pref_known_issues">ИзвеÑтные проблемы</string> <string name="pref_no_browser_found">Веб-браузер не обнаружен.</string> <string name="pref_cast_title">Поддержка Chromecast</string> - <string name="pref_cast_message">Включить поддержку удалённого воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð½Ð° уÑтройÑтвах Ñ Google Cast (таких как Chromecast, динамики или ТВ на ОС Android)</string> + <string name="pref_cast_message_play_flavor">Включить поддержку удалённого воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð½Ð° уÑтройÑтвах Ñ Google Cast (таких как Chromecast, динамики или ТВ на ОС Android)</string> + <string name="pref_cast_message_free_flavor">Ð”Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ Chromecast требуютÑÑ ÑобÑтвенничеÑкие библиотеки третьей Ñтороны, которые не включены в данную верÑию AntennaPod</string> + <string name="pref_enqueue_downloaded_title">ДобавлÑÑ‚ÑŒ загруженные в очередь</string> + <string name="pref_enqueue_downloaded_summary">ДобавлÑÑ‚ÑŒ загруженные выпуÑки в очередь</string> <!--Auto-Flattr dialog--> <string name="auto_flattr_enable">Включить автоматичеÑкую поддержку через Flattr</string> <string name="auto_flattr_after_percent">Поддерживать через Flattr Ñпизоды, проÑлушанные на %d процентов</string> <string name="auto_flattr_ater_beginning">Поддерживать Ñпизод через Flattr в начале воÑпроизведениÑ</string> <string name="auto_flattr_ater_end">Поддерживать Ñпизод через Flattr в конце воÑпроизведениÑ</string> <!--Search--> - <string name="search_hint">ПоиÑк каналов или выпуÑков</string> - <string name="found_in_shownotes_label">Ðайдено в опиÑании выпуÑка</string> + <string name="search_hint">Ðайти выпуÑки</string> + <string name="found_in_shownotes_label">Ðайдено в примечаниÑÑ… к выпуÑку</string> <string name="found_in_chapters_label">Ðайдено в главах</string> + <string name="found_in_authors_label">Ðайдено в авторах</string> + <string name="found_in_feeds_label">Ðайдено в каналах</string> <string name="search_status_no_results">Ðичего не найдено</string> <string name="search_label">ПоиÑк</string> <string name="found_in_title_label">Ðайдено в заголовке</string> + <string name="no_results_for_query">Ð”Ð»Ñ \"%1$s\" ничего не найдено</string> <!--OPML import and export--> <string name="opml_import_txtv_button_lable">OPML файлы позволÑÑŽÑ‚ перемещать ваши подкаÑÑ‚Ñ‹ из одного менеджера подкаÑтов в другой.</string> <string name="opml_import_option">ÐаÑтройка %1$d</string> @@ -418,6 +447,7 @@ <string name="choose_file_from_filesystem">Из файловой ÑиÑтемы</string> <string name="choose_file_from_external_application">С помощью внешнего приложениÑ</string> <string name="opml_export_label">ÐкÑпорт в OPML</string> + <string name="html_export_label">ÐкÑпорт в HTML</string> <string name="exporting_label">ÐкÑпортируетÑÑ...</string> <string name="export_error_label">Ошибка ÑкÑпорта</string> <string name="opml_export_success_title">OPML уÑпешно ÑкÑпортирован.</string> @@ -454,6 +484,9 @@ <item quantity="many">%d чаÑов</item> <item quantity="other">%d чаÑов</item> </plurals> + <string name="auto_enable_label">ЗапуÑкать автоматичеÑки</string> + <string name="sleep_timer_enabled_label">Таймер Ñна включён</string> + <string name="sleep_timer_disabled_label">Таймер Ñна отключён</string> <!--gpodder.net--> <string name="gpodnet_taglist_header">Категории</string> <string name="gpodnet_toplist_header">Лучшее</string> @@ -483,6 +516,8 @@ <string name="gpodnetsync_auth_error_descr">Ðеправильное Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð»Ð¸ пароль</string> <string name="gpodnetsync_error_title">Ошибка Ñинхронизации Ñ gpodder.net</string> <string name="gpodnetsync_error_descr">Произошла ошибка во Ð²Ñ€ÐµÐ¼Ñ Ñинхронизации:\u0020</string> + <string name="gpodnetsync_pref_report_successful">УÑпешно</string> + <string name="gpodnetsync_pref_report_failed">Ðеудачно</string> <!--Directory chooser--> <string name="selected_folder_label">Ð’Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð°Ñ Ð¿Ð°Ð¿ÐºÐ°:</string> <string name="create_folder_label">Создать папку</string> @@ -502,16 +537,16 @@ <string name="set_to_default_folder">Выберите папку по умолчанию</string> <string name="pref_pausePlaybackForFocusLoss_sum">Пауза вмеÑто ÑƒÐ¼ÐµÐ½ÑŒÑˆÐµÐ½Ð¸Ñ Ð³Ñ€Ð¾Ð¼ÐºÐ¾Ñти, когда другое приложение проигрывает звуки</string> <string name="pref_pausePlaybackForFocusLoss_title">Пауза при прерывании</string> - <string name="pref_resumeAfterCall_sum">Продолжение воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð¿Ð¾Ñле Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ð·Ð²Ð¾Ð½ÐºÐ°</string> - <string name="pref_resumeAfterCall_title">Включать поÑле звонка</string> - <string name="pref_restart_required">AntennaPod нужно перезапуÑтить Ð´Ð»Ñ Ð¿Ñ€Ð¸Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð½Ð°Ñтроек.</string> + <string name="pref_resumeAfterCall_sum">Продолжать воÑпроизведение поÑле Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ð·Ð²Ð¾Ð½ÐºÐ°</string> + <string name="pref_resumeAfterCall_title">Продолжать поÑле вызова</string> + <string name="pref_restart_required">Следует перезапуÑтить AntennaPod Ð´Ð»Ñ Ð¿Ñ€Ð¸Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð½Ð°Ñтроек.</string> <!--Online feed view--> <string name="subscribe_label">ПодпиÑатьÑÑ</string> <string name="subscribed_label">ПодпиÑка оформлена</string> <string name="downloading_label">Идёт загрузка…</string> <!--Content descriptions for image buttons--> <string name="rewind_label">Ðазад</string> - <string name="fast_forward_label">Вперед</string> + <string name="fast_forward_label">Вперёд</string> <string name="media_type_audio_label">Ðудио</string> <string name="media_type_video_label">Видео</string> <string name="navigate_upwards_label">Перейти выше</string> @@ -535,6 +570,7 @@ <string name="sp_apps_importing_feeds_msg">Импорт подпиÑок из одноцелевых приложений…</string> <string name="search_itunes_label">ПоиÑк в iTunes</string> <string name="filter">Фильтровать</string> + <string name="search_fyyd_label">ПоиÑк в fyyd</string> <!--Episodes apply actions--> <string name="all_label">Ð’Ñе</string> <string name="selected_all_label">Отмечены вÑе выпуÑки</string> @@ -552,6 +588,8 @@ <string name="selected_queued_label">Выбраны выпуÑки из очереди</string> <string name="not_queued_label">Ðе в очереди</string> <string name="selected_not_queued_label">Выбраны выпуÑки не из очереди</string> + <string name="has_media">С файлами</string> + <string name="selected_has_media_label">Выбраны выпуÑки Ñ Ñ„Ð°Ð¹Ð»Ð°Ð¼Ð¸</string> <!--Sort--> <string name="sort_title_a_z">Заголовку (Ð \u2192 Я)</string> <string name="sort_title_z_a">Заголовку (Я \u2192 Ð)</string> diff --git a/core/src/main/res/values-sv-rSE/strings.xml b/core/src/main/res/values-sv-rSE/strings.xml index 8cc3cba6a..83f618d48 100644 --- a/core/src/main/res/values-sv-rSE/strings.xml +++ b/core/src/main/res/values-sv-rSE/strings.xml @@ -26,6 +26,10 @@ <!--Statistics fragment--> <string name="total_time_listened_to_podcasts">Total uppspelningstid:</string> <string name="statistics_details_dialog">%1$d av %2$d episoder startade.\n\nSpelat %3$s av %4$s.</string> + <string name="statistics_mode">Statistikläge</string> + <string name="statistics_mode_normal">Beräkna faktisk speltid. Att spela tvÃ¥ gÃ¥nger räknas tvÃ¥ gÃ¥nger, men att markera som spelad räknas inte</string> + <string name="statistics_mode_count_all">Summera alla podcasts som markerats som spelade</string> + <string name="statistics_speed_not_counted">Notera: Uppspelningshastighet tas inte med i beräkningarna. </string> <!--Main activity--> <string name="drawer_open">Öppna meny</string> <string name="drawer_close">Stäng meny</string> @@ -33,9 +37,11 @@ <string name="drawer_feed_order_unplayed_episodes">Sortera efter räknare</string> <string name="drawer_feed_order_alphabetical">Sortera alfabetiskt</string> <string name="drawer_feed_order_last_update">Sortera efter publiceringsdatum</string> + <string name="drawer_feed_order_most_played">Sortera efter antal spelade episoder</string> <string name="drawer_feed_counter_new_unplayed">Antal nya och ospelade episoder</string> <string name="drawer_feed_counter_new">Antal nya episoder</string> <string name="drawer_feed_counter_unplayed">Antal ospelade episoder</string> + <string name="drawer_feed_counter_downloaded">Antal nedladdade episoder</string> <string name="drawer_feed_counter_none">Inga</string> <!--Webview actions--> <string name="open_in_browser_label">Öppna i Webbläsare</string> @@ -50,6 +56,7 @@ <string name="cancel_label">Avbryt</string> <string name="yes">Ja</string> <string name="no">Nej</string> + <string name="reset">Ã…terställ</string> <string name="author_label">Skapare</string> <string name="language_label">SprÃ¥k</string> <string name="url_label">URL</string> @@ -60,6 +67,7 @@ <string name="refresh_label">Uppdatera</string> <string name="external_storage_error_msg">Ingen extern lagring är tillgänglig. Se till att montera en extern lagringsenhet sÃ¥ att appen kan fungera korrekt.</string> <string name="chapters_label">Kapitel</string> + <string name="chapter_duration">Längd: %1$s</string> <string name="shownotes_label">Shownotes</string> <string name="description_label">Beskrivning</string> <string name="most_recent_prefix">Senaste episoden:\u0020</string> @@ -92,7 +100,7 @@ <string name="etxtFeedurlHint">URL till flöde eller webbsida</string> <string name="txtvfeedurl_label">Lägg till podcast via URL</string> <string name="podcastdirectories_label">Hitta Podcast i Biblioteket</string> - <string name="podcastdirectories_descr">Du kan söka efter podcasts baserat pÃ¥ namn, kategori eller populäritet med tjänsten gpodder.net eller pÃ¥ iTunes Store.</string> + <string name="podcastdirectories_descr">För att hitta nya podcasts kan du söka i iTunes, fyyd, eller pÃ¥ gpodder.net baserat pÃ¥ namn, kategori eller popularitet.</string> <string name="browse_gpoddernet_label">Bläddra pÃ¥ gpodder.net</string> <!--Actions on feeds--> <string name="mark_all_read_label">Markera alla som spelade</string> @@ -100,7 +108,10 @@ <string name="mark_all_read_confirmation_msg">Bekräfta att du verkligen vill markera alla episoder som spelade.</string> <string name="mark_all_read_feed_confirmation_msg">Bekräfta att du verkligen vill markera alla episoder i detta flöde som spelade.</string> <string name="mark_all_seen_label">Markera alla som sedda</string> + <string name="mark_all_seen_msg">Markera alla Episoder som sedda</string> + <string name="mark_all_seen_confirmation_msg">Bekräfta att du vill markera alla episoder som sedda.</string> <string name="show_info_label">Visa information</string> + <string name="rename_feed_label">Byt namn pÃ¥ Podcast</string> <string name="remove_feed_label">Ta bort Podcast</string> <string name="share_label">Dela…</string> <string name="share_link_label">Dela Länk</string> @@ -108,7 +119,7 @@ <string name="share_feed_url_label">Dela Flödets URL</string> <string name="share_item_url_label">Dela Episoden Fil-URL</string> <string name="share_item_url_with_position_label">Dela Episodens Fil-URL med Position</string> - <string name="feed_delete_confirmation_msg">Bekräfta att du vill ta bort denna feed och ALLA avsnitt av denna feed som du har hämtat.</string> + <string name="feed_delete_confirmation_msg">Bekräfta att du vill ta bort flödet \"%1$s\" och ALLA episoder du laddat ned frÃ¥n detta flöde.</string> <string name="feed_remover_msg">Tar bort Flöde</string> <string name="load_complete_feed">Uppdatera hela Flödet</string> <string name="hide_episodes_title">Dölj Episoder</string> @@ -120,6 +131,7 @@ <string name="hide_not_queued_episodes_label">Inte köade</string> <string name="hide_downloaded_episodes_label">Nedladdade</string> <string name="hide_not_downloaded_episodes_label">Ej nedladdade</string> + <string name="hide_has_media_label">Har media</string> <string name="filtered_label">Filtrerad</string> <string name="refresh_failed_msg">{fa-exclamation-circle} Senaste uppdateringen misslyckades</string> <string name="open_podcast">Öppna Podcast</string> @@ -130,7 +142,9 @@ <string name="stop_label">Stopp</string> <string name="stream_label">Strömma</string> <string name="remove_label">Ta bort</string> + <string name="delete_label">Ta bort</string> <string name="remove_episode_lable">Ta bort Episod</string> + <string name="marked_as_seen_label">Markera som sedd</string> <string name="mark_read_label">Markera som spelad</string> <string name="marked_as_read_label">Markera som spelad</string> <string name="mark_unread_label">Markera som ospelad</string> @@ -216,9 +230,10 @@ <string name="move_to_top_label">Flytta längst upp</string> <string name="move_to_bottom_label">Flytta längst ned</string> <string name="sort">Sortering</string> - <string name="alpha">Alfabetiskt</string> <string name="date">Datum</string> <string name="duration">Längd</string> + <string name="episode_title">Episodtitel</string> + <string name="feed_title">Flödestitel</string> <string name="ascending">Stigande</string> <string name="descending">Fallande</string> <string name="clear_queue_confirmation_msg">Bekräfta att du vill rensa kön frÃ¥n ALLA episoder.</string> @@ -272,13 +287,15 @@ <string name="pref_pauseOnDisconnect_sum">Pausa uppspelningen när hörlurar eller bluetooth kopplas ifrÃ¥n.</string> <string name="pref_unpauseOnHeadsetReconnect_sum">Fortsätt uppspelningen när hörlurarna Ã¥teransluts</string> <string name="pref_unpauseOnBluetoothReconnect_sum">Fortsätt uppspelningen när bluetooth Ã¥teransluts</string> - <string name="pref_hardwareForwardButtonSkips_title">FramÃ¥t-knappen hoppar</string> + <string name="pref_hardwareForwardButtonSkips_title">Knappen spola fram hoppar</string> <string name="pref_hardwareForwardButtonSkips_sum">Hoppa till nästa episod istället för att snabbspola vid tryck pÃ¥ hÃ¥rdvaruknappen</string> + <string name="pref_hardwarePreviousButtonRestarts_title">Knappen föregÃ¥ende startar om</string> + <string name="pref_hardwarePreviousButtonRestarts_sum">Starta om den nuvarande episoden när du trycker pÃ¥ hÃ¥rdvaruknappen för föregÃ¥ende istället för att spola tillbaka</string> <string name="pref_followQueue_sum">Hoppa till nästa i kön när uppspelningen är klar</string> <string name="pref_auto_delete_sum">Ta bort episoden när uppspelningen är klar</string> <string name="pref_auto_delete_title">Automatisk Borttagning</string> <string name="pref_smart_mark_as_played_sum">Markera episoder som spelade även om mindre än ett visst antal sekunder är kvar</string> - <string name="pref_smart_mark_as_played_title">Smart markering av uppspelat innehÃ¥ll</string> + <string name="pref_smart_mark_as_played_title">Smart markera som spelad</string> <string name="pref_skip_keeps_episodes_sum">Ta inte bort episoder när de hoppas över</string> <string name="pref_skip_keeps_episodes_title">BehÃ¥ll Överhoppade Episoder</string> <string name="playback_pref">Uppspelning</string> @@ -340,14 +357,22 @@ <string name="pref_gpodnet_logout_toast">Utloggning lyckades</string> <string name="pref_gpodnet_setlogin_information_title">Ändra inloggningsinformation</string> <string name="pref_gpodnet_setlogin_information_sum">Ändra inloggningsinformationen för ditt gpodder.net konto.</string> - <string name="pref_gpodnet_sync_title">Synkronisera nu</string> - <string name="pref_gpodnet_sync_sum">Synkronisera prenumerationer och episodtillstÃ¥nd med gpodder.net</string> + <string name="pref_gpodnet_sync_changes_title">Synkronisera ändringar nu</string> + <string name="pref_gpodnet_sync_changes_sum">Synkronisera ändringar i prenumerationer och episodstatus med gpodder.net.</string> + <string name="pref_gpodnet_full_sync_title">Full synkronisering nu</string> + <string name="pref_gpodnet_full_sync_sum">Synkronisera alla prenumerationer och episodstatus med gpodder.net.</string> + <string name="pref_gpodnet_sync_sum_last_sync_line">Senaste synkroniseringsförsök: %1$s (%2$s)</string> <string name="pref_gpodnet_sync_started">Synkronisering startad</string> + <string name="pref_gpodnet_full_sync_started">Full synkronisering pÃ¥börjad</string> <string name="pref_gpodnet_login_status"><![CDATA[Inloggad som <i>%1$s</i> med enhet <i>%2$s</i>]]></string> + <string name="pref_gpodnet_notifications_title">Visa notifieringar om synkroniseringsfel</string> + <string name="pref_gpodnet_notifications_sum">Denna inställning pÃ¥verkar inte autentiseringsfel.</string> <string name="pref_playback_speed_title">Uppspelningshastigheter</string> <string name="pref_playback_speed_sum">Anpassa de tillgängliga hastigheterna för variabel uppspelningshastighet.</string> - <string name="pref_fast_forward">Spola framÃ¥t</string> - <string name="pref_rewind">Spola bakÃ¥t</string> + <string name="pref_fast_forward">Snabbspolningslängd</string> + <string name="pref_fast_forward_sum">Anpassa antalet sekunder att hoppa framÃ¥t när snabbspolningsknappen används</string> + <string name="pref_rewind">Snabbspolningslängd bakÃ¥t</string> + <string name="pref_rewind_sum">Anpassa antalet sekunder att hoppa bakÃ¥t när snabbspolningsknappen bakÃ¥t används</string> <string name="pref_gpodnet_sethostname_title">Sätt värdnamn</string> <string name="pref_gpodnet_sethostname_use_default_host">Använd standardvärden</string> <string name="pref_expandNotify_title">Expandera aviseringen</string> @@ -358,8 +383,6 @@ <string name="pref_compact_notification_buttons_sum">Ändra uppspelningsknapparna pÃ¥ lÃ¥sskärmen. Spela/Pausa knappen är alltid inkluderad.</string> <string name="pref_compact_notification_buttons_dialog_title">Välj maximalt %1$d st.</string> <string name="pref_compact_notification_buttons_dialog_error">Du kan bara välja maximalt %1$d st.</string> - <string name="pref_show_subscriptions_in_drawer_title">Visa Prenumerationer</string> - <string name="pref_show_subscriptions_in_drawer_sum">Visa prenumerationslistan direkt i navigeringsmenyn</string> <string name="pref_lockscreen_background_title">Sätt LÃ¥sskärmens Bakgrund</string> <string name="pref_lockscreen_background_sum">Sätt lÃ¥sskärmens bakgrund till den spelade episodens bild. En bieffekt är att även tredjepartsappar kan visa bilden.</string> <string name="pref_showDownloadReport_title">Visa Nedladdningsrapport</string> @@ -374,7 +397,7 @@ <string name="crash_report_sum">Sänd den senaste krashrapporten via e-post</string> <string name="send_email">Sänd e-post</string> <string name="experimental_pref">Experimentellt</string> - <string name="pref_sonic_title">Sonic mediaspelare</string> + <string name="pref_sonic_title">Sonic Mediaspelare</string> <string name="pref_sonic_message">Använd den inbyggda Sonic mediaspelare som ersättning för Androids egna mediaspelare och Prestissimo</string> <string name="pref_current_value">Nuvarande värde: %1$s</string> <string name="pref_proxy_title">Proxy</string> @@ -383,19 +406,25 @@ <string name="pref_known_issues">Kända problem</string> <string name="pref_no_browser_found">Ingen webbläsare hittades.</string> <string name="pref_cast_title">Chromecast-stöd</string> - <string name="pref_cast_message">Aktivera stöd för fjärruppspelning av media pÃ¥ Cast-enheter (sÃ¥som Chromecast, Ljudanläggningar eller Android TV)</string> + <string name="pref_cast_message_play_flavor">Aktivera stöd för fjärruppspelning av media pÃ¥ Cast-enheter (sÃ¥som Chromecast, Ljudanläggningar eller Android TV)</string> + <string name="pref_cast_message_free_flavor">Chromecast kräver propretiära tredjepartsbibliotek som inte är inkluderade i denna version av AntennaPod</string> + <string name="pref_enqueue_downloaded_title">Lägg nedladdade i kön</string> + <string name="pref_enqueue_downloaded_summary">Lägg nedladdade episoder i uppspelningskön</string> <!--Auto-Flattr dialog--> <string name="auto_flattr_enable">Aktivera automatisk Flattring</string> <string name="auto_flattr_after_percent">Flattra episoden sÃ¥ snart %d procent har spelats</string> <string name="auto_flattr_ater_beginning">Flattra episoden när den startas</string> <string name="auto_flattr_ater_end">Flattra episoden när den spelats klart</string> <!--Search--> - <string name="search_hint">Sök efter flöden eller episoder</string> + <string name="search_hint">Sök efter episoder</string> <string name="found_in_shownotes_label">Hittad i shownotes</string> <string name="found_in_chapters_label">Hittad i kapitel</string> + <string name="found_in_authors_label">Hittad i författare</string> + <string name="found_in_feeds_label">Hittad i flöden</string> <string name="search_status_no_results">Inga resultat hittades</string> <string name="search_label">Sök</string> <string name="found_in_title_label">Hittad i titeln</string> + <string name="no_results_for_query">Inga resultat hittades för \"%1$s\"</string> <!--OPML import and export--> <string name="opml_import_txtv_button_lable">OPML-filer lÃ¥ter dig flytta dina podcasts frÃ¥n en podcatcher till en annan.</string> <string name="opml_import_option">Val %1$d</string> @@ -414,6 +443,7 @@ <string name="choose_file_from_filesystem">FrÃ¥n lokalt filsystem</string> <string name="choose_file_from_external_application">Använd extern applikation</string> <string name="opml_export_label">OPML export</string> + <string name="html_export_label">HTML export</string> <string name="exporting_label">Exporterar…</string> <string name="export_error_label">Exporteringsfel</string> <string name="opml_export_success_title">OPML Exportering lyckades.</string> @@ -444,6 +474,9 @@ <item quantity="one">1 timme</item> <item quantity="other">%d timmar</item> </plurals> + <string name="auto_enable_label">Auto-aktivera</string> + <string name="sleep_timer_enabled_label">Sömntimer aktiverad</string> + <string name="sleep_timer_disabled_label">Sömntimer inaktiverad</string> <!--gpodder.net--> <string name="gpodnet_taglist_header">KATEGORIER</string> <string name="gpodnet_toplist_header">BÄSTA PODCASTS</string> @@ -473,6 +506,8 @@ <string name="gpodnetsync_auth_error_descr">Fel användarnamn eller lösenord</string> <string name="gpodnetsync_error_title">gpodder.net synkroniseringsfel</string> <string name="gpodnetsync_error_descr">Ett fel uppstod under synkronisering:\u0020</string> + <string name="gpodnetsync_pref_report_successful">Lyckades</string> + <string name="gpodnetsync_pref_report_failed">Misslyckades</string> <!--Directory chooser--> <string name="selected_folder_label">Vald mapp:</string> <string name="create_folder_label">Skapa mapp</string> @@ -525,6 +560,7 @@ <string name="sp_apps_importing_feeds_msg">Importerar prenumerationer frÃ¥n appar gjorda för ett enda syfte…</string> <string name="search_itunes_label">Leta i iTunes</string> <string name="filter">Filtrera</string> + <string name="search_fyyd_label">Sök i fyyd</string> <!--Episodes apply actions--> <string name="all_label">Alla</string> <string name="selected_all_label">Välj alla Episoder</string> @@ -542,6 +578,8 @@ <string name="selected_queued_label">Valde köade Episoder</string> <string name="not_queued_label">Ej köad</string> <string name="selected_not_queued_label">Välj ej köade Episoder</string> + <string name="has_media">Har media</string> + <string name="selected_has_media_label">Valde episoder med media</string> <!--Sort--> <string name="sort_title_a_z">Titel (A \u2192 Ö)</string> <string name="sort_title_z_a">Titel (Ö \u2192 A)</string> diff --git a/core/src/main/res/values-sw-rKE/strings.xml b/core/src/main/res/values-sw-rKE/strings.xml new file mode 100644 index 000000000..28dfeb6e8 --- /dev/null +++ b/core/src/main/res/values-sw-rKE/strings.xml @@ -0,0 +1,38 @@ +<?xml version='1.0' encoding='UTF-8'?> +<resources xmlns:tools="http://schemas.android.com/tools"> + <!--Activitiy and fragment titles--> + <!--Statistics fragment--> + <!--Main activity--> + <!--Webview actions--> + <!--Playback history--> + <!--Other--> + <!--'Add Feed' Activity labels--> + <!--Actions on feeds--> + <!--actions on feeditems--> + <!--Download messages and labels--> + <!--Mediaplayer messages--> + <!--Queue operations--> + <!--Flattr--> + <!--Flattr--> + <!--Variable Speed--> + <!--Empty list labels--> + <!--Preferences--> + <!--Auto-Flattr dialog--> + <!--Search--> + <!--OPML import and export--> + <!--Sleep timer--> + <!--gpodder.net--> + <!--Directory chooser--> + <!--Online feed view--> + <!--Content descriptions for image buttons--> + <!--Feed information screen--> + <!--Progress information--> + <!--AntennaPodSP--> + <!--Episodes apply actions--> + <!--Sort--> + <!--Rating dialog--> + <!--Audio controls--> + <!--proxy settings--> + <!--Casting--> + <!--<string name="cast_failed_to_connect">Could not connect to the device</string>--> +</resources> diff --git a/core/src/main/res/values-te/strings.xml b/core/src/main/res/values-te/strings.xml new file mode 100644 index 000000000..8afbdb37d --- /dev/null +++ b/core/src/main/res/values-te/strings.xml @@ -0,0 +1,103 @@ +<?xml version='1.0' encoding='UTF-8'?> +<resources xmlns:tools="http://schemas.android.com/tools"> + <!--Activitiy and fragment titles--> + <string name="feeds_label">ఫీడà±à°²à±</string> + <string name="statistics_label">గణాంకాలà±</string> + <string name="all_episodes_short_label">à°…à°¨à±à°¨à±€</string> + <string name="favorite_episodes_label">ఇషà±à°Ÿà°¾à°²à±</string> + <string name="new_label">కొతà±à°¤à°¦à°¿</string> + <string name="settings_label">అమరికలà±</string> + <string name="downloads_label">దింపà±à°•à±‹à°³à±à°³à±</string> + <string name="downloads_running_label">నడà±à°¸à±à°¤à±à°¨à±à°¨à°µà°¿</string> + <string name="downloads_completed_label">పూరà±à°¤à°¯à°¿à°¨à°µà°¿</string> + <string name="downloads_log_label">à°šà°¿à°Ÿà±à°Ÿà°¾</string> + <string name="subscriptions_label">చందాలà±</string> + <string name="subscriptions_list_label">చందాల జాబితా</string> + <string name="free_space_label">%1$s ఖాళీ</string> + <!--Statistics fragment--> + <!--Main activity--> + <string name="drawer_feed_counter_none">à°à°®à±€à°²à±‡à°µà±</string> + <!--Webview actions--> + <!--Playback history--> + <!--Other--> + <string name="cancel_label">à°°à°¦à±à°¦à±à°šà±‡à°¯à°¿</string> + <string name="yes">à°…à°µà±à°¨à±</string> + <string name="no">కాదà±</string> + <string name="language_label">à°à°¾à°·</string> + <string name="podcast_settings_label">అమరికలà±</string> + <string name="description_label">వివరణ</string> + <string name="length_prefix">నిడివి:\u0020</string> + <string name="loading_label">వసà±à°¤à±‹à°‚ది…</string> + <string name="close_label">మూసివేయి</string> + <string name="feed_auto_download_always">à°Žà°²à±à°²à°ªà±à°ªà±à°¡à±‚</string> + <string name="send_label">పంపించà±â€¦</string> + <!--'Add Feed' Activity labels--> + <!--Actions on feeds--> + <string name="share_label">పంచà±à°•à±‹à°‚డి…</string> + <!--actions on feeditems--> + <string name="play_label">ఆడించà±</string> + <string name="pause_label">నిలà±à°ªà±</string> + <string name="stop_label">ఆపివేయి</string> + <string name="delete_label">తొలగించà±</string> + <!--Download messages and labels--> + <!--Mediaplayer messages--> + <!--Queue operations--> + <string name="date">తేదీ</string> + <string name="duration">నిడివి</string> + <string name="ascending">ఆరోహణ</string> + <string name="descending">అవరోహణ</string> + <!--Flattr--> + <!--Flattr--> + <!--Variable Speed--> + <!--Empty list labels--> + <!--Preferences--> + <string name="about_pref">à°—à±à°°à°¿à°‚à°šà°¿</string> + <string name="services_label">సేవలà±</string> + <string name="network_pref">నెటà±â€Œà°µà°°à±à°•à±</string> + <string name="pref_update_interval_hours_plural">à°—à°‚à°Ÿà°²à±</string> + <string name="pref_update_interval_hours_singular">à°—à°‚à°Ÿ</string> + <string name="experimental_pref">à°ªà±à°°à°¯à±‹à°—ాతà±à°®à°•à°‚</string> + <string name="pref_proxy_title">à°ªà±à°°à°¾à°•à±à°¸à±€</string> + <!--Auto-Flattr dialog--> + <!--Search--> + <!--OPML import and export--> + <string name="select_all_label">à°…à°¨à±à°¨à±€ à°Žà°‚à°šà±à°•à±‹à°‚à°¡à°¿</string> + <!--Sleep timer--> + <string name="time_seconds">à°•à±à°·à°£à°¾à°²à±</string> + <string name="time_minutes">నిమిషాలà±</string> + <string name="time_hours">à°—à°‚à°Ÿà°²à±</string> + <plurals name="time_seconds_quantified"> + <item quantity="one">1 à°•à±à°·à°£à°‚</item> + <item quantity="other">%d à°•à±à°·à°£à°¾à°²à±</item> + </plurals> + <plurals name="time_minutes_quantified"> + <item quantity="one">1 నిమిషం</item> + <item quantity="other">%d నిమిషాలà±</item> + </plurals> + <plurals name="time_hours_quantified"> + <item quantity="one">1 à°—à°‚à°Ÿ</item> + <item quantity="other">%d à°—à°‚à°Ÿà°²à±</item> + </plurals> + <!--gpodder.net--> + <string name="gpodnet_taglist_header">వరà±à°—ాలà±</string> + <string name="username_label">వాడà±à°•à°°à°¿ పేరà±</string> + <string name="password_label">సంకేతపదం</string> + <!--Directory chooser--> + <!--Online feed view--> + <!--Content descriptions for image buttons--> + <!--Feed information screen--> + <!--Progress information--> + <!--AntennaPodSP--> + <!--Episodes apply actions--> + <string name="all_label">à°…à°¨à±à°¨à±€</string> + <string name="none_label">à°à°®à±€à°²à±‡à°¦à±</string> + <!--Sort--> + <!--Rating dialog--> + <string name="rating_later_label">తరà±à°µà°¾à°¤ à°—à±à°°à±à°¤à±à°šà±‡à°¯à°¿</string> + <!--Audio controls--> + <!--proxy settings--> + <string name="proxy_type_label">à°°à°•à°‚</string> + <string name="optional_hint">(à°à°šà±à°šà°¿à°•à°‚)</string> + <!--Casting--> + <!--<string name="cast_failed_to_connect">Could not connect to the device</string>--> +</resources> diff --git a/core/src/main/res/values-tr/strings.xml b/core/src/main/res/values-tr/strings.xml index c57eb0663..8b9bd5f20 100644 --- a/core/src/main/res/values-tr/strings.xml +++ b/core/src/main/res/values-tr/strings.xml @@ -1,31 +1,28 @@ <?xml version='1.0' encoding='UTF-8'?> <resources xmlns:tools="http://schemas.android.com/tools"> <!--Activitiy and fragment titles--> - <string name="app_name">AntennaPod</string> <string name="feeds_label">Beslemeler</string> + <string name="statistics_label">Ä°statistikler</string> <string name="add_feed_label">Cep yayını ekle</string> - <string name="podcasts_label">CEP YAYINLARI</string> <string name="episodes_label">Bölümler</string> - <string name="new_episodes_label">Yeni bölümler</string> - <string name="all_episodes_label">Tüm bölümler</string> <string name="all_episodes_short_label">Tümü</string> <string name="favorite_episodes_label">Favoriler</string> <string name="new_label">Yeni</string> - <string name="waiting_list_label">Bekleme listesi</string> <string name="settings_label">Ayarlar</string> <string name="add_new_feed_label">Cep Yayını ekle</string> <string name="downloads_label">Ä°ndirilenler</string> <string name="downloads_running_label">Çalışıyor</string> <string name="downloads_completed_label">Tamamlandı</string> <string name="downloads_log_label">Günlük</string> + <string name="subscriptions_label">Abonelikler</string> + <string name="subscriptions_list_label">Abonelik Listesi</string> <string name="cancel_download_label">Ä°ndirmeyi Ä°ptal Et</string> <string name="playback_history_label">Çalma geçmiÅŸi</string> <string name="gpodnet_main_label">gpodder.net</string> <string name="gpodnet_auth_label">gpodder.net giriÅŸ</string> - <!--New episodes fragment--> - <string name="recently_published_episodes_label">Son yayınlananlar</string> - <string name="episode_filter_label">Sadece yeni bölümleri göster</string> + <string name="free_space_label">%1$s ücretsiz</string> <!--Statistics fragment--> + <string name="total_time_listened_to_podcasts">Toplam cep yayını çalma zamanı:</string> <!--Main activity--> <string name="drawer_open">Münüyü aç</string> <string name="drawer_close">Menüyü kapat</string> @@ -36,6 +33,7 @@ <string name="drawer_feed_counter_new_unplayed">Yeni ve çalınmamış bölümlerin sayısı</string> <string name="drawer_feed_counter_new">Yeni bölümlerin sayısı</string> <string name="drawer_feed_counter_unplayed">Çalınmamış bölümlerin sayısı</string> + <string name="drawer_feed_counter_downloaded">Ä°ndirilen bölümlerin sayısı</string> <string name="drawer_feed_counter_none">Hiçbiri</string> <!--Webview actions--> <string name="open_in_browser_label">Tarayıcıda aç</string> @@ -50,6 +48,7 @@ <string name="cancel_label">Ä°ptal</string> <string name="yes">Evet</string> <string name="no">Hayır</string> + <string name="reset">Sıfırla</string> <string name="author_label">Yayıncı</string> <string name="language_label">Dil</string> <string name="url_label">URL</string> @@ -67,16 +66,18 @@ <string name="length_prefix">Uzunluk:\u0020</string> <string name="size_prefix">Boyut:\u0020</string> <string name="processing_label">Ä°ÅŸleniyor</string> + <string name="loading_label">Yükleniyor...</string> <string name="save_username_password_label">Kullanıcı adı ve ÅŸifreyi kaydet</string> <string name="close_label">Kapat</string> <string name="retry_label">Yeniden dene</string> <string name="auto_download_label">Otomatik indirmelere dahil et</string> <string name="auto_download_apply_to_items_title">Önceki Bölümlere Uygula</string> - <string name="auto_delete_label">Bölümü Otomatik Olarak Sil\n(genel varsayılanı yoksayar)</string> + <string name="auto_delete_label">Bölümü Otomatik Sil</string> <string name="parallel_downloads_suffix">\u0020paralel indirmeler</string> - <string name="feed_auto_download_global">Genel</string> + <string name="feed_auto_download_global">Varsayılan ayarlar</string> <string name="feed_auto_download_always">Her zaman</string> <string name="feed_auto_download_never">Hiçbir zaman</string> + <string name="send_label">Gönder...</string> <string name="episode_cleanup_never">Hiçbir zaman</string> <string name="episode_cleanup_queue_removal">Sırada deÄŸilse</string> <string name="episode_cleanup_after_listening">Bittikten sonra</string> @@ -89,7 +90,6 @@ <string name="etxtFeedurlHint">www.example.com/feed</string> <string name="txtvfeedurl_label">URL ile cep yayını ekle</string> <string name="podcastdirectories_label">Dizinde cep yayını bul</string> - <string name="podcastdirectories_descr">gdpodder.net dizininde yeni cep yayınlarını isme, kategoriye veya popülerliÄŸe göre arayabilirsiniz veya iTunes maÄŸazasında arama yapabilirsiniz.</string> <string name="browse_gpoddernet_label">gpodder.net\'e gözat</string> <!--Actions on feeds--> <string name="mark_all_read_label">Hepsini oynatıldı olarak iÅŸaretle</string> @@ -97,14 +97,17 @@ <string name="mark_all_read_confirmation_msg">Lütfen tüm bölümleri oynatıldı olarak iÅŸaretlemek istediÄŸinizi onaylayın.</string> <string name="mark_all_read_feed_confirmation_msg">Lütfen bu besleme içindeki tüm bölümleri oynatıldı olarak iÅŸaretlemek istediÄŸinizi onaylayın.</string> <string name="mark_all_seen_label">Hepsini görüldü olarak iÅŸaretle</string> + <string name="mark_all_seen_msg">Tüm bölümler görüldü olarak iÅŸaretlendi</string> + <string name="mark_all_seen_confirmation_msg">Lütfen tüm bölümleri görüldü olarak iÅŸaretlemek istediÄŸinizi onaylayın.</string> <string name="show_info_label">Bilgiyi göster</string> + <string name="rename_feed_label">Cep yayınını yeniden adlandır</string> <string name="remove_feed_label">Cep yayını kaldır</string> + <string name="share_label">PaylaÅŸ...</string> <string name="share_link_label">Link\'i paylaÅŸ</string> <string name="share_link_with_position_label">Link\'i Konumla birlikte paylaÅŸ</string> <string name="share_feed_url_label">Besleme Adresini PaylaÅŸ</string> - <string name="share_item_url_label">Bölüm Adresini PaylaÅŸ</string> - <string name="share_item_url_with_position_label">Bölüm Adresini Konumla birlikte paylaÅŸ</string> - <string name="feed_delete_confirmation_msg">Lütfen bu beslemeyi ve bu beslemeye ait indirilmiÅŸ BÃœTÃœN bölümleri silme isteÄŸinizi onaylayın.</string> + <string name="share_item_url_label">Bölüm Dosyası Adresini PaylaÅŸ</string> + <string name="share_item_url_with_position_label">Bölüm Dosyası Adresini Konumla birlikte paylaÅŸ</string> <string name="feed_remover_msg">Besleme kaldırılıyor</string> <string name="load_complete_feed">Tüm beslemeyi yenile</string> <string name="hide_episodes_title">Bölümleri gizle</string> @@ -116,8 +119,10 @@ <string name="hide_not_queued_episodes_label">Kuyrukta deÄŸil</string> <string name="hide_downloaded_episodes_label">Ä°ndirildi</string> <string name="hide_not_downloaded_episodes_label">Ä°ndirilmedi</string> + <string name="hide_has_media_label">Medya var</string> <string name="filtered_label">Filtrelendi</string> <string name="refresh_failed_msg">{fa-exclamation-circle} Son yenileme baÅŸarısız oldu</string> + <string name="open_podcast">Cep yayını aç</string> <!--actions on feeditems--> <string name="download_label">Ä°ndir</string> <string name="play_label">Oynat</string> @@ -125,7 +130,9 @@ <string name="stop_label">Durdur</string> <string name="stream_label">Akış</string> <string name="remove_label">Kaldır</string> + <string name="delete_label">Sil</string> <string name="remove_episode_lable">Bölümü kaldır</string> + <string name="marked_as_seen_label">Görüldü olarak iÅŸaretlendi</string> <string name="mark_read_label">Oynatıldı olarak iÅŸaretle</string> <string name="marked_as_read_label">Oynatıldı olarak iÅŸaretlendi</string> <string name="mark_unread_label">Oynatılmadı olarak iÅŸaretle</string> @@ -133,11 +140,11 @@ <string name="added_to_queue_label">KuyruÄŸa Eklendi</string> <string name="remove_from_queue_label">Kuyruktan Kaldır</string> <string name="add_to_favorite_label">Favorilere Ekle</string> + <string name="added_to_favorites">Favorilere Eklendi</string> <string name="remove_from_favorite_label">Favorilerden Kaldır</string> + <string name="removed_from_favorites">Favorilerden Kaldırıldı</string> <string name="visit_website_label">Siteyi Ziyaret Et</string> <string name="support_label">Flattr ile destekle</string> - <string name="enqueue_all_new">Hepsini kuyruÄŸa ekle</string> - <string name="download_all">Hepsini indir</string> <string name="skip_episode_label">Bölümü atla</string> <string name="activate_auto_download">Otomatik indirmeyi etkinleÅŸtir</string> <string name="deactivate_auto_download">Otomatik indirmeyi devre dışı bırak</string> @@ -158,6 +165,8 @@ <string name="download_error_connection_error">Baplantı hatası</string> <string name="download_error_unknown_host">Bilinmeyen sunucu</string> <string name="download_error_unauthorized">Yetkilendirme hatası</string> + <string name="download_error_file_type_type">Dosya Tipi Hatası</string> + <string name="download_error_forbidden">Yasak</string> <string name="cancel_all_downloads_label">Bütün indirmeleri iptal et</string> <string name="download_canceled_msg">Ä°ndirme iptal edildi</string> <string name="download_canceled_autodownload_enabled_msg">Ä°ndirme iptal edildi\nBu öğe için <i>Otomatik Ä°ndirme</i> devre dışı</string> @@ -167,6 +176,10 @@ <string name="download_error_io_error">G/Ç Hatası</string> <string name="download_error_request_error">Ä°stek hatası</string> <string name="download_error_db_access">Veritabanı eriÅŸim hatası</string> + <plurals name="downloads_left"> + <item quantity="one">%d indirme kaldı</item> + <item quantity="other">%d indirme kaldı</item> + </plurals> <string name="downloads_processing">Ä°ndirmeler iÅŸleniyor</string> <string name="download_notification_title">Cep yayını verileri indiriliyor</string> <string name="download_report_content">%1$d indirme baÅŸarılı, %2$d baÅŸarısız</string> @@ -191,22 +204,24 @@ <string name="playback_error_server_died">Sunucu geberdi</string> <string name="playback_error_unknown">Bilinmeyen Hata</string> <string name="no_media_playing_label">Çalınan medya yok</string> - <string name="position_default_label">00:00:00</string> <string name="player_buffering_msg">Ara belleÄŸe alınıyor</string> <string name="playbackservice_notification_title">Cep yayını çalınıyor</string> <string name="unknown_media_key">AntennaPod - Bilinmeyen medya anahtarı: %1$d</string> <!--Queue operations--> <string name="lock_queue">KuyruÄŸu kilitle</string> <string name="unlock_queue">KuyruÄŸun kilidini aç</string> + <string name="queue_locked">Kuyruk kilitlendi</string> + <string name="queue_unlocked">Kuyruk kilidi açıldı</string> <string name="clear_queue_label">KuyruÄŸu temizle</string> <string name="undo">Geri al</string> <string name="removed_from_queue">Öge kaldırıldı</string> <string name="move_to_top_label">En üste taşı</string> <string name="move_to_bottom_label">En alta taşı</string> <string name="sort">Sırala</string> - <string name="alpha">Alfabetik olarak</string> <string name="date">Tarih</string> <string name="duration">Süre</string> + <string name="episode_title">Blüm baÅŸlığı</string> + <string name="feed_title">Besleme baÅŸlığı</string> <string name="ascending">Artan</string> <string name="descending">Azalan</string> <string name="clear_queue_confirmation_msg">Lütfen içerisindeki BÃœTÃœN ölümlerle birlikte kuyruÄŸu temizleme isteÄŸinizi onaylayın.</string> @@ -245,6 +260,8 @@ <string name="no_items_label">Bu listede hiç öge yok.</string> <string name="no_feeds_label">Henüz hiçbir beslemeye abone deÄŸilsiniz.</string> <!--Preferences--> + <string name="storage_pref">Depolama</string> + <string name="project_pref">Proje</string> <string name="other_pref">DiÄŸer</string> <string name="about_pref">Hakkında</string> <string name="queue_label">Kuyruk</string> @@ -312,8 +329,6 @@ <string name="pref_gpodnet_setlogin_information_sum">gpodder.net hesabınız için giriÅŸ bilgisini deÄŸiÅŸtirin.</string> <string name="pref_playback_speed_title">Çalma hızları</string> <string name="pref_playback_speed_sum">DeÄŸiÅŸken hızlı ses yürütmesi için kullanılabilir hızları özelleÅŸtirin</string> - <string name="pref_fast_forward">Ä°leri sarma süresi</string> - <string name="pref_rewind">Geri sarma süresi</string> <string name="pref_gpodnet_sethostname_title">Sunucu ismini ayarla</string> <string name="pref_gpodnet_sethostname_use_default_host">Varsayılan sunucuyu kullan</string> <string name="pref_expandNotify_title">Bildirimi GeniÅŸlet</string> @@ -332,15 +347,13 @@ <string name="crash_report_sum">En son çökme raporunu e-posta ile gönder</string> <string name="send_email">E-posta gönder</string> <string name="experimental_pref">Deneysel</string> - <string name="pref_sonic_title">Sonic ortam yürütücüsü</string> + <string name="pref_faq">SSS</string> <!--Auto-Flattr dialog--> <string name="auto_flattr_enable">Otomatik Flattr\'lamayı etkinleÅŸtir</string> <string name="auto_flattr_after_percent">Bölümün yüzde %d kısmı oynatıldığında Flattr\'la</string> <string name="auto_flattr_ater_beginning">Oynatma baÅŸladığında bölümü Flattr\'la</string> <string name="auto_flattr_ater_end">Oynatma bittiÄŸinde bölümü Flattr\'la</string> <!--Search--> - <string name="search_hint">Besleme veya Bölüm Ara</string> - <string name="found_in_shownotes_label">Nolarda bulundu</string> <string name="found_in_chapters_label">Kısımlarda bulundu</string> <string name="search_status_no_results">Sonuç bulunamadı</string> <string name="search_label">Ara</string> @@ -357,6 +370,7 @@ <string name="reading_opml_label">OPML dosyası okunuyor</string> <string name="select_all_label">Hepsini seç</string> <string name="deselect_all_label">Tüm seçimleri geri al</string> + <string name="select_options_label">Seç...</string> <string name="choose_file_from_filesystem">Yerel dosya sisteminden</string> <string name="choose_file_from_external_application">Harici uygulama kullan</string> <string name="opml_export_label">OPML dışa aktar</string> @@ -440,33 +454,27 @@ <!--Online feed view--> <string name="subscribe_label">Ãœye ol</string> <string name="subscribed_label">Ãœye olundu</string> + <string name="downloading_label">Ä°ndiriliyor...</string> <!--Content descriptions for image buttons--> - <string name="show_chapters_label">Kısımları göster</string> - <string name="show_shownotes_label">Notları göster</string> - <string name="show_cover_label">Resmi göster</string> <string name="rewind_label">Geri sar</string> <string name="fast_forward_label">Ä°leri sar</string> <string name="media_type_audio_label">Ses</string> <string name="media_type_video_label">Vidyo</string> <string name="navigate_upwards_label">Yukarı çık</string> - <string name="butAction_label">Daha fazla eylem</string> - <string name="status_playing_label">Bölüm çalınıyor</string> <string name="status_downloading_label">Bölüm indiriliyor</string> - <string name="status_downloaded_label">Bölüm indirildi</string> - <string name="status_unread_label">Bu öğe yeni</string> <string name="in_queue_label">Bölüm kuyrukta</string> - <string name="new_episodes_count_label">Yeni bölümlerin sayısı</string> - <string name="in_progress_episodes_count_label">Dinlemeye baÅŸladığınız yeni bölümlerin sayısı</string> <string name="drag_handle_content_description">Bu öğenin pozisyonunu deÄŸiÅŸtirmek için sürükleyin</string> <string name="load_next_page_label">Sonraki sayfayı yükle</string> <!--Feed information screen--> <string name="authentication_label">Yetkilendirme</string> <string name="authentication_descr">Bu cep yayını ve içerdiÄŸi bölümler için kullanıcı adı ÅŸifreyi deÄŸiÅŸtir.</string> + <string name="auto_download_settings_label">Otomatik Ä°ndirme Seçenekleri</string> <!--Progress information--> <string name="progress_upgrading_database">Veritabanı yükseltiliyor</string> <!--AntennaPodSP--> <string name="sp_apps_importing_feeds_msg">Ãœyelikler tek-amaçlı uygulamalardan içe aktarılıyor...</string> <string name="search_itunes_label">iTunes\'da Arama</string> + <!--Episodes apply actions--> <string name="all_label">Tümü</string> <string name="selected_all_label">Tüm Bölümler Seçildi</string> <string name="none_label">Hiçbiri</string> @@ -479,6 +487,7 @@ <string name="selected_downloaded_label">Ä°ndirilen Bölümler Seçildi</string> <string name="not_downloaded_label">Ä°ndirilmeyen</string> <string name="selected_not_downloaded_label">Ä°ndirilmeyen Bölümler Seçildi</string> + <!--Sort--> <string name="sort_title_a_z">BaÅŸlık (A \u2192 Z)</string> <string name="sort_title_z_a">BaÅŸlık (Z \u2192 A)</string> <string name="sort_date_new_old">Tarih (Yeni \u2192 Eski)</string> @@ -492,5 +501,11 @@ <string name="rating_later_label">Daha sonra hatırlat</string> <string name="rating_now_label">Evet, ÅŸimdi yapalım!</string> <!--Audio controls--> + <string name="volume">Ses</string> <!--proxy settings--> + <string name="proxy_test_label">Test</string> + <string name="proxy_test_successful">Test baÅŸarılı</string> + <string name="proxy_test_failed">Test baÅŸarısız</string> + <!--Casting--> + <!--<string name="cast_failed_to_connect">Could not connect to the device</string>--> </resources> diff --git a/core/src/main/res/values-uk-rUA/strings.xml b/core/src/main/res/values-uk-rUA/strings.xml index 43707e8f4..308d390c6 100644 --- a/core/src/main/res/values-uk-rUA/strings.xml +++ b/core/src/main/res/values-uk-rUA/strings.xml @@ -26,6 +26,10 @@ <!--Statistics fragment--> <string name="total_time_listened_to_podcasts">Загальний Ñ‡Ð°Ñ Ð¿Ñ€Ð¾Ñлуханих подкаÑтів:</string> <string name="statistics_details_dialog">%1$d з %2$d епізодів почато.\n\nПроÑлухано %3$s з %4$s.</string> + <string name="statistics_mode">Режим ÑтатиÑтики</string> + <string name="statistics_mode_normal">ОбчиÑлити триваліÑÑ‚ÑŒ проÑлуханого. ПроÑлухане двічі враховуєтьÑÑ Ð´Ð²Ñ–Ñ‡Ð¸, але проÑто позначене Ñк проÑлухане не враховуєтьÑÑ </string> + <string name="statistics_mode_count_all">ПідÑумувати вÑÑ– подкаÑти позначені Ñк проÑлухані</string> + <string name="statistics_speed_not_counted">ЗауваженнÑ: ШвидкіÑÑ‚ÑŒ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð²Ð°Ð½Ð½Ñ Ð½Ðµ беретьÑÑ Ð´Ð¾ уваги.</string> <!--Main activity--> <string name="drawer_open">Показати меню</string> <string name="drawer_close">Сховати меню</string> @@ -33,9 +37,11 @@ <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> <string name="drawer_feed_counter_new">КількіÑÑ‚ÑŒ нових епізодів</string> <string name="drawer_feed_counter_unplayed">КількіÑÑ‚ÑŒ непроÑлуханих епізодів</string> + <string name="drawer_feed_counter_downloaded">КількіÑÑ‚ÑŒ завантажених епізодів</string> <string name="drawer_feed_counter_none">Жодних</string> <!--Webview actions--> <string name="open_in_browser_label">Відкрити в браузері</string> @@ -50,6 +56,7 @@ <string name="cancel_label">СкаÑувати</string> <string name="yes">Так</string> <string name="no">ÐÑ–</string> + <string name="reset">ПерезапуÑк</string> <string name="author_label">Ðвтор</string> <string name="language_label">Мова</string> <string name="url_label">URL</string> @@ -60,6 +67,7 @@ <string name="refresh_label">Оновити</string> <string name="external_storage_error_msg">Ðемає доÑтупної карти пам\'ÑÑ‚Ñ–. Зовнішній ноÑій потрібен Ð´Ð»Ñ ÐºÐ¾Ñ€ÐµÐºÑ‚Ð½Ð¾Ñ— роботи додатку</string> <string name="chapters_label">Глави</string> + <string name="chapter_duration">ТриваліÑÑ‚ÑŒ: %1$s</string> <string name="shownotes_label">Ðотатки до епізода</string> <string name="description_label">ОпиÑ</string> <string name="most_recent_prefix">Ðайновіший епізод:\u0020</string> @@ -93,7 +101,7 @@ <string name="etxtFeedurlHint">URL канала або Ñайта</string> <string name="txtvfeedurl_label">Додати подкаÑÑ‚ за URL</string> <string name="podcastdirectories_label">Знайти подкаÑÑ‚ в каталозі</string> - <string name="podcastdirectories_descr">Ð’ каталозі gpodder.net можливий пошук за назвою, категорією або популÑрніÑÑ‚ÑŽ.</string> + <string name="podcastdirectories_descr">Ðові подкаÑти можна шукати на iTunes або fyyd, або переглÑнути gpodder.net за іменами, категоріÑми або популÑрніÑÑ‚ÑŽ.</string> <string name="browse_gpoddernet_label">ПереглÑнути gpodder.net</string> <!--Actions on feeds--> <string name="mark_all_read_label">Позначити вÑÑ– Ñк грані</string> @@ -101,7 +109,10 @@ <string name="mark_all_read_confirmation_msg">Будь лаÑка, підтвердіть що ви бажаєте позначити вÑÑ– епізоди Ñк грані.</string> <string name="mark_all_read_feed_confirmation_msg">Будь лаÑка, підтвердіть що ви бажаєте позначити вÑÑ– епізоди цього канала Ñк грані.</string> <string name="mark_all_seen_label">Позначити вÑÑ– Ñк переглÑнуті</string> + <string name="mark_all_seen_msg">Ð’ÑÑ– епізоди позначено Ñк переглÑнуті</string> + <string name="mark_all_seen_confirmation_msg">Будь лаÑка, підтвердіть що ви бажаєте позначити вÑÑ– епізоди Ñк переглÑнуті.</string> <string name="show_info_label">ІнформаціÑ</string> + <string name="rename_feed_label">Перейменувати подкаÑÑ‚</string> <string name="remove_feed_label">Видалити подкаÑÑ‚</string> <string name="share_label">ПоділитиÑÑ…</string> <string name="share_link_label">ПоділитиÑÑ URL Ñайту</string> @@ -109,7 +120,7 @@ <string name="share_feed_url_label">ПоділитиÑÑŒ поÑиланнÑм на канал</string> <string name="share_item_url_label">ПоділитиÑÑŒ поÑиланнÑм на файл епізода</string> <string name="share_item_url_with_position_label">ПоділитиÑÑŒ поÑиланнÑм на файл епізода з позицією</string> - <string name="feed_delete_confirmation_msg">Ви впенені що хочете видаліти канал та вÑÑ– завантажені епізоди?</string> + <string name="feed_delete_confirmation_msg">Будь лаÑка, підтвердіть що ви бажаєте видалити канал \"%1$s\" Ñ– ВСІ епізоди цього канала Ñкі ви завантажили.</string> <string name="feed_remover_msg">УдалÑÑŽ канал</string> <string name="load_complete_feed">Оновити канал цілком</string> <string name="hide_episodes_title">Приховати епізоди</string> @@ -121,6 +132,7 @@ <string name="hide_not_queued_episodes_label">Ðе в черзі</string> <string name="hide_downloaded_episodes_label">Завантажені</string> <string name="hide_not_downloaded_episodes_label">Ðе завантажені</string> + <string name="hide_has_media_label">Із звуком або відео</string> <string name="filtered_label">Фільтровані</string> <string name="refresh_failed_msg">{fa-exclamation-circle} ОÑтаннє Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð±ÑƒÐ»Ð¾ невдалим</string> <string name="open_podcast">Відкрити подкаÑÑ‚</string> @@ -131,7 +143,9 @@ <string name="stop_label">Стоп</string> <string name="stream_label">ПроÑлухати без завантаженнÑ</string> <string name="remove_label">Видалити</string> + <string name="delete_label">Видалити</string> <string name="remove_episode_lable">Видалити епізод</string> + <string name="marked_as_seen_label">Позначено Ñк переглÑнутий</string> <string name="mark_read_label">Позначити Ñк граний</string> <string name="marked_as_read_label">Позначено Ñк граний</string> <string name="mark_unread_label">Позначити Ñк не граний</string> @@ -218,9 +232,10 @@ <string name="move_to_top_label">Догори</string> <string name="move_to_bottom_label">Донизу</string> <string name="sort">ВпорÑдкувати</string> - <string name="alpha">За абеткою</string> <string name="date">За датою</string> <string name="duration">За триваліÑÑ‚ÑŽ</string> + <string name="episode_title">Ðазва епізода</string> + <string name="feed_title">Ðазва канала</string> <string name="ascending">За зроÑтаннÑм</string> <string name="descending">За ÑпаданнÑм</string> <string name="clear_queue_confirmation_msg">Будь лаÑка, підтвердіть що ви бажаєте вилучити вÑÑ– епізоди з черги.</string> @@ -274,13 +289,15 @@ <string name="pref_pauseOnDisconnect_sum">ЗупинÑтиÑÑŒ коли навушники або блютуз від’єднано</string> <string name="pref_unpauseOnHeadsetReconnect_sum">Поновити Ð²Ñ–Ð´Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ ÐºÐ¾Ð»Ð¸ навушники повторно під’єднано</string> <string name="pref_unpauseOnBluetoothReconnect_sum">Поновити Ð²Ñ–Ð´Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ ÐºÐ¾Ð»Ð¸ блютуз повторно під’єднано</string> - <string name="pref_hardwareForwardButtonSkips_title">ПропуÑк кнопкой перемотки</string> + <string name="pref_hardwareForwardButtonSkips_title">Кнопка перемотки пропуÑкає</string> <string name="pref_hardwareForwardButtonSkips_sum">При натиÑканні апаратної кнопки перемотки перейти до наÑтупного епізода заміÑÑ‚ÑŒ перемотки.</string> + <string name="pref_hardwarePreviousButtonRestarts_title">Кнопка \"назад\" повертає до початку</string> + <string name="pref_hardwarePreviousButtonRestarts_sum">При натиÑканні апаратної кнопки \"назад\", заміÑÑ‚ÑŒ перемотки, розпочати Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð²Ð°Ð½Ð½Ñ Ð¿Ð¾Ñ‚Ð¾Ñ‡Ð½Ð¾Ð³Ð¾ епізода заново</string> <string name="pref_followQueue_sum">Перейти до наÑтупного епізода в черзі коли поточний закінчено</string> <string name="pref_auto_delete_sum">Видалити епізод піÑÐ»Ñ Ð¿Ð¾Ð²Ð½Ð¾Ð³Ð¾ відтвореннÑ</string> <string name="pref_auto_delete_title">ÐвтовидаленнÑ</string> <string name="pref_smart_mark_as_played_sum">Позначити епізоди Ñк грані навіть Ñкщо залишилоÑÑŒ менш ніж зазначене чиÑло Ñекунд до ÐºÑ–Ð½Ñ†Ñ Ð²Ñ–Ð´Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ</string> - <string name="pref_smart_mark_as_played_title">Розумне Ð¿Ð¾Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð³Ñ€Ð°Ð½Ð¸Ñ… епізодів</string> + <string name="pref_smart_mark_as_played_title">Розумне Ð¿Ð¾Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ñлуханих епізодів</string> <string name="pref_skip_keeps_episodes_sum">Зберігати епізоди що пропущені при програванні </string> <string name="pref_skip_keeps_episodes_title">Зберігати пропущені при програванні епізоди </string> <string name="playback_pref">ВідтвореннÑ</string> @@ -342,14 +359,22 @@ <string name="pref_gpodnet_logout_toast">УÑпішно закрили доÑтуп</string> <string name="pref_gpodnet_setlogin_information_title">Змінити інформацію Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ</string> <string name="pref_gpodnet_setlogin_information_sum">Змінити інформацію щодо облікового запиÑу gpodder.net</string> - <string name="pref_gpodnet_sync_title">Cинхронізувати зараз</string> - <string name="pref_gpodnet_sync_sum">Cинхронізувати підпиÑки та Ñтан епізодів з ÑервіÑом gpodder.net</string> + <string name="pref_gpodnet_sync_changes_title">Синхронізувати зміни негайно</string> + <string name="pref_gpodnet_sync_changes_sum">Синхронізувати підпиÑки та зміни Ñтана епізодів з gpodder.net</string> + <string name="pref_gpodnet_full_sync_title">Виконати повну Ñинхронізацію негайно</string> + <string name="pref_gpodnet_full_sync_sum">Синхронізувати вÑÑ– підпиÑки та Ñтан епізодів з gpodder.net.</string> + <string name="pref_gpodnet_sync_sum_last_sync_line">ОÑÑ‚Ð°Ð½Ð½Ñ Ñпроба Ñинхронізації: %1$s (%2$s)</string> <string name="pref_gpodnet_sync_started">CÐ¸Ð½Ñ…Ñ€Ð¾Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ Ð¿Ð¾Ñ‡Ð°Ð»Ð°ÑÑŒ</string> + <string name="pref_gpodnet_full_sync_started">Повну Ñинхронізацію розпочато</string> <string name="pref_gpodnet_login_status"><![CDATA[Ви увійшли Ñк <i>%1$s</i> з приÑÑ‚Ñ€Ð¾Ñ <i>%2$s</i>]]></string> + <string name="pref_gpodnet_notifications_title">ПовідомлÑти про помилки Ñинхронізації</string> + <string name="pref_gpodnet_notifications_sum">Це Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ðµ заÑтоÑовуєтьÑÑ Ð´Ð¾ помилок автентифікації.</string> <string name="pref_playback_speed_title">ШвидкіÑÑ‚ÑŒ програваннÑ</string> <string name="pref_playback_speed_sum">ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÑˆÐ²Ñ–Ð´ÐºÐ¾ÑÑ‚Ñ– доÑтупно Ð´Ð»Ñ Ð·Ð¼Ñ–Ð½Ð½Ð¾Ñ— швидкоÑÑ‚Ñ– програваннÑ</string> - <string name="pref_fast_forward">Ð§Ð°Ñ Ð¿ÐµÑ€ÐµÐ¼Ð¾Ñ‚ÐºÐ¸ вперед</string> - <string name="pref_rewind">Ð§Ð°Ñ Ð¿ÐµÑ€ÐµÐ¼Ð¾Ñ‚ÐºÐ¸ назад</string> + <string name="pref_fast_forward">Ð§Ð°Ñ Ð¿Ñ€Ð¾Ð¿ÑƒÑка кнопкой перемотки вперед</string> + <string name="pref_fast_forward_sum">Ðалаштувати кількіÑÑ‚ÑŒ Ñекунд Ñкі пропуÑкаютьÑÑ Ð¿Ñ€Ð¸ натиÑканні кнопки перемотки вперед</string> + <string name="pref_rewind">Ð§Ð°Ñ Ð¿Ñ€Ð¾Ð¿ÑƒÑка кнопкой перемотки назад</string> + <string name="pref_rewind_sum">Ðалаштувати кількіÑÑ‚ÑŒ Ñекунд Ñкі відмотуютьÑÑ Ð¿Ñ€Ð¸ натиÑканні кнопки перемотки назад</string> <string name="pref_gpodnet_sethostname_title">Ð’Ñтановити ім\'Ñ Ñ…Ð¾Ñта</string> <string name="pref_gpodnet_sethostname_use_default_host">ВикориÑтати хоÑÑ‚ по замовчанню</string> <string name="pref_expandNotify_title">Розгорнути повідомленнÑ</string> @@ -360,8 +385,6 @@ <string name="pref_compact_notification_buttons_sum">Змінити кнопки на екрані блокуваннÑ. Кнопки програваннÑ/пауза завжди включені.</string> <string name="pref_compact_notification_buttons_dialog_title">Оберіть не більше ніж %1$d кнопок</string> <string name="pref_compact_notification_buttons_dialog_error">Ви можете обрати не більше ніж %1$d кнопок.</string> - <string name="pref_show_subscriptions_in_drawer_title">Показати підпиÑки</string> - <string name="pref_show_subscriptions_in_drawer_sum">Показати перелік підпиÑок безпоÑередньо в меню навігації</string> <string name="pref_lockscreen_background_title">Змінювати фон екрана блокуваннÑ</string> <string name="pref_lockscreen_background_sum">Ð’Ñтановити картинку поточного епізода Ñк фон екрана блокуваннÑ. Побічний ефект - це Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð±ÑƒÐ´Ðµ також видно в інших додатках.</string> <string name="pref_showDownloadReport_title">Показати звіт про завантаженнÑ</string> @@ -376,7 +399,7 @@ <string name="crash_report_sum">ÐадіÑлати е-пошту зі звітом про оÑтанній збій</string> <string name="send_email">ÐадіÑлати е-пошту</string> <string name="experimental_pref">ЕкÑпериментальні</string> - <string name="pref_sonic_title">Програвач Sonic</string> + <string name="pref_sonic_title">Sonic Media Player</string> <string name="pref_sonic_message">ЗаÑтоÑувати вбудований програвач sonic заміÑÑ‚ÑŒ програвача Android та Prestissimo</string> <string name="pref_current_value">Поточне значеннÑ: %1$s</string> <string name="pref_proxy_title">ПрокÑÑ–</string> @@ -385,18 +408,25 @@ <string name="pref_known_issues">Відомі проблеми</string> <string name="pref_no_browser_found">Веб браузер не знайдено.</string> <string name="pref_cast_title">Підтримка Ð´Ð»Ñ Chromecast</string> + <string name="pref_cast_message_play_flavor">Включити підтримку Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð²Ð°Ð½Ð½Ñ Ð½Ð° таких приÑтроÑÑ… Ñк Chromecast або Android TV</string> + <string name="pref_cast_message_free_flavor">Ð”Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ Chromecast потрібні бібліотеки Ñкі не включені в цю верÑÑ–ÑŽ AntennaPod</string> + <string name="pref_enqueue_downloaded_title">Додавати до черги завантажене</string> + <string name="pref_enqueue_downloaded_summary">Додавати завантажені епізоди до черги</string> <!--Auto-Flattr dialog--> <string name="auto_flattr_enable">Включити автоматичне Ð·Ð°Ð¾Ñ…Ð¾Ñ‡ÐµÐ½Ð½Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ñ–Ð² через ÑÐµÑ€Ð²Ñ–Ñ flattr</string> <string name="auto_flattr_after_percent">Заохотити автора через Flattr щойно %d відÑотків епізода було відтворено</string> <string name="auto_flattr_ater_beginning">Заохотити автора через Flattr коли починаєтьÑÑ Ð²Ñ–Ð´Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ</string> <string name="auto_flattr_ater_end">Заохотити автора через Flattr коли закінчуєтьÑÑ Ð²Ñ–Ð´Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ</string> <!--Search--> - <string name="search_hint">Пошук каналів та епізодів</string> - <string name="found_in_shownotes_label">Знайдено у примітках</string> + <string name="search_hint">Пошук епізодів</string> + <string name="found_in_shownotes_label">Знайдено в нотатках епізода</string> <string name="found_in_chapters_label">Знайдено в главах</string> + <string name="found_in_authors_label">Знайдено в авторах</string> + <string name="found_in_feeds_label">Знайдено в каналах</string> <string name="search_status_no_results">Жодних результатів немає</string> <string name="search_label">Пошук</string> <string name="found_in_title_label">Знайдено у назві</string> + <string name="no_results_for_query">Ðічого не знайдено за запитом \"%1$s\"</string> <!--OPML import and export--> <string name="opml_import_txtv_button_lable">OPML файли дозволÑÑŽÑ‚ вам перенеÑти подкаÑти з однієї программи до іншої</string> <string name="opml_import_option">Варіант %1$d</string> @@ -415,6 +445,7 @@ <string name="choose_file_from_filesystem">З локальної файлової ÑиÑтеми</string> <string name="choose_file_from_external_application">За допомогою додатка</string> <string name="opml_export_label">OPML ÑкÑпорт</string> + <string name="html_export_label">ЕкÑпорт до HTML</string> <string name="exporting_label">ЕкÑпортуєтьÑÑ…</string> <string name="export_error_label">Помилка екÑпорту</string> <string name="opml_export_success_title">OPML екÑпорт уÑпішний</string> @@ -448,6 +479,9 @@ <item quantity="few">%d години</item> <item quantity="other">%d годин</item> </plurals> + <string name="auto_enable_label">Увімкнути автоматично</string> + <string name="sleep_timer_enabled_label">Таймер Ñну увімкнено</string> + <string name="sleep_timer_disabled_label">Таймер Ñну вимкнено</string> <!--gpodder.net--> <string name="gpodnet_taglist_header">КÐТЕГОРІЇ</string> <string name="gpodnet_toplist_header">ТОП ПОДКÐСТІВ</string> @@ -467,6 +501,7 @@ <string name="gpodnetauth_device_chooseExistingDevice">Вибрати Ñ–Ñнуючий приÑтрій</string> <string name="gpodnetauth_device_errorEmpty">ID приÑтрою не можете бути пуÑтим</string> <string name="gpodnetauth_device_errorAlreadyUsed">Таке ID приÑтрою вже Ñ”</string> + <string name="gpodnetauth_device_caption_errorEmpty">ÐŸÑ–Ð´Ð¿Ð¸Ñ Ð½Ðµ повинен бути пуÑтим</string> <string name="gpodnetauth_device_butChoose">Обрати</string> <string name="gpodnetauth_finish_title">УÑпішно зайшли</string> <string name="gpodnetauth_finish_descr">ПоздоровлÑємо! Ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ð½Ð° gpodder.net зараз пов\'Ñзаний за вашим приÑтроєм</string> @@ -476,6 +511,8 @@ <string name="gpodnetsync_auth_error_descr">Помилка в імені кориÑтувача або паролі</string> <string name="gpodnetsync_error_title">gpodder.net помилка Ñинхронізації</string> <string name="gpodnetsync_error_descr">ТрапилаÑÑŒ помилка при Ñінхронизації:\u0020</string> + <string name="gpodnetsync_pref_report_successful">УÑпішно</string> + <string name="gpodnetsync_pref_report_failed">Ðевдало</string> <!--Directory chooser--> <string name="selected_folder_label">Обрати папку:</string> <string name="create_folder_label">Ðова папка</string> @@ -528,6 +565,7 @@ <string name="sp_apps_importing_feeds_msg">Імпорт подкаÑтів з інших програм...</string> <string name="search_itunes_label">Пошук в iTunes</string> <string name="filter">Фільтр</string> + <string name="search_fyyd_label">Шукати в fyyd</string> <!--Episodes apply actions--> <string name="all_label">Ð’ÑÑ–</string> <string name="selected_all_label">Обрано вÑÑ– епізоди</string> @@ -545,6 +583,8 @@ <string name="selected_queued_label">Обрано епізоди що в черзі</string> <string name="not_queued_label">Ðе в черзі</string> <string name="selected_not_queued_label">Обрано епізоди що не в черзі</string> + <string name="has_media">Із звуком або відео</string> + <string name="selected_has_media_label">Обрано епізоди із звуком або відео</string> <!--Sort--> <string name="sort_title_a_z">Ðазва (Ð \u2192 Я)</string> <string name="sort_title_z_a">Ðазва (Я \u2192 Ð)</string> @@ -576,7 +616,23 @@ <string name="proxy_checking">ПеревірÑєтьÑÑ...</string> <string name="proxy_test_successful">ПротеÑтовано уÑпішно</string> <string name="proxy_test_failed">ПротеÑтовано з помилками</string> + <string name="proxy_host_empty_error">ХоÑÑ‚ не може бути пуÑтим</string> + <string name="proxy_host_invalid_error">ХоÑÑ‚ не Ñ” правильною IP-адреÑою або доменним ім’Ñм</string> <string name="proxy_port_invalid_error">Ðеправильний порт</string> <!--Casting--> + <string name="cast_media_route_menu_title">Грати на…</string> + <string name="cast_disconnect_label">Від’єднатиÑÑŒ від приÑÑ‚Ñ€Ð¾Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð²Ð°Ð½Ð½Ñ</string> + <string name="cast_not_castable">Обраний файл не ÑуміÑний з приÑтроєм програваннÑ</string> + <string name="cast_failed_to_play">Помилка Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð²Ð°Ð½Ð½Ñ Ñ„Ð°Ð¹Ð»Ð°</string> + <string name="cast_failed_to_stop">Помилка Ñпроби зупинки програваннÑ</string> + <string name="cast_failed_to_pause">Помилка Ñпроби Ð¿Ñ€Ð¸Ð·ÑƒÐ¿Ð¸Ð½ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð²Ð°Ð½Ð½Ñ</string> <!--<string name="cast_failed_to_connect">Could not connect to the device</string>--> + <string name="cast_failed_setting_volume">Помилка вÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð³ÑƒÑ‡Ð½Ð¾ÑÑ‚Ñ–</string> + <string name="cast_failed_no_connection">Ðемає Ð·â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð· приÑтроєм програваннÑ</string> + <string name="cast_failed_no_connection_trans">Зв’Ñзок з приÑтроєм Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð²Ð°Ð½Ð½Ñ Ð²Ñ‚Ñ€Ð°Ñ‡ÐµÐ½Ð¾. Програма намагаєтьÑÑ Ð¿Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ зв’Ñзок, Ñкщо це можливо. Будь лаÑка зачекайте кілька Ñекунд Ñ– Ñпробуйте знов.</string> + <string name="cast_failed_perform_action">Помилка Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð´Ñ–Ñ—</string> + <string name="cast_failed_status_request">Помилка Ñинхронизації з приÑтроєм програваннÑ</string> + <string name="cast_failed_seek">Помилка перехода на нову позицію Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð²Ð°Ð½Ð½Ñ Ð½Ð° приÑтрої.</string> + <string name="cast_failed_receiver_player_error">Серйозна помилка Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð²Ð°Ð½Ð½Ñ Ð½Ð° приÑтрої</string> + <string name="cast_failed_media_error_skipping">Помилка Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð²Ð°Ð½Ð½Ñ Ñ„Ð°Ð¹Ð»Ð°. ПропуÑкаю...</string> </resources> diff --git a/core/src/main/res/values-vi/strings.xml b/core/src/main/res/values-vi/strings.xml index a900b1217..2c304e07c 100644 --- a/core/src/main/res/values-vi/strings.xml +++ b/core/src/main/res/values-vi/strings.xml @@ -2,63 +2,310 @@ <resources xmlns:tools="http://schemas.android.com/tools"> <!--Activitiy and fragment titles--> <string name="feeds_label">Các feed</string> + <string name="statistics_label">Thống kê</string> + <string name="add_feed_label">Thêm podcast</string> + <string name="episodes_label">Số táºp</string> + <string name="all_episodes_short_label">Tất cả</string> + <string name="favorite_episodes_label">Lượt thÃch</string> <string name="new_label">Tạo má»›i</string> <string name="settings_label">Thiết láºp</string> + <string name="add_new_feed_label">Thêm podcast</string> <string name="downloads_label">Tải vá»</string> + <string name="downloads_running_label">Äang tải</string> + <string name="downloads_completed_label">Äã tải</string> + <string name="downloads_log_label">Lịch sá»</string> + <string name="cancel_download_label">Huá»·\ntải xuống</string> + <string name="playback_history_label">Lịch sá» phát</string> + <string name="gpodnet_main_label">gpodder.net</string> + <string name="gpodnet_auth_label">Äăng nháºp gpodder.net</string> + <string name="free_space_label">Còn trống %1$s</string> + <string name="episode_cache_full_title">Äầy bá»™ nhá»› tạm</string> + <string name="episode_cache_full_message">Bá»™ nhá»› tạm cho các táºp podcast đã đạt dung lượng tối Ä‘a. Bạn có thể tăng giá»›i hạn nà y lên trong phần Thiết láºp.</string> <!--Statistics fragment--> + <string name="total_time_listened_to_podcasts">Tổng thá»i gian nghe:</string> <!--Main activity--> + <string name="drawer_open">Mở menu</string> + <string name="drawer_close">Äóng menu</string> + <string name="drawer_preferences">Cà i đặt menu kéo ra</string> + <string name="drawer_feed_order_unplayed_episodes">Sắp xếp theo số lượng</string> + <string name="drawer_feed_order_alphabetical">Sắp xếp theo bảng chữ cái</string> + <string name="drawer_feed_order_last_update">Sắp xếp theo ngà y phát hà nh</string> + <string name="drawer_feed_counter_new_unplayed">Số táºp má»›i hoặc chÆ°a nghe</string> + <string name="drawer_feed_counter_new">Số táºp má»›i</string> + <string name="drawer_feed_counter_unplayed">Số táºp chÆ°a nghe</string> + <string name="drawer_feed_counter_downloaded">Số táºp đã tải</string> + <string name="drawer_feed_counter_none">Không có</string> <!--Webview actions--> + <string name="open_in_browser_label">Mở bằng trình duyệt</string> + <string name="copy_url_label">Sao chép liên kết</string> + <string name="share_url_label">Chia sẻ liên kết</string> + <string name="copied_url_msg">Äã sao chép liên kết và o bảng nhá»› tạm</string> + <string name="go_to_position_label">Äi đến vị trà nà y</string> <!--Playback history--> + <string name="clear_history_label">Xoá lịch sá»</string> <!--Other--> <string name="confirm_label">Xác nháºn</string> <string name="cancel_label">Hủy bá»</string> + <string name="yes">Có</string> + <string name="no">Không</string> + <string name="reset">Äặt lại</string> <string name="author_label">Tác giả</string> <string name="language_label">Ngôn ngữ</string> + <string name="url_label">Liên kết</string> + <string name="podcast_settings_label">Thiết láºp</string> + <string name="cover_label">Hình</string> <string name="error_label">Lá»—i</string> + <string name="error_msg_prefix">Äã xảy ra lá»—i:</string> <string name="refresh_label">Cáºp nháºt lại</string> <string name="external_storage_error_msg">Hiện không có thiết bị lÆ°u trữ gắn ngoà i nà o. Hãy chắc rằng bạn đã kết nối máy của mình vá»›i thiết bị lÆ°u trữ gắn ngoà i để ứng dụng có thể được hoạt Ä‘á»™ng trÆ¡n tru.</string> <string name="chapters_label">ChÆ°Æ¡ng</string> - <string name="shownotes_label">Hiển thị ghi chú</string> + <string name="shownotes_label">Ghi chú</string> + <string name="description_label">Mô tả</string> + <string name="most_recent_prefix">Táºp má»›i nhất:\u0020</string> <string name="episodes_suffix">\u0020táºp</string> <string name="length_prefix">Äá»™ dà i:\u0020</string> <string name="size_prefix">KÃch thÆ°á»›c:\u0020</string> - <string name="processing_label">Äang xá» lý</string> + <string name="processing_label">Äang xá» lÃ</string> + <string name="loading_label">Äang tải…</string> + <string name="save_username_password_label">LÆ°u tên đăng nháºp và máºt khẩu</string> + <string name="close_label">Äóng</string> + <string name="retry_label">Thá» lại</string> + <string name="auto_download_apply_to_items_title">Ãp dụng cho các táºp trÆ°á»›c</string> + <string name="auto_delete_label">Tá»± xoá táºp podcast</string> + <string name="parallel_downloads_suffix">\u0020tải xuống song song</string> + <string name="feed_auto_download_always">Luôn luôn</string> + <string name="feed_auto_download_never">Không bao giá»</string> + <string name="send_label">Gá»i…</string> + <string name="episode_cleanup_never">Không bao giá»</string> + <string name="episode_cleanup_queue_removal">Khi không trong hà ng đợi</string> + <string name="episode_cleanup_after_listening">Sau khi nghe xong</string> + <plurals name="episode_cleanup_days_after_listening"> + <item quantity="other">%d ngà y sau khi nghe xong</item> + </plurals> <!--'Add Feed' Activity labels--> <string name="feedurl_label">ÄÆ°á»ng dẫn liên kết feed</string> + <string name="etxtFeedurlHint">www.example.com/feed</string> + <string name="txtvfeedurl_label">Thêm podcast theo liên kết</string> + <string name="podcastdirectories_label">Tìm podcast trong danh mục</string> + <string name="podcastdirectories_descr">Äể tải podcast má»›i, bạn có thể tìm kiếm trên iTunes hoặc fyyd, tra cứu trên gpodder.net theo tên, thể loại hoặc xếp hạng.</string> + <string name="browse_gpoddernet_label">Tra cứu gpodder.net</string> <!--Actions on feeds--> - <string name="show_info_label">Hiển thị thông ti</string> - <string name="feed_delete_confirmation_msg">Xin vui lòng xác nháºn rằng bạn muốn xóa feed nà y và toà n bá»™ các phần khác của feed nà y mà bạn đã tải vá».</string> + <string name="mark_all_read_label">Äánh dấu đã nghe tất cả</string> + <string name="mark_all_read_msg">Äánh dấu đã nghe tất cả các táºp</string> + <string name="mark_all_read_confirmation_msg">Hãy xác nháºn bạn muốn đánh dấu đã nghe tất cả các táºp.</string> + <string name="mark_all_seen_label">Äánh dấu đã xem tất cả</string> + <string name="mark_all_seen_msg">Äánh dấu đã xem tất cả các táºp</string> + <string name="mark_all_seen_confirmation_msg">Hãy xác nháºn bạn muốn đánh dấu đã xem tất cả các táºp.</string> + <string name="show_info_label">Hiện thông tin</string> + <string name="rename_feed_label">Äổi tên podcast</string> + <string name="remove_feed_label">Xoá podcast</string> + <string name="share_label">Chia sẻ…</string> + <string name="share_link_label">Chia sẻ liên kết</string> + <string name="share_link_with_position_label">Chia sẻ liên kết cùng vị trà phát</string> + <string name="share_feed_url_label">Chia sẻ liên kết feed</string> + <string name="share_item_url_label">Chia sẻ liên kết của táºp nà y</string> + <string name="share_item_url_with_position_label">Chia sẻ liên kết và vị trà phát táºp nà y</string> + <string name="feed_remover_msg">Äang xoá feed</string> + <string name="hide_episodes_title">Ẩn các táºp</string> + <string name="episode_actions">Ãp dụng hà nh Ä‘á»™ng</string> + <string name="hide_unplayed_episodes_label">ChÆ°a nghe</string> + <string name="hide_paused_episodes_label">Äang tạm dừng</string> + <string name="hide_played_episodes_label">Äã nghe</string> + <string name="hide_queued_episodes_label">Äã thêm và o hà ng đợi</string> + <string name="hide_not_queued_episodes_label">ChÆ°a thêm và o hà ng đợi</string> + <string name="hide_downloaded_episodes_label">Äã tải</string> + <string name="hide_not_downloaded_episodes_label">ChÆ°a tải</string> + <string name="hide_has_media_label">Có táºp tin phÆ°Æ¡ng tiện</string> + <string name="filtered_label">Äã lá»c</string> + <string name="open_podcast">Mở podcast</string> <!--actions on feeditems--> <string name="download_label">Tải vá»</string> <string name="play_label">Phát</string> - <string name="stream_label">Phân luồng</string> + <string name="pause_label">Tạm dừng</string> + <string name="stop_label">Dừng</string> + <string name="stream_label">Nghe trá»±c tiếp</string> <string name="remove_label">Loại bá»</string> + <string name="delete_label">Xoá</string> + <string name="remove_episode_lable">Xoá táºp nà y</string> + <string name="marked_as_seen_label">Äánh dấu đã xem</string> + <string name="mark_read_label">Äánh dấu đã nghe</string> + <string name="marked_as_read_label">Äã đánh dấu đã nghe</string> + <string name="mark_unread_label">Äánh dấu chÆ°a nghe</string> <string name="add_to_queue_label">Thêm và o hà ng đợi</string> - <string name="remove_from_queue_label">Loại bá» khá»i hà ng đợi</string> + <string name="added_to_queue_label">Äã thêm và o hà ng đợi</string> + <string name="remove_from_queue_label">Xoá khá»i hà ng đợi</string> + <string name="add_to_favorite_label">Thêm và o danh sách Æ°a thÃch</string> + <string name="added_to_favorites">Äã thêm và o danh sách Æ°a thÃch</string> + <string name="remove_from_favorite_label">Xoá khá»i danh sách Æ°a thÃch</string> + <string name="removed_from_favorites">Äã xoá khá»i danh sách Æ°a thÃch</string> <string name="visit_website_label">Truy cáºp website</string> + <string name="skip_episode_label">Bá» qua táºp nà y</string> + <string name="activate_auto_download">Báºt tá»± Ä‘á»™ng tải xuống</string> + <string name="deactivate_auto_download">Tắt tá»± Ä‘á»™ng tải xuống</string> + <string name="reset_position">Äặt lại vị trà phát</string> + <string name="removed_item">Äã xoá mục nà y</string> <!--Download messages and labels--> + <string name="download_successful">thà nh công</string> + <string name="download_failed">thất bại</string> + <string name="download_pending">Äang chá» tải xuống</string> + <string name="download_running">Äang tải xuống</string> + <string name="download_error_device_not_found">Không tìm được thiết bị lÆ°u trữ</string> + <string name="download_error_insufficient_space">Không đủ bá»™ nhá»›</string> + <string name="download_error_file_error">Lá»—i táºp tin</string> + <string name="download_error_http_data_error">Lá»—i dữ liệu HTTP</string> + <string name="download_error_error_unknown">Lá»—i không rõ nguyên nhân</string> + <string name="download_error_unsupported_type">Loại feed không được há»— trợ</string> + <string name="download_error_connection_error">Lá»—i kết nối</string> + <string name="download_error_unknown_host">Không rõ máy chủ</string> + <string name="download_error_unauthorized">Lá»—i xác thá»±c</string> + <string name="download_error_file_type_type">Lá»—i loại táºp tin</string> + <string name="download_error_forbidden">Bị cấm truy cáºp</string> + <string name="cancel_all_downloads_label">Huá»· bá» má»i tải xuống</string> + <string name="download_canceled_msg">Äã huá»· bá» tải xuống</string> + <string name="download_canceled_autodownload_enabled_msg">Äã huá»· bá» tải xuống\n +Äã tắt <i>tá»± Ä‘á»™ng tải xuống</i> vá»›i mục nà y</string> + <string name="download_report_content_title">Báo cáo tải xuống</string> + <string name="download_error_malformed_url">Liên kết sai định dạng</string> + <string name="download_error_io_error">Lá»—i và o ra dữ liệu</string> + <string name="download_error_db_access">Lá»—i truy cáºp cÆ¡ sở dữ liệu</string> + <plurals name="downloads_left"> + <item quantity="other">Còn %d tải xuống</item> + </plurals> + <string name="downloads_processing">Äang xá» là các mục tải xuống</string> + <string name="download_notification_title">Äang tải dữ liệu podcast</string> + <string name="download_report_content">%1$d tải xuống thà nh công, %2$d thất bại</string> + <string name="download_log_title_unknown">Không rõ tiêu Ä‘á»</string> + <string name="download_type_feed">Feed</string> + <string name="download_type_media">Táºp tin phÆ°Æ¡ng tiện</string> + <string name="download_type_image">Hình</string> + <string name="download_request_error_dialog_message_prefix">Äã xảy ra lá»—i khi tải táºp tin:\u0020</string> + <string name="authentication_notification_title">Yêu cầu xác thá»±c</string> + <string name="authentication_notification_msg">Phải nháºp tên đăng nháºp và máºt khẩu để truy cáºp tà i nguyên</string> + <string name="confirm_mobile_download_dialog_title">Xác nháºn tải xuống bằng kết nối di Ä‘á»™ng</string> + <string name="confirm_mobile_download_dialog_only_add_to_queue">Thêm và o hà ng đợi</string> + <string name="confirm_mobile_download_dialog_enable_temporarily">Tạm thá»i cho phép</string> <!--Mediaplayer messages--> + <string name="player_error_msg">Lá»—i!</string> + <string name="player_preparing_msg">Äang chuẩn bị</string> + <string name="player_ready_msg">Sẵn sà ng</string> + <string name="playback_error_server_died">Máy chủ lá»—i</string> + <string name="playback_error_unknown">Lá»—i không rõ nguyên nhân</string> + <string name="playbackservice_notification_title">Äang nghe podcast</string> <!--Queue operations--> + <string name="lock_queue">Khoá hà ng đợi</string> + <string name="unlock_queue">Mở khoá hà ng đợi</string> + <string name="queue_locked">Äã khoá hà ng đợi</string> + <string name="queue_unlocked">Äã mở khoá hà ng đợi</string> + <string name="clear_queue_label">Xoá hà ng đợi</string> + <string name="undo">Hoà n tác</string> + <string name="removed_from_queue">Äã xoá mục nà y</string> + <string name="move_to_top_label">Chuyển lên trên cùng</string> + <string name="move_to_bottom_label">Chuyển xuống dÆ°á»›i cùng</string> + <string name="sort">Sắp xếp</string> + <string name="date">Ngà y</string> + <string name="duration">Thá»i lượng</string> + <string name="episode_title">Tiêu Ä‘á» táºp</string> + <string name="feed_title">Tiêu Ä‘á» feed</string> + <string name="ascending">Tăng dần</string> + <string name="descending">Giảm dần</string> <!--Flattr--> + <string name="flattr_auth_label">Äăng nháºp Flatter</string> + <string name="authenticate_label">Xác thá»±c</string> + <string name="return_home_label">Trở vá» trang chủ</string> + <string name="authenticate_now_label">Xác thá»±c</string> <!--Flattr--> <!--Variable Speed--> + <string name="download_plugin_label">Tải plugin</string> + <string name="no_playback_plugin_title">ChÆ°a cà i plugin</string> + <string name="set_playback_speed_label">Tốc Ä‘á»™ phát</string> + <string name="enable_sonic">Báºt plugin Sonic</string> <!--Empty list labels--> + <string name="no_items_label">Danh sách nà y không có mục nà o.</string> + <string name="no_chapters_label">Táºp nà y không có chÆ°Æ¡ng nà o.</string> + <string name="no_shownotes_label">Táºp nà y không có ghi chú.</string> <!--Preferences--> + <string name="storage_pref">Bá»™ nhá»› lÆ°u trữ</string> + <string name="other_pref">Khác</string> + <string name="about_pref">Thông tin</string> + <string name="queue_label">Hà ng đợi</string> + <string name="flattr_label">Flatter</string> + <string name="pref_episode_cleanup_title">Dá»n các táºp podcast</string> + <string name="pref_episode_cleanup_summary">Có thể xoá các táºp không trong hà ng đợi phát hoặc danh sách Æ°a thÃch nếu tÃnh năng tá»± tải xuống cần thêm bá»™ nhá»› trống cho các táºp má»›i </string> + <string name="pref_pauseOnDisconnect_sum">Tạm dừng khi tai nghe hoặc thiết bị Bluetooth bị ngắt kết nối</string> + <string name="pref_unpauseOnHeadsetReconnect_sum">Tiếp tục phát khi tai nghe được kết nối lại</string> + <string name="pref_unpauseOnBluetoothReconnect_sum">Tiếp tục phát khi thiết bị Bluetooth được kết nối lại</string> + <string name="pref_hardwareForwardButtonSkips_sum">Khi ấn nút tua nhanh (nút cứng), không tua mà chuyến sang táºp tiếp theo</string> + <string name="pref_hardwarePreviousButtonRestarts_title">Nghe lại khi ấn nút tua lại</string> + <string name="pref_hardwarePreviousButtonRestarts_sum">Khi ấn nút tua lại (nút cứng), không tua lại mà phát lại táºp Ä‘ang nghe</string> + <string name="pref_followQueue_sum">Chuyển đến mục đợi phát tiếp theo khi nghe xong</string> + <string name="pref_auto_delete_sum">Xoá các táºp podcast sau khi nghe xong</string> + <string name="pref_auto_delete_title">Tá»± Ä‘á»™ng xoá</string> + <string name="pref_smart_mark_as_played_sum">Khi còn má»™t khoảng thá»i gian chÆ°a nghe hết, vẫn đánh dấu đã nghe táºp podcast</string> + <string name="pref_skip_keeps_episodes_sum">Giữ lại các táºp podcast khi bị bá» qua</string> + <string name="pref_skip_keeps_episodes_title">Giữ các táºp bị bá» qua</string> + <string name="playback_pref">Phát</string> + <string name="network_pref">Mạng</string> + <string name="pref_autoUpdateIntervallOrTime_Disable">Tắt</string> + <string name="pref_autoUpdateIntervallOrTime_every">má»—i %1$s</string> + <string name="pref_autoUpdateIntervallOrTime_at">và o lúc %1$s</string> + <string name="pref_downloadMediaOnWifiOnly_sum">Chỉ tải xuống táºp tin Ä‘a phÆ°Æ¡ng tiện qua WiFi</string> + <string name="pref_followQueue_title">Phát liên tục</string> + <string name="pref_mobileUpdate_title">Cáºp nháºt qua mạng di Ä‘á»™ng</string> + <string name="pref_mobileUpdate_sum">Cho phép cáºp nháºt qua kết nối mạng di Ä‘á»™ng</string> + <string name="pref_theme_title_light">Sáng</string> + <string name="pref_theme_title_dark">Tối</string> + <string name="pref_episode_cache_unlimited">Không giá»›i hạn</string> + <string name="pref_update_interval_hours_plural">giá»</string> + <string name="pref_update_interval_hours_singular">giá»</string> + <string name="pref_update_interval_hours_manual">Thủ công</string> + <string name="pref_gpodnet_authenticate_title">Äăng nháºp</string> + <string name="pref_gpodnet_logout_title">Äăng xuất</string> + <string name="pref_gpodnet_logout_toast">Äăng xuất thà nh công</string> + <string name="pref_gpodnet_setlogin_information_title">Thay đổi thông tin đăng nháºp</string> + <string name="pref_showDownloadReport_title">Hiện báo cáo tải xuống</string> + <string name="pref_queueAddToFront_title">Thêm và o đầu hà ng đợi</string> + <string name="pref_smart_mark_as_played_disabled">Tắt</string> + <string name="pref_image_cache_size_sum">KÃch cỡ bá»™ nhá»› tạm cho các hình ảnh.</string> + <string name="send_email">Gá»i email</string> + <string name="experimental_pref">Thá» nghiệm</string> + <string name="pref_proxy_title">Proxy</string> + <string name="pref_proxy_sum">Äặt proxy mạng</string> + <string name="pref_faq">Câu há»i thÆ°á»ng gặp</string> + <string name="pref_no_browser_found">Không tìm thấy trình duyệt nà o.</string> + <string name="pref_cast_title">Há»— trợ Chromecast</string> <!--Auto-Flattr dialog--> <!--Search--> + <string name="search_hint">Tìm các táºp podcast</string> + <string name="search_status_no_results">Không tìm thấy kết quả nà o</string> + <string name="search_label">Tìm kiếm</string> <!--OPML import and export--> <!--Sleep timer--> <!--gpodder.net--> + <string name="gpodnet_search_hint">Tìm kiếm gpodder.net</string> <!--Directory chooser--> <!--Online feed view--> <!--Content descriptions for image buttons--> <!--Feed information screen--> <!--Progress information--> <!--AntennaPodSP--> + <string name="search_itunes_label">Tìm kiếm iTunes</string> + <string name="filter">Lá»c</string> + <string name="search_fyyd_label">Tìm kiếm fyyd</string> <!--Episodes apply actions--> <!--Sort--> + <string name="sort_title_a_z">Tiêu Ä‘á» (A \u2192 Z)</string> + <string name="sort_title_z_a">Tiêu Ä‘á» (Z \u2192 A)</string> + <string name="sort_date_new_old">Ngà y (Má»›i \u2192 CÅ©)</string> + <string name="sort_date_old_new">Ngà y (CÅ© \u2192 Má»›i)</string> + <string name="sort_duration_short_long">Thá»i lượng (Ngắn \u2192 Dà i)</string> + <string name="sort_duration_long_short">Thá»i lượng (Dà i \u2192 Ngắn)</string> <!--Rating dialog--> + <string name="rating_later_label">Nhắc lại sau</string> + <string name="rating_now_label">DÄ© nhiên rồi!</string> <!--Audio controls--> + <string name="playback_speed">Tốc Ä‘á»™ phát</string> + <string name="volume">Âm lượng</string> + <string name="audio_effects">Hiệu ứng âm thanh</string> <!--proxy settings--> <!--Casting--> <!--<string name="cast_failed_to_connect">Could not connect to the device</string>--> diff --git a/core/src/main/res/values-zh-rCN/strings.xml b/core/src/main/res/values-zh-rCN/strings.xml index 7a1603bba..bdf9f3484 100644 --- a/core/src/main/res/values-zh-rCN/strings.xml +++ b/core/src/main/res/values-zh-rCN/strings.xml @@ -1,34 +1,35 @@ <?xml version='1.0' encoding='UTF-8'?> <resources xmlns:tools="http://schemas.android.com/tools"> <!--Activitiy and fragment titles--> - <string name="app_name">AntennaPod</string> <string name="feeds_label">订阅</string> + <string name="statistics_label">统计</string> <string name="add_feed_label">æ·»åŠ æ’客</string> - <string name="podcasts_label">æ’客</string> <string name="episodes_label">曲目</string> - <string name="new_episodes_label">新曲目</string> - <string name="all_episodes_label">所有曲目</string> <string name="all_episodes_short_label">全部</string> <string name="favorite_episodes_label">收è—</string> <string name="new_label">最新</string> - <string name="waiting_list_label">ç‰å¾…列表</string> <string name="settings_label">设置</string> <string name="add_new_feed_label">æ·»åŠ æ’客</string> <string name="downloads_label">下载</string> <string name="downloads_running_label">æ£åœ¨è¿è¡Œ</string> <string name="downloads_completed_label">已完æˆ</string> <string name="downloads_log_label">日志</string> + <string name="subscriptions_label">订阅</string> + <string name="subscriptions_list_label">订阅列表</string> <string name="cancel_download_label">å–消下载</string> <string name="playback_history_label">æ’放历å²</string> <string name="gpodnet_main_label">gpodder.net</string> <string name="gpodnet_auth_label">gpodder.net 登录</string> + <string name="free_space_label">%1$så¯ç”¨</string> <string name="episode_cache_full_title">曲目缓å˜å·²æ»¡</string> <string name="episode_cache_full_message">已达到曲目缓å˜é™åˆ¶ï¼Œå¯ä»¥åœ¨è®¾ç½®ä¸æ高缓å˜å¤§å°ã€‚</string> - <!--New episodes fragment--> - <string name="recently_published_episodes_label">最近å‘布</string> - <string name="episode_filter_label">仅显示新曲目</string> <!--Statistics fragment--> <string name="total_time_listened_to_podcasts">总æ’放时长:</string> + <string name="statistics_details_dialog">%1$d out of %2$d episodes started.\n\nPlayed %3$s out of %4$s.</string> + <string name="statistics_mode">统计模å¼</string> + <string name="statistics_mode_normal">计算实际æ’放时长。æ’放两次的情况被æ£ç¡®è¯†åˆ«ä¸ºä¸¤æ¬¡ï¼Œä½†æ˜¯è¢«æ ‡è®°ä¸ºæœªæ’放状æ€çš„都没有被æ£ç¡®è¯†åˆ«æ”¶å¬æ¬¡æ•°ã€‚</string> + <string name="statistics_mode_count_all">统计所有带有已æ’放æ’å®¢æ ‡è®°çš„æ•°é‡</string> + <string name="statistics_speed_not_counted">注æ„:回放速度ä¸åœ¨è€ƒè™‘范围之内。</string> <!--Main activity--> <string name="drawer_open">打开èœå•</string> <string name="drawer_close">å…³é—èœå•</string> @@ -36,9 +37,11 @@ <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> <string name="drawer_feed_counter_new">新曲目数</string> <string name="drawer_feed_counter_unplayed">未æ’曲目数</string> + <string name="drawer_feed_counter_downloaded">已下载曲目数é‡</string> <string name="drawer_feed_counter_none">æ— </string> <!--Webview actions--> <string name="open_in_browser_label">在æµè§ˆå™¨æ‰“å¼€</string> @@ -53,6 +56,7 @@ <string name="cancel_label">å–消</string> <string name="yes">是</string> <string name="no">å¦</string> + <string name="reset">é‡ç½®</string> <string name="author_label">作者</string> <string name="language_label">è¯è¨€</string> <string name="url_label">链接地å€</string> @@ -63,6 +67,7 @@ <string name="refresh_label">刷新</string> <string name="external_storage_error_msg">没有å¯ç”¨çš„外部å˜å‚¨. 请确ä¿å®‰è£…外部å˜å‚¨å™¨, è¿™æ ·æœ¬åº”ç”¨æ‰å¯ä»¥æ£å¸¸å·¥ä½œ.</string> <string name="chapters_label">ç« èŠ‚</string> + <string name="chapter_duration">按时长: %1$s</string> <string name="shownotes_label">笔记</string> <string name="description_label">æè¿°</string> <string name="most_recent_prefix">最近曲目:\u0020</string> @@ -76,9 +81,10 @@ <string name="retry_label">é‡è¯•</string> <string name="auto_download_label">包å«åˆ°è‡ªåŠ¨ä¸‹è½½</string> <string name="auto_download_apply_to_items_title"> 应用到之å‰çš„曲目ä¸</string> - <string name="auto_delete_label">è‡ªåŠ¨åˆ é™¤æ›²ç›®(覆盖全局选项)</string> + <string name="auto_download_apply_to_items_message">æ–°çš„ <i>自动下载</i> 的设定将会自动应用到新曲目ä¸ã€‚\nä½ æƒ³åº”ç”¨åˆ°ä¹‹å‰çš„曲目å—?</string> + <string name="auto_delete_label">è‡ªåŠ¨åˆ é™¤å‰§é›†</string> <string name="parallel_downloads_suffix">\u0020 并行下载</string> - <string name="feed_auto_download_global">全局</string> + <string name="feed_auto_download_global">全局默认</string> <string name="feed_auto_download_always"> 总是</string> <string name="feed_auto_download_never">从ä¸</string> <string name="send_label">å‘é€</string> @@ -101,15 +107,18 @@ <string name="mark_all_read_confirmation_msg">请确认您è¦å°†æ‰€æœ‰æ›²ç›®æ ‡ä¸ºå·²æ’放</string> <string name="mark_all_read_feed_confirmation_msg">请确认您è¦å°†è¯¥è®¢é˜…ä¸‹çš„æ‰€æœ‰æ›²ç›®æ ‡ä¸ºå·²æ’放</string> <string name="mark_all_seen_label">所有å¯è§</string> + <string name="mark_all_seen_msg">å°†æ‰€æœ‰æ›²ç›®æ ‡è®°ä¸ºå·²è¯»</string> + <string name="mark_all_seen_confirmation_msg">请确认您è¦å°†æ‰€æœ‰æ›²ç›®æ ‡è®°ä¸ºå·²è¯»ã€‚</string> <string name="show_info_label">查看信æ¯</string> + <string name="rename_feed_label">é‡å‘½åæ’客</string> <string name="remove_feed_label">åˆ é™¤æ’客</string> <string name="share_label">分享</string> <string name="share_link_label">分享网站链接</string> <string name="share_link_with_position_label">分享网站链接与ä½ç½®</string> <string name="share_feed_url_label">分享订阅地å€</string> - <string name="share_item_url_label">分享曲目下载地å€</string> - <string name="share_item_url_with_position_label">分享曲目下载地å€ä¸Žä½ç½®</string> - <string name="feed_delete_confirmation_msg">确认è¦åˆ 除这些订阅å—? 该订阅所有已ç»ä¸‹è½½çš„æ›²ç›®å°†ä¸€å¹¶åˆ é™¤. </string> + <string name="share_item_url_label">分享剧集文件URL</string> + <string name="share_item_url_with_position_label">分享剧集文件URLåŠå…¶çŠ¶æ€</string> + <string name="feed_delete_confirmation_msg">请确认您è¦åˆ 除订阅 \"%1$s\" 包括 所有 æ¤è®¢é˜…ä¸çš„已下载曲目。</string> <string name="feed_remover_msg">åˆ é™¤è®¢é˜…</string> <string name="load_complete_feed">刷新全部订阅</string> <string name="hide_episodes_title">éšè—曲目</string> @@ -123,7 +132,7 @@ <string name="hide_not_downloaded_episodes_label">未下载</string> <string name="filtered_label">已过滤的</string> <string name="refresh_failed_msg">{fa-exclamation-circle} 上次刷新失败</string> - <string name="open_podcast">打开åšå®¢</string> + <string name="open_podcast">打开æ’客</string> <!--actions on feeditems--> <string name="download_label">下载</string> <string name="play_label">æ’放</string> @@ -131,7 +140,9 @@ <string name="stop_label">åœæ¢</string> <string name="stream_label">æµåª’体</string> <string name="remove_label">åˆ é™¤</string> + <string name="delete_label">åˆ é™¤</string> <string name="remove_episode_lable">移除曲目</string> + <string name="marked_as_seen_label">æ ‡è®°ä¸ºå·²è¯»</string> <string name="mark_read_label">æ ‡è®°å·²æ’放</string> <string name="marked_as_read_label">å·²æ ‡è®°ä¸ºå·²æ’放</string> <string name="mark_unread_label">æ ‡è®°æœªæ’放</string> @@ -144,8 +155,6 @@ <string name="removed_from_favorites">从收è—ä¸ç§»é™¤</string> <string name="visit_website_label">访问网站</string> <string name="support_label">Flattr ä»–</string> - <string name="enqueue_all_new">å…¨éƒ¨æ·»åŠ åˆ°æ’放列表</string> - <string name="download_all">全部下载</string> <string name="skip_episode_label">跳过曲目</string> <string name="activate_auto_download">å¼€å¯è‡ªåŠ¨ä¸‹è½½</string> <string name="deactivate_auto_download">å…³é—自动下载</string> @@ -167,6 +176,7 @@ <string name="download_error_unknown_host">未知主机</string> <string name="download_error_unauthorized">认è¯é”™è¯¯</string> <string name="download_error_file_type_type">文件类型错误</string> + <string name="download_error_forbidden">ç¦ç”¨çš„</string> <string name="cancel_all_downloads_label">å–消所有下载</string> <string name="download_canceled_msg">å·²å–消下载</string> <string name="download_canceled_autodownload_enabled_msg">å·²å–消下载\n对该曲目ç¦ç”¨<i>自动下载</i></string> @@ -190,6 +200,9 @@ <string name="authentication_notification_title">需è¦è®¤è¯</string> <string name="authentication_notification_msg">您所请求的资æºéœ€è¦ç”¨æˆ·å和密ç </string> <string name="confirm_mobile_download_dialog_title">确认手机下载</string> + <string name="confirm_mobile_download_dialog_message_not_in_queue">移动数æ®è¿žæŽ¥ä¸‹è½½å·²äºŽè®¾ç½®ä¸è¢«å…³é—。\n\n您å¯ä»¥é€‰æ‹©ä»…åŠ å…¥ä¸‹è½½é˜Ÿåˆ—æˆ–è€…æš‚æ—¶å…许下载。\n\n<small>您的决定将会在10分钟åŽè¢«é—忘。</small></string> + <string name="confirm_mobile_download_dialog_message">移动数æ®è¿žæŽ¥ä¸‹è½½å·²äºŽè®¾ç½®ä¸è¢«å…³é—。\n\n您è¦æš‚æ—¶å…许下载å—?。<small>\n\n您的决定将会在10分钟åŽè¢«é—忘。</small></string> + <string name="confirm_mobile_download_dialog_only_add_to_queue">队列</string> <string name="confirm_mobile_download_dialog_enable_temporarily">æš‚æ—¶å…许</string> <!--Mediaplayer messages--> <string name="player_error_msg">错误!</string> @@ -200,7 +213,6 @@ <string name="playback_error_server_died">æœåŠ¡å™¨å®•æœº</string> <string name="playback_error_unknown">未知错误</string> <string name="no_media_playing_label">没有å¯æ’放的媒体</string> - <string name="position_default_label">00:00:00</string> <string name="player_buffering_msg">缓冲ä¸</string> <string name="playbackservice_notification_title">æ’客æ’放ä¸</string> <string name="unknown_media_key">AntennaPod - 未知媒体密钥: %1$d</string> @@ -215,9 +227,10 @@ <string name="move_to_top_label">移到顶端</string> <string name="move_to_bottom_label">移到下部</string> <string name="sort">排åº</string> - <string name="alpha">按å—æ¯</string> <string name="date">按日期</string> <string name="duration">按时长</string> + <string name="episode_title">å‰§é›†æ ‡é¢˜</string> + <string name="feed_title">è®¢é˜…æ ‡é¢˜</string> <string name="ascending">å‡åº</string> <string name="descending">é™åº</string> <string name="clear_queue_confirmation_msg">请确认您è¦æ¸…除队列ä¸çš„全部曲目</string> @@ -251,11 +264,15 @@ <string name="download_plugin_label">æ’件下载</string> <string name="no_playback_plugin_title">æ’件没有安装</string> <string name="set_playback_speed_label">æ’放速度</string> + <string name="enable_sonic">å…许声音</string> <!--Empty list labels--> <string name="no_items_label">列表为空.</string> <string name="no_feeds_label">还没有任何订阅.</string> <string name="no_chapters_label">æ¤æ›²ç›®æ²¡æœ‰ç« 节信æ¯</string> + <string name="no_shownotes_label">本集ä¸åŒ…å«å±•ç¤ºä¿¡æ¯</string> <!--Preferences--> + <string name="storage_pref">å˜å‚¨</string> + <string name="project_pref">项目</string> <string name="other_pref">其他</string> <string name="about_pref">关于</string> <string name="queue_label">æ’放列表</string> @@ -273,6 +290,7 @@ <string name="playback_pref">æ’放</string> <string name="network_pref">网络</string> <string name="pref_autoUpdateIntervallOrTime_title">定时更新</string> + <string name="pref_autoUpdateIntervallOrTime_sum">指定自动刷新订阅的间隔或æ¯æ—¥ç‰¹å®šæ—¶é—´</string> <string name="pref_autoUpdateIntervallOrTime_message">å¯ä»¥è®¾ç½®æ›´æ–° <i>é—´éš”</i>,比如“2 å°æ—¶â€ï¼›æˆ–ç€æ¯å¤©ç‰¹å®šçš„ <i>时间</i> ,比如\"ä¸Šåˆ 7:00\";或者 <i>ç¦ç”¨</i> 自动更新。\n\n<small>请注æ„:更新时间ä¸æ˜¯ä¸¥æ ¼çš„,å¯èƒ½ä¼šæœ‰å°‘许的延时。</small></string> <string name="pref_autoUpdateIntervallOrTime_Disable">ç¦ç”¨</string> <string name="pref_autoUpdateIntervallOrTime_Interval">设置间隔</string> @@ -329,18 +347,30 @@ <string name="pref_gpodnet_logout_toast">注销æˆåŠŸ</string> <string name="pref_gpodnet_setlogin_information_title">改å˜ç™»å½•ä¿¡æ¯</string> <string name="pref_gpodnet_setlogin_information_sum">æ”¹å˜ gpodder.net 账户登录信æ¯.</string> - <string name="pref_gpodnet_sync_title">æ£åœ¨åŒæ¥</string> + <string name="pref_gpodnet_sync_changes_title">ç«‹å³åŒæ¥æ”¹åŠ¨</string> + <string name="pref_gpodnet_full_sync_title">ç«‹å³å®Œæ•´åŒæ¥</string> + <string name="pref_gpodnet_sync_sum_last_sync_line">最åŽåŒæ¥å°è¯•äºŽï¼š%1$s(%2$s)</string> <string name="pref_gpodnet_sync_started">已开始åŒæ¥</string> + <string name="pref_gpodnet_full_sync_started">完整åŒæ¥ä»¥å¼€å§‹</string> + <string name="pref_gpodnet_login_status"><![CDATA[在设备 <i>%2$s</i> 上以 <i>%1$s</i> 身份登录]]></string> + <string name="pref_gpodnet_notifications_title">显示åŒæ¥å¤±è´¥çš„æ示信æ¯</string> + <string name="pref_gpodnet_notifications_sum">è¯¥è®¾ç½®æ— æ³•é€‚ç”¨äºŽéªŒè¯é”™è¯¯ã€‚</string> <string name="pref_playback_speed_title">æ’放速度</string> <string name="pref_playback_speed_sum">自定义音频æ’放速度</string> - <string name="pref_rewind">时间倒回</string> + <string name="pref_fast_forward_sum">自定义æ¯æ¬¡å¿«è¿›èŠ‚目的秒数</string> + <string name="pref_rewind_sum">自定义æ¯æ¬¡å€’回节目的秒数</string> <string name="pref_gpodnet_sethostname_title">设置主机å</string> <string name="pref_gpodnet_sethostname_use_default_host">使用默认主机</string> <string name="pref_expandNotify_title">扩展通知</string> <string name="pref_expandNotify_sum">总是扩展通知以显示æ’放按钮</string> <string name="pref_persistNotify_title">ä¿æŒæ’放控制</string> <string name="pref_persistNotify_sum">在暂åœæ—¶ä¿æŒé€šçŸ¥å’Œé”å±ç•Œé¢çš„控制。</string> + <string name="pref_compact_notification_buttons_title">设置é”å±æŒ‰é’®</string> + <string name="pref_compact_notification_buttons_sum">修改é”å±ç•Œé¢ä¸Šçš„回放按钮(åŒæ ·ä¼šå½±å“æ’放/æš‚åœæŒ‰é’®ï¼‰ã€‚</string> + <string name="pref_compact_notification_buttons_dialog_title">选择%1$dä¸çš„最大值</string> + <string name="pref_compact_notification_buttons_dialog_error">ä½ åªèƒ½é€‰æ‹©%1$dä¸çš„最大值</string> <string name="pref_lockscreen_background_title">设置é”å±èƒŒæ™¯</string> + <string name="pref_lockscreen_background_sum">å°†é”å±èƒŒæ™¯è®¾ç½®ä¸ºå½“å‰æ’放节目的å°é¢å›¾ï¼ˆæ½œåœ¨çš„副作用是图片å¯èƒ½ä¼šåœ¨å‡ºçŽ°åœ¨ç¬¬ä¸‰æ–¹åº”用ä¸ï¼‰ã€‚</string> <string name="pref_showDownloadReport_title">显示下载报告</string> <string name="pref_showDownloadReport_sum">如果下载失败,生æˆä¸€ä»½æ˜¾ç¤ºè¯¦ç»†å¤±è´¥ä¿¡æ¯çš„报告。</string> <string name="pref_expand_notify_unsupport_toast">Android 4.1 之å‰ä¸æ”¯æŒæ‰©å±•é€šçŸ¥ã€‚</string> @@ -352,23 +382,33 @@ <string name="crash_report_title">崩溃报告</string> <string name="crash_report_sum">通过 E-mail å‘é€æœ€åŽå´©æºƒæŠ¥å‘Š</string> <string name="send_email">å‘é€ E-mail</string> - <string name="pref_sonic_title">内置æ’放器</string> + <string name="experimental_pref">实验性</string> + <string name="pref_sonic_title">音频媒体æ’放器</string> + <string name="pref_sonic_message">使用内置音频媒体æ’放器代替 Android 原生媒体æ’放器</string> + <string name="pref_current_value">当å‰å€¼ï¼š%1$s</string> <string name="pref_proxy_title">代ç†</string> <string name="pref_proxy_sum">选择一个网络代ç†</string> + <string name="pref_faq">FAQ</string> <string name="pref_known_issues">已知问题</string> - <string name="pref_no_browser_found">未找到æµè§ˆå™¨</string> + <string name="pref_no_browser_found">æ— ç½‘ç»œæµè§ˆå™¨</string> + <string name="pref_cast_title">Chromecast 支æŒ</string> + <string name="pref_cast_message_play_flavor">å¯ç”¨åœ¨ Cast 设备(例如 Chromecast 〠Audio Speakers å’Œ Android TV )上对于远端媒体回放的支æŒ</string> + <string name="pref_cast_message_free_flavor">Chromecast 所需è¦çš„第三方库文件在这个版本的 AntennaPod ä¸è¢«ç¦ç”¨</string> + <string name="pref_enqueue_downloaded_title">队列任务下载完毕</string> + <string name="pref_enqueue_downloaded_summary">å‘é˜Ÿåˆ—æ·»åŠ å·²ä¸‹è½½çš„èŠ‚ç›®</string> <!--Auto-Flattr dialog--> <string name="auto_flattr_enable">å¯ç”¨è‡ªåŠ¨ flattring</string> <string name="auto_flattr_after_percent">当æ’放到百分之%dæ—¶Flattr改曲目</string> <string name="auto_flattr_ater_beginning">当æ’放开始时Flattr改曲目</string> <string name="auto_flattr_ater_end">当æ’放结æŸæ—¶Flattr改曲目</string> <!--Search--> - <string name="search_hint">æœç´¢è®¢é˜…或者曲目</string> - <string name="found_in_shownotes_label">笔记ä¸æŸ¥æ‰¾</string> + <string name="search_hint">查找节目</string> <string name="found_in_chapters_label">ç« èŠ‚ä¸æŸ¥æ‰¾</string> + <string name="found_in_feeds_label">Feeds ä¸æŸ¥æ‰¾</string> <string name="search_status_no_results">没有找到任何结果</string> <string name="search_label">æœç´¢</string> <string name="found_in_title_label">æ ‡é¢˜ä¸æŸ¥æ‰¾</string> + <string name="no_results_for_query">未找到关于 \"%1$s\" 的结果</string> <!--OPML import and export--> <string name="opml_import_txtv_button_lable">OPML 文件å¯ä»¥æ–¹ä¾¿çš„从别的æ’客转移数æ®è¿‡æ¥ã€‚</string> <string name="opml_import_option">设置 %1$d</string> @@ -379,7 +419,7 @@ <string name="opml_import_label">OPML 导入</string> <string name="opml_directory_error">错误!</string> <string name="reading_opml_label">OPML 文件读å–ä¸</string> - <string name="opml_reader_error">读å–OPML文档时å‘生错误</string> + <string name="opml_reader_error">è¯»å– OPML 文档时å‘生错误</string> <string name="opml_import_error_no_file">没有选择文件ï¼</string> <string name="select_all_label">全选</string> <string name="deselect_all_label">å–消所有选择</string> @@ -387,10 +427,12 @@ <string name="choose_file_from_filesystem">æ¥è‡ªæœ¬åœ°æ–‡ä»¶ç³»ç»Ÿ</string> <string name="choose_file_from_external_application">使用外部应用</string> <string name="opml_export_label">OPML 导出</string> + <string name="html_export_label">导出为 HTML 文件</string> <string name="exporting_label">æ£åœ¨å¯¼å‡º</string> <string name="export_error_label">导出出错</string> <string name="opml_export_success_title">OPML 导出æˆåŠŸ.</string> <string name="opml_export_success_sum">.opml 文件已ä¿å˜åˆ°:\u0020</string> + <string name="opml_import_ask_read_permission">è¯»å– OPML 文件需è¦è®¿é—®å¤–部å˜å‚¨çš„æƒé™</string> <!--Sleep timer--> <string name="set_sleeptimer_label">è®¾ç½®ä¼‘çœ è®¡æ—¶å™¨</string> <string name="disable_sleeptimer_label">ç¦ç”¨ä¼‘çœ è®¡æ—¶å™¨</string> @@ -413,6 +455,9 @@ <plurals name="time_hours_quantified"> <item quantity="other">%d å°æ—¶</item> </plurals> + <string name="auto_enable_label">自动å¯ç”¨</string> + <string name="sleep_timer_enabled_label">ç¡çœ 计时器已å¯ç”¨</string> + <string name="sleep_timer_disabled_label">ç¡çœ 计时器已ç¦ç”¨</string> <!--gpodder.net--> <string name="gpodnet_taglist_header">目录</string> <string name="gpodnet_toplist_header">头æ¡æ’客</string> @@ -432,6 +477,7 @@ <string name="gpodnetauth_device_chooseExistingDevice">选择已å˜åœ¨è®¾å¤‡</string> <string name="gpodnetauth_device_errorEmpty">设备编å·å¿…须填写</string> <string name="gpodnetauth_device_errorAlreadyUsed">设备编å·å·²è¢«ä½¿ç”¨</string> + <string name="gpodnetauth_device_caption_errorEmpty">æ ‡é¢˜ä¸èƒ½ä¸ºç©º</string> <string name="gpodnetauth_device_butChoose">选择</string> <string name="gpodnetauth_finish_title">登录æˆåŠŸ!</string> <string name="gpodnetauth_finish_descr">æå–œ! ä½ çš„ gpodder.net å¸æˆ·ä¸Žè®¾å¤‡å·²è¿žç»“完æˆ. 现在开始 AntennaPod 将自动åŒæ¥ä½ gpodder.net å¸æˆ·å†…的订阅信æ¯åˆ°è®¾å¤‡ä¸Š.</string> @@ -441,10 +487,14 @@ <string name="gpodnetsync_auth_error_descr">错误的用户å或者密ç </string> <string name="gpodnetsync_error_title">gpodder.net åŒæ¥é”™è¯¯</string> <string name="gpodnetsync_error_descr">åŒæ¥è¿‡ç¨‹ä¸å‘生错误: \u0020</string> + <string name="gpodnetsync_pref_report_successful">æˆåŠŸäº†</string> + <string name="gpodnetsync_pref_report_failed">失败了</string> <!--Directory chooser--> <string name="selected_folder_label">已选文件夹:</string> <string name="create_folder_label">穿件文件夹</string> <string name="choose_data_directory">选择数æ®æ–‡ä»¶å¤¹</string> + <string name="choose_data_directory_message">请选择用于 AntennaPod çš„æ•°æ®æ ¹ç›®å½•ï¼Œ AntennaPod 将会创建åˆé€‚çš„å目录。</string> + <string name="choose_data_directory_permission_rationale">访问外部å˜å‚¨éœ€è¦</string> <string name="create_folder_msg">确实创建 \"%1$s\" 文件夹?</string> <string name="create_folder_success">创建新文件夹</string> <string name="create_folder_error_no_write_access">本文件夹ä¸èƒ½å†™å…¥</string> @@ -466,22 +516,13 @@ <string name="subscribed_label">已订阅</string> <string name="downloading_label">æ£åœ¨ä¸‹è½½</string> <!--Content descriptions for image buttons--> - <string name="show_chapters_label">æ˜¾ç¤ºç« èŠ‚</string> - <string name="show_shownotes_label">显示笔记</string> - <string name="show_cover_label">显示图片</string> <string name="rewind_label">回放</string> <string name="fast_forward_label">å¿«è¿›</string> <string name="media_type_audio_label">音频</string> <string name="media_type_video_label">视频</string> <string name="navigate_upwards_label">å‘上导航</string> - <string name="butAction_label">更多动作</string> - <string name="status_playing_label">曲目æ£åœ¨æ’放</string> <string name="status_downloading_label">曲目æ£åœ¨ä¸‹è½½</string> - <string name="status_downloaded_label">曲目已下载</string> - <string name="status_unread_label">新项目</string> <string name="in_queue_label">曲目已ç»åœ¨æ’放列表ä¸</string> - <string name="new_episodes_count_label">新曲目数</string> - <string name="in_progress_episodes_count_label">已收å¬æ›²ç›®æ•°</string> <string name="drag_handle_content_description">拖动以å˜æ›´æœ¬é¡¹ç›®çš„ä½ç½®</string> <string name="load_next_page_label">载入下一页</string> <!--Feed information screen--> @@ -498,6 +539,8 @@ <string name="sp_apps_importing_feeds_msg">æ£åœ¨ä»Žé€‰å®šçš„应用ä¸å¯¼å…¥è®¢é˜…...</string> <string name="search_itunes_label">æœç´¢ iTunes</string> <string name="filter">过滤器</string> + <string name="search_fyyd_label">在 fyyd 上æœç´¢</string> + <!--Episodes apply actions--> <string name="all_label">全部</string> <string name="selected_all_label">全选</string> <string name="none_label">æ— </string> @@ -514,6 +557,7 @@ <string name="selected_queued_label">已选曲目</string> <string name="not_queued_label">ä¸åœ¨æ’放列表ä¸</string> <string name="selected_not_queued_label">选择ä¸åœ¨æ’放列表的曲目</string> + <!--Sort--> <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> @@ -522,6 +566,7 @@ <string name="sort_duration_long_short">时长 (é•¿ \u2192 çŸ)</string> <!--Rating dialog--> <string name="rating_title">喜欢 AntennaPod?</string> + <string name="rating_message">如您能在百忙之外抽时间评价一下AntennaPod,我们感激ä¸å°½.</string> <string name="rating_never_label">请勿打扰</string> <string name="rating_later_label">ç¨åŽæ醒</string> <string name="rating_now_label">好的, å°±è¿™æ ·ï¼</string> @@ -532,6 +577,7 @@ <string name="left_short">L</string> <string name="right_short">R</string> <string name="audio_effects">音频效果</string> + <string name="sonic_only">仅声音</string> <!--proxy settings--> <string name="proxy_type_label">类型</string> <string name="host_label">主机地å€</string> @@ -542,6 +588,13 @@ <string name="proxy_test_successful">测试æˆåŠŸ</string> <string name="proxy_test_failed">测试失败</string> <string name="proxy_host_empty_error">主机地å€ä¸èƒ½ä¸ºç©º</string> - <string name="proxy_host_invalid_error">主机地å€ä¸æ˜¯æœ‰æ•ˆIP或域å</string> + <string name="proxy_host_invalid_error">主机地å€ä¸ºæ— 效的IP地å€æˆ–域å</string> <string name="proxy_port_invalid_error">端å£ä¸å¯ç”¨</string> + <!--Casting--> + <string name="cast_failed_to_play">媒体回放开始失败</string> + <string name="cast_failed_to_stop">媒体回放åœæ¢å¤±è´¥</string> + <string name="cast_failed_to_pause">媒体回放暂åœå¤±è´¥</string> + <!--<string name="cast_failed_to_connect">Could not connect to the device</string>--> + <string name="cast_failed_setting_volume">音é‡è®¾ç½®å¤±è´¥</string> + <string name="cast_failed_media_error_skipping">媒体æ’放出错.跳转ä¸...</string> </resources> diff --git a/core/src/main/res/values-zh-rHK/strings.xml b/core/src/main/res/values-zh-rHK/strings.xml new file mode 100644 index 000000000..28dfeb6e8 --- /dev/null +++ b/core/src/main/res/values-zh-rHK/strings.xml @@ -0,0 +1,38 @@ +<?xml version='1.0' encoding='UTF-8'?> +<resources xmlns:tools="http://schemas.android.com/tools"> + <!--Activitiy and fragment titles--> + <!--Statistics fragment--> + <!--Main activity--> + <!--Webview actions--> + <!--Playback history--> + <!--Other--> + <!--'Add Feed' Activity labels--> + <!--Actions on feeds--> + <!--actions on feeditems--> + <!--Download messages and labels--> + <!--Mediaplayer messages--> + <!--Queue operations--> + <!--Flattr--> + <!--Flattr--> + <!--Variable Speed--> + <!--Empty list labels--> + <!--Preferences--> + <!--Auto-Flattr dialog--> + <!--Search--> + <!--OPML import and export--> + <!--Sleep timer--> + <!--gpodder.net--> + <!--Directory chooser--> + <!--Online feed view--> + <!--Content descriptions for image buttons--> + <!--Feed information screen--> + <!--Progress information--> + <!--AntennaPodSP--> + <!--Episodes apply actions--> + <!--Sort--> + <!--Rating dialog--> + <!--Audio controls--> + <!--proxy settings--> + <!--Casting--> + <!--<string name="cast_failed_to_connect">Could not connect to the device</string>--> +</resources> diff --git a/core/src/main/res/values-zh-rTW/strings.xml b/core/src/main/res/values-zh-rTW/strings.xml new file mode 100644 index 000000000..28dfeb6e8 --- /dev/null +++ b/core/src/main/res/values-zh-rTW/strings.xml @@ -0,0 +1,38 @@ +<?xml version='1.0' encoding='UTF-8'?> +<resources xmlns:tools="http://schemas.android.com/tools"> + <!--Activitiy and fragment titles--> + <!--Statistics fragment--> + <!--Main activity--> + <!--Webview actions--> + <!--Playback history--> + <!--Other--> + <!--'Add Feed' Activity labels--> + <!--Actions on feeds--> + <!--actions on feeditems--> + <!--Download messages and labels--> + <!--Mediaplayer messages--> + <!--Queue operations--> + <!--Flattr--> + <!--Flattr--> + <!--Variable Speed--> + <!--Empty list labels--> + <!--Preferences--> + <!--Auto-Flattr dialog--> + <!--Search--> + <!--OPML import and export--> + <!--Sleep timer--> + <!--gpodder.net--> + <!--Directory chooser--> + <!--Online feed view--> + <!--Content descriptions for image buttons--> + <!--Feed information screen--> + <!--Progress information--> + <!--AntennaPodSP--> + <!--Episodes apply actions--> + <!--Sort--> + <!--Rating dialog--> + <!--Audio controls--> + <!--proxy settings--> + <!--Casting--> + <!--<string name="cast_failed_to_connect">Could not connect to the device</string>--> +</resources> diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml index fba22b985..45650495c 100644 --- a/core/src/main/res/values/arrays.xml +++ b/core/src/main/res/values/arrays.xml @@ -157,23 +157,27 @@ <item>@string/drawer_feed_order_unplayed_episodes</item> <item>@string/drawer_feed_order_alphabetical</item> <item>@string/drawer_feed_order_last_update</item> + <item>@string/drawer_feed_order_most_played</item> </string-array> <string-array name="nav_drawer_feed_order_values"> <item>0</item> <item>1</item> <item>2</item> + <item>3</item> </string-array> <string-array name="nav_drawer_feed_counter_options"> <item>@string/drawer_feed_counter_new_unplayed</item> <item>@string/drawer_feed_counter_new</item> <item>@string/drawer_feed_counter_unplayed</item> + <item>@string/drawer_feed_counter_downloaded</item> <item>@string/drawer_feed_counter_none</item> </string-array> <string-array name="nav_drawer_feed_counter_values"> <item>0</item> <item>1</item> <item>2</item> + <item>4</item> <item>3</item> </string-array> @@ -185,6 +189,7 @@ <item>@string/hide_not_queued_episodes_label</item> <item>@string/hide_downloaded_episodes_label</item> <item>@string/hide_not_downloaded_episodes_label</item> + <item>@string/hide_has_media_label</item> </string-array> <string-array name="episode_filter_values"> @@ -195,6 +200,7 @@ <item>not_queued</item> <item>downloaded</item> <item>not_downloaded</item> + <item>has_media</item> </string-array> <string-array name="image_cache_size_options"> diff --git a/core/src/main/res/values/dimens.xml b/core/src/main/res/values/dimens.xml index 4f549efd7..01dce6a1c 100644 --- a/core/src/main/res/values/dimens.xml +++ b/core/src/main/res/values/dimens.xml @@ -36,4 +36,9 @@ <dimen name="audioplayer_playercontrols_length">48dp</dimen> + <dimen name="media_router_controller_playback_control_vertical_padding">16dp</dimen> + <dimen name="media_router_controller_playback_control_horizontal_spacing">12dp</dimen> + <dimen name="media_router_controller_playback_control_start_padding">24dp</dimen> + <dimen name="media_router_controller_bottom_margin">8dp</dimen> + </resources> diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 238a24c81..65697be28 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -12,7 +12,6 @@ <string name="favorite_episodes_label">Favorites</string> <string name="new_label">New</string> <string name="settings_label">Settings</string> - <string name="add_new_feed_label">Add Podcast</string> <string name="downloads_label">Downloads</string> <string name="downloads_running_label">Running</string> <string name="downloads_completed_label">Completed</string> @@ -30,6 +29,10 @@ <!-- Statistics fragment --> <string name="total_time_listened_to_podcasts">Total time of podcasts played:</string> <string name="statistics_details_dialog">%1$d out of %2$d episodes started.\n\nPlayed %3$s out of %4$s.</string> + <string name="statistics_mode">Statistics mode</string> + <string name="statistics_mode_normal">Calculate duration that was actually played. Playing twice is counted twice, while marking as played is not counted</string> + <string name="statistics_mode_count_all">Sum up all podcasts marked as played</string> + <string name="statistics_speed_not_counted">Notice: Playback speed is never taken into account.</string> <!-- Main activity --> <string name="drawer_open">Open menu</string> @@ -38,9 +41,11 @@ <string name="drawer_feed_order_unplayed_episodes">Sort by counter</string> <string name="drawer_feed_order_alphabetical">Sort alphabetically</string> <string name="drawer_feed_order_last_update">Sort by publication date</string> + <string name="drawer_feed_order_most_played">Sort by number of played episodes</string> <string name="drawer_feed_counter_new_unplayed">Number of new and unplayed episodes</string> <string name="drawer_feed_counter_new">Number of new episodes</string> <string name="drawer_feed_counter_unplayed">Number of unplayed episodes</string> + <string name="drawer_feed_counter_downloaded">Number of downloaded episodes</string> <string name="drawer_feed_counter_none">None</string> <!-- Webview actions --> @@ -58,6 +63,7 @@ <string name="cancel_label">Cancel</string> <string name="yes">Yes</string> <string name="no">No</string> + <string name="reset">Reset</string> <string name="author_label">Author</string> <string name="language_label">Language</string> <string name="url_label">URL</string> @@ -68,6 +74,7 @@ <string name="refresh_label">Refresh</string> <string name="external_storage_error_msg">No external storage is available. Please make sure that external storage is mounted so that the app can work properly.</string> <string name="chapters_label">Chapters</string> + <string name="chapter_duration">Duration: %1$s</string> <string name="shownotes_label">Shownotes</string> <string name="description_label">Description</string> <string name="most_recent_prefix">Most recent episode:\u0020</string> @@ -101,7 +108,7 @@ <string name="etxtFeedurlHint">www.example.com/feed</string> <string name="txtvfeedurl_label">Add Podcast by URL</string> <string name="podcastdirectories_label">Find Podcast in Directory</string> - <string name="podcastdirectories_descr">You can search for new podcasts by name, category or popularity in the gpodder.net directory, or search the iTunes store.</string> + <string name="podcastdirectories_descr">For new podcasts, you can search iTunes or fyyd, or browse gpodder.net by name, category or popularity.</string> <string name="browse_gpoddernet_label">Browse gpodder.net</string> <!-- Actions on feeds --> @@ -110,15 +117,19 @@ <string name="mark_all_read_confirmation_msg">Please confirm that you want to mark all episodes as being played.</string> <string name="mark_all_read_feed_confirmation_msg">Please confirm that you want to mark all episodes in this feed as being played.</string> <string name="mark_all_seen_label">Mark all as seen</string> + <string name="mark_all_seen_msg">Marked all Episodes as seen</string> + <string name="mark_all_seen_confirmation_msg">Please confirm that you want to mark all episodes as seen.</string> <string name="show_info_label">Show information</string> + <string name="rename_feed_label">Rename Podcast</string> <string name="remove_feed_label">Remove Podcast</string> <string name="share_label">Share…</string> <string name="share_link_label">Share Link</string> + <string name="share_file_label">Share File</string> <string name="share_link_with_position_label">Share Link with Position</string> <string name="share_feed_url_label">Share Feed URL</string> <string name="share_item_url_label">Share Episode File URL</string> <string name="share_item_url_with_position_label">Share Episode File URL with Position</string> - <string name="feed_delete_confirmation_msg">Please confirm that you want to delete this feed and ALL episodes of this feed that you have downloaded.</string> + <string name="feed_delete_confirmation_msg">Please confirm that you want to delete the feed \"%1$s\" and ALL episodes of this feed that you have downloaded.</string> <string name="feed_remover_msg">Removing Feed</string> <string name="load_complete_feed">Refresh complete Feed</string> <string name="hide_episodes_title">Hide Episodes</string> @@ -130,6 +141,7 @@ <string name="hide_not_queued_episodes_label">Not queued</string> <string name="hide_downloaded_episodes_label">Downloaded</string> <string name="hide_not_downloaded_episodes_label">Not downloaded</string> + <string name="hide_has_media_label">Has media</string> <string name="filtered_label">Filtered</string> <string name="refresh_failed_msg">{fa-exclamation-circle} Last Refresh failed</string> <string name="open_podcast">Open Podcast</string> @@ -141,7 +153,10 @@ <string name="stop_label">Stop</string> <string name="stream_label">Stream</string> <string name="remove_label">Remove</string> + <string name="delete_label">Delete</string> + <string name="delete_failed">Unable to delete file. Rebooting the device could help.</string> <string name="remove_episode_lable">Remove Episode</string> + <string name="marked_as_seen_label">Marked as seen</string> <string name="mark_read_label">Mark as played</string> <string name="marked_as_read_label">Marked as played</string> <string name="mark_unread_label">Mark as unplayed</string> @@ -231,9 +246,10 @@ <string name="move_to_top_label">Move to top</string> <string name="move_to_bottom_label">Move to bottom</string> <string name="sort">Sort</string> - <string name="alpha">Alphabetically</string> <string name="date">Date</string> <string name="duration">Duration</string> + <string name="episode_title">Episode title</string> + <string name="feed_title">Feed title</string> <string name="ascending">Ascending</string> <string name="descending">Descending</string> <string name="clear_queue_confirmation_msg">Please confirm that you want to clear the queue of ALL of the episodes in it</string> @@ -292,15 +308,19 @@ <string name="pref_pauseOnDisconnect_sum">Pause playback when headphones or bluetooth are disconnected</string> <string name="pref_unpauseOnHeadsetReconnect_sum">Resume playback when the headphones are reconnected</string> <string name="pref_unpauseOnBluetoothReconnect_sum">Resume playback when bluetooth reconnects</string> - <string name="pref_hardwareForwardButtonSkips_title">Forward button skips</string> + <string name="pref_hardwareForwardButtonSkips_title">Forward Button Skips</string> <string name="pref_hardwareForwardButtonSkips_sum">When pressing a hardware forward button skip to the next episode instead of fast-forwarding</string> + <string name="pref_hardwarePreviousButtonRestarts_title">Previous button restarts</string> + <string name="pref_hardwarePreviousButtonRestarts_sum">When pressing a hardware previous button restart playing the current episode instead of rewinding</string> <string name="pref_followQueue_sum">Jump to next queue item when playback completes</string> <string name="pref_auto_delete_sum">Delete episode when playback completes</string> <string name="pref_auto_delete_title">Auto Delete</string> <string name="pref_smart_mark_as_played_sum">Mark episodes as played even if less than a certain amount of seconds of playing time is still left</string> - <string name="pref_smart_mark_as_played_title">Smart mark as played</string> + <string name="pref_smart_mark_as_played_title">Smart Mark as Played</string> <string name="pref_skip_keeps_episodes_sum">Keep episodes when they are skipped</string> <string name="pref_skip_keeps_episodes_title">Keep Skipped Episodes</string> + <string name="pref_favorite_keeps_episodes_sum">Keep episodes when they are marked Favorite</string> + <string name="pref_favorite_keeps_episodes_title">Keep Favorite Episodes</string> <string name="playback_pref">Playback</string> <string name="network_pref">Network</string> <string name="pref_autoUpdateIntervallOrTime_title">Update Interval or Time of Day</string> @@ -327,7 +347,7 @@ <string name="pref_flattr_this_app_sum">Support the development of AntennaPod by flattring it. Thanks!</string> <string name="pref_revokeAccess_title">Revoke access</string> <string name="pref_revokeAccess_sum">Revoke the access permission to your flattr account for this app.</string> - <string name="pref_auto_flattr_title">Automatic Flattr</string> + <string name="pref_auto_flattr_title">Automatic Flattr</string> <string name="pref_auto_flattr_sum">Configure automatic flattring</string> <string name="user_interface_label">User Interface</string> <string name="pref_set_theme_title">Select Theme</string> @@ -344,6 +364,8 @@ <string name="pref_automatic_download_sum">Configure the automatic download of episodes.</string> <string name="pref_autodl_wifi_filter_title">Enable Wi-Fi filter</string> <string name="pref_autodl_wifi_filter_sum">Allow automatic download only for selected Wi-Fi networks.</string> + <string name="pref_autodl_allow_on_mobile_title">Download on mobile connection</string> + <string name="pref_autodl_allow_on_mobile_sum">Allow automatic download over the mobile data connection.</string> <string name="pref_automatic_download_on_battery_title">Download when not charging</string> <string name="pref_automatic_download_on_battery_sum">Allow automatic download when the battery is not charging</string> <string name="pref_parallel_downloads_title">Parallel Downloads</string> @@ -351,23 +373,31 @@ <string name="pref_theme_title_light">Light</string> <string name="pref_theme_title_dark">Dark</string> <string name="pref_episode_cache_unlimited">Unlimited</string> - <string name="pref_update_interval_hours_plural">hours</string> - <string name="pref_update_interval_hours_singular">hour</string> - <string name="pref_update_interval_hours_manual">Manual</string> + <string name="pref_update_interval_hours_plural">hours</string> + <string name="pref_update_interval_hours_singular">hour</string> + <string name="pref_update_interval_hours_manual">Manual</string> <string name="pref_gpodnet_authenticate_title">Login</string> <string name="pref_gpodnet_authenticate_sum">Login with your gpodder.net account in order to sync your subscriptions.</string> <string name="pref_gpodnet_logout_title">Logout</string> <string name="pref_gpodnet_logout_toast">Logout was successful</string> <string name="pref_gpodnet_setlogin_information_title">Change login information</string> <string name="pref_gpodnet_setlogin_information_sum">Change the login information for your gpodder.net account.</string> - <string name="pref_gpodnet_sync_title">Sync now</string> - <string name="pref_gpodnet_sync_sum">Sync subscriptions and episode states with gpodder.net</string> + <string name="pref_gpodnet_sync_changes_title">Sync changes now</string> + <string name="pref_gpodnet_sync_changes_sum">Sync subscription and episode state changes with gpodder.net.</string> + <string name="pref_gpodnet_full_sync_title">Full sync now</string> + <string name="pref_gpodnet_full_sync_sum">Sync all subscriptions and episode states with gpodder.net.</string> + <string name="pref_gpodnet_sync_sum_last_sync_line">Last sync attempt: %1$s (%2$s)</string> <string name="pref_gpodnet_sync_started">Sync started</string> + <string name="pref_gpodnet_full_sync_started">Full sync started</string> <string name="pref_gpodnet_login_status"><![CDATA[Logged in as <i>%1$s</i> with device <i>%2$s</i>]]></string> + <string name="pref_gpodnet_notifications_title">Show sync error notifications</string> + <string name="pref_gpodnet_notifications_sum">This setting does not apply to authentication errors.</string> <string name="pref_playback_speed_title">Playback Speeds</string> <string name="pref_playback_speed_sum">Customize the speeds available for variable speed audio playback</string> - <string name="pref_fast_forward">Fast forward time</string> - <string name="pref_rewind">Rewind time</string> + <string name="pref_fast_forward">Fast Forward Skip Time</string> + <string name="pref_fast_forward_sum">Customize the number of seconds to jump forward when the fast forward button is clicked</string> + <string name="pref_rewind">Rewind Skip Time</string> + <string name="pref_rewind_sum">Customize the number of seconds to jump backwards when the rewind button is clicked</string> <string name="pref_gpodnet_sethostname_title">Set hostname</string> <string name="pref_gpodnet_sethostname_use_default_host">Use default host</string> <string name="pref_expandNotify_title">Expand Notification</string> @@ -378,8 +408,6 @@ <string name="pref_compact_notification_buttons_sum">Change the playback buttons on the lockscreen. The play/pause button is always included.</string> <string name="pref_compact_notification_buttons_dialog_title">Select a maximum of %1$d items</string> <string name="pref_compact_notification_buttons_dialog_error">You can only select a maximum of %1$d items.</string> - <string name="pref_show_subscriptions_in_drawer_title">Show Subscriptions</string> - <string name="pref_show_subscriptions_in_drawer_sum">Show subscription list directly in navigation drawer</string> <string name="pref_lockscreen_background_title">Set Lockscreen Background</string> <string name="pref_lockscreen_background_sum">Set the lockscreen background to the current episode\'s image. As a side effect, this will also show the image in third party apps.</string> <string name="pref_showDownloadReport_title">Show Download Report</string> @@ -394,7 +422,7 @@ <string name="crash_report_sum">Send the latest crash report via e-mail</string> <string name="send_email">Send e-mail</string> <string name="experimental_pref">Experimental</string> - <string name="pref_sonic_title">Sonic media player</string> + <string name="pref_sonic_title">Sonic Media Player</string> <string name="pref_sonic_message">Use built-in sonic media player as a replacement for Android\'s native mediaplayer and Prestissimo</string> <string name="pref_current_value">Current value: %1$s</string> <string name="pref_proxy_title">Proxy</string> @@ -403,7 +431,10 @@ <string name="pref_known_issues">Known issues</string> <string name="pref_no_browser_found">No web browser found.</string> <string name="pref_cast_title">Chromecast support</string> - <string name="pref_cast_message">Enable support for remote media playback on Cast devices (such as Chromecast, Audio Speakers or Android TV)</string> + <string name="pref_cast_message_play_flavor">Enable support for remote media playback on Cast devices (such as Chromecast, Audio Speakers or Android TV)</string> + <string name="pref_cast_message_free_flavor">Chromecast requires third party proprietary libraries that are disabled in this version of AntennaPod</string> + <string name="pref_enqueue_downloaded_title">Enqueue Downloaded</string> + <string name="pref_enqueue_downloaded_summary">Add downloaded episodes to the queue</string> <!-- Auto-Flattr dialog --> <string name="auto_flattr_enable">Enable automatic flattring</string> @@ -412,12 +443,15 @@ <string name="auto_flattr_ater_end">Flattr episode when playback ends</string> <!-- Search --> - <string name="search_hint">Search for Feeds or Episodes</string> - <string name="found_in_shownotes_label">Found in shownotes</string> + <string name="search_hint">Search for episodes</string> + <string name="found_in_shownotes_label">Found in show notes</string> <string name="found_in_chapters_label">Found in chapters</string> + <string name="found_in_authors_label">Found in authors</string> + <string name="found_in_feeds_label">Found in feeds</string> <string name="search_status_no_results">No results were found</string> <string name="search_label">Search</string> <string name="found_in_title_label">Found in title</string> + <string name="no_results_for_query">No results were found for \"%1$s\"</string> <!-- OPML import and export --> <string name="opml_import_txtv_button_lable">OPML files allow you to move your podcasts from one podcatcher to another.</string> @@ -436,6 +470,7 @@ <string name="choose_file_from_filesystem">From local filesystem</string> <string name="choose_file_from_external_application">Use external application</string> <string name="opml_export_label">OPML export</string> + <string name="html_export_label">HTML export</string> <string name="exporting_label">Exporting…</string> <string name="export_error_label">Export error</string> <string name="opml_export_success_title">OPML Export successful.</string> @@ -467,6 +502,9 @@ <item quantity="one">1 hour</item> <item quantity="other">%d hours</item> </plurals> + <string name="auto_enable_label">Auto-enable</string> + <string name="sleep_timer_enabled_label">Sleep timer enabled</string> + <string name="sleep_timer_disabled_label">Sleep timer disabled</string> <!-- gpodder.net --> <string name="gpodnet_taglist_header">CATEGORIES</string> @@ -499,6 +537,8 @@ <string name="gpodnetsync_auth_error_descr">Wrong username or password</string> <string name="gpodnetsync_error_title">gpodder.net sync error</string> <string name="gpodnetsync_error_descr">An error occurred during syncing:\u0020</string> + <string name="gpodnetsync_pref_report_successful">Successful</string> + <string name="gpodnetsync_pref_report_failed">Failed</string> <!-- Directory chooser --> <string name="selected_folder_label">Selected folder:</string> @@ -558,6 +598,8 @@ <string name="search_itunes_label">Search iTunes</string> <string name="filter">Filter</string> + + <string name="search_fyyd_label">Search fyyd</string> <!-- Episodes apply actions --> <string name="all_label">All</string> @@ -576,6 +618,8 @@ <string name="selected_queued_label">Selected queued Episodes</string> <string name="not_queued_label">Not queued</string> <string name="selected_not_queued_label">Selected not queued Episodes</string> + <string name="has_media">Has media</string> + <string name="selected_has_media_label">Selected episodes with media</string> <!-- Sort --> <string name="sort_title_a_z">Title (A \u2192 Z)</string> diff --git a/core/src/main/res/values/styles.xml b/core/src/main/res/values/styles.xml index 6a4dc4781..4f228f8f1 100644 --- a/core/src/main/res/values/styles.xml +++ b/core/src/main/res/values/styles.xml @@ -239,6 +239,10 @@ <item name="attr/ic_cast_disconnect">@drawable/ic_cast_disconnect_white_36dp</item> </style> + <style name="Theme.AntennaPod.Dark.Splash" parent="Theme.AppCompat.NoActionBar"> + <item name="android:windowBackground">@drawable/bg_splash</item> + </style> + <style name="Theme.AntennaPod.VideoPlayer" parent="@style/Theme.AntennaPod.Dark"> <item name="windowActionBarOverlay">true</item> </style> @@ -285,6 +289,16 @@ <item name="textAllCaps">false</item> </style> + <style name="Divider"> + <item name="android:layout_width">match_parent</item> + <item name="android:layout_height">1dp</item> + <item name="android:layout_marginTop">8dp</item> + <item name="android:layout_marginLeft">16dp</item> + <item name="android:layout_marginRight">16dp</item> + <item name="android:layout_marginBottom">8dp</item> + <item name="android:background">?android:attr/listDivider</item> + </style> + <style name="AntennaPod.Dialog.Light" parent="Theme.AppCompat.Light.Dialog"> <item name="colorAccent">@color/holo_blue_light</item> </style> diff --git a/core/src/play/java/de/danoeh/antennapod/core/CastCallbacks.java b/core/src/play/java/de/danoeh/antennapod/core/CastCallbacks.java new file mode 100644 index 000000000..770fee9b9 --- /dev/null +++ b/core/src/play/java/de/danoeh/antennapod/core/CastCallbacks.java @@ -0,0 +1,12 @@ +package de.danoeh.antennapod.core; + +import android.support.annotation.Nullable; +import android.support.v7.app.MediaRouteDialogFactory; + +/** + * Callbacks for Chromecast support on the core module + */ +public interface CastCallbacks { + + @Nullable MediaRouteDialogFactory getMediaRouterDialogFactory(); +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java b/core/src/play/java/de/danoeh/antennapod/core/ClientConfig.java index 8dc91b3f2..9af76cf86 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java +++ b/core/src/play/java/de/danoeh/antennapod/core/ClientConfig.java @@ -4,6 +4,7 @@ import android.content.Context; import de.danoeh.antennapod.core.cast.CastManager; import de.danoeh.antennapod.core.preferences.PlaybackPreferences; +import de.danoeh.antennapod.core.preferences.SleepTimerPreferences; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.storage.PodDBAdapter; import de.danoeh.antennapod.core.util.NetworkUtils; @@ -32,6 +33,8 @@ public class ClientConfig { public static DBTasksCallbacks dbTasksCallbacks; + public static CastCallbacks castCallbacks; + private static boolean initialized = false; public static synchronized void initialize(Context context) { @@ -44,6 +47,7 @@ public class ClientConfig { PlaybackPreferences.init(context); NetworkUtils.init(context); CastManager.init(context); + SleepTimerPreferences.init(context); initialized = true; } diff --git a/core/src/main/java/de/danoeh/antennapod/core/cast/CastConsumer.java b/core/src/play/java/de/danoeh/antennapod/core/cast/CastConsumer.java index 213dd1875..213dd1875 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/cast/CastConsumer.java +++ b/core/src/play/java/de/danoeh/antennapod/core/cast/CastConsumer.java diff --git a/core/src/main/java/de/danoeh/antennapod/core/cast/CastManager.java b/core/src/play/java/de/danoeh/antennapod/core/cast/CastManager.java index 5b1fdab61..27fb7344d 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/cast/CastManager.java +++ b/core/src/play/java/de/danoeh/antennapod/core/cast/CastManager.java @@ -24,6 +24,8 @@ package de.danoeh.antennapod.core.cast; import android.content.Context; import android.os.Build; +import android.support.annotation.NonNull; +import android.support.v4.view.ActionProvider; import android.support.v4.view.MenuItemCompat; import android.support.v7.media.MediaRouter; import android.util.Log; @@ -60,6 +62,7 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.TimeUnit; +import de.danoeh.antennapod.core.ClientConfig; import de.danoeh.antennapod.core.R; import static com.google.android.gms.cast.RemoteMediaPlayer.RESUME_STATE_PLAY; @@ -128,18 +131,17 @@ public class CastManager extends BaseCastManager implements OnFailedListener { public static synchronized CastManager init(Context context) { if (INSTANCE == null) { - //TODO also setup dialog factory if necessary CastConfiguration castConfiguration = new CastConfiguration.Builder(CAST_APP_ID) .enableDebug() .enableAutoReconnect() .enableWifiReconnection() .setLaunchOptions(true, Locale.getDefault()) + .setMediaRouteDialogFactory(ClientConfig.castCallbacks.getMediaRouterDialogFactory()) .build(); Log.d(TAG, "New instance of CastManager is created"); if (ConnectionResult.SUCCESS != GoogleApiAvailability.getInstance() .isGooglePlayServicesAvailable(context)) { Log.e(TAG, "Couldn't find the appropriate version of Google Play Services"); - //TODO check whether creating an instance without google play services installed actually gives an exception } INSTANCE = new CastManager(context, castConfiguration); } @@ -1739,9 +1741,17 @@ public class CastManager extends BaseCastManager implements OnFailedListener { * * @param menuItem MenuItem of the Media Router cast button. */ - public final SwitchableMediaRouteActionProvider addMediaRouterButton(MenuItem menuItem) { - SwitchableMediaRouteActionProvider mediaRouteActionProvider = (SwitchableMediaRouteActionProvider) - MenuItemCompat.getActionProvider(menuItem); + public final SwitchableMediaRouteActionProvider addMediaRouterButton(@NonNull MenuItem menuItem) { + ActionProvider actionProvider = MenuItemCompat.getActionProvider(menuItem); + if (!(actionProvider instanceof SwitchableMediaRouteActionProvider)) { + Log.wtf(TAG, "MenuItem provided to addMediaRouterButton() is not compatible with " + + "SwitchableMediaRouteActionProvider." + + ((actionProvider == null) ? " Its action provider is null!" : ""), + new ClassCastException()); + return null; + } + SwitchableMediaRouteActionProvider mediaRouteActionProvider = + (SwitchableMediaRouteActionProvider) actionProvider; mediaRouteActionProvider.setRouteSelector(mMediaRouteSelector); if (mCastConfiguration.getMediaRouteDialogFactory() != null) { mediaRouteActionProvider.setDialogFactory(mCastConfiguration.getMediaRouteDialogFactory()); diff --git a/core/src/main/java/de/danoeh/antennapod/core/cast/CastUtils.java b/core/src/play/java/de/danoeh/antennapod/core/cast/CastUtils.java index 305f93e43..305f93e43 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/cast/CastUtils.java +++ b/core/src/play/java/de/danoeh/antennapod/core/cast/CastUtils.java diff --git a/core/src/main/java/de/danoeh/antennapod/core/cast/DefaultCastConsumer.java b/core/src/play/java/de/danoeh/antennapod/core/cast/DefaultCastConsumer.java index fe4183d54..fe4183d54 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/cast/DefaultCastConsumer.java +++ b/core/src/play/java/de/danoeh/antennapod/core/cast/DefaultCastConsumer.java diff --git a/core/src/main/java/de/danoeh/antennapod/core/cast/RemoteMedia.java b/core/src/play/java/de/danoeh/antennapod/core/cast/RemoteMedia.java index 99f7b9496..a3ac87062 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/cast/RemoteMedia.java +++ b/core/src/play/java/de/danoeh/antennapod/core/cast/RemoteMedia.java @@ -1,9 +1,11 @@ package de.danoeh.antennapod.core.cast; +import android.content.Context; import android.content.SharedPreferences; import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; +import android.support.annotation.Nullable; import android.text.TextUtils; import com.google.android.gms.cast.MediaInfo; @@ -24,6 +26,8 @@ import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.util.ChapterUtils; import de.danoeh.antennapod.core.util.playback.Playable; +import org.apache.commons.lang3.builder.HashCodeBuilder; + /** * Playable implementation for media on a Cast Device for which a local version of * {@link de.danoeh.antennapod.core.feed.FeedMedia} hasn't been found. @@ -252,7 +256,12 @@ public class RemoteMedia implements Playable { } @Override - public void onPlaybackCompleted() { + public void onPlaybackPause(Context context) { + // no-op + } + + @Override + public void onPlaybackCompleted(Context context) { // no-op } @@ -267,11 +276,9 @@ public class RemoteMedia implements Playable { } @Override - public Uri getImageUri() { - if (imageUrl != null) { - return Uri.parse(imageUrl); - } - return null; + @Nullable + public String getImageLocation() { + return imageUrl; } @Override @@ -344,4 +351,13 @@ public class RemoteMedia implements Playable { } return false; } + + @Override + public int hashCode() { + return new HashCodeBuilder() + .append(downloadUrl) + .append(feedUrl) + .append(itemIdentifier) + .toHashCode(); + } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/cast/SwitchableMediaRouteActionProvider.java b/core/src/play/java/de/danoeh/antennapod/core/cast/SwitchableMediaRouteActionProvider.java index f063cf5e3..f063cf5e3 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/cast/SwitchableMediaRouteActionProvider.java +++ b/core/src/play/java/de/danoeh/antennapod/core/cast/SwitchableMediaRouteActionProvider.java diff --git a/core/src/play/java/de/danoeh/antennapod/core/feed/FeedMediaFlavorHelper.java b/core/src/play/java/de/danoeh/antennapod/core/feed/FeedMediaFlavorHelper.java new file mode 100644 index 000000000..fe0f771d6 --- /dev/null +++ b/core/src/play/java/de/danoeh/antennapod/core/feed/FeedMediaFlavorHelper.java @@ -0,0 +1,13 @@ +package de.danoeh.antennapod.core.feed; + +import de.danoeh.antennapod.core.cast.RemoteMedia; + +/** + * Implements methods for FeedMedia that are flavor dependent. + */ +public class FeedMediaFlavorHelper { + private FeedMediaFlavorHelper(){} + static boolean instanceOfRemoteMedia(Object o) { + return o instanceof RemoteMedia; + } +} diff --git a/core/src/play/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceFlavorHelper.java b/core/src/play/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceFlavorHelper.java new file mode 100644 index 000000000..0cca2ffa4 --- /dev/null +++ b/core/src/play/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceFlavorHelper.java @@ -0,0 +1,279 @@ +package de.danoeh.antennapod.core.service.playback; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.net.NetworkInfo; +import android.net.wifi.WifiManager; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.StringRes; +import android.support.v4.media.session.MediaSessionCompat; +import android.support.v4.media.session.PlaybackStateCompat; +import android.support.v7.media.MediaRouter; +import android.support.wearable.media.MediaControlConstants; +import android.util.Log; +import android.widget.Toast; + +import com.google.android.gms.cast.ApplicationMetadata; +import com.google.android.libraries.cast.companionlibrary.cast.BaseCastManager; + +import java.util.concurrent.ExecutionException; + +import de.danoeh.antennapod.core.cast.CastConsumer; +import de.danoeh.antennapod.core.cast.CastManager; +import de.danoeh.antennapod.core.cast.DefaultCastConsumer; +import de.danoeh.antennapod.core.feed.MediaType; +import de.danoeh.antennapod.core.preferences.UserPreferences; +import de.danoeh.antennapod.core.util.NetworkUtils; + +/** + * Class intended to work along PlaybackService and provide support for different flavors. + */ +public class PlaybackServiceFlavorHelper { + public static final String TAG = "PlaybackSrvFlavorHelper"; + + /** + * Time in seconds during which the CastManager will try to reconnect to the Cast Device after + * the Wifi Connection is regained. + */ + private static final int RECONNECTION_ATTEMPT_PERIOD_S = 15; + /** + * Stores the state of the cast playback just before it disconnects. + */ + private volatile PlaybackServiceMediaPlayer.PSMPInfo infoBeforeCastDisconnection; + + private boolean wifiConnectivity = true; + private BroadcastReceiver wifiBroadcastReceiver; + + private CastManager castManager; + private MediaRouter mediaRouter; + private PlaybackService.FlavorHelperCallback callback; + private CastConsumer castConsumer; + + PlaybackServiceFlavorHelper(Context context, PlaybackService.FlavorHelperCallback callback) { + this.callback = callback; + mediaRouter = MediaRouter.getInstance(context.getApplicationContext()); + setCastConsumer(context); + } + + void initializeMediaPlayer(Context context) { + castManager = CastManager.getInstance(); + castManager.addCastConsumer(castConsumer); + boolean isCasting = castManager.isConnected(); + callback.setIsCasting(isCasting); + if (isCasting) { + if (UserPreferences.isCastEnabled()) { + onCastAppConnected(context, false); + } else { + castManager.disconnect(); + } + } else { + callback.setMediaPlayer(new LocalPSMP(context, callback.getMediaPlayerCallback())); + } + } + + void removeCastConsumer() { + castManager.removeCastConsumer(castConsumer); + } + + boolean castDisconnect(boolean castDisconnect) { + if (castDisconnect) { + castManager.disconnect(); + } + return castDisconnect; + } + + boolean onMediaPlayerInfo(Context context, int code, @StringRes int resourceId) { + switch (code) { + case RemotePSMP.CAST_ERROR: + callback.sendNotificationBroadcast(PlaybackService.NOTIFICATION_TYPE_SHOW_TOAST, resourceId); + return true; + case RemotePSMP.CAST_ERROR_PRIORITY_HIGH: + Toast.makeText(context, resourceId, Toast.LENGTH_SHORT).show(); + return true; + default: + return false; + } + } + + private void setCastConsumer(Context context) { + castConsumer = new DefaultCastConsumer() { + @Override + public void onApplicationConnected(ApplicationMetadata appMetadata, String sessionId, boolean wasLaunched) { + onCastAppConnected(context, wasLaunched); + } + + @Override + public void onDisconnectionReason(int reason) { + Log.d(TAG, "onDisconnectionReason() with code " + reason); + // This is our final chance to update the underlying stream position + // In onDisconnected(), the underlying CastPlayback#mVideoCastConsumer + // is disconnected and hence we update our local value of stream position + // to the latest position. + PlaybackServiceMediaPlayer mediaPlayer = callback.getMediaPlayer(); + if (mediaPlayer != null) { + callback.saveCurrentPosition(true, null, PlaybackServiceMediaPlayer.INVALID_TIME); + infoBeforeCastDisconnection = mediaPlayer.getPSMPInfo(); + if (reason != BaseCastManager.DISCONNECT_REASON_EXPLICIT && + infoBeforeCastDisconnection.playerStatus == PlayerStatus.PLAYING) { + // If it's NOT based on user action, we shouldn't automatically resume local playback + infoBeforeCastDisconnection.playerStatus = PlayerStatus.PAUSED; + } + } + } + + @Override + public void onDisconnected() { + Log.d(TAG, "onDisconnected()"); + callback.setIsCasting(false); + PlaybackServiceMediaPlayer.PSMPInfo info = infoBeforeCastDisconnection; + infoBeforeCastDisconnection = null; + PlaybackServiceMediaPlayer mediaPlayer = callback.getMediaPlayer(); + if (info == null && mediaPlayer != null) { + info = mediaPlayer.getPSMPInfo(); + } + if (info == null) { + info = new PlaybackServiceMediaPlayer.PSMPInfo(PlayerStatus.INDETERMINATE, + PlayerStatus.STOPPED, null); + } + switchMediaPlayer(new LocalPSMP(context, callback.getMediaPlayerCallback()), + info, true); + if (info.playable != null) { + callback.sendNotificationBroadcast(PlaybackService.NOTIFICATION_TYPE_RELOAD, + info.playable.getMediaType() == MediaType.AUDIO ? + PlaybackService.EXTRA_CODE_AUDIO : PlaybackService.EXTRA_CODE_VIDEO); + } else { + Log.d(TAG, "Cast session disconnected, but no current media"); + callback.sendNotificationBroadcast(PlaybackService.NOTIFICATION_TYPE_PLAYBACK_END, 0); + } + // hardware volume buttons control the local device volume + mediaRouter.setMediaSessionCompat(null); + unregisterWifiBroadcastReceiver(); + callback.setupNotification(false, info); + } + }; + } + + private void onCastAppConnected(Context context, boolean wasLaunched) { + Log.d(TAG, "A cast device application was " + (wasLaunched ? "launched" : "joined")); + callback.setIsCasting(true); + PlaybackServiceMediaPlayer.PSMPInfo info = null; + PlaybackServiceMediaPlayer mediaPlayer = callback.getMediaPlayer(); + if (mediaPlayer != null) { + info = mediaPlayer.getPSMPInfo(); + if (info.playerStatus == PlayerStatus.PLAYING) { + // could be pause, but this way we make sure the new player will get the correct position, + // since pause runs asynchronously and we could be directing the new player to play even before + // the old player gives us back the position. + callback.saveCurrentPosition(true, null, PlaybackServiceMediaPlayer.INVALID_TIME); + } + } + if (info == null) { + info = new PlaybackServiceMediaPlayer.PSMPInfo(PlayerStatus.INDETERMINATE, PlayerStatus.STOPPED, null); + } + callback.sendNotificationBroadcast(PlaybackService.NOTIFICATION_TYPE_RELOAD, + PlaybackService.EXTRA_CODE_CAST); + switchMediaPlayer(new RemotePSMP(context, callback.getMediaPlayerCallback()), + info, + wasLaunched); + // hardware volume buttons control the remote device volume + mediaRouter.setMediaSessionCompat(callback.getMediaSession()); + registerWifiBroadcastReceiver(); + callback.setupNotification(true, info); + } + + private void switchMediaPlayer(@NonNull PlaybackServiceMediaPlayer newPlayer, + @NonNull PlaybackServiceMediaPlayer.PSMPInfo info, + boolean wasLaunched) { + PlaybackServiceMediaPlayer mediaPlayer = callback.getMediaPlayer(); + if (mediaPlayer != null) { + try { + mediaPlayer.stopPlayback(false).get(); + } catch (InterruptedException | ExecutionException e) { + Log.e(TAG, "There was a problem stopping playback while switching media players", e); + } + mediaPlayer.shutdownQuietly(); + } + mediaPlayer = newPlayer; + callback.setMediaPlayer(mediaPlayer); + Log.d(TAG, "switched to " + mediaPlayer.getClass().getSimpleName()); + if (!wasLaunched) { + PlaybackServiceMediaPlayer.PSMPInfo candidate = mediaPlayer.getPSMPInfo(); + if (candidate.playable != null && + candidate.playerStatus.isAtLeast(PlayerStatus.PREPARING)) { + // do not automatically send new media to cast device + info.playable = null; + } + } + if (info.playable != null) { + mediaPlayer.playMediaObject(info.playable, + !info.playable.localFileAvailable(), + info.playerStatus == PlayerStatus.PLAYING, + info.playerStatus.isAtLeast(PlayerStatus.PREPARING)); + } + } + + void registerWifiBroadcastReceiver() { + if (wifiBroadcastReceiver != null) { + return; + } + wifiBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { + NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); + boolean isConnected = info.isConnected(); + //apparently this method gets called twice when a change happens, but one run is enough. + if (isConnected && !wifiConnectivity) { + wifiConnectivity = true; + castManager.startCastDiscovery(); + castManager.reconnectSessionIfPossible(RECONNECTION_ATTEMPT_PERIOD_S, NetworkUtils.getWifiSsid()); + } else { + wifiConnectivity = isConnected; + } + } + } + }; + callback.registerReceiver(wifiBroadcastReceiver, + new IntentFilter(WifiManager.NETWORK_STATE_CHANGED_ACTION)); + } + + void unregisterWifiBroadcastReceiver() { + if (wifiBroadcastReceiver != null) { + callback.unregisterReceiver(wifiBroadcastReceiver); + wifiBroadcastReceiver = null; + } + } + + boolean onSharedPreference(String key) { + if (UserPreferences.PREF_CAST_ENABLED.equals(key)) { + if (!UserPreferences.isCastEnabled()) { + if (castManager.isConnecting() || castManager.isConnected()) { + Log.d(TAG, "Disconnecting cast device due to a change in user preferences"); + castManager.disconnect(); + } + } + return true; + } + return false; + } + + void sessionStateAddActionForWear(PlaybackStateCompat.Builder sessionState, String actionName, CharSequence name, int icon) { + PlaybackStateCompat.CustomAction.Builder actionBuilder = + new PlaybackStateCompat.CustomAction.Builder(actionName, name, icon); + Bundle actionExtras = new Bundle(); + actionExtras.putBoolean(MediaControlConstants.EXTRA_CUSTOM_ACTION_SHOW_ON_WEAR, true); + actionBuilder.setExtras(actionExtras); + + sessionState.addCustomAction(actionBuilder.build()); + } + + void mediaSessionSetExtraForWear(MediaSessionCompat mediaSession) { + Bundle sessionExtras = new Bundle(); + sessionExtras.putBoolean(MediaControlConstants.EXTRA_RESERVE_SLOT_SKIP_TO_PREVIOUS, true); + sessionExtras.putBoolean(MediaControlConstants.EXTRA_RESERVE_SLOT_SKIP_TO_NEXT, true); + mediaSession.setExtras(sessionExtras); + } +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java b/core/src/play/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java index 4262b8a70..79e058d0c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java +++ b/core/src/play/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java @@ -15,6 +15,8 @@ import com.google.android.libraries.cast.companionlibrary.cast.exceptions.CastEx import com.google.android.libraries.cast.companionlibrary.cast.exceptions.NoConnectionException; import com.google.android.libraries.cast.companionlibrary.cast.exceptions.TransientNetworkDisconnectionException; +import java.util.concurrent.Future; +import java.util.concurrent.FutureTask; import java.util.concurrent.atomic.AtomicBoolean; import de.danoeh.antennapod.core.R; @@ -25,6 +27,7 @@ import de.danoeh.antennapod.core.cast.DefaultCastConsumer; import de.danoeh.antennapod.core.cast.RemoteMedia; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.MediaType; +import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.util.RewindAfterPauseUtils; import de.danoeh.antennapod.core.util.playback.Playable; @@ -42,8 +45,9 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer { private final CastManager castMgr; private volatile Playable media; - private volatile MediaInfo remoteMedia; private volatile MediaType mediaType; + private volatile MediaInfo remoteMedia; + private volatile int remoteState; private final AtomicBoolean isBuffering; @@ -57,31 +61,28 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer { mediaType = null; startWhenPrepared = new AtomicBoolean(false); isBuffering = new AtomicBoolean(false); + remoteState = MediaStatus.PLAYER_STATE_UNKNOWN; try { if (castMgr.isConnected() && castMgr.isRemoteMediaLoaded()) { - // updates the state, but does not start playing new media if it was going to - onRemoteMediaPlayerStatusUpdated( - ((p, playNextEpisode, wasSkipped, switchingPlayers) -> - this.callback.endPlayback(p, false, wasSkipped, switchingPlayers))); + onRemoteMediaPlayerStatusUpdated(); } } catch (TransientNetworkDisconnectionException | NoConnectionException e) { Log.e(TAG, "Unable to do initial check for loaded media", e); } castMgr.addCastConsumer(castConsumer); - //TODO } private CastConsumer castConsumer = new DefaultCastConsumer() { @Override public void onRemoteMediaPlayerMetadataUpdated() { - RemotePSMP.this.onRemoteMediaPlayerStatusUpdated(callback::endPlayback); + RemotePSMP.this.onRemoteMediaPlayerStatusUpdated(); } @Override public void onRemoteMediaPlayerStatusUpdated() { - RemotePSMP.this.onRemoteMediaPlayerStatusUpdated(callback::endPlayback); + RemotePSMP.this.onRemoteMediaPlayerStatusUpdated(); } @Override @@ -121,8 +122,9 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer { Log.d(TAG, "unable to get standbyState on onApplicationStatusChanged()"); } if (playbackEnded) { - setPlayerStatus(PlayerStatus.INDETERMINATE, media); - callback.endPlayback(media, true, false, false); + // This is an unconventional thing to occur... + Log.w(TAG, "Somehow, Chromecast went from playing directly to standby mode"); + endPlayback(false, false, true, true); } } @@ -166,85 +168,123 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer { return null; } - private void onRemoteMediaPlayerStatusUpdated(@NonNull EndPlaybackCall endPlaybackCall) { + private void onRemoteMediaPlayerStatusUpdated() { MediaStatus status = castMgr.getMediaStatus(); if (status == null) { Log.d(TAG, "Received null MediaStatus"); - //setBuffering(false); - //setPlayerStatus(PlayerStatus.INDETERMINATE, null); return; } else { Log.d(TAG, "Received remote status/media update. New state=" + status.getPlayerState()); } - Playable currentMedia = localVersion(status.getMediaInfo()); - boolean updateUI = currentMedia != media; - if (currentMedia != null) { - long position = status.getStreamPosition(); - if (position > 0 && currentMedia.getPosition() == 0) { - currentMedia.setPosition((int) position); - } - } int state = status.getPlayerState(); + int oldState = remoteState; + remoteMedia = status.getMediaInfo(); + boolean mediaChanged = !CastUtils.matches(remoteMedia, media); + boolean stateChanged = state != oldState; + if (!mediaChanged && !stateChanged) { + Log.d(TAG, "Both media and state haven't changed, so nothing to do"); + return; + } + Playable currentMedia = mediaChanged ? localVersion(remoteMedia) : media; + Playable oldMedia = media; + int position = (int) status.getStreamPosition(); + // check for incompatible states + if ((state == MediaStatus.PLAYER_STATE_PLAYING || state == MediaStatus.PLAYER_STATE_PAUSED) + && currentMedia == null) { + Log.w(TAG, "RemoteMediaPlayer returned playing or pausing state, but with no media"); + state = MediaStatus.PLAYER_STATE_UNKNOWN; + stateChanged = oldState != MediaStatus.PLAYER_STATE_UNKNOWN; + } + + if (stateChanged) { + remoteState = state; + } + + if (mediaChanged && stateChanged && oldState == MediaStatus.PLAYER_STATE_PLAYING && + state != MediaStatus.PLAYER_STATE_IDLE) { + callback.onPlaybackPause(null, INVALID_TIME); + // We don't want setPlayerStatus to handle the onPlaybackPause callback + setPlayerStatus(PlayerStatus.INDETERMINATE, currentMedia); + } + setBuffering(state == MediaStatus.PLAYER_STATE_BUFFERING); + switch (state) { case MediaStatus.PLAYER_STATE_PLAYING: - setPlayerStatus(PlayerStatus.PLAYING, currentMedia); + if (!stateChanged) { + //These steps are necessary because they won't be performed by setPlayerStatus() + if (position >= 0) { + currentMedia.setPosition(position); + } + currentMedia.onPlaybackStart(); + } + setPlayerStatus(PlayerStatus.PLAYING, currentMedia, position); break; case MediaStatus.PLAYER_STATE_PAUSED: - setPlayerStatus(PlayerStatus.PAUSED, currentMedia); + setPlayerStatus(PlayerStatus.PAUSED, currentMedia, position); break; case MediaStatus.PLAYER_STATE_BUFFERING: - setPlayerStatus(playerStatus, currentMedia); + setPlayerStatus((mediaChanged || playerStatus == PlayerStatus.PREPARING) ? + PlayerStatus.PREPARING : PlayerStatus.SEEKING, + currentMedia, + currentMedia != null ? currentMedia.getPosition() : INVALID_TIME); break; case MediaStatus.PLAYER_STATE_IDLE: int reason = status.getIdleReason(); switch (reason) { case MediaStatus.IDLE_REASON_CANCELED: - // check if we're already loading something else - if (!updateUI || media == null) { - setPlayerStatus(PlayerStatus.STOPPED, currentMedia); - } else { - updateUI = false; + // Essentially means stopped at the request of a user + callback.onPlaybackEnded(null, true); + setPlayerStatus(PlayerStatus.STOPPED, currentMedia); + if (oldMedia != null) { + if (position >= 0) { + oldMedia.setPosition(position); + } + callback.onPostPlayback(oldMedia, false, false, false); } - break; + // onPlaybackEnded pretty much takes care of updating the UI + return; case MediaStatus.IDLE_REASON_INTERRUPTED: - // check if we're already loading something else - if (!updateUI || media == null) { - setPlayerStatus(PlayerStatus.PREPARING, currentMedia); - } else { - updateUI = false; + // Means that a request to load a different media was sent + // Not sure if currentMedia already reflects the to be loaded one + if (mediaChanged && oldState == MediaStatus.PLAYER_STATE_PLAYING) { + callback.onPlaybackPause(null, INVALID_TIME); + setPlayerStatus(PlayerStatus.INDETERMINATE, currentMedia); } + setPlayerStatus(PlayerStatus.PREPARING, currentMedia); break; case MediaStatus.IDLE_REASON_NONE: + // This probably only happens when we connected but no command has been sent yet. setPlayerStatus(PlayerStatus.INITIALIZED, currentMedia); break; case MediaStatus.IDLE_REASON_FINISHED: - boolean playing = playerStatus == PlayerStatus.PLAYING; - setPlayerStatus(PlayerStatus.INDETERMINATE, currentMedia); - endPlaybackCall.endPlayback(currentMedia,playing, false, false); - // endPlayback already updates the UI, so no need to trigger it ourselves - updateUI = false; - break; + // This is our onCompletionListener... + if (mediaChanged && currentMedia != null) { + media = currentMedia; + } + endPlayback(true, false, true, true); + return; case MediaStatus.IDLE_REASON_ERROR: Log.w(TAG, "Got an error status from the Chromecast. Skipping, if possible, to the next episode..."); - setPlayerStatus(PlayerStatus.INDETERMINATE, currentMedia); callback.onMediaPlayerInfo(CAST_ERROR_PRIORITY_HIGH, R.string.cast_failed_media_error_skipping); - endPlaybackCall.endPlayback(currentMedia, startWhenPrepared.get(), true, false); - // endPlayback already updates the UI, so no need to trigger it ourselves - updateUI = false; + endPlayback(false, false, true, true); + return; } break; case MediaStatus.PLAYER_STATE_UNKNOWN: - //is this right? - setPlayerStatus(PlayerStatus.INDETERMINATE, currentMedia); + if (playerStatus != PlayerStatus.INDETERMINATE || media != currentMedia) { + setPlayerStatus(PlayerStatus.INDETERMINATE, currentMedia); + } break; default: - Log.e(TAG, "Remote media state undetermined!"); - setPlayerStatus(PlayerStatus.INDETERMINATE, currentMedia); + Log.wtf(TAG, "Remote media state undetermined!"); } - if (updateUI) { + if (mediaChanged) { callback.onMediaChanged(true); + if (oldMedia != null) { + callback.onPostPlayback(oldMedia, false, false, currentMedia != null); + } } } @@ -264,12 +304,13 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer { if (!CastUtils.isCastable(playable)) { Log.d(TAG, "media provided is not compatible with cast device"); callback.onMediaPlayerInfo(CAST_ERROR_PRIORITY_HIGH, R.string.cast_not_castable); - try { - playable.loadMetadata(); - } catch (Playable.PlayableException e) { - Log.e(TAG, "Unable to load metadata of playable", e); + Playable nextPlayable = playable; + do { + nextPlayable = callback.getNextInQueue(nextPlayable); + } while (nextPlayable != null && !CastUtils.isCastable(nextPlayable)); + if (nextPlayable != null) { + playMediaObject(nextPlayable, forceReset, stream, startWhenPrepared, prepareImmediately); } - callback.endPlayback(playable, startWhenPrepared, true, false); return; } @@ -281,19 +322,21 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer { return; } else { // set temporarily to pause in order to update list with current position + boolean isPlaying = playerStatus == PlayerStatus.PLAYING; + int position = media.getPosition(); try { - if (castMgr.isRemoteMediaPlaying()) { - setPlayerStatus(PlayerStatus.PAUSED, media); - } + isPlaying = castMgr.isRemoteMediaPlaying(); + position = (int) castMgr.getCurrentMediaPosition(); } catch (TransientNetworkDisconnectionException | NoConnectionException e) { Log.e(TAG, "Unable to determine whether media was playing, falling back to stored player status", e); - // this might end up just being pointless if we need to query the remote device for the position - if (playerStatus == PlayerStatus.PLAYING) { - setPlayerStatus(PlayerStatus.PAUSED, media); - } } - smartMarkAsPlayed(media); - + if (isPlaying) { + callback.onPlaybackPause(media, position); + } + if (!media.getIdentifier().equals(playable.getIdentifier())) { + final Playable oldMedia = media; + callback.onPostPlayback(oldMedia, false, false, true); + } setPlayerStatus(PlayerStatus.INDETERMINATE, null); } @@ -301,7 +344,6 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer { this.media = playable; remoteMedia = remoteVersion(playable); - //this.stream = stream; this.mediaType = media.getMediaType(); this.startWhenPrepared.set(startWhenPrepared); setPlayerStatus(PlayerStatus.INITIALIZING, media); @@ -328,8 +370,9 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer { media.getPosition(), media.getLastPlayedTime()); castMgr.play(newPosition); + } else { + castMgr.play(); } - castMgr.play(); } catch (CastException | TransientNetworkDisconnectionException | NoConnectionException e) { Log.e(TAG, "Unable to resume remote playback", e); } @@ -464,8 +507,8 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer { this.startWhenPrepared.set(startWhenPrepared); } - //TODO I believe some parts of the code make the same decision skipping this check, so that - //should be changed as well + // As things are right now, changing the return value of this function is not enough to ensure + // all other components recognize it. @Override public boolean canSetSpeed() { return false; @@ -557,23 +600,68 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer { } @Override - public void endPlayback(boolean wasSkipped, boolean switchingPlayers) { + protected Future<?> endPlayback(boolean hasEnded, boolean wasSkipped, boolean shouldContinue, + boolean toStoppedState) { Log.d(TAG, "endPlayback() called"); boolean isPlaying = playerStatus == PlayerStatus.PLAYING; - try { - isPlaying = castMgr.isRemoteMediaPlaying(); - } catch (TransientNetworkDisconnectionException | NoConnectionException e) { - Log.e(TAG, "Could not determine if media is playing", e); - } - // TODO make sure we stop playback whenever there's no next episode. if (playerStatus != PlayerStatus.INDETERMINATE) { setPlayerStatus(PlayerStatus.INDETERMINATE, media); } - callback.endPlayback(media, isPlaying, wasSkipped, switchingPlayers); + if (media != null && wasSkipped) { + // current position only really matters when we skip + int position = getPosition(); + if (position >= 0) { + media.setPosition(position); + } + } + final Playable currentMedia = media; + Playable nextMedia = null; + if (shouldContinue) { + nextMedia = callback.getNextInQueue(currentMedia); + + boolean playNextEpisode = isPlaying && nextMedia != null && UserPreferences.isFollowQueue(); + if (playNextEpisode) { + Log.d(TAG, "Playback of next episode will start immediately."); + } else if (nextMedia == null){ + Log.d(TAG, "No more episodes available to play"); + } else { + Log.d(TAG, "Loading next episode, but not playing automatically."); + } + + if (nextMedia != null) { + callback.onPlaybackEnded(nextMedia.getMediaType(), !playNextEpisode); + // setting media to null signals to playMediaObject() that we're taking care of post-playback processing + media = null; + playMediaObject(nextMedia, false, true /*TODO for now we always stream*/, playNextEpisode, playNextEpisode); + } + } + if (shouldContinue || toStoppedState) { + boolean shouldPostProcess = true; + if (nextMedia == null) { + try { + castMgr.stop(); + shouldPostProcess = false; + } catch (CastException | TransientNetworkDisconnectionException | NoConnectionException e) { + Log.e(TAG, "Unable to stop playback", e); + callback.onPlaybackEnded(null, true); + stop(); + } + } + if (shouldPostProcess) { + // Otherwise we rely on the chromecast callback to tell us the playback has stopped. + callback.onPostPlayback(currentMedia, hasEnded, wasSkipped, nextMedia != null); + } + } else if (isPlaying) { + callback.onPlaybackPause(currentMedia, + currentMedia != null ? currentMedia.getPosition() : INVALID_TIME); + } + + FutureTask<?> future = new FutureTask<>(() -> {}, null); + future.run(); + return future; } - @Override - public void stop() { + private void stop() { if (playerStatus == PlayerStatus.INDETERMINATE) { setPlayerStatus(PlayerStatus.STOPPED, null); } else { @@ -585,8 +673,4 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer { protected boolean shouldLockWifi() { return false; } - - private interface EndPlaybackCall { - boolean endPlayback(Playable media, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers); - } } diff --git a/core/src/play/res/values/strings.xml b/core/src/play/res/values/strings.xml new file mode 100644 index 000000000..4fd13d2de --- /dev/null +++ b/core/src/play/res/values/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="pref_cast_message">@string/pref_cast_message_play_flavor</string> +</resources> diff --git a/description/cs_CZ.txt b/description/cs_CZ.txt deleted file mode 100644 index b4955d18a..000000000 --- a/description/cs_CZ.txt +++ /dev/null @@ -1,42 +0,0 @@ -Easy-to-use, flexible and open-source podcast manager and player - -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> -But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -<b>All features:</b><br> -IMPORT, ORGANIZE AND PLAY<br> -• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> -• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> -• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> -• Access password-protected feeds and episodes<br> -• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE<br> -• Keep track of the best of the best by marking episodes as favourites<br> -• Find that one episode through the playback history or by searching (titles and shownotes)<br> -• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> -• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM<br> -• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> -• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> -• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> -• Adapt to your environment using the light and dark theme<br> -• Back-up your subscriptions with the gPodder.net integration and OPML export - -<b>Join the AntennaPod community!</b><br> -AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:<br> -https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> -https://groups.google.com/forum/#!forum/antennapod - -Transifex is the place to help with translations:<br> -https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:<br> -https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/description/da.txt b/description/da.txt deleted file mode 100644 index b4955d18a..000000000 --- a/description/da.txt +++ /dev/null @@ -1,42 +0,0 @@ -Easy-to-use, flexible and open-source podcast manager and player - -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> -But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -<b>All features:</b><br> -IMPORT, ORGANIZE AND PLAY<br> -• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> -• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> -• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> -• Access password-protected feeds and episodes<br> -• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE<br> -• Keep track of the best of the best by marking episodes as favourites<br> -• Find that one episode through the playback history or by searching (titles and shownotes)<br> -• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> -• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM<br> -• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> -• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> -• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> -• Adapt to your environment using the light and dark theme<br> -• Back-up your subscriptions with the gPodder.net integration and OPML export - -<b>Join the AntennaPod community!</b><br> -AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:<br> -https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> -https://groups.google.com/forum/#!forum/antennapod - -Transifex is the place to help with translations:<br> -https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:<br> -https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/description/el.txt b/description/el.txt deleted file mode 100644 index b4955d18a..000000000 --- a/description/el.txt +++ /dev/null @@ -1,42 +0,0 @@ -Easy-to-use, flexible and open-source podcast manager and player - -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> -But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -<b>All features:</b><br> -IMPORT, ORGANIZE AND PLAY<br> -• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> -• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> -• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> -• Access password-protected feeds and episodes<br> -• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE<br> -• Keep track of the best of the best by marking episodes as favourites<br> -• Find that one episode through the playback history or by searching (titles and shownotes)<br> -• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> -• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM<br> -• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> -• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> -• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> -• Adapt to your environment using the light and dark theme<br> -• Back-up your subscriptions with the gPodder.net integration and OPML export - -<b>Join the AntennaPod community!</b><br> -AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:<br> -https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> -https://groups.google.com/forum/#!forum/antennapod - -Transifex is the place to help with translations:<br> -https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:<br> -https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/description/en.txt b/description/en.txt deleted file mode 100755 index 74b864455..000000000 --- a/description/en.txt +++ /dev/null @@ -1,45 +0,0 @@ -Easy-to-use, flexible and open-source podcast manager and player - -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (episode filtering, specify times, intervals and WiFi networks) and deleting episodes (based your favorites and delay settings).<br> -But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -<b>All features:</b><br> -IMPORT, ORGANIZE AND PLAY<br> -• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> -• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> -• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> -• Access password-protected feeds and episodes<br> -• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE<br> -• Keep track of the best of the best by marking episodes as favorites<br> -• Find that one episode through the playback history or by searching (titles and shownotes)<br> -• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> -• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM<br> -• Take control over automated downloading: choose feeds, filter episodes based on keywords, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> -• Manage storage by setting the amount of cached episodes, smart deletion (based on your favorites and play status) and selecting your preferred location<br> -• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> -• Adapt to your environment using the light and dark theme<br> -• Back-up your subscriptions with the gPodder.net integration and OPML export - -<b>Join the AntennaPod community!</b> -AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -Ask your question or give feedback via Twitter: -https://twitter.com/@AntennaPod - -Share your ideas, favorite podcasting moments and gratitude to all the volunteers in our Google group: -https://groups.google.com/forum/#!forum/antennapod - -Help translate the app to your mother tongue on Transifex: -https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first: -https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod - -Visit GitHub to submit feature requests, bug reports and code contributions: -https://www.github.com/AntennaPod/AntennaPod diff --git a/description/es_ES.txt b/description/es_ES.txt deleted file mode 100644 index b4955d18a..000000000 --- a/description/es_ES.txt +++ /dev/null @@ -1,42 +0,0 @@ -Easy-to-use, flexible and open-source podcast manager and player - -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> -But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -<b>All features:</b><br> -IMPORT, ORGANIZE AND PLAY<br> -• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> -• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> -• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> -• Access password-protected feeds and episodes<br> -• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE<br> -• Keep track of the best of the best by marking episodes as favourites<br> -• Find that one episode through the playback history or by searching (titles and shownotes)<br> -• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> -• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM<br> -• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> -• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> -• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> -• Adapt to your environment using the light and dark theme<br> -• Back-up your subscriptions with the gPodder.net integration and OPML export - -<b>Join the AntennaPod community!</b><br> -AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:<br> -https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> -https://groups.google.com/forum/#!forum/antennapod - -Transifex is the place to help with translations:<br> -https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:<br> -https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/description/fi.txt b/description/fi.txt deleted file mode 100644 index b4955d18a..000000000 --- a/description/fi.txt +++ /dev/null @@ -1,42 +0,0 @@ -Easy-to-use, flexible and open-source podcast manager and player - -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> -But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -<b>All features:</b><br> -IMPORT, ORGANIZE AND PLAY<br> -• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> -• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> -• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> -• Access password-protected feeds and episodes<br> -• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE<br> -• Keep track of the best of the best by marking episodes as favourites<br> -• Find that one episode through the playback history or by searching (titles and shownotes)<br> -• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> -• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM<br> -• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> -• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> -• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> -• Adapt to your environment using the light and dark theme<br> -• Back-up your subscriptions with the gPodder.net integration and OPML export - -<b>Join the AntennaPod community!</b><br> -AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:<br> -https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> -https://groups.google.com/forum/#!forum/antennapod - -Transifex is the place to help with translations:<br> -https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:<br> -https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/description/he_IL.txt b/description/he_IL.txt deleted file mode 100644 index b4955d18a..000000000 --- a/description/he_IL.txt +++ /dev/null @@ -1,42 +0,0 @@ -Easy-to-use, flexible and open-source podcast manager and player - -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> -But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -<b>All features:</b><br> -IMPORT, ORGANIZE AND PLAY<br> -• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> -• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> -• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> -• Access password-protected feeds and episodes<br> -• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE<br> -• Keep track of the best of the best by marking episodes as favourites<br> -• Find that one episode through the playback history or by searching (titles and shownotes)<br> -• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> -• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM<br> -• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> -• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> -• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> -• Adapt to your environment using the light and dark theme<br> -• Back-up your subscriptions with the gPodder.net integration and OPML export - -<b>Join the AntennaPod community!</b><br> -AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:<br> -https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> -https://groups.google.com/forum/#!forum/antennapod - -Transifex is the place to help with translations:<br> -https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:<br> -https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/description/hi_IN.txt b/description/hi_IN.txt deleted file mode 100644 index b4955d18a..000000000 --- a/description/hi_IN.txt +++ /dev/null @@ -1,42 +0,0 @@ -Easy-to-use, flexible and open-source podcast manager and player - -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> -But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -<b>All features:</b><br> -IMPORT, ORGANIZE AND PLAY<br> -• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> -• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> -• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> -• Access password-protected feeds and episodes<br> -• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE<br> -• Keep track of the best of the best by marking episodes as favourites<br> -• Find that one episode through the playback history or by searching (titles and shownotes)<br> -• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> -• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM<br> -• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> -• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> -• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> -• Adapt to your environment using the light and dark theme<br> -• Back-up your subscriptions with the gPodder.net integration and OPML export - -<b>Join the AntennaPod community!</b><br> -AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:<br> -https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> -https://groups.google.com/forum/#!forum/antennapod - -Transifex is the place to help with translations:<br> -https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:<br> -https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/description/hu.txt b/description/hu.txt deleted file mode 100644 index b4955d18a..000000000 --- a/description/hu.txt +++ /dev/null @@ -1,42 +0,0 @@ -Easy-to-use, flexible and open-source podcast manager and player - -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> -But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -<b>All features:</b><br> -IMPORT, ORGANIZE AND PLAY<br> -• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> -• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> -• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> -• Access password-protected feeds and episodes<br> -• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE<br> -• Keep track of the best of the best by marking episodes as favourites<br> -• Find that one episode through the playback history or by searching (titles and shownotes)<br> -• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> -• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM<br> -• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> -• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> -• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> -• Adapt to your environment using the light and dark theme<br> -• Back-up your subscriptions with the gPodder.net integration and OPML export - -<b>Join the AntennaPod community!</b><br> -AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:<br> -https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> -https://groups.google.com/forum/#!forum/antennapod - -Transifex is the place to help with translations:<br> -https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:<br> -https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/description/id.txt b/description/id.txt deleted file mode 100644 index b4955d18a..000000000 --- a/description/id.txt +++ /dev/null @@ -1,42 +0,0 @@ -Easy-to-use, flexible and open-source podcast manager and player - -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> -But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -<b>All features:</b><br> -IMPORT, ORGANIZE AND PLAY<br> -• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> -• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> -• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> -• Access password-protected feeds and episodes<br> -• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE<br> -• Keep track of the best of the best by marking episodes as favourites<br> -• Find that one episode through the playback history or by searching (titles and shownotes)<br> -• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> -• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM<br> -• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> -• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> -• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> -• Adapt to your environment using the light and dark theme<br> -• Back-up your subscriptions with the gPodder.net integration and OPML export - -<b>Join the AntennaPod community!</b><br> -AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:<br> -https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> -https://groups.google.com/forum/#!forum/antennapod - -Transifex is the place to help with translations:<br> -https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:<br> -https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/description/kn_IN.txt b/description/kn_IN.txt deleted file mode 100644 index b4955d18a..000000000 --- a/description/kn_IN.txt +++ /dev/null @@ -1,42 +0,0 @@ -Easy-to-use, flexible and open-source podcast manager and player - -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> -But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -<b>All features:</b><br> -IMPORT, ORGANIZE AND PLAY<br> -• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> -• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> -• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> -• Access password-protected feeds and episodes<br> -• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE<br> -• Keep track of the best of the best by marking episodes as favourites<br> -• Find that one episode through the playback history or by searching (titles and shownotes)<br> -• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> -• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM<br> -• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> -• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> -• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> -• Adapt to your environment using the light and dark theme<br> -• Back-up your subscriptions with the gPodder.net integration and OPML export - -<b>Join the AntennaPod community!</b><br> -AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:<br> -https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> -https://groups.google.com/forum/#!forum/antennapod - -Transifex is the place to help with translations:<br> -https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:<br> -https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/description/ko_KR.txt b/description/ko_KR.txt deleted file mode 100644 index b4955d18a..000000000 --- a/description/ko_KR.txt +++ /dev/null @@ -1,42 +0,0 @@ -Easy-to-use, flexible and open-source podcast manager and player - -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> -But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -<b>All features:</b><br> -IMPORT, ORGANIZE AND PLAY<br> -• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> -• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> -• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> -• Access password-protected feeds and episodes<br> -• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE<br> -• Keep track of the best of the best by marking episodes as favourites<br> -• Find that one episode through the playback history or by searching (titles and shownotes)<br> -• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> -• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM<br> -• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> -• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> -• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> -• Adapt to your environment using the light and dark theme<br> -• Back-up your subscriptions with the gPodder.net integration and OPML export - -<b>Join the AntennaPod community!</b><br> -AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:<br> -https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> -https://groups.google.com/forum/#!forum/antennapod - -Transifex is the place to help with translations:<br> -https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:<br> -https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/description/nb.txt b/description/nb.txt deleted file mode 100644 index b4955d18a..000000000 --- a/description/nb.txt +++ /dev/null @@ -1,42 +0,0 @@ -Easy-to-use, flexible and open-source podcast manager and player - -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> -But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -<b>All features:</b><br> -IMPORT, ORGANIZE AND PLAY<br> -• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> -• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> -• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> -• Access password-protected feeds and episodes<br> -• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE<br> -• Keep track of the best of the best by marking episodes as favourites<br> -• Find that one episode through the playback history or by searching (titles and shownotes)<br> -• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> -• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM<br> -• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> -• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> -• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> -• Adapt to your environment using the light and dark theme<br> -• Back-up your subscriptions with the gPodder.net integration and OPML export - -<b>Join the AntennaPod community!</b><br> -AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:<br> -https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> -https://groups.google.com/forum/#!forum/antennapod - -Transifex is the place to help with translations:<br> -https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:<br> -https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/description/nl.txt b/description/nl.txt deleted file mode 100644 index 926a7a70f..000000000 --- a/description/nl.txt +++ /dev/null @@ -1,42 +0,0 @@ -Gemakkelijk te gebruiken, flexibele en open-source podcast manager en speler - -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> -But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -<b>All features:</b><br> -IMPORT, ORGANIZE AND PLAY<br> -• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> -• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> -• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> -• Access password-protected feeds and episodes<br> -• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE<br> -• Keep track of the best of the best by marking episodes as favourites<br> -• Find that one episode through the playback history or by searching (titles and shownotes)<br> -• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> -• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM<br> -• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> -• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> -• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> -• Adapt to your environment using the light and dark theme<br> -• Back-up your subscriptions with the gPodder.net integration and OPML export - -<b>Join the AntennaPod community!</b><br> -AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:<br> -https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> -https://groups.google.com/forum/#!forum/antennapod - -Transifex is the place to help with translations:<br> -https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:<br> -https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/description/no.txt b/description/no.txt deleted file mode 100644 index b4955d18a..000000000 --- a/description/no.txt +++ /dev/null @@ -1,42 +0,0 @@ -Easy-to-use, flexible and open-source podcast manager and player - -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> -But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -<b>All features:</b><br> -IMPORT, ORGANIZE AND PLAY<br> -• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> -• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> -• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> -• Access password-protected feeds and episodes<br> -• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE<br> -• Keep track of the best of the best by marking episodes as favourites<br> -• Find that one episode through the playback history or by searching (titles and shownotes)<br> -• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> -• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM<br> -• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> -• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> -• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> -• Adapt to your environment using the light and dark theme<br> -• Back-up your subscriptions with the gPodder.net integration and OPML export - -<b>Join the AntennaPod community!</b><br> -AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:<br> -https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> -https://groups.google.com/forum/#!forum/antennapod - -Transifex is the place to help with translations:<br> -https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:<br> -https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/description/pl.txt b/description/pl.txt deleted file mode 100644 index b4955d18a..000000000 --- a/description/pl.txt +++ /dev/null @@ -1,42 +0,0 @@ -Easy-to-use, flexible and open-source podcast manager and player - -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> -But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -<b>All features:</b><br> -IMPORT, ORGANIZE AND PLAY<br> -• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> -• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> -• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> -• Access password-protected feeds and episodes<br> -• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE<br> -• Keep track of the best of the best by marking episodes as favourites<br> -• Find that one episode through the playback history or by searching (titles and shownotes)<br> -• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> -• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM<br> -• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> -• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> -• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> -• Adapt to your environment using the light and dark theme<br> -• Back-up your subscriptions with the gPodder.net integration and OPML export - -<b>Join the AntennaPod community!</b><br> -AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:<br> -https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> -https://groups.google.com/forum/#!forum/antennapod - -Transifex is the place to help with translations:<br> -https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:<br> -https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/description/pl_PL.txt b/description/pl_PL.txt deleted file mode 100644 index b4955d18a..000000000 --- a/description/pl_PL.txt +++ /dev/null @@ -1,42 +0,0 @@ -Easy-to-use, flexible and open-source podcast manager and player - -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> -But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -<b>All features:</b><br> -IMPORT, ORGANIZE AND PLAY<br> -• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> -• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> -• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> -• Access password-protected feeds and episodes<br> -• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE<br> -• Keep track of the best of the best by marking episodes as favourites<br> -• Find that one episode through the playback history or by searching (titles and shownotes)<br> -• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> -• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM<br> -• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> -• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> -• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> -• Adapt to your environment using the light and dark theme<br> -• Back-up your subscriptions with the gPodder.net integration and OPML export - -<b>Join the AntennaPod community!</b><br> -AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:<br> -https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> -https://groups.google.com/forum/#!forum/antennapod - -Transifex is the place to help with translations:<br> -https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:<br> -https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/description/pt_BR.txt b/description/pt_BR.txt deleted file mode 100644 index b4955d18a..000000000 --- a/description/pt_BR.txt +++ /dev/null @@ -1,42 +0,0 @@ -Easy-to-use, flexible and open-source podcast manager and player - -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> -But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -<b>All features:</b><br> -IMPORT, ORGANIZE AND PLAY<br> -• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> -• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> -• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> -• Access password-protected feeds and episodes<br> -• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE<br> -• Keep track of the best of the best by marking episodes as favourites<br> -• Find that one episode through the playback history or by searching (titles and shownotes)<br> -• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> -• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM<br> -• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> -• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> -• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> -• Adapt to your environment using the light and dark theme<br> -• Back-up your subscriptions with the gPodder.net integration and OPML export - -<b>Join the AntennaPod community!</b><br> -AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:<br> -https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> -https://groups.google.com/forum/#!forum/antennapod - -Transifex is the place to help with translations:<br> -https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:<br> -https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/description/ro_RO.txt b/description/ro_RO.txt deleted file mode 100644 index b4955d18a..000000000 --- a/description/ro_RO.txt +++ /dev/null @@ -1,42 +0,0 @@ -Easy-to-use, flexible and open-source podcast manager and player - -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> -But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -<b>All features:</b><br> -IMPORT, ORGANIZE AND PLAY<br> -• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> -• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> -• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> -• Access password-protected feeds and episodes<br> -• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE<br> -• Keep track of the best of the best by marking episodes as favourites<br> -• Find that one episode through the playback history or by searching (titles and shownotes)<br> -• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> -• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM<br> -• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> -• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> -• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> -• Adapt to your environment using the light and dark theme<br> -• Back-up your subscriptions with the gPodder.net integration and OPML export - -<b>Join the AntennaPod community!</b><br> -AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:<br> -https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> -https://groups.google.com/forum/#!forum/antennapod - -Transifex is the place to help with translations:<br> -https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:<br> -https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/description/ru_RU.txt b/description/ru_RU.txt deleted file mode 100644 index b4955d18a..000000000 --- a/description/ru_RU.txt +++ /dev/null @@ -1,42 +0,0 @@ -Easy-to-use, flexible and open-source podcast manager and player - -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> -But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -<b>All features:</b><br> -IMPORT, ORGANIZE AND PLAY<br> -• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> -• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> -• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> -• Access password-protected feeds and episodes<br> -• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE<br> -• Keep track of the best of the best by marking episodes as favourites<br> -• Find that one episode through the playback history or by searching (titles and shownotes)<br> -• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> -• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM<br> -• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> -• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> -• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> -• Adapt to your environment using the light and dark theme<br> -• Back-up your subscriptions with the gPodder.net integration and OPML export - -<b>Join the AntennaPod community!</b><br> -AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:<br> -https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> -https://groups.google.com/forum/#!forum/antennapod - -Transifex is the place to help with translations:<br> -https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:<br> -https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/description/tr.txt b/description/tr.txt deleted file mode 100644 index b4955d18a..000000000 --- a/description/tr.txt +++ /dev/null @@ -1,42 +0,0 @@ -Easy-to-use, flexible and open-source podcast manager and player - -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> -But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -<b>All features:</b><br> -IMPORT, ORGANIZE AND PLAY<br> -• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> -• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> -• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> -• Access password-protected feeds and episodes<br> -• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE<br> -• Keep track of the best of the best by marking episodes as favourites<br> -• Find that one episode through the playback history or by searching (titles and shownotes)<br> -• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> -• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM<br> -• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> -• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> -• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> -• Adapt to your environment using the light and dark theme<br> -• Back-up your subscriptions with the gPodder.net integration and OPML export - -<b>Join the AntennaPod community!</b><br> -AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:<br> -https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> -https://groups.google.com/forum/#!forum/antennapod - -Transifex is the place to help with translations:<br> -https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:<br> -https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/description/vi.txt b/description/vi.txt deleted file mode 100644 index b4955d18a..000000000 --- a/description/vi.txt +++ /dev/null @@ -1,42 +0,0 @@ -Easy-to-use, flexible and open-source podcast manager and player - -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> -But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -<b>All features:</b><br> -IMPORT, ORGANIZE AND PLAY<br> -• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> -• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> -• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> -• Access password-protected feeds and episodes<br> -• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE<br> -• Keep track of the best of the best by marking episodes as favourites<br> -• Find that one episode through the playback history or by searching (titles and shownotes)<br> -• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> -• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM<br> -• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> -• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> -• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> -• Adapt to your environment using the light and dark theme<br> -• Back-up your subscriptions with the gPodder.net integration and OPML export - -<b>Join the AntennaPod community!</b><br> -AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:<br> -https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> -https://groups.google.com/forum/#!forum/antennapod - -Transifex is the place to help with translations:<br> -https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:<br> -https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/description/vi_VN.txt b/description/vi_VN.txt deleted file mode 100644 index b4955d18a..000000000 --- a/description/vi_VN.txt +++ /dev/null @@ -1,42 +0,0 @@ -Easy-to-use, flexible and open-source podcast manager and player - -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> -But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -<b>All features:</b><br> -IMPORT, ORGANIZE AND PLAY<br> -• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> -• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> -• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> -• Access password-protected feeds and episodes<br> -• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE<br> -• Keep track of the best of the best by marking episodes as favourites<br> -• Find that one episode through the playback history or by searching (titles and shownotes)<br> -• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> -• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM<br> -• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> -• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> -• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> -• Adapt to your environment using the light and dark theme<br> -• Back-up your subscriptions with the gPodder.net integration and OPML export - -<b>Join the AntennaPod community!</b><br> -AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:<br> -https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> -https://groups.google.com/forum/#!forum/antennapod - -Transifex is the place to help with translations:<br> -https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:<br> -https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/description/zh_CN.txt b/description/zh_CN.txt deleted file mode 100644 index b4955d18a..000000000 --- a/description/zh_CN.txt +++ /dev/null @@ -1,42 +0,0 @@ -Easy-to-use, flexible and open-source podcast manager and player - -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br> -But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -<b>All features:</b><br> -IMPORT, ORGANIZE AND PLAY<br> -• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br> -• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br> -• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br> -• Access password-protected feeds and episodes<br> -• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE<br> -• Keep track of the best of the best by marking episodes as favourites<br> -• Find that one episode through the playback history or by searching (titles and shownotes)<br> -• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br> -• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM<br> -• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br> -• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br> -• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br> -• Adapt to your environment using the light and dark theme<br> -• Back-up your subscriptions with the gPodder.net integration and OPML export - -<b>Join the AntennaPod community!</b><br> -AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:<br> -https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br> -https://groups.google.com/forum/#!forum/antennapod - -Transifex is the place to help with translations:<br> -https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:<br> -https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
\ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar Binary files differindex 5ccda13e9..736fb7d3f 100644 --- a/gradle/wrapper/gradle-wrapper.jar +++ b/gradle/wrapper/gradle-wrapper.jar diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2cf959511..52dd1f044 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Sat Feb 13 13:14:00 CET 2016 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.11-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.2-bin.zip @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh ############################################################################## ## @@ -6,20 +6,38 @@ ## ############################################################################## -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" -warn ( ) { +warn () { echo "$*" } -die ( ) { +die () { echo echo "$*" echo @@ -30,6 +48,7 @@ die ( ) { cygwin=false msys=false darwin=false +nonstop=false case "`uname`" in CYGWIN* ) cygwin=true @@ -40,26 +59,11 @@ case "`uname`" in MINGW* ) msys=true ;; + NONSTOP* ) + nonstop=true + ;; esac -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -85,7 +89,7 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then @@ -150,11 +154,19 @@ if $cygwin ; then esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " } -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 5f192121e..e95643d6a 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,90 +1,84 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/makeRelease.sh b/makeRelease.sh index cca75f7c2..c3b684ec0 100755 --- a/makeRelease.sh +++ b/makeRelease.sh @@ -1,4 +1,10 @@ #!/bin/sh + +if [ "$#" -ne 2 ]; then + echo "Usage:\n ./makeRelease 1.2.3rc0 Directory/" + exit 1 +fi + set -e DEST=$2 VERSION_NAME=$1 @@ -6,6 +12,6 @@ VERSION_NAME=$1 # need to get rid of this so that it gets regenerated # probably a way to solve this in Gradle too... rm -f app/src/main/assets/about.html -./gradlew clean assembleDebug assembleRelease -cp app/build/outputs/apk/app-debug.apk $DEST/AntennaPod_${VERSION_NAME}_debug.apk -cp app/build/outputs/apk/app-release.apk $DEST/AntennaPod_${VERSION_NAME}_release.apk +./gradlew clean assemblePlayDebug assemblePlayRelease +cp app/build/outputs/apk/app-play-debug.apk $DEST/AntennaPod_${VERSION_NAME}_debug.apk +cp app/build/outputs/apk/app-play-release.apk $DEST/AntennaPod_${VERSION_NAME}_release.apk |