mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-05-16 05:29:15 +02:00
feat(i18n): replace all hardcoded strings with l10n keys across 13 screens
- Added 80+ new keys to app_en.arb covering lyrics, SAF, download settings, snackbars, dialogs, home, cache, and store screens - Replaced hardcoded strings in main_shell, album_screen, playlist_screen, library_tracks_folder_screen, home_tab, settings_tab, download_settings_page, lyrics_provider_priority_page, track_metadata_screen, extension_detail_page, cache_management_page, local_album_screen, downloaded_album_screen, search_screen - Fixed structural bug in track_metadata_screen (duplicate closing brace) - Added missing l10n.dart import to search_screen.dart - Regenerated all app_localizations*.dart files via flutter gen-l10n
This commit is contained in:
@@ -256,7 +256,7 @@ abstract class AppLocalizations {
|
||||
/// **'Filename Format'**
|
||||
String get downloadFilenameFormat;
|
||||
|
||||
/// Setting for folder structure
|
||||
/// Title of the folder organization picker bottom sheet
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Folder Organization'**
|
||||
@@ -2236,6 +2236,84 @@ abstract class AppLocalizations {
|
||||
/// **'Clear filters'**
|
||||
String get storeClearFilters;
|
||||
|
||||
/// Store setup screen - heading when no repo is configured
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Add Extension Repository'**
|
||||
String get storeAddRepoTitle;
|
||||
|
||||
/// Store setup screen - explanatory text
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Enter a GitHub repository URL that contains a registry.json file to browse and install extensions.'**
|
||||
String get storeAddRepoDescription;
|
||||
|
||||
/// Label for the repository URL input field
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Repository URL'**
|
||||
String get storeRepoUrlLabel;
|
||||
|
||||
/// Hint/placeholder for the repository URL input field
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'https://github.com/user/repo'**
|
||||
String get storeRepoUrlHint;
|
||||
|
||||
/// Helper text below the repository URL input field
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'e.g. https://github.com/user/extensions-repo'**
|
||||
String get storeRepoUrlHelper;
|
||||
|
||||
/// Button to submit a new repository URL
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Add Repository'**
|
||||
String get storeAddRepoButton;
|
||||
|
||||
/// Tooltip for the change-repository icon button in the app bar
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Change repository'**
|
||||
String get storeChangeRepoTooltip;
|
||||
|
||||
/// Title of the change/remove repository dialog
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Extension Repository'**
|
||||
String get storeRepoDialogTitle;
|
||||
|
||||
/// Label shown above the current repository URL in the dialog
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Current repository:'**
|
||||
String get storeRepoDialogCurrent;
|
||||
|
||||
/// Label for the new repository URL field inside the dialog
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'New Repository URL'**
|
||||
String get storeNewRepoUrlLabel;
|
||||
|
||||
/// Error heading when the store cannot be loaded
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Failed to load store'**
|
||||
String get storeLoadError;
|
||||
|
||||
/// Message when store has no extensions
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'No extensions available'**
|
||||
String get storeEmptyNoExtensions;
|
||||
|
||||
/// Message when search/filter returns no results
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'No extensions found'**
|
||||
String get storeEmptyNoResults;
|
||||
|
||||
/// Default search provider option
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
@@ -4205,6 +4283,540 @@ abstract class AppLocalizations {
|
||||
/// In en, this message translates to:
|
||||
/// **'Artist folders use Track Artist only'**
|
||||
String get downloadUseAlbumArtistForFoldersTrackSubtitle;
|
||||
|
||||
/// Title for the lyrics provider priority page
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Lyrics Providers'**
|
||||
String get lyricsProvidersTitle;
|
||||
|
||||
/// Description on the lyrics provider priority page
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Enable, disable and reorder lyrics sources. Providers are tried top-to-bottom until lyrics are found.'**
|
||||
String get lyricsProvidersDescription;
|
||||
|
||||
/// Info tip on lyrics provider priority page
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Extension lyrics providers always run before built-in providers. At least one provider must remain enabled.'**
|
||||
String get lyricsProvidersInfoText;
|
||||
|
||||
/// Section header for enabled providers
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Enabled ({count})'**
|
||||
String lyricsProvidersEnabledSection(int count);
|
||||
|
||||
/// Section header for disabled providers
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Disabled ({count})'**
|
||||
String lyricsProvidersDisabledSection(int count);
|
||||
|
||||
/// Snackbar when user tries to disable the last enabled provider
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'At least one provider must remain enabled'**
|
||||
String get lyricsProvidersAtLeastOne;
|
||||
|
||||
/// Snackbar after saving lyrics provider priority
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Lyrics provider priority saved'**
|
||||
String get lyricsProvidersSaved;
|
||||
|
||||
/// Body text of the discard-changes dialog on lyrics provider page
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'You have unsaved changes that will be lost.'**
|
||||
String get lyricsProvidersDiscardContent;
|
||||
|
||||
/// Description for Spotify Lyrics API provider
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Spotify-sourced synced lyrics via community API'**
|
||||
String get lyricsProviderSpotifyApiDesc;
|
||||
|
||||
/// Description for LRCLIB provider
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Open-source synced lyrics database'**
|
||||
String get lyricsProviderLrclibDesc;
|
||||
|
||||
/// Description for Netease provider
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'NetEase Cloud Music (good for Asian songs)'**
|
||||
String get lyricsProviderNeteaseDesc;
|
||||
|
||||
/// Description for Musixmatch provider
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Largest lyrics database (multi-language)'**
|
||||
String get lyricsProviderMusixmatchDesc;
|
||||
|
||||
/// Description for Apple Music provider
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Word-by-word synced lyrics (via proxy)'**
|
||||
String get lyricsProviderAppleMusicDesc;
|
||||
|
||||
/// Description for QQ Music provider
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'QQ Music (good for Chinese songs, via proxy)'**
|
||||
String get lyricsProviderQqMusicDesc;
|
||||
|
||||
/// Generic description for extension-based lyrics providers
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Extension provider'**
|
||||
String get lyricsProviderExtensionDesc;
|
||||
|
||||
/// Title of SAF migration dialog
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Storage Update Required'**
|
||||
String get safMigrationTitle;
|
||||
|
||||
/// First paragraph of SAF migration dialog
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'SpotiFLAC now uses Android Storage Access Framework (SAF) for downloads. This fixes \"permission denied\" errors on Android 10+.'**
|
||||
String get safMigrationMessage1;
|
||||
|
||||
/// Second paragraph of SAF migration dialog
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Please select your download folder again to switch to the new storage system.'**
|
||||
String get safMigrationMessage2;
|
||||
|
||||
/// Snackbar after successfully migrating to SAF
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Download folder updated to SAF mode'**
|
||||
String get safMigrationSuccess;
|
||||
|
||||
/// Settings menu item - donate
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Donate'**
|
||||
String get settingsDonate;
|
||||
|
||||
/// Subtitle for donate menu item
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Support SpotiFLAC-Mobile development'**
|
||||
String get settingsDonateSubtitle;
|
||||
|
||||
/// Tooltip for the Love All button on album/playlist screens
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Love All'**
|
||||
String get tooltipLoveAll;
|
||||
|
||||
/// Tooltip for the Add to Playlist button
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Add to Playlist'**
|
||||
String get tooltipAddToPlaylist;
|
||||
|
||||
/// Snackbar after removing multiple tracks from Loved folder
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Removed {count} tracks from Loved'**
|
||||
String snackbarRemovedTracksFromLoved(int count);
|
||||
|
||||
/// Snackbar after adding multiple tracks to Loved folder
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Added {count} tracks to Loved'**
|
||||
String snackbarAddedTracksToLoved(int count);
|
||||
|
||||
/// Title of the Download All confirmation dialog
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Download All'**
|
||||
String get dialogDownloadAllTitle;
|
||||
|
||||
/// Body of the Download All confirmation dialog
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Download {count} tracks?'**
|
||||
String dialogDownloadAllMessage(int count);
|
||||
|
||||
/// Confirm button in Download All dialog
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Download'**
|
||||
String get dialogDownload;
|
||||
|
||||
/// Checkbox label in import dialog to skip already-downloaded songs
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Skip already downloaded songs'**
|
||||
String get homeSkipAlreadyDownloaded;
|
||||
|
||||
/// Context menu item to navigate to the album page
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Go to Album'**
|
||||
String get homeGoToAlbum;
|
||||
|
||||
/// Snackbar when album info cannot be loaded
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Album info not available'**
|
||||
String get homeAlbumInfoUnavailable;
|
||||
|
||||
/// Snackbar while loading a CUE sheet file
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Loading CUE sheet...'**
|
||||
String get snackbarLoadingCueSheet;
|
||||
|
||||
/// Snackbar after successfully saving track metadata
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Metadata saved successfully'**
|
||||
String get snackbarMetadataSaved;
|
||||
|
||||
/// Snackbar when lyrics embedding fails
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Failed to embed lyrics'**
|
||||
String get snackbarFailedToEmbedLyrics;
|
||||
|
||||
/// Snackbar when writing metadata back to file fails
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Failed to write back to storage'**
|
||||
String get snackbarFailedToWriteStorage;
|
||||
|
||||
/// Generic error snackbar with error detail
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Error: {error}'**
|
||||
String snackbarError(String error);
|
||||
|
||||
/// Snackbar when an extension button has no action configured
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'No action defined for this button'**
|
||||
String get snackbarNoActionDefined;
|
||||
|
||||
/// Empty state message when an album has no tracks
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'No tracks found for this album'**
|
||||
String get noTracksFoundForAlbum;
|
||||
|
||||
/// Subtitle text in Android download location bottom sheet
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Choose storage mode for downloaded files.'**
|
||||
String get downloadLocationSubtitle;
|
||||
|
||||
/// Storage mode option - use legacy app folder
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'App folder (non-SAF)'**
|
||||
String get storageModeAppFolder;
|
||||
|
||||
/// Subtitle for app folder storage mode
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Use default Music/SpotiFLAC path'**
|
||||
String get storageModeAppFolderSubtitle;
|
||||
|
||||
/// Storage mode option - use Android SAF picker
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'SAF folder'**
|
||||
String get storageModeSaf;
|
||||
|
||||
/// Subtitle for SAF storage mode
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Pick folder via Android Storage Access Framework'**
|
||||
String get storageModeSafSubtitle;
|
||||
|
||||
/// Description text in filename format bottom sheet
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Customize how your files are named.'**
|
||||
String get downloadFilenameDescription;
|
||||
|
||||
/// Label above filename tag chips
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Tap to insert tag:'**
|
||||
String get downloadFilenameInsertTag;
|
||||
|
||||
/// Subtitle when separate singles folder is enabled
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Albums/ and Singles/ folders'**
|
||||
String get downloadSeparateSinglesEnabled;
|
||||
|
||||
/// Subtitle when separate singles folder is disabled
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'All files in same structure'**
|
||||
String get downloadSeparateSinglesDisabled;
|
||||
|
||||
/// Setting title for artist folder filter options
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Artist Name Filters'**
|
||||
String get downloadArtistNameFilters;
|
||||
|
||||
/// Setting title for SongLink country region
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'SongLink Region'**
|
||||
String get downloadSongLinkRegion;
|
||||
|
||||
/// Setting title for network compatibility toggle
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Network compatibility mode'**
|
||||
String get downloadNetworkCompatibilityMode;
|
||||
|
||||
/// Subtitle when network compatibility mode is enabled
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Enabled: try HTTP + accept invalid TLS certificates (unsafe)'**
|
||||
String get downloadNetworkCompatibilityModeEnabled;
|
||||
|
||||
/// Subtitle when network compatibility mode is disabled
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Off: strict HTTPS certificate validation (recommended)'**
|
||||
String get downloadNetworkCompatibilityModeDisabled;
|
||||
|
||||
/// Hint shown instead of Ask-quality subtitle when no built-in service selected
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Select a built-in service to enable'**
|
||||
String get downloadSelectServiceToEnable;
|
||||
|
||||
/// Quality option label for Tidal lossy 320kbps
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Lossy 320kbps'**
|
||||
String get downloadLossy320;
|
||||
|
||||
/// Setting title to pick output format for Tidal lossy downloads
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Lossy Format'**
|
||||
String get downloadLossyFormat;
|
||||
|
||||
/// Info hint when non-Tidal/Qobuz service is selected
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Select Tidal or Qobuz above to configure quality'**
|
||||
String get downloadSelectTidalQobuz;
|
||||
|
||||
/// Subtitle for Embed Lyrics when Embed Metadata is disabled
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Disabled while Embed Metadata is turned off'**
|
||||
String get downloadEmbedLyricsDisabled;
|
||||
|
||||
/// Toggle title for including Netease translated lyrics
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Netease: Include Translation'**
|
||||
String get downloadNeteaseIncludeTranslation;
|
||||
|
||||
/// Subtitle when Netease translation is enabled
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Append translated lyrics when available'**
|
||||
String get downloadNeteaseIncludeTranslationEnabled;
|
||||
|
||||
/// Subtitle when Netease translation is disabled
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Use original lyrics only'**
|
||||
String get downloadNeteaseIncludeTranslationDisabled;
|
||||
|
||||
/// Toggle title for including Netease romanized lyrics
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Netease: Include Romanization'**
|
||||
String get downloadNeteaseIncludeRomanization;
|
||||
|
||||
/// Subtitle when Netease romanization is enabled
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Append romanized lyrics when available'**
|
||||
String get downloadNeteaseIncludeRomanizationEnabled;
|
||||
|
||||
/// Subtitle when Netease romanization is disabled
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Disabled'**
|
||||
String get downloadNeteaseIncludeRomanizationDisabled;
|
||||
|
||||
/// Toggle title for Apple/QQ multi-person word-by-word lyrics
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Apple/QQ Multi-Person Word-by-Word'**
|
||||
String get downloadAppleQqMultiPerson;
|
||||
|
||||
/// Subtitle when multi-person word-by-word is enabled
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Enable v1/v2 speaker and [bg:] tags'**
|
||||
String get downloadAppleQqMultiPersonEnabled;
|
||||
|
||||
/// Subtitle when multi-person word-by-word is disabled
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Simplified word-by-word formatting'**
|
||||
String get downloadAppleQqMultiPersonDisabled;
|
||||
|
||||
/// Setting title for Musixmatch language preference
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Musixmatch Language'**
|
||||
String get downloadMusixmatchLanguage;
|
||||
|
||||
/// Option label when Musixmatch uses original language
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Auto (original)'**
|
||||
String get downloadMusixmatchLanguageAuto;
|
||||
|
||||
/// Toggle title for filtering contributing artists in Album Artist metadata
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Filter contributing artists in Album Artist'**
|
||||
String get downloadFilterContributing;
|
||||
|
||||
/// Subtitle when contributing artist filter is enabled
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Album Artist metadata uses primary artist only'**
|
||||
String get downloadFilterContributingEnabled;
|
||||
|
||||
/// Subtitle when contributing artist filter is disabled
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Keep full Album Artist metadata value'**
|
||||
String get downloadFilterContributingDisabled;
|
||||
|
||||
/// Subtitle for lyrics providers setting when no providers are enabled
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'None enabled'**
|
||||
String get downloadProvidersNoneEnabled;
|
||||
|
||||
/// Label for the Musixmatch language code text field
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Language code'**
|
||||
String get downloadMusixmatchLanguageCode;
|
||||
|
||||
/// Hint text for the Musixmatch language code field
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'auto / en / es / ja'**
|
||||
String get downloadMusixmatchLanguageHint;
|
||||
|
||||
/// Description in the Musixmatch language picker
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Set preferred language code (example: en, es, ja). Leave empty for auto.'**
|
||||
String get downloadMusixmatchLanguageDesc;
|
||||
|
||||
/// Button to reset Musixmatch language to automatic
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Auto'**
|
||||
String get downloadMusixmatchAuto;
|
||||
|
||||
/// Title of the Tidal lossy format picker bottom sheet
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Lossy 320kbps Format'**
|
||||
String get downloadLossy320Format;
|
||||
|
||||
/// Description in the Tidal lossy format picker
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Choose the output format for Tidal 320kbps lossy downloads. The original AAC stream will be converted to your selected format.'**
|
||||
String get downloadLossy320FormatDesc;
|
||||
|
||||
/// Tidal lossy format option - MP3 320kbps
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'MP3 320kbps'**
|
||||
String get downloadLossyMp3;
|
||||
|
||||
/// Subtitle for MP3 320kbps option
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Best compatibility, ~10MB per track'**
|
||||
String get downloadLossyMp3Subtitle;
|
||||
|
||||
/// Tidal lossy format option - Opus 256kbps
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Opus 256kbps'**
|
||||
String get downloadLossyOpus256;
|
||||
|
||||
/// Subtitle for Opus 256kbps option
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Best quality Opus, ~8MB per track'**
|
||||
String get downloadLossyOpus256Subtitle;
|
||||
|
||||
/// Tidal lossy format option - Opus 128kbps
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Opus 128kbps'**
|
||||
String get downloadLossyOpus128;
|
||||
|
||||
/// Subtitle for Opus 128kbps option
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Smallest size, ~4MB per track'**
|
||||
String get downloadLossyOpus128Subtitle;
|
||||
|
||||
/// Subtitle for 'Any' network mode option
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'WiFi + Mobile Data'**
|
||||
String get downloadNetworkAnySubtitle;
|
||||
|
||||
/// Subtitle for 'WiFi only' network mode option
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Pause downloads on mobile data'**
|
||||
String get downloadNetworkWifiOnlySubtitle;
|
||||
|
||||
/// Description in the SongLink region picker
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Used as userCountry for SongLink API lookup.'**
|
||||
String get downloadSongLinkRegionDesc;
|
||||
|
||||
/// Snackbar when the audio format is not supported for the requested operation
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Unsupported audio format'**
|
||||
String get snackbarUnsupportedAudioFormat;
|
||||
|
||||
/// Tooltip for refresh button on cache management page
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Refresh'**
|
||||
String get cacheRefresh;
|
||||
}
|
||||
|
||||
class _AppLocalizationsDelegate
|
||||
|
||||
@@ -1215,6 +1215,47 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||
@override
|
||||
String get storeClearFilters => 'Filter entfernen';
|
||||
|
||||
@override
|
||||
String get storeAddRepoTitle => 'Add Extension Repository';
|
||||
|
||||
@override
|
||||
String get storeAddRepoDescription =>
|
||||
'Enter a GitHub repository URL that contains a registry.json file to browse and install extensions.';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlLabel => 'Repository URL';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlHint => 'https://github.com/user/repo';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlHelper =>
|
||||
'e.g. https://github.com/user/extensions-repo';
|
||||
|
||||
@override
|
||||
String get storeAddRepoButton => 'Add Repository';
|
||||
|
||||
@override
|
||||
String get storeChangeRepoTooltip => 'Change repository';
|
||||
|
||||
@override
|
||||
String get storeRepoDialogTitle => 'Extension Repository';
|
||||
|
||||
@override
|
||||
String get storeRepoDialogCurrent => 'Current repository:';
|
||||
|
||||
@override
|
||||
String get storeNewRepoUrlLabel => 'New Repository URL';
|
||||
|
||||
@override
|
||||
String get storeLoadError => 'Failed to load store';
|
||||
|
||||
@override
|
||||
String get storeEmptyNoExtensions => 'No extensions available';
|
||||
|
||||
@override
|
||||
String get storeEmptyNoResults => 'No extensions found';
|
||||
|
||||
@override
|
||||
String get extensionDefaultProvider => 'Standard (Deezer/Spotify)';
|
||||
|
||||
@@ -2436,4 +2477,317 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||
@override
|
||||
String get downloadUseAlbumArtistForFoldersTrackSubtitle =>
|
||||
'Artist folders use Track Artist only';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersTitle => 'Lyrics Providers';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersDescription =>
|
||||
'Enable, disable and reorder lyrics sources. Providers are tried top-to-bottom until lyrics are found.';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersInfoText =>
|
||||
'Extension lyrics providers always run before built-in providers. At least one provider must remain enabled.';
|
||||
|
||||
@override
|
||||
String lyricsProvidersEnabledSection(int count) {
|
||||
return 'Enabled ($count)';
|
||||
}
|
||||
|
||||
@override
|
||||
String lyricsProvidersDisabledSection(int count) {
|
||||
return 'Disabled ($count)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get lyricsProvidersAtLeastOne =>
|
||||
'At least one provider must remain enabled';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersSaved => 'Lyrics provider priority saved';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersDiscardContent =>
|
||||
'You have unsaved changes that will be lost.';
|
||||
|
||||
@override
|
||||
String get lyricsProviderSpotifyApiDesc =>
|
||||
'Spotify-sourced synced lyrics via community API';
|
||||
|
||||
@override
|
||||
String get lyricsProviderLrclibDesc => 'Open-source synced lyrics database';
|
||||
|
||||
@override
|
||||
String get lyricsProviderNeteaseDesc =>
|
||||
'NetEase Cloud Music (good for Asian songs)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderMusixmatchDesc =>
|
||||
'Largest lyrics database (multi-language)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderAppleMusicDesc =>
|
||||
'Word-by-word synced lyrics (via proxy)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderQqMusicDesc =>
|
||||
'QQ Music (good for Chinese songs, via proxy)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderExtensionDesc => 'Extension provider';
|
||||
|
||||
@override
|
||||
String get safMigrationTitle => 'Storage Update Required';
|
||||
|
||||
@override
|
||||
String get safMigrationMessage1 =>
|
||||
'SpotiFLAC now uses Android Storage Access Framework (SAF) for downloads. This fixes \"permission denied\" errors on Android 10+.';
|
||||
|
||||
@override
|
||||
String get safMigrationMessage2 =>
|
||||
'Please select your download folder again to switch to the new storage system.';
|
||||
|
||||
@override
|
||||
String get safMigrationSuccess => 'Download folder updated to SAF mode';
|
||||
|
||||
@override
|
||||
String get settingsDonate => 'Donate';
|
||||
|
||||
@override
|
||||
String get settingsDonateSubtitle => 'Support SpotiFLAC-Mobile development';
|
||||
|
||||
@override
|
||||
String get tooltipLoveAll => 'Love All';
|
||||
|
||||
@override
|
||||
String get tooltipAddToPlaylist => 'Add to Playlist';
|
||||
|
||||
@override
|
||||
String snackbarRemovedTracksFromLoved(int count) {
|
||||
return 'Removed $count tracks from Loved';
|
||||
}
|
||||
|
||||
@override
|
||||
String snackbarAddedTracksToLoved(int count) {
|
||||
return 'Added $count tracks to Loved';
|
||||
}
|
||||
|
||||
@override
|
||||
String get dialogDownloadAllTitle => 'Download All';
|
||||
|
||||
@override
|
||||
String dialogDownloadAllMessage(int count) {
|
||||
return 'Download $count tracks?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get dialogDownload => 'Download';
|
||||
|
||||
@override
|
||||
String get homeSkipAlreadyDownloaded => 'Skip already downloaded songs';
|
||||
|
||||
@override
|
||||
String get homeGoToAlbum => 'Go to Album';
|
||||
|
||||
@override
|
||||
String get homeAlbumInfoUnavailable => 'Album info not available';
|
||||
|
||||
@override
|
||||
String get snackbarLoadingCueSheet => 'Loading CUE sheet...';
|
||||
|
||||
@override
|
||||
String get snackbarMetadataSaved => 'Metadata saved successfully';
|
||||
|
||||
@override
|
||||
String get snackbarFailedToEmbedLyrics => 'Failed to embed lyrics';
|
||||
|
||||
@override
|
||||
String get snackbarFailedToWriteStorage => 'Failed to write back to storage';
|
||||
|
||||
@override
|
||||
String snackbarError(String error) {
|
||||
return 'Error: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get snackbarNoActionDefined => 'No action defined for this button';
|
||||
|
||||
@override
|
||||
String get noTracksFoundForAlbum => 'No tracks found for this album';
|
||||
|
||||
@override
|
||||
String get downloadLocationSubtitle =>
|
||||
'Choose storage mode for downloaded files.';
|
||||
|
||||
@override
|
||||
String get storageModeAppFolder => 'App folder (non-SAF)';
|
||||
|
||||
@override
|
||||
String get storageModeAppFolderSubtitle => 'Use default Music/SpotiFLAC path';
|
||||
|
||||
@override
|
||||
String get storageModeSaf => 'SAF folder';
|
||||
|
||||
@override
|
||||
String get storageModeSafSubtitle =>
|
||||
'Pick folder via Android Storage Access Framework';
|
||||
|
||||
@override
|
||||
String get downloadFilenameDescription =>
|
||||
'Customize how your files are named.';
|
||||
|
||||
@override
|
||||
String get downloadFilenameInsertTag => 'Tap to insert tag:';
|
||||
|
||||
@override
|
||||
String get downloadSeparateSinglesEnabled => 'Albums/ and Singles/ folders';
|
||||
|
||||
@override
|
||||
String get downloadSeparateSinglesDisabled => 'All files in same structure';
|
||||
|
||||
@override
|
||||
String get downloadArtistNameFilters => 'Artist Name Filters';
|
||||
|
||||
@override
|
||||
String get downloadSongLinkRegion => 'SongLink Region';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityMode => 'Network compatibility mode';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityModeEnabled =>
|
||||
'Enabled: try HTTP + accept invalid TLS certificates (unsafe)';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityModeDisabled =>
|
||||
'Off: strict HTTPS certificate validation (recommended)';
|
||||
|
||||
@override
|
||||
String get downloadSelectServiceToEnable =>
|
||||
'Select a built-in service to enable';
|
||||
|
||||
@override
|
||||
String get downloadLossy320 => 'Lossy 320kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyFormat => 'Lossy Format';
|
||||
|
||||
@override
|
||||
String get downloadSelectTidalQobuz =>
|
||||
'Select Tidal or Qobuz above to configure quality';
|
||||
|
||||
@override
|
||||
String get downloadEmbedLyricsDisabled =>
|
||||
'Disabled while Embed Metadata is turned off';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslation =>
|
||||
'Netease: Include Translation';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslationEnabled =>
|
||||
'Append translated lyrics when available';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslationDisabled =>
|
||||
'Use original lyrics only';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanization =>
|
||||
'Netease: Include Romanization';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanizationEnabled =>
|
||||
'Append romanized lyrics when available';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanizationDisabled => 'Disabled';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPerson => 'Apple/QQ Multi-Person Word-by-Word';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPersonEnabled =>
|
||||
'Enable v1/v2 speaker and [bg:] tags';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPersonDisabled =>
|
||||
'Simplified word-by-word formatting';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguage => 'Musixmatch Language';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageAuto => 'Auto (original)';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributing =>
|
||||
'Filter contributing artists in Album Artist';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributingEnabled =>
|
||||
'Album Artist metadata uses primary artist only';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributingDisabled =>
|
||||
'Keep full Album Artist metadata value';
|
||||
|
||||
@override
|
||||
String get downloadProvidersNoneEnabled => 'None enabled';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageCode => 'Language code';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageHint => 'auto / en / es / ja';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageDesc =>
|
||||
'Set preferred language code (example: en, es, ja). Leave empty for auto.';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchAuto => 'Auto';
|
||||
|
||||
@override
|
||||
String get downloadLossy320Format => 'Lossy 320kbps Format';
|
||||
|
||||
@override
|
||||
String get downloadLossy320FormatDesc =>
|
||||
'Choose the output format for Tidal 320kbps lossy downloads. The original AAC stream will be converted to your selected format.';
|
||||
|
||||
@override
|
||||
String get downloadLossyMp3 => 'MP3 320kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyMp3Subtitle => 'Best compatibility, ~10MB per track';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus256 => 'Opus 256kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus256Subtitle =>
|
||||
'Best quality Opus, ~8MB per track';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus128 => 'Opus 128kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus128Subtitle => 'Smallest size, ~4MB per track';
|
||||
|
||||
@override
|
||||
String get downloadNetworkAnySubtitle => 'WiFi + Mobile Data';
|
||||
|
||||
@override
|
||||
String get downloadNetworkWifiOnlySubtitle =>
|
||||
'Pause downloads on mobile data';
|
||||
|
||||
@override
|
||||
String get downloadSongLinkRegionDesc =>
|
||||
'Used as userCountry for SongLink API lookup.';
|
||||
|
||||
@override
|
||||
String get snackbarUnsupportedAudioFormat => 'Unsupported audio format';
|
||||
|
||||
@override
|
||||
String get cacheRefresh => 'Refresh';
|
||||
}
|
||||
|
||||
@@ -1195,6 +1195,47 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
@override
|
||||
String get storeClearFilters => 'Clear filters';
|
||||
|
||||
@override
|
||||
String get storeAddRepoTitle => 'Add Extension Repository';
|
||||
|
||||
@override
|
||||
String get storeAddRepoDescription =>
|
||||
'Enter a GitHub repository URL that contains a registry.json file to browse and install extensions.';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlLabel => 'Repository URL';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlHint => 'https://github.com/user/repo';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlHelper =>
|
||||
'e.g. https://github.com/user/extensions-repo';
|
||||
|
||||
@override
|
||||
String get storeAddRepoButton => 'Add Repository';
|
||||
|
||||
@override
|
||||
String get storeChangeRepoTooltip => 'Change repository';
|
||||
|
||||
@override
|
||||
String get storeRepoDialogTitle => 'Extension Repository';
|
||||
|
||||
@override
|
||||
String get storeRepoDialogCurrent => 'Current repository:';
|
||||
|
||||
@override
|
||||
String get storeNewRepoUrlLabel => 'New Repository URL';
|
||||
|
||||
@override
|
||||
String get storeLoadError => 'Failed to load store';
|
||||
|
||||
@override
|
||||
String get storeEmptyNoExtensions => 'No extensions available';
|
||||
|
||||
@override
|
||||
String get storeEmptyNoResults => 'No extensions found';
|
||||
|
||||
@override
|
||||
String get extensionDefaultProvider => 'Default (Deezer/Spotify)';
|
||||
|
||||
@@ -2408,4 +2449,317 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
@override
|
||||
String get downloadUseAlbumArtistForFoldersTrackSubtitle =>
|
||||
'Artist folders use Track Artist only';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersTitle => 'Lyrics Providers';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersDescription =>
|
||||
'Enable, disable and reorder lyrics sources. Providers are tried top-to-bottom until lyrics are found.';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersInfoText =>
|
||||
'Extension lyrics providers always run before built-in providers. At least one provider must remain enabled.';
|
||||
|
||||
@override
|
||||
String lyricsProvidersEnabledSection(int count) {
|
||||
return 'Enabled ($count)';
|
||||
}
|
||||
|
||||
@override
|
||||
String lyricsProvidersDisabledSection(int count) {
|
||||
return 'Disabled ($count)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get lyricsProvidersAtLeastOne =>
|
||||
'At least one provider must remain enabled';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersSaved => 'Lyrics provider priority saved';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersDiscardContent =>
|
||||
'You have unsaved changes that will be lost.';
|
||||
|
||||
@override
|
||||
String get lyricsProviderSpotifyApiDesc =>
|
||||
'Spotify-sourced synced lyrics via community API';
|
||||
|
||||
@override
|
||||
String get lyricsProviderLrclibDesc => 'Open-source synced lyrics database';
|
||||
|
||||
@override
|
||||
String get lyricsProviderNeteaseDesc =>
|
||||
'NetEase Cloud Music (good for Asian songs)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderMusixmatchDesc =>
|
||||
'Largest lyrics database (multi-language)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderAppleMusicDesc =>
|
||||
'Word-by-word synced lyrics (via proxy)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderQqMusicDesc =>
|
||||
'QQ Music (good for Chinese songs, via proxy)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderExtensionDesc => 'Extension provider';
|
||||
|
||||
@override
|
||||
String get safMigrationTitle => 'Storage Update Required';
|
||||
|
||||
@override
|
||||
String get safMigrationMessage1 =>
|
||||
'SpotiFLAC now uses Android Storage Access Framework (SAF) for downloads. This fixes \"permission denied\" errors on Android 10+.';
|
||||
|
||||
@override
|
||||
String get safMigrationMessage2 =>
|
||||
'Please select your download folder again to switch to the new storage system.';
|
||||
|
||||
@override
|
||||
String get safMigrationSuccess => 'Download folder updated to SAF mode';
|
||||
|
||||
@override
|
||||
String get settingsDonate => 'Donate';
|
||||
|
||||
@override
|
||||
String get settingsDonateSubtitle => 'Support SpotiFLAC-Mobile development';
|
||||
|
||||
@override
|
||||
String get tooltipLoveAll => 'Love All';
|
||||
|
||||
@override
|
||||
String get tooltipAddToPlaylist => 'Add to Playlist';
|
||||
|
||||
@override
|
||||
String snackbarRemovedTracksFromLoved(int count) {
|
||||
return 'Removed $count tracks from Loved';
|
||||
}
|
||||
|
||||
@override
|
||||
String snackbarAddedTracksToLoved(int count) {
|
||||
return 'Added $count tracks to Loved';
|
||||
}
|
||||
|
||||
@override
|
||||
String get dialogDownloadAllTitle => 'Download All';
|
||||
|
||||
@override
|
||||
String dialogDownloadAllMessage(int count) {
|
||||
return 'Download $count tracks?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get dialogDownload => 'Download';
|
||||
|
||||
@override
|
||||
String get homeSkipAlreadyDownloaded => 'Skip already downloaded songs';
|
||||
|
||||
@override
|
||||
String get homeGoToAlbum => 'Go to Album';
|
||||
|
||||
@override
|
||||
String get homeAlbumInfoUnavailable => 'Album info not available';
|
||||
|
||||
@override
|
||||
String get snackbarLoadingCueSheet => 'Loading CUE sheet...';
|
||||
|
||||
@override
|
||||
String get snackbarMetadataSaved => 'Metadata saved successfully';
|
||||
|
||||
@override
|
||||
String get snackbarFailedToEmbedLyrics => 'Failed to embed lyrics';
|
||||
|
||||
@override
|
||||
String get snackbarFailedToWriteStorage => 'Failed to write back to storage';
|
||||
|
||||
@override
|
||||
String snackbarError(String error) {
|
||||
return 'Error: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get snackbarNoActionDefined => 'No action defined for this button';
|
||||
|
||||
@override
|
||||
String get noTracksFoundForAlbum => 'No tracks found for this album';
|
||||
|
||||
@override
|
||||
String get downloadLocationSubtitle =>
|
||||
'Choose storage mode for downloaded files.';
|
||||
|
||||
@override
|
||||
String get storageModeAppFolder => 'App folder (non-SAF)';
|
||||
|
||||
@override
|
||||
String get storageModeAppFolderSubtitle => 'Use default Music/SpotiFLAC path';
|
||||
|
||||
@override
|
||||
String get storageModeSaf => 'SAF folder';
|
||||
|
||||
@override
|
||||
String get storageModeSafSubtitle =>
|
||||
'Pick folder via Android Storage Access Framework';
|
||||
|
||||
@override
|
||||
String get downloadFilenameDescription =>
|
||||
'Customize how your files are named.';
|
||||
|
||||
@override
|
||||
String get downloadFilenameInsertTag => 'Tap to insert tag:';
|
||||
|
||||
@override
|
||||
String get downloadSeparateSinglesEnabled => 'Albums/ and Singles/ folders';
|
||||
|
||||
@override
|
||||
String get downloadSeparateSinglesDisabled => 'All files in same structure';
|
||||
|
||||
@override
|
||||
String get downloadArtistNameFilters => 'Artist Name Filters';
|
||||
|
||||
@override
|
||||
String get downloadSongLinkRegion => 'SongLink Region';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityMode => 'Network compatibility mode';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityModeEnabled =>
|
||||
'Enabled: try HTTP + accept invalid TLS certificates (unsafe)';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityModeDisabled =>
|
||||
'Off: strict HTTPS certificate validation (recommended)';
|
||||
|
||||
@override
|
||||
String get downloadSelectServiceToEnable =>
|
||||
'Select a built-in service to enable';
|
||||
|
||||
@override
|
||||
String get downloadLossy320 => 'Lossy 320kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyFormat => 'Lossy Format';
|
||||
|
||||
@override
|
||||
String get downloadSelectTidalQobuz =>
|
||||
'Select Tidal or Qobuz above to configure quality';
|
||||
|
||||
@override
|
||||
String get downloadEmbedLyricsDisabled =>
|
||||
'Disabled while Embed Metadata is turned off';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslation =>
|
||||
'Netease: Include Translation';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslationEnabled =>
|
||||
'Append translated lyrics when available';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslationDisabled =>
|
||||
'Use original lyrics only';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanization =>
|
||||
'Netease: Include Romanization';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanizationEnabled =>
|
||||
'Append romanized lyrics when available';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanizationDisabled => 'Disabled';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPerson => 'Apple/QQ Multi-Person Word-by-Word';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPersonEnabled =>
|
||||
'Enable v1/v2 speaker and [bg:] tags';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPersonDisabled =>
|
||||
'Simplified word-by-word formatting';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguage => 'Musixmatch Language';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageAuto => 'Auto (original)';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributing =>
|
||||
'Filter contributing artists in Album Artist';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributingEnabled =>
|
||||
'Album Artist metadata uses primary artist only';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributingDisabled =>
|
||||
'Keep full Album Artist metadata value';
|
||||
|
||||
@override
|
||||
String get downloadProvidersNoneEnabled => 'None enabled';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageCode => 'Language code';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageHint => 'auto / en / es / ja';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageDesc =>
|
||||
'Set preferred language code (example: en, es, ja). Leave empty for auto.';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchAuto => 'Auto';
|
||||
|
||||
@override
|
||||
String get downloadLossy320Format => 'Lossy 320kbps Format';
|
||||
|
||||
@override
|
||||
String get downloadLossy320FormatDesc =>
|
||||
'Choose the output format for Tidal 320kbps lossy downloads. The original AAC stream will be converted to your selected format.';
|
||||
|
||||
@override
|
||||
String get downloadLossyMp3 => 'MP3 320kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyMp3Subtitle => 'Best compatibility, ~10MB per track';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus256 => 'Opus 256kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus256Subtitle =>
|
||||
'Best quality Opus, ~8MB per track';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus128 => 'Opus 128kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus128Subtitle => 'Smallest size, ~4MB per track';
|
||||
|
||||
@override
|
||||
String get downloadNetworkAnySubtitle => 'WiFi + Mobile Data';
|
||||
|
||||
@override
|
||||
String get downloadNetworkWifiOnlySubtitle =>
|
||||
'Pause downloads on mobile data';
|
||||
|
||||
@override
|
||||
String get downloadSongLinkRegionDesc =>
|
||||
'Used as userCountry for SongLink API lookup.';
|
||||
|
||||
@override
|
||||
String get snackbarUnsupportedAudioFormat => 'Unsupported audio format';
|
||||
|
||||
@override
|
||||
String get cacheRefresh => 'Refresh';
|
||||
}
|
||||
|
||||
@@ -1195,6 +1195,47 @@ class AppLocalizationsEs extends AppLocalizations {
|
||||
@override
|
||||
String get storeClearFilters => 'Clear filters';
|
||||
|
||||
@override
|
||||
String get storeAddRepoTitle => 'Add Extension Repository';
|
||||
|
||||
@override
|
||||
String get storeAddRepoDescription =>
|
||||
'Enter a GitHub repository URL that contains a registry.json file to browse and install extensions.';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlLabel => 'Repository URL';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlHint => 'https://github.com/user/repo';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlHelper =>
|
||||
'e.g. https://github.com/user/extensions-repo';
|
||||
|
||||
@override
|
||||
String get storeAddRepoButton => 'Add Repository';
|
||||
|
||||
@override
|
||||
String get storeChangeRepoTooltip => 'Change repository';
|
||||
|
||||
@override
|
||||
String get storeRepoDialogTitle => 'Extension Repository';
|
||||
|
||||
@override
|
||||
String get storeRepoDialogCurrent => 'Current repository:';
|
||||
|
||||
@override
|
||||
String get storeNewRepoUrlLabel => 'New Repository URL';
|
||||
|
||||
@override
|
||||
String get storeLoadError => 'Failed to load store';
|
||||
|
||||
@override
|
||||
String get storeEmptyNoExtensions => 'No extensions available';
|
||||
|
||||
@override
|
||||
String get storeEmptyNoResults => 'No extensions found';
|
||||
|
||||
@override
|
||||
String get extensionDefaultProvider => 'Default (Deezer/Spotify)';
|
||||
|
||||
@@ -2408,6 +2449,319 @@ class AppLocalizationsEs extends AppLocalizations {
|
||||
@override
|
||||
String get downloadUseAlbumArtistForFoldersTrackSubtitle =>
|
||||
'Artist folders use Track Artist only';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersTitle => 'Lyrics Providers';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersDescription =>
|
||||
'Enable, disable and reorder lyrics sources. Providers are tried top-to-bottom until lyrics are found.';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersInfoText =>
|
||||
'Extension lyrics providers always run before built-in providers. At least one provider must remain enabled.';
|
||||
|
||||
@override
|
||||
String lyricsProvidersEnabledSection(int count) {
|
||||
return 'Enabled ($count)';
|
||||
}
|
||||
|
||||
@override
|
||||
String lyricsProvidersDisabledSection(int count) {
|
||||
return 'Disabled ($count)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get lyricsProvidersAtLeastOne =>
|
||||
'At least one provider must remain enabled';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersSaved => 'Lyrics provider priority saved';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersDiscardContent =>
|
||||
'You have unsaved changes that will be lost.';
|
||||
|
||||
@override
|
||||
String get lyricsProviderSpotifyApiDesc =>
|
||||
'Spotify-sourced synced lyrics via community API';
|
||||
|
||||
@override
|
||||
String get lyricsProviderLrclibDesc => 'Open-source synced lyrics database';
|
||||
|
||||
@override
|
||||
String get lyricsProviderNeteaseDesc =>
|
||||
'NetEase Cloud Music (good for Asian songs)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderMusixmatchDesc =>
|
||||
'Largest lyrics database (multi-language)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderAppleMusicDesc =>
|
||||
'Word-by-word synced lyrics (via proxy)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderQqMusicDesc =>
|
||||
'QQ Music (good for Chinese songs, via proxy)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderExtensionDesc => 'Extension provider';
|
||||
|
||||
@override
|
||||
String get safMigrationTitle => 'Storage Update Required';
|
||||
|
||||
@override
|
||||
String get safMigrationMessage1 =>
|
||||
'SpotiFLAC now uses Android Storage Access Framework (SAF) for downloads. This fixes \"permission denied\" errors on Android 10+.';
|
||||
|
||||
@override
|
||||
String get safMigrationMessage2 =>
|
||||
'Please select your download folder again to switch to the new storage system.';
|
||||
|
||||
@override
|
||||
String get safMigrationSuccess => 'Download folder updated to SAF mode';
|
||||
|
||||
@override
|
||||
String get settingsDonate => 'Donate';
|
||||
|
||||
@override
|
||||
String get settingsDonateSubtitle => 'Support SpotiFLAC-Mobile development';
|
||||
|
||||
@override
|
||||
String get tooltipLoveAll => 'Love All';
|
||||
|
||||
@override
|
||||
String get tooltipAddToPlaylist => 'Add to Playlist';
|
||||
|
||||
@override
|
||||
String snackbarRemovedTracksFromLoved(int count) {
|
||||
return 'Removed $count tracks from Loved';
|
||||
}
|
||||
|
||||
@override
|
||||
String snackbarAddedTracksToLoved(int count) {
|
||||
return 'Added $count tracks to Loved';
|
||||
}
|
||||
|
||||
@override
|
||||
String get dialogDownloadAllTitle => 'Download All';
|
||||
|
||||
@override
|
||||
String dialogDownloadAllMessage(int count) {
|
||||
return 'Download $count tracks?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get dialogDownload => 'Download';
|
||||
|
||||
@override
|
||||
String get homeSkipAlreadyDownloaded => 'Skip already downloaded songs';
|
||||
|
||||
@override
|
||||
String get homeGoToAlbum => 'Go to Album';
|
||||
|
||||
@override
|
||||
String get homeAlbumInfoUnavailable => 'Album info not available';
|
||||
|
||||
@override
|
||||
String get snackbarLoadingCueSheet => 'Loading CUE sheet...';
|
||||
|
||||
@override
|
||||
String get snackbarMetadataSaved => 'Metadata saved successfully';
|
||||
|
||||
@override
|
||||
String get snackbarFailedToEmbedLyrics => 'Failed to embed lyrics';
|
||||
|
||||
@override
|
||||
String get snackbarFailedToWriteStorage => 'Failed to write back to storage';
|
||||
|
||||
@override
|
||||
String snackbarError(String error) {
|
||||
return 'Error: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get snackbarNoActionDefined => 'No action defined for this button';
|
||||
|
||||
@override
|
||||
String get noTracksFoundForAlbum => 'No tracks found for this album';
|
||||
|
||||
@override
|
||||
String get downloadLocationSubtitle =>
|
||||
'Choose storage mode for downloaded files.';
|
||||
|
||||
@override
|
||||
String get storageModeAppFolder => 'App folder (non-SAF)';
|
||||
|
||||
@override
|
||||
String get storageModeAppFolderSubtitle => 'Use default Music/SpotiFLAC path';
|
||||
|
||||
@override
|
||||
String get storageModeSaf => 'SAF folder';
|
||||
|
||||
@override
|
||||
String get storageModeSafSubtitle =>
|
||||
'Pick folder via Android Storage Access Framework';
|
||||
|
||||
@override
|
||||
String get downloadFilenameDescription =>
|
||||
'Customize how your files are named.';
|
||||
|
||||
@override
|
||||
String get downloadFilenameInsertTag => 'Tap to insert tag:';
|
||||
|
||||
@override
|
||||
String get downloadSeparateSinglesEnabled => 'Albums/ and Singles/ folders';
|
||||
|
||||
@override
|
||||
String get downloadSeparateSinglesDisabled => 'All files in same structure';
|
||||
|
||||
@override
|
||||
String get downloadArtistNameFilters => 'Artist Name Filters';
|
||||
|
||||
@override
|
||||
String get downloadSongLinkRegion => 'SongLink Region';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityMode => 'Network compatibility mode';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityModeEnabled =>
|
||||
'Enabled: try HTTP + accept invalid TLS certificates (unsafe)';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityModeDisabled =>
|
||||
'Off: strict HTTPS certificate validation (recommended)';
|
||||
|
||||
@override
|
||||
String get downloadSelectServiceToEnable =>
|
||||
'Select a built-in service to enable';
|
||||
|
||||
@override
|
||||
String get downloadLossy320 => 'Lossy 320kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyFormat => 'Lossy Format';
|
||||
|
||||
@override
|
||||
String get downloadSelectTidalQobuz =>
|
||||
'Select Tidal or Qobuz above to configure quality';
|
||||
|
||||
@override
|
||||
String get downloadEmbedLyricsDisabled =>
|
||||
'Disabled while Embed Metadata is turned off';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslation =>
|
||||
'Netease: Include Translation';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslationEnabled =>
|
||||
'Append translated lyrics when available';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslationDisabled =>
|
||||
'Use original lyrics only';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanization =>
|
||||
'Netease: Include Romanization';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanizationEnabled =>
|
||||
'Append romanized lyrics when available';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanizationDisabled => 'Disabled';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPerson => 'Apple/QQ Multi-Person Word-by-Word';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPersonEnabled =>
|
||||
'Enable v1/v2 speaker and [bg:] tags';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPersonDisabled =>
|
||||
'Simplified word-by-word formatting';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguage => 'Musixmatch Language';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageAuto => 'Auto (original)';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributing =>
|
||||
'Filter contributing artists in Album Artist';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributingEnabled =>
|
||||
'Album Artist metadata uses primary artist only';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributingDisabled =>
|
||||
'Keep full Album Artist metadata value';
|
||||
|
||||
@override
|
||||
String get downloadProvidersNoneEnabled => 'None enabled';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageCode => 'Language code';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageHint => 'auto / en / es / ja';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageDesc =>
|
||||
'Set preferred language code (example: en, es, ja). Leave empty for auto.';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchAuto => 'Auto';
|
||||
|
||||
@override
|
||||
String get downloadLossy320Format => 'Lossy 320kbps Format';
|
||||
|
||||
@override
|
||||
String get downloadLossy320FormatDesc =>
|
||||
'Choose the output format for Tidal 320kbps lossy downloads. The original AAC stream will be converted to your selected format.';
|
||||
|
||||
@override
|
||||
String get downloadLossyMp3 => 'MP3 320kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyMp3Subtitle => 'Best compatibility, ~10MB per track';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus256 => 'Opus 256kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus256Subtitle =>
|
||||
'Best quality Opus, ~8MB per track';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus128 => 'Opus 128kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus128Subtitle => 'Smallest size, ~4MB per track';
|
||||
|
||||
@override
|
||||
String get downloadNetworkAnySubtitle => 'WiFi + Mobile Data';
|
||||
|
||||
@override
|
||||
String get downloadNetworkWifiOnlySubtitle =>
|
||||
'Pause downloads on mobile data';
|
||||
|
||||
@override
|
||||
String get downloadSongLinkRegionDesc =>
|
||||
'Used as userCountry for SongLink API lookup.';
|
||||
|
||||
@override
|
||||
String get snackbarUnsupportedAudioFormat => 'Unsupported audio format';
|
||||
|
||||
@override
|
||||
String get cacheRefresh => 'Refresh';
|
||||
}
|
||||
|
||||
/// The translations for Spanish Castilian, as used in Spain (`es_ES`).
|
||||
|
||||
@@ -1197,6 +1197,47 @@ class AppLocalizationsFr extends AppLocalizations {
|
||||
@override
|
||||
String get storeClearFilters => 'Clear filters';
|
||||
|
||||
@override
|
||||
String get storeAddRepoTitle => 'Add Extension Repository';
|
||||
|
||||
@override
|
||||
String get storeAddRepoDescription =>
|
||||
'Enter a GitHub repository URL that contains a registry.json file to browse and install extensions.';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlLabel => 'Repository URL';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlHint => 'https://github.com/user/repo';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlHelper =>
|
||||
'e.g. https://github.com/user/extensions-repo';
|
||||
|
||||
@override
|
||||
String get storeAddRepoButton => 'Add Repository';
|
||||
|
||||
@override
|
||||
String get storeChangeRepoTooltip => 'Change repository';
|
||||
|
||||
@override
|
||||
String get storeRepoDialogTitle => 'Extension Repository';
|
||||
|
||||
@override
|
||||
String get storeRepoDialogCurrent => 'Current repository:';
|
||||
|
||||
@override
|
||||
String get storeNewRepoUrlLabel => 'New Repository URL';
|
||||
|
||||
@override
|
||||
String get storeLoadError => 'Failed to load store';
|
||||
|
||||
@override
|
||||
String get storeEmptyNoExtensions => 'No extensions available';
|
||||
|
||||
@override
|
||||
String get storeEmptyNoResults => 'No extensions found';
|
||||
|
||||
@override
|
||||
String get extensionDefaultProvider => 'Default (Deezer/Spotify)';
|
||||
|
||||
@@ -2410,4 +2451,317 @@ class AppLocalizationsFr extends AppLocalizations {
|
||||
@override
|
||||
String get downloadUseAlbumArtistForFoldersTrackSubtitle =>
|
||||
'Artist folders use Track Artist only';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersTitle => 'Lyrics Providers';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersDescription =>
|
||||
'Enable, disable and reorder lyrics sources. Providers are tried top-to-bottom until lyrics are found.';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersInfoText =>
|
||||
'Extension lyrics providers always run before built-in providers. At least one provider must remain enabled.';
|
||||
|
||||
@override
|
||||
String lyricsProvidersEnabledSection(int count) {
|
||||
return 'Enabled ($count)';
|
||||
}
|
||||
|
||||
@override
|
||||
String lyricsProvidersDisabledSection(int count) {
|
||||
return 'Disabled ($count)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get lyricsProvidersAtLeastOne =>
|
||||
'At least one provider must remain enabled';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersSaved => 'Lyrics provider priority saved';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersDiscardContent =>
|
||||
'You have unsaved changes that will be lost.';
|
||||
|
||||
@override
|
||||
String get lyricsProviderSpotifyApiDesc =>
|
||||
'Spotify-sourced synced lyrics via community API';
|
||||
|
||||
@override
|
||||
String get lyricsProviderLrclibDesc => 'Open-source synced lyrics database';
|
||||
|
||||
@override
|
||||
String get lyricsProviderNeteaseDesc =>
|
||||
'NetEase Cloud Music (good for Asian songs)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderMusixmatchDesc =>
|
||||
'Largest lyrics database (multi-language)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderAppleMusicDesc =>
|
||||
'Word-by-word synced lyrics (via proxy)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderQqMusicDesc =>
|
||||
'QQ Music (good for Chinese songs, via proxy)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderExtensionDesc => 'Extension provider';
|
||||
|
||||
@override
|
||||
String get safMigrationTitle => 'Storage Update Required';
|
||||
|
||||
@override
|
||||
String get safMigrationMessage1 =>
|
||||
'SpotiFLAC now uses Android Storage Access Framework (SAF) for downloads. This fixes \"permission denied\" errors on Android 10+.';
|
||||
|
||||
@override
|
||||
String get safMigrationMessage2 =>
|
||||
'Please select your download folder again to switch to the new storage system.';
|
||||
|
||||
@override
|
||||
String get safMigrationSuccess => 'Download folder updated to SAF mode';
|
||||
|
||||
@override
|
||||
String get settingsDonate => 'Donate';
|
||||
|
||||
@override
|
||||
String get settingsDonateSubtitle => 'Support SpotiFLAC-Mobile development';
|
||||
|
||||
@override
|
||||
String get tooltipLoveAll => 'Love All';
|
||||
|
||||
@override
|
||||
String get tooltipAddToPlaylist => 'Add to Playlist';
|
||||
|
||||
@override
|
||||
String snackbarRemovedTracksFromLoved(int count) {
|
||||
return 'Removed $count tracks from Loved';
|
||||
}
|
||||
|
||||
@override
|
||||
String snackbarAddedTracksToLoved(int count) {
|
||||
return 'Added $count tracks to Loved';
|
||||
}
|
||||
|
||||
@override
|
||||
String get dialogDownloadAllTitle => 'Download All';
|
||||
|
||||
@override
|
||||
String dialogDownloadAllMessage(int count) {
|
||||
return 'Download $count tracks?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get dialogDownload => 'Download';
|
||||
|
||||
@override
|
||||
String get homeSkipAlreadyDownloaded => 'Skip already downloaded songs';
|
||||
|
||||
@override
|
||||
String get homeGoToAlbum => 'Go to Album';
|
||||
|
||||
@override
|
||||
String get homeAlbumInfoUnavailable => 'Album info not available';
|
||||
|
||||
@override
|
||||
String get snackbarLoadingCueSheet => 'Loading CUE sheet...';
|
||||
|
||||
@override
|
||||
String get snackbarMetadataSaved => 'Metadata saved successfully';
|
||||
|
||||
@override
|
||||
String get snackbarFailedToEmbedLyrics => 'Failed to embed lyrics';
|
||||
|
||||
@override
|
||||
String get snackbarFailedToWriteStorage => 'Failed to write back to storage';
|
||||
|
||||
@override
|
||||
String snackbarError(String error) {
|
||||
return 'Error: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get snackbarNoActionDefined => 'No action defined for this button';
|
||||
|
||||
@override
|
||||
String get noTracksFoundForAlbum => 'No tracks found for this album';
|
||||
|
||||
@override
|
||||
String get downloadLocationSubtitle =>
|
||||
'Choose storage mode for downloaded files.';
|
||||
|
||||
@override
|
||||
String get storageModeAppFolder => 'App folder (non-SAF)';
|
||||
|
||||
@override
|
||||
String get storageModeAppFolderSubtitle => 'Use default Music/SpotiFLAC path';
|
||||
|
||||
@override
|
||||
String get storageModeSaf => 'SAF folder';
|
||||
|
||||
@override
|
||||
String get storageModeSafSubtitle =>
|
||||
'Pick folder via Android Storage Access Framework';
|
||||
|
||||
@override
|
||||
String get downloadFilenameDescription =>
|
||||
'Customize how your files are named.';
|
||||
|
||||
@override
|
||||
String get downloadFilenameInsertTag => 'Tap to insert tag:';
|
||||
|
||||
@override
|
||||
String get downloadSeparateSinglesEnabled => 'Albums/ and Singles/ folders';
|
||||
|
||||
@override
|
||||
String get downloadSeparateSinglesDisabled => 'All files in same structure';
|
||||
|
||||
@override
|
||||
String get downloadArtistNameFilters => 'Artist Name Filters';
|
||||
|
||||
@override
|
||||
String get downloadSongLinkRegion => 'SongLink Region';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityMode => 'Network compatibility mode';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityModeEnabled =>
|
||||
'Enabled: try HTTP + accept invalid TLS certificates (unsafe)';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityModeDisabled =>
|
||||
'Off: strict HTTPS certificate validation (recommended)';
|
||||
|
||||
@override
|
||||
String get downloadSelectServiceToEnable =>
|
||||
'Select a built-in service to enable';
|
||||
|
||||
@override
|
||||
String get downloadLossy320 => 'Lossy 320kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyFormat => 'Lossy Format';
|
||||
|
||||
@override
|
||||
String get downloadSelectTidalQobuz =>
|
||||
'Select Tidal or Qobuz above to configure quality';
|
||||
|
||||
@override
|
||||
String get downloadEmbedLyricsDisabled =>
|
||||
'Disabled while Embed Metadata is turned off';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslation =>
|
||||
'Netease: Include Translation';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslationEnabled =>
|
||||
'Append translated lyrics when available';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslationDisabled =>
|
||||
'Use original lyrics only';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanization =>
|
||||
'Netease: Include Romanization';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanizationEnabled =>
|
||||
'Append romanized lyrics when available';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanizationDisabled => 'Disabled';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPerson => 'Apple/QQ Multi-Person Word-by-Word';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPersonEnabled =>
|
||||
'Enable v1/v2 speaker and [bg:] tags';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPersonDisabled =>
|
||||
'Simplified word-by-word formatting';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguage => 'Musixmatch Language';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageAuto => 'Auto (original)';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributing =>
|
||||
'Filter contributing artists in Album Artist';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributingEnabled =>
|
||||
'Album Artist metadata uses primary artist only';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributingDisabled =>
|
||||
'Keep full Album Artist metadata value';
|
||||
|
||||
@override
|
||||
String get downloadProvidersNoneEnabled => 'None enabled';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageCode => 'Language code';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageHint => 'auto / en / es / ja';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageDesc =>
|
||||
'Set preferred language code (example: en, es, ja). Leave empty for auto.';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchAuto => 'Auto';
|
||||
|
||||
@override
|
||||
String get downloadLossy320Format => 'Lossy 320kbps Format';
|
||||
|
||||
@override
|
||||
String get downloadLossy320FormatDesc =>
|
||||
'Choose the output format for Tidal 320kbps lossy downloads. The original AAC stream will be converted to your selected format.';
|
||||
|
||||
@override
|
||||
String get downloadLossyMp3 => 'MP3 320kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyMp3Subtitle => 'Best compatibility, ~10MB per track';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus256 => 'Opus 256kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus256Subtitle =>
|
||||
'Best quality Opus, ~8MB per track';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus128 => 'Opus 128kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus128Subtitle => 'Smallest size, ~4MB per track';
|
||||
|
||||
@override
|
||||
String get downloadNetworkAnySubtitle => 'WiFi + Mobile Data';
|
||||
|
||||
@override
|
||||
String get downloadNetworkWifiOnlySubtitle =>
|
||||
'Pause downloads on mobile data';
|
||||
|
||||
@override
|
||||
String get downloadSongLinkRegionDesc =>
|
||||
'Used as userCountry for SongLink API lookup.';
|
||||
|
||||
@override
|
||||
String get snackbarUnsupportedAudioFormat => 'Unsupported audio format';
|
||||
|
||||
@override
|
||||
String get cacheRefresh => 'Refresh';
|
||||
}
|
||||
|
||||
@@ -1195,6 +1195,47 @@ class AppLocalizationsHi extends AppLocalizations {
|
||||
@override
|
||||
String get storeClearFilters => 'Clear filters';
|
||||
|
||||
@override
|
||||
String get storeAddRepoTitle => 'Add Extension Repository';
|
||||
|
||||
@override
|
||||
String get storeAddRepoDescription =>
|
||||
'Enter a GitHub repository URL that contains a registry.json file to browse and install extensions.';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlLabel => 'Repository URL';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlHint => 'https://github.com/user/repo';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlHelper =>
|
||||
'e.g. https://github.com/user/extensions-repo';
|
||||
|
||||
@override
|
||||
String get storeAddRepoButton => 'Add Repository';
|
||||
|
||||
@override
|
||||
String get storeChangeRepoTooltip => 'Change repository';
|
||||
|
||||
@override
|
||||
String get storeRepoDialogTitle => 'Extension Repository';
|
||||
|
||||
@override
|
||||
String get storeRepoDialogCurrent => 'Current repository:';
|
||||
|
||||
@override
|
||||
String get storeNewRepoUrlLabel => 'New Repository URL';
|
||||
|
||||
@override
|
||||
String get storeLoadError => 'Failed to load store';
|
||||
|
||||
@override
|
||||
String get storeEmptyNoExtensions => 'No extensions available';
|
||||
|
||||
@override
|
||||
String get storeEmptyNoResults => 'No extensions found';
|
||||
|
||||
@override
|
||||
String get extensionDefaultProvider => 'Default (Deezer/Spotify)';
|
||||
|
||||
@@ -2408,4 +2449,317 @@ class AppLocalizationsHi extends AppLocalizations {
|
||||
@override
|
||||
String get downloadUseAlbumArtistForFoldersTrackSubtitle =>
|
||||
'Artist folders use Track Artist only';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersTitle => 'Lyrics Providers';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersDescription =>
|
||||
'Enable, disable and reorder lyrics sources. Providers are tried top-to-bottom until lyrics are found.';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersInfoText =>
|
||||
'Extension lyrics providers always run before built-in providers. At least one provider must remain enabled.';
|
||||
|
||||
@override
|
||||
String lyricsProvidersEnabledSection(int count) {
|
||||
return 'Enabled ($count)';
|
||||
}
|
||||
|
||||
@override
|
||||
String lyricsProvidersDisabledSection(int count) {
|
||||
return 'Disabled ($count)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get lyricsProvidersAtLeastOne =>
|
||||
'At least one provider must remain enabled';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersSaved => 'Lyrics provider priority saved';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersDiscardContent =>
|
||||
'You have unsaved changes that will be lost.';
|
||||
|
||||
@override
|
||||
String get lyricsProviderSpotifyApiDesc =>
|
||||
'Spotify-sourced synced lyrics via community API';
|
||||
|
||||
@override
|
||||
String get lyricsProviderLrclibDesc => 'Open-source synced lyrics database';
|
||||
|
||||
@override
|
||||
String get lyricsProviderNeteaseDesc =>
|
||||
'NetEase Cloud Music (good for Asian songs)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderMusixmatchDesc =>
|
||||
'Largest lyrics database (multi-language)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderAppleMusicDesc =>
|
||||
'Word-by-word synced lyrics (via proxy)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderQqMusicDesc =>
|
||||
'QQ Music (good for Chinese songs, via proxy)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderExtensionDesc => 'Extension provider';
|
||||
|
||||
@override
|
||||
String get safMigrationTitle => 'Storage Update Required';
|
||||
|
||||
@override
|
||||
String get safMigrationMessage1 =>
|
||||
'SpotiFLAC now uses Android Storage Access Framework (SAF) for downloads. This fixes \"permission denied\" errors on Android 10+.';
|
||||
|
||||
@override
|
||||
String get safMigrationMessage2 =>
|
||||
'Please select your download folder again to switch to the new storage system.';
|
||||
|
||||
@override
|
||||
String get safMigrationSuccess => 'Download folder updated to SAF mode';
|
||||
|
||||
@override
|
||||
String get settingsDonate => 'Donate';
|
||||
|
||||
@override
|
||||
String get settingsDonateSubtitle => 'Support SpotiFLAC-Mobile development';
|
||||
|
||||
@override
|
||||
String get tooltipLoveAll => 'Love All';
|
||||
|
||||
@override
|
||||
String get tooltipAddToPlaylist => 'Add to Playlist';
|
||||
|
||||
@override
|
||||
String snackbarRemovedTracksFromLoved(int count) {
|
||||
return 'Removed $count tracks from Loved';
|
||||
}
|
||||
|
||||
@override
|
||||
String snackbarAddedTracksToLoved(int count) {
|
||||
return 'Added $count tracks to Loved';
|
||||
}
|
||||
|
||||
@override
|
||||
String get dialogDownloadAllTitle => 'Download All';
|
||||
|
||||
@override
|
||||
String dialogDownloadAllMessage(int count) {
|
||||
return 'Download $count tracks?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get dialogDownload => 'Download';
|
||||
|
||||
@override
|
||||
String get homeSkipAlreadyDownloaded => 'Skip already downloaded songs';
|
||||
|
||||
@override
|
||||
String get homeGoToAlbum => 'Go to Album';
|
||||
|
||||
@override
|
||||
String get homeAlbumInfoUnavailable => 'Album info not available';
|
||||
|
||||
@override
|
||||
String get snackbarLoadingCueSheet => 'Loading CUE sheet...';
|
||||
|
||||
@override
|
||||
String get snackbarMetadataSaved => 'Metadata saved successfully';
|
||||
|
||||
@override
|
||||
String get snackbarFailedToEmbedLyrics => 'Failed to embed lyrics';
|
||||
|
||||
@override
|
||||
String get snackbarFailedToWriteStorage => 'Failed to write back to storage';
|
||||
|
||||
@override
|
||||
String snackbarError(String error) {
|
||||
return 'Error: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get snackbarNoActionDefined => 'No action defined for this button';
|
||||
|
||||
@override
|
||||
String get noTracksFoundForAlbum => 'No tracks found for this album';
|
||||
|
||||
@override
|
||||
String get downloadLocationSubtitle =>
|
||||
'Choose storage mode for downloaded files.';
|
||||
|
||||
@override
|
||||
String get storageModeAppFolder => 'App folder (non-SAF)';
|
||||
|
||||
@override
|
||||
String get storageModeAppFolderSubtitle => 'Use default Music/SpotiFLAC path';
|
||||
|
||||
@override
|
||||
String get storageModeSaf => 'SAF folder';
|
||||
|
||||
@override
|
||||
String get storageModeSafSubtitle =>
|
||||
'Pick folder via Android Storage Access Framework';
|
||||
|
||||
@override
|
||||
String get downloadFilenameDescription =>
|
||||
'Customize how your files are named.';
|
||||
|
||||
@override
|
||||
String get downloadFilenameInsertTag => 'Tap to insert tag:';
|
||||
|
||||
@override
|
||||
String get downloadSeparateSinglesEnabled => 'Albums/ and Singles/ folders';
|
||||
|
||||
@override
|
||||
String get downloadSeparateSinglesDisabled => 'All files in same structure';
|
||||
|
||||
@override
|
||||
String get downloadArtistNameFilters => 'Artist Name Filters';
|
||||
|
||||
@override
|
||||
String get downloadSongLinkRegion => 'SongLink Region';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityMode => 'Network compatibility mode';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityModeEnabled =>
|
||||
'Enabled: try HTTP + accept invalid TLS certificates (unsafe)';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityModeDisabled =>
|
||||
'Off: strict HTTPS certificate validation (recommended)';
|
||||
|
||||
@override
|
||||
String get downloadSelectServiceToEnable =>
|
||||
'Select a built-in service to enable';
|
||||
|
||||
@override
|
||||
String get downloadLossy320 => 'Lossy 320kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyFormat => 'Lossy Format';
|
||||
|
||||
@override
|
||||
String get downloadSelectTidalQobuz =>
|
||||
'Select Tidal or Qobuz above to configure quality';
|
||||
|
||||
@override
|
||||
String get downloadEmbedLyricsDisabled =>
|
||||
'Disabled while Embed Metadata is turned off';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslation =>
|
||||
'Netease: Include Translation';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslationEnabled =>
|
||||
'Append translated lyrics when available';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslationDisabled =>
|
||||
'Use original lyrics only';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanization =>
|
||||
'Netease: Include Romanization';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanizationEnabled =>
|
||||
'Append romanized lyrics when available';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanizationDisabled => 'Disabled';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPerson => 'Apple/QQ Multi-Person Word-by-Word';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPersonEnabled =>
|
||||
'Enable v1/v2 speaker and [bg:] tags';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPersonDisabled =>
|
||||
'Simplified word-by-word formatting';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguage => 'Musixmatch Language';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageAuto => 'Auto (original)';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributing =>
|
||||
'Filter contributing artists in Album Artist';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributingEnabled =>
|
||||
'Album Artist metadata uses primary artist only';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributingDisabled =>
|
||||
'Keep full Album Artist metadata value';
|
||||
|
||||
@override
|
||||
String get downloadProvidersNoneEnabled => 'None enabled';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageCode => 'Language code';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageHint => 'auto / en / es / ja';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageDesc =>
|
||||
'Set preferred language code (example: en, es, ja). Leave empty for auto.';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchAuto => 'Auto';
|
||||
|
||||
@override
|
||||
String get downloadLossy320Format => 'Lossy 320kbps Format';
|
||||
|
||||
@override
|
||||
String get downloadLossy320FormatDesc =>
|
||||
'Choose the output format for Tidal 320kbps lossy downloads. The original AAC stream will be converted to your selected format.';
|
||||
|
||||
@override
|
||||
String get downloadLossyMp3 => 'MP3 320kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyMp3Subtitle => 'Best compatibility, ~10MB per track';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus256 => 'Opus 256kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus256Subtitle =>
|
||||
'Best quality Opus, ~8MB per track';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus128 => 'Opus 128kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus128Subtitle => 'Smallest size, ~4MB per track';
|
||||
|
||||
@override
|
||||
String get downloadNetworkAnySubtitle => 'WiFi + Mobile Data';
|
||||
|
||||
@override
|
||||
String get downloadNetworkWifiOnlySubtitle =>
|
||||
'Pause downloads on mobile data';
|
||||
|
||||
@override
|
||||
String get downloadSongLinkRegionDesc =>
|
||||
'Used as userCountry for SongLink API lookup.';
|
||||
|
||||
@override
|
||||
String get snackbarUnsupportedAudioFormat => 'Unsupported audio format';
|
||||
|
||||
@override
|
||||
String get cacheRefresh => 'Refresh';
|
||||
}
|
||||
|
||||
@@ -1200,6 +1200,47 @@ class AppLocalizationsId extends AppLocalizations {
|
||||
@override
|
||||
String get storeClearFilters => 'Hapus filter';
|
||||
|
||||
@override
|
||||
String get storeAddRepoTitle => 'Add Extension Repository';
|
||||
|
||||
@override
|
||||
String get storeAddRepoDescription =>
|
||||
'Enter a GitHub repository URL that contains a registry.json file to browse and install extensions.';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlLabel => 'Repository URL';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlHint => 'https://github.com/user/repo';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlHelper =>
|
||||
'e.g. https://github.com/user/extensions-repo';
|
||||
|
||||
@override
|
||||
String get storeAddRepoButton => 'Add Repository';
|
||||
|
||||
@override
|
||||
String get storeChangeRepoTooltip => 'Change repository';
|
||||
|
||||
@override
|
||||
String get storeRepoDialogTitle => 'Extension Repository';
|
||||
|
||||
@override
|
||||
String get storeRepoDialogCurrent => 'Current repository:';
|
||||
|
||||
@override
|
||||
String get storeNewRepoUrlLabel => 'New Repository URL';
|
||||
|
||||
@override
|
||||
String get storeLoadError => 'Failed to load store';
|
||||
|
||||
@override
|
||||
String get storeEmptyNoExtensions => 'No extensions available';
|
||||
|
||||
@override
|
||||
String get storeEmptyNoResults => 'No extensions found';
|
||||
|
||||
@override
|
||||
String get extensionDefaultProvider => 'Default (Deezer/Spotify)';
|
||||
|
||||
@@ -2415,4 +2456,317 @@ class AppLocalizationsId extends AppLocalizations {
|
||||
@override
|
||||
String get downloadUseAlbumArtistForFoldersTrackSubtitle =>
|
||||
'Artist folders use Track Artist only';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersTitle => 'Lyrics Providers';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersDescription =>
|
||||
'Enable, disable and reorder lyrics sources. Providers are tried top-to-bottom until lyrics are found.';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersInfoText =>
|
||||
'Extension lyrics providers always run before built-in providers. At least one provider must remain enabled.';
|
||||
|
||||
@override
|
||||
String lyricsProvidersEnabledSection(int count) {
|
||||
return 'Enabled ($count)';
|
||||
}
|
||||
|
||||
@override
|
||||
String lyricsProvidersDisabledSection(int count) {
|
||||
return 'Disabled ($count)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get lyricsProvidersAtLeastOne =>
|
||||
'At least one provider must remain enabled';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersSaved => 'Lyrics provider priority saved';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersDiscardContent =>
|
||||
'You have unsaved changes that will be lost.';
|
||||
|
||||
@override
|
||||
String get lyricsProviderSpotifyApiDesc =>
|
||||
'Spotify-sourced synced lyrics via community API';
|
||||
|
||||
@override
|
||||
String get lyricsProviderLrclibDesc => 'Open-source synced lyrics database';
|
||||
|
||||
@override
|
||||
String get lyricsProviderNeteaseDesc =>
|
||||
'NetEase Cloud Music (good for Asian songs)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderMusixmatchDesc =>
|
||||
'Largest lyrics database (multi-language)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderAppleMusicDesc =>
|
||||
'Word-by-word synced lyrics (via proxy)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderQqMusicDesc =>
|
||||
'QQ Music (good for Chinese songs, via proxy)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderExtensionDesc => 'Extension provider';
|
||||
|
||||
@override
|
||||
String get safMigrationTitle => 'Storage Update Required';
|
||||
|
||||
@override
|
||||
String get safMigrationMessage1 =>
|
||||
'SpotiFLAC now uses Android Storage Access Framework (SAF) for downloads. This fixes \"permission denied\" errors on Android 10+.';
|
||||
|
||||
@override
|
||||
String get safMigrationMessage2 =>
|
||||
'Please select your download folder again to switch to the new storage system.';
|
||||
|
||||
@override
|
||||
String get safMigrationSuccess => 'Download folder updated to SAF mode';
|
||||
|
||||
@override
|
||||
String get settingsDonate => 'Donate';
|
||||
|
||||
@override
|
||||
String get settingsDonateSubtitle => 'Support SpotiFLAC-Mobile development';
|
||||
|
||||
@override
|
||||
String get tooltipLoveAll => 'Love All';
|
||||
|
||||
@override
|
||||
String get tooltipAddToPlaylist => 'Add to Playlist';
|
||||
|
||||
@override
|
||||
String snackbarRemovedTracksFromLoved(int count) {
|
||||
return 'Removed $count tracks from Loved';
|
||||
}
|
||||
|
||||
@override
|
||||
String snackbarAddedTracksToLoved(int count) {
|
||||
return 'Added $count tracks to Loved';
|
||||
}
|
||||
|
||||
@override
|
||||
String get dialogDownloadAllTitle => 'Download All';
|
||||
|
||||
@override
|
||||
String dialogDownloadAllMessage(int count) {
|
||||
return 'Download $count tracks?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get dialogDownload => 'Download';
|
||||
|
||||
@override
|
||||
String get homeSkipAlreadyDownloaded => 'Skip already downloaded songs';
|
||||
|
||||
@override
|
||||
String get homeGoToAlbum => 'Go to Album';
|
||||
|
||||
@override
|
||||
String get homeAlbumInfoUnavailable => 'Album info not available';
|
||||
|
||||
@override
|
||||
String get snackbarLoadingCueSheet => 'Loading CUE sheet...';
|
||||
|
||||
@override
|
||||
String get snackbarMetadataSaved => 'Metadata saved successfully';
|
||||
|
||||
@override
|
||||
String get snackbarFailedToEmbedLyrics => 'Failed to embed lyrics';
|
||||
|
||||
@override
|
||||
String get snackbarFailedToWriteStorage => 'Failed to write back to storage';
|
||||
|
||||
@override
|
||||
String snackbarError(String error) {
|
||||
return 'Error: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get snackbarNoActionDefined => 'No action defined for this button';
|
||||
|
||||
@override
|
||||
String get noTracksFoundForAlbum => 'No tracks found for this album';
|
||||
|
||||
@override
|
||||
String get downloadLocationSubtitle =>
|
||||
'Choose storage mode for downloaded files.';
|
||||
|
||||
@override
|
||||
String get storageModeAppFolder => 'App folder (non-SAF)';
|
||||
|
||||
@override
|
||||
String get storageModeAppFolderSubtitle => 'Use default Music/SpotiFLAC path';
|
||||
|
||||
@override
|
||||
String get storageModeSaf => 'SAF folder';
|
||||
|
||||
@override
|
||||
String get storageModeSafSubtitle =>
|
||||
'Pick folder via Android Storage Access Framework';
|
||||
|
||||
@override
|
||||
String get downloadFilenameDescription =>
|
||||
'Customize how your files are named.';
|
||||
|
||||
@override
|
||||
String get downloadFilenameInsertTag => 'Tap to insert tag:';
|
||||
|
||||
@override
|
||||
String get downloadSeparateSinglesEnabled => 'Albums/ and Singles/ folders';
|
||||
|
||||
@override
|
||||
String get downloadSeparateSinglesDisabled => 'All files in same structure';
|
||||
|
||||
@override
|
||||
String get downloadArtistNameFilters => 'Artist Name Filters';
|
||||
|
||||
@override
|
||||
String get downloadSongLinkRegion => 'SongLink Region';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityMode => 'Network compatibility mode';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityModeEnabled =>
|
||||
'Enabled: try HTTP + accept invalid TLS certificates (unsafe)';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityModeDisabled =>
|
||||
'Off: strict HTTPS certificate validation (recommended)';
|
||||
|
||||
@override
|
||||
String get downloadSelectServiceToEnable =>
|
||||
'Select a built-in service to enable';
|
||||
|
||||
@override
|
||||
String get downloadLossy320 => 'Lossy 320kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyFormat => 'Lossy Format';
|
||||
|
||||
@override
|
||||
String get downloadSelectTidalQobuz =>
|
||||
'Select Tidal or Qobuz above to configure quality';
|
||||
|
||||
@override
|
||||
String get downloadEmbedLyricsDisabled =>
|
||||
'Disabled while Embed Metadata is turned off';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslation =>
|
||||
'Netease: Include Translation';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslationEnabled =>
|
||||
'Append translated lyrics when available';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslationDisabled =>
|
||||
'Use original lyrics only';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanization =>
|
||||
'Netease: Include Romanization';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanizationEnabled =>
|
||||
'Append romanized lyrics when available';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanizationDisabled => 'Disabled';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPerson => 'Apple/QQ Multi-Person Word-by-Word';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPersonEnabled =>
|
||||
'Enable v1/v2 speaker and [bg:] tags';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPersonDisabled =>
|
||||
'Simplified word-by-word formatting';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguage => 'Musixmatch Language';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageAuto => 'Auto (original)';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributing =>
|
||||
'Filter contributing artists in Album Artist';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributingEnabled =>
|
||||
'Album Artist metadata uses primary artist only';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributingDisabled =>
|
||||
'Keep full Album Artist metadata value';
|
||||
|
||||
@override
|
||||
String get downloadProvidersNoneEnabled => 'None enabled';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageCode => 'Language code';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageHint => 'auto / en / es / ja';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageDesc =>
|
||||
'Set preferred language code (example: en, es, ja). Leave empty for auto.';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchAuto => 'Auto';
|
||||
|
||||
@override
|
||||
String get downloadLossy320Format => 'Lossy 320kbps Format';
|
||||
|
||||
@override
|
||||
String get downloadLossy320FormatDesc =>
|
||||
'Choose the output format for Tidal 320kbps lossy downloads. The original AAC stream will be converted to your selected format.';
|
||||
|
||||
@override
|
||||
String get downloadLossyMp3 => 'MP3 320kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyMp3Subtitle => 'Best compatibility, ~10MB per track';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus256 => 'Opus 256kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus256Subtitle =>
|
||||
'Best quality Opus, ~8MB per track';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus128 => 'Opus 128kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus128Subtitle => 'Smallest size, ~4MB per track';
|
||||
|
||||
@override
|
||||
String get downloadNetworkAnySubtitle => 'WiFi + Mobile Data';
|
||||
|
||||
@override
|
||||
String get downloadNetworkWifiOnlySubtitle =>
|
||||
'Pause downloads on mobile data';
|
||||
|
||||
@override
|
||||
String get downloadSongLinkRegionDesc =>
|
||||
'Used as userCountry for SongLink API lookup.';
|
||||
|
||||
@override
|
||||
String get snackbarUnsupportedAudioFormat => 'Unsupported audio format';
|
||||
|
||||
@override
|
||||
String get cacheRefresh => 'Refresh';
|
||||
}
|
||||
|
||||
@@ -1189,6 +1189,47 @@ class AppLocalizationsJa extends AppLocalizations {
|
||||
@override
|
||||
String get storeClearFilters => 'フィルターを消去';
|
||||
|
||||
@override
|
||||
String get storeAddRepoTitle => 'Add Extension Repository';
|
||||
|
||||
@override
|
||||
String get storeAddRepoDescription =>
|
||||
'Enter a GitHub repository URL that contains a registry.json file to browse and install extensions.';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlLabel => 'Repository URL';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlHint => 'https://github.com/user/repo';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlHelper =>
|
||||
'e.g. https://github.com/user/extensions-repo';
|
||||
|
||||
@override
|
||||
String get storeAddRepoButton => 'Add Repository';
|
||||
|
||||
@override
|
||||
String get storeChangeRepoTooltip => 'Change repository';
|
||||
|
||||
@override
|
||||
String get storeRepoDialogTitle => 'Extension Repository';
|
||||
|
||||
@override
|
||||
String get storeRepoDialogCurrent => 'Current repository:';
|
||||
|
||||
@override
|
||||
String get storeNewRepoUrlLabel => 'New Repository URL';
|
||||
|
||||
@override
|
||||
String get storeLoadError => 'Failed to load store';
|
||||
|
||||
@override
|
||||
String get storeEmptyNoExtensions => 'No extensions available';
|
||||
|
||||
@override
|
||||
String get storeEmptyNoResults => 'No extensions found';
|
||||
|
||||
@override
|
||||
String get extensionDefaultProvider => 'デフォルト (Deezer/Spotify)';
|
||||
|
||||
@@ -2395,4 +2436,317 @@ class AppLocalizationsJa extends AppLocalizations {
|
||||
@override
|
||||
String get downloadUseAlbumArtistForFoldersTrackSubtitle =>
|
||||
'Artist folders use Track Artist only';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersTitle => 'Lyrics Providers';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersDescription =>
|
||||
'Enable, disable and reorder lyrics sources. Providers are tried top-to-bottom until lyrics are found.';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersInfoText =>
|
||||
'Extension lyrics providers always run before built-in providers. At least one provider must remain enabled.';
|
||||
|
||||
@override
|
||||
String lyricsProvidersEnabledSection(int count) {
|
||||
return 'Enabled ($count)';
|
||||
}
|
||||
|
||||
@override
|
||||
String lyricsProvidersDisabledSection(int count) {
|
||||
return 'Disabled ($count)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get lyricsProvidersAtLeastOne =>
|
||||
'At least one provider must remain enabled';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersSaved => 'Lyrics provider priority saved';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersDiscardContent =>
|
||||
'You have unsaved changes that will be lost.';
|
||||
|
||||
@override
|
||||
String get lyricsProviderSpotifyApiDesc =>
|
||||
'Spotify-sourced synced lyrics via community API';
|
||||
|
||||
@override
|
||||
String get lyricsProviderLrclibDesc => 'Open-source synced lyrics database';
|
||||
|
||||
@override
|
||||
String get lyricsProviderNeteaseDesc =>
|
||||
'NetEase Cloud Music (good for Asian songs)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderMusixmatchDesc =>
|
||||
'Largest lyrics database (multi-language)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderAppleMusicDesc =>
|
||||
'Word-by-word synced lyrics (via proxy)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderQqMusicDesc =>
|
||||
'QQ Music (good for Chinese songs, via proxy)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderExtensionDesc => 'Extension provider';
|
||||
|
||||
@override
|
||||
String get safMigrationTitle => 'Storage Update Required';
|
||||
|
||||
@override
|
||||
String get safMigrationMessage1 =>
|
||||
'SpotiFLAC now uses Android Storage Access Framework (SAF) for downloads. This fixes \"permission denied\" errors on Android 10+.';
|
||||
|
||||
@override
|
||||
String get safMigrationMessage2 =>
|
||||
'Please select your download folder again to switch to the new storage system.';
|
||||
|
||||
@override
|
||||
String get safMigrationSuccess => 'Download folder updated to SAF mode';
|
||||
|
||||
@override
|
||||
String get settingsDonate => 'Donate';
|
||||
|
||||
@override
|
||||
String get settingsDonateSubtitle => 'Support SpotiFLAC-Mobile development';
|
||||
|
||||
@override
|
||||
String get tooltipLoveAll => 'Love All';
|
||||
|
||||
@override
|
||||
String get tooltipAddToPlaylist => 'Add to Playlist';
|
||||
|
||||
@override
|
||||
String snackbarRemovedTracksFromLoved(int count) {
|
||||
return 'Removed $count tracks from Loved';
|
||||
}
|
||||
|
||||
@override
|
||||
String snackbarAddedTracksToLoved(int count) {
|
||||
return 'Added $count tracks to Loved';
|
||||
}
|
||||
|
||||
@override
|
||||
String get dialogDownloadAllTitle => 'Download All';
|
||||
|
||||
@override
|
||||
String dialogDownloadAllMessage(int count) {
|
||||
return 'Download $count tracks?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get dialogDownload => 'Download';
|
||||
|
||||
@override
|
||||
String get homeSkipAlreadyDownloaded => 'Skip already downloaded songs';
|
||||
|
||||
@override
|
||||
String get homeGoToAlbum => 'Go to Album';
|
||||
|
||||
@override
|
||||
String get homeAlbumInfoUnavailable => 'Album info not available';
|
||||
|
||||
@override
|
||||
String get snackbarLoadingCueSheet => 'Loading CUE sheet...';
|
||||
|
||||
@override
|
||||
String get snackbarMetadataSaved => 'Metadata saved successfully';
|
||||
|
||||
@override
|
||||
String get snackbarFailedToEmbedLyrics => 'Failed to embed lyrics';
|
||||
|
||||
@override
|
||||
String get snackbarFailedToWriteStorage => 'Failed to write back to storage';
|
||||
|
||||
@override
|
||||
String snackbarError(String error) {
|
||||
return 'Error: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get snackbarNoActionDefined => 'No action defined for this button';
|
||||
|
||||
@override
|
||||
String get noTracksFoundForAlbum => 'No tracks found for this album';
|
||||
|
||||
@override
|
||||
String get downloadLocationSubtitle =>
|
||||
'Choose storage mode for downloaded files.';
|
||||
|
||||
@override
|
||||
String get storageModeAppFolder => 'App folder (non-SAF)';
|
||||
|
||||
@override
|
||||
String get storageModeAppFolderSubtitle => 'Use default Music/SpotiFLAC path';
|
||||
|
||||
@override
|
||||
String get storageModeSaf => 'SAF folder';
|
||||
|
||||
@override
|
||||
String get storageModeSafSubtitle =>
|
||||
'Pick folder via Android Storage Access Framework';
|
||||
|
||||
@override
|
||||
String get downloadFilenameDescription =>
|
||||
'Customize how your files are named.';
|
||||
|
||||
@override
|
||||
String get downloadFilenameInsertTag => 'Tap to insert tag:';
|
||||
|
||||
@override
|
||||
String get downloadSeparateSinglesEnabled => 'Albums/ and Singles/ folders';
|
||||
|
||||
@override
|
||||
String get downloadSeparateSinglesDisabled => 'All files in same structure';
|
||||
|
||||
@override
|
||||
String get downloadArtistNameFilters => 'Artist Name Filters';
|
||||
|
||||
@override
|
||||
String get downloadSongLinkRegion => 'SongLink Region';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityMode => 'Network compatibility mode';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityModeEnabled =>
|
||||
'Enabled: try HTTP + accept invalid TLS certificates (unsafe)';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityModeDisabled =>
|
||||
'Off: strict HTTPS certificate validation (recommended)';
|
||||
|
||||
@override
|
||||
String get downloadSelectServiceToEnable =>
|
||||
'Select a built-in service to enable';
|
||||
|
||||
@override
|
||||
String get downloadLossy320 => 'Lossy 320kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyFormat => 'Lossy Format';
|
||||
|
||||
@override
|
||||
String get downloadSelectTidalQobuz =>
|
||||
'Select Tidal or Qobuz above to configure quality';
|
||||
|
||||
@override
|
||||
String get downloadEmbedLyricsDisabled =>
|
||||
'Disabled while Embed Metadata is turned off';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslation =>
|
||||
'Netease: Include Translation';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslationEnabled =>
|
||||
'Append translated lyrics when available';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslationDisabled =>
|
||||
'Use original lyrics only';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanization =>
|
||||
'Netease: Include Romanization';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanizationEnabled =>
|
||||
'Append romanized lyrics when available';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanizationDisabled => 'Disabled';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPerson => 'Apple/QQ Multi-Person Word-by-Word';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPersonEnabled =>
|
||||
'Enable v1/v2 speaker and [bg:] tags';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPersonDisabled =>
|
||||
'Simplified word-by-word formatting';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguage => 'Musixmatch Language';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageAuto => 'Auto (original)';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributing =>
|
||||
'Filter contributing artists in Album Artist';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributingEnabled =>
|
||||
'Album Artist metadata uses primary artist only';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributingDisabled =>
|
||||
'Keep full Album Artist metadata value';
|
||||
|
||||
@override
|
||||
String get downloadProvidersNoneEnabled => 'None enabled';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageCode => 'Language code';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageHint => 'auto / en / es / ja';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageDesc =>
|
||||
'Set preferred language code (example: en, es, ja). Leave empty for auto.';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchAuto => 'Auto';
|
||||
|
||||
@override
|
||||
String get downloadLossy320Format => 'Lossy 320kbps Format';
|
||||
|
||||
@override
|
||||
String get downloadLossy320FormatDesc =>
|
||||
'Choose the output format for Tidal 320kbps lossy downloads. The original AAC stream will be converted to your selected format.';
|
||||
|
||||
@override
|
||||
String get downloadLossyMp3 => 'MP3 320kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyMp3Subtitle => 'Best compatibility, ~10MB per track';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus256 => 'Opus 256kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus256Subtitle =>
|
||||
'Best quality Opus, ~8MB per track';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus128 => 'Opus 128kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus128Subtitle => 'Smallest size, ~4MB per track';
|
||||
|
||||
@override
|
||||
String get downloadNetworkAnySubtitle => 'WiFi + Mobile Data';
|
||||
|
||||
@override
|
||||
String get downloadNetworkWifiOnlySubtitle =>
|
||||
'Pause downloads on mobile data';
|
||||
|
||||
@override
|
||||
String get downloadSongLinkRegionDesc =>
|
||||
'Used as userCountry for SongLink API lookup.';
|
||||
|
||||
@override
|
||||
String get snackbarUnsupportedAudioFormat => 'Unsupported audio format';
|
||||
|
||||
@override
|
||||
String get cacheRefresh => 'Refresh';
|
||||
}
|
||||
|
||||
@@ -1175,6 +1175,47 @@ class AppLocalizationsKo extends AppLocalizations {
|
||||
@override
|
||||
String get storeClearFilters => 'Clear filters';
|
||||
|
||||
@override
|
||||
String get storeAddRepoTitle => 'Add Extension Repository';
|
||||
|
||||
@override
|
||||
String get storeAddRepoDescription =>
|
||||
'Enter a GitHub repository URL that contains a registry.json file to browse and install extensions.';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlLabel => 'Repository URL';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlHint => 'https://github.com/user/repo';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlHelper =>
|
||||
'e.g. https://github.com/user/extensions-repo';
|
||||
|
||||
@override
|
||||
String get storeAddRepoButton => 'Add Repository';
|
||||
|
||||
@override
|
||||
String get storeChangeRepoTooltip => 'Change repository';
|
||||
|
||||
@override
|
||||
String get storeRepoDialogTitle => 'Extension Repository';
|
||||
|
||||
@override
|
||||
String get storeRepoDialogCurrent => 'Current repository:';
|
||||
|
||||
@override
|
||||
String get storeNewRepoUrlLabel => 'New Repository URL';
|
||||
|
||||
@override
|
||||
String get storeLoadError => 'Failed to load store';
|
||||
|
||||
@override
|
||||
String get storeEmptyNoExtensions => 'No extensions available';
|
||||
|
||||
@override
|
||||
String get storeEmptyNoResults => 'No extensions found';
|
||||
|
||||
@override
|
||||
String get extensionDefaultProvider => 'Default (Deezer/Spotify)';
|
||||
|
||||
@@ -2388,4 +2429,317 @@ class AppLocalizationsKo extends AppLocalizations {
|
||||
@override
|
||||
String get downloadUseAlbumArtistForFoldersTrackSubtitle =>
|
||||
'Artist folders use Track Artist only';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersTitle => 'Lyrics Providers';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersDescription =>
|
||||
'Enable, disable and reorder lyrics sources. Providers are tried top-to-bottom until lyrics are found.';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersInfoText =>
|
||||
'Extension lyrics providers always run before built-in providers. At least one provider must remain enabled.';
|
||||
|
||||
@override
|
||||
String lyricsProvidersEnabledSection(int count) {
|
||||
return 'Enabled ($count)';
|
||||
}
|
||||
|
||||
@override
|
||||
String lyricsProvidersDisabledSection(int count) {
|
||||
return 'Disabled ($count)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get lyricsProvidersAtLeastOne =>
|
||||
'At least one provider must remain enabled';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersSaved => 'Lyrics provider priority saved';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersDiscardContent =>
|
||||
'You have unsaved changes that will be lost.';
|
||||
|
||||
@override
|
||||
String get lyricsProviderSpotifyApiDesc =>
|
||||
'Spotify-sourced synced lyrics via community API';
|
||||
|
||||
@override
|
||||
String get lyricsProviderLrclibDesc => 'Open-source synced lyrics database';
|
||||
|
||||
@override
|
||||
String get lyricsProviderNeteaseDesc =>
|
||||
'NetEase Cloud Music (good for Asian songs)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderMusixmatchDesc =>
|
||||
'Largest lyrics database (multi-language)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderAppleMusicDesc =>
|
||||
'Word-by-word synced lyrics (via proxy)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderQqMusicDesc =>
|
||||
'QQ Music (good for Chinese songs, via proxy)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderExtensionDesc => 'Extension provider';
|
||||
|
||||
@override
|
||||
String get safMigrationTitle => 'Storage Update Required';
|
||||
|
||||
@override
|
||||
String get safMigrationMessage1 =>
|
||||
'SpotiFLAC now uses Android Storage Access Framework (SAF) for downloads. This fixes \"permission denied\" errors on Android 10+.';
|
||||
|
||||
@override
|
||||
String get safMigrationMessage2 =>
|
||||
'Please select your download folder again to switch to the new storage system.';
|
||||
|
||||
@override
|
||||
String get safMigrationSuccess => 'Download folder updated to SAF mode';
|
||||
|
||||
@override
|
||||
String get settingsDonate => 'Donate';
|
||||
|
||||
@override
|
||||
String get settingsDonateSubtitle => 'Support SpotiFLAC-Mobile development';
|
||||
|
||||
@override
|
||||
String get tooltipLoveAll => 'Love All';
|
||||
|
||||
@override
|
||||
String get tooltipAddToPlaylist => 'Add to Playlist';
|
||||
|
||||
@override
|
||||
String snackbarRemovedTracksFromLoved(int count) {
|
||||
return 'Removed $count tracks from Loved';
|
||||
}
|
||||
|
||||
@override
|
||||
String snackbarAddedTracksToLoved(int count) {
|
||||
return 'Added $count tracks to Loved';
|
||||
}
|
||||
|
||||
@override
|
||||
String get dialogDownloadAllTitle => 'Download All';
|
||||
|
||||
@override
|
||||
String dialogDownloadAllMessage(int count) {
|
||||
return 'Download $count tracks?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get dialogDownload => 'Download';
|
||||
|
||||
@override
|
||||
String get homeSkipAlreadyDownloaded => 'Skip already downloaded songs';
|
||||
|
||||
@override
|
||||
String get homeGoToAlbum => 'Go to Album';
|
||||
|
||||
@override
|
||||
String get homeAlbumInfoUnavailable => 'Album info not available';
|
||||
|
||||
@override
|
||||
String get snackbarLoadingCueSheet => 'Loading CUE sheet...';
|
||||
|
||||
@override
|
||||
String get snackbarMetadataSaved => 'Metadata saved successfully';
|
||||
|
||||
@override
|
||||
String get snackbarFailedToEmbedLyrics => 'Failed to embed lyrics';
|
||||
|
||||
@override
|
||||
String get snackbarFailedToWriteStorage => 'Failed to write back to storage';
|
||||
|
||||
@override
|
||||
String snackbarError(String error) {
|
||||
return 'Error: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get snackbarNoActionDefined => 'No action defined for this button';
|
||||
|
||||
@override
|
||||
String get noTracksFoundForAlbum => 'No tracks found for this album';
|
||||
|
||||
@override
|
||||
String get downloadLocationSubtitle =>
|
||||
'Choose storage mode for downloaded files.';
|
||||
|
||||
@override
|
||||
String get storageModeAppFolder => 'App folder (non-SAF)';
|
||||
|
||||
@override
|
||||
String get storageModeAppFolderSubtitle => 'Use default Music/SpotiFLAC path';
|
||||
|
||||
@override
|
||||
String get storageModeSaf => 'SAF folder';
|
||||
|
||||
@override
|
||||
String get storageModeSafSubtitle =>
|
||||
'Pick folder via Android Storage Access Framework';
|
||||
|
||||
@override
|
||||
String get downloadFilenameDescription =>
|
||||
'Customize how your files are named.';
|
||||
|
||||
@override
|
||||
String get downloadFilenameInsertTag => 'Tap to insert tag:';
|
||||
|
||||
@override
|
||||
String get downloadSeparateSinglesEnabled => 'Albums/ and Singles/ folders';
|
||||
|
||||
@override
|
||||
String get downloadSeparateSinglesDisabled => 'All files in same structure';
|
||||
|
||||
@override
|
||||
String get downloadArtistNameFilters => 'Artist Name Filters';
|
||||
|
||||
@override
|
||||
String get downloadSongLinkRegion => 'SongLink Region';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityMode => 'Network compatibility mode';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityModeEnabled =>
|
||||
'Enabled: try HTTP + accept invalid TLS certificates (unsafe)';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityModeDisabled =>
|
||||
'Off: strict HTTPS certificate validation (recommended)';
|
||||
|
||||
@override
|
||||
String get downloadSelectServiceToEnable =>
|
||||
'Select a built-in service to enable';
|
||||
|
||||
@override
|
||||
String get downloadLossy320 => 'Lossy 320kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyFormat => 'Lossy Format';
|
||||
|
||||
@override
|
||||
String get downloadSelectTidalQobuz =>
|
||||
'Select Tidal or Qobuz above to configure quality';
|
||||
|
||||
@override
|
||||
String get downloadEmbedLyricsDisabled =>
|
||||
'Disabled while Embed Metadata is turned off';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslation =>
|
||||
'Netease: Include Translation';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslationEnabled =>
|
||||
'Append translated lyrics when available';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslationDisabled =>
|
||||
'Use original lyrics only';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanization =>
|
||||
'Netease: Include Romanization';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanizationEnabled =>
|
||||
'Append romanized lyrics when available';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanizationDisabled => 'Disabled';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPerson => 'Apple/QQ Multi-Person Word-by-Word';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPersonEnabled =>
|
||||
'Enable v1/v2 speaker and [bg:] tags';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPersonDisabled =>
|
||||
'Simplified word-by-word formatting';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguage => 'Musixmatch Language';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageAuto => 'Auto (original)';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributing =>
|
||||
'Filter contributing artists in Album Artist';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributingEnabled =>
|
||||
'Album Artist metadata uses primary artist only';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributingDisabled =>
|
||||
'Keep full Album Artist metadata value';
|
||||
|
||||
@override
|
||||
String get downloadProvidersNoneEnabled => 'None enabled';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageCode => 'Language code';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageHint => 'auto / en / es / ja';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageDesc =>
|
||||
'Set preferred language code (example: en, es, ja). Leave empty for auto.';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchAuto => 'Auto';
|
||||
|
||||
@override
|
||||
String get downloadLossy320Format => 'Lossy 320kbps Format';
|
||||
|
||||
@override
|
||||
String get downloadLossy320FormatDesc =>
|
||||
'Choose the output format for Tidal 320kbps lossy downloads. The original AAC stream will be converted to your selected format.';
|
||||
|
||||
@override
|
||||
String get downloadLossyMp3 => 'MP3 320kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyMp3Subtitle => 'Best compatibility, ~10MB per track';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus256 => 'Opus 256kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus256Subtitle =>
|
||||
'Best quality Opus, ~8MB per track';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus128 => 'Opus 128kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus128Subtitle => 'Smallest size, ~4MB per track';
|
||||
|
||||
@override
|
||||
String get downloadNetworkAnySubtitle => 'WiFi + Mobile Data';
|
||||
|
||||
@override
|
||||
String get downloadNetworkWifiOnlySubtitle =>
|
||||
'Pause downloads on mobile data';
|
||||
|
||||
@override
|
||||
String get downloadSongLinkRegionDesc =>
|
||||
'Used as userCountry for SongLink API lookup.';
|
||||
|
||||
@override
|
||||
String get snackbarUnsupportedAudioFormat => 'Unsupported audio format';
|
||||
|
||||
@override
|
||||
String get cacheRefresh => 'Refresh';
|
||||
}
|
||||
|
||||
@@ -1195,6 +1195,47 @@ class AppLocalizationsNl extends AppLocalizations {
|
||||
@override
|
||||
String get storeClearFilters => 'Clear filters';
|
||||
|
||||
@override
|
||||
String get storeAddRepoTitle => 'Add Extension Repository';
|
||||
|
||||
@override
|
||||
String get storeAddRepoDescription =>
|
||||
'Enter a GitHub repository URL that contains a registry.json file to browse and install extensions.';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlLabel => 'Repository URL';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlHint => 'https://github.com/user/repo';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlHelper =>
|
||||
'e.g. https://github.com/user/extensions-repo';
|
||||
|
||||
@override
|
||||
String get storeAddRepoButton => 'Add Repository';
|
||||
|
||||
@override
|
||||
String get storeChangeRepoTooltip => 'Change repository';
|
||||
|
||||
@override
|
||||
String get storeRepoDialogTitle => 'Extension Repository';
|
||||
|
||||
@override
|
||||
String get storeRepoDialogCurrent => 'Current repository:';
|
||||
|
||||
@override
|
||||
String get storeNewRepoUrlLabel => 'New Repository URL';
|
||||
|
||||
@override
|
||||
String get storeLoadError => 'Failed to load store';
|
||||
|
||||
@override
|
||||
String get storeEmptyNoExtensions => 'No extensions available';
|
||||
|
||||
@override
|
||||
String get storeEmptyNoResults => 'No extensions found';
|
||||
|
||||
@override
|
||||
String get extensionDefaultProvider => 'Default (Deezer/Spotify)';
|
||||
|
||||
@@ -2408,4 +2449,317 @@ class AppLocalizationsNl extends AppLocalizations {
|
||||
@override
|
||||
String get downloadUseAlbumArtistForFoldersTrackSubtitle =>
|
||||
'Artist folders use Track Artist only';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersTitle => 'Lyrics Providers';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersDescription =>
|
||||
'Enable, disable and reorder lyrics sources. Providers are tried top-to-bottom until lyrics are found.';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersInfoText =>
|
||||
'Extension lyrics providers always run before built-in providers. At least one provider must remain enabled.';
|
||||
|
||||
@override
|
||||
String lyricsProvidersEnabledSection(int count) {
|
||||
return 'Enabled ($count)';
|
||||
}
|
||||
|
||||
@override
|
||||
String lyricsProvidersDisabledSection(int count) {
|
||||
return 'Disabled ($count)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get lyricsProvidersAtLeastOne =>
|
||||
'At least one provider must remain enabled';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersSaved => 'Lyrics provider priority saved';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersDiscardContent =>
|
||||
'You have unsaved changes that will be lost.';
|
||||
|
||||
@override
|
||||
String get lyricsProviderSpotifyApiDesc =>
|
||||
'Spotify-sourced synced lyrics via community API';
|
||||
|
||||
@override
|
||||
String get lyricsProviderLrclibDesc => 'Open-source synced lyrics database';
|
||||
|
||||
@override
|
||||
String get lyricsProviderNeteaseDesc =>
|
||||
'NetEase Cloud Music (good for Asian songs)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderMusixmatchDesc =>
|
||||
'Largest lyrics database (multi-language)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderAppleMusicDesc =>
|
||||
'Word-by-word synced lyrics (via proxy)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderQqMusicDesc =>
|
||||
'QQ Music (good for Chinese songs, via proxy)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderExtensionDesc => 'Extension provider';
|
||||
|
||||
@override
|
||||
String get safMigrationTitle => 'Storage Update Required';
|
||||
|
||||
@override
|
||||
String get safMigrationMessage1 =>
|
||||
'SpotiFLAC now uses Android Storage Access Framework (SAF) for downloads. This fixes \"permission denied\" errors on Android 10+.';
|
||||
|
||||
@override
|
||||
String get safMigrationMessage2 =>
|
||||
'Please select your download folder again to switch to the new storage system.';
|
||||
|
||||
@override
|
||||
String get safMigrationSuccess => 'Download folder updated to SAF mode';
|
||||
|
||||
@override
|
||||
String get settingsDonate => 'Donate';
|
||||
|
||||
@override
|
||||
String get settingsDonateSubtitle => 'Support SpotiFLAC-Mobile development';
|
||||
|
||||
@override
|
||||
String get tooltipLoveAll => 'Love All';
|
||||
|
||||
@override
|
||||
String get tooltipAddToPlaylist => 'Add to Playlist';
|
||||
|
||||
@override
|
||||
String snackbarRemovedTracksFromLoved(int count) {
|
||||
return 'Removed $count tracks from Loved';
|
||||
}
|
||||
|
||||
@override
|
||||
String snackbarAddedTracksToLoved(int count) {
|
||||
return 'Added $count tracks to Loved';
|
||||
}
|
||||
|
||||
@override
|
||||
String get dialogDownloadAllTitle => 'Download All';
|
||||
|
||||
@override
|
||||
String dialogDownloadAllMessage(int count) {
|
||||
return 'Download $count tracks?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get dialogDownload => 'Download';
|
||||
|
||||
@override
|
||||
String get homeSkipAlreadyDownloaded => 'Skip already downloaded songs';
|
||||
|
||||
@override
|
||||
String get homeGoToAlbum => 'Go to Album';
|
||||
|
||||
@override
|
||||
String get homeAlbumInfoUnavailable => 'Album info not available';
|
||||
|
||||
@override
|
||||
String get snackbarLoadingCueSheet => 'Loading CUE sheet...';
|
||||
|
||||
@override
|
||||
String get snackbarMetadataSaved => 'Metadata saved successfully';
|
||||
|
||||
@override
|
||||
String get snackbarFailedToEmbedLyrics => 'Failed to embed lyrics';
|
||||
|
||||
@override
|
||||
String get snackbarFailedToWriteStorage => 'Failed to write back to storage';
|
||||
|
||||
@override
|
||||
String snackbarError(String error) {
|
||||
return 'Error: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get snackbarNoActionDefined => 'No action defined for this button';
|
||||
|
||||
@override
|
||||
String get noTracksFoundForAlbum => 'No tracks found for this album';
|
||||
|
||||
@override
|
||||
String get downloadLocationSubtitle =>
|
||||
'Choose storage mode for downloaded files.';
|
||||
|
||||
@override
|
||||
String get storageModeAppFolder => 'App folder (non-SAF)';
|
||||
|
||||
@override
|
||||
String get storageModeAppFolderSubtitle => 'Use default Music/SpotiFLAC path';
|
||||
|
||||
@override
|
||||
String get storageModeSaf => 'SAF folder';
|
||||
|
||||
@override
|
||||
String get storageModeSafSubtitle =>
|
||||
'Pick folder via Android Storage Access Framework';
|
||||
|
||||
@override
|
||||
String get downloadFilenameDescription =>
|
||||
'Customize how your files are named.';
|
||||
|
||||
@override
|
||||
String get downloadFilenameInsertTag => 'Tap to insert tag:';
|
||||
|
||||
@override
|
||||
String get downloadSeparateSinglesEnabled => 'Albums/ and Singles/ folders';
|
||||
|
||||
@override
|
||||
String get downloadSeparateSinglesDisabled => 'All files in same structure';
|
||||
|
||||
@override
|
||||
String get downloadArtistNameFilters => 'Artist Name Filters';
|
||||
|
||||
@override
|
||||
String get downloadSongLinkRegion => 'SongLink Region';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityMode => 'Network compatibility mode';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityModeEnabled =>
|
||||
'Enabled: try HTTP + accept invalid TLS certificates (unsafe)';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityModeDisabled =>
|
||||
'Off: strict HTTPS certificate validation (recommended)';
|
||||
|
||||
@override
|
||||
String get downloadSelectServiceToEnable =>
|
||||
'Select a built-in service to enable';
|
||||
|
||||
@override
|
||||
String get downloadLossy320 => 'Lossy 320kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyFormat => 'Lossy Format';
|
||||
|
||||
@override
|
||||
String get downloadSelectTidalQobuz =>
|
||||
'Select Tidal or Qobuz above to configure quality';
|
||||
|
||||
@override
|
||||
String get downloadEmbedLyricsDisabled =>
|
||||
'Disabled while Embed Metadata is turned off';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslation =>
|
||||
'Netease: Include Translation';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslationEnabled =>
|
||||
'Append translated lyrics when available';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslationDisabled =>
|
||||
'Use original lyrics only';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanization =>
|
||||
'Netease: Include Romanization';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanizationEnabled =>
|
||||
'Append romanized lyrics when available';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanizationDisabled => 'Disabled';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPerson => 'Apple/QQ Multi-Person Word-by-Word';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPersonEnabled =>
|
||||
'Enable v1/v2 speaker and [bg:] tags';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPersonDisabled =>
|
||||
'Simplified word-by-word formatting';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguage => 'Musixmatch Language';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageAuto => 'Auto (original)';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributing =>
|
||||
'Filter contributing artists in Album Artist';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributingEnabled =>
|
||||
'Album Artist metadata uses primary artist only';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributingDisabled =>
|
||||
'Keep full Album Artist metadata value';
|
||||
|
||||
@override
|
||||
String get downloadProvidersNoneEnabled => 'None enabled';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageCode => 'Language code';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageHint => 'auto / en / es / ja';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageDesc =>
|
||||
'Set preferred language code (example: en, es, ja). Leave empty for auto.';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchAuto => 'Auto';
|
||||
|
||||
@override
|
||||
String get downloadLossy320Format => 'Lossy 320kbps Format';
|
||||
|
||||
@override
|
||||
String get downloadLossy320FormatDesc =>
|
||||
'Choose the output format for Tidal 320kbps lossy downloads. The original AAC stream will be converted to your selected format.';
|
||||
|
||||
@override
|
||||
String get downloadLossyMp3 => 'MP3 320kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyMp3Subtitle => 'Best compatibility, ~10MB per track';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus256 => 'Opus 256kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus256Subtitle =>
|
||||
'Best quality Opus, ~8MB per track';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus128 => 'Opus 128kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus128Subtitle => 'Smallest size, ~4MB per track';
|
||||
|
||||
@override
|
||||
String get downloadNetworkAnySubtitle => 'WiFi + Mobile Data';
|
||||
|
||||
@override
|
||||
String get downloadNetworkWifiOnlySubtitle =>
|
||||
'Pause downloads on mobile data';
|
||||
|
||||
@override
|
||||
String get downloadSongLinkRegionDesc =>
|
||||
'Used as userCountry for SongLink API lookup.';
|
||||
|
||||
@override
|
||||
String get snackbarUnsupportedAudioFormat => 'Unsupported audio format';
|
||||
|
||||
@override
|
||||
String get cacheRefresh => 'Refresh';
|
||||
}
|
||||
|
||||
@@ -1195,6 +1195,47 @@ class AppLocalizationsPt extends AppLocalizations {
|
||||
@override
|
||||
String get storeClearFilters => 'Clear filters';
|
||||
|
||||
@override
|
||||
String get storeAddRepoTitle => 'Add Extension Repository';
|
||||
|
||||
@override
|
||||
String get storeAddRepoDescription =>
|
||||
'Enter a GitHub repository URL that contains a registry.json file to browse and install extensions.';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlLabel => 'Repository URL';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlHint => 'https://github.com/user/repo';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlHelper =>
|
||||
'e.g. https://github.com/user/extensions-repo';
|
||||
|
||||
@override
|
||||
String get storeAddRepoButton => 'Add Repository';
|
||||
|
||||
@override
|
||||
String get storeChangeRepoTooltip => 'Change repository';
|
||||
|
||||
@override
|
||||
String get storeRepoDialogTitle => 'Extension Repository';
|
||||
|
||||
@override
|
||||
String get storeRepoDialogCurrent => 'Current repository:';
|
||||
|
||||
@override
|
||||
String get storeNewRepoUrlLabel => 'New Repository URL';
|
||||
|
||||
@override
|
||||
String get storeLoadError => 'Failed to load store';
|
||||
|
||||
@override
|
||||
String get storeEmptyNoExtensions => 'No extensions available';
|
||||
|
||||
@override
|
||||
String get storeEmptyNoResults => 'No extensions found';
|
||||
|
||||
@override
|
||||
String get extensionDefaultProvider => 'Default (Deezer/Spotify)';
|
||||
|
||||
@@ -2408,6 +2449,319 @@ class AppLocalizationsPt extends AppLocalizations {
|
||||
@override
|
||||
String get downloadUseAlbumArtistForFoldersTrackSubtitle =>
|
||||
'Artist folders use Track Artist only';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersTitle => 'Lyrics Providers';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersDescription =>
|
||||
'Enable, disable and reorder lyrics sources. Providers are tried top-to-bottom until lyrics are found.';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersInfoText =>
|
||||
'Extension lyrics providers always run before built-in providers. At least one provider must remain enabled.';
|
||||
|
||||
@override
|
||||
String lyricsProvidersEnabledSection(int count) {
|
||||
return 'Enabled ($count)';
|
||||
}
|
||||
|
||||
@override
|
||||
String lyricsProvidersDisabledSection(int count) {
|
||||
return 'Disabled ($count)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get lyricsProvidersAtLeastOne =>
|
||||
'At least one provider must remain enabled';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersSaved => 'Lyrics provider priority saved';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersDiscardContent =>
|
||||
'You have unsaved changes that will be lost.';
|
||||
|
||||
@override
|
||||
String get lyricsProviderSpotifyApiDesc =>
|
||||
'Spotify-sourced synced lyrics via community API';
|
||||
|
||||
@override
|
||||
String get lyricsProviderLrclibDesc => 'Open-source synced lyrics database';
|
||||
|
||||
@override
|
||||
String get lyricsProviderNeteaseDesc =>
|
||||
'NetEase Cloud Music (good for Asian songs)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderMusixmatchDesc =>
|
||||
'Largest lyrics database (multi-language)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderAppleMusicDesc =>
|
||||
'Word-by-word synced lyrics (via proxy)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderQqMusicDesc =>
|
||||
'QQ Music (good for Chinese songs, via proxy)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderExtensionDesc => 'Extension provider';
|
||||
|
||||
@override
|
||||
String get safMigrationTitle => 'Storage Update Required';
|
||||
|
||||
@override
|
||||
String get safMigrationMessage1 =>
|
||||
'SpotiFLAC now uses Android Storage Access Framework (SAF) for downloads. This fixes \"permission denied\" errors on Android 10+.';
|
||||
|
||||
@override
|
||||
String get safMigrationMessage2 =>
|
||||
'Please select your download folder again to switch to the new storage system.';
|
||||
|
||||
@override
|
||||
String get safMigrationSuccess => 'Download folder updated to SAF mode';
|
||||
|
||||
@override
|
||||
String get settingsDonate => 'Donate';
|
||||
|
||||
@override
|
||||
String get settingsDonateSubtitle => 'Support SpotiFLAC-Mobile development';
|
||||
|
||||
@override
|
||||
String get tooltipLoveAll => 'Love All';
|
||||
|
||||
@override
|
||||
String get tooltipAddToPlaylist => 'Add to Playlist';
|
||||
|
||||
@override
|
||||
String snackbarRemovedTracksFromLoved(int count) {
|
||||
return 'Removed $count tracks from Loved';
|
||||
}
|
||||
|
||||
@override
|
||||
String snackbarAddedTracksToLoved(int count) {
|
||||
return 'Added $count tracks to Loved';
|
||||
}
|
||||
|
||||
@override
|
||||
String get dialogDownloadAllTitle => 'Download All';
|
||||
|
||||
@override
|
||||
String dialogDownloadAllMessage(int count) {
|
||||
return 'Download $count tracks?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get dialogDownload => 'Download';
|
||||
|
||||
@override
|
||||
String get homeSkipAlreadyDownloaded => 'Skip already downloaded songs';
|
||||
|
||||
@override
|
||||
String get homeGoToAlbum => 'Go to Album';
|
||||
|
||||
@override
|
||||
String get homeAlbumInfoUnavailable => 'Album info not available';
|
||||
|
||||
@override
|
||||
String get snackbarLoadingCueSheet => 'Loading CUE sheet...';
|
||||
|
||||
@override
|
||||
String get snackbarMetadataSaved => 'Metadata saved successfully';
|
||||
|
||||
@override
|
||||
String get snackbarFailedToEmbedLyrics => 'Failed to embed lyrics';
|
||||
|
||||
@override
|
||||
String get snackbarFailedToWriteStorage => 'Failed to write back to storage';
|
||||
|
||||
@override
|
||||
String snackbarError(String error) {
|
||||
return 'Error: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get snackbarNoActionDefined => 'No action defined for this button';
|
||||
|
||||
@override
|
||||
String get noTracksFoundForAlbum => 'No tracks found for this album';
|
||||
|
||||
@override
|
||||
String get downloadLocationSubtitle =>
|
||||
'Choose storage mode for downloaded files.';
|
||||
|
||||
@override
|
||||
String get storageModeAppFolder => 'App folder (non-SAF)';
|
||||
|
||||
@override
|
||||
String get storageModeAppFolderSubtitle => 'Use default Music/SpotiFLAC path';
|
||||
|
||||
@override
|
||||
String get storageModeSaf => 'SAF folder';
|
||||
|
||||
@override
|
||||
String get storageModeSafSubtitle =>
|
||||
'Pick folder via Android Storage Access Framework';
|
||||
|
||||
@override
|
||||
String get downloadFilenameDescription =>
|
||||
'Customize how your files are named.';
|
||||
|
||||
@override
|
||||
String get downloadFilenameInsertTag => 'Tap to insert tag:';
|
||||
|
||||
@override
|
||||
String get downloadSeparateSinglesEnabled => 'Albums/ and Singles/ folders';
|
||||
|
||||
@override
|
||||
String get downloadSeparateSinglesDisabled => 'All files in same structure';
|
||||
|
||||
@override
|
||||
String get downloadArtistNameFilters => 'Artist Name Filters';
|
||||
|
||||
@override
|
||||
String get downloadSongLinkRegion => 'SongLink Region';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityMode => 'Network compatibility mode';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityModeEnabled =>
|
||||
'Enabled: try HTTP + accept invalid TLS certificates (unsafe)';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityModeDisabled =>
|
||||
'Off: strict HTTPS certificate validation (recommended)';
|
||||
|
||||
@override
|
||||
String get downloadSelectServiceToEnable =>
|
||||
'Select a built-in service to enable';
|
||||
|
||||
@override
|
||||
String get downloadLossy320 => 'Lossy 320kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyFormat => 'Lossy Format';
|
||||
|
||||
@override
|
||||
String get downloadSelectTidalQobuz =>
|
||||
'Select Tidal or Qobuz above to configure quality';
|
||||
|
||||
@override
|
||||
String get downloadEmbedLyricsDisabled =>
|
||||
'Disabled while Embed Metadata is turned off';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslation =>
|
||||
'Netease: Include Translation';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslationEnabled =>
|
||||
'Append translated lyrics when available';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslationDisabled =>
|
||||
'Use original lyrics only';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanization =>
|
||||
'Netease: Include Romanization';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanizationEnabled =>
|
||||
'Append romanized lyrics when available';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanizationDisabled => 'Disabled';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPerson => 'Apple/QQ Multi-Person Word-by-Word';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPersonEnabled =>
|
||||
'Enable v1/v2 speaker and [bg:] tags';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPersonDisabled =>
|
||||
'Simplified word-by-word formatting';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguage => 'Musixmatch Language';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageAuto => 'Auto (original)';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributing =>
|
||||
'Filter contributing artists in Album Artist';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributingEnabled =>
|
||||
'Album Artist metadata uses primary artist only';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributingDisabled =>
|
||||
'Keep full Album Artist metadata value';
|
||||
|
||||
@override
|
||||
String get downloadProvidersNoneEnabled => 'None enabled';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageCode => 'Language code';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageHint => 'auto / en / es / ja';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageDesc =>
|
||||
'Set preferred language code (example: en, es, ja). Leave empty for auto.';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchAuto => 'Auto';
|
||||
|
||||
@override
|
||||
String get downloadLossy320Format => 'Lossy 320kbps Format';
|
||||
|
||||
@override
|
||||
String get downloadLossy320FormatDesc =>
|
||||
'Choose the output format for Tidal 320kbps lossy downloads. The original AAC stream will be converted to your selected format.';
|
||||
|
||||
@override
|
||||
String get downloadLossyMp3 => 'MP3 320kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyMp3Subtitle => 'Best compatibility, ~10MB per track';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus256 => 'Opus 256kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus256Subtitle =>
|
||||
'Best quality Opus, ~8MB per track';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus128 => 'Opus 128kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus128Subtitle => 'Smallest size, ~4MB per track';
|
||||
|
||||
@override
|
||||
String get downloadNetworkAnySubtitle => 'WiFi + Mobile Data';
|
||||
|
||||
@override
|
||||
String get downloadNetworkWifiOnlySubtitle =>
|
||||
'Pause downloads on mobile data';
|
||||
|
||||
@override
|
||||
String get downloadSongLinkRegionDesc =>
|
||||
'Used as userCountry for SongLink API lookup.';
|
||||
|
||||
@override
|
||||
String get snackbarUnsupportedAudioFormat => 'Unsupported audio format';
|
||||
|
||||
@override
|
||||
String get cacheRefresh => 'Refresh';
|
||||
}
|
||||
|
||||
/// The translations for Portuguese, as used in Portugal (`pt_PT`).
|
||||
|
||||
@@ -1216,6 +1216,47 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
@override
|
||||
String get storeClearFilters => 'Очистить фильтры';
|
||||
|
||||
@override
|
||||
String get storeAddRepoTitle => 'Add Extension Repository';
|
||||
|
||||
@override
|
||||
String get storeAddRepoDescription =>
|
||||
'Enter a GitHub repository URL that contains a registry.json file to browse and install extensions.';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlLabel => 'Repository URL';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlHint => 'https://github.com/user/repo';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlHelper =>
|
||||
'e.g. https://github.com/user/extensions-repo';
|
||||
|
||||
@override
|
||||
String get storeAddRepoButton => 'Add Repository';
|
||||
|
||||
@override
|
||||
String get storeChangeRepoTooltip => 'Change repository';
|
||||
|
||||
@override
|
||||
String get storeRepoDialogTitle => 'Extension Repository';
|
||||
|
||||
@override
|
||||
String get storeRepoDialogCurrent => 'Current repository:';
|
||||
|
||||
@override
|
||||
String get storeNewRepoUrlLabel => 'New Repository URL';
|
||||
|
||||
@override
|
||||
String get storeLoadError => 'Failed to load store';
|
||||
|
||||
@override
|
||||
String get storeEmptyNoExtensions => 'No extensions available';
|
||||
|
||||
@override
|
||||
String get storeEmptyNoResults => 'No extensions found';
|
||||
|
||||
@override
|
||||
String get extensionDefaultProvider => 'По умолчанию (Deezer/Spotify)';
|
||||
|
||||
@@ -2467,4 +2508,317 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
@override
|
||||
String get downloadUseAlbumArtistForFoldersTrackSubtitle =>
|
||||
'Папки исполнителя используют только трек исполнителя';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersTitle => 'Lyrics Providers';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersDescription =>
|
||||
'Enable, disable and reorder lyrics sources. Providers are tried top-to-bottom until lyrics are found.';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersInfoText =>
|
||||
'Extension lyrics providers always run before built-in providers. At least one provider must remain enabled.';
|
||||
|
||||
@override
|
||||
String lyricsProvidersEnabledSection(int count) {
|
||||
return 'Enabled ($count)';
|
||||
}
|
||||
|
||||
@override
|
||||
String lyricsProvidersDisabledSection(int count) {
|
||||
return 'Disabled ($count)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get lyricsProvidersAtLeastOne =>
|
||||
'At least one provider must remain enabled';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersSaved => 'Lyrics provider priority saved';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersDiscardContent =>
|
||||
'You have unsaved changes that will be lost.';
|
||||
|
||||
@override
|
||||
String get lyricsProviderSpotifyApiDesc =>
|
||||
'Spotify-sourced synced lyrics via community API';
|
||||
|
||||
@override
|
||||
String get lyricsProviderLrclibDesc => 'Open-source synced lyrics database';
|
||||
|
||||
@override
|
||||
String get lyricsProviderNeteaseDesc =>
|
||||
'NetEase Cloud Music (good for Asian songs)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderMusixmatchDesc =>
|
||||
'Largest lyrics database (multi-language)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderAppleMusicDesc =>
|
||||
'Word-by-word synced lyrics (via proxy)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderQqMusicDesc =>
|
||||
'QQ Music (good for Chinese songs, via proxy)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderExtensionDesc => 'Extension provider';
|
||||
|
||||
@override
|
||||
String get safMigrationTitle => 'Storage Update Required';
|
||||
|
||||
@override
|
||||
String get safMigrationMessage1 =>
|
||||
'SpotiFLAC now uses Android Storage Access Framework (SAF) for downloads. This fixes \"permission denied\" errors on Android 10+.';
|
||||
|
||||
@override
|
||||
String get safMigrationMessage2 =>
|
||||
'Please select your download folder again to switch to the new storage system.';
|
||||
|
||||
@override
|
||||
String get safMigrationSuccess => 'Download folder updated to SAF mode';
|
||||
|
||||
@override
|
||||
String get settingsDonate => 'Donate';
|
||||
|
||||
@override
|
||||
String get settingsDonateSubtitle => 'Support SpotiFLAC-Mobile development';
|
||||
|
||||
@override
|
||||
String get tooltipLoveAll => 'Love All';
|
||||
|
||||
@override
|
||||
String get tooltipAddToPlaylist => 'Add to Playlist';
|
||||
|
||||
@override
|
||||
String snackbarRemovedTracksFromLoved(int count) {
|
||||
return 'Removed $count tracks from Loved';
|
||||
}
|
||||
|
||||
@override
|
||||
String snackbarAddedTracksToLoved(int count) {
|
||||
return 'Added $count tracks to Loved';
|
||||
}
|
||||
|
||||
@override
|
||||
String get dialogDownloadAllTitle => 'Download All';
|
||||
|
||||
@override
|
||||
String dialogDownloadAllMessage(int count) {
|
||||
return 'Download $count tracks?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get dialogDownload => 'Download';
|
||||
|
||||
@override
|
||||
String get homeSkipAlreadyDownloaded => 'Skip already downloaded songs';
|
||||
|
||||
@override
|
||||
String get homeGoToAlbum => 'Go to Album';
|
||||
|
||||
@override
|
||||
String get homeAlbumInfoUnavailable => 'Album info not available';
|
||||
|
||||
@override
|
||||
String get snackbarLoadingCueSheet => 'Loading CUE sheet...';
|
||||
|
||||
@override
|
||||
String get snackbarMetadataSaved => 'Metadata saved successfully';
|
||||
|
||||
@override
|
||||
String get snackbarFailedToEmbedLyrics => 'Failed to embed lyrics';
|
||||
|
||||
@override
|
||||
String get snackbarFailedToWriteStorage => 'Failed to write back to storage';
|
||||
|
||||
@override
|
||||
String snackbarError(String error) {
|
||||
return 'Error: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get snackbarNoActionDefined => 'No action defined for this button';
|
||||
|
||||
@override
|
||||
String get noTracksFoundForAlbum => 'No tracks found for this album';
|
||||
|
||||
@override
|
||||
String get downloadLocationSubtitle =>
|
||||
'Choose storage mode for downloaded files.';
|
||||
|
||||
@override
|
||||
String get storageModeAppFolder => 'App folder (non-SAF)';
|
||||
|
||||
@override
|
||||
String get storageModeAppFolderSubtitle => 'Use default Music/SpotiFLAC path';
|
||||
|
||||
@override
|
||||
String get storageModeSaf => 'SAF folder';
|
||||
|
||||
@override
|
||||
String get storageModeSafSubtitle =>
|
||||
'Pick folder via Android Storage Access Framework';
|
||||
|
||||
@override
|
||||
String get downloadFilenameDescription =>
|
||||
'Customize how your files are named.';
|
||||
|
||||
@override
|
||||
String get downloadFilenameInsertTag => 'Tap to insert tag:';
|
||||
|
||||
@override
|
||||
String get downloadSeparateSinglesEnabled => 'Albums/ and Singles/ folders';
|
||||
|
||||
@override
|
||||
String get downloadSeparateSinglesDisabled => 'All files in same structure';
|
||||
|
||||
@override
|
||||
String get downloadArtistNameFilters => 'Artist Name Filters';
|
||||
|
||||
@override
|
||||
String get downloadSongLinkRegion => 'SongLink Region';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityMode => 'Network compatibility mode';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityModeEnabled =>
|
||||
'Enabled: try HTTP + accept invalid TLS certificates (unsafe)';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityModeDisabled =>
|
||||
'Off: strict HTTPS certificate validation (recommended)';
|
||||
|
||||
@override
|
||||
String get downloadSelectServiceToEnable =>
|
||||
'Select a built-in service to enable';
|
||||
|
||||
@override
|
||||
String get downloadLossy320 => 'Lossy 320kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyFormat => 'Lossy Format';
|
||||
|
||||
@override
|
||||
String get downloadSelectTidalQobuz =>
|
||||
'Select Tidal or Qobuz above to configure quality';
|
||||
|
||||
@override
|
||||
String get downloadEmbedLyricsDisabled =>
|
||||
'Disabled while Embed Metadata is turned off';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslation =>
|
||||
'Netease: Include Translation';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslationEnabled =>
|
||||
'Append translated lyrics when available';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslationDisabled =>
|
||||
'Use original lyrics only';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanization =>
|
||||
'Netease: Include Romanization';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanizationEnabled =>
|
||||
'Append romanized lyrics when available';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanizationDisabled => 'Disabled';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPerson => 'Apple/QQ Multi-Person Word-by-Word';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPersonEnabled =>
|
||||
'Enable v1/v2 speaker and [bg:] tags';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPersonDisabled =>
|
||||
'Simplified word-by-word formatting';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguage => 'Musixmatch Language';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageAuto => 'Auto (original)';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributing =>
|
||||
'Filter contributing artists in Album Artist';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributingEnabled =>
|
||||
'Album Artist metadata uses primary artist only';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributingDisabled =>
|
||||
'Keep full Album Artist metadata value';
|
||||
|
||||
@override
|
||||
String get downloadProvidersNoneEnabled => 'None enabled';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageCode => 'Language code';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageHint => 'auto / en / es / ja';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageDesc =>
|
||||
'Set preferred language code (example: en, es, ja). Leave empty for auto.';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchAuto => 'Auto';
|
||||
|
||||
@override
|
||||
String get downloadLossy320Format => 'Lossy 320kbps Format';
|
||||
|
||||
@override
|
||||
String get downloadLossy320FormatDesc =>
|
||||
'Choose the output format for Tidal 320kbps lossy downloads. The original AAC stream will be converted to your selected format.';
|
||||
|
||||
@override
|
||||
String get downloadLossyMp3 => 'MP3 320kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyMp3Subtitle => 'Best compatibility, ~10MB per track';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus256 => 'Opus 256kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus256Subtitle =>
|
||||
'Best quality Opus, ~8MB per track';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus128 => 'Opus 128kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus128Subtitle => 'Smallest size, ~4MB per track';
|
||||
|
||||
@override
|
||||
String get downloadNetworkAnySubtitle => 'WiFi + Mobile Data';
|
||||
|
||||
@override
|
||||
String get downloadNetworkWifiOnlySubtitle =>
|
||||
'Pause downloads on mobile data';
|
||||
|
||||
@override
|
||||
String get downloadSongLinkRegionDesc =>
|
||||
'Used as userCountry for SongLink API lookup.';
|
||||
|
||||
@override
|
||||
String get snackbarUnsupportedAudioFormat => 'Unsupported audio format';
|
||||
|
||||
@override
|
||||
String get cacheRefresh => 'Refresh';
|
||||
}
|
||||
|
||||
@@ -1206,6 +1206,47 @@ class AppLocalizationsTr extends AppLocalizations {
|
||||
@override
|
||||
String get storeClearFilters => 'Filtreleri temizle';
|
||||
|
||||
@override
|
||||
String get storeAddRepoTitle => 'Add Extension Repository';
|
||||
|
||||
@override
|
||||
String get storeAddRepoDescription =>
|
||||
'Enter a GitHub repository URL that contains a registry.json file to browse and install extensions.';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlLabel => 'Repository URL';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlHint => 'https://github.com/user/repo';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlHelper =>
|
||||
'e.g. https://github.com/user/extensions-repo';
|
||||
|
||||
@override
|
||||
String get storeAddRepoButton => 'Add Repository';
|
||||
|
||||
@override
|
||||
String get storeChangeRepoTooltip => 'Change repository';
|
||||
|
||||
@override
|
||||
String get storeRepoDialogTitle => 'Extension Repository';
|
||||
|
||||
@override
|
||||
String get storeRepoDialogCurrent => 'Current repository:';
|
||||
|
||||
@override
|
||||
String get storeNewRepoUrlLabel => 'New Repository URL';
|
||||
|
||||
@override
|
||||
String get storeLoadError => 'Failed to load store';
|
||||
|
||||
@override
|
||||
String get storeEmptyNoExtensions => 'No extensions available';
|
||||
|
||||
@override
|
||||
String get storeEmptyNoResults => 'No extensions found';
|
||||
|
||||
@override
|
||||
String get extensionDefaultProvider => 'Varsayılan (Deezer/Spotify)';
|
||||
|
||||
@@ -2420,4 +2461,317 @@ class AppLocalizationsTr extends AppLocalizations {
|
||||
@override
|
||||
String get downloadUseAlbumArtistForFoldersTrackSubtitle =>
|
||||
'Artist folders use Track Artist only';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersTitle => 'Lyrics Providers';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersDescription =>
|
||||
'Enable, disable and reorder lyrics sources. Providers are tried top-to-bottom until lyrics are found.';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersInfoText =>
|
||||
'Extension lyrics providers always run before built-in providers. At least one provider must remain enabled.';
|
||||
|
||||
@override
|
||||
String lyricsProvidersEnabledSection(int count) {
|
||||
return 'Enabled ($count)';
|
||||
}
|
||||
|
||||
@override
|
||||
String lyricsProvidersDisabledSection(int count) {
|
||||
return 'Disabled ($count)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get lyricsProvidersAtLeastOne =>
|
||||
'At least one provider must remain enabled';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersSaved => 'Lyrics provider priority saved';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersDiscardContent =>
|
||||
'You have unsaved changes that will be lost.';
|
||||
|
||||
@override
|
||||
String get lyricsProviderSpotifyApiDesc =>
|
||||
'Spotify-sourced synced lyrics via community API';
|
||||
|
||||
@override
|
||||
String get lyricsProviderLrclibDesc => 'Open-source synced lyrics database';
|
||||
|
||||
@override
|
||||
String get lyricsProviderNeteaseDesc =>
|
||||
'NetEase Cloud Music (good for Asian songs)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderMusixmatchDesc =>
|
||||
'Largest lyrics database (multi-language)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderAppleMusicDesc =>
|
||||
'Word-by-word synced lyrics (via proxy)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderQqMusicDesc =>
|
||||
'QQ Music (good for Chinese songs, via proxy)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderExtensionDesc => 'Extension provider';
|
||||
|
||||
@override
|
||||
String get safMigrationTitle => 'Storage Update Required';
|
||||
|
||||
@override
|
||||
String get safMigrationMessage1 =>
|
||||
'SpotiFLAC now uses Android Storage Access Framework (SAF) for downloads. This fixes \"permission denied\" errors on Android 10+.';
|
||||
|
||||
@override
|
||||
String get safMigrationMessage2 =>
|
||||
'Please select your download folder again to switch to the new storage system.';
|
||||
|
||||
@override
|
||||
String get safMigrationSuccess => 'Download folder updated to SAF mode';
|
||||
|
||||
@override
|
||||
String get settingsDonate => 'Donate';
|
||||
|
||||
@override
|
||||
String get settingsDonateSubtitle => 'Support SpotiFLAC-Mobile development';
|
||||
|
||||
@override
|
||||
String get tooltipLoveAll => 'Love All';
|
||||
|
||||
@override
|
||||
String get tooltipAddToPlaylist => 'Add to Playlist';
|
||||
|
||||
@override
|
||||
String snackbarRemovedTracksFromLoved(int count) {
|
||||
return 'Removed $count tracks from Loved';
|
||||
}
|
||||
|
||||
@override
|
||||
String snackbarAddedTracksToLoved(int count) {
|
||||
return 'Added $count tracks to Loved';
|
||||
}
|
||||
|
||||
@override
|
||||
String get dialogDownloadAllTitle => 'Download All';
|
||||
|
||||
@override
|
||||
String dialogDownloadAllMessage(int count) {
|
||||
return 'Download $count tracks?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get dialogDownload => 'Download';
|
||||
|
||||
@override
|
||||
String get homeSkipAlreadyDownloaded => 'Skip already downloaded songs';
|
||||
|
||||
@override
|
||||
String get homeGoToAlbum => 'Go to Album';
|
||||
|
||||
@override
|
||||
String get homeAlbumInfoUnavailable => 'Album info not available';
|
||||
|
||||
@override
|
||||
String get snackbarLoadingCueSheet => 'Loading CUE sheet...';
|
||||
|
||||
@override
|
||||
String get snackbarMetadataSaved => 'Metadata saved successfully';
|
||||
|
||||
@override
|
||||
String get snackbarFailedToEmbedLyrics => 'Failed to embed lyrics';
|
||||
|
||||
@override
|
||||
String get snackbarFailedToWriteStorage => 'Failed to write back to storage';
|
||||
|
||||
@override
|
||||
String snackbarError(String error) {
|
||||
return 'Error: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get snackbarNoActionDefined => 'No action defined for this button';
|
||||
|
||||
@override
|
||||
String get noTracksFoundForAlbum => 'No tracks found for this album';
|
||||
|
||||
@override
|
||||
String get downloadLocationSubtitle =>
|
||||
'Choose storage mode for downloaded files.';
|
||||
|
||||
@override
|
||||
String get storageModeAppFolder => 'App folder (non-SAF)';
|
||||
|
||||
@override
|
||||
String get storageModeAppFolderSubtitle => 'Use default Music/SpotiFLAC path';
|
||||
|
||||
@override
|
||||
String get storageModeSaf => 'SAF folder';
|
||||
|
||||
@override
|
||||
String get storageModeSafSubtitle =>
|
||||
'Pick folder via Android Storage Access Framework';
|
||||
|
||||
@override
|
||||
String get downloadFilenameDescription =>
|
||||
'Customize how your files are named.';
|
||||
|
||||
@override
|
||||
String get downloadFilenameInsertTag => 'Tap to insert tag:';
|
||||
|
||||
@override
|
||||
String get downloadSeparateSinglesEnabled => 'Albums/ and Singles/ folders';
|
||||
|
||||
@override
|
||||
String get downloadSeparateSinglesDisabled => 'All files in same structure';
|
||||
|
||||
@override
|
||||
String get downloadArtistNameFilters => 'Artist Name Filters';
|
||||
|
||||
@override
|
||||
String get downloadSongLinkRegion => 'SongLink Region';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityMode => 'Network compatibility mode';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityModeEnabled =>
|
||||
'Enabled: try HTTP + accept invalid TLS certificates (unsafe)';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityModeDisabled =>
|
||||
'Off: strict HTTPS certificate validation (recommended)';
|
||||
|
||||
@override
|
||||
String get downloadSelectServiceToEnable =>
|
||||
'Select a built-in service to enable';
|
||||
|
||||
@override
|
||||
String get downloadLossy320 => 'Lossy 320kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyFormat => 'Lossy Format';
|
||||
|
||||
@override
|
||||
String get downloadSelectTidalQobuz =>
|
||||
'Select Tidal or Qobuz above to configure quality';
|
||||
|
||||
@override
|
||||
String get downloadEmbedLyricsDisabled =>
|
||||
'Disabled while Embed Metadata is turned off';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslation =>
|
||||
'Netease: Include Translation';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslationEnabled =>
|
||||
'Append translated lyrics when available';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslationDisabled =>
|
||||
'Use original lyrics only';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanization =>
|
||||
'Netease: Include Romanization';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanizationEnabled =>
|
||||
'Append romanized lyrics when available';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanizationDisabled => 'Disabled';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPerson => 'Apple/QQ Multi-Person Word-by-Word';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPersonEnabled =>
|
||||
'Enable v1/v2 speaker and [bg:] tags';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPersonDisabled =>
|
||||
'Simplified word-by-word formatting';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguage => 'Musixmatch Language';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageAuto => 'Auto (original)';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributing =>
|
||||
'Filter contributing artists in Album Artist';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributingEnabled =>
|
||||
'Album Artist metadata uses primary artist only';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributingDisabled =>
|
||||
'Keep full Album Artist metadata value';
|
||||
|
||||
@override
|
||||
String get downloadProvidersNoneEnabled => 'None enabled';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageCode => 'Language code';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageHint => 'auto / en / es / ja';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageDesc =>
|
||||
'Set preferred language code (example: en, es, ja). Leave empty for auto.';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchAuto => 'Auto';
|
||||
|
||||
@override
|
||||
String get downloadLossy320Format => 'Lossy 320kbps Format';
|
||||
|
||||
@override
|
||||
String get downloadLossy320FormatDesc =>
|
||||
'Choose the output format for Tidal 320kbps lossy downloads. The original AAC stream will be converted to your selected format.';
|
||||
|
||||
@override
|
||||
String get downloadLossyMp3 => 'MP3 320kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyMp3Subtitle => 'Best compatibility, ~10MB per track';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus256 => 'Opus 256kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus256Subtitle =>
|
||||
'Best quality Opus, ~8MB per track';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus128 => 'Opus 128kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus128Subtitle => 'Smallest size, ~4MB per track';
|
||||
|
||||
@override
|
||||
String get downloadNetworkAnySubtitle => 'WiFi + Mobile Data';
|
||||
|
||||
@override
|
||||
String get downloadNetworkWifiOnlySubtitle =>
|
||||
'Pause downloads on mobile data';
|
||||
|
||||
@override
|
||||
String get downloadSongLinkRegionDesc =>
|
||||
'Used as userCountry for SongLink API lookup.';
|
||||
|
||||
@override
|
||||
String get snackbarUnsupportedAudioFormat => 'Unsupported audio format';
|
||||
|
||||
@override
|
||||
String get cacheRefresh => 'Refresh';
|
||||
}
|
||||
|
||||
@@ -1195,6 +1195,47 @@ class AppLocalizationsZh extends AppLocalizations {
|
||||
@override
|
||||
String get storeClearFilters => 'Clear filters';
|
||||
|
||||
@override
|
||||
String get storeAddRepoTitle => 'Add Extension Repository';
|
||||
|
||||
@override
|
||||
String get storeAddRepoDescription =>
|
||||
'Enter a GitHub repository URL that contains a registry.json file to browse and install extensions.';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlLabel => 'Repository URL';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlHint => 'https://github.com/user/repo';
|
||||
|
||||
@override
|
||||
String get storeRepoUrlHelper =>
|
||||
'e.g. https://github.com/user/extensions-repo';
|
||||
|
||||
@override
|
||||
String get storeAddRepoButton => 'Add Repository';
|
||||
|
||||
@override
|
||||
String get storeChangeRepoTooltip => 'Change repository';
|
||||
|
||||
@override
|
||||
String get storeRepoDialogTitle => 'Extension Repository';
|
||||
|
||||
@override
|
||||
String get storeRepoDialogCurrent => 'Current repository:';
|
||||
|
||||
@override
|
||||
String get storeNewRepoUrlLabel => 'New Repository URL';
|
||||
|
||||
@override
|
||||
String get storeLoadError => 'Failed to load store';
|
||||
|
||||
@override
|
||||
String get storeEmptyNoExtensions => 'No extensions available';
|
||||
|
||||
@override
|
||||
String get storeEmptyNoResults => 'No extensions found';
|
||||
|
||||
@override
|
||||
String get extensionDefaultProvider => 'Default (Deezer/Spotify)';
|
||||
|
||||
@@ -2408,6 +2449,319 @@ class AppLocalizationsZh extends AppLocalizations {
|
||||
@override
|
||||
String get downloadUseAlbumArtistForFoldersTrackSubtitle =>
|
||||
'Artist folders use Track Artist only';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersTitle => 'Lyrics Providers';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersDescription =>
|
||||
'Enable, disable and reorder lyrics sources. Providers are tried top-to-bottom until lyrics are found.';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersInfoText =>
|
||||
'Extension lyrics providers always run before built-in providers. At least one provider must remain enabled.';
|
||||
|
||||
@override
|
||||
String lyricsProvidersEnabledSection(int count) {
|
||||
return 'Enabled ($count)';
|
||||
}
|
||||
|
||||
@override
|
||||
String lyricsProvidersDisabledSection(int count) {
|
||||
return 'Disabled ($count)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get lyricsProvidersAtLeastOne =>
|
||||
'At least one provider must remain enabled';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersSaved => 'Lyrics provider priority saved';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersDiscardContent =>
|
||||
'You have unsaved changes that will be lost.';
|
||||
|
||||
@override
|
||||
String get lyricsProviderSpotifyApiDesc =>
|
||||
'Spotify-sourced synced lyrics via community API';
|
||||
|
||||
@override
|
||||
String get lyricsProviderLrclibDesc => 'Open-source synced lyrics database';
|
||||
|
||||
@override
|
||||
String get lyricsProviderNeteaseDesc =>
|
||||
'NetEase Cloud Music (good for Asian songs)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderMusixmatchDesc =>
|
||||
'Largest lyrics database (multi-language)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderAppleMusicDesc =>
|
||||
'Word-by-word synced lyrics (via proxy)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderQqMusicDesc =>
|
||||
'QQ Music (good for Chinese songs, via proxy)';
|
||||
|
||||
@override
|
||||
String get lyricsProviderExtensionDesc => 'Extension provider';
|
||||
|
||||
@override
|
||||
String get safMigrationTitle => 'Storage Update Required';
|
||||
|
||||
@override
|
||||
String get safMigrationMessage1 =>
|
||||
'SpotiFLAC now uses Android Storage Access Framework (SAF) for downloads. This fixes \"permission denied\" errors on Android 10+.';
|
||||
|
||||
@override
|
||||
String get safMigrationMessage2 =>
|
||||
'Please select your download folder again to switch to the new storage system.';
|
||||
|
||||
@override
|
||||
String get safMigrationSuccess => 'Download folder updated to SAF mode';
|
||||
|
||||
@override
|
||||
String get settingsDonate => 'Donate';
|
||||
|
||||
@override
|
||||
String get settingsDonateSubtitle => 'Support SpotiFLAC-Mobile development';
|
||||
|
||||
@override
|
||||
String get tooltipLoveAll => 'Love All';
|
||||
|
||||
@override
|
||||
String get tooltipAddToPlaylist => 'Add to Playlist';
|
||||
|
||||
@override
|
||||
String snackbarRemovedTracksFromLoved(int count) {
|
||||
return 'Removed $count tracks from Loved';
|
||||
}
|
||||
|
||||
@override
|
||||
String snackbarAddedTracksToLoved(int count) {
|
||||
return 'Added $count tracks to Loved';
|
||||
}
|
||||
|
||||
@override
|
||||
String get dialogDownloadAllTitle => 'Download All';
|
||||
|
||||
@override
|
||||
String dialogDownloadAllMessage(int count) {
|
||||
return 'Download $count tracks?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get dialogDownload => 'Download';
|
||||
|
||||
@override
|
||||
String get homeSkipAlreadyDownloaded => 'Skip already downloaded songs';
|
||||
|
||||
@override
|
||||
String get homeGoToAlbum => 'Go to Album';
|
||||
|
||||
@override
|
||||
String get homeAlbumInfoUnavailable => 'Album info not available';
|
||||
|
||||
@override
|
||||
String get snackbarLoadingCueSheet => 'Loading CUE sheet...';
|
||||
|
||||
@override
|
||||
String get snackbarMetadataSaved => 'Metadata saved successfully';
|
||||
|
||||
@override
|
||||
String get snackbarFailedToEmbedLyrics => 'Failed to embed lyrics';
|
||||
|
||||
@override
|
||||
String get snackbarFailedToWriteStorage => 'Failed to write back to storage';
|
||||
|
||||
@override
|
||||
String snackbarError(String error) {
|
||||
return 'Error: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get snackbarNoActionDefined => 'No action defined for this button';
|
||||
|
||||
@override
|
||||
String get noTracksFoundForAlbum => 'No tracks found for this album';
|
||||
|
||||
@override
|
||||
String get downloadLocationSubtitle =>
|
||||
'Choose storage mode for downloaded files.';
|
||||
|
||||
@override
|
||||
String get storageModeAppFolder => 'App folder (non-SAF)';
|
||||
|
||||
@override
|
||||
String get storageModeAppFolderSubtitle => 'Use default Music/SpotiFLAC path';
|
||||
|
||||
@override
|
||||
String get storageModeSaf => 'SAF folder';
|
||||
|
||||
@override
|
||||
String get storageModeSafSubtitle =>
|
||||
'Pick folder via Android Storage Access Framework';
|
||||
|
||||
@override
|
||||
String get downloadFilenameDescription =>
|
||||
'Customize how your files are named.';
|
||||
|
||||
@override
|
||||
String get downloadFilenameInsertTag => 'Tap to insert tag:';
|
||||
|
||||
@override
|
||||
String get downloadSeparateSinglesEnabled => 'Albums/ and Singles/ folders';
|
||||
|
||||
@override
|
||||
String get downloadSeparateSinglesDisabled => 'All files in same structure';
|
||||
|
||||
@override
|
||||
String get downloadArtistNameFilters => 'Artist Name Filters';
|
||||
|
||||
@override
|
||||
String get downloadSongLinkRegion => 'SongLink Region';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityMode => 'Network compatibility mode';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityModeEnabled =>
|
||||
'Enabled: try HTTP + accept invalid TLS certificates (unsafe)';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityModeDisabled =>
|
||||
'Off: strict HTTPS certificate validation (recommended)';
|
||||
|
||||
@override
|
||||
String get downloadSelectServiceToEnable =>
|
||||
'Select a built-in service to enable';
|
||||
|
||||
@override
|
||||
String get downloadLossy320 => 'Lossy 320kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyFormat => 'Lossy Format';
|
||||
|
||||
@override
|
||||
String get downloadSelectTidalQobuz =>
|
||||
'Select Tidal or Qobuz above to configure quality';
|
||||
|
||||
@override
|
||||
String get downloadEmbedLyricsDisabled =>
|
||||
'Disabled while Embed Metadata is turned off';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslation =>
|
||||
'Netease: Include Translation';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslationEnabled =>
|
||||
'Append translated lyrics when available';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslationDisabled =>
|
||||
'Use original lyrics only';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanization =>
|
||||
'Netease: Include Romanization';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanizationEnabled =>
|
||||
'Append romanized lyrics when available';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanizationDisabled => 'Disabled';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPerson => 'Apple/QQ Multi-Person Word-by-Word';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPersonEnabled =>
|
||||
'Enable v1/v2 speaker and [bg:] tags';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPersonDisabled =>
|
||||
'Simplified word-by-word formatting';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguage => 'Musixmatch Language';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageAuto => 'Auto (original)';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributing =>
|
||||
'Filter contributing artists in Album Artist';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributingEnabled =>
|
||||
'Album Artist metadata uses primary artist only';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributingDisabled =>
|
||||
'Keep full Album Artist metadata value';
|
||||
|
||||
@override
|
||||
String get downloadProvidersNoneEnabled => 'None enabled';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageCode => 'Language code';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageHint => 'auto / en / es / ja';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageDesc =>
|
||||
'Set preferred language code (example: en, es, ja). Leave empty for auto.';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchAuto => 'Auto';
|
||||
|
||||
@override
|
||||
String get downloadLossy320Format => 'Lossy 320kbps Format';
|
||||
|
||||
@override
|
||||
String get downloadLossy320FormatDesc =>
|
||||
'Choose the output format for Tidal 320kbps lossy downloads. The original AAC stream will be converted to your selected format.';
|
||||
|
||||
@override
|
||||
String get downloadLossyMp3 => 'MP3 320kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyMp3Subtitle => 'Best compatibility, ~10MB per track';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus256 => 'Opus 256kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus256Subtitle =>
|
||||
'Best quality Opus, ~8MB per track';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus128 => 'Opus 128kbps';
|
||||
|
||||
@override
|
||||
String get downloadLossyOpus128Subtitle => 'Smallest size, ~4MB per track';
|
||||
|
||||
@override
|
||||
String get downloadNetworkAnySubtitle => 'WiFi + Mobile Data';
|
||||
|
||||
@override
|
||||
String get downloadNetworkWifiOnlySubtitle =>
|
||||
'Pause downloads on mobile data';
|
||||
|
||||
@override
|
||||
String get downloadSongLinkRegionDesc =>
|
||||
'Used as userCountry for SongLink API lookup.';
|
||||
|
||||
@override
|
||||
String get snackbarUnsupportedAudioFormat => 'Unsupported audio format';
|
||||
|
||||
@override
|
||||
String get cacheRefresh => 'Refresh';
|
||||
}
|
||||
|
||||
/// The translations for Chinese, as used in China (`zh_CN`).
|
||||
|
||||
@@ -1570,6 +1570,58 @@
|
||||
"@storeClearFilters": {
|
||||
"description": "Button to clear all filters"
|
||||
},
|
||||
"storeAddRepoTitle": "Add Extension Repository",
|
||||
"@storeAddRepoTitle": {
|
||||
"description": "Store setup screen - heading when no repo is configured"
|
||||
},
|
||||
"storeAddRepoDescription": "Enter a GitHub repository URL that contains a registry.json file to browse and install extensions.",
|
||||
"@storeAddRepoDescription": {
|
||||
"description": "Store setup screen - explanatory text"
|
||||
},
|
||||
"storeRepoUrlLabel": "Repository URL",
|
||||
"@storeRepoUrlLabel": {
|
||||
"description": "Label for the repository URL input field"
|
||||
},
|
||||
"storeRepoUrlHint": "https://github.com/user/repo",
|
||||
"@storeRepoUrlHint": {
|
||||
"description": "Hint/placeholder for the repository URL input field"
|
||||
},
|
||||
"storeRepoUrlHelper": "e.g. https://github.com/user/extensions-repo",
|
||||
"@storeRepoUrlHelper": {
|
||||
"description": "Helper text below the repository URL input field"
|
||||
},
|
||||
"storeAddRepoButton": "Add Repository",
|
||||
"@storeAddRepoButton": {
|
||||
"description": "Button to submit a new repository URL"
|
||||
},
|
||||
"storeChangeRepoTooltip": "Change repository",
|
||||
"@storeChangeRepoTooltip": {
|
||||
"description": "Tooltip for the change-repository icon button in the app bar"
|
||||
},
|
||||
"storeRepoDialogTitle": "Extension Repository",
|
||||
"@storeRepoDialogTitle": {
|
||||
"description": "Title of the change/remove repository dialog"
|
||||
},
|
||||
"storeRepoDialogCurrent": "Current repository:",
|
||||
"@storeRepoDialogCurrent": {
|
||||
"description": "Label shown above the current repository URL in the dialog"
|
||||
},
|
||||
"storeNewRepoUrlLabel": "New Repository URL",
|
||||
"@storeNewRepoUrlLabel": {
|
||||
"description": "Label for the new repository URL field inside the dialog"
|
||||
},
|
||||
"storeLoadError": "Failed to load store",
|
||||
"@storeLoadError": {
|
||||
"description": "Error heading when the store cannot be loaded"
|
||||
},
|
||||
"storeEmptyNoExtensions": "No extensions available",
|
||||
"@storeEmptyNoExtensions": {
|
||||
"description": "Message when store has no extensions"
|
||||
},
|
||||
"storeEmptyNoResults": "No extensions found",
|
||||
"@storeEmptyNoResults": {
|
||||
"description": "Message when search/filter returns no results"
|
||||
},
|
||||
"extensionDefaultProvider": "Default (Deezer/Spotify)",
|
||||
"@extensionDefaultProvider": {
|
||||
"description": "Default search provider option"
|
||||
@@ -3205,5 +3257,405 @@
|
||||
"downloadUseAlbumArtistForFoldersTrackSubtitle": "Artist folders use Track Artist only",
|
||||
"@downloadUseAlbumArtistForFoldersTrackSubtitle": {
|
||||
"description": "Subtitle when Track Artist is used for folder naming"
|
||||
},
|
||||
|
||||
"lyricsProvidersTitle": "Lyrics Providers",
|
||||
"@lyricsProvidersTitle": {
|
||||
"description": "Title for the lyrics provider priority page"
|
||||
},
|
||||
"lyricsProvidersDescription": "Enable, disable and reorder lyrics sources. Providers are tried top-to-bottom until lyrics are found.",
|
||||
"@lyricsProvidersDescription": {
|
||||
"description": "Description on the lyrics provider priority page"
|
||||
},
|
||||
"lyricsProvidersInfoText": "Extension lyrics providers always run before built-in providers. At least one provider must remain enabled.",
|
||||
"@lyricsProvidersInfoText": {
|
||||
"description": "Info tip on lyrics provider priority page"
|
||||
},
|
||||
"lyricsProvidersEnabledSection": "Enabled ({count})",
|
||||
"@lyricsProvidersEnabledSection": {
|
||||
"description": "Section header for enabled providers",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"lyricsProvidersDisabledSection": "Disabled ({count})",
|
||||
"@lyricsProvidersDisabledSection": {
|
||||
"description": "Section header for disabled providers",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"lyricsProvidersAtLeastOne": "At least one provider must remain enabled",
|
||||
"@lyricsProvidersAtLeastOne": {
|
||||
"description": "Snackbar when user tries to disable the last enabled provider"
|
||||
},
|
||||
"lyricsProvidersSaved": "Lyrics provider priority saved",
|
||||
"@lyricsProvidersSaved": {
|
||||
"description": "Snackbar after saving lyrics provider priority"
|
||||
},
|
||||
"lyricsProvidersDiscardContent": "You have unsaved changes that will be lost.",
|
||||
"@lyricsProvidersDiscardContent": {
|
||||
"description": "Body text of the discard-changes dialog on lyrics provider page"
|
||||
},
|
||||
"lyricsProviderSpotifyApiDesc": "Spotify-sourced synced lyrics via community API",
|
||||
"@lyricsProviderSpotifyApiDesc": {
|
||||
"description": "Description for Spotify Lyrics API provider"
|
||||
},
|
||||
"lyricsProviderLrclibDesc": "Open-source synced lyrics database",
|
||||
"@lyricsProviderLrclibDesc": {
|
||||
"description": "Description for LRCLIB provider"
|
||||
},
|
||||
"lyricsProviderNeteaseDesc": "NetEase Cloud Music (good for Asian songs)",
|
||||
"@lyricsProviderNeteaseDesc": {
|
||||
"description": "Description for Netease provider"
|
||||
},
|
||||
"lyricsProviderMusixmatchDesc": "Largest lyrics database (multi-language)",
|
||||
"@lyricsProviderMusixmatchDesc": {
|
||||
"description": "Description for Musixmatch provider"
|
||||
},
|
||||
"lyricsProviderAppleMusicDesc": "Word-by-word synced lyrics (via proxy)",
|
||||
"@lyricsProviderAppleMusicDesc": {
|
||||
"description": "Description for Apple Music provider"
|
||||
},
|
||||
"lyricsProviderQqMusicDesc": "QQ Music (good for Chinese songs, via proxy)",
|
||||
"@lyricsProviderQqMusicDesc": {
|
||||
"description": "Description for QQ Music provider"
|
||||
},
|
||||
"lyricsProviderExtensionDesc": "Extension provider",
|
||||
"@lyricsProviderExtensionDesc": {
|
||||
"description": "Generic description for extension-based lyrics providers"
|
||||
},
|
||||
|
||||
"safMigrationTitle": "Storage Update Required",
|
||||
"@safMigrationTitle": {
|
||||
"description": "Title of SAF migration dialog"
|
||||
},
|
||||
"safMigrationMessage1": "SpotiFLAC now uses Android Storage Access Framework (SAF) for downloads. This fixes \"permission denied\" errors on Android 10+.",
|
||||
"@safMigrationMessage1": {
|
||||
"description": "First paragraph of SAF migration dialog"
|
||||
},
|
||||
"safMigrationMessage2": "Please select your download folder again to switch to the new storage system.",
|
||||
"@safMigrationMessage2": {
|
||||
"description": "Second paragraph of SAF migration dialog"
|
||||
},
|
||||
"safMigrationSuccess": "Download folder updated to SAF mode",
|
||||
"@safMigrationSuccess": {
|
||||
"description": "Snackbar after successfully migrating to SAF"
|
||||
},
|
||||
|
||||
"settingsDonate": "Donate",
|
||||
"@settingsDonate": {
|
||||
"description": "Settings menu item - donate"
|
||||
},
|
||||
"settingsDonateSubtitle": "Support SpotiFLAC-Mobile development",
|
||||
"@settingsDonateSubtitle": {
|
||||
"description": "Subtitle for donate menu item"
|
||||
},
|
||||
|
||||
"tooltipLoveAll": "Love All",
|
||||
"@tooltipLoveAll": {
|
||||
"description": "Tooltip for the Love All button on album/playlist screens"
|
||||
},
|
||||
"tooltipAddToPlaylist": "Add to Playlist",
|
||||
"@tooltipAddToPlaylist": {
|
||||
"description": "Tooltip for the Add to Playlist button"
|
||||
},
|
||||
"snackbarRemovedTracksFromLoved": "Removed {count} tracks from Loved",
|
||||
"@snackbarRemovedTracksFromLoved": {
|
||||
"description": "Snackbar after removing multiple tracks from Loved folder",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"snackbarAddedTracksToLoved": "Added {count} tracks to Loved",
|
||||
"@snackbarAddedTracksToLoved": {
|
||||
"description": "Snackbar after adding multiple tracks to Loved folder",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"dialogDownloadAllTitle": "Download All",
|
||||
"@dialogDownloadAllTitle": {
|
||||
"description": "Title of the Download All confirmation dialog"
|
||||
},
|
||||
"dialogDownloadAllMessage": "Download {count} tracks?",
|
||||
"@dialogDownloadAllMessage": {
|
||||
"description": "Body of the Download All confirmation dialog",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dialogDownload": "Download",
|
||||
"@dialogDownload": {
|
||||
"description": "Confirm button in Download All dialog"
|
||||
},
|
||||
|
||||
"homeSkipAlreadyDownloaded": "Skip already downloaded songs",
|
||||
"@homeSkipAlreadyDownloaded": {
|
||||
"description": "Checkbox label in import dialog to skip already-downloaded songs"
|
||||
},
|
||||
"homeGoToAlbum": "Go to Album",
|
||||
"@homeGoToAlbum": {
|
||||
"description": "Context menu item to navigate to the album page"
|
||||
},
|
||||
"homeAlbumInfoUnavailable": "Album info not available",
|
||||
"@homeAlbumInfoUnavailable": {
|
||||
"description": "Snackbar when album info cannot be loaded"
|
||||
},
|
||||
|
||||
"snackbarLoadingCueSheet": "Loading CUE sheet...",
|
||||
"@snackbarLoadingCueSheet": {
|
||||
"description": "Snackbar while loading a CUE sheet file"
|
||||
},
|
||||
"snackbarMetadataSaved": "Metadata saved successfully",
|
||||
"@snackbarMetadataSaved": {
|
||||
"description": "Snackbar after successfully saving track metadata"
|
||||
},
|
||||
"snackbarFailedToEmbedLyrics": "Failed to embed lyrics",
|
||||
"@snackbarFailedToEmbedLyrics": {
|
||||
"description": "Snackbar when lyrics embedding fails"
|
||||
},
|
||||
"snackbarFailedToWriteStorage": "Failed to write back to storage",
|
||||
"@snackbarFailedToWriteStorage": {
|
||||
"description": "Snackbar when writing metadata back to file fails"
|
||||
},
|
||||
"snackbarError": "Error: {error}",
|
||||
"@snackbarError": {
|
||||
"description": "Generic error snackbar with error detail",
|
||||
"placeholders": {
|
||||
"error": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"snackbarNoActionDefined": "No action defined for this button",
|
||||
"@snackbarNoActionDefined": {
|
||||
"description": "Snackbar when an extension button has no action configured"
|
||||
},
|
||||
|
||||
"noTracksFoundForAlbum": "No tracks found for this album",
|
||||
"@noTracksFoundForAlbum": {
|
||||
"description": "Empty state message when an album has no tracks"
|
||||
},
|
||||
|
||||
"downloadLocationSubtitle": "Choose storage mode for downloaded files.",
|
||||
"@downloadLocationSubtitle": {
|
||||
"description": "Subtitle text in Android download location bottom sheet"
|
||||
},
|
||||
"storageModeAppFolder": "App folder (non-SAF)",
|
||||
"@storageModeAppFolder": {
|
||||
"description": "Storage mode option - use legacy app folder"
|
||||
},
|
||||
"storageModeAppFolderSubtitle": "Use default Music/SpotiFLAC path",
|
||||
"@storageModeAppFolderSubtitle": {
|
||||
"description": "Subtitle for app folder storage mode"
|
||||
},
|
||||
"storageModeSaf": "SAF folder",
|
||||
"@storageModeSaf": {
|
||||
"description": "Storage mode option - use Android SAF picker"
|
||||
},
|
||||
"storageModeSafSubtitle": "Pick folder via Android Storage Access Framework",
|
||||
"@storageModeSafSubtitle": {
|
||||
"description": "Subtitle for SAF storage mode"
|
||||
},
|
||||
"downloadFilenameDescription": "Customize how your files are named.",
|
||||
"@downloadFilenameDescription": {
|
||||
"description": "Description text in filename format bottom sheet"
|
||||
},
|
||||
"downloadFilenameInsertTag": "Tap to insert tag:",
|
||||
"@downloadFilenameInsertTag": {
|
||||
"description": "Label above filename tag chips"
|
||||
},
|
||||
"downloadSeparateSinglesEnabled": "Albums/ and Singles/ folders",
|
||||
"@downloadSeparateSinglesEnabled": {
|
||||
"description": "Subtitle when separate singles folder is enabled"
|
||||
},
|
||||
"downloadSeparateSinglesDisabled": "All files in same structure",
|
||||
"@downloadSeparateSinglesDisabled": {
|
||||
"description": "Subtitle when separate singles folder is disabled"
|
||||
},
|
||||
"downloadArtistNameFilters": "Artist Name Filters",
|
||||
"@downloadArtistNameFilters": {
|
||||
"description": "Setting title for artist folder filter options"
|
||||
},
|
||||
"downloadSongLinkRegion": "SongLink Region",
|
||||
"@downloadSongLinkRegion": {
|
||||
"description": "Setting title for SongLink country region"
|
||||
},
|
||||
"downloadNetworkCompatibilityMode": "Network compatibility mode",
|
||||
"@downloadNetworkCompatibilityMode": {
|
||||
"description": "Setting title for network compatibility toggle"
|
||||
},
|
||||
"downloadNetworkCompatibilityModeEnabled": "Enabled: try HTTP + accept invalid TLS certificates (unsafe)",
|
||||
"@downloadNetworkCompatibilityModeEnabled": {
|
||||
"description": "Subtitle when network compatibility mode is enabled"
|
||||
},
|
||||
"downloadNetworkCompatibilityModeDisabled": "Off: strict HTTPS certificate validation (recommended)",
|
||||
"@downloadNetworkCompatibilityModeDisabled": {
|
||||
"description": "Subtitle when network compatibility mode is disabled"
|
||||
},
|
||||
"downloadSelectServiceToEnable": "Select a built-in service to enable",
|
||||
"@downloadSelectServiceToEnable": {
|
||||
"description": "Hint shown instead of Ask-quality subtitle when no built-in service selected"
|
||||
},
|
||||
"downloadLossy320": "Lossy 320kbps",
|
||||
"@downloadLossy320": {
|
||||
"description": "Quality option label for Tidal lossy 320kbps"
|
||||
},
|
||||
"downloadLossyFormat": "Lossy Format",
|
||||
"@downloadLossyFormat": {
|
||||
"description": "Setting title to pick output format for Tidal lossy downloads"
|
||||
},
|
||||
"downloadSelectTidalQobuz": "Select Tidal or Qobuz above to configure quality",
|
||||
"@downloadSelectTidalQobuz": {
|
||||
"description": "Info hint when non-Tidal/Qobuz service is selected"
|
||||
},
|
||||
"downloadEmbedLyricsDisabled": "Disabled while Embed Metadata is turned off",
|
||||
"@downloadEmbedLyricsDisabled": {
|
||||
"description": "Subtitle for Embed Lyrics when Embed Metadata is disabled"
|
||||
},
|
||||
"downloadNeteaseIncludeTranslation": "Netease: Include Translation",
|
||||
"@downloadNeteaseIncludeTranslation": {
|
||||
"description": "Toggle title for including Netease translated lyrics"
|
||||
},
|
||||
"downloadNeteaseIncludeTranslationEnabled": "Append translated lyrics when available",
|
||||
"@downloadNeteaseIncludeTranslationEnabled": {
|
||||
"description": "Subtitle when Netease translation is enabled"
|
||||
},
|
||||
"downloadNeteaseIncludeTranslationDisabled": "Use original lyrics only",
|
||||
"@downloadNeteaseIncludeTranslationDisabled": {
|
||||
"description": "Subtitle when Netease translation is disabled"
|
||||
},
|
||||
"downloadNeteaseIncludeRomanization": "Netease: Include Romanization",
|
||||
"@downloadNeteaseIncludeRomanization": {
|
||||
"description": "Toggle title for including Netease romanized lyrics"
|
||||
},
|
||||
"downloadNeteaseIncludeRomanizationEnabled": "Append romanized lyrics when available",
|
||||
"@downloadNeteaseIncludeRomanizationEnabled": {
|
||||
"description": "Subtitle when Netease romanization is enabled"
|
||||
},
|
||||
"downloadNeteaseIncludeRomanizationDisabled": "Disabled",
|
||||
"@downloadNeteaseIncludeRomanizationDisabled": {
|
||||
"description": "Subtitle when Netease romanization is disabled"
|
||||
},
|
||||
"downloadAppleQqMultiPerson": "Apple/QQ Multi-Person Word-by-Word",
|
||||
"@downloadAppleQqMultiPerson": {
|
||||
"description": "Toggle title for Apple/QQ multi-person word-by-word lyrics"
|
||||
},
|
||||
"downloadAppleQqMultiPersonEnabled": "Enable v1/v2 speaker and [bg:] tags",
|
||||
"@downloadAppleQqMultiPersonEnabled": {
|
||||
"description": "Subtitle when multi-person word-by-word is enabled"
|
||||
},
|
||||
"downloadAppleQqMultiPersonDisabled": "Simplified word-by-word formatting",
|
||||
"@downloadAppleQqMultiPersonDisabled": {
|
||||
"description": "Subtitle when multi-person word-by-word is disabled"
|
||||
},
|
||||
"downloadMusixmatchLanguage": "Musixmatch Language",
|
||||
"@downloadMusixmatchLanguage": {
|
||||
"description": "Setting title for Musixmatch language preference"
|
||||
},
|
||||
"downloadMusixmatchLanguageAuto": "Auto (original)",
|
||||
"@downloadMusixmatchLanguageAuto": {
|
||||
"description": "Option label when Musixmatch uses original language"
|
||||
},
|
||||
"downloadFilterContributing": "Filter contributing artists in Album Artist",
|
||||
"@downloadFilterContributing": {
|
||||
"description": "Toggle title for filtering contributing artists in Album Artist metadata"
|
||||
},
|
||||
"downloadFilterContributingEnabled": "Album Artist metadata uses primary artist only",
|
||||
"@downloadFilterContributingEnabled": {
|
||||
"description": "Subtitle when contributing artist filter is enabled"
|
||||
},
|
||||
"downloadFilterContributingDisabled": "Keep full Album Artist metadata value",
|
||||
"@downloadFilterContributingDisabled": {
|
||||
"description": "Subtitle when contributing artist filter is disabled"
|
||||
},
|
||||
|
||||
"downloadProvidersNoneEnabled": "None enabled",
|
||||
"@downloadProvidersNoneEnabled": {
|
||||
"description": "Subtitle for lyrics providers setting when no providers are enabled"
|
||||
},
|
||||
"downloadMusixmatchLanguageCode": "Language code",
|
||||
"@downloadMusixmatchLanguageCode": {
|
||||
"description": "Label for the Musixmatch language code text field"
|
||||
},
|
||||
"downloadMusixmatchLanguageHint": "auto / en / es / ja",
|
||||
"@downloadMusixmatchLanguageHint": {
|
||||
"description": "Hint text for the Musixmatch language code field"
|
||||
},
|
||||
"downloadMusixmatchLanguageDesc": "Set preferred language code (example: en, es, ja). Leave empty for auto.",
|
||||
"@downloadMusixmatchLanguageDesc": {
|
||||
"description": "Description in the Musixmatch language picker"
|
||||
},
|
||||
"downloadMusixmatchAuto": "Auto",
|
||||
"@downloadMusixmatchAuto": {
|
||||
"description": "Button to reset Musixmatch language to automatic"
|
||||
},
|
||||
"downloadLossy320Format": "Lossy 320kbps Format",
|
||||
"@downloadLossy320Format": {
|
||||
"description": "Title of the Tidal lossy format picker bottom sheet"
|
||||
},
|
||||
"downloadLossy320FormatDesc": "Choose the output format for Tidal 320kbps lossy downloads. The original AAC stream will be converted to your selected format.",
|
||||
"@downloadLossy320FormatDesc": {
|
||||
"description": "Description in the Tidal lossy format picker"
|
||||
},
|
||||
"downloadLossyMp3": "MP3 320kbps",
|
||||
"@downloadLossyMp3": {
|
||||
"description": "Tidal lossy format option - MP3 320kbps"
|
||||
},
|
||||
"downloadLossyMp3Subtitle": "Best compatibility, ~10MB per track",
|
||||
"@downloadLossyMp3Subtitle": {
|
||||
"description": "Subtitle for MP3 320kbps option"
|
||||
},
|
||||
"downloadLossyOpus256": "Opus 256kbps",
|
||||
"@downloadLossyOpus256": {
|
||||
"description": "Tidal lossy format option - Opus 256kbps"
|
||||
},
|
||||
"downloadLossyOpus256Subtitle": "Best quality Opus, ~8MB per track",
|
||||
"@downloadLossyOpus256Subtitle": {
|
||||
"description": "Subtitle for Opus 256kbps option"
|
||||
},
|
||||
"downloadLossyOpus128": "Opus 128kbps",
|
||||
"@downloadLossyOpus128": {
|
||||
"description": "Tidal lossy format option - Opus 128kbps"
|
||||
},
|
||||
"downloadLossyOpus128Subtitle": "Smallest size, ~4MB per track",
|
||||
"@downloadLossyOpus128Subtitle": {
|
||||
"description": "Subtitle for Opus 128kbps option"
|
||||
},
|
||||
"downloadNetworkAnySubtitle": "WiFi + Mobile Data",
|
||||
"@downloadNetworkAnySubtitle": {
|
||||
"description": "Subtitle for 'Any' network mode option"
|
||||
},
|
||||
"downloadNetworkWifiOnlySubtitle": "Pause downloads on mobile data",
|
||||
"@downloadNetworkWifiOnlySubtitle": {
|
||||
"description": "Subtitle for 'WiFi only' network mode option"
|
||||
},
|
||||
"downloadSongLinkRegionDesc": "Used as userCountry for SongLink API lookup.",
|
||||
"@downloadSongLinkRegionDesc": {
|
||||
"description": "Description in the SongLink region picker"
|
||||
},
|
||||
"downloadFolderOrganization": "Folder Organization",
|
||||
"@downloadFolderOrganization": {
|
||||
"description": "Title of the folder organization picker bottom sheet"
|
||||
},
|
||||
"snackbarUnsupportedAudioFormat": "Unsupported audio format",
|
||||
"@snackbarUnsupportedAudioFormat": {
|
||||
"description": "Snackbar when the audio format is not supported for the requested operation"
|
||||
},
|
||||
"cacheRefresh": "Refresh",
|
||||
"@cacheRefresh": {
|
||||
"description": "Tooltip for refresh button on cache management page"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -619,7 +619,7 @@ class _AlbumScreenState extends ConsumerState<AlbumScreen> {
|
||||
size: 22,
|
||||
color: allLoved ? Colors.redAccent : Colors.white,
|
||||
),
|
||||
tooltip: allLoved ? 'Remove from Loved' : 'Love All',
|
||||
tooltip: allLoved ? context.l10n.trackOptionRemoveFromLoved : context.l10n.tooltipLoveAll,
|
||||
padding: EdgeInsets.zero,
|
||||
),
|
||||
);
|
||||
@@ -642,7 +642,7 @@ class _AlbumScreenState extends ConsumerState<AlbumScreen> {
|
||||
? null
|
||||
: () => showAddTracksToPlaylistSheet(context, ref, _tracks!),
|
||||
icon: const Icon(Icons.add, size: 22, color: Colors.white),
|
||||
tooltip: 'Add to Playlist',
|
||||
tooltip: context.l10n.tooltipAddToPlaylist,
|
||||
padding: EdgeInsets.zero,
|
||||
),
|
||||
);
|
||||
@@ -660,7 +660,11 @@ class _AlbumScreenState extends ConsumerState<AlbumScreen> {
|
||||
}
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Removed ${tracks.length} tracks from Loved')),
|
||||
SnackBar(
|
||||
content: Text(
|
||||
context.l10n.snackbarRemovedTracksFromLoved(tracks.length),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
@@ -673,7 +677,11 @@ class _AlbumScreenState extends ConsumerState<AlbumScreen> {
|
||||
}
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Added $addedCount tracks to Loved')),
|
||||
SnackBar(
|
||||
content: Text(
|
||||
context.l10n.snackbarAddedTracksToLoved(addedCount),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -363,7 +363,7 @@ class _DownloadedAlbumScreenState extends ConsumerState<DownloadedAlbumScreen> {
|
||||
if (tracks.isEmpty) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text(widget.albumName)),
|
||||
body: Center(child: Text('No tracks found for this album')),
|
||||
body: Center(child: Text(context.l10n.noTracksFoundForAlbum)),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -816,7 +816,7 @@ class _HomeTabState extends ConsumerState<HomeTab>
|
||||
const SizedBox(height: 12),
|
||||
CheckboxListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
title: const Text('Skip already downloaded songs'),
|
||||
title: Text(l10n.homeSkipAlreadyDownloaded),
|
||||
value: skipDownloaded,
|
||||
onChanged: (value) {
|
||||
setDialogState(() {
|
||||
@@ -1750,7 +1750,7 @@ class _HomeTabState extends ConsumerState<HomeTab>
|
||||
),
|
||||
ListTile(
|
||||
leading: Icon(Icons.album, color: colorScheme.onSurfaceVariant),
|
||||
title: const Text('Go to Album'),
|
||||
title: Text(context.l10n.homeGoToAlbum),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
_navigateToTrackAlbum(item);
|
||||
@@ -1824,7 +1824,7 @@ class _HomeTabState extends ConsumerState<HomeTab>
|
||||
} else {
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(const SnackBar(content: Text('Album info not available')));
|
||||
).showSnackBar(SnackBar(content: Text(context.l10n.homeAlbumInfoUnavailable)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -850,8 +850,8 @@ class _LibraryTracksFolderScreenState
|
||||
final colorScheme = Theme.of(dialogContext).colorScheme;
|
||||
return AlertDialog(
|
||||
backgroundColor: colorScheme.surfaceContainerHigh,
|
||||
title: const Text('Download All'),
|
||||
content: Text('Download ${tracks.length} tracks?'),
|
||||
title: Text(context.l10n.dialogDownloadAllTitle),
|
||||
content: Text(context.l10n.dialogDownloadAllMessage(tracks.length)),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(dialogContext),
|
||||
@@ -862,7 +862,7 @@ class _LibraryTracksFolderScreenState
|
||||
Navigator.pop(dialogContext);
|
||||
_downloadAll(tracks);
|
||||
},
|
||||
child: const Text('Download'),
|
||||
child: Text(context.l10n.dialogDownload),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -247,7 +247,7 @@ class _LocalAlbumScreenState extends ConsumerState<LocalAlbumScreen> {
|
||||
if (tracks.isEmpty) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text(widget.albumName)),
|
||||
body: const Center(child: Text('No tracks found for this album')),
|
||||
body: Center(child: Text(context.l10n.noTracksFoundForAlbum)),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -181,25 +181,20 @@ class _MainShellState extends ConsumerState<MainShell> {
|
||||
size: 32,
|
||||
color: colorScheme.primary,
|
||||
),
|
||||
title: const Text('Storage Update Required'),
|
||||
content: const Column(
|
||||
title: Text(context.l10n.safMigrationTitle),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'SpotiFLAC now uses Android Storage Access Framework (SAF) for downloads. '
|
||||
'This fixes "permission denied" errors on Android 10+.',
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
Text(
|
||||
'Please select your download folder again to switch to the new storage system.',
|
||||
),
|
||||
Text(context.l10n.safMigrationMessage1),
|
||||
const SizedBox(height: 12),
|
||||
Text(context.l10n.safMigrationMessage2),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(ctx),
|
||||
child: const Text('Later'),
|
||||
child: Text(context.l10n.updateLater),
|
||||
),
|
||||
FilledButton(
|
||||
onPressed: () async {
|
||||
@@ -219,15 +214,15 @@ class _MainShellState extends ConsumerState<MainShell> {
|
||||
);
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Download folder updated to SAF mode'),
|
||||
SnackBar(
|
||||
content: Text(context.l10n.safMigrationSuccess),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
child: const Text('Select Folder'),
|
||||
child: Text(context.l10n.setupSelectFolder),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -482,7 +482,7 @@ class _PlaylistScreenState extends ConsumerState<PlaylistScreen> {
|
||||
size: 22,
|
||||
color: allLoved ? Colors.redAccent : Colors.white,
|
||||
),
|
||||
tooltip: allLoved ? 'Remove from Loved' : 'Love All',
|
||||
tooltip: allLoved ? context.l10n.trackOptionRemoveFromLoved : context.l10n.tooltipLoveAll,
|
||||
padding: EdgeInsets.zero,
|
||||
),
|
||||
);
|
||||
@@ -505,7 +505,7 @@ class _PlaylistScreenState extends ConsumerState<PlaylistScreen> {
|
||||
Widget _buildAddToPlaylistButton(BuildContext context) {
|
||||
return _buildCircleButton(
|
||||
icon: Icons.playlist_add,
|
||||
tooltip: 'Add to Playlist',
|
||||
tooltip: context.l10n.tooltipAddToPlaylist,
|
||||
onPressed: _tracks.isEmpty
|
||||
? null
|
||||
: () => showAddTracksToPlaylistSheet(context, ref, _tracks),
|
||||
@@ -520,8 +520,8 @@ class _PlaylistScreenState extends ConsumerState<PlaylistScreen> {
|
||||
final colorScheme = Theme.of(dialogContext).colorScheme;
|
||||
return AlertDialog(
|
||||
backgroundColor: colorScheme.surfaceContainerHigh,
|
||||
title: const Text('Download All'),
|
||||
content: Text('Download ${_tracks.length} tracks?'),
|
||||
title: Text(context.l10n.dialogDownloadAllTitle),
|
||||
content: Text(context.l10n.dialogDownloadAllMessage(_tracks.length)),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(dialogContext),
|
||||
@@ -532,7 +532,7 @@ class _PlaylistScreenState extends ConsumerState<PlaylistScreen> {
|
||||
Navigator.pop(dialogContext);
|
||||
_downloadAll(context);
|
||||
},
|
||||
child: const Text('Download'),
|
||||
child: Text(context.l10n.dialogDownload),
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -552,7 +552,11 @@ class _PlaylistScreenState extends ConsumerState<PlaylistScreen> {
|
||||
}
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Removed ${tracks.length} tracks from Loved')),
|
||||
SnackBar(
|
||||
content: Text(
|
||||
context.l10n.snackbarRemovedTracksFromLoved(tracks.length),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
@@ -565,7 +569,11 @@ class _PlaylistScreenState extends ConsumerState<PlaylistScreen> {
|
||||
}
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Added $addedCount tracks to Loved')),
|
||||
SnackBar(
|
||||
content: Text(
|
||||
context.l10n.snackbarAddedTracksToLoved(addedCount),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:spotiflac_android/l10n/l10n.dart';
|
||||
import 'package:spotiflac_android/services/cover_cache_manager.dart';
|
||||
import 'package:spotiflac_android/models/track.dart';
|
||||
import 'package:spotiflac_android/providers/track_provider.dart';
|
||||
@@ -52,7 +53,7 @@ class _SearchScreenState extends ConsumerState<SearchScreen> {
|
||||
.addToQueue(track, settings.defaultService);
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text('Added "${track.name}" to queue')));
|
||||
).showSnackBar(SnackBar(content: Text(context.l10n.snackbarAddedToQueue(track.name))));
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -56,7 +56,7 @@ class _CacheManagementPageState extends ConsumerState<CacheManagementPage> {
|
||||
setState(() => _isLoading = false);
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text('Error: $e')));
|
||||
).showSnackBar(SnackBar(content: Text(context.l10n.snackbarError(e.toString()))));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,7 +282,7 @@ class _CacheManagementPageState extends ConsumerState<CacheManagementPage> {
|
||||
if (!mounted) return;
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text('Error: $e')));
|
||||
).showSnackBar(SnackBar(content: Text(context.l10n.snackbarError(e.toString()))));
|
||||
} finally {
|
||||
if (mounted) {
|
||||
setState(() => _busyAction = null);
|
||||
@@ -394,7 +394,7 @@ class _CacheManagementPageState extends ConsumerState<CacheManagementPage> {
|
||||
),
|
||||
actions: [
|
||||
IconButton(
|
||||
tooltip: 'Refresh',
|
||||
tooltip: context.l10n.cacheRefresh,
|
||||
onPressed: _isBusy ? null : _refreshOverview,
|
||||
icon: const Icon(Icons.refresh),
|
||||
),
|
||||
|
||||
@@ -376,7 +376,7 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
title: context.l10n.downloadAskBeforeDownload,
|
||||
subtitle: isBuiltInService
|
||||
? context.l10n.downloadAskQualitySubtitle
|
||||
: 'Select a built-in service to enable',
|
||||
: context.l10n.downloadSelectServiceToEnable,
|
||||
value: settings.askQualityBeforeDownload,
|
||||
enabled: isBuiltInService,
|
||||
onChanged: (value) => ref
|
||||
@@ -413,7 +413,7 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
// Lossy 320kbps option (Tidal only) - downloads M4A, converts to MP3/Opus
|
||||
if (isTidalService)
|
||||
_QualityOption(
|
||||
title: 'Lossy 320kbps',
|
||||
title: context.l10n.downloadLossy320,
|
||||
subtitle: _getTidalHighFormatLabel(
|
||||
settings.tidalHighFormat,
|
||||
),
|
||||
@@ -426,7 +426,7 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
if (isTidalService && settings.audioQuality == 'HIGH')
|
||||
SettingsItem(
|
||||
icon: Icons.tune,
|
||||
title: 'Lossy Format',
|
||||
title: context.l10n.downloadLossyFormat,
|
||||
subtitle: _getTidalHighFormatLabel(
|
||||
settings.tidalHighFormat,
|
||||
),
|
||||
@@ -451,7 +451,7 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Select Tidal or Qobuz above to configure quality',
|
||||
context.l10n.downloadSelectTidalQobuz,
|
||||
style: Theme.of(context).textTheme.bodySmall
|
||||
?.copyWith(
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
@@ -504,7 +504,7 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
title: context.l10n.optionsEmbedLyrics,
|
||||
subtitle: settings.embedMetadata
|
||||
? context.l10n.optionsEmbedLyricsSubtitle
|
||||
: 'Disabled while Embed Metadata is turned off',
|
||||
: context.l10n.downloadEmbedLyricsDisabled,
|
||||
value: settings.embedLyrics,
|
||||
enabled: settings.embedMetadata,
|
||||
onChanged: (value) => ref
|
||||
@@ -528,7 +528,7 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
),
|
||||
SettingsItem(
|
||||
icon: Icons.source_outlined,
|
||||
title: 'Lyrics Providers',
|
||||
title: context.l10n.lyricsProvidersTitle,
|
||||
subtitle: _getLyricsProvidersSubtitle(
|
||||
settings.lyricsProviders,
|
||||
),
|
||||
@@ -541,10 +541,10 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
),
|
||||
SettingsSwitchItem(
|
||||
icon: Icons.translate_outlined,
|
||||
title: 'Netease: Include Translation',
|
||||
title: context.l10n.downloadNeteaseIncludeTranslation,
|
||||
subtitle: settings.lyricsIncludeTranslationNetease
|
||||
? 'Append translated lyrics when available'
|
||||
: 'Use original lyrics only',
|
||||
? context.l10n.downloadNeteaseIncludeTranslationEnabled
|
||||
: context.l10n.downloadNeteaseIncludeTranslationDisabled,
|
||||
value: settings.lyricsIncludeTranslationNetease,
|
||||
onChanged: (value) => ref
|
||||
.read(settingsProvider.notifier)
|
||||
@@ -552,10 +552,10 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
),
|
||||
SettingsSwitchItem(
|
||||
icon: Icons.text_fields_outlined,
|
||||
title: 'Netease: Include Romanization',
|
||||
title: context.l10n.downloadNeteaseIncludeRomanization,
|
||||
subtitle: settings.lyricsIncludeRomanizationNetease
|
||||
? 'Append romanized lyrics when available'
|
||||
: 'Disabled',
|
||||
? context.l10n.downloadNeteaseIncludeRomanizationEnabled
|
||||
: context.l10n.downloadNeteaseIncludeRomanizationDisabled,
|
||||
value: settings.lyricsIncludeRomanizationNetease,
|
||||
onChanged: (value) => ref
|
||||
.read(settingsProvider.notifier)
|
||||
@@ -563,10 +563,10 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
),
|
||||
SettingsSwitchItem(
|
||||
icon: Icons.record_voice_over_outlined,
|
||||
title: 'Apple/QQ Multi-Person Word-by-Word',
|
||||
title: context.l10n.downloadAppleQqMultiPerson,
|
||||
subtitle: settings.lyricsMultiPersonWordByWord
|
||||
? 'Enable v1/v2 speaker and [bg:] tags'
|
||||
: 'Simplified word-by-word formatting',
|
||||
? context.l10n.downloadAppleQqMultiPersonEnabled
|
||||
: context.l10n.downloadAppleQqMultiPersonDisabled,
|
||||
value: settings.lyricsMultiPersonWordByWord,
|
||||
onChanged: (value) => ref
|
||||
.read(settingsProvider.notifier)
|
||||
@@ -574,9 +574,9 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
),
|
||||
SettingsItem(
|
||||
icon: Icons.language_outlined,
|
||||
title: 'Musixmatch Language',
|
||||
title: context.l10n.downloadMusixmatchLanguage,
|
||||
subtitle: settings.musixmatchLanguage.isEmpty
|
||||
? 'Auto (original)'
|
||||
? context.l10n.downloadMusixmatchLanguageAuto
|
||||
: settings.musixmatchLanguage.toUpperCase(),
|
||||
onTap: () => _showMusixmatchLanguagePicker(
|
||||
context,
|
||||
@@ -622,8 +622,8 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
icon: Icons.library_music_outlined,
|
||||
title: context.l10n.downloadSeparateSinglesFolder,
|
||||
subtitle: settings.separateSingles
|
||||
? 'Albums/ and Singles/ folders'
|
||||
: 'All files in same structure',
|
||||
? context.l10n.downloadSeparateSinglesEnabled
|
||||
: context.l10n.downloadSeparateSinglesDisabled,
|
||||
value: settings.separateSingles,
|
||||
onChanged: (value) => ref
|
||||
.read(settingsProvider.notifier)
|
||||
@@ -670,9 +670,9 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
.read(settingsProvider.notifier)
|
||||
.setUseAlbumArtistForFolders(value),
|
||||
),
|
||||
SettingsItem(
|
||||
SettingsItem(
|
||||
icon: Icons.filter_alt_outlined,
|
||||
title: 'Artist Name Filters',
|
||||
title: context.l10n.downloadArtistNameFilters,
|
||||
subtitle: _getArtistFolderFilterSubtitle(
|
||||
context,
|
||||
usePrimaryArtistOnly: settings.usePrimaryArtistOnly,
|
||||
@@ -707,28 +707,16 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
if (_artistFolderFiltersExpanded)
|
||||
SettingsSwitchItem(
|
||||
icon: Icons.group_remove_outlined,
|
||||
title: 'Filter contributing artists in Album Artist',
|
||||
title: context.l10n.downloadFilterContributing,
|
||||
subtitle: settings.filterContributingArtistsInAlbumArtist
|
||||
? 'Album Artist metadata uses primary artist only'
|
||||
: 'Keep full Album Artist metadata value',
|
||||
? context.l10n.downloadFilterContributingEnabled
|
||||
: context.l10n.downloadFilterContributingDisabled,
|
||||
value: settings.filterContributingArtistsInAlbumArtist,
|
||||
onChanged: (value) => ref
|
||||
.read(settingsProvider.notifier)
|
||||
.setFilterContributingArtistsInAlbumArtist(value),
|
||||
showDivider: false,
|
||||
),
|
||||
SettingsSwitchItem(
|
||||
icon: Icons.person_outline,
|
||||
title: context.l10n.downloadUsePrimaryArtistOnly,
|
||||
subtitle: settings.usePrimaryArtistOnly
|
||||
? context.l10n.downloadUsePrimaryArtistOnlyEnabled
|
||||
: context.l10n.downloadUsePrimaryArtistOnlyDisabled,
|
||||
value: settings.usePrimaryArtistOnly,
|
||||
onChanged: (value) => ref
|
||||
.read(settingsProvider.notifier)
|
||||
.setUsePrimaryArtistOnly(value),
|
||||
showDivider: false,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -753,7 +741,7 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
),
|
||||
SettingsItem(
|
||||
icon: Icons.public,
|
||||
title: 'SongLink Region',
|
||||
title: context.l10n.downloadSongLinkRegion,
|
||||
subtitle: _getSongLinkRegionLabel(settings.songLinkRegion),
|
||||
onTap: () => _showSongLinkRegionPicker(
|
||||
context,
|
||||
@@ -763,10 +751,10 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
),
|
||||
SettingsSwitchItem(
|
||||
icon: Icons.security_outlined,
|
||||
title: 'Network compatibility mode',
|
||||
title: context.l10n.downloadNetworkCompatibilityMode,
|
||||
subtitle: settings.networkCompatibilityMode
|
||||
? 'Enabled: try HTTP + accept invalid TLS certificates (unsafe)'
|
||||
: 'Off: strict HTTPS certificate validation (recommended)',
|
||||
? context.l10n.downloadNetworkCompatibilityModeEnabled
|
||||
: context.l10n.downloadNetworkCompatibilityModeDisabled,
|
||||
value: settings.networkCompatibilityMode,
|
||||
onChanged: (value) {
|
||||
ref
|
||||
@@ -1045,7 +1033,7 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'Customize how your files are named.',
|
||||
context.l10n.downloadFilenameDescription,
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
@@ -1070,7 +1058,7 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
const SizedBox(height: 24),
|
||||
|
||||
Text(
|
||||
'Tap to insert tag:',
|
||||
context.l10n.downloadFilenameInsertTag,
|
||||
style: Theme.of(context).textTheme.titleSmall?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
@@ -1238,7 +1226,7 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 24, 24, 8),
|
||||
child: Text(
|
||||
'Download Location',
|
||||
context.l10n.setupDownloadLocationTitle,
|
||||
style: Theme.of(
|
||||
ctx,
|
||||
).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.bold),
|
||||
@@ -1247,7 +1235,7 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 0, 24, 16),
|
||||
child: Text(
|
||||
'Choose storage mode for downloaded files.',
|
||||
context.l10n.downloadLocationSubtitle,
|
||||
style: Theme.of(ctx).textTheme.bodyMedium?.copyWith(
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
@@ -1255,8 +1243,8 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
),
|
||||
ListTile(
|
||||
leading: Icon(Icons.folder_special, color: colorScheme.primary),
|
||||
title: const Text('App folder (non-SAF)'),
|
||||
subtitle: const Text('Use default Music/SpotiFLAC path'),
|
||||
title: Text(context.l10n.storageModeAppFolder),
|
||||
subtitle: Text(context.l10n.storageModeAppFolderSubtitle),
|
||||
trailing: !isSafMode ? const Icon(Icons.check) : null,
|
||||
onTap: () async {
|
||||
Navigator.pop(ctx);
|
||||
@@ -1269,10 +1257,8 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
),
|
||||
ListTile(
|
||||
leading: Icon(Icons.folder_open, color: colorScheme.primary),
|
||||
title: const Text('SAF folder'),
|
||||
subtitle: const Text(
|
||||
'Pick folder via Android Storage Access Framework',
|
||||
),
|
||||
title: Text(context.l10n.storageModeSaf),
|
||||
subtitle: Text(context.l10n.storageModeSafSubtitle),
|
||||
trailing: isSafMode ? const Icon(Icons.check) : null,
|
||||
onTap: () async {
|
||||
Navigator.pop(ctx);
|
||||
@@ -1546,7 +1532,7 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
};
|
||||
|
||||
String _getLyricsProvidersSubtitle(List<String> providers) {
|
||||
if (providers.isEmpty) return 'None enabled';
|
||||
if (providers.isEmpty) return context.l10n.downloadProvidersNoneEnabled;
|
||||
return providers.map((p) => _providerDisplayNames[p] ?? p).join(' > ');
|
||||
}
|
||||
|
||||
@@ -1645,14 +1631,14 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Musixmatch Language',
|
||||
context.l10n.downloadMusixmatchLanguage,
|
||||
style: Theme.of(
|
||||
context,
|
||||
).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'Set preferred language code (example: en, es, ja). Leave empty for auto.',
|
||||
context.l10n.downloadMusixmatchLanguageDesc,
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
@@ -1661,9 +1647,9 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
TextField(
|
||||
controller: controller,
|
||||
textInputAction: TextInputAction.done,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Language code',
|
||||
hintText: 'auto / en / es / ja',
|
||||
decoration: InputDecoration(
|
||||
labelText: context.l10n.downloadMusixmatchLanguageCode,
|
||||
hintText: context.l10n.downloadMusixmatchLanguageHint,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
@@ -1682,7 +1668,7 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
.setMusixmatchLanguage('');
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: const Text('Auto'),
|
||||
child: Text(context.l10n.downloadMusixmatchAuto),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
FilledButton(
|
||||
@@ -1739,7 +1725,7 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 24, 24, 8),
|
||||
child: Text(
|
||||
'Lossy 320kbps Format',
|
||||
context.l10n.downloadLossy320Format,
|
||||
style: Theme.of(
|
||||
context,
|
||||
).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.bold),
|
||||
@@ -1748,7 +1734,7 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 0, 24, 16),
|
||||
child: Text(
|
||||
'Choose the output format for Tidal 320kbps lossy downloads. The original AAC stream will be converted to your selected format.',
|
||||
context.l10n.downloadLossy320FormatDesc,
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
@@ -1756,8 +1742,8 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.audiotrack),
|
||||
title: const Text('MP3 320kbps'),
|
||||
subtitle: const Text('Best compatibility, ~10MB per track'),
|
||||
title: Text(context.l10n.downloadLossyMp3),
|
||||
subtitle: Text(context.l10n.downloadLossyMp3Subtitle),
|
||||
trailing: current == 'mp3_320'
|
||||
? Icon(Icons.check, color: colorScheme.primary)
|
||||
: null,
|
||||
@@ -1770,8 +1756,8 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.graphic_eq),
|
||||
title: const Text('Opus 256kbps'),
|
||||
subtitle: const Text('Best quality Opus, ~8MB per track'),
|
||||
title: Text(context.l10n.downloadLossyOpus256),
|
||||
subtitle: Text(context.l10n.downloadLossyOpus256Subtitle),
|
||||
trailing: current == 'opus_256'
|
||||
? Icon(Icons.check, color: colorScheme.primary)
|
||||
: null,
|
||||
@@ -1784,8 +1770,8 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.graphic_eq),
|
||||
title: const Text('Opus 128kbps'),
|
||||
subtitle: const Text('Smallest size, ~4MB per track'),
|
||||
title: Text(context.l10n.downloadLossyOpus128),
|
||||
subtitle: Text(context.l10n.downloadLossyOpus128Subtitle),
|
||||
trailing: current == 'opus_128'
|
||||
? Icon(Icons.check, color: colorScheme.primary)
|
||||
: null,
|
||||
@@ -1842,7 +1828,7 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
ListTile(
|
||||
leading: const Icon(Icons.signal_cellular_alt),
|
||||
title: Text(context.l10n.settingsDownloadNetworkAny),
|
||||
subtitle: const Text('WiFi + Mobile Data'),
|
||||
subtitle: Text(context.l10n.downloadNetworkAnySubtitle),
|
||||
trailing: current == 'any'
|
||||
? Icon(Icons.check, color: colorScheme.primary)
|
||||
: null,
|
||||
@@ -1856,7 +1842,7 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
ListTile(
|
||||
leading: const Icon(Icons.wifi),
|
||||
title: Text(context.l10n.settingsDownloadNetworkWifiOnly),
|
||||
subtitle: const Text('Pause downloads on mobile data'),
|
||||
subtitle: Text(context.l10n.downloadNetworkWifiOnlySubtitle),
|
||||
trailing: current == 'wifi_only'
|
||||
? Icon(Icons.check, color: colorScheme.primary)
|
||||
: null,
|
||||
@@ -1897,17 +1883,17 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 24, 24, 8),
|
||||
child: Text(
|
||||
'SongLink Region',
|
||||
style: Theme.of(
|
||||
context,
|
||||
).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.bold),
|
||||
),
|
||||
child: Text(
|
||||
context.l10n.downloadSongLinkRegion,
|
||||
style: Theme.of(
|
||||
context,
|
||||
).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.bold),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 0, 24, 16),
|
||||
child: Text(
|
||||
'Used as userCountry for SongLink API lookup.',
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 0, 24, 16),
|
||||
child: Text(
|
||||
context.l10n.downloadSongLinkRegionDesc,
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
@@ -1968,12 +1954,12 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 24, 24, 8),
|
||||
child: Text(
|
||||
'Folder Organization',
|
||||
style: Theme.of(
|
||||
context,
|
||||
).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.bold),
|
||||
),
|
||||
child: Text(
|
||||
context.l10n.downloadFolderOrganization,
|
||||
style: Theme.of(
|
||||
context,
|
||||
).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 0, 24, 16),
|
||||
|
||||
@@ -801,7 +801,7 @@ class _SettingItemState extends State<_SettingItem> {
|
||||
Future<void> _invokeAction(BuildContext context) async {
|
||||
if (widget.setting.action == null) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('No action defined for this button')),
|
||||
SnackBar(content: Text(context.l10n.snackbarNoActionDefined)),
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -834,7 +834,7 @@ class _SettingItemState extends State<_SettingItem> {
|
||||
if (context.mounted) {
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text('Error: $e')));
|
||||
).showSnackBar(SnackBar(content: Text(context.l10n.snackbarError(e.toString()))));
|
||||
}
|
||||
} finally {
|
||||
if (mounted) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:spotiflac_android/l10n/l10n.dart';
|
||||
import 'package:spotiflac_android/providers/settings_provider.dart';
|
||||
import 'package:spotiflac_android/widgets/priority_settings_scaffold.dart';
|
||||
import 'package:spotiflac_android/widgets/settings_group.dart';
|
||||
@@ -55,18 +56,18 @@ class _LyricsProviderPriorityPageState
|
||||
|
||||
return PrioritySettingsScaffold(
|
||||
hasChanges: _hasChanges,
|
||||
title: 'Lyrics Providers',
|
||||
description:
|
||||
'Enable, disable and reorder lyrics sources. Providers are tried top-to-bottom until lyrics are found.',
|
||||
infoText:
|
||||
'Extension lyrics providers always run before built-in providers. At least one provider must remain enabled.',
|
||||
title: context.l10n.lyricsProvidersTitle,
|
||||
description: context.l10n.lyricsProvidersDescription,
|
||||
infoText: context.l10n.lyricsProvidersInfoText,
|
||||
onSave: _saveChanges,
|
||||
onConfirmDiscard: _confirmDiscard,
|
||||
slivers: [
|
||||
if (_enabledProviders.isNotEmpty)
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsSectionHeader(
|
||||
title: 'Enabled (${_enabledProviders.length})',
|
||||
title: context.l10n.lyricsProvidersEnabledSection(
|
||||
_enabledProviders.length,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (_enabledProviders.isNotEmpty)
|
||||
@@ -76,7 +77,7 @@ class _LyricsProviderPriorityPageState
|
||||
itemCount: _enabledProviders.length,
|
||||
itemBuilder: (context, index) {
|
||||
final id = _enabledProviders[index];
|
||||
final info = _getLyricsProviderInfo(id);
|
||||
final info = _getLyricsProviderInfo(id, context);
|
||||
return _EnabledProviderItem(
|
||||
key: ValueKey(id),
|
||||
providerId: id,
|
||||
@@ -99,7 +100,9 @@ class _LyricsProviderPriorityPageState
|
||||
if (disabled.isNotEmpty)
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsSectionHeader(
|
||||
title: 'Disabled (${disabled.length})',
|
||||
title: context.l10n.lyricsProvidersDisabledSection(
|
||||
disabled.length,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (disabled.isNotEmpty)
|
||||
@@ -108,7 +111,7 @@ class _LyricsProviderPriorityPageState
|
||||
sliver: SliverList(
|
||||
delegate: SliverChildBuilderDelegate((context, index) {
|
||||
final id = disabled[index];
|
||||
final info = _getLyricsProviderInfo(id);
|
||||
final info = _getLyricsProviderInfo(id, context);
|
||||
return _DisabledProviderItem(
|
||||
key: ValueKey(id),
|
||||
providerId: id,
|
||||
@@ -130,8 +133,8 @@ class _LyricsProviderPriorityPageState
|
||||
void _disableProvider(String id) {
|
||||
if (_enabledProviders.length <= 1) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('At least one provider must remain enabled'),
|
||||
SnackBar(
|
||||
content: Text(context.l10n.lyricsProvidersAtLeastOne),
|
||||
),
|
||||
);
|
||||
return;
|
||||
@@ -150,7 +153,7 @@ class _LyricsProviderPriorityPageState
|
||||
});
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('Lyrics provider priority saved')),
|
||||
SnackBar(content: Text(context.l10n.lyricsProvidersSaved)),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -159,16 +162,16 @@ class _LyricsProviderPriorityPageState
|
||||
final result = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: const Text('Discard changes?'),
|
||||
content: const Text('You have unsaved changes that will be lost.'),
|
||||
title: Text(context.l10n.dialogDiscardChanges),
|
||||
content: Text(context.l10n.lyricsProvidersDiscardContent),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, false),
|
||||
child: const Text('Cancel'),
|
||||
child: Text(context.l10n.dialogCancel),
|
||||
),
|
||||
FilledButton(
|
||||
onPressed: () => Navigator.pop(context, true),
|
||||
child: const Text('Discard'),
|
||||
child: Text(context.l10n.dialogDiscard),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -176,48 +179,51 @@ class _LyricsProviderPriorityPageState
|
||||
return result ?? false;
|
||||
}
|
||||
|
||||
static _LyricsProviderInfo _getLyricsProviderInfo(String id) {
|
||||
static _LyricsProviderInfo _getLyricsProviderInfo(
|
||||
String id,
|
||||
BuildContext context,
|
||||
) {
|
||||
switch (id) {
|
||||
case 'spotify_api':
|
||||
return _LyricsProviderInfo(
|
||||
name: 'Spotify Lyrics API',
|
||||
description: 'Spotify-sourced synced lyrics via community API',
|
||||
description: context.l10n.lyricsProviderSpotifyApiDesc,
|
||||
icon: Icons.music_note_outlined,
|
||||
);
|
||||
case 'lrclib':
|
||||
return _LyricsProviderInfo(
|
||||
name: 'LRCLIB',
|
||||
description: 'Open-source synced lyrics database',
|
||||
description: context.l10n.lyricsProviderLrclibDesc,
|
||||
icon: Icons.subtitles_outlined,
|
||||
);
|
||||
case 'netease':
|
||||
return _LyricsProviderInfo(
|
||||
name: 'Netease',
|
||||
description: 'NetEase Cloud Music (good for Asian songs)',
|
||||
description: context.l10n.lyricsProviderNeteaseDesc,
|
||||
icon: Icons.cloud_outlined,
|
||||
);
|
||||
case 'musixmatch':
|
||||
return _LyricsProviderInfo(
|
||||
name: 'Musixmatch',
|
||||
description: 'Largest lyrics database (multi-language)',
|
||||
description: context.l10n.lyricsProviderMusixmatchDesc,
|
||||
icon: Icons.translate,
|
||||
);
|
||||
case 'apple_music':
|
||||
return _LyricsProviderInfo(
|
||||
name: 'Apple Music',
|
||||
description: 'Word-by-word synced lyrics (via proxy)',
|
||||
description: context.l10n.lyricsProviderAppleMusicDesc,
|
||||
icon: Icons.music_note,
|
||||
);
|
||||
case 'qqmusic':
|
||||
return _LyricsProviderInfo(
|
||||
name: 'QQ Music',
|
||||
description: 'QQ Music (good for Chinese songs, via proxy)',
|
||||
description: context.l10n.lyricsProviderQqMusicDesc,
|
||||
icon: Icons.queue_music,
|
||||
);
|
||||
default:
|
||||
return _LyricsProviderInfo(
|
||||
name: id,
|
||||
description: 'Extension provider',
|
||||
description: context.l10n.lyricsProviderExtensionDesc,
|
||||
icon: Icons.extension,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -107,8 +107,8 @@ class SettingsTab extends ConsumerWidget {
|
||||
),
|
||||
SettingsItem(
|
||||
icon: Icons.favorite_outline,
|
||||
title: 'Donate',
|
||||
subtitle: 'Support SpotiFLAC-Mobile development',
|
||||
title: l10n.settingsDonate,
|
||||
subtitle: l10n.settingsDonateSubtitle,
|
||||
onTap: () => _navigateTo(context, const DonatePage()),
|
||||
showDivider: false,
|
||||
),
|
||||
|
||||
@@ -1731,13 +1731,13 @@ class _TrackMetadataScreenState extends ConsumerState<TrackMetadataScreen> {
|
||||
);
|
||||
success = ok;
|
||||
if (!ok) {
|
||||
error = 'Failed to write back to storage';
|
||||
error = context.l10n.snackbarFailedToWriteStorage;
|
||||
}
|
||||
} else {
|
||||
success = true;
|
||||
}
|
||||
} else {
|
||||
error = result['error']?.toString() ?? 'Failed to embed lyrics';
|
||||
error = result['error']?.toString() ?? context.l10n.snackbarFailedToEmbedLyrics;
|
||||
}
|
||||
} else if (isMp3 || isOpus) {
|
||||
final metadata = _buildFallbackMetadata();
|
||||
@@ -1783,7 +1783,7 @@ class _TrackMetadataScreenState extends ConsumerState<TrackMetadataScreen> {
|
||||
}
|
||||
|
||||
if (ffmpegResult == null) {
|
||||
error = 'Failed to embed lyrics';
|
||||
error = context.l10n.snackbarFailedToEmbedLyrics;
|
||||
} else if (_isSafFile) {
|
||||
final ok = await PlatformBridge.writeTempToSaf(
|
||||
ffmpegResult,
|
||||
@@ -1791,13 +1791,13 @@ class _TrackMetadataScreenState extends ConsumerState<TrackMetadataScreen> {
|
||||
);
|
||||
success = ok;
|
||||
if (!ok) {
|
||||
error = 'Failed to write back to storage';
|
||||
error = context.l10n.snackbarFailedToWriteStorage;
|
||||
}
|
||||
} else {
|
||||
success = true;
|
||||
}
|
||||
} else {
|
||||
error = 'Unsupported audio format';
|
||||
error = context.l10n.snackbarUnsupportedAudioFormat;
|
||||
}
|
||||
|
||||
if (mounted) {
|
||||
@@ -1812,7 +1812,7 @@ class _TrackMetadataScreenState extends ConsumerState<TrackMetadataScreen> {
|
||||
} else {
|
||||
setState(() => _isEmbedding = false);
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text(error ?? 'Failed to embed lyrics')),
|
||||
SnackBar(content: Text(error ?? context.l10n.snackbarFailedToEmbedLyrics)),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1821,7 +1821,7 @@ class _TrackMetadataScreenState extends ConsumerState<TrackMetadataScreen> {
|
||||
setState(() => _isEmbedding = false);
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text('Error: $e')));
|
||||
).showSnackBar(SnackBar(content: Text(context.l10n.snackbarError(e.toString()))));
|
||||
}
|
||||
} finally {
|
||||
if (coverPath != null) {
|
||||
@@ -2271,7 +2271,7 @@ class _TrackMetadataScreenState extends ConsumerState<TrackMetadataScreen> {
|
||||
SnackBar(
|
||||
content: Text(
|
||||
context.l10n.trackSaveFailed(
|
||||
'Failed to write back to storage',
|
||||
context.l10n.snackbarFailedToWriteStorage,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -2873,7 +2873,7 @@ class _TrackMetadataScreenState extends ConsumerState<TrackMetadataScreen> {
|
||||
|
||||
// Show loading indicator
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('Loading CUE sheet...')),
|
||||
SnackBar(content: Text(context.l10n.snackbarLoadingCueSheet)),
|
||||
);
|
||||
|
||||
try {
|
||||
@@ -3644,7 +3644,7 @@ class _TrackMetadataScreenState extends ConsumerState<TrackMetadataScreen> {
|
||||
|
||||
if (saved == true && mounted) {
|
||||
ScaffoldMessenger.of(this.context).showSnackBar(
|
||||
const SnackBar(content: Text('Metadata saved successfully')),
|
||||
SnackBar(content: Text(this.context.l10n.snackbarMetadataSaved)),
|
||||
);
|
||||
// Re-read metadata from file to refresh the display
|
||||
try {
|
||||
@@ -4066,7 +4066,7 @@ class _EditMetadataSheetState extends State<_EditMetadataSheet> {
|
||||
if (!mounted) return;
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text('Failed to pick cover: $e')));
|
||||
).showSnackBar(SnackBar(content: Text(context.l10n.snackbarError(e.toString()))));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4290,7 +4290,7 @@ class _EditMetadataSheetState extends State<_EditMetadataSheet> {
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text('Failed to save metadata: $e')));
|
||||
).showSnackBar(SnackBar(content: Text(context.l10n.snackbarError(e.toString()))));
|
||||
}
|
||||
} finally {
|
||||
if (mounted) setState(() => _saving = false);
|
||||
|
||||
Reference in New Issue
Block a user