Whole Lotta Fixes (Carti reference) - Read description (#202)

* German and Slovak

* Seiike cant do shit dawggggg

* Fix translator credits

* Added safari button for movie view

* Search button for AllBookmarks and AllWatching

* Delete all in download view without opening item (long hold))

* Redo downloadview

* Added Kazakh

* Added Swedish

* Fixed searchview images being squeezed in
This commit is contained in:
50/50 2025-06-17 09:59:50 +02:00 committed by GitHub
parent 53fa2950e6
commit 8420b373b4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 2548 additions and 300 deletions

View file

@ -0,0 +1,390 @@
/* General */
"About" = "Über";
"About Sora" = "Über Sora";
"Active" = "Aktiv";
"Active Downloads" = "Aktive Downloads";
"Actively downloading media can be tracked from here." = "Hier kannst du deine laufenden Downloads verfolgen.";
"Add Module" = "Modul hinzufügen";
"Adjust the number of media items per row in portrait and landscape modes." = "Passe die Anzahl der Medienelemente pro Zeile im Hoch- und Querformat an.";
"Advanced" = "Erweitert";
"AKA Sulfur" = "Alias Sulfur";
"All Bookmarks" = "Alle Lesezeichen";
"All Watching" = "Alle ansehen";
"Also known as Sulfur" = "Auch bekannt als Sulfur";
"AniList" = "AniList";
"AniList ID" = "AniList-ID";
"AniList Match" = "AniList-Zuordnung";
"AniList.co" = "AniList.co";
"Anonymous data is collected to improve the app. No personal information is collected. This can be disabled at any time." = "Anonyme Daten werden gesammelt, um die App zu verbessern. Es werden keine persönlichen Informationen erfasst. Du kannst dies jederzeit deaktivieren.";
"App Info" = "App-Infos";
"App Language" = "App-Sprache";
"App Storage" = "App-Speicher";
"Appearance" = "Darstellung";
/* Alerts and Actions */
"Are you sure you want to clear all cached data? This will help free up storage space." = "Bist du sicher, dass du den Cache leeren möchtest? Dies hilft, Speicherplatz freizugeben.";
"Are you sure you want to delete '%@'?" = "Bist du sicher, dass du '%@' löschen möchtest?";
"Are you sure you want to delete all %1$d episodes in '%2$@'?" = "Bist du sicher, dass du alle %1$d Folgen in '%2$@' löschen möchtest?";
"Are you sure you want to delete all downloaded assets? You can choose to clear only the library while preserving the downloaded files for future use." = "Bist du sicher, dass du alle Downloads löschen möchtest? Du kannst auch nur die Bibliothek leeren und die heruntergeladenen Dateien für später behalten.";
"Are you sure you want to erase all app data? This action cannot be undone." = "Bist du sicher, dass du alle App-Daten löschen möchtest? Diese Aktion kann nicht rückgängig gemacht werden.";
/* Features */
"Background Enabled" = "Hintergrund aktiviert";
"Bookmark items for an easier access later." = "Setze Lesezeichen für späteren schnellen Zugriff.";
"Bookmarks" = "Lesezeichen";
"Bottom Padding" = "Abstand unten";
"Cancel" = "Abbrechen";
"Cellular Quality" = "Qualität (Mobilfunk)";
"Check out some community modules here!" = "Entdecke Community-Module hier!";
"Choose preferred video resolution for WiFi and cellular connections. Higher resolutions use more data but provide better quality. If the exact quality isn't available, the closest option will be selected automatically.\n\nNote: Not all video sources and players support quality selection. This feature works best with HLS streams using the Sora player." = "Wähle deine bevorzugte Videoqualität für WLAN und Mobilfunk. Höhere Qualität verbraucht mehr Daten. Falls nicht verfügbar, wird automatisch die nächstbeste Option gewählt.\n\nHinweis: Nicht alle Quellen unterstützen Qualitätsauswahl. Funktioniert am besten mit HLS-Streams im Sora-Player.";
"Clear" = "Löschen";
"Clear All Downloads" = "Alle Downloads löschen";
"Clear Cache" = "Cache leeren";
"Clear Library Only" = "Nur Bibliothek leeren";
"Clear Logs" = "Logs löschen";
"Click the plus button to add a module!" = "Tippe auf das Plus-Symbol, um ein Modul hinzuzufügen!";
"Continue Watching" = "Weiterschauen";
"Continue Watching Episode %d" = "Folge %d weiterschauen";
"Contributors" = "Mitwirkende";
"Copied to Clipboard" = "In die Zwischenablage kopiert";
"Copy to Clipboard" = "In die Zwischenablage kopieren";
"Copy URL" = "URL kopieren";
/* Episodes */
"%lld Episodes" = "%lld Folgen";
"%lld of %lld" = "%lld von %lld";
"%lld-%lld" = "%lld-%lld";
"%lld%% seen" = "%lld%% gesehen";
"Episode %lld" = "Folge %lld";
"Episodes" = "Folgen";
"Episodes might not be available yet or there could be an issue with the source." = "Die Folgen sind möglicherweise noch nicht verfügbar oder es gibt ein Problem mit der Quelle.";
"Episodes Range" = "Folgenbereich";
/* System */
"cranci1" = "cranci1";
"Dark" = "Dunkel";
"DATA & LOGS" = "DATEN & LOGS";
"Debug" = "Debug";
"Debugging and troubleshooting." = "Fehlersuche und Problembehebung.";
/* Actions */
"Delete" = "Löschen";
"Delete All" = "Alle löschen";
"Delete All Downloads" = "Alle Downloads löschen";
"Delete All Episodes" = "Alle Folgen löschen";
"Delete Download" = "Download löschen";
"Delete Episode" = "Folge löschen";
/* Player */
"Double Tap to Seek" = "Tippe doppelt zum Spulen";
"Double tapping the screen on it's sides will skip with the short tap setting." = "Doppeltippen auf die Bildschirmseiten überspringt entsprechend deiner Einstellung.";
/* Downloads */
"Download" = "Herunterladen";
"Download Episode" = "Folge herunterladen";
"Download Summary" = "Download-Übersicht";
"Download This Episode" = "Diese Folge herunterladen";
"Downloaded" = "Heruntergeladen";
"Downloaded Shows" = "Heruntergeladene Serien";
"Downloading" = "Lädt herunter";
"Downloads" = "Downloads";
/* Settings */
"Enable Analytics" = "Analytik aktivieren";
"Enable Subtitles" = "Untertitel aktivieren";
/* Data Management */
"Erase" = "Löschen";
"Erase all App Data" = "Alle App-Daten löschen";
"Erase App Data" = "App-Daten löschen";
/* Errors */
"Error" = "Fehler";
"Error Fetching Results" = "Fehler beim Laden";
"Errors and critical issues." = "Fehler und kritische Probleme.";
"Failed to load contributors" = "Mitwirkende konnten nicht geladen werden";
/* Features */
"Fetch Episode metadata" = "Folgen-Metadaten abrufen";
"Files Downloaded" = "Dateien heruntergeladen";
"Font Size" = "Schriftgröße";
/* Interface */
"Force Landscape" = "Querformat erzwingen";
"General" = "Allgemein";
"General events and activities." = "Allgemeine Aktivitäten.";
"General Preferences" = "Allgemeine Einstellungen";
"Hide Splash Screen" = "Startbildschirm ausblenden";
"HLS video downloading." = "HLS Video-Downloads.";
"Hold Speed" = "Geschwindigkeit halten";
/* Info */
"Info" = "Info";
"INFOS" = "INFOS";
"Installed Modules" = "Deine Module";
"Interface" = "Oberfläche";
/* Social */
"Join the Discord" = "Tritt unserem Discord-Server bei";
/* Layout */
"Landscape Columns" = "Spalten (Querformat)";
"Language" = "Sprache";
"LESS" = "WENIGER";
/* Library */
"Library" = "Bibliothek";
"License (GPLv3.0)" = "Lizenz (GPLv3.0)";
"Light" = "Hell";
/* Loading States */
"Loading Episode %lld..." = "Lade Folge %lld...";
"Loading logs..." = "Lade Logs...";
"Loading module information..." = "Lade Modulinfos...";
"Loading Stream" = "Stream wird geladen";
/* Logging */
"Log Debug Info" = "Debug-Infos protokollieren";
"Log Filters" = "Log-Filter";
"Log In with AniList" = "Mit AniList anmelden";
"Log In with Trakt" = "Mit Trakt anmelden";
"Log Out from AniList" = "Von AniList abmelden";
"Log Out from Trakt" = "Von Trakt abmelden";
"Log Types" = "Log-Typen";
"Logged in as" = "Angemeldet als";
"Logged in as " = "Angemeldet als ";
/* Logs and Settings */
"Logs" = "Logs";
"Long press Skip" = "Lang drücken zum Überspringen";
"MAIN" = "MAIN";
"Main Developer" = "Hauptentwickler";
"MAIN SETTINGS" = "HAUPTEINSTELLUNGEN";
/* Media Actions */
"Mark All Previous Watched" = "Alle vorherigen als gesehen markieren";
"Mark as Watched" = "Als gesehen markieren";
"Mark Episode as Watched" = "Folge als gesehen markieren";
"Mark Previous Episodes as Watched" = "Vorherige Folgen als gesehen markieren";
"Mark watched" = "Als gesehen markieren";
"Match with AniList" = "Mit AniList abgleichen";
"Match with TMDB" = "Mit TMDB abgleichen";
"Matched ID: %lld" = "Zugeordnete ID: %lld";
"Matched with: %@" = "Abgeglichen mit: %@";
"Max Concurrent Downloads" = "Max. gleichzeitige Downloads";
/* Media Interface */
"Media Grid Layout" = "Medienraster-Layout";
"Media Player" = "Media-Player";
"Media View" = "Medienansicht";
"Metadata Provider" = "Metadaten-Anbieter";
"Metadata Providers Order" = "Reihenfolge der Metadaten-Anbieter";
"Module Removed" = "Modul entfernt";
"Modules" = "Module";
/* Headers */
"MODULES" = "MODULE";
"MORE" = "MEHR";
/* Status Messages */
"No Active Downloads" = "Keine aktiven Downloads";
"No AniList matches found" = "Keine AniList-Übereinstimmungen";
"No Data Available" = "Keine Daten";
"No Downloads" = "Keine Downloads";
"No episodes available" = "Keine Folgen verfügbar";
"No Episodes Available" = "Keine Folgen verfügbar";
"No items to continue watching." = "Keine Inhalte zum Weiterschauen verfügbar.";
"No matches found" = "Keine Übereinstimmungen gefunden";
"No Module Selected" = "Kein Modul ausgewählt";
"No Modules" = "Keine Module";
"No Results Found" = "Keine Ergebnisse";
"No Search Results Found" = "Keine Suchergebnisse";
"Nothing to Continue Watching" = "Keine Inhalte zum Weiterschauen";
/* Notes and Messages */
"Note that the modules will be replaced only if there is a different version string inside the JSON file." = "Beachte, dass Module nur ersetzt werden, wenn in der JSON-Datei eine andere Versionskennung enthalten ist.";
/* Actions */
"OK" = "OK";
"Open Community Library" = "Community-Bibliothek öffnen";
/* External Services */
"Open in AniList" = "In AniList öffnen";
"Original Poster" = "Original-Poster";
/* Playback */
"Paused" = "Pausiert";
"Play" = "Abspielen";
"Player" = "Player";
/* System Messages */
"Please restart the app to apply the language change." = "Starte die App neu, um die Sprache zu ändern.";
"Please select a module from settings" = "Wähle ein Modul in den Einstellungen";
/* Interface */
"Portrait Columns" = "Spalten (Hochformat)";
"Progress bar Marker Color" = "Farbe der Fortschrittsanzeige";
"Provider: %@" = "Anbieter: %@";
/* Queue */
"Queue" = "Warteschlange";
"Queued" = "In Warteschlange";
/* Content */
"Recently watched content will appear here." = "Deine kürzlich angesehenen Inhalte werden hier angezeigt.";
/* Settings */
"Refresh Modules on Launch" = "Module beim Start aktualisieren";
"Refresh Storage Info" = "Speicherinfo aktualisieren";
"Remember Playback speed" = "Wiedergabegeschwindigkeit merken";
/* Actions */
"Remove" = "Entfernen";
"Remove All Cache" = "Cache komplett löschen";
/* File Management */
"Remove All Documents" = "Alle Dokumente löschen";
"Remove Documents" = "Dokumente löschen";
"Remove Downloaded Media" = "Downloads entfernen";
"Remove Downloads" = "Downloads entfernen";
"Remove from Bookmarks" = "Aus Lesezeichen entfernen";
"Remove Item" = "Element entfernen";
/* Support */
"Report an Issue" = "Problem melden";
/* Reset Options */
"Reset" = "Zurücksetzen";
"Reset AniList ID" = "AniList-ID zurücksetzen";
"Reset Episode Progress" = "Folgenfortschritt zurücksetzen";
"Reset progress" = "Fortschritt zurücksetzen";
"Reset Progress" = "Fortschritt zurücksetzen";
/* System */
"Restart Required" = "Neustart erforderlich";
"Running Sora %@ - cranci1" = "Sora %@ - cranci1";
/* Actions */
"Save" = "Speichern";
"Search" = "Suchen";
/* Search */
"Search downloads" = "Downloads durchsuchen";
"Search for something..." = "Suche nach etwas...";
"Search..." = "Suchen...";
/* Content */
"Season %d" = "Staffel %d";
"Season %lld" = "Staffel %lld";
"Segments Color" = "Segmentfarbe";
/* Modules */
"Select Module" = "Modul auswählen";
"Set Custom AniList ID" = "Eigene AniList-ID festlegen";
/* Interface */
"Settings" = "Einstellungen";
"Shadow" = "Schatten";
"Show More (%lld more characters)" = "Mehr anzeigen (%lld Zeichen mehr)";
"Show PiP Button" = "PiP-Taste anzeigen";
"Show Skip 85s Button" = "85s-Überspringen-Taste anzeigen";
"Show Skip Intro / Outro Buttons" = "Intro/Outro-Tasten anzeigen";
"Shows" = "Serien";
"Size (%@)" = "Größe (%@)";
"Skip Settings" = "Überspringen-Einstellungen";
/* Player Features */
"Some features are limited to the Sora and Default player, such as ForceLandscape, holdSpeed and custom time skip increments." = "Einige Funktionen sind auf den Sora- und Standard-Player beschränkt, wie z.B. Querformat erzwingen, Geschwindigkeit halten und individuelle Zeitsprünge.";
/* App Info */
"Sora" = "Sora";
"Sora %@ by cranci1" = "Sora %@ von cranci1";
"Sora and cranci1 are not affiliated with AniList or Trakt in any way.\n\nAlso note that progress updates may not be 100% accurate." = "Sora und cranci1 sind in keiner Weise mit AniList oder Trakt verbunden.\n\nBitte beachte, dass Fortschrittsaktualisierungen möglicherweise nicht zu 100% genau sind.";
"Sora GitHub Repository" = "Sora GitHub-Repository";
"Sora/Sulfur will always remain free with no ADs!" = "Sora/Sulfur bleibt für immer kostenlos und ohne Werbung!";
/* Interface */
"Sort" = "Sortieren";
"Speed Settings" = "Geschwindigkeitseinstellungen";
/* Playback */
"Start Watching" = "Jetzt ansehen";
"Start Watching Episode %d" = "Folge %d starten";
"Storage Used" = "Belegter Speicher";
"Stream" = "Streamen";
"Streaming and video playback." = "Streaming und Videowiedergabe.";
/* Subtitles */
"Subtitle Color" = "Untertitel-Farbe";
"Subtitle Settings" = "Untertitel-Einstellungen";
/* Sync */
"Sync anime progress" = "Anime-Fortschritt syncen";
"Sync TV shows progress" = "Serien-Fortschritt syncen";
/* System */
"System" = "System";
/* Instructions */
"Tap a title to override the current match." = "Tippe einen Titel, um die Zuordnung zu ändern.";
"Tap Skip" = "Tippe zum Überspringen";
"Tap to manage your modules" = "Tippe hier, um deine Module zu verwalten";
"Tap to select a module" = "Tippe hier, um ein Modul auszuwählen";
/* App Information */
"The app cache helps the app load images faster.\n\nClearing the Documents folder will delete all downloaded modules.\n\nDo not erase App Data unless you understand the consequences — it may cause the app to malfunction." = "Der App-Cache hilft, Bilder schneller zu laden.\n\nDas Löschen des Dokumentenordners entfernt alle heruntergeladenen Module.\n\nLösche App-Daten nur, wenn du die Konsequenzen verstehst — dies könnte dazu führen, dass die App nicht mehr richtig funktioniert.";
"The episode range controls how many episodes appear on each page. Episodes are grouped into sets (like 125, 2650, and so on), allowing you to navigate through them more easily.\n\nFor episode metadata, it refers to the episode thumbnail and title, since sometimes it can contain spoilers." = "Der Folgenbereich legt fest, wie viele Folgen pro Seite angezeigt werden. Folgen werden in Gruppen zusammengefasst (z.B. 1-25, 26-50 usw.), um die Navigation zu erleichtern.\n\nFolgen-Metadaten beziehen sich auf Vorschaubilder und Titel, die manchmal Spoiler enthalten können.";
"The module provided only a single episode, this is most likely a movie, so we decided to make separate screens for these cases." = "Das Modul stellt nur eine einzelne Folge bereit, was wahrscheinlich ein Film ist, daher haben wir für diese Fälle separate Ansichten erstellt.";
/* Interface */
"Thumbnails Width" = "Thumbnail-Breite";
"TMDB Match" = "TMDB-Zuordnung";
"Trackers" = "Tracker";
"Trakt" = "Trakt";
"Trakt.tv" = "Trakt.tv";
/* Search */
"Try different keywords" = "Versuche es mit anderen Suchbegriffen";
"Try different search terms" = "Verwende andere Suchbegriffe";
/* Player Controls */
"Two Finger Hold for Pause" = "Halte mit zwei Fingern zum Pausieren";
"Unable to fetch matches. Please try again later." = "Konnte keine Übereinstimmungen abrufen. Bitte versuche es später erneut.";
"Use TMDB Poster Image" = "TMDB-Poster verwenden";
/* Version */
"v%@" = "v%@";
"Video Player" = "Video-Player";
/* Video Settings */
"Video Quality Preferences" = "Videoqualität";
"View All" = "Alle anzeigen";
"Watched" = "Gesehen";
"Why am I not seeing any episodes?" = "Warum werden keine Folgen angezeigt?";
"WiFi Quality" = "Qualität (WLAN)";
/* User Status */
"You are not logged in" = "Du bist nicht angemeldet";
"You have no items saved." = "Du hast keine gespeicherten Elemente.";
"Your downloaded episodes will appear here" = "Deine heruntergeladenen Folgen werden hier angezeigt.";
"Your recently watched content will appear here" = "Deine kürzlich angesehenen Inhalte werden hier angezeigt.";
/* Download Settings */
"Download Settings" = "Download-Einstellungen";
"Max concurrent downloads controls how many episodes can download simultaneously. Higher values may use more bandwidth and device resources." = "Die maximale Anzahl gleichzeitiger Downloads legt fest, wie viele Folgen gleichzeitig heruntergeladen werden können. Höhere Werte können mehr Bandbreite und Geräteleistung beanspruchen.";
"Quality" = "Qualität";
"Max Concurrent Downloads" = "Max. gleichzeitige Downloads";
"Allow Cellular Downloads" = "Downloads über Mobilfunk erlauben";
"Quality Information" = "Qualitäts-Info";
/* Storage */
"Storage Management" = "Speicherverwaltung";
"Storage Used" = "Belegter Speicher";
"Library cleared successfully" = "Bibliothek erfolgreich geleert";
"All downloads deleted successfully" = "Alle Downloads erfolgreich gelöscht";
/* New additions */
"Recent searches" = "Letzte Suchanfragen";
"me frfr" = "Ich, ohne Witz";
"Data" = "Daten";
"Maximum Quality Available" = "Maximal verfügbare Qualität";

View file

@ -0,0 +1,406 @@
/* General */
"About" = "Туралы";
"About Sora" = "Sora туралы";
"Active" = "Белсенді";
"Active Downloads" = "Белсенді жүктеулер";
"Actively downloading media can be tracked from here." = "Белсенді жүктелетін медианы осы жерден бақылауға болады.";
"Add Module" = "Модуль қосу";
"Adjust the number of media items per row in portrait and landscape modes." = "Портрет және альбом режимдерінде қатардағы медиа элементтерінің санын реттеу.";
"Advanced" = "Кеңейтілген";
"AKA Sulfur" = "Sulfur деп те белгілі";
"All Bookmarks" = "Барлық бетбелгілер";
"All Watching" = "Барлық көрілетін";
"Also known as Sulfur" = "Sulfur деп те белгілі";
"AniList" = "AniList";
"AniList ID" = "AniList ID";
"AniList Match" = "AniList сәйкестігі";
"AniList.co" = "AniList.co";
"Anonymous data is collected to improve the app. No personal information is collected. This can be disabled at any time." = "Қолданбаны жақсарту үшін анонимді деректер жиналады. Жеке ақпарат жиналмайды. Мұны кез келген уақытта өшіруге болады.";
"App Info" = "Қолданба ақпараты";
"App Language" = "Қолданба тілі";
"App Storage" = "Қолданба қоймасы";
"Appearance" = "Сыртқы түр";
/* Alerts and Actions */
"Are you sure you want to clear all cached data? This will help free up storage space." = "Барлық кэштелген деректерді өшіруді қалайсыз ба? Бұл қойма орынын босатуға көмектеседі.";
"Are you sure you want to delete '%@'?" = "'%@' жоюды қалайсыз ба?";
"Are you sure you want to delete all %1$d episodes in '%2$@'?" = "'%2$@' ішіндегі барлық %1$d эпизодты жоюды қалайсыз ба?";
"Are you sure you want to delete all downloaded assets? You can choose to clear only the library while preserving the downloaded files for future use." = "Барлық жүктелген активтерді жоюды қалайсыз ба? Жүктелген файлдарды болашақ пайдалану үшін сақтай отырып, тек кітапхананы тазартуды таңдай аласыз.";
"Are you sure you want to erase all app data? This action cannot be undone." = "Барлық қолданба деректерін өшіруді қалайсыз ба? Бұл әрекетті қайтаруға болмайды.";
/* Features */
"Background Enabled" = "Фон қосылған";
"Bookmark items for an easier access later." = "Кейін оңай қол жеткізу үшін элементтерге бетбелгі қою.";
"Bookmarks" = "Бетбелгілер";
"Bottom Padding" = "Төменгі жиек";
"Cancel" = "Болдырмау";
"Cellular Quality" = "Ұялы байланыс сапасы";
"Check out some community modules here!" = "Қауымдастық модульдерін осы жерден қараңыз!";
"Choose preferred video resolution for WiFi and cellular connections. Higher resolutions use more data but provide better quality. If the exact quality isn't available, the closest option will be selected automatically.\n\nNote: Not all video sources and players support quality selection. This feature works best with HLS streams using the Sora player." = "WiFi және ұялы байланыс үшін қалаулы бейне ажыратымдылығын таңдаңыз. Жоғары ажыратымдылық көбірек деректерді пайдаланады, бірақ жақсы сапа береді. Нақты сапа қолжетімді болмаса, ең жақын нұсқа автоматты түрде таңдалады.\n\nЕскерту: Барлық бейне көздері мен ойнатқыштар сапа таңдауды қолдамайды. Бұл мүмкіндік Sora ойнатқышымен HLS ағындарында ең жақсы жұмыс істейді.";
"Clear" = "Тазарту";
"Clear All Downloads" = "Барлық жүктеулерді тазарту";
"Clear Cache" = "Кэшті тазарту";
"Clear Library Only" = "Тек кітапхананы тазарту";
"Clear Logs" = "Журналдарды тазарту";
"Click the plus button to add a module!" = "Модуль қосу үшін плюс түймесін басыңыз!";
"Continue Watching" = "Көруді жалғастыру";
"Continue Watching Episode %d" = "%d эпизодты көруді жалғастыру";
"Contributors" = "Үлес қосушылар";
"Copied to Clipboard" = "Буферге көшірілді";
"Copy to Clipboard" = "Буферге көшіру";
"Copy URL" = "URL көшіру";
/* Episodes */
"%lld Episodes" = "%lld эпизод";
"%lld of %lld" = "%lld / %lld";
"%lld-%lld" = "%lld-%lld";
"%lld%% seen" = "%lld%% көрілді";
"Episode %lld" = "%lld эпизод";
"Episodes" = "Эпизодтар";
"Episodes might not be available yet or there could be an issue with the source." = "Эпизодтар әлі қолжетімді болмауы мүмкін немесе көзде мәселе болуы мүмкін.";
"Episodes Range" = "Эпизодтар ауқымы";
/* System */
"cranci1" = "cranci1";
"Dark" = "Қараңғы";
"DATA & LOGS" = "ДЕРЕКТЕР ЖӘНЕ ЖУРНАЛДАР";
"Debug" = "Жөндеу";
"Debugging and troubleshooting." = "Жөндеу және ақаулықтарды жою.";
/* Actions */
"Delete" = "Жою";
"Delete All" = "Барлығын жою";
"Delete All Downloads" = "Барлық жүктеулерді жою";
"Delete All Episodes" = "Барлық эпизодтарды жою";
"Delete Download" = "Жүктеуді жою";
"Delete Episode" = "Эпизодты жою";
/* Player */
"Double Tap to Seek" = "Іздеу үшін екі рет басу";
"Double tapping the screen on it's sides will skip with the short tap setting." = "Экранның жақтарын екі рет басу қысқа басу параметрімен өткізіп жіберетін болады.";
/* Downloads */
"Download" = "Жүктеу";
"Download Episode" = "Эпизодты жүктеу";
"Download Summary" = "Жүктеу қорытындысы";
"Download This Episode" = "Осы эпизодты жүктеу";
"Downloaded" = "Жүктелді";
"Downloaded Shows" = "Жүктелген шоулар";
"Downloading" = "Жүктелуде";
"Downloads" = "Жүктеулер";
/* Settings */
"Enable Analytics" = "Аналитиканы қосу";
"Enable Subtitles" = "Субтитрлерді қосу";
/* Data Management */
"Erase" = "Өшіру";
"Erase all App Data" = "Барлық қолданба деректерін өшіру";
"Erase App Data" = "Қолданба деректерін өшіру";
/* Errors */
"Error" = "Қате";
"Error Fetching Results" = "Нәтижелерді алуда қате";
"Errors and critical issues." = "Қателер және сыни мәселелер.";
"Failed to load contributors" = "Үлес қосушыларды жүктеу сәтсіз аяқталды";
/* Features */
"Fetch Episode metadata" = "Эпизод метадеректерін алу";
"Files Downloaded" = "Жүктелген файлдар";
"Font Size" = "Қаріп өлшемі";
/* Interface */
"Force Landscape" = "Альбом режимін мәжбүрлеу";
"General" = "Жалпы";
"General events and activities." = "Жалпы оқиғалар мен іс-әрекеттер.";
"General Preferences" = "Жалпы параметрлер";
"Hide Splash Screen" = "Кіріспе экранын жасыру";
"HLS video downloading." = "HLS бейне жүктеу.";
"Hold Speed" = "Ұстау жылдамдығы";
/* Info */
"Info" = "Ақпарат";
"INFOS" = "АҚПАРАТТАР";
"Installed Modules" = "Орнатылған модульдер";
"Interface" = "Интерфейс";
/* Social */
"Join the Discord" = "Discord-қа қосылу";
/* Layout */
"Landscape Columns" = "Альбом бағандары";
"Language" = "Тіл";
"LESS" = "АЗ";
/* Library */
"Library" = "Кітапхана";
"License (GPLv3.0)" = "Лицензия (GPLv3.0)";
"Light" = "Жарық";
/* Loading States */
"Loading Episode %lld..." = "%lld эпизод жүктелуде...";
"Loading logs..." = "Журналдар жүктелуде...";
"Loading module information..." = "Модуль ақпараты жүктелуде...";
"Loading Stream" = "Ағын жүктелуде";
/* Logging */
"Log Debug Info" = "Жөндеу ақпаратын жазу";
"Log Filters" = "Журнал сүзгілері";
"Log In with AniList" = "AniList арқылы кіру";
"Log In with Trakt" = "Trakt арқылы кіру";
"Log Out from AniList" = "AniList-тен шығу";
"Log Out from Trakt" = "Trakt-тен шығу";
"Log Types" = "Журнал түрлері";
"Logged in as" = "Кірген пайдаланушы:";
"Logged in as " = "Кірген пайдаланушы: ";
/* Logs and Settings */
"Logs" = "Журналдар";
"Long press Skip" = "Ұзақ басып өткізу";
"MAIN" = "НЕГІЗГІ";
"Main Developer" = "Негізгі әзірлеуші";
"MAIN SETTINGS" = "НЕГІЗГІ ПАРАМЕТРЛЕР";
/* Media Actions */
"Mark All Previous Watched" = "Алдыңғыларды көрілді деп белгілеу";
"Mark as Watched" = "Көрілді деп белгілеу";
"Mark Episode as Watched" = "Эпизодты көрілді деп белгілеу";
"Mark Previous Episodes as Watched" = "Алдыңғы эпизодтарды көрілді деп белгілеу";
"Mark watched" = "Көрілді деп белгілеу";
"Match with AniList" = "AniList-пен сәйкестендіру";
"Match with TMDB" = "TMDB-мен сәйкестендіру";
"Matched ID: %lld" = "Сәйкестендірілген ID: %lld";
"Matched with: %@" = "Сәйкестендірілді: %@";
"Max Concurrent Downloads" = "Максималды бір мезгілдегі жүктеулер";
/* Media Interface */
"Media Grid Layout" = "Медиа тор орналасуы";
"Media Player" = "Медиа ойнатқыш";
"Media View" = "Медиа көрінісі";
"Metadata Provider" = "Метадерек провайдері";
"Metadata Providers Order" = "Метадерек провайдерлерінің реті";
"Module Removed" = "Модуль жойылды";
"Modules" = "Модульдер";
/* Headers */
"MODULES" = "МОДУЛЬДЕР";
"MORE" = "КӨБІРЕК";
/* Status Messages */
"No Active Downloads" = "Белсенді жүктеулер жоқ";
"No AniList matches found" = "AniList сәйкестіктері табылмады";
"No Data Available" = "Деректер қолжетімді емес";
"No Downloads" = "Жүктеулер жоқ";
"No episodes available" = "Эпизодтар қолжетімді емес";
"No Episodes Available" = "Эпизодтар қолжетімді емес";
"No items to continue watching." = "Көруді жалғастыратын элементтер жоқ.";
"No matches found" = "Сәйкестіктер табылмады";
"No Module Selected" = "Модуль таңдалмады";
"No Modules" = "Модульдер жоқ";
"No Results Found" = "Нәтижелер табылмады";
"No Search Results Found" = "Іздеу нәтижелері табылмады";
"Nothing to Continue Watching" = "Көруді жалғастыратын ешнәрсе жоқ";
/* Notes and Messages */
"Note that the modules will be replaced only if there is a different version string inside the JSON file." = "Модульдер тек JSON файлының ішінде басқа нұсқа жолы болған жағдайда ғана ауыстырылатынын ескеріңіз.";
/* Actions */
"OK" = "Жарайды";
"Open Community Library" = "Қауымдастық кітапханасын ашу";
/* External Services */
"Open in AniList" = "AniList-те ашу";
"Original Poster" = "Түпнұсқа постер";
/* Playback */
"Paused" = "Тоқтатылды";
"Play" = "Ойнату";
"Player" = "Ойнатқыш";
/* System Messages */
"Please restart the app to apply the language change." = "Тіл өзгерісін қолдану үшін қолданбаны қайта іске қосыңыз.";
"Please select a module from settings" = "Параметрлерден модуль таңдаңыз";
/* Interface */
"Portrait Columns" = "Портрет бағандары";
"Progress bar Marker Color" = "Прогресс жолағы белгішесінің түсі";
"Provider: %@" = "Провайдер: %@";
/* Queue */
"Queue" = "Кезек";
"Queued" = "Кезекте";
/* Content */
"Recently watched content will appear here." = "Жақында көрілген мазмұн осы жерде пайда болады.";
/* Settings */
"Refresh Modules on Launch" = "Іске қосу кезінде модульдерді жаңарту";
"Refresh Storage Info" = "Қойма ақпаратын жаңарту";
"Remember Playback speed" = "Ойнату жылдамдығын есте сақтау";
/* Actions */
"Remove" = "Жою";
"Remove All Cache" = "Барлық кэшті жою";
/* File Management */
"Remove All Documents" = "Барлық құжаттарды жою";
"Remove Documents" = "Құжаттарды жою";
"Remove Downloaded Media" = "Жүктелген медианы жою";
"Remove Downloads" = "Жүктеулерді жою";
"Remove from Bookmarks" = "Бетбелгілерден жою";
"Remove Item" = "Элементті жою";
/* Support */
"Report an Issue" = "Мәселе туралы хабарлау";
/* Reset Options */
"Reset" = "Қалпына келтіру";
"Reset AniList ID" = "AniList ID қалпына келтіру";
"Reset Episode Progress" = "Эпизод прогрессін қалпына келтіру";
"Reset progress" = "Прогрессті қалпына келтіру";
"Reset Progress" = "Прогрессті қалпына келтіру";
/* System */
"Restart Required" = "Қайта іске қосу қажет";
"Running Sora %@ - cranci1" = "Sora %@ жұмыс істеп тұр - cranci1";
/* Actions */
"Save" = "Сақтау";
"Search" = "Іздеу";
/* Search */
"Search downloads" = "Жүктеулерді іздеу";
"Search for something..." = "Бір нәрсені іздеу...";
"Search..." = "Іздеу...";
/* Content */
"Season %d" = "%d маусым";
"Season %lld" = "%lld маусым";
"Segments Color" = "Сегменттер түсі";
/* Modules */
"Select Module" = "Модуль таңдау";
"Set Custom AniList ID" = "Пайдаланушы AniList ID орнату";
/* Interface */
"Settings" = "Параметрлер";
"Shadow" = "Көлеңке";
"Show More (%lld more characters)" = "Көбірек көрсету (тағы %lld таңба)";
"Show PiP Button" = "PiP түймесін көрсету";
"Show Skip 85s Button" = "85с өткізу түймесін көрсету";
"Show Skip Intro / Outro Buttons" = "Кіріспе/шығыспаны өткізу түймелерін көрсету";
"Shows" = "Шоулар";
"Size (%@)" = "Өлшем (%@)";
"Skip Settings" = "Өткізу параметрлері";
/* Player Features */
"Some features are limited to the Sora and Default player, such as ForceLandscape, holdSpeed and custom time skip increments." = "Кейбір мүмкіндіктер Sora және Әдепкі ойнатқышпен шектелген, мысалы ForceLandscape, holdSpeed және пайдаланушы уақыт өткізу өсімшелері.";
/* App Info */
"Sora" = "Sora";
"Sora %@ by cranci1" = "Sora %@ - cranci1 әзірлеген";
"Sora and cranci1 are not affiliated with AniList or Trakt in any way.
Also note that progress updates may not be 100% accurate." = "Sora мен cranci1 AniList немесе Trakt-пен ешқандай байланысы жоқ.
Сонымен қатар прогресс жаңартулары 100% дәл болмауы мүмкін.";
"Sora GitHub Repository" = "Sora GitHub репозиторийі";
"Sora/Sulfur will always remain free with no ADs!" = "Sora/Sulfur әрқашан жарнамасыз тегін болып қалады!";
/* Interface */
"Sort" = "Сұрыптау";
"Speed Settings" = "Жылдамдық параметрлері";
/* Playback */
"Start Watching" = "Көруді бастау";
"Start Watching Episode %d" = "%d эпизодты көруді бастау";
"Storage Used" = "Пайдаланылған қойма";
"Stream" = "Ағын";
"Streaming and video playback." = "Ағын және бейне ойнату.";
/* Subtitles */
"Subtitle Color" = "Субтитр түсі";
"Subtitle Settings" = "Субтитр параметрлері";
/* Sync */
"Sync anime progress" = "Аниме прогрессін синхрондау";
"Sync TV shows progress" = "ТВ шоулар прогрессін синхрондау";
/* System */
"System" = "Жүйе";
/* Instructions */
"Tap a title to override the current match." = "Ағымдағы сәйкестікті ауыстыру үшін атауды басыңыз.";
"Tap Skip" = "Өткізуді басу";
"Tap to manage your modules" = "Модульдеріңізді басқару үшін басыңыз";
"Tap to select a module" = "Модуль таңдау үшін басыңыз";
/* App Information */
"The app cache helps the app load images faster.
Clearing the Documents folder will delete all downloaded modules.
Do not erase App Data unless you understand the consequences — it may cause the app to malfunction." = "Қолданба кэші қолданбаға суреттерді жылдам жүктеуге көмектеседі.
Құжаттар қалтасын тазарту барлық жүктелген модульдерді жояды.
Салдарын түсінбесеңіз, қолданба деректерін өшірмеңіз - бұл қолданбаның дұрыс жұмыс істемеуіне әкелуі мүмкін.";
"The episode range controls how many episodes appear on each page. Episodes are grouped into sets (like 125, 2650, and so on), allowing you to navigate through them more easily.
For episode metadata, it refers to the episode thumbnail and title, since sometimes it can contain spoilers." = "Эпизодтар ауқымы әр бетте қанша эпизод пайда болатынын басқарады. Эпизодтар топтарға бөлінеді (125, 2650 сияқты), бұл олар арқылы оңайырақ жүруге мүмкіндік береді.
Эпизод метадеректері үшін бұл эпизодтың кішкене суреті мен атауын білдіреді, өйткені кейде ол спойлерлерді қамтуы мүмкін.";
"The module provided only a single episode, this is most likely a movie, so we decided to make separate screens for these cases." = "Модуль тек бір эпизод ұсынды, бұл ең ықтимал фильм, сондықтан біз осы жағдайлар үшін жеке экрандар жасауды шештік.";
/* Interface */
"Thumbnails Width" = "Кішкене суреттер ені";
"TMDB Match" = "TMDB сәйкестігі";
"Trackers" = "Трекерлер";
"Trakt" = "Trakt";
"Trakt.tv" = "Trakt.tv";
/* Search */
"Try different keywords" = "Басқа кілт сөздерді қолданып көріңіз";
"Try different search terms" = "Басқа іздеу терминдерін қолданып көріңіз";
/* Player Controls */
"Two Finger Hold for Pause" = "Тоқтату үшін екі саусақпен ұстау";
"Unable to fetch matches. Please try again later." = "Сәйкестіктерді алу мүмкін емес. Кейінірек қайталап көріңіз.";
"Use TMDB Poster Image" = "TMDB постер суретін пайдалану";
/* Version */
"v%@" = "v%@";
"Video Player" = "Бейне ойнатқыш";
/* Video Settings */
"Video Quality Preferences" = "Бейне сапасы таңдаулары";
"View All" = "Барлығын көру";
"Watched" = "Көрілді";
"Why am I not seeing any episodes?" = "Неліктен мен ешқандай эпизод көрмеймін?";
"WiFi Quality" = "WiFi сапасы";
/* User Status */
"You are not logged in" = "Сіз кірмегенсіз";
"You have no items saved." = "Сізде сақталған элементтер жоқ.";
"Your downloaded episodes will appear here" = "Жүктелген эпизодтарыңыз осында пайда болады";
"Your recently watched content will appear here" = "Жақында көрген мазмұныңыз осында пайда болады";
/* Download Settings */
"Download Settings" = "Жүктеу параметрлері";
"Max concurrent downloads controls how many episodes can download simultaneously. Higher values may use more bandwidth and device resources." = "Максималды бір мезгілдегі жүктеулер қанша эпизодты бір уақытта жүктеуге болатынын басқарады. Жоғары мәндер көбірек өткізу қабілеті мен құрылғы ресурстарын пайдалануы мүмкін.";
"Quality" = "Сапа";
"Max Concurrent Downloads" = "Максималды бір мезгілдегі жүктеулер";
"Allow Cellular Downloads" = "Ұялы жүктеулерге рұқсат беру";
"Quality Information" = "Сапа ақпараты";
/* Storage */
"Storage Management" = "Қойма басқаруы";
"Storage Used" = "Пайдаланылған қойма";
"Library cleared successfully" = "Кітапхана сәтті тазартылды";
"All downloads deleted successfully" = "Барлық жүктеулер сәтті жойылды";
/* New additions */
"Recent searches" = "Соңғы іздеулер";
"me frfr" = "мен шынында";
"Data" = "Деректер";
"Maximum Quality Available" = "Қолжетімді максималды сапа";

View file

@ -0,0 +1,406 @@
/* General */
"About" = "O aplikácii";
"About Sora" = "O aplikácii Sora";
"Active" = "Aktívne";
"Active Downloads" = "Aktívne sťahovania";
"Actively downloading media can be tracked from here." = "Aktívne preberané médiá môžete sledovať tu.";
"Add Module" = "Pridať modul";
"Adjust the number of media items per row in portrait and landscape modes." = "Nastavte počet mediálnych položiek na riadok v režime na výšku a na šírku.";
"Advanced" = "Pokročilé";
"AKA Sulfur" = "AKA Sulfur";
"All Bookmarks" = "Všetky záložky";
"All Watching" = "Všetky rozpozerané";
"Also known as Sulfur" = "Tiež známe ako Sulfur";
"AniList" = "AniList";
"AniList ID" = "ID AniList";
"AniList Match" = "AniList Match";
"AniList.co" = "AniList.co";
"Anonymous data is collected to improve the app. No personal information is collected. This can be disabled at any time." = "Anonymné údaje sa zbierajú na zlepšenie aplikácie. Žiadne osobné údaje sa nezbierajú. Túto možnosť môžete kedykoľvek vypnúť.";
"App Info" = "Informácie o aplikácii";
"App Language" = "Jazyk aplikácie";
"App Storage" = "Ukladací priestor aplikácie";
"Appearance" = "Vzhľad";
/* Alerts and Actions */
"Are you sure you want to clear all cached data? This will help free up storage space." = "Naozaj chcete vymazať všetku medzipamäť? Pomôže to uvoľniť miesto na disku.";
"Are you sure you want to delete '%@'?" = "Naozaj chcete zmazať '%@'?";
"Are you sure you want to delete all %1\$d episodes in '%2\$@'?" = "Naozaj chcete zmazať všetkých %1\$d epizód v '%2\$@'?";
"Are you sure you want to delete all downloaded assets? You can choose to clear only the library while preserving the downloaded files for future use." = "Naozaj chcete zmazať všetky stiahnuté súbory? Môžete vymazať iba knižnicu a stiahnuté súbory si ponechať.";
"Are you sure you want to erase all app data? This action cannot be undone." = "Naozaj chcete vymazať všetky dáta aplikácie? Túto akciu nie je možné vrátiť späť.";
/* Features */
"Background Enabled" = "V pozadí povolené";
"Bookmark items for an easier access later." = "Označte položky záložkou pre ľahší prístup neskôr.";
"Bookmarks" = "Záložky";
"Bottom Padding" = "Spodná výplň";
"Cancel" = "Zrušiť";
"Cellular Quality" = "Kvalita cez mobilné dáta";
"Check out some community modules here!" = "Prezrite si nejaké komunitou vytvorené moduly tu!";
"Choose preferred video resolution for WiFi and cellular connections. Higher resolutions use more data but provide better quality. If the exact quality isn't available, the closest option will be selected automatically.\n\nNote: Not all video sources and players support quality selection. This feature works best with HLS streams using the Sora player." = "Vyberte preferované video rozlíšenie pre WiFi a mobilné pripojenia. Vyššie rozlíšenia používajú viac dát, ale poskytujú lepšiu kvalitu. Ak presné rozlíšenie nie je dostupné, automaticky sa vyberie najbližšia možnosť.\n\nPoznámka: Nie všetky video zdroje a prehrávače podporujú výber kvality. Táto funkcia funguje najlepšie s HLS streamami pomocou prehrávača Sora.";
"Clear" = "Vymazať";
"Clear All Downloads" = "Vymazať všetky sťiahnuté položky";
"Clear Cache" = "Vymazať medzipamäť";
"Clear Library Only" = "Vymazať len knižnicu";
"Clear Logs" = "Vymazať záznamy";
"Click the plus button to add a module!" = "Kliknite na tlačidlo plus pre pridanie modulu!";
"Continue Watching" = "Pokračovať v sledovaní";
"Continue Watching Episode %d" = "Pokračovať v sledovaní epizódy %d";
"Contributors" = "Prispievatelia";
"Copied to Clipboard" = "Skopírované do schránky";
"Copy to Clipboard" = "Kopírovať do schránky";
"Copy URL" = "Kopírovať URL";
/* Episodes */
"%lld Episodes" = "%lld epizód";
"%lld of %lld" = "%lld z %lld";
"%lld-%lld" = "%lld%lld";
"%lld%% seen" = "%lld%% zhliadnuté";
"Episode %lld" = "Epizóda %lld";
"Episodes" = "Epizódy";
"Episodes might not be available yet or there could be an issue with the source." = "Epizódy môžu byť ešte nedostupné alebo môže byť problém so zdrojom.";
"Episodes Range" = "Rozsah epizód";
/* System */
"cranci1" = "cranci1";
"Dark" = "Tmavé";
"DATA & LOGS" = "DÁTA A ZÁZNAMY";
"Debug" = "Ladenie";
"Debugging and troubleshooting." = "Ladenie a troubleshooting.";
/* Actions */
"Delete" = "Zmazať";
"Delete All" = "Zmazať všetko";
"Delete All Downloads" = "Zmazať všetky preberania";
"Delete All Episodes" = "Zmazať všetky epizódy";
"Delete Download" = "Zmazať preberanie";
"Delete Episode" = "Zmazať epizódu";
/* Player */
"Double Tap to Seek" = "Dvojité klepnutie pre skok";
"Double tapping the screen on it's sides will skip with the short tap setting." = "Dvojité klepnutie na okraje obrazovky preskočí podľa nastavenia krátkeho klepnutia.";
/* Downloads */
"Download" = "Stiahnuť";
"Download Episode" = "Stiahnuť epizódu";
"Download Summary" = "Súhrn sťiahnutých";
"Download This Episode" = "Stiahnuť túto epizódu";
"Downloaded" = "Stiahnuté";
"Downloaded Shows" = "Stiahnuté shows";
"Downloading" = "Sťahuje sa";
"Downloads" = "Sťiahnuté";
/* Settings */
"Enable Analytics" = "Povoliť analytiku";
"Enable Subtitles" = "Povoliť titulky";
/* Data Management */
"Erase" = "Vymazať";
"Erase all App Data" = "Vymazať všetky dáta aplikácie";
"Erase App Data" = "Vymazať dáta aplikácie";
/* Errors */
"Error" = "Chyba";
"Error Fetching Results" = "Chyba pri získavaní výsledkov";
"Errors and critical issues." = "Chyby a kritické problémy.";
"Failed to load contributors" = "Nepodarilo sa načítať prispievateľov";
/* Features */
"Fetch Episode metadata" = "Získať metadata epizódy";
"Files Downloaded" = "Stiahnuté súbory";
"Font Size" = "Veľkosť písma";
/* Interface */
"Force Landscape" = "Vynútiť režim na šírku";
"General" = "Všeobecné";
"General events and activities." = "Všeobecné udalosti a aktivity.";
"General Preferences" = "Všeobecné nastavenia";
"Hide Splash Screen" = "Skryť uvítaciu obrazovku";
"HLS video downloading." = "Sťahovanie HLS videa.";
"Hold Speed" = "Rýchlosť podržania";
/* Info */
"Info" = "Informácie";
"INFOS" = "INFORMÁCIE";
"Installed Modules" = "Inštalované moduly";
"Interface" = "Rozhranie";
/* Social */
"Join the Discord" = "Pripojte sa k nášmu Discordu";
/* Layout */
"Landscape Columns" = "Stĺpce v režime na šírku";
"Language" = "Jazyk";
"LESS" = "MENEJ";
/* Library */
"Library" = "Knižnica";
"License (GPLv3.0)" = "Licencia (GPLv3.0)";
"Light" = "Svetlé";
/* Loading States */
"Loading Episode %lld..." = "Načítava sa epizóda %lld...";
"Loading logs..." = "Načítavajú sa záznamy...";
"Loading module information..." = "Načítavajú sa informácie o module...";
"Loading Stream" = "Načítava sa stream";
/* Logging */
"Log Debug Info" = "Zaznamenať ladacie informácie";
"Log Filters" = "Filtre záznamov";
"Log In with AniList" = "Prihlásiť sa cez AniList";
"Log In with Trakt" = "Prihlásiť sa cez Trakt";
"Log Out from AniList" = "Odhlásiť sa z AniList";
"Log Out from Trakt" = "Odhlásiť sa z Trakt";
"Log Types" = "Typy záznamov";
"Logged in as" = "Prihlásený ako";
"Logged in as " = "Prihlásený ako ";
/* Logs and Settings */
"Logs" = "Záznamy";
"Long press Skip" = "Dlhé stlačenie preskočí";
"MAIN" = "HLAVNÉ";
"Main Developer" = "Hlavný vývojár";
"MAIN SETTINGS" = "HLAVNÉ NASTAVENIA";
/* Media Actions */
"Mark All Previous Watched" = "Označiť všetky predchádzajúce ako zhliadnuté";
"Mark as Watched" = "Označiť ako zhliadnuté";
"Mark Episode as Watched" = "Označiť epizódu ako zhliadnutú";
"Mark Previous Episodes as Watched" = "Označiť predchádzajúce epizódy ako zhliadnuté";
"Mark watched" = "Označiť ako zhliadnuté";
"Match with AniList" = "Match with AniList";
"Match with TMDB" = "Match with TMDB";
"Matched ID: %lld" = "Matched ID: %lld";
"Matched with: %@" = "Matched with: %@";
"Max Concurrent Downloads" = "Maximálny počet súbežných šťahovaní";
/* Media Interface */
"Media Grid Layout" = "Rozloženie mriežky médií";
"Media Player" = "Prehrávač médií";
"Media View" = "Zobrazenie médií";
"Metadata Provider" = "Poskytovateľ metadát";
"Metadata Providers Order" = "Poradie poskytovateľov metadata";
"Module Removed" = "Modul odstránený";
"Modules" = "Moduly";
/* Headers */
"MODULES" = "MODULY";
"MORE" = "VIAC";
/* Status Messages */
"No Active Downloads" = "Žiadne aktívne sťahovania";
"No AniList matches found" = "No AniList matches found";
"No Data Available" = "Žiadne dostupné dáta";
"No Downloads" = "Žiadne sťahovania";
"No episodes available" = "Žiadne dostupné epizódy";
"No Episodes Available" = "Žiadne dostupné epizódy";
"No items to continue watching." = "Žiadne položky na pokračovanie v sledovaní.";
"No matches found" = "Nenašli sa žiadne zhody";
"No Module Selected" = "Nie je vybratý žiaden modul";
"No Modules" = "Žiadne moduly";
"No Results Found" = "Nenašli sa žiadne výsledky";
"No Search Results Found" = "Nenašli sa žiadne výsledky vyhľadávania";
"Nothing to Continue Watching" = "Niž nič na pokračovanie v sledovaní";
/* Notes and Messages */
"Note that the modules will be replaced only if there is a different version string inside the JSON file." = "Moduly sa nahradia iba v prípade, že v JSON súbore je odlišná verzia.";
/* Actions */
"OK" = "OK";
"Open Community Library" = "Otvoriť komunitnú knižnicu";
/* External Services */
"Open in AniList" = "Otvoriť v AniList";
"Original Poster" = "Pôvodný plagát";
/* Playback */
"Paused" = "Pozastavené";
"Play" = "Prehrať";
"Player" = "Prehrávač";
/* System Messages */
"Please restart the app to apply the language change." = "Reštartujte aplikáciu pre zmenu jazyka.";
"Please select a module from settings" = "Vyberte modul v nastaveniach";
/* Interface */
"Portrait Columns" = "Stĺpce na výšku";
"Progress bar Marker Color" = "Farba značky na časového úseku";
"Provider: %@" = "Poskytovateľ: %@";
/* Queue */
"Queue" = "Fronta";
"Queued" = "Vo fronte";
/* Content */
"Recently watched content will appear here." = "Nedávno sledovaný obsah sa zobrazí tu.";
/* Settings */
"Refresh Modules on Launch" = "Obnoviť moduly pri spustení";
"Refresh Storage Info" = "Obnoviť informácie o úložisku";
"Remember Playback speed" = "Zapamätať rýchlosť prehrávania";
/* Actions */
"Remove" = "Odstrániť";
"Remove All Cache" = "Odstrániť všetku medzipamäť";
/* File Management */
"Remove All Documents" = "Odstrániť všetky dokumenty";
"Remove Documents" = "Odstrániť dokumenty";
"Remove Downloaded Media" = "Odstrániť stiahnuté médiá";
"Remove Downloads" = "Odstrániť preberania";
"Remove from Bookmarks" = "Odstrániť zo záložiek";
"Remove Item" = "Odstrániť položku";
/* Support */
"Report an Issue" = "Nahlásiť problém";
/* Reset Options */
"Reset" = "Obnoviť";
"Reset AniList ID" = "Obnoviť ID AniList";
"Reset Episode Progress" = "Obnoviť pokrok epizódy";
"Reset progress" = "Obnoviť pokrok";
"Reset Progress" = "Obnoviť pokrok";
/* System */
"Restart Required" = "Vyžaduje sa reštart";
"Running Sora %@ - cranci1" = "Spustená Sora %@ - cranci1";
/* Actions */
"Save" = "Uložiť";
"Search" = "Vyhľadať";
/* Search */
"Search downloads" = "Vyhľadávať preberania";
"Search for something..." = "Hľadať niečo...";
"Search..." = "Hľadať...";
/* Content */
"Season %d" = "Séria %d";
"Season %lld" = "Séria %lld";
"Segments Color" = "Farba segmentov";
/* Modules */
"Select Module" = "Vybrať modul";
"Set Custom AniList ID" = "Nastaviť vlastné AniList ID";
/* Interface */
"Settings" = "Nastavenia";
"Shadow" = "Tieň";
"Show More (%lld more characters)" = "Zobraziť viac (%lld znakov)";
"Show PiP Button" = "Zobraziť tlačidlo PiP";
"Show Skip 85s Button" = "Zobraziť tlačidlo preskočiť 85s";
"Show Skip Intro / Outro Buttons" = "Zobraziť tlačidlá preskočiť úvod / záver";
"Shows" = "Relácie";
"Size (%@)" = "Veľkosť (%@)";
"Skip Settings" = "Nastavenia preskočenia";
/* Player Features */
"Some features are limited to the Sora and Default player, such as ForceLandscape, holdSpeed and custom time skip increments." = "Niektoré funkcie sú obmedzené na prehrávač Sora a predvolený prehrávač, ako ForceLandscape, holdSpeed a vlastné inkrementy preskočenia času.";
/* App Info */
"Sora" = "Sora";
"Sora %@ by cranci1" = "Sora %@ od cranci1";
"Sora and cranci1 are not affiliated with AniList or Trakt in any way.
Also note that progress updates may not be 100% accurate." = "Sora a cranci1 nie sú v žiadnom prípade spojené s AniList alebo Trakt.
Upozorňujeme, že aktualizácie pozerania nemusia byť stopercentne presné.";
"Sora GitHub Repository" = "GitHub repozitár Sora";
"Sora/Sulfur will always remain free with no ADs!" = "Sora/Sulfur bude vždy zadarmo bez reklám!";
/* Interface */
"Sort" = "Zoradiť";
"Speed Settings" = "Nastavenia rýchlosti";
/* Playback */
"Start Watching" = "Začať pozerať";
"Start Watching Episode %d" = "Začať pozerať epizódu %d";
"Storage Used" = "Použitá pamäť";
"Stream" = "Stream";
"Streaming and video playback." = "Streamovanie a prehrávanie videa.";
/* Subtitles */
"Subtitle Color" = "Farba tituliek";
"Subtitle Settings" = "Nastavenia tituliek";
/* Sync */
"Sync anime progress" = "Synchronizovať pozeranie anime";
"Sync TV shows progress" = "Synchronizovať pozeranie TV relácií";
/* System */
"System" = "Systém";
/* Instructions */
"Tap a title to override the current match." = "Klepnite na názov prepíšte aktuálnu zhodu.";
"Tap Skip" = "Klepnite na Preskočiť";
"Tap to manage your modules" = "Klepnite pre správu modulov";
"Tap to select a module" = "Klepnite na výber modulu";
/* App Information */
"The app cache helps the app load images faster.
Clearing the Documents folder will delete all downloaded modules.
Do not erase App Data unless you understand the consequences — it may cause the app to malfunction." = "Medzipamäť aplikácie pomáha aplikácii rýchlejšie načítať obrázky.
Vyprázdnením priečinka Dokumenty sa odstránia všetky stiahnuté moduly.
Neodstraňujte dáta aplikácie, ak nerozumiete následkom — môže to spôsobiť nesprávne fungovanie aplikácie.";
"The episode range controls how many episodes appear on each page. Episodes are grouped into sets (like 125, 2650, and so on), allowing you to navigate through them more easily.
For episode metadata, it refers to the episode thumbnail and title, since sometimes it can contain spoilers." = "Rozsah epizód riadi, koľko epizód sa zobrazí na každej stránke. Epizódy sú zoskupené do sád (napr. 125, 2650 atď.), čo vám umožňuje ľahšie sa medzi nimi pohybovať.
Čo sa týka metadata epizódy, ide o náhľad epizódy a názov, pretože niekedy môže obsahovať spoilery.";
"The module provided only a single episode, this is most likely a movie, so we decided to make separate screens for these cases." = "Modul poskytol iba jednu epizódu; pravdepodobne ide o film, preto sme sa rozhodli vytvoriť pre tieto prípady samostatné obrazovky.";
/* Interface */
"Thumbnails Width" = "Šírka náhľadov";
"TMDB Match" = "Match s TMDB";
"Trackers" = "Sledovače";
"Trakt" = "Trakt";
"Trakt.tv" = "Trakt.tv";
/* Search */
"Try different keywords" = "Skúste iné kľúčové slová";
"Try different search terms" = "Skúste iné vyhľadávacie výrazy";
/* Player Controls */
"Two Finger Hold for Pause" = "Podržanie dvoma prstami na pozastavenie";
"Unable to fetch matches. Please try again later." = "Nie je možné načítať zhody. Skúste to prosím neskôr.";
"Use TMDB Poster Image" = "Použiť plagát z TMDB";
/* Version */
"v%@" = "v%@";
"Video Player" = "Video prehrávač";
/* Video Settings */
"Video Quality Preferences" = "Preferencie kvality videa";
"View All" = "Zobraziť všetko";
"Watched" = "Zhliadnuté";
"Why am I not seeing any episodes?" = "Prečo nevidím žiadne epizódy?";
"WiFi Quality" = "Kvalita WiFi";
/* User Status */
"You are not logged in" = "Nie ste prihlásený";
"You have no items saved." = "Nemáte uložené žiadne položky.";
"Your downloaded episodes will appear here" = "Stiahnuté epizódy sa zobrazia tu";
"Your recently watched content will appear here" = "Nedávno zhliadnutý obsah sa zobrazí tu";
/* Download Settings */
"Download Settings" = "Nastavenia sťahovania";
"Max concurrent downloads controls how many episodes can download simultaneously. Higher values may use more bandwidth and device resources." = "Maximálny počet súbežných sťahovaní určuje, koľko epizód sa môže sťahovať v jeden moment. Vyššie hodnoty môžu využívať viacej internetu/dát a zaťažovať zariadenie.";
"Quality" = "Kvalita";
"Max Concurrent Downloads" = "Maximálne súbežné sťahovania";
"Allow Cellular Downloads" = "Povoliť sťahovanie cez mobilné dáta";
"Quality Information" = "Informácie o kvalite";
/* Storage */
"Storage Management" = "Správa ukladacieho priestoru";
"Storage Used" = "Použitý priestor";
"Library cleared successfully" = "Knižnica bola úspešne vymazaná";
"All downloads deleted successfully" = "Všetky sťahovania boli úspešne zmazané";
/* New additions */
"Recent searches" = "Nedávne vyhľadávania";
"me frfr" = "me frfr";
"Data" = "Dáta";
"Maximum Quality Available" = "Maximálna dostupná kvalita";

View file

@ -0,0 +1,384 @@
/* General */
"About" = "Om oss";
"About Sora" = "Om Sora";
"Active" = "Aktiv";
"Active Downloads" = "Aktiva nedladdningar";
"Actively downloading media can be tracked from here." = "Aktiva nedladdningar av media kan spåras här.";
"Add Module" = "Lägg till Modul";
"Adjust the number of media items per row in portrait and landscape modes." = "Justera antalet mediaelement per rad i porträtt- och landskapsläge.";
"Advanced" = "Avancerat";
"AKA Sulfur" = "AKA Sulfur";
"All Bookmarks" = "Alla bokmärken";
"All Watching" = "Allt du tittar på";
"Also known as Sulfur" = "Även känd som Sulfur";
"AniList" = "AniList";
"AniList ID" = "AniList-ID";
"AniList Match" = "AniList-matchning";
"AniList.co" = "AniList.co";
"Anonymous data is collected to improve the app. No personal information is collected. This can be disabled at any time." = "Anonym data samlas in för att förbättra appen. Ingen personlig information samlas in. Detta kan inaktiveras när som helst.";
"App Info" = "Appinformation";
"App Language" = "Appspråk";
"App Storage" = "Applagring";
"Appearance" = "Utseende";
/* Alerts and Actions */
"Are you sure you want to clear all cached data? This will help free up storage space." = "Är du säker på att du vill rensa all cachad data? Detta hjälper till att frigöra lagringsutrymme.";
"Are you sure you want to delete '%@'?" = "Är du säker på att du vill radera '%@'?";
"Are you sure you want to delete all %1$d episodes in '%2$@'?" = "Är du säker på att du vill radera alla %1$d avsnitt i '%2$@'?";
"Are you sure you want to delete all downloaded assets? You can choose to clear only the library while preserving the downloaded files for future use." = "Är du säker på att du vill radera alla nedladdade filer? Du kan välja att endast rensa biblioteket och behålla de nedladdade filerna för framtida bruk.";
"Are you sure you want to erase all app data? This action cannot be undone." = "Är du säker på att du vill radera all appdata? Denna åtgärd kan inte ångras.";
/* Features */
"Background Enabled" = "Bakgrund Aktiverad";
"Bookmark items for an easier access later." = "Bokmärk objekt för enklare åtkomst senare.";
"Bookmarks" = "Bokmärken";
"Bottom Padding" = "Bottenutfyllnad";
"Cancel" = "Avbryt";
"Cellular Quality" = "Mobilnätskvalitet";
"Check out some community modules here!" = "Kolla in några communitymoduler här!";
"Choose preferred video resolution for WiFi and cellular connections. Higher resolutions use more data but provide better quality." = "Välj önskad videoupplösning för WiFi och mobilnät. Högre upplösningar använder mer data men ger bättre kvalitet.";
"Clear" = "Rensa";
"Clear All Downloads" = "Rensa alla nedladdningar";
"Clear Cache" = "Rensa cache";
"Clear Library Only" = "Rensa endast bibliotek";
"Clear Logs" = "Rensa loggar";
"Click the plus button to add a module!" = "Klicka på plusknappen för att lägga till en modul!";
"Continue Watching" = "Fortsätt titta";
"Continue Watching Episode %d" = "Fortsätt titta på Avsnitt %d";
"Contributors" = "Medverkande";
"Copied to Clipboard" = "Kopierat till Urklipp";
"Copy to Clipboard" = "Kopiera till Urklipp";
"Copy URL" = "Kopiera URL";
/* Episodes */
"%lld Episodes" = "%lld Avsnitt";
"%lld of %lld" = "%lld av %lld";
"%lld-%lld" = "%lld-%lld";
"%lld%% seen" = "%lld%% sedda";
"Episode %lld" = "Avsnitt %lld";
"Episodes" = "Avsnitt";
"Episodes might not be available yet or there could be an issue with the source." = "Avsnitten kanske inte är tillgängliga än eller så kan det vara ett problem med källan.";
"Episodes Range" = "Avsnittsintervall";
/* System */
"cranci1" = "cranci1";
"Dark" = "Mörk";
"DATA & LOGS" = "DATA & LOGGAR";
"Debug" = "Felsökning";
"Debugging and troubleshooting." = "Felsökning och problemlösning.";
/* Actions */
"Delete" = "Radera";
"Delete All" = "Radera alla";
"Delete All Downloads" = "Radera alla nedladdningar";
"Delete All Episodes" = "Radera alla avsnitt";
"Delete Download" = "Radera nedladdning";
"Delete Episode" = "Radera avsnitt";
/* Player */
"Double Tap to Seek" = "Dubbeltryck för att söka";
"Double tapping the screen on it's sides will skip with the short tap setting." = "Genom att dubbeltrycka på skärmens sidor hoppar spelaren enligt korttrycksinställningen.";
/* Downloads */
"Download" = "Ladda ner";
"Download Episode" = "Ladda ner avsnitt";
"Download Summary" = "Nedladdningssammanfattning";
"Download This Episode" = "Ladda ner detta avsnitt";
"Downloaded" = "Nedladdat";
"Downloaded Shows" = "Nedladdade serier";
"Downloading" = "Laddar ner";
"Downloads" = "Nedladdningar";
/* Settings */
"Enable Analytics" = "Aktivera analys";
"Enable Subtitles" = "Aktivera undertexter";
/* Data Management */
"Erase" = "Radera";
"Erase all App Data" = "Radera all appdata";
"Erase App Data" = "Radera appdata";
/* Errors */
"Error" = "Fel";
"Error Fetching Results" = "Fel vid hämtning av resultat";
"Errors and critical issues." = "Fel och kritiska problem.";
"Failed to load contributors" = "Kunde inte ladda medverkande";
/* Features */
"Fetch Episode metadata" = "Hämta avsnittsmetadata";
"Files Downloaded" = "Nedladdade filer";
"Font Size" = "Fontstorlek";
/* Interface */
"Force Landscape" = "Tvinga landskapsläge";
"General" = "Allmänt";
"General events and activities." = "Allmänna händelser och aktiviteter.";
"General Preferences" = "Allmänna inställningar";
"Hide Splash Screen" = "Dölj välkomstskärm";
"HLS video downloading." = "HLS-videonedladdning.";
"Hold Speed" = "Tillfällig hållhastighet";
/* Info */
"Info" = "Info";
"INFOS" = "INFO";
"Installed Modules" = "Installerade moduler";
"Interface" = "Gränssnitt";
/* Social */
"Join the Discord" = "Gå med i vår Discord";
/* Layout */
"Landscape Columns" = "Kolumner i landskapsläge";
"Language" = "Språk";
"LESS" = "MINDRE";
/* Library */
"Library" = "Bibliotek";
"License (GPLv3.0)" = "Licens (GPLv3.0)";
"Light" = "Ljust";
/* Loading States */
"Loading Episode %lld..." = "Laddar avsnitt %lld...";
"Loading logs..." = "Laddar loggar...";
"Loading module information..." = "Laddar modulinformation...";
"Loading Stream" = "Laddar videoström";
/* Logging */
"Log Debug Info" = "Logga felsökningsinfo";
"Log Filters" = "Loggfilter";
"Log In with AniList" = "Logga in med AniList";
"Log In with Trakt" = "Logga in med Trakt";
"Log Out from AniList" = "Logga ut från AniList";
"Log Out from Trakt" = "Logga ut från Trakt";
"Log Types" = "Loggtyper";
"Logged in as" = "Inloggad som";
"Logged in as " = "Inloggad som ";
/* Logs and Settings */
"Logs" = "Loggar";
"Long press Skip" = "Långtryck för att hoppa";
"MAIN" = "HUVUD";
"Main Developer" = "Huvudutvecklare";
"MAIN SETTINGS" = "HUVUDINSTÄLLNINGAR";
/* Media Actions */
"Mark All Previous Watched" = "Markera alla tidigare som sedda";
"Mark as Watched" = "Markera som sedd";
"Mark Episode as Watched" = "Markera avsnitt som sedd";
"Mark Previous Episodes as Watched" = "Markera tidigare avsnitt som sedda";
"Mark watched" = "Markera som sedd";
"Match with AniList" = "Matcha med AniList";
"Match with TMDB" = "Matcha med TMDB";
"Matched ID: %lld" = "Matchat ID: %lld";
"Matched with: %@" = "Matchad med: %@";
"Max Concurrent Downloads" = "Max antal parallella nedladdningar";
/* Media Interface */
"Media Grid Layout" = "Medierutnätslayout";
"Media Player" = "Mediauppspelare";
"Media View" = "Mediavisning";
"Metadata Provider" = "Metadata Leverantör";
"Metadata Providers Order" = "Metadata Leverantörers Ordning";
"Module Removed" = "Modul Borttagen";
"Modules" = "Moduler";
/* Headers */
"MODULES" = "MODULER";
"MORE" = "MER";
/* Status Messages */
"No Active Downloads" = "Inga Aktiva Nedladdningar";
"No AniList matches found" = "Inga AniList matchningar hittades";
"No Data Available" = "Ingen Data Tillgänglig";
"No Downloads" = "Inga Nedladdningar";
"No episodes available" = "Inga avsnitt tillgängliga";
"No Episodes Available" = "Inga Avsnitt Tillgängliga";
"No items to continue watching." = "Inga objekt att fortsätta titta på.";
"No matches found" = "Inga matchningar hittades";
"No Module Selected" = "Ingen Modul Vald";
"No Modules" = "Inga Moduler";
"No Results Found" = "Inga Resultat Hittades";
"No Search Results Found" = "Inga Sökresultat Hittades";
"Nothing to Continue Watching" = "Inget att fortsätta titta på";
/* Notes and Messages */
"Note that the modules will be replaced only if there is a different version string inside the JSON file." = "Observera att modulerna ersätts endast om det finns en annan versionssträng i JSON-filen.";
/* Actions */
"OK" = "OK";
"Open Community Library" = "Öppna Community Bibliotek";
/* External Services */
"Open in AniList" = "Öppna i AniList";
"Original Poster" = "Original Miniatyrbild";
/* Playback */
"Paused" = "Pausad";
"Play" = "Spela";
"Player" = "Spelare";
/* System Messages */
"Please restart the app to apply the language change." = "Starta om appen för att språkändringen ska träda i kraft.";
"Please select a module from settings" = "Välj en modul från inställningar";
/* Interface */
"Portrait Columns" = "Kolumner i porträttläge";
"Progress bar Marker Color" = "Färg på Förloppsindikator";
"Provider: %@" = "Leverantör: %@";
/* Queue */
"Queue" = "Kö";
"Queued" = "I kö";
/* Content */
"Recently watched content will appear here." = "Nyligen sedda innehåll visas här.";
/* Settings */
"Refresh Modules on Launch" = "Uppdatera Moduler vid Start";
"Refresh Storage Info" = "Uppdatera Lagringsinformation";
"Remember Playback speed" = "Kom ihåg uppspelningshastighet";
/* Actions */
"Remove" = "Radera";
"Remove All Cache" = "Radera all cache";
/* File Management */
"Remove All Documents" = "Radera alla dokument";
"Remove Documents" = "Radera dokument";
"Remove Downloaded Media" = "Radera nedladdad media";
"Remove Downloads" = "Radera nedladdningar";
"Remove from Bookmarks" = "Radera från bokmärken";
"Remove Item" = "Radera objekt";
/* Support */
"Report an Issue" = "Rapportera ett Problem";
/* Reset Options */
"Reset" = "Återställ";
"Reset AniList ID" = "Återställ AniList-ID";
"Reset Episode Progress" = "Återställ Avsnittsprogress";
"Reset progress" = "Återställ progress";
"Reset Progress" = "Återställ Progress";
/* System */
"Restart Required" = "Omstart Krävs";
"Running Sora %@ - cranci1" = "Körar Sora %@ - cranci1";
/* Actions */
"Save" = "Spara";
"Search" = "Sök";
/* Search */
"Search downloads" = "Sök i nedladdningar";
"Search for something..." = "Sök efter något...";
"Search..." = "Sök...";
/* Content */
"Season %d" = "Säsong %d";
"Season %lld" = "Säsong %lld";
"Segments Color" = "Segmentfärg";
/* Modules */
"Select Module" = "Välj Modul";
"Set Custom AniList ID" = "Ange Anpassat AniList-ID";
/* Interface */
"Settings" = "Inställningar";
"Shadow" = "Skugga";
"Show More (%lld more characters)" = "Visa Mer (%lld fler tecken)";
"Show PiP Button" = "Visa PiP Knapp";
"Show Skip 85s Button" = "Visa Hoppa 85s Knapp";
"Show Skip Intro / Outro Buttons" = "Visa Hoppa över Intro / Outro Knappar";
"Shows" = "Serier";
"Size (%@)" = "Storlek (%@)";
"Skip Settings" = "Hoppa Inställningar";
/* Player Features */
"Some features are limited to the Sora and Default player, such as ForceLandscape, holdSpeed and custom time skip increments." = "Vissa funktioner är begränsade till Sora och standarduppspelaren, som Tvinga landskapsläge, tillfällig hållhastighet och anpassade hoppintervall.";
/* App Info */
"Sora" = "Sora";
"Sora %@ by cranci1" = "Sora %@ av cranci1";
"Sora and cranci1 are not affiliated with AniList or Trakt in any way.\n\nAlso note that progress updates may not be 100% accurate." = "Sora och cranci1 är på inget sätt knutna till AniList eller Trakt.\n\nObservera också att progressuppdateringar kanske inte är 100% exakta.";
"Sora GitHub Repository" = "Sora GitHub-förråd";
"Sora/Sulfur will always remain free with no ADs!" = "Sora/Sulfur kommer alltid att vara gratis och utan reklam!";
/* Interface */
"Sort" = "Sortera";
"Speed Settings" = "Hastighetsinställningar";
/* Playback */
"Start Watching" = "Börja Titta";
"Start Watching Episode %d" = "Börja Titta på Avsnitt %d";
"Storage Used" = "Använt Lagringsutrymme";
"Stream" = "Strömma";
"Streaming and video playback." = "Strömning och videouppspelning.";
/* Subtitles */
"Subtitle Color" = "Undertextfärg";
"Subtitle Settings" = "Undertextinställningar";
/* Sync */
"Sync anime progress" = "Synkronisera animeprogress";
"Sync TV shows progress" = "Synkronisera TV-serieprogress";
/* System */
"System" = "System";
/* Instructions */
"Tap a title to override the current match." = "Tryck på en titel för att åsidosätta aktuell matchning.";
"Tap Skip" = "Tryck för att hoppa Fram / Tillbaka";
"Tap to manage your modules" = "Tryck för att hantera dina moduler";
"Tap to select a module" = "Tryck för att välja en modul";
/* App Information */
"The app cache helps the app load images faster.\n\nClearing the Documents folder will delete all downloaded modules.\n\nDo not erase App Data unless you understand the consequences — it may cause the app to malfunction." = "Appens cache hjälper appen att ladda bilder snabbare.\n\nAtt rensa dokumentmappen tar bort alla nedladdade moduler.\n\nRadera inte appdata om du inte förstår konsekvenserna - det kan få appen att fungera fel.";
"The episode range controls how many episodes appear on each page. Episodes are grouped into sets (like 125, 2650, and so on), allowing you to navigate through them more easily.\n\nFor episode metadata, it refers to the episode thumbnail and title, since sometimes it can contain spoilers." = "Avsnittsintervallet styr hur många avsnitt som visas på varje sida. Avsnitten är grupperade i uppsättningar (som 125, 2650, osv.), vilket gör det enklare att navigera mellan dem.\n\nFör avsnittsmetadata avses miniatyrbild och titel, eftersom dessa ibland kan innehålla spoilers.";
"The module provided only a single episode, this is most likely a movie, so we decided to make separate screens for these cases." = "Modulen tillhandahöll endast ett avsnitt, detta är troligen en film, så vi beslutade att skapa separata skärmar för dessa fall.";
/* Interface */
"Thumbnails Width" = "Miniatyrbildsbredd";
"TMDB Match" = "TMDB Matchning";
"Trackers" = "Spårare";
"Trakt" = "Trakt";
"Trakt.tv" = "Trakt.tv";
/* Search */
"Try different keywords" = "Prova andra sökord";
"Try different search terms" = "Prova andra söktermer";
/* Player Controls */
"Two Finger Hold for Pause" = "Håll med två fingrar för paus";
"Unable to fetch matches. Please try again later." = "Kunde inte hämta matchningar. Försök igen senare.";
"Use TMDB Poster Image" = "Använd TMDB Miniatyrbild";
/* Version */
"v%@" = "v%@";
"Video Player" = "Videouppspelare";
/* Video Settings */
"Video Quality Preferences" = "Videokvalitetsinställningar";
"View All" = "Visa alla";
"Watched" = "Sedda";
"Why am I not seeing any episodes?" = "Varför ser jag inga avsnitt?";
"WiFi Quality" = "WiFi Kvalitet";
/* User Status */
"You are not logged in" = "Du är inte inloggad";
"You have no items saved." = "Du har inga sparade objekt.";
"Your downloaded episodes will appear here" = "Dina nedladdade avsnitt visas här";
"Your recently watched content will appear here" = "Ditt nyligen sedda innehåll visas här";
/* Download Settings */
"Download Settings" = "Nedladdningsinställningar";
"Max concurrent downloads controls how many episodes can download simultaneously. Higher values may use more bandwidth and device resources." = "Max antal parallella nedladdningar styr hur många avsnitt som kan laddas ner samtidigt. Högre värden kan använda mer bandbredd och enhetsresurser.";
"Quality" = "Kvalitet";
"Max Concurrent Downloads" = "Max antal Parallella Nedladdningar";
"Allow Cellular Downloads" = "Tillåt Nedladdningar via Mobilnät";
"Quality Information" = "Kvalitetsinformation";
/* Storage */
"Storage Management" = "Lagringshantering";
"Storage Used" = "Använt Lagringsutrymme";
"Library cleared successfully" = "Biblioteket rensat";
"All downloads deleted successfully" = "Alla nedladdningar borttagna";

View file

@ -17,6 +17,7 @@ struct DownloadView: View {
@State private var showDeleteAlert = false
@State private var assetToDelete: DownloadedAsset?
@State private var isSearchActive = false
@State private var showDeleteAllAlert = false
enum SortOption: String, CaseIterable, Identifiable {
case newest = "Newest"
@ -625,6 +626,10 @@ struct DownloadedSection: View {
let onDelete: (DownloadedAsset) -> Void
let onPlay: (DownloadedAsset) -> Void
@State private var groupToDelete: SimpleDownloadGroup?
@State private var showDeleteGroupAlert = false
@EnvironmentObject var jsController: JSController
var body: some View {
VStack(alignment: .leading, spacing: 12) {
HStack {
@ -638,32 +643,39 @@ struct DownloadedSection: View {
.padding(.horizontal, 20)
VStack(spacing: 8) {
ForEach(groups, id: \.title) { group in
ForEach(groups, id: \ .title) { group in
EnhancedDownloadGroupCard(
group: group,
onDelete: onDelete,
onPlay: onPlay
)
.contextMenu {
Button(role: .destructive, action: {
groupToDelete = group
showDeleteGroupAlert = true
}) {
Label(NSLocalizedString("Delete All", comment: ""), systemImage: "trash")
}
}
}
}
.background(.ultraThinMaterial)
.clipShape(RoundedRectangle(cornerRadius: 16))
.overlay(
RoundedRectangle(cornerRadius: 16)
.strokeBorder(
LinearGradient(
gradient: Gradient(stops: [
.init(color: Color.accentColor.opacity(0.3), location: 0),
.init(color: Color.accentColor.opacity(0), location: 1)
]),
startPoint: .top,
endPoint: .bottom
),
lineWidth: 0.5
)
)
.padding(.horizontal, 20)
}
.alert(NSLocalizedString("Delete All Episodes", comment: ""), isPresented: $showDeleteGroupAlert) {
Button(NSLocalizedString("Cancel", comment: ""), role: .cancel) { }
Button(NSLocalizedString("Delete All", comment: ""), role: .destructive) {
if let group = groupToDelete {
for asset in group.assets {
jsController.deleteAsset(asset)
}
}
groupToDelete = nil
}
} message: {
if let group = groupToDelete {
Text(String(format: NSLocalizedString("Are you sure you want to delete all %d episodes in '%@'?", comment: ""), group.assetCount, group.title))
}
}
}
}
@ -907,6 +919,22 @@ struct EnhancedDownloadGroupCard: View {
.padding(16)
.contentShape(Rectangle())
}
.background(.ultraThinMaterial)
.clipShape(RoundedRectangle(cornerRadius: 16))
.overlay(
RoundedRectangle(cornerRadius: 16)
.strokeBorder(
LinearGradient(
gradient: Gradient(stops: [
.init(color: Color.accentColor.opacity(0.3), location: 0),
.init(color: Color.accentColor.opacity(0), location: 1)
]),
startPoint: .top,
endPoint: .bottom
),
lineWidth: 0.5
)
)
}
.buttonStyle(PlainButtonStyle())
}
@ -927,8 +955,12 @@ struct EnhancedShowEpisodesView: View {
@State private var showDeleteAllAlert = false
@State private var assetToDelete: DownloadedAsset?
@EnvironmentObject var jsController: JSController
@EnvironmentObject var tabBarController: TabBarController
@Environment(\.colorScheme) private var colorScheme
@Environment(\.dismiss) private var dismiss
@State private var episodeSortOption: EpisodeSortOption = .episodeOrder
@State private var showFullSynopsis = false
enum EpisodeSortOption: String, CaseIterable, Identifiable {
case downloadDate = "Download Date"
@ -956,165 +988,231 @@ struct EnhancedShowEpisodesView: View {
}
var body: some View {
ScrollView(showsIndicators: false) {
VStack(spacing: 24) {
VStack(spacing: 20) {
HStack(alignment: .top, spacing: 20) {
Group {
if let posterURL = group.posterURL {
LazyImage(url: posterURL) { state in
if let uiImage = state.imageContainer?.image {
Image(uiImage: uiImage)
.resizable()
.aspectRatio(contentMode: .fill)
} else {
Rectangle()
.fill(.tertiary)
}
}
} else {
Rectangle()
.fill(.tertiary)
.overlay(
Image(systemName: "tv")
.font(.largeTitle)
.foregroundColor(.secondary)
)
}
}
.frame(width: 120, height: 180)
.clipShape(RoundedRectangle(cornerRadius: 12))
.shadow(color: .black.opacity(0.1), radius: 8, x: 0, y: 4)
VStack(alignment: .leading, spacing: 12) {
Text(group.title)
.font(.title2)
.fontWeight(.bold)
.lineLimit(3)
.foregroundColor(.primary)
VStack(alignment: .leading, spacing: 8) {
HStack {
Image(systemName: "play.rectangle.fill")
.foregroundColor(.accentColor)
Text("\(group.assetCount) \(group.assetCount == 1 ? "Episode" : "Episodes")")
.font(.headline)
.foregroundColor(.secondary)
}
HStack {
Image(systemName: "internaldrive.fill")
.foregroundColor(.accentColor)
Text(formatFileSize(group.totalFileSize))
.font(.subheadline)
.foregroundColor(.secondary)
}
}
Spacer()
}
.frame(maxWidth: .infinity, alignment: .leading)
}
.padding(.horizontal, 20)
ZStack {
mainScrollView
.navigationBarHidden(true)
.ignoresSafeArea(.container, edges: .top)
navigationOverlay
}
.onAppear {
tabBarController.hideTabBar()
// Enable swipe-to-go-back gesture
if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let window = windowScene.windows.first,
let navigationController = window.rootViewController?.children.first as? UINavigationController {
navigationController.interactivePopGestureRecognizer?.isEnabled = true
navigationController.interactivePopGestureRecognizer?.delegate = nil
}
}
.onDisappear {
tabBarController.showTabBar()
}
.navigationBarBackButtonHidden(true)
}
@ViewBuilder
private var navigationOverlay: some View {
VStack {
HStack {
Button(action: {
tabBarController.showTabBar()
dismiss()
}) {
Image(systemName: "chevron.left")
.font(.system(size: 24))
.foregroundColor(.primary)
.padding(12)
.background(Color.gray.opacity(0.2))
.clipShape(Circle())
.circularGradientOutline()
}
.padding(.top, 20)
// Episodes Section
VStack(spacing: 16) {
// Section Header
VStack(spacing: 12) {
HStack {
Image(systemName: "list.bullet.rectangle")
.foregroundColor(.accentColor)
Text(NSLocalizedString("Episodes", comment: "").uppercased())
.font(.footnote)
.fontWeight(.medium)
.foregroundColor(.secondary)
Spacer()
Menu {
ForEach(EpisodeSortOption.allCases) { option in
Button(action: {
episodeSortOption = option
}) {
HStack {
Image(systemName: option.systemImage)
Text(option.rawValue)
if episodeSortOption == option {
Spacer()
Image(systemName: "checkmark")
}
}
}
}
} label: {
HStack(spacing: 4) {
Image(systemName: episodeSortOption.systemImage)
Text(NSLocalizedString("Sort", comment: ""))
}
.font(.subheadline)
.foregroundColor(.accentColor)
}
Button(action: {
showDeleteAllAlert = true
}) {
HStack(spacing: 4) {
Image(systemName: "trash")
Text(NSLocalizedString("Delete All", comment: ""))
}
.font(.subheadline)
.foregroundColor(.red)
}
}
.padding(.horizontal, 20)
}
// Episodes List
if group.assets.isEmpty {
Text(NSLocalizedString("No episodes available", comment: ""))
.foregroundColor(.secondary)
.italic()
.padding(40)
.padding(.top, 8)
.padding(.leading, 16)
Spacer()
}
Spacer()
}
}
@ViewBuilder
private var mainScrollView: some View {
ScrollView(showsIndicators: false) {
ZStack(alignment: .top) {
heroImageSection
contentContainer
}
}
.onAppear {
UIScrollView.appearance().bounces = false
}
}
@ViewBuilder
private var heroImageSection: some View {
Group {
if let posterURL = group.posterURL {
LazyImage(url: posterURL) { state in
if let uiImage = state.imageContainer?.image {
Image(uiImage: uiImage)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: UIScreen.main.bounds.width, height: 700)
.clipped()
} else {
VStack(spacing: 8) {
ForEach(Array(sortedEpisodes.enumerated()), id: \.element.id) { index, asset in
EnhancedEpisodeRow(
asset: asset,
showDivider: index < sortedEpisodes.count - 1
)
.contextMenu {
Button(action: { onPlay(asset) }) {
Label(NSLocalizedString("Play", comment: ""), systemImage: "play.fill")
}
.disabled(!asset.fileExists)
Button(role: .destructive, action: {
assetToDelete = asset
showDeleteAlert = true
}) {
Label(NSLocalizedString("Delete", comment: ""), systemImage: "trash")
}
}
.onTapGesture {
onPlay(asset)
}
}
placeholderGradient
}
}
} else {
placeholderGradient
}
}
}
private var placeholderGradient: some View {
Rectangle()
.fill(
LinearGradient(
gradient: Gradient(colors: [
Color.gray.opacity(0.2),
Color.gray.opacity(0.3),
Color.gray.opacity(0.2)
]),
startPoint: .topLeading,
endPoint: .bottomTrailing
)
)
.frame(width: UIScreen.main.bounds.width, height: 700)
.clipped()
}
@ViewBuilder
private var contentContainer: some View {
VStack(spacing: 0) {
Rectangle()
.fill(Color.clear)
.frame(height: 400)
ZStack(alignment: .top) {
gradientOverlay
VStack(alignment: .leading, spacing: 16) {
headerSection
episodesSection
}
.padding()
}
}
}
@ViewBuilder
private var gradientOverlay: some View {
LinearGradient(
gradient: Gradient(stops: [
.init(color: (colorScheme == .dark ? Color.black : Color.white).opacity(0.0), location: 0.0),
.init(color: (colorScheme == .dark ? Color.black : Color.white).opacity(0.5), location: 0.2),
.init(color: (colorScheme == .dark ? Color.black : Color.white).opacity(0.8), location: 0.5),
.init(color: (colorScheme == .dark ? Color.black : Color.white), location: 1.0)
]),
startPoint: .top,
endPoint: .bottom
)
.frame(height: 300)
.clipShape(RoundedRectangle(cornerRadius: 0))
.shadow(color: (colorScheme == .dark ? Color.black : Color.white).opacity(1), radius: 10, x: 0, y: 10)
}
@ViewBuilder
private var headerSection: some View {
VStack(alignment: .leading, spacing: 8) {
Text(group.title)
.font(.system(size: 28, weight: .bold))
.foregroundColor(.primary)
.lineLimit(3)
VStack(alignment: .leading, spacing: 8) {
HStack {
Image(systemName: "play.rectangle.fill")
.foregroundColor(.accentColor)
Text("\(group.assetCount) \(group.assetCount == 1 ? "Episode" : "Episodes")")
.font(.headline)
.foregroundColor(.secondary)
}
HStack {
Image(systemName: "internaldrive.fill")
.foregroundColor(.accentColor)
Text(formatFileSize(group.totalFileSize))
.font(.subheadline)
.foregroundColor(.secondary)
}
}
HStack(spacing: 12) {
Button(action: { showDeleteAllAlert = true }) {
HStack(spacing: 8) {
Image(systemName: "trash")
.foregroundColor(.red)
Text(NSLocalizedString("Delete All", comment: ""))
.font(.system(size: 16, weight: .medium))
.foregroundColor(.red)
}
.frame(maxWidth: .infinity)
.padding(.vertical, 12)
.padding(.horizontal, 20)
.background(
RoundedRectangle(cornerRadius: 25)
.fill(Color.red.opacity(0.1))
)
}
}
}
}
@ViewBuilder
private var episodesSection: some View {
VStack(alignment: .leading, spacing: 12) {
HStack {
Image(systemName: "play.rectangle.fill")
.foregroundColor(.accentColor)
Text(NSLocalizedString("Episodes", comment: "").uppercased())
.font(.footnote)
.fontWeight(.medium)
.foregroundColor(.secondary)
}
VStack(spacing: 8) {
ForEach(Array(sortedEpisodes.enumerated()), id: \.element.id) { index, asset in
EnhancedEpisodeRow(
asset: asset,
showDivider: index < sortedEpisodes.count - 1,
onPlay: onPlay,
onDelete: { asset in
assetToDelete = asset
showDeleteAlert = true
}
)
.contextMenu {
Button(action: { onPlay(asset) }) {
Label(NSLocalizedString("Play", comment: ""), systemImage: "play.fill")
}
.disabled(!asset.fileExists)
Button(role: .destructive, action: {
assetToDelete = asset
showDeleteAlert = true
}) {
Label(NSLocalizedString("Delete", comment: ""), systemImage: "trash")
}
}
.onTapGesture {
onPlay(asset)
}
}
}
.padding(.vertical)
.scrollViewBottomPadding()
}
.navigationTitle(NSLocalizedString("Episodes", comment: ""))
.navigationBarTitleDisplayMode(.inline)
.alert(NSLocalizedString("Delete Episode", comment: ""), isPresented: $showDeleteAlert) {
Button(NSLocalizedString("Cancel", comment: ""), role: .cancel) { }
Button(NSLocalizedString("Delete", comment: ""), role: .destructive) {
if let asset = assetToDelete {
onDelete(asset)
jsController.deleteAsset(asset)
}
}
} message: {
@ -1149,84 +1247,213 @@ struct EnhancedShowEpisodesView: View {
struct EnhancedEpisodeRow: View {
let asset: DownloadedAsset
let showDivider: Bool
let onPlay: (DownloadedAsset) -> Void
let onDelete: (DownloadedAsset) -> Void
@State private var swipeOffset: CGFloat = 0
@State private var isShowingActions: Bool = false
@State private var dragState = DragState.inactive
struct DragState {
var translation: CGSize
var isActive: Bool
static var inactive: DragState {
DragState(translation: .zero, isActive: false)
}
}
var body: some View {
VStack(spacing: 0) {
HStack(spacing: 16) {
Group {
if let backdropURL = asset.metadata?.backdropURL ?? asset.metadata?.posterURL {
LazyImage(url: backdropURL) { state in
if let uiImage = state.imageContainer?.image {
Image(uiImage: uiImage)
.resizable()
.aspectRatio(contentMode: .fill)
} else {
Rectangle()
.fill(.tertiary)
}
}
} else {
Rectangle()
.fill(.tertiary)
.overlay(
Image(systemName: "photo")
.foregroundColor(.secondary)
)
}
}
.frame(width: 100, height: 60)
.clipShape(RoundedRectangle(cornerRadius: 8))
VStack(alignment: .leading, spacing: 4) {
Text(asset.episodeDisplayName)
.font(.headline)
.lineLimit(2)
.foregroundColor(.primary)
Text(formatFileSize(asset.fileSize))
ZStack {
actionButtonsBackground
episodeCellContent
}
}
private var actionButtonsBackground: some View {
HStack {
Spacer()
Button(action: {
onDelete(asset)
}) {
VStack(spacing: 4) {
Image(systemName: "trash.fill")
.font(.title2)
.foregroundColor(.red)
Text("Delete")
.font(.caption)
.foregroundColor(.secondary)
HStack(spacing: 6) {
Text(asset.downloadDate.formatted(date: .abbreviated, time: .shortened))
.font(.caption)
.foregroundColor(.secondary)
if asset.localSubtitleURL != nil {
Image(systemName: "captions.bubble")
.foregroundColor(.blue)
.font(.caption)
}
if !asset.fileExists {
Image(systemName: "exclamationmark.triangle")
.foregroundColor(.orange)
.font(.caption)
.foregroundColor(.red)
}
.frame(width: 60)
}
.frame(height: 76)
}
.zIndex(0)
}
private var episodeCellContent: some View {
HStack {
// Thumbnail
Group {
if let backdropURL = asset.metadata?.backdropURL ?? asset.metadata?.posterURL {
LazyImage(url: backdropURL) { state in
if let uiImage = state.imageContainer?.image {
Image(uiImage: uiImage)
.resizable()
.aspectRatio(16/9, contentMode: .fill)
} else {
Rectangle()
.fill(.tertiary)
.overlay(
Image(systemName: "photo")
.foregroundColor(.secondary)
)
}
}
} else {
Rectangle()
.fill(.tertiary)
.overlay(
Image(systemName: "photo")
.foregroundColor(.secondary)
)
}
Spacer()
Image(systemName: "play.circle.fill")
.foregroundColor(asset.fileExists ? .blue : .gray)
.font(.title2)
}
.padding(.vertical, 8)
.padding(.horizontal, 16)
.frame(width: 100, height: 56)
.clipShape(RoundedRectangle(cornerRadius: 8))
if showDivider {
Divider()
.padding(.horizontal, 16)
VStack(alignment: .leading) {
Text("Episode \(asset.metadata?.episode ?? 0)")
.font(.system(size: 15))
if let title = asset.metadata?.title {
Text(title)
.font(.system(size: 13))
.foregroundColor(.secondary)
.lineLimit(1)
}
}
Spacer()
CircularProgressBar(progress: 0.0)
.frame(width: 40, height: 40)
.padding(.trailing, 4)
}
.contentShape(Rectangle())
.padding(.horizontal, 8)
.padding(.vertical, 8)
.frame(maxWidth: .infinity)
.background(cellBackground)
.clipShape(RoundedRectangle(cornerRadius: 15))
.offset(x: swipeOffset + dragState.translation.width)
.zIndex(1)
.scaleEffect(dragState.isActive ? 0.98 : 1.0)
.animation(.spring(response: 0.4, dampingFraction: 0.8), value: swipeOffset)
.animation(.spring(response: 0.3, dampingFraction: 0.6), value: dragState.isActive)
.simultaneousGesture(
DragGesture(coordinateSpace: .local)
.onChanged { value in
handleDragChanged(value)
}
.onEnded { value in
handleDragEnded(value)
}
)
.onTapGesture { handleTap() }
}
private var cellBackground: some View {
RoundedRectangle(cornerRadius: 15)
.fill(Color(UIColor.systemBackground))
.overlay(
RoundedRectangle(cornerRadius: 15)
.fill(Color.gray.opacity(0.2))
)
.overlay(
RoundedRectangle(cornerRadius: 15)
.stroke(
LinearGradient(
gradient: Gradient(stops: [
.init(color: Color.accentColor.opacity(0.25), location: 0),
.init(color: Color.accentColor.opacity(0), location: 1)
]),
startPoint: .top,
endPoint: .bottom
),
lineWidth: 0.5
)
)
}
private func handleDragChanged(_ value: DragGesture.Value) {
let translation = value.translation
let velocity = value.velocity
let isHorizontalGesture = abs(translation.width) > abs(translation.height)
let hasSignificantHorizontalMovement = abs(translation.width) > 10
if isHorizontalGesture && hasSignificantHorizontalMovement {
dragState = .inactive
let proposedOffset = swipeOffset + translation.width
let maxSwipe: CGFloat = 60 // Only one button
if translation.width < 0 {
let newOffset = max(proposedOffset, -maxSwipe)
if proposedOffset < -maxSwipe {
let resistance = abs(proposedOffset + maxSwipe) * 0.15
swipeOffset = -maxSwipe - resistance
} else {
swipeOffset = newOffset
}
} else if isShowingActions {
swipeOffset = min(max(proposedOffset, -maxSwipe), maxSwipe * 0.2)
}
} else if !hasSignificantHorizontalMovement {
dragState = .inactive
}
}
private func handleDragEnded(_ value: DragGesture.Value) {
let translation = value.translation
let velocity = value.velocity
dragState = .inactive
let isHorizontalGesture = abs(translation.width) > abs(translation.height)
let hasSignificantHorizontalMovement = abs(translation.width) > 10
if isHorizontalGesture && hasSignificantHorizontalMovement {
let maxSwipe: CGFloat = 60
let threshold = maxSwipe * 0.3
let velocityThreshold: CGFloat = 500
withAnimation(.spring(response: 0.4, dampingFraction: 0.8)) {
if translation.width < -threshold || velocity.width < -velocityThreshold {
swipeOffset = -maxSwipe
isShowingActions = true
} else if translation.width > threshold || velocity.width > velocityThreshold {
swipeOffset = 0
isShowingActions = false
} else {
swipeOffset = isShowingActions ? -maxSwipe : 0
}
}
} else {
withAnimation(.spring(response: 0.4, dampingFraction: 0.8)) {
swipeOffset = isShowingActions ? -60 : 0
}
}
}
private func formatFileSize(_ size: Int64) -> String {
let formatter = ByteCountFormatter()
formatter.allowedUnits = [.useKB, .useMB, .useGB]
formatter.countStyle = .file
return formatter.string(fromByteCount: size)
private func handleTap() {
if isShowingActions {
withAnimation(.spring(response: 0.3, dampingFraction: 0.8)) {
swipeOffset = 0
isShowingActions = false
}
} else {
onPlay(asset)
}
}
}

View file

@ -31,12 +31,156 @@ extension View {
struct AllBookmarks: View {
@EnvironmentObject var libraryManager: LibraryManager
@EnvironmentObject var moduleManager: ModuleManager
@State private var searchText: String = ""
@State private var isSearchActive: Bool = false
@State private var sortOption: SortOption = .title
enum SortOption: String, CaseIterable {
case title = "Title"
case dateAdded = "Date Added"
case source = "Source"
}
var filteredAndSortedBookmarks: [LibraryItem] {
let filtered = searchText.isEmpty ? libraryManager.bookmarks : libraryManager.bookmarks.filter { item in
item.title.localizedCaseInsensitiveContains(searchText) ||
item.moduleName.localizedCaseInsensitiveContains(searchText)
}
switch sortOption {
case .title:
return filtered.sorted { $0.title.lowercased() < $1.title.lowercased() }
case .dateAdded:
return filtered
case .source:
return filtered.sorted { $0.moduleName < $1.moduleName }
}
}
var body: some View {
BookmarkGridView(
bookmarks: libraryManager.bookmarks.sorted { $0.title < $1.title },
moduleManager: moduleManager
)
VStack(alignment: .leading) {
HStack {
Button(action: { }) {
Image(systemName: "chevron.left")
.font(.system(size: 24))
.foregroundColor(.primary)
}
Button(action: { }) {
Text("All Bookmarks")
.font(.title3)
.fontWeight(.bold)
.foregroundColor(.primary)
}
Spacer()
HStack(spacing: 16) {
Button(action: {
withAnimation(.easeInOut(duration: 0.3)) {
isSearchActive.toggle()
}
if !isSearchActive {
searchText = ""
}
}) {
Image(systemName: isSearchActive ? "xmark.circle.fill" : "magnifyingglass")
.resizable()
.scaledToFit()
.frame(width: 18, height: 18)
.foregroundColor(.accentColor)
.padding(10)
.background(
Circle()
.fill(Color.gray.opacity(0.2))
.shadow(color: .accentColor.opacity(0.2), radius: 2)
)
.circularGradientOutlineTwo()
}
Menu {
ForEach(SortOption.allCases, id: \.self) { option in
Button {
sortOption = option
} label: {
HStack {
Text(option.rawValue)
if option == sortOption {
Image(systemName: "checkmark")
.foregroundColor(.accentColor)
}
}
}
}
} label: {
Image(systemName: "line.3.horizontal.decrease.circle")
.resizable()
.scaledToFit()
.frame(width: 18, height: 18)
.foregroundColor(.accentColor)
.padding(10)
.background(
Circle()
.fill(Color.gray.opacity(0.2))
.shadow(color: .accentColor.opacity(0.2), radius: 2)
)
.circularGradientOutlineTwo()
}
}
}
.padding(.horizontal)
.padding(.top)
if isSearchActive {
HStack(spacing: 12) {
HStack(spacing: 12) {
Image(systemName: "magnifyingglass")
.resizable()
.scaledToFit()
.frame(width: 18, height: 18)
.foregroundColor(.secondary)
TextField("Search bookmarks...", text: $searchText)
.textFieldStyle(PlainTextFieldStyle())
.foregroundColor(.primary)
if !searchText.isEmpty {
Button(action: {
searchText = ""
}) {
Image(systemName: "xmark.circle.fill")
.resizable()
.scaledToFit()
.frame(width: 18, height: 18)
.foregroundColor(.secondary)
}
}
}
.padding(.horizontal, 16)
.padding(.vertical, 12)
.background(.ultraThinMaterial)
.clipShape(RoundedRectangle(cornerRadius: 12))
.overlay(
RoundedRectangle(cornerRadius: 12)
.strokeBorder(
LinearGradient(
gradient: Gradient(stops: [
.init(color: Color.accentColor.opacity(0.25), location: 0),
.init(color: Color.accentColor.opacity(0), location: 1)
]),
startPoint: .top,
endPoint: .bottom
),
lineWidth: 1.5
)
)
}
.padding(.horizontal)
.padding(.bottom, 8)
.transition(.asymmetric(
insertion: .move(edge: .top).combined(with: .opacity),
removal: .move(edge: .top).combined(with: .opacity)
))
}
BookmarkGridView(
bookmarks: filteredAndSortedBookmarks,
moduleManager: moduleManager
)
.withGridPadding()
Spacer()
}
.navigationBarBackButtonHidden(true)
.navigationBarTitleDisplayMode(.inline)
.onAppear(perform: setupNavigationController)

View file

@ -34,6 +34,8 @@ struct AllWatchingView: View {
@State private var continueWatchingItems: [ContinueWatchingItem] = []
@State private var sortOption: SortOption = .dateAdded
@State private var searchText: String = ""
@State private var isSearchActive: Bool = false
enum SortOption: String, CaseIterable {
case dateAdded = "Recently Added"
@ -42,16 +44,20 @@ struct AllWatchingView: View {
case progress = "Watch Progress"
}
var sortedItems: [ContinueWatchingItem] {
var filteredAndSortedItems: [ContinueWatchingItem] {
let filtered = searchText.isEmpty ? continueWatchingItems : continueWatchingItems.filter { item in
item.mediaTitle.localizedCaseInsensitiveContains(searchText) ||
item.module.metadata.sourceName.localizedCaseInsensitiveContains(searchText)
}
switch sortOption {
case .dateAdded:
return continueWatchingItems.reversed()
return filtered.reversed()
case .title:
return continueWatchingItems.sorted { $0.mediaTitle.lowercased() < $1.mediaTitle.lowercased() }
return filtered.sorted { $0.mediaTitle.lowercased() < $1.mediaTitle.lowercased() }
case .source:
return continueWatchingItems.sorted { $0.module.metadata.sourceName < $1.module.metadata.sourceName }
return filtered.sorted { $0.module.metadata.sourceName < $1.module.metadata.sourceName }
case .progress:
return continueWatchingItems.sorted { $0.progress > $1.progress }
return filtered.sorted { $0.progress > $1.progress }
}
}
@ -77,37 +83,114 @@ struct AllWatchingView: View {
Spacer()
Menu {
ForEach(SortOption.allCases, id: \.self) { option in
Button {
sortOption = option
} label: {
HStack {
Text(option.rawValue)
if option == sortOption {
Image(systemName: "checkmark")
.foregroundColor(.accentColor)
HStack(spacing: 16) {
Button(action: {
withAnimation(.easeInOut(duration: 0.3)) {
isSearchActive.toggle()
}
if !isSearchActive {
searchText = ""
}
}) {
Image(systemName: isSearchActive ? "xmark.circle.fill" : "magnifyingglass")
.resizable()
.scaledToFit()
.frame(width: 18, height: 18)
.foregroundColor(.accentColor)
.padding(10)
.background(
Circle()
.fill(Color.gray.opacity(0.2))
.shadow(color: .accentColor.opacity(0.2), radius: 2)
)
.circularGradientOutline()
}
Menu {
ForEach(SortOption.allCases, id: \.self) { option in
Button {
sortOption = option
} label: {
HStack {
Text(option.rawValue)
if option == sortOption {
Image(systemName: "checkmark")
.foregroundColor(.accentColor)
}
}
}
}
} label: {
Image(systemName: "line.3.horizontal.decrease.circle")
.resizable()
.scaledToFit()
.frame(width: 18, height: 18)
.foregroundColor(.accentColor)
.padding(10)
.background(
Circle()
.fill(Color.gray.opacity(0.2))
.shadow(color: .accentColor.opacity(0.2), radius: 2)
)
.circularGradientOutline()
}
} label: {
Image(systemName: "line.3.horizontal.decrease.circle")
.resizable()
.frame(width: 24, height: 24)
.foregroundColor(.accentColor)
.padding(6)
.background(Color.gray.opacity(0.2))
.clipShape(Circle())
.circularGradientOutline()
}
}
.padding(.horizontal)
.padding(.top)
if isSearchActive {
HStack(spacing: 12) {
HStack(spacing: 12) {
Image(systemName: "magnifyingglass")
.resizable()
.scaledToFit()
.frame(width: 18, height: 18)
.foregroundColor(.secondary)
TextField("Search watching...", text: $searchText)
.textFieldStyle(PlainTextFieldStyle())
.foregroundColor(.primary)
if !searchText.isEmpty {
Button(action: {
searchText = ""
}) {
Image(systemName: "xmark.circle.fill")
.resizable()
.scaledToFit()
.frame(width: 18, height: 18)
.foregroundColor(.secondary)
}
}
}
.padding(.horizontal, 16)
.padding(.vertical, 12)
.background(.ultraThinMaterial)
.clipShape(RoundedRectangle(cornerRadius: 12))
.overlay(
RoundedRectangle(cornerRadius: 12)
.strokeBorder(
LinearGradient(
gradient: Gradient(stops: [
.init(color: Color.accentColor.opacity(0.25), location: 0),
.init(color: Color.accentColor.opacity(0), location: 1)
]),
startPoint: .top,
endPoint: .bottom
),
lineWidth: 1.5
)
)
}
.padding(.horizontal)
.padding(.bottom, 8)
.transition(.asymmetric(
insertion: .move(edge: .top).combined(with: .opacity),
removal: .move(edge: .top).combined(with: .opacity)
))
}
ScrollView(showsIndicators: false) {
LazyVStack(spacing: 12) {
ForEach(sortedItems) { item in
ForEach(filteredAndSortedItems) { item in
FullWidthContinueWatchingCell(
item: item,
markAsWatched: {

View file

@ -15,6 +15,8 @@ struct BookmarksDetailView: View {
@Binding var bookmarks: [LibraryItem]
@State private var sortOption: SortOption = .dateAdded
@State private var searchText: String = ""
@State private var isSearchActive: Bool = false
enum SortOption: String, CaseIterable {
case dateAdded = "Date Added"
@ -22,14 +24,18 @@ struct BookmarksDetailView: View {
case source = "Source"
}
var sortedBookmarks: [LibraryItem] {
var filteredAndSortedBookmarks: [LibraryItem] {
let filtered = searchText.isEmpty ? bookmarks : bookmarks.filter { item in
item.title.localizedCaseInsensitiveContains(searchText) ||
item.moduleName.localizedCaseInsensitiveContains(searchText)
}
switch sortOption {
case .dateAdded:
return bookmarks
return filtered
case .title:
return bookmarks.sorted { $0.title.lowercased() < $1.title.lowercased() }
return filtered.sorted { $0.title.lowercased() < $1.title.lowercased() }
case .source:
return bookmarks.sorted { item1, item2 in
return filtered.sorted { item1, item2 in
let module1 = moduleManager.modules.first { $0.id.uuidString == item1.moduleId }
let module2 = moduleManager.modules.first { $0.id.uuidString == item2.moduleId }
return (module1?.metadata.sourceName ?? "") < (module2?.metadata.sourceName ?? "")
@ -52,12 +58,111 @@ struct BookmarksDetailView: View {
.foregroundColor(.primary)
}
Spacer()
SortMenu(sortOption: $sortOption)
HStack(spacing: 16) {
Button(action: {
withAnimation(.easeInOut(duration: 0.3)) {
isSearchActive.toggle()
}
if !isSearchActive {
searchText = ""
}
}) {
Image(systemName: isSearchActive ? "xmark.circle.fill" : "magnifyingglass")
.resizable()
.scaledToFit()
.frame(width: 18, height: 18)
.foregroundColor(.accentColor)
.padding(10)
.background(
Circle()
.fill(Color.gray.opacity(0.2))
.shadow(color: .accentColor.opacity(0.2), radius: 2)
)
.circularGradientOutline()
}
Menu {
ForEach(SortOption.allCases, id: \.self) { option in
Button {
sortOption = option
} label: {
HStack {
Text(option.rawValue)
if option == sortOption {
Image(systemName: "checkmark")
.foregroundColor(.accentColor)
}
}
}
}
} label: {
Image(systemName: "line.3.horizontal.decrease.circle")
.resizable()
.scaledToFit()
.frame(width: 18, height: 18)
.foregroundColor(.accentColor)
.padding(10)
.background(
Circle()
.fill(Color.gray.opacity(0.2))
.shadow(color: .accentColor.opacity(0.2), radius: 2)
)
.circularGradientOutline()
}
}
}
.padding(.horizontal)
.padding(.top)
if isSearchActive {
HStack(spacing: 12) {
HStack(spacing: 12) {
Image(systemName: "magnifyingglass")
.resizable()
.scaledToFit()
.frame(width: 18, height: 18)
.foregroundColor(.secondary)
TextField("Search bookmarks...", text: $searchText)
.textFieldStyle(PlainTextFieldStyle())
.foregroundColor(.primary)
if !searchText.isEmpty {
Button(action: {
searchText = ""
}) {
Image(systemName: "xmark.circle.fill")
.resizable()
.scaledToFit()
.frame(width: 18, height: 18)
.foregroundColor(.secondary)
}
}
}
.padding(.horizontal, 16)
.padding(.vertical, 12)
.background(.ultraThinMaterial)
.clipShape(RoundedRectangle(cornerRadius: 12))
.overlay(
RoundedRectangle(cornerRadius: 12)
.strokeBorder(
LinearGradient(
gradient: Gradient(stops: [
.init(color: Color.accentColor.opacity(0.25), location: 0),
.init(color: Color.accentColor.opacity(0), location: 1)
]),
startPoint: .top,
endPoint: .bottom
),
lineWidth: 1.5
)
)
}
.padding(.horizontal)
.padding(.bottom, 8)
.transition(.asymmetric(
insertion: .move(edge: .top).combined(with: .opacity),
removal: .move(edge: .top).combined(with: .opacity)
))
}
BookmarksDetailGrid(
bookmarks: sortedBookmarks,
bookmarks: filteredAndSortedBookmarks,
moduleManager: moduleManager
)
}

View file

@ -421,12 +421,23 @@ struct MediaInfoView: View {
.font(.system(size: 14, weight: .medium))
.foregroundColor(.primary)
}
.frame(maxWidth: .infinity)
.frame(maxWidth: 120)
.padding(.vertical, 6)
.background(Color.gray.opacity(0.2))
.cornerRadius(15)
.gradientOutline()
}
Button(action: { openSafariViewController(with: href) }) {
Image(systemName: "safari")
.resizable()
.frame(width: 16, height: 16)
.foregroundColor(.primary)
.padding(6)
.background(Color.gray.opacity(0.2))
.clipShape(Circle())
.circularGradientOutline()
}
menuButton
}

View file

@ -41,7 +41,7 @@ struct SearchResultsGrid: View {
if let uiImage = state.imageContainer?.image {
Image(uiImage: uiImage)
.resizable()
.aspectRatio(0.72, contentMode: .fill)
.aspectRatio(contentMode: .fill)
.frame(width: cellWidth, height: cellWidth * 1.5)
.cornerRadius(12)
.clipped()

View file

@ -290,19 +290,19 @@ struct TranslatorsView: View {
id: 3,
login: "ibro",
avatarUrl: "https://github.com/50n50/assets/blob/main/pfps/05cd4f3508f99ba0a4ae2d0985c2f68c_webp.png?raw=true",
language: "Russian - Czech"
language: "Russian, Czech, Kazakh"
),
Translator(
id: 4,
login: "Ciro",
avatarUrl: "https://github.com/50n50/assets/blob/main/pfps/4accfc2fcfa436165febe4cad18de978_webp.png?raw=true",
language: "Arabic - French"
language: "Arabic, French"
),
Translator(
id: 5,
login: "storm",
avatarUrl: "https://github.com/50n50/assets/blob/main/pfps/a6cc97f87d356523820461fd761fc3e1_webp.png?raw=true",
language: "Norwegian - Swedish"
language: "Norwegian, Swedish"
),
Translator(
id: 6,
@ -326,38 +326,30 @@ struct TranslatorsView: View {
var body: some View {
ForEach(translators) { translator in
Button(action: {
if let url = URL(string: "https://github.com/\(translator.login)") {
UIApplication.shared.open(url)
HStack {
LazyImage(url: URL(string: translator.avatarUrl)) { state in
if let uiImage = state.imageContainer?.image {
Image(uiImage: uiImage)
.resizable()
.frame(width: 40, height: 40)
.clipShape(Circle())
} else {
ProgressView()
.frame(width: 40, height: 40)
}
}
}) {
HStack {
LazyImage(url: URL(string: translator.avatarUrl)) { state in
if let uiImage = state.imageContainer?.image {
Image(uiImage: uiImage)
.resizable()
.frame(width: 40, height: 40)
.clipShape(Circle())
} else {
ProgressView()
.frame(width: 40, height: 40)
}
}
VStack(alignment: .leading, spacing: 2) {
Text(translator.login)
.font(.headline)
.foregroundColor(.accentColor)
Text(translator.language)
.font(.caption)
.foregroundColor(.secondary)
}
Spacer()
Image(systemName: "safari")
VStack(alignment: .leading, spacing: 2) {
Text(translator.login)
.font(.headline)
.foregroundColor(.accentColor)
Text(translator.language)
.font(.caption)
.foregroundColor(.secondary)
}
.padding(.horizontal, 16)
.padding(.vertical, 12)
Spacer()
}
.padding(.horizontal, 16)
.padding(.vertical, 12)
if translator.id != translators.last?.id {
Divider()
.padding(.horizontal, 16)

View file

@ -208,20 +208,28 @@ struct SettingsViewGeneral: View {
"Czech",
"Dutch",
"French",
"German",
"Kazakh",
"Norsk",
"Russian",
"Spanish"
"Slovak",
"Spanish",
"Swedish"
],
optionToString: { lang in
switch lang {
case "English": return "English"
case "Dutch": return "Nederlands"
case "French": return "Français"
case "German": return "Deutsch"
case "Arabic": return "العربية"
case "Czech": return "Čeština"
case "Slovak": return "Slovenčina"
case "Spanish": return "Español"
case "Russian": return "Русский"
case "Norsk": return "Norsk"
case "Kazakh": return "Қазақша"
case "Swedish": return "Svenska"
default: return lang
}
},

View file

@ -407,16 +407,24 @@ class Settings: ObservableObject {
languageCode = "nl"
case "French":
languageCode = "fr"
case "German":
languageCode = "de"
case "Arabic":
languageCode = "ar"
case "Czech":
languageCode = "cs"
case "Slovak":
languageCode = "sk"
case "Spanish":
languageCode = "es"
case "Russian":
languageCode = "ru"
case "Norsk":
languageCode = "nn"
case "Kazakh":
languageCode = "kk"
case "Swedish":
languageCode = "sv"
default:
languageCode = "en"
}

View file

@ -15,6 +15,10 @@
0409FE872DFF0870000DB00C /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0409FE852DFF0870000DB00C /* Localizable.strings */; };
0409FE882DFF0870000DB00C /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0409FE822DFF0870000DB00C /* Localizable.strings */; };
0409FE8C2DFF2886000DB00C /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0409FE8A2DFF2886000DB00C /* Localizable.strings */; };
0410697E2E00ABE900A157BB /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 041069792E00ABE900A157BB /* Localizable.strings */; };
0410697F2E00ABE900A157BB /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0410697C2E00ABE900A157BB /* Localizable.strings */; };
041069832E00C71000A157BB /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 041069812E00C71000A157BB /* Localizable.strings */; };
041261042E00D14F00D05B47 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 041261022E00D14F00D05B47 /* Localizable.strings */; };
0457C5972DE7712A000AFBD9 /* DeviceScaleModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0457C5942DE7712A000AFBD9 /* DeviceScaleModifier.swift */; };
0457C59D2DE78267000AFBD9 /* BookmarkGridView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0457C59A2DE78267000AFBD9 /* BookmarkGridView.swift */; };
0457C59E2DE78267000AFBD9 /* BookmarkLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0457C59B2DE78267000AFBD9 /* BookmarkLink.swift */; };
@ -118,6 +122,10 @@
0409FE812DFF0870000DB00C /* cz */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cz; path = Localizable.strings; sourceTree = "<group>"; };
0409FE842DFF0870000DB00C /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = Localizable.strings; sourceTree = "<group>"; };
0409FE892DFF2886000DB00C /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = Localizable.strings; sourceTree = "<group>"; };
041069782E00ABE900A157BB /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = Localizable.strings; sourceTree = "<group>"; };
0410697B2E00ABE900A157BB /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = Localizable.strings; sourceTree = "<group>"; };
041069802E00C71000A157BB /* kk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kk; path = Localizable.strings; sourceTree = "<group>"; };
041261012E00D14F00D05B47 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = Localizable.strings; sourceTree = "<group>"; };
0457C5942DE7712A000AFBD9 /* DeviceScaleModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceScaleModifier.swift; sourceTree = "<group>"; };
0457C5992DE78267000AFBD9 /* BookmarkGridItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkGridItemView.swift; sourceTree = "<group>"; };
0457C59A2DE78267000AFBD9 /* BookmarkGridView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkGridView.swift; sourceTree = "<group>"; };
@ -262,6 +270,38 @@
path = ru.lproj;
sourceTree = "<group>";
};
0410697A2E00ABE900A157BB /* de.lproj */ = {
isa = PBXGroup;
children = (
041069792E00ABE900A157BB /* Localizable.strings */,
);
path = de.lproj;
sourceTree = "<group>";
};
0410697D2E00ABE900A157BB /* sk.lproj */ = {
isa = PBXGroup;
children = (
0410697C2E00ABE900A157BB /* Localizable.strings */,
);
path = sk.lproj;
sourceTree = "<group>";
};
041069822E00C71000A157BB /* kk.lproj */ = {
isa = PBXGroup;
children = (
041069812E00C71000A157BB /* Localizable.strings */,
);
path = kk.lproj;
sourceTree = "<group>";
};
041261032E00D14F00D05B47 /* sv.lproj */ = {
isa = PBXGroup;
children = (
041261022E00D14F00D05B47 /* Localizable.strings */,
);
path = sv.lproj;
sourceTree = "<group>";
};
0457C5962DE7712A000AFBD9 /* ViewModifiers */ = {
isa = PBXGroup;
children = (
@ -576,6 +616,10 @@
13530BE02E00028E0048B7DE /* Localization */ = {
isa = PBXGroup;
children = (
041261032E00D14F00D05B47 /* sv.lproj */,
041069822E00C71000A157BB /* kk.lproj */,
0410697A2E00ABE900A157BB /* de.lproj */,
0410697D2E00ABE900A157BB /* sk.lproj */,
04A1B73B2DFF39EB0064688A /* nn.lproj */,
0409FE8B2DFF2886000DB00C /* ru.lproj */,
0409FE832DFF0870000DB00C /* cz.lproj */,
@ -795,6 +839,10 @@
es,
ru,
nn,
de,
sk,
kk,
sv,
);
mainGroup = 133D7C612D2BE2500075467E;
packageReferences = (
@ -820,10 +868,14 @@
0488FA9A2DFDF380007575E1 /* Localizable.strings in Resources */,
0488FA9E2DFDF3BB007575E1 /* Localizable.strings in Resources */,
0409FE872DFF0870000DB00C /* Localizable.strings in Resources */,
041261042E00D14F00D05B47 /* Localizable.strings in Resources */,
0409FE882DFF0870000DB00C /* Localizable.strings in Resources */,
0410697E2E00ABE900A157BB /* Localizable.strings in Resources */,
0410697F2E00ABE900A157BB /* Localizable.strings in Resources */,
0409FE8C2DFF2886000DB00C /* Localizable.strings in Resources */,
04A1B73C2DFF39EB0064688A /* Localizable.strings in Resources */,
133D7C752D2BE2520075467E /* Preview Assets.xcassets in Resources */,
041069832E00C71000A157BB /* Localizable.strings in Resources */,
133D7C722D2BE2520075467E /* Assets.xcassets in Resources */,
0488FA952DFDE724007575E1 /* Localizable.strings in Resources */,
0488FA962DFDE724007575E1 /* Localizable.strings in Resources */,
@ -952,6 +1004,38 @@
name = Localizable.strings;
sourceTree = "<group>";
};
041069792E00ABE900A157BB /* Localizable.strings */ = {
isa = PBXVariantGroup;
children = (
041069782E00ABE900A157BB /* de */,
);
name = Localizable.strings;
sourceTree = "<group>";
};
0410697C2E00ABE900A157BB /* Localizable.strings */ = {
isa = PBXVariantGroup;
children = (
0410697B2E00ABE900A157BB /* sk */,
);
name = Localizable.strings;
sourceTree = "<group>";
};
041069812E00C71000A157BB /* Localizable.strings */ = {
isa = PBXVariantGroup;
children = (
041069802E00C71000A157BB /* kk */,
);
name = Localizable.strings;
sourceTree = "<group>";
};
041261022E00D14F00D05B47 /* Localizable.strings */ = {
isa = PBXVariantGroup;
children = (
041261012E00D14F00D05B47 /* sv */,
);
name = Localizable.strings;
sourceTree = "<group>";
};
0488FA902DFDE724007575E1 /* Localizable.strings */ = {
isa = PBXVariantGroup;
children = (