Add support of localisations.
This commit is contained in:
parent
33f0d07782
commit
95af9f59bd
|
@ -0,0 +1,231 @@
|
|||
// MARK: Common strings.
|
||||
"global.title.contentWarning" = "Sensitive content";
|
||||
"global.title.seePost" = "See post";
|
||||
"global.title.seePost" = "Refresh";
|
||||
|
||||
// MARK: Global errors.
|
||||
"global.error.unexpected" = "Unexpected error.";
|
||||
"global.error.statusesNotRetrieved" = "Statuses not retrieved.";
|
||||
"global.error.errorDuringDownloadStatuses" = "Error during download statuses from server.";
|
||||
"global.error.errorDuringDownloadHashtag" = "Error during download tag from server.";
|
||||
"global.error.hashtagNotExists" = "Hashtag not exists.";
|
||||
"global.error.errorDuringImageDownload" = "Cannot download image.";
|
||||
"global.error.canceledImageDownload" = "Download image has been canceled.";
|
||||
"global.error.errorDuringDataLoad" = "Loading data failed.";
|
||||
|
||||
// MARK: Main view (main navigation bar).
|
||||
"mainview.tab.homeTimeline" = "Home";
|
||||
"mainview.tab.localTimeline" = "Local";
|
||||
"mainview.tab.federatedTimeline" = "Federated";
|
||||
"mainview.tab.trendingPhotos" = "Photos";
|
||||
"mainview.tab.trendingTags" = "Tags";
|
||||
"mainview.tab.trendingAccounts" = "Accounts";
|
||||
"mainview.tab.userProfile" = "Profile";
|
||||
"mainview.tab.notifications" = "Notifications";
|
||||
"mainview.tab.search" = "Search";
|
||||
"mainview.tab.trending" = "Trending";
|
||||
|
||||
// MARK: Main view (leading navigation bar).
|
||||
"mainview.menu.settings" = "Settings";
|
||||
|
||||
// MARK: Main view (error notifications).
|
||||
"mainview.error.switchAccounts" = "Cannot switch accounts.";
|
||||
|
||||
// MARK: Home timeline.
|
||||
"home.title.allCaughtUp" = "You're all caught up";
|
||||
"home.title.noPhotos" = "Unfortunately, there are no photos here.";
|
||||
|
||||
// MARK: Statuses timeline (local/federated/favourite/bookmarks etc.).
|
||||
"statuses.navigationBar.localTimeline" = "Local";
|
||||
"statuses.navigationBar.federatedTimeline" = "Federated";
|
||||
"statuses.navigationBar.favourites" = "Favourites";
|
||||
"statuses.navigationBar.bookmarks" = "Bookmarks";
|
||||
"statuses.title.noPhotos" = "Unfortunately, there are no photos here.";
|
||||
"statuses.title.tagFollowed" = "You are following the tag.";
|
||||
"statuses.title.tagUnfollowed" = "Tag has been unfollowed.";
|
||||
"statuses.error.loadingStatusesFailed" = "Loading statuses failed.";
|
||||
"statuses.error.tagFollowFailed" = "Follow tag failed.";
|
||||
"statuses.error.tagUnfollowFailed" = "Unfollow tag failed.";
|
||||
|
||||
// Mark: Search view.
|
||||
"search.navigationBar.title" = "Search";
|
||||
"search.title.placeholder" = "Search...";
|
||||
"search.title.usersWith" = "Users with %@";
|
||||
"search.title.goToUser" = "Go to user %@";
|
||||
"search.title.hashtagWith" = "Hashtags with %@";
|
||||
"search.title.goToHashtag" = "Go to hashtag %@";
|
||||
|
||||
// Mark: Trending statuses.
|
||||
"trendingStatuses.navigationBar.title" = "Photos";
|
||||
"trendingStatuses.title.daily" = "Daily";
|
||||
"trendingStatuses.title.monthly" = "Monthly";
|
||||
"trendingStatuses.title.yearly" = "Yearly";
|
||||
"trendingStatuses.error.loadingStatusesFailed" = "Loading statuses failed.";
|
||||
"trendingStatuses.title.noPhotos" = "Unfortunately, there are no photos here.";
|
||||
|
||||
// Mark: Trending tags.
|
||||
"trendingTags.navigationBar.title" = "Tags";
|
||||
"trendingTags.title.noTags" = "Unfortunately, there are no tags here.";
|
||||
"trendingTags.title.amountOfPosts" = "%d posts";
|
||||
"trendingTags.error.loadingTagsFailed" = "Loading tags failed.";
|
||||
|
||||
// Mark: Trending accounts.
|
||||
"trendingAccounts.navigationBar.title" = "Accounts";
|
||||
"trendingAccounts.title.noAccounts" = "Unfortunately, there is no one here.";
|
||||
"trendingAccounts.error.loadingAccountsFailed" = "Loading accounts failed.";
|
||||
|
||||
// Mark: User profile view.
|
||||
"userProfile.title.openInBrowser" = "Open in browser";
|
||||
"userProfile.title.share" = "Share";
|
||||
"userProfile.title.unmute" = "Unmute";
|
||||
"userProfile.title.mute" = "Mute";
|
||||
"userProfile.title.unblock" = "Unblock";
|
||||
"userProfile.title.block" = "Block";
|
||||
"userProfile.title.favourites" = "Favourites";
|
||||
"userProfile.title.bookmarks" = "Bookmarks";
|
||||
"userProfile.title.posts" = "Posts";
|
||||
"userProfile.title.followers" = "Followers";
|
||||
"userProfile.title.following" = "Following";
|
||||
"userProfile.title.joined" = "Joined %@";
|
||||
"userProfile.title.unfollow" = "Unfollow";
|
||||
"userProfile.title.followBack" = "Follow back";
|
||||
"userProfile.title.follow" = "Follow";
|
||||
"userProfile.error.notExists" = "Account not exists.";
|
||||
"userProfile.error.loadingAccountFailed" = "Error during download account from server.";
|
||||
"userProfile.error.muting" = "Muting/unmuting action failed.";
|
||||
"userProfile.error.block" = "Block/unblock action failed.";
|
||||
"userProfile.error.relationship" = "Relationship action failed.";
|
||||
|
||||
// Mark: Notifications view.
|
||||
"notifications.navigationBar.title" = "Notifications";
|
||||
"notifications.title.noNotifications" = "Unfortunately, there is nothing here.";
|
||||
"notifications.title.followedYou" = "followed you";
|
||||
"notifications.title.mentionedYou" = "mentioned you";
|
||||
"notifications.title.boosted" = "boosted";
|
||||
"notifications.title.favourited" = "favourited";
|
||||
"notifications.title.postedStatus" = "posted status";
|
||||
"notifications.title.followRequest" = "follow request";
|
||||
"notifications.title.poll" = "poll";
|
||||
"notifications.title.updatedStatus" = "updated status";
|
||||
"notifications.title.signedUp" = "signed up";
|
||||
"notifications.title.newReport" = "new report";
|
||||
"notifications.error.loadingNotificationsFailed" = "Loading notifications failed.";
|
||||
|
||||
// Mark: Compose view.
|
||||
"compose.navigationBar.title" = "Compose";
|
||||
"compose.title.everyone" = "Everyone";
|
||||
"compose.title.unlisted" = "Unlisted";
|
||||
"compose.title.followers" = "Followers";
|
||||
"compose.title.attachPhotoFull" = "Attach a photo and type what's on your mind";
|
||||
"compose.title.attachPhotoMini" = "Type what's on your mind";
|
||||
"compose.title.publish" = "Publish";
|
||||
"compose.title.cancel" = "Cancel";
|
||||
"compose.title.writeContentWarning" = "Write content warning";
|
||||
"compose.title.commentsWillBeDisabled" = "Comments will be disabled";
|
||||
"compose.title.statusPublished" = "Status published";
|
||||
"compose.title.tryToUpload" = "Try to upload";
|
||||
"compose.title.delete" = "Delete";
|
||||
"compose.title.edit" = "Edit";
|
||||
"compose.error.loadingPhotosFailed" = "Cannot retreive image from library.";
|
||||
"compose.error.postingPhotoFailed" = "Error during posting photo.";
|
||||
"compose.error.postingStatusFailed" = "Error during posting status.";
|
||||
|
||||
// Mark: Photo editor view.
|
||||
"photoEdit.navigationBar.title" = "Photo details";
|
||||
"photoEdit.title.photo" = "Photo";
|
||||
"photoEdit.title.accessibility" = "Accessibility";
|
||||
"photoEdit.title.accessibilityDescription" = "Description for the visually impaired";
|
||||
"photoEdit.title.save" = "Save";
|
||||
"photoEdit.title.cancel" = "Cancel";
|
||||
"photoEdit.error.updatePhotoFailed" = "Error during updating photo.";
|
||||
|
||||
// Mark: Place selector view.
|
||||
"placeSelector.navigationBar.title" = "Places";
|
||||
"placeSelector.title.search" = "Search...";
|
||||
"placeSelector.title.buttonSearch" = "Search";
|
||||
"placeSelector.title.cancel" = "Cancel";
|
||||
"placeSelector.error.loadingPlacesFailed" = "Loading notifications failed.";
|
||||
|
||||
// Mark: Settings view.
|
||||
"settings.navigationBar.title" = "Settings";
|
||||
"settings.title.close" = "Close";
|
||||
"settings.title.version" = "Version";
|
||||
"settings.title.accounts" = "Accounts";
|
||||
"settings.title.newAccount" = "New account";
|
||||
"settings.title.accent" = "Accent";
|
||||
"settings.title.theme" = "Theme";
|
||||
"settings.title.system" = "System";
|
||||
"settings.title.light" = "Light";
|
||||
"settings.title.dark" = "Dark";
|
||||
"settings.title.avatar" = "Avatar";
|
||||
"settings.title.circle" = "Circle";
|
||||
"settings.title.rounderRectangle" = "Rounded rectangle";
|
||||
"settings.title.other" = "Other";
|
||||
"settings.title.thirdParty" = "Third party";
|
||||
"settings.title.reportBug" = "Report a bug";
|
||||
"settings.title.githubIssues" = "Issues on Github";
|
||||
"settings.title.follow" = "Follow me on Mastodon";
|
||||
"settings.title.support" = "Support";
|
||||
"settings.title.thankYouTitle" = "Thank you 💕";
|
||||
"settings.title.thankYouMessage" = "Thanks for your purchase. Purchases both big and small help us keep our dream of providing the best quality products to our customers. We hope you’re loving Vernissage.";
|
||||
"settings.title.thankYouClose" = "Close";
|
||||
"settings.title.haptics" = "Haptics";
|
||||
"settings.title.hapticsTabSelection" = "Tab selection";
|
||||
"settings.title.hapticsButtonPress" = "Button press";
|
||||
"settings.title.hapticsListRefresh" = "List refresh";
|
||||
"settings.title.hapticsAnimationFinished" = "Animation finished";
|
||||
"settings.title.mediaSettings" = "Media settings";
|
||||
"settings.title.alwaysShowSensitiveTitle" = "Always show NSFW";
|
||||
"settings.title.alwaysShowSensitiveDescription" = "Force show all NFSW (sensitive) media without warnings";
|
||||
"settings.title.alwaysShowAltTitle" = "Show alternative text";
|
||||
"settings.title.alwaysShowAltDescription" = "Show alternative text if present on status details screen";
|
||||
|
||||
// Mark: Signin view.
|
||||
"signin.navigationBar.title" = "Sign in to Pixelfed";
|
||||
"signin.title.serverAddress" = "Server address";
|
||||
"signin.title.signIn" = "Sign in";
|
||||
"signin.title.enterServerAddress" = "Enter server address";
|
||||
"signin.title.howToJoinLink" = "How to join Pixelfed";
|
||||
"signin.title.chooseServer" = "Or choose Pixelfed server";
|
||||
"signin.title.amountOfUsers" = "%d users";
|
||||
"signin.title.amountOStatuses" = "%d statuses";
|
||||
"signin.error.communicationFailed" = "Communication with server failed.";
|
||||
|
||||
// Mark: Status view.
|
||||
"status.navigationBar.title" = "Details";
|
||||
"status.title.uploaded" = "Uploaded";
|
||||
"status.title.via" = "via %@";
|
||||
"status.title.reboostedBy" = "Reboosted by";
|
||||
"status.title.favouritedBy" = "Favourited by";
|
||||
"status.title.openInBrowser" = "Open in browser";
|
||||
"status.title.shareStatus" = "Share status";
|
||||
"status.title.yourStatus" = "Your status";
|
||||
"status.title.delete" = "Delete";
|
||||
"status.title.reboosted" = "Reboosted";
|
||||
"status.title.unreboosted" = "Unreboosted";
|
||||
"status.title.favourited" = "Favourited";
|
||||
"status.title.unfavourited" = "Unfavourited";
|
||||
"status.title.bookmarked" = "Bookmarked";
|
||||
"status.title.unbookmarked" = "Unbookmarked";
|
||||
"status.title.statusDeleted" = "Status deleted";
|
||||
"status.error.loadingStatusFailed" = "Loading status failed.";
|
||||
"status.error.notFound" = "Status not existing anymore.";
|
||||
"status.error.loadingCommentsFailed" = "Comments cannot be downloaded.";
|
||||
"status.error.reboostFailed" = "Reboost action failed.";
|
||||
"status.error.favouriteFailed" = "Favourite action failed.";
|
||||
"status.error.bookmarkFailed" = "Bookmark action failed.";
|
||||
"status.error.deleteFailed" = "Delete action failed.";
|
||||
|
||||
// Mark: Accounts view.
|
||||
"accounts.navigationBar.followers" = "Followers";
|
||||
"accounts.navigationBar.following" = "Following";
|
||||
"accounts.navigationBar.favouritedBy" = "Favourited by";
|
||||
"accounts.navigationBar.reboostedBy" = "Reboosted by";
|
||||
"accounts.title.noAccounts" = "Unfortunately, there is no one here.";
|
||||
"accounts.error.loadingAccountsFailed" = "Loading accounts failed.";
|
||||
|
||||
// Mark: Third party view.
|
||||
"thirdParty.navigationBar.title" = "Third party";
|
||||
|
||||
// Mark: Widget view.
|
||||
"widget.title.description" = "Widget with photos from Pixelfed.";
|
|
@ -0,0 +1,231 @@
|
|||
// MARK: Common strings.
|
||||
"global.title.contentWarning" = "Wrażliwe treści";
|
||||
"global.title.seePost" = "Pokaż zdjęcie";
|
||||
"global.title.seePost" = "Odśwież";
|
||||
|
||||
// MARK: Global errors.
|
||||
"global.error.unexpected" = "Wystąpił nieoczekiwany błąd.";
|
||||
"global.error.statusesNotRetrieved" = "Statusy nie zostały pobrane.";
|
||||
"global.error.errorDuringDownloadStatuses" = "Błąd podczas pobierania statusów.";
|
||||
"global.error.errorDuringDownloadHashtag" = "Błąd podczas pobierania taga.";
|
||||
"global.error.hashtagNotExists" = "Tag nie istnieje.";
|
||||
"global.error.errorDuringImageDownload" = "Błąd podczas pobierania zdjęcia.";
|
||||
"global.error.canceledImageDownload" = "Pobieranie zdjęcia zostało anulowane.";
|
||||
"global.error.errorDuringDataLoad" = "Błąd podczas pobierania danych.";
|
||||
|
||||
// MARK: Main view (main navigation bar).
|
||||
"mainview.tab.homeTimeline" = "Główna";
|
||||
"mainview.tab.localTimeline" = "Lokalne";
|
||||
"mainview.tab.federatedTimeline" = "Globalne";
|
||||
"mainview.tab.trendingPhotos" = "Zdjęcia";
|
||||
"mainview.tab.trendingTags" = "Tagi";
|
||||
"mainview.tab.trendingAccounts" = "Użytkownicy";
|
||||
"mainview.tab.userProfile" = "Profil";
|
||||
"mainview.tab.notifications" = "Powiadomienia";
|
||||
"mainview.tab.search" = "Wyszukaj";
|
||||
"mainview.tab.trending" = "Popularne";
|
||||
|
||||
// MARK: Main view (leading navigation bar).
|
||||
"mainview.menu.settings" = "Ustawienia";
|
||||
|
||||
// MARK: Main view (error notifications).
|
||||
"mainview.error.switchAccounts" = "Błąd podczas przełączania kont.";
|
||||
|
||||
// MARK: Home timeline.
|
||||
"home.title.allCaughtUp" = "Jesteś na bieżąco";
|
||||
"home.title.noPhotos" = "Niestety nie ma jeszcze żadnych zdjęć.";
|
||||
|
||||
// MARK: Statuses timeline (local/federated/favourite/bookmarks etc.).
|
||||
"statuses.navigationBar.localTimeline" = "Lokalne";
|
||||
"statuses.navigationBar.federatedTimeline" = "Globalne";
|
||||
"statuses.navigationBar.favourites" = "Polubione";
|
||||
"statuses.navigationBar.bookmarks" = "Zakładki";
|
||||
"statuses.title.noPhotos" = "Niestety nie ma jeszcze żadnych zdjęć.";
|
||||
"statuses.title.tagFollowed" = "Od teraz śledzisz taga.";
|
||||
"statuses.title.tagUnfollowed" = "Nie śledzisz już taga.";
|
||||
"statuses.error.loadingStatusesFailed" = "Błąd podczas wczytywania statusów.";
|
||||
"statuses.error.tagFollowFailed" = "Błąd podczas żądania śledzenia taga.";
|
||||
"statuses.error.tagUnfollowFailed" = "Błąd podczas wyłączenia śledzenia taga.";
|
||||
|
||||
// Mark: Search view.
|
||||
"search.navigationBar.title" = "Wyszukaj";
|
||||
"search.title.placeholder" = "Wyszukaj...";
|
||||
"search.title.usersWith" = "Użytkownicy zawierający %@";
|
||||
"search.title.goToUser" = "Przejdź do użytkownika %@";
|
||||
"search.title.hashtagWith" = "Tagi zawierające %@";
|
||||
"search.title.goToHashtag" = "Przejdź do taga %@";
|
||||
|
||||
// Mark: Trending statuses.
|
||||
"trendingStatuses.navigationBar.title" = "Zdjęcia";
|
||||
"trendingStatuses.title.daily" = "Dzień";
|
||||
"trendingStatuses.title.monthly" = "Miesiąc";
|
||||
"trendingStatuses.title.yearly" = "Rok";
|
||||
"trendingStatuses.error.loadingStatusesFailed" = "Błąd podczas wczytywania statusów.";
|
||||
"trendingStatuses.title.noPhotos" = "Niestety nie ma jeszcze żadnych zdjęć.";
|
||||
|
||||
// Mark: Trending tags.
|
||||
"trendingTags.navigationBar.title" = "Tags";
|
||||
"trendingTags.title.noTags" = "Niestety nie ma jeszcze żadnych tagów.";
|
||||
"trendingTags.title.amountOfPosts" = "%d statusów";
|
||||
"trendingTags.error.loadingTagsFailed" = "Błąd podczas wczytywania tagów.";
|
||||
|
||||
// Mark: Trending accounts.
|
||||
"trendingAccounts.navigationBar.title" = "Użytkownicy";
|
||||
"trendingAccounts.title.noAccounts" = "Niestety nie ma tutaj nikogo.";
|
||||
"trendingAccounts.error.loadingAccountsFailed" = "Błąd podczas wczytywania użytkownikow.";
|
||||
|
||||
// Mark: User profile view.
|
||||
"userProfile.title.openInBrowser" = "Otwórz w przeglądarce";
|
||||
"userProfile.title.share" = "Udostępnij";
|
||||
"userProfile.title.unmute" = "Wyłącz wyciszenie";
|
||||
"userProfile.title.mute" = "Wycisz";
|
||||
"userProfile.title.unblock" = "Odblokuj";
|
||||
"userProfile.title.block" = "Zablokuj";
|
||||
"userProfile.title.favourites" = "Polubione";
|
||||
"userProfile.title.bookmarks" = "Zakładki";
|
||||
"userProfile.title.posts" = "Statusy";
|
||||
"userProfile.title.followers" = "Obserwujący";
|
||||
"userProfile.title.following" = "Obserwowani";
|
||||
"userProfile.title.joined" = "Dołączył(a) %@";
|
||||
"userProfile.title.unfollow" = "Przestań obserwować";
|
||||
"userProfile.title.followBack" = "Również obserwuj";
|
||||
"userProfile.title.follow" = "Obserwuj";
|
||||
"userProfile.error.notExists" = "Konto nie istnieje.";
|
||||
"userProfile.error.notExists" = "Błąd podczas pobierania danych użytkownika.";
|
||||
"userProfile.error.mute" = "Błąd podczas wyciszania użytkownika.";
|
||||
"userProfile.error.block" = "Błąd podczas blokowania/odblokowywania użytkownika.";
|
||||
"userProfile.error.relationship" = "Błąd podczas zmiany relacji z użytkownikiem.";
|
||||
|
||||
// Mark: Notifications view.
|
||||
"notifications.navigationBar.title" = "Powiadomienia";
|
||||
"notifications.title.noNotifications" = "Niestety nic tutaj nie ma.";
|
||||
"notifications.title.followedYou" = "obserwuje ciebie";
|
||||
"notifications.title.mentionedYou" = "wspomniał ciebie";
|
||||
"notifications.title.boosted" = "podbił";
|
||||
"notifications.title.favourited" = "polubił";
|
||||
"notifications.title.postedStatus" = "stworzył status";
|
||||
"notifications.title.followRequest" = "chce obserwować";
|
||||
"notifications.title.poll" = "ankieta";
|
||||
"notifications.title.updatedStatus" = "zaktualizował status";
|
||||
"notifications.title.signedUp" = "zalogował się";
|
||||
"notifications.title.newReport" = "nowy raport";
|
||||
"notifications.error.loadingNotificationsFailed" = "Błąd podczas wczytywania powiadomień.";
|
||||
|
||||
// Mark: Compose view.
|
||||
"compose.navigationBar.title" = "Utwórz";
|
||||
"compose.title.everyone" = "Publiczny";
|
||||
"compose.title.unlisted" = "Publiczny (niewidoczny)";
|
||||
"compose.title.followers" = "Tylko obserwujący";
|
||||
"compose.title.attachPhotoFull" = "Dołącz zdjęcie i napisz, co myślisz";
|
||||
"compose.title.attachPhotoMini" = "Wpisz, co masz na myśli";
|
||||
"compose.title.publish" = "Wyślij";
|
||||
"compose.title.cancel" = "Anuluj";
|
||||
"compose.title.writeContentWarning" = "Napisz ostrzeżenie o treści";
|
||||
"compose.title.commentsWillBeDisabled" = "Komentarze zostaną wyłączone";
|
||||
"compose.title.statusPublished" = "Stan opublikowany";
|
||||
"compose.title.tryToUpload" = "Ponów";
|
||||
"compose.title.delete" = "Usuń";
|
||||
"compose.title.edit" = "Edytuj";
|
||||
"compose.error.loadingPhotosFailed" = "Nie można pobrać zdjęcia z biblioteki.";
|
||||
"compose.error.postingPhotoFailed" = "Błąd podczas publikowania zdjęcia.";
|
||||
"compose.error.postingStatusFailed" = "Błąd podczas wysyłania statusu.";
|
||||
|
||||
// Mark: Photo editor view.
|
||||
"photoEdit.navigationBar.title" = "Szczegóły zdjęcia";
|
||||
"photoEdit.title.photo" = "Zdjęcie";
|
||||
"photoEdit.title.accessibility" = "Dostępność";
|
||||
"photoEdit.title.accessibilityDescription" = "Opis dla osób niedowidzących";
|
||||
"photoEdit.title.save" = "Zapisz";
|
||||
"photoEdit.title.cancel" = "Anuluj";
|
||||
"photoEdit.error.updatePhotoFailed" = "Błąd podczas aktualizowania zdjęcia.";
|
||||
|
||||
// Mark: Place selector view.
|
||||
"placeSelector.navigationBar.title" = "Lokalizacja";
|
||||
"placeSelector.title.search" = "Wyszukaj...";
|
||||
"placeSelector.title.buttonSearch" = "Szukaj";
|
||||
"placeSelector.title.cancel" = "Anuluj";
|
||||
"placeSelector.error.loadingPlacesFailed" = "Błąd podczas wczytywanie lokalizacji.";
|
||||
|
||||
// Mark: Settings view.
|
||||
"settings.navigationBar.title" = "Ustawienia";
|
||||
"settings.title.close" = "Zamknij";
|
||||
"settings.title.version" = "Wersja";
|
||||
"settings.title.accounts" = "Konta";
|
||||
"settings.title.newAccount" = "Dodaj konto";
|
||||
"settings.title.accent" = "Akcent";
|
||||
"settings.title.theme" = "Wygląd";
|
||||
"settings.title.system" = "Systemowy";
|
||||
"settings.title.light" = "Jasny";
|
||||
"settings.title.dark" = "Ciemny";
|
||||
"settings.title.avatar" = "Awatar";
|
||||
"settings.title.circle" = "Okrągły";
|
||||
"settings.title.rounderRectangle" = "Zaokrąglony kwadratowy";
|
||||
"settings.title.other" = "Inne";
|
||||
"settings.title.thirdParty" = "Zewnętrzne biblioteki";
|
||||
"settings.title.reportBug" = "Zgłoś błąd";
|
||||
"settings.title.githubIssues" = "Błędy na Github";
|
||||
"settings.title.follow" = "Obserwuj mnie na Mastodon";
|
||||
"settings.title.support" = "Wsparcie";
|
||||
"settings.title.thankYouTitle" = "Dziękuję 💕";
|
||||
"settings.title.thankYouMessage" = "Dziękujemy za twój zakup. Zakupy zarówno te duże, jak i te małe pomagają nam w realizacji marzenia o dostarczaniu naszym klientom produktów najwyższej jakości. Mamy nadzieję, że Vernissage spełnia Twoje oczekiwania.";
|
||||
"settings.title.thankYouClose" = "Zamknij";
|
||||
"settings.title.haptics" = "Haptyka";
|
||||
"settings.title.hapticsTabSelection" = "Wybór zakładki";
|
||||
"settings.title.hapticsButtonPress" = "Naciśnięcie przycisku";
|
||||
"settings.title.hapticsListRefresh" = "Odświeżanie listy";
|
||||
"settings.title.hapticsAnimationFinished" = "Zakończenie animacji";
|
||||
"settings.title.mediaSettings" = "Ustawienia mediów";
|
||||
"settings.title.alwaysShowSensitiveTitle" = "Zawsze pokazuj statusy NSFW";
|
||||
"settings.title.alwaysShowSensitiveDescription" = "Wymuś pokazywanie statusów NFSW (czułych) bez ostrzeżeń";
|
||||
"settings.title.alwaysShowAltTitle" = "Pokaż tekst alternatywny";
|
||||
"settings.title.alwaysShowAltDescription" = "Pokaż alternatywny tekst, jeśli jest obecny na szczegółach statusu";
|
||||
|
||||
// Mark: Signin view.
|
||||
"signin.navigationBar.title" = "Zaloguj się do Pixelfed";
|
||||
"signin.title.serverAddress" = "Adres serwera";
|
||||
"signin.title.signIn" = "Zaloguj się";
|
||||
"signin.title.enterServerAddress" = "Wpisz adres serwera";
|
||||
"signin.title.howToJoinLink" = "Jak przyłączyć się do Pixelfed";
|
||||
"signin.title.chooseServer" = "Lub wybierz serwer Pixelfed";
|
||||
"signin.title.amountOfUsers" = "%d użytkowników";
|
||||
"signin.title.amountOStatuses" = "%d statusów";
|
||||
"signin.error.communicationFailed" = "Błąd podczas komunikacji z serwerem.";
|
||||
|
||||
// Mark: Status view.
|
||||
"status.navigationBar.title" = "Szczegóły";
|
||||
"status.title.uploaded" = "Wysłano";
|
||||
"status.title.via" = "przez %@";
|
||||
"status.title.reboostedBy" = "Podbite przez";
|
||||
"status.title.favouritedBy" = "Polubione przez";
|
||||
"status.title.openInBrowser" = "Otwórz w przeglądarce";
|
||||
"status.title.shareStatus" = "Udostępnij";
|
||||
"status.title.yourStatus" = "Twój status";
|
||||
"status.title.delete" = "Usuń";
|
||||
"status.title.reboosted" = "Podbite";
|
||||
"status.title.unreboosted" = "Podbicie wycofane";
|
||||
"status.title.favourited" = "Polubione";
|
||||
"status.title.unfavourited" = "Polubienie wycofane";
|
||||
"status.title.bookmarked" = "Dodane do zakładek";
|
||||
"status.title.unbookmarked" = "Usunięte z zakładek";
|
||||
"status.title.statusDeleted" = "Status usunięty";
|
||||
"status.error.loadingStatusFailed" = "Błąd podczas wczytywanie statusu.";
|
||||
"status.error.notFound" = "Status już nie istnieje.";
|
||||
"status.error.loadingCommentsFailed" =" Błąd podczas wczytywanie komentarzy.";
|
||||
"status.error.reboostFailed" = "Błąd podczas podbijania.";
|
||||
"status.error.favouriteFailed" = "Błąd podczas polubiania.";
|
||||
"status.error.bookmarkFailed" = "Błąd podczas dodawania/uzuwania z zakładek.";
|
||||
"status.error.deleteFailed" = "Błąd podczas usuwania.";
|
||||
|
||||
// Mark: Accounts view.
|
||||
"accounts.navigationBar.followers" = "Obserwujący";
|
||||
"accounts.navigationBar.following" = "Obserwowani";
|
||||
"accounts.navigationBar.favouritedBy" = "Polubione przez";
|
||||
"accounts.navigationBar.reboostedBy" = "Podbite przez";
|
||||
"accounts.title.noAccounts" = "Niestety nie ma tutaj nikogo.";
|
||||
"accounts.error.loadingAccountsFailed" = "Błąd podczas wczytywania użytkownikow.";
|
||||
|
||||
// Mark: Third party view.
|
||||
"thirdParty.navigationBar.title" = "Zewnętrzne biblioteki";
|
||||
|
||||
// Mark: Widget view.
|
||||
"widget.title.description" = "Widget ze zdjęciami z Pixelfed.";
|
|
@ -27,6 +27,8 @@
|
|||
F8210DEA2966E4F9001D9973 /* AnimatePlaceholderModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8210DE92966E4F9001D9973 /* AnimatePlaceholderModifier.swift */; };
|
||||
F829193C2983012400367CE2 /* ImageSizeService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F829193B2983012400367CE2 /* ImageSizeService.swift */; };
|
||||
F8341F90295C636C009C8EE6 /* Data+Exif.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8341F8F295C636C009C8EE6 /* Data+Exif.swift */; };
|
||||
F835082329BEF9C400DE3247 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = F835082629BEF9C400DE3247 /* Localizable.strings */; };
|
||||
F835082429BEF9C400DE3247 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = F835082629BEF9C400DE3247 /* Localizable.strings */; };
|
||||
F83901A6295D8EC000456AE2 /* LabelIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = F83901A5295D8EC000456AE2 /* LabelIcon.swift */; };
|
||||
F83CBEFB298298A1002972C8 /* ImageCarouselPicture.swift in Sources */ = {isa = PBXBuildFile; fileRef = F83CBEFA298298A1002972C8 /* ImageCarouselPicture.swift */; };
|
||||
F83E00ED29A2237C005D25A3 /* PixelfedKit in Frameworks */ = {isa = PBXBuildFile; productRef = F83E00EC29A2237C005D25A3 /* PixelfedKit */; };
|
||||
|
@ -247,6 +249,8 @@
|
|||
F8210DE92966E4F9001D9973 /* AnimatePlaceholderModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnimatePlaceholderModifier.swift; sourceTree = "<group>"; };
|
||||
F829193B2983012400367CE2 /* ImageSizeService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageSizeService.swift; sourceTree = "<group>"; };
|
||||
F8341F8F295C636C009C8EE6 /* Data+Exif.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Data+Exif.swift"; sourceTree = "<group>"; };
|
||||
F835082529BEF9C400DE3247 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
F835082729BEFA1E00DE3247 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
F837269429A221420098D3C4 /* PixelfedKit */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = PixelfedKit; sourceTree = "<group>"; };
|
||||
F83901A5295D8EC000456AE2 /* LabelIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelIcon.swift; sourceTree = "<group>"; };
|
||||
F83CBEFA298298A1002972C8 /* ImageCarouselPicture.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCarouselPicture.swift; sourceTree = "<group>"; };
|
||||
|
@ -576,6 +580,14 @@
|
|||
path = CoreData;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F835081F29BEF88600DE3247 /* Localization */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F835082629BEF9C400DE3247 /* Localizable.strings */,
|
||||
);
|
||||
path = Localization;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F83901A2295D863B00456AE2 /* Widgets */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -724,6 +736,7 @@
|
|||
F8F6E44329BC5CAA0004795E /* VernissageWidgetExtension.entitlements */,
|
||||
F837269429A221420098D3C4 /* PixelfedKit */,
|
||||
F88ABD9529687D4D004EF61E /* README.md */,
|
||||
F835081F29BEF88600DE3247 /* Localization */,
|
||||
F864F79C29BB9D2400B13921 /* Models */,
|
||||
F8341F96295C6427009C8EE6 /* CoreData */,
|
||||
F88C246A295C37B80006098B /* Vernissage */,
|
||||
|
@ -972,6 +985,7 @@
|
|||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
pl,
|
||||
);
|
||||
mainGroup = F88C245F295C37B80006098B;
|
||||
packageReferences = (
|
||||
|
@ -996,6 +1010,7 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
F864F76829BB91B600B13921 /* Assets.xcassets in Resources */,
|
||||
F835082429BEF9C400DE3247 /* Localizable.strings in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -1004,6 +1019,7 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
F88C2473295C37BB0006098B /* Preview Assets.xcassets in Resources */,
|
||||
F835082329BEF9C400DE3247 /* Localizable.strings in Resources */,
|
||||
F88C2470295C37BB0006098B /* Assets.xcassets in Resources */,
|
||||
F86A42FF299A8C5500DF7645 /* InAppPurchaseStoreKitConfiguration.storekit in Resources */,
|
||||
);
|
||||
|
@ -1216,6 +1232,18 @@
|
|||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
F835082629BEF9C400DE3247 /* Localizable.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
F835082529BEF9C400DE3247 /* en */,
|
||||
F835082729BEFA1E00DE3247 /* pl */,
|
||||
);
|
||||
name = Localizable.strings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
F864F76E29BB91B600B13921 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
|
@ -1278,6 +1306,7 @@
|
|||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||
|
@ -1338,6 +1367,7 @@
|
|||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||
|
|
|
@ -21,6 +21,7 @@ public class ErrorService {
|
|||
}
|
||||
}
|
||||
|
||||
print("Error ['\(message)']: \(error.localizedDescription)")
|
||||
let localizedMessage = NSLocalizedString(message, comment: "Error message")
|
||||
print("Error ['\(localizedMessage)']: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,10 +108,13 @@ public class HomeTimelineService {
|
|||
break
|
||||
}
|
||||
|
||||
amountOfStatuses = amountOfStatuses + downloadedStatuses.count
|
||||
// We have to include in the counter only statuses with images.
|
||||
let statusesWithImagesOnly = downloadedStatuses.getStatusesWithImagesOnly()
|
||||
|
||||
amountOfStatuses = amountOfStatuses + statusesWithImagesOnly.count
|
||||
newestStatusId = firstStatus.id
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Error during downloading new statuses for amountof new statuses.")
|
||||
ErrorService.shared.handle(error, message: "Error during downloading new statuses for amount of new statuses.")
|
||||
break
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ public class ToastrService {
|
|||
|
||||
public func showSuccess(_ title: String, imageSystemName: String, subtitle: String? = nil) {
|
||||
let drop = Drop(
|
||||
title: title,
|
||||
title: NSLocalizedString(title, comment: "Success displayed to the user."),
|
||||
subtitle: subtitle,
|
||||
subtitleNumberOfLines: 2,
|
||||
icon: self.createImage(systemName: imageSystemName, color: UIColor(Color.accentColor)),
|
||||
|
@ -29,9 +29,9 @@ public class ToastrService {
|
|||
Drops.show(drop)
|
||||
}
|
||||
|
||||
public func showError(title: String = "Unexpected error", imageSystemName: String = "ant.circle.fill", subtitle: String? = nil) {
|
||||
public func showError(title: String = "global.error.unexpected", imageSystemName: String = "ant.circle.fill", subtitle: String? = nil) {
|
||||
let drop = Drop(
|
||||
title: title,
|
||||
title: NSLocalizedString(title, comment: "Error displayed to the user."),
|
||||
subtitle: subtitle,
|
||||
subtitleNumberOfLines: 2,
|
||||
icon: self.createImage(systemName: imageSystemName, color: UIColor(Color.red)),
|
||||
|
|
|
@ -25,7 +25,7 @@ struct AccountsPhotoView: View {
|
|||
|
||||
var body: some View {
|
||||
self.mainBody()
|
||||
.navigationTitle("Accounts")
|
||||
.navigationTitle("trendingAccounts.navigationBar.title")
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
|
@ -38,7 +38,7 @@ struct AccountsPhotoView: View {
|
|||
}
|
||||
case .loaded:
|
||||
if self.accounts.isEmpty {
|
||||
NoDataView(imageSystemName: "person.3.sequence", text: "Unfortunately, there is no one here.")
|
||||
NoDataView(imageSystemName: "person.3.sequence", text: "trendingAccounts.title.noAccounts")
|
||||
} else {
|
||||
List {
|
||||
ForEach(self.accounts, id: \.id) { account in
|
||||
|
@ -84,10 +84,10 @@ struct AccountsPhotoView: View {
|
|||
self.state = .loaded
|
||||
} catch {
|
||||
if !Task.isCancelled {
|
||||
ErrorService.shared.handle(error, message: "Accounts not retrieved.", showToastr: true)
|
||||
ErrorService.shared.handle(error, message: "trendingAccounts.error.loadingAccountsFailed", showToastr: true)
|
||||
self.state = .error(error)
|
||||
} else {
|
||||
ErrorService.shared.handle(error, message: "Accounts not retrieved.", showToastr: false)
|
||||
ErrorService.shared.handle(error, message: "trendingAccounts.error.loadingAccountsFailed", showToastr: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ struct AccountsView: View {
|
|||
}
|
||||
case .loaded:
|
||||
if self.accounts.isEmpty {
|
||||
NoDataView(imageSystemName: "person.3.sequence", text: "Unfortunately, there is no one here.")
|
||||
NoDataView(imageSystemName: "person.3.sequence", text: "accounts.title.noAccounts")
|
||||
} else {
|
||||
List {
|
||||
ForEach(accounts, id: \.id) { account in
|
||||
|
@ -92,10 +92,10 @@ struct AccountsView: View {
|
|||
self.state = .loaded
|
||||
} catch {
|
||||
if !Task.isCancelled {
|
||||
ErrorService.shared.handle(error, message: "Accounts not retrieved.", showToastr: true)
|
||||
ErrorService.shared.handle(error, message: "accounts.error.loadingAccountsFailed", showToastr: true)
|
||||
self.state = .error(error)
|
||||
} else {
|
||||
ErrorService.shared.handle(error, message: "Accounts not retrieved.", showToastr: false)
|
||||
ErrorService.shared.handle(error, message: "accounts.error.loadingAccountsFailed", showToastr: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -115,13 +115,13 @@ struct AccountsView: View {
|
|||
private func getTitle() -> String {
|
||||
switch self.listType {
|
||||
case .followers:
|
||||
return "Followers"
|
||||
return NSLocalizedString("accounts.navigationBar.followers", comment: "Followers")
|
||||
case .following:
|
||||
return "Following"
|
||||
return NSLocalizedString("accounts.navigationBar.following", comment: "Following")
|
||||
case .favourited:
|
||||
return "Favourited by"
|
||||
return NSLocalizedString("accounts.navigationBar.favouritedBy", comment: "Favourited by")
|
||||
case .reblogged:
|
||||
return "Reboosted by"
|
||||
return NSLocalizedString("accounts.navigationBar.reboostedBy", comment: "Reboosted by")
|
||||
case .search(let query):
|
||||
return query
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ struct ComposeView: View {
|
|||
@State private var photosAttachment: [PhotoAttachment] = []
|
||||
|
||||
@State private var visibility = Pixelfed.Statuses.Visibility.pub
|
||||
@State private var visibilityText = "Everyone"
|
||||
@State private var visibilityText: LocalizedStringKey = "compose.title.everyone"
|
||||
@State private var visibilityImage = "globe.europe.africa"
|
||||
|
||||
@FocusState private var focusedField: FocusField?
|
||||
|
@ -91,14 +91,14 @@ struct ComposeView: View {
|
|||
ActionButton(showLoader: false) {
|
||||
await self.publishStatus()
|
||||
} label: {
|
||||
Text("Publish")
|
||||
Text("compose.title.publish", comment: "Publish")
|
||||
}
|
||||
.disabled(self.publishDisabled)
|
||||
.buttonStyle(.borderedProminent)
|
||||
}
|
||||
|
||||
ToolbarItem(placement: .cancellationAction) {
|
||||
Button("Cancel", role: .cancel) {
|
||||
Button(NSLocalizedString("compose.title.cancel", comment: "Cancel"), role: .cancel) {
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
|
@ -131,7 +131,7 @@ struct ComposeView: View {
|
|||
selection: $selectedItems,
|
||||
maxSelectionCount: self.applicationState.statusMaxMediaAttachments,
|
||||
matching: .images)
|
||||
.navigationTitle("Compose")
|
||||
.navigationTitle("compose.navigationBar.title")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
}
|
||||
.withAppRouteur()
|
||||
|
@ -256,7 +256,7 @@ struct ComposeView: View {
|
|||
@ViewBuilder
|
||||
private func contentWarningView() -> some View {
|
||||
if self.isSensitive {
|
||||
TextField("Write content warning", text: $spoilerText, axis: .vertical)
|
||||
TextField("compose.title.writeContentWarning", text: $spoilerText, axis: .vertical)
|
||||
.padding(8)
|
||||
.lineLimit(1...2)
|
||||
.focused($focusedField, equals: .spoilerText)
|
||||
|
@ -270,7 +270,7 @@ struct ComposeView: View {
|
|||
if self.commentsDisabled {
|
||||
HStack {
|
||||
Spacer()
|
||||
Text("Comments will be disabled")
|
||||
Text("compose.title.commentsWillBeDisabled")
|
||||
.textCase(.uppercase)
|
||||
.font(.caption2)
|
||||
.foregroundColor(.dangerColor)
|
||||
|
@ -285,26 +285,26 @@ struct ComposeView: View {
|
|||
Menu {
|
||||
Button {
|
||||
self.visibility = .pub
|
||||
self.visibilityText = "Everyone"
|
||||
self.visibilityText = "compose.title.everyone"
|
||||
self.visibilityImage = "globe.europe.africa"
|
||||
} label: {
|
||||
Label("Everyone", systemImage: "globe.europe.africa")
|
||||
Label("compose.title.everyone", systemImage: "globe.europe.africa")
|
||||
}
|
||||
|
||||
Button {
|
||||
self.visibility = .unlisted
|
||||
self.visibilityText = "Unlisted"
|
||||
self.visibilityText = "compose.title.unlisted"
|
||||
self.visibilityImage = "lock.open"
|
||||
} label: {
|
||||
Label("Unlisted", systemImage: "lock.open")
|
||||
Label("compose.title.unlisted", systemImage: "lock.open")
|
||||
}
|
||||
|
||||
Button {
|
||||
self.visibility = .priv
|
||||
self.visibilityText = "Followers"
|
||||
self.visibilityText = "compose.title.followers"
|
||||
self.visibilityImage = "lock"
|
||||
} label: {
|
||||
Label("Followers", systemImage: "lock")
|
||||
Label("compose.title.followers", systemImage: "lock")
|
||||
}
|
||||
} label: {
|
||||
HStack {
|
||||
|
@ -452,8 +452,8 @@ struct ComposeView: View {
|
|||
.background(Color.keyboardToolbarColor)
|
||||
}
|
||||
|
||||
private func placeholder() -> String {
|
||||
self.statusViewModel == nil ? "Attach a photo and type what's on your mind" : "Type what's on your mind"
|
||||
private func placeholder() -> LocalizedStringKey {
|
||||
self.statusViewModel == nil ? "compose.title.attachPhotoFull" : "compose.title.attachPhotoMini"
|
||||
}
|
||||
|
||||
private func isPublishButtonDisabled() -> Bool {
|
||||
|
@ -528,7 +528,7 @@ struct ComposeView: View {
|
|||
self.photosAreUploading = false
|
||||
self.refreshScreenState()
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Cannot retreive image from library.", showToastr: true)
|
||||
ErrorService.shared.handle(error, message: "compose.error.loadingPhotosFailed", showToastr: true)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -567,7 +567,7 @@ struct ComposeView: View {
|
|||
}
|
||||
} catch {
|
||||
photoAttachment.error = error
|
||||
ErrorService.shared.handle(error, message: "Error during post photo.", showToastr: true)
|
||||
ErrorService.shared.handle(error, message: "compose.error.postingPhotoFailed", showToastr: true)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -599,7 +599,7 @@ struct ComposeView: View {
|
|||
do {
|
||||
let status = self.createStatus()
|
||||
if let newStatus = try await self.client.statuses?.new(status: status) {
|
||||
ToastrService.shared.showSuccess("Status published", imageSystemName: "message.fill")
|
||||
ToastrService.shared.showSuccess("compose.title.statusPublished", imageSystemName: "message.fill")
|
||||
|
||||
let statusModel = StatusModel(status: newStatus)
|
||||
let commentModel = CommentModel(status: statusModel, showDivider: false)
|
||||
|
@ -608,7 +608,7 @@ struct ComposeView: View {
|
|||
dismiss()
|
||||
}
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Error during post status.", showToastr: true)
|
||||
ErrorService.shared.handle(error, message: "compose.error.postingStatusFailed", showToastr: true)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ struct ImageUploadView: View {
|
|||
HapticService.shared.fireHaptic(of: .buttonPress)
|
||||
self.upload()
|
||||
} label: {
|
||||
Label("Try to upload", systemImage: "exclamationmark.arrow.triangle.2.circlepath")
|
||||
Label("compose.title.tryToUpload", systemImage: "exclamationmark.arrow.triangle.2.circlepath")
|
||||
}
|
||||
|
||||
Divider()
|
||||
|
@ -37,7 +37,7 @@ struct ImageUploadView: View {
|
|||
HapticService.shared.fireHaptic(of: .buttonPress)
|
||||
self.delete()
|
||||
} label: {
|
||||
Label("Delete", systemImage: "trash")
|
||||
Label("compose.title.delete", systemImage: "trash")
|
||||
.tint(.red)
|
||||
}
|
||||
} label: {
|
||||
|
@ -63,7 +63,7 @@ struct ImageUploadView: View {
|
|||
HapticService.shared.fireHaptic(of: .buttonPress)
|
||||
self.open()
|
||||
} label: {
|
||||
Label("Edit", systemImage: "pencil")
|
||||
Label("compose.title.edit", systemImage: "pencil")
|
||||
}
|
||||
|
||||
Divider()
|
||||
|
@ -72,7 +72,7 @@ struct ImageUploadView: View {
|
|||
HapticService.shared.fireHaptic(of: .buttonPress)
|
||||
self.delete()
|
||||
} label: {
|
||||
Label("Delete", systemImage: "trash")
|
||||
Label("compose.title.delete", systemImage: "trash")
|
||||
}
|
||||
} label: {
|
||||
self.imageView()
|
||||
|
|
|
@ -25,7 +25,7 @@ struct HashtagsView: View {
|
|||
|
||||
var body: some View {
|
||||
self.mainBody()
|
||||
.navigationTitle("Tags")
|
||||
.navigationTitle("trendingTags.navigationBar.title")
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
|
@ -38,7 +38,7 @@ struct HashtagsView: View {
|
|||
}
|
||||
case .loaded:
|
||||
if self.tags.isEmpty {
|
||||
NoDataView(imageSystemName: "person.3.sequence", text: "Unfortunately, there is no one here.")
|
||||
NoDataView(imageSystemName: "person.3.sequence", text: "trendingTags.title.noTags")
|
||||
} else {
|
||||
List {
|
||||
ForEach(self.tags, id: \.id) { tag in
|
||||
|
@ -49,7 +49,8 @@ struct HashtagsView: View {
|
|||
Text(tag.name).font(.headline)
|
||||
Spacer()
|
||||
if let total = tag.total {
|
||||
Text("\(total) posts").font(.caption)
|
||||
Text(String(format: NSLocalizedString("trendingTags.title.amountOfPosts", comment: "Amount of posts"), total))
|
||||
.font(.caption)
|
||||
}
|
||||
}
|
||||
.onTapGesture {
|
||||
|
@ -76,10 +77,10 @@ struct HashtagsView: View {
|
|||
self.state = .loaded
|
||||
} catch {
|
||||
if !Task.isCancelled {
|
||||
ErrorService.shared.handle(error, message: "Tags not retrieved.", showToastr: true)
|
||||
ErrorService.shared.handle(error, message: "trendingTags.error.loadingTagsFailed", showToastr: true)
|
||||
self.state = .error(error)
|
||||
} else {
|
||||
ErrorService.shared.handle(error, message: "Tags not retrieved.", showToastr: false)
|
||||
ErrorService.shared.handle(error, message: "trendingTags.error.loadingTagsFailed", showToastr: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ struct HomeFeedView: View {
|
|||
}
|
||||
case .loaded:
|
||||
if self.dbStatuses.isEmpty {
|
||||
NoDataView(imageSystemName: "photo.on.rectangle.angled", text: "Unfortunately, there are no photos here.")
|
||||
NoDataView(imageSystemName: "photo.on.rectangle.angled", text: "home.title.noPhotos")
|
||||
} else {
|
||||
self.timeline()
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ struct HomeFeedView: View {
|
|||
}
|
||||
}
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Error during download statuses from server.", showToastr: !Task.isCancelled)
|
||||
ErrorService.shared.handle(error, message: "global.error.errorDuringDownloadStatuses", showToastr: !Task.isCancelled)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ struct HomeFeedView: View {
|
|||
}
|
||||
}
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Error during download statuses from server.", showToastr: !Task.isCancelled)
|
||||
ErrorService.shared.handle(error, message: "global.error.errorDuringDownloadStatuses", showToastr: !Task.isCancelled)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,10 +125,10 @@ struct HomeFeedView: View {
|
|||
self.state = .loaded
|
||||
} catch {
|
||||
if !Task.isCancelled {
|
||||
ErrorService.shared.handle(error, message: "Statuses not retrieved.", showToastr: true)
|
||||
ErrorService.shared.handle(error, message: "global.error.statusesNotRetrieved", showToastr: true)
|
||||
self.state = .error(error)
|
||||
} else {
|
||||
ErrorService.shared.handle(error, message: "Statuses not retrieved.", showToastr: false)
|
||||
ErrorService.shared.handle(error, message: "global.error.statusesNotRetrieved", showToastr: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -167,7 +167,7 @@ struct HomeFeedView: View {
|
|||
.frame(width: 64, height: 64)
|
||||
.fontWeight(.ultraLight)
|
||||
.foregroundColor(.accentColor.opacity(0.6))
|
||||
Text("You're all caught up")
|
||||
Text("home.title.allCaughtUp", comment: "You're all caught up")
|
||||
.font(.title2)
|
||||
.fontWeight(.thin)
|
||||
.foregroundColor(Color.mainTextColor.opacity(0.6))
|
||||
|
|
|
@ -17,7 +17,7 @@ struct MainView: View {
|
|||
@EnvironmentObject var routerPath: RouterPath
|
||||
@EnvironmentObject var tipsStore: TipsStore
|
||||
|
||||
@State private var navBarTitle: String = "Home"
|
||||
@State private var navBarTitle: LocalizedStringKey = "mainview.tab.homeTimeline"
|
||||
@State private var viewMode: ViewMode = .home {
|
||||
didSet {
|
||||
self.navBarTitle = self.getViewTitle(viewMode: viewMode)
|
||||
|
@ -159,7 +159,7 @@ struct MainView: View {
|
|||
}
|
||||
} label: {
|
||||
HStack {
|
||||
Text("Trending")
|
||||
Text("mainview.tab.trending", comment: "Trending menu section")
|
||||
Image(systemName: "chart.line.uptrend.xyaxis")
|
||||
}
|
||||
}
|
||||
|
@ -185,7 +185,7 @@ struct MainView: View {
|
|||
}
|
||||
} label: {
|
||||
HStack {
|
||||
Text(navBarTitle)
|
||||
Text(navBarTitle, comment: "Navbar title")
|
||||
.font(.headline)
|
||||
Image(systemName: "chevron.down")
|
||||
.fontWeight(.semibold)
|
||||
|
@ -219,7 +219,7 @@ struct MainView: View {
|
|||
HapticService.shared.fireHaptic(of: .buttonPress)
|
||||
self.routerPath.presentedSheet = .settings
|
||||
} label: {
|
||||
Label("Settings", systemImage: "gear")
|
||||
Label("mainview.menu.settings", systemImage: "gear")
|
||||
}
|
||||
} label: {
|
||||
self.getAvatarImage(avatarUrl: self.applicationState.account?.avatar,
|
||||
|
@ -271,26 +271,26 @@ struct MainView: View {
|
|||
}
|
||||
}
|
||||
|
||||
private func getViewTitle(viewMode: ViewMode) -> String {
|
||||
private func getViewTitle(viewMode: ViewMode) -> LocalizedStringKey {
|
||||
switch viewMode {
|
||||
case .home:
|
||||
return "Home"
|
||||
return "mainview.tab.homeTimeline"
|
||||
case .trendingPhotos:
|
||||
return "Photos"
|
||||
return "mainview.tab.trendingPhotos"
|
||||
case .trendingTags:
|
||||
return "Tags"
|
||||
return "mainview.tab.trendingTags"
|
||||
case .trendingAccounts:
|
||||
return "Accounts"
|
||||
return "mainview.tab.trendingAccounts"
|
||||
case .local:
|
||||
return "Local"
|
||||
return "mainview.tab.localTimeline"
|
||||
case .federated:
|
||||
return "Federated"
|
||||
return "mainview.tab.federatedTimeline"
|
||||
case .profile:
|
||||
return "Profile"
|
||||
return "mainview.tab.userProfile"
|
||||
case .notifications:
|
||||
return "Notifications"
|
||||
return "mainview.tab.notifications"
|
||||
case .search:
|
||||
return "Search"
|
||||
return "mainview.tab.search"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -326,7 +326,7 @@ struct MainView: View {
|
|||
let authorizationSession = AuthorizationSession()
|
||||
await AuthorizationService.shared.verifyAccount(session: authorizationSession, currentAccount: account) { accountData in
|
||||
guard let accountData = accountData else {
|
||||
ToastrService.shared.showError(subtitle: "Cannot switch accounts.")
|
||||
ToastrService.shared.showError(subtitle: "mainview.error.switchAccounts")
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ struct NotificationsView: View {
|
|||
|
||||
var body: some View {
|
||||
self.mainBody()
|
||||
.navigationTitle("Notifications")
|
||||
.navigationTitle("notifications.navigationBar.title")
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
|
@ -36,7 +36,7 @@ struct NotificationsView: View {
|
|||
}
|
||||
case .loaded:
|
||||
if self.notifications.isEmpty {
|
||||
NoDataView(imageSystemName: "bell", text: "Unfortunately, there is nothing here.")
|
||||
NoDataView(imageSystemName: "bell", text: "notifications.title.noNotifications")
|
||||
} else {
|
||||
List {
|
||||
ForEach(notifications, id: \.id) { notification in
|
||||
|
@ -86,10 +86,10 @@ struct NotificationsView: View {
|
|||
}
|
||||
} catch {
|
||||
if !Task.isCancelled {
|
||||
ErrorService.shared.handle(error, message: "Notifications not retrieved.", showToastr: true)
|
||||
ErrorService.shared.handle(error, message: "notifications.error.loadingNotificationsFailed", showToastr: true)
|
||||
self.state = .error(error)
|
||||
} else {
|
||||
ErrorService.shared.handle(error, message: "Notifications not retrieved.", showToastr: false)
|
||||
ErrorService.shared.handle(error, message: "notifications.error.loadingNotificationsFailed", showToastr: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ struct NotificationsView: View {
|
|||
self.notifications.append(contentsOf: linkable.data)
|
||||
}
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Error during download notifications from server.", showToastr: !Task.isCancelled)
|
||||
ErrorService.shared.handle(error, message: "notifications.error.loadingNotificationsFailed", showToastr: !Task.isCancelled)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,7 +122,7 @@ struct NotificationsView: View {
|
|||
self.notifications.insert(contentsOf: linkable.data, at: 0)
|
||||
}
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Error during download notifications from server.", showToastr: !Task.isCancelled)
|
||||
ErrorService.shared.handle(error, message: "notifications.error.loadingNotificationsFailed", showToastr: !Task.isCancelled)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ struct NotificationRowView: View {
|
|||
.font(.footnote)
|
||||
}
|
||||
|
||||
Text(self.getTitle())
|
||||
Text(self.getTitle(), comment: "Notification type")
|
||||
.foregroundColor(.lightGrayColor)
|
||||
.font(.footnote)
|
||||
.fontWeight(.light)
|
||||
|
@ -154,28 +154,28 @@ struct NotificationRowView: View {
|
|||
}
|
||||
}
|
||||
|
||||
private func getTitle() -> String {
|
||||
private func getTitle() -> LocalizedStringKey {
|
||||
switch notification.type {
|
||||
case .follow:
|
||||
return "followed you"
|
||||
return "notifications.title.followedYou"
|
||||
case .mention:
|
||||
return "mentioned you"
|
||||
return "notifications.title.mentionedYou"
|
||||
case .reblog:
|
||||
return "boosted"
|
||||
return "notifications.title.boosted"
|
||||
case .favourite:
|
||||
return "favourited"
|
||||
return "notifications.title.favourited"
|
||||
case .status:
|
||||
return "posted status"
|
||||
return "notifications.title.postedStatus"
|
||||
case .followRequest:
|
||||
return "follow request"
|
||||
return "notifications.title.followRequest"
|
||||
case .poll:
|
||||
return "poll"
|
||||
return "notifications.title.poll"
|
||||
case .update:
|
||||
return "updated post"
|
||||
return "notifications.title.updatedStatus"
|
||||
case .adminSignUp:
|
||||
return "signed up"
|
||||
return "notifications.title.signedUp"
|
||||
case .adminReport:
|
||||
return "new report"
|
||||
return "notifications.title.newReport"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ struct PaginableStatusesView: View {
|
|||
}
|
||||
case .loaded:
|
||||
if self.statusViewModels.isEmpty {
|
||||
NoDataView(imageSystemName: "photo.on.rectangle.angled", text: "Unfortunately, there are no photos here.")
|
||||
NoDataView(imageSystemName: "photo.on.rectangle.angled", text: "statuses.title.noPhotos")
|
||||
} else {
|
||||
ScrollView {
|
||||
LazyVStack(alignment: .center) {
|
||||
|
@ -66,7 +66,7 @@ struct PaginableStatusesView: View {
|
|||
do {
|
||||
try await self.loadMoreStatuses()
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Loading more statuses failed.", showToastr: !Task.isCancelled)
|
||||
ErrorService.shared.handle(error, message: "statuses.error.loadingStatusesFailed", showToastr: !Task.isCancelled)
|
||||
}
|
||||
}
|
||||
Spacer()
|
||||
|
@ -92,7 +92,7 @@ struct PaginableStatusesView: View {
|
|||
try await self.loadStatuses()
|
||||
self.state = .loaded
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Loading statuses failed.", showToastr: !Task.isCancelled)
|
||||
ErrorService.shared.handle(error, message: "statuses.error.loadingStatusesFailed", showToastr: !Task.isCancelled)
|
||||
self.state = .error(error)
|
||||
}
|
||||
}
|
||||
|
@ -144,12 +144,12 @@ struct PaginableStatusesView: View {
|
|||
}
|
||||
}
|
||||
|
||||
private func getTitle() -> String {
|
||||
private func getTitle() -> LocalizedStringKey {
|
||||
switch self.listType {
|
||||
case .favourites:
|
||||
return "Favourites"
|
||||
return "statuses.navigationBar.favourites"
|
||||
case .bookmarks:
|
||||
return "Bookmarks"
|
||||
return "statuses.navigationBar.bookmarks"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ struct PhotoEditorView: View {
|
|||
VStack(alignment: .leading) {
|
||||
if let data = photoAttachment.photoData, let uiImage = UIImage(data: data) {
|
||||
List {
|
||||
Section(header: Text("Photo")) {
|
||||
Section(header: Text("photoEdit.title.photo")) {
|
||||
HStack {
|
||||
Spacer()
|
||||
Image(uiImage: uiImage)
|
||||
|
@ -30,8 +30,8 @@ struct PhotoEditorView: View {
|
|||
}
|
||||
}
|
||||
|
||||
Section(header: Text("Accessibility")) {
|
||||
TextField("Description for the visually impaired", text: $description, axis: .vertical)
|
||||
Section(header: Text("photoEdit.title.accessibility")) {
|
||||
TextField("photoEdit.title.accessibilityDescription", text: $description, axis: .vertical)
|
||||
.keyboardType(.default)
|
||||
.lineLimit(3...6)
|
||||
.multilineTextAlignment(.leading)
|
||||
|
@ -47,7 +47,7 @@ struct PhotoEditorView: View {
|
|||
.onAppear {
|
||||
self.description = self.photoAttachment.uploadedAttachment?.description ?? String.empty()
|
||||
}
|
||||
.navigationTitle("Photo details")
|
||||
.navigationTitle("photoEdit.navigationBar.title")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.toolbar {
|
||||
self.getTrailingToolbar()
|
||||
|
@ -61,12 +61,12 @@ struct PhotoEditorView: View {
|
|||
ActionButton(showLoader: false) {
|
||||
await self.update()
|
||||
} label: {
|
||||
Text("Save")
|
||||
Text("photoEdit.title.save", comment: "Save")
|
||||
}.buttonStyle(.borderedProminent)
|
||||
}
|
||||
|
||||
ToolbarItem(placement: .cancellationAction) {
|
||||
Button("Cancel", role: .cancel) {
|
||||
Button(NSLocalizedString("photoEdit.title.cancel", comment: "Cancel"), role: .cancel) {
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ struct PhotoEditorView: View {
|
|||
self.photoAttachment.uploadedAttachment = updated
|
||||
self.dismiss()
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Cannot update attachment.", showToastr: true)
|
||||
ErrorService.shared.handle(error, message: "photoEdit.error.updatePhotoFailed", showToastr: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ struct PlaceSelectorView: View {
|
|||
List {
|
||||
Section {
|
||||
HStack {
|
||||
TextField("Search...", text: $query)
|
||||
TextField("placeSelector.title.search", text: $query)
|
||||
.padding(8)
|
||||
.focused($focusedField, equals: .search)
|
||||
.keyboardType(.default)
|
||||
|
@ -43,7 +43,7 @@ struct PlaceSelectorView: View {
|
|||
await self.searchPlaces()
|
||||
}
|
||||
} label: {
|
||||
Text("Search")
|
||||
Text("placeSelector.title.buttonSearch", comment: "Search")
|
||||
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
|
@ -86,7 +86,7 @@ struct PlaceSelectorView: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle("Places")
|
||||
.navigationTitle("placeSelector.navigationBar.title")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.toolbar {
|
||||
self.getTrailingToolbar()
|
||||
|
@ -97,7 +97,7 @@ struct PlaceSelectorView: View {
|
|||
@ToolbarContentBuilder
|
||||
private func getTrailingToolbar() -> some ToolbarContent {
|
||||
ToolbarItem(placement: .cancellationAction) {
|
||||
Button("Cancel", role: .cancel) {
|
||||
Button(NSLocalizedString("placeSelector.title.cancel", comment: "Cancel"), role: .cancel) {
|
||||
self.dismiss()
|
||||
}
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ struct PlaceSelectorView: View {
|
|||
self.places = placesFromApi
|
||||
}
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Cannot download places.", showToastr: true)
|
||||
ErrorService.shared.handle(error, message: "placeSelector.error.loadingPlacesFailed", showToastr: true)
|
||||
}
|
||||
|
||||
self.showLoader = false
|
||||
|
|
|
@ -20,7 +20,7 @@ struct SearchView: View {
|
|||
var body: some View {
|
||||
List {
|
||||
Section {
|
||||
TextField("Search...", text: $query)
|
||||
TextField("search.title.placeholder", text: $query)
|
||||
.padding(8)
|
||||
.focused($focusedField, equals: .search)
|
||||
.keyboardType(.default)
|
||||
|
@ -36,25 +36,29 @@ struct SearchView: View {
|
|||
if self.query.isEmpty == false {
|
||||
Section {
|
||||
NavigationLink(value: RouteurDestinations.accountsPhoto(listType: .search(query: self.query))) {
|
||||
Label("Users with \"\(self.query)\"", systemImage: "person.3.sequence")
|
||||
Label(String(format: NSLocalizedString("search.title.usersWith", comment: "Users with "), self.query),
|
||||
systemImage: "person.3.sequence")
|
||||
}
|
||||
|
||||
NavigationLink(value: RouteurDestinations.userProfile(accountId: "", accountDisplayName: "", accountUserName: self.query)) {
|
||||
Label("Go to user \"@\(self.query)\"", systemImage: "person.crop.circle")
|
||||
Label(String(format: NSLocalizedString("search.title.goToUser", comment: "Go to user "), "\"@\(self.query)\""),
|
||||
systemImage: "person.crop.circle")
|
||||
}
|
||||
}
|
||||
|
||||
Section {
|
||||
NavigationLink(value: RouteurDestinations.hashtags(listType: .search(query: self.query))) {
|
||||
Label("Hashtags with \"\(self.query)\"", systemImage: "tag")
|
||||
Label(String(format: NSLocalizedString("search.title.hashtagWith", comment: "Hashtags with "), self.query),
|
||||
systemImage: "tag")
|
||||
}
|
||||
|
||||
NavigationLink(value: RouteurDestinations.statuses(listType: .hashtag(tag: self.query))) {
|
||||
Label("Go to hashtag \"#\(self.query)\"", systemImage: "tag.circle")
|
||||
Label(String(format: NSLocalizedString("search.title.goToHashtag", comment: "Go to hashtag "), "\"#\(self.query)\""),
|
||||
systemImage: "tag.circle")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle("Search")
|
||||
.navigationTitle("search.navigationBar.title")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ struct SettingsView: View {
|
|||
.frame(alignment: .topLeading)
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .cancellationAction) {
|
||||
Button("Close", role: .cancel) {
|
||||
Button(NSLocalizedString("settings.title.close", comment: "Close"), role: .cancel) {
|
||||
self.dismiss()
|
||||
}
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ struct SettingsView: View {
|
|||
.onReceive(NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification), perform: { _ in
|
||||
self.theme = applicationState.theme.colorScheme() ?? self.getSystemColorScheme()
|
||||
})
|
||||
.navigationTitle("Settings")
|
||||
.navigationTitle("settings.navigationBar.title")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.preferredColorScheme(self.theme)
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ struct SettingsView: View {
|
|||
private func version() -> some View {
|
||||
Section() {
|
||||
HStack {
|
||||
Text("Version")
|
||||
Text("settings.title.version", comment: "Version")
|
||||
Spacer()
|
||||
Text("\(appVersion ?? String.empty()) (\(appBundleVersion ?? String.empty()))")
|
||||
.foregroundColor(.accentColor)
|
||||
|
|
|
@ -13,7 +13,7 @@ struct AccentsSectionView: View {
|
|||
private let accentColors2: [TintColor] = [.accentColor6, .accentColor7, .accentColor8, .accentColor9, .accentColor10]
|
||||
|
||||
var body: some View {
|
||||
Section("Accent") {
|
||||
Section("settings.title.accent") {
|
||||
VStack(alignment: .leading) {
|
||||
HStack(alignment: .center) {
|
||||
ForEach(accentColors1, id: \.self) { color in
|
||||
|
|
|
@ -14,7 +14,7 @@ struct AccountsSectionView: View {
|
|||
@State private var dbAccounts: [AccountData] = []
|
||||
|
||||
var body: some View {
|
||||
Section("Accounts") {
|
||||
Section("settings.title.accounts") {
|
||||
ForEach(self.accounts) { account in
|
||||
HStack(alignment: .center) {
|
||||
UsernameRow(accountId: account.id,
|
||||
|
@ -33,7 +33,7 @@ struct AccountsSectionView: View {
|
|||
|
||||
NavigationLink(value: RouteurDestinations.signIn) {
|
||||
HStack {
|
||||
Text("New account")
|
||||
Text("settings.title.newAccount", comment: "New account")
|
||||
Spacer()
|
||||
Image(systemName: "person.crop.circle.badge.plus")
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ struct AvatarShapesSectionView: View {
|
|||
@EnvironmentObject var applicationState: ApplicationState
|
||||
|
||||
var body: some View {
|
||||
Section("Avatar") {
|
||||
Section("settings.title.avatar") {
|
||||
Button {
|
||||
self.applicationState.avatarShape = .circle
|
||||
ApplicationSettingsHandler.shared.setDefaultAvatarShape(avatarShape: .circle)
|
||||
|
@ -22,7 +22,7 @@ struct AvatarShapesSectionView: View {
|
|||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: 32, height: 32)
|
||||
|
||||
Text("Circle")
|
||||
Text("settings.title.circle", comment: "Circle")
|
||||
.foregroundColor(.label)
|
||||
Spacer()
|
||||
|
||||
|
@ -44,7 +44,7 @@ struct AvatarShapesSectionView: View {
|
|||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: 32, height: 32)
|
||||
|
||||
Text("Rounded rectangle")
|
||||
Text("settings.title.rounderRectangle", comment: "Rounded rectangle")
|
||||
.foregroundColor(.label)
|
||||
Spacer()
|
||||
|
||||
|
|
|
@ -17,27 +17,27 @@ struct HapticsSectionView: View {
|
|||
@State var hapticNotificationEnabled = true
|
||||
|
||||
var body: some View {
|
||||
Section("Haptics") {
|
||||
Section("settings.title.haptics") {
|
||||
|
||||
Toggle("Tab selection", isOn: $hapticTabSelectionEnabled)
|
||||
Toggle("settings.title.hapticsTabSelection", isOn: $hapticTabSelectionEnabled)
|
||||
.onChange(of: hapticTabSelectionEnabled) { newValue in
|
||||
self.applicationState.hapticTabSelectionEnabled = newValue
|
||||
ApplicationSettingsHandler.shared.setHapticTabSelectionEnabled(value: newValue)
|
||||
}
|
||||
|
||||
Toggle("Button press", isOn: $hapticButtonPressEnabled)
|
||||
Toggle("settings.title.hapticsButtonPress", isOn: $hapticButtonPressEnabled)
|
||||
.onChange(of: hapticButtonPressEnabled) { newValue in
|
||||
self.applicationState.hapticButtonPressEnabled = newValue
|
||||
ApplicationSettingsHandler.shared.setHapticButtonPressEnabled(value: newValue)
|
||||
}
|
||||
|
||||
Toggle("List refresh", isOn: $hapticRefreshEnabled)
|
||||
Toggle("settings.title.hapticsListRefresh", isOn: $hapticRefreshEnabled)
|
||||
.onChange(of: hapticRefreshEnabled) { newValue in
|
||||
self.applicationState.hapticRefreshEnabled = newValue
|
||||
ApplicationSettingsHandler.shared.setHapticRefreshEnabled(value: newValue)
|
||||
}
|
||||
|
||||
Toggle("Animation finished", isOn: $hapticAnimationEnabled)
|
||||
Toggle("settings.title.hapticsAnimationFinished", isOn: $hapticAnimationEnabled)
|
||||
.onChange(of: hapticAnimationEnabled) { newValue in
|
||||
self.applicationState.hapticAnimationEnabled = newValue
|
||||
ApplicationSettingsHandler.shared.setHapticAnimationEnabled(value: newValue)
|
||||
|
|
|
@ -14,12 +14,12 @@ struct MediaSettingsView: View {
|
|||
@State var showPhotoDescription = true
|
||||
|
||||
var body: some View {
|
||||
Section("Media settings") {
|
||||
Section("settings.title.mediaSettings") {
|
||||
|
||||
Toggle(isOn: $showSensitive) {
|
||||
VStack(alignment: .leading) {
|
||||
Text("Always show NSFW")
|
||||
Text("Force show all NFSW (sensitive) media without warnings")
|
||||
Text("settings.title.alwaysShowSensitiveTitle", comment: "Always show NSFW")
|
||||
Text("settings.title.alwaysShowSensitiveDescription", comment: "Force show all NFSW (sensitive) media without warnings")
|
||||
.font(.footnote)
|
||||
.foregroundColor(.lightGrayColor)
|
||||
}
|
||||
|
@ -31,8 +31,8 @@ struct MediaSettingsView: View {
|
|||
|
||||
Toggle(isOn: $showPhotoDescription) {
|
||||
VStack(alignment: .leading) {
|
||||
Text("Show alternative text")
|
||||
Text("Show alternative text if present on status details screen")
|
||||
Text("settings.title.alwaysShowAltTitle", comment: "Show alternative text")
|
||||
Text("settings.title.alwaysShowAltDescription", comment: "Show alternative text if present on status details screen")
|
||||
.font(.footnote)
|
||||
.foregroundColor(.lightGrayColor)
|
||||
}
|
||||
|
|
|
@ -8,20 +8,20 @@ import SwiftUI
|
|||
|
||||
struct OtherSectionView: View {
|
||||
var body: some View {
|
||||
Section("Other") {
|
||||
Section("settings.title.other") {
|
||||
NavigationLink(value: RouteurDestinations.thirdParty) {
|
||||
Text("Third party")
|
||||
Text("settings.title.thirdParty", comment: "Third party")
|
||||
}
|
||||
|
||||
HStack {
|
||||
Text("Report a bug")
|
||||
Text("settings.title.reportBug", comment: "Report a bug")
|
||||
Spacer()
|
||||
Link("Issues on Github", destination: URL(string: "https://github.com/VernissageApp/Home/issues")!)
|
||||
Link(NSLocalizedString("settings.title.githubIssues", comment: "Issues on GitHub"), destination: URL(string: "https://github.com/VernissageApp/Home/issues")!)
|
||||
.font(.footnote)
|
||||
}
|
||||
|
||||
HStack {
|
||||
Text("Follow me on Mastodon")
|
||||
Text("settings.title.follow", comment: "Follow me on Mastodon")
|
||||
Spacer()
|
||||
Link("@mczachurski", destination: URL(string: "https://mastodon.social/@mczachurski")!)
|
||||
.font(.footnote)
|
||||
|
|
|
@ -11,7 +11,7 @@ struct SupportView: View {
|
|||
@EnvironmentObject var tipsStore: TipsStore
|
||||
|
||||
var body: some View {
|
||||
Section("Support") {
|
||||
Section("settings.title.support") {
|
||||
ForEach(tipsStore.items) { product in
|
||||
HStack(alignment: .center) {
|
||||
Text(self.getIcon(for: product))
|
||||
|
|
|
@ -14,17 +14,17 @@ struct ThanksView: View {
|
|||
Spacer()
|
||||
VStack {
|
||||
Group {
|
||||
Text("Thank you 💕")
|
||||
Text("settings.title.thankYouTitle", comment: "Thank you 💕")
|
||||
.font(.title3)
|
||||
.fontWeight(.bold)
|
||||
.foregroundColor(.viewTextColor)
|
||||
.padding(.top, 8)
|
||||
Text("Thanks for your purchase. Purchases both big and small help us keep our dream of providing the best quality products to our customers. We hope you’re loving Vernissage.")
|
||||
Text("settings.title.thankYouMessage", comment: "Thank you message")
|
||||
.font(.footnote)
|
||||
.multilineTextAlignment(.center)
|
||||
.foregroundColor(.viewTextColor)
|
||||
|
||||
Button("Close") {
|
||||
Button(NSLocalizedString("settings.title.thankYouClose", comment: "Close")) {
|
||||
HapticService.shared.fireHaptic(of: .buttonPress)
|
||||
|
||||
withAnimation(.spring()) {
|
||||
|
|
|
@ -11,13 +11,13 @@ struct ThemeSectionView: View {
|
|||
@Environment(\.colorScheme) var colorScheme
|
||||
|
||||
var body: some View {
|
||||
Section("Theme") {
|
||||
Section("settings.title.theme") {
|
||||
Button {
|
||||
self.applicationState.theme = .system
|
||||
ApplicationSettingsHandler.shared.setDefaultTheme(theme: .system)
|
||||
} label: {
|
||||
HStack {
|
||||
Text("System")
|
||||
Text("settings.title.system", comment: "System")
|
||||
.foregroundColor(.label)
|
||||
Spacer()
|
||||
if self.applicationState.theme == .system {
|
||||
|
@ -31,7 +31,7 @@ struct ThemeSectionView: View {
|
|||
ApplicationSettingsHandler.shared.setDefaultTheme(theme: .light)
|
||||
} label: {
|
||||
HStack {
|
||||
Text("Light")
|
||||
Text("settings.title.light", comment: "Light")
|
||||
.foregroundColor(.label)
|
||||
Spacer()
|
||||
if self.applicationState.theme == .light {
|
||||
|
@ -45,7 +45,7 @@ struct ThemeSectionView: View {
|
|||
ApplicationSettingsHandler.shared.setDefaultTheme(theme: .dark)
|
||||
} label: {
|
||||
HStack {
|
||||
Text("Dark")
|
||||
Text("settings.title.dark", comment: "Dark")
|
||||
.foregroundColor(.label)
|
||||
Spacer()
|
||||
if self.applicationState.theme == .dark {
|
||||
|
|
|
@ -26,7 +26,7 @@ struct SignInView: View {
|
|||
Section {
|
||||
VStack(alignment: .center) {
|
||||
HStack(alignment: .center, spacing: 4) {
|
||||
TextField("Server address", text: $serverAddress)
|
||||
TextField("signin.title.serverAddress", text: $serverAddress)
|
||||
.onSubmit {
|
||||
let baseAddress = self.getServerAddress(uri: self.serverAddress)
|
||||
self.signIn(baseAddress: baseAddress)
|
||||
|
@ -36,7 +36,7 @@ struct SignInView: View {
|
|||
.disableAutocorrection(true)
|
||||
.clearButton(text: $serverAddress)
|
||||
|
||||
Button("Sign in") {
|
||||
Button(NSLocalizedString("signin.title.signIn", comment: "Sign in")) {
|
||||
HapticService.shared.fireHaptic(of: .buttonPress)
|
||||
|
||||
let baseAddress = self.getServerAddress(uri: self.serverAddress)
|
||||
|
@ -49,19 +49,19 @@ struct SignInView: View {
|
|||
.buttonStyle(PlainButtonStyle())
|
||||
|
||||
} header: {
|
||||
Text("Enter server address")
|
||||
Text("signin.title.enterServerAddress", comment: "Enter server address")
|
||||
} footer: {
|
||||
if let instructionsUrlString = self.instructionsUrlString,
|
||||
let instructionsUrl = URL(string: instructionsUrlString) {
|
||||
HStack {
|
||||
Spacer()
|
||||
Link("How to join Pixelfed", destination: instructionsUrl)
|
||||
Link(NSLocalizedString("signin.title.howToJoinLink", comment: "How to join Pixelfed"), destination: instructionsUrl)
|
||||
.font(.caption)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Section("Or choose Pixelfed server") {
|
||||
Section("signin.title.chooseServer") {
|
||||
if self.instances.isEmpty {
|
||||
HStack {
|
||||
Spacer()
|
||||
|
@ -83,7 +83,7 @@ struct SignInView: View {
|
|||
self.instances = await self.client.instances.instances(instanceUrls: metadata.instances)
|
||||
self.instructionsUrlString = metadata.instructionsUrl
|
||||
}
|
||||
.navigationTitle("Sign in to Pixelfed")
|
||||
.navigationTitle("signin.navigationBar.title")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,7 @@ struct SignInView: View {
|
|||
ErrorService.shared.handle(error, message: error.localizedDescription, showToastr: true)
|
||||
}
|
||||
catch {
|
||||
ErrorService.shared.handle(error, message: "Communication with server failed.", showToastr: true)
|
||||
ErrorService.shared.handle(error, message: "signin.error.communicationFailed", showToastr: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ struct InstanceRowView: View {
|
|||
|
||||
Spacer()
|
||||
|
||||
Button("Sign in") {
|
||||
Button(NSLocalizedString("signin.title.signIn", comment: "Sign in")) {
|
||||
HapticService.shared.fireHaptic(of: .buttonPress)
|
||||
self.action(instance.uri)
|
||||
}
|
||||
|
@ -66,10 +66,10 @@ struct InstanceRowView: View {
|
|||
if let stats = instance.stats {
|
||||
HStack {
|
||||
Image(systemName: "person.2.fill")
|
||||
Text("\(stats.userCount) users")
|
||||
Text(String(format: NSLocalizedString("signin.title.amountOfUsers", comment: "users"), stats.userCount))
|
||||
|
||||
Image(systemName: "photo.stack.fill")
|
||||
Text("\(stats.statusCount) posts")
|
||||
Text(String(format: NSLocalizedString("signin.title.amountOStatuses", comment: "statuses"), stats.statusCount))
|
||||
|
||||
Spacer()
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ struct StatusView: View {
|
|||
|
||||
var body: some View {
|
||||
self.mainBody()
|
||||
.navigationTitle("Details")
|
||||
.navigationTitle("status.navigationBar.title")
|
||||
.fullScreenCover(item: $tappedAttachmentModel, content: { attachmentModel in
|
||||
ImageViewer(attachmentModel: attachmentModel)
|
||||
})
|
||||
|
@ -102,11 +102,11 @@ struct StatusView: View {
|
|||
.foregroundColor(.lightGrayColor)
|
||||
|
||||
HStack {
|
||||
Text("Uploaded")
|
||||
Text("status.title.uploaded", comment: "Uploaded")
|
||||
Text(statusViewModel.createdAt.toRelative(.isoDateTimeMilliSec))
|
||||
.padding(.horizontal, -4)
|
||||
if let applicationName = statusViewModel.application?.name {
|
||||
Text("via \(applicationName)")
|
||||
Text(String(format: NSLocalizedString("status.title.via", comment: "via"), applicationName))
|
||||
}
|
||||
}
|
||||
.foregroundColor(.lightGrayColor)
|
||||
|
@ -179,16 +179,16 @@ struct StatusView: View {
|
|||
} catch NetworkError.notSuccessResponse(let response) {
|
||||
if response.statusCode() == HTTPStatusCode.notFound, let accountId = self.applicationState.account?.id {
|
||||
StatusDataHandler.shared.remove(accountId: accountId, statusId: self.statusId)
|
||||
ErrorService.shared.handle(NetworkError.notSuccessResponse(response), message: "Status not existing anymore.", showToastr: true)
|
||||
ErrorService.shared.handle(NetworkError.notSuccessResponse(response), message: "status.error.notFound", showToastr: true)
|
||||
self.dismiss()
|
||||
}
|
||||
}
|
||||
catch {
|
||||
if !Task.isCancelled {
|
||||
ErrorService.shared.handle(error, message: "Status not retreived.", showToastr: true)
|
||||
ErrorService.shared.handle(error, message: "status.error.loadingStatusFailed", showToastr: true)
|
||||
self.state = .loaded
|
||||
} else {
|
||||
ErrorService.shared.handle(error, message: "Status not retreived.", showToastr: false)
|
||||
ErrorService.shared.handle(error, message: "status.error.loadingStatusFailed", showToastr: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ struct CommentsSectionView: View {
|
|||
do {
|
||||
self.commentViewModels = try await self.client.statuses?.comments(to: statusId) ?? []
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Comments cannot be downloaded.", showToastr: !Task.isCancelled)
|
||||
ErrorService.shared.handle(error, message: "status.error.loadingCommentsFailed", showToastr: !Task.isCancelled)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ struct StatusesView: View {
|
|||
}
|
||||
case .loaded:
|
||||
if self.statusViewModels.isEmpty {
|
||||
NoDataView(imageSystemName: "photo.on.rectangle.angled", text: "Unfortunately, there are no photos here.")
|
||||
NoDataView(imageSystemName: "photo.on.rectangle.angled", text: "statuses.title.noPhotos")
|
||||
} else {
|
||||
ScrollView {
|
||||
LazyVStack(alignment: .center) {
|
||||
|
@ -75,7 +75,7 @@ struct StatusesView: View {
|
|||
do {
|
||||
try await self.loadMoreStatuses()
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Loading more statuses failed.", showToastr: !Task.isCancelled)
|
||||
ErrorService.shared.handle(error, message: "statuses.error.loadingStatusesFailed", showToastr: !Task.isCancelled)
|
||||
}
|
||||
}
|
||||
Spacer()
|
||||
|
@ -89,7 +89,7 @@ struct StatusesView: View {
|
|||
try await self.loadTopStatuses()
|
||||
HapticService.shared.fireHaptic(of: .dataRefresh(intensity: 0.7))
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Loading statuses failed.", showToastr: !Task.isCancelled)
|
||||
ErrorService.shared.handle(error, message: "statuses.error.loadingStatusesFailed", showToastr: !Task.isCancelled)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ struct StatusesView: View {
|
|||
|
||||
self.state = .loaded
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Loading statuses failed.", showToastr: !Task.isCancelled)
|
||||
ErrorService.shared.handle(error, message: "statuses.error.loadingStatusesFailed", showToastr: !Task.isCancelled)
|
||||
self.state = .error(error)
|
||||
}
|
||||
}
|
||||
|
@ -197,7 +197,7 @@ struct StatusesView: View {
|
|||
case .hashtag(let tag):
|
||||
let hashtagsFromApi = try await self.client.search?.search(query: tag, resultsType: .hashtags)
|
||||
guard let hashtagsFromApi = hashtagsFromApi, hashtagsFromApi.hashtags.isEmpty == false else {
|
||||
ToastrService.shared.showError(title: "Hashtag not exists", imageSystemName: "exclamationmark.octagon")
|
||||
ToastrService.shared.showError(title: "global.error.hashtagNotExists", imageSystemName: "exclamationmark.octagon")
|
||||
dismiss()
|
||||
|
||||
return []
|
||||
|
@ -214,16 +214,16 @@ struct StatusesView: View {
|
|||
}
|
||||
}
|
||||
|
||||
private func getTitle() -> String {
|
||||
private func getTitle() -> LocalizedStringKey {
|
||||
switch self.listType {
|
||||
case .local:
|
||||
return "Local"
|
||||
return "statuses.navigationBar.localTimeline"
|
||||
case .federated:
|
||||
return "Federated"
|
||||
return "statuses.navigationBar.federatedTimeline"
|
||||
case .favourites:
|
||||
return "Favourites"
|
||||
return "statuses.navigationBar.favourites"
|
||||
case .bookmarks:
|
||||
return "Bookmarks"
|
||||
return "statuses.navigationBar.bookmarks"
|
||||
case .hashtag(let tag):
|
||||
return "#\(tag)"
|
||||
}
|
||||
|
@ -253,25 +253,25 @@ struct StatusesView: View {
|
|||
do {
|
||||
self.tag = try await self.client.tags?.get(tag: hashtag)
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Error during loading tag from server.", showToastr: false)
|
||||
ErrorService.shared.handle(error, message: "global.error.errorDuringDownloadHashtag", showToastr: false)
|
||||
}
|
||||
}
|
||||
|
||||
private func follow(hashtag: String) async {
|
||||
do {
|
||||
self.tag = try await self.client.tags?.follow(tag: hashtag)
|
||||
ToastrService.shared.showSuccess("You are following the tag.", imageSystemName: "number.square.fill")
|
||||
ToastrService.shared.showSuccess("statuses.title.tagFollowed", imageSystemName: "number.square.fill")
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Follow tag failed.", showToastr: true)
|
||||
ErrorService.shared.handle(error, message: "statuses.error.tagFollowFailed", showToastr: true)
|
||||
}
|
||||
}
|
||||
|
||||
private func unfollow(hashtag: String) async {
|
||||
do {
|
||||
self.tag = try await self.client.tags?.unfollow(tag: hashtag)
|
||||
ToastrService.shared.showSuccess("Tag has been unfollowed.", imageSystemName: "number.square")
|
||||
ToastrService.shared.showSuccess("statuses.title.tagUnfollowed", imageSystemName: "number.square")
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Unfollow tag failed.", showToastr: true)
|
||||
ErrorService.shared.handle(error, message: "statuses.error.tagUnfollowFailed", showToastr: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ struct ThirdPartyView: View {
|
|||
.font(.footnote)
|
||||
}
|
||||
}
|
||||
.navigationTitle("Third party")
|
||||
.navigationTitle("thirdParty.navigationBar.title")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,9 +20,9 @@ struct TrendStatusesView: View {
|
|||
var body: some View {
|
||||
ScrollView {
|
||||
Picker(selection: $tabSelectedValue, label: Text("")) {
|
||||
Text("Daily").tag(Pixelfed.Trends.TrendRange.daily)
|
||||
Text("Monthly").tag(Pixelfed.Trends.TrendRange.monthly)
|
||||
Text("Yearly").tag(Pixelfed.Trends.TrendRange.yearly)
|
||||
Text("trendingStatuses.title.daily", comment: "Daily").tag(Pixelfed.Trends.TrendRange.daily)
|
||||
Text("trendingStatuses.title.monthly", comment: "Monthly").tag(Pixelfed.Trends.TrendRange.monthly)
|
||||
Text("trendingStatuses.title.yearly", comment: "Yearly").tag(Pixelfed.Trends.TrendRange.yearly)
|
||||
|
||||
}
|
||||
.padding()
|
||||
|
@ -34,14 +34,14 @@ struct TrendStatusesView: View {
|
|||
self.statusViewModels = []
|
||||
try await self.loadStatuses()
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Loading statuses failed.", showToastr: !Task.isCancelled)
|
||||
ErrorService.shared.handle(error, message: "trendingStatuses.error.loadingStatusesFailed", showToastr: !Task.isCancelled)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.mainBody()
|
||||
}
|
||||
.navigationTitle("Trends")
|
||||
.navigationTitle("trendingStatuses.navigationBar.title")
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
|
@ -55,16 +55,16 @@ struct TrendStatusesView: View {
|
|||
self.state = .loaded
|
||||
} catch {
|
||||
if !Task.isCancelled {
|
||||
ErrorService.shared.handle(error, message: "Loading statuses failed.", showToastr: true)
|
||||
ErrorService.shared.handle(error, message: "trendingStatuses.error.loadingStatusesFailed", showToastr: true)
|
||||
self.state = .error(error)
|
||||
} else {
|
||||
ErrorService.shared.handle(error, message: "Loading statuses failed.", showToastr: false)
|
||||
ErrorService.shared.handle(error, message: "trendingStatuses.error.loadingStatusesFailed", showToastr: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
case .loaded:
|
||||
if self.statusViewModels.isEmpty {
|
||||
NoDataView(imageSystemName: "photo.on.rectangle.angled", text: "Unfortunately, there are no photos here.")
|
||||
NoDataView(imageSystemName: "photo.on.rectangle.angled", text: "trendingStatuses.title.noPhotos")
|
||||
} else {
|
||||
LazyVStack(alignment: .center) {
|
||||
ForEach(self.statusViewModels, id: \.id) { item in
|
||||
|
@ -86,7 +86,7 @@ struct TrendStatusesView: View {
|
|||
try await self.loadStatuses()
|
||||
HapticService.shared.fireHaptic(of: .dataRefresh(intensity: 0.7))
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Loading statuses failed.", showToastr: !Task.isCancelled)
|
||||
ErrorService.shared.handle(error, message: "trendingStatuses.error.loadingStatusesFailed", showToastr: !Task.isCancelled)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -99,10 +99,10 @@ struct TrendStatusesView: View {
|
|||
self.state = .loaded
|
||||
} catch {
|
||||
if !Task.isCancelled {
|
||||
ErrorService.shared.handle(error, message: "Loading statuses failed.", showToastr: true)
|
||||
ErrorService.shared.handle(error, message: "trendingStatuses.error.loadingStatusesFailed", showToastr: true)
|
||||
self.state = .error(error)
|
||||
} else {
|
||||
ErrorService.shared.handle(error, message: "Loading statuses failed.", showToastr: false)
|
||||
ErrorService.shared.handle(error, message: "trendingStatuses.error.loadingStatusesFailed", showToastr: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ struct UserProfileHeaderView: View {
|
|||
VStack(alignment: .center) {
|
||||
Text("\(account.statusesCount)")
|
||||
.font(.title3)
|
||||
Text("Posts")
|
||||
Text("userProfile.title.posts", comment: "Posts")
|
||||
.font(.subheadline)
|
||||
.opacity(0.6)
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ struct UserProfileHeaderView: View {
|
|||
VStack(alignment: .center) {
|
||||
Text("\(account.followersCount)")
|
||||
.font(.title3)
|
||||
Text("Followers")
|
||||
Text("userProfile.title.followers", comment: "Followers")
|
||||
.font(.subheadline)
|
||||
.opacity(0.6)
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ struct UserProfileHeaderView: View {
|
|||
VStack(alignment: .center) {
|
||||
Text("\(account.followingCount)")
|
||||
.font(.title3)
|
||||
Text("Following")
|
||||
Text("userProfile.title.following", comment: "Following")
|
||||
.font(.subheadline)
|
||||
.opacity(0.6)
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ struct UserProfileHeaderView: View {
|
|||
})
|
||||
}
|
||||
|
||||
Text("Joined \(account.createdAt.toRelative(.isoDateTimeMilliSec))")
|
||||
Text(String(format: NSLocalizedString("userProfile.title.joined", comment: "Joined"), account.createdAt.toRelative(.isoDateTimeMilliSec)))
|
||||
.foregroundColor(.lightGrayColor.opacity(0.5))
|
||||
.font(.footnote)
|
||||
|
||||
|
@ -95,7 +95,7 @@ struct UserProfileHeaderView: View {
|
|||
} label: {
|
||||
HStack {
|
||||
Image(systemName: relationship?.following == true ? "person.badge.minus" : "person.badge.plus")
|
||||
Text(relationship?.following == true ? "Unfollow" : (relationship?.followedBy == true ? "Follow back" : "Follow"))
|
||||
Text(relationship?.following == true ? "userProfile.title.unfollow" : (relationship?.followedBy == true ? "userProfile.title.followBack" : "userProfile.title.follow"), comment: "Follow/unfollow actions")
|
||||
}
|
||||
}
|
||||
.buttonStyle(.borderedProminent)
|
||||
|
@ -114,7 +114,7 @@ struct UserProfileHeaderView: View {
|
|||
}
|
||||
}
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Relationship action failed.", showToastr: true)
|
||||
ErrorService.shared.handle(error, message: "userProfile.error.relationship", showToastr: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ struct UserProfileStatusesView: View {
|
|||
do {
|
||||
try await self.loadMoreStatuses()
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Loading more statuses failed.", showToastr: true)
|
||||
ErrorService.shared.handle(error, message: "global.error.errorDuringDownloadStatuses", showToastr: true)
|
||||
}
|
||||
}
|
||||
Spacer()
|
||||
|
@ -56,7 +56,7 @@ struct UserProfileStatusesView: View {
|
|||
do {
|
||||
try await self.loadStatuses()
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Loading statuses failed.", showToastr: !Task.isCancelled)
|
||||
ErrorService.shared.handle(error, message: "global.error.errorDuringDownloadStatuses", showToastr: !Task.isCancelled)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ struct UserProfileView: View {
|
|||
if let accountFromApi = accountsFromApi?.accounts.first {
|
||||
self.accountId = accountFromApi.id
|
||||
} else {
|
||||
ToastrService.shared.showError(title: "Account not exists", imageSystemName: "exclamationmark.octagon")
|
||||
ToastrService.shared.showError(title: "userProfile.error.notExists", imageSystemName: "exclamationmark.octagon")
|
||||
dismiss()
|
||||
|
||||
return
|
||||
|
@ -81,7 +81,7 @@ struct UserProfileView: View {
|
|||
|
||||
self.state = .loaded
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Error during download account from server.", showToastr: !Task.isCancelled)
|
||||
ErrorService.shared.handle(error, message: "userProfile.error.loadingAccountFailed", showToastr: !Task.isCancelled)
|
||||
self.state = .error(error)
|
||||
}
|
||||
}
|
||||
|
@ -92,11 +92,11 @@ struct UserProfileView: View {
|
|||
Menu (content: {
|
||||
if let accountUrl = account.url {
|
||||
Link(destination: accountUrl) {
|
||||
Label("Open in browser", systemImage: "safari")
|
||||
Label(NSLocalizedString("userProfile.title.openInBrowser", comment: "Open in browser"), systemImage: "safari")
|
||||
}
|
||||
|
||||
ShareLink(item: accountUrl) {
|
||||
Label("Share", systemImage: "square.and.arrow.up")
|
||||
Label(NSLocalizedString("userProfile.title.share", comment: "Share"), systemImage: "square.and.arrow.up")
|
||||
}
|
||||
|
||||
Divider()
|
||||
|
@ -108,9 +108,9 @@ struct UserProfileView: View {
|
|||
}
|
||||
} label: {
|
||||
if self.relationship?.muting == true {
|
||||
Label("Unute", systemImage: "message.and.waveform.fill")
|
||||
Label(NSLocalizedString("userProfile.title.unmute", comment: "Unute"), systemImage: "message.and.waveform.fill")
|
||||
} else {
|
||||
Label("Mute", systemImage: "message.and.waveform")
|
||||
Label(NSLocalizedString("userProfile.title.mute", comment: "Mute"), systemImage: "message.and.waveform")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,9 +120,9 @@ struct UserProfileView: View {
|
|||
}
|
||||
} label: {
|
||||
if self.relationship?.blocking == true {
|
||||
Label("Unblock", systemImage: "hand.raised.fill")
|
||||
Label(NSLocalizedString("userProfile.title.unblock", comment: "Unblock"), systemImage: "hand.raised.fill")
|
||||
} else {
|
||||
Label("Block", systemImage: "hand.raised")
|
||||
Label(NSLocalizedString("userProfile.title.block", comment: "Block"), systemImage: "hand.raised")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -141,22 +141,22 @@ struct UserProfileView: View {
|
|||
Menu (content: {
|
||||
if let accountUrl = account.url {
|
||||
Link(destination: accountUrl) {
|
||||
Label("Open in browser", systemImage: "safari")
|
||||
Label(NSLocalizedString("userProfile.title.openInBrowser", comment: "Open in browser"), systemImage: "safari")
|
||||
}
|
||||
|
||||
ShareLink(item: accountUrl) {
|
||||
Label("Share", systemImage: "square.and.arrow.up")
|
||||
Label(NSLocalizedString("userProfile.title.share", comment: "Share"), systemImage: "square.and.arrow.up")
|
||||
}
|
||||
|
||||
Divider()
|
||||
}
|
||||
|
||||
NavigationLink(value: RouteurDestinations.favourites) {
|
||||
Label("Favourites", systemImage: "hand.thumbsup")
|
||||
Label(NSLocalizedString("userProfile.title.favourites", comment: "Favourites"), systemImage: "hand.thumbsup")
|
||||
}
|
||||
|
||||
NavigationLink(value: RouteurDestinations.bookmarks) {
|
||||
Label("Bookmarks", systemImage: "bookmark")
|
||||
Label(NSLocalizedString("userProfile.title.bookmarks", comment: "Bookmarks"), systemImage: "bookmark")
|
||||
}
|
||||
|
||||
}, label: {
|
||||
|
@ -179,7 +179,7 @@ struct UserProfileView: View {
|
|||
}
|
||||
}
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Muting/unmuting action failed.", showToastr: true)
|
||||
ErrorService.shared.handle(error, message: "userProfile.error.mute", showToastr: true)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,7 +195,7 @@ struct UserProfileView: View {
|
|||
}
|
||||
}
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Block/unblock action failed.", showToastr: true)
|
||||
ErrorService.shared.handle(error, message: "userProfile.error.block", showToastr: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ struct ContentWarning<Content: View>: View {
|
|||
Image(systemName: "eye.slash.fill")
|
||||
.font(.title2)
|
||||
.shadow(color: Color.systemBackground, radius: 0.3)
|
||||
Text("Sensitive content")
|
||||
Text("global.title.contentWarning", comment: "Sensitive content")
|
||||
.font(.title2)
|
||||
.shadow(color: Color.systemBackground, radius: 0.3)
|
||||
if let spoilerText {
|
||||
|
@ -63,7 +63,7 @@ struct ContentWarning<Content: View>: View {
|
|||
self.showSensitive = true
|
||||
}
|
||||
} label: {
|
||||
Text("See post")
|
||||
Text("global.title.seePost", comment: "See post")
|
||||
.shadow(color: Color.systemBackground, radius: 0.3)
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
|
|
|
@ -30,7 +30,7 @@ struct ImageCarouselPicture: View {
|
|||
self.onImageDownloaded(attachment, imageData)
|
||||
}
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Cannot download image for status")
|
||||
ErrorService.shared.handle(error, message: "global.error.errorDuringImageDownload")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -148,10 +148,10 @@ struct ImageRow: View {
|
|||
}
|
||||
} catch {
|
||||
if !Task.isCancelled {
|
||||
ErrorService.shared.handle(error, message: "Cannot download the image.")
|
||||
ErrorService.shared.handle(error, message: "global.error.errorDuringImageDownload")
|
||||
self.error = error
|
||||
} else {
|
||||
ErrorService.shared.handle(error, message: "Download image has been canceled.")
|
||||
ErrorService.shared.handle(error, message: "global.error.canceledImageDownload")
|
||||
self.cancelled = true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ struct ImageRowAsync: View {
|
|||
|
||||
VStack(alignment: .center) {
|
||||
Spacer()
|
||||
Text("Cannot download image")
|
||||
Text("global.error.errorDuringImageDownload", comment: "Cannot download image")
|
||||
.foregroundColor(.systemBackground)
|
||||
Spacer()
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ struct ImagesGrid: View {
|
|||
let statusesWithImages = statusesFromApi.getStatusesWithImagesOnly()
|
||||
self.updatePhotos(statusesWithImages: statusesWithImages)
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Loading tags failed.", showToastr: !Task.isCancelled)
|
||||
ErrorService.shared.handle(error, message: "global.error.errorDuringDataLoad", showToastr: !Task.isCancelled)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -81,31 +81,31 @@ struct InteractionRow: View {
|
|||
|
||||
Menu {
|
||||
NavigationLink(value: RouteurDestinations.accounts(listType: .reblogged(entityId: statusModel.id))) {
|
||||
Label("Reboosted by", systemImage: "paperplane")
|
||||
Label("status.title.reboostedBy", systemImage: "paperplane")
|
||||
}
|
||||
|
||||
NavigationLink(value: RouteurDestinations.accounts(listType: .favourited(entityId: statusModel.id))) {
|
||||
Label("Favourited by", systemImage: "hand.thumbsup")
|
||||
Label("status.title.favouritedBy", systemImage: "hand.thumbsup")
|
||||
}
|
||||
|
||||
if let url = statusModel.url {
|
||||
Divider()
|
||||
|
||||
Link(destination: url) {
|
||||
Label("Open in browser", systemImage: "safari")
|
||||
Label("status.title.openInBrowser", systemImage: "safari")
|
||||
}
|
||||
|
||||
ShareLink(item: url) {
|
||||
Label("Share post", systemImage: "square.and.arrow.up")
|
||||
Label("status.title.shareStatus", systemImage: "square.and.arrow.up")
|
||||
}
|
||||
}
|
||||
|
||||
if self.statusModel.account.id == self.applicationState.account?.id {
|
||||
Section(header: Text("Your post")) {
|
||||
Section(header: Text("status.title.yourStatus", comment: "Your post")) {
|
||||
Button(role: .destructive) {
|
||||
self.deleteStatus()
|
||||
} label: {
|
||||
Label("Delete", systemImage: "trash")
|
||||
Label("status.title.delete", systemImage: "trash")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -143,9 +143,11 @@ struct InteractionRow: View {
|
|||
self.reblogged = status.reblogged
|
||||
}
|
||||
|
||||
ToastrService.shared.showSuccess(self.reblogged ? "Reboosted" : "Unreboosted", imageSystemName: "paperplane.fill")
|
||||
ToastrService.shared.showSuccess(self.reblogged
|
||||
? NSLocalizedString("status.title.reboosted", comment: "Reboosted")
|
||||
: NSLocalizedString("status.title.unreboosted", comment: "Unreboosted"), imageSystemName: "paperplane.fill")
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Reboost action failed.", showToastr: true)
|
||||
ErrorService.shared.handle(error, message: "status.error.reboostFailed", showToastr: true)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,9 +165,11 @@ struct InteractionRow: View {
|
|||
self.favourited = status.favourited
|
||||
}
|
||||
|
||||
ToastrService.shared.showSuccess(self.favourited ? "Favourited" : "Unfavourited", imageSystemName: "hand.thumbsup.fill")
|
||||
ToastrService.shared.showSuccess(self.favourited
|
||||
? NSLocalizedString("status.title.favourited", comment: "Favourited")
|
||||
: NSLocalizedString("status.title.unfavourited", comment: "Unfavourited"), imageSystemName: "hand.thumbsup.fill")
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Favourite action failed.", showToastr: true)
|
||||
ErrorService.shared.handle(error, message: "status.error.favouriteFailed", showToastr: true)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -176,9 +180,11 @@ struct InteractionRow: View {
|
|||
: try await self.client.statuses?.bookmark(statusId: self.statusModel.id)
|
||||
|
||||
self.bookmarked.toggle()
|
||||
ToastrService.shared.showSuccess(self.bookmarked ? "Bookmarked" : "Unbookmarked", imageSystemName: "bookmark.fill")
|
||||
ToastrService.shared.showSuccess(self.bookmarked
|
||||
? NSLocalizedString("status.title.bookmarked", comment: "Bookmarked")
|
||||
: NSLocalizedString("status.title.unbookmarked", comment: "Unbookmarked"), imageSystemName: "bookmark.fill")
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Bookmark action failed.", showToastr: true)
|
||||
ErrorService.shared.handle(error, message: "status.error.bookmarkFailed", showToastr: true)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -186,11 +192,11 @@ struct InteractionRow: View {
|
|||
Task {
|
||||
do {
|
||||
try await self.client.statuses?.delete(statusId: self.statusModel.id)
|
||||
ToastrService.shared.showSuccess("Post deleted", imageSystemName: "checkmark.circle.fill")
|
||||
ToastrService.shared.showSuccess("status.title.statusDeleted", imageSystemName: "checkmark.circle.fill")
|
||||
|
||||
self.delete?()
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Delete action failed.", showToastr: true)
|
||||
ErrorService.shared.handle(error, message: "status.error.deleteFailed", showToastr: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,9 +9,9 @@ import SwiftUI
|
|||
struct NoDataView: View {
|
||||
|
||||
private let imageSystemName: String
|
||||
private let text: String
|
||||
private let text: LocalizedStringKey
|
||||
|
||||
init(imageSystemName: String, text: String) {
|
||||
init(imageSystemName: String, text: LocalizedStringKey) {
|
||||
self.imageSystemName = imageSystemName
|
||||
self.text = text
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ struct NoDataView: View {
|
|||
Image(systemName: self.imageSystemName)
|
||||
.font(.largeTitle)
|
||||
.padding(.bottom, 4)
|
||||
Text(self.text)
|
||||
Text(self.text, comment: "No data message")
|
||||
.font(.title3)
|
||||
}
|
||||
.foregroundColor(.lightGrayColor)
|
||||
|
|
|
@ -185,7 +185,7 @@ extension TextView.Representable.Coordinator {
|
|||
public extension TextView {
|
||||
/// Specify a placeholder text
|
||||
/// - Parameter placeholder: The placeholder text
|
||||
func placeholder(_ placeholder: String) -> TextView {
|
||||
func placeholder(_ placeholder: LocalizedStringKey) -> TextView {
|
||||
self.placeholder(placeholder) { $0 }
|
||||
}
|
||||
|
||||
|
@ -197,7 +197,7 @@ public extension TextView {
|
|||
/// .placeholder("placeholder") { view in
|
||||
/// view.foregroundColor(.red)
|
||||
/// }
|
||||
func placeholder<V: View>(_ placeholder: String, _ configure: (Text) -> V) -> TextView {
|
||||
func placeholder<V: View>(_ placeholder: LocalizedStringKey, _ configure: (Text) -> V) -> TextView {
|
||||
var view = self
|
||||
let text = Text(placeholder)
|
||||
view.placeholderView = AnyView(configure(text))
|
||||
|
|
|
@ -14,7 +14,7 @@ public class ImageFetcher {
|
|||
|
||||
private let maxImageSize = 1000.0
|
||||
|
||||
func fetchWidgetEntries(length: Int = 6) async throws -> [WidgetEntry] {
|
||||
func fetchWidgetEntries(length: Int = 8) async throws -> [WidgetEntry] {
|
||||
let defaultSettings = ApplicationSettingsHandler.shared.getDefaultSettings()
|
||||
guard let accountId = defaultSettings.currentAccount else {
|
||||
return [self.placeholder()]
|
||||
|
@ -29,7 +29,7 @@ public class ImageFetcher {
|
|||
}
|
||||
|
||||
let client = PixelfedClient(baseURL: account.serverUrl).getAuthenticated(token: accessToken)
|
||||
let statuses = try await client.getHomeTimeline(limit: 10)
|
||||
let statuses = try await client.getHomeTimeline(limit: 20)
|
||||
var widgetEntries: [WidgetEntry] = []
|
||||
|
||||
for status in statuses {
|
||||
|
@ -54,7 +54,7 @@ public class ImageFetcher {
|
|||
continue
|
||||
}
|
||||
|
||||
let displayDate = Calendar.current.date(byAdding: .minute, value: widgetEntries.count * 10, to: Date())
|
||||
let displayDate = Calendar.current.date(byAdding: .minute, value: widgetEntries.count * 15, to: Date())
|
||||
|
||||
widgetEntries.append(WidgetEntry(date: displayDate ?? Date(),
|
||||
image: uiImage,
|
||||
|
|
|
@ -31,13 +31,13 @@ struct Provider: TimelineProvider {
|
|||
let currentDate = Date()
|
||||
let widgetEntries = await self.getWidgetEntries()
|
||||
|
||||
let nextUpdateDate = Calendar.current.date(byAdding: .hour, value: 1, to: currentDate)!
|
||||
let nextUpdateDate = Calendar.current.date(byAdding: .hour, value: 2, to: currentDate)!
|
||||
let timeline = Timeline(entries: widgetEntries, policy: .after(nextUpdateDate))
|
||||
completion(timeline)
|
||||
}
|
||||
}
|
||||
|
||||
func getWidgetEntries(length: Int = 6) async -> [WidgetEntry] {
|
||||
func getWidgetEntries(length: Int = 8) async -> [WidgetEntry] {
|
||||
do {
|
||||
return try await ImageFetcher.shared.fetchWidgetEntries(length: length)
|
||||
} catch {
|
||||
|
|
|
@ -15,7 +15,7 @@ struct VernissageWidget: Widget {
|
|||
VernissageWidgetEntryView(entry: entry)
|
||||
}
|
||||
.configurationDisplayName("Vernissage")
|
||||
.description("Widget with photos from Pixelfed.")
|
||||
.description("widget.title.description")
|
||||
.supportedFamilies([.systemSmall, .systemMedium, .systemLarge])
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue