From d2fe21b169e09ea94114ecfa880dec28aac45fe1 Mon Sep 17 00:00:00 2001 From: edde746 <86283021+edde746@users.noreply.github.com> Date: Sat, 5 Sep 2026 04:14:46 +0200 Subject: [PATCH] feat(player): per-marker skip modes with an Off option for intros and credits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Turning auto-skip off still surfaced a skip button on every intro and credits marker, so a viewer who wants to watch episodes in full had no way to silence it. The two auto-skip switches become per-marker selectors — Off, Show button, Automatic — stored as skip_intro_mode and skip_credits_mode. Off filters the marker before it becomes current, so the player behaves as if the server had sent none: no prompt, no countdown, no TV autofocus, and Back reaches the screen. Flipping a kind to Off while its prompt is up drops the prompt immediately. The legacy auto_skip_intro/auto_skip_credits booleans migrate on first read: true becomes Automatic, false becomes Show button, matching what each meant before. close #2138 --- lib/i18n/az.i18n.json | 15 +++-- lib/i18n/bg.i18n.json | 15 +++-- lib/i18n/da.i18n.json | 15 +++-- lib/i18n/de.i18n.json | 15 +++-- lib/i18n/en.i18n.json | 15 +++-- lib/i18n/es.i18n.json | 15 +++-- lib/i18n/fr.i18n.json | 15 +++-- lib/i18n/hu.i18n.json | 15 +++-- lib/i18n/it.i18n.json | 15 +++-- lib/i18n/ja.i18n.json | 15 +++-- lib/i18n/kk.i18n.json | 15 +++-- lib/i18n/ko.i18n.json | 15 +++-- lib/i18n/nb.i18n.json | 15 +++-- lib/i18n/nl.i18n.json | 15 +++-- lib/i18n/pl.i18n.json | 15 +++-- lib/i18n/pt.i18n.json | 15 +++-- lib/i18n/ru.i18n.json | 15 +++-- lib/i18n/strings.g.dart | 2 +- lib/i18n/strings_az.g.dart | 20 ++---- lib/i18n/strings_bg.g.dart | 20 ++---- lib/i18n/strings_da.g.dart | 20 ++---- lib/i18n/strings_de.g.dart | 20 ++---- lib/i18n/strings_en.g.dart | 64 +++++++++++++------ lib/i18n/strings_es.g.dart | 20 ++---- lib/i18n/strings_fr.g.dart | 20 ++---- lib/i18n/strings_hu.g.dart | 20 ++---- lib/i18n/strings_it.g.dart | 20 ++---- lib/i18n/strings_ja.g.dart | 20 ++---- lib/i18n/strings_kk.g.dart | 20 ++---- lib/i18n/strings_ko.g.dart | 20 ++---- lib/i18n/strings_nb.g.dart | 20 ++---- lib/i18n/strings_nl.g.dart | 20 ++---- lib/i18n/strings_pl.g.dart | 20 ++---- lib/i18n/strings_pt.g.dart | 20 ++---- lib/i18n/strings_ru.g.dart | 20 ++---- lib/i18n/strings_sv.g.dart | 20 ++---- lib/i18n/strings_tr.g.dart | 20 ++---- lib/i18n/strings_uz.g.dart | 20 ++---- lib/i18n/strings_zh.g.dart | 20 ++---- lib/i18n/strings_zh_Hant.g.dart | 20 ++---- lib/i18n/sv.i18n.json | 15 +++-- lib/i18n/tr.i18n.json | 15 +++-- lib/i18n/uz.i18n.json | 15 +++-- lib/i18n/zh-Hant.i18n.json | 15 +++-- lib/i18n/zh.i18n.json | 15 +++-- .../settings/playback_settings_screen.dart | 39 +++++++---- lib/services/settings_service.dart | 46 +++++++++++-- lib/widgets/video_controls/parts/markers.dart | 10 ++- .../video_controls/video_controls.dart | 14 ++-- test/services/settings_service_test.dart | 27 ++++++++ .../video_controls_select_key_test.dart | 41 +++++++++++- 51 files changed, 565 insertions(+), 428 deletions(-) diff --git a/lib/i18n/az.i18n.json b/lib/i18n/az.i18n.json index 5568b1183..1bd2e26b7 100644 --- a/lib/i18n/az.i18n.json +++ b/lib/i18n/az.i18n.json @@ -275,10 +275,17 @@ "autoPlayNextEpisodeDescription": "Bir seriya bitdikdə növbətisini avtomatik başlat", "playNextCountdown": "Növbəti seriya geri sayımı", "playNextCountdownImmediate": "Dərhal oynat", - "autoSkipIntro": "Girişi avtomatik ötür", - "autoSkipIntroDescription": "Bir neçə saniyədən sonra giriş işarələrini avtomatik ötür", - "autoSkipCredits": "Titrləri avtomatik ötür", - "autoSkipCreditsDescription": "Titrləri avtomatik ötür və növbəti seriyanı oynat", + "skipIntroMode": "", + "skipIntroModeOffDescription": "", + "skipIntroModeButtonDescription": "", + "skipIntroModeAutoDescription": "", + "skipCreditsMode": "", + "skipCreditsModeOffDescription": "", + "skipCreditsModeButtonDescription": "", + "skipCreditsModeAutoDescription": "", + "skipMarkerModeOff": "", + "skipMarkerModeButton": "", + "skipMarkerModeAuto": "", "forceSkipMarkerFallback": "Ehtiyat işarələri məcburi et", "forceSkipMarkerFallbackDescription": "Plex işarələri olsa belə hissə başlığı şablonlarını istifadə et", "autoSkipDelay": "Avtomatik ötürmə ləngiməsi", diff --git a/lib/i18n/bg.i18n.json b/lib/i18n/bg.i18n.json index 484cfbd2f..62ddf316a 100644 --- a/lib/i18n/bg.i18n.json +++ b/lib/i18n/bg.i18n.json @@ -275,10 +275,17 @@ "autoPlayNextEpisodeDescription": "Пускай следващия епизод автоматично, когато текущият свърши", "playNextCountdown": "Отброяване до следващия епизод", "playNextCountdownImmediate": "Пусни веднага", - "autoSkipIntro": "Автоматично прескачане на интро", - "autoSkipIntroDescription": "Автоматично прескачай интро маркери след няколко секунди", - "autoSkipCredits": "Автоматично прескачане на финални надписи", - "autoSkipCreditsDescription": "Автоматично прескачай финалните надписи и пускай следващия епизод", + "skipIntroMode": "", + "skipIntroModeOffDescription": "", + "skipIntroModeButtonDescription": "", + "skipIntroModeAutoDescription": "", + "skipCreditsMode": "", + "skipCreditsModeOffDescription": "", + "skipCreditsModeButtonDescription": "", + "skipCreditsModeAutoDescription": "", + "skipMarkerModeOff": "", + "skipMarkerModeButton": "", + "skipMarkerModeAuto": "", "forceSkipMarkerFallback": "Принуди резервни маркери", "forceSkipMarkerFallbackDescription": "Използвай шаблони в заглавията на главите дори когато Plex има маркери", "autoSkipDelay": "Забавяне за автоматично прескачане", diff --git a/lib/i18n/da.i18n.json b/lib/i18n/da.i18n.json index d9c0dc7cd..611fd8b29 100644 --- a/lib/i18n/da.i18n.json +++ b/lib/i18n/da.i18n.json @@ -275,10 +275,17 @@ "autoPlayNextEpisodeDescription": "Start automatisk næste afsnit, når et afsnit slutter", "playNextCountdown": "Nedtælling til næste afsnit", "playNextCountdownImmediate": "Afspil med det samme", - "autoSkipIntro": "Spring intro over automatisk", - "autoSkipIntroDescription": "Spring automatisk intromarkører over efter få sekunder", - "autoSkipCredits": "Spring rulletekster over automatisk", - "autoSkipCreditsDescription": "Spring automatisk rulleteksterne over, og afspil næste episode", + "skipIntroMode": "", + "skipIntroModeOffDescription": "", + "skipIntroModeButtonDescription": "", + "skipIntroModeAutoDescription": "", + "skipCreditsMode": "", + "skipCreditsModeOffDescription": "", + "skipCreditsModeButtonDescription": "", + "skipCreditsModeAutoDescription": "", + "skipMarkerModeOff": "", + "skipMarkerModeButton": "", + "skipMarkerModeAuto": "", "forceSkipMarkerFallback": "Tving reservemarkører", "forceSkipMarkerFallbackDescription": "Brug mønstre i kapiteltitler, selv når Plex har markører", "autoSkipDelay": "Forsinkelse ved automatisk spring", diff --git a/lib/i18n/de.i18n.json b/lib/i18n/de.i18n.json index 18f9f215c..37196072b 100644 --- a/lib/i18n/de.i18n.json +++ b/lib/i18n/de.i18n.json @@ -275,10 +275,17 @@ "autoPlayNextEpisodeDescription": "Die nächste Episode automatisch starten, wenn die aktuelle endet", "playNextCountdown": "Countdown bis zur nächsten Episode", "playNextCountdownImmediate": "Sofort abspielen", - "autoSkipIntro": "Intro automatisch überspringen", - "autoSkipIntroDescription": "Intro-Marker nach wenigen Sekunden automatisch überspringen", - "autoSkipCredits": "Abspann automatisch überspringen", - "autoSkipCreditsDescription": "Abspann automatisch überspringen und nächste Episode abspielen", + "skipIntroMode": "", + "skipIntroModeOffDescription": "", + "skipIntroModeButtonDescription": "", + "skipIntroModeAutoDescription": "", + "skipCreditsMode": "", + "skipCreditsModeOffDescription": "", + "skipCreditsModeButtonDescription": "", + "skipCreditsModeAutoDescription": "", + "skipMarkerModeOff": "", + "skipMarkerModeButton": "", + "skipMarkerModeAuto": "", "forceSkipMarkerFallback": "Ersatzmarkierungen erzwingen", "forceSkipMarkerFallbackDescription": "Kapitel-Titelmuster auch dann verwenden, wenn Plex über Markierungen verfügt", "autoSkipDelay": "Verzögerung für automatisches Überspringen", diff --git a/lib/i18n/en.i18n.json b/lib/i18n/en.i18n.json index fea814981..60bd9b1b6 100644 --- a/lib/i18n/en.i18n.json +++ b/lib/i18n/en.i18n.json @@ -275,10 +275,17 @@ "autoPlayNextEpisodeDescription": "Start the next episode automatically when one ends", "playNextCountdown": "Play Next Countdown", "playNextCountdownImmediate": "Play immediately", - "autoSkipIntro": "Auto Skip Intro", - "autoSkipIntroDescription": "Automatically skip intro markers after a few seconds", - "autoSkipCredits": "Auto Skip Credits", - "autoSkipCreditsDescription": "Automatically skip credits and play next episode", + "skipIntroMode": "Skip Intro", + "skipIntroModeOffDescription": "Play intros normally without a skip button", + "skipIntroModeButtonDescription": "Show a skip button when an intro starts", + "skipIntroModeAutoDescription": "Skip intros automatically after the delay below", + "skipCreditsMode": "Skip Credits", + "skipCreditsModeOffDescription": "Play credits normally without a skip button", + "skipCreditsModeButtonDescription": "Show a skip button when credits start", + "skipCreditsModeAutoDescription": "Skip credits automatically and play the next episode", + "skipMarkerModeOff": "Off", + "skipMarkerModeButton": "Show button", + "skipMarkerModeAuto": "Automatic", "forceSkipMarkerFallback": "Force Fallback Markers", "forceSkipMarkerFallbackDescription": "Use chapter title patterns even when Plex has markers", "autoSkipDelay": "Auto Skip Delay", diff --git a/lib/i18n/es.i18n.json b/lib/i18n/es.i18n.json index bdee754b0..ce27f2541 100644 --- a/lib/i18n/es.i18n.json +++ b/lib/i18n/es.i18n.json @@ -275,10 +275,17 @@ "autoPlayNextEpisodeDescription": "Iniciar automáticamente el siguiente episodio cuando termine el actual", "playNextCountdown": "Cuenta atrás para el siguiente episodio", "playNextCountdownImmediate": "Reproducir de inmediato", - "autoSkipIntro": "Saltar introducción automáticamente", - "autoSkipIntroDescription": "Saltar automáticamente los marcadores de introducción después de unos segundos", - "autoSkipCredits": "Saltar créditos automáticamente", - "autoSkipCreditsDescription": "Saltar automáticamente los créditos y reproducir el episodio siguiente", + "skipIntroMode": "", + "skipIntroModeOffDescription": "", + "skipIntroModeButtonDescription": "", + "skipIntroModeAutoDescription": "", + "skipCreditsMode": "", + "skipCreditsModeOffDescription": "", + "skipCreditsModeButtonDescription": "", + "skipCreditsModeAutoDescription": "", + "skipMarkerModeOff": "", + "skipMarkerModeButton": "", + "skipMarkerModeAuto": "", "forceSkipMarkerFallback": "Forzar marcadores alternativos", "forceSkipMarkerFallbackDescription": "Usar patrones de títulos de capítulos aunque Plex tenga marcadores", "autoSkipDelay": "Retraso del salto automático", diff --git a/lib/i18n/fr.i18n.json b/lib/i18n/fr.i18n.json index 4d13eed1e..3920e89d5 100644 --- a/lib/i18n/fr.i18n.json +++ b/lib/i18n/fr.i18n.json @@ -275,10 +275,17 @@ "autoPlayNextEpisodeDescription": "Lancer automatiquement l'épisode suivant lorsqu'un épisode se termine", "playNextCountdown": "Compte à rebours avant l'épisode suivant", "playNextCountdownImmediate": "Lire immédiatement", - "autoSkipIntro": "Passer automatiquement l’introduction", - "autoSkipIntroDescription": "Passer automatiquement les marqueurs d’introduction après quelques secondes", - "autoSkipCredits": "Passer automatiquement le générique", - "autoSkipCreditsDescription": "Passer automatiquement le générique et lire l’épisode suivant", + "skipIntroMode": "", + "skipIntroModeOffDescription": "", + "skipIntroModeButtonDescription": "", + "skipIntroModeAutoDescription": "", + "skipCreditsMode": "", + "skipCreditsModeOffDescription": "", + "skipCreditsModeButtonDescription": "", + "skipCreditsModeAutoDescription": "", + "skipMarkerModeOff": "", + "skipMarkerModeButton": "", + "skipMarkerModeAuto": "", "forceSkipMarkerFallback": "Forcer les marqueurs de secours", "forceSkipMarkerFallbackDescription": "Utiliser les motifs des titres de chapitre même lorsque Plex fournit des marqueurs", "autoSkipDelay": "Délai avant le saut automatique", diff --git a/lib/i18n/hu.i18n.json b/lib/i18n/hu.i18n.json index d14a10d61..d6ec6ef7e 100644 --- a/lib/i18n/hu.i18n.json +++ b/lib/i18n/hu.i18n.json @@ -275,10 +275,17 @@ "autoPlayNextEpisodeDescription": "A következő epizód automatikus elindítása, amikor az aktuális véget ér", "playNextCountdown": "Visszaszámlálás a következő epizódig", "playNextCountdownImmediate": "Azonnali lejátszás", - "autoSkipIntro": "Intró automatikus átugrása", - "autoSkipIntroDescription": "Az intrójelölők automatikus átugrása néhány másodperc után", - "autoSkipCredits": "Stáblista automatikus átugrása", - "autoSkipCreditsDescription": "A stáblista automatikus átugrása és a következő epizód lejátszása", + "skipIntroMode": "", + "skipIntroModeOffDescription": "", + "skipIntroModeButtonDescription": "", + "skipIntroModeAutoDescription": "", + "skipCreditsMode": "", + "skipCreditsModeOffDescription": "", + "skipCreditsModeButtonDescription": "", + "skipCreditsModeAutoDescription": "", + "skipMarkerModeOff": "", + "skipMarkerModeButton": "", + "skipMarkerModeAuto": "", "forceSkipMarkerFallback": "Tartalék jelölők kényszerítése", "forceSkipMarkerFallbackDescription": "Fejezetcím-minták használata akkor is, ha a Plex rendelkezik jelölőkkel", "autoSkipDelay": "Automatikus átugrás késleltetése", diff --git a/lib/i18n/it.i18n.json b/lib/i18n/it.i18n.json index 5596694ca..7861b449f 100644 --- a/lib/i18n/it.i18n.json +++ b/lib/i18n/it.i18n.json @@ -275,10 +275,17 @@ "autoPlayNextEpisodeDescription": "Avvia automaticamente l'episodio successivo quando termina quello in riproduzione", "playNextCountdown": "Conto alla rovescia del successivo", "playNextCountdownImmediate": "Riproduci subito", - "autoSkipIntro": "Salta automaticamente la sigla iniziale", - "autoSkipIntroDescription": "Salta automaticamente i marcatori della sigla iniziale dopo alcuni secondi", - "autoSkipCredits": "Salta automaticamente i titoli di coda", - "autoSkipCreditsDescription": "Salta automaticamente i titoli di coda e riproduce l'episodio successivo", + "skipIntroMode": "", + "skipIntroModeOffDescription": "", + "skipIntroModeButtonDescription": "", + "skipIntroModeAutoDescription": "", + "skipCreditsMode": "", + "skipCreditsModeOffDescription": "", + "skipCreditsModeButtonDescription": "", + "skipCreditsModeAutoDescription": "", + "skipMarkerModeOff": "", + "skipMarkerModeButton": "", + "skipMarkerModeAuto": "", "forceSkipMarkerFallback": "Forza i marcatori di ripiego", "forceSkipMarkerFallbackDescription": "Usa i modelli dei titoli dei capitoli anche quando Plex dispone di marcatori", "autoSkipDelay": "Ritardo del salto automatico", diff --git a/lib/i18n/ja.i18n.json b/lib/i18n/ja.i18n.json index 439d4f79f..3a581462c 100644 --- a/lib/i18n/ja.i18n.json +++ b/lib/i18n/ja.i18n.json @@ -275,10 +275,17 @@ "autoPlayNextEpisodeDescription": "エピソードが終了すると、次のエピソードを自動的に再生します", "playNextCountdown": "次回再生のカウントダウン", "playNextCountdownImmediate": "すぐに再生", - "autoSkipIntro": "イントロを自動スキップ", - "autoSkipIntroDescription": "数秒後にイントロマーカーを自動的にスキップ", - "autoSkipCredits": "クレジットを自動スキップ", - "autoSkipCreditsDescription": "クレジットを自動的にスキップして次のエピソードを再生", + "skipIntroMode": "", + "skipIntroModeOffDescription": "", + "skipIntroModeButtonDescription": "", + "skipIntroModeAutoDescription": "", + "skipCreditsMode": "", + "skipCreditsModeOffDescription": "", + "skipCreditsModeButtonDescription": "", + "skipCreditsModeAutoDescription": "", + "skipMarkerModeOff": "", + "skipMarkerModeButton": "", + "skipMarkerModeAuto": "", "forceSkipMarkerFallback": "フォールバックマーカーを強制", "forceSkipMarkerFallbackDescription": "Plexにマーカーがある場合でもチャプタータイトルのパターンを使用します", "autoSkipDelay": "自動スキップの遅延", diff --git a/lib/i18n/kk.i18n.json b/lib/i18n/kk.i18n.json index 02fed3989..2a5a637c9 100644 --- a/lib/i18n/kk.i18n.json +++ b/lib/i18n/kk.i18n.json @@ -275,10 +275,17 @@ "autoPlayNextEpisodeDescription": "Бір бөлім аяқталғанда келесі бөлімді автоматты түрде бастау", "playNextCountdown": "Келесіні ойнату санағы", "playNextCountdownImmediate": "Дереу ойнату", - "autoSkipIntro": "Киріс бөлімді (Intro) автоматты өткізу", - "autoSkipIntroDescription": "Бірнеше секундтан кейін киріс белгілерін автоматты өткізу", - "autoSkipCredits": "Титрлерді автоматты өткізу", - "autoSkipCreditsDescription": "Титрлерді автоматты өткізіп, келесі бөлімді ойнату", + "skipIntroMode": "", + "skipIntroModeOffDescription": "", + "skipIntroModeButtonDescription": "", + "skipIntroModeAutoDescription": "", + "skipCreditsMode": "", + "skipCreditsModeOffDescription": "", + "skipCreditsModeButtonDescription": "", + "skipCreditsModeAutoDescription": "", + "skipMarkerModeOff": "", + "skipMarkerModeButton": "", + "skipMarkerModeAuto": "", "forceSkipMarkerFallback": "Қосалқы белгілерді мәжбүрлеу", "forceSkipMarkerFallbackDescription": "Plex белгілері болса да бөлім тақырыбы үлгілерін пайдалану", "autoSkipDelay": "Автоматты өткізу кідірісі", diff --git a/lib/i18n/ko.i18n.json b/lib/i18n/ko.i18n.json index 312cf03ec..8bcaa7468 100644 --- a/lib/i18n/ko.i18n.json +++ b/lib/i18n/ko.i18n.json @@ -275,10 +275,17 @@ "autoPlayNextEpisodeDescription": "에피소드가 끝나면 다음 에피소드를 자동으로 재생", "playNextCountdown": "다음 재생 카운트다운", "playNextCountdownImmediate": "즉시 재생", - "autoSkipIntro": "자동으로 오프닝 건너뛰기", - "autoSkipIntroDescription": "몇 초 후 오프닝을 자동으로 건너뛰기", - "autoSkipCredits": "자동으로 엔딩 건너뛰기", - "autoSkipCreditsDescription": "엔딩 크레딧 자동 건너뛰기 후 다음 에피소드 재생", + "skipIntroMode": "", + "skipIntroModeOffDescription": "", + "skipIntroModeButtonDescription": "", + "skipIntroModeAutoDescription": "", + "skipCreditsMode": "", + "skipCreditsModeOffDescription": "", + "skipCreditsModeButtonDescription": "", + "skipCreditsModeAutoDescription": "", + "skipMarkerModeOff": "", + "skipMarkerModeButton": "", + "skipMarkerModeAuto": "", "forceSkipMarkerFallback": "대체 마커 강제 사용", "forceSkipMarkerFallbackDescription": "Plex에 마커가 있어도 챕터 제목 패턴 사용", "autoSkipDelay": "자동 건너뛰기 지연", diff --git a/lib/i18n/nb.i18n.json b/lib/i18n/nb.i18n.json index d32f11e13..c40e66a5d 100644 --- a/lib/i18n/nb.i18n.json +++ b/lib/i18n/nb.i18n.json @@ -275,10 +275,17 @@ "autoPlayNextEpisodeDescription": "Start neste episode automatisk når en episode er ferdig", "playNextCountdown": "Nedtelling for neste episode", "playNextCountdownImmediate": "Spill umiddelbart", - "autoSkipIntro": "Hopp over intro automatisk", - "autoSkipIntroDescription": "Hopp automatisk over intromarkører etter noen sekunder", - "autoSkipCredits": "Hopp over rulletekst automatisk", - "autoSkipCreditsDescription": "Hopp automatisk over rulletekst og spill neste episode", + "skipIntroMode": "", + "skipIntroModeOffDescription": "", + "skipIntroModeButtonDescription": "", + "skipIntroModeAutoDescription": "", + "skipCreditsMode": "", + "skipCreditsModeOffDescription": "", + "skipCreditsModeButtonDescription": "", + "skipCreditsModeAutoDescription": "", + "skipMarkerModeOff": "", + "skipMarkerModeButton": "", + "skipMarkerModeAuto": "", "forceSkipMarkerFallback": "Tving reservemarkører", "forceSkipMarkerFallbackDescription": "Bruk mønstre i kapiteltitler selv når Plex har markører", "autoSkipDelay": "Forsinkelse for automatisk hopp", diff --git a/lib/i18n/nl.i18n.json b/lib/i18n/nl.i18n.json index 3d5e6f742..1f13deb8f 100644 --- a/lib/i18n/nl.i18n.json +++ b/lib/i18n/nl.i18n.json @@ -275,10 +275,17 @@ "autoPlayNextEpisodeDescription": "Start de volgende aflevering automatisch wanneer een aflevering eindigt", "playNextCountdown": "Aftellen voor volgende aflevering", "playNextCountdownImmediate": "Direct afspelen", - "autoSkipIntro": "Intro automatisch overslaan", - "autoSkipIntroDescription": "Intromarkeringen na enkele seconden automatisch overslaan", - "autoSkipCredits": "Aftiteling automatisch overslaan", - "autoSkipCreditsDescription": "Aftiteling automatisch overslaan en de volgende aflevering afspelen", + "skipIntroMode": "", + "skipIntroModeOffDescription": "", + "skipIntroModeButtonDescription": "", + "skipIntroModeAutoDescription": "", + "skipCreditsMode": "", + "skipCreditsModeOffDescription": "", + "skipCreditsModeButtonDescription": "", + "skipCreditsModeAutoDescription": "", + "skipMarkerModeOff": "", + "skipMarkerModeButton": "", + "skipMarkerModeAuto": "", "forceSkipMarkerFallback": "Reservemarkeringen afdwingen", "forceSkipMarkerFallbackDescription": "Gebruik patronen in hoofdstuktitels, zelfs wanneer Plex markeringen heeft", "autoSkipDelay": "Vertraging voor automatisch overslaan", diff --git a/lib/i18n/pl.i18n.json b/lib/i18n/pl.i18n.json index 72d0cfead..a4533bc44 100644 --- a/lib/i18n/pl.i18n.json +++ b/lib/i18n/pl.i18n.json @@ -275,10 +275,17 @@ "autoPlayNextEpisodeDescription": "Automatycznie uruchamiaj następny odcinek, gdy bieżący się skończy", "playNextCountdown": "Odliczanie do następnego odcinka", "playNextCountdownImmediate": "Odtwarzaj natychmiast", - "autoSkipIntro": "Automatyczne pomijanie intro", - "autoSkipIntroDescription": "Automatycznie pomijaj znaczniki intro po kilku sekundach", - "autoSkipCredits": "Automatyczne pomijanie napisów końcowych", - "autoSkipCreditsDescription": "Automatycznie pomijaj napisy końcowe i odtwórz następny odcinek", + "skipIntroMode": "", + "skipIntroModeOffDescription": "", + "skipIntroModeButtonDescription": "", + "skipIntroModeAutoDescription": "", + "skipCreditsMode": "", + "skipCreditsModeOffDescription": "", + "skipCreditsModeButtonDescription": "", + "skipCreditsModeAutoDescription": "", + "skipMarkerModeOff": "", + "skipMarkerModeButton": "", + "skipMarkerModeAuto": "", "forceSkipMarkerFallback": "Wymuś znaczniki awaryjne", "forceSkipMarkerFallbackDescription": "Używaj wzorców tytułów rozdziałów, nawet gdy Plex ma znaczniki", "autoSkipDelay": "Opóźnienie automatycznego pomijania", diff --git a/lib/i18n/pt.i18n.json b/lib/i18n/pt.i18n.json index c0dd5c758..e88910162 100644 --- a/lib/i18n/pt.i18n.json +++ b/lib/i18n/pt.i18n.json @@ -275,10 +275,17 @@ "autoPlayNextEpisodeDescription": "Iniciar o próximo episódio automaticamente quando um terminar", "playNextCountdown": "Contagem regressiva do próximo episódio", "playNextCountdownImmediate": "Reproduzir imediatamente", - "autoSkipIntro": "Pular introdução automaticamente", - "autoSkipIntroDescription": "Pular marcadores de introdução automaticamente após alguns segundos", - "autoSkipCredits": "Pular créditos automaticamente", - "autoSkipCreditsDescription": "Pular os créditos automaticamente e reproduzir o próximo episódio", + "skipIntroMode": "", + "skipIntroModeOffDescription": "", + "skipIntroModeButtonDescription": "", + "skipIntroModeAutoDescription": "", + "skipCreditsMode": "", + "skipCreditsModeOffDescription": "", + "skipCreditsModeButtonDescription": "", + "skipCreditsModeAutoDescription": "", + "skipMarkerModeOff": "", + "skipMarkerModeButton": "", + "skipMarkerModeAuto": "", "forceSkipMarkerFallback": "Forçar marcadores alternativos", "forceSkipMarkerFallbackDescription": "Usar padrões de títulos de capítulos mesmo quando o Plex tiver marcadores", "autoSkipDelay": "Atraso para pular automaticamente", diff --git a/lib/i18n/ru.i18n.json b/lib/i18n/ru.i18n.json index 314898d77..7eeba3b01 100644 --- a/lib/i18n/ru.i18n.json +++ b/lib/i18n/ru.i18n.json @@ -275,10 +275,17 @@ "autoPlayNextEpisodeDescription": "Автоматически запускать следующий эпизод, когда заканчивается текущий", "playNextCountdown": "Обратный отсчёт перед следующим", "playNextCountdownImmediate": "Воспроизводить сразу", - "autoSkipIntro": "Автопропуск вступления", - "autoSkipIntroDescription": "Автоматически пропускать маркеры вступления через несколько секунд", - "autoSkipCredits": "Автопропуск титров", - "autoSkipCreditsDescription": "Автоматически пропускать титры и воспроизводить следующий эпизод", + "skipIntroMode": "", + "skipIntroModeOffDescription": "", + "skipIntroModeButtonDescription": "", + "skipIntroModeAutoDescription": "", + "skipCreditsMode": "", + "skipCreditsModeOffDescription": "", + "skipCreditsModeButtonDescription": "", + "skipCreditsModeAutoDescription": "", + "skipMarkerModeOff": "", + "skipMarkerModeButton": "", + "skipMarkerModeAuto": "", "forceSkipMarkerFallback": "Всегда использовать резервные маркеры", "forceSkipMarkerFallbackDescription": "Использовать шаблоны названий глав, даже если в Plex есть собственные маркеры", "autoSkipDelay": "Задержка автопропуска", diff --git a/lib/i18n/strings.g.dart b/lib/i18n/strings.g.dart index 1e32d7252..2010731f7 100644 --- a/lib/i18n/strings.g.dart +++ b/lib/i18n/strings.g.dart @@ -4,7 +4,7 @@ /// To regenerate, run: `dart run slang` /// /// Locales: 22 -/// Strings: 43758 (1989 per locale) +/// Strings: 43681 (1985 per locale) // coverage:ignore-file // ignore_for_file: type=lint, unused_import diff --git a/lib/i18n/strings_az.g.dart b/lib/i18n/strings_az.g.dart index 37da2315e..95b6ed775 100644 --- a/lib/i18n/strings_az.g.dart +++ b/lib/i18n/strings_az.g.dart @@ -380,10 +380,6 @@ class _Translations$settings$az extends Translations$settings$en { @override String get autoPlayNextEpisodeDescription => 'Bir seriya bitdikdə növbətisini avtomatik başlat'; @override String get playNextCountdown => 'Növbəti seriya geri sayımı'; @override String get playNextCountdownImmediate => 'Dərhal oynat'; - @override String get autoSkipIntro => 'Girişi avtomatik ötür'; - @override String get autoSkipIntroDescription => 'Bir neçə saniyədən sonra giriş işarələrini avtomatik ötür'; - @override String get autoSkipCredits => 'Titrləri avtomatik ötür'; - @override String get autoSkipCreditsDescription => 'Titrləri avtomatik ötür və növbəti seriyanı oynat'; @override String get forceSkipMarkerFallback => 'Ehtiyat işarələri məcburi et'; @override String get forceSkipMarkerFallbackDescription => 'Plex işarələri olsa belə hissə başlığı şablonlarını istifadə et'; @override String get autoSkipDelay => 'Avtomatik ötürmə ləngiməsi'; @@ -3194,10 +3190,6 @@ extension on TranslationsAz { 'settings.autoPlayNextEpisodeDescription' => 'Bir seriya bitdikdə növbətisini avtomatik başlat', 'settings.playNextCountdown' => 'Növbəti seriya geri sayımı', 'settings.playNextCountdownImmediate' => 'Dərhal oynat', - 'settings.autoSkipIntro' => 'Girişi avtomatik ötür', - 'settings.autoSkipIntroDescription' => 'Bir neçə saniyədən sonra giriş işarələrini avtomatik ötür', - 'settings.autoSkipCredits' => 'Titrləri avtomatik ötür', - 'settings.autoSkipCreditsDescription' => 'Titrləri avtomatik ötür və növbəti seriyanı oynat', 'settings.forceSkipMarkerFallback' => 'Ehtiyat işarələri məcburi et', 'settings.forceSkipMarkerFallbackDescription' => 'Plex işarələri olsa belə hissə başlığı şablonlarını istifadə et', 'settings.autoSkipDelay' => 'Avtomatik ötürmə ləngiməsi', @@ -3449,12 +3441,12 @@ extension on TranslationsAz { 'fileInfo.has64bitOffsets' => '64-bit ofsetlər', 'fileInfo.protocol' => 'Protokol', 'fileInfo.mediaType' => 'Media növü', - _ => null, - } ?? switch (path) { 'fileInfo.sourceKind' => 'Mənbə növü', 'fileInfo.optimizedVersion' => 'Optimallaşdırılmış versiya', 'fileInfo.optimizationTarget' => 'Optimallaşdırma hədəfi', 'fileInfo.deletedAt' => 'Silinib', + _ => null, + } ?? switch (path) { 'fileInfo.remoteSource' => 'Uzaq mənbə', 'fileInfo.infiniteStream' => 'Sonsuz axın', 'fileInfo.directPlay' => 'Birbaşa oynatma', @@ -3963,12 +3955,12 @@ extension on TranslationsAz { 'libraries.filterCategories.contentRating' => 'Məzmun reytinqi', 'libraries.filterCategories.tag' => 'Teq', 'libraries.filterCategories.unwatched' => 'Baxılmayıb', - _ => null, - } ?? switch (path) { 'libraries.filterCategories.unplayed' => 'Oynadılmayıb', 'libraries.filterCategories.favorites' => 'Sevimlilər', 'libraries.sortLabels.title' => 'Ad', 'libraries.sortLabels.dateAdded' => 'Əlavə olunma tarixi', + _ => null, + } ?? switch (path) { 'libraries.sortLabels.releaseDate' => 'Buraxılış tarixi', 'libraries.sortLabels.rating' => 'Reytinq', 'libraries.sortLabels.communityRating' => 'İcma reytinqi', @@ -4477,12 +4469,12 @@ extension on TranslationsAz { 'downloads.syncRuleCleanupUnavailable' => 'Əlaqəli yükləmələr təhlükəsiz şəkildə müəyyən edilə bilmədi. Serverə yenidən qoşulub cəhd edin və ya qaydanı yükləmələri silmədən silin.', 'downloads.syncedNewEpisodes' => ({required Object title, required Object count}) => '${title} üçün ${count} yeni seriya eyniləşdirildi', 'downloads.activeSyncRules' => 'Eyniləşdirmə qaydaları', - _ => null, - } ?? switch (path) { 'downloads.noSyncRules' => 'Eyniləşdirmə qaydası yoxdur', 'downloads.manageSyncRule' => 'Eyniləşdirməni idarə et', 'downloads.editEpisodeCount' => 'Seriya sayı', 'downloads.editSyncFilter' => 'Eyniləşdirmə filtri', + _ => null, + } ?? switch (path) { 'downloads.syncAllItems' => 'Bütün elementlər eyniləşdirilir', 'downloads.syncUnwatchedItems' => 'Baxılmayan elementlər eyniləşdirilir', 'downloads.syncRuleServerContext' => ({required Object server, required Object status}) => 'Server: ${server} • ${status}', diff --git a/lib/i18n/strings_bg.g.dart b/lib/i18n/strings_bg.g.dart index 9a37a4d38..1a7d34293 100644 --- a/lib/i18n/strings_bg.g.dart +++ b/lib/i18n/strings_bg.g.dart @@ -380,10 +380,6 @@ class _Translations$settings$bg extends Translations$settings$en { @override String get autoPlayNextEpisodeDescription => 'Пускай следващия епизод автоматично, когато текущият свърши'; @override String get playNextCountdown => 'Отброяване до следващия епизод'; @override String get playNextCountdownImmediate => 'Пусни веднага'; - @override String get autoSkipIntro => 'Автоматично прескачане на интро'; - @override String get autoSkipIntroDescription => 'Автоматично прескачай интро маркери след няколко секунди'; - @override String get autoSkipCredits => 'Автоматично прескачане на финални надписи'; - @override String get autoSkipCreditsDescription => 'Автоматично прескачай финалните надписи и пускай следващия епизод'; @override String get forceSkipMarkerFallback => 'Принуди резервни маркери'; @override String get forceSkipMarkerFallbackDescription => 'Използвай шаблони в заглавията на главите дори когато Plex има маркери'; @override String get autoSkipDelay => 'Забавяне за автоматично прескачане'; @@ -3194,10 +3190,6 @@ extension on TranslationsBg { 'settings.autoPlayNextEpisodeDescription' => 'Пускай следващия епизод автоматично, когато текущият свърши', 'settings.playNextCountdown' => 'Отброяване до следващия епизод', 'settings.playNextCountdownImmediate' => 'Пусни веднага', - 'settings.autoSkipIntro' => 'Автоматично прескачане на интро', - 'settings.autoSkipIntroDescription' => 'Автоматично прескачай интро маркери след няколко секунди', - 'settings.autoSkipCredits' => 'Автоматично прескачане на финални надписи', - 'settings.autoSkipCreditsDescription' => 'Автоматично прескачай финалните надписи и пускай следващия епизод', 'settings.forceSkipMarkerFallback' => 'Принуди резервни маркери', 'settings.forceSkipMarkerFallbackDescription' => 'Използвай шаблони в заглавията на главите дори когато Plex има маркери', 'settings.autoSkipDelay' => 'Забавяне за автоматично прескачане', @@ -3449,12 +3441,12 @@ extension on TranslationsBg { 'fileInfo.has64bitOffsets' => '64-битови отмествания', 'fileInfo.protocol' => 'Протокол', 'fileInfo.mediaType' => 'Тип медия', - _ => null, - } ?? switch (path) { 'fileInfo.sourceKind' => 'Вид източник', 'fileInfo.optimizedVersion' => 'Оптимизирана версия', 'fileInfo.optimizationTarget' => 'Цел на оптимизацията', 'fileInfo.deletedAt' => 'Изтрит', + _ => null, + } ?? switch (path) { 'fileInfo.remoteSource' => 'Отдалечен източник', 'fileInfo.infiniteStream' => 'Безкраен поток', 'fileInfo.directPlay' => 'Директно възпроизвеждане', @@ -3963,12 +3955,12 @@ extension on TranslationsBg { 'libraries.filterCategories.contentRating' => 'Възрастов рейтинг', 'libraries.filterCategories.tag' => 'Таг', 'libraries.filterCategories.unwatched' => 'Негледани', - _ => null, - } ?? switch (path) { 'libraries.filterCategories.unplayed' => 'Непускани', 'libraries.filterCategories.favorites' => 'Любими', 'libraries.sortLabels.title' => 'Заглавие', 'libraries.sortLabels.dateAdded' => 'Дата на добавяне', + _ => null, + } ?? switch (path) { 'libraries.sortLabels.releaseDate' => 'Дата на излизане', 'libraries.sortLabels.rating' => 'Рейтинг', 'libraries.sortLabels.communityRating' => 'Оценка от общността', @@ -4477,12 +4469,12 @@ extension on TranslationsBg { 'downloads.syncRuleCleanupUnavailable' => 'Свързаните изтегляния не можаха да бъдат идентифицирани безопасно. Свържете се отново със сървъра и опитайте отново, или премахнете правилото, без да изтривате изтеглянията.', 'downloads.syncedNewEpisodes' => ({required Object count, required Object title}) => 'Синхронизирани са ${count} нови епизода за ${title}', 'downloads.activeSyncRules' => 'Правила за синхронизация', - _ => null, - } ?? switch (path) { 'downloads.noSyncRules' => 'Няма правила за синхронизация', 'downloads.manageSyncRule' => 'Управление на синхронизацията', 'downloads.editEpisodeCount' => 'Брой епизоди', 'downloads.editSyncFilter' => 'Филтър за синхронизация', + _ => null, + } ?? switch (path) { 'downloads.syncAllItems' => 'Синхронизират се всички елементи', 'downloads.syncUnwatchedItems' => 'Синхронизират се негледаните елементи', 'downloads.syncRuleServerContext' => ({required Object server, required Object status}) => 'Сървър: ${server} • ${status}', diff --git a/lib/i18n/strings_da.g.dart b/lib/i18n/strings_da.g.dart index 899a9777d..a1be15c8f 100644 --- a/lib/i18n/strings_da.g.dart +++ b/lib/i18n/strings_da.g.dart @@ -380,10 +380,6 @@ class _Translations$settings$da extends Translations$settings$en { @override String get autoPlayNextEpisodeDescription => 'Start automatisk næste afsnit, når et afsnit slutter'; @override String get playNextCountdown => 'Nedtælling til næste afsnit'; @override String get playNextCountdownImmediate => 'Afspil med det samme'; - @override String get autoSkipIntro => 'Spring intro over automatisk'; - @override String get autoSkipIntroDescription => 'Spring automatisk intromarkører over efter få sekunder'; - @override String get autoSkipCredits => 'Spring rulletekster over automatisk'; - @override String get autoSkipCreditsDescription => 'Spring automatisk rulleteksterne over, og afspil næste episode'; @override String get forceSkipMarkerFallback => 'Tving reservemarkører'; @override String get forceSkipMarkerFallbackDescription => 'Brug mønstre i kapiteltitler, selv når Plex har markører'; @override String get autoSkipDelay => 'Forsinkelse ved automatisk spring'; @@ -3194,10 +3190,6 @@ extension on TranslationsDa { 'settings.autoPlayNextEpisodeDescription' => 'Start automatisk næste afsnit, når et afsnit slutter', 'settings.playNextCountdown' => 'Nedtælling til næste afsnit', 'settings.playNextCountdownImmediate' => 'Afspil med det samme', - 'settings.autoSkipIntro' => 'Spring intro over automatisk', - 'settings.autoSkipIntroDescription' => 'Spring automatisk intromarkører over efter få sekunder', - 'settings.autoSkipCredits' => 'Spring rulletekster over automatisk', - 'settings.autoSkipCreditsDescription' => 'Spring automatisk rulleteksterne over, og afspil næste episode', 'settings.forceSkipMarkerFallback' => 'Tving reservemarkører', 'settings.forceSkipMarkerFallbackDescription' => 'Brug mønstre i kapiteltitler, selv når Plex har markører', 'settings.autoSkipDelay' => 'Forsinkelse ved automatisk spring', @@ -3449,12 +3441,12 @@ extension on TranslationsDa { 'fileInfo.has64bitOffsets' => '64-bit-forskydninger', 'fileInfo.protocol' => 'Protokol', 'fileInfo.mediaType' => 'Medietype', - _ => null, - } ?? switch (path) { 'fileInfo.sourceKind' => 'Kildetype', 'fileInfo.optimizedVersion' => 'Optimeret version', 'fileInfo.optimizationTarget' => 'Optimeringsmål', 'fileInfo.deletedAt' => 'Slettet', + _ => null, + } ?? switch (path) { 'fileInfo.remoteSource' => 'Fjernkilde', 'fileInfo.infiniteStream' => 'Uendelig strøm', 'fileInfo.directPlay' => 'Direkte afspilning', @@ -3963,12 +3955,12 @@ extension on TranslationsDa { 'libraries.filterCategories.contentRating' => 'Aldersvurdering', 'libraries.filterCategories.tag' => 'Tag', 'libraries.filterCategories.unwatched' => 'Usete', - _ => null, - } ?? switch (path) { 'libraries.filterCategories.unplayed' => 'Ikke afspillet', 'libraries.filterCategories.favorites' => 'Favoritter', 'libraries.sortLabels.title' => 'Titel', 'libraries.sortLabels.dateAdded' => 'Tilføjet dato', + _ => null, + } ?? switch (path) { 'libraries.sortLabels.releaseDate' => 'Udgivelsesdato', 'libraries.sortLabels.rating' => 'Vurdering', 'libraries.sortLabels.communityRating' => 'Fællesskabsvurdering', @@ -4477,12 +4469,12 @@ extension on TranslationsDa { 'downloads.syncRuleCleanupUnavailable' => 'Tilknyttede downloads kunne ikke identificeres sikkert. Genopret forbindelse til serveren og prøv igen, eller fjern reglen uden at slette downloads.', 'downloads.syncedNewEpisodes' => ({required Object count, required Object title}) => 'Synkroniserede ${count} nye episoder for ${title}', 'downloads.activeSyncRules' => 'Synkroniseringsregler', - _ => null, - } ?? switch (path) { 'downloads.noSyncRules' => 'Ingen synkroniseringsregler', 'downloads.manageSyncRule' => 'Administrer synkronisering', 'downloads.editEpisodeCount' => 'Antal episoder', 'downloads.editSyncFilter' => 'Synkroniseringsfilter', + _ => null, + } ?? switch (path) { 'downloads.syncAllItems' => 'Synkroniserer alle elementer', 'downloads.syncUnwatchedItems' => 'Synkroniserer usete elementer', 'downloads.syncRuleServerContext' => ({required Object server, required Object status}) => 'Server: ${server} • ${status}', diff --git a/lib/i18n/strings_de.g.dart b/lib/i18n/strings_de.g.dart index 813704500..fb90641da 100644 --- a/lib/i18n/strings_de.g.dart +++ b/lib/i18n/strings_de.g.dart @@ -380,10 +380,6 @@ class _Translations$settings$de extends Translations$settings$en { @override String get autoPlayNextEpisodeDescription => 'Die nächste Episode automatisch starten, wenn die aktuelle endet'; @override String get playNextCountdown => 'Countdown bis zur nächsten Episode'; @override String get playNextCountdownImmediate => 'Sofort abspielen'; - @override String get autoSkipIntro => 'Intro automatisch überspringen'; - @override String get autoSkipIntroDescription => 'Intro-Marker nach wenigen Sekunden automatisch überspringen'; - @override String get autoSkipCredits => 'Abspann automatisch überspringen'; - @override String get autoSkipCreditsDescription => 'Abspann automatisch überspringen und nächste Episode abspielen'; @override String get forceSkipMarkerFallback => 'Ersatzmarkierungen erzwingen'; @override String get forceSkipMarkerFallbackDescription => 'Kapitel-Titelmuster auch dann verwenden, wenn Plex über Markierungen verfügt'; @override String get autoSkipDelay => 'Verzögerung für automatisches Überspringen'; @@ -3194,10 +3190,6 @@ extension on TranslationsDe { 'settings.autoPlayNextEpisodeDescription' => 'Die nächste Episode automatisch starten, wenn die aktuelle endet', 'settings.playNextCountdown' => 'Countdown bis zur nächsten Episode', 'settings.playNextCountdownImmediate' => 'Sofort abspielen', - 'settings.autoSkipIntro' => 'Intro automatisch überspringen', - 'settings.autoSkipIntroDescription' => 'Intro-Marker nach wenigen Sekunden automatisch überspringen', - 'settings.autoSkipCredits' => 'Abspann automatisch überspringen', - 'settings.autoSkipCreditsDescription' => 'Abspann automatisch überspringen und nächste Episode abspielen', 'settings.forceSkipMarkerFallback' => 'Ersatzmarkierungen erzwingen', 'settings.forceSkipMarkerFallbackDescription' => 'Kapitel-Titelmuster auch dann verwenden, wenn Plex über Markierungen verfügt', 'settings.autoSkipDelay' => 'Verzögerung für automatisches Überspringen', @@ -3449,12 +3441,12 @@ extension on TranslationsDe { 'fileInfo.has64bitOffsets' => '64-Bit-Offsets', 'fileInfo.protocol' => 'Protokoll', 'fileInfo.mediaType' => 'Medientyp', - _ => null, - } ?? switch (path) { 'fileInfo.sourceKind' => 'Quellenart', 'fileInfo.optimizedVersion' => 'Optimierte Version', 'fileInfo.optimizationTarget' => 'Optimierungsziel', 'fileInfo.deletedAt' => 'Gelöscht', + _ => null, + } ?? switch (path) { 'fileInfo.remoteSource' => 'Remote-Quelle', 'fileInfo.infiniteStream' => 'Endlos-Stream', 'fileInfo.directPlay' => 'Direct Play', @@ -3963,12 +3955,12 @@ extension on TranslationsDe { 'libraries.filterCategories.contentRating' => 'Altersfreigabe', 'libraries.filterCategories.tag' => 'Tag', 'libraries.filterCategories.unwatched' => 'Ungesehene', - _ => null, - } ?? switch (path) { 'libraries.filterCategories.unplayed' => 'Nicht abgespielt', 'libraries.filterCategories.favorites' => 'Favoriten', 'libraries.sortLabels.title' => 'Titel', 'libraries.sortLabels.dateAdded' => 'Hinzugefügt am', + _ => null, + } ?? switch (path) { 'libraries.sortLabels.releaseDate' => 'Erscheinungsdatum', 'libraries.sortLabels.rating' => 'Bewertung', 'libraries.sortLabels.communityRating' => 'Communitybewertung', @@ -4477,12 +4469,12 @@ extension on TranslationsDe { 'downloads.syncRuleCleanupUnavailable' => 'Zugehörige Downloads konnten nicht sicher ermittelt werden. Verbinde den Server erneut und versuche es noch einmal, oder entferne die Regel, ohne die Downloads zu löschen.', 'downloads.syncedNewEpisodes' => ({required Object count, required Object title}) => '${count} neue Episoden für ${title} synchronisiert', 'downloads.activeSyncRules' => 'Synchronisierungsregeln', - _ => null, - } ?? switch (path) { 'downloads.noSyncRules' => 'Keine Synchronisierungsregeln', 'downloads.manageSyncRule' => 'Synchronisierung verwalten', 'downloads.editEpisodeCount' => 'Episodenanzahl', 'downloads.editSyncFilter' => 'Synchronisierungsfilter', + _ => null, + } ?? switch (path) { 'downloads.syncAllItems' => 'Alle Elemente synchronisieren', 'downloads.syncUnwatchedItems' => 'Ungesehene Elemente synchronisieren', 'downloads.syncRuleServerContext' => ({required Object server, required Object status}) => 'Server: ${server} • ${status}', diff --git a/lib/i18n/strings_en.g.dart b/lib/i18n/strings_en.g.dart index eec892713..87fd07c37 100644 --- a/lib/i18n/strings_en.g.dart +++ b/lib/i18n/strings_en.g.dart @@ -864,17 +864,38 @@ class Translations$settings$en { /// en: 'Play immediately' String get playNextCountdownImmediate => 'Play immediately'; - /// en: 'Auto Skip Intro' - String get autoSkipIntro => 'Auto Skip Intro'; + /// en: 'Skip Intro' + String get skipIntroMode => 'Skip Intro'; - /// en: 'Automatically skip intro markers after a few seconds' - String get autoSkipIntroDescription => 'Automatically skip intro markers after a few seconds'; + /// en: 'Play intros normally without a skip button' + String get skipIntroModeOffDescription => 'Play intros normally without a skip button'; - /// en: 'Auto Skip Credits' - String get autoSkipCredits => 'Auto Skip Credits'; + /// en: 'Show a skip button when an intro starts' + String get skipIntroModeButtonDescription => 'Show a skip button when an intro starts'; - /// en: 'Automatically skip credits and play next episode' - String get autoSkipCreditsDescription => 'Automatically skip credits and play next episode'; + /// en: 'Skip intros automatically after the delay below' + String get skipIntroModeAutoDescription => 'Skip intros automatically after the delay below'; + + /// en: 'Skip Credits' + String get skipCreditsMode => 'Skip Credits'; + + /// en: 'Play credits normally without a skip button' + String get skipCreditsModeOffDescription => 'Play credits normally without a skip button'; + + /// en: 'Show a skip button when credits start' + String get skipCreditsModeButtonDescription => 'Show a skip button when credits start'; + + /// en: 'Skip credits automatically and play the next episode' + String get skipCreditsModeAutoDescription => 'Skip credits automatically and play the next episode'; + + /// en: 'Off' + String get skipMarkerModeOff => 'Off'; + + /// en: 'Show button' + String get skipMarkerModeButton => 'Show button'; + + /// en: 'Automatic' + String get skipMarkerModeAuto => 'Automatic'; /// en: 'Force Fallback Markers' String get forceSkipMarkerFallback => 'Force Fallback Markers'; @@ -7241,10 +7262,17 @@ extension on Translations { 'settings.autoPlayNextEpisodeDescription' => 'Start the next episode automatically when one ends', 'settings.playNextCountdown' => 'Play Next Countdown', 'settings.playNextCountdownImmediate' => 'Play immediately', - 'settings.autoSkipIntro' => 'Auto Skip Intro', - 'settings.autoSkipIntroDescription' => 'Automatically skip intro markers after a few seconds', - 'settings.autoSkipCredits' => 'Auto Skip Credits', - 'settings.autoSkipCreditsDescription' => 'Automatically skip credits and play next episode', + 'settings.skipIntroMode' => 'Skip Intro', + 'settings.skipIntroModeOffDescription' => 'Play intros normally without a skip button', + 'settings.skipIntroModeButtonDescription' => 'Show a skip button when an intro starts', + 'settings.skipIntroModeAutoDescription' => 'Skip intros automatically after the delay below', + 'settings.skipCreditsMode' => 'Skip Credits', + 'settings.skipCreditsModeOffDescription' => 'Play credits normally without a skip button', + 'settings.skipCreditsModeButtonDescription' => 'Show a skip button when credits start', + 'settings.skipCreditsModeAutoDescription' => 'Skip credits automatically and play the next episode', + 'settings.skipMarkerModeOff' => 'Off', + 'settings.skipMarkerModeButton' => 'Show button', + 'settings.skipMarkerModeAuto' => 'Automatic', 'settings.forceSkipMarkerFallback' => 'Force Fallback Markers', 'settings.forceSkipMarkerFallbackDescription' => 'Use chapter title patterns even when Plex has markers', 'settings.autoSkipDelay' => 'Auto Skip Delay', @@ -7485,6 +7513,8 @@ extension on Translations { 'fileInfo.path' => 'Path', 'fileInfo.fileName' => 'File Name', 'fileInfo.size' => 'Size', + _ => null, + } ?? switch (path) { 'fileInfo.totalSize' => 'Total Size', 'fileInfo.container' => 'Container', 'fileInfo.duration' => 'Duration', @@ -7492,8 +7522,6 @@ extension on Translations { 'fileInfo.previewIndex' => 'Preview Index', 'fileInfo.packetLength' => 'Packet Length', 'fileInfo.filePresent' => 'File Present', - _ => null, - } ?? switch (path) { 'fileInfo.fileReadable' => 'Readable by Server', 'fileInfo.streamPath' => 'Stream Path', 'fileInfo.optimizedForStreaming' => 'Optimized for Streaming', @@ -7999,6 +8027,8 @@ extension on Translations { 'libraries.tabs.recommended' => 'Recommended', 'libraries.tabs.browse' => 'Browse', 'libraries.tabs.collections' => 'Collections', + _ => null, + } ?? switch (path) { 'libraries.tabs.playlists' => 'Playlists', 'libraries.groupings.title' => 'Grouping', 'libraries.groupings.all' => 'All', @@ -8006,8 +8036,6 @@ extension on Translations { 'libraries.groupings.shows' => 'TV Shows', 'libraries.groupings.seasons' => 'Seasons', 'libraries.groupings.episodes' => 'Episodes', - _ => null, - } ?? switch (path) { 'libraries.groupings.artists' => 'Artists', 'libraries.groupings.albums' => 'Albums', 'libraries.groupings.tracks' => 'Tracks', @@ -8513,6 +8541,8 @@ extension on Translations { 'downloads.resumeAll' => 'Resume all', 'downloads.deleteAll' => 'Delete all', 'downloads.selectVersion' => 'Select Version', + _ => null, + } ?? switch (path) { 'downloads.allEpisodes' => 'All episodes', 'downloads.unwatchedOnly' => 'Unwatched only', 'downloads.nextNUnwatched' => ({required Object count}) => 'Next ${count} unwatched', @@ -8520,8 +8550,6 @@ extension on Translations { 'downloads.includeSpecials' => 'Include Specials', 'downloads.howManyEpisodes' => 'How many episodes?', 'downloads.invalidEpisodeCount' => 'Enter a valid episode count.', - _ => null, - } ?? switch (path) { 'downloads.keepSynced' => 'Keep synced', 'downloads.downloadOnce' => 'Download once', 'downloads.keepNUnwatched' => ({required Object count}) => 'Keep ${count} unwatched', diff --git a/lib/i18n/strings_es.g.dart b/lib/i18n/strings_es.g.dart index 44ca4ba9f..7d9fac715 100644 --- a/lib/i18n/strings_es.g.dart +++ b/lib/i18n/strings_es.g.dart @@ -380,10 +380,6 @@ class _Translations$settings$es extends Translations$settings$en { @override String get autoPlayNextEpisodeDescription => 'Iniciar automáticamente el siguiente episodio cuando termine el actual'; @override String get playNextCountdown => 'Cuenta atrás para el siguiente episodio'; @override String get playNextCountdownImmediate => 'Reproducir de inmediato'; - @override String get autoSkipIntro => 'Saltar introducción automáticamente'; - @override String get autoSkipIntroDescription => 'Saltar automáticamente los marcadores de introducción después de unos segundos'; - @override String get autoSkipCredits => 'Saltar créditos automáticamente'; - @override String get autoSkipCreditsDescription => 'Saltar automáticamente los créditos y reproducir el episodio siguiente'; @override String get forceSkipMarkerFallback => 'Forzar marcadores alternativos'; @override String get forceSkipMarkerFallbackDescription => 'Usar patrones de títulos de capítulos aunque Plex tenga marcadores'; @override String get autoSkipDelay => 'Retraso del salto automático'; @@ -3194,10 +3190,6 @@ extension on TranslationsEs { 'settings.autoPlayNextEpisodeDescription' => 'Iniciar automáticamente el siguiente episodio cuando termine el actual', 'settings.playNextCountdown' => 'Cuenta atrás para el siguiente episodio', 'settings.playNextCountdownImmediate' => 'Reproducir de inmediato', - 'settings.autoSkipIntro' => 'Saltar introducción automáticamente', - 'settings.autoSkipIntroDescription' => 'Saltar automáticamente los marcadores de introducción después de unos segundos', - 'settings.autoSkipCredits' => 'Saltar créditos automáticamente', - 'settings.autoSkipCreditsDescription' => 'Saltar automáticamente los créditos y reproducir el episodio siguiente', 'settings.forceSkipMarkerFallback' => 'Forzar marcadores alternativos', 'settings.forceSkipMarkerFallbackDescription' => 'Usar patrones de títulos de capítulos aunque Plex tenga marcadores', 'settings.autoSkipDelay' => 'Retraso del salto automático', @@ -3449,12 +3441,12 @@ extension on TranslationsEs { 'fileInfo.has64bitOffsets' => 'Desplazamientos de 64 bits', 'fileInfo.protocol' => 'Protocolo', 'fileInfo.mediaType' => 'Tipo de medio', - _ => null, - } ?? switch (path) { 'fileInfo.sourceKind' => 'Tipo de origen', 'fileInfo.optimizedVersion' => 'Versión optimizada', 'fileInfo.optimizationTarget' => 'Destino de optimización', 'fileInfo.deletedAt' => 'Eliminado', + _ => null, + } ?? switch (path) { 'fileInfo.remoteSource' => 'Origen remoto', 'fileInfo.infiniteStream' => 'Flujo infinito', 'fileInfo.directPlay' => 'Reproducción directa', @@ -3963,12 +3955,12 @@ extension on TranslationsEs { 'libraries.filterCategories.contentRating' => 'Clasificación por edad', 'libraries.filterCategories.tag' => 'Etiqueta', 'libraries.filterCategories.unwatched' => 'No vistos', - _ => null, - } ?? switch (path) { 'libraries.filterCategories.unplayed' => 'No reproducidos', 'libraries.filterCategories.favorites' => 'Favoritos', 'libraries.sortLabels.title' => 'Título', 'libraries.sortLabels.dateAdded' => 'Fecha de adición', + _ => null, + } ?? switch (path) { 'libraries.sortLabels.releaseDate' => 'Fecha de estreno', 'libraries.sortLabels.rating' => 'Valoración', 'libraries.sortLabels.communityRating' => 'Valoración de la comunidad', @@ -4477,12 +4469,12 @@ extension on TranslationsEs { 'downloads.syncRuleCleanupUnavailable' => 'No se pudieron identificar las descargas asociadas de forma segura. Vuelve a conectar el servidor e inténtalo de nuevo, o elimina la regla sin borrar las descargas.', 'downloads.syncedNewEpisodes' => ({required Object count, required Object title}) => '${count} nuevos episodios sincronizados para ${title}', 'downloads.activeSyncRules' => 'Reglas de sincronización', - _ => null, - } ?? switch (path) { 'downloads.noSyncRules' => 'Sin reglas de sincronización', 'downloads.manageSyncRule' => 'Gestionar sincronización', 'downloads.editEpisodeCount' => 'Número de episodios', 'downloads.editSyncFilter' => 'Filtro de sincronización', + _ => null, + } ?? switch (path) { 'downloads.syncAllItems' => 'Sincronizando todos los elementos', 'downloads.syncUnwatchedItems' => 'Sincronizando elementos no vistos', 'downloads.syncRuleServerContext' => ({required Object server, required Object status}) => 'Servidor: ${server} • ${status}', diff --git a/lib/i18n/strings_fr.g.dart b/lib/i18n/strings_fr.g.dart index 013da4948..644cb347d 100644 --- a/lib/i18n/strings_fr.g.dart +++ b/lib/i18n/strings_fr.g.dart @@ -380,10 +380,6 @@ class _Translations$settings$fr extends Translations$settings$en { @override String get autoPlayNextEpisodeDescription => 'Lancer automatiquement l\'épisode suivant lorsqu\'un épisode se termine'; @override String get playNextCountdown => 'Compte à rebours avant l\'épisode suivant'; @override String get playNextCountdownImmediate => 'Lire immédiatement'; - @override String get autoSkipIntro => 'Passer automatiquement l’introduction'; - @override String get autoSkipIntroDescription => 'Passer automatiquement les marqueurs d’introduction après quelques secondes'; - @override String get autoSkipCredits => 'Passer automatiquement le générique'; - @override String get autoSkipCreditsDescription => 'Passer automatiquement le générique et lire l’épisode suivant'; @override String get forceSkipMarkerFallback => 'Forcer les marqueurs de secours'; @override String get forceSkipMarkerFallbackDescription => 'Utiliser les motifs des titres de chapitre même lorsque Plex fournit des marqueurs'; @override String get autoSkipDelay => 'Délai avant le saut automatique'; @@ -3194,10 +3190,6 @@ extension on TranslationsFr { 'settings.autoPlayNextEpisodeDescription' => 'Lancer automatiquement l\'épisode suivant lorsqu\'un épisode se termine', 'settings.playNextCountdown' => 'Compte à rebours avant l\'épisode suivant', 'settings.playNextCountdownImmediate' => 'Lire immédiatement', - 'settings.autoSkipIntro' => 'Passer automatiquement l’introduction', - 'settings.autoSkipIntroDescription' => 'Passer automatiquement les marqueurs d’introduction après quelques secondes', - 'settings.autoSkipCredits' => 'Passer automatiquement le générique', - 'settings.autoSkipCreditsDescription' => 'Passer automatiquement le générique et lire l’épisode suivant', 'settings.forceSkipMarkerFallback' => 'Forcer les marqueurs de secours', 'settings.forceSkipMarkerFallbackDescription' => 'Utiliser les motifs des titres de chapitre même lorsque Plex fournit des marqueurs', 'settings.autoSkipDelay' => 'Délai avant le saut automatique', @@ -3449,12 +3441,12 @@ extension on TranslationsFr { 'fileInfo.has64bitOffsets' => 'Décalages 64 bits', 'fileInfo.protocol' => 'Protocole', 'fileInfo.mediaType' => 'Type de média', - _ => null, - } ?? switch (path) { 'fileInfo.sourceKind' => 'Type de source', 'fileInfo.optimizedVersion' => 'Version optimisée', 'fileInfo.optimizationTarget' => 'Cible d\'optimisation', 'fileInfo.deletedAt' => 'Supprimé', + _ => null, + } ?? switch (path) { 'fileInfo.remoteSource' => 'Source distante', 'fileInfo.infiniteStream' => 'Flux infini', 'fileInfo.directPlay' => 'Lecture directe', @@ -3963,12 +3955,12 @@ extension on TranslationsFr { 'libraries.filterCategories.contentRating' => 'Classification', 'libraries.filterCategories.tag' => 'Étiquette', 'libraries.filterCategories.unwatched' => 'Non vus', - _ => null, - } ?? switch (path) { 'libraries.filterCategories.unplayed' => 'Non lus', 'libraries.filterCategories.favorites' => 'Favoris', 'libraries.sortLabels.title' => 'Titre', 'libraries.sortLabels.dateAdded' => 'Date d\'ajout', + _ => null, + } ?? switch (path) { 'libraries.sortLabels.releaseDate' => 'Date de sortie', 'libraries.sortLabels.rating' => 'Note', 'libraries.sortLabels.communityRating' => 'Note communautaire', @@ -4477,12 +4469,12 @@ extension on TranslationsFr { 'downloads.syncRuleCleanupUnavailable' => 'Les téléchargements associés n\'ont pas pu être identifiés en toute sécurité. Reconnectez le serveur et réessayez, ou retirez la règle sans supprimer les téléchargements.', 'downloads.syncedNewEpisodes' => ({required Object count, required Object title}) => '${count} nouveaux épisodes synchronisés pour ${title}', 'downloads.activeSyncRules' => 'Règles de synchronisation', - _ => null, - } ?? switch (path) { 'downloads.noSyncRules' => 'Aucune règle de synchronisation', 'downloads.manageSyncRule' => 'Gérer la synchronisation', 'downloads.editEpisodeCount' => 'Nombre d’épisodes', 'downloads.editSyncFilter' => 'Filtre de synchronisation', + _ => null, + } ?? switch (path) { 'downloads.syncAllItems' => 'Synchronisation de tous les éléments', 'downloads.syncUnwatchedItems' => 'Synchronisation des éléments non vus', 'downloads.syncRuleServerContext' => ({required Object server, required Object status}) => 'Serveur : ${server} • ${status}', diff --git a/lib/i18n/strings_hu.g.dart b/lib/i18n/strings_hu.g.dart index 55bb6069c..a37b14a6d 100644 --- a/lib/i18n/strings_hu.g.dart +++ b/lib/i18n/strings_hu.g.dart @@ -380,10 +380,6 @@ class _Translations$settings$hu extends Translations$settings$en { @override String get autoPlayNextEpisodeDescription => 'A következő epizód automatikus elindítása, amikor az aktuális véget ér'; @override String get playNextCountdown => 'Visszaszámlálás a következő epizódig'; @override String get playNextCountdownImmediate => 'Azonnali lejátszás'; - @override String get autoSkipIntro => 'Intró automatikus átugrása'; - @override String get autoSkipIntroDescription => 'Az intrójelölők automatikus átugrása néhány másodperc után'; - @override String get autoSkipCredits => 'Stáblista automatikus átugrása'; - @override String get autoSkipCreditsDescription => 'A stáblista automatikus átugrása és a következő epizód lejátszása'; @override String get forceSkipMarkerFallback => 'Tartalék jelölők kényszerítése'; @override String get forceSkipMarkerFallbackDescription => 'Fejezetcím-minták használata akkor is, ha a Plex rendelkezik jelölőkkel'; @override String get autoSkipDelay => 'Automatikus átugrás késleltetése'; @@ -3194,10 +3190,6 @@ extension on TranslationsHu { 'settings.autoPlayNextEpisodeDescription' => 'A következő epizód automatikus elindítása, amikor az aktuális véget ér', 'settings.playNextCountdown' => 'Visszaszámlálás a következő epizódig', 'settings.playNextCountdownImmediate' => 'Azonnali lejátszás', - 'settings.autoSkipIntro' => 'Intró automatikus átugrása', - 'settings.autoSkipIntroDescription' => 'Az intrójelölők automatikus átugrása néhány másodperc után', - 'settings.autoSkipCredits' => 'Stáblista automatikus átugrása', - 'settings.autoSkipCreditsDescription' => 'A stáblista automatikus átugrása és a következő epizód lejátszása', 'settings.forceSkipMarkerFallback' => 'Tartalék jelölők kényszerítése', 'settings.forceSkipMarkerFallbackDescription' => 'Fejezetcím-minták használata akkor is, ha a Plex rendelkezik jelölőkkel', 'settings.autoSkipDelay' => 'Automatikus átugrás késleltetése', @@ -3449,12 +3441,12 @@ extension on TranslationsHu { 'fileInfo.has64bitOffsets' => '64 bites eltolások', 'fileInfo.protocol' => 'Protokoll', 'fileInfo.mediaType' => 'Médiatípus', - _ => null, - } ?? switch (path) { 'fileInfo.sourceKind' => 'Forrás típusa', 'fileInfo.optimizedVersion' => 'Optimalizált verzió', 'fileInfo.optimizationTarget' => 'Optimalizálási cél', 'fileInfo.deletedAt' => 'Törölve', + _ => null, + } ?? switch (path) { 'fileInfo.remoteSource' => 'Távoli forrás', 'fileInfo.infiniteStream' => 'Végtelen adatfolyam', 'fileInfo.directPlay' => 'Közvetlen lejátszás', @@ -3963,12 +3955,12 @@ extension on TranslationsHu { 'libraries.filterCategories.contentRating' => 'Korhatár-besorolás', 'libraries.filterCategories.tag' => 'Címke', 'libraries.filterCategories.unwatched' => 'Nem látott', - _ => null, - } ?? switch (path) { 'libraries.filterCategories.unplayed' => 'Nem lejátszott', 'libraries.filterCategories.favorites' => 'Kedvencek', 'libraries.sortLabels.title' => 'Cím', 'libraries.sortLabels.dateAdded' => 'Hozzáadás dátuma', + _ => null, + } ?? switch (path) { 'libraries.sortLabels.releaseDate' => 'Bemutató dátuma', 'libraries.sortLabels.rating' => 'Értékelés', 'libraries.sortLabels.communityRating' => 'Közösségi értékelés', @@ -4477,12 +4469,12 @@ extension on TranslationsHu { 'downloads.syncRuleCleanupUnavailable' => 'A kapcsolódó letöltések nem azonosíthatók biztonságosan. Csatlakoztassa újra a szervert, és próbálja újra, vagy távolítsa el a szabályt a letöltések törlése nélkül.', 'downloads.syncedNewEpisodes' => ({required Object count, required Object title}) => '${count} új epizód szinkronizálva a következőhöz: ${title}', 'downloads.activeSyncRules' => 'Szinkronizálási szabályok', - _ => null, - } ?? switch (path) { 'downloads.noSyncRules' => 'Nincsenek szinkronizálási szabályok', 'downloads.manageSyncRule' => 'Szinkronizálás kezelése', 'downloads.editEpisodeCount' => 'Epizódszám', 'downloads.editSyncFilter' => 'Szinkronizálási szűrő', + _ => null, + } ?? switch (path) { 'downloads.syncAllItems' => 'Minden elem szinkronizálása', 'downloads.syncUnwatchedItems' => 'Nem látott elemek szinkronizálása', 'downloads.syncRuleServerContext' => ({required Object server, required Object status}) => 'Szerver: ${server} • ${status}', diff --git a/lib/i18n/strings_it.g.dart b/lib/i18n/strings_it.g.dart index b5909ade8..e57dce391 100644 --- a/lib/i18n/strings_it.g.dart +++ b/lib/i18n/strings_it.g.dart @@ -380,10 +380,6 @@ class _Translations$settings$it extends Translations$settings$en { @override String get autoPlayNextEpisodeDescription => 'Avvia automaticamente l\'episodio successivo quando termina quello in riproduzione'; @override String get playNextCountdown => 'Conto alla rovescia del successivo'; @override String get playNextCountdownImmediate => 'Riproduci subito'; - @override String get autoSkipIntro => 'Salta automaticamente la sigla iniziale'; - @override String get autoSkipIntroDescription => 'Salta automaticamente i marcatori della sigla iniziale dopo alcuni secondi'; - @override String get autoSkipCredits => 'Salta automaticamente i titoli di coda'; - @override String get autoSkipCreditsDescription => 'Salta automaticamente i titoli di coda e riproduce l\'episodio successivo'; @override String get forceSkipMarkerFallback => 'Forza i marcatori di ripiego'; @override String get forceSkipMarkerFallbackDescription => 'Usa i modelli dei titoli dei capitoli anche quando Plex dispone di marcatori'; @override String get autoSkipDelay => 'Ritardo del salto automatico'; @@ -3194,10 +3190,6 @@ extension on TranslationsIt { 'settings.autoPlayNextEpisodeDescription' => 'Avvia automaticamente l\'episodio successivo quando termina quello in riproduzione', 'settings.playNextCountdown' => 'Conto alla rovescia del successivo', 'settings.playNextCountdownImmediate' => 'Riproduci subito', - 'settings.autoSkipIntro' => 'Salta automaticamente la sigla iniziale', - 'settings.autoSkipIntroDescription' => 'Salta automaticamente i marcatori della sigla iniziale dopo alcuni secondi', - 'settings.autoSkipCredits' => 'Salta automaticamente i titoli di coda', - 'settings.autoSkipCreditsDescription' => 'Salta automaticamente i titoli di coda e riproduce l\'episodio successivo', 'settings.forceSkipMarkerFallback' => 'Forza i marcatori di ripiego', 'settings.forceSkipMarkerFallbackDescription' => 'Usa i modelli dei titoli dei capitoli anche quando Plex dispone di marcatori', 'settings.autoSkipDelay' => 'Ritardo del salto automatico', @@ -3449,12 +3441,12 @@ extension on TranslationsIt { 'fileInfo.has64bitOffsets' => 'Offset a 64 bit', 'fileInfo.protocol' => 'Protocollo', 'fileInfo.mediaType' => 'Tipo di supporto', - _ => null, - } ?? switch (path) { 'fileInfo.sourceKind' => 'Tipo di origine', 'fileInfo.optimizedVersion' => 'Versione ottimizzata', 'fileInfo.optimizationTarget' => 'Obiettivo ottimizzazione', 'fileInfo.deletedAt' => 'Eliminato', + _ => null, + } ?? switch (path) { 'fileInfo.remoteSource' => 'Origine remota', 'fileInfo.infiniteStream' => 'Flusso infinito', 'fileInfo.directPlay' => 'Riproduzione diretta', @@ -3963,12 +3955,12 @@ extension on TranslationsIt { 'libraries.filterCategories.contentRating' => 'Classificazione per età', 'libraries.filterCategories.tag' => 'Tag', 'libraries.filterCategories.unwatched' => 'Non visti', - _ => null, - } ?? switch (path) { 'libraries.filterCategories.unplayed' => 'Non riprodotti', 'libraries.filterCategories.favorites' => 'Preferiti', 'libraries.sortLabels.title' => 'Titolo', 'libraries.sortLabels.dateAdded' => 'Data di aggiunta', + _ => null, + } ?? switch (path) { 'libraries.sortLabels.releaseDate' => 'Data di uscita', 'libraries.sortLabels.rating' => 'Valutazione', 'libraries.sortLabels.communityRating' => 'Valutazione della comunità', @@ -4477,12 +4469,12 @@ extension on TranslationsIt { 'downloads.syncRuleCleanupUnavailable' => 'Non è stato possibile identificare in sicurezza i download associati. Riconnetti il server e riprova, oppure rimuovi la regola senza eliminare i download.', 'downloads.syncedNewEpisodes' => ({required Object count, required Object title}) => '${count} nuovi episodi sincronizzati per ${title}', 'downloads.activeSyncRules' => 'Regole di sincronizzazione', - _ => null, - } ?? switch (path) { 'downloads.noSyncRules' => 'Nessuna regola di sincronizzazione', 'downloads.manageSyncRule' => 'Gestisci sincronizzazione', 'downloads.editEpisodeCount' => 'Numero di episodi', 'downloads.editSyncFilter' => 'Filtro di sincronizzazione', + _ => null, + } ?? switch (path) { 'downloads.syncAllItems' => 'Sincronizzazione di tutti gli elementi', 'downloads.syncUnwatchedItems' => 'Sincronizzazione degli elementi non visti', 'downloads.syncRuleServerContext' => ({required Object server, required Object status}) => 'Server: ${server} • ${status}', diff --git a/lib/i18n/strings_ja.g.dart b/lib/i18n/strings_ja.g.dart index 4e707ede1..cc815c05b 100644 --- a/lib/i18n/strings_ja.g.dart +++ b/lib/i18n/strings_ja.g.dart @@ -380,10 +380,6 @@ class _Translations$settings$ja extends Translations$settings$en { @override String get autoPlayNextEpisodeDescription => 'エピソードが終了すると、次のエピソードを自動的に再生します'; @override String get playNextCountdown => '次回再生のカウントダウン'; @override String get playNextCountdownImmediate => 'すぐに再生'; - @override String get autoSkipIntro => 'イントロを自動スキップ'; - @override String get autoSkipIntroDescription => '数秒後にイントロマーカーを自動的にスキップ'; - @override String get autoSkipCredits => 'クレジットを自動スキップ'; - @override String get autoSkipCreditsDescription => 'クレジットを自動的にスキップして次のエピソードを再生'; @override String get forceSkipMarkerFallback => 'フォールバックマーカーを強制'; @override String get forceSkipMarkerFallbackDescription => 'Plexにマーカーがある場合でもチャプタータイトルのパターンを使用します'; @override String get autoSkipDelay => '自動スキップの遅延'; @@ -3184,10 +3180,6 @@ extension on TranslationsJa { 'settings.autoPlayNextEpisodeDescription' => 'エピソードが終了すると、次のエピソードを自動的に再生します', 'settings.playNextCountdown' => '次回再生のカウントダウン', 'settings.playNextCountdownImmediate' => 'すぐに再生', - 'settings.autoSkipIntro' => 'イントロを自動スキップ', - 'settings.autoSkipIntroDescription' => '数秒後にイントロマーカーを自動的にスキップ', - 'settings.autoSkipCredits' => 'クレジットを自動スキップ', - 'settings.autoSkipCreditsDescription' => 'クレジットを自動的にスキップして次のエピソードを再生', 'settings.forceSkipMarkerFallback' => 'フォールバックマーカーを強制', 'settings.forceSkipMarkerFallbackDescription' => 'Plexにマーカーがある場合でもチャプタータイトルのパターンを使用します', 'settings.autoSkipDelay' => '自動スキップの遅延', @@ -3439,12 +3431,12 @@ extension on TranslationsJa { 'fileInfo.has64bitOffsets' => '64ビットオフセット', 'fileInfo.protocol' => 'プロトコル', 'fileInfo.mediaType' => 'メディアタイプ', - _ => null, - } ?? switch (path) { 'fileInfo.sourceKind' => 'ソース種別', 'fileInfo.optimizedVersion' => '最適化バージョン', 'fileInfo.optimizationTarget' => '最適化ターゲット', 'fileInfo.deletedAt' => '削除済み', + _ => null, + } ?? switch (path) { 'fileInfo.remoteSource' => 'リモートソース', 'fileInfo.infiniteStream' => '無限ストリーム', 'fileInfo.directPlay' => 'ダイレクト再生', @@ -3953,12 +3945,12 @@ extension on TranslationsJa { 'libraries.filterCategories.contentRating' => '視聴年齢区分', 'libraries.filterCategories.tag' => 'タグ', 'libraries.filterCategories.unwatched' => '未視聴', - _ => null, - } ?? switch (path) { 'libraries.filterCategories.unplayed' => '未再生', 'libraries.filterCategories.favorites' => 'お気に入り', 'libraries.sortLabels.title' => 'タイトル', 'libraries.sortLabels.dateAdded' => '追加日', + _ => null, + } ?? switch (path) { 'libraries.sortLabels.releaseDate' => 'リリース日', 'libraries.sortLabels.rating' => '評価', 'libraries.sortLabels.communityRating' => 'コミュニティ評価', @@ -4467,12 +4459,12 @@ extension on TranslationsJa { 'downloads.syncRuleCleanupUnavailable' => '関連するダウンロードを安全に特定できませんでした。サーバーに再接続して再試行するか、ダウンロードを削除せずにルールを削除してください。', 'downloads.syncedNewEpisodes' => ({required Object title, required Object count}) => '${title}の新しいエピソードを${count}件同期しました', 'downloads.activeSyncRules' => '同期ルール', - _ => null, - } ?? switch (path) { 'downloads.noSyncRules' => '同期ルールなし', 'downloads.manageSyncRule' => '同期を管理', 'downloads.editEpisodeCount' => 'エピソード数', 'downloads.editSyncFilter' => '同期フィルター', + _ => null, + } ?? switch (path) { 'downloads.syncAllItems' => 'すべてのアイテムを同期中', 'downloads.syncUnwatchedItems' => '未視聴のアイテムを同期中', 'downloads.syncRuleServerContext' => ({required Object server, required Object status}) => 'サーバー: ${server} • ${status}', diff --git a/lib/i18n/strings_kk.g.dart b/lib/i18n/strings_kk.g.dart index d0c4b14f2..2f801d5f5 100644 --- a/lib/i18n/strings_kk.g.dart +++ b/lib/i18n/strings_kk.g.dart @@ -380,10 +380,6 @@ class _Translations$settings$kk extends Translations$settings$en { @override String get autoPlayNextEpisodeDescription => 'Бір бөлім аяқталғанда келесі бөлімді автоматты түрде бастау'; @override String get playNextCountdown => 'Келесіні ойнату санағы'; @override String get playNextCountdownImmediate => 'Дереу ойнату'; - @override String get autoSkipIntro => 'Киріс бөлімді (Intro) автоматты өткізу'; - @override String get autoSkipIntroDescription => 'Бірнеше секундтан кейін киріс белгілерін автоматты өткізу'; - @override String get autoSkipCredits => 'Титрлерді автоматты өткізу'; - @override String get autoSkipCreditsDescription => 'Титрлерді автоматты өткізіп, келесі бөлімді ойнату'; @override String get forceSkipMarkerFallback => 'Қосалқы белгілерді мәжбүрлеу'; @override String get forceSkipMarkerFallbackDescription => 'Plex белгілері болса да бөлім тақырыбы үлгілерін пайдалану'; @override String get autoSkipDelay => 'Автоматты өткізу кідірісі'; @@ -3194,10 +3190,6 @@ extension on TranslationsKk { 'settings.autoPlayNextEpisodeDescription' => 'Бір бөлім аяқталғанда келесі бөлімді автоматты түрде бастау', 'settings.playNextCountdown' => 'Келесіні ойнату санағы', 'settings.playNextCountdownImmediate' => 'Дереу ойнату', - 'settings.autoSkipIntro' => 'Киріс бөлімді (Intro) автоматты өткізу', - 'settings.autoSkipIntroDescription' => 'Бірнеше секундтан кейін киріс белгілерін автоматты өткізу', - 'settings.autoSkipCredits' => 'Титрлерді автоматты өткізу', - 'settings.autoSkipCreditsDescription' => 'Титрлерді автоматты өткізіп, келесі бөлімді ойнату', 'settings.forceSkipMarkerFallback' => 'Қосалқы белгілерді мәжбүрлеу', 'settings.forceSkipMarkerFallbackDescription' => 'Plex белгілері болса да бөлім тақырыбы үлгілерін пайдалану', 'settings.autoSkipDelay' => 'Автоматты өткізу кідірісі', @@ -3449,12 +3441,12 @@ extension on TranslationsKk { 'fileInfo.has64bitOffsets' => '64-биттік ығысулар', 'fileInfo.protocol' => 'Протокол', 'fileInfo.mediaType' => 'Медиа түрі', - _ => null, - } ?? switch (path) { 'fileInfo.sourceKind' => 'Дереккөз түрі', 'fileInfo.optimizedVersion' => 'Оңтайландырылған нұсқа', 'fileInfo.optimizationTarget' => 'Оңтайландыру мақсаты', 'fileInfo.deletedAt' => 'Өшірілген', + _ => null, + } ?? switch (path) { 'fileInfo.remoteSource' => 'Қашықтағы дереккөз', 'fileInfo.infiniteStream' => 'Шексіз ағын', 'fileInfo.directPlay' => 'Тікелей ойнату', @@ -3963,12 +3955,12 @@ extension on TranslationsKk { 'libraries.filterCategories.contentRating' => 'Мазмұн рейтингі', 'libraries.filterCategories.tag' => 'Тег', 'libraries.filterCategories.unwatched' => 'Көрілмеген', - _ => null, - } ?? switch (path) { 'libraries.filterCategories.unplayed' => 'Ойнатылмаған', 'libraries.filterCategories.favorites' => 'Таңдаулылар', 'libraries.sortLabels.title' => 'Атауы', 'libraries.sortLabels.dateAdded' => 'Қосылған күні', + _ => null, + } ?? switch (path) { 'libraries.sortLabels.releaseDate' => 'Шыққан күні', 'libraries.sortLabels.rating' => 'Рейтинг', 'libraries.sortLabels.communityRating' => 'Қауымдастық рейтингі', @@ -4477,12 +4469,12 @@ extension on TranslationsKk { 'downloads.syncRuleCleanupUnavailable' => 'Байланысты жүктеулерді қауіпсіз анықтау мүмкін болмады. Серверге қайта қосылып көріңіз немесе ережені жүктеулерді жоймай өшіріңіз.', 'downloads.syncedNewEpisodes' => ({required Object title, required Object count}) => '${title} үшін ${count} жаңа бөлім синхрондалды', 'downloads.activeSyncRules' => 'Белсенді синхрондау ережелері', - _ => null, - } ?? switch (path) { 'downloads.noSyncRules' => 'Синхрондау ережелері жоқ', 'downloads.manageSyncRule' => 'Синхрондауды басқару', 'downloads.editEpisodeCount' => 'Бөлімдер саны', 'downloads.editSyncFilter' => 'Синхрондау фильтрі', + _ => null, + } ?? switch (path) { 'downloads.syncAllItems' => 'Барлық элементтер синхрондалады', 'downloads.syncUnwatchedItems' => 'Көрілмеген элементтер синхрондалады', 'downloads.syncRuleServerContext' => ({required Object server, required Object status}) => 'Сервер: ${server} • ${status}', diff --git a/lib/i18n/strings_ko.g.dart b/lib/i18n/strings_ko.g.dart index 6ecfa8978..f1bf93fe0 100644 --- a/lib/i18n/strings_ko.g.dart +++ b/lib/i18n/strings_ko.g.dart @@ -380,10 +380,6 @@ class _Translations$settings$ko extends Translations$settings$en { @override String get autoPlayNextEpisodeDescription => '에피소드가 끝나면 다음 에피소드를 자동으로 재생'; @override String get playNextCountdown => '다음 재생 카운트다운'; @override String get playNextCountdownImmediate => '즉시 재생'; - @override String get autoSkipIntro => '자동으로 오프닝 건너뛰기'; - @override String get autoSkipIntroDescription => '몇 초 후 오프닝을 자동으로 건너뛰기'; - @override String get autoSkipCredits => '자동으로 엔딩 건너뛰기'; - @override String get autoSkipCreditsDescription => '엔딩 크레딧 자동 건너뛰기 후 다음 에피소드 재생'; @override String get forceSkipMarkerFallback => '대체 마커 강제 사용'; @override String get forceSkipMarkerFallbackDescription => 'Plex에 마커가 있어도 챕터 제목 패턴 사용'; @override String get autoSkipDelay => '자동 건너뛰기 지연'; @@ -3184,10 +3180,6 @@ extension on TranslationsKo { 'settings.autoPlayNextEpisodeDescription' => '에피소드가 끝나면 다음 에피소드를 자동으로 재생', 'settings.playNextCountdown' => '다음 재생 카운트다운', 'settings.playNextCountdownImmediate' => '즉시 재생', - 'settings.autoSkipIntro' => '자동으로 오프닝 건너뛰기', - 'settings.autoSkipIntroDescription' => '몇 초 후 오프닝을 자동으로 건너뛰기', - 'settings.autoSkipCredits' => '자동으로 엔딩 건너뛰기', - 'settings.autoSkipCreditsDescription' => '엔딩 크레딧 자동 건너뛰기 후 다음 에피소드 재생', 'settings.forceSkipMarkerFallback' => '대체 마커 강제 사용', 'settings.forceSkipMarkerFallbackDescription' => 'Plex에 마커가 있어도 챕터 제목 패턴 사용', 'settings.autoSkipDelay' => '자동 건너뛰기 지연', @@ -3439,12 +3431,12 @@ extension on TranslationsKo { 'fileInfo.has64bitOffsets' => '64비트 오프셋', 'fileInfo.protocol' => '프로토콜', 'fileInfo.mediaType' => '미디어 유형', - _ => null, - } ?? switch (path) { 'fileInfo.sourceKind' => '소스 종류', 'fileInfo.optimizedVersion' => '최적화 버전', 'fileInfo.optimizationTarget' => '최적화 대상', 'fileInfo.deletedAt' => '삭제됨', + _ => null, + } ?? switch (path) { 'fileInfo.remoteSource' => '원격 소스', 'fileInfo.infiniteStream' => '무한 스트림', 'fileInfo.directPlay' => 'Direct Play', @@ -3953,12 +3945,12 @@ extension on TranslationsKo { 'libraries.filterCategories.contentRating' => '시청 등급', 'libraries.filterCategories.tag' => '태그', 'libraries.filterCategories.unwatched' => '미시청', - _ => null, - } ?? switch (path) { 'libraries.filterCategories.unplayed' => '재생하지 않음', 'libraries.filterCategories.favorites' => '즐겨찾기', 'libraries.sortLabels.title' => '제목', 'libraries.sortLabels.dateAdded' => '추가된 날짜', + _ => null, + } ?? switch (path) { 'libraries.sortLabels.releaseDate' => '출시일', 'libraries.sortLabels.rating' => '평점', 'libraries.sortLabels.communityRating' => '커뮤니티 평점', @@ -4467,12 +4459,12 @@ extension on TranslationsKo { 'downloads.syncRuleCleanupUnavailable' => '연결된 다운로드를 안전하게 확인할 수 없습니다. 서버에 다시 연결한 후 시도하거나, 다운로드를 삭제하지 않고 규칙만 제거하세요.', 'downloads.syncedNewEpisodes' => ({required Object title, required Object count}) => '${title}의 새 에피소드 ${count}개 동기화됨', 'downloads.activeSyncRules' => '동기화 규칙', - _ => null, - } ?? switch (path) { 'downloads.noSyncRules' => '동기화 규칙 없음', 'downloads.manageSyncRule' => '동기화 관리', 'downloads.editEpisodeCount' => '에피소드 수', 'downloads.editSyncFilter' => '동기화 필터', + _ => null, + } ?? switch (path) { 'downloads.syncAllItems' => '모든 항목 동기화 중', 'downloads.syncUnwatchedItems' => '시청하지 않은 항목 동기화 중', 'downloads.syncRuleServerContext' => ({required Object server, required Object status}) => '서버: ${server} • ${status}', diff --git a/lib/i18n/strings_nb.g.dart b/lib/i18n/strings_nb.g.dart index b2d0e0572..59a19c5d5 100644 --- a/lib/i18n/strings_nb.g.dart +++ b/lib/i18n/strings_nb.g.dart @@ -380,10 +380,6 @@ class _Translations$settings$nb extends Translations$settings$en { @override String get autoPlayNextEpisodeDescription => 'Start neste episode automatisk når en episode er ferdig'; @override String get playNextCountdown => 'Nedtelling for neste episode'; @override String get playNextCountdownImmediate => 'Spill umiddelbart'; - @override String get autoSkipIntro => 'Hopp over intro automatisk'; - @override String get autoSkipIntroDescription => 'Hopp automatisk over intromarkører etter noen sekunder'; - @override String get autoSkipCredits => 'Hopp over rulletekst automatisk'; - @override String get autoSkipCreditsDescription => 'Hopp automatisk over rulletekst og spill neste episode'; @override String get forceSkipMarkerFallback => 'Tving reservemarkører'; @override String get forceSkipMarkerFallbackDescription => 'Bruk mønstre i kapiteltitler selv når Plex har markører'; @override String get autoSkipDelay => 'Forsinkelse for automatisk hopp'; @@ -3194,10 +3190,6 @@ extension on TranslationsNb { 'settings.autoPlayNextEpisodeDescription' => 'Start neste episode automatisk når en episode er ferdig', 'settings.playNextCountdown' => 'Nedtelling for neste episode', 'settings.playNextCountdownImmediate' => 'Spill umiddelbart', - 'settings.autoSkipIntro' => 'Hopp over intro automatisk', - 'settings.autoSkipIntroDescription' => 'Hopp automatisk over intromarkører etter noen sekunder', - 'settings.autoSkipCredits' => 'Hopp over rulletekst automatisk', - 'settings.autoSkipCreditsDescription' => 'Hopp automatisk over rulletekst og spill neste episode', 'settings.forceSkipMarkerFallback' => 'Tving reservemarkører', 'settings.forceSkipMarkerFallbackDescription' => 'Bruk mønstre i kapiteltitler selv når Plex har markører', 'settings.autoSkipDelay' => 'Forsinkelse for automatisk hopp', @@ -3449,12 +3441,12 @@ extension on TranslationsNb { 'fileInfo.has64bitOffsets' => '64-biters forskyvninger', 'fileInfo.protocol' => 'Protokoll', 'fileInfo.mediaType' => 'Mediatype', - _ => null, - } ?? switch (path) { 'fileInfo.sourceKind' => 'Kildetype', 'fileInfo.optimizedVersion' => 'Optimalisert versjon', 'fileInfo.optimizationTarget' => 'Optimaliseringsmål', 'fileInfo.deletedAt' => 'Slettet', + _ => null, + } ?? switch (path) { 'fileInfo.remoteSource' => 'Ekstern kilde', 'fileInfo.infiniteStream' => 'Uendelig strøm', 'fileInfo.directPlay' => 'Direct Play', @@ -3963,12 +3955,12 @@ extension on TranslationsNb { 'libraries.filterCategories.contentRating' => 'Aldersgrense', 'libraries.filterCategories.tag' => 'Tagg', 'libraries.filterCategories.unwatched' => 'Usette', - _ => null, - } ?? switch (path) { 'libraries.filterCategories.unplayed' => 'Ikke avspilt', 'libraries.filterCategories.favorites' => 'Favoritter', 'libraries.sortLabels.title' => 'Tittel', 'libraries.sortLabels.dateAdded' => 'Dato lagt til', + _ => null, + } ?? switch (path) { 'libraries.sortLabels.releaseDate' => 'Utgivelsesdato', 'libraries.sortLabels.rating' => 'Vurdering', 'libraries.sortLabels.communityRating' => 'Fellesskapsvurdering', @@ -4477,12 +4469,12 @@ extension on TranslationsNb { 'downloads.syncRuleCleanupUnavailable' => 'Tilknyttede nedlastinger kunne ikke identifiseres på en trygg måte. Koble til serveren på nytt og prøv igjen, eller fjern regelen uten å slette nedlastingene.', 'downloads.syncedNewEpisodes' => ({required Object count, required Object title}) => 'Synkroniserte ${count} nye episoder for ${title}', 'downloads.activeSyncRules' => 'Synkroniseringsregler', - _ => null, - } ?? switch (path) { 'downloads.noSyncRules' => 'Ingen synkroniseringsregler', 'downloads.manageSyncRule' => 'Administrer synkronisering', 'downloads.editEpisodeCount' => 'Antall episoder', 'downloads.editSyncFilter' => 'Synkroniseringsfilter', + _ => null, + } ?? switch (path) { 'downloads.syncAllItems' => 'Synkroniserer alle elementer', 'downloads.syncUnwatchedItems' => 'Synkroniserer usette elementer', 'downloads.syncRuleServerContext' => ({required Object server, required Object status}) => 'Server: ${server} • ${status}', diff --git a/lib/i18n/strings_nl.g.dart b/lib/i18n/strings_nl.g.dart index b15a04309..6b3a7a7e3 100644 --- a/lib/i18n/strings_nl.g.dart +++ b/lib/i18n/strings_nl.g.dart @@ -380,10 +380,6 @@ class _Translations$settings$nl extends Translations$settings$en { @override String get autoPlayNextEpisodeDescription => 'Start de volgende aflevering automatisch wanneer een aflevering eindigt'; @override String get playNextCountdown => 'Aftellen voor volgende aflevering'; @override String get playNextCountdownImmediate => 'Direct afspelen'; - @override String get autoSkipIntro => 'Intro automatisch overslaan'; - @override String get autoSkipIntroDescription => 'Intromarkeringen na enkele seconden automatisch overslaan'; - @override String get autoSkipCredits => 'Aftiteling automatisch overslaan'; - @override String get autoSkipCreditsDescription => 'Aftiteling automatisch overslaan en de volgende aflevering afspelen'; @override String get forceSkipMarkerFallback => 'Reservemarkeringen afdwingen'; @override String get forceSkipMarkerFallbackDescription => 'Gebruik patronen in hoofdstuktitels, zelfs wanneer Plex markeringen heeft'; @override String get autoSkipDelay => 'Vertraging voor automatisch overslaan'; @@ -3194,10 +3190,6 @@ extension on TranslationsNl { 'settings.autoPlayNextEpisodeDescription' => 'Start de volgende aflevering automatisch wanneer een aflevering eindigt', 'settings.playNextCountdown' => 'Aftellen voor volgende aflevering', 'settings.playNextCountdownImmediate' => 'Direct afspelen', - 'settings.autoSkipIntro' => 'Intro automatisch overslaan', - 'settings.autoSkipIntroDescription' => 'Intromarkeringen na enkele seconden automatisch overslaan', - 'settings.autoSkipCredits' => 'Aftiteling automatisch overslaan', - 'settings.autoSkipCreditsDescription' => 'Aftiteling automatisch overslaan en de volgende aflevering afspelen', 'settings.forceSkipMarkerFallback' => 'Reservemarkeringen afdwingen', 'settings.forceSkipMarkerFallbackDescription' => 'Gebruik patronen in hoofdstuktitels, zelfs wanneer Plex markeringen heeft', 'settings.autoSkipDelay' => 'Vertraging voor automatisch overslaan', @@ -3449,12 +3441,12 @@ extension on TranslationsNl { 'fileInfo.has64bitOffsets' => '64-bits offsets', 'fileInfo.protocol' => 'Protocol', 'fileInfo.mediaType' => 'Mediatype', - _ => null, - } ?? switch (path) { 'fileInfo.sourceKind' => 'Soort bron', 'fileInfo.optimizedVersion' => 'Geoptimaliseerde versie', 'fileInfo.optimizationTarget' => 'Optimalisatiedoel', 'fileInfo.deletedAt' => 'Verwijderd', + _ => null, + } ?? switch (path) { 'fileInfo.remoteSource' => 'Externe bron', 'fileInfo.infiniteStream' => 'Oneindige stream', 'fileInfo.directPlay' => 'Direct Play', @@ -3963,12 +3955,12 @@ extension on TranslationsNl { 'libraries.filterCategories.contentRating' => 'Leeftijdsclassificatie', 'libraries.filterCategories.tag' => 'Tag', 'libraries.filterCategories.unwatched' => 'Onbekeken', - _ => null, - } ?? switch (path) { 'libraries.filterCategories.unplayed' => 'Niet afgespeeld', 'libraries.filterCategories.favorites' => 'Favorieten', 'libraries.sortLabels.title' => 'Titel', 'libraries.sortLabels.dateAdded' => 'Toegevoegd op', + _ => null, + } ?? switch (path) { 'libraries.sortLabels.releaseDate' => 'Uitgavedatum', 'libraries.sortLabels.rating' => 'Beoordeling', 'libraries.sortLabels.communityRating' => 'Beoordeling door community', @@ -4477,12 +4469,12 @@ extension on TranslationsNl { 'downloads.syncRuleCleanupUnavailable' => 'Gekoppelde downloads konden niet veilig worden geïdentificeerd. Maak opnieuw verbinding met de server en probeer het opnieuw, of verwijder de regel zonder de downloads te verwijderen.', 'downloads.syncedNewEpisodes' => ({required Object count, required Object title}) => '${count} nieuwe afleveringen gesynchroniseerd voor ${title}', 'downloads.activeSyncRules' => 'Synchronisatieregels', - _ => null, - } ?? switch (path) { 'downloads.noSyncRules' => 'Geen synchronisatieregels', 'downloads.manageSyncRule' => 'Synchronisatie beheren', 'downloads.editEpisodeCount' => 'Aantal afleveringen', 'downloads.editSyncFilter' => 'Synchronisatiefilter', + _ => null, + } ?? switch (path) { 'downloads.syncAllItems' => 'Alle items synchroniseren', 'downloads.syncUnwatchedItems' => 'Ongekeken items synchroniseren', 'downloads.syncRuleServerContext' => ({required Object server, required Object status}) => 'Server: ${server} • ${status}', diff --git a/lib/i18n/strings_pl.g.dart b/lib/i18n/strings_pl.g.dart index 0341bf20d..bbc77b9f5 100644 --- a/lib/i18n/strings_pl.g.dart +++ b/lib/i18n/strings_pl.g.dart @@ -380,10 +380,6 @@ class _Translations$settings$pl extends Translations$settings$en { @override String get autoPlayNextEpisodeDescription => 'Automatycznie uruchamiaj następny odcinek, gdy bieżący się skończy'; @override String get playNextCountdown => 'Odliczanie do następnego odcinka'; @override String get playNextCountdownImmediate => 'Odtwarzaj natychmiast'; - @override String get autoSkipIntro => 'Automatyczne pomijanie intro'; - @override String get autoSkipIntroDescription => 'Automatycznie pomijaj znaczniki intro po kilku sekundach'; - @override String get autoSkipCredits => 'Automatyczne pomijanie napisów końcowych'; - @override String get autoSkipCreditsDescription => 'Automatycznie pomijaj napisy końcowe i odtwórz następny odcinek'; @override String get forceSkipMarkerFallback => 'Wymuś znaczniki awaryjne'; @override String get forceSkipMarkerFallbackDescription => 'Używaj wzorców tytułów rozdziałów, nawet gdy Plex ma znaczniki'; @override String get autoSkipDelay => 'Opóźnienie automatycznego pomijania'; @@ -3214,10 +3210,6 @@ extension on TranslationsPl { 'settings.autoPlayNextEpisodeDescription' => 'Automatycznie uruchamiaj następny odcinek, gdy bieżący się skończy', 'settings.playNextCountdown' => 'Odliczanie do następnego odcinka', 'settings.playNextCountdownImmediate' => 'Odtwarzaj natychmiast', - 'settings.autoSkipIntro' => 'Automatyczne pomijanie intro', - 'settings.autoSkipIntroDescription' => 'Automatycznie pomijaj znaczniki intro po kilku sekundach', - 'settings.autoSkipCredits' => 'Automatyczne pomijanie napisów końcowych', - 'settings.autoSkipCreditsDescription' => 'Automatycznie pomijaj napisy końcowe i odtwórz następny odcinek', 'settings.forceSkipMarkerFallback' => 'Wymuś znaczniki awaryjne', 'settings.forceSkipMarkerFallbackDescription' => 'Używaj wzorców tytułów rozdziałów, nawet gdy Plex ma znaczniki', 'settings.autoSkipDelay' => 'Opóźnienie automatycznego pomijania', @@ -3469,12 +3461,12 @@ extension on TranslationsPl { 'fileInfo.has64bitOffsets' => 'Przesunięcia 64-bitowe', 'fileInfo.protocol' => 'Protokół', 'fileInfo.mediaType' => 'Typ multimediów', - _ => null, - } ?? switch (path) { 'fileInfo.sourceKind' => 'Rodzaj źródła', 'fileInfo.optimizedVersion' => 'Zoptymalizowana wersja', 'fileInfo.optimizationTarget' => 'Cel optymalizacji', 'fileInfo.deletedAt' => 'Usunięto', + _ => null, + } ?? switch (path) { 'fileInfo.remoteSource' => 'Źródło zdalne', 'fileInfo.infiniteStream' => 'Nieskończony strumień', 'fileInfo.directPlay' => 'Odtwarzanie bezpośrednie', @@ -3983,12 +3975,12 @@ extension on TranslationsPl { 'libraries.filterCategories.contentRating' => 'Klasyfikacja wiekowa', 'libraries.filterCategories.tag' => 'Tag', 'libraries.filterCategories.unwatched' => 'Nieobejrzane', - _ => null, - } ?? switch (path) { 'libraries.filterCategories.unplayed' => 'Nieodtworzone', 'libraries.filterCategories.favorites' => 'Ulubione', 'libraries.sortLabels.title' => 'Tytuł', 'libraries.sortLabels.dateAdded' => 'Data dodania', + _ => null, + } ?? switch (path) { 'libraries.sortLabels.releaseDate' => 'Data premiery', 'libraries.sortLabels.rating' => 'Ocena', 'libraries.sortLabels.communityRating' => 'Ocena społeczności', @@ -4497,12 +4489,12 @@ extension on TranslationsPl { 'downloads.syncRuleCleanupUnavailable' => 'Nie udało się bezpiecznie zidentyfikować powiązanych pobrań. Połącz się ponownie z serwerem i spróbuj ponownie albo usuń regułę bez usuwania pobrań.', 'downloads.syncedNewEpisodes' => ({required Object count, required Object title}) => 'Zsynchronizowano ${count} nowych odcinków dla ${title}', 'downloads.activeSyncRules' => 'Reguły synchronizacji', - _ => null, - } ?? switch (path) { 'downloads.noSyncRules' => 'Brak reguł synchronizacji', 'downloads.manageSyncRule' => 'Zarządzaj synchronizacją', 'downloads.editEpisodeCount' => 'Liczba odcinków', 'downloads.editSyncFilter' => 'Filtr synchronizacji', + _ => null, + } ?? switch (path) { 'downloads.syncAllItems' => 'Synchronizacja wszystkich elementów', 'downloads.syncUnwatchedItems' => 'Synchronizacja nieobejrzanych elementów', 'downloads.syncRuleServerContext' => ({required Object server, required Object status}) => 'Serwer: ${server} • ${status}', diff --git a/lib/i18n/strings_pt.g.dart b/lib/i18n/strings_pt.g.dart index 9380acadc..9ddd01158 100644 --- a/lib/i18n/strings_pt.g.dart +++ b/lib/i18n/strings_pt.g.dart @@ -380,10 +380,6 @@ class _Translations$settings$pt extends Translations$settings$en { @override String get autoPlayNextEpisodeDescription => 'Iniciar o próximo episódio automaticamente quando um terminar'; @override String get playNextCountdown => 'Contagem regressiva do próximo episódio'; @override String get playNextCountdownImmediate => 'Reproduzir imediatamente'; - @override String get autoSkipIntro => 'Pular introdução automaticamente'; - @override String get autoSkipIntroDescription => 'Pular marcadores de introdução automaticamente após alguns segundos'; - @override String get autoSkipCredits => 'Pular créditos automaticamente'; - @override String get autoSkipCreditsDescription => 'Pular os créditos automaticamente e reproduzir o próximo episódio'; @override String get forceSkipMarkerFallback => 'Forçar marcadores alternativos'; @override String get forceSkipMarkerFallbackDescription => 'Usar padrões de títulos de capítulos mesmo quando o Plex tiver marcadores'; @override String get autoSkipDelay => 'Atraso para pular automaticamente'; @@ -3194,10 +3190,6 @@ extension on TranslationsPt { 'settings.autoPlayNextEpisodeDescription' => 'Iniciar o próximo episódio automaticamente quando um terminar', 'settings.playNextCountdown' => 'Contagem regressiva do próximo episódio', 'settings.playNextCountdownImmediate' => 'Reproduzir imediatamente', - 'settings.autoSkipIntro' => 'Pular introdução automaticamente', - 'settings.autoSkipIntroDescription' => 'Pular marcadores de introdução automaticamente após alguns segundos', - 'settings.autoSkipCredits' => 'Pular créditos automaticamente', - 'settings.autoSkipCreditsDescription' => 'Pular os créditos automaticamente e reproduzir o próximo episódio', 'settings.forceSkipMarkerFallback' => 'Forçar marcadores alternativos', 'settings.forceSkipMarkerFallbackDescription' => 'Usar padrões de títulos de capítulos mesmo quando o Plex tiver marcadores', 'settings.autoSkipDelay' => 'Atraso para pular automaticamente', @@ -3449,12 +3441,12 @@ extension on TranslationsPt { 'fileInfo.has64bitOffsets' => 'Deslocamentos de 64 bits', 'fileInfo.protocol' => 'Protocolo', 'fileInfo.mediaType' => 'Tipo de mídia', - _ => null, - } ?? switch (path) { 'fileInfo.sourceKind' => 'Tipo de origem', 'fileInfo.optimizedVersion' => 'Versão otimizada', 'fileInfo.optimizationTarget' => 'Alvo de otimização', 'fileInfo.deletedAt' => 'Excluído', + _ => null, + } ?? switch (path) { 'fileInfo.remoteSource' => 'Origem remota', 'fileInfo.infiniteStream' => 'Fluxo infinito', 'fileInfo.directPlay' => 'Reprodução direta', @@ -3963,12 +3955,12 @@ extension on TranslationsPt { 'libraries.filterCategories.contentRating' => 'Classificação indicativa', 'libraries.filterCategories.tag' => 'Tag', 'libraries.filterCategories.unwatched' => 'Não assistidos', - _ => null, - } ?? switch (path) { 'libraries.filterCategories.unplayed' => 'Não reproduzidos', 'libraries.filterCategories.favorites' => 'Favoritos', 'libraries.sortLabels.title' => 'Título', 'libraries.sortLabels.dateAdded' => 'Data de adição', + _ => null, + } ?? switch (path) { 'libraries.sortLabels.releaseDate' => 'Data de lançamento', 'libraries.sortLabels.rating' => 'Avaliação', 'libraries.sortLabels.communityRating' => 'Avaliação da comunidade', @@ -4477,12 +4469,12 @@ extension on TranslationsPt { 'downloads.syncRuleCleanupUnavailable' => 'Os downloads associados não puderam ser identificados com segurança. Reconecte o servidor e tente novamente, ou remova a regra sem excluir os downloads.', 'downloads.syncedNewEpisodes' => ({required Object count, required Object title}) => '${count} novos episódios sincronizados para ${title}', 'downloads.activeSyncRules' => 'Regras de sincronização', - _ => null, - } ?? switch (path) { 'downloads.noSyncRules' => 'Nenhuma regra de sincronização', 'downloads.manageSyncRule' => 'Gerenciar sincronização', 'downloads.editEpisodeCount' => 'Número de episódios', 'downloads.editSyncFilter' => 'Filtro de sincronização', + _ => null, + } ?? switch (path) { 'downloads.syncAllItems' => 'Sincronizando todos os itens', 'downloads.syncUnwatchedItems' => 'Sincronizando itens não assistidos', 'downloads.syncRuleServerContext' => ({required Object server, required Object status}) => 'Servidor: ${server} • ${status}', diff --git a/lib/i18n/strings_ru.g.dart b/lib/i18n/strings_ru.g.dart index 417e610fa..7d20d04fe 100644 --- a/lib/i18n/strings_ru.g.dart +++ b/lib/i18n/strings_ru.g.dart @@ -380,10 +380,6 @@ class _Translations$settings$ru extends Translations$settings$en { @override String get autoPlayNextEpisodeDescription => 'Автоматически запускать следующий эпизод, когда заканчивается текущий'; @override String get playNextCountdown => 'Обратный отсчёт перед следующим'; @override String get playNextCountdownImmediate => 'Воспроизводить сразу'; - @override String get autoSkipIntro => 'Автопропуск вступления'; - @override String get autoSkipIntroDescription => 'Автоматически пропускать маркеры вступления через несколько секунд'; - @override String get autoSkipCredits => 'Автопропуск титров'; - @override String get autoSkipCreditsDescription => 'Автоматически пропускать титры и воспроизводить следующий эпизод'; @override String get forceSkipMarkerFallback => 'Всегда использовать резервные маркеры'; @override String get forceSkipMarkerFallbackDescription => 'Использовать шаблоны названий глав, даже если в Plex есть собственные маркеры'; @override String get autoSkipDelay => 'Задержка автопропуска'; @@ -3214,10 +3210,6 @@ extension on TranslationsRu { 'settings.autoPlayNextEpisodeDescription' => 'Автоматически запускать следующий эпизод, когда заканчивается текущий', 'settings.playNextCountdown' => 'Обратный отсчёт перед следующим', 'settings.playNextCountdownImmediate' => 'Воспроизводить сразу', - 'settings.autoSkipIntro' => 'Автопропуск вступления', - 'settings.autoSkipIntroDescription' => 'Автоматически пропускать маркеры вступления через несколько секунд', - 'settings.autoSkipCredits' => 'Автопропуск титров', - 'settings.autoSkipCreditsDescription' => 'Автоматически пропускать титры и воспроизводить следующий эпизод', 'settings.forceSkipMarkerFallback' => 'Всегда использовать резервные маркеры', 'settings.forceSkipMarkerFallbackDescription' => 'Использовать шаблоны названий глав, даже если в Plex есть собственные маркеры', 'settings.autoSkipDelay' => 'Задержка автопропуска', @@ -3469,12 +3461,12 @@ extension on TranslationsRu { 'fileInfo.has64bitOffsets' => '64-битные смещения', 'fileInfo.protocol' => 'Протокол', 'fileInfo.mediaType' => 'Тип медиа', - _ => null, - } ?? switch (path) { 'fileInfo.sourceKind' => 'Тип источника', 'fileInfo.optimizedVersion' => 'Оптимизированная версия', 'fileInfo.optimizationTarget' => 'Цель оптимизации', 'fileInfo.deletedAt' => 'Удалено', + _ => null, + } ?? switch (path) { 'fileInfo.remoteSource' => 'Удалённый источник', 'fileInfo.infiniteStream' => 'Бесконечный поток', 'fileInfo.directPlay' => 'Прямое воспроизведение', @@ -3983,12 +3975,12 @@ extension on TranslationsRu { 'libraries.filterCategories.contentRating' => 'Возрастной рейтинг', 'libraries.filterCategories.tag' => 'Тег', 'libraries.filterCategories.unwatched' => 'Непросмотренные', - _ => null, - } ?? switch (path) { 'libraries.filterCategories.unplayed' => 'Не прослушано', 'libraries.filterCategories.favorites' => 'Избранное', 'libraries.sortLabels.title' => 'Название', 'libraries.sortLabels.dateAdded' => 'Дата добавления', + _ => null, + } ?? switch (path) { 'libraries.sortLabels.releaseDate' => 'Дата выхода', 'libraries.sortLabels.rating' => 'Рейтинг', 'libraries.sortLabels.communityRating' => 'Оценка сообщества', @@ -4497,12 +4489,12 @@ extension on TranslationsRu { 'downloads.syncRuleCleanupUnavailable' => 'Не удалось надёжно определить связанные загрузки. Переподключите сервер и повторите попытку либо удалите правило без удаления загрузок.', 'downloads.syncedNewEpisodes' => ({required Object count, required Object title}) => 'Синхронизировано ${count} новых эпизодов для ${title}', 'downloads.activeSyncRules' => 'Правила синхронизации', - _ => null, - } ?? switch (path) { 'downloads.noSyncRules' => 'Нет правил синхронизации', 'downloads.manageSyncRule' => 'Управление синхронизацией', 'downloads.editEpisodeCount' => 'Количество эпизодов', 'downloads.editSyncFilter' => 'Фильтр синхронизации', + _ => null, + } ?? switch (path) { 'downloads.syncAllItems' => 'Синхронизация всех элементов', 'downloads.syncUnwatchedItems' => 'Синхронизация непросмотренных элементов', 'downloads.syncRuleServerContext' => ({required Object server, required Object status}) => 'Сервер: ${server} • ${status}', diff --git a/lib/i18n/strings_sv.g.dart b/lib/i18n/strings_sv.g.dart index 943dc82d6..050a7e1ff 100644 --- a/lib/i18n/strings_sv.g.dart +++ b/lib/i18n/strings_sv.g.dart @@ -380,10 +380,6 @@ class _Translations$settings$sv extends Translations$settings$en { @override String get autoPlayNextEpisodeDescription => 'Starta nästa avsnitt automatiskt när det aktuella avsnittet slutar'; @override String get playNextCountdown => 'Nedräkning för nästa avsnitt'; @override String get playNextCountdownImmediate => 'Spela direkt'; - @override String get autoSkipIntro => 'Hoppa över intro automatiskt'; - @override String get autoSkipIntroDescription => 'Hoppa automatiskt över intromarkörer efter några sekunder'; - @override String get autoSkipCredits => 'Hoppa över eftertexter automatiskt'; - @override String get autoSkipCreditsDescription => 'Hoppa automatiskt över eftertexterna och spela nästa avsnitt'; @override String get forceSkipMarkerFallback => 'Tvinga reservmarkörer'; @override String get forceSkipMarkerFallbackDescription => 'Använd mönster i kapiteltitlar även när Plex har markörer'; @override String get autoSkipDelay => 'Fördröjning före automatiskt hopp'; @@ -3194,10 +3190,6 @@ extension on TranslationsSv { 'settings.autoPlayNextEpisodeDescription' => 'Starta nästa avsnitt automatiskt när det aktuella avsnittet slutar', 'settings.playNextCountdown' => 'Nedräkning för nästa avsnitt', 'settings.playNextCountdownImmediate' => 'Spela direkt', - 'settings.autoSkipIntro' => 'Hoppa över intro automatiskt', - 'settings.autoSkipIntroDescription' => 'Hoppa automatiskt över intromarkörer efter några sekunder', - 'settings.autoSkipCredits' => 'Hoppa över eftertexter automatiskt', - 'settings.autoSkipCreditsDescription' => 'Hoppa automatiskt över eftertexterna och spela nästa avsnitt', 'settings.forceSkipMarkerFallback' => 'Tvinga reservmarkörer', 'settings.forceSkipMarkerFallbackDescription' => 'Använd mönster i kapiteltitlar även när Plex har markörer', 'settings.autoSkipDelay' => 'Fördröjning före automatiskt hopp', @@ -3449,12 +3441,12 @@ extension on TranslationsSv { 'fileInfo.has64bitOffsets' => '64-bitars offsetvärden', 'fileInfo.protocol' => 'Protokoll', 'fileInfo.mediaType' => 'Mediatyp', - _ => null, - } ?? switch (path) { 'fileInfo.sourceKind' => 'Källtyp', 'fileInfo.optimizedVersion' => 'Optimerad version', 'fileInfo.optimizationTarget' => 'Optimeringsmål', 'fileInfo.deletedAt' => 'Raderad', + _ => null, + } ?? switch (path) { 'fileInfo.remoteSource' => 'Fjärrkälla', 'fileInfo.infiniteStream' => 'Oändlig ström', 'fileInfo.directPlay' => 'Direktuppspelning', @@ -3963,12 +3955,12 @@ extension on TranslationsSv { 'libraries.filterCategories.contentRating' => 'Åldersgräns', 'libraries.filterCategories.tag' => 'Tagg', 'libraries.filterCategories.unwatched' => 'Osedda', - _ => null, - } ?? switch (path) { 'libraries.filterCategories.unplayed' => 'Ospelat', 'libraries.filterCategories.favorites' => 'Favoriter', 'libraries.sortLabels.title' => 'Titel', 'libraries.sortLabels.dateAdded' => 'Tillagd', + _ => null, + } ?? switch (path) { 'libraries.sortLabels.releaseDate' => 'Releasedatum', 'libraries.sortLabels.rating' => 'Betyg', 'libraries.sortLabels.communityRating' => 'Användarbetyg', @@ -4477,12 +4469,12 @@ extension on TranslationsSv { 'downloads.syncRuleCleanupUnavailable' => 'Associerade nedladdningar kunde inte identifieras på ett säkert sätt. Återanslut servern och försök igen, eller ta bort regeln utan att ta bort nedladdningar.', 'downloads.syncedNewEpisodes' => ({required Object count, required Object title}) => 'Synkroniserade ${count} nya avsnitt för ${title}', 'downloads.activeSyncRules' => 'Synkregler', - _ => null, - } ?? switch (path) { 'downloads.noSyncRules' => 'Inga synkregler', 'downloads.manageSyncRule' => 'Hantera synkronisering', 'downloads.editEpisodeCount' => 'Antal avsnitt', 'downloads.editSyncFilter' => 'Synkroniseringsfilter', + _ => null, + } ?? switch (path) { 'downloads.syncAllItems' => 'Synkroniserar alla objekt', 'downloads.syncUnwatchedItems' => 'Synkroniserar osedda objekt', 'downloads.syncRuleServerContext' => ({required Object server, required Object status}) => 'Server: ${server} • ${status}', diff --git a/lib/i18n/strings_tr.g.dart b/lib/i18n/strings_tr.g.dart index d545874e8..e13c50acc 100644 --- a/lib/i18n/strings_tr.g.dart +++ b/lib/i18n/strings_tr.g.dart @@ -380,10 +380,6 @@ class _Translations$settings$tr extends Translations$settings$en { @override String get autoPlayNextEpisodeDescription => 'Bir bölüm bittiğinde sonraki bölümü otomatik başlat'; @override String get playNextCountdown => 'Sonraki Bölüm Geri Sayımı'; @override String get playNextCountdownImmediate => 'Hemen oynat'; - @override String get autoSkipIntro => 'Jeneriği Otomatik Atla'; - @override String get autoSkipIntroDescription => 'Kaç saniye sonra jenerik işaretçilerini otomatik atla'; - @override String get autoSkipCredits => 'Emeği Geçenleri Otomatik Atla'; - @override String get autoSkipCreditsDescription => 'Emeği geçenleri otomatik atla ve sonraki bölümü oynat'; @override String get forceSkipMarkerFallback => 'Yedek İşaretçileri Zorla'; @override String get forceSkipMarkerFallbackDescription => 'Plex işaretçileri olsa bile kısım başlığı kalıplarını kullan'; @override String get autoSkipDelay => 'Otomatik Atlama Gecikmesi'; @@ -3194,10 +3190,6 @@ extension on TranslationsTr { 'settings.autoPlayNextEpisodeDescription' => 'Bir bölüm bittiğinde sonraki bölümü otomatik başlat', 'settings.playNextCountdown' => 'Sonraki Bölüm Geri Sayımı', 'settings.playNextCountdownImmediate' => 'Hemen oynat', - 'settings.autoSkipIntro' => 'Jeneriği Otomatik Atla', - 'settings.autoSkipIntroDescription' => 'Kaç saniye sonra jenerik işaretçilerini otomatik atla', - 'settings.autoSkipCredits' => 'Emeği Geçenleri Otomatik Atla', - 'settings.autoSkipCreditsDescription' => 'Emeği geçenleri otomatik atla ve sonraki bölümü oynat', 'settings.forceSkipMarkerFallback' => 'Yedek İşaretçileri Zorla', 'settings.forceSkipMarkerFallbackDescription' => 'Plex işaretçileri olsa bile kısım başlığı kalıplarını kullan', 'settings.autoSkipDelay' => 'Otomatik Atlama Gecikmesi', @@ -3449,12 +3441,12 @@ extension on TranslationsTr { 'fileInfo.has64bitOffsets' => '64-bit Ofsetler', 'fileInfo.protocol' => 'Protokol', 'fileInfo.mediaType' => 'Medya Türü', - _ => null, - } ?? switch (path) { 'fileInfo.sourceKind' => 'Kaynak Türü', 'fileInfo.optimizedVersion' => 'Optimize Edilmiş Sürüm', 'fileInfo.optimizationTarget' => 'Optimizasyon Hedefi', 'fileInfo.deletedAt' => 'Silindi', + _ => null, + } ?? switch (path) { 'fileInfo.remoteSource' => 'Uzak Kaynak', 'fileInfo.infiniteStream' => 'Sonsuz Akış', 'fileInfo.directPlay' => 'Doğrudan Oynatma', @@ -3963,12 +3955,12 @@ extension on TranslationsTr { 'libraries.filterCategories.contentRating' => 'İçerik Derecelendirmesi', 'libraries.filterCategories.tag' => 'Etiket', 'libraries.filterCategories.unwatched' => 'İzlenmemiş', - _ => null, - } ?? switch (path) { 'libraries.filterCategories.unplayed' => 'Oynatılmamış', 'libraries.filterCategories.favorites' => 'Favoriler', 'libraries.sortLabels.title' => 'Başlık', 'libraries.sortLabels.dateAdded' => 'Ekleme Tarihi', + _ => null, + } ?? switch (path) { 'libraries.sortLabels.releaseDate' => 'Yayınlanma Tarihi', 'libraries.sortLabels.rating' => 'Puan', 'libraries.sortLabels.communityRating' => 'Topluluk Puanı', @@ -4477,12 +4469,12 @@ extension on TranslationsTr { 'downloads.syncRuleCleanupUnavailable' => 'İlişkili indirmeler güvenli biçimde belirlenemedi. Sunucuya yeniden bağlanıp tekrar deneyin veya kuralı indirmeleri silmeden kaldırın.', 'downloads.syncedNewEpisodes' => ({required Object title, required Object count}) => '${title} için ${count} yeni bölüm eşitlendi', 'downloads.activeSyncRules' => 'Eşitleme kuralları', - _ => null, - } ?? switch (path) { 'downloads.noSyncRules' => 'Eşitleme kuralı yok', 'downloads.manageSyncRule' => 'Eşitlemeyi yönet', 'downloads.editEpisodeCount' => 'Bölüm sayısı', 'downloads.editSyncFilter' => 'Eşitleme filtresi', + _ => null, + } ?? switch (path) { 'downloads.syncAllItems' => 'Tüm ögeler eşitleniyor', 'downloads.syncUnwatchedItems' => 'İzlenmeyen ögeler eşitleniyor', 'downloads.syncRuleServerContext' => ({required Object server, required Object status}) => 'Sunucu: ${server} • ${status}', diff --git a/lib/i18n/strings_uz.g.dart b/lib/i18n/strings_uz.g.dart index 38883b319..99bf457af 100644 --- a/lib/i18n/strings_uz.g.dart +++ b/lib/i18n/strings_uz.g.dart @@ -380,10 +380,6 @@ class _Translations$settings$uz extends Translations$settings$en { @override String get autoPlayNextEpisodeDescription => 'Qism tugagach, keyingisini avtomatik ijro etish'; @override String get playNextCountdown => 'Keyingi qism sanogʻi'; @override String get playNextCountdownImmediate => 'Darhol ijro etish'; - @override String get autoSkipIntro => 'Kirish qismini (Intro) avtomatik oʻtkazish'; - @override String get autoSkipIntroDescription => 'Bir necha soniyadan soʻng kirish qismlarini avtomatik oʻtkazish'; - @override String get autoSkipCredits => 'Titrlarni avtomatik oʻtkazish'; - @override String get autoSkipCreditsDescription => 'Titrlarni oʻtkazib yuborish va keyingi qismni ijro etish'; @override String get forceSkipMarkerFallback => 'Zahira belgilarini majburlash'; @override String get forceSkipMarkerFallbackDescription => 'Plex belgilari boʻlsa ham boʻlim sarlavhasi shablonlaridan foydalanish'; @override String get autoSkipDelay => 'Avtomatik oʻtkazish kechikishi'; @@ -3194,10 +3190,6 @@ extension on TranslationsUz { 'settings.autoPlayNextEpisodeDescription' => 'Qism tugagach, keyingisini avtomatik ijro etish', 'settings.playNextCountdown' => 'Keyingi qism sanogʻi', 'settings.playNextCountdownImmediate' => 'Darhol ijro etish', - 'settings.autoSkipIntro' => 'Kirish qismini (Intro) avtomatik oʻtkazish', - 'settings.autoSkipIntroDescription' => 'Bir necha soniyadan soʻng kirish qismlarini avtomatik oʻtkazish', - 'settings.autoSkipCredits' => 'Titrlarni avtomatik oʻtkazish', - 'settings.autoSkipCreditsDescription' => 'Titrlarni oʻtkazib yuborish va keyingi qismni ijro etish', 'settings.forceSkipMarkerFallback' => 'Zahira belgilarini majburlash', 'settings.forceSkipMarkerFallbackDescription' => 'Plex belgilari boʻlsa ham boʻlim sarlavhasi shablonlaridan foydalanish', 'settings.autoSkipDelay' => 'Avtomatik oʻtkazish kechikishi', @@ -3449,12 +3441,12 @@ extension on TranslationsUz { 'fileInfo.has64bitOffsets' => '64-bitli siljishlar', 'fileInfo.protocol' => 'Protokol', 'fileInfo.mediaType' => 'Media turi', - _ => null, - } ?? switch (path) { 'fileInfo.sourceKind' => 'Manba turi', 'fileInfo.optimizedVersion' => 'Optimallashtirilgan versiya', 'fileInfo.optimizationTarget' => 'Optimallashtirish maqsadi', 'fileInfo.deletedAt' => 'Oʻchirilgan', + _ => null, + } ?? switch (path) { 'fileInfo.remoteSource' => 'Masofaviy manba', 'fileInfo.infiniteStream' => 'Cheksiz oqim', 'fileInfo.directPlay' => 'Toʻgʻridan-toʻgʻri ijro', @@ -3963,12 +3955,12 @@ extension on TranslationsUz { 'libraries.filterCategories.contentRating' => 'Kontent reytingi', 'libraries.filterCategories.tag' => 'Teg', 'libraries.filterCategories.unwatched' => 'Koʻrilmagan', - _ => null, - } ?? switch (path) { 'libraries.filterCategories.unplayed' => 'Eshitilmagan', 'libraries.filterCategories.favorites' => 'Tanlanganlar', 'libraries.sortLabels.title' => 'Nomi', 'libraries.sortLabels.dateAdded' => 'Qoʻshilgan sanasi', + _ => null, + } ?? switch (path) { 'libraries.sortLabels.releaseDate' => 'Chıqqan sanasi', 'libraries.sortLabels.rating' => 'Reyting', 'libraries.sortLabels.communityRating' => 'Hamjamiyat reytingi', @@ -4477,12 +4469,12 @@ extension on TranslationsUz { 'downloads.syncRuleCleanupUnavailable' => 'Bogʻliq yuklamalarni xavfsiz aniqlab boʻlmadi. Serverga qayta ulanib koʻring yoki yuklamalarni oʻchirmasdan qoidani olib tashlang.', 'downloads.syncedNewEpisodes' => ({required Object title, required Object count}) => '${title} uchun ${count} yangi qism sinxronlandi', 'downloads.activeSyncRules' => 'Faol sinxronlash qoidalari', - _ => null, - } ?? switch (path) { 'downloads.noSyncRules' => 'Sinxronlash qoidalari yoʻq', 'downloads.manageSyncRule' => 'Sinxronlashni boshqarish', 'downloads.editEpisodeCount' => 'Qismlar soni', 'downloads.editSyncFilter' => 'Sinxronlash filtri', + _ => null, + } ?? switch (path) { 'downloads.syncAllItems' => 'Barcha elementlar sinxronlanadi', 'downloads.syncUnwatchedItems' => 'Koʻrilmagan elementlar sinxronlanadi', 'downloads.syncRuleServerContext' => ({required Object server, required Object status}) => 'Server: ${server} • ${status}', diff --git a/lib/i18n/strings_zh.g.dart b/lib/i18n/strings_zh.g.dart index 202df3da1..76e0bdb66 100644 --- a/lib/i18n/strings_zh.g.dart +++ b/lib/i18n/strings_zh.g.dart @@ -380,10 +380,6 @@ class Translations$settings$zh extends Translations$settings$en { @override String get autoPlayNextEpisodeDescription => '当前剧集结束时自动播放下一集'; @override String get playNextCountdown => '播放下一集倒计时'; @override String get playNextCountdownImmediate => '立即播放'; - @override String get autoSkipIntro => '自动跳过片头'; - @override String get autoSkipIntroDescription => '几秒钟后自动跳过片头标记'; - @override String get autoSkipCredits => '自动跳过片尾'; - @override String get autoSkipCreditsDescription => '自动跳过片尾并播放下一集'; @override String get forceSkipMarkerFallback => '强制使用备用标记'; @override String get forceSkipMarkerFallbackDescription => '即使 Plex 有标记,也使用章节标题模式'; @override String get autoSkipDelay => '自动跳过延迟'; @@ -3184,10 +3180,6 @@ extension on TranslationsZh { 'settings.autoPlayNextEpisodeDescription' => '当前剧集结束时自动播放下一集', 'settings.playNextCountdown' => '播放下一集倒计时', 'settings.playNextCountdownImmediate' => '立即播放', - 'settings.autoSkipIntro' => '自动跳过片头', - 'settings.autoSkipIntroDescription' => '几秒钟后自动跳过片头标记', - 'settings.autoSkipCredits' => '自动跳过片尾', - 'settings.autoSkipCreditsDescription' => '自动跳过片尾并播放下一集', 'settings.forceSkipMarkerFallback' => '强制使用备用标记', 'settings.forceSkipMarkerFallbackDescription' => '即使 Plex 有标记,也使用章节标题模式', 'settings.autoSkipDelay' => '自动跳过延迟', @@ -3439,12 +3431,12 @@ extension on TranslationsZh { 'fileInfo.has64bitOffsets' => '64 位偏移量', 'fileInfo.protocol' => '协议', 'fileInfo.mediaType' => '媒体类型', - _ => null, - } ?? switch (path) { 'fileInfo.sourceKind' => '来源类型', 'fileInfo.optimizedVersion' => '优化版本', 'fileInfo.optimizationTarget' => '优化目标', 'fileInfo.deletedAt' => '已删除', + _ => null, + } ?? switch (path) { 'fileInfo.remoteSource' => '远程来源', 'fileInfo.infiniteStream' => '无限流', 'fileInfo.directPlay' => '直接播放', @@ -3953,12 +3945,12 @@ extension on TranslationsZh { 'libraries.filterCategories.contentRating' => '内容分级', 'libraries.filterCategories.tag' => '标签', 'libraries.filterCategories.unwatched' => '未观看', - _ => null, - } ?? switch (path) { 'libraries.filterCategories.unplayed' => '未播放', 'libraries.filterCategories.favorites' => '收藏夹', 'libraries.sortLabels.title' => '标题', 'libraries.sortLabels.dateAdded' => '添加日期', + _ => null, + } ?? switch (path) { 'libraries.sortLabels.releaseDate' => '发行日期', 'libraries.sortLabels.rating' => '评分', 'libraries.sortLabels.communityRating' => '社区评分', @@ -4467,12 +4459,12 @@ extension on TranslationsZh { 'downloads.syncRuleCleanupUnavailable' => '无法安全识别相关下载。请重新连接服务器后再试,或在不删除下载的情况下移除规则。', 'downloads.syncedNewEpisodes' => ({required Object title, required Object count}) => '已为 ${title} 同步 ${count} 个新剧集', 'downloads.activeSyncRules' => '同步规则', - _ => null, - } ?? switch (path) { 'downloads.noSyncRules' => '没有同步规则', 'downloads.manageSyncRule' => '管理同步', 'downloads.editEpisodeCount' => '剧集数量', 'downloads.editSyncFilter' => '同步筛选', + _ => null, + } ?? switch (path) { 'downloads.syncAllItems' => '同步所有项目', 'downloads.syncUnwatchedItems' => '同步未观看项目', 'downloads.syncRuleServerContext' => ({required Object server, required Object status}) => '服务器:${server} • ${status}', diff --git a/lib/i18n/strings_zh_Hant.g.dart b/lib/i18n/strings_zh_Hant.g.dart index bc974a924..5099d7013 100644 --- a/lib/i18n/strings_zh_Hant.g.dart +++ b/lib/i18n/strings_zh_Hant.g.dart @@ -381,10 +381,6 @@ class _Translations$settings$zh_Hant extends Translations$settings$zh { @override String get autoPlayNextEpisodeDescription => '目前單集結束時自動播放下一集'; @override String get playNextCountdown => '下一集倒數計時'; @override String get playNextCountdownImmediate => '立即播放'; - @override String get autoSkipIntro => '自動跳過片頭'; - @override String get autoSkipIntroDescription => '幾秒鐘後自動跳過片頭標記'; - @override String get autoSkipCredits => '自動跳過片尾'; - @override String get autoSkipCreditsDescription => '自動跳過片尾並播放下一集'; @override String get forceSkipMarkerFallback => '強制使用備用標記'; @override String get forceSkipMarkerFallbackDescription => '即使 Plex 有標記,也強制使用章節標題模式'; @override String get autoSkipDelay => '自動跳過延遲'; @@ -3185,10 +3181,6 @@ extension on TranslationsZhHant { 'settings.autoPlayNextEpisodeDescription' => '目前單集結束時自動播放下一集', 'settings.playNextCountdown' => '下一集倒數計時', 'settings.playNextCountdownImmediate' => '立即播放', - 'settings.autoSkipIntro' => '自動跳過片頭', - 'settings.autoSkipIntroDescription' => '幾秒鐘後自動跳過片頭標記', - 'settings.autoSkipCredits' => '自動跳過片尾', - 'settings.autoSkipCreditsDescription' => '自動跳過片尾並播放下一集', 'settings.forceSkipMarkerFallback' => '強制使用備用標記', 'settings.forceSkipMarkerFallbackDescription' => '即使 Plex 有標記,也強制使用章節標題模式', 'settings.autoSkipDelay' => '自動跳過延遲', @@ -3440,12 +3432,12 @@ extension on TranslationsZhHant { 'fileInfo.has64bitOffsets' => '具 64 位元偏移量', 'fileInfo.protocol' => '通訊協定', 'fileInfo.mediaType' => '媒體類型', - _ => null, - } ?? switch (path) { 'fileInfo.sourceKind' => '來源類型', 'fileInfo.optimizedVersion' => '最佳化版本', 'fileInfo.optimizationTarget' => '最佳化目標', 'fileInfo.deletedAt' => '已刪除', + _ => null, + } ?? switch (path) { 'fileInfo.remoteSource' => '遠端來源', 'fileInfo.infiniteStream' => '無限串流', 'fileInfo.directPlay' => '直接播放', @@ -3954,12 +3946,12 @@ extension on TranslationsZhHant { 'libraries.filterCategories.contentRating' => '分級', 'libraries.filterCategories.tag' => '標籤', 'libraries.filterCategories.unwatched' => '未觀看', - _ => null, - } ?? switch (path) { 'libraries.filterCategories.unplayed' => '未播放', 'libraries.filterCategories.favorites' => '我的最愛', 'libraries.sortLabels.title' => '標題', 'libraries.sortLabels.dateAdded' => '新增日期', + _ => null, + } ?? switch (path) { 'libraries.sortLabels.releaseDate' => '發行日期', 'libraries.sortLabels.rating' => '評分', 'libraries.sortLabels.communityRating' => '社群評分', @@ -4468,12 +4460,12 @@ extension on TranslationsZhHant { 'downloads.syncRuleCleanupUnavailable' => '無法安全地識別相關的下載內容。請重新連線伺服器後再試,或在不刪除下載內容的情況下移除規則。', 'downloads.syncedNewEpisodes' => ({required Object title, required Object count}) => '已為 ${title} 同步 ${count} 個新單集', 'downloads.activeSyncRules' => '同步規則', - _ => null, - } ?? switch (path) { 'downloads.noSyncRules' => '沒有同步規則', 'downloads.manageSyncRule' => '管理同步', 'downloads.editEpisodeCount' => '單集數量', 'downloads.editSyncFilter' => '同步篩選器', + _ => null, + } ?? switch (path) { 'downloads.syncAllItems' => '同步所有項目', 'downloads.syncUnwatchedItems' => '同步未觀看項目', 'downloads.syncRuleServerContext' => ({required Object server, required Object status}) => '伺服器:${server} • ${status}', diff --git a/lib/i18n/sv.i18n.json b/lib/i18n/sv.i18n.json index 68fc7f7ac..d9601c21b 100644 --- a/lib/i18n/sv.i18n.json +++ b/lib/i18n/sv.i18n.json @@ -275,10 +275,17 @@ "autoPlayNextEpisodeDescription": "Starta nästa avsnitt automatiskt när det aktuella avsnittet slutar", "playNextCountdown": "Nedräkning för nästa avsnitt", "playNextCountdownImmediate": "Spela direkt", - "autoSkipIntro": "Hoppa över intro automatiskt", - "autoSkipIntroDescription": "Hoppa automatiskt över intromarkörer efter några sekunder", - "autoSkipCredits": "Hoppa över eftertexter automatiskt", - "autoSkipCreditsDescription": "Hoppa automatiskt över eftertexterna och spela nästa avsnitt", + "skipIntroMode": "", + "skipIntroModeOffDescription": "", + "skipIntroModeButtonDescription": "", + "skipIntroModeAutoDescription": "", + "skipCreditsMode": "", + "skipCreditsModeOffDescription": "", + "skipCreditsModeButtonDescription": "", + "skipCreditsModeAutoDescription": "", + "skipMarkerModeOff": "", + "skipMarkerModeButton": "", + "skipMarkerModeAuto": "", "forceSkipMarkerFallback": "Tvinga reservmarkörer", "forceSkipMarkerFallbackDescription": "Använd mönster i kapiteltitlar även när Plex har markörer", "autoSkipDelay": "Fördröjning före automatiskt hopp", diff --git a/lib/i18n/tr.i18n.json b/lib/i18n/tr.i18n.json index 5c2b21f01..bbab5bdad 100644 --- a/lib/i18n/tr.i18n.json +++ b/lib/i18n/tr.i18n.json @@ -275,10 +275,17 @@ "autoPlayNextEpisodeDescription": "Bir bölüm bittiğinde sonraki bölümü otomatik başlat", "playNextCountdown": "Sonraki Bölüm Geri Sayımı", "playNextCountdownImmediate": "Hemen oynat", - "autoSkipIntro": "Jeneriği Otomatik Atla", - "autoSkipIntroDescription": "Kaç saniye sonra jenerik işaretçilerini otomatik atla", - "autoSkipCredits": "Emeği Geçenleri Otomatik Atla", - "autoSkipCreditsDescription": "Emeği geçenleri otomatik atla ve sonraki bölümü oynat", + "skipIntroMode": "", + "skipIntroModeOffDescription": "", + "skipIntroModeButtonDescription": "", + "skipIntroModeAutoDescription": "", + "skipCreditsMode": "", + "skipCreditsModeOffDescription": "", + "skipCreditsModeButtonDescription": "", + "skipCreditsModeAutoDescription": "", + "skipMarkerModeOff": "", + "skipMarkerModeButton": "", + "skipMarkerModeAuto": "", "forceSkipMarkerFallback": "Yedek İşaretçileri Zorla", "forceSkipMarkerFallbackDescription": "Plex işaretçileri olsa bile kısım başlığı kalıplarını kullan", "autoSkipDelay": "Otomatik Atlama Gecikmesi", diff --git a/lib/i18n/uz.i18n.json b/lib/i18n/uz.i18n.json index c1790c1a5..2c08923da 100644 --- a/lib/i18n/uz.i18n.json +++ b/lib/i18n/uz.i18n.json @@ -275,10 +275,17 @@ "autoPlayNextEpisodeDescription": "Qism tugagach, keyingisini avtomatik ijro etish", "playNextCountdown": "Keyingi qism sanogʻi", "playNextCountdownImmediate": "Darhol ijro etish", - "autoSkipIntro": "Kirish qismini (Intro) avtomatik oʻtkazish", - "autoSkipIntroDescription": "Bir necha soniyadan soʻng kirish qismlarini avtomatik oʻtkazish", - "autoSkipCredits": "Titrlarni avtomatik oʻtkazish", - "autoSkipCreditsDescription": "Titrlarni oʻtkazib yuborish va keyingi qismni ijro etish", + "skipIntroMode": "", + "skipIntroModeOffDescription": "", + "skipIntroModeButtonDescription": "", + "skipIntroModeAutoDescription": "", + "skipCreditsMode": "", + "skipCreditsModeOffDescription": "", + "skipCreditsModeButtonDescription": "", + "skipCreditsModeAutoDescription": "", + "skipMarkerModeOff": "", + "skipMarkerModeButton": "", + "skipMarkerModeAuto": "", "forceSkipMarkerFallback": "Zahira belgilarini majburlash", "forceSkipMarkerFallbackDescription": "Plex belgilari boʻlsa ham boʻlim sarlavhasi shablonlaridan foydalanish", "autoSkipDelay": "Avtomatik oʻtkazish kechikishi", diff --git a/lib/i18n/zh-Hant.i18n.json b/lib/i18n/zh-Hant.i18n.json index 770f97271..5aa9532c3 100644 --- a/lib/i18n/zh-Hant.i18n.json +++ b/lib/i18n/zh-Hant.i18n.json @@ -275,10 +275,17 @@ "autoPlayNextEpisodeDescription": "目前單集結束時自動播放下一集", "playNextCountdown": "下一集倒數計時", "playNextCountdownImmediate": "立即播放", - "autoSkipIntro": "自動跳過片頭", - "autoSkipIntroDescription": "幾秒鐘後自動跳過片頭標記", - "autoSkipCredits": "自動跳過片尾", - "autoSkipCreditsDescription": "自動跳過片尾並播放下一集", + "skipIntroMode": "", + "skipIntroModeOffDescription": "", + "skipIntroModeButtonDescription": "", + "skipIntroModeAutoDescription": "", + "skipCreditsMode": "", + "skipCreditsModeOffDescription": "", + "skipCreditsModeButtonDescription": "", + "skipCreditsModeAutoDescription": "", + "skipMarkerModeOff": "", + "skipMarkerModeButton": "", + "skipMarkerModeAuto": "", "forceSkipMarkerFallback": "強制使用備用標記", "forceSkipMarkerFallbackDescription": "即使 Plex 有標記,也強制使用章節標題模式", "autoSkipDelay": "自動跳過延遲", diff --git a/lib/i18n/zh.i18n.json b/lib/i18n/zh.i18n.json index b0725fce5..264ddd7ec 100644 --- a/lib/i18n/zh.i18n.json +++ b/lib/i18n/zh.i18n.json @@ -275,10 +275,17 @@ "autoPlayNextEpisodeDescription": "当前剧集结束时自动播放下一集", "playNextCountdown": "播放下一集倒计时", "playNextCountdownImmediate": "立即播放", - "autoSkipIntro": "自动跳过片头", - "autoSkipIntroDescription": "几秒钟后自动跳过片头标记", - "autoSkipCredits": "自动跳过片尾", - "autoSkipCreditsDescription": "自动跳过片尾并播放下一集", + "skipIntroMode": "", + "skipIntroModeOffDescription": "", + "skipIntroModeButtonDescription": "", + "skipIntroModeAutoDescription": "", + "skipCreditsMode": "", + "skipCreditsModeOffDescription": "", + "skipCreditsModeButtonDescription": "", + "skipCreditsModeAutoDescription": "", + "skipMarkerModeOff": "", + "skipMarkerModeButton": "", + "skipMarkerModeAuto": "", "forceSkipMarkerFallback": "强制使用备用标记", "forceSkipMarkerFallbackDescription": "即使 Plex 有标记,也使用章节标题模式", "autoSkipDelay": "自动跳过延迟", diff --git a/lib/screens/settings/playback_settings_screen.dart b/lib/screens/settings/playback_settings_screen.dart index eeb7997f4..9d67967d4 100644 --- a/lib/screens/settings/playback_settings_screen.dart +++ b/lib/screens/settings/playback_settings_screen.dart @@ -325,20 +325,19 @@ class _PlaybackSettingsScreenState extends State { min: 0, max: 30, ), - // TODO: Replace the two auto-skip switches below with per-marker skip - // modes — Off / Show button / Auto (#2138); migrate true→auto, - // false→button in SettingsService. - SettingSwitchTile( - pref: SettingsService.autoSkipIntro, + SettingSelectionTile( + pref: SettingsService.skipIntroMode, icon: Symbols.fast_forward_rounded, - title: t.settings.autoSkipIntro, - subtitle: t.settings.autoSkipIntroDescription, + title: t.settings.skipIntroMode, + subtitleBuilder: (mode) => '${_skipMarkerModeLabel(mode)} · ${_skipIntroModeDescription(mode)}', + options: SkipMarkerMode.values.map((m) => DialogOption(value: m, title: _skipMarkerModeLabel(m))).toList(), ), - SettingSwitchTile( - pref: SettingsService.autoSkipCredits, + SettingSelectionTile( + pref: SettingsService.skipCreditsMode, icon: Symbols.skip_next_rounded, - title: t.settings.autoSkipCredits, - subtitle: t.settings.autoSkipCreditsDescription, + title: t.settings.skipCreditsMode, + subtitleBuilder: (mode) => '${_skipMarkerModeLabel(mode)} · ${_skipCreditsModeDescription(mode)}', + options: SkipMarkerMode.values.map((m) => DialogOption(value: m, title: _skipMarkerModeLabel(m))).toList(), ), SettingSwitchTile( pref: SettingsService.forceSkipMarkerFallback, @@ -373,6 +372,24 @@ class _PlaybackSettingsScreenState extends State { ], ); + String _skipMarkerModeLabel(SkipMarkerMode mode) => switch (mode) { + SkipMarkerMode.off => t.settings.skipMarkerModeOff, + SkipMarkerMode.button => t.settings.skipMarkerModeButton, + SkipMarkerMode.auto => t.settings.skipMarkerModeAuto, + }; + + String _skipIntroModeDescription(SkipMarkerMode mode) => switch (mode) { + SkipMarkerMode.off => t.settings.skipIntroModeOffDescription, + SkipMarkerMode.button => t.settings.skipIntroModeButtonDescription, + SkipMarkerMode.auto => t.settings.skipIntroModeAutoDescription, + }; + + String _skipCreditsModeDescription(SkipMarkerMode mode) => switch (mode) { + SkipMarkerMode.off => t.settings.skipCreditsModeOffDescription, + SkipMarkerMode.button => t.settings.skipCreditsModeButtonDescription, + SkipMarkerMode.auto => t.settings.skipCreditsModeAutoDescription, + }; + /// Optional touch gestures on the player surface (#1810); the group only /// renders on mobile, matching where the gestures exist. Widget _gesturesGroup() => SettingsGroup( diff --git a/lib/services/settings_service.dart b/lib/services/settings_service.dart index 8ab53d8e5..eb8c8a8eb 100644 --- a/lib/services/settings_service.dart +++ b/lib/services/settings_service.dart @@ -101,6 +101,19 @@ enum SpecialsOrdering { specialsLast, } +/// What the player does when playback enters an intro or credits marker. +/// One pref per marker kind (#2138). +enum SkipMarkerMode { + /// Play through: no skip button, no countdown. The marker is invisible. + off, + + /// Show the skip button; the viewer decides. + button, + + /// Show the button and skip on its own after [SettingsService.autoSkipDelay]. + auto, +} + enum SubAssOverride { no, yes, scale, force, strip } /// Resolution ASS/image subtitles are rasterized at. @@ -161,6 +174,8 @@ const String _legacyDemuxerModeKey = 'demuxer_mode'; const String _legacyUseSeasonPosterKey = 'use_season_poster'; const String _legacyMpvConfigEntriesKey = 'mpv_config_entries'; const String _legacyUseExoPlayerKey = 'use_exoplayer'; +const String _legacyAutoSkipIntroKey = 'auto_skip_intro'; +const String _legacyAutoSkipCreditsKey = 'auto_skip_credits'; /// Migrates from the legacy enum-string format and clamps to 1..5. class _LibraryDensityPref extends Pref { @@ -237,6 +252,27 @@ class _EpisodePosterModePref extends EnumPref { } } +/// Migrates from the legacy `auto_skip_*` booleans: on → [SkipMarkerMode.auto], +/// off → [SkipMarkerMode.button], which is what each used to mean. +class _SkipMarkerModePref extends EnumPref { + final String legacyKey; + + const _SkipMarkerModePref(super.key, {required this.legacyKey}) + : super(values: SkipMarkerMode.values, defaultValue: SkipMarkerMode.button); + + @override + SkipMarkerMode readFrom(BaseSharedPreferencesService svc) { + final legacyValue = svc.readNullableBool(legacyKey); + if (legacyValue != null) { + final migrated = legacyValue ? SkipMarkerMode.auto : SkipMarkerMode.button; + svc.prefs.remove(legacyKey); + svc.prefs.setString(key, migrated.name); + return migrated; + } + return super.readFrom(svc); + } +} + /// Stored as the locale enum name; null/empty falls back to the device locale. class _AppLocalePref extends Pref { const _AppLocalePref() : super('app_locale'); @@ -486,8 +522,8 @@ class SettingsService extends BaseSharedPreferencesService { static const followServerTrackSelections = BoolPref('follow_server_track_selections'); static const showChapterMarkersOnTimeline = BoolPref('show_chapter_markers_on_timeline', defaultValue: true); static const clickVideoTogglesPlayback = BoolPref('click_video_toggles_playback'); - static const autoSkipIntro = BoolPref('auto_skip_intro'); - static const autoSkipCredits = BoolPref('auto_skip_credits'); + static const skipIntroMode = _SkipMarkerModePref('skip_intro_mode', legacyKey: _legacyAutoSkipIntroKey); + static const skipCreditsMode = _SkipMarkerModePref('skip_credits_mode', legacyKey: _legacyAutoSkipCreditsKey); static const forceSkipMarkerFallback = BoolPref('force_skip_marker_fallback'); static const autoSkipDelay = IntPref('auto_skip_delay', defaultValue: 5); static const introPattern = StringPref('intro_pattern', defaultValue: defaultIntroPattern); @@ -1223,8 +1259,8 @@ class SettingsService extends BaseSharedPreferencesService { subtitleItalic, showChapterMarkersOnTimeline, clickVideoTogglesPlayback, - autoSkipIntro, - autoSkipCredits, + skipIntroMode, + skipCreditsMode, forceSkipMarkerFallback, autoSkipDelay, introPattern, @@ -1271,6 +1307,8 @@ class SettingsService extends BaseSharedPreferencesService { ..._resettablePrefs.map((p) => prefs.remove(p.key)), // Legacy migration sentinels — removed alongside the keys they guarded. prefs.remove(_legacyUseSeasonPosterKey), + prefs.remove(_legacyAutoSkipIntroKey), + prefs.remove(_legacyAutoSkipCreditsKey), prefs.remove(_legacyMpvConfigEntriesKey), prefs.remove(_legacyBufferSizeKey), prefs.remove(_legacyDemuxerModeKey), diff --git a/lib/widgets/video_controls/parts/markers.dart b/lib/widgets/video_controls/parts/markers.dart index 1873295c2..f0aefa830 100644 --- a/lib/widgets/video_controls/parts/markers.dart +++ b/lib/widgets/video_controls/parts/markers.dart @@ -19,6 +19,8 @@ extension _PlexVideoControlsMarkerMethods on _PlexVideoControlsState { MediaMarker? foundMarker; for (final marker in _markers) { + // An Off marker kind plays through as if the server had sent no marker. + if (_skipModeFor(marker) == SkipMarkerMode.off) continue; if (marker.containsPosition(position)) { foundMarker = marker; break; @@ -134,9 +136,7 @@ extension _PlexVideoControlsMarkerMethods on _PlexVideoControlsState { _cancelAutoSkipTimer(); if (!_hasRenderedFirstFrame) return; - final shouldAutoSkip = (marker.isCredits && _autoSkipCredits) || (!marker.isCredits && _autoSkipIntro); - - if (!shouldAutoSkip || _autoSkipDelay <= 0) return; + if (!_shouldAutoSkipForMarker(marker) || _autoSkipDelay <= 0) return; _autoSkipProgress.value = 0.0; const tickDuration = Duration(milliseconds: 200); @@ -213,9 +213,7 @@ extension _PlexVideoControlsMarkerMethods on _PlexVideoControlsState { unawaited(_skipMarker(skipAutoPlayCountdown: skipAutoPlayCountdown)); } - bool _shouldAutoSkipForMarker(MediaMarker marker) { - return (marker.isCredits && _autoSkipCredits) || (!marker.isCredits && _autoSkipIntro); - } + bool _shouldAutoSkipForMarker(MediaMarker marker) => _skipModeFor(marker) == SkipMarkerMode.auto; bool _shouldShowAutoSkip() { if (_currentMarker == null) return false; diff --git a/lib/widgets/video_controls/video_controls.dart b/lib/widgets/video_controls/video_controls.dart index 7deeedfd2..dd247d48f 100644 --- a/lib/widgets/video_controls/video_controls.dart +++ b/lib/widgets/video_controls/video_controls.dart @@ -856,9 +856,9 @@ class _PlexVideoControlsState extends State StreamSubscription? _completedSubscription; // Position subscription for marker tracking StreamSubscription? _positionSubscription; - // Auto-skip state - bool get _autoSkipIntro => _settings.read(SettingsService.autoSkipIntro); - bool get _autoSkipCredits => _settings.read(SettingsService.autoSkipCredits); + // Skip-marker state + SkipMarkerMode _skipModeFor(MediaMarker marker) => + _settings.read(marker.isCredits ? SettingsService.skipCreditsMode : SettingsService.skipIntroMode); int get _autoSkipDelay => _settings.read(SettingsService.autoSkipDelay); Timer? _autoSkipTimer; final ValueNotifier _autoSkipProgress = ValueNotifier(0.0); @@ -946,8 +946,8 @@ class _PlexVideoControlsState extends State SettingsService.scopedPlayerPrefValues, SettingsService.syncOffsetScope, SettingsService.rotationLocked, - SettingsService.autoSkipIntro, - SettingsService.autoSkipCredits, + SettingsService.skipIntroMode, + SettingsService.skipCreditsMode, SettingsService.autoSkipDelay, SettingsService.videoPlayerNavigationEnabled, SettingsService.showPerformanceOverlay, @@ -955,6 +955,10 @@ class _PlexVideoControlsState extends State SettingsService.clickVideoTogglesPlayback, SettingsService.showChapterMarkersOnTimeline, ]); + // A marker kind switched Off while inside one of its markers must drop the + // prompt now, not on the next position tick (paused playback never ticks). + bindEffect(SettingsService.skipIntroMode, (_) => _syncCurrentMarkerForCurrentPosition(), fireImmediately: false); + bindEffect(SettingsService.skipCreditsMode, (_) => _syncCurrentMarkerForCurrentPosition(), fireImmediately: false); widget.chromeController.addListener(_onChromeChanged); _configureChromeController(); widget.chromeController.setPlaying(widget.player.state.playing); diff --git a/test/services/settings_service_test.dart b/test/services/settings_service_test.dart index 57daa1c88..d013949e3 100644 --- a/test/services/settings_service_test.dart +++ b/test/services/settings_service_test.dart @@ -128,6 +128,33 @@ void main() { }); }); + group('SettingsService skip marker modes', () { + test('default to showing the button, independently per marker kind', () async { + final settings = await SettingsService.getInstance(); + + expect(settings.read(SettingsService.skipIntroMode), SkipMarkerMode.button); + expect(settings.read(SettingsService.skipCreditsMode), SkipMarkerMode.button); + + await settings.write(SettingsService.skipIntroMode, SkipMarkerMode.off); + expect(settings.read(SettingsService.skipIntroMode), SkipMarkerMode.off); + expect(settings.read(SettingsService.skipCreditsMode), SkipMarkerMode.button); + }); + + test('migrate the legacy auto-skip booleans: on → auto, off → button (#2138)', () async { + resetSharedPreferencesForTest(initialAsync: const {'auto_skip_intro': true, 'auto_skip_credits': false}); + final settings = await SettingsService.getInstance(); + + expect(settings.read(SettingsService.skipIntroMode), SkipMarkerMode.auto); + expect(settings.read(SettingsService.skipCreditsMode), SkipMarkerMode.button); + expect(settings.prefs.containsKey('auto_skip_intro'), isFalse, reason: 'migrated once, then forgotten'); + expect(settings.prefs.containsKey('auto_skip_credits'), isFalse); + + // A later explicit choice is not clobbered by a stale legacy key. + await settings.write(SettingsService.skipIntroMode, SkipMarkerMode.off); + expect(settings.read(SettingsService.skipIntroMode), SkipMarkerMode.off); + }); + }); + group('SettingsService music quality', () { test('defaults to original and persists changes by enum name', () async { var settings = await SettingsService.getInstance(); diff --git a/test/widgets/video_controls_select_key_test.dart b/test/widgets/video_controls_select_key_test.dart index 7bad6e65f..f5f5e5628 100644 --- a/test/widgets/video_controls_select_key_test.dart +++ b/test/widgets/video_controls_select_key_test.dart @@ -489,7 +489,7 @@ void main() { // The gesture the feature exists for: "no thanks" while the countdown runs. playerTest('declining stops a running auto-skip countdown', markers: [introMarker], (tester) async { - await settings.write(SettingsService.autoSkipIntro, true); + await settings.write(SettingsService.skipIntroMode, SkipMarkerMode.auto); await showPrompt(tester); await press(tester, LogicalKeyboardKey.gameButtonB); @@ -499,6 +499,45 @@ void main() { expect(screenBackDispositions, isEmpty); }); + // #2138: Off means the marker is invisible — no prompt, no countdown, and + // Back goes straight to the screen because there is nothing to decline. + playerTest('an Off marker kind plays through without a prompt', markers: [introMarker], (tester) async { + await settings.write(SettingsService.skipIntroMode, SkipMarkerMode.off); + player.emitPosition(const Duration(seconds: 15)); + await tester.pump(const Duration(seconds: 10)); + + expect(find.byType(SkipMarkerButton), findsNothing); + expect(player.state.position, const Duration(seconds: 15)); + + await press(tester, LogicalKeyboardKey.gameButtonB); + expect(screenBackDispositions, [PlayerBackDisposition.exitPlayer], reason: 'nothing to decline'); + }); + + playerTest('switching a marker kind Off drops a prompt already up', markers: [introMarker], (tester) async { + await showPrompt(tester); + + await settings.write(SettingsService.skipIntroMode, SkipMarkerMode.off); + await tester.pumpAndSettle(); + + expect(find.byType(SkipMarkerButton), findsNothing); + expect(player.state.position, const Duration(seconds: 15)); + }); + + playerTest( + 'an Off intro does not silence a credits prompt', + markers: [ + introMarker, + MediaMarker(id: 2, type: 'credits', startTimeOffset: 100000, endTimeOffset: 120000), + ], + (tester) async { + await settings.write(SettingsService.skipIntroMode, SkipMarkerMode.off); + player.emitPosition(const Duration(seconds: 110)); + await tester.pumpAndSettle(); + + expect(find.byType(SkipMarkerButton), findsOneWidget); + }, + ); + // The latch covers the button vanishing mid-press, not the chrome rising. // With the OSD up Back belongs to the chrome, so a press that starts under // a bare prompt and ends under the OSD has to be handed back.