Merge remote-tracking branch 'spotiflacapp/main'
# Conflicts: # android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png # android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png # android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png # android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png # android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png # android/app/src/main/res/mipmap-hdpi/ic_launcher.png # android/app/src/main/res/mipmap-mdpi/ic_launcher.png # android/app/src/main/res/mipmap-xhdpi/ic_launcher.png # android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png # android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png # crowdin.yml # ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png # ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png # ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png # ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png # ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png # ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png # ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png # ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png # ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png # ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png # ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png # ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png # ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png # ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png # ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png # ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png # ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png # ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png # ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png # ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png # ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png # lib/l10n/app_localizations_de.dart # lib/l10n/app_localizations_fr.dart # lib/l10n/app_localizations_id.dart # lib/l10n/app_localizations_tr.dart # lib/l10n/arb/app_en.arb # lib/l10n/arb/app_id.arb # lib/l10n/arb/app_ja.arb # lib/l10n/arb/app_tr.arb # lib/screens/settings/download_settings_page.dart # lib/screens/settings/options_settings_page.dart
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 828 B After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.7 KiB |
@@ -12,7 +12,7 @@
|
||||
"downloadURL": "https://github.com/zarzet/SpotiFLAC-Mobile/releases/download/v4.3.1/SpotiFLAC-v4.3.1-ios-unsigned.ipa",
|
||||
"localizedDescription": "Mobile version of SpotiFLAC written in Flutter. Download Tracks in true FLAC from Tidal, Qobuz, & Amazon Music.",
|
||||
"iconURL": "https://raw.githubusercontent.com/zarzet/SpotiFLAC-Mobile/main/assets/images/logo.png",
|
||||
"size": 34773598
|
||||
"size": 34773644
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ files:
|
||||
pt-PT: pt_PT
|
||||
ru: ru
|
||||
tr: tr
|
||||
uk: uk
|
||||
zh: zh
|
||||
# Full codes for Chinese variants
|
||||
zh-CN: zh_CN
|
||||
|
||||
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 428 B After Width: | Height: | Size: 603 B |
|
Before Width: | Height: | Size: 872 B After Width: | Height: | Size: 966 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 648 B After Width: | Height: | Size: 783 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 872 B After Width: | Height: | Size: 966 B |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 3.3 KiB |
@@ -17,6 +17,7 @@ import 'app_localizations_nl.dart';
|
||||
import 'app_localizations_pt.dart';
|
||||
import 'app_localizations_ru.dart';
|
||||
import 'app_localizations_tr.dart';
|
||||
import 'app_localizations_uk.dart';
|
||||
import 'app_localizations_zh.dart';
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
@@ -119,6 +120,7 @@ abstract class AppLocalizations {
|
||||
Locale('pt', 'PT'),
|
||||
Locale('ru'),
|
||||
Locale('tr'),
|
||||
Locale('uk'),
|
||||
Locale('zh'),
|
||||
Locale('zh', 'CN'),
|
||||
Locale('zh', 'TW'),
|
||||
@@ -355,7 +357,7 @@ abstract class AppLocalizations {
|
||||
/// Subtitle for primary provider
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Service used when searching by track name.'**
|
||||
/// **'Service used for searching by track or album name'**
|
||||
String get optionsPrimaryProviderSubtitle;
|
||||
|
||||
/// Shows active extension name
|
||||
@@ -376,10 +378,10 @@ abstract class AppLocalizations {
|
||||
/// **'Choose which tab opens first for new search results.'**
|
||||
String get optionsDefaultSearchTabSubtitle;
|
||||
|
||||
/// Hint to switch away from the current provider selection
|
||||
/// Hint to switch back to built-in providers
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Choose another provider below to stop using the current extension'**
|
||||
/// **'Tap Deezer or Spotify to switch back from extension'**
|
||||
String get optionsSwitchBack;
|
||||
|
||||
/// Auto-retry with other services
|
||||
@@ -406,10 +408,10 @@ abstract class AppLocalizations {
|
||||
/// **'Extensions will be tried first'**
|
||||
String get optionsUseExtensionProvidersOn;
|
||||
|
||||
/// Status when extension providers are disabled
|
||||
/// Status when extension providers disabled
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Extensions are turned off'**
|
||||
/// **'Using built-in providers only'**
|
||||
String get optionsUseExtensionProvidersOff;
|
||||
|
||||
/// Embed lyrics in audio files
|
||||
@@ -421,7 +423,7 @@ abstract class AppLocalizations {
|
||||
/// Subtitle for embed lyrics
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Embed synced lyrics into FLAC files'**
|
||||
/// **'Save synced lyrics alongside your downloaded tracks'**
|
||||
String get optionsEmbedLyricsSubtitle;
|
||||
|
||||
/// Download highest quality album art
|
||||
@@ -1795,7 +1797,7 @@ abstract class AppLocalizations {
|
||||
/// Section description for extension fallback selection
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Choose which installed download extensions can be used during automatic fallback.'**
|
||||
/// **'Choose which installed download extensions can be used during automatic fallback. Built-in providers still follow the priority order above.'**
|
||||
String get providerPriorityFallbackExtensionsDescription;
|
||||
|
||||
/// Hint below the extension fallback selection list
|
||||
@@ -1804,10 +1806,10 @@ abstract class AppLocalizations {
|
||||
/// **'Only enabled extensions with download-provider capability are listed here.'**
|
||||
String get providerPriorityFallbackExtensionsHint;
|
||||
|
||||
/// Label for legacy providers kept for compatibility
|
||||
/// Label for built-in providers (Tidal/Qobuz)
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Legacy'**
|
||||
/// **'Built-in'**
|
||||
String get providerBuiltIn;
|
||||
|
||||
/// Label for extension-provided providers
|
||||
@@ -2125,13 +2127,13 @@ abstract class AppLocalizations {
|
||||
/// Download settings description
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Service, quality, filename format'**
|
||||
/// **'Service, quality, fallback'**
|
||||
String get settingsDownloadSubtitle;
|
||||
|
||||
/// Options settings description
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Fallback, lyrics, cover art, updates'**
|
||||
/// **'Fallback, metadata, lyrics, cover art'**
|
||||
String get settingsOptionsSubtitle;
|
||||
|
||||
/// Extensions settings description
|
||||
@@ -4803,22 +4805,22 @@ abstract class AppLocalizations {
|
||||
/// **'{count} downloaded'**
|
||||
String downloadedAlbumDownloadedCount(int count);
|
||||
|
||||
/// Subtitle when Album Artist is used for folder naming
|
||||
/// Subtitle when album artist is used for folder names
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Artist folders use Album Artist when available'**
|
||||
/// **'Folder named after Album Artist tag'**
|
||||
String get downloadUseAlbumArtistForFoldersAlbumSubtitle;
|
||||
|
||||
/// Subtitle when Track Artist is used for folder naming
|
||||
/// Subtitle when track artist is used for folder names
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Artist folders use Track Artist only'**
|
||||
/// **'Folder named after Track Artist tag'**
|
||||
String get downloadUseAlbumArtistForFoldersTrackSubtitle;
|
||||
|
||||
/// Title for the lyrics provider priority page
|
||||
/// Settings item title for lyrics provider order
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Lyrics Providers'**
|
||||
/// **'Lyrics Provider Priority'**
|
||||
String get lyricsProvidersTitle;
|
||||
|
||||
/// Description on the lyrics provider priority page
|
||||
@@ -4923,16 +4925,16 @@ abstract class AppLocalizations {
|
||||
/// **'Download folder updated to SAF mode'**
|
||||
String get safMigrationSuccess;
|
||||
|
||||
/// Settings menu item - donate
|
||||
/// Settings menu item - donate page
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Donate'**
|
||||
/// **'Support Development'**
|
||||
String get settingsDonate;
|
||||
|
||||
/// Subtitle for donate menu item
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Support SpotiFLAC-Mobile development'**
|
||||
/// **'Buy the developer a coffee'**
|
||||
String get settingsDonateSubtitle;
|
||||
|
||||
/// Tooltip for the Love All button on album/playlist screens
|
||||
@@ -5031,41 +5033,49 @@ abstract class AppLocalizations {
|
||||
/// **'No tracks found for this album'**
|
||||
String get noTracksFoundForAlbum;
|
||||
|
||||
/// Subtitle text in Android download location bottom sheet
|
||||
/// Subtitle shown in the download location picker sheet
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Choose storage mode for downloaded files.'**
|
||||
/// **'Choose where to save your downloaded tracks'**
|
||||
String get downloadLocationSubtitle;
|
||||
|
||||
/// Storage mode option - use legacy app folder
|
||||
/// Storage mode option - app-managed folder
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'App folder (non-SAF)'**
|
||||
/// **'App Folder (Recommended)'**
|
||||
String get storageModeAppFolder;
|
||||
|
||||
/// Subtitle for app folder storage mode
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Use default Music/SpotiFLAC path'**
|
||||
/// **'Saves to Music/SpotiFLAC by default'**
|
||||
String get storageModeAppFolderSubtitle;
|
||||
|
||||
/// Storage mode option - use Android SAF picker
|
||||
/// Storage mode option - Storage Access Framework
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'SAF folder'**
|
||||
/// **'Custom Folder (SAF)'**
|
||||
String get storageModeSaf;
|
||||
|
||||
/// Subtitle for SAF storage mode
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Pick folder via Android Storage Access Framework'**
|
||||
/// **'Pick any folder, including SD card'**
|
||||
String get storageModeSafSubtitle;
|
||||
|
||||
/// Description text in filename format bottom sheet
|
||||
/// Description shown in filename format editor
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Customize how your files are named.'**
|
||||
String get downloadFilenameDescription;
|
||||
/// **'Use {artist}, {title}, {album}, {track}, {year}, {date}, {disc} as placeholders.'**
|
||||
String downloadFilenameDescription(
|
||||
Object album,
|
||||
Object artist,
|
||||
Object date,
|
||||
Object disc,
|
||||
Object title,
|
||||
Object track,
|
||||
Object year,
|
||||
);
|
||||
|
||||
/// Label above filename tag chips
|
||||
///
|
||||
@@ -5073,16 +5083,16 @@ abstract class AppLocalizations {
|
||||
/// **'Tap to insert tag:'**
|
||||
String get downloadFilenameInsertTag;
|
||||
|
||||
/// Subtitle when separate singles folder is enabled
|
||||
/// Subtitle when separate singles folder is on
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Albums/ and Singles/ folders'**
|
||||
/// **'Singles and EPs saved in a separate folder'**
|
||||
String get downloadSeparateSinglesEnabled;
|
||||
|
||||
/// Subtitle when separate singles folder is disabled
|
||||
/// Subtitle when separate singles folder is off
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'All files in same structure'**
|
||||
/// **'Singles and albums saved in the same folder'**
|
||||
String get downloadSeparateSinglesDisabled;
|
||||
|
||||
/// Setting title for artist folder filter options
|
||||
@@ -5091,202 +5101,202 @@ abstract class AppLocalizations {
|
||||
/// **'Artist Name Filters'**
|
||||
String get downloadArtistNameFilters;
|
||||
|
||||
/// Setting title for adding a playlist folder prefix before the normal organization structure
|
||||
/// Setting to create a subfolder per playlist source
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Create playlist source folder'**
|
||||
/// **'Playlist Source Folder'**
|
||||
String get downloadCreatePlaylistSourceFolder;
|
||||
|
||||
/// Subtitle when playlist source folder prefix is enabled
|
||||
/// Subtitle when playlist folder is enabled
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Playlist downloads use Playlist/ plus your normal folder structure.'**
|
||||
/// **'A subfolder is created for each playlist'**
|
||||
String get downloadCreatePlaylistSourceFolderEnabled;
|
||||
|
||||
/// Subtitle when playlist source folder prefix is disabled
|
||||
/// Subtitle when playlist folder is disabled
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Playlist downloads use the normal folder structure only.'**
|
||||
/// **'All tracks saved directly to download folder'**
|
||||
String get downloadCreatePlaylistSourceFolderDisabled;
|
||||
|
||||
/// Subtitle when playlist folder prefix setting is redundant because folder organization is already by playlist
|
||||
/// Subtitle when folder organization is already set to playlist
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'By Playlist already places downloads inside a playlist folder.'**
|
||||
/// **'Handled by folder organization setting'**
|
||||
String get downloadCreatePlaylistSourceFolderRedundant;
|
||||
|
||||
/// Setting title for SongLink country region
|
||||
/// Setting for SongLink region used during fallback resolution
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'SongLink Region'**
|
||||
String get downloadSongLinkRegion;
|
||||
|
||||
/// Setting title for network compatibility toggle
|
||||
/// Setting for legacy TLS/network handling
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Network compatibility mode'**
|
||||
/// **'Network Compatibility Mode'**
|
||||
String get downloadNetworkCompatibilityMode;
|
||||
|
||||
/// Subtitle when network compatibility mode is enabled
|
||||
/// Subtitle when network compatibility mode is on
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Enabled: try HTTP + accept invalid TLS certificates (unsafe)'**
|
||||
/// **'Using legacy TLS settings for older networks'**
|
||||
String get downloadNetworkCompatibilityModeEnabled;
|
||||
|
||||
/// Subtitle when network compatibility mode is disabled
|
||||
/// Subtitle when network compatibility mode is off
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Off: strict HTTPS certificate validation (recommended)'**
|
||||
/// **'Using standard network settings'**
|
||||
String get downloadNetworkCompatibilityModeDisabled;
|
||||
|
||||
/// Hint shown instead of Ask-quality subtitle when the selected provider does not expose built-in quality controls
|
||||
/// Subtitle when quality picker is disabled due to extension service
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Select a compatible download provider to enable quality options'**
|
||||
/// **'Select Tidal or Qobuz to enable this option'**
|
||||
String get downloadSelectServiceToEnable;
|
||||
|
||||
/// Info hint when the selected provider does not expose built-in quality controls
|
||||
/// Info shown when a non-built-in service is selected
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Select a compatible provider above to configure quality'**
|
||||
/// **'Select Tidal or Qobuz to choose audio quality'**
|
||||
String get downloadSelectTidalQobuz;
|
||||
|
||||
/// Subtitle for Embed Lyrics when Embed Metadata is disabled
|
||||
/// Subtitle when lyrics embedding is blocked by metadata toggle
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Disabled while Embed Metadata is turned off'**
|
||||
/// **'Enable metadata embedding first'**
|
||||
String get downloadEmbedLyricsDisabled;
|
||||
|
||||
/// Toggle title for including Netease translated lyrics
|
||||
/// Setting to include translated lyrics from Netease
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Netease: Include Translation'**
|
||||
String get downloadNeteaseIncludeTranslation;
|
||||
|
||||
/// Subtitle when Netease translation is enabled
|
||||
/// Subtitle when Netease translation is on
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Append translated lyrics when available'**
|
||||
/// **'Chinese translation lines included'**
|
||||
String get downloadNeteaseIncludeTranslationEnabled;
|
||||
|
||||
/// Subtitle when Netease translation is disabled
|
||||
/// Subtitle when Netease translation is off
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Use original lyrics only'**
|
||||
/// **'Original lyrics only'**
|
||||
String get downloadNeteaseIncludeTranslationDisabled;
|
||||
|
||||
/// Toggle title for including Netease romanized lyrics
|
||||
/// Setting to include romanized lyrics from Netease
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Netease: Include Romanization'**
|
||||
String get downloadNeteaseIncludeRomanization;
|
||||
|
||||
/// Subtitle when Netease romanization is enabled
|
||||
/// Subtitle when Netease romanization is on
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Append romanized lyrics when available'**
|
||||
/// **'Romanization lines included'**
|
||||
String get downloadNeteaseIncludeRomanizationEnabled;
|
||||
|
||||
/// Subtitle when Netease romanization is disabled
|
||||
/// Subtitle when Netease romanization is off
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Disabled'**
|
||||
/// **'No romanization'**
|
||||
String get downloadNeteaseIncludeRomanizationDisabled;
|
||||
|
||||
/// Toggle title for Apple/QQ multi-person word-by-word lyrics
|
||||
/// Setting for word-by-word multi-person lyrics from Apple Music and QQ Music
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Apple/QQ Multi-Person Word-by-Word'**
|
||||
/// **'Apple / QQ: Multi-Person Lyrics'**
|
||||
String get downloadAppleQqMultiPerson;
|
||||
|
||||
/// Subtitle when multi-person word-by-word is enabled
|
||||
/// Subtitle when multi-person lyrics is on
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Enable v1/v2 speaker and [bg:] tags'**
|
||||
/// **'Speaker labels included for duets and group tracks'**
|
||||
String get downloadAppleQqMultiPersonEnabled;
|
||||
|
||||
/// Subtitle when multi-person word-by-word is disabled
|
||||
/// Subtitle when multi-person lyrics is off
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Simplified word-by-word formatting'**
|
||||
/// **'Standard lyrics without speaker labels'**
|
||||
String get downloadAppleQqMultiPersonDisabled;
|
||||
|
||||
/// Setting title for Musixmatch language preference
|
||||
/// Setting for Musixmatch lyrics translation language
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Musixmatch Language'**
|
||||
String get downloadMusixmatchLanguage;
|
||||
|
||||
/// Option label when Musixmatch uses original language
|
||||
/// Subtitle when no language is set
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Auto (original)'**
|
||||
/// **'Auto (original language)'**
|
||||
String get downloadMusixmatchLanguageAuto;
|
||||
|
||||
/// Toggle title for filtering contributing artists in Album Artist metadata
|
||||
/// Setting to strip contributing artists from Album Artist folder name
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Filter contributing artists in Album Artist'**
|
||||
/// **'Filter Contributing Artists'**
|
||||
String get downloadFilterContributing;
|
||||
|
||||
/// Subtitle when contributing artist filter is enabled
|
||||
/// Subtitle when contributing artist filter is on
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Album Artist metadata uses primary artist only'**
|
||||
/// **'Contributing artists removed from Album Artist folder name'**
|
||||
String get downloadFilterContributingEnabled;
|
||||
|
||||
/// Subtitle when contributing artist filter is disabled
|
||||
/// Subtitle when contributing artist filter is off
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Keep full Album Artist metadata value'**
|
||||
/// **'Full Album Artist string used'**
|
||||
String get downloadFilterContributingDisabled;
|
||||
|
||||
/// Subtitle for lyrics providers setting when no providers are enabled
|
||||
/// Shown when no lyrics providers are active
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'None enabled'**
|
||||
/// **'No providers enabled'**
|
||||
String get downloadProvidersNoneEnabled;
|
||||
|
||||
/// Label for the Musixmatch language code text field
|
||||
/// Label for Musixmatch language input field
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Language code'**
|
||||
String get downloadMusixmatchLanguageCode;
|
||||
|
||||
/// Hint text for the Musixmatch language code field
|
||||
/// Placeholder for Musixmatch language input
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'auto / en / es / ja'**
|
||||
/// **'e.g. en, de, ja'**
|
||||
String get downloadMusixmatchLanguageHint;
|
||||
|
||||
/// Description in the Musixmatch language picker
|
||||
/// Description in Musixmatch language picker
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Set preferred language code (example: en, es, ja). Leave empty for auto.'**
|
||||
/// **'Enter a BCP-47 language code (e.g. en, de, ja) to request translated lyrics from Musixmatch.'**
|
||||
String get downloadMusixmatchLanguageDesc;
|
||||
|
||||
/// Button to reset Musixmatch language to automatic
|
||||
/// Button to clear Musixmatch language (use auto)
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Auto'**
|
||||
String get downloadMusixmatchAuto;
|
||||
|
||||
/// Subtitle for 'Any' network mode option
|
||||
/// Subtitle for any-network option in picker
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'WiFi + Mobile Data'**
|
||||
/// **'Use WiFi or mobile data'**
|
||||
String get downloadNetworkAnySubtitle;
|
||||
|
||||
/// Subtitle for 'WiFi only' network mode option
|
||||
/// Subtitle for WiFi-only option in picker
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Pause downloads on mobile data'**
|
||||
/// **'Downloads pause when on mobile data'**
|
||||
String get downloadNetworkWifiOnlySubtitle;
|
||||
|
||||
/// Description in the SongLink region picker
|
||||
/// Description in SongLink region picker
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Used as userCountry for SongLink API lookup.'**
|
||||
/// **'Region used when resolving track links via SongLink. Choose the country where your streaming services are available.'**
|
||||
String get downloadSongLinkRegionDesc;
|
||||
|
||||
/// Snackbar when the audio format is not supported for the requested operation
|
||||
@@ -5637,7 +5647,7 @@ abstract class AppLocalizations {
|
||||
/// **'Choose which extension provides the home feed on the main screen'**
|
||||
String get extensionsHomeFeedDescription;
|
||||
|
||||
/// Extensions page - home feed provider option: auto
|
||||
/// Label for auto-selected search provider
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Auto'**
|
||||
@@ -6280,6 +6290,126 @@ abstract class AppLocalizations {
|
||||
/// In en, this message translates to:
|
||||
/// **'Open album {albumName}'**
|
||||
String a11yOpenAlbum(String albumName);
|
||||
|
||||
/// Default search tab option - Albums tab
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Albums'**
|
||||
String get optionsDefaultSearchTabAlbums;
|
||||
|
||||
/// Default search tab option - Tracks tab
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Tracks'**
|
||||
String get optionsDefaultSearchTabTracks;
|
||||
|
||||
/// Settings menu item - file and folder settings
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Files & Folders'**
|
||||
String get settingsFiles;
|
||||
|
||||
/// Subtitle for files & folders settings
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Download location, filename, folder structure'**
|
||||
String get settingsFilesSubtitle;
|
||||
|
||||
/// Settings menu item - metadata settings
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Metadata'**
|
||||
String get settingsMetadata;
|
||||
|
||||
/// Subtitle for metadata settings
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Cover art, tags, ReplayGain, providers'**
|
||||
String get settingsMetadataSubtitle;
|
||||
|
||||
/// Settings menu item - lyrics settings
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Lyrics'**
|
||||
String get settingsLyrics;
|
||||
|
||||
/// Subtitle for lyrics settings
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Embed, mode, providers, language options'**
|
||||
String get settingsLyricsSubtitle;
|
||||
|
||||
/// Settings menu item - app settings
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'App'**
|
||||
String get settingsApp;
|
||||
|
||||
/// Subtitle for app settings
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Updates, data, extension repo, debug'**
|
||||
String get settingsAppSubtitle;
|
||||
|
||||
/// Settings section header for metadata providers
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Providers'**
|
||||
String get sectionMetadataProviders;
|
||||
|
||||
/// Settings section header for deduplication
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Duplicates'**
|
||||
String get sectionDuplicates;
|
||||
|
||||
/// Settings section header for per-provider lyrics options
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Provider Options'**
|
||||
String get sectionLyricsProviderOptions;
|
||||
|
||||
/// Settings item title for metadata provider order
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Metadata Provider Priority'**
|
||||
String get metadataProvidersTitle;
|
||||
|
||||
/// Subtitle for metadata provider priority item
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Drag to set search and metadata source order'**
|
||||
String get metadataProvidersSubtitle;
|
||||
|
||||
/// Setting - skip tracks already in download history
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Skip Duplicate Downloads'**
|
||||
String get downloadDeduplication;
|
||||
|
||||
/// Subtitle when deduplication is on
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Already-downloaded tracks will be skipped'**
|
||||
String get downloadDeduplicationEnabled;
|
||||
|
||||
/// Subtitle when deduplication is off
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'All tracks will be downloaded regardless of history'**
|
||||
String get downloadDeduplicationDisabled;
|
||||
|
||||
/// Settings item for configuring fallback extension providers
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Fallback Extensions'**
|
||||
String get downloadFallbackExtensions;
|
||||
|
||||
/// Subtitle for fallback extensions item
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Choose which extensions can be used as fallback'**
|
||||
String get downloadFallbackExtensionsSubtitle;
|
||||
}
|
||||
|
||||
class _AppLocalizationsDelegate
|
||||
@@ -6305,6 +6435,7 @@ class _AppLocalizationsDelegate
|
||||
'pt',
|
||||
'ru',
|
||||
'tr',
|
||||
'uk',
|
||||
'zh',
|
||||
].contains(locale.languageCode);
|
||||
|
||||
@@ -6369,6 +6500,8 @@ AppLocalizations lookupAppLocalizations(Locale locale) {
|
||||
return AppLocalizationsRu();
|
||||
case 'tr':
|
||||
return AppLocalizationsTr();
|
||||
case 'uk':
|
||||
return AppLocalizationsUk();
|
||||
case 'zh':
|
||||
return AppLocalizationsZh();
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get optionsPrimaryProviderSubtitle =>
|
||||
'Service used when searching by track name.';
|
||||
'Service used for searching by track or album name';
|
||||
|
||||
@override
|
||||
String optionsUsingExtension(String extensionName) {
|
||||
@@ -142,7 +142,7 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get optionsSwitchBack =>
|
||||
'Choose another provider below to stop using the current extension';
|
||||
'Tap Deezer or Spotify to switch back from extension';
|
||||
|
||||
@override
|
||||
String get optionsAutoFallback => 'Auto Fallback';
|
||||
@@ -158,14 +158,14 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
String get optionsUseExtensionProvidersOn => 'Extensions will be tried first';
|
||||
|
||||
@override
|
||||
String get optionsUseExtensionProvidersOff => 'Extensions are turned off';
|
||||
String get optionsUseExtensionProvidersOff => 'Using built-in providers only';
|
||||
|
||||
@override
|
||||
String get optionsEmbedLyrics => 'Embed Lyrics';
|
||||
|
||||
@override
|
||||
String get optionsEmbedLyricsSubtitle =>
|
||||
'Embed synced lyrics into FLAC files';
|
||||
'Save synced lyrics alongside your downloaded tracks';
|
||||
|
||||
@override
|
||||
String get optionsMaxQualityCover => 'Max Quality Cover';
|
||||
@@ -957,14 +957,14 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get providerPriorityFallbackExtensionsDescription =>
|
||||
'Choose which installed download extensions can be used during automatic fallback.';
|
||||
'Choose which installed download extensions can be used during automatic fallback. Built-in providers still follow the priority order above.';
|
||||
|
||||
@override
|
||||
String get providerPriorityFallbackExtensionsHint =>
|
||||
'Only enabled extensions with download-provider capability are listed here.';
|
||||
|
||||
@override
|
||||
String get providerBuiltIn => 'Legacy';
|
||||
String get providerBuiltIn => 'Built-in';
|
||||
|
||||
@override
|
||||
String get providerExtension => 'Extension';
|
||||
@@ -1132,10 +1132,10 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
String get settingsAppearanceSubtitle => 'Theme, colors, display';
|
||||
|
||||
@override
|
||||
String get settingsDownloadSubtitle => 'Service, quality, filename format';
|
||||
String get settingsDownloadSubtitle => 'Service, quality, fallback';
|
||||
|
||||
@override
|
||||
String get settingsOptionsSubtitle => 'Fallback, lyrics, cover art, updates';
|
||||
String get settingsOptionsSubtitle => 'Fallback, metadata, lyrics, cover art';
|
||||
|
||||
@override
|
||||
String get settingsExtensionsSubtitle => 'Manage download providers';
|
||||
@@ -2765,14 +2765,14 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get downloadUseAlbumArtistForFoldersAlbumSubtitle =>
|
||||
'Artist folders use Album Artist when available';
|
||||
'Folder named after Album Artist tag';
|
||||
|
||||
@override
|
||||
String get downloadUseAlbumArtistForFoldersTrackSubtitle =>
|
||||
'Artist folders use Track Artist only';
|
||||
'Folder named after Track Artist tag';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersTitle => 'Lyrics Providers';
|
||||
String get lyricsProvidersTitle => 'Lyrics Provider Priority';
|
||||
|
||||
@override
|
||||
String get lyricsProvidersDescription =>
|
||||
@@ -2840,10 +2840,10 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
String get safMigrationSuccess => 'Download folder updated to SAF mode';
|
||||
|
||||
@override
|
||||
String get settingsDonate => 'Donate';
|
||||
String get settingsDonate => 'Support Development';
|
||||
|
||||
@override
|
||||
String get settingsDonateSubtitle => 'Support SpotiFLAC-Mobile development';
|
||||
String get settingsDonateSubtitle => 'Buy the developer a coffee';
|
||||
|
||||
@override
|
||||
String get tooltipLoveAll => 'Love All';
|
||||
@@ -2903,78 +2903,87 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get downloadLocationSubtitle =>
|
||||
'Choose storage mode for downloaded files.';
|
||||
'Choose where to save your downloaded tracks';
|
||||
|
||||
@override
|
||||
String get storageModeAppFolder => 'App folder (non-SAF)';
|
||||
String get storageModeAppFolder => 'App Folder (Recommended)';
|
||||
|
||||
@override
|
||||
String get storageModeAppFolderSubtitle => 'Use default Music/SpotiFLAC path';
|
||||
String get storageModeAppFolderSubtitle =>
|
||||
'Saves to Music/SpotiFLAC by default';
|
||||
|
||||
@override
|
||||
String get storageModeSaf => 'SAF folder';
|
||||
String get storageModeSaf => 'Custom Folder (SAF)';
|
||||
|
||||
@override
|
||||
String get storageModeSafSubtitle =>
|
||||
'Pick folder via Android Storage Access Framework';
|
||||
String get storageModeSafSubtitle => 'Pick any folder, including SD card';
|
||||
|
||||
@override
|
||||
String get downloadFilenameDescription =>
|
||||
'Customize how your files are named.';
|
||||
String downloadFilenameDescription(
|
||||
Object album,
|
||||
Object artist,
|
||||
Object date,
|
||||
Object disc,
|
||||
Object title,
|
||||
Object track,
|
||||
Object year,
|
||||
) {
|
||||
return 'Use $artist, $title, $album, $track, $year, $date, $disc as placeholders.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get downloadFilenameInsertTag => 'Tap to insert tag:';
|
||||
|
||||
@override
|
||||
String get downloadSeparateSinglesEnabled => 'Albums/ and Singles/ folders';
|
||||
String get downloadSeparateSinglesEnabled =>
|
||||
'Singles and EPs saved in a separate folder';
|
||||
|
||||
@override
|
||||
String get downloadSeparateSinglesDisabled => 'All files in same structure';
|
||||
String get downloadSeparateSinglesDisabled =>
|
||||
'Singles and albums saved in the same folder';
|
||||
|
||||
@override
|
||||
String get downloadArtistNameFilters => 'Artist Name Filters';
|
||||
|
||||
@override
|
||||
String get downloadCreatePlaylistSourceFolder =>
|
||||
'Create playlist source folder';
|
||||
String get downloadCreatePlaylistSourceFolder => 'Playlist Source Folder';
|
||||
|
||||
@override
|
||||
String get downloadCreatePlaylistSourceFolderEnabled =>
|
||||
'Playlist downloads use Playlist/ plus your normal folder structure.';
|
||||
'A subfolder is created for each playlist';
|
||||
|
||||
@override
|
||||
String get downloadCreatePlaylistSourceFolderDisabled =>
|
||||
'Playlist downloads use the normal folder structure only.';
|
||||
'All tracks saved directly to download folder';
|
||||
|
||||
@override
|
||||
String get downloadCreatePlaylistSourceFolderRedundant =>
|
||||
'By Playlist already places downloads inside a playlist folder.';
|
||||
'Handled by folder organization setting';
|
||||
|
||||
@override
|
||||
String get downloadSongLinkRegion => 'SongLink Region';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityMode => 'Network compatibility mode';
|
||||
String get downloadNetworkCompatibilityMode => 'Network Compatibility Mode';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityModeEnabled =>
|
||||
'Enabled: try HTTP + accept invalid TLS certificates (unsafe)';
|
||||
'Using legacy TLS settings for older networks';
|
||||
|
||||
@override
|
||||
String get downloadNetworkCompatibilityModeDisabled =>
|
||||
'Off: strict HTTPS certificate validation (recommended)';
|
||||
'Using standard network settings';
|
||||
|
||||
@override
|
||||
String get downloadSelectServiceToEnable =>
|
||||
'Select a compatible download provider to enable quality options';
|
||||
'Select Tidal or Qobuz to enable this option';
|
||||
|
||||
@override
|
||||
String get downloadSelectTidalQobuz =>
|
||||
'Select a compatible provider above to configure quality';
|
||||
'Select Tidal or Qobuz to choose audio quality';
|
||||
|
||||
@override
|
||||
String get downloadEmbedLyricsDisabled =>
|
||||
'Disabled while Embed Metadata is turned off';
|
||||
String get downloadEmbedLyricsDisabled => 'Enable metadata embedding first';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslation =>
|
||||
@@ -2982,11 +2991,11 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslationEnabled =>
|
||||
'Append translated lyrics when available';
|
||||
'Chinese translation lines included';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeTranslationDisabled =>
|
||||
'Use original lyrics only';
|
||||
'Original lyrics only';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanization =>
|
||||
@@ -2994,66 +3003,65 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanizationEnabled =>
|
||||
'Append romanized lyrics when available';
|
||||
'Romanization lines included';
|
||||
|
||||
@override
|
||||
String get downloadNeteaseIncludeRomanizationDisabled => 'Disabled';
|
||||
String get downloadNeteaseIncludeRomanizationDisabled => 'No romanization';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPerson => 'Apple/QQ Multi-Person Word-by-Word';
|
||||
String get downloadAppleQqMultiPerson => 'Apple / QQ: Multi-Person Lyrics';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPersonEnabled =>
|
||||
'Enable v1/v2 speaker and [bg:] tags';
|
||||
'Speaker labels included for duets and group tracks';
|
||||
|
||||
@override
|
||||
String get downloadAppleQqMultiPersonDisabled =>
|
||||
'Simplified word-by-word formatting';
|
||||
'Standard lyrics without speaker labels';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguage => 'Musixmatch Language';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageAuto => 'Auto (original)';
|
||||
String get downloadMusixmatchLanguageAuto => 'Auto (original language)';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributing =>
|
||||
'Filter contributing artists in Album Artist';
|
||||
String get downloadFilterContributing => 'Filter Contributing Artists';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributingEnabled =>
|
||||
'Album Artist metadata uses primary artist only';
|
||||
'Contributing artists removed from Album Artist folder name';
|
||||
|
||||
@override
|
||||
String get downloadFilterContributingDisabled =>
|
||||
'Keep full Album Artist metadata value';
|
||||
'Full Album Artist string used';
|
||||
|
||||
@override
|
||||
String get downloadProvidersNoneEnabled => 'None enabled';
|
||||
String get downloadProvidersNoneEnabled => 'No providers enabled';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageCode => 'Language code';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageHint => 'auto / en / es / ja';
|
||||
String get downloadMusixmatchLanguageHint => 'e.g. en, de, ja';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchLanguageDesc =>
|
||||
'Set preferred language code (example: en, es, ja). Leave empty for auto.';
|
||||
'Enter a BCP-47 language code (e.g. en, de, ja) to request translated lyrics from Musixmatch.';
|
||||
|
||||
@override
|
||||
String get downloadMusixmatchAuto => 'Auto';
|
||||
|
||||
@override
|
||||
String get downloadNetworkAnySubtitle => 'WiFi + Mobile Data';
|
||||
String get downloadNetworkAnySubtitle => 'Use WiFi or mobile data';
|
||||
|
||||
@override
|
||||
String get downloadNetworkWifiOnlySubtitle =>
|
||||
'Pause downloads on mobile data';
|
||||
'Downloads pause when on mobile data';
|
||||
|
||||
@override
|
||||
String get downloadSongLinkRegionDesc =>
|
||||
'Used as userCountry for SongLink API lookup.';
|
||||
'Region used when resolving track links via SongLink. Choose the country where your streaming services are available.';
|
||||
|
||||
@override
|
||||
String get snackbarUnsupportedAudioFormat => 'Unsupported audio format';
|
||||
@@ -3696,4 +3704,71 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
String a11yOpenAlbum(String albumName) {
|
||||
return 'Open album $albumName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get optionsDefaultSearchTabAlbums => 'Albums';
|
||||
|
||||
@override
|
||||
String get optionsDefaultSearchTabTracks => 'Tracks';
|
||||
|
||||
@override
|
||||
String get settingsFiles => 'Files & Folders';
|
||||
|
||||
@override
|
||||
String get settingsFilesSubtitle =>
|
||||
'Download location, filename, folder structure';
|
||||
|
||||
@override
|
||||
String get settingsMetadata => 'Metadata';
|
||||
|
||||
@override
|
||||
String get settingsMetadataSubtitle =>
|
||||
'Cover art, tags, ReplayGain, providers';
|
||||
|
||||
@override
|
||||
String get settingsLyrics => 'Lyrics';
|
||||
|
||||
@override
|
||||
String get settingsLyricsSubtitle =>
|
||||
'Embed, mode, providers, language options';
|
||||
|
||||
@override
|
||||
String get settingsApp => 'App';
|
||||
|
||||
@override
|
||||
String get settingsAppSubtitle => 'Updates, data, extension repo, debug';
|
||||
|
||||
@override
|
||||
String get sectionMetadataProviders => 'Providers';
|
||||
|
||||
@override
|
||||
String get sectionDuplicates => 'Duplicates';
|
||||
|
||||
@override
|
||||
String get sectionLyricsProviderOptions => 'Provider Options';
|
||||
|
||||
@override
|
||||
String get metadataProvidersTitle => 'Metadata Provider Priority';
|
||||
|
||||
@override
|
||||
String get metadataProvidersSubtitle =>
|
||||
'Drag to set search and metadata source order';
|
||||
|
||||
@override
|
||||
String get downloadDeduplication => 'Skip Duplicate Downloads';
|
||||
|
||||
@override
|
||||
String get downloadDeduplicationEnabled =>
|
||||
'Already-downloaded tracks will be skipped';
|
||||
|
||||
@override
|
||||
String get downloadDeduplicationDisabled =>
|
||||
'All tracks will be downloaded regardless of history';
|
||||
|
||||
@override
|
||||
String get downloadFallbackExtensions => 'Fallback Extensions';
|
||||
|
||||
@override
|
||||
String get downloadFallbackExtensionsSubtitle =>
|
||||
'Choose which extensions can be used as fallback';
|
||||
}
|
||||
|
||||
@@ -21,13 +21,13 @@ class AppLocalizationsFr extends AppLocalizations {
|
||||
String get navSettings => 'Paramètres';
|
||||
|
||||
@override
|
||||
String get navStore => 'Magasin';
|
||||
String get navStore => 'Repo';
|
||||
|
||||
@override
|
||||
String get homeTitle => 'Accueil';
|
||||
|
||||
@override
|
||||
String get homeSubtitle => 'Coller un lien Spotify ou rechercher par nom';
|
||||
String get homeSubtitle => 'Paste a supported URL or search by name';
|
||||
|
||||
@override
|
||||
String get homeEmptyTitle => 'No search providers yet';
|
||||
@@ -224,10 +224,10 @@ class AppLocalizationsFr extends AppLocalizations {
|
||||
'Parallel downloads may trigger rate limiting';
|
||||
|
||||
@override
|
||||
String get optionsExtensionStore => 'Extension Store';
|
||||
String get optionsExtensionStore => 'Extension Repo';
|
||||
|
||||
@override
|
||||
String get optionsExtensionStoreSubtitle => 'Show Store tab in navigation';
|
||||
String get optionsExtensionStoreSubtitle => 'Show Repo tab in navigation';
|
||||
|
||||
@override
|
||||
String get optionsCheckUpdates => 'Check for Updates';
|
||||
@@ -288,7 +288,7 @@ class AppLocalizationsFr extends AppLocalizations {
|
||||
String get extensionsTitle => 'Extensions';
|
||||
|
||||
@override
|
||||
String get extensionsDisabled => 'Disabled';
|
||||
String get extensionsDisabled => 'Désactivée';
|
||||
|
||||
@override
|
||||
String extensionsVersion(String version) {
|
||||
@@ -297,38 +297,38 @@ class AppLocalizationsFr extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String extensionsAuthor(String author) {
|
||||
return 'by $author';
|
||||
return 'par $author';
|
||||
}
|
||||
|
||||
@override
|
||||
String get extensionsUninstall => 'Désinstaller';
|
||||
|
||||
@override
|
||||
String get storeTitle => 'Magasin d\'extension';
|
||||
String get storeTitle => 'Extension Repo';
|
||||
|
||||
@override
|
||||
String get storeSearch => 'Recherche d\'extensions...';
|
||||
|
||||
@override
|
||||
String get storeInstall => 'Install';
|
||||
String get storeInstall => 'Installer';
|
||||
|
||||
@override
|
||||
String get storeInstalled => 'Installed';
|
||||
String get storeInstalled => 'Installé';
|
||||
|
||||
@override
|
||||
String get storeUpdate => 'Update';
|
||||
String get storeUpdate => 'Mettre à jour';
|
||||
|
||||
@override
|
||||
String get aboutTitle => 'About';
|
||||
String get aboutTitle => 'À propos de';
|
||||
|
||||
@override
|
||||
String get aboutContributors => 'Contributors';
|
||||
String get aboutContributors => 'Contributeurs';
|
||||
|
||||
@override
|
||||
String get aboutMobileDeveloper => 'Mobile version developer';
|
||||
String get aboutMobileDeveloper => 'Développeur de la version mobile';
|
||||
|
||||
@override
|
||||
String get aboutOriginalCreator => 'Creator of the original SpotiFLAC';
|
||||
String get aboutOriginalCreator => 'Créateur de SpotiFLAC original';
|
||||
|
||||
@override
|
||||
String get aboutLogoArtist =>
|
||||
@@ -368,7 +368,7 @@ class AppLocalizationsFr extends AppLocalizations {
|
||||
String get aboutTelegramChannel => 'Telegram Channel';
|
||||
|
||||
@override
|
||||
String get aboutTelegramChannelSubtitle => 'Announcements and updates';
|
||||
String get aboutTelegramChannelSubtitle => 'Annonces et mises à jour';
|
||||
|
||||
@override
|
||||
String get aboutTelegramChat => 'Telegram Community';
|
||||
@@ -526,10 +526,11 @@ class AppLocalizationsFr extends AppLocalizations {
|
||||
'SpotiFLAC needs storage permission to save your downloaded music files.';
|
||||
|
||||
@override
|
||||
String get setupNotificationGranted => 'Notification Permission Granted!';
|
||||
String get setupNotificationGranted =>
|
||||
'Autorisation de notifications accordée!';
|
||||
|
||||
@override
|
||||
String get setupNotificationEnable => 'Enable Notifications';
|
||||
String get setupNotificationEnable => 'Activer les notifications';
|
||||
|
||||
@override
|
||||
String get setupFolderChoose => 'Choisissez le dossier pour télécharger';
|
||||
@@ -539,27 +540,27 @@ class AppLocalizationsFr extends AppLocalizations {
|
||||
'Sélectionnez un dossier dans lequel votre musique téléchargée sera enregistrée.';
|
||||
|
||||
@override
|
||||
String get setupSelectFolder => 'Select Folder';
|
||||
String get setupSelectFolder => 'Sélectionner un dossier';
|
||||
|
||||
@override
|
||||
String get setupEnableNotifications => 'Enable Notifications';
|
||||
String get setupEnableNotifications => 'Activer les notifications';
|
||||
|
||||
@override
|
||||
String get setupNotificationBackgroundDescription =>
|
||||
'Get notified about download progress and completion. This helps you track downloads when the app is in background.';
|
||||
|
||||
@override
|
||||
String get setupSkipForNow => 'Skip for now';
|
||||
String get setupSkipForNow => 'Ignorer pour le moment';
|
||||
|
||||
@override
|
||||
String get setupNext => 'Next';
|
||||
String get setupNext => 'Suivant';
|
||||
|
||||
@override
|
||||
String get setupGetStarted => 'Get Started';
|
||||
String get setupGetStarted => 'Démarrer';
|
||||
|
||||
@override
|
||||
String get setupAllowAccessToManageFiles =>
|
||||
'Please enable \"Allow access to manage all files\" in the next screen.';
|
||||
'Veuillez activer \"Autoriser l\'accès à tous les fichiers\" sur l\'écran suivant.';
|
||||
|
||||
@override
|
||||
String get setupLanguageTitle => 'Choose Language';
|
||||
@@ -572,16 +573,16 @@ class AppLocalizationsFr extends AppLocalizations {
|
||||
String get setupLanguageSystemDefault => 'System Default';
|
||||
|
||||
@override
|
||||
String get dialogCancel => 'Cancel';
|
||||
String get dialogCancel => 'Annuler';
|
||||
|
||||
@override
|
||||
String get dialogSave => 'Save';
|
||||
String get dialogSave => 'Sauvegarder';
|
||||
|
||||
@override
|
||||
String get dialogDelete => 'Delete';
|
||||
String get dialogDelete => 'Supprimer';
|
||||
|
||||
@override
|
||||
String get dialogRetry => 'Retry';
|
||||
String get dialogRetry => 'Réessayer';
|
||||
|
||||
@override
|
||||
String get dialogClear => 'Clear';
|
||||
@@ -593,7 +594,7 @@ class AppLocalizationsFr extends AppLocalizations {
|
||||
String get dialogImport => 'Import';
|
||||
|
||||
@override
|
||||
String get dialogDownload => 'Download';
|
||||
String get dialogDownload => 'Télécharger';
|
||||
|
||||
@override
|
||||
String get dialogDiscard => 'Discard';
|
||||
@@ -602,10 +603,10 @@ class AppLocalizationsFr extends AppLocalizations {
|
||||
String get dialogRemove => 'Remove';
|
||||
|
||||
@override
|
||||
String get dialogUninstall => 'Uninstall';
|
||||
String get dialogUninstall => 'Désinstaller';
|
||||
|
||||
@override
|
||||
String get dialogDiscardChanges => 'Discard Changes?';
|
||||
String get dialogDiscardChanges => 'Ignorer les modifications ?';
|
||||
|
||||
@override
|
||||
String get dialogUnsavedChanges =>
|
||||
@@ -959,7 +960,7 @@ class AppLocalizationsFr extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get providerPriorityFallbackExtensionsDescription =>
|
||||
'Choose which installed download extensions can be used during automatic fallback.';
|
||||
'Choose which installed download extensions can be used during automatic fallback. Built-in providers still follow the priority order above.';
|
||||
|
||||
@override
|
||||
String get providerPriorityFallbackExtensionsHint =>
|
||||
@@ -1354,7 +1355,7 @@ class AppLocalizationsFr extends AppLocalizations {
|
||||
String get storeEmptyNoResults => 'No extensions found';
|
||||
|
||||
@override
|
||||
String get extensionDefaultProvider => 'Default (Deezer/Spotify)';
|
||||
String get extensionDefaultProvider => 'Default (Deezer)';
|
||||
|
||||
@override
|
||||
String get extensionDefaultProviderSubtitle => 'Use built-in search';
|
||||
@@ -2132,7 +2133,7 @@ class AppLocalizationsFr extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get tutorialExtensionsTip1 =>
|
||||
'Browse the Store tab to discover useful extensions';
|
||||
'Browse the Repo tab to discover useful extensions';
|
||||
|
||||
@override
|
||||
String get tutorialExtensionsTip2 =>
|
||||
@@ -2413,7 +2414,8 @@ class AppLocalizationsFr extends AppLocalizations {
|
||||
String get trackConvertFormat => 'Convert Format';
|
||||
|
||||
@override
|
||||
String get trackConvertFormatSubtitle => 'Convert to MP3 or Opus';
|
||||
String get trackConvertFormatSubtitle =>
|
||||
'Convert to MP3, Opus, ALAC, or FLAC';
|
||||
|
||||
@override
|
||||
String get trackConvertTitle => 'Convert Audio';
|
||||
@@ -2920,8 +2922,17 @@ class AppLocalizationsFr extends AppLocalizations {
|
||||
'Pick folder via Android Storage Access Framework';
|
||||
|
||||
@override
|
||||
String get downloadFilenameDescription =>
|
||||
'Customize how your files are named.';
|
||||
String downloadFilenameDescription(
|
||||
Object album,
|
||||
Object artist,
|
||||
Object date,
|
||||
Object disc,
|
||||
Object title,
|
||||
Object track,
|
||||
Object year,
|
||||
) {
|
||||
return 'Customize how your files are named.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get downloadFilenameInsertTag => 'Tap to insert tag:';
|
||||
@@ -2967,11 +2978,11 @@ class AppLocalizationsFr extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get downloadSelectServiceToEnable =>
|
||||
'Select a compatible download provider to enable quality options';
|
||||
'Select a built-in service to enable';
|
||||
|
||||
@override
|
||||
String get downloadSelectTidalQobuz =>
|
||||
'Select a compatible provider above to configure quality';
|
||||
'Select Tidal or Qobuz above to configure quality';
|
||||
|
||||
@override
|
||||
String get downloadEmbedLyricsDisabled =>
|
||||
@@ -3697,4 +3708,71 @@ class AppLocalizationsFr extends AppLocalizations {
|
||||
String a11yOpenAlbum(String albumName) {
|
||||
return 'Open album $albumName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get optionsDefaultSearchTabAlbums => 'Albums';
|
||||
|
||||
@override
|
||||
String get optionsDefaultSearchTabTracks => 'Tracks';
|
||||
|
||||
@override
|
||||
String get settingsFiles => 'Files & Folders';
|
||||
|
||||
@override
|
||||
String get settingsFilesSubtitle =>
|
||||
'Download location, filename, folder structure';
|
||||
|
||||
@override
|
||||
String get settingsMetadata => 'Metadata';
|
||||
|
||||
@override
|
||||
String get settingsMetadataSubtitle =>
|
||||
'Cover art, tags, ReplayGain, providers';
|
||||
|
||||
@override
|
||||
String get settingsLyrics => 'Lyrics';
|
||||
|
||||
@override
|
||||
String get settingsLyricsSubtitle =>
|
||||
'Embed, mode, providers, language options';
|
||||
|
||||
@override
|
||||
String get settingsApp => 'App';
|
||||
|
||||
@override
|
||||
String get settingsAppSubtitle => 'Updates, data, extension repo, debug';
|
||||
|
||||
@override
|
||||
String get sectionMetadataProviders => 'Providers';
|
||||
|
||||
@override
|
||||
String get sectionDuplicates => 'Duplicates';
|
||||
|
||||
@override
|
||||
String get sectionLyricsProviderOptions => 'Provider Options';
|
||||
|
||||
@override
|
||||
String get metadataProvidersTitle => 'Metadata Provider Priority';
|
||||
|
||||
@override
|
||||
String get metadataProvidersSubtitle =>
|
||||
'Drag to set search and metadata source order';
|
||||
|
||||
@override
|
||||
String get downloadDeduplication => 'Skip Duplicate Downloads';
|
||||
|
||||
@override
|
||||
String get downloadDeduplicationEnabled =>
|
||||
'Already-downloaded tracks will be skipped';
|
||||
|
||||
@override
|
||||
String get downloadDeduplicationDisabled =>
|
||||
'All tracks will be downloaded regardless of history';
|
||||
|
||||
@override
|
||||
String get downloadFallbackExtensions => 'Fallback Extensions';
|
||||
|
||||
@override
|
||||
String get downloadFallbackExtensionsSubtitle =>
|
||||
'Choose which extensions can be used as fallback';
|
||||
}
|
||||
|
||||
@@ -21,13 +21,13 @@ class AppLocalizationsHi extends AppLocalizations {
|
||||
String get navSettings => 'विकल्प';
|
||||
|
||||
@override
|
||||
String get navStore => 'Store';
|
||||
String get navStore => 'Repo';
|
||||
|
||||
@override
|
||||
String get homeTitle => 'Home';
|
||||
|
||||
@override
|
||||
String get homeSubtitle => 'Paste a Spotify link or search by name';
|
||||
String get homeSubtitle => 'Paste a supported URL or search by name';
|
||||
|
||||
@override
|
||||
String get homeEmptyTitle => 'No search providers yet';
|
||||
@@ -222,10 +222,10 @@ class AppLocalizationsHi extends AppLocalizations {
|
||||
'Parallel downloads may trigger rate limiting';
|
||||
|
||||
@override
|
||||
String get optionsExtensionStore => 'Extension Store';
|
||||
String get optionsExtensionStore => 'Extension Repo';
|
||||
|
||||
@override
|
||||
String get optionsExtensionStoreSubtitle => 'Show Store tab in navigation';
|
||||
String get optionsExtensionStoreSubtitle => 'Show Repo tab in navigation';
|
||||
|
||||
@override
|
||||
String get optionsCheckUpdates => 'Check for Updates';
|
||||
@@ -302,7 +302,7 @@ class AppLocalizationsHi extends AppLocalizations {
|
||||
String get extensionsUninstall => 'Uninstall';
|
||||
|
||||
@override
|
||||
String get storeTitle => 'Extension Store';
|
||||
String get storeTitle => 'Extension Repo';
|
||||
|
||||
@override
|
||||
String get storeSearch => 'Search extensions...';
|
||||
@@ -957,7 +957,7 @@ class AppLocalizationsHi extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get providerPriorityFallbackExtensionsDescription =>
|
||||
'Choose which installed download extensions can be used during automatic fallback.';
|
||||
'Choose which installed download extensions can be used during automatic fallback. Built-in providers still follow the priority order above.';
|
||||
|
||||
@override
|
||||
String get providerPriorityFallbackExtensionsHint =>
|
||||
@@ -1352,7 +1352,7 @@ class AppLocalizationsHi extends AppLocalizations {
|
||||
String get storeEmptyNoResults => 'No extensions found';
|
||||
|
||||
@override
|
||||
String get extensionDefaultProvider => 'Default (Deezer/Spotify)';
|
||||
String get extensionDefaultProvider => 'Default (Deezer)';
|
||||
|
||||
@override
|
||||
String get extensionDefaultProviderSubtitle => 'Use built-in search';
|
||||
@@ -2130,7 +2130,7 @@ class AppLocalizationsHi extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get tutorialExtensionsTip1 =>
|
||||
'Browse the Store tab to discover useful extensions';
|
||||
'Browse the Repo tab to discover useful extensions';
|
||||
|
||||
@override
|
||||
String get tutorialExtensionsTip2 =>
|
||||
@@ -2411,7 +2411,8 @@ class AppLocalizationsHi extends AppLocalizations {
|
||||
String get trackConvertFormat => 'Convert Format';
|
||||
|
||||
@override
|
||||
String get trackConvertFormatSubtitle => 'Convert to MP3 or Opus';
|
||||
String get trackConvertFormatSubtitle =>
|
||||
'Convert to MP3, Opus, ALAC, or FLAC';
|
||||
|
||||
@override
|
||||
String get trackConvertTitle => 'Convert Audio';
|
||||
@@ -2918,8 +2919,17 @@ class AppLocalizationsHi extends AppLocalizations {
|
||||
'Pick folder via Android Storage Access Framework';
|
||||
|
||||
@override
|
||||
String get downloadFilenameDescription =>
|
||||
'Customize how your files are named.';
|
||||
String downloadFilenameDescription(
|
||||
Object album,
|
||||
Object artist,
|
||||
Object date,
|
||||
Object disc,
|
||||
Object title,
|
||||
Object track,
|
||||
Object year,
|
||||
) {
|
||||
return 'Customize how your files are named.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get downloadFilenameInsertTag => 'Tap to insert tag:';
|
||||
@@ -2965,11 +2975,11 @@ class AppLocalizationsHi extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get downloadSelectServiceToEnable =>
|
||||
'Select a compatible download provider to enable quality options';
|
||||
'Select a built-in service to enable';
|
||||
|
||||
@override
|
||||
String get downloadSelectTidalQobuz =>
|
||||
'Select a compatible provider above to configure quality';
|
||||
'Select Tidal or Qobuz above to configure quality';
|
||||
|
||||
@override
|
||||
String get downloadEmbedLyricsDisabled =>
|
||||
@@ -3695,4 +3705,71 @@ class AppLocalizationsHi extends AppLocalizations {
|
||||
String a11yOpenAlbum(String albumName) {
|
||||
return 'Open album $albumName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get optionsDefaultSearchTabAlbums => 'Albums';
|
||||
|
||||
@override
|
||||
String get optionsDefaultSearchTabTracks => 'Tracks';
|
||||
|
||||
@override
|
||||
String get settingsFiles => 'Files & Folders';
|
||||
|
||||
@override
|
||||
String get settingsFilesSubtitle =>
|
||||
'Download location, filename, folder structure';
|
||||
|
||||
@override
|
||||
String get settingsMetadata => 'Metadata';
|
||||
|
||||
@override
|
||||
String get settingsMetadataSubtitle =>
|
||||
'Cover art, tags, ReplayGain, providers';
|
||||
|
||||
@override
|
||||
String get settingsLyrics => 'Lyrics';
|
||||
|
||||
@override
|
||||
String get settingsLyricsSubtitle =>
|
||||
'Embed, mode, providers, language options';
|
||||
|
||||
@override
|
||||
String get settingsApp => 'App';
|
||||
|
||||
@override
|
||||
String get settingsAppSubtitle => 'Updates, data, extension repo, debug';
|
||||
|
||||
@override
|
||||
String get sectionMetadataProviders => 'Providers';
|
||||
|
||||
@override
|
||||
String get sectionDuplicates => 'Duplicates';
|
||||
|
||||
@override
|
||||
String get sectionLyricsProviderOptions => 'Provider Options';
|
||||
|
||||
@override
|
||||
String get metadataProvidersTitle => 'Metadata Provider Priority';
|
||||
|
||||
@override
|
||||
String get metadataProvidersSubtitle =>
|
||||
'Drag to set search and metadata source order';
|
||||
|
||||
@override
|
||||
String get downloadDeduplication => 'Skip Duplicate Downloads';
|
||||
|
||||
@override
|
||||
String get downloadDeduplicationEnabled =>
|
||||
'Already-downloaded tracks will be skipped';
|
||||
|
||||
@override
|
||||
String get downloadDeduplicationDisabled =>
|
||||
'All tracks will be downloaded regardless of history';
|
||||
|
||||
@override
|
||||
String get downloadFallbackExtensions => 'Fallback Extensions';
|
||||
|
||||
@override
|
||||
String get downloadFallbackExtensionsSubtitle =>
|
||||
'Choose which extensions can be used as fallback';
|
||||
}
|
||||
|
||||
@@ -27,8 +27,7 @@ class AppLocalizationsId extends AppLocalizations {
|
||||
String get homeTitle => 'Beranda';
|
||||
|
||||
@override
|
||||
String get homeSubtitle =>
|
||||
'Tempel URL yang didukung atau cari berdasarkan nama';
|
||||
String get homeSubtitle => 'Paste a supported URL or search by name';
|
||||
|
||||
@override
|
||||
String get homeEmptyTitle => 'Belum ada provider pencarian';
|
||||
@@ -136,15 +135,15 @@ class AppLocalizationsId extends AppLocalizations {
|
||||
}
|
||||
|
||||
@override
|
||||
String get optionsDefaultSearchTab => 'Tab Pencarian Default';
|
||||
String get optionsDefaultSearchTab => 'Default Search Tab';
|
||||
|
||||
@override
|
||||
String get optionsDefaultSearchTabSubtitle =>
|
||||
'Pilih tab yang dibuka lebih dulu untuk hasil pencarian baru.';
|
||||
'Choose which tab opens first for new search results.';
|
||||
|
||||
@override
|
||||
String get optionsSwitchBack =>
|
||||
'Pilih provider lain di bawah untuk berhenti memakai ekstensi saat ini';
|
||||
'Ketuk Deezer atau Spotify untuk beralih dari ekstensi';
|
||||
|
||||
@override
|
||||
String get optionsAutoFallback => 'Cadangan Otomatis';
|
||||
@@ -161,7 +160,8 @@ class AppLocalizationsId extends AppLocalizations {
|
||||
'Ekstensi akan dicoba terlebih dahulu';
|
||||
|
||||
@override
|
||||
String get optionsUseExtensionProvidersOff => 'Ekstensi dimatikan';
|
||||
String get optionsUseExtensionProvidersOff =>
|
||||
'Hanya menggunakan provider bawaan';
|
||||
|
||||
@override
|
||||
String get optionsEmbedLyrics => 'Sematkan Lirik';
|
||||
@@ -225,10 +225,10 @@ class AppLocalizationsId extends AppLocalizations {
|
||||
'Unduhan paralel dapat memicu pembatasan rate';
|
||||
|
||||
@override
|
||||
String get optionsExtensionStore => 'Repo Ekstensi';
|
||||
String get optionsExtensionStore => 'Extension Repo';
|
||||
|
||||
@override
|
||||
String get optionsExtensionStoreSubtitle => 'Tampilkan tab Repo di navigasi';
|
||||
String get optionsExtensionStoreSubtitle => 'Show Repo tab in navigation';
|
||||
|
||||
@override
|
||||
String get optionsCheckUpdates => 'Periksa Pembaruan';
|
||||
@@ -304,7 +304,7 @@ class AppLocalizationsId extends AppLocalizations {
|
||||
String get extensionsUninstall => 'Copot';
|
||||
|
||||
@override
|
||||
String get storeTitle => 'Repo Ekstensi';
|
||||
String get storeTitle => 'Extension Repo';
|
||||
|
||||
@override
|
||||
String get storeSearch => 'Cari ekstensi...';
|
||||
@@ -760,15 +760,15 @@ class AppLocalizationsId extends AppLocalizations {
|
||||
String get errorNoTracksFound => 'Tidak ada lagu ditemukan';
|
||||
|
||||
@override
|
||||
String get errorUrlNotRecognized => 'Link tidak dikenali';
|
||||
String get errorUrlNotRecognized => 'Tautan tidak dikenali';
|
||||
|
||||
@override
|
||||
String get errorUrlNotRecognizedMessage =>
|
||||
'Link ini tidak didukung. Pastikan URL benar dan ekstensi yang kompatibel sudah terpasang.';
|
||||
'Tautan ini tidak didukung. Pastikan URL sudah benar dan ekstensi yang kompatibel telah terpasang.';
|
||||
|
||||
@override
|
||||
String get errorUrlFetchFailed =>
|
||||
'Gagal memuat konten dari link ini. Silakan coba lagi.';
|
||||
'Konten dari tautan ini gagal dimuat. Silakan coba lagi.';
|
||||
|
||||
@override
|
||||
String errorMissingExtensionSource(String item) {
|
||||
@@ -956,18 +956,18 @@ class AppLocalizationsId extends AppLocalizations {
|
||||
'Jika lagu tidak tersedia di provider pertama, aplikasi akan otomatis mencoba yang berikutnya.';
|
||||
|
||||
@override
|
||||
String get providerPriorityFallbackExtensionsTitle => 'Fallback Ekstensi';
|
||||
String get providerPriorityFallbackExtensionsTitle => 'Extension Fallback';
|
||||
|
||||
@override
|
||||
String get providerPriorityFallbackExtensionsDescription =>
|
||||
'Pilih ekstensi unduhan terpasang mana yang boleh dipakai saat fallback otomatis.';
|
||||
'Choose which installed download extensions can be used during automatic fallback. Built-in providers still follow the priority order above.';
|
||||
|
||||
@override
|
||||
String get providerPriorityFallbackExtensionsHint =>
|
||||
'Hanya ekstensi aktif dengan kemampuan download provider yang ditampilkan di sini.';
|
||||
'Only enabled extensions with download-provider capability are listed here.';
|
||||
|
||||
@override
|
||||
String get providerBuiltIn => 'Legacy';
|
||||
String get providerBuiltIn => 'Bawaan';
|
||||
|
||||
@override
|
||||
String get providerExtension => 'Ekstensi';
|
||||
@@ -1349,7 +1349,7 @@ class AppLocalizationsId extends AppLocalizations {
|
||||
String get storeNewRepoUrlLabel => 'New Repository URL';
|
||||
|
||||
@override
|
||||
String get storeLoadError => 'Gagal memuat repo';
|
||||
String get storeLoadError => 'Failed to load repository';
|
||||
|
||||
@override
|
||||
String get storeEmptyNoExtensions => 'No extensions available';
|
||||
@@ -1358,7 +1358,7 @@ class AppLocalizationsId extends AppLocalizations {
|
||||
String get storeEmptyNoResults => 'No extensions found';
|
||||
|
||||
@override
|
||||
String get extensionDefaultProvider => 'Bawaan (Deezer/Spotify)';
|
||||
String get extensionDefaultProvider => 'Default (Deezer)';
|
||||
|
||||
@override
|
||||
String get extensionDefaultProviderSubtitle => 'Gunakan pencarian bawaan';
|
||||
@@ -1464,7 +1464,7 @@ class AppLocalizationsId extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get extensionsFallbackSubtitle =>
|
||||
'Pilih ekstensi unduhan terpasang yang boleh dipakai saat fallback';
|
||||
'Choose which installed download extensions can be used as fallback';
|
||||
|
||||
@override
|
||||
String get extensionsNoDownloadProvider =>
|
||||
@@ -2139,7 +2139,7 @@ class AppLocalizationsId extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get tutorialExtensionsTip1 =>
|
||||
'Buka tab Repo untuk menemukan ekstensi yang berguna';
|
||||
'Browse the Repo tab to discover useful extensions';
|
||||
|
||||
@override
|
||||
String get tutorialExtensionsTip2 =>
|
||||
@@ -2390,25 +2390,25 @@ class AppLocalizationsId extends AppLocalizations {
|
||||
String get trackReEnrichFfmpegFailed => 'FFmpeg metadata embed failed';
|
||||
|
||||
@override
|
||||
String get queueFlacAction => 'Antrekan FLAC';
|
||||
String get queueFlacAction => 'Queue FLAC';
|
||||
|
||||
@override
|
||||
String queueFlacConfirmMessage(int count) {
|
||||
return 'Cari kecocokan online untuk track yang dipilih lalu antrekan download FLAC.\n\nFile yang sudah ada tidak akan diubah atau dihapus.\n\nHanya kecocokan dengan keyakinan tinggi yang akan diantrikan otomatis.\n\n$count dipilih';
|
||||
return 'Search online matches for the selected tracks and queue FLAC downloads.\n\nExisting files will not be modified or deleted.\n\nOnly high-confidence matches are queued automatically.\n\n$count selected';
|
||||
}
|
||||
|
||||
@override
|
||||
String queueFlacFindingProgress(int current, int total) {
|
||||
return 'Mencari kecocokan FLAC... ($current/$total)';
|
||||
return 'Finding FLAC matches... ($current/$total)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get queueFlacNoReliableMatches =>
|
||||
'Tidak ada kecocokan online yang cukup meyakinkan untuk pilihan ini';
|
||||
'No reliable online matches found for the selection';
|
||||
|
||||
@override
|
||||
String queueFlacQueuedWithSkipped(int addedCount, int skippedCount) {
|
||||
return 'Menambahkan $addedCount track ke antrean, melewati $skippedCount';
|
||||
return 'Added $addedCount tracks to queue, skipped $skippedCount';
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -2421,7 +2421,7 @@ class AppLocalizationsId extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get trackConvertFormatSubtitle =>
|
||||
'Konversi ke MP3, Opus, ALAC, atau FLAC';
|
||||
'Convert to MP3, Opus, ALAC, or FLAC';
|
||||
|
||||
@override
|
||||
String get trackConvertTitle => 'Convert Audio';
|
||||
@@ -2449,12 +2449,12 @@ class AppLocalizationsId extends AppLocalizations {
|
||||
String sourceFormat,
|
||||
String targetFormat,
|
||||
) {
|
||||
return 'Konversi dari $sourceFormat ke $targetFormat? (Lossless — tanpa kehilangan kualitas)\n\nFile asli akan dihapus setelah konversi.';
|
||||
return 'Convert from $sourceFormat to $targetFormat? (Lossless — no quality loss)\n\nThe original file will be deleted after conversion.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get trackConvertLosslessHint =>
|
||||
'Konversi lossless — tanpa kehilangan kualitas';
|
||||
'Lossless conversion — no quality loss';
|
||||
|
||||
@override
|
||||
String get trackConvertConverting => 'Converting audio...';
|
||||
@@ -2928,8 +2928,17 @@ class AppLocalizationsId extends AppLocalizations {
|
||||
'Pick folder via Android Storage Access Framework';
|
||||
|
||||
@override
|
||||
String get downloadFilenameDescription =>
|
||||
'Customize how your files are named.';
|
||||
String downloadFilenameDescription(
|
||||
Object album,
|
||||
Object artist,
|
||||
Object date,
|
||||
Object disc,
|
||||
Object title,
|
||||
Object track,
|
||||
Object year,
|
||||
) {
|
||||
return 'Customize how your files are named.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get downloadFilenameInsertTag => 'Tap to insert tag:';
|
||||
@@ -2945,19 +2954,19 @@ class AppLocalizationsId extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get downloadCreatePlaylistSourceFolder =>
|
||||
'Buat folder sumber playlist';
|
||||
'Create playlist source folder';
|
||||
|
||||
@override
|
||||
String get downloadCreatePlaylistSourceFolderEnabled =>
|
||||
'Unduhan dari playlist memakai Playlist/ lalu struktur folder normal Anda.';
|
||||
'Playlist downloads use Playlist/ plus your normal folder structure.';
|
||||
|
||||
@override
|
||||
String get downloadCreatePlaylistSourceFolderDisabled =>
|
||||
'Unduhan dari playlist hanya memakai struktur folder normal.';
|
||||
'Playlist downloads use the normal folder structure only.';
|
||||
|
||||
@override
|
||||
String get downloadCreatePlaylistSourceFolderRedundant =>
|
||||
'Mode Berdasarkan Playlist sudah menaruh unduhan ke dalam folder playlist.';
|
||||
'By Playlist already places downloads inside a playlist folder.';
|
||||
|
||||
@override
|
||||
String get downloadSongLinkRegion => 'SongLink Region';
|
||||
@@ -2975,11 +2984,11 @@ class AppLocalizationsId extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get downloadSelectServiceToEnable =>
|
||||
'Select a compatible download provider to enable quality options';
|
||||
'Select a built-in service to enable';
|
||||
|
||||
@override
|
||||
String get downloadSelectTidalQobuz =>
|
||||
'Select a compatible provider above to configure quality';
|
||||
'Select Tidal or Qobuz above to configure quality';
|
||||
|
||||
@override
|
||||
String get downloadEmbedLyricsDisabled =>
|
||||
@@ -3705,4 +3714,71 @@ class AppLocalizationsId extends AppLocalizations {
|
||||
String a11yOpenAlbum(String albumName) {
|
||||
return 'Open album $albumName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get optionsDefaultSearchTabAlbums => 'Albums';
|
||||
|
||||
@override
|
||||
String get optionsDefaultSearchTabTracks => 'Tracks';
|
||||
|
||||
@override
|
||||
String get settingsFiles => 'Files & Folders';
|
||||
|
||||
@override
|
||||
String get settingsFilesSubtitle =>
|
||||
'Download location, filename, folder structure';
|
||||
|
||||
@override
|
||||
String get settingsMetadata => 'Metadata';
|
||||
|
||||
@override
|
||||
String get settingsMetadataSubtitle =>
|
||||
'Cover art, tags, ReplayGain, providers';
|
||||
|
||||
@override
|
||||
String get settingsLyrics => 'Lyrics';
|
||||
|
||||
@override
|
||||
String get settingsLyricsSubtitle =>
|
||||
'Embed, mode, providers, language options';
|
||||
|
||||
@override
|
||||
String get settingsApp => 'App';
|
||||
|
||||
@override
|
||||
String get settingsAppSubtitle => 'Updates, data, extension repo, debug';
|
||||
|
||||
@override
|
||||
String get sectionMetadataProviders => 'Providers';
|
||||
|
||||
@override
|
||||
String get sectionDuplicates => 'Duplicates';
|
||||
|
||||
@override
|
||||
String get sectionLyricsProviderOptions => 'Provider Options';
|
||||
|
||||
@override
|
||||
String get metadataProvidersTitle => 'Metadata Provider Priority';
|
||||
|
||||
@override
|
||||
String get metadataProvidersSubtitle =>
|
||||
'Drag to set search and metadata source order';
|
||||
|
||||
@override
|
||||
String get downloadDeduplication => 'Skip Duplicate Downloads';
|
||||
|
||||
@override
|
||||
String get downloadDeduplicationEnabled =>
|
||||
'Already-downloaded tracks will be skipped';
|
||||
|
||||
@override
|
||||
String get downloadDeduplicationDisabled =>
|
||||
'All tracks will be downloaded regardless of history';
|
||||
|
||||
@override
|
||||
String get downloadFallbackExtensions => 'Fallback Extensions';
|
||||
|
||||
@override
|
||||
String get downloadFallbackExtensionsSubtitle =>
|
||||
'Choose which extensions can be used as fallback';
|
||||
}
|
||||
|
||||
@@ -21,13 +21,13 @@ class AppLocalizationsJa extends AppLocalizations {
|
||||
String get navSettings => '設定';
|
||||
|
||||
@override
|
||||
String get navStore => 'ストア';
|
||||
String get navStore => 'Repo';
|
||||
|
||||
@override
|
||||
String get homeTitle => 'ホーム';
|
||||
|
||||
@override
|
||||
String get homeSubtitle => 'Spotify のリンクを貼り付けるか、名前で検索します';
|
||||
String get homeSubtitle => 'Paste a supported URL or search by name';
|
||||
|
||||
@override
|
||||
String get homeEmptyTitle => 'No search providers yet';
|
||||
@@ -141,7 +141,8 @@ class AppLocalizationsJa extends AppLocalizations {
|
||||
'Choose which tab opens first for new search results.';
|
||||
|
||||
@override
|
||||
String get optionsSwitchBack => '現在の拡張の使用をやめるには、下から別のプロバイダーを選択してください';
|
||||
String get optionsSwitchBack =>
|
||||
'Tap Deezer or Spotify to switch back from extension';
|
||||
|
||||
@override
|
||||
String get optionsAutoFallback => 'Auto Fallback';
|
||||
@@ -157,7 +158,7 @@ class AppLocalizationsJa extends AppLocalizations {
|
||||
String get optionsUseExtensionProvidersOn => '最初に拡張で試みます';
|
||||
|
||||
@override
|
||||
String get optionsUseExtensionProvidersOff => '拡張はオフです';
|
||||
String get optionsUseExtensionProvidersOff => '内蔵のプロバイダーのみを使用する';
|
||||
|
||||
@override
|
||||
String get optionsEmbedLyrics => '歌詞を埋め込む';
|
||||
@@ -219,10 +220,10 @@ class AppLocalizationsJa extends AppLocalizations {
|
||||
'Parallel downloads may trigger rate limiting';
|
||||
|
||||
@override
|
||||
String get optionsExtensionStore => '拡張ストア';
|
||||
String get optionsExtensionStore => 'Extension Repo';
|
||||
|
||||
@override
|
||||
String get optionsExtensionStoreSubtitle => 'ナビゲーションにストアタブを表示';
|
||||
String get optionsExtensionStoreSubtitle => 'Show Repo tab in navigation';
|
||||
|
||||
@override
|
||||
String get optionsCheckUpdates => '更新を確認';
|
||||
@@ -298,7 +299,7 @@ class AppLocalizationsJa extends AppLocalizations {
|
||||
String get extensionsUninstall => 'アンインストール';
|
||||
|
||||
@override
|
||||
String get storeTitle => '拡張ストア';
|
||||
String get storeTitle => 'Extension Repo';
|
||||
|
||||
@override
|
||||
String get storeSearch => '拡張を検索...';
|
||||
@@ -950,7 +951,7 @@ class AppLocalizationsJa extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get providerPriorityFallbackExtensionsDescription =>
|
||||
'Choose which installed download extensions can be used during automatic fallback.';
|
||||
'Choose which installed download extensions can be used during automatic fallback. Built-in providers still follow the priority order above.';
|
||||
|
||||
@override
|
||||
String get providerPriorityFallbackExtensionsHint =>
|
||||
@@ -1345,7 +1346,7 @@ class AppLocalizationsJa extends AppLocalizations {
|
||||
String get storeEmptyNoResults => 'No extensions found';
|
||||
|
||||
@override
|
||||
String get extensionDefaultProvider => 'デフォルト (Deezer/Spotify)';
|
||||
String get extensionDefaultProvider => 'Default (Deezer)';
|
||||
|
||||
@override
|
||||
String get extensionDefaultProviderSubtitle => '内蔵の検索を使用する';
|
||||
@@ -2116,7 +2117,7 @@ class AppLocalizationsJa extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get tutorialExtensionsTip1 =>
|
||||
'Browse the Store tab to discover useful extensions';
|
||||
'Browse the Repo tab to discover useful extensions';
|
||||
|
||||
@override
|
||||
String get tutorialExtensionsTip2 =>
|
||||
@@ -2397,7 +2398,8 @@ class AppLocalizationsJa extends AppLocalizations {
|
||||
String get trackConvertFormat => '変換の形式';
|
||||
|
||||
@override
|
||||
String get trackConvertFormatSubtitle => 'MP3 または Opus に変換';
|
||||
String get trackConvertFormatSubtitle =>
|
||||
'Convert to MP3, Opus, ALAC, or FLAC';
|
||||
|
||||
@override
|
||||
String get trackConvertTitle => 'オーディオを変換';
|
||||
@@ -2904,8 +2906,17 @@ class AppLocalizationsJa extends AppLocalizations {
|
||||
'Pick folder via Android Storage Access Framework';
|
||||
|
||||
@override
|
||||
String get downloadFilenameDescription =>
|
||||
'Customize how your files are named.';
|
||||
String downloadFilenameDescription(
|
||||
Object album,
|
||||
Object artist,
|
||||
Object date,
|
||||
Object disc,
|
||||
Object title,
|
||||
Object track,
|
||||
Object year,
|
||||
) {
|
||||
return 'Customize how your files are named.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get downloadFilenameInsertTag => 'Tap to insert tag:';
|
||||
@@ -2951,11 +2962,11 @@ class AppLocalizationsJa extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get downloadSelectServiceToEnable =>
|
||||
'Select a compatible download provider to enable quality options';
|
||||
'Select a built-in service to enable';
|
||||
|
||||
@override
|
||||
String get downloadSelectTidalQobuz =>
|
||||
'Select a compatible provider above to configure quality';
|
||||
'Select Tidal or Qobuz above to configure quality';
|
||||
|
||||
@override
|
||||
String get downloadEmbedLyricsDisabled =>
|
||||
@@ -3681,4 +3692,71 @@ class AppLocalizationsJa extends AppLocalizations {
|
||||
String a11yOpenAlbum(String albumName) {
|
||||
return 'Open album $albumName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get optionsDefaultSearchTabAlbums => 'Albums';
|
||||
|
||||
@override
|
||||
String get optionsDefaultSearchTabTracks => 'Tracks';
|
||||
|
||||
@override
|
||||
String get settingsFiles => 'Files & Folders';
|
||||
|
||||
@override
|
||||
String get settingsFilesSubtitle =>
|
||||
'Download location, filename, folder structure';
|
||||
|
||||
@override
|
||||
String get settingsMetadata => 'Metadata';
|
||||
|
||||
@override
|
||||
String get settingsMetadataSubtitle =>
|
||||
'Cover art, tags, ReplayGain, providers';
|
||||
|
||||
@override
|
||||
String get settingsLyrics => 'Lyrics';
|
||||
|
||||
@override
|
||||
String get settingsLyricsSubtitle =>
|
||||
'Embed, mode, providers, language options';
|
||||
|
||||
@override
|
||||
String get settingsApp => 'App';
|
||||
|
||||
@override
|
||||
String get settingsAppSubtitle => 'Updates, data, extension repo, debug';
|
||||
|
||||
@override
|
||||
String get sectionMetadataProviders => 'Providers';
|
||||
|
||||
@override
|
||||
String get sectionDuplicates => 'Duplicates';
|
||||
|
||||
@override
|
||||
String get sectionLyricsProviderOptions => 'Provider Options';
|
||||
|
||||
@override
|
||||
String get metadataProvidersTitle => 'Metadata Provider Priority';
|
||||
|
||||
@override
|
||||
String get metadataProvidersSubtitle =>
|
||||
'Drag to set search and metadata source order';
|
||||
|
||||
@override
|
||||
String get downloadDeduplication => 'Skip Duplicate Downloads';
|
||||
|
||||
@override
|
||||
String get downloadDeduplicationEnabled =>
|
||||
'Already-downloaded tracks will be skipped';
|
||||
|
||||
@override
|
||||
String get downloadDeduplicationDisabled =>
|
||||
'All tracks will be downloaded regardless of history';
|
||||
|
||||
@override
|
||||
String get downloadFallbackExtensions => 'Fallback Extensions';
|
||||
|
||||
@override
|
||||
String get downloadFallbackExtensionsSubtitle =>
|
||||
'Choose which extensions can be used as fallback';
|
||||
}
|
||||
|
||||
@@ -21,13 +21,13 @@ class AppLocalizationsKo extends AppLocalizations {
|
||||
String get navSettings => 'Settings';
|
||||
|
||||
@override
|
||||
String get navStore => 'Store';
|
||||
String get navStore => 'Repo';
|
||||
|
||||
@override
|
||||
String get homeTitle => 'Home';
|
||||
|
||||
@override
|
||||
String get homeSubtitle => 'Spotify URL을 붙여 넣거나 검색';
|
||||
String get homeSubtitle => 'Paste a supported URL or search by name';
|
||||
|
||||
@override
|
||||
String get homeEmptyTitle => 'No search providers yet';
|
||||
@@ -215,10 +215,10 @@ class AppLocalizationsKo extends AppLocalizations {
|
||||
String get optionsConcurrentWarning => '동시에 다수의 음반을 다운로드하면 속도 제한이 발생할 수 있습니다';
|
||||
|
||||
@override
|
||||
String get optionsExtensionStore => '확장 기능 스토어';
|
||||
String get optionsExtensionStore => 'Extension Repo';
|
||||
|
||||
@override
|
||||
String get optionsExtensionStoreSubtitle => '탐색 메뉴에 스토어 탭 표시';
|
||||
String get optionsExtensionStoreSubtitle => 'Show Repo tab in navigation';
|
||||
|
||||
@override
|
||||
String get optionsCheckUpdates => '업데이트 확인';
|
||||
@@ -292,7 +292,7 @@ class AppLocalizationsKo extends AppLocalizations {
|
||||
String get extensionsUninstall => '삭제';
|
||||
|
||||
@override
|
||||
String get storeTitle => '확장 기능 스토어';
|
||||
String get storeTitle => 'Extension Repo';
|
||||
|
||||
@override
|
||||
String get storeSearch => '확장 기능 검색';
|
||||
@@ -939,7 +939,7 @@ class AppLocalizationsKo extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get providerPriorityFallbackExtensionsDescription =>
|
||||
'Choose which installed download extensions can be used during automatic fallback.';
|
||||
'Choose which installed download extensions can be used during automatic fallback. Built-in providers still follow the priority order above.';
|
||||
|
||||
@override
|
||||
String get providerPriorityFallbackExtensionsHint =>
|
||||
@@ -1332,7 +1332,7 @@ class AppLocalizationsKo extends AppLocalizations {
|
||||
String get storeEmptyNoResults => 'No extensions found';
|
||||
|
||||
@override
|
||||
String get extensionDefaultProvider => 'Default (Deezer/Spotify)';
|
||||
String get extensionDefaultProvider => 'Default (Deezer)';
|
||||
|
||||
@override
|
||||
String get extensionDefaultProviderSubtitle => 'Use built-in search';
|
||||
@@ -2110,7 +2110,7 @@ class AppLocalizationsKo extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get tutorialExtensionsTip1 =>
|
||||
'Browse the Store tab to discover useful extensions';
|
||||
'Browse the Repo tab to discover useful extensions';
|
||||
|
||||
@override
|
||||
String get tutorialExtensionsTip2 =>
|
||||
@@ -2391,7 +2391,8 @@ class AppLocalizationsKo extends AppLocalizations {
|
||||
String get trackConvertFormat => 'Convert Format';
|
||||
|
||||
@override
|
||||
String get trackConvertFormatSubtitle => 'Convert to MP3 or Opus';
|
||||
String get trackConvertFormatSubtitle =>
|
||||
'Convert to MP3, Opus, ALAC, or FLAC';
|
||||
|
||||
@override
|
||||
String get trackConvertTitle => 'Convert Audio';
|
||||
@@ -2898,8 +2899,17 @@ class AppLocalizationsKo extends AppLocalizations {
|
||||
'Pick folder via Android Storage Access Framework';
|
||||
|
||||
@override
|
||||
String get downloadFilenameDescription =>
|
||||
'Customize how your files are named.';
|
||||
String downloadFilenameDescription(
|
||||
Object album,
|
||||
Object artist,
|
||||
Object date,
|
||||
Object disc,
|
||||
Object title,
|
||||
Object track,
|
||||
Object year,
|
||||
) {
|
||||
return 'Customize how your files are named.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get downloadFilenameInsertTag => 'Tap to insert tag:';
|
||||
@@ -2945,11 +2955,11 @@ class AppLocalizationsKo extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get downloadSelectServiceToEnable =>
|
||||
'Select a compatible download provider to enable quality options';
|
||||
'Select a built-in service to enable';
|
||||
|
||||
@override
|
||||
String get downloadSelectTidalQobuz =>
|
||||
'Select a compatible provider above to configure quality';
|
||||
'Select Tidal or Qobuz above to configure quality';
|
||||
|
||||
@override
|
||||
String get downloadEmbedLyricsDisabled =>
|
||||
@@ -3675,4 +3685,71 @@ class AppLocalizationsKo extends AppLocalizations {
|
||||
String a11yOpenAlbum(String albumName) {
|
||||
return 'Open album $albumName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get optionsDefaultSearchTabAlbums => 'Albums';
|
||||
|
||||
@override
|
||||
String get optionsDefaultSearchTabTracks => 'Tracks';
|
||||
|
||||
@override
|
||||
String get settingsFiles => 'Files & Folders';
|
||||
|
||||
@override
|
||||
String get settingsFilesSubtitle =>
|
||||
'Download location, filename, folder structure';
|
||||
|
||||
@override
|
||||
String get settingsMetadata => 'Metadata';
|
||||
|
||||
@override
|
||||
String get settingsMetadataSubtitle =>
|
||||
'Cover art, tags, ReplayGain, providers';
|
||||
|
||||
@override
|
||||
String get settingsLyrics => 'Lyrics';
|
||||
|
||||
@override
|
||||
String get settingsLyricsSubtitle =>
|
||||
'Embed, mode, providers, language options';
|
||||
|
||||
@override
|
||||
String get settingsApp => 'App';
|
||||
|
||||
@override
|
||||
String get settingsAppSubtitle => 'Updates, data, extension repo, debug';
|
||||
|
||||
@override
|
||||
String get sectionMetadataProviders => 'Providers';
|
||||
|
||||
@override
|
||||
String get sectionDuplicates => 'Duplicates';
|
||||
|
||||
@override
|
||||
String get sectionLyricsProviderOptions => 'Provider Options';
|
||||
|
||||
@override
|
||||
String get metadataProvidersTitle => 'Metadata Provider Priority';
|
||||
|
||||
@override
|
||||
String get metadataProvidersSubtitle =>
|
||||
'Drag to set search and metadata source order';
|
||||
|
||||
@override
|
||||
String get downloadDeduplication => 'Skip Duplicate Downloads';
|
||||
|
||||
@override
|
||||
String get downloadDeduplicationEnabled =>
|
||||
'Already-downloaded tracks will be skipped';
|
||||
|
||||
@override
|
||||
String get downloadDeduplicationDisabled =>
|
||||
'All tracks will be downloaded regardless of history';
|
||||
|
||||
@override
|
||||
String get downloadFallbackExtensions => 'Fallback Extensions';
|
||||
|
||||
@override
|
||||
String get downloadFallbackExtensionsSubtitle =>
|
||||
'Choose which extensions can be used as fallback';
|
||||
}
|
||||
|
||||
@@ -21,13 +21,13 @@ class AppLocalizationsNl extends AppLocalizations {
|
||||
String get navSettings => 'Settings';
|
||||
|
||||
@override
|
||||
String get navStore => 'Store';
|
||||
String get navStore => 'Repo';
|
||||
|
||||
@override
|
||||
String get homeTitle => 'Home';
|
||||
|
||||
@override
|
||||
String get homeSubtitle => 'Paste a Spotify link or search by name';
|
||||
String get homeSubtitle => 'Paste a supported URL or search by name';
|
||||
|
||||
@override
|
||||
String get homeEmptyTitle => 'No search providers yet';
|
||||
@@ -222,10 +222,10 @@ class AppLocalizationsNl extends AppLocalizations {
|
||||
'Parallel downloaden kan leiden tot rate-limiting';
|
||||
|
||||
@override
|
||||
String get optionsExtensionStore => 'Extension Store';
|
||||
String get optionsExtensionStore => 'Extension Repo';
|
||||
|
||||
@override
|
||||
String get optionsExtensionStoreSubtitle => 'Show Store tab in navigation';
|
||||
String get optionsExtensionStoreSubtitle => 'Show Repo tab in navigation';
|
||||
|
||||
@override
|
||||
String get optionsCheckUpdates => 'Check for Updates';
|
||||
@@ -302,7 +302,7 @@ class AppLocalizationsNl extends AppLocalizations {
|
||||
String get extensionsUninstall => 'Uninstall';
|
||||
|
||||
@override
|
||||
String get storeTitle => 'Extension Store';
|
||||
String get storeTitle => 'Extension Repo';
|
||||
|
||||
@override
|
||||
String get storeSearch => 'Search extensions...';
|
||||
@@ -957,7 +957,7 @@ class AppLocalizationsNl extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get providerPriorityFallbackExtensionsDescription =>
|
||||
'Choose which installed download extensions can be used during automatic fallback.';
|
||||
'Choose which installed download extensions can be used during automatic fallback. Built-in providers still follow the priority order above.';
|
||||
|
||||
@override
|
||||
String get providerPriorityFallbackExtensionsHint =>
|
||||
@@ -1352,7 +1352,7 @@ class AppLocalizationsNl extends AppLocalizations {
|
||||
String get storeEmptyNoResults => 'No extensions found';
|
||||
|
||||
@override
|
||||
String get extensionDefaultProvider => 'Default (Deezer/Spotify)';
|
||||
String get extensionDefaultProvider => 'Default (Deezer)';
|
||||
|
||||
@override
|
||||
String get extensionDefaultProviderSubtitle => 'Use built-in search';
|
||||
@@ -2130,7 +2130,7 @@ class AppLocalizationsNl extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get tutorialExtensionsTip1 =>
|
||||
'Browse the Store tab to discover useful extensions';
|
||||
'Browse the Repo tab to discover useful extensions';
|
||||
|
||||
@override
|
||||
String get tutorialExtensionsTip2 =>
|
||||
@@ -2411,7 +2411,8 @@ class AppLocalizationsNl extends AppLocalizations {
|
||||
String get trackConvertFormat => 'Convert Format';
|
||||
|
||||
@override
|
||||
String get trackConvertFormatSubtitle => 'Convert to MP3 or Opus';
|
||||
String get trackConvertFormatSubtitle =>
|
||||
'Convert to MP3, Opus, ALAC, or FLAC';
|
||||
|
||||
@override
|
||||
String get trackConvertTitle => 'Convert Audio';
|
||||
@@ -2918,8 +2919,17 @@ class AppLocalizationsNl extends AppLocalizations {
|
||||
'Pick folder via Android Storage Access Framework';
|
||||
|
||||
@override
|
||||
String get downloadFilenameDescription =>
|
||||
'Customize how your files are named.';
|
||||
String downloadFilenameDescription(
|
||||
Object album,
|
||||
Object artist,
|
||||
Object date,
|
||||
Object disc,
|
||||
Object title,
|
||||
Object track,
|
||||
Object year,
|
||||
) {
|
||||
return 'Customize how your files are named.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get downloadFilenameInsertTag => 'Tap to insert tag:';
|
||||
@@ -2965,11 +2975,11 @@ class AppLocalizationsNl extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get downloadSelectServiceToEnable =>
|
||||
'Select a compatible download provider to enable quality options';
|
||||
'Select a built-in service to enable';
|
||||
|
||||
@override
|
||||
String get downloadSelectTidalQobuz =>
|
||||
'Select a compatible provider above to configure quality';
|
||||
'Select Tidal or Qobuz above to configure quality';
|
||||
|
||||
@override
|
||||
String get downloadEmbedLyricsDisabled =>
|
||||
@@ -3695,4 +3705,71 @@ class AppLocalizationsNl extends AppLocalizations {
|
||||
String a11yOpenAlbum(String albumName) {
|
||||
return 'Open album $albumName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get optionsDefaultSearchTabAlbums => 'Albums';
|
||||
|
||||
@override
|
||||
String get optionsDefaultSearchTabTracks => 'Tracks';
|
||||
|
||||
@override
|
||||
String get settingsFiles => 'Files & Folders';
|
||||
|
||||
@override
|
||||
String get settingsFilesSubtitle =>
|
||||
'Download location, filename, folder structure';
|
||||
|
||||
@override
|
||||
String get settingsMetadata => 'Metadata';
|
||||
|
||||
@override
|
||||
String get settingsMetadataSubtitle =>
|
||||
'Cover art, tags, ReplayGain, providers';
|
||||
|
||||
@override
|
||||
String get settingsLyrics => 'Lyrics';
|
||||
|
||||
@override
|
||||
String get settingsLyricsSubtitle =>
|
||||
'Embed, mode, providers, language options';
|
||||
|
||||
@override
|
||||
String get settingsApp => 'App';
|
||||
|
||||
@override
|
||||
String get settingsAppSubtitle => 'Updates, data, extension repo, debug';
|
||||
|
||||
@override
|
||||
String get sectionMetadataProviders => 'Providers';
|
||||
|
||||
@override
|
||||
String get sectionDuplicates => 'Duplicates';
|
||||
|
||||
@override
|
||||
String get sectionLyricsProviderOptions => 'Provider Options';
|
||||
|
||||
@override
|
||||
String get metadataProvidersTitle => 'Metadata Provider Priority';
|
||||
|
||||
@override
|
||||
String get metadataProvidersSubtitle =>
|
||||
'Drag to set search and metadata source order';
|
||||
|
||||
@override
|
||||
String get downloadDeduplication => 'Skip Duplicate Downloads';
|
||||
|
||||
@override
|
||||
String get downloadDeduplicationEnabled =>
|
||||
'Already-downloaded tracks will be skipped';
|
||||
|
||||
@override
|
||||
String get downloadDeduplicationDisabled =>
|
||||
'All tracks will be downloaded regardless of history';
|
||||
|
||||
@override
|
||||
String get downloadFallbackExtensions => 'Fallback Extensions';
|
||||
|
||||
@override
|
||||
String get downloadFallbackExtensionsSubtitle =>
|
||||
'Choose which extensions can be used as fallback';
|
||||
}
|
||||
|
||||
@@ -21,13 +21,13 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
String get navSettings => 'Настройки';
|
||||
|
||||
@override
|
||||
String get navStore => 'Магазин';
|
||||
String get navStore => 'Repo';
|
||||
|
||||
@override
|
||||
String get homeTitle => 'Главная';
|
||||
|
||||
@override
|
||||
String get homeSubtitle => 'Вставьте ссылку Spotify или ищите по названию';
|
||||
String get homeSubtitle => 'Paste a supported URL or search by name';
|
||||
|
||||
@override
|
||||
String get homeEmptyTitle => 'No search providers yet';
|
||||
@@ -227,11 +227,10 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
'Параллельные загрузки могут вызвать ограничение скорости';
|
||||
|
||||
@override
|
||||
String get optionsExtensionStore => 'Магазин расширений';
|
||||
String get optionsExtensionStore => 'Extension Repo';
|
||||
|
||||
@override
|
||||
String get optionsExtensionStoreSubtitle =>
|
||||
'Показывать вкладку Магазин в гл. меню';
|
||||
String get optionsExtensionStoreSubtitle => 'Show Repo tab in navigation';
|
||||
|
||||
@override
|
||||
String get optionsCheckUpdates => 'Проверить обновления';
|
||||
@@ -308,7 +307,7 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
String get extensionsUninstall => 'Удалить';
|
||||
|
||||
@override
|
||||
String get storeTitle => 'Магазин расширений';
|
||||
String get storeTitle => 'Extension Repo';
|
||||
|
||||
@override
|
||||
String get storeSearch => 'Поиск расширений...';
|
||||
@@ -652,9 +651,9 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
count,
|
||||
locale: localeName,
|
||||
other: 'треков',
|
||||
one: 'трек',
|
||||
many: 'треков',
|
||||
few: 'трека',
|
||||
one: 'трек',
|
||||
);
|
||||
return 'Удалить $count $_temp0 из истории?\n\nЭто также удалит файлы из хранилища.';
|
||||
}
|
||||
@@ -707,9 +706,9 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
count,
|
||||
locale: localeName,
|
||||
other: 'треков',
|
||||
one: 'трек',
|
||||
many: 'треков',
|
||||
few: 'трека',
|
||||
one: 'трек',
|
||||
);
|
||||
return 'Удалено $count $_temp0';
|
||||
}
|
||||
@@ -971,7 +970,7 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get providerPriorityFallbackExtensionsDescription =>
|
||||
'Choose which installed download extensions can be used during automatic fallback.';
|
||||
'Choose which installed download extensions can be used during automatic fallback. Built-in providers still follow the priority order above.';
|
||||
|
||||
@override
|
||||
String get providerPriorityFallbackExtensionsHint =>
|
||||
@@ -1177,9 +1176,9 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
count,
|
||||
locale: localeName,
|
||||
other: '$count треков',
|
||||
one: '1 трек',
|
||||
many: '$count треков',
|
||||
few: '$count трека',
|
||||
one: '$count трек',
|
||||
);
|
||||
return '$_temp0';
|
||||
}
|
||||
@@ -1373,7 +1372,7 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
String get storeEmptyNoResults => 'No extensions found';
|
||||
|
||||
@override
|
||||
String get extensionDefaultProvider => 'По умолчанию (Deezer/Spotify)';
|
||||
String get extensionDefaultProvider => 'Default (Deezer)';
|
||||
|
||||
@override
|
||||
String get extensionDefaultProviderSubtitle =>
|
||||
@@ -1686,9 +1685,9 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
count,
|
||||
locale: localeName,
|
||||
other: 'треков',
|
||||
one: 'трек',
|
||||
many: 'треков',
|
||||
few: 'трека',
|
||||
one: 'трек',
|
||||
);
|
||||
return 'Удалить $count $_temp0 из этого альбома?\n\nЭто также удалит файлы из хранилища.';
|
||||
}
|
||||
@@ -1710,9 +1709,9 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
count,
|
||||
locale: localeName,
|
||||
other: 'треков',
|
||||
one: 'трек',
|
||||
many: 'треков',
|
||||
few: 'трека',
|
||||
one: 'трек',
|
||||
);
|
||||
return 'Удалить $count $_temp0';
|
||||
}
|
||||
@@ -1943,9 +1942,9 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
count,
|
||||
locale: localeName,
|
||||
other: 'треков',
|
||||
one: 'трек',
|
||||
many: 'треков',
|
||||
few: 'трека',
|
||||
one: 'трек',
|
||||
);
|
||||
return '$_temp0';
|
||||
}
|
||||
@@ -2099,9 +2098,9 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
count,
|
||||
locale: localeName,
|
||||
other: '$count минут',
|
||||
one: '1 минуту',
|
||||
many: '$count минут',
|
||||
few: '$count минуты',
|
||||
one: '$count минуту',
|
||||
);
|
||||
return '$_temp0 назад';
|
||||
}
|
||||
@@ -2112,9 +2111,9 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
count,
|
||||
locale: localeName,
|
||||
other: '$count часов',
|
||||
one: '1 час',
|
||||
many: '$count часов',
|
||||
few: '$count часа',
|
||||
one: '$count час',
|
||||
);
|
||||
return '$_temp0 назад';
|
||||
}
|
||||
@@ -2180,7 +2179,7 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get tutorialExtensionsTip1 =>
|
||||
'Просмотрите вкладку Магазина, чтобы найти полезные расширения';
|
||||
'Browse the Repo tab to discover useful extensions';
|
||||
|
||||
@override
|
||||
String get tutorialExtensionsTip2 =>
|
||||
@@ -2464,7 +2463,8 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
String get trackConvertFormat => 'Переконвертировать формат';
|
||||
|
||||
@override
|
||||
String get trackConvertFormatSubtitle => 'Конвертировать в MP3 или Opus';
|
||||
String get trackConvertFormatSubtitle =>
|
||||
'Convert to MP3, Opus, ALAC, or FLAC';
|
||||
|
||||
@override
|
||||
String get trackConvertTitle => 'Конвертировать аудио';
|
||||
@@ -2598,9 +2598,9 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
count,
|
||||
locale: localeName,
|
||||
other: '$count треков',
|
||||
one: '1 трек',
|
||||
many: '$count треков',
|
||||
few: '$count трека',
|
||||
one: '$count трек',
|
||||
);
|
||||
return '$_temp0';
|
||||
}
|
||||
@@ -2751,9 +2751,9 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
count,
|
||||
locale: localeName,
|
||||
other: 'треков',
|
||||
one: 'трек',
|
||||
many: 'треков',
|
||||
few: 'трека',
|
||||
one: 'трек',
|
||||
);
|
||||
return 'Отправить $count $_temp0';
|
||||
}
|
||||
@@ -2768,9 +2768,9 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
count,
|
||||
locale: localeName,
|
||||
other: 'треков',
|
||||
one: 'трек',
|
||||
many: 'треков',
|
||||
few: 'трека',
|
||||
one: 'трек',
|
||||
);
|
||||
return 'Конвертировать $count $_temp0';
|
||||
}
|
||||
@@ -2978,8 +2978,17 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
'Pick folder via Android Storage Access Framework';
|
||||
|
||||
@override
|
||||
String get downloadFilenameDescription =>
|
||||
'Customize how your files are named.';
|
||||
String downloadFilenameDescription(
|
||||
Object album,
|
||||
Object artist,
|
||||
Object date,
|
||||
Object disc,
|
||||
Object title,
|
||||
Object track,
|
||||
Object year,
|
||||
) {
|
||||
return 'Customize how your files are named.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get downloadFilenameInsertTag => 'Tap to insert tag:';
|
||||
@@ -3025,11 +3034,11 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get downloadSelectServiceToEnable =>
|
||||
'Select a compatible download provider to enable quality options';
|
||||
'Select a built-in service to enable';
|
||||
|
||||
@override
|
||||
String get downloadSelectTidalQobuz =>
|
||||
'Select a compatible provider above to configure quality';
|
||||
'Select Tidal or Qobuz above to configure quality';
|
||||
|
||||
@override
|
||||
String get downloadEmbedLyricsDisabled =>
|
||||
@@ -3755,4 +3764,71 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
String a11yOpenAlbum(String albumName) {
|
||||
return 'Open album $albumName';
|
||||
}
|
||||
|
||||
@override
|
||||
String get optionsDefaultSearchTabAlbums => 'Albums';
|
||||
|
||||
@override
|
||||
String get optionsDefaultSearchTabTracks => 'Tracks';
|
||||
|
||||
@override
|
||||
String get settingsFiles => 'Files & Folders';
|
||||
|
||||
@override
|
||||
String get settingsFilesSubtitle =>
|
||||
'Download location, filename, folder structure';
|
||||
|
||||
@override
|
||||
String get settingsMetadata => 'Metadata';
|
||||
|
||||
@override
|
||||
String get settingsMetadataSubtitle =>
|
||||
'Cover art, tags, ReplayGain, providers';
|
||||
|
||||
@override
|
||||
String get settingsLyrics => 'Lyrics';
|
||||
|
||||
@override
|
||||
String get settingsLyricsSubtitle =>
|
||||
'Embed, mode, providers, language options';
|
||||
|
||||
@override
|
||||
String get settingsApp => 'App';
|
||||
|
||||
@override
|
||||
String get settingsAppSubtitle => 'Updates, data, extension repo, debug';
|
||||
|
||||
@override
|
||||
String get sectionMetadataProviders => 'Providers';
|
||||
|
||||
@override
|
||||
String get sectionDuplicates => 'Duplicates';
|
||||
|
||||
@override
|
||||
String get sectionLyricsProviderOptions => 'Provider Options';
|
||||
|
||||
@override
|
||||
String get metadataProvidersTitle => 'Metadata Provider Priority';
|
||||
|
||||
@override
|
||||
String get metadataProvidersSubtitle =>
|
||||
'Drag to set search and metadata source order';
|
||||
|
||||
@override
|
||||
String get downloadDeduplication => 'Skip Duplicate Downloads';
|
||||
|
||||
@override
|
||||
String get downloadDeduplicationEnabled =>
|
||||
'Already-downloaded tracks will be skipped';
|
||||
|
||||
@override
|
||||
String get downloadDeduplicationDisabled =>
|
||||
'All tracks will be downloaded regardless of history';
|
||||
|
||||
@override
|
||||
String get downloadFallbackExtensions => 'Fallback Extensions';
|
||||
|
||||
@override
|
||||
String get downloadFallbackExtensionsSubtitle =>
|
||||
'Choose which extensions can be used as fallback';
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"@@locale": "en",
|
||||
"@@last_modified": "2026-01-16",
|
||||
"@@last_modified": "2026-04-28",
|
||||
"appName": "SpotiFLAC",
|
||||
"@appName": {
|
||||
"description": "App name - DO NOT TRANSLATE"
|
||||
@@ -107,7 +107,7 @@
|
||||
},
|
||||
"downloadFolderOrganization": "Folder Organization",
|
||||
"@downloadFolderOrganization": {
|
||||
"description": "Setting for folder structure"
|
||||
"description": "Title of the folder organization picker bottom sheet"
|
||||
},
|
||||
"appearanceTitle": "Appearance",
|
||||
"@appearanceTitle": {
|
||||
@@ -153,7 +153,7 @@
|
||||
"@optionsPrimaryProvider": {
|
||||
"description": "Main search provider setting"
|
||||
},
|
||||
"optionsPrimaryProviderSubtitle": "Service used when searching by track name.",
|
||||
"optionsPrimaryProviderSubtitle": "Service used for searching by track or album name",
|
||||
"@optionsPrimaryProviderSubtitle": {
|
||||
"description": "Subtitle for primary provider"
|
||||
},
|
||||
@@ -174,9 +174,9 @@
|
||||
"@optionsDefaultSearchTabSubtitle": {
|
||||
"description": "Subtitle for the preferred default search tab setting"
|
||||
},
|
||||
"optionsSwitchBack": "Choose another provider below to stop using the current extension",
|
||||
"optionsSwitchBack": "Tap Deezer or Spotify to switch back from extension",
|
||||
"@optionsSwitchBack": {
|
||||
"description": "Hint to switch away from the current provider selection"
|
||||
"description": "Hint to switch back to built-in providers"
|
||||
},
|
||||
"optionsAutoFallback": "Auto Fallback",
|
||||
"@optionsAutoFallback": {
|
||||
@@ -194,15 +194,15 @@
|
||||
"@optionsUseExtensionProvidersOn": {
|
||||
"description": "Status when extension providers enabled"
|
||||
},
|
||||
"optionsUseExtensionProvidersOff": "Extensions are turned off",
|
||||
"optionsUseExtensionProvidersOff": "Using built-in providers only",
|
||||
"@optionsUseExtensionProvidersOff": {
|
||||
"description": "Status when extension providers are disabled"
|
||||
"description": "Status when extension providers disabled"
|
||||
},
|
||||
"optionsEmbedLyrics": "Embed Lyrics",
|
||||
"@optionsEmbedLyrics": {
|
||||
"description": "Embed lyrics in audio files"
|
||||
},
|
||||
"optionsEmbedLyricsSubtitle": "Embed synced lyrics into FLAC files",
|
||||
"optionsEmbedLyricsSubtitle": "Save synced lyrics alongside your downloaded tracks",
|
||||
"@optionsEmbedLyricsSubtitle": {
|
||||
"description": "Subtitle for embed lyrics"
|
||||
},
|
||||
@@ -749,7 +749,7 @@
|
||||
},
|
||||
"dialogDownload": "Download",
|
||||
"@dialogDownload": {
|
||||
"description": "Dialog button - download action"
|
||||
"description": "Confirm button in Download All dialog"
|
||||
},
|
||||
"dialogDiscard": "Discard",
|
||||
"@dialogDiscard": {
|
||||
@@ -1239,7 +1239,7 @@
|
||||
"@providerPriorityFallbackExtensionsTitle": {
|
||||
"description": "Section title for choosing which download extensions can be used as fallback providers"
|
||||
},
|
||||
"providerPriorityFallbackExtensionsDescription": "Choose which installed download extensions can be used during automatic fallback.",
|
||||
"providerPriorityFallbackExtensionsDescription": "Choose which installed download extensions can be used during automatic fallback. Built-in providers still follow the priority order above.",
|
||||
"@providerPriorityFallbackExtensionsDescription": {
|
||||
"description": "Section description for extension fallback selection"
|
||||
},
|
||||
@@ -1247,9 +1247,9 @@
|
||||
"@providerPriorityFallbackExtensionsHint": {
|
||||
"description": "Hint below the extension fallback selection list"
|
||||
},
|
||||
"providerBuiltIn": "Legacy",
|
||||
"providerBuiltIn": "Built-in",
|
||||
"@providerBuiltIn": {
|
||||
"description": "Label for legacy providers kept for compatibility"
|
||||
"description": "Label for built-in providers (Tidal/Qobuz)"
|
||||
},
|
||||
"providerExtension": "Extension",
|
||||
"@providerExtension": {
|
||||
@@ -1469,11 +1469,11 @@
|
||||
"@settingsAppearanceSubtitle": {
|
||||
"description": "Appearance settings description"
|
||||
},
|
||||
"settingsDownloadSubtitle": "Service, quality, filename format",
|
||||
"settingsDownloadSubtitle": "Service, quality, fallback",
|
||||
"@settingsDownloadSubtitle": {
|
||||
"description": "Download settings description"
|
||||
},
|
||||
"settingsOptionsSubtitle": "Fallback, lyrics, cover art, updates",
|
||||
"settingsOptionsSubtitle": "Fallback, metadata, lyrics, cover art",
|
||||
"@settingsOptionsSubtitle": {
|
||||
"description": "Options settings description"
|
||||
},
|
||||
@@ -3659,18 +3659,17 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"downloadUseAlbumArtistForFoldersAlbumSubtitle": "Artist folders use Album Artist when available",
|
||||
"downloadUseAlbumArtistForFoldersAlbumSubtitle": "Folder named after Album Artist tag",
|
||||
"@downloadUseAlbumArtistForFoldersAlbumSubtitle": {
|
||||
"description": "Subtitle when Album Artist is used for folder naming"
|
||||
"description": "Subtitle when album artist is used for folder names"
|
||||
},
|
||||
"downloadUseAlbumArtistForFoldersTrackSubtitle": "Artist folders use Track Artist only",
|
||||
"downloadUseAlbumArtistForFoldersTrackSubtitle": "Folder named after Track Artist tag",
|
||||
"@downloadUseAlbumArtistForFoldersTrackSubtitle": {
|
||||
"description": "Subtitle when Track Artist is used for folder naming"
|
||||
"description": "Subtitle when track artist is used for folder names"
|
||||
},
|
||||
|
||||
"lyricsProvidersTitle": "Lyrics Providers",
|
||||
"lyricsProvidersTitle": "Lyrics Provider Priority",
|
||||
"@lyricsProvidersTitle": {
|
||||
"description": "Title for the lyrics provider priority page"
|
||||
"description": "Settings item title for lyrics provider order"
|
||||
},
|
||||
"lyricsProvidersDescription": "Enable, disable and reorder lyrics sources. Providers are tried top-to-bottom until lyrics are found.",
|
||||
"@lyricsProvidersDescription": {
|
||||
@@ -3734,7 +3733,6 @@
|
||||
"@lyricsProviderExtensionDesc": {
|
||||
"description": "Generic description for extension-based lyrics providers"
|
||||
},
|
||||
|
||||
"safMigrationTitle": "Storage Update Required",
|
||||
"@safMigrationTitle": {
|
||||
"description": "Title of SAF migration dialog"
|
||||
@@ -3751,16 +3749,14 @@
|
||||
"@safMigrationSuccess": {
|
||||
"description": "Snackbar after successfully migrating to SAF"
|
||||
},
|
||||
|
||||
"settingsDonate": "Donate",
|
||||
"settingsDonate": "Support Development",
|
||||
"@settingsDonate": {
|
||||
"description": "Settings menu item - donate"
|
||||
"description": "Settings menu item - donate page"
|
||||
},
|
||||
"settingsDonateSubtitle": "Support SpotiFLAC-Mobile development",
|
||||
"settingsDonateSubtitle": "Buy the developer a coffee",
|
||||
"@settingsDonateSubtitle": {
|
||||
"description": "Subtitle for donate menu item"
|
||||
},
|
||||
|
||||
"tooltipLoveAll": "Love All",
|
||||
"@tooltipLoveAll": {
|
||||
"description": "Tooltip for the Love All button on album/playlist screens"
|
||||
@@ -3787,10 +3783,9 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"dialogDownloadAllTitle": "Download All",
|
||||
"@dialogDownloadAllTitle": {
|
||||
"description": "Title of the Download All confirmation dialog"
|
||||
"description": "Dialog title for bulk download confirmation"
|
||||
},
|
||||
"dialogDownloadAllMessage": "Download {count} tracks?",
|
||||
"@dialogDownloadAllMessage": {
|
||||
@@ -3801,11 +3796,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"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"
|
||||
@@ -3818,7 +3808,6 @@
|
||||
"@homeAlbumInfoUnavailable": {
|
||||
"description": "Snackbar when album info cannot be loaded"
|
||||
},
|
||||
|
||||
"snackbarLoadingCueSheet": "Loading CUE sheet...",
|
||||
"@snackbarLoadingCueSheet": {
|
||||
"description": "Snackbar while loading a CUE sheet file"
|
||||
@@ -3848,190 +3837,181 @@
|
||||
"@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": "Choose where to save your downloaded tracks",
|
||||
"@downloadLocationSubtitle": {
|
||||
"description": "Subtitle text in Android download location bottom sheet"
|
||||
"description": "Subtitle shown in the download location picker sheet"
|
||||
},
|
||||
"storageModeAppFolder": "App folder (non-SAF)",
|
||||
"storageModeAppFolder": "App Folder (Recommended)",
|
||||
"@storageModeAppFolder": {
|
||||
"description": "Storage mode option - use legacy app folder"
|
||||
"description": "Storage mode option - app-managed folder"
|
||||
},
|
||||
"storageModeAppFolderSubtitle": "Use default Music/SpotiFLAC path",
|
||||
"storageModeAppFolderSubtitle": "Saves to Music/SpotiFLAC by default",
|
||||
"@storageModeAppFolderSubtitle": {
|
||||
"description": "Subtitle for app folder storage mode"
|
||||
},
|
||||
"storageModeSaf": "SAF folder",
|
||||
"storageModeSaf": "Custom Folder (SAF)",
|
||||
"@storageModeSaf": {
|
||||
"description": "Storage mode option - use Android SAF picker"
|
||||
"description": "Storage mode option - Storage Access Framework"
|
||||
},
|
||||
"storageModeSafSubtitle": "Pick folder via Android Storage Access Framework",
|
||||
"storageModeSafSubtitle": "Pick any folder, including SD card",
|
||||
"@storageModeSafSubtitle": {
|
||||
"description": "Subtitle for SAF storage mode"
|
||||
},
|
||||
"downloadFilenameDescription": "Customize how your files are named.",
|
||||
"downloadFilenameDescription": "Use {artist}, {title}, {album}, {track}, {year}, {date}, {disc} as placeholders.",
|
||||
"@downloadFilenameDescription": {
|
||||
"description": "Description text in filename format bottom sheet"
|
||||
"description": "Description shown in filename format editor"
|
||||
},
|
||||
"downloadFilenameInsertTag": "Tap to insert tag:",
|
||||
"@downloadFilenameInsertTag": {
|
||||
"description": "Label above filename tag chips"
|
||||
},
|
||||
"downloadSeparateSinglesEnabled": "Albums/ and Singles/ folders",
|
||||
"downloadSeparateSinglesEnabled": "Singles and EPs saved in a separate folder",
|
||||
"@downloadSeparateSinglesEnabled": {
|
||||
"description": "Subtitle when separate singles folder is enabled"
|
||||
"description": "Subtitle when separate singles folder is on"
|
||||
},
|
||||
"downloadSeparateSinglesDisabled": "All files in same structure",
|
||||
"downloadSeparateSinglesDisabled": "Singles and albums saved in the same folder",
|
||||
"@downloadSeparateSinglesDisabled": {
|
||||
"description": "Subtitle when separate singles folder is disabled"
|
||||
"description": "Subtitle when separate singles folder is off"
|
||||
},
|
||||
"downloadArtistNameFilters": "Artist Name Filters",
|
||||
"@downloadArtistNameFilters": {
|
||||
"description": "Setting title for artist folder filter options"
|
||||
},
|
||||
"downloadCreatePlaylistSourceFolder": "Create playlist source folder",
|
||||
"downloadCreatePlaylistSourceFolder": "Playlist Source Folder",
|
||||
"@downloadCreatePlaylistSourceFolder": {
|
||||
"description": "Setting title for adding a playlist folder prefix before the normal organization structure"
|
||||
"description": "Setting to create a subfolder per playlist source"
|
||||
},
|
||||
"downloadCreatePlaylistSourceFolderEnabled": "Playlist downloads use Playlist/ plus your normal folder structure.",
|
||||
"downloadCreatePlaylistSourceFolderEnabled": "A subfolder is created for each playlist",
|
||||
"@downloadCreatePlaylistSourceFolderEnabled": {
|
||||
"description": "Subtitle when playlist source folder prefix is enabled"
|
||||
"description": "Subtitle when playlist folder is enabled"
|
||||
},
|
||||
"downloadCreatePlaylistSourceFolderDisabled": "Playlist downloads use the normal folder structure only.",
|
||||
"downloadCreatePlaylistSourceFolderDisabled": "All tracks saved directly to download folder",
|
||||
"@downloadCreatePlaylistSourceFolderDisabled": {
|
||||
"description": "Subtitle when playlist source folder prefix is disabled"
|
||||
"description": "Subtitle when playlist folder is disabled"
|
||||
},
|
||||
"downloadCreatePlaylistSourceFolderRedundant": "By Playlist already places downloads inside a playlist folder.",
|
||||
"downloadCreatePlaylistSourceFolderRedundant": "Handled by folder organization setting",
|
||||
"@downloadCreatePlaylistSourceFolderRedundant": {
|
||||
"description": "Subtitle when playlist folder prefix setting is redundant because folder organization is already by playlist"
|
||||
"description": "Subtitle when folder organization is already set to playlist"
|
||||
},
|
||||
"downloadSongLinkRegion": "SongLink Region",
|
||||
"@downloadSongLinkRegion": {
|
||||
"description": "Setting title for SongLink country region"
|
||||
"description": "Setting for SongLink region used during fallback resolution"
|
||||
},
|
||||
"downloadNetworkCompatibilityMode": "Network compatibility mode",
|
||||
"downloadNetworkCompatibilityMode": "Network Compatibility Mode",
|
||||
"@downloadNetworkCompatibilityMode": {
|
||||
"description": "Setting title for network compatibility toggle"
|
||||
"description": "Setting for legacy TLS/network handling"
|
||||
},
|
||||
"downloadNetworkCompatibilityModeEnabled": "Enabled: try HTTP + accept invalid TLS certificates (unsafe)",
|
||||
"downloadNetworkCompatibilityModeEnabled": "Using legacy TLS settings for older networks",
|
||||
"@downloadNetworkCompatibilityModeEnabled": {
|
||||
"description": "Subtitle when network compatibility mode is enabled"
|
||||
"description": "Subtitle when network compatibility mode is on"
|
||||
},
|
||||
"downloadNetworkCompatibilityModeDisabled": "Off: strict HTTPS certificate validation (recommended)",
|
||||
"downloadNetworkCompatibilityModeDisabled": "Using standard network settings",
|
||||
"@downloadNetworkCompatibilityModeDisabled": {
|
||||
"description": "Subtitle when network compatibility mode is disabled"
|
||||
"description": "Subtitle when network compatibility mode is off"
|
||||
},
|
||||
"downloadSelectServiceToEnable": "Select a compatible download provider to enable quality options",
|
||||
"downloadSelectServiceToEnable": "Select Tidal or Qobuz to enable this option",
|
||||
"@downloadSelectServiceToEnable": {
|
||||
"description": "Hint shown instead of Ask-quality subtitle when the selected provider does not expose built-in quality controls"
|
||||
"description": "Subtitle when quality picker is disabled due to extension service"
|
||||
},
|
||||
|
||||
"downloadSelectTidalQobuz": "Select a compatible provider above to configure quality",
|
||||
"downloadSelectTidalQobuz": "Select Tidal or Qobuz to choose audio quality",
|
||||
"@downloadSelectTidalQobuz": {
|
||||
"description": "Info hint when the selected provider does not expose built-in quality controls"
|
||||
"description": "Info shown when a non-built-in service is selected"
|
||||
},
|
||||
"downloadEmbedLyricsDisabled": "Disabled while Embed Metadata is turned off",
|
||||
"downloadEmbedLyricsDisabled": "Enable metadata embedding first",
|
||||
"@downloadEmbedLyricsDisabled": {
|
||||
"description": "Subtitle for Embed Lyrics when Embed Metadata is disabled"
|
||||
"description": "Subtitle when lyrics embedding is blocked by metadata toggle"
|
||||
},
|
||||
"downloadNeteaseIncludeTranslation": "Netease: Include Translation",
|
||||
"@downloadNeteaseIncludeTranslation": {
|
||||
"description": "Toggle title for including Netease translated lyrics"
|
||||
"description": "Setting to include translated lyrics from Netease"
|
||||
},
|
||||
"downloadNeteaseIncludeTranslationEnabled": "Append translated lyrics when available",
|
||||
"downloadNeteaseIncludeTranslationEnabled": "Chinese translation lines included",
|
||||
"@downloadNeteaseIncludeTranslationEnabled": {
|
||||
"description": "Subtitle when Netease translation is enabled"
|
||||
"description": "Subtitle when Netease translation is on"
|
||||
},
|
||||
"downloadNeteaseIncludeTranslationDisabled": "Use original lyrics only",
|
||||
"downloadNeteaseIncludeTranslationDisabled": "Original lyrics only",
|
||||
"@downloadNeteaseIncludeTranslationDisabled": {
|
||||
"description": "Subtitle when Netease translation is disabled"
|
||||
"description": "Subtitle when Netease translation is off"
|
||||
},
|
||||
"downloadNeteaseIncludeRomanization": "Netease: Include Romanization",
|
||||
"@downloadNeteaseIncludeRomanization": {
|
||||
"description": "Toggle title for including Netease romanized lyrics"
|
||||
"description": "Setting to include romanized lyrics from Netease"
|
||||
},
|
||||
"downloadNeteaseIncludeRomanizationEnabled": "Append romanized lyrics when available",
|
||||
"downloadNeteaseIncludeRomanizationEnabled": "Romanization lines included",
|
||||
"@downloadNeteaseIncludeRomanizationEnabled": {
|
||||
"description": "Subtitle when Netease romanization is enabled"
|
||||
"description": "Subtitle when Netease romanization is on"
|
||||
},
|
||||
"downloadNeteaseIncludeRomanizationDisabled": "Disabled",
|
||||
"downloadNeteaseIncludeRomanizationDisabled": "No romanization",
|
||||
"@downloadNeteaseIncludeRomanizationDisabled": {
|
||||
"description": "Subtitle when Netease romanization is disabled"
|
||||
"description": "Subtitle when Netease romanization is off"
|
||||
},
|
||||
"downloadAppleQqMultiPerson": "Apple/QQ Multi-Person Word-by-Word",
|
||||
"downloadAppleQqMultiPerson": "Apple / QQ: Multi-Person Lyrics",
|
||||
"@downloadAppleQqMultiPerson": {
|
||||
"description": "Toggle title for Apple/QQ multi-person word-by-word lyrics"
|
||||
"description": "Setting for word-by-word multi-person lyrics from Apple Music and QQ Music"
|
||||
},
|
||||
"downloadAppleQqMultiPersonEnabled": "Enable v1/v2 speaker and [bg:] tags",
|
||||
"downloadAppleQqMultiPersonEnabled": "Speaker labels included for duets and group tracks",
|
||||
"@downloadAppleQqMultiPersonEnabled": {
|
||||
"description": "Subtitle when multi-person word-by-word is enabled"
|
||||
"description": "Subtitle when multi-person lyrics is on"
|
||||
},
|
||||
"downloadAppleQqMultiPersonDisabled": "Simplified word-by-word formatting",
|
||||
"downloadAppleQqMultiPersonDisabled": "Standard lyrics without speaker labels",
|
||||
"@downloadAppleQqMultiPersonDisabled": {
|
||||
"description": "Subtitle when multi-person word-by-word is disabled"
|
||||
"description": "Subtitle when multi-person lyrics is off"
|
||||
},
|
||||
"downloadMusixmatchLanguage": "Musixmatch Language",
|
||||
"@downloadMusixmatchLanguage": {
|
||||
"description": "Setting title for Musixmatch language preference"
|
||||
"description": "Setting for Musixmatch lyrics translation language"
|
||||
},
|
||||
"downloadMusixmatchLanguageAuto": "Auto (original)",
|
||||
"downloadMusixmatchLanguageAuto": "Auto (original language)",
|
||||
"@downloadMusixmatchLanguageAuto": {
|
||||
"description": "Option label when Musixmatch uses original language"
|
||||
"description": "Subtitle when no language is set"
|
||||
},
|
||||
"downloadFilterContributing": "Filter contributing artists in Album Artist",
|
||||
"downloadFilterContributing": "Filter Contributing Artists",
|
||||
"@downloadFilterContributing": {
|
||||
"description": "Toggle title for filtering contributing artists in Album Artist metadata"
|
||||
"description": "Setting to strip contributing artists from Album Artist folder name"
|
||||
},
|
||||
"downloadFilterContributingEnabled": "Album Artist metadata uses primary artist only",
|
||||
"downloadFilterContributingEnabled": "Contributing artists removed from Album Artist folder name",
|
||||
"@downloadFilterContributingEnabled": {
|
||||
"description": "Subtitle when contributing artist filter is enabled"
|
||||
"description": "Subtitle when contributing artist filter is on"
|
||||
},
|
||||
"downloadFilterContributingDisabled": "Keep full Album Artist metadata value",
|
||||
"downloadFilterContributingDisabled": "Full Album Artist string used",
|
||||
"@downloadFilterContributingDisabled": {
|
||||
"description": "Subtitle when contributing artist filter is disabled"
|
||||
"description": "Subtitle when contributing artist filter is off"
|
||||
},
|
||||
|
||||
"downloadProvidersNoneEnabled": "None enabled",
|
||||
"downloadProvidersNoneEnabled": "No providers enabled",
|
||||
"@downloadProvidersNoneEnabled": {
|
||||
"description": "Subtitle for lyrics providers setting when no providers are enabled"
|
||||
"description": "Shown when no lyrics providers are active"
|
||||
},
|
||||
"downloadMusixmatchLanguageCode": "Language code",
|
||||
"@downloadMusixmatchLanguageCode": {
|
||||
"description": "Label for the Musixmatch language code text field"
|
||||
"description": "Label for Musixmatch language input field"
|
||||
},
|
||||
"downloadMusixmatchLanguageHint": "auto / en / es / ja",
|
||||
"downloadMusixmatchLanguageHint": "e.g. en, de, ja",
|
||||
"@downloadMusixmatchLanguageHint": {
|
||||
"description": "Hint text for the Musixmatch language code field"
|
||||
"description": "Placeholder for Musixmatch language input"
|
||||
},
|
||||
"downloadMusixmatchLanguageDesc": "Set preferred language code (example: en, es, ja). Leave empty for auto.",
|
||||
"downloadMusixmatchLanguageDesc": "Enter a BCP-47 language code (e.g. en, de, ja) to request translated lyrics from Musixmatch.",
|
||||
"@downloadMusixmatchLanguageDesc": {
|
||||
"description": "Description in the Musixmatch language picker"
|
||||
"description": "Description in Musixmatch language picker"
|
||||
},
|
||||
"downloadMusixmatchAuto": "Auto",
|
||||
"@downloadMusixmatchAuto": {
|
||||
"description": "Button to reset Musixmatch language to automatic"
|
||||
"description": "Button to clear Musixmatch language (use auto)"
|
||||
},
|
||||
|
||||
"downloadNetworkAnySubtitle": "WiFi + Mobile Data",
|
||||
"downloadNetworkAnySubtitle": "Use WiFi or mobile data",
|
||||
"@downloadNetworkAnySubtitle": {
|
||||
"description": "Subtitle for 'Any' network mode option"
|
||||
"description": "Subtitle for any-network option in picker"
|
||||
},
|
||||
"downloadNetworkWifiOnlySubtitle": "Pause downloads on mobile data",
|
||||
"downloadNetworkWifiOnlySubtitle": "Downloads pause when on mobile data",
|
||||
"@downloadNetworkWifiOnlySubtitle": {
|
||||
"description": "Subtitle for 'WiFi only' network mode option"
|
||||
"description": "Subtitle for WiFi-only option in picker"
|
||||
},
|
||||
"downloadSongLinkRegionDesc": "Used as userCountry for SongLink API lookup.",
|
||||
"downloadSongLinkRegionDesc": "Region used when resolving track links via SongLink. Choose the country where your streaming services are available.",
|
||||
"@downloadSongLinkRegionDesc": {
|
||||
"description": "Description in the SongLink region picker"
|
||||
},
|
||||
"downloadFolderOrganization": "Folder Organization",
|
||||
"@downloadFolderOrganization": {
|
||||
"description": "Title of the folder organization picker bottom sheet"
|
||||
"description": "Description in SongLink region picker"
|
||||
},
|
||||
"snackbarUnsupportedAudioFormat": "Unsupported audio format",
|
||||
"@snackbarUnsupportedAudioFormat": {
|
||||
@@ -4041,10 +4021,6 @@
|
||||
"@cacheRefresh": {
|
||||
"description": "Tooltip for refresh button on cache management page"
|
||||
},
|
||||
"dialogDownloadAllTitle": "Download All",
|
||||
"@dialogDownloadAllTitle": {
|
||||
"description": "Dialog title for bulk download confirmation"
|
||||
},
|
||||
"dialogDownloadPlaylistsMessage": "Download {trackCount} {trackCount, plural, =1{track} other{tracks}} from {playlistCount} {playlistCount, plural, =1{playlist} other{playlists}}?",
|
||||
"@dialogDownloadPlaylistsMessage": {
|
||||
"description": "Dialog message for bulk playlist download confirmation",
|
||||
@@ -4172,7 +4148,6 @@
|
||||
"@editMetadataSelectEmpty": {
|
||||
"description": "Button to select only fields that are currently empty"
|
||||
},
|
||||
|
||||
"queueDownloadingCount": "Downloading ({count})",
|
||||
"@queueDownloadingCount": {
|
||||
"description": "Header for active downloads section with count",
|
||||
@@ -4296,7 +4271,6 @@
|
||||
"@audioAnalysisSamples": {
|
||||
"description": "Total samples metric label"
|
||||
},
|
||||
|
||||
"extensionsSearchWith": "Search with {providerName}",
|
||||
"@extensionsSearchWith": {
|
||||
"description": "Extensions page - subtitle for built-in search provider option",
|
||||
@@ -4316,7 +4290,7 @@
|
||||
},
|
||||
"extensionsHomeFeedAuto": "Auto",
|
||||
"@extensionsHomeFeedAuto": {
|
||||
"description": "Extensions page - home feed provider option: auto"
|
||||
"description": "Label for auto-selected search provider"
|
||||
},
|
||||
"extensionsHomeFeedAutoSubtitle": "Automatically select the best available",
|
||||
"@extensionsHomeFeedAutoSubtitle": {
|
||||
@@ -4343,7 +4317,6 @@
|
||||
"@extensionsNoHomeFeedExtensions": {
|
||||
"description": "Extensions page - shown when no installed extension has home feed"
|
||||
},
|
||||
|
||||
"sortAlphaAsc": "A-Z",
|
||||
"@sortAlphaAsc": {
|
||||
"description": "Sort option - alphabetical ascending"
|
||||
@@ -4369,7 +4342,6 @@
|
||||
"@cancelDownloadKeep": {
|
||||
"description": "Dialog button - keep the active download (do not cancel)"
|
||||
},
|
||||
|
||||
"metadataSaveFailedFfmpeg": "Failed to save metadata via FFmpeg",
|
||||
"@metadataSaveFailedFfmpeg": {
|
||||
"description": "Snackbar error when FFmpeg fails to write metadata"
|
||||
@@ -4378,7 +4350,6 @@
|
||||
"@metadataSaveFailedStorage": {
|
||||
"description": "Snackbar error when writing metadata file back to storage fails"
|
||||
},
|
||||
|
||||
"snackbarFolderPickerFailed": "Failed to open folder picker: {error}",
|
||||
"@snackbarFolderPickerFailed": {
|
||||
"description": "Snackbar shown when folder picker fails to open",
|
||||
@@ -4388,7 +4359,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"errorLoadAlbum": "Failed to load album",
|
||||
"@errorLoadAlbum": {
|
||||
"description": "Error state shown when album fails to load"
|
||||
@@ -4401,7 +4371,6 @@
|
||||
"@errorLoadArtist": {
|
||||
"description": "Error state shown when artist fails to load"
|
||||
},
|
||||
|
||||
"notifChannelDownloadName": "Download Progress",
|
||||
"@notifChannelDownloadName": {
|
||||
"description": "Android notification channel name for download progress"
|
||||
@@ -4919,5 +4888,85 @@
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"optionsDefaultSearchTabAlbums": "Albums",
|
||||
"@optionsDefaultSearchTabAlbums": {
|
||||
"description": "Default search tab option - Albums tab"
|
||||
},
|
||||
"optionsDefaultSearchTabTracks": "Tracks",
|
||||
"@optionsDefaultSearchTabTracks": {
|
||||
"description": "Default search tab option - Tracks tab"
|
||||
},
|
||||
"settingsFiles": "Files & Folders",
|
||||
"@settingsFiles": {
|
||||
"description": "Settings menu item - file and folder settings"
|
||||
},
|
||||
"settingsFilesSubtitle": "Download location, filename, folder structure",
|
||||
"@settingsFilesSubtitle": {
|
||||
"description": "Subtitle for files & folders settings"
|
||||
},
|
||||
"settingsMetadata": "Metadata",
|
||||
"@settingsMetadata": {
|
||||
"description": "Settings menu item - metadata settings"
|
||||
},
|
||||
"settingsMetadataSubtitle": "Cover art, tags, ReplayGain, providers",
|
||||
"@settingsMetadataSubtitle": {
|
||||
"description": "Subtitle for metadata settings"
|
||||
},
|
||||
"settingsLyrics": "Lyrics",
|
||||
"@settingsLyrics": {
|
||||
"description": "Settings menu item - lyrics settings"
|
||||
},
|
||||
"settingsLyricsSubtitle": "Embed, mode, providers, language options",
|
||||
"@settingsLyricsSubtitle": {
|
||||
"description": "Subtitle for lyrics settings"
|
||||
},
|
||||
"settingsApp": "App",
|
||||
"@settingsApp": {
|
||||
"description": "Settings menu item - app settings"
|
||||
},
|
||||
"settingsAppSubtitle": "Updates, data, extension repo, debug",
|
||||
"@settingsAppSubtitle": {
|
||||
"description": "Subtitle for app settings"
|
||||
},
|
||||
"sectionMetadataProviders": "Providers",
|
||||
"@sectionMetadataProviders": {
|
||||
"description": "Settings section header for metadata providers"
|
||||
},
|
||||
"sectionDuplicates": "Duplicates",
|
||||
"@sectionDuplicates": {
|
||||
"description": "Settings section header for deduplication"
|
||||
},
|
||||
"sectionLyricsProviderOptions": "Provider Options",
|
||||
"@sectionLyricsProviderOptions": {
|
||||
"description": "Settings section header for per-provider lyrics options"
|
||||
},
|
||||
"metadataProvidersTitle": "Metadata Provider Priority",
|
||||
"@metadataProvidersTitle": {
|
||||
"description": "Settings item title for metadata provider order"
|
||||
},
|
||||
"metadataProvidersSubtitle": "Drag to set search and metadata source order",
|
||||
"@metadataProvidersSubtitle": {
|
||||
"description": "Subtitle for metadata provider priority item"
|
||||
},
|
||||
"downloadDeduplication": "Skip Duplicate Downloads",
|
||||
"@downloadDeduplication": {
|
||||
"description": "Setting - skip tracks already in download history"
|
||||
},
|
||||
"downloadDeduplicationEnabled": "Already-downloaded tracks will be skipped",
|
||||
"@downloadDeduplicationEnabled": {
|
||||
"description": "Subtitle when deduplication is on"
|
||||
},
|
||||
"downloadDeduplicationDisabled": "All tracks will be downloaded regardless of history",
|
||||
"@downloadDeduplicationDisabled": {
|
||||
"description": "Subtitle when deduplication is off"
|
||||
},
|
||||
"downloadFallbackExtensions": "Fallback Extensions",
|
||||
"@downloadFallbackExtensions": {
|
||||
"description": "Settings item for configuring fallback extension providers"
|
||||
},
|
||||
"downloadFallbackExtensionsSubtitle": "Choose which extensions can be used as fallback",
|
||||
"@downloadFallbackExtensionsSubtitle": {
|
||||
"description": "Subtitle for fallback extensions item"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ const List<Locale> filteredSupportedLocales = <Locale>[
|
||||
Locale('pt', 'PT'),
|
||||
Locale('ja'),
|
||||
Locale('tr'),
|
||||
Locale('uk'),
|
||||
];
|
||||
|
||||
/// Set of locale codes for quick lookup.
|
||||
@@ -31,4 +32,5 @@ const Set<String> filteredLocaleCodes = <String>{
|
||||
'pt_PT',
|
||||
'ja',
|
||||
'tr',
|
||||
'uk',
|
||||
};
|
||||
|
||||
@@ -85,6 +85,9 @@ class AppSettings {
|
||||
final String
|
||||
lastSeenVersion; // Last app version the user has acknowledged (e.g. '3.7.0')
|
||||
|
||||
final bool
|
||||
deduplicateDownloads; // Skip downloading tracks already present in history
|
||||
|
||||
const AppSettings({
|
||||
this.defaultService = '',
|
||||
this.audioQuality = 'LOSSLESS',
|
||||
@@ -148,6 +151,7 @@ class AppSettings {
|
||||
this.lyricsMultiPersonWordByWord = false,
|
||||
this.musixmatchLanguage = '',
|
||||
this.lastSeenVersion = '',
|
||||
this.deduplicateDownloads = true,
|
||||
});
|
||||
|
||||
AppSettings copyWith({
|
||||
@@ -210,6 +214,7 @@ class AppSettings {
|
||||
bool? lyricsMultiPersonWordByWord,
|
||||
String? musixmatchLanguage,
|
||||
String? lastSeenVersion,
|
||||
bool? deduplicateDownloads,
|
||||
}) {
|
||||
return AppSettings(
|
||||
defaultService: defaultService ?? this.defaultService,
|
||||
@@ -288,6 +293,7 @@ class AppSettings {
|
||||
lyricsMultiPersonWordByWord ?? this.lyricsMultiPersonWordByWord,
|
||||
musixmatchLanguage: musixmatchLanguage ?? this.musixmatchLanguage,
|
||||
lastSeenVersion: lastSeenVersion ?? this.lastSeenVersion,
|
||||
deduplicateDownloads: deduplicateDownloads ?? this.deduplicateDownloads,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -563,6 +563,11 @@ class SettingsNotifier extends Notifier<AppSettings> {
|
||||
state = state.copyWith(hasCompletedTutorial: true);
|
||||
_saveSettings();
|
||||
}
|
||||
|
||||
void setDeduplicateDownloads(bool enabled) {
|
||||
state = state.copyWith(deduplicateDownloads: enabled);
|
||||
_saveSettings();
|
||||
}
|
||||
}
|
||||
|
||||
final settingsProvider = NotifierProvider<SettingsNotifier, AppSettings>(
|
||||
|
||||
@@ -0,0 +1,364 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:spotiflac_android/l10n/l10n.dart';
|
||||
import 'package:spotiflac_android/providers/download_queue_provider.dart';
|
||||
import 'package:spotiflac_android/providers/settings_provider.dart';
|
||||
import 'package:spotiflac_android/utils/app_bar_layout.dart';
|
||||
import 'package:spotiflac_android/widgets/settings_group.dart';
|
||||
|
||||
class AppSettingsPage extends ConsumerWidget {
|
||||
const AppSettingsPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final settings = ref.watch(settingsProvider);
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final topPadding = normalizedHeaderTopPadding(context);
|
||||
|
||||
return PopScope(
|
||||
canPop: true,
|
||||
child: Scaffold(
|
||||
body: CustomScrollView(
|
||||
slivers: [
|
||||
SliverAppBar(
|
||||
expandedHeight: 120 + topPadding,
|
||||
collapsedHeight: kToolbarHeight,
|
||||
floating: false,
|
||||
pinned: true,
|
||||
backgroundColor: colorScheme.surface,
|
||||
surfaceTintColor: Colors.transparent,
|
||||
leading: IconButton(
|
||||
tooltip: MaterialLocalizations.of(context).backButtonTooltip,
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
flexibleSpace: LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final maxHeight = 120 + topPadding;
|
||||
final minHeight = kToolbarHeight + topPadding;
|
||||
final expandRatio =
|
||||
((constraints.maxHeight - minHeight) /
|
||||
(maxHeight - minHeight))
|
||||
.clamp(0.0, 1.0);
|
||||
final leftPadding = 56 - (32 * expandRatio);
|
||||
return FlexibleSpaceBar(
|
||||
expandedTitleScale: 1.0,
|
||||
titlePadding: EdgeInsets.only(
|
||||
left: leftPadding,
|
||||
bottom: 16,
|
||||
),
|
||||
title: Text(
|
||||
context.l10n.settingsApp,
|
||||
style: TextStyle(
|
||||
fontSize: 20 + (8 * expandRatio),
|
||||
fontWeight: FontWeight.bold,
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
// ── Updates ────────────────────────────────────────────────
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsSectionHeader(title: context.l10n.sectionApp),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsGroup(
|
||||
children: [
|
||||
SettingsSwitchItem(
|
||||
icon: Icons.extension,
|
||||
title: context.l10n.optionsExtensionStore,
|
||||
subtitle: context.l10n.optionsExtensionStoreSubtitle,
|
||||
value: settings.showExtensionStore,
|
||||
onChanged: (v) => ref
|
||||
.read(settingsProvider.notifier)
|
||||
.setShowExtensionStore(v),
|
||||
),
|
||||
SettingsSwitchItem(
|
||||
icon: Icons.system_update,
|
||||
title: context.l10n.optionsCheckUpdates,
|
||||
subtitle: context.l10n.optionsCheckUpdatesSubtitle,
|
||||
value: settings.checkForUpdates,
|
||||
onChanged: (v) => ref
|
||||
.read(settingsProvider.notifier)
|
||||
.setCheckForUpdates(v),
|
||||
showDivider: settings.checkForUpdates,
|
||||
),
|
||||
if (settings.checkForUpdates)
|
||||
_UpdateChannelSelector(
|
||||
currentChannel: settings.updateChannel,
|
||||
onChanged: (v) => ref
|
||||
.read(settingsProvider.notifier)
|
||||
.setUpdateChannel(v),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// ── Data ───────────────────────────────────────────────────
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsSectionHeader(title: context.l10n.sectionData),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsGroup(
|
||||
children: [
|
||||
SettingsItem(
|
||||
icon: Icons.cleaning_services_outlined,
|
||||
title: context.l10n.cleanupOrphanedDownloads,
|
||||
subtitle: context.l10n.cleanupOrphanedDownloadsSubtitle,
|
||||
onTap: () => _cleanupOrphanedDownloads(context, ref),
|
||||
),
|
||||
SettingsItem(
|
||||
icon: Icons.delete_forever,
|
||||
title: context.l10n.optionsClearHistory,
|
||||
subtitle: context.l10n.optionsClearHistorySubtitle,
|
||||
onTap: () =>
|
||||
_showClearHistoryDialog(context, ref, colorScheme),
|
||||
showDivider: false,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// ── Debug ──────────────────────────────────────────────────
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsSectionHeader(title: context.l10n.sectionDebug),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsGroup(
|
||||
children: [
|
||||
SettingsSwitchItem(
|
||||
icon: Icons.bug_report,
|
||||
title: context.l10n.optionsDetailedLogging,
|
||||
subtitle: settings.enableLogging
|
||||
? context.l10n.optionsDetailedLoggingOn
|
||||
: context.l10n.optionsDetailedLoggingOff,
|
||||
value: settings.enableLogging,
|
||||
onChanged: (v) =>
|
||||
ref.read(settingsProvider.notifier).setEnableLogging(v),
|
||||
showDivider: false,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
const SliverToBoxAdapter(child: SizedBox(height: 32)),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _showClearHistoryDialog(
|
||||
BuildContext context,
|
||||
WidgetRef ref,
|
||||
ColorScheme colorScheme,
|
||||
) {
|
||||
showDialog<void>(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(context.l10n.dialogClearHistoryTitle),
|
||||
content: Text(context.l10n.dialogClearHistoryMessage),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: Text(context.l10n.dialogCancel),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
ref.read(downloadHistoryProvider.notifier).clearHistory();
|
||||
Navigator.pop(context);
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text(context.l10n.snackbarHistoryCleared)),
|
||||
);
|
||||
},
|
||||
child: Text(
|
||||
context.l10n.dialogClear,
|
||||
style: TextStyle(color: colorScheme.error),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _cleanupOrphanedDownloads(
|
||||
BuildContext context,
|
||||
WidgetRef ref,
|
||||
) async {
|
||||
showDialog<void>(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => AlertDialog(
|
||||
content: Row(
|
||||
children: [
|
||||
const CircularProgressIndicator(),
|
||||
const SizedBox(width: 16),
|
||||
Text(context.l10n.cleanupOrphanedDownloads),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
try {
|
||||
final removed = await ref
|
||||
.read(downloadHistoryProvider.notifier)
|
||||
.cleanupOrphanedDownloads();
|
||||
if (context.mounted) {
|
||||
Navigator.pop(context);
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
removed > 0
|
||||
? context.l10n.cleanupOrphanedDownloadsResult(removed)
|
||||
: context.l10n.cleanupOrphanedDownloadsNone,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (context.mounted) {
|
||||
Navigator.pop(context);
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text(context.l10n.snackbarError(e.toString()))),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class _UpdateChannelSelector extends StatelessWidget {
|
||||
final String currentChannel;
|
||||
final ValueChanged<String> onChanged;
|
||||
const _UpdateChannelSelector({
|
||||
required this.currentChannel,
|
||||
required this.onChanged,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.new_releases,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
size: 24,
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
context.l10n.optionsUpdateChannel,
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
currentChannel == 'preview'
|
||||
? context.l10n.optionsUpdateChannelPreview
|
||||
: context.l10n.optionsUpdateChannelStable,
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Row(
|
||||
children: [
|
||||
_ChannelChip(
|
||||
label: context.l10n.channelStable,
|
||||
isSelected: currentChannel == 'stable',
|
||||
onTap: () => onChanged('stable'),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
_ChannelChip(
|
||||
label: context.l10n.channelPreview,
|
||||
isSelected: currentChannel == 'preview',
|
||||
onTap: () => onChanged('preview'),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.info_outline,
|
||||
size: 16,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
context.l10n.optionsUpdateChannelWarning,
|
||||
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ChannelChip extends StatelessWidget {
|
||||
final String label;
|
||||
final bool isSelected;
|
||||
final VoidCallback onTap;
|
||||
const _ChannelChip({
|
||||
required this.label,
|
||||
required this.isSelected,
|
||||
required this.onTap,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final isDark = Theme.of(context).brightness == Brightness.dark;
|
||||
final unselectedColor = isDark
|
||||
? Color.alphaBlend(
|
||||
Colors.white.withValues(alpha: 0.05),
|
||||
colorScheme.surface,
|
||||
)
|
||||
: colorScheme.surfaceContainerHigh;
|
||||
return Expanded(
|
||||
child: Material(
|
||||
color: isSelected ? colorScheme.primaryContainer : unselectedColor,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
child: InkWell(
|
||||
onTap: onTap,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12),
|
||||
child: Center(
|
||||
child: Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal,
|
||||
color: isSelected
|
||||
? colorScheme.onPrimaryContainer
|
||||
: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -735,6 +735,7 @@ class _LanguageSelector extends StatelessWidget {
|
||||
('pt_PT', 'Português (Brasil)', Icons.language),
|
||||
('ru', 'Русский', Icons.language),
|
||||
('tr', 'Türkçe', Icons.language),
|
||||
('uk', 'Українська', Icons.language),
|
||||
('zh', '简体中文', Icons.language),
|
||||
('zh_CN', '简体中文 (中国)', Icons.language),
|
||||
('zh_TW', '繁體中文', Icons.language),
|
||||
|
||||
@@ -0,0 +1,373 @@
|
||||
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/utils/app_bar_layout.dart';
|
||||
import 'package:spotiflac_android/screens/settings/lyrics_provider_priority_page.dart';
|
||||
import 'package:spotiflac_android/widgets/settings_group.dart';
|
||||
|
||||
class LyricsSettingsPage extends ConsumerWidget {
|
||||
const LyricsSettingsPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final settings = ref.watch(settingsProvider);
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final topPadding = normalizedHeaderTopPadding(context);
|
||||
|
||||
return PopScope(
|
||||
canPop: true,
|
||||
child: Scaffold(
|
||||
body: CustomScrollView(
|
||||
slivers: [
|
||||
SliverAppBar(
|
||||
expandedHeight: 120 + topPadding,
|
||||
collapsedHeight: kToolbarHeight,
|
||||
floating: false,
|
||||
pinned: true,
|
||||
backgroundColor: colorScheme.surface,
|
||||
surfaceTintColor: Colors.transparent,
|
||||
leading: IconButton(
|
||||
tooltip: MaterialLocalizations.of(context).backButtonTooltip,
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
flexibleSpace: LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final maxHeight = 120 + topPadding;
|
||||
final minHeight = kToolbarHeight + topPadding;
|
||||
final expandRatio =
|
||||
((constraints.maxHeight - minHeight) /
|
||||
(maxHeight - minHeight))
|
||||
.clamp(0.0, 1.0);
|
||||
final leftPadding = 56 - (32 * expandRatio);
|
||||
return FlexibleSpaceBar(
|
||||
expandedTitleScale: 1.0,
|
||||
titlePadding: EdgeInsets.only(
|
||||
left: leftPadding,
|
||||
bottom: 16,
|
||||
),
|
||||
title: Text(
|
||||
context.l10n.settingsLyrics,
|
||||
style: TextStyle(
|
||||
fontSize: 20 + (8 * expandRatio),
|
||||
fontWeight: FontWeight.bold,
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
// ── Lyrics Embedding ───────────────────────────────────────
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsSectionHeader(title: context.l10n.sectionLyrics),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsGroup(
|
||||
children: [
|
||||
SettingsSwitchItem(
|
||||
icon: Icons.subtitles_outlined,
|
||||
title: context.l10n.optionsEmbedLyrics,
|
||||
subtitle: settings.embedMetadata
|
||||
? context.l10n.optionsEmbedLyricsSubtitle
|
||||
: context.l10n.downloadEmbedLyricsDisabled,
|
||||
value: settings.embedLyrics,
|
||||
enabled: settings.embedMetadata,
|
||||
onChanged: (value) => ref
|
||||
.read(settingsProvider.notifier)
|
||||
.setEmbedLyrics(value),
|
||||
showDivider:
|
||||
settings.embedMetadata && settings.embedLyrics,
|
||||
),
|
||||
if (settings.embedMetadata && settings.embedLyrics) ...[
|
||||
SettingsItem(
|
||||
icon: Icons.lyrics_outlined,
|
||||
title: context.l10n.lyricsMode,
|
||||
subtitle: _getLyricsModeLabel(
|
||||
context,
|
||||
settings.lyricsMode,
|
||||
),
|
||||
onTap: () =>
|
||||
_showLyricsModePicker(context, ref, settings.lyricsMode),
|
||||
),
|
||||
SettingsItem(
|
||||
icon: Icons.source_outlined,
|
||||
title: context.l10n.lyricsProvidersTitle,
|
||||
subtitle: _getLyricsProvidersSubtitle(
|
||||
context,
|
||||
settings.lyricsProviders,
|
||||
),
|
||||
onTap: () => Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute<void>(
|
||||
builder: (_) => const LyricsProviderPriorityPage(),
|
||||
),
|
||||
),
|
||||
showDivider: false,
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// ── Provider Options ───────────────────────────────────────
|
||||
if (settings.embedMetadata && settings.embedLyrics) ...[
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsSectionHeader(
|
||||
title: context.l10n.sectionLyricsProviderOptions,
|
||||
),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsGroup(
|
||||
children: [
|
||||
SettingsSwitchItem(
|
||||
icon: Icons.translate_outlined,
|
||||
title: context.l10n.downloadNeteaseIncludeTranslation,
|
||||
subtitle: settings.lyricsIncludeTranslationNetease
|
||||
? context.l10n.downloadNeteaseIncludeTranslationEnabled
|
||||
: context.l10n.downloadNeteaseIncludeTranslationDisabled,
|
||||
value: settings.lyricsIncludeTranslationNetease,
|
||||
onChanged: (value) => ref
|
||||
.read(settingsProvider.notifier)
|
||||
.setLyricsIncludeTranslationNetease(value),
|
||||
),
|
||||
SettingsSwitchItem(
|
||||
icon: Icons.text_fields_outlined,
|
||||
title: context.l10n.downloadNeteaseIncludeRomanization,
|
||||
subtitle: settings.lyricsIncludeRomanizationNetease
|
||||
? context
|
||||
.l10n
|
||||
.downloadNeteaseIncludeRomanizationEnabled
|
||||
: context
|
||||
.l10n
|
||||
.downloadNeteaseIncludeRomanizationDisabled,
|
||||
value: settings.lyricsIncludeRomanizationNetease,
|
||||
onChanged: (value) => ref
|
||||
.read(settingsProvider.notifier)
|
||||
.setLyricsIncludeRomanizationNetease(value),
|
||||
),
|
||||
SettingsSwitchItem(
|
||||
icon: Icons.record_voice_over_outlined,
|
||||
title: context.l10n.downloadAppleQqMultiPerson,
|
||||
subtitle: settings.lyricsMultiPersonWordByWord
|
||||
? context.l10n.downloadAppleQqMultiPersonEnabled
|
||||
: context.l10n.downloadAppleQqMultiPersonDisabled,
|
||||
value: settings.lyricsMultiPersonWordByWord,
|
||||
onChanged: (value) => ref
|
||||
.read(settingsProvider.notifier)
|
||||
.setLyricsMultiPersonWordByWord(value),
|
||||
),
|
||||
SettingsItem(
|
||||
icon: Icons.language_outlined,
|
||||
title: context.l10n.downloadMusixmatchLanguage,
|
||||
subtitle: settings.musixmatchLanguage.isEmpty
|
||||
? context.l10n.downloadMusixmatchLanguageAuto
|
||||
: settings.musixmatchLanguage.toUpperCase(),
|
||||
onTap: () => _showMusixmatchLanguagePicker(
|
||||
context,
|
||||
ref,
|
||||
settings.musixmatchLanguage,
|
||||
),
|
||||
showDivider: false,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
const SliverToBoxAdapter(child: SizedBox(height: 32)),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String _getLyricsModeLabel(BuildContext context, String mode) {
|
||||
switch (mode) {
|
||||
case 'external':
|
||||
return context.l10n.lyricsModeExternal;
|
||||
case 'both':
|
||||
return context.l10n.lyricsModeBoth;
|
||||
default:
|
||||
return context.l10n.lyricsModeEmbed;
|
||||
}
|
||||
}
|
||||
|
||||
static const _providerDisplayNames = <String, String>{
|
||||
'lrclib': 'LRCLIB',
|
||||
'netease': 'Netease',
|
||||
'musixmatch': 'Musixmatch',
|
||||
'apple_music': 'Apple Music',
|
||||
'qqmusic': 'QQ Music',
|
||||
};
|
||||
|
||||
String _getLyricsProvidersSubtitle(
|
||||
BuildContext context,
|
||||
List<String> providers,
|
||||
) {
|
||||
if (providers.isEmpty) return context.l10n.downloadProvidersNoneEnabled;
|
||||
return providers
|
||||
.map((p) => _providerDisplayNames[p] ?? p)
|
||||
.join(' > ');
|
||||
}
|
||||
|
||||
void _showLyricsModePicker(
|
||||
BuildContext context,
|
||||
WidgetRef ref,
|
||||
String current,
|
||||
) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
showModalBottomSheet<void>(
|
||||
context: context,
|
||||
useRootNavigator: true,
|
||||
backgroundColor: colorScheme.surfaceContainerHigh,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(28)),
|
||||
),
|
||||
builder: (context) => SafeArea(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 24, 24, 8),
|
||||
child: Text(
|
||||
context.l10n.lyricsMode,
|
||||
style: Theme.of(context).textTheme.titleLarge
|
||||
?.copyWith(fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 0, 24, 16),
|
||||
child: Text(
|
||||
context.l10n.lyricsModeDescription,
|
||||
style: Theme.of(context).textTheme.bodyMedium
|
||||
?.copyWith(color: colorScheme.onSurfaceVariant),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.audiotrack),
|
||||
title: Text(context.l10n.lyricsModeEmbed),
|
||||
subtitle: Text(context.l10n.lyricsModeEmbedSubtitle),
|
||||
trailing: current == 'embed' ? const Icon(Icons.check) : null,
|
||||
onTap: () {
|
||||
ref.read(settingsProvider.notifier).setLyricsMode('embed');
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.insert_drive_file_outlined),
|
||||
title: Text(context.l10n.lyricsModeExternal),
|
||||
subtitle: Text(context.l10n.lyricsModeExternalSubtitle),
|
||||
trailing: current == 'external' ? const Icon(Icons.check) : null,
|
||||
onTap: () {
|
||||
ref.read(settingsProvider.notifier).setLyricsMode('external');
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.library_music_outlined),
|
||||
title: Text(context.l10n.lyricsModeBoth),
|
||||
subtitle: Text(context.l10n.lyricsModeBothSubtitle),
|
||||
trailing: current == 'both' ? const Icon(Icons.check) : null,
|
||||
onTap: () {
|
||||
ref.read(settingsProvider.notifier).setLyricsMode('both');
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _showMusixmatchLanguagePicker(
|
||||
BuildContext context,
|
||||
WidgetRef ref,
|
||||
String currentLanguage,
|
||||
) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final controller = TextEditingController(text: currentLanguage);
|
||||
|
||||
showModalBottomSheet<void>(
|
||||
context: context,
|
||||
useRootNavigator: true,
|
||||
backgroundColor: colorScheme.surfaceContainerHigh,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(28)),
|
||||
),
|
||||
isScrollControlled: true,
|
||||
builder: (context) => Padding(
|
||||
padding: EdgeInsets.only(
|
||||
left: 24,
|
||||
right: 24,
|
||||
top: 24,
|
||||
bottom: 24 + MediaQuery.of(context).viewInsets.bottom,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
context.l10n.downloadMusixmatchLanguage,
|
||||
style: Theme.of(context).textTheme.titleLarge
|
||||
?.copyWith(fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
context.l10n.downloadMusixmatchLanguageDesc,
|
||||
style: Theme.of(context).textTheme.bodyMedium
|
||||
?.copyWith(color: colorScheme.onSurfaceVariant),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextField(
|
||||
controller: controller,
|
||||
textInputAction: TextInputAction.done,
|
||||
decoration: InputDecoration(
|
||||
labelText: context.l10n.downloadMusixmatchLanguageCode,
|
||||
hintText: context.l10n.downloadMusixmatchLanguageHint,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: Text(context.l10n.dialogCancel),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
ref
|
||||
.read(settingsProvider.notifier)
|
||||
.setMusixmatchLanguage('');
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text(context.l10n.downloadMusixmatchAuto),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
FilledButton(
|
||||
onPressed: () {
|
||||
final normalized = controller.text
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
.replaceAll(RegExp(r'[^a-z0-9\-_]'), '');
|
||||
ref
|
||||
.read(settingsProvider.notifier)
|
||||
.setMusixmatchLanguage(normalized);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text(context.l10n.dialogSave),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
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/utils/app_bar_layout.dart';
|
||||
import 'package:spotiflac_android/utils/artist_utils.dart';
|
||||
import 'package:spotiflac_android/screens/settings/metadata_provider_priority_page.dart';
|
||||
import 'package:spotiflac_android/widgets/settings_group.dart';
|
||||
|
||||
class MetadataSettingsPage extends ConsumerWidget {
|
||||
const MetadataSettingsPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final settings = ref.watch(settingsProvider);
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final topPadding = normalizedHeaderTopPadding(context);
|
||||
|
||||
return PopScope(
|
||||
canPop: true,
|
||||
child: Scaffold(
|
||||
body: CustomScrollView(
|
||||
slivers: [
|
||||
SliverAppBar(
|
||||
expandedHeight: 120 + topPadding,
|
||||
collapsedHeight: kToolbarHeight,
|
||||
floating: false,
|
||||
pinned: true,
|
||||
backgroundColor: colorScheme.surface,
|
||||
surfaceTintColor: Colors.transparent,
|
||||
leading: IconButton(
|
||||
tooltip: MaterialLocalizations.of(context).backButtonTooltip,
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
flexibleSpace: LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final maxHeight = 120 + topPadding;
|
||||
final minHeight = kToolbarHeight + topPadding;
|
||||
final expandRatio =
|
||||
((constraints.maxHeight - minHeight) /
|
||||
(maxHeight - minHeight))
|
||||
.clamp(0.0, 1.0);
|
||||
final leftPadding = 56 - (32 * expandRatio);
|
||||
return FlexibleSpaceBar(
|
||||
expandedTitleScale: 1.0,
|
||||
titlePadding: EdgeInsets.only(
|
||||
left: leftPadding,
|
||||
bottom: 16,
|
||||
),
|
||||
title: Text(
|
||||
context.l10n.settingsMetadata,
|
||||
style: TextStyle(
|
||||
fontSize: 20 + (8 * expandRatio),
|
||||
fontWeight: FontWeight.bold,
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
// ── Embedding ──────────────────────────────────────────────
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsSectionHeader(title: context.l10n.sectionDownload),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsGroup(
|
||||
children: [
|
||||
SettingsSwitchItem(
|
||||
icon: Icons.sell_outlined,
|
||||
title: 'Embed Metadata',
|
||||
subtitle: settings.embedMetadata
|
||||
? 'Write metadata, cover art, and lyrics to files'
|
||||
: 'Disabled (advanced): skip all metadata embedding',
|
||||
value: settings.embedMetadata,
|
||||
onChanged: (v) =>
|
||||
ref.read(settingsProvider.notifier).setEmbedMetadata(v),
|
||||
showDivider: settings.embedMetadata,
|
||||
),
|
||||
if (settings.embedMetadata) ...[
|
||||
SettingsItem(
|
||||
icon: Icons.people_alt_outlined,
|
||||
title: context.l10n.optionsArtistTagMode,
|
||||
subtitle: _getArtistTagModeLabel(
|
||||
context,
|
||||
settings.artistTagMode,
|
||||
),
|
||||
onTap: () =>
|
||||
_showArtistTagModePicker(context, ref, settings.artistTagMode),
|
||||
),
|
||||
SettingsSwitchItem(
|
||||
icon: Icons.image,
|
||||
title: context.l10n.optionsMaxQualityCover,
|
||||
subtitle: context.l10n.optionsMaxQualityCoverSubtitle,
|
||||
value: settings.maxQualityCover,
|
||||
onChanged: (v) => ref
|
||||
.read(settingsProvider.notifier)
|
||||
.setMaxQualityCover(v),
|
||||
),
|
||||
SettingsSwitchItem(
|
||||
icon: Icons.graphic_eq,
|
||||
title: context.l10n.optionsReplayGain,
|
||||
subtitle: settings.embedReplayGain
|
||||
? context.l10n.optionsReplayGainSubtitleOn
|
||||
: context.l10n.optionsReplayGainSubtitleOff,
|
||||
value: settings.embedReplayGain,
|
||||
onChanged: (v) => ref
|
||||
.read(settingsProvider.notifier)
|
||||
.setEmbedReplayGain(v),
|
||||
showDivider: false,
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// ── Providers ─────────────────────────────────────────────
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsSectionHeader(
|
||||
title: context.l10n.sectionMetadataProviders,
|
||||
),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsGroup(
|
||||
children: [
|
||||
SettingsItem(
|
||||
icon: Icons.source_outlined,
|
||||
title: context.l10n.metadataProvidersTitle,
|
||||
subtitle: context.l10n.metadataProvidersSubtitle,
|
||||
onTap: () => Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute<void>(
|
||||
builder: (_) => const MetadataProviderPriorityPage(),
|
||||
),
|
||||
),
|
||||
showDivider: false,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// ── Deduplication ──────────────────────────────────────────
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsSectionHeader(
|
||||
title: context.l10n.sectionDuplicates,
|
||||
),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsGroup(
|
||||
children: [
|
||||
SettingsSwitchItem(
|
||||
icon: Icons.filter_list_outlined,
|
||||
title: context.l10n.downloadDeduplication,
|
||||
subtitle: settings.deduplicateDownloads
|
||||
? context.l10n.downloadDeduplicationEnabled
|
||||
: context.l10n.downloadDeduplicationDisabled,
|
||||
value: settings.deduplicateDownloads,
|
||||
onChanged: (value) => ref
|
||||
.read(settingsProvider.notifier)
|
||||
.setDeduplicateDownloads(value),
|
||||
showDivider: false,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
const SliverToBoxAdapter(child: SizedBox(height: 32)),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String _getArtistTagModeLabel(BuildContext context, String mode) {
|
||||
switch (mode) {
|
||||
case artistTagModeSplitVorbis:
|
||||
return context.l10n.optionsArtistTagModeSplitVorbis;
|
||||
default:
|
||||
return context.l10n.optionsArtistTagModeJoined;
|
||||
}
|
||||
}
|
||||
|
||||
void _showArtistTagModePicker(
|
||||
BuildContext context,
|
||||
WidgetRef ref,
|
||||
String currentMode,
|
||||
) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
showModalBottomSheet<void>(
|
||||
context: context,
|
||||
useRootNavigator: true,
|
||||
backgroundColor: colorScheme.surfaceContainerHigh,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(28)),
|
||||
),
|
||||
builder: (context) => SafeArea(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 24, 24, 8),
|
||||
child: Text(
|
||||
context.l10n.optionsArtistTagMode,
|
||||
style: Theme.of(context).textTheme.titleLarge
|
||||
?.copyWith(fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 0, 24, 16),
|
||||
child: Text(
|
||||
context.l10n.optionsArtistTagModeDescription,
|
||||
style: Theme.of(context).textTheme.bodyMedium
|
||||
?.copyWith(color: colorScheme.onSurfaceVariant),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.segment_outlined),
|
||||
title: Text(context.l10n.optionsArtistTagModeJoined),
|
||||
subtitle: Text(context.l10n.optionsArtistTagModeJoinedSubtitle),
|
||||
trailing: currentMode == artistTagModeJoined
|
||||
? const Icon(Icons.check)
|
||||
: null,
|
||||
onTap: () {
|
||||
ref
|
||||
.read(settingsProvider.notifier)
|
||||
.setArtistTagMode(artistTagModeJoined);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.library_music_outlined),
|
||||
title: Text(context.l10n.optionsArtistTagModeSplitVorbis),
|
||||
subtitle: Text(context.l10n.optionsArtistTagModeSplitVorbisSubtitle),
|
||||
trailing: currentMode == artistTagModeSplitVorbis
|
||||
? const Icon(Icons.check)
|
||||
: null,
|
||||
onTap: () {
|
||||
ref
|
||||
.read(settingsProvider.notifier)
|
||||
.setArtistTagMode(artistTagModeSplitVorbis);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,12 @@ import 'package:spotiflac_android/constants/app_info.dart';
|
||||
import 'package:spotiflac_android/l10n/l10n.dart';
|
||||
import 'package:spotiflac_android/screens/settings/appearance_settings_page.dart';
|
||||
import 'package:spotiflac_android/screens/settings/download_settings_page.dart';
|
||||
import 'package:spotiflac_android/screens/settings/files_settings_page.dart';
|
||||
import 'package:spotiflac_android/screens/settings/lyrics_settings_page.dart';
|
||||
import 'package:spotiflac_android/screens/settings/metadata_settings_page.dart';
|
||||
import 'package:spotiflac_android/screens/settings/extensions_page.dart';
|
||||
import 'package:spotiflac_android/screens/settings/library_settings_page.dart';
|
||||
import 'package:spotiflac_android/screens/settings/options_settings_page.dart';
|
||||
import 'package:spotiflac_android/screens/settings/app_settings_page.dart';
|
||||
import 'package:spotiflac_android/screens/settings/about_page.dart';
|
||||
import 'package:spotiflac_android/screens/settings/cache_management_page.dart';
|
||||
import 'package:spotiflac_android/screens/settings/donate_page.dart';
|
||||
@@ -48,7 +51,7 @@ class SettingsTab extends ConsumerWidget {
|
||||
title: Text(
|
||||
context.l10n.settingsTitle,
|
||||
style: TextStyle(
|
||||
fontSize: 20 + (14 * expandRatio), // 20 -> 34
|
||||
fontSize: 20 + (14 * expandRatio),
|
||||
fontWeight: FontWeight.bold,
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
@@ -58,6 +61,7 @@ class SettingsTab extends ConsumerWidget {
|
||||
),
|
||||
),
|
||||
|
||||
// ── Group 1: Appearance & Content ──────────────────────────────
|
||||
SliverToBoxAdapter(
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
@@ -72,6 +76,34 @@ class SettingsTab extends ConsumerWidget {
|
||||
onTap: () =>
|
||||
_navigateTo(context, const AppearanceSettingsPage()),
|
||||
),
|
||||
SettingsItem(
|
||||
icon: Icons.library_music_outlined,
|
||||
title: l10n.settingsLocalLibrary,
|
||||
subtitle: l10n.settingsLocalLibrarySubtitle,
|
||||
onTap: () =>
|
||||
_navigateTo(context, const LibrarySettingsPage()),
|
||||
),
|
||||
SettingsItem(
|
||||
icon: Icons.extension_outlined,
|
||||
title: l10n.settingsExtensions,
|
||||
subtitle: l10n.settingsExtensionsSubtitle,
|
||||
onTap: () => _navigateTo(context, const ExtensionsPage()),
|
||||
showDivider: false,
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
// ── Group 2: Download ──────────────────────────────────────────
|
||||
SliverToBoxAdapter(
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
final l10n = context.l10n;
|
||||
return SettingsGroup(
|
||||
margin: const EdgeInsets.fromLTRB(16, 4, 16, 4),
|
||||
children: [
|
||||
SettingsItem(
|
||||
icon: Icons.download_outlined,
|
||||
title: l10n.settingsDownload,
|
||||
@@ -80,12 +112,41 @@ class SettingsTab extends ConsumerWidget {
|
||||
_navigateTo(context, const DownloadSettingsPage()),
|
||||
),
|
||||
SettingsItem(
|
||||
icon: Icons.library_music_outlined,
|
||||
title: l10n.settingsLocalLibrary,
|
||||
subtitle: l10n.settingsLocalLibrarySubtitle,
|
||||
icon: Icons.folder_outlined,
|
||||
title: l10n.settingsFiles,
|
||||
subtitle: l10n.settingsFilesSubtitle,
|
||||
onTap: () =>
|
||||
_navigateTo(context, const LibrarySettingsPage()),
|
||||
_navigateTo(context, const FilesSettingsPage()),
|
||||
),
|
||||
SettingsItem(
|
||||
icon: Icons.sell_outlined,
|
||||
title: l10n.settingsMetadata,
|
||||
subtitle: l10n.settingsMetadataSubtitle,
|
||||
onTap: () =>
|
||||
_navigateTo(context, const MetadataSettingsPage()),
|
||||
),
|
||||
SettingsItem(
|
||||
icon: Icons.lyrics_outlined,
|
||||
title: l10n.settingsLyrics,
|
||||
subtitle: l10n.settingsLyricsSubtitle,
|
||||
onTap: () =>
|
||||
_navigateTo(context, const LyricsSettingsPage()),
|
||||
showDivider: false,
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
// ── Group 3: App ───────────────────────────────────────────────
|
||||
SliverToBoxAdapter(
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
final l10n = context.l10n;
|
||||
return SettingsGroup(
|
||||
margin: const EdgeInsets.fromLTRB(16, 4, 16, 4),
|
||||
children: [
|
||||
SettingsItem(
|
||||
icon: Icons.storage_outlined,
|
||||
title: l10n.settingsCache,
|
||||
@@ -95,41 +156,22 @@ class SettingsTab extends ConsumerWidget {
|
||||
),
|
||||
SettingsItem(
|
||||
icon: Icons.tune_outlined,
|
||||
title: l10n.settingsOptions,
|
||||
subtitle: l10n.settingsOptionsSubtitle,
|
||||
title: l10n.settingsApp,
|
||||
subtitle: l10n.settingsAppSubtitle,
|
||||
onTap: () =>
|
||||
_navigateTo(context, const OptionsSettingsPage()),
|
||||
_navigateTo(context, const AppSettingsPage()),
|
||||
),
|
||||
SettingsItem(
|
||||
icon: Icons.extension_outlined,
|
||||
title: l10n.settingsExtensions,
|
||||
subtitle: l10n.settingsExtensionsSubtitle,
|
||||
onTap: () => _navigateTo(context, const ExtensionsPage()),
|
||||
icon: Icons.article_outlined,
|
||||
title: l10n.logTitle,
|
||||
subtitle: l10n.settingsLogsSubtitle,
|
||||
onTap: () => _navigateTo(context, const LogScreen()),
|
||||
),
|
||||
SettingsItem(
|
||||
icon: Icons.favorite_outline,
|
||||
title: l10n.settingsDonate,
|
||||
subtitle: l10n.settingsDonateSubtitle,
|
||||
onTap: () => _navigateTo(context, const DonatePage()),
|
||||
showDivider: false,
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
SliverToBoxAdapter(
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
final l10n = context.l10n;
|
||||
return SettingsGroup(
|
||||
children: [
|
||||
SettingsItem(
|
||||
icon: Icons.article_outlined,
|
||||
title: l10n.logTitle,
|
||||
subtitle: l10n.settingsLogsSubtitle,
|
||||
onTap: () => _navigateTo(context, const LogScreen()),
|
||||
),
|
||||
SettingsItem(
|
||||
icon: Icons.info_outline,
|
||||
|
||||
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 71 KiB |