diff --git a/lib/data/models/aggregated_item.dart b/lib/data/models/aggregated_item.dart index b45b9d97a..7010d76bf 100644 --- a/lib/data/models/aggregated_item.dart +++ b/lib/data/models/aggregated_item.dart @@ -88,6 +88,10 @@ class AggregatedItem { bool get isFavorite => _userData?['IsFavorite'] as bool? ?? false; + double? get personalRating => (_userData?['Rating'] as num?)?.toDouble(); + + bool? get personalRatingLikes => _userData?['Likes'] as bool?; + int? get playbackPositionTicks => _toInt(_userData?['PlaybackPositionTicks']); Duration? get playbackPosition => playbackPositionTicks != null diff --git a/lib/data/offline/offline_stub_apis.dart b/lib/data/offline/offline_stub_apis.dart index 03f21c68d..d6123593b 100644 --- a/lib/data/offline/offline_stub_apis.dart +++ b/lib/data/offline/offline_stub_apis.dart @@ -53,6 +53,9 @@ class OfflineUserLibraryApi implements UserLibraryApi { OfflineUserLibraryApi(this._catalog); + @override + bool get supportsNumericUserRatings => false; + @override Future> getItem(String itemId) async { final entry = _catalog.byId(itemId); @@ -85,6 +88,14 @@ class OfflineUserLibraryApi implements UserLibraryApi { throw offlineUnavailable('/UserItems/$itemId/Rating'); } + @override + Future updateNumericUserRating( + String itemId, { + required double rating, + }) async { + throw offlineUnavailable('/UserItems/$itemId/UserData'); + } + @override Future deleteUserRating(String itemId) async { throw offlineUnavailable('/UserItems/$itemId/Rating'); diff --git a/lib/data/repositories/item_mutation_repository.dart b/lib/data/repositories/item_mutation_repository.dart index 822c7879f..6f66c7839 100644 --- a/lib/data/repositories/item_mutation_repository.dart +++ b/lib/data/repositories/item_mutation_repository.dart @@ -31,6 +31,13 @@ class ItemMutationRepository { await _client.userLibraryApi.updateUserRating(itemId, likes: likes); } + Future setNumericRating(String itemId, {required double rating}) async { + await _client.userLibraryApi.updateNumericUserRating( + itemId, + rating: rating, + ); + } + Future clearRating(String itemId) async { await _client.userLibraryApi.deleteUserRating(itemId); } diff --git a/lib/data/viewmodels/item_detail_view_model.dart b/lib/data/viewmodels/item_detail_view_model.dart index 288043c08..19d66dfc9 100644 --- a/lib/data/viewmodels/item_detail_view_model.dart +++ b/lib/data/viewmodels/item_detail_view_model.dart @@ -186,6 +186,11 @@ class ItemDetailViewModel extends ChangeNotifier { ImageApi get imageApi => _client.imageApi; String get baseUrl => _client.baseUrl; + bool get supportsNumericUserRatings => + _client.userLibraryApi.supportsNumericUserRatings; + + bool _isRatingMutationInProgress = false; + bool get isRatingMutationInProgress => _isRatingMutationInProgress; bool get canManagePlaylistTracks => _item?.type == 'Playlist' && @@ -1097,6 +1102,73 @@ class ItemDetailViewModel extends ChangeNotifier { } } + Future setThumbRating(bool likes) async { + return _mutateRating( + {'Rating': likes ? 10.0 : 1.0, 'Likes': likes}, + () => _mutations.setRating(itemId, likes: likes), + ); + } + + Future setNumericRating(double rating) async { + if (_isRatingMutationInProgress) return; + if (!rating.isFinite || rating < 0 || rating > 10) { + throw ArgumentError.value(rating, 'rating', 'must be between 0 and 10'); + } + return _mutateRating( + {'Rating': rating, 'Likes': rating >= 6.5}, + () => _mutations.setNumericRating(itemId, rating: rating), + ); + } + + Future clearRating() async { + return _mutateRating( + {'Rating': null, 'Likes': null}, + () => _mutations.clearRating(itemId), + ); + } + + Future _mutateRating( + Map userDataPatch, + Future Function() mutation, + ) async { + if (_isRatingMutationInProgress) return; + final previousUserData = _copyUserData(); + _isRatingMutationInProgress = true; + try { + _applyOptimisticUpdate(userDataPatch); + await mutation(); + await _reload(); + } catch (_) { + _restoreUserData(previousUserData); + rethrow; + } finally { + _isRatingMutationInProgress = false; + notifyListeners(); + } + } + + Map? _copyUserData() { + final userData = _item?.rawData['UserData']; + return userData is Map ? Map.from(userData) : null; + } + + void _restoreUserData(Map? userData) { + final item = _item; + if (item == null) return; + final updatedRaw = Map.from(item.rawData); + if (userData == null) { + updatedRaw.remove('UserData'); + } else { + updatedRaw['UserData'] = userData; + } + _item = AggregatedItem( + id: item.id, + serverId: item.serverId, + rawData: updatedRaw, + ); + notifyListeners(); + } + void _applyOptimisticUpdate(Map userDataPatch) { final item = _item; if (item == null) return; diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 3d48584e2..11717b0f3 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -8772,5 +8772,63 @@ "imdbMostPopularMovies": "IMDb Most Popular Movies", "imdbMostPopularTvShows": "IMDb Most Popular TV Shows", "imdbLowestRatedMovies": "IMDb Lowest Rated Movies", - "imdbTopEnglishMovies": "IMDb Top Rated English Movies" + "imdbTopEnglishMovies": "IMDb Top Rated English Movies", + "personalRatingStyle": "Personal rating style", + "@personalRatingStyle": { + "description": "Selects how personal ratings are displayed and entered on media details." + }, + "personalRatingThumbs": "Like / dislike", + "@personalRatingThumbs": { + "description": "Personal rating style using like and dislike actions." + }, + "personalRatingStars": "5 stars", + "@personalRatingStars": { + "description": "Personal rating style using a five-star scale." + }, + "personalRatingNumeric": "Numeric score out of 10", + "@personalRatingNumeric": { + "description": "Personal rating style using a numeric score out of ten." + }, + "rate": "Rate", + "@rate": { + "description": "Action that opens the personal rating control." + }, + "like": "Like", + "@like": { + "description": "Personal rating action for a positive rating." + }, + "dislike": "Dislike", + "@dislike": { + "description": "Personal rating action for a negative rating." + }, + "personalRatingClear": "Clear rating", + "@personalRatingClear": { + "description": "Action that removes the personal rating from the media item." + }, + "personalRatingRated": "Rated", + "@personalRatingRated": { + "description": "Tooltip for a media item that has a numeric personal rating." + }, + "personalRatingSaveFailed": "Could not save rating", + "@personalRatingSaveFailed": { + "description": "Error shown when saving a personal rating fails." + }, + "increase": "Increase", + "@increase": { + "description": "Action that increases a numeric personal rating." + }, + "decrease": "Decrease", + "@decrease": { + "description": "Action that decreases a numeric personal rating." + }, + "personalRatingOutOfTen": "{rating} / 10", + "@personalRatingOutOfTen": { + "description": "Numeric personal rating displayed on a scale out of ten.", + "placeholders": { "rating": { "type": "String" } } + }, + "personalRatingOutOfFive": "{rating} / 5", + "@personalRatingOutOfFive": { + "description": "Personal rating displayed on a five-star scale.", + "placeholders": { "rating": { "type": "String" } } + } } diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index 688a5d4be..f328d8669 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -17595,6 +17595,90 @@ abstract class AppLocalizations { /// In en, this message translates to: /// **'IMDb Top Rated English Movies'** String get imdbTopEnglishMovies; + + /// Selects how personal ratings are displayed and entered on media details. + /// + /// In en, this message translates to: + /// **'Personal rating style'** + String get personalRatingStyle; + + /// Personal rating style using like and dislike actions. + /// + /// In en, this message translates to: + /// **'Like / dislike'** + String get personalRatingThumbs; + + /// Personal rating style using a five-star scale. + /// + /// In en, this message translates to: + /// **'5 stars'** + String get personalRatingStars; + + /// Personal rating style using a numeric score out of ten. + /// + /// In en, this message translates to: + /// **'Numeric score out of 10'** + String get personalRatingNumeric; + + /// Action that opens the personal rating control. + /// + /// In en, this message translates to: + /// **'Rate'** + String get rate; + + /// Personal rating action for a positive rating. + /// + /// In en, this message translates to: + /// **'Like'** + String get like; + + /// Personal rating action for a negative rating. + /// + /// In en, this message translates to: + /// **'Dislike'** + String get dislike; + + /// Action that removes the personal rating from the media item. + /// + /// In en, this message translates to: + /// **'Clear rating'** + String get personalRatingClear; + + /// Tooltip for a media item that has a numeric personal rating. + /// + /// In en, this message translates to: + /// **'Rated'** + String get personalRatingRated; + + /// Error shown when saving a personal rating fails. + /// + /// In en, this message translates to: + /// **'Could not save rating'** + String get personalRatingSaveFailed; + + /// Action that increases a numeric personal rating. + /// + /// In en, this message translates to: + /// **'Increase'** + String get increase; + + /// Action that decreases a numeric personal rating. + /// + /// In en, this message translates to: + /// **'Decrease'** + String get decrease; + + /// Numeric personal rating displayed on a scale out of ten. + /// + /// In en, this message translates to: + /// **'{rating} / 10'** + String personalRatingOutOfTen(String rating); + + /// Personal rating displayed on a five-star scale. + /// + /// In en, this message translates to: + /// **'{rating} / 5'** + String personalRatingOutOfFive(String rating); } class _AppLocalizationsDelegate diff --git a/lib/l10n/app_localizations_af.dart b/lib/l10n/app_localizations_af.dart index bee15aa98..441f86382 100644 --- a/lib/l10n/app_localizations_af.dart +++ b/lib/l10n/app_localizations_af.dart @@ -9897,4 +9897,50 @@ class AppLocalizationsAf extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_ar.dart b/lib/l10n/app_localizations_ar.dart index 35c8dfff9..64009f5d2 100644 --- a/lib/l10n/app_localizations_ar.dart +++ b/lib/l10n/app_localizations_ar.dart @@ -9843,4 +9843,50 @@ class AppLocalizationsAr extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_be.dart b/lib/l10n/app_localizations_be.dart index a9544ae74..aada7da0c 100644 --- a/lib/l10n/app_localizations_be.dart +++ b/lib/l10n/app_localizations_be.dart @@ -9924,4 +9924,50 @@ class AppLocalizationsBe extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_bg.dart b/lib/l10n/app_localizations_bg.dart index 0c1b76583..ebd0ee3c4 100644 --- a/lib/l10n/app_localizations_bg.dart +++ b/lib/l10n/app_localizations_bg.dart @@ -9969,4 +9969,50 @@ class AppLocalizationsBg extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_bn.dart b/lib/l10n/app_localizations_bn.dart index 85ae46399..41a3a16d6 100644 --- a/lib/l10n/app_localizations_bn.dart +++ b/lib/l10n/app_localizations_bn.dart @@ -9885,4 +9885,50 @@ class AppLocalizationsBn extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_ca.dart b/lib/l10n/app_localizations_ca.dart index e2e5178ba..ce261719f 100644 --- a/lib/l10n/app_localizations_ca.dart +++ b/lib/l10n/app_localizations_ca.dart @@ -10011,4 +10011,50 @@ class AppLocalizationsCa extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_cs.dart b/lib/l10n/app_localizations_cs.dart index c1cb4b12b..fba91de7f 100644 --- a/lib/l10n/app_localizations_cs.dart +++ b/lib/l10n/app_localizations_cs.dart @@ -9905,4 +9905,50 @@ class AppLocalizationsCs extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_cy.dart b/lib/l10n/app_localizations_cy.dart index 80a020e35..47abb63e3 100644 --- a/lib/l10n/app_localizations_cy.dart +++ b/lib/l10n/app_localizations_cy.dart @@ -9918,4 +9918,50 @@ class AppLocalizationsCy extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_da.dart b/lib/l10n/app_localizations_da.dart index c42f2b9ed..3d459e321 100644 --- a/lib/l10n/app_localizations_da.dart +++ b/lib/l10n/app_localizations_da.dart @@ -9887,4 +9887,50 @@ class AppLocalizationsDa extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_de.dart b/lib/l10n/app_localizations_de.dart index ae89a2ab8..5c9ce1765 100644 --- a/lib/l10n/app_localizations_de.dart +++ b/lib/l10n/app_localizations_de.dart @@ -10030,4 +10030,50 @@ class AppLocalizationsDe extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_el.dart b/lib/l10n/app_localizations_el.dart index dbf4494f2..4e3b6dfbd 100644 --- a/lib/l10n/app_localizations_el.dart +++ b/lib/l10n/app_localizations_el.dart @@ -10015,4 +10015,50 @@ class AppLocalizationsEl extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index 30d248ee9..536c51be5 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -9830,6 +9830,52 @@ class AppLocalizationsEn extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } /// The translations for English, as used in the United Kingdom (`en_GB`). diff --git a/lib/l10n/app_localizations_eo.dart b/lib/l10n/app_localizations_eo.dart index ae2e0a5f0..74e83b157 100644 --- a/lib/l10n/app_localizations_eo.dart +++ b/lib/l10n/app_localizations_eo.dart @@ -9881,4 +9881,50 @@ class AppLocalizationsEo extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_es.dart b/lib/l10n/app_localizations_es.dart index 25a8b73c8..2f1d53a5f 100644 --- a/lib/l10n/app_localizations_es.dart +++ b/lib/l10n/app_localizations_es.dart @@ -9971,6 +9971,52 @@ class AppLocalizationsEs extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } /// The translations for Spanish Castilian, as used in Latin America and the Caribbean (`es_419`). diff --git a/lib/l10n/app_localizations_et.dart b/lib/l10n/app_localizations_et.dart index 362711bcd..f38a06168 100644 --- a/lib/l10n/app_localizations_et.dart +++ b/lib/l10n/app_localizations_et.dart @@ -9906,4 +9906,50 @@ class AppLocalizationsEt extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_fa.dart b/lib/l10n/app_localizations_fa.dart index b8b67a836..350d6bd31 100644 --- a/lib/l10n/app_localizations_fa.dart +++ b/lib/l10n/app_localizations_fa.dart @@ -9850,4 +9850,50 @@ class AppLocalizationsFa extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_fi.dart b/lib/l10n/app_localizations_fi.dart index 708eb1de8..237489a70 100644 --- a/lib/l10n/app_localizations_fi.dart +++ b/lib/l10n/app_localizations_fi.dart @@ -9917,4 +9917,50 @@ class AppLocalizationsFi extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_fr.dart b/lib/l10n/app_localizations_fr.dart index 8128ce895..99b370301 100644 --- a/lib/l10n/app_localizations_fr.dart +++ b/lib/l10n/app_localizations_fr.dart @@ -10003,4 +10003,50 @@ class AppLocalizationsFr extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_gl.dart b/lib/l10n/app_localizations_gl.dart index 19e21f004..3f3e82375 100644 --- a/lib/l10n/app_localizations_gl.dart +++ b/lib/l10n/app_localizations_gl.dart @@ -9986,4 +9986,50 @@ class AppLocalizationsGl extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_he.dart b/lib/l10n/app_localizations_he.dart index b02c42ae0..cd768068c 100644 --- a/lib/l10n/app_localizations_he.dart +++ b/lib/l10n/app_localizations_he.dart @@ -9785,4 +9785,50 @@ class AppLocalizationsHe extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_hi.dart b/lib/l10n/app_localizations_hi.dart index f070cd794..2bc0bb3eb 100644 --- a/lib/l10n/app_localizations_hi.dart +++ b/lib/l10n/app_localizations_hi.dart @@ -9867,4 +9867,50 @@ class AppLocalizationsHi extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_hr.dart b/lib/l10n/app_localizations_hr.dart index 2641a8308..7ad4ffc25 100644 --- a/lib/l10n/app_localizations_hr.dart +++ b/lib/l10n/app_localizations_hr.dart @@ -9911,4 +9911,50 @@ class AppLocalizationsHr extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_hu.dart b/lib/l10n/app_localizations_hu.dart index f6d3342b2..37a9ab514 100644 --- a/lib/l10n/app_localizations_hu.dart +++ b/lib/l10n/app_localizations_hu.dart @@ -10003,4 +10003,50 @@ class AppLocalizationsHu extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_id.dart b/lib/l10n/app_localizations_id.dart index 0e2d67bf6..8e5595d88 100644 --- a/lib/l10n/app_localizations_id.dart +++ b/lib/l10n/app_localizations_id.dart @@ -9894,4 +9894,50 @@ class AppLocalizationsId extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_it.dart b/lib/l10n/app_localizations_it.dart index 677811356..d2ba397fb 100644 --- a/lib/l10n/app_localizations_it.dart +++ b/lib/l10n/app_localizations_it.dart @@ -9935,4 +9935,50 @@ class AppLocalizationsIt extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_ja.dart b/lib/l10n/app_localizations_ja.dart index 40674c014..a50f4c254 100644 --- a/lib/l10n/app_localizations_ja.dart +++ b/lib/l10n/app_localizations_ja.dart @@ -9694,4 +9694,50 @@ class AppLocalizationsJa extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_kk.dart b/lib/l10n/app_localizations_kk.dart index e872d4f28..fcdc88fc7 100644 --- a/lib/l10n/app_localizations_kk.dart +++ b/lib/l10n/app_localizations_kk.dart @@ -9922,4 +9922,50 @@ class AppLocalizationsKk extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_kn.dart b/lib/l10n/app_localizations_kn.dart index 0bb620fdb..bfce6ae48 100644 --- a/lib/l10n/app_localizations_kn.dart +++ b/lib/l10n/app_localizations_kn.dart @@ -9937,4 +9937,50 @@ class AppLocalizationsKn extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_ko.dart b/lib/l10n/app_localizations_ko.dart index 7153a46a8..867827d09 100644 --- a/lib/l10n/app_localizations_ko.dart +++ b/lib/l10n/app_localizations_ko.dart @@ -9689,4 +9689,50 @@ class AppLocalizationsKo extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_lt.dart b/lib/l10n/app_localizations_lt.dart index 0c6921592..717fcec30 100644 --- a/lib/l10n/app_localizations_lt.dart +++ b/lib/l10n/app_localizations_lt.dart @@ -9923,4 +9923,50 @@ class AppLocalizationsLt extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_lv.dart b/lib/l10n/app_localizations_lv.dart index bf68a1f91..ba1d6cf7b 100644 --- a/lib/l10n/app_localizations_lv.dart +++ b/lib/l10n/app_localizations_lv.dart @@ -9933,4 +9933,50 @@ class AppLocalizationsLv extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_mk.dart b/lib/l10n/app_localizations_mk.dart index b4a7d918a..73608036c 100644 --- a/lib/l10n/app_localizations_mk.dart +++ b/lib/l10n/app_localizations_mk.dart @@ -9940,4 +9940,50 @@ class AppLocalizationsMk extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_ml.dart b/lib/l10n/app_localizations_ml.dart index d91884891..ca0fd0324 100644 --- a/lib/l10n/app_localizations_ml.dart +++ b/lib/l10n/app_localizations_ml.dart @@ -9987,4 +9987,50 @@ class AppLocalizationsMl extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_mn.dart b/lib/l10n/app_localizations_mn.dart index 02153f575..a54ce40ef 100644 --- a/lib/l10n/app_localizations_mn.dart +++ b/lib/l10n/app_localizations_mn.dart @@ -9918,4 +9918,50 @@ class AppLocalizationsMn extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_nb.dart b/lib/l10n/app_localizations_nb.dart index 3b2f298e5..86b0748ea 100644 --- a/lib/l10n/app_localizations_nb.dart +++ b/lib/l10n/app_localizations_nb.dart @@ -9890,4 +9890,50 @@ class AppLocalizationsNb extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_nl.dart b/lib/l10n/app_localizations_nl.dart index 774313276..4232ee5c5 100644 --- a/lib/l10n/app_localizations_nl.dart +++ b/lib/l10n/app_localizations_nl.dart @@ -9920,4 +9920,50 @@ class AppLocalizationsNl extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_pa.dart b/lib/l10n/app_localizations_pa.dart index 3302b9612..4e29028b6 100644 --- a/lib/l10n/app_localizations_pa.dart +++ b/lib/l10n/app_localizations_pa.dart @@ -9870,4 +9870,50 @@ class AppLocalizationsPa extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_pl.dart b/lib/l10n/app_localizations_pl.dart index 71ca82c46..710ef6c1e 100644 --- a/lib/l10n/app_localizations_pl.dart +++ b/lib/l10n/app_localizations_pl.dart @@ -9,26 +9,26 @@ class AppLocalizationsPl extends AppLocalizations { AppLocalizationsPl([String locale = 'pl']) : super(locale); @override - String get appTitle => 'Księżycowa Płetwa'; + String get appTitle => 'Moonfin'; @override - String get accountPreferences => 'ACCOUNT PREFERENCES'; + String get accountPreferences => 'Ustawienia konta'; @override - String get interfaceLanguage => 'Interface Language'; + String get interfaceLanguage => 'Język interfejsu'; @override - String get systemLanguageDefault => 'System Default'; + String get systemLanguageDefault => 'Zgodnie z systemem'; @override - String get signIn => 'Zalogować się'; + String get signIn => 'Logowanie'; @override - String get empty => 'Empty'; + String get empty => 'Brak'; @override String connectingToServer(String serverName) { - return 'Connecting to $serverName'; + return 'Połącz z $serverName'; } @override @@ -45,13 +45,13 @@ class AppLocalizationsPl extends AppLocalizations { @override String get quickConnectInstruction => - 'Wpisz ten kod na panelu internetowym swojego serwera:'; + 'Wpisz ten kod w panelu internetowym swojego serwera:'; @override - String get waitingForAuthorization => 'Oczekiwanie na autoryzację...'; + String get waitingForAuthorization => 'Autoryzacja...'; @override - String get back => 'Z powrotem'; + String get back => 'Powrót'; @override String get serverUnavailable => 'Serwer jest niedostępny'; @@ -61,12 +61,12 @@ class AppLocalizationsPl extends AppLocalizations { @override String quickConnectUnavailable(String detail) { - return 'QuickConnect unavailable: $detail'; + return 'Szybkie połączenie nieudane: $detail'; } @override String quickConnectUnavailableWithStatus(String status, String detail) { - return 'QuickConnect unavailable ($status): $detail'; + return 'Szybkie połączenie nieudane ($status): $detail'; } @override @@ -80,17 +80,17 @@ class AppLocalizationsPl extends AppLocalizations { @override String appVersionFooter(String version) { - return 'Moonfin version $version'; + return 'Moonfin wersja $version'; } @override String get savedServers => 'Zapisane serwery'; @override - String get discoveredServers => 'Odkryte serwery'; + String get discoveredServers => 'Wykryte serwery'; @override - String get noneFound => 'Nie znaleziono żadnych'; + String get noneFound => 'Nie znaleziono'; @override String get unableToConnectToServer => 'Nie można połączyć się z serwerem'; @@ -99,21 +99,21 @@ class AppLocalizationsPl extends AppLocalizations { String get addServer => 'Dodaj serwer'; @override - String get embyConnect => 'Emby Połącz'; + String get embyConnect => 'Połącz z Emby'; @override String get removeServer => 'Usuń serwer'; @override String removeServerConfirmation(String serverName) { - return 'Remove \"$serverName\" from your servers?'; + return 'Usunąć \"$serverName\" ?'; } @override - String get cancel => 'Anulować'; + String get cancel => 'Anuluj'; @override - String get remove => 'Usunąć'; + String get remove => 'Usuń'; @override String get connectToServer => 'Połącz się z serwerem'; @@ -125,11 +125,10 @@ class AppLocalizationsPl extends AppLocalizations { String get serverAddressHint => 'https://twój-serwer.example.com'; @override - String get connect => 'Łączyć'; + String get connect => 'Połącz'; @override - String get secureStorageUnavailable => - 'Bezpieczne przechowywanie jest niedostępne'; + String get secureStorageUnavailable => 'Bezpieczny magazyn niedostępny'; @override String get secureStorageUnavailableMessage => @@ -142,24 +141,24 @@ class AppLocalizationsPl extends AppLocalizations { String get settingsAppearanceTheme => 'Motyw aplikacji'; @override - String get detailScreenStyle => 'Detail screen style'; + String get detailScreenStyle => 'Widok szczegółów'; @override String get detailScreenStyleSubtitle => - 'Classic is the original centered moonfin layout. Modern is a responsive cinematic layout.'; + 'Klasyczny to oryginalny układ Moonfin. Nowoczesny to responsywny układ w stylu kinowym.'; @override - String get detailScreenStyleMoonfin => 'Classic'; + String get detailScreenStyleMoonfin => 'Klasyczny'; @override - String get detailScreenStyleModern => 'Modern'; + String get detailScreenStyleModern => 'Nowoczesny'; @override - String get expandedTabs => 'Expanded Tabs'; + String get expandedTabs => 'Rozwinięcie zakładki'; @override String get expandedTabsSubtitle => - 'Automatically show tab content while browsing tabs. Turn off to open and close each tab manually.'; + 'Automatycznie pokazuj zawartość zakładki podczas przeglądania. Wyłącz aby otwierać i zamykać zakładki ręcznie.'; @override String get showTechnicalDetails => 'Show Technical Details?'; @@ -169,35 +168,35 @@ class AppLocalizationsPl extends AppLocalizations { 'Show codec, resolution, and stream information in banner summary'; @override - String get recommendationSystem => 'Recommendation System'; + String get recommendationSystem => 'System rekomendacji'; @override String get recommendationSystemSubtitle => - 'Use the Moonfin Recommends local-library algorithm or the online TMDb\'s Similarity Metrics. Note: Online recommendations require Seerr integration.'; + 'Użyj lokalnego algorytmu Moonfin lub metryk online z TMDb. Uwaga! Rekomendacje online wymagają integracji z Seerr.'; @override String get recommendationSystemMoonfin => 'Moonfin Recommends'; @override - String get recommendationSystemTmdb => 'TMDb Similarity'; + String get recommendationSystemTmdb => 'Dopasowanie TMDb'; @override String get recommendationsApplyParentalRatingCap => - 'Apply Parental Rating Cap?'; + 'Zastosować limit oceny rodzicielskiej?'; @override String get recommendationsApplyParentalRatingCapSubtitle => - 'Limit Moonfin Recommends suggestions by parental rating of target media'; + 'Ogranicz sugestie Moonfin do poziomu oceny rodzicielskiej filmu'; @override - String get interfaceStyle => 'Interface Style'; + String get interfaceStyle => 'Styl interfejsu'; @override String get interfaceStyleSubtitle => - 'Automatic matches your device. Choose Apple or Material to force a look.'; + 'Automatyczne dopasowanie do urządzenia. Wybierz Apple lub Material aby wymusić wygląd.'; @override - String get interfaceStyleAutomatic => 'Automatic'; + String get interfaceStyleAutomatic => 'Tryb auto'; @override String get interfaceStyleApple => 'Apple'; @@ -206,66 +205,65 @@ class AppLocalizationsPl extends AppLocalizations { String get interfaceStyleMaterial => 'Material'; @override - String get glassQuality => 'Glass Quality'; + String get glassQuality => 'Jakość efektu szkła/rozmycia'; @override String get glassQualitySubtitle => - 'Auto picks the best glass effect for this device. Full forces real blur; Reduced uses a lightweight glass that saves GPU power.'; + 'Automatycznie dobiera najlepszy efekt dla tego urządzenia. Pełny wymusza prawdziwe rozmycie. Zmniejszony korzysta z uproszczonego efektu, oszczędzając GPU.'; @override String get glassQualityAuto => 'Auto'; @override - String get glassQualityFull => 'Full'; + String get glassQualityFull => 'Pełny'; @override - String get glassQualityReduced => 'Reduced'; + String get glassQualityReduced => 'Zmniejszony'; @override String get settingsAppearanceThemeSubtitle => - 'Przełączaj się między Moonfin i Neon Pulse bez ponownego uruchamiania aplikacji'; + 'Zastosuj niestandardowy motyw i przełączaj się między interfejsami.'; @override - String get customThemeTitle => 'Custom Theme'; + String get customThemeTitle => 'Niestandardowy motyw'; @override String get customThemeSubtitle => - 'Custom themes alter visual elements across Moonfin. Choose one of these options to suit your style.'; + 'Niestandardowe motywy zmieniają elementy wizualne całej aplikacji Moonfin. Wybierz jedną z opcji, aby dopasować wygląd do swojego upodobania.'; @override - String get keyboardPreferSystemIme => 'Prefer system keyboard'; + String get keyboardPreferSystemIme => 'Preferuj klawiaturę systemową'; @override String get keyboardPreferSystemImeDescription => - 'Use your device input method by default for text entry'; + 'Używaj systemowej metody wprowadzania tekstu'; @override - String get themeMoonfin => 'Księżycowa Płetwa'; + String get themeMoonfin => 'Moonfin'; @override - String get themeMoonfinSubtitle => - 'Obecny wygląd Moonfin, który wszyscy pokochaliście'; + String get themeMoonfinSubtitle => 'Oryginalny czysty motyw Moonfin.'; @override - String get themeNeonPulse => 'Neonowy puls'; + String get themeNeonPulse => 'Neon Pulse'; @override String get themeNeonPulseSubtitle => - 'Styl Synthwave z magentową poświatą, cyjanowym tekstem i silniejszym kontrastem chromu'; + 'Synthwave z magentową poświatą, cyjanowym tekstem i silniejszym kontrastem chromu'; @override - String get themeGlass => 'Glass'; + String get themeGlass => 'Rozmycie'; @override String get themeGlassSubtitle => - 'Liquid-glass styling with a drifting gradient backdrop, frosted surfaces, and Apple-blue accent'; + 'Liquid-glass z gradientowym tłem, matowymi powierzchniami i akcentem w kolorze Apple-blue'; @override String get theme8BitHero => '8-bit Hero'; @override String get theme8BitHeroSubtitle => - 'Retro pixel-art styling with a chunky palette, blocky borders, hard drop-shadows, and a pixel font'; + 'Retro pikselowy styl z grubą paletą kolorów, kanciastymi ramkami, twardymi cieniami i pikselową czcionką'; @override String get embyConnectSignInSubtitle => @@ -315,7 +313,7 @@ class AppLocalizationsPl extends AppLocalizations { @override String unableToConnectTo(String target) { - return 'Unable to connect to $target'; + return 'Nie można połączyć się z $target'; } @override @@ -331,39 +329,40 @@ class AppLocalizationsPl extends AppLocalizations { String get gameMenu => 'Menu'; @override - String get gamePaused => 'Paused'; + String get gamePaused => 'Wstrzymano'; @override - String get gameSaveState => 'Save state'; + String get gameSaveState => 'Zapisz stan'; @override - String get gameLoadState => 'Load state'; + String get gameLoadState => 'Wczytaj stan'; @override - String get gameFastForward => 'Fast-forward'; + String get gameFastForward => 'Przewijanie do przodu'; @override - String get gameEmulatorSettings => 'Emulator settings'; + String get gameEmulatorSettings => 'Opcje emulatora'; @override - String get gameNoCoreOptions => 'This core has no adjustable options.'; + String get gameNoCoreOptions => + 'Ten rdzeń nie udostępnia żadnych opcji do zastosowania.'; @override - String get gameHoldToOpenMenu => 'Hold to open menu'; + String get gameHoldToOpenMenu => 'Przytrzymaj aby otworzyć menu'; @override String get gamePlaybackUnsupported => - 'Game playback is not supported on this device yet.'; + 'Odtwarzanie gier nie jest jeszcze obsługiwane na tym urządzeniu.'; @override String get noHomeRowsLoaded => 'Nie można wczytać żadnych wierszy głównych'; @override String get noHomeRowsHint => - 'Spróbuj odświeżyć lub zmniejszyć aktywne sekcje strony głównej.'; + 'Spróbuj odświeżyć stronę lub zmniejszyć liczbę aktywnych sekcji na ekranie głównym.'; @override - String get retryHomeRows => 'Ponów próbę wierszy głównych'; + String get retryHomeRows => 'Odśwież wiersze Home'; @override String get guide => 'Przewodnik'; @@ -375,7 +374,7 @@ class AppLocalizationsPl extends AppLocalizations { String get schedule => 'Harmonogram'; @override - String get series => 'Szereg'; + String get series => 'Seriale'; @override String get noItemsFound => 'Nie znaleziono żadnych elementów'; @@ -393,7 +392,7 @@ class AppLocalizationsPl extends AppLocalizations { String get collectionPlaceholder => 'Tutaj pojawią się elementy kolekcji'; @override - String get browseByLetter => 'Przeglądaj według listu'; + String get browseByLetter => 'Alfabetycznie'; @override String get alphabeticalBrowsePlaceholder => @@ -425,7 +424,7 @@ class AppLocalizationsPl extends AppLocalizations { @override String failedToLoadFolderError(String error) { - return 'Failed to load folder: $error'; + return 'Nie udało się wczytać folderu: $error'; } @override @@ -433,14 +432,14 @@ class AppLocalizationsPl extends AppLocalizations { @override String itemCountLabel(int count) { - return '$count items'; + return '$count elementów'; } @override String get failedToLoadFavorites => 'Nie udało się załadować ulubionych'; @override - String get retry => 'Spróbować ponownie'; + String get retry => 'Ponów'; @override String get noFavoritesYet => 'Nie ma jeszcze ulubionych'; @@ -450,11 +449,11 @@ class AppLocalizationsPl extends AppLocalizations { @override String totalCountItems(int count) { - return '$count Items'; + return '$count elementów'; } @override - String get continuing => 'Kontynuacja'; + String get continuing => 'W trakcie'; @override String get ended => 'Zakończone'; @@ -469,7 +468,7 @@ class AppLocalizationsPl extends AppLocalizations { String get sortBy => 'Sortuj według'; @override - String get display => 'Wyświetlacz'; + String get display => 'Wyświetlanie'; @override String get imageType => 'Typ obrazu'; @@ -491,7 +490,7 @@ class AppLocalizationsPl extends AppLocalizations { @override String libraryGenresTitle(String name) { - return '$name — Genres'; + return '$name — Gatunki'; } @override @@ -501,7 +500,7 @@ class AppLocalizationsPl extends AppLocalizations { String get albums => 'Albumy'; @override - String get albumArtists => 'Artyści albumowi'; + String get albumArtists => 'Wykonawcy albumu'; @override String get artists => 'Artyści'; @@ -526,32 +525,32 @@ class AppLocalizationsPl extends AppLocalizations { String get bookmark => 'Zakładka w książce'; @override - String get justNow => 'Właśnie'; + String get justNow => 'Przed chwilą'; @override String minutesAgo(int count) { - return '${count}m ago'; + return '${count}m temu'; } @override String hoursAgo(int count) { - return '${count}h ago'; + return '${count}h temu'; } @override String daysAgo(int count) { - return '${count}d ago'; + return '${count}d temu'; } @override - String get discoverySubjects => 'Przedmioty odkrycia'; + String get discoverySubjects => 'Tematy'; @override String get pickDiscoverySubjects => 'Wybierz kanały tematyczne, które mają być wyświetlane w Discover.'; @override - String get apply => 'Stosować'; + String get apply => 'Zastosuj'; @override String get openLink => 'Otwórz łącze'; @@ -570,12 +569,11 @@ class AppLocalizationsPl extends AppLocalizations { String get discoverAudiobooks => 'Odkryj audiobooki'; @override - String get librivoxDescription => - 'Popularne tytuły domeny publicznej od LibriVox.'; + String get librivoxDescription => 'Popularne tytuły od LibriVox.'; @override String titlesCount(int count) { - return '$count titles'; + return '$count tytułów'; } @override @@ -597,10 +595,10 @@ class AppLocalizationsPl extends AppLocalizations { String get continueListening => 'Kontynuuj słuchanie'; @override - String get listen => 'Słuchać'; + String get listen => 'Słuchaj'; @override - String get resume => 'Wznawiać'; + String get resume => 'Wznów'; @override String get failedToLoadLibrary => 'Nie udało się załadować biblioteki'; @@ -615,10 +613,10 @@ class AppLocalizationsPl extends AppLocalizations { String get topListens => 'Najczęściej słuchane'; @override - String get unreadDiscoveries => 'Nieprzeczytane odkrycia'; + String get unreadDiscoveries => 'Nieprzeczytane propozycje'; @override - String get pickUpAgain => 'Odbierz ponownie'; + String get pickUpAgain => 'Wróć do czytania'; @override String get bookHighlightsDescription => @@ -637,11 +635,11 @@ class AppLocalizationsPl extends AppLocalizations { @override String get jumpBackNarration => - 'Wróć do narracji bez szukania swojego miejsca.'; + 'Wróć dosłuchania bez szukania miejsca, w którym skończyłeś.'; @override String get unreadBooksReady => - 'Nieprzeczytane książki gotowe na następną cichą godzinę.'; + 'Nieprzeczytane książki gotowe na Twoją najbliższą wolną chwilę.'; @override String get quickAccessFavorites => @@ -663,24 +661,24 @@ class AppLocalizationsPl extends AppLocalizations { @override String authorsCount(int count) { - return '$count authors'; + return '$count autorzy'; } @override String genresCount(int count) { - return '$count genres'; + return '$count gatunki'; } @override String percentCompleted(int percent) { - return '$percent% completed'; + return '$percent% ukończone'; } @override - String get readyWhenYouAre => 'Gotowy, kiedy będziesz'; + String get readyWhenYouAre => 'Czekamy, aż zaczniesz'; @override - String get details => 'Bliższe dane'; + String get details => 'Detale'; @override String get listeningRoom => 'Pokój Słuchania'; @@ -690,7 +688,7 @@ class AppLocalizationsPl extends AppLocalizations { @override String titlesArrangedForBrowsing(int count) { - return '$count titles arranged for reading-first browsing.'; + return '$count tytułów dostępnych do przeglądania.'; } @override @@ -700,7 +698,7 @@ class AppLocalizationsPl extends AppLocalizations { String get allTitles => 'Wszystkie tytuły'; @override - String get authors => 'Autorski'; + String get authors => 'Autorzy'; @override String get browseByAuthor => 'Przeglądaj według autora'; @@ -709,7 +707,7 @@ class AppLocalizationsPl extends AppLocalizations { String get browseByGenre => 'Przeglądaj według gatunku'; @override - String get discover => 'Odkryć'; + String get discover => 'Odkrywaj'; @override String get trendingTitlesOpenLibrary => @@ -728,11 +726,11 @@ class AppLocalizationsPl extends AppLocalizations { @override String noLabelFound(String label) { - return 'No $label found'; + return 'Nie znaleziono $label'; } @override - String get folder => 'Falcówka'; + String get folder => 'Folder'; @override String get filters => 'Filtry'; @@ -741,22 +739,22 @@ class AppLocalizationsPl extends AppLocalizations { String get readingStatus => 'Stan czytania'; @override - String get playedStatus => 'Stan gry'; + String get playedStatus => 'Status odtworzenia'; @override - String get readStatus => 'Czytać'; + String get readStatus => 'Czytaj'; @override - String get watched => 'Obejrzałem'; + String get watched => 'Obejrzane'; @override - String get unread => 'Niewykształcony'; + String get unread => 'Nieprzeczytane'; @override - String get unwatched => 'Nieobserwowane'; + String get unwatched => 'Zaznacz jako obejrzane'; @override - String get seriesStatus => 'Stan serii'; + String get seriesStatus => 'Status serialu'; @override String get allLibraries => 'Wszystkie biblioteki'; @@ -765,43 +763,43 @@ class AppLocalizationsPl extends AppLocalizations { String get books => 'Książki'; @override - String get latestBooks => 'Latest Books'; + String get latestBooks => 'Ostatnio dodane książki'; @override - String get latestAudiobooks => 'Latest Audiobooks'; + String get latestAudiobooks => 'Ostatnio dodane Audiobooki'; @override String bookSeriesItemCount(int count) { String _temp0 = intl.Intl.pluralLogic( count, locale: localeName, - other: '$count books', - one: '1 book', + other: '$count książki', + one: '1 książka', ); return '$_temp0'; } @override - String get bookFormatBook => 'Book'; + String get bookFormatBook => 'Książka'; @override String get bookFormatAudiobook => 'Audiobook'; @override String bookPercentRead(int percent) { - return '$percent% read'; + return '$percent% przeczytane'; } @override String bookTimeLeft(String time) { - return '$time left'; + return '$time zostało'; } @override - String get bookHeroRead => 'Read'; + String get bookHeroRead => 'Przeczytane'; @override - String get bookHeroListen => 'Listen'; + String get bookHeroListen => 'Słuchaj'; @override String get author => 'Autor'; @@ -820,7 +818,7 @@ class AppLocalizationsPl extends AppLocalizations { 'LibriVox nie dostarczył jeszcze opisu dla tego tytułu.'; @override - String get readers => 'Czytelnicy'; + String get readers => 'Lektorzy'; @override String get openLinks => 'Otwórz linki'; @@ -839,12 +837,12 @@ class AppLocalizationsPl extends AppLocalizations { @override String sectionCountLabel(int count) { - return '$count sections'; + return '$count sekcji'; } @override String firstPublished(int year) { - return 'First published $year'; + return 'Data pierwszego wydania $year'; } @override @@ -852,14 +850,14 @@ class AppLocalizationsPl extends AppLocalizations { 'W Open Library nie ma jeszcze przeglądu tego tytułu.'; @override - String get subjects => 'Przedmioty'; + String get subjects => 'Tematy'; @override String get all => 'Wszystko'; @override String booksCount(int count) { - return '$count books'; + return '$count książek'; } @override @@ -870,7 +868,7 @@ class AppLocalizationsPl extends AppLocalizations { @override String authorsCountTitle(int count) { - return '$count Authors'; + return '$count Autorów'; } @override @@ -878,7 +876,7 @@ class AppLocalizationsPl extends AppLocalizations { String _temp0 = intl.Intl.pluralLogic( count, locale: localeName, - other: '$count audiobooks', + other: '$count audiobooki', one: '1 audiobook', ); return '$_temp0'; @@ -888,22 +886,22 @@ class AppLocalizationsPl extends AppLocalizations { String get trackList => 'Lista utworów'; @override - String get itemListPlaceholder => 'Tutaj pojawi się lista przedmiotów'; + String get itemListPlaceholder => 'Tutaj pojawi się lista pozycji'; @override String get favoriteTracksPlaceholder => 'Tutaj pojawią się ulubione utwory'; @override - String get failedToLoad => 'Nie udało się załadować'; + String get failedToLoad => 'Nie udało się wczytać'; @override - String get delete => 'Usuwać'; + String get delete => 'Usuń'; @override - String get save => 'Ratować'; + String get save => 'Zapisz'; @override - String get moreLikeThis => 'Więcej takich'; + String get moreLikeThis => 'Więcej podobnych'; @override String get castAndCrew => 'Obsada i ekipa'; @@ -918,22 +916,22 @@ class AppLocalizationsPl extends AppLocalizations { String get nextUp => 'Następny w kolejce'; @override - String get seasons => 'Pory roku'; + String get seasons => 'Sezony'; @override String get chapters => 'Rozdziały'; @override - String get features => 'Cechy'; + String get features => 'Dodatki specjalne'; @override - String get movies => 'Kino'; + String get movies => 'Filmy'; @override - String get musicVideos => 'Music Videos'; + String get musicVideos => 'Teledyski'; @override - String get other => 'Inny'; + String get other => 'Inne'; @override String get discography => 'Dyskografia'; @@ -949,14 +947,14 @@ class AppLocalizationsPl extends AppLocalizations { @override String discNumber(int number) { - return 'Disc $number'; + return 'Płyta $number'; } @override String get biography => 'Biografia'; @override - String get authorDetails => 'Szczegóły autora'; + String get authorDetails => 'O autorze'; @override String get noOverviewAvailable => 'Nie ma jeszcze przeglądu tego tytułu.'; @@ -973,7 +971,7 @@ class AppLocalizationsPl extends AppLocalizations { @override String published(int year) { - return 'Published $year'; + return 'Wydane w $year'; } @override @@ -984,52 +982,52 @@ class AppLocalizationsPl extends AppLocalizations { String _temp0 = intl.Intl.pluralLogic( count, locale: localeName, - other: '$count Seasons', - one: '1 Season', + other: '$count Sezony', + one: '1 Sezon', ); return '$_temp0'; } @override String endsAt(String time) { - return 'Ends at $time'; + return 'Koniec o $time'; } @override - String get items => 'Items'; + String get items => 'Elementy'; @override - String get extras => 'Extras'; + String get extras => 'Dodatki'; @override - String get behindTheScenes => 'Behind the Scenes'; + String get behindTheScenes => 'Kulisy produkcji'; @override - String get deletedScenes => 'Deleted Scenes'; + String get deletedScenes => 'Usunięte sceny'; @override - String get featurettes => 'Featurettes'; + String get featurettes => 'Materiały dodatkowe'; @override - String get interviews => 'Interviews'; + String get interviews => 'Wywiady'; @override - String get scenes => 'Scenes'; + String get scenes => 'Sceny'; @override - String get shorts => 'Shorts'; + String get shorts => 'Krótkie filmy'; @override - String get trailers => 'Trailers'; + String get trailers => 'Zwiastuny'; @override String timeRemaining(String time) { - return '$time remaining'; + return '$time pozostało'; } @override String endsIn(String time) { - return 'Ends in $time'; + return 'Koniec za $time'; } @override @@ -1039,15 +1037,15 @@ class AppLocalizationsPl extends AppLocalizations { String get resumeReading => 'Wznów czytanie'; @override - String get read => 'Czytać'; + String get read => 'Czytaj'; @override String resumeFrom(String position) { - return 'Resume from $position'; + return 'Wznów od $position'; } @override - String get play => 'Grać'; + String get play => 'Włącz'; @override String get startOver => 'Zacznij od nowa'; @@ -1062,22 +1060,22 @@ class AppLocalizationsPl extends AppLocalizations { String get playOffline => 'Graj w trybie offline'; @override - String get audio => 'Audio'; + String get audio => 'Wybierz ścieżkę audio'; @override - String get subtitles => 'Napisy na filmie obcojęzycznym'; + String get subtitles => 'Napisy'; @override String get version => 'Wersja'; @override - String get cast => 'Rzucać'; + String get cast => 'Przesyłaj'; @override - String get trailer => 'Przyczepa'; + String get trailer => 'Zwiastun'; @override - String get finished => 'Gotowy'; + String get finished => 'Ukończono'; @override String get favorited => 'Ulubione'; @@ -1095,7 +1093,7 @@ class AppLocalizationsPl extends AppLocalizations { String get downloadAll => 'Pobierz wszystko'; @override - String get download => 'Pobierać'; + String get download => 'Pobierz'; @override String get deleteDownloaded => 'Usuń pobrane'; @@ -1141,7 +1139,7 @@ class AppLocalizationsPl extends AppLocalizations { @override String deleteDownloadedTracksMessage(String title) { - return 'Delete downloaded tracks for \"$title\"?'; + return 'Usuń pobrany utwór \"$title\"?'; } @override @@ -1156,28 +1154,28 @@ class AppLocalizationsPl extends AppLocalizations { @override String noItemsLoaded(String itemLabel) { - return 'No $itemLabel loaded'; + return 'Nie udało się wczytać $itemLabel'; } @override String downloadingTitle(String title, int count) { - return 'Downloading $title ($count items)...'; + return 'Pobieranie $title ($count elementów)...'; } @override String deleteConfirmMessage(String name) { - return 'Are you sure you want to delete \"$name\" from the server? This action cannot be undone.'; + return 'Napewno chcesz usunąć \"$name\" z serwera? Tego nie można cofnąć.'; } @override String get itemDeleted => 'Element usunięty'; @override - String get noPlayableTrailerFound => 'Nie znaleziono grywalnego zwiastuna.'; + String get noPlayableTrailerFound => 'Nie znaleziono zwiastuna.'; @override String unsupportedBookFormat(String extension) { - return 'Unsupported book format: .$extension'; + return 'NIewspierany format: .$extension'; } @override @@ -1187,14 +1185,13 @@ class AppLocalizationsPl extends AppLocalizations { String get subtitleTrack => 'Ścieżka napisów'; @override - String get none => 'Nic'; + String get none => 'Brak'; @override String get downloadSubtitlesLabel => 'Pobierz napisy...'; @override - String get searchOpenSubtitlesPlugin => - 'Szukaj za pomocą wtyczki OpenSubtitles'; + String get searchOpenSubtitlesPlugin => 'Szukaj z wtyczką OpenSubtitles'; @override String get downloadSubtitles => 'Pobierz napisy'; @@ -1204,7 +1201,7 @@ class AppLocalizationsPl extends AppLocalizations { @override String subtitleDownloadedSelected(String name) { - return 'Subtitle downloaded and selected: $name'; + return 'Napisy pobrane i wybrane: $name'; } @override @@ -1213,15 +1210,15 @@ class AppLocalizationsPl extends AppLocalizations { @override String noRemoteSubtitlesFound(String language) { - return 'No remote subtitles found for $language.'; + return 'Nie znaleziono napisów po $language.'; } @override - String get selectVersion => 'Wybierz opcję Wersja'; + String get selectVersion => 'Wybierz wersję'; @override String versionNumber(int number) { - return 'Version $number'; + return 'Wersja $number'; } @override @@ -1231,19 +1228,17 @@ class AppLocalizationsPl extends AppLocalizations { String get downloadQuality => 'Jakość pobierania'; @override - String get originalFileNoReencoding => - 'Oryginalny plik, bez ponownego kodowania'; + String get originalFileNoReencoding => 'Oryginalny plik'; @override - String get originalFilesNoReencoding => - 'Oryginalne pliki, bez ponownego kodowania'; + String get originalFilesNoReencoding => 'Oryginalne pliki'; @override String get noEpisodesLoaded => 'Nie wczytano żadnych odcinków'; @override String downloadingItem(String name, String quality) { - return 'Downloading $name ($quality)...'; + return 'Pobieranie $name ($quality)...'; } @override @@ -1251,7 +1246,7 @@ class AppLocalizationsPl extends AppLocalizations { @override String deleteLocalFilesMessage(String typeLabel) { - return 'Delete local files for $typeLabel?\n\nThis will free up storage space. You can re-download later.'; + return 'Usuń lokalne pliki $typeLabel?\n\nZwolni to miejsce. Pliki można pobrać ponownie później.'; } @override @@ -1264,28 +1259,28 @@ class AppLocalizationsPl extends AppLocalizations { String get deleteFiles => 'Usuń pliki'; @override - String get director => 'DYREKTOR'; + String get director => 'REŻYSER'; @override - String get directors => 'DIRECTORS'; + String get directors => 'REŻYSERIA'; @override - String get writer => 'WRITER'; + String get writer => 'SCENARIUSZ'; @override - String get writers => 'PISARZE'; + String get writers => 'SCENARIUSZ'; @override String get studio => 'STUDIO'; @override String studioMoreCount(int count) { - return '+$count more'; + return '+$count więcej'; } @override String totalEpisodes(int count) { - return '$count Episodes'; + return '$count odcinków'; } @override @@ -1295,12 +1290,12 @@ class AppLocalizationsPl extends AppLocalizations { @override String episodeLabel(int number) { - return 'Episode $number'; + return 'Odcinek $number'; } @override String chapterNumber(int number) { - return 'Chapter $number'; + return 'Rozdział $number'; } @override @@ -1308,8 +1303,8 @@ class AppLocalizationsPl extends AppLocalizations { String _temp0 = intl.Intl.pluralLogic( count, locale: localeName, - other: '$count tracks', - one: '1 track', + other: '$count utworów', + one: '1 utwór', ); return '$_temp0'; } @@ -1319,48 +1314,48 @@ class AppLocalizationsPl extends AppLocalizations { String _temp0 = intl.Intl.pluralLogic( count, locale: localeName, - other: '$count chapters', - one: '1 chapter', + other: '$count rozdziałów', + one: '1 rozdział', ); return '$_temp0'; } @override String born(String date) { - return 'Born $date'; + return 'Urodziny $date'; } @override String died(String date) { - return 'Died $date'; + return 'Śmierć $date'; } @override String age(int age) { - return 'Age $age'; + return 'Wiek $age'; } @override String get showLess => 'Pokaż mniej'; @override - String get readMore => 'Przeczytaj więcej'; + String get readMore => 'Czytaj więcej'; @override - String get shuffle => 'Człapać'; + String get shuffle => 'Losowo'; @override - String get shuffleAllMusic => 'Shuffle all music'; + String get shuffleAllMusic => 'Odtwarzaj muzykę losowo'; @override - String get carSignInPrompt => 'Sign in to Moonfin on your phone'; + String get carSignInPrompt => 'Zaloguj się do Moonfin na telefonie'; @override - String get carServerUnreachable => 'Can\'t reach your server'; + String get carServerUnreachable => 'Nie można połączyć się z serwerem'; @override String downloadsCount(int count) { - return '$count downloads'; + return '$count pobrań'; } @override @@ -1368,43 +1363,43 @@ class AppLocalizationsPl extends AppLocalizations { @override String channelsCount(int count) { - return '${count}ch'; + return '${count}kanałów'; } @override - String get mono => 'Mononukleoza'; + String get mono => 'Mono'; @override - String get stereo => 'Stereofoniczny'; + String get stereo => 'Stereo'; @override String remoteSubtitlePermissionError(String action) { - return 'Remote subtitle $action requires the Jellyfin subtitle management permission for this user.'; + return 'Wykonanie $action wymaga uprawnienia do zarządzania napisami w Jellyfin dla tego użytkownika.'; } @override String remoteSubtitleNotFoundError(String action) { - return 'This item could not be found on the server for remote subtitle $action.'; + return 'Nie znaleziono na serwerze $action.'; } @override String remoteSubtitleDetailError(String action, String detail) { - return 'Remote subtitle $action failed: $detail'; + return 'Napisy zdalne $action nieudane: $detail'; } @override String remoteSubtitleHttpError(String action, int status) { - return 'Remote subtitle $action failed (HTTP $status).'; + return 'Napisy $action nieudane (HTTP $status).'; } @override String remoteSubtitleGenericError(String action) { - return 'Failed to $action remote subtitles.'; + return 'Nieudane $action napisów.'; } @override String deleteSeriesFiles(String name) { - return 'all downloaded episodes for \"$name\"'; + return 'wszystkie pobrane odcinki \"$name\"'; } @override @@ -1414,12 +1409,10 @@ class AppLocalizationsPl extends AppLocalizations { String get stillWatching => 'Nadal oglądasz?'; @override - String get unableToLoadTrailerStream => - 'Nie można załadować strumienia zwiastuna.'; + String get unableToLoadTrailerStream => 'Nie można wczytać zwiastuna.'; @override - String get trailerTimedOut => - 'Przekroczono limit czasu przyczepy podczas ładowania.'; + String get trailerTimedOut => 'Przekroczono limit czasu ładowania zwiastuna.'; @override String get playbackFailedForTrailer => @@ -1436,24 +1429,24 @@ class AppLocalizationsPl extends AppLocalizations { @override String castActionFailed(String label, String error) { - return '$label action failed: $error'; + return '$label nieudane: $error'; } @override String failedToSetCastVolume(String error) { - return 'Failed to set cast volume: $error'; + return 'Nieudane przesyłanie głośności: $error'; } @override String castControlsTitle(String label) { - return '$label Controls'; + return '$label Sterowanie'; } @override String get deviceVolume => 'Głośność urządzenia'; @override - String get unavailable => 'Nie płynny'; + String get unavailable => 'Niedostępne'; @override String get pause => 'Pauza'; @@ -1471,11 +1464,11 @@ class AppLocalizationsPl extends AppLocalizations { @override String trackNumber(int number) { - return 'Track $number'; + return 'Utwór $number'; } @override - String get remotePlayback => 'Zdalne odtwarzanie'; + String get remotePlayback => 'Odtwarzanie zdalne'; @override String get castingToGoogleCast => 'Przesyłanie do Google Cast'; @@ -1488,14 +1481,14 @@ class AppLocalizationsPl extends AppLocalizations { @override String secondsCount(int seconds) { - return '$seconds seconds'; + return '$seconds s'; } @override - String get longPressToUnlock => 'Naciśnij długo, aby odblokować'; + String get longPressToUnlock => 'Przytrzymaj, aby odblokować'; @override - String get off => 'Wyłączony'; + String get off => 'Wyłączone'; @override String streamTypeFallback(String streamType, int number) { @@ -1503,7 +1496,7 @@ class AppLocalizationsPl extends AppLocalizations { } @override - String get auto => 'Automatyczny'; + String get auto => 'Auto'; @override String bitrateValueMbps(int mbps) { @@ -1511,7 +1504,7 @@ class AppLocalizationsPl extends AppLocalizations { } @override - String get bitrateOverride => 'Zastąpienie szybkości transmisji'; + String get bitrateOverride => 'Wymuszony bitrate'; @override String get audioDelay => 'Opóźnienie dźwięku'; @@ -1530,22 +1523,22 @@ class AppLocalizationsPl extends AppLocalizations { String get subtitleDelay => 'Opóźnienie napisów'; @override - String get reset => 'Nastawić'; + String get reset => 'Resetuj'; @override - String get unknown => 'Nieznany'; + String get unknown => 'Nieznane'; @override String get playbackInformation => 'Informacje o odtwarzaniu'; @override - String get playback => 'Odtwarzanie nagranego dźwięku'; + String get playback => 'Odtwarzanie'; @override String get playMethod => 'Metoda odtwarzania'; @override - String get directPlay => 'Gra bezpośrednia'; + String get directPlay => 'Odtwarzanie bezpośrednie'; @override String get directStream => 'Bezpośredni strumień'; @@ -1560,7 +1553,7 @@ class AppLocalizationsPl extends AppLocalizations { String get player => 'Odtwarzacz'; @override - String get container => 'Pojemnik'; + String get container => 'Kontener'; @override String get bitrate => 'Szybkość transmisji'; @@ -1569,7 +1562,7 @@ class AppLocalizationsPl extends AppLocalizations { String get video => 'Wideo'; @override - String get resolution => 'Rezolucja'; + String get resolution => 'Rozdzielczość'; @override String get hdr => 'HDR'; @@ -1578,7 +1571,7 @@ class AppLocalizationsPl extends AppLocalizations { String get codec => 'Kodek'; @override - String get videoBitrate => 'Szybkość transmisji wideo'; + String get videoBitrate => 'Bitrate wideo'; @override String get track => 'Ścieżka'; @@ -1587,10 +1580,10 @@ class AppLocalizationsPl extends AppLocalizations { String get channels => 'Kanały'; @override - String get audioBitrate => 'Szybkość transmisji dźwięku'; + String get audioBitrate => 'Bitrate dźwięku'; @override - String get sampleRate => 'Częstotliwość próbkowania'; + String get sampleRate => 'Częstotliwość audio'; @override String get format => 'Format'; @@ -1603,12 +1596,12 @@ class AppLocalizationsPl extends AppLocalizations { @override String castSessionError(String protocol) { - return '$protocol session error'; + return '$protocol błąd sesji'; } @override String failedToLoadBookDetails(String error) { - return 'Failed to load book details: $error'; + return 'Nie udało się wczytać informacji o książce: $error'; } @override @@ -1617,7 +1610,7 @@ class AppLocalizationsPl extends AppLocalizations { @override String formatCannotRenderInApp(String extension) { - return 'This format (.$extension) cannot be rendered in-app yet.'; + return 'Ten format (.$extension) nie jest jeszcze obsługiwany.'; } @override @@ -1630,17 +1623,17 @@ class AppLocalizationsPl extends AppLocalizations { @override String failedToOpenInAppReader(String error) { - return 'Failed to open in-app reader: $error'; + return 'Nie udało się otworzyć czytnika w aplikacji: $error'; } @override String bookmarkAlreadySaved(String label) { - return 'Bookmark already saved at $label.'; + return 'Zakładka już zapisana w $label.'; } @override String bookmarkAdded(String label) { - return 'Bookmark added: $label'; + return 'Zakładka dodana: $label'; } @override @@ -1652,14 +1645,14 @@ class AppLocalizationsPl extends AppLocalizations { @override String pageLabel(int number) { - return 'Page $number'; + return 'Strona $number'; } @override String get position => 'Pozycja'; @override - String get bookReader => 'Czytelnik książek'; + String get bookReader => 'Czytnik książek'; @override String formatExtension(String extension) { @@ -1668,7 +1661,7 @@ class AppLocalizationsPl extends AppLocalizations { @override String percentRead(String percent) { - return '$percent% read'; + return '$percent% przeczytane'; } @override @@ -1692,14 +1685,14 @@ class AppLocalizationsPl extends AppLocalizations { @override String resetZoom(String zoom) { - return 'Reset Zoom (${zoom}x)'; + return 'Reset powiększenia (${zoom}x)'; } @override String get singlePage => 'Pojedyncza strona'; @override - String get twoPageSpread => 'Rozkładówka dwustronicowa'; + String get twoPageSpread => 'Widok dwustronnicowy'; @override String get addBookmark => 'Dodaj zakładkę'; @@ -1715,20 +1708,20 @@ class AppLocalizationsPl extends AppLocalizations { @override String failedToUpdateReadState(String error) { - return 'Failed to update read state: $error'; + return 'Nie udało się zaktualizować stanu czytania: $error'; } @override - String get themeSystem => 'Temat: System'; + String get themeSystem => 'Styl: Systemowy'; @override - String get themeLight => 'Temat: Światło'; + String get themeLight => 'Styl: Jasny'; @override - String get themeDark => 'Temat: Ciemność'; + String get themeDark => 'Styl: Ciemny'; @override - String get themeSepia => 'Temat: Sepia'; + String get themeSepia => 'Styl: Sepia'; @override String get invertColorsFixedLayout => 'Odwróć kolory (stały układ)'; @@ -1747,7 +1740,7 @@ class AppLocalizationsPl extends AppLocalizations { @override String platformCannotHostDocumentEngine(String extension) { - return 'This platform cannot host the embedded document engine for $extension files.'; + return 'Ta platforma nie obsługuje wbudowanego silnika $extension plików.'; } @override @@ -1770,10 +1763,10 @@ class AppLocalizationsPl extends AppLocalizations { String get now => 'Teraz'; @override - String get sports => 'Lekkoatletyka'; + String get sports => 'Sport'; @override - String get news => 'Aktualności'; + String get news => 'Wiadomości'; @override String get kids => 'Dzieci'; @@ -1786,7 +1779,7 @@ class AppLocalizationsPl extends AppLocalizations { @override String failedToLoadGuide(String error) { - return 'Failed to load guide: $error'; + return 'Nie udało sie załadować przewodnika: $error'; } @override @@ -1797,22 +1790,22 @@ class AppLocalizationsPl extends AppLocalizations { @override String guideNextProgram(String time, String title) { - return 'Next: $time $title'; + return 'Następny: $time $title'; } @override String guideMinutesLeft(int minutes) { - return '${minutes}m left'; + return '${minutes}m zostało'; } @override String guideHoursLeft(int hours) { - return '${hours}h left'; + return '${hours}h zostało'; } @override String guideHoursMinutesLeft(int hours, int minutes) { - return '${hours}h ${minutes}m left'; + return '${hours}h ${minutes}m zostało'; } @override @@ -1835,29 +1828,29 @@ class AppLocalizationsPl extends AppLocalizations { String get favoriteChannel => 'Ulubiony kanał'; @override - String get record => 'Record'; + String get record => 'Nagrywaj'; @override - String get cancelRecordingAction => 'Cancel Recording'; + String get cancelRecordingAction => 'Anuluj nagrywanie'; @override - String get programSetToRecord => 'Program set to record'; + String get programSetToRecord => 'Nagrywanie zaplanowane'; @override - String get recordingCancelled => 'Recording cancelled'; + String get recordingCancelled => 'Nagrywanie anulowane'; @override - String get unableToCreateRecording => 'Unable to create recording'; + String get unableToCreateRecording => 'Nie udało się włączyć nagrywania'; @override - String get watch => 'Oglądać'; + String get watch => 'Oglądaj'; @override - String get close => 'Zamknąć'; + String get close => 'Zamknij'; @override String failedToPlayChannel(String name) { - return 'Failed to play $name'; + return 'Nie można włączyć $name'; } @override @@ -1884,7 +1877,7 @@ class AppLocalizationsPl extends AppLocalizations { @override String cancelScheduledRecordingOf(String name) { - return 'Cancel scheduled recording of \"$name\"?'; + return 'Anulować zaplanowane nagrywanie \"$name\"?'; } @override @@ -1911,7 +1904,7 @@ class AppLocalizationsPl extends AppLocalizations { @override String stopRecordingName(String name) { - return 'Stop recording \"$name\"?'; + return 'Zakończ nagrywanie \"$name\"?'; } @override @@ -1926,12 +1919,12 @@ class AppLocalizationsPl extends AppLocalizations { @override String noResultsForQuery(String query) { - return 'No results for \"$query\"'; + return 'Brak wyników dla \"$query\"'; } @override String searchFailedError(String error) { - return 'Search failed: $error'; + return 'Wyszukiwanie nieudane: $error'; } @override @@ -1968,16 +1961,16 @@ class AppLocalizationsPl extends AppLocalizations { String get browseLibrary => 'Przeglądaj bibliotekę'; @override - String get deleteDownload => 'Usuń pobieranie'; + String get deleteDownload => 'Usuń pobrany plik'; @override String removeItemAndFiles(String name) { - return 'Remove \"$name\" and its files?'; + return 'Usuń \"$name\" wraz z plikami?'; } @override String tracksCount(int count) { - return '$count tracks'; + return '$count utworów'; } @override @@ -1988,12 +1981,12 @@ class AppLocalizationsPl extends AppLocalizations { @override String failedToLoadAlbum(String error) { - return 'Failed to load album: $error'; + return 'Nie udało sie załadować albumu: $error'; } @override String noDownloadedTracksForAlbum(String name) { - return 'No downloaded tracks found for $name.'; + return 'Nie znaleziono pobranych utworów dla $name.'; } @override @@ -2010,7 +2003,7 @@ class AppLocalizationsPl extends AppLocalizations { @override String removeName(String name) { - return 'Remove \"$name\"?'; + return 'Usunąć \"$name\"?'; } @override @@ -2020,12 +2013,12 @@ class AppLocalizationsPl extends AppLocalizations { @override String seasonEpisodeLabel(int season, int episode) { - return 'S$season E$episode'; + return 'S$season O$episode'; } @override String episodeNumber(int number) { - return 'Episode $number'; + return 'Odcinek $number'; } @override @@ -2039,7 +2032,7 @@ class AppLocalizationsPl extends AppLocalizations { @override String seasonNumber(int number) { - return 'Season $number'; + return 'Sezon $number'; } @override @@ -2048,14 +2041,14 @@ class AppLocalizationsPl extends AppLocalizations { } @override - String get specials => 'Promocje'; + String get specials => 'Odcinki specjalne'; @override String get deleteSeason => 'Usuń sezon'; @override String deleteAllEpisodesInSeason(String season) { - return 'Delete all downloaded episodes in $season?'; + return 'Usunąć wszystkie pobrane odcinki w $season?'; } @override @@ -2063,23 +2056,23 @@ class AppLocalizationsPl extends AppLocalizations { String _temp0 = intl.Intl.pluralLogic( count, locale: localeName, - other: '$count episodes', - one: '1 episode', + other: '$count odcinki', + one: '1 odcinek', ); return '$_temp0'; } @override - String get storageManagement => 'Zarządzanie pamięcią masową'; + String get storageManagement => 'Zarządzanie pamięcią'; @override - String get storageBreakdown => 'Podział magazynu'; + String get storageBreakdown => 'Podział pamięci'; @override String get downloadedItems => 'Pobrane elementy'; @override - String get storageLimit => 'Limit przechowywania'; + String get storageLimit => 'Limit pamięci'; @override String get noLimit => 'Bez limitu'; @@ -2099,7 +2092,7 @@ class AppLocalizationsPl extends AppLocalizations { @override String deleteSelectedCount(int count) { - return 'Delete $count downloaded items?'; + return 'Usunąć $count pobranych elementów?'; } @override @@ -2113,7 +2106,7 @@ class AppLocalizationsPl extends AppLocalizations { @override String ofStorageLimit(String limit) { - return 'of $limit limit'; + return 'z $limit limitu'; } @override @@ -2139,21 +2132,20 @@ class AppLocalizationsPl extends AppLocalizations { String get contentRatingRestrictions => 'Ograniczenia dotyczące oceny treści'; @override - String get bitRateResolutionBehavior => - 'Szybkość transmisji, rozdzielczość, zachowanie'; + String get bitRateResolutionBehavior => 'Bitrate, rozdzielczość, zachowanie'; @override String get languageSizeAppearance => 'Język, rozmiar, wygląd'; @override - String get qualityStorage => 'Jakość, magazyn'; + String get qualityStorage => 'Jakość, pamięć'; @override String get serverSyncAndPluginStatus => - 'Synchronizacja serwera i stan wtyczki'; + 'Synchronizacja z serwerem i status wtyczek'; @override - String get mediaRequestIntegration => 'Integracja żądań mediów'; + String get mediaRequestIntegration => 'Integracja żądań multimediów'; @override String get switchServer => 'Przełącz serwer'; @@ -2190,7 +2182,7 @@ class AppLocalizationsPl extends AppLocalizations { String get integrations => 'Integracje'; @override - String get pluginAndRequests => 'Wtyczka i żądania'; + String get pluginAndRequests => 'Wtyczki i żądania'; @override String get customizeAccountPlaybackInterface => @@ -2198,23 +2190,23 @@ class AppLocalizationsPl extends AppLocalizations { @override String optionsCount(int count) { - return '$count options'; + return '$count opcji'; } @override String get themeAndAppearance => 'Motyw i wygląd'; @override - String get focusBorderColor => 'Kolor obramowania ostrości'; + String get focusBorderColor => 'Kolor obramowania fokusu'; @override - String get watchedIndicators => 'Obserwowane wskaźniki'; + String get watchedIndicators => 'Wskaźniki obejrzanych'; @override String get always => 'Zawsze'; @override - String get hideUnwatched => 'Ukryj nieobserwowane'; + String get hideUnwatched => 'Ukryj nieobejrzane'; @override String get episodesOnly => 'Tylko odcinki'; @@ -2223,37 +2215,38 @@ class AppLocalizationsPl extends AppLocalizations { String get never => 'Nigdy'; @override - String get focusExpansionAnimation => 'Animacja rozwijania ostrości'; + String get focusExpansionAnimation => 'Animacja powiększenia przy fokusie'; @override - String get desktopUiScale => 'Skala interfejsu użytkownika pulpitu'; + String get desktopUiScale => 'Skalowanie interfejsu'; @override String get scaleFocusedCards => - 'Skaluj skupione lub najechane karty i kafelki'; + 'Skaluj karty i kafelki po najechaniu lub zaznaczeniu'; @override - String get backgroundBackdrops => 'Tła Tła'; + String get backgroundBackdrops => 'Tła w tle'; @override String get showBackdropImages => 'Pokaż obrazy tła za treścią'; @override - String get seriesThumbnails => 'Miniatury serii'; + String get seriesThumbnails => 'Wyświetlaj miniatury seriali'; @override String get seriesThumbnailsDescription => - 'Tylko odcinki: użyj grafiki serialu odpowiadającej typowi obrazu w każdym wierszu'; + 'Dla seriali używaj głównej grafiki serialu zamiast miniatury odcinka.'; @override - String get homeRowInfoOverlay => 'Nakładka informacyjna wiersza głównego'; + String get homeRowInfoOverlay => + 'Nakładka informacyjna w wierszu ekranu głównego'; @override String get showTitleMetadataOnHomeRows => - 'Pokaż tytuł i metadane podczas przeglądania wierszy głównych'; + 'Pokazuj tytuł i metadane podczas przeglądania wierszy ekranu głównego'; @override - String get clockDisplay => 'Wyświetlacz zegara'; + String get clockDisplay => 'Wyświetlaj zegar'; @override String get inMenus => 'W Menu'; @@ -2292,7 +2285,7 @@ class AppLocalizationsPl extends AppLocalizations { @override String get themeMusicSettingsSubtitle => - 'Detail pages, home rows, and volume'; + 'Strony szczegółów, wiersze ekranu głównego i głośność'; @override String percentValue(int value) { @@ -2300,21 +2293,22 @@ class AppLocalizationsPl extends AppLocalizations { } @override - String get themeMusicOnHomeRows => 'Motyw muzyczny w rzędach domowych'; + String get themeMusicOnHomeRows => + 'Muzyka motywu w wierszach ekranu głównego'; @override String get playWhenBrowsingHomeScreen => - 'Odtwórz podczas przeglądania ekranu głównego'; + 'Odtwarzaj podczas przeglądania ekranu głównego'; @override - String get loopThemeMusic => 'Loop Theme Music'; + String get loopThemeMusic => 'Odtwarzaj muzykę motywu w pętli'; @override String get loopThemeMusicSubtitle => - 'Repeat the track instead of playing it once'; + 'Powtarzaj utwór zamiast odtworzyć go raz'; @override - String get detailsBackgroundBlur => 'Szczegóły Rozmycie tła'; + String get detailsBackgroundBlur => 'Rozmycie tła na stronie szczegółów'; @override String pixelValue(int value) { @@ -2322,120 +2316,119 @@ class AppLocalizationsPl extends AppLocalizations { } @override - String get browsingBackgroundBlur => 'Przeglądanie rozmycia tła'; + String get browsingBackgroundBlur => 'Rozmycie tła podczas przeglądania'; @override - String get maxStreamingBitrate => - 'Maksymalna szybkość transmisji strumieniowej'; + String get maxStreamingBitrate => 'Maksymalny bitrate strumieniowania'; @override String get maxResolution => 'Maksymalna rozdzielczość'; @override - String get playerZoomMode => 'Tryb powiększenia gracza'; + String get playerZoomMode => 'Tryb powiększenia odtwarzacza'; @override - String get settingsScrollWheelAction => 'Mouse scroll wheel'; + String get settingsScrollWheelAction => 'Kółko przewijania myszy'; @override String get settingsScrollWheelActionDescription => - 'Choose what scrolling the mouse wheel over the video does during playback.'; + 'Wybierz, co robi przewijanie kółkiem myszy nad wideo podczas odtwarzania.'; @override - String get scrollWheelActionOff => 'Off'; + String get scrollWheelActionOff => 'Wyłączone'; @override - String get scrollWheelActionSeek => 'Seek (forward / back)'; + String get scrollWheelActionSeek => 'Przewijanie (do przodu / do tyłu)'; @override - String get scrollWheelActionVolume => 'Volume'; + String get scrollWheelActionVolume => 'Głośność'; @override - String get playerTooltipVolume => 'Volume'; + String get playerTooltipVolume => 'Głośność'; @override - String get fit => 'Pasować'; + String get fit => 'Dopasuj'; @override - String get autoCrop => 'Automatyczne przycinanie'; + String get autoCrop => 'Automatyczne dopasowanie'; @override - String get stretch => 'Rozciągać się'; + String get stretch => 'Rozciągnij'; @override - String get refreshRateSwitching => 'Przełączanie częstotliwości odświeżania'; + String get refreshRateSwitching => 'Zmiana częstotliwości odświeżania'; @override String get disabled => 'Wyłączony'; @override - String get scaleOnTv => 'Skala w telewizji'; + String get scaleOnTv => 'Skaluj na TV'; @override String get scaleOnDevice => 'Skaluj na urządzeniu'; @override - String get trickPlay => 'Zabawa w sztuczki'; + String get trickPlay => 'Podgląd klatek (Trick Play)'; @override String get showPreviewThumbnailsWhenSeeking => - 'Pokaż miniatury podglądu podczas wyszukiwania'; + 'Pokazuj podgląd klatek podczas przewijania'; @override - String get showDescriptionOnPause => 'Pokaż opis w trybie pauzy'; + String get showDescriptionOnPause => 'Pokazuj opis podczas pauzy'; @override String get dimVideoShowOverview => - 'Przyciemnij wideo i pokaż tekst przeglądu podczas pauzy'; + 'Przyciemnij wideo i pokazuj opis podczas pauzy'; @override String get osdLockButton => 'Przycisk blokady OSD'; @override String get osdLockButtonDescription => - 'Pokaż przycisk blokady, który blokuje wprowadzanie dotykowe do momentu długiego naciśnięcia'; + 'Pokazuj przycisk blokady, który blokuje dotyk do czasu długiego naciśnięcia'; @override - String get audioBehavior => 'Zachowanie dźwiękowe'; + String get audioBehavior => 'Zachowanie dźwięku'; @override String get downmixToStereo => 'Zmiksuj do stereo'; @override - String get defaultAudioLanguage => 'Domyślny język dźwięku'; + String get defaultAudioLanguage => 'Domyślny język audio'; @override - String get fallbackAudioLanguage => 'Fallback Audio Language'; + String get fallbackAudioLanguage => 'Zapasowy język audio'; @override - String get preferDefaultAudioTrack => 'Prefer Default Audio Track'; + String get preferDefaultAudioTrack => 'Preferuj domyślną ścieżkę audio'; @override String get preferDefaultAudioTrackDescription => - 'Prefer original audio track over localized dub.'; + 'Preferuj oryginalną ścieżkę audio zamiast dubbingu.'; @override - String get preferAudioDescription => 'Prefer Audio Description Tracks'; + String get preferAudioDescription => 'Preferuj ścieżki audiodeskrypcji'; @override String get preferAudioDescriptionDescription => - 'Prefer audio description tracks over normal tracks.'; + 'Preferuj ścieżki audiodeskrypcji zamiast zwykłych ścieżek.'; @override - String get transcodingAudio => 'Transcoding (Audio)'; + String get transcodingAudio => 'Transkodowanie (audio)'; @override - String get directStreamRemux => 'Direct Stream (Remux)'; + String get directStreamRemux => 'Strumieniowanie bezpośrednie (remux)'; @override String get transcodingBitrateOrResolution => - 'Transcoding (Bitrate or Resolution)'; + 'Transkodowanie (bitrate lub rozdzielczość)'; @override - String get transcodingVideoAndAudio => 'Transcoding (Video & Audio)'; + String get transcodingVideoAndAudio => 'Transkodowanie (wideo i audio)'; @override - String get transcodingVideo => 'Transcoding (Video)'; + String get transcodingVideo => 'Transkodowanie (wideo)'; @override String get autoServerDefault => 'Automatycznie (domyślne ustawienie serwera)'; @@ -2480,7 +2473,7 @@ class AppLocalizationsPl extends AppLocalizations { String get dutch => 'Holenderski'; @override - String get swedish => 'szwedzki'; + String get swedish => 'Szwedzki'; @override String get norwegian => 'norweski'; @@ -2505,34 +2498,35 @@ class AppLocalizationsPl extends AppLocalizations { @override String get enableDtsPassthrough => - 'Tylko dźwięk Bitstream DTS do AVR; wymaga obsługi odbiornika i ścieżki źródłowej DTS'; + 'Przesyłaj strumień DTS bezpośrednio (bitstream) do amplitunera; wymaga obsługi przez amplituner oraz źródłowej ścieżki DTS'; @override String get enableTrueHdAudio => 'Włącz dźwięk TrueHD (może nie działać na wszystkich platformach)'; @override - String get settingsAudioOutputMode => 'Audio Output Mode'; + String get settingsAudioOutputMode => 'Tryb wyjścia audio'; @override String get settingsAudioOutputModeDescription => - 'Choose how audio is decoded. AVR Passthrough sends raw Dolby/DTS streams to your receiver; Auto or Downmix decodes locally.'; + 'Wybierz sposób dekodowania audio. Passthrough do amplitunera przesyła surowy strumień Dolby/DTS; tryb Automatyczny lub Downmix dekoduje lokalnie.'; @override String get settingsAudioOutputModeAvrPassthrough => 'AVR Passthrough'; @override - String get settingsAudioFallbackCodec => 'Audio Fallback Codec'; + String get settingsAudioFallbackCodec => 'Zapasowy kodek audio'; @override String get settingsAudioFallbackCodecDescription => - 'Select the target format to transcode multi-channel audio when the source stream cannot be direct-played or passed through.'; + 'Wybierz format docelowy do transkodowania dźwięku wielokanałowego, gdy strumień źródłowy nie może zostać odtworzony bezpośrednio ani przesłany przez passthrough.'; @override - String get settingsAudioFallbackCodecAuto => 'Auto Detect\n(Recommended)'; + String get settingsAudioFallbackCodecAuto => + 'Wykrywanie automatyczne\n(zalecane)'; @override - String get settingsAudioFallbackCodecAac => 'AAC\n(Default)'; + String get settingsAudioFallbackCodecAac => 'AAC\n(Domyślnie)'; @override String get settingsAudioFallbackCodecAc3 => 'AC3\n(Dolby Digital)'; @@ -2544,23 +2538,24 @@ class AppLocalizationsPl extends AppLocalizations { String get settingsAudioFallbackCodecTrueHd => 'TrueHD\n(Lossless)'; @override - String get settingsAudioFallbackCodecMp3 => 'MP3\n(Stereo Only)'; + String get settingsAudioFallbackCodecMp3 => 'MP3\n(Stereo)'; @override - String get settingsAudioFallbackCodecOpus => 'Opus\n(Efficient)'; + String get settingsAudioFallbackCodecOpus => 'Opus\n(Wydajny)'; @override - String get settingsAudioFallbackCodecFlac => 'FLAC\n(Lossless)'; + String get settingsAudioFallbackCodecFlac => 'FLAC\n(Bezstratny)'; @override - String get settingsMaxAudioChannels => 'Max Audio Channels'; + String get settingsMaxAudioChannels => 'Maksymalna liczba kanałów audio'; @override String get settingsMaxAudioChannelsDescription => - 'Configure the maximum channels of your audio setup. Multichannel streams exceeding this limit will downmix or transcode.'; + 'Skonfiguruj maksymalną liczbę kanałów obsługiwaną przez Twój zestaw audio. Strumienie wielokanałowe przekraczające ten limit zostaną zmiksowane w dół lub transkodowane.'; @override - String get settingsMaxAudioChannelsAuto => 'Auto Detect\n(Hardware Default)'; + String get settingsMaxAudioChannelsAuto => + 'Wykrywanie automatyczne\n(domyślne sprzętowe)'; @override String get settingsMaxAudioChannelsMono => '1.0 Mono'; @@ -2587,36 +2582,36 @@ class AppLocalizationsPl extends AppLocalizations { String get settingsMaxAudioChannels7_1 => '7.1 Surround'; @override - String get settingsAudioPassthroughAdvanced => 'Passthrough (Advanced)'; + String get settingsAudioPassthroughAdvanced => 'Passthrough (zaawansowane)'; @override - String get settingsAudioCodecPassthrough => 'Codec Passthrough'; + String get settingsAudioCodecPassthrough => 'Passthrough kodeka'; @override String get settingsAudioCodecPassthroughDescription => - 'Enable only formats your AVR or HDMI sink supports.'; + 'Włączaj tylko formaty obsługiwane przez Twój amplituner lub odbiornik HDMI.'; @override - String get settingsAudioEac3Passthrough => 'EAC3 Passthrough'; + String get settingsAudioEac3Passthrough => 'EAC3 przejście'; @override - String get settingsAudioEac3JocPassthrough => 'EAC3 JOC (Atmos) Passthrough'; + String get settingsAudioEac3JocPassthrough => 'EAC3 JOC (Atmos) przejście'; @override - String get settingsAudioDtsCorePassthrough => 'DTS Core Passthrough'; + String get settingsAudioDtsCorePassthrough => 'DTS Core przejście'; @override - String get settingsAudioDtsHdPassthrough => 'DTS-HD MA Passthrough'; + String get settingsAudioDtsHdPassthrough => 'DTS-HD MA przejście'; @override - String get settingsAudioTrueHdPassthrough => 'TrueHD Passthrough'; + String get settingsAudioTrueHdPassthrough => 'TrueHD przejście'; @override - String get settingsAudioTrueHdAtmosPassthrough => 'TrueHD Atmos Passthrough'; + String get settingsAudioTrueHdAtmosPassthrough => 'TrueHD Atmos przejście'; @override String get settingsAudioBitstreamEac3ToExternalDecoder => - 'Bitstream Dolby Digital Plus (EAC3) to external decoder.'; + 'Przesyłaj strumień Dolby Digital Plus (EAC3) bezpośrednio do zewnętrznego dekodera.'; @override String get settingsAudioBitstreamEac3JocToExternalDecoder => @@ -2665,7 +2660,7 @@ class AppLocalizationsPl extends AppLocalizations { String get settingsAudioRouteSpeaker => 'Speaker'; @override - String get settingsAudioRouteHeadphones => 'Headphones'; + String get settingsAudioRouteHeadphones => 'Słuchawki'; @override String settingsAudioPcmChannels(int count) { @@ -2844,31 +2839,31 @@ class AppLocalizationsPl extends AppLocalizations { String get subtitleCustomizationDescription => 'Dostosuj wygląd napisów'; @override - String get subtitleMode => 'Subtitle Mode'; + String get subtitleMode => 'Tryb napisów'; @override - String get subtitleModeFlagged => 'Flagged'; + String get subtitleModeFlagged => 'Oznaczone'; @override - String get subtitleModeAlways => 'Always'; + String get subtitleModeAlways => 'Zawsze'; @override - String get subtitleModeForeign => 'Foreign'; + String get subtitleModeForeign => 'W innym języku'; @override - String get subtitleModeForced => 'Forced'; + String get subtitleModeForced => 'Wymuszone'; @override String get subtitleModeFlaggedDescription => - 'Plays tracks internally flagged in the media file\'s metadata as \"default\" or \"forced\".'; + 'Odtwarza ścieżki oznaczone w metadanych pliku jako „domyślne” lub „wymuszone”.'; @override String get subtitleModeAlwaysDescription => - 'Automatically loads and displays subtitles every time a video starts.'; + 'Automatycznie wczytuj i wyświetlaj napisy przy każdym uruchomieniu wideo.'; @override String get subtitleModeForeignDescription => - 'Automatically turns on subtitles if the default audio track is in a foreign language.'; + 'Automatycznie włącza napisy, jeśli domyślna ścieżka audio jest w innym języku niż wybrany.'; @override String get subtitleModeForcedDescription => @@ -9932,4 +9927,50 @@ class AppLocalizationsPl extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_pt.dart b/lib/l10n/app_localizations_pt.dart index 5c280b403..6932082f1 100644 --- a/lib/l10n/app_localizations_pt.dart +++ b/lib/l10n/app_localizations_pt.dart @@ -9951,6 +9951,52 @@ class AppLocalizationsPt extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } /// The translations for Portuguese, as used in Brazil (`pt_BR`). diff --git a/lib/l10n/app_localizations_ro.dart b/lib/l10n/app_localizations_ro.dart index 1db2adb71..89251e2ff 100644 --- a/lib/l10n/app_localizations_ro.dart +++ b/lib/l10n/app_localizations_ro.dart @@ -9935,4 +9935,50 @@ class AppLocalizationsRo extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_ru.dart b/lib/l10n/app_localizations_ru.dart index 994431786..36c53d53c 100644 --- a/lib/l10n/app_localizations_ru.dart +++ b/lib/l10n/app_localizations_ru.dart @@ -9941,4 +9941,50 @@ class AppLocalizationsRu extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_si.dart b/lib/l10n/app_localizations_si.dart index 6b7cd74f4..21e2308cf 100644 --- a/lib/l10n/app_localizations_si.dart +++ b/lib/l10n/app_localizations_si.dart @@ -9877,4 +9877,50 @@ class AppLocalizationsSi extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_sk.dart b/lib/l10n/app_localizations_sk.dart index f36f18fbc..20cec384b 100644 --- a/lib/l10n/app_localizations_sk.dart +++ b/lib/l10n/app_localizations_sk.dart @@ -9922,4 +9922,50 @@ class AppLocalizationsSk extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_sl.dart b/lib/l10n/app_localizations_sl.dart index 9ba1696a5..b860c26b4 100644 --- a/lib/l10n/app_localizations_sl.dart +++ b/lib/l10n/app_localizations_sl.dart @@ -9919,4 +9919,50 @@ class AppLocalizationsSl extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_sq.dart b/lib/l10n/app_localizations_sq.dart index b2818ac09..4ef6d5713 100644 --- a/lib/l10n/app_localizations_sq.dart +++ b/lib/l10n/app_localizations_sq.dart @@ -9950,4 +9950,50 @@ class AppLocalizationsSq extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_sr.dart b/lib/l10n/app_localizations_sr.dart index ceab9781f..be2791cbf 100644 --- a/lib/l10n/app_localizations_sr.dart +++ b/lib/l10n/app_localizations_sr.dart @@ -9916,4 +9916,50 @@ class AppLocalizationsSr extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_sv.dart b/lib/l10n/app_localizations_sv.dart index 6020173ed..f48d7a49a 100644 --- a/lib/l10n/app_localizations_sv.dart +++ b/lib/l10n/app_localizations_sv.dart @@ -9901,4 +9901,50 @@ class AppLocalizationsSv extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_sw.dart b/lib/l10n/app_localizations_sw.dart index 6ca4d0fc6..6b24f3bb3 100644 --- a/lib/l10n/app_localizations_sw.dart +++ b/lib/l10n/app_localizations_sw.dart @@ -9942,4 +9942,50 @@ class AppLocalizationsSw extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_ta.dart b/lib/l10n/app_localizations_ta.dart index 96ad71a30..792dda820 100644 --- a/lib/l10n/app_localizations_ta.dart +++ b/lib/l10n/app_localizations_ta.dart @@ -9944,4 +9944,50 @@ class AppLocalizationsTa extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_te.dart b/lib/l10n/app_localizations_te.dart index facea4037..673e3874d 100644 --- a/lib/l10n/app_localizations_te.dart +++ b/lib/l10n/app_localizations_te.dart @@ -9942,4 +9942,50 @@ class AppLocalizationsTe extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_th.dart b/lib/l10n/app_localizations_th.dart index a64eb473f..266204eb9 100644 --- a/lib/l10n/app_localizations_th.dart +++ b/lib/l10n/app_localizations_th.dart @@ -9836,4 +9836,50 @@ class AppLocalizationsTh extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_tl.dart b/lib/l10n/app_localizations_tl.dart index cbb2c547e..71639d27b 100644 --- a/lib/l10n/app_localizations_tl.dart +++ b/lib/l10n/app_localizations_tl.dart @@ -9969,4 +9969,50 @@ class AppLocalizationsTl extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_tr.dart b/lib/l10n/app_localizations_tr.dart index 13bc10c9f..1043a053f 100644 --- a/lib/l10n/app_localizations_tr.dart +++ b/lib/l10n/app_localizations_tr.dart @@ -2294,11 +2294,11 @@ class AppLocalizationsTr extends AppLocalizations { String get playWhenBrowsingHomeScreen => 'Ana ekrana göz atarken oynat'; @override - String get loopThemeMusic => 'Loop Theme Music'; + String get loopThemeMusic => 'Tema Müziğini Sürekli Çal'; @override String get loopThemeMusicSubtitle => - 'Repeat the track instead of playing it once'; + 'Parçayı bir kez oynatmak yerine döngüye al'; @override String get detailsBackgroundBlur => 'Detay Arka Plan Bulanıklığı'; @@ -3284,10 +3284,11 @@ class AppLocalizationsTr extends AppLocalizations { 'Fragmanları medya çubuğunda 3 saniye sonra otomatik oynat'; @override - String get trailerAudio => 'Trailer Audio'; + String get trailerAudio => 'Fragman Sesi'; @override - String get enableTrailerAudio => 'Enable audio for trailers in media bar'; + String get enableTrailerAudio => + 'Medya çubuğundaki fragmanlar için sesi etkinleştir'; @override String get episodePreview => 'Bölüm Önizlemesi'; @@ -3307,8 +3308,7 @@ class AppLocalizationsTr extends AppLocalizations { String get previewAudio => 'Sesi Önizle'; @override - String get enablePreviewAudio => - 'Fragman ve bölüm önizlemeleri için sesi etkinleştirin'; + String get enablePreviewAudio => 'Medya önizlemeleri için sesi aç'; @override String get latestMedia => 'En Son Eklenen Medya'; @@ -3680,11 +3680,10 @@ class AppLocalizationsTr extends AppLocalizations { 'Onaylandı, reddedildi ve kütüphanenize eklendi'; @override - String get seerrNotifyIssuesTitle => 'Issue updates'; + String get seerrNotifyIssuesTitle => 'Sorun Güncellemeleri'; @override - String get seerrNotifyIssuesSubtitle => - 'New issues, replies, and resolutions'; + String get seerrNotifyIssuesSubtitle => 'Yeni sorunlar, yanıtlar ve çözümler'; @override String loggedInAs(String username) { @@ -3842,11 +3841,11 @@ class AppLocalizationsTr extends AppLocalizations { @override String seerrDownloadingPercent(int percent) { - return 'Downloading · $percent%'; + return 'İndiriliyor · %$percent'; } @override - String get seerrImportingStatus => 'Importing'; + String get seerrImportingStatus => 'İçe Aktarılıyor'; @override String itemsCount(int count) { @@ -3988,148 +3987,147 @@ class AppLocalizationsTr extends AppLocalizations { String get deletedStatus => 'Silindi'; @override - String get failedStatus => 'Failed'; + String get failedStatus => 'Başarısız Oldu'; @override - String get processingStatus => 'Processing'; + String get processingStatus => 'İşleniyor'; @override String modifiedByName(String name) { - return 'Modified by $name'; + return '$name tarafından değiştirildi'; } @override - String get completedStatus => 'Completed'; + String get completedStatus => 'Tamamlandı'; @override - String get requestErrorDuplicate => 'This title was already requested'; + String get requestErrorDuplicate => 'Bu içerik zaten talep edilmiş'; @override - String get requestErrorQuota => 'Request limit reached'; + String get requestErrorQuota => 'İstek sınırına ulaşıldı'; @override - String get requestErrorBlocklisted => 'This title is blocklisted'; + String get requestErrorBlocklisted => 'Bu içerik kara listede'; @override - String get requestErrorNoSeasons => 'No seasons left to request'; + String get requestErrorNoSeasons => 'Talep edilecek sezon kalmadı'; @override String get requestErrorPermission => - 'You don\'t have permission to make this request'; + 'Bu talebi gerçekleştirmek için izniniz yok'; @override - String get seerrRequestsTitle => 'Requests'; + String get seerrRequestsTitle => 'İstekler'; @override - String get seerrIssuesTitle => 'Issues'; + String get seerrIssuesTitle => 'Sorunlar'; @override - String get sortNewest => 'Newest'; + String get sortNewest => 'En Yeni'; @override - String get sortLastModified => 'Last Modified'; + String get sortLastModified => 'Son Düzenlenen'; @override - String get noIssues => 'No issues'; + String get noIssues => 'Sorun Yok'; @override String movieQuotaRemaining(int remaining, int limit) { - return '$remaining of $limit movie requests remaining'; + return 'Kalan film talebi: $remaining / $limit'; } @override String seasonQuotaRemaining(int remaining, int limit) { - return '$remaining of $limit season requests remaining'; + return 'Kalan sezon talebi: $remaining / $limit'; } @override String partOfCollectionName(String name) { - return 'Part of $name'; + return '$name koleksiyonunun parçası'; } @override - String get viewCollection => 'View Collection'; + String get viewCollection => 'Koleksiyonu Görüntüle'; @override - String get requestCollection => 'Request Collection'; + String get requestCollection => 'Koleksiyonu İste'; @override String collectionMoviesSummary(int total, int available) { - return '$total movies · $available available'; + return '$total film · $available mevcut'; } @override String requestMoviesCount(int count) { - return 'Request $count movies'; + return '$count film iste'; } @override String requestingProgress(int current, int total) { - return 'Requesting $current of $total...'; + return 'İsteniyor: $current / $total...'; } @override String requestedMoviesCount(int count) { - return 'Requested $count movies'; + return '$count film istendi'; } @override String requestedMoviesPartial(int ok, int total) { - return 'Requested $ok of $total movies'; + return 'İstenen film: $ok / $total'; } @override - String get collectionAllRequested => - 'All movies are already available or requested'; + String get collectionAllRequested => 'Tüm filmler zaten mevcut veya istenmiş'; @override - String get reportIssue => 'Report Issue'; + String get reportIssue => 'Sorun Bildir'; @override String get issueTypeVideo => 'Video'; @override - String get issueTypeAudio => 'Audio'; + String get issueTypeAudio => 'Ses'; @override - String get whatsWrong => 'What\'s wrong?'; + String get whatsWrong => 'Sorun ne?'; @override - String get allEpisodes => 'All Episodes'; + String get allEpisodes => 'Tüm Bölümler'; @override - String get episode => 'Episode'; + String get episode => 'Bölüm'; @override - String get openStatus => 'Open'; + String get openStatus => 'Açık'; @override - String get resolvedStatus => 'Resolved'; + String get resolvedStatus => 'Çözüldü'; @override - String get resolveAction => 'Resolve'; + String get resolveAction => 'Çöz'; @override - String get reopenAction => 'Reopen'; + String get reopenAction => 'Tekrar aç'; @override String reportedByName(String name) { - return 'Reported by $name'; + return '$name tarafından bildirildi'; } @override String commentsCount(int count) { - return '$count comments'; + return '$count yorum'; } @override - String get addComment => 'Add a comment'; + String get addComment => 'Yorum ekle'; @override - String get deleteIssueConfirm => 'Delete this issue?'; + String get deleteIssueConfirm => 'Sorun silinsin mi?'; @override - String get submitReport => 'Submit Report'; + String get submitReport => 'Raporu Gönder'; @override String get tmdbScore => 'TMDB Puanı'; @@ -7673,20 +7671,20 @@ class AppLocalizationsTr extends AppLocalizations { String get offlineSavedMedia => 'Kayıtlı Medya'; @override - String get offlineBannerTitle => 'You\'re offline'; + String get offlineBannerTitle => 'Çevrimdışısın'; @override - String get offlineBannerSubtitle => 'Showing your downloads'; + String get offlineBannerSubtitle => 'İndirdikleriniz gösteriliyor'; @override - String get offlineBannerAction => 'Downloads'; + String get offlineBannerAction => 'İndirilenler'; @override - String get serverUnreachableBannerTitle => 'Can\'t reach your server'; + String get serverUnreachableBannerTitle => 'Sunucuya erişilemiyor'; @override String get serverUnreachableBannerSubtitle => - 'Playing from downloads until it\'s back'; + 'Bağlantı geri gelene kadar indirilenlerden oynatılıyor'; @override String get castGoogleCast => 'Google Cast'; @@ -9742,7 +9740,7 @@ class AppLocalizationsTr extends AppLocalizations { 'Jellyfin görselleri güncelleyemedi. Kütüphaneniz, görselleri doğrudan medya klasörlerine kaydedecek şekilde yapılandırılmış (\'Görselleri medya klasörlerine kaydet\' seçeneği etkin). Bu hata genellikle Jellyfin sunucu işleminin, medya dizinlerinize dosya yazma izni olmadığında meydana gelir.'; @override - String get externalLists => 'Harici Ana Sayfa Satır Listeleri'; + String get externalLists => 'Harici Listeler'; @override String get replay => 'Tekrar'; @@ -9913,20 +9911,66 @@ class AppLocalizationsTr extends AppLocalizations { String get adminLibChapterImageResolutionMatchSource => 'Kaynağa göre eşle'; @override - String get imdbTop250Movies => 'IMDb Top 250 Movies'; + String get imdbTop250Movies => 'IMDB En İyi 250 Film'; @override - String get imdbTop250TvShows => 'IMDb Top 250 TV Shows'; + String get imdbTop250TvShows => 'IMDB En İyi 250 Dizi'; @override - String get imdbMostPopularMovies => 'IMDb Most Popular Movies'; + String get imdbMostPopularMovies => 'IMDB En Popüler Filmler'; @override - String get imdbMostPopularTvShows => 'IMDb Most Popular TV Shows'; + String get imdbMostPopularTvShows => 'IMDB En Popüler Diziler'; @override - String get imdbLowestRatedMovies => 'IMDb Lowest Rated Movies'; + String get imdbLowestRatedMovies => 'IMDB En Düşük Puanlı Filmler'; @override - String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + String get imdbTopEnglishMovies => 'IMDB En Yüksek Puanlı İngilizce Filmler'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_ug.dart b/lib/l10n/app_localizations_ug.dart index 8182d5fde..5cedabbe4 100644 --- a/lib/l10n/app_localizations_ug.dart +++ b/lib/l10n/app_localizations_ug.dart @@ -9897,4 +9897,50 @@ class AppLocalizationsUg extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_uk.dart b/lib/l10n/app_localizations_uk.dart index cf193bbb2..c93cb688a 100644 --- a/lib/l10n/app_localizations_uk.dart +++ b/lib/l10n/app_localizations_uk.dart @@ -9943,4 +9943,50 @@ class AppLocalizationsUk extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_vi.dart b/lib/l10n/app_localizations_vi.dart index 3374d95a3..e3ebc505c 100644 --- a/lib/l10n/app_localizations_vi.dart +++ b/lib/l10n/app_localizations_vi.dart @@ -9903,4 +9903,50 @@ class AppLocalizationsVi extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } diff --git a/lib/l10n/app_localizations_yue.dart b/lib/l10n/app_localizations_yue.dart index bd315ae98..6d4ea48b8 100644 --- a/lib/l10n/app_localizations_yue.dart +++ b/lib/l10n/app_localizations_yue.dart @@ -9646,6 +9646,52 @@ class AppLocalizationsYue extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } /// The translations for Yue Chinese Cantonese, as used in China (`yue_CN`). diff --git a/lib/l10n/app_localizations_zh.dart b/lib/l10n/app_localizations_zh.dart index d3bb9a96c..41ed27b80 100644 --- a/lib/l10n/app_localizations_zh.dart +++ b/lib/l10n/app_localizations_zh.dart @@ -9526,6 +9526,52 @@ class AppLocalizationsZh extends AppLocalizations { @override String get imdbTopEnglishMovies => 'IMDb Top Rated English Movies'; + + @override + String get personalRatingStyle => 'Personal rating style'; + + @override + String get personalRatingThumbs => 'Like / dislike'; + + @override + String get personalRatingStars => '5 stars'; + + @override + String get personalRatingNumeric => 'Numeric score out of 10'; + + @override + String get rate => 'Rate'; + + @override + String get like => 'Like'; + + @override + String get dislike => 'Dislike'; + + @override + String get personalRatingClear => 'Clear rating'; + + @override + String get personalRatingRated => 'Rated'; + + @override + String get personalRatingSaveFailed => 'Could not save rating'; + + @override + String get increase => 'Increase'; + + @override + String get decrease => 'Decrease'; + + @override + String personalRatingOutOfTen(String rating) { + return '$rating / 10'; + } + + @override + String personalRatingOutOfFive(String rating) { + return '$rating / 5'; + } } /// The translations for Chinese, using the Han script (`zh_Hant`). diff --git a/lib/preference/preference_constants.dart b/lib/preference/preference_constants.dart index d1da4ccb3..f59f798ae 100644 --- a/lib/preference/preference_constants.dart +++ b/lib/preference/preference_constants.dart @@ -233,6 +233,12 @@ enum RatingType { hidden, } +enum PersonalRatingStyle { + thumbs, + stars, + numeric, +} + enum MediaSegmentAction { nothing, skip, @@ -577,4 +583,3 @@ enum RewatchSortBy { String get displayName => this == recentlyWatched ? 'Recently Watched' : 'Random'; } - diff --git a/lib/preference/user_preferences.dart b/lib/preference/user_preferences.dart index 93d3e1f2b..0bf522348 100644 --- a/lib/preference/user_preferences.dart +++ b/lib/preference/user_preferences.dart @@ -259,6 +259,7 @@ class UserPreferences extends ChangeNotifier { 'showRatingLabels', 'showRatingBadges', 'enableEpisodeRatings', + 'pref_personal_rating_style', 'tmdbApiKey', 'seerrEnabled', 'seerrBlockNsfw', @@ -1621,6 +1622,12 @@ class UserPreferences extends ChangeNotifier { defaultValue: false, ); + static final personalRatingStyle = EnumPreference( + key: 'pref_personal_rating_style', + values: PersonalRatingStyle.values, + defaultValue: PersonalRatingStyle.thumbs, + ); + static final tmdbApiKey = Preference(key: 'tmdbApiKey', defaultValue: ''); static final showRatingLabels = Preference( @@ -2353,4 +2360,3 @@ class UserPreferences extends ChangeNotifier { return result; } } - diff --git a/lib/ui/screens/detail/item_detail_screen.dart b/lib/ui/screens/detail/item_detail_screen.dart index 640eeafb9..5afebd3c4 100644 --- a/lib/ui/screens/detail/item_detail_screen.dart +++ b/lib/ui/screens/detail/item_detail_screen.dart @@ -49,6 +49,7 @@ import '../../widgets/change_artwork_dialog.dart'; import '../../widgets/navigation_layout.dart'; import '../../widgets/horizontal_scroll_section.dart'; import '../../widgets/rating_display.dart'; +import '../../widgets/personal_rating_dialog.dart'; import '../../widgets/track_action_dialog.dart'; import '../../widgets/track_selector_dialog.dart'; import '../../widgets/remote_play_to_session_dialog.dart'; @@ -191,7 +192,7 @@ class _ItemDetailScreenState extends State itemId: widget.itemId, serverId: widget.serverId, client: client, - mutations: GetIt.instance(), + mutations: ItemMutationRepository(client), mdbListRepository: GetIt.instance(), tmdbRepository: GetIt.instance(), ); @@ -5280,6 +5281,7 @@ class DetailActionButtonsState extends State { return _DetailActionButton( label: button.label, icon: button.icon, + iconBuilder: button.iconBuilder, onPressed: button.onPressed, onLongPress: button.onLongPress, onFocused: onFocused ?? button.onFocused, @@ -5536,6 +5538,54 @@ class DetailActionButtonsState extends State { return maxButtons > 2 ? maxButtons : 2; } + PersonalRatingStyle _personalRatingStyle() { + final style = GetIt.instance().get( + UserPreferences.personalRatingStyle, + ); + return viewModel.supportsNumericUserRatings + ? style + : PersonalRatingStyle.thumbs; + } + + bool? _displayRatingLikes(AggregatedItem item) => + item.personalRatingLikes ?? + (item.personalRating == null ? null : item.personalRating! >= 6.5); + + String _personalRatingActionLabel( + AppLocalizations l10n, + AggregatedItem item, + ) { + final rating = item.personalRating; + switch (_personalRatingStyle()) { + case PersonalRatingStyle.thumbs: + if (rating == null) return l10n.rate; + return _displayRatingLikes(item) == true ? l10n.like : l10n.dislike; + case PersonalRatingStyle.stars: + if (rating == null) return l10n.rate; + final stars = rating / 2; + if (stars == 0) return l10n.personalRatingOutOfFive('0'); + final fullStars = stars.floor(); + final hasHalfStar = stars - fullStars >= 0.25; + return '${'★' * fullStars}${hasHalfStar ? '½' : ''}'; + case PersonalRatingStyle.numeric: + return rating == null ? l10n.rate : l10n.personalRatingRated; + } + } + + Future _showPersonalRatingDialog(BuildContext context) { + final item = viewModel.item; + if (item == null) return Future.value(); + return PersonalRatingDialog.show( + context, + style: _personalRatingStyle(), + rating: item.personalRating, + likes: _displayRatingLikes(item), + onSetThumbRating: viewModel.setThumbRating, + onSetNumericRating: viewModel.setNumericRating, + onClearRating: viewModel.clearRating, + ); + } + @override void didUpdateWidget(covariant DetailActionButtons oldWidget) { super.didUpdateWidget(oldWidget); @@ -6001,6 +6051,31 @@ class DetailActionButtonsState extends State { isActive: item.isFavorite, activeColor: const Color(0xFFFF4757), ), + if (item.type == 'Movie') + _DetailActionButton( + label: _personalRatingActionLabel(l10n, item), + icon: switch (_personalRatingStyle()) { + PersonalRatingStyle.thumbs => _displayRatingLikes(item) == true + ? Icons.thumb_up + : _displayRatingLikes(item) == false + ? Icons.thumb_down + : Icons.thumb_up_outlined, + PersonalRatingStyle.stars => Icons.star_outline, + PersonalRatingStyle.numeric => Icons.numbers, + }, + iconBuilder: (size, color) => _PersonalRatingActionIcon( + style: _personalRatingStyle(), + rating: item.personalRating, + likes: _displayRatingLikes(item), + size: size, + color: color, + ), + onPressed: viewModel.isRatingMutationInProgress + ? () {} + : () => _showPersonalRatingDialog(context), + isActive: item.personalRating != null, + activeColor: Colors.amber, + ), if (!isBook) _DetailActionButton( label: l10n.playlist, @@ -6047,6 +6122,7 @@ class DetailActionButtonsState extends State { return _DetailActionButton( label: widget.label, icon: widget.icon, + iconBuilder: widget.iconBuilder, isPrimary: widget.isPrimary, onPressed: widget.onPressed, onLongPress: widget.onLongPress, @@ -9555,6 +9631,133 @@ class _DeleteDownloadButtonState extends State<_DeleteDownloadButton> { } } +class _PersonalRatingActionIcon extends StatelessWidget { + final PersonalRatingStyle style; + final double? rating; + final bool? likes; + final double size; + final Color color; + + const _PersonalRatingActionIcon({ + required this.style, + required this.rating, + required this.likes, + required this.size, + required this.color, + }); + + @override + Widget build(BuildContext context) { + return switch (style) { + PersonalRatingStyle.thumbs => likes == null + ? Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.thumb_up_outlined, color: color, size: size * 0.5), + SizedBox(width: size * 0.08), + Icon( + Icons.thumb_down_outlined, + color: color, + size: size * 0.5, + ), + ], + ) + : Icon( + likes! ? Icons.thumb_up : Icons.thumb_down, + color: color, + size: size * 0.72, + ), + PersonalRatingStyle.stars => _StarFillIcon( + fill: ((rating ?? 0).clamp(0, 10) / 10).toDouble(), + size: size * 0.82, + color: color, + ), + PersonalRatingStyle.numeric => Row( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.baseline, + textBaseline: TextBaseline.alphabetic, + children: [ + Text( + rating == null + ? '–' + : rating == rating!.roundToDouble() + ? rating!.toInt().toString() + : rating!.toString(), + style: TextStyle( + color: color, + fontWeight: FontWeight.w800, + fontSize: size * 0.58, + height: 1, + ), + ), + Text( + ' / 10', + style: TextStyle( + color: color.withValues(alpha: 0.82), + fontWeight: FontWeight.w700, + fontSize: size * 0.28, + height: 1, + ), + ), + ], + ), + }; + } +} + +class _StarFillIcon extends StatelessWidget { + final double fill; + final double size; + final Color color; + + const _StarFillIcon({ + required this.fill, + required this.size, + required this.color, + }); + + @override + Widget build(BuildContext context) { + // A linear fill is imperceptible at this button size: 1/5 looks empty and + // 4/5 looks full because the missing portion falls into a star point. + // Keep exact empty/full endpoints, but pull intermediate values toward the + // middle so every saved rating remains visually distinguishable. + final visualFill = fill == 0 + ? 0.0 + : fill == 1 + ? 1.0 + : 0.5 + (fill - 0.5) * 0.3; + if (visualFill == 0) { + return Icon(Icons.star_border, color: color, size: size); + } + if (visualFill == 1) { + return Icon(Icons.star, color: color, size: size); + } + return SizedBox( + width: size, + height: size, + child: Stack( + children: [ + Icon(Icons.star_border, color: color, size: size), + ShaderMask( + blendMode: BlendMode.srcIn, + shaderCallback: (bounds) => LinearGradient( + colors: [ + color, + color, + color.withValues(alpha: 0), + color.withValues(alpha: 0), + ], + stops: [0, visualFill, visualFill, 1], + ).createShader(bounds), + child: Icon(Icons.star, color: Colors.white, size: size), + ), + ], + ), + ); + } +} + class _DetailActionButton extends StatefulWidget { final String label; final IconData? icon; @@ -9862,7 +10065,7 @@ class _DetailActionButtonState extends State<_DetailActionButton> ), ), ), - if (isExpanded) ...[ + if (isExpanded && widget.label.isNotEmpty) ...[ const SizedBox(width: 6), Text( widget.label, diff --git a/lib/ui/screens/settings/panel/details_screen_settings_screen.dart b/lib/ui/screens/settings/panel/details_screen_settings_screen.dart index 554b7f0fd..ceff12027 100644 --- a/lib/ui/screens/settings/panel/details_screen_settings_screen.dart +++ b/lib/ui/screens/settings/panel/details_screen_settings_screen.dart @@ -25,13 +25,13 @@ class _DetailsScreenSettingsScreenState Widget build(BuildContext context) { final bottomPad = PlatformDetection.isTV ? 96.0 : 24.0; final l10n = AppLocalizations.of(context); - final _prefs = GetIt.instance(); + final prefs = GetIt.instance(); return Scaffold( appBar: buildSettingsAppBar(context, Text(l10n.settingsDetailsScreen)), body: FocusScope( node: _detailsScreenScope, child: ListenableBuilder( - listenable: _prefs, + listenable: prefs, builder: (context, _) => ListView( padding: EdgeInsets.only(bottom: bottomPad), children: [ @@ -49,7 +49,22 @@ class _DetailsScreenSettingsScreenState DetailScreenStyle.modern => l10n.detailScreenStyleModern, }, ), - if (_prefs.get(UserPreferences.detailScreenStyle) != DetailScreenStyle.modern) + EnumPreferenceTile( + preference: UserPreferences.personalRatingStyle, + title: l10n.personalRatingStyle, + icon: Icons.rate_review, + values: GetIt.instance() + .userLibraryApi + .supportsNumericUserRatings + ? PersonalRatingStyle.values + : const [PersonalRatingStyle.thumbs], + labelOf: (style) => switch (style) { + PersonalRatingStyle.thumbs => l10n.personalRatingThumbs, + PersonalRatingStyle.stars => l10n.personalRatingStars, + PersonalRatingStyle.numeric => l10n.personalRatingNumeric, + }, + ), + if (prefs.get(UserPreferences.detailScreenStyle) != DetailScreenStyle.modern) SliderPreferenceTile( preference: UserPreferences.detailsBackgroundBlurAmount, title: l10n.detailsBackgroundBlur, @@ -60,7 +75,7 @@ class _DetailsScreenSettingsScreenState labelOf: (v) => '$v', onChangeEnd: _pushPersonalizationSync, ), - if (_prefs.get(UserPreferences.detailScreenStyle) == DetailScreenStyle.modern) + if (prefs.get(UserPreferences.detailScreenStyle) == DetailScreenStyle.modern) SwitchPreferenceTile( preference: UserPreferences.detailExpandedTabs, title: l10n.expandedTabs, diff --git a/lib/ui/widgets/personal_rating_dialog.dart b/lib/ui/widgets/personal_rating_dialog.dart new file mode 100644 index 000000000..1e42406ca --- /dev/null +++ b/lib/ui/widgets/personal_rating_dialog.dart @@ -0,0 +1,311 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:intl/intl.dart'; + +import '../../l10n/app_localizations.dart'; +import '../../preference/preference_constants.dart'; +import 'overlay_sheet.dart'; + +class PersonalRatingDialog extends StatefulWidget { + final PersonalRatingStyle style; + final double? rating; + final bool? likes; + final Future Function(bool likes) onSetThumbRating; + final Future Function(double rating) onSetNumericRating; + final Future Function() onClearRating; + + const PersonalRatingDialog({ + super.key, + required this.style, + required this.rating, + required this.likes, + required this.onSetThumbRating, + required this.onSetNumericRating, + required this.onClearRating, + }); + + static Future show( + BuildContext context, { + required PersonalRatingStyle style, + required double? rating, + required bool? likes, + required Future Function(bool likes) onSetThumbRating, + required Future Function(double rating) onSetNumericRating, + required Future Function() onClearRating, + }) async { + await showFocusRestoringDialog( + context: context, + useRootNavigator: false, + builder: (_) => PersonalRatingDialog( + style: style, + rating: rating, + likes: likes, + onSetThumbRating: onSetThumbRating, + onSetNumericRating: onSetNumericRating, + onClearRating: onClearRating, + ), + ); + } + + @override + State createState() => _PersonalRatingDialogState(); +} + +class _PersonalRatingDialogState extends State { + late double _draftRating; + bool _ratingChanged = false; + bool _saving = false; + + bool? get _displayLikes => + widget.likes ?? (widget.rating == null ? null : widget.rating! >= 6.5); + + @override + void initState() { + super.initState(); + _draftRating = _normalizedRating(widget.rating); + _ratingChanged = widget.rating == null; + } + + double _normalizedRating(double? rating) { + if (rating == null || !rating.isFinite) return 0; + return rating.clamp(0, 10).toDouble(); + } + + String _formatRating(AppLocalizations l10n, double value) => + NumberFormat.decimalPattern(l10n.localeName).format(value); + + Future _submit(Future Function() mutation) async { + if (_saving) return; + setState(() => _saving = true); + try { + await mutation(); + if (mounted) Navigator.of(context).pop(); + } catch (_) { + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + AppLocalizations.of(context).personalRatingSaveFailed, + ), + ), + ); + } + } finally { + if (mounted) setState(() => _saving = false); + } + } + + Widget _buildThumbs(AppLocalizations l10n) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + _ThumbRatingButton( + icon: Icons.thumb_up, + label: l10n.like, + selected: _displayLikes == true, + onPressed: _saving + ? null + : () => _submit(() => widget.onSetThumbRating(true)), + ), + const SizedBox(width: 12), + _ThumbRatingButton( + icon: Icons.thumb_down, + label: l10n.dislike, + selected: _displayLikes == false, + onPressed: _saving + ? null + : () => _submit(() => widget.onSetThumbRating(false)), + ), + ], + ), + ], + ); + } + + Widget _buildStarsEditor(AppLocalizations l10n) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Focus( + autofocus: true, + onKeyEvent: (_, event) { + if (_saving || event is! KeyDownEvent) { + return KeyEventResult.ignored; + } + if (event.logicalKey == LogicalKeyboardKey.arrowLeft && + _draftRating > 0) { + setState(() { + _draftRating = + (_draftRating - 0.5).clamp(0, 10).toDouble(); + _ratingChanged = true; + }); + return KeyEventResult.handled; + } + if (event.logicalKey == LogicalKeyboardKey.arrowRight && + _draftRating < 10) { + setState(() { + _draftRating = + (_draftRating + 0.5).clamp(0, 10).toDouble(); + _ratingChanged = true; + }); + return KeyEventResult.handled; + } + return KeyEventResult.ignored; + }, + child: Semantics( + label: l10n.personalRatingOutOfFive( + _formatRating(l10n, _draftRating / 2), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: List.generate(5, (index) { + final remaining = _draftRating / 2 - index; + final icon = remaining >= 0.75 + ? Icons.star + : remaining >= 0.25 + ? Icons.star_half + : Icons.star_border; + return GestureDetector( + key: ValueKey('personal_rating_star_$index'), + behavior: HitTestBehavior.opaque, + onTapDown: _saving + ? null + : (details) { + final isHalf = details.localPosition.dx < 24; + setState(() { + _draftRating = (index + (isHalf ? 0.5 : 1)) * 2; + _ratingChanged = true; + }); + }, + child: Padding( + padding: const EdgeInsets.all(2), + child: Icon(icon, size: 44, color: Colors.amber), + ), + ); + }), + ), + ), + ), + const SizedBox(height: 12), + Text( + l10n.personalRatingOutOfFive(_formatRating(l10n, _draftRating / 2)), + ), + ], + ); + } + + Widget _buildNumericEditor(AppLocalizations l10n) { + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + IconButton( + tooltip: l10n.decrease, + onPressed: _saving || _draftRating <= 0 + ? null + : () => setState(() { + _draftRating = (_draftRating.ceilToDouble() - 1) + .clamp(0, 10) + .toDouble(); + _ratingChanged = true; + }), + icon: const Icon(Icons.remove), + ), + SizedBox( + width: 120, + child: Text( + l10n.personalRatingOutOfTen(_formatRating(l10n, _draftRating)), + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.headlineSmall, + ), + ), + IconButton( + tooltip: l10n.increase, + onPressed: _saving || _draftRating >= 10 + ? null + : () => setState(() { + _draftRating = (_draftRating.floorToDouble() + 1) + .clamp(0, 10) + .toDouble(); + _ratingChanged = true; + }), + icon: const Icon(Icons.add), + ), + ], + ); + } + + @override + Widget build(BuildContext context) { + final l10n = AppLocalizations.of(context); + final isThumbs = widget.style == PersonalRatingStyle.thumbs; + final content = switch (widget.style) { + PersonalRatingStyle.thumbs => _buildThumbs(l10n), + PersonalRatingStyle.stars => _buildStarsEditor(l10n), + PersonalRatingStyle.numeric => _buildNumericEditor(l10n), + }; + + return AlertDialog( + title: Text(l10n.rate), + content: SizedBox(width: 320, child: content), + actions: [ + if (widget.rating != null) + TextButton.icon( + onPressed: _saving ? null : () => _submit(widget.onClearRating), + icon: const Icon(Icons.clear), + label: Text(l10n.personalRatingClear), + ), + if (!isThumbs) + FilledButton( + onPressed: _saving || !_ratingChanged + ? null + : () => _submit(() => widget.onSetNumericRating(_draftRating)), + child: Text(l10n.save), + ), + ], + ); + } +} + +class _ThumbRatingButton extends StatelessWidget { + final IconData icon; + final String label; + final bool selected; + final VoidCallback? onPressed; + + const _ThumbRatingButton({ + required this.icon, + required this.label, + required this.selected, + required this.onPressed, + }); + + @override + Widget build(BuildContext context) { + final colorScheme = Theme.of(context).colorScheme; + return Semantics( + label: label, + selected: selected, + button: true, + child: IconButton( + autofocus: icon == Icons.thumb_up, + tooltip: label, + onPressed: onPressed, + style: IconButton.styleFrom( + backgroundColor: selected + ? colorScheme.primaryContainer + : Colors.transparent, + foregroundColor: selected + ? colorScheme.onPrimaryContainer + : colorScheme.onSurface, + side: BorderSide( + color: selected ? colorScheme.primary : colorScheme.outline, + ), + ), + icon: Icon(icon, size: 28), + ), + ); + } +} diff --git a/packages/server_core/lib/src/api/user_library_api.dart b/packages/server_core/lib/src/api/user_library_api.dart index 51708cb17..af7f31de1 100644 --- a/packages/server_core/lib/src/api/user_library_api.dart +++ b/packages/server_core/lib/src/api/user_library_api.dart @@ -1,9 +1,11 @@ abstract class UserLibraryApi { + bool get supportsNumericUserRatings; Future markFavorite(String itemId); Future unmarkFavorite(String itemId); Future markPlayed(String itemId); Future unmarkPlayed(String itemId); Future updateUserRating(String itemId, {required bool likes}); + Future updateNumericUserRating(String itemId, {required double rating}); Future deleteUserRating(String itemId); Future> getItem(String itemId); } diff --git a/packages/server_core/lib/src/models/server_models.dart b/packages/server_core/lib/src/models/server_models.dart index 7970d5faa..ed909c946 100644 --- a/packages/server_core/lib/src/models/server_models.dart +++ b/packages/server_core/lib/src/models/server_models.dart @@ -169,6 +169,8 @@ class ServerMediaSource { } class UserItemData { + final double? rating; + final bool? likes; final double? playedPercentage; final int? playbackPositionTicks; final int playCount; @@ -177,6 +179,8 @@ class UserItemData { final DateTime? lastPlayedDate; const UserItemData({ + this.rating, + this.likes, this.playedPercentage, this.playbackPositionTicks, this.playCount = 0, @@ -186,6 +190,8 @@ class UserItemData { }); factory UserItemData.fromJson(Map json) => UserItemData( + rating: (json['Rating'] as num?)?.toDouble(), + likes: json['Likes'] as bool?, playedPercentage: (json['PlayedPercentage'] as num?)?.toDouble(), playbackPositionTicks: json['PlaybackPositionTicks'] as int?, playCount: json['PlayCount'] as int? ?? 0, diff --git a/packages/server_core/test/server_models_test.dart b/packages/server_core/test/server_models_test.dart new file mode 100644 index 000000000..a2d3d2884 --- /dev/null +++ b/packages/server_core/test/server_models_test.dart @@ -0,0 +1,42 @@ +import 'package:server_core/server_core.dart'; +import 'package:test/test.dart'; + +void main() { + group('UserItemData', () { + test('parses decimal personal rating and likes', () { + final item = ServerItem.fromJson({ + 'Id': 'movie-1', + 'UserData': {'Rating': 8.5, 'Likes': true}, + }); + + expect(item.userData?.rating, 8.5); + expect(item.userData?.likes, isTrue); + }); + + test('parses integer personal rating as double', () { + final item = ServerItem.fromJson({ + 'Id': 'movie-1', + 'UserData': {'Rating': 8}, + }); + + expect(item.userData?.rating, 8.0); + expect(item.userData?.likes, isNull); + }); + + test('keeps absent personal rating and likes null', () { + final item = ServerItem.fromJson({ + 'Id': 'movie-1', + 'UserData': {}, + }); + + expect(item.userData?.rating, isNull); + expect(item.userData?.likes, isNull); + }); + + test('keeps user data null when it is absent', () { + final item = ServerItem.fromJson({'Id': 'movie-1'}); + + expect(item.userData, isNull); + }); + }); +} diff --git a/packages/server_emby/lib/src/api/emby_user_library_api.dart b/packages/server_emby/lib/src/api/emby_user_library_api.dart index 772c3546b..b4a5152d2 100644 --- a/packages/server_emby/lib/src/api/emby_user_library_api.dart +++ b/packages/server_emby/lib/src/api/emby_user_library_api.dart @@ -7,6 +7,9 @@ class EmbyUserLibraryApi implements UserLibraryApi { EmbyUserLibraryApi(this._dio, this._getUserId); + @override + bool get supportsNumericUserRatings => true; + @override Future markFavorite(String itemId) async { final userId = _getUserId(); @@ -40,6 +43,18 @@ class EmbyUserLibraryApi implements UserLibraryApi { ); } + @override + Future updateNumericUserRating( + String itemId, { + required double rating, + }) async { + final userId = _getUserId(); + await _dio.post( + '/Users/$userId/Items/$itemId/UserData', + data: {'Rating': rating}, + ); + } + @override Future deleteUserRating(String itemId) async { final userId = _getUserId(); diff --git a/packages/server_emby/test/emby_user_library_api_test.dart b/packages/server_emby/test/emby_user_library_api_test.dart new file mode 100644 index 000000000..235095f0a --- /dev/null +++ b/packages/server_emby/test/emby_user_library_api_test.dart @@ -0,0 +1,35 @@ +import 'package:dio/dio.dart'; +import 'package:server_emby/src/api/emby_user_library_api.dart'; +import 'package:test/test.dart'; + +class _FakeServer extends Interceptor { + _FakeServer(this.handle); + + final void Function(RequestOptions options, RequestInterceptorHandler handler) + handle; + + @override + void onRequest(RequestOptions options, RequestInterceptorHandler handler) => + handle(options, handler); +} + +void main() { + test('numeric rating posts Rating to the Emby user data endpoint', () async { + RequestOptions? request; + final dio = Dio() + ..interceptors.add( + _FakeServer((options, handler) { + request = options; + handler.resolve(Response(requestOptions: options, statusCode: 204)); + }), + ); + + final api = EmbyUserLibraryApi(dio, () => 'user-1'); + await api.updateNumericUserRating('movie-1', rating: 8.5); + + expect(api.supportsNumericUserRatings, isTrue); + expect(request?.method, 'POST'); + expect(request?.path, '/Users/user-1/Items/movie-1/UserData'); + expect(request?.data, {'Rating': 8.5}); + }); +} diff --git a/packages/server_jellyfin/lib/src/api/jellyfin_item_fields.dart b/packages/server_jellyfin/lib/src/api/jellyfin_item_fields.dart index b855ded5e..6ee794168 100644 --- a/packages/server_jellyfin/lib/src/api/jellyfin_item_fields.dart +++ b/packages/server_jellyfin/lib/src/api/jellyfin_item_fields.dart @@ -1,2 +1,2 @@ const kItemFields = - 'Trickplay,Chapters,MediaSources,MediaStreams,People,Overview,Genres,RecursiveItemCount,ChildCount,ParentLogoItemId,ParentLogoImageTag'; + 'Trickplay,Chapters,MediaSources,MediaStreams,People,Overview,Genres,UserData,RecursiveItemCount,ChildCount,ParentLogoItemId,ParentLogoImageTag'; diff --git a/packages/server_jellyfin/lib/src/api/jellyfin_user_library_api.dart b/packages/server_jellyfin/lib/src/api/jellyfin_user_library_api.dart index 90017a780..ed8e98140 100644 --- a/packages/server_jellyfin/lib/src/api/jellyfin_user_library_api.dart +++ b/packages/server_jellyfin/lib/src/api/jellyfin_user_library_api.dart @@ -7,6 +7,9 @@ class JellyfinUserLibraryApi implements UserLibraryApi { JellyfinUserLibraryApi(this._dio); + @override + bool get supportsNumericUserRatings => true; + @override Future markFavorite(String itemId) async { await _dio.post('/UserFavoriteItems/$itemId'); @@ -34,6 +37,14 @@ class JellyfinUserLibraryApi implements UserLibraryApi { }); } + @override + Future updateNumericUserRating( + String itemId, { + required double rating, + }) async { + await _dio.post('/UserItems/$itemId/UserData', data: {'Rating': rating}); + } + @override Future deleteUserRating(String itemId) async { await _dio.delete('/UserItems/$itemId/Rating'); diff --git a/packages/server_jellyfin/test/jellyfin_items_api_test.dart b/packages/server_jellyfin/test/jellyfin_items_api_test.dart new file mode 100644 index 000000000..e9de430d3 --- /dev/null +++ b/packages/server_jellyfin/test/jellyfin_items_api_test.dart @@ -0,0 +1,35 @@ +import 'package:dio/dio.dart'; +import 'package:server_jellyfin/src/api/jellyfin_items_api.dart'; +import 'package:test/test.dart'; + +class _FakeServer extends Interceptor { + _FakeServer(this.handle); + + final void Function(RequestOptions options, RequestInterceptorHandler handler) + handle; + + @override + void onRequest(RequestOptions options, RequestInterceptorHandler handler) => + handle(options, handler); +} + +void main() { + test('item details request UserData', () async { + RequestOptions? request; + final dio = Dio() + ..interceptors.add( + _FakeServer((options, handler) { + request = options; + handler.resolve( + Response(requestOptions: options, data: {}), + ); + }), + ); + + await JellyfinItemsApi(dio, () => 'user-1').getItem('movie-1'); + + expect(request?.method, 'GET'); + expect(request?.path, '/Users/user-1/Items/movie-1'); + expect(request?.queryParameters['Fields'], contains('UserData')); + }); +} diff --git a/packages/server_jellyfin/test/jellyfin_user_library_api_test.dart b/packages/server_jellyfin/test/jellyfin_user_library_api_test.dart new file mode 100644 index 000000000..6be4c9cdc --- /dev/null +++ b/packages/server_jellyfin/test/jellyfin_user_library_api_test.dart @@ -0,0 +1,69 @@ +import 'package:dio/dio.dart'; +import 'package:server_jellyfin/src/api/jellyfin_user_library_api.dart'; +import 'package:test/test.dart'; + +class _FakeServer extends Interceptor { + _FakeServer(this.handle); + + final void Function(RequestOptions options, RequestInterceptorHandler handler) + handle; + + @override + void onRequest(RequestOptions options, RequestInterceptorHandler handler) => + handle(options, handler); +} + +void main() { + test('numeric rating posts only Rating to UserData', () async { + RequestOptions? request; + final dio = Dio() + ..interceptors.add( + _FakeServer((options, handler) { + request = options; + handler.resolve(Response(requestOptions: options, statusCode: 204)); + }), + ); + + final api = JellyfinUserLibraryApi(dio); + await api.updateNumericUserRating('movie-1', rating: 8.5); + + expect(api.supportsNumericUserRatings, isTrue); + expect(request?.method, 'POST'); + expect(request?.path, '/UserItems/movie-1/UserData'); + expect(request?.queryParameters, isEmpty); + expect(request?.data, {'Rating': 8.5}); + }); + + test('thumb rating continues to use the legacy Likes endpoint', () async { + RequestOptions? request; + final dio = Dio() + ..interceptors.add( + _FakeServer((options, handler) { + request = options; + handler.resolve(Response(requestOptions: options, statusCode: 204)); + }), + ); + + await JellyfinUserLibraryApi(dio).updateUserRating('movie-1', likes: true); + + expect(request?.method, 'POST'); + expect(request?.path, '/UserItems/movie-1/Rating'); + expect(request?.queryParameters, {'Likes': true}); + }); + + test('clearing a rating uses the Rating delete endpoint', () async { + RequestOptions? request; + final dio = Dio() + ..interceptors.add( + _FakeServer((options, handler) { + request = options; + handler.resolve(Response(requestOptions: options, statusCode: 204)); + }), + ); + + await JellyfinUserLibraryApi(dio).deleteUserRating('movie-1'); + + expect(request?.method, 'DELETE'); + expect(request?.path, '/UserItems/movie-1/Rating'); + }); +} diff --git a/test/personal_rating_dialog_test.dart b/test/personal_rating_dialog_test.dart new file mode 100644 index 000000000..3d95a98e4 --- /dev/null +++ b/test/personal_rating_dialog_test.dart @@ -0,0 +1,144 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:moonfin/l10n/app_localizations.dart'; +import 'package:moonfin/preference/preference_constants.dart'; +import 'package:moonfin/ui/widgets/personal_rating_dialog.dart'; + +Widget _app({ + required FocusNode focusNode, + required PersonalRatingStyle style, + double? rating, + bool? likes, + required Future Function(bool) onThumb, + required Future Function(double) onNumeric, + required Future Function() onClear, +}) { + return MaterialApp( + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, + home: Scaffold( + body: Builder( + builder: (context) => ElevatedButton( + focusNode: focusNode, + onPressed: () => PersonalRatingDialog.show( + context, + style: style, + rating: rating, + likes: likes, + onSetThumbRating: onThumb, + onSetNumericRating: onNumeric, + onClearRating: onClear, + ), + child: const Text('Open'), + ), + ), + ), + ); +} + +void main() { + testWidgets('thumbs mode saves a like and restores focus', (tester) async { + final focusNode = FocusNode(); + addTearDown(focusNode.dispose); + bool? savedLike; + + await tester.pumpWidget( + _app( + focusNode: focusNode, + style: PersonalRatingStyle.thumbs, + onThumb: (likes) async => savedLike = likes, + onNumeric: (_) async {}, + onClear: () async {}, + ), + ); + + focusNode.requestFocus(); + await tester.tap(find.text('Open')); + await tester.pumpAndSettle(); + await tester.tap(find.byTooltip('Like')); + await tester.pumpAndSettle(); + + expect(savedLike, isTrue); + expect(focusNode.hasFocus, isTrue); + }); + + testWidgets('stars mode saves half-star values', (tester) async { + final focusNode = FocusNode(); + addTearDown(focusNode.dispose); + double? savedRating; + + await tester.pumpWidget( + _app( + focusNode: focusNode, + style: PersonalRatingStyle.stars, + rating: 9, + onThumb: (_) async {}, + onNumeric: (rating) async => savedRating = rating, + onClear: () async {}, + ), + ); + + await tester.tap(find.text('Open')); + await tester.pumpAndSettle(); + expect(find.byIcon(Icons.star_half), findsOneWidget); + final thirdStar = find.byKey(const ValueKey('personal_rating_star_2')); + final thirdStarBounds = tester.getRect(thirdStar); + await tester.tapAt( + Offset(thirdStarBounds.left + thirdStarBounds.width * 0.25, thirdStarBounds.center.dy), + ); + await tester.pumpAndSettle(); + await tester.tap(find.text('Save')); + await tester.pumpAndSettle(); + + expect(savedRating, isNotNull); + expect(savedRating, 5); + }); + + testWidgets('numeric mode clears an existing rating', (tester) async { + final focusNode = FocusNode(); + addTearDown(focusNode.dispose); + var cleared = false; + + await tester.pumpWidget( + _app( + focusNode: focusNode, + style: PersonalRatingStyle.numeric, + rating: 8, + likes: true, + onThumb: (_) async {}, + onNumeric: (_) async {}, + onClear: () async => cleared = true, + ), + ); + + await tester.tap(find.text('Open')); + await tester.pumpAndSettle(); + await tester.tap(find.text('Clear rating')); + await tester.pumpAndSettle(); + + expect(cleared, isTrue); + }); + + testWidgets('numeric mode steps down to the previous integer', (tester) async { + final focusNode = FocusNode(); + addTearDown(focusNode.dispose); + + await tester.pumpWidget( + _app( + focusNode: focusNode, + style: PersonalRatingStyle.numeric, + rating: 8, + onThumb: (_) async {}, + onNumeric: (_) async {}, + onClear: () async {}, + ), + ); + + await tester.tap(find.text('Open')); + await tester.pumpAndSettle(); + await tester.tap(find.byTooltip('Decrease')); + await tester.pump(); + + expect(find.text('7 / 10'), findsOneWidget); + }); +} diff --git a/test/preference/personal_rating_style_test.dart b/test/preference/personal_rating_style_test.dart new file mode 100644 index 000000000..092a2dbcb --- /dev/null +++ b/test/preference/personal_rating_style_test.dart @@ -0,0 +1,57 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:jellyfin_preference/jellyfin_preference.dart'; +import 'package:moonfin/preference/preference_constants.dart'; +import 'package:moonfin/preference/user_preferences.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +Future _prefs([Map initial = const {}]) async { + SharedPreferences.setMockInitialValues(initial); + final store = PreferenceStore(); + await store.init(); + return UserPreferences(store); +} + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + test('personal rating style defaults to thumbs', () async { + final prefs = await _prefs(); + + expect( + prefs.get(UserPreferences.personalRatingStyle), + PersonalRatingStyle.thumbs, + ); + }); + + test('personal rating style serializes as an enum name', () async { + final prefs = await _prefs(); + await prefs.set( + UserPreferences.personalRatingStyle, + PersonalRatingStyle.numeric, + ); + await prefs.flushPendingWrites(); + + expect( + prefs.get(UserPreferences.personalRatingStyle), + PersonalRatingStyle.numeric, + ); + }); + + test('personal rating style is scoped by active server and user', () async { + final prefs = await _prefs(); + await prefs.set(UserPreferences.lastServerId, 'server-1'); + await prefs.set(UserPreferences.lastUserId, 'user-1'); + await prefs.set( + UserPreferences.personalRatingStyle, + PersonalRatingStyle.stars, + ); + + await prefs.set(UserPreferences.lastServerId, 'server-2'); + await prefs.set(UserPreferences.lastUserId, 'user-2'); + + expect( + prefs.get(UserPreferences.personalRatingStyle), + PersonalRatingStyle.thumbs, + ); + }); +} diff --git a/test/viewmodels/item_detail_rating_view_model_test.dart b/test/viewmodels/item_detail_rating_view_model_test.dart new file mode 100644 index 000000000..3aa326fb0 --- /dev/null +++ b/test/viewmodels/item_detail_rating_view_model_test.dart @@ -0,0 +1,142 @@ +import 'dart:async'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:get_it/get_it.dart'; +import 'package:jellyfin_preference/jellyfin_preference.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:moonfin/data/repositories/item_mutation_repository.dart'; +import 'package:moonfin/data/repositories/mdblist_repository.dart'; +import 'package:moonfin/data/repositories/tmdb_repository.dart'; +import 'package:moonfin/data/viewmodels/item_detail_view_model.dart'; +import 'package:moonfin/preference/user_preferences.dart'; +import 'package:server_core/server_core.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +class _Client extends Mock implements MediaServerClient {} + +class _ItemsApi extends Mock implements ItemsApi {} + +class _UserLibraryApi extends Mock implements UserLibraryApi {} + +Future _prefs() async { + SharedPreferences.setMockInitialValues({}); + final store = PreferenceStore(); + await store.init(); + return UserPreferences(store); +} + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + late _Client client; + late _ItemsApi itemsApi; + late _UserLibraryApi userLibraryApi; + late Map itemData; + + setUp(() async { + await GetIt.instance.reset(); + GetIt.instance.registerSingleton(await _prefs()); + client = _Client(); + itemsApi = _ItemsApi(); + userLibraryApi = _UserLibraryApi(); + itemData = { + 'Id': 'movie-1', + 'Type': 'Movie', + 'UserData': {'Rating': 8.0, 'Likes': true}, + }; + when(() => client.itemsApi).thenReturn(itemsApi); + when(() => client.userLibraryApi).thenReturn(userLibraryApi); + when(() => client.baseUrl).thenReturn('http://server'); + when( + () => itemsApi.getItem( + 'movie-1', + mediaSourceId: any(named: 'mediaSourceId'), + ), + ).thenAnswer((_) async => Map.from(itemData)); + when( + () => itemsApi.getItem('movie-1'), + ).thenAnswer((_) async => Map.from(itemData)); + }); + + tearDown(() => GetIt.instance.reset()); + + ItemDetailViewModel createViewModel() => ItemDetailViewModel( + itemId: 'movie-1', + client: client, + mutations: ItemMutationRepository(client), + mdbListRepository: MdbListRepository(client), + tmdbRepository: TmdbRepository(client), + ); + + test( + 'numeric rating updates optimistically and reloads after success', + () async { + final viewModel = createViewModel(); + await viewModel.load(); + itemData = { + 'Id': 'movie-1', + 'Type': 'Movie', + 'UserData': {'Rating': 9.0, 'Likes': true}, + }; + when( + () => userLibraryApi.updateNumericUserRating('movie-1', rating: 9), + ).thenAnswer((_) async {}); + + await viewModel.setNumericRating(9); + + expect(viewModel.item?.personalRating, 9); + verify( + () => userLibraryApi.updateNumericUserRating('movie-1', rating: 9), + ).called(1); + }, + ); + + test( + 'numeric rating restores the previous value when saving fails', + () async { + final viewModel = createViewModel(); + await viewModel.load(); + final request = Completer(); + when( + () => userLibraryApi.updateNumericUserRating('movie-1', rating: 9), + ).thenAnswer((_) => request.future); + + final result = viewModel.setNumericRating(9); + expect(viewModel.item?.personalRating, 9); + request.completeError(StateError('network failure')); + + await expectLater(result, throwsStateError); + expect(viewModel.item?.personalRating, 8); + }, + ); + + test('numeric rating updates the optimistic like state', () async { + final viewModel = createViewModel(); + await viewModel.load(); + final request = Completer(); + when( + () => userLibraryApi.updateNumericUserRating('movie-1', rating: 4), + ).thenAnswer((_) => request.future); + + final result = viewModel.setNumericRating(4); + + expect(viewModel.item?.personalRating, 4); + expect(viewModel.item?.personalRatingLikes, isFalse); + + request.complete(); + await result; + }); + + test('numeric rating rejects non-finite values', () async { + final viewModel = createViewModel(); + await viewModel.load(); + + await expectLater(viewModel.setNumericRating(double.nan), throwsArgumentError); + verifyNever( + () => userLibraryApi.updateNumericUserRating( + any(), + rating: any(named: 'rating'), + ), + ); + }); +}