mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-07-02 11:05:38 +02:00
l10n: localize settings, store, and metadata UI strings
Wire remaining hardcoded strings in about, download region picker, file organization settings, extension repo snackbars, release type badges, metadata queue actions, online cover labels, and update changelog fallback.
This commit is contained in:
@@ -1967,7 +1967,9 @@ class _ArtistScreenState extends ConsumerState<ArtistScreen> {
|
||||
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,
|
||||
|
||||
@@ -608,8 +608,8 @@ class _RepoTabState extends ConsumerState<RepoTab> {
|
||||
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<RepoTab> {
|
||||
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,
|
||||
),
|
||||
|
||||
@@ -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,
|
||||
),
|
||||
|
||||
@@ -281,7 +281,10 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
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<DownloadSettingsPage> {
|
||||
);
|
||||
}
|
||||
|
||||
String _getSongLinkRegionLabel(String code) {
|
||||
const names = <String, String>{
|
||||
'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<DownloadSettingsPage> {
|
||||
'ZM',
|
||||
'ZW',
|
||||
];
|
||||
const names = <String, String>{
|
||||
'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<void>(
|
||||
@@ -821,9 +828,12 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
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,
|
||||
|
||||
@@ -424,11 +424,14 @@ class _FilesSettingsPageState extends ConsumerState<FilesSettingsPage> {
|
||||
required bool usePrimaryArtistOnly,
|
||||
required bool filterAlbumArtistContributors,
|
||||
}) {
|
||||
final l10n = context.l10n;
|
||||
final statuses = <String>[
|
||||
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(' | ');
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ class _ResolvedAutoFillTrack {
|
||||
}
|
||||
|
||||
class _EditMetadataSheet extends StatefulWidget {
|
||||
static const _onlineCoverSentinel = '__online_cover__';
|
||||
final ColorScheme colorScheme;
|
||||
final Map<String, String> 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),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -223,7 +223,10 @@ class _UpdateDialogState extends State<UpdateDialog> {
|
||||
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<UpdateDialog> {
|
||||
}
|
||||
|
||||
/// 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<UpdateDialog> {
|
||||
formatted = '${formatted.substring(0, 2000)}...';
|
||||
}
|
||||
|
||||
return formatted.isEmpty ? 'See release notes for details.' : formatted;
|
||||
return formatted.isEmpty ? emptyFallback : formatted;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user