mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-05-17 22:04:47 +02:00
i18n: extract hardcoded strings into l10n keys
Move hardcoded UI strings across multiple screens and the notification service into ARB-backed l10n keys so they can be translated via Crowdin. Adds 62 new keys covering sort labels, dialog copy, metadata error snackbars, folder-picker errors, home-tab error states, extensions home feed selector, and all notification titles/bodies. NotificationService now caches an AppLocalizations instance (injected from MainShell via didChangeDependencies) and falls back to English literals when no locale is available.
This commit is contained in:
@@ -5300,6 +5300,298 @@ abstract class AppLocalizations {
|
||||
/// In en, this message translates to:
|
||||
/// **'Samples'**
|
||||
String get audioAnalysisSamples;
|
||||
|
||||
/// Extensions page - subtitle for built-in search provider option
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Search with {providerName}'**
|
||||
String extensionsSearchWith(String providerName);
|
||||
|
||||
/// Extensions page - label for home feed provider selector
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Home Feed Provider'**
|
||||
String get extensionsHomeFeedProvider;
|
||||
|
||||
/// Extensions page - description for home feed provider picker
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Choose which extension provides the home feed on the main screen'**
|
||||
String get extensionsHomeFeedDescription;
|
||||
|
||||
/// Extensions page - home feed provider option: auto
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Auto'**
|
||||
String get extensionsHomeFeedAuto;
|
||||
|
||||
/// Extensions page - subtitle for auto home feed option
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Automatically select the best available'**
|
||||
String get extensionsHomeFeedAutoSubtitle;
|
||||
|
||||
/// Extensions page - subtitle for a specific extension home feed option
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Use {extensionName} home feed'**
|
||||
String extensionsHomeFeedUse(String extensionName);
|
||||
|
||||
/// Extensions page - shown when no installed extension has home feed
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'No extensions with home feed'**
|
||||
String get extensionsNoHomeFeedExtensions;
|
||||
|
||||
/// Sort option - alphabetical ascending
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'A-Z'**
|
||||
String get sortAlphaAsc;
|
||||
|
||||
/// Sort option - alphabetical descending
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Z-A'**
|
||||
String get sortAlphaDesc;
|
||||
|
||||
/// Dialog title when confirming cancellation of an active download
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Cancel download?'**
|
||||
String get cancelDownloadTitle;
|
||||
|
||||
/// Dialog body when confirming cancellation of an active download
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'This will cancel the active download for \"{trackName}\".'**
|
||||
String cancelDownloadContent(String trackName);
|
||||
|
||||
/// Dialog button - keep the active download (do not cancel)
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Keep'**
|
||||
String get cancelDownloadKeep;
|
||||
|
||||
/// Snackbar error when FFmpeg fails to write metadata
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Failed to save metadata via FFmpeg'**
|
||||
String get metadataSaveFailedFfmpeg;
|
||||
|
||||
/// Snackbar error when writing metadata file back to storage fails
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Failed to write metadata back to storage'**
|
||||
String get metadataSaveFailedStorage;
|
||||
|
||||
/// Snackbar shown when folder picker fails to open
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Failed to open folder picker: {error}'**
|
||||
String snackbarFolderPickerFailed(String error);
|
||||
|
||||
/// Error state shown when album fails to load
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Failed to load album'**
|
||||
String get errorLoadAlbum;
|
||||
|
||||
/// Error state shown when playlist fails to load
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Failed to load playlist'**
|
||||
String get errorLoadPlaylist;
|
||||
|
||||
/// Error state shown when artist fails to load
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Failed to load artist'**
|
||||
String get errorLoadArtist;
|
||||
|
||||
/// Android notification channel name for download progress
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Download Progress'**
|
||||
String get notifChannelDownloadName;
|
||||
|
||||
/// Android notification channel description for download progress
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Shows download progress for tracks'**
|
||||
String get notifChannelDownloadDesc;
|
||||
|
||||
/// Android notification channel name for library scan
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Library Scan'**
|
||||
String get notifChannelLibraryScanName;
|
||||
|
||||
/// Android notification channel description for library scan
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Shows local library scan progress'**
|
||||
String get notifChannelLibraryScanDesc;
|
||||
|
||||
/// Notification title while downloading a track
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Downloading {trackName}'**
|
||||
String notifDownloadingTrack(String trackName);
|
||||
|
||||
/// Notification title while finalizing (embedding metadata) a track
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Finalizing {trackName}'**
|
||||
String notifFinalizingTrack(String trackName);
|
||||
|
||||
/// Notification body while embedding metadata into a downloaded track
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Embedding metadata...'**
|
||||
String get notifEmbeddingMetadata;
|
||||
|
||||
/// Notification title when track is already in library, with count
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Already in Library ({completed}/{total})'**
|
||||
String notifAlreadyInLibraryCount(int completed, int total);
|
||||
|
||||
/// Notification title when track is already in library
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Already in Library'**
|
||||
String get notifAlreadyInLibrary;
|
||||
|
||||
/// Notification title when download is complete, with count
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Download Complete ({completed}/{total})'**
|
||||
String notifDownloadCompleteCount(int completed, int total);
|
||||
|
||||
/// Notification title when a single download is complete
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Download Complete'**
|
||||
String get notifDownloadComplete;
|
||||
|
||||
/// Notification title when queue finishes with some failures
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Downloads Finished ({completed} done, {failed} failed)'**
|
||||
String notifDownloadsFinished(int completed, int failed);
|
||||
|
||||
/// Notification title when all downloads finish successfully
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'All Downloads Complete'**
|
||||
String get notifAllDownloadsComplete;
|
||||
|
||||
/// Notification body for queue complete - how many tracks were downloaded
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'{count} tracks downloaded successfully'**
|
||||
String notifTracksDownloadedSuccess(int count);
|
||||
|
||||
/// Notification title while scanning local library
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Scanning local library'**
|
||||
String get notifScanningLibrary;
|
||||
|
||||
/// Notification body for library scan progress when total is known
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'{scanned}/{total} files • {percentage}%'**
|
||||
String notifLibraryScanProgressWithTotal(
|
||||
int scanned,
|
||||
int total,
|
||||
int percentage,
|
||||
);
|
||||
|
||||
/// Notification body for library scan progress when total is unknown
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'{scanned} files scanned • {percentage}%'**
|
||||
String notifLibraryScanProgressNoTotal(int scanned, int percentage);
|
||||
|
||||
/// Notification title when library scan finishes
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Library scan complete'**
|
||||
String get notifLibraryScanComplete;
|
||||
|
||||
/// Notification body for library scan complete - number of indexed tracks
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'{count} tracks indexed'**
|
||||
String notifLibraryScanCompleteBody(int count);
|
||||
|
||||
/// Library scan complete suffix - excluded track count
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'{count} excluded'**
|
||||
String notifLibraryScanExcluded(int count);
|
||||
|
||||
/// Library scan complete suffix - error count
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'{count} errors'**
|
||||
String notifLibraryScanErrors(int count);
|
||||
|
||||
/// Notification title when library scan fails
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Library scan failed'**
|
||||
String get notifLibraryScanFailed;
|
||||
|
||||
/// Notification title when library scan is cancelled by the user
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Library scan cancelled'**
|
||||
String get notifLibraryScanCancelled;
|
||||
|
||||
/// Notification body when library scan is cancelled
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Scan stopped before completion.'**
|
||||
String get notifLibraryScanStopped;
|
||||
|
||||
/// Notification title while downloading an app update
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Downloading SpotiFLAC v{version}'**
|
||||
String notifDownloadingUpdate(String version);
|
||||
|
||||
/// Notification body showing update download progress
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'{received} / {total} MB • {percentage}%'**
|
||||
String notifUpdateProgress(String received, String total, int percentage);
|
||||
|
||||
/// Notification title when app update download is complete
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Update Ready'**
|
||||
String get notifUpdateReady;
|
||||
|
||||
/// Notification body when app update is ready to install
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'SpotiFLAC v{version} downloaded. Tap to install.'**
|
||||
String notifUpdateReadyBody(String version);
|
||||
|
||||
/// Notification title when app update download fails
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Update Failed'**
|
||||
String get notifUpdateFailed;
|
||||
|
||||
/// Notification body when app update download fails
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Could not download update. Try again later.'**
|
||||
String get notifUpdateFailedBody;
|
||||
}
|
||||
|
||||
class _AppLocalizationsDelegate
|
||||
|
||||
@@ -3124,4 +3124,192 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get audioAnalysisSamples => 'Samples';
|
||||
|
||||
@override
|
||||
String extensionsSearchWith(String providerName) {
|
||||
return 'Search with $providerName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedProvider => 'Home Feed Provider';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedDescription =>
|
||||
'Choose which extension provides the home feed on the main screen';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedAuto => 'Auto';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedAutoSubtitle =>
|
||||
'Automatically select the best available';
|
||||
|
||||
@override
|
||||
String extensionsHomeFeedUse(String extensionName) {
|
||||
return 'Use $extensionName home feed';
|
||||
}
|
||||
|
||||
@override
|
||||
String get extensionsNoHomeFeedExtensions => 'No extensions with home feed';
|
||||
|
||||
@override
|
||||
String get sortAlphaAsc => 'A-Z';
|
||||
|
||||
@override
|
||||
String get sortAlphaDesc => 'Z-A';
|
||||
|
||||
@override
|
||||
String get cancelDownloadTitle => 'Cancel download?';
|
||||
|
||||
@override
|
||||
String cancelDownloadContent(String trackName) {
|
||||
return 'This will cancel the active download for \"$trackName\".';
|
||||
}
|
||||
|
||||
@override
|
||||
String get cancelDownloadKeep => 'Keep';
|
||||
|
||||
@override
|
||||
String get metadataSaveFailedFfmpeg => 'Failed to save metadata via FFmpeg';
|
||||
|
||||
@override
|
||||
String get metadataSaveFailedStorage =>
|
||||
'Failed to write metadata back to storage';
|
||||
|
||||
@override
|
||||
String snackbarFolderPickerFailed(String error) {
|
||||
return 'Failed to open folder picker: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get errorLoadAlbum => 'Failed to load album';
|
||||
|
||||
@override
|
||||
String get errorLoadPlaylist => 'Failed to load playlist';
|
||||
|
||||
@override
|
||||
String get errorLoadArtist => 'Failed to load artist';
|
||||
|
||||
@override
|
||||
String get notifChannelDownloadName => 'Download Progress';
|
||||
|
||||
@override
|
||||
String get notifChannelDownloadDesc => 'Shows download progress for tracks';
|
||||
|
||||
@override
|
||||
String get notifChannelLibraryScanName => 'Library Scan';
|
||||
|
||||
@override
|
||||
String get notifChannelLibraryScanDesc => 'Shows local library scan progress';
|
||||
|
||||
@override
|
||||
String notifDownloadingTrack(String trackName) {
|
||||
return 'Downloading $trackName';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifFinalizingTrack(String trackName) {
|
||||
return 'Finalizing $trackName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifEmbeddingMetadata => 'Embedding metadata...';
|
||||
|
||||
@override
|
||||
String notifAlreadyInLibraryCount(int completed, int total) {
|
||||
return 'Already in Library ($completed/$total)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifAlreadyInLibrary => 'Already in Library';
|
||||
|
||||
@override
|
||||
String notifDownloadCompleteCount(int completed, int total) {
|
||||
return 'Download Complete ($completed/$total)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifDownloadComplete => 'Download Complete';
|
||||
|
||||
@override
|
||||
String notifDownloadsFinished(int completed, int failed) {
|
||||
return 'Downloads Finished ($completed done, $failed failed)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifAllDownloadsComplete => 'All Downloads Complete';
|
||||
|
||||
@override
|
||||
String notifTracksDownloadedSuccess(int count) {
|
||||
return '$count tracks downloaded successfully';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifScanningLibrary => 'Scanning local library';
|
||||
|
||||
@override
|
||||
String notifLibraryScanProgressWithTotal(
|
||||
int scanned,
|
||||
int total,
|
||||
int percentage,
|
||||
) {
|
||||
return '$scanned/$total files • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanProgressNoTotal(int scanned, int percentage) {
|
||||
return '$scanned files scanned • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifLibraryScanComplete => 'Library scan complete';
|
||||
|
||||
@override
|
||||
String notifLibraryScanCompleteBody(int count) {
|
||||
return '$count tracks indexed';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanExcluded(int count) {
|
||||
return '$count excluded';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanErrors(int count) {
|
||||
return '$count errors';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifLibraryScanFailed => 'Library scan failed';
|
||||
|
||||
@override
|
||||
String get notifLibraryScanCancelled => 'Library scan cancelled';
|
||||
|
||||
@override
|
||||
String get notifLibraryScanStopped => 'Scan stopped before completion.';
|
||||
|
||||
@override
|
||||
String notifDownloadingUpdate(String version) {
|
||||
return 'Downloading SpotiFLAC v$version';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifUpdateProgress(String received, String total, int percentage) {
|
||||
return '$received / $total MB • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifUpdateReady => 'Update Ready';
|
||||
|
||||
@override
|
||||
String notifUpdateReadyBody(String version) {
|
||||
return 'SpotiFLAC v$version downloaded. Tap to install.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifUpdateFailed => 'Update Failed';
|
||||
|
||||
@override
|
||||
String get notifUpdateFailedBody =>
|
||||
'Could not download update. Try again later.';
|
||||
}
|
||||
|
||||
@@ -3092,4 +3092,192 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get audioAnalysisSamples => 'Samples';
|
||||
|
||||
@override
|
||||
String extensionsSearchWith(String providerName) {
|
||||
return 'Search with $providerName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedProvider => 'Home Feed Provider';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedDescription =>
|
||||
'Choose which extension provides the home feed on the main screen';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedAuto => 'Auto';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedAutoSubtitle =>
|
||||
'Automatically select the best available';
|
||||
|
||||
@override
|
||||
String extensionsHomeFeedUse(String extensionName) {
|
||||
return 'Use $extensionName home feed';
|
||||
}
|
||||
|
||||
@override
|
||||
String get extensionsNoHomeFeedExtensions => 'No extensions with home feed';
|
||||
|
||||
@override
|
||||
String get sortAlphaAsc => 'A-Z';
|
||||
|
||||
@override
|
||||
String get sortAlphaDesc => 'Z-A';
|
||||
|
||||
@override
|
||||
String get cancelDownloadTitle => 'Cancel download?';
|
||||
|
||||
@override
|
||||
String cancelDownloadContent(String trackName) {
|
||||
return 'This will cancel the active download for \"$trackName\".';
|
||||
}
|
||||
|
||||
@override
|
||||
String get cancelDownloadKeep => 'Keep';
|
||||
|
||||
@override
|
||||
String get metadataSaveFailedFfmpeg => 'Failed to save metadata via FFmpeg';
|
||||
|
||||
@override
|
||||
String get metadataSaveFailedStorage =>
|
||||
'Failed to write metadata back to storage';
|
||||
|
||||
@override
|
||||
String snackbarFolderPickerFailed(String error) {
|
||||
return 'Failed to open folder picker: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get errorLoadAlbum => 'Failed to load album';
|
||||
|
||||
@override
|
||||
String get errorLoadPlaylist => 'Failed to load playlist';
|
||||
|
||||
@override
|
||||
String get errorLoadArtist => 'Failed to load artist';
|
||||
|
||||
@override
|
||||
String get notifChannelDownloadName => 'Download Progress';
|
||||
|
||||
@override
|
||||
String get notifChannelDownloadDesc => 'Shows download progress for tracks';
|
||||
|
||||
@override
|
||||
String get notifChannelLibraryScanName => 'Library Scan';
|
||||
|
||||
@override
|
||||
String get notifChannelLibraryScanDesc => 'Shows local library scan progress';
|
||||
|
||||
@override
|
||||
String notifDownloadingTrack(String trackName) {
|
||||
return 'Downloading $trackName';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifFinalizingTrack(String trackName) {
|
||||
return 'Finalizing $trackName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifEmbeddingMetadata => 'Embedding metadata...';
|
||||
|
||||
@override
|
||||
String notifAlreadyInLibraryCount(int completed, int total) {
|
||||
return 'Already in Library ($completed/$total)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifAlreadyInLibrary => 'Already in Library';
|
||||
|
||||
@override
|
||||
String notifDownloadCompleteCount(int completed, int total) {
|
||||
return 'Download Complete ($completed/$total)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifDownloadComplete => 'Download Complete';
|
||||
|
||||
@override
|
||||
String notifDownloadsFinished(int completed, int failed) {
|
||||
return 'Downloads Finished ($completed done, $failed failed)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifAllDownloadsComplete => 'All Downloads Complete';
|
||||
|
||||
@override
|
||||
String notifTracksDownloadedSuccess(int count) {
|
||||
return '$count tracks downloaded successfully';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifScanningLibrary => 'Scanning local library';
|
||||
|
||||
@override
|
||||
String notifLibraryScanProgressWithTotal(
|
||||
int scanned,
|
||||
int total,
|
||||
int percentage,
|
||||
) {
|
||||
return '$scanned/$total files • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanProgressNoTotal(int scanned, int percentage) {
|
||||
return '$scanned files scanned • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifLibraryScanComplete => 'Library scan complete';
|
||||
|
||||
@override
|
||||
String notifLibraryScanCompleteBody(int count) {
|
||||
return '$count tracks indexed';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanExcluded(int count) {
|
||||
return '$count excluded';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanErrors(int count) {
|
||||
return '$count errors';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifLibraryScanFailed => 'Library scan failed';
|
||||
|
||||
@override
|
||||
String get notifLibraryScanCancelled => 'Library scan cancelled';
|
||||
|
||||
@override
|
||||
String get notifLibraryScanStopped => 'Scan stopped before completion.';
|
||||
|
||||
@override
|
||||
String notifDownloadingUpdate(String version) {
|
||||
return 'Downloading SpotiFLAC v$version';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifUpdateProgress(String received, String total, int percentage) {
|
||||
return '$received / $total MB • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifUpdateReady => 'Update Ready';
|
||||
|
||||
@override
|
||||
String notifUpdateReadyBody(String version) {
|
||||
return 'SpotiFLAC v$version downloaded. Tap to install.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifUpdateFailed => 'Update Failed';
|
||||
|
||||
@override
|
||||
String get notifUpdateFailedBody =>
|
||||
'Could not download update. Try again later.';
|
||||
}
|
||||
|
||||
@@ -3092,6 +3092,194 @@ class AppLocalizationsEs extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get audioAnalysisSamples => 'Samples';
|
||||
|
||||
@override
|
||||
String extensionsSearchWith(String providerName) {
|
||||
return 'Search with $providerName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedProvider => 'Home Feed Provider';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedDescription =>
|
||||
'Choose which extension provides the home feed on the main screen';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedAuto => 'Auto';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedAutoSubtitle =>
|
||||
'Automatically select the best available';
|
||||
|
||||
@override
|
||||
String extensionsHomeFeedUse(String extensionName) {
|
||||
return 'Use $extensionName home feed';
|
||||
}
|
||||
|
||||
@override
|
||||
String get extensionsNoHomeFeedExtensions => 'No extensions with home feed';
|
||||
|
||||
@override
|
||||
String get sortAlphaAsc => 'A-Z';
|
||||
|
||||
@override
|
||||
String get sortAlphaDesc => 'Z-A';
|
||||
|
||||
@override
|
||||
String get cancelDownloadTitle => 'Cancel download?';
|
||||
|
||||
@override
|
||||
String cancelDownloadContent(String trackName) {
|
||||
return 'This will cancel the active download for \"$trackName\".';
|
||||
}
|
||||
|
||||
@override
|
||||
String get cancelDownloadKeep => 'Keep';
|
||||
|
||||
@override
|
||||
String get metadataSaveFailedFfmpeg => 'Failed to save metadata via FFmpeg';
|
||||
|
||||
@override
|
||||
String get metadataSaveFailedStorage =>
|
||||
'Failed to write metadata back to storage';
|
||||
|
||||
@override
|
||||
String snackbarFolderPickerFailed(String error) {
|
||||
return 'Failed to open folder picker: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get errorLoadAlbum => 'Failed to load album';
|
||||
|
||||
@override
|
||||
String get errorLoadPlaylist => 'Failed to load playlist';
|
||||
|
||||
@override
|
||||
String get errorLoadArtist => 'Failed to load artist';
|
||||
|
||||
@override
|
||||
String get notifChannelDownloadName => 'Download Progress';
|
||||
|
||||
@override
|
||||
String get notifChannelDownloadDesc => 'Shows download progress for tracks';
|
||||
|
||||
@override
|
||||
String get notifChannelLibraryScanName => 'Library Scan';
|
||||
|
||||
@override
|
||||
String get notifChannelLibraryScanDesc => 'Shows local library scan progress';
|
||||
|
||||
@override
|
||||
String notifDownloadingTrack(String trackName) {
|
||||
return 'Downloading $trackName';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifFinalizingTrack(String trackName) {
|
||||
return 'Finalizing $trackName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifEmbeddingMetadata => 'Embedding metadata...';
|
||||
|
||||
@override
|
||||
String notifAlreadyInLibraryCount(int completed, int total) {
|
||||
return 'Already in Library ($completed/$total)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifAlreadyInLibrary => 'Already in Library';
|
||||
|
||||
@override
|
||||
String notifDownloadCompleteCount(int completed, int total) {
|
||||
return 'Download Complete ($completed/$total)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifDownloadComplete => 'Download Complete';
|
||||
|
||||
@override
|
||||
String notifDownloadsFinished(int completed, int failed) {
|
||||
return 'Downloads Finished ($completed done, $failed failed)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifAllDownloadsComplete => 'All Downloads Complete';
|
||||
|
||||
@override
|
||||
String notifTracksDownloadedSuccess(int count) {
|
||||
return '$count tracks downloaded successfully';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifScanningLibrary => 'Scanning local library';
|
||||
|
||||
@override
|
||||
String notifLibraryScanProgressWithTotal(
|
||||
int scanned,
|
||||
int total,
|
||||
int percentage,
|
||||
) {
|
||||
return '$scanned/$total files • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanProgressNoTotal(int scanned, int percentage) {
|
||||
return '$scanned files scanned • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifLibraryScanComplete => 'Library scan complete';
|
||||
|
||||
@override
|
||||
String notifLibraryScanCompleteBody(int count) {
|
||||
return '$count tracks indexed';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanExcluded(int count) {
|
||||
return '$count excluded';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanErrors(int count) {
|
||||
return '$count errors';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifLibraryScanFailed => 'Library scan failed';
|
||||
|
||||
@override
|
||||
String get notifLibraryScanCancelled => 'Library scan cancelled';
|
||||
|
||||
@override
|
||||
String get notifLibraryScanStopped => 'Scan stopped before completion.';
|
||||
|
||||
@override
|
||||
String notifDownloadingUpdate(String version) {
|
||||
return 'Downloading SpotiFLAC v$version';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifUpdateProgress(String received, String total, int percentage) {
|
||||
return '$received / $total MB • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifUpdateReady => 'Update Ready';
|
||||
|
||||
@override
|
||||
String notifUpdateReadyBody(String version) {
|
||||
return 'SpotiFLAC v$version downloaded. Tap to install.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifUpdateFailed => 'Update Failed';
|
||||
|
||||
@override
|
||||
String get notifUpdateFailedBody =>
|
||||
'Could not download update. Try again later.';
|
||||
}
|
||||
|
||||
/// The translations for Spanish Castilian, as used in Spain (`es_ES`).
|
||||
|
||||
@@ -3093,4 +3093,192 @@ class AppLocalizationsFr extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get audioAnalysisSamples => 'Samples';
|
||||
|
||||
@override
|
||||
String extensionsSearchWith(String providerName) {
|
||||
return 'Search with $providerName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedProvider => 'Home Feed Provider';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedDescription =>
|
||||
'Choose which extension provides the home feed on the main screen';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedAuto => 'Auto';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedAutoSubtitle =>
|
||||
'Automatically select the best available';
|
||||
|
||||
@override
|
||||
String extensionsHomeFeedUse(String extensionName) {
|
||||
return 'Use $extensionName home feed';
|
||||
}
|
||||
|
||||
@override
|
||||
String get extensionsNoHomeFeedExtensions => 'No extensions with home feed';
|
||||
|
||||
@override
|
||||
String get sortAlphaAsc => 'A-Z';
|
||||
|
||||
@override
|
||||
String get sortAlphaDesc => 'Z-A';
|
||||
|
||||
@override
|
||||
String get cancelDownloadTitle => 'Cancel download?';
|
||||
|
||||
@override
|
||||
String cancelDownloadContent(String trackName) {
|
||||
return 'This will cancel the active download for \"$trackName\".';
|
||||
}
|
||||
|
||||
@override
|
||||
String get cancelDownloadKeep => 'Keep';
|
||||
|
||||
@override
|
||||
String get metadataSaveFailedFfmpeg => 'Failed to save metadata via FFmpeg';
|
||||
|
||||
@override
|
||||
String get metadataSaveFailedStorage =>
|
||||
'Failed to write metadata back to storage';
|
||||
|
||||
@override
|
||||
String snackbarFolderPickerFailed(String error) {
|
||||
return 'Failed to open folder picker: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get errorLoadAlbum => 'Failed to load album';
|
||||
|
||||
@override
|
||||
String get errorLoadPlaylist => 'Failed to load playlist';
|
||||
|
||||
@override
|
||||
String get errorLoadArtist => 'Failed to load artist';
|
||||
|
||||
@override
|
||||
String get notifChannelDownloadName => 'Download Progress';
|
||||
|
||||
@override
|
||||
String get notifChannelDownloadDesc => 'Shows download progress for tracks';
|
||||
|
||||
@override
|
||||
String get notifChannelLibraryScanName => 'Library Scan';
|
||||
|
||||
@override
|
||||
String get notifChannelLibraryScanDesc => 'Shows local library scan progress';
|
||||
|
||||
@override
|
||||
String notifDownloadingTrack(String trackName) {
|
||||
return 'Downloading $trackName';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifFinalizingTrack(String trackName) {
|
||||
return 'Finalizing $trackName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifEmbeddingMetadata => 'Embedding metadata...';
|
||||
|
||||
@override
|
||||
String notifAlreadyInLibraryCount(int completed, int total) {
|
||||
return 'Already in Library ($completed/$total)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifAlreadyInLibrary => 'Already in Library';
|
||||
|
||||
@override
|
||||
String notifDownloadCompleteCount(int completed, int total) {
|
||||
return 'Download Complete ($completed/$total)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifDownloadComplete => 'Download Complete';
|
||||
|
||||
@override
|
||||
String notifDownloadsFinished(int completed, int failed) {
|
||||
return 'Downloads Finished ($completed done, $failed failed)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifAllDownloadsComplete => 'All Downloads Complete';
|
||||
|
||||
@override
|
||||
String notifTracksDownloadedSuccess(int count) {
|
||||
return '$count tracks downloaded successfully';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifScanningLibrary => 'Scanning local library';
|
||||
|
||||
@override
|
||||
String notifLibraryScanProgressWithTotal(
|
||||
int scanned,
|
||||
int total,
|
||||
int percentage,
|
||||
) {
|
||||
return '$scanned/$total files • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanProgressNoTotal(int scanned, int percentage) {
|
||||
return '$scanned files scanned • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifLibraryScanComplete => 'Library scan complete';
|
||||
|
||||
@override
|
||||
String notifLibraryScanCompleteBody(int count) {
|
||||
return '$count tracks indexed';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanExcluded(int count) {
|
||||
return '$count excluded';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanErrors(int count) {
|
||||
return '$count errors';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifLibraryScanFailed => 'Library scan failed';
|
||||
|
||||
@override
|
||||
String get notifLibraryScanCancelled => 'Library scan cancelled';
|
||||
|
||||
@override
|
||||
String get notifLibraryScanStopped => 'Scan stopped before completion.';
|
||||
|
||||
@override
|
||||
String notifDownloadingUpdate(String version) {
|
||||
return 'Downloading SpotiFLAC v$version';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifUpdateProgress(String received, String total, int percentage) {
|
||||
return '$received / $total MB • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifUpdateReady => 'Update Ready';
|
||||
|
||||
@override
|
||||
String notifUpdateReadyBody(String version) {
|
||||
return 'SpotiFLAC v$version downloaded. Tap to install.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifUpdateFailed => 'Update Failed';
|
||||
|
||||
@override
|
||||
String get notifUpdateFailedBody =>
|
||||
'Could not download update. Try again later.';
|
||||
}
|
||||
|
||||
@@ -3091,4 +3091,192 @@ class AppLocalizationsHi extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get audioAnalysisSamples => 'Samples';
|
||||
|
||||
@override
|
||||
String extensionsSearchWith(String providerName) {
|
||||
return 'Search with $providerName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedProvider => 'Home Feed Provider';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedDescription =>
|
||||
'Choose which extension provides the home feed on the main screen';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedAuto => 'Auto';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedAutoSubtitle =>
|
||||
'Automatically select the best available';
|
||||
|
||||
@override
|
||||
String extensionsHomeFeedUse(String extensionName) {
|
||||
return 'Use $extensionName home feed';
|
||||
}
|
||||
|
||||
@override
|
||||
String get extensionsNoHomeFeedExtensions => 'No extensions with home feed';
|
||||
|
||||
@override
|
||||
String get sortAlphaAsc => 'A-Z';
|
||||
|
||||
@override
|
||||
String get sortAlphaDesc => 'Z-A';
|
||||
|
||||
@override
|
||||
String get cancelDownloadTitle => 'Cancel download?';
|
||||
|
||||
@override
|
||||
String cancelDownloadContent(String trackName) {
|
||||
return 'This will cancel the active download for \"$trackName\".';
|
||||
}
|
||||
|
||||
@override
|
||||
String get cancelDownloadKeep => 'Keep';
|
||||
|
||||
@override
|
||||
String get metadataSaveFailedFfmpeg => 'Failed to save metadata via FFmpeg';
|
||||
|
||||
@override
|
||||
String get metadataSaveFailedStorage =>
|
||||
'Failed to write metadata back to storage';
|
||||
|
||||
@override
|
||||
String snackbarFolderPickerFailed(String error) {
|
||||
return 'Failed to open folder picker: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get errorLoadAlbum => 'Failed to load album';
|
||||
|
||||
@override
|
||||
String get errorLoadPlaylist => 'Failed to load playlist';
|
||||
|
||||
@override
|
||||
String get errorLoadArtist => 'Failed to load artist';
|
||||
|
||||
@override
|
||||
String get notifChannelDownloadName => 'Download Progress';
|
||||
|
||||
@override
|
||||
String get notifChannelDownloadDesc => 'Shows download progress for tracks';
|
||||
|
||||
@override
|
||||
String get notifChannelLibraryScanName => 'Library Scan';
|
||||
|
||||
@override
|
||||
String get notifChannelLibraryScanDesc => 'Shows local library scan progress';
|
||||
|
||||
@override
|
||||
String notifDownloadingTrack(String trackName) {
|
||||
return 'Downloading $trackName';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifFinalizingTrack(String trackName) {
|
||||
return 'Finalizing $trackName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifEmbeddingMetadata => 'Embedding metadata...';
|
||||
|
||||
@override
|
||||
String notifAlreadyInLibraryCount(int completed, int total) {
|
||||
return 'Already in Library ($completed/$total)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifAlreadyInLibrary => 'Already in Library';
|
||||
|
||||
@override
|
||||
String notifDownloadCompleteCount(int completed, int total) {
|
||||
return 'Download Complete ($completed/$total)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifDownloadComplete => 'Download Complete';
|
||||
|
||||
@override
|
||||
String notifDownloadsFinished(int completed, int failed) {
|
||||
return 'Downloads Finished ($completed done, $failed failed)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifAllDownloadsComplete => 'All Downloads Complete';
|
||||
|
||||
@override
|
||||
String notifTracksDownloadedSuccess(int count) {
|
||||
return '$count tracks downloaded successfully';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifScanningLibrary => 'Scanning local library';
|
||||
|
||||
@override
|
||||
String notifLibraryScanProgressWithTotal(
|
||||
int scanned,
|
||||
int total,
|
||||
int percentage,
|
||||
) {
|
||||
return '$scanned/$total files • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanProgressNoTotal(int scanned, int percentage) {
|
||||
return '$scanned files scanned • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifLibraryScanComplete => 'Library scan complete';
|
||||
|
||||
@override
|
||||
String notifLibraryScanCompleteBody(int count) {
|
||||
return '$count tracks indexed';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanExcluded(int count) {
|
||||
return '$count excluded';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanErrors(int count) {
|
||||
return '$count errors';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifLibraryScanFailed => 'Library scan failed';
|
||||
|
||||
@override
|
||||
String get notifLibraryScanCancelled => 'Library scan cancelled';
|
||||
|
||||
@override
|
||||
String get notifLibraryScanStopped => 'Scan stopped before completion.';
|
||||
|
||||
@override
|
||||
String notifDownloadingUpdate(String version) {
|
||||
return 'Downloading SpotiFLAC v$version';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifUpdateProgress(String received, String total, int percentage) {
|
||||
return '$received / $total MB • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifUpdateReady => 'Update Ready';
|
||||
|
||||
@override
|
||||
String notifUpdateReadyBody(String version) {
|
||||
return 'SpotiFLAC v$version downloaded. Tap to install.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifUpdateFailed => 'Update Failed';
|
||||
|
||||
@override
|
||||
String get notifUpdateFailedBody =>
|
||||
'Could not download update. Try again later.';
|
||||
}
|
||||
|
||||
@@ -3102,4 +3102,192 @@ class AppLocalizationsId extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get audioAnalysisSamples => 'Samples';
|
||||
|
||||
@override
|
||||
String extensionsSearchWith(String providerName) {
|
||||
return 'Search with $providerName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedProvider => 'Home Feed Provider';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedDescription =>
|
||||
'Choose which extension provides the home feed on the main screen';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedAuto => 'Auto';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedAutoSubtitle =>
|
||||
'Automatically select the best available';
|
||||
|
||||
@override
|
||||
String extensionsHomeFeedUse(String extensionName) {
|
||||
return 'Use $extensionName home feed';
|
||||
}
|
||||
|
||||
@override
|
||||
String get extensionsNoHomeFeedExtensions => 'No extensions with home feed';
|
||||
|
||||
@override
|
||||
String get sortAlphaAsc => 'A-Z';
|
||||
|
||||
@override
|
||||
String get sortAlphaDesc => 'Z-A';
|
||||
|
||||
@override
|
||||
String get cancelDownloadTitle => 'Cancel download?';
|
||||
|
||||
@override
|
||||
String cancelDownloadContent(String trackName) {
|
||||
return 'This will cancel the active download for \"$trackName\".';
|
||||
}
|
||||
|
||||
@override
|
||||
String get cancelDownloadKeep => 'Keep';
|
||||
|
||||
@override
|
||||
String get metadataSaveFailedFfmpeg => 'Failed to save metadata via FFmpeg';
|
||||
|
||||
@override
|
||||
String get metadataSaveFailedStorage =>
|
||||
'Failed to write metadata back to storage';
|
||||
|
||||
@override
|
||||
String snackbarFolderPickerFailed(String error) {
|
||||
return 'Failed to open folder picker: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get errorLoadAlbum => 'Failed to load album';
|
||||
|
||||
@override
|
||||
String get errorLoadPlaylist => 'Failed to load playlist';
|
||||
|
||||
@override
|
||||
String get errorLoadArtist => 'Failed to load artist';
|
||||
|
||||
@override
|
||||
String get notifChannelDownloadName => 'Download Progress';
|
||||
|
||||
@override
|
||||
String get notifChannelDownloadDesc => 'Shows download progress for tracks';
|
||||
|
||||
@override
|
||||
String get notifChannelLibraryScanName => 'Library Scan';
|
||||
|
||||
@override
|
||||
String get notifChannelLibraryScanDesc => 'Shows local library scan progress';
|
||||
|
||||
@override
|
||||
String notifDownloadingTrack(String trackName) {
|
||||
return 'Downloading $trackName';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifFinalizingTrack(String trackName) {
|
||||
return 'Finalizing $trackName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifEmbeddingMetadata => 'Embedding metadata...';
|
||||
|
||||
@override
|
||||
String notifAlreadyInLibraryCount(int completed, int total) {
|
||||
return 'Already in Library ($completed/$total)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifAlreadyInLibrary => 'Already in Library';
|
||||
|
||||
@override
|
||||
String notifDownloadCompleteCount(int completed, int total) {
|
||||
return 'Download Complete ($completed/$total)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifDownloadComplete => 'Download Complete';
|
||||
|
||||
@override
|
||||
String notifDownloadsFinished(int completed, int failed) {
|
||||
return 'Downloads Finished ($completed done, $failed failed)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifAllDownloadsComplete => 'All Downloads Complete';
|
||||
|
||||
@override
|
||||
String notifTracksDownloadedSuccess(int count) {
|
||||
return '$count tracks downloaded successfully';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifScanningLibrary => 'Scanning local library';
|
||||
|
||||
@override
|
||||
String notifLibraryScanProgressWithTotal(
|
||||
int scanned,
|
||||
int total,
|
||||
int percentage,
|
||||
) {
|
||||
return '$scanned/$total files • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanProgressNoTotal(int scanned, int percentage) {
|
||||
return '$scanned files scanned • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifLibraryScanComplete => 'Library scan complete';
|
||||
|
||||
@override
|
||||
String notifLibraryScanCompleteBody(int count) {
|
||||
return '$count tracks indexed';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanExcluded(int count) {
|
||||
return '$count excluded';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanErrors(int count) {
|
||||
return '$count errors';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifLibraryScanFailed => 'Library scan failed';
|
||||
|
||||
@override
|
||||
String get notifLibraryScanCancelled => 'Library scan cancelled';
|
||||
|
||||
@override
|
||||
String get notifLibraryScanStopped => 'Scan stopped before completion.';
|
||||
|
||||
@override
|
||||
String notifDownloadingUpdate(String version) {
|
||||
return 'Downloading SpotiFLAC v$version';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifUpdateProgress(String received, String total, int percentage) {
|
||||
return '$received / $total MB • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifUpdateReady => 'Update Ready';
|
||||
|
||||
@override
|
||||
String notifUpdateReadyBody(String version) {
|
||||
return 'SpotiFLAC v$version downloaded. Tap to install.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifUpdateFailed => 'Update Failed';
|
||||
|
||||
@override
|
||||
String get notifUpdateFailedBody =>
|
||||
'Could not download update. Try again later.';
|
||||
}
|
||||
|
||||
@@ -3078,4 +3078,192 @@ class AppLocalizationsJa extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get audioAnalysisSamples => 'Samples';
|
||||
|
||||
@override
|
||||
String extensionsSearchWith(String providerName) {
|
||||
return 'Search with $providerName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedProvider => 'Home Feed Provider';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedDescription =>
|
||||
'Choose which extension provides the home feed on the main screen';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedAuto => 'Auto';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedAutoSubtitle =>
|
||||
'Automatically select the best available';
|
||||
|
||||
@override
|
||||
String extensionsHomeFeedUse(String extensionName) {
|
||||
return 'Use $extensionName home feed';
|
||||
}
|
||||
|
||||
@override
|
||||
String get extensionsNoHomeFeedExtensions => 'No extensions with home feed';
|
||||
|
||||
@override
|
||||
String get sortAlphaAsc => 'A-Z';
|
||||
|
||||
@override
|
||||
String get sortAlphaDesc => 'Z-A';
|
||||
|
||||
@override
|
||||
String get cancelDownloadTitle => 'Cancel download?';
|
||||
|
||||
@override
|
||||
String cancelDownloadContent(String trackName) {
|
||||
return 'This will cancel the active download for \"$trackName\".';
|
||||
}
|
||||
|
||||
@override
|
||||
String get cancelDownloadKeep => 'Keep';
|
||||
|
||||
@override
|
||||
String get metadataSaveFailedFfmpeg => 'Failed to save metadata via FFmpeg';
|
||||
|
||||
@override
|
||||
String get metadataSaveFailedStorage =>
|
||||
'Failed to write metadata back to storage';
|
||||
|
||||
@override
|
||||
String snackbarFolderPickerFailed(String error) {
|
||||
return 'Failed to open folder picker: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get errorLoadAlbum => 'Failed to load album';
|
||||
|
||||
@override
|
||||
String get errorLoadPlaylist => 'Failed to load playlist';
|
||||
|
||||
@override
|
||||
String get errorLoadArtist => 'Failed to load artist';
|
||||
|
||||
@override
|
||||
String get notifChannelDownloadName => 'Download Progress';
|
||||
|
||||
@override
|
||||
String get notifChannelDownloadDesc => 'Shows download progress for tracks';
|
||||
|
||||
@override
|
||||
String get notifChannelLibraryScanName => 'Library Scan';
|
||||
|
||||
@override
|
||||
String get notifChannelLibraryScanDesc => 'Shows local library scan progress';
|
||||
|
||||
@override
|
||||
String notifDownloadingTrack(String trackName) {
|
||||
return 'Downloading $trackName';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifFinalizingTrack(String trackName) {
|
||||
return 'Finalizing $trackName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifEmbeddingMetadata => 'Embedding metadata...';
|
||||
|
||||
@override
|
||||
String notifAlreadyInLibraryCount(int completed, int total) {
|
||||
return 'Already in Library ($completed/$total)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifAlreadyInLibrary => 'Already in Library';
|
||||
|
||||
@override
|
||||
String notifDownloadCompleteCount(int completed, int total) {
|
||||
return 'Download Complete ($completed/$total)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifDownloadComplete => 'Download Complete';
|
||||
|
||||
@override
|
||||
String notifDownloadsFinished(int completed, int failed) {
|
||||
return 'Downloads Finished ($completed done, $failed failed)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifAllDownloadsComplete => 'All Downloads Complete';
|
||||
|
||||
@override
|
||||
String notifTracksDownloadedSuccess(int count) {
|
||||
return '$count tracks downloaded successfully';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifScanningLibrary => 'Scanning local library';
|
||||
|
||||
@override
|
||||
String notifLibraryScanProgressWithTotal(
|
||||
int scanned,
|
||||
int total,
|
||||
int percentage,
|
||||
) {
|
||||
return '$scanned/$total files • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanProgressNoTotal(int scanned, int percentage) {
|
||||
return '$scanned files scanned • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifLibraryScanComplete => 'Library scan complete';
|
||||
|
||||
@override
|
||||
String notifLibraryScanCompleteBody(int count) {
|
||||
return '$count tracks indexed';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanExcluded(int count) {
|
||||
return '$count excluded';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanErrors(int count) {
|
||||
return '$count errors';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifLibraryScanFailed => 'Library scan failed';
|
||||
|
||||
@override
|
||||
String get notifLibraryScanCancelled => 'Library scan cancelled';
|
||||
|
||||
@override
|
||||
String get notifLibraryScanStopped => 'Scan stopped before completion.';
|
||||
|
||||
@override
|
||||
String notifDownloadingUpdate(String version) {
|
||||
return 'Downloading SpotiFLAC v$version';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifUpdateProgress(String received, String total, int percentage) {
|
||||
return '$received / $total MB • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifUpdateReady => 'Update Ready';
|
||||
|
||||
@override
|
||||
String notifUpdateReadyBody(String version) {
|
||||
return 'SpotiFLAC v$version downloaded. Tap to install.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifUpdateFailed => 'Update Failed';
|
||||
|
||||
@override
|
||||
String get notifUpdateFailedBody =>
|
||||
'Could not download update. Try again later.';
|
||||
}
|
||||
|
||||
@@ -3071,4 +3071,192 @@ class AppLocalizationsKo extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get audioAnalysisSamples => 'Samples';
|
||||
|
||||
@override
|
||||
String extensionsSearchWith(String providerName) {
|
||||
return 'Search with $providerName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedProvider => 'Home Feed Provider';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedDescription =>
|
||||
'Choose which extension provides the home feed on the main screen';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedAuto => 'Auto';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedAutoSubtitle =>
|
||||
'Automatically select the best available';
|
||||
|
||||
@override
|
||||
String extensionsHomeFeedUse(String extensionName) {
|
||||
return 'Use $extensionName home feed';
|
||||
}
|
||||
|
||||
@override
|
||||
String get extensionsNoHomeFeedExtensions => 'No extensions with home feed';
|
||||
|
||||
@override
|
||||
String get sortAlphaAsc => 'A-Z';
|
||||
|
||||
@override
|
||||
String get sortAlphaDesc => 'Z-A';
|
||||
|
||||
@override
|
||||
String get cancelDownloadTitle => 'Cancel download?';
|
||||
|
||||
@override
|
||||
String cancelDownloadContent(String trackName) {
|
||||
return 'This will cancel the active download for \"$trackName\".';
|
||||
}
|
||||
|
||||
@override
|
||||
String get cancelDownloadKeep => 'Keep';
|
||||
|
||||
@override
|
||||
String get metadataSaveFailedFfmpeg => 'Failed to save metadata via FFmpeg';
|
||||
|
||||
@override
|
||||
String get metadataSaveFailedStorage =>
|
||||
'Failed to write metadata back to storage';
|
||||
|
||||
@override
|
||||
String snackbarFolderPickerFailed(String error) {
|
||||
return 'Failed to open folder picker: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get errorLoadAlbum => 'Failed to load album';
|
||||
|
||||
@override
|
||||
String get errorLoadPlaylist => 'Failed to load playlist';
|
||||
|
||||
@override
|
||||
String get errorLoadArtist => 'Failed to load artist';
|
||||
|
||||
@override
|
||||
String get notifChannelDownloadName => 'Download Progress';
|
||||
|
||||
@override
|
||||
String get notifChannelDownloadDesc => 'Shows download progress for tracks';
|
||||
|
||||
@override
|
||||
String get notifChannelLibraryScanName => 'Library Scan';
|
||||
|
||||
@override
|
||||
String get notifChannelLibraryScanDesc => 'Shows local library scan progress';
|
||||
|
||||
@override
|
||||
String notifDownloadingTrack(String trackName) {
|
||||
return 'Downloading $trackName';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifFinalizingTrack(String trackName) {
|
||||
return 'Finalizing $trackName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifEmbeddingMetadata => 'Embedding metadata...';
|
||||
|
||||
@override
|
||||
String notifAlreadyInLibraryCount(int completed, int total) {
|
||||
return 'Already in Library ($completed/$total)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifAlreadyInLibrary => 'Already in Library';
|
||||
|
||||
@override
|
||||
String notifDownloadCompleteCount(int completed, int total) {
|
||||
return 'Download Complete ($completed/$total)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifDownloadComplete => 'Download Complete';
|
||||
|
||||
@override
|
||||
String notifDownloadsFinished(int completed, int failed) {
|
||||
return 'Downloads Finished ($completed done, $failed failed)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifAllDownloadsComplete => 'All Downloads Complete';
|
||||
|
||||
@override
|
||||
String notifTracksDownloadedSuccess(int count) {
|
||||
return '$count tracks downloaded successfully';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifScanningLibrary => 'Scanning local library';
|
||||
|
||||
@override
|
||||
String notifLibraryScanProgressWithTotal(
|
||||
int scanned,
|
||||
int total,
|
||||
int percentage,
|
||||
) {
|
||||
return '$scanned/$total files • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanProgressNoTotal(int scanned, int percentage) {
|
||||
return '$scanned files scanned • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifLibraryScanComplete => 'Library scan complete';
|
||||
|
||||
@override
|
||||
String notifLibraryScanCompleteBody(int count) {
|
||||
return '$count tracks indexed';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanExcluded(int count) {
|
||||
return '$count excluded';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanErrors(int count) {
|
||||
return '$count errors';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifLibraryScanFailed => 'Library scan failed';
|
||||
|
||||
@override
|
||||
String get notifLibraryScanCancelled => 'Library scan cancelled';
|
||||
|
||||
@override
|
||||
String get notifLibraryScanStopped => 'Scan stopped before completion.';
|
||||
|
||||
@override
|
||||
String notifDownloadingUpdate(String version) {
|
||||
return 'Downloading SpotiFLAC v$version';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifUpdateProgress(String received, String total, int percentage) {
|
||||
return '$received / $total MB • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifUpdateReady => 'Update Ready';
|
||||
|
||||
@override
|
||||
String notifUpdateReadyBody(String version) {
|
||||
return 'SpotiFLAC v$version downloaded. Tap to install.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifUpdateFailed => 'Update Failed';
|
||||
|
||||
@override
|
||||
String get notifUpdateFailedBody =>
|
||||
'Could not download update. Try again later.';
|
||||
}
|
||||
|
||||
@@ -3091,4 +3091,192 @@ class AppLocalizationsNl extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get audioAnalysisSamples => 'Samples';
|
||||
|
||||
@override
|
||||
String extensionsSearchWith(String providerName) {
|
||||
return 'Search with $providerName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedProvider => 'Home Feed Provider';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedDescription =>
|
||||
'Choose which extension provides the home feed on the main screen';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedAuto => 'Auto';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedAutoSubtitle =>
|
||||
'Automatically select the best available';
|
||||
|
||||
@override
|
||||
String extensionsHomeFeedUse(String extensionName) {
|
||||
return 'Use $extensionName home feed';
|
||||
}
|
||||
|
||||
@override
|
||||
String get extensionsNoHomeFeedExtensions => 'No extensions with home feed';
|
||||
|
||||
@override
|
||||
String get sortAlphaAsc => 'A-Z';
|
||||
|
||||
@override
|
||||
String get sortAlphaDesc => 'Z-A';
|
||||
|
||||
@override
|
||||
String get cancelDownloadTitle => 'Cancel download?';
|
||||
|
||||
@override
|
||||
String cancelDownloadContent(String trackName) {
|
||||
return 'This will cancel the active download for \"$trackName\".';
|
||||
}
|
||||
|
||||
@override
|
||||
String get cancelDownloadKeep => 'Keep';
|
||||
|
||||
@override
|
||||
String get metadataSaveFailedFfmpeg => 'Failed to save metadata via FFmpeg';
|
||||
|
||||
@override
|
||||
String get metadataSaveFailedStorage =>
|
||||
'Failed to write metadata back to storage';
|
||||
|
||||
@override
|
||||
String snackbarFolderPickerFailed(String error) {
|
||||
return 'Failed to open folder picker: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get errorLoadAlbum => 'Failed to load album';
|
||||
|
||||
@override
|
||||
String get errorLoadPlaylist => 'Failed to load playlist';
|
||||
|
||||
@override
|
||||
String get errorLoadArtist => 'Failed to load artist';
|
||||
|
||||
@override
|
||||
String get notifChannelDownloadName => 'Download Progress';
|
||||
|
||||
@override
|
||||
String get notifChannelDownloadDesc => 'Shows download progress for tracks';
|
||||
|
||||
@override
|
||||
String get notifChannelLibraryScanName => 'Library Scan';
|
||||
|
||||
@override
|
||||
String get notifChannelLibraryScanDesc => 'Shows local library scan progress';
|
||||
|
||||
@override
|
||||
String notifDownloadingTrack(String trackName) {
|
||||
return 'Downloading $trackName';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifFinalizingTrack(String trackName) {
|
||||
return 'Finalizing $trackName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifEmbeddingMetadata => 'Embedding metadata...';
|
||||
|
||||
@override
|
||||
String notifAlreadyInLibraryCount(int completed, int total) {
|
||||
return 'Already in Library ($completed/$total)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifAlreadyInLibrary => 'Already in Library';
|
||||
|
||||
@override
|
||||
String notifDownloadCompleteCount(int completed, int total) {
|
||||
return 'Download Complete ($completed/$total)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifDownloadComplete => 'Download Complete';
|
||||
|
||||
@override
|
||||
String notifDownloadsFinished(int completed, int failed) {
|
||||
return 'Downloads Finished ($completed done, $failed failed)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifAllDownloadsComplete => 'All Downloads Complete';
|
||||
|
||||
@override
|
||||
String notifTracksDownloadedSuccess(int count) {
|
||||
return '$count tracks downloaded successfully';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifScanningLibrary => 'Scanning local library';
|
||||
|
||||
@override
|
||||
String notifLibraryScanProgressWithTotal(
|
||||
int scanned,
|
||||
int total,
|
||||
int percentage,
|
||||
) {
|
||||
return '$scanned/$total files • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanProgressNoTotal(int scanned, int percentage) {
|
||||
return '$scanned files scanned • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifLibraryScanComplete => 'Library scan complete';
|
||||
|
||||
@override
|
||||
String notifLibraryScanCompleteBody(int count) {
|
||||
return '$count tracks indexed';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanExcluded(int count) {
|
||||
return '$count excluded';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanErrors(int count) {
|
||||
return '$count errors';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifLibraryScanFailed => 'Library scan failed';
|
||||
|
||||
@override
|
||||
String get notifLibraryScanCancelled => 'Library scan cancelled';
|
||||
|
||||
@override
|
||||
String get notifLibraryScanStopped => 'Scan stopped before completion.';
|
||||
|
||||
@override
|
||||
String notifDownloadingUpdate(String version) {
|
||||
return 'Downloading SpotiFLAC v$version';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifUpdateProgress(String received, String total, int percentage) {
|
||||
return '$received / $total MB • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifUpdateReady => 'Update Ready';
|
||||
|
||||
@override
|
||||
String notifUpdateReadyBody(String version) {
|
||||
return 'SpotiFLAC v$version downloaded. Tap to install.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifUpdateFailed => 'Update Failed';
|
||||
|
||||
@override
|
||||
String get notifUpdateFailedBody =>
|
||||
'Could not download update. Try again later.';
|
||||
}
|
||||
|
||||
@@ -3092,6 +3092,194 @@ class AppLocalizationsPt extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get audioAnalysisSamples => 'Samples';
|
||||
|
||||
@override
|
||||
String extensionsSearchWith(String providerName) {
|
||||
return 'Search with $providerName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedProvider => 'Home Feed Provider';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedDescription =>
|
||||
'Choose which extension provides the home feed on the main screen';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedAuto => 'Auto';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedAutoSubtitle =>
|
||||
'Automatically select the best available';
|
||||
|
||||
@override
|
||||
String extensionsHomeFeedUse(String extensionName) {
|
||||
return 'Use $extensionName home feed';
|
||||
}
|
||||
|
||||
@override
|
||||
String get extensionsNoHomeFeedExtensions => 'No extensions with home feed';
|
||||
|
||||
@override
|
||||
String get sortAlphaAsc => 'A-Z';
|
||||
|
||||
@override
|
||||
String get sortAlphaDesc => 'Z-A';
|
||||
|
||||
@override
|
||||
String get cancelDownloadTitle => 'Cancel download?';
|
||||
|
||||
@override
|
||||
String cancelDownloadContent(String trackName) {
|
||||
return 'This will cancel the active download for \"$trackName\".';
|
||||
}
|
||||
|
||||
@override
|
||||
String get cancelDownloadKeep => 'Keep';
|
||||
|
||||
@override
|
||||
String get metadataSaveFailedFfmpeg => 'Failed to save metadata via FFmpeg';
|
||||
|
||||
@override
|
||||
String get metadataSaveFailedStorage =>
|
||||
'Failed to write metadata back to storage';
|
||||
|
||||
@override
|
||||
String snackbarFolderPickerFailed(String error) {
|
||||
return 'Failed to open folder picker: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get errorLoadAlbum => 'Failed to load album';
|
||||
|
||||
@override
|
||||
String get errorLoadPlaylist => 'Failed to load playlist';
|
||||
|
||||
@override
|
||||
String get errorLoadArtist => 'Failed to load artist';
|
||||
|
||||
@override
|
||||
String get notifChannelDownloadName => 'Download Progress';
|
||||
|
||||
@override
|
||||
String get notifChannelDownloadDesc => 'Shows download progress for tracks';
|
||||
|
||||
@override
|
||||
String get notifChannelLibraryScanName => 'Library Scan';
|
||||
|
||||
@override
|
||||
String get notifChannelLibraryScanDesc => 'Shows local library scan progress';
|
||||
|
||||
@override
|
||||
String notifDownloadingTrack(String trackName) {
|
||||
return 'Downloading $trackName';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifFinalizingTrack(String trackName) {
|
||||
return 'Finalizing $trackName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifEmbeddingMetadata => 'Embedding metadata...';
|
||||
|
||||
@override
|
||||
String notifAlreadyInLibraryCount(int completed, int total) {
|
||||
return 'Already in Library ($completed/$total)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifAlreadyInLibrary => 'Already in Library';
|
||||
|
||||
@override
|
||||
String notifDownloadCompleteCount(int completed, int total) {
|
||||
return 'Download Complete ($completed/$total)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifDownloadComplete => 'Download Complete';
|
||||
|
||||
@override
|
||||
String notifDownloadsFinished(int completed, int failed) {
|
||||
return 'Downloads Finished ($completed done, $failed failed)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifAllDownloadsComplete => 'All Downloads Complete';
|
||||
|
||||
@override
|
||||
String notifTracksDownloadedSuccess(int count) {
|
||||
return '$count tracks downloaded successfully';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifScanningLibrary => 'Scanning local library';
|
||||
|
||||
@override
|
||||
String notifLibraryScanProgressWithTotal(
|
||||
int scanned,
|
||||
int total,
|
||||
int percentage,
|
||||
) {
|
||||
return '$scanned/$total files • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanProgressNoTotal(int scanned, int percentage) {
|
||||
return '$scanned files scanned • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifLibraryScanComplete => 'Library scan complete';
|
||||
|
||||
@override
|
||||
String notifLibraryScanCompleteBody(int count) {
|
||||
return '$count tracks indexed';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanExcluded(int count) {
|
||||
return '$count excluded';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanErrors(int count) {
|
||||
return '$count errors';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifLibraryScanFailed => 'Library scan failed';
|
||||
|
||||
@override
|
||||
String get notifLibraryScanCancelled => 'Library scan cancelled';
|
||||
|
||||
@override
|
||||
String get notifLibraryScanStopped => 'Scan stopped before completion.';
|
||||
|
||||
@override
|
||||
String notifDownloadingUpdate(String version) {
|
||||
return 'Downloading SpotiFLAC v$version';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifUpdateProgress(String received, String total, int percentage) {
|
||||
return '$received / $total MB • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifUpdateReady => 'Update Ready';
|
||||
|
||||
@override
|
||||
String notifUpdateReadyBody(String version) {
|
||||
return 'SpotiFLAC v$version downloaded. Tap to install.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifUpdateFailed => 'Update Failed';
|
||||
|
||||
@override
|
||||
String get notifUpdateFailedBody =>
|
||||
'Could not download update. Try again later.';
|
||||
}
|
||||
|
||||
/// The translations for Portuguese, as used in Portugal (`pt_PT`).
|
||||
|
||||
@@ -3151,4 +3151,192 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get audioAnalysisSamples => 'Samples';
|
||||
|
||||
@override
|
||||
String extensionsSearchWith(String providerName) {
|
||||
return 'Search with $providerName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedProvider => 'Home Feed Provider';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedDescription =>
|
||||
'Choose which extension provides the home feed on the main screen';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedAuto => 'Auto';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedAutoSubtitle =>
|
||||
'Automatically select the best available';
|
||||
|
||||
@override
|
||||
String extensionsHomeFeedUse(String extensionName) {
|
||||
return 'Use $extensionName home feed';
|
||||
}
|
||||
|
||||
@override
|
||||
String get extensionsNoHomeFeedExtensions => 'No extensions with home feed';
|
||||
|
||||
@override
|
||||
String get sortAlphaAsc => 'A-Z';
|
||||
|
||||
@override
|
||||
String get sortAlphaDesc => 'Z-A';
|
||||
|
||||
@override
|
||||
String get cancelDownloadTitle => 'Cancel download?';
|
||||
|
||||
@override
|
||||
String cancelDownloadContent(String trackName) {
|
||||
return 'This will cancel the active download for \"$trackName\".';
|
||||
}
|
||||
|
||||
@override
|
||||
String get cancelDownloadKeep => 'Keep';
|
||||
|
||||
@override
|
||||
String get metadataSaveFailedFfmpeg => 'Failed to save metadata via FFmpeg';
|
||||
|
||||
@override
|
||||
String get metadataSaveFailedStorage =>
|
||||
'Failed to write metadata back to storage';
|
||||
|
||||
@override
|
||||
String snackbarFolderPickerFailed(String error) {
|
||||
return 'Failed to open folder picker: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get errorLoadAlbum => 'Failed to load album';
|
||||
|
||||
@override
|
||||
String get errorLoadPlaylist => 'Failed to load playlist';
|
||||
|
||||
@override
|
||||
String get errorLoadArtist => 'Failed to load artist';
|
||||
|
||||
@override
|
||||
String get notifChannelDownloadName => 'Download Progress';
|
||||
|
||||
@override
|
||||
String get notifChannelDownloadDesc => 'Shows download progress for tracks';
|
||||
|
||||
@override
|
||||
String get notifChannelLibraryScanName => 'Library Scan';
|
||||
|
||||
@override
|
||||
String get notifChannelLibraryScanDesc => 'Shows local library scan progress';
|
||||
|
||||
@override
|
||||
String notifDownloadingTrack(String trackName) {
|
||||
return 'Downloading $trackName';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifFinalizingTrack(String trackName) {
|
||||
return 'Finalizing $trackName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifEmbeddingMetadata => 'Embedding metadata...';
|
||||
|
||||
@override
|
||||
String notifAlreadyInLibraryCount(int completed, int total) {
|
||||
return 'Already in Library ($completed/$total)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifAlreadyInLibrary => 'Already in Library';
|
||||
|
||||
@override
|
||||
String notifDownloadCompleteCount(int completed, int total) {
|
||||
return 'Download Complete ($completed/$total)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifDownloadComplete => 'Download Complete';
|
||||
|
||||
@override
|
||||
String notifDownloadsFinished(int completed, int failed) {
|
||||
return 'Downloads Finished ($completed done, $failed failed)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifAllDownloadsComplete => 'All Downloads Complete';
|
||||
|
||||
@override
|
||||
String notifTracksDownloadedSuccess(int count) {
|
||||
return '$count tracks downloaded successfully';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifScanningLibrary => 'Scanning local library';
|
||||
|
||||
@override
|
||||
String notifLibraryScanProgressWithTotal(
|
||||
int scanned,
|
||||
int total,
|
||||
int percentage,
|
||||
) {
|
||||
return '$scanned/$total files • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanProgressNoTotal(int scanned, int percentage) {
|
||||
return '$scanned files scanned • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifLibraryScanComplete => 'Library scan complete';
|
||||
|
||||
@override
|
||||
String notifLibraryScanCompleteBody(int count) {
|
||||
return '$count tracks indexed';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanExcluded(int count) {
|
||||
return '$count excluded';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanErrors(int count) {
|
||||
return '$count errors';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifLibraryScanFailed => 'Library scan failed';
|
||||
|
||||
@override
|
||||
String get notifLibraryScanCancelled => 'Library scan cancelled';
|
||||
|
||||
@override
|
||||
String get notifLibraryScanStopped => 'Scan stopped before completion.';
|
||||
|
||||
@override
|
||||
String notifDownloadingUpdate(String version) {
|
||||
return 'Downloading SpotiFLAC v$version';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifUpdateProgress(String received, String total, int percentage) {
|
||||
return '$received / $total MB • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifUpdateReady => 'Update Ready';
|
||||
|
||||
@override
|
||||
String notifUpdateReadyBody(String version) {
|
||||
return 'SpotiFLAC v$version downloaded. Tap to install.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifUpdateFailed => 'Update Failed';
|
||||
|
||||
@override
|
||||
String get notifUpdateFailedBody =>
|
||||
'Could not download update. Try again later.';
|
||||
}
|
||||
|
||||
@@ -3097,4 +3097,192 @@ class AppLocalizationsTr extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get audioAnalysisSamples => 'Samples';
|
||||
|
||||
@override
|
||||
String extensionsSearchWith(String providerName) {
|
||||
return 'Search with $providerName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedProvider => 'Home Feed Provider';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedDescription =>
|
||||
'Choose which extension provides the home feed on the main screen';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedAuto => 'Auto';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedAutoSubtitle =>
|
||||
'Automatically select the best available';
|
||||
|
||||
@override
|
||||
String extensionsHomeFeedUse(String extensionName) {
|
||||
return 'Use $extensionName home feed';
|
||||
}
|
||||
|
||||
@override
|
||||
String get extensionsNoHomeFeedExtensions => 'No extensions with home feed';
|
||||
|
||||
@override
|
||||
String get sortAlphaAsc => 'A-Z';
|
||||
|
||||
@override
|
||||
String get sortAlphaDesc => 'Z-A';
|
||||
|
||||
@override
|
||||
String get cancelDownloadTitle => 'Cancel download?';
|
||||
|
||||
@override
|
||||
String cancelDownloadContent(String trackName) {
|
||||
return 'This will cancel the active download for \"$trackName\".';
|
||||
}
|
||||
|
||||
@override
|
||||
String get cancelDownloadKeep => 'Keep';
|
||||
|
||||
@override
|
||||
String get metadataSaveFailedFfmpeg => 'Failed to save metadata via FFmpeg';
|
||||
|
||||
@override
|
||||
String get metadataSaveFailedStorage =>
|
||||
'Failed to write metadata back to storage';
|
||||
|
||||
@override
|
||||
String snackbarFolderPickerFailed(String error) {
|
||||
return 'Failed to open folder picker: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get errorLoadAlbum => 'Failed to load album';
|
||||
|
||||
@override
|
||||
String get errorLoadPlaylist => 'Failed to load playlist';
|
||||
|
||||
@override
|
||||
String get errorLoadArtist => 'Failed to load artist';
|
||||
|
||||
@override
|
||||
String get notifChannelDownloadName => 'Download Progress';
|
||||
|
||||
@override
|
||||
String get notifChannelDownloadDesc => 'Shows download progress for tracks';
|
||||
|
||||
@override
|
||||
String get notifChannelLibraryScanName => 'Library Scan';
|
||||
|
||||
@override
|
||||
String get notifChannelLibraryScanDesc => 'Shows local library scan progress';
|
||||
|
||||
@override
|
||||
String notifDownloadingTrack(String trackName) {
|
||||
return 'Downloading $trackName';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifFinalizingTrack(String trackName) {
|
||||
return 'Finalizing $trackName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifEmbeddingMetadata => 'Embedding metadata...';
|
||||
|
||||
@override
|
||||
String notifAlreadyInLibraryCount(int completed, int total) {
|
||||
return 'Already in Library ($completed/$total)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifAlreadyInLibrary => 'Already in Library';
|
||||
|
||||
@override
|
||||
String notifDownloadCompleteCount(int completed, int total) {
|
||||
return 'Download Complete ($completed/$total)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifDownloadComplete => 'Download Complete';
|
||||
|
||||
@override
|
||||
String notifDownloadsFinished(int completed, int failed) {
|
||||
return 'Downloads Finished ($completed done, $failed failed)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifAllDownloadsComplete => 'All Downloads Complete';
|
||||
|
||||
@override
|
||||
String notifTracksDownloadedSuccess(int count) {
|
||||
return '$count tracks downloaded successfully';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifScanningLibrary => 'Scanning local library';
|
||||
|
||||
@override
|
||||
String notifLibraryScanProgressWithTotal(
|
||||
int scanned,
|
||||
int total,
|
||||
int percentage,
|
||||
) {
|
||||
return '$scanned/$total files • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanProgressNoTotal(int scanned, int percentage) {
|
||||
return '$scanned files scanned • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifLibraryScanComplete => 'Library scan complete';
|
||||
|
||||
@override
|
||||
String notifLibraryScanCompleteBody(int count) {
|
||||
return '$count tracks indexed';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanExcluded(int count) {
|
||||
return '$count excluded';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanErrors(int count) {
|
||||
return '$count errors';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifLibraryScanFailed => 'Library scan failed';
|
||||
|
||||
@override
|
||||
String get notifLibraryScanCancelled => 'Library scan cancelled';
|
||||
|
||||
@override
|
||||
String get notifLibraryScanStopped => 'Scan stopped before completion.';
|
||||
|
||||
@override
|
||||
String notifDownloadingUpdate(String version) {
|
||||
return 'Downloading SpotiFLAC v$version';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifUpdateProgress(String received, String total, int percentage) {
|
||||
return '$received / $total MB • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifUpdateReady => 'Update Ready';
|
||||
|
||||
@override
|
||||
String notifUpdateReadyBody(String version) {
|
||||
return 'SpotiFLAC v$version downloaded. Tap to install.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifUpdateFailed => 'Update Failed';
|
||||
|
||||
@override
|
||||
String get notifUpdateFailedBody =>
|
||||
'Could not download update. Try again later.';
|
||||
}
|
||||
|
||||
@@ -3092,6 +3092,194 @@ class AppLocalizationsZh extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get audioAnalysisSamples => 'Samples';
|
||||
|
||||
@override
|
||||
String extensionsSearchWith(String providerName) {
|
||||
return 'Search with $providerName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedProvider => 'Home Feed Provider';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedDescription =>
|
||||
'Choose which extension provides the home feed on the main screen';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedAuto => 'Auto';
|
||||
|
||||
@override
|
||||
String get extensionsHomeFeedAutoSubtitle =>
|
||||
'Automatically select the best available';
|
||||
|
||||
@override
|
||||
String extensionsHomeFeedUse(String extensionName) {
|
||||
return 'Use $extensionName home feed';
|
||||
}
|
||||
|
||||
@override
|
||||
String get extensionsNoHomeFeedExtensions => 'No extensions with home feed';
|
||||
|
||||
@override
|
||||
String get sortAlphaAsc => 'A-Z';
|
||||
|
||||
@override
|
||||
String get sortAlphaDesc => 'Z-A';
|
||||
|
||||
@override
|
||||
String get cancelDownloadTitle => 'Cancel download?';
|
||||
|
||||
@override
|
||||
String cancelDownloadContent(String trackName) {
|
||||
return 'This will cancel the active download for \"$trackName\".';
|
||||
}
|
||||
|
||||
@override
|
||||
String get cancelDownloadKeep => 'Keep';
|
||||
|
||||
@override
|
||||
String get metadataSaveFailedFfmpeg => 'Failed to save metadata via FFmpeg';
|
||||
|
||||
@override
|
||||
String get metadataSaveFailedStorage =>
|
||||
'Failed to write metadata back to storage';
|
||||
|
||||
@override
|
||||
String snackbarFolderPickerFailed(String error) {
|
||||
return 'Failed to open folder picker: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get errorLoadAlbum => 'Failed to load album';
|
||||
|
||||
@override
|
||||
String get errorLoadPlaylist => 'Failed to load playlist';
|
||||
|
||||
@override
|
||||
String get errorLoadArtist => 'Failed to load artist';
|
||||
|
||||
@override
|
||||
String get notifChannelDownloadName => 'Download Progress';
|
||||
|
||||
@override
|
||||
String get notifChannelDownloadDesc => 'Shows download progress for tracks';
|
||||
|
||||
@override
|
||||
String get notifChannelLibraryScanName => 'Library Scan';
|
||||
|
||||
@override
|
||||
String get notifChannelLibraryScanDesc => 'Shows local library scan progress';
|
||||
|
||||
@override
|
||||
String notifDownloadingTrack(String trackName) {
|
||||
return 'Downloading $trackName';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifFinalizingTrack(String trackName) {
|
||||
return 'Finalizing $trackName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifEmbeddingMetadata => 'Embedding metadata...';
|
||||
|
||||
@override
|
||||
String notifAlreadyInLibraryCount(int completed, int total) {
|
||||
return 'Already in Library ($completed/$total)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifAlreadyInLibrary => 'Already in Library';
|
||||
|
||||
@override
|
||||
String notifDownloadCompleteCount(int completed, int total) {
|
||||
return 'Download Complete ($completed/$total)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifDownloadComplete => 'Download Complete';
|
||||
|
||||
@override
|
||||
String notifDownloadsFinished(int completed, int failed) {
|
||||
return 'Downloads Finished ($completed done, $failed failed)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifAllDownloadsComplete => 'All Downloads Complete';
|
||||
|
||||
@override
|
||||
String notifTracksDownloadedSuccess(int count) {
|
||||
return '$count tracks downloaded successfully';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifScanningLibrary => 'Scanning local library';
|
||||
|
||||
@override
|
||||
String notifLibraryScanProgressWithTotal(
|
||||
int scanned,
|
||||
int total,
|
||||
int percentage,
|
||||
) {
|
||||
return '$scanned/$total files • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanProgressNoTotal(int scanned, int percentage) {
|
||||
return '$scanned files scanned • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifLibraryScanComplete => 'Library scan complete';
|
||||
|
||||
@override
|
||||
String notifLibraryScanCompleteBody(int count) {
|
||||
return '$count tracks indexed';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanExcluded(int count) {
|
||||
return '$count excluded';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifLibraryScanErrors(int count) {
|
||||
return '$count errors';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifLibraryScanFailed => 'Library scan failed';
|
||||
|
||||
@override
|
||||
String get notifLibraryScanCancelled => 'Library scan cancelled';
|
||||
|
||||
@override
|
||||
String get notifLibraryScanStopped => 'Scan stopped before completion.';
|
||||
|
||||
@override
|
||||
String notifDownloadingUpdate(String version) {
|
||||
return 'Downloading SpotiFLAC v$version';
|
||||
}
|
||||
|
||||
@override
|
||||
String notifUpdateProgress(String received, String total, int percentage) {
|
||||
return '$received / $total MB • $percentage%';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifUpdateReady => 'Update Ready';
|
||||
|
||||
@override
|
||||
String notifUpdateReadyBody(String version) {
|
||||
return 'SpotiFLAC v$version downloaded. Tap to install.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get notifUpdateFailed => 'Update Failed';
|
||||
|
||||
@override
|
||||
String get notifUpdateFailedBody =>
|
||||
'Could not download update. Try again later.';
|
||||
}
|
||||
|
||||
/// The translations for Chinese, as used in China (`zh_CN`).
|
||||
|
||||
@@ -4063,5 +4063,317 @@
|
||||
"audioAnalysisSamples": "Samples",
|
||||
"@audioAnalysisSamples": {
|
||||
"description": "Total samples metric label"
|
||||
},
|
||||
|
||||
"extensionsSearchWith": "Search with {providerName}",
|
||||
"@extensionsSearchWith": {
|
||||
"description": "Extensions page - subtitle for built-in search provider option",
|
||||
"placeholders": {
|
||||
"providerName": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"extensionsHomeFeedProvider": "Home Feed Provider",
|
||||
"@extensionsHomeFeedProvider": {
|
||||
"description": "Extensions page - label for home feed provider selector"
|
||||
},
|
||||
"extensionsHomeFeedDescription": "Choose which extension provides the home feed on the main screen",
|
||||
"@extensionsHomeFeedDescription": {
|
||||
"description": "Extensions page - description for home feed provider picker"
|
||||
},
|
||||
"extensionsHomeFeedAuto": "Auto",
|
||||
"@extensionsHomeFeedAuto": {
|
||||
"description": "Extensions page - home feed provider option: auto"
|
||||
},
|
||||
"extensionsHomeFeedAutoSubtitle": "Automatically select the best available",
|
||||
"@extensionsHomeFeedAutoSubtitle": {
|
||||
"description": "Extensions page - subtitle for auto home feed option"
|
||||
},
|
||||
"extensionsHomeFeedUse": "Use {extensionName} home feed",
|
||||
"@extensionsHomeFeedUse": {
|
||||
"description": "Extensions page - subtitle for a specific extension home feed option",
|
||||
"placeholders": {
|
||||
"extensionName": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"extensionsNoHomeFeedExtensions": "No extensions with home feed",
|
||||
"@extensionsNoHomeFeedExtensions": {
|
||||
"description": "Extensions page - shown when no installed extension has home feed"
|
||||
},
|
||||
|
||||
"sortAlphaAsc": "A-Z",
|
||||
"@sortAlphaAsc": {
|
||||
"description": "Sort option - alphabetical ascending"
|
||||
},
|
||||
"sortAlphaDesc": "Z-A",
|
||||
"@sortAlphaDesc": {
|
||||
"description": "Sort option - alphabetical descending"
|
||||
},
|
||||
"cancelDownloadTitle": "Cancel download?",
|
||||
"@cancelDownloadTitle": {
|
||||
"description": "Dialog title when confirming cancellation of an active download"
|
||||
},
|
||||
"cancelDownloadContent": "This will cancel the active download for \"{trackName}\".",
|
||||
"@cancelDownloadContent": {
|
||||
"description": "Dialog body when confirming cancellation of an active download",
|
||||
"placeholders": {
|
||||
"trackName": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"cancelDownloadKeep": "Keep",
|
||||
"@cancelDownloadKeep": {
|
||||
"description": "Dialog button - keep the active download (do not cancel)"
|
||||
},
|
||||
|
||||
"metadataSaveFailedFfmpeg": "Failed to save metadata via FFmpeg",
|
||||
"@metadataSaveFailedFfmpeg": {
|
||||
"description": "Snackbar error when FFmpeg fails to write metadata"
|
||||
},
|
||||
"metadataSaveFailedStorage": "Failed to write metadata back to storage",
|
||||
"@metadataSaveFailedStorage": {
|
||||
"description": "Snackbar error when writing metadata file back to storage fails"
|
||||
},
|
||||
|
||||
"snackbarFolderPickerFailed": "Failed to open folder picker: {error}",
|
||||
"@snackbarFolderPickerFailed": {
|
||||
"description": "Snackbar shown when folder picker fails to open",
|
||||
"placeholders": {
|
||||
"error": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"errorLoadAlbum": "Failed to load album",
|
||||
"@errorLoadAlbum": {
|
||||
"description": "Error state shown when album fails to load"
|
||||
},
|
||||
"errorLoadPlaylist": "Failed to load playlist",
|
||||
"@errorLoadPlaylist": {
|
||||
"description": "Error state shown when playlist fails to load"
|
||||
},
|
||||
"errorLoadArtist": "Failed to load artist",
|
||||
"@errorLoadArtist": {
|
||||
"description": "Error state shown when artist fails to load"
|
||||
},
|
||||
|
||||
"notifChannelDownloadName": "Download Progress",
|
||||
"@notifChannelDownloadName": {
|
||||
"description": "Android notification channel name for download progress"
|
||||
},
|
||||
"notifChannelDownloadDesc": "Shows download progress for tracks",
|
||||
"@notifChannelDownloadDesc": {
|
||||
"description": "Android notification channel description for download progress"
|
||||
},
|
||||
"notifChannelLibraryScanName": "Library Scan",
|
||||
"@notifChannelLibraryScanName": {
|
||||
"description": "Android notification channel name for library scan"
|
||||
},
|
||||
"notifChannelLibraryScanDesc": "Shows local library scan progress",
|
||||
"@notifChannelLibraryScanDesc": {
|
||||
"description": "Android notification channel description for library scan"
|
||||
},
|
||||
"notifDownloadingTrack": "Downloading {trackName}",
|
||||
"@notifDownloadingTrack": {
|
||||
"description": "Notification title while downloading a track",
|
||||
"placeholders": {
|
||||
"trackName": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"notifFinalizingTrack": "Finalizing {trackName}",
|
||||
"@notifFinalizingTrack": {
|
||||
"description": "Notification title while finalizing (embedding metadata) a track",
|
||||
"placeholders": {
|
||||
"trackName": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"notifEmbeddingMetadata": "Embedding metadata...",
|
||||
"@notifEmbeddingMetadata": {
|
||||
"description": "Notification body while embedding metadata into a downloaded track"
|
||||
},
|
||||
"notifAlreadyInLibraryCount": "Already in Library ({completed}/{total})",
|
||||
"@notifAlreadyInLibraryCount": {
|
||||
"description": "Notification title when track is already in library, with count",
|
||||
"placeholders": {
|
||||
"completed": {
|
||||
"type": "int"
|
||||
},
|
||||
"total": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"notifAlreadyInLibrary": "Already in Library",
|
||||
"@notifAlreadyInLibrary": {
|
||||
"description": "Notification title when track is already in library"
|
||||
},
|
||||
"notifDownloadCompleteCount": "Download Complete ({completed}/{total})",
|
||||
"@notifDownloadCompleteCount": {
|
||||
"description": "Notification title when download is complete, with count",
|
||||
"placeholders": {
|
||||
"completed": {
|
||||
"type": "int"
|
||||
},
|
||||
"total": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"notifDownloadComplete": "Download Complete",
|
||||
"@notifDownloadComplete": {
|
||||
"description": "Notification title when a single download is complete"
|
||||
},
|
||||
"notifDownloadsFinished": "Downloads Finished ({completed} done, {failed} failed)",
|
||||
"@notifDownloadsFinished": {
|
||||
"description": "Notification title when queue finishes with some failures",
|
||||
"placeholders": {
|
||||
"completed": {
|
||||
"type": "int"
|
||||
},
|
||||
"failed": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"notifAllDownloadsComplete": "All Downloads Complete",
|
||||
"@notifAllDownloadsComplete": {
|
||||
"description": "Notification title when all downloads finish successfully"
|
||||
},
|
||||
"notifTracksDownloadedSuccess": "{count} tracks downloaded successfully",
|
||||
"@notifTracksDownloadedSuccess": {
|
||||
"description": "Notification body for queue complete - how many tracks were downloaded",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"notifScanningLibrary": "Scanning local library",
|
||||
"@notifScanningLibrary": {
|
||||
"description": "Notification title while scanning local library"
|
||||
},
|
||||
"notifLibraryScanProgressWithTotal": "{scanned}/{total} files • {percentage}%",
|
||||
"@notifLibraryScanProgressWithTotal": {
|
||||
"description": "Notification body for library scan progress when total is known",
|
||||
"placeholders": {
|
||||
"scanned": {
|
||||
"type": "int"
|
||||
},
|
||||
"total": {
|
||||
"type": "int"
|
||||
},
|
||||
"percentage": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"notifLibraryScanProgressNoTotal": "{scanned} files scanned • {percentage}%",
|
||||
"@notifLibraryScanProgressNoTotal": {
|
||||
"description": "Notification body for library scan progress when total is unknown",
|
||||
"placeholders": {
|
||||
"scanned": {
|
||||
"type": "int"
|
||||
},
|
||||
"percentage": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"notifLibraryScanComplete": "Library scan complete",
|
||||
"@notifLibraryScanComplete": {
|
||||
"description": "Notification title when library scan finishes"
|
||||
},
|
||||
"notifLibraryScanCompleteBody": "{count} tracks indexed",
|
||||
"@notifLibraryScanCompleteBody": {
|
||||
"description": "Notification body for library scan complete - number of indexed tracks",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"notifLibraryScanExcluded": "{count} excluded",
|
||||
"@notifLibraryScanExcluded": {
|
||||
"description": "Library scan complete suffix - excluded track count",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"notifLibraryScanErrors": "{count} errors",
|
||||
"@notifLibraryScanErrors": {
|
||||
"description": "Library scan complete suffix - error count",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"notifLibraryScanFailed": "Library scan failed",
|
||||
"@notifLibraryScanFailed": {
|
||||
"description": "Notification title when library scan fails"
|
||||
},
|
||||
"notifLibraryScanCancelled": "Library scan cancelled",
|
||||
"@notifLibraryScanCancelled": {
|
||||
"description": "Notification title when library scan is cancelled by the user"
|
||||
},
|
||||
"notifLibraryScanStopped": "Scan stopped before completion.",
|
||||
"@notifLibraryScanStopped": {
|
||||
"description": "Notification body when library scan is cancelled"
|
||||
},
|
||||
"notifDownloadingUpdate": "Downloading SpotiFLAC v{version}",
|
||||
"@notifDownloadingUpdate": {
|
||||
"description": "Notification title while downloading an app update",
|
||||
"placeholders": {
|
||||
"version": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"notifUpdateProgress": "{received} / {total} MB • {percentage}%",
|
||||
"@notifUpdateProgress": {
|
||||
"description": "Notification body showing update download progress",
|
||||
"placeholders": {
|
||||
"received": {
|
||||
"type": "String"
|
||||
},
|
||||
"total": {
|
||||
"type": "String"
|
||||
},
|
||||
"percentage": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"notifUpdateReady": "Update Ready",
|
||||
"@notifUpdateReady": {
|
||||
"description": "Notification title when app update download is complete"
|
||||
},
|
||||
"notifUpdateReadyBody": "SpotiFLAC v{version} downloaded. Tap to install.",
|
||||
"@notifUpdateReadyBody": {
|
||||
"description": "Notification body when app update is ready to install",
|
||||
"placeholders": {
|
||||
"version": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"notifUpdateFailed": "Update Failed",
|
||||
"@notifUpdateFailed": {
|
||||
"description": "Notification title when app update download fails"
|
||||
},
|
||||
"notifUpdateFailedBody": "Could not download update. Try again later.",
|
||||
"@notifUpdateFailedBody": {
|
||||
"description": "Notification body when app update download fails"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3124,7 +3124,7 @@ class _HomeTabState extends ConsumerState<HomeTab>
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 8),
|
||||
child: FilterChip(
|
||||
label: const Text('All'),
|
||||
label: Text(context.l10n.historyFilterAll),
|
||||
selected: selectedFilter == null,
|
||||
onSelected: (_) {
|
||||
ref.read(trackProvider.notifier).setSearchFilter(null);
|
||||
@@ -4212,7 +4212,7 @@ class _ExtensionAlbumScreenState extends ConsumerState<ExtensionAlbumScreen> {
|
||||
|
||||
if (result == null) {
|
||||
setState(() {
|
||||
_error = 'Failed to load album';
|
||||
_error = context.l10n.errorLoadAlbum;
|
||||
_isLoading = false;
|
||||
});
|
||||
return;
|
||||
@@ -4221,7 +4221,7 @@ class _ExtensionAlbumScreenState extends ConsumerState<ExtensionAlbumScreen> {
|
||||
final trackList = result['tracks'] as List<dynamic>?;
|
||||
if (trackList == null) {
|
||||
setState(() {
|
||||
_error = 'No tracks found';
|
||||
_error = context.l10n.errorNoTracksFound;
|
||||
_isLoading = false;
|
||||
});
|
||||
return;
|
||||
@@ -4243,7 +4243,7 @@ class _ExtensionAlbumScreenState extends ConsumerState<ExtensionAlbumScreen> {
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_error = 'Error: $e';
|
||||
_error = context.l10n.snackbarError(e.toString());
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
@@ -4376,7 +4376,7 @@ class _ExtensionPlaylistScreenState
|
||||
|
||||
if (result == null) {
|
||||
setState(() {
|
||||
_error = 'Failed to load playlist';
|
||||
_error = context.l10n.errorLoadPlaylist;
|
||||
_isLoading = false;
|
||||
});
|
||||
return;
|
||||
@@ -4385,7 +4385,7 @@ class _ExtensionPlaylistScreenState
|
||||
final trackList = result['tracks'] as List<dynamic>?;
|
||||
if (trackList == null) {
|
||||
setState(() {
|
||||
_error = 'No tracks found';
|
||||
_error = context.l10n.errorNoTracksFound;
|
||||
_isLoading = false;
|
||||
});
|
||||
return;
|
||||
@@ -4402,7 +4402,7 @@ class _ExtensionPlaylistScreenState
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_error = 'Error: $e';
|
||||
_error = context.l10n.snackbarError(e.toString());
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
@@ -4528,7 +4528,7 @@ class _ExtensionArtistScreenState extends ConsumerState<ExtensionArtistScreen> {
|
||||
|
||||
if (result == null) {
|
||||
setState(() {
|
||||
_error = 'Failed to load artist';
|
||||
_error = context.l10n.errorLoadArtist;
|
||||
_isLoading = false;
|
||||
});
|
||||
return;
|
||||
@@ -4562,7 +4562,7 @@ class _ExtensionArtistScreenState extends ConsumerState<ExtensionArtistScreen> {
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_error = 'Error: $e';
|
||||
_error = context.l10n.snackbarError(e.toString());
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import 'package:spotiflac_android/screens/settings/settings_tab.dart';
|
||||
import 'package:spotiflac_android/services/platform_bridge.dart';
|
||||
import 'package:spotiflac_android/services/shell_navigation_service.dart';
|
||||
import 'package:spotiflac_android/services/share_intent_service.dart';
|
||||
import 'package:spotiflac_android/services/notification_service.dart';
|
||||
import 'package:spotiflac_android/services/update_checker.dart';
|
||||
import 'package:spotiflac_android/widgets/update_dialog.dart';
|
||||
import 'package:spotiflac_android/widgets/animation_utils.dart';
|
||||
@@ -47,6 +48,12 @@ class _MainShellState extends ConsumerState<MainShell>
|
||||
final GlobalKey<NavigatorState> _repoTabNavigatorKey =
|
||||
ShellNavigationService.repoTabNavigatorKey;
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
NotificationService().updateStrings(context.l10n);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
@@ -2174,13 +2174,13 @@ class _QueueTabState extends ConsumerState<QueueTab> {
|
||||
),
|
||||
),
|
||||
FilterChip(
|
||||
label: const Text('A-Z'),
|
||||
label: Text(context.l10n.sortAlphaAsc),
|
||||
selected: tempSortMode == 'a-z',
|
||||
onSelected: (_) =>
|
||||
setSheetState(() => tempSortMode = 'a-z'),
|
||||
),
|
||||
FilterChip(
|
||||
label: const Text('Z-A'),
|
||||
label: Text(context.l10n.sortAlphaDesc),
|
||||
selected: tempSortMode == 'z-a',
|
||||
onSelected: (_) =>
|
||||
setSheetState(() => tempSortMode = 'z-a'),
|
||||
@@ -5461,18 +5461,18 @@ class _QueueTabState extends ConsumerState<QueueTab> {
|
||||
return await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (ctx) => AlertDialog(
|
||||
title: const Text('Cancel download?'),
|
||||
title: Text(context.l10n.cancelDownloadTitle),
|
||||
content: Text(
|
||||
'This will cancel the active download for "${item.track.name}".',
|
||||
context.l10n.cancelDownloadContent(item.track.name),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(ctx).pop(false),
|
||||
child: const Text('Keep'),
|
||||
child: Text(context.l10n.cancelDownloadKeep),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(ctx).pop(true),
|
||||
child: const Text('Cancel'),
|
||||
child: Text(context.l10n.dialogCancel),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -1359,7 +1359,9 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
if (ctx.mounted) {
|
||||
ScaffoldMessenger.of(ctx).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Failed to open folder picker: $e'),
|
||||
content: Text(
|
||||
ctx.l10n.snackbarFolderPickerFailed(e.toString()),
|
||||
),
|
||||
backgroundColor: Theme.of(ctx).colorScheme.error,
|
||||
duration: const Duration(seconds: 4),
|
||||
),
|
||||
|
||||
@@ -735,7 +735,7 @@ class _SearchProviderSelector extends ConsumerWidget {
|
||||
(entry) => ListTile(
|
||||
leading: Icon(Icons.search, color: colorScheme.tertiary),
|
||||
title: Text(entry.value),
|
||||
subtitle: Text('Search with ${entry.value}'),
|
||||
subtitle: Text(ctx.l10n.extensionsSearchWith(entry.value)),
|
||||
trailing: settings.searchProvider == entry.key
|
||||
? Icon(Icons.check_circle, color: colorScheme.primary)
|
||||
: Icon(Icons.circle_outlined, color: colorScheme.outline),
|
||||
@@ -791,7 +791,7 @@ class _HomeFeedProviderSelector extends ConsumerWidget {
|
||||
|
||||
final hasAnyProvider = homeFeedProviders.isNotEmpty;
|
||||
|
||||
String currentProviderName = 'Auto';
|
||||
String currentProviderName = context.l10n.extensionsHomeFeedAuto;
|
||||
if (settings.homeFeedProvider != null &&
|
||||
settings.homeFeedProvider!.isNotEmpty) {
|
||||
final ext = homeFeedProviders
|
||||
@@ -828,7 +828,7 @@ class _HomeFeedProviderSelector extends ConsumerWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Home Feed Provider',
|
||||
context.l10n.extensionsHomeFeedProvider,
|
||||
style: Theme.of(context).textTheme.bodyLarge?.copyWith(
|
||||
color: !hasAnyProvider ? colorScheme.outline : null,
|
||||
),
|
||||
@@ -836,7 +836,7 @@ class _HomeFeedProviderSelector extends ConsumerWidget {
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
!hasAnyProvider
|
||||
? 'No extensions with home feed'
|
||||
? context.l10n.extensionsNoHomeFeedExtensions
|
||||
: currentProviderName,
|
||||
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
@@ -883,7 +883,7 @@ class _HomeFeedProviderSelector extends ConsumerWidget {
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 24, 24, 8),
|
||||
child: Text(
|
||||
'Home Feed Provider',
|
||||
ctx.l10n.extensionsHomeFeedProvider,
|
||||
style: Theme.of(
|
||||
context,
|
||||
).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.bold),
|
||||
@@ -892,7 +892,7 @@ class _HomeFeedProviderSelector extends ConsumerWidget {
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 0, 24, 16),
|
||||
child: Text(
|
||||
'Choose which extension provides the home feed on the main screen',
|
||||
ctx.l10n.extensionsHomeFeedDescription,
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
@@ -900,8 +900,8 @@ class _HomeFeedProviderSelector extends ConsumerWidget {
|
||||
),
|
||||
ListTile(
|
||||
leading: Icon(Icons.auto_awesome, color: colorScheme.primary),
|
||||
title: const Text('Auto'),
|
||||
subtitle: const Text('Automatically select the best available'),
|
||||
title: Text(ctx.l10n.extensionsHomeFeedAuto),
|
||||
subtitle: Text(ctx.l10n.extensionsHomeFeedAutoSubtitle),
|
||||
trailing:
|
||||
(settings.homeFeedProvider == null ||
|
||||
settings.homeFeedProvider!.isEmpty)
|
||||
@@ -917,7 +917,9 @@ class _HomeFeedProviderSelector extends ConsumerWidget {
|
||||
(ext) => ListTile(
|
||||
leading: Icon(Icons.extension, color: colorScheme.secondary),
|
||||
title: Text(ext.displayName),
|
||||
subtitle: Text('Use ${ext.displayName} home feed'),
|
||||
subtitle: Text(
|
||||
ctx.l10n.extensionsHomeFeedUse(ext.displayName),
|
||||
),
|
||||
trailing: settings.homeFeedProvider == ext.id
|
||||
? Icon(Icons.check_circle, color: colorScheme.primary)
|
||||
: Icon(Icons.circle_outlined, color: colorScheme.outline),
|
||||
|
||||
@@ -307,9 +307,9 @@ class OptionsSettingsPage extends ConsumerWidget {
|
||||
} catch (e) {
|
||||
if (context.mounted) {
|
||||
Navigator.pop(context); // Close loading dialog
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text('Error: $e')));
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text(context.l10n.snackbarError(e.toString()))),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,7 +339,9 @@ class _SetupScreenState extends ConsumerState<SetupScreen> {
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Failed to open folder picker: $e'),
|
||||
content: Text(
|
||||
context.l10n.snackbarFolderPickerFailed(e.toString()),
|
||||
),
|
||||
backgroundColor: Theme.of(context).colorScheme.error,
|
||||
duration: const Duration(seconds: 4),
|
||||
),
|
||||
@@ -430,9 +432,9 @@ class _SetupScreenState extends ConsumerState<SetupScreen> {
|
||||
if (mounted) context.go('/tutorial');
|
||||
} catch (e) {
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text('Error: $e')));
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text(context.l10n.snackbarError(e.toString()))),
|
||||
);
|
||||
}
|
||||
} finally {
|
||||
setState(() => _isLoading = false);
|
||||
|
||||
@@ -5025,9 +5025,7 @@ class _EditMetadataSheetState extends State<_EditMetadataSheet> {
|
||||
if (ffmpegResult == null) {
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Failed to save metadata via FFmpeg'),
|
||||
),
|
||||
SnackBar(content: Text(context.l10n.metadataSaveFailedFfmpeg)),
|
||||
);
|
||||
}
|
||||
setState(() => _saving = false);
|
||||
@@ -5038,9 +5036,7 @@ class _EditMetadataSheetState extends State<_EditMetadataSheet> {
|
||||
final ok = await PlatformBridge.writeTempToSaf(ffmpegResult, safUri);
|
||||
if (!ok && mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Failed to write metadata back to storage'),
|
||||
),
|
||||
SnackBar(content: Text(context.l10n.metadataSaveFailedStorage)),
|
||||
);
|
||||
setState(() => _saving = false);
|
||||
return;
|
||||
@@ -5094,7 +5090,7 @@ class _EditMetadataSheetState extends State<_EditMetadataSheet> {
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Edit Metadata',
|
||||
context.l10n.trackEditMetadata,
|
||||
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
@@ -5107,7 +5103,10 @@ class _EditMetadataSheetState extends State<_EditMetadataSheet> {
|
||||
child: CircularProgressIndicator(strokeWidth: 2),
|
||||
)
|
||||
else
|
||||
FilledButton(onPressed: _save, child: const Text('Save')),
|
||||
FilledButton(
|
||||
onPressed: _save,
|
||||
child: Text(context.l10n.dialogSave),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:spotiflac_android/l10n/app_localizations.dart';
|
||||
|
||||
class NotificationService {
|
||||
static final NotificationService _instance = NotificationService._internal();
|
||||
@@ -13,6 +14,13 @@ class NotificationService {
|
||||
FlutterLocalNotificationsPlugin();
|
||||
bool _isInitialized = false;
|
||||
bool _notificationPermissionRequested = false;
|
||||
AppLocalizations? _l10n;
|
||||
|
||||
/// Call this from the widget tree (e.g. didChangeDependencies) whenever the
|
||||
/// app locale changes so that notification strings stay in sync.
|
||||
void updateStrings(AppLocalizations l10n) {
|
||||
_l10n = l10n;
|
||||
}
|
||||
|
||||
static const int downloadProgressId = 1;
|
||||
static const int updateDownloadId = 2;
|
||||
@@ -165,7 +173,8 @@ class NotificationService {
|
||||
|
||||
await _showSafely(
|
||||
id: downloadProgressId,
|
||||
title: 'Downloading $trackName',
|
||||
title:
|
||||
_l10n?.notifDownloadingTrack(trackName) ?? 'Downloading $trackName',
|
||||
body: '$artistName • $percentage%',
|
||||
details: details,
|
||||
);
|
||||
@@ -208,8 +217,9 @@ class NotificationService {
|
||||
|
||||
await _showSafely(
|
||||
id: downloadProgressId,
|
||||
title: 'Finalizing $trackName',
|
||||
body: '$artistName • Embedding metadata...',
|
||||
title: _l10n?.notifFinalizingTrack(trackName) ?? 'Finalizing $trackName',
|
||||
body:
|
||||
'$artistName • ${_l10n?.notifEmbeddingMetadata ?? 'Embedding metadata...'}',
|
||||
details: details,
|
||||
);
|
||||
}
|
||||
@@ -226,12 +236,14 @@ class NotificationService {
|
||||
String title;
|
||||
if (alreadyInLibrary) {
|
||||
title = completedCount != null && totalCount != null
|
||||
? 'Already in Library ($completedCount/$totalCount)'
|
||||
: 'Already in Library';
|
||||
? (_l10n?.notifAlreadyInLibraryCount(completedCount, totalCount) ??
|
||||
'Already in Library ($completedCount/$totalCount)')
|
||||
: (_l10n?.notifAlreadyInLibrary ?? 'Already in Library');
|
||||
} else {
|
||||
title = completedCount != null && totalCount != null
|
||||
? 'Download Complete ($completedCount/$totalCount)'
|
||||
: 'Download Complete';
|
||||
? (_l10n?.notifDownloadCompleteCount(completedCount, totalCount) ??
|
||||
'Download Complete ($completedCount/$totalCount)')
|
||||
: (_l10n?.notifDownloadComplete ?? 'Download Complete');
|
||||
}
|
||||
|
||||
const androidDetails = AndroidNotificationDetails(
|
||||
@@ -271,8 +283,9 @@ class NotificationService {
|
||||
if (!_isInitialized) await initialize();
|
||||
|
||||
final title = failedCount > 0
|
||||
? 'Downloads Finished ($completedCount done, $failedCount failed)'
|
||||
: 'All Downloads Complete';
|
||||
? (_l10n?.notifDownloadsFinished(completedCount, failedCount) ??
|
||||
'Downloads Finished ($completedCount done, $failedCount failed)')
|
||||
: (_l10n?.notifAllDownloadsComplete ?? 'All Downloads Complete');
|
||||
|
||||
const androidDetails = AndroidNotificationDetails(
|
||||
channelId,
|
||||
@@ -299,7 +312,9 @@ class NotificationService {
|
||||
await _showSafely(
|
||||
id: downloadProgressId,
|
||||
title: title,
|
||||
body: '$completedCount tracks downloaded successfully',
|
||||
body:
|
||||
_l10n?.notifTracksDownloadedSuccess(completedCount) ??
|
||||
'$completedCount tracks downloaded successfully',
|
||||
details: details,
|
||||
);
|
||||
}
|
||||
@@ -319,8 +334,14 @@ class NotificationService {
|
||||
final clampedProgress = progress.clamp(0.0, 100.0);
|
||||
final percentage = clampedProgress.round();
|
||||
final progressBody = totalFiles > 0
|
||||
? '$scannedFiles/$totalFiles files • $percentage%'
|
||||
: '$scannedFiles files scanned • $percentage%';
|
||||
? (_l10n?.notifLibraryScanProgressWithTotal(
|
||||
scannedFiles,
|
||||
totalFiles,
|
||||
percentage,
|
||||
) ??
|
||||
'$scannedFiles/$totalFiles files • $percentage%')
|
||||
: (_l10n?.notifLibraryScanProgressNoTotal(scannedFiles, percentage) ??
|
||||
'$scannedFiles files scanned • $percentage%');
|
||||
final body = (currentFile != null && currentFile.isNotEmpty)
|
||||
? '$progressBody\n$currentFile'
|
||||
: progressBody;
|
||||
@@ -355,7 +376,7 @@ class NotificationService {
|
||||
|
||||
await _showSafely(
|
||||
id: libraryScanId,
|
||||
title: 'Scanning local library',
|
||||
title: _l10n?.notifScanningLibrary ?? 'Scanning local library',
|
||||
body: body,
|
||||
details: details,
|
||||
);
|
||||
@@ -370,10 +391,15 @@ class NotificationService {
|
||||
|
||||
final extras = <String>[];
|
||||
if (excludedDownloadedCount > 0) {
|
||||
extras.add('$excludedDownloadedCount excluded');
|
||||
extras.add(
|
||||
_l10n?.notifLibraryScanExcluded(excludedDownloadedCount) ??
|
||||
'$excludedDownloadedCount excluded',
|
||||
);
|
||||
}
|
||||
if (errorCount > 0) {
|
||||
extras.add('$errorCount errors');
|
||||
extras.add(
|
||||
_l10n?.notifLibraryScanErrors(errorCount) ?? '$errorCount errors',
|
||||
);
|
||||
}
|
||||
final suffix = extras.isEmpty ? '' : ' (${extras.join(', ')})';
|
||||
|
||||
@@ -401,8 +427,9 @@ class NotificationService {
|
||||
|
||||
await _showSafely(
|
||||
id: libraryScanId,
|
||||
title: 'Library scan complete',
|
||||
body: '$totalTracks tracks indexed$suffix',
|
||||
title: _l10n?.notifLibraryScanComplete ?? 'Library scan complete',
|
||||
body:
|
||||
'${_l10n?.notifLibraryScanCompleteBody(totalTracks) ?? '$totalTracks tracks indexed'}$suffix',
|
||||
details: details,
|
||||
);
|
||||
}
|
||||
@@ -434,7 +461,7 @@ class NotificationService {
|
||||
|
||||
await _showSafely(
|
||||
id: libraryScanId,
|
||||
title: 'Library scan failed',
|
||||
title: _l10n?.notifLibraryScanFailed ?? 'Library scan failed',
|
||||
body: message,
|
||||
details: details,
|
||||
);
|
||||
@@ -467,8 +494,8 @@ class NotificationService {
|
||||
|
||||
await _showSafely(
|
||||
id: libraryScanId,
|
||||
title: 'Library scan cancelled',
|
||||
body: 'Scan stopped before completion.',
|
||||
title: _l10n?.notifLibraryScanCancelled ?? 'Library scan cancelled',
|
||||
body: _l10n?.notifLibraryScanStopped ?? 'Scan stopped before completion.',
|
||||
details: details,
|
||||
);
|
||||
}
|
||||
@@ -518,8 +545,12 @@ class NotificationService {
|
||||
|
||||
await _showSafely(
|
||||
id: updateDownloadId,
|
||||
title: 'Downloading SpotiFLAC v$version',
|
||||
body: '$receivedMB / $totalMB MB • $percentage%',
|
||||
title:
|
||||
_l10n?.notifDownloadingUpdate(version) ??
|
||||
'Downloading SpotiFLAC v$version',
|
||||
body:
|
||||
_l10n?.notifUpdateProgress(receivedMB, totalMB, percentage) ??
|
||||
'$receivedMB / $totalMB MB • $percentage%',
|
||||
details: details,
|
||||
);
|
||||
}
|
||||
@@ -551,8 +582,10 @@ class NotificationService {
|
||||
|
||||
await _showSafely(
|
||||
id: updateDownloadId,
|
||||
title: 'Update Ready',
|
||||
body: 'SpotiFLAC v$version downloaded. Tap to install.',
|
||||
title: _l10n?.notifUpdateReady ?? 'Update Ready',
|
||||
body:
|
||||
_l10n?.notifUpdateReadyBody(version) ??
|
||||
'SpotiFLAC v$version downloaded. Tap to install.',
|
||||
details: details,
|
||||
);
|
||||
}
|
||||
@@ -583,8 +616,10 @@ class NotificationService {
|
||||
|
||||
await _showSafely(
|
||||
id: updateDownloadId,
|
||||
title: 'Update Failed',
|
||||
body: 'Could not download update. Try again later.',
|
||||
title: _l10n?.notifUpdateFailed ?? 'Update Failed',
|
||||
body:
|
||||
_l10n?.notifUpdateFailedBody ??
|
||||
'Could not download update. Try again later.',
|
||||
details: details,
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user