diff --git a/lib/screens/artist_screen.dart b/lib/screens/artist_screen.dart index 6dee6e2a..457a9ead 100644 --- a/lib/screens/artist_screen.dart +++ b/lib/screens/artist_screen.dart @@ -1967,7 +1967,9 @@ class _ArtistScreenState extends ConsumerState { borderRadius: BorderRadius.circular(4), ), child: Text( - album.albumType == 'ep' ? 'EP' : 'Single', + album.albumType == 'ep' + ? context.l10n.releaseTypeEp + : context.l10n.releaseTypeSingle, style: const TextStyle( color: Colors.white, fontSize: 10, diff --git a/lib/screens/repo_tab.dart b/lib/screens/repo_tab.dart index 8fef33b4..3de5b60c 100644 --- a/lib/screens/repo_tab.dart +++ b/lib/screens/repo_tab.dart @@ -608,8 +608,8 @@ class _RepoTabState extends ConsumerState { SnackBar( content: Text( success - ? '${ext.displayName} installed. Enable it in Settings > Extensions' - : 'Failed to install ${ext.displayName}', + ? context.l10n.snackbarExtensionInstalledEnable(ext.displayName) + : context.l10n.snackbarFailedToInstallNamed(ext.displayName), ), behavior: SnackBarBehavior.floating, ), @@ -629,8 +629,11 @@ class _RepoTabState extends ConsumerState { SnackBar( content: Text( success - ? '${ext.displayName} updated to v${ext.version}' - : 'Failed to update ${ext.displayName}', + ? context.l10n.snackbarExtensionUpdatedVersion( + ext.displayName, + ext.version, + ) + : context.l10n.snackbarFailedToUpdateNamed(ext.displayName), ), behavior: SnackBarBehavior.floating, ), diff --git a/lib/screens/settings/about_page.dart b/lib/screens/settings/about_page.dart index 3c1d4f61..6713c2f4 100644 --- a/lib/screens/settings/about_page.dart +++ b/lib/screens/settings/about_page.dart @@ -140,9 +140,7 @@ class AboutPage extends StatelessWidget { _AboutSettingsItem( icon: Icons.lyrics_outlined, title: 'Paxsenix', - subtitle: - 'Lyrics proxy for Musixmatch, Netease, Apple Music, ' - 'QQ Music, Spotify, Deezer, YouTube, Kugou, and Genius', + subtitle: context.l10n.aboutPaxsenixSubtitle, onTap: () => _launchUrl('https://lyrics.paxsenix.org'), showDivider: false, ), diff --git a/lib/screens/settings/download_settings_page.dart b/lib/screens/settings/download_settings_page.dart index ba91f0ba..01bbe84f 100644 --- a/lib/screens/settings/download_settings_page.dart +++ b/lib/screens/settings/download_settings_page.dart @@ -281,7 +281,10 @@ class _DownloadSettingsPageState extends ConsumerState { SettingsItem( icon: Icons.public, title: context.l10n.downloadSongLinkRegion, - subtitle: _getSongLinkRegionLabel(settings.songLinkRegion), + subtitle: _getSongLinkRegionLabel( + context, + settings.songLinkRegion, + ), onTap: () => _showSongLinkRegionPicker( context, ref, @@ -309,26 +312,45 @@ class _DownloadSettingsPageState extends ConsumerState { ); } - String _getSongLinkRegionLabel(String code) { - const names = { - 'US': 'United States', - 'GB': 'United Kingdom', - 'FR': 'France', - 'DE': 'Germany', - 'JP': 'Japan', - 'KR': 'South Korea', - 'IN': 'India', - 'ID': 'Indonesia', - 'BR': 'Brazil', - 'MX': 'Mexico', - 'AU': 'Australia', - 'CA': 'Canada', - 'XK': 'Kosovo', - }; + String _regionCountryName(BuildContext context, String code) { + final l10n = context.l10n; + switch (code) { + case 'US': + return l10n.regionCountryUS; + case 'GB': + return l10n.regionCountryGB; + case 'FR': + return l10n.regionCountryFR; + case 'DE': + return l10n.regionCountryDE; + case 'JP': + return l10n.regionCountryJP; + case 'KR': + return l10n.regionCountryKR; + case 'IN': + return l10n.regionCountryIN; + case 'ID': + return l10n.regionCountryID; + case 'BR': + return l10n.regionCountryBR; + case 'MX': + return l10n.regionCountryMX; + case 'AU': + return l10n.regionCountryAU; + case 'CA': + return l10n.regionCountryCA; + case 'XK': + return l10n.regionCountryXK; + default: + return code; + } + } + + String _getSongLinkRegionLabel(BuildContext context, String code) { final normalized = code.trim().toUpperCase(); final effective = normalized.isEmpty ? 'US' : normalized; - final name = names[effective]; - return name == null ? effective : '$effective - $name'; + final name = _regionCountryName(context, effective); + return name == effective ? effective : '$effective - $name'; } IconData _qualityIcon(String qualityId) { @@ -766,21 +788,6 @@ class _DownloadSettingsPageState extends ConsumerState { 'ZM', 'ZW', ]; - const names = { - 'US': 'United States', - 'GB': 'United Kingdom', - 'FR': 'France', - 'DE': 'Germany', - 'JP': 'Japan', - 'KR': 'South Korea', - 'IN': 'India', - 'ID': 'Indonesia', - 'BR': 'Brazil', - 'MX': 'Mexico', - 'AU': 'Australia', - 'CA': 'Canada', - 'XK': 'Kosovo', - }; final colorScheme = Theme.of(context).colorScheme; final normalizedCurrent = current.trim().toUpperCase(); showModalBottomSheet( @@ -821,9 +828,12 @@ class _DownloadSettingsPageState extends ConsumerState { itemBuilder: (context, index) { final code = regions[index]; final isSelected = code == normalizedCurrent; + final countryName = _regionCountryName(context, code); return ListTile( title: Text(code), - subtitle: names[code] != null ? Text(names[code]!) : null, + subtitle: countryName != code + ? Text(countryName) + : null, trailing: isSelected ? Icon(Icons.check, color: colorScheme.primary) : null, diff --git a/lib/screens/settings/files_settings_page.dart b/lib/screens/settings/files_settings_page.dart index 52165d58..3c49ee08 100644 --- a/lib/screens/settings/files_settings_page.dart +++ b/lib/screens/settings/files_settings_page.dart @@ -424,11 +424,14 @@ class _FilesSettingsPageState extends ConsumerState { required bool usePrimaryArtistOnly, required bool filterAlbumArtistContributors, }) { + final l10n = context.l10n; final statuses = [ - usePrimaryArtistOnly ? 'Primary only: On' : 'Primary only: Off', + usePrimaryArtistOnly + ? l10n.downloadPrimaryArtistOnlyOn + : l10n.downloadPrimaryArtistOnlyOff, filterAlbumArtistContributors - ? 'Album Artist metadata: Primary only' - : 'Album Artist metadata: Full', + ? l10n.downloadAlbumArtistMetadataPrimaryOnly + : l10n.downloadAlbumArtistMetadataFull, ]; return statuses.join(' | '); } diff --git a/lib/screens/track_metadata_edit_sheet.dart b/lib/screens/track_metadata_edit_sheet.dart index 01ce0606..63ea7139 100644 --- a/lib/screens/track_metadata_edit_sheet.dart +++ b/lib/screens/track_metadata_edit_sheet.dart @@ -8,6 +8,7 @@ class _ResolvedAutoFillTrack { } class _EditMetadataSheet extends StatefulWidget { + static const _onlineCoverSentinel = '__online_cover__'; final ColorScheme colorScheme; final Map initialValues; final String filePath; @@ -941,7 +942,7 @@ class _EditMetadataSheetState extends State<_EditMetadataSheet> { setState(() { _selectedCoverPath = coverOutput; _selectedCoverTempDir = tempDir.path; - _selectedCoverName = 'Online cover'; + _selectedCoverName = _EditMetadataSheet._onlineCoverSentinel; }); filledCount++; } @@ -1623,8 +1624,11 @@ class _EditMetadataSheetState extends State<_EditMetadataSheet> { child: _buildCoverPreviewTile( cs: cs, path: _selectedCoverPath!, - label: - _selectedCoverName ?? context.l10n.trackCoverSelected, + label: _selectedCoverName == + _EditMetadataSheet._onlineCoverSentinel + ? context.l10n.trackCoverOnline + : (_selectedCoverName ?? + context.l10n.trackCoverSelected), ), ), ], diff --git a/lib/widgets/update_dialog.dart b/lib/widgets/update_dialog.dart index b015a293..0c6d8c67 100644 --- a/lib/widgets/update_dialog.dart +++ b/lib/widgets/update_dialog.dart @@ -223,7 +223,10 @@ class _UpdateDialogState extends State { child: SingleChildScrollView( padding: const EdgeInsets.all(16), child: Text( - _formatChangelog(widget.updateInfo.changelog), + _formatChangelog( + widget.updateInfo.changelog, + context.l10n.updateSeeReleaseNotes, + ), style: Theme.of(context).textTheme.bodySmall?.copyWith(height: 1.5), ), ), @@ -299,7 +302,7 @@ class _UpdateDialogState extends State { } /// Format changelog - clean up markdown and extract relevant content - String _formatChangelog(String changelog) { + String _formatChangelog(String changelog, String emptyFallback) { var content = changelog; final whatsNewMatch = _whatsNewPattern.firstMatch(content); @@ -352,7 +355,7 @@ class _UpdateDialogState extends State { formatted = '${formatted.substring(0, 2000)}...'; } - return formatted.isEmpty ? 'See release notes for details.' : formatted; + return formatted.isEmpty ? emptyFallback : formatted; } }