fix: completar migracion i18n de literales visibles
Build & Deploy PluriWave / Análisis de código (push) Failing after 28s
Build & Deploy PluriWave / Build APK + AAB release (push) Has been skipped

This commit is contained in:
Javier Bautista Fernández
2026-06-03 13:43:13 +02:00
parent 7abc8c3b0f
commit 643ba1eb45
20 changed files with 1572 additions and 635 deletions
+32 -49
View File
@@ -11,6 +11,7 @@ import 'package:uuid/uuid.dart';
import '../estado/estado_idioma.dart';
import '../estado/estado_radio.dart';
import '../l10n/app_localizations_ext.dart';
import '../l10n/gen/app_localizations.dart';
import '../modelos/emisora.dart';
import '../modelos/grupo_favoritos.dart';
@@ -982,7 +983,7 @@ class _SeccionEmisoras extends StatelessWidget {
const Spacer(),
TextButton.icon(
icon: const Icon(Icons.add),
label: const Text('Añadir'),
label: Text(AppLocalizations.of(context).customStationsAdd),
onPressed: () => _mostrarFormularioAnadir(context),
),
],
@@ -1079,6 +1080,7 @@ class _FormularioEmisoraState extends State<_FormularioEmisora> {
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context);
final bottom = MediaQuery.of(context).viewInsets.bottom;
return Padding(
padding: EdgeInsets.fromLTRB(
@@ -1094,7 +1096,7 @@ class _FormularioEmisoraState extends State<_FormularioEmisora> {
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'Añadir emisora',
l10n.addStationTitle,
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 16),
@@ -1121,19 +1123,19 @@ class _FormularioEmisoraState extends State<_FormularioEmisora> {
keyboardType: TextInputType.url,
validator: (v) {
if (v == null || v.trim().isEmpty) {
return AppLocalizations.of(context).requiredField;
return l10n.requiredField;
}
final uri = Uri.tryParse(v.trim());
if (uri == null || !uri.hasScheme) return 'URL no válida';
if (uri == null || !uri.hasScheme) return l10n.invalidUrl;
return null;
},
),
const SizedBox(height: 12),
TextFormField(
controller: _paisCtrl,
decoration: const InputDecoration(
labelText: 'País (opcional)',
border: OutlineInputBorder(),
decoration: InputDecoration(
labelText: l10n.countryOptionalLabel,
border: const OutlineInputBorder(),
),
),
const SizedBox(height: 20),
@@ -1170,9 +1172,10 @@ class _SeccionBackup extends StatelessWidget {
await Share.shareXFiles(
[XFile(file.path)],
subject: 'PluriWave — copia de seguridad',
text:
'Configuración de PluriWave exportada el ${DateTime.now().toLocal()}',
subject: AppLocalizations.of(context).backupShareSubject,
text: AppLocalizations.of(
context,
).backupShareText(DateTime.now().toLocal()),
);
} catch (e) {
if (context.mounted) {
@@ -1204,9 +1207,9 @@ class _SeccionBackup extends StatelessWidget {
context: context,
builder:
(ctx) => AlertDialog(
title: const Text('Importar configuración'),
content: const Text(
'Esto añadirá los favoritos, emisoras y presets del fichero. ¿Continuar?',
title: Text(AppLocalizations.of(ctx).backupImportTitle),
content: Text(
AppLocalizations.of(ctx).backupImportConfirmMessage,
),
actions: [
TextButton(
@@ -1226,8 +1229,8 @@ class _SeccionBackup extends StatelessWidget {
final messenger = ScaffoldMessenger.of(context);
await estado.importarConfig(json);
messenger.showSnackBar(
const SnackBar(
content: Text('Configuración importada correctamente'),
SnackBar(
content: Text(AppLocalizations.of(context).backupImportSuccess),
),
);
}
@@ -1264,14 +1267,14 @@ class _SeccionBackup extends StatelessWidget {
ListTile(
contentPadding: EdgeInsets.zero,
leading: const Icon(Icons.upload_outlined),
title: const Text('Exportar configuración'),
title: Text(AppLocalizations.of(context).backupExportTitle),
subtitle: Text(AppLocalizations.of(context).backupExportSubtitle),
onTap: () => _exportar(context),
),
ListTile(
contentPadding: EdgeInsets.zero,
leading: const Icon(Icons.download_outlined),
title: const Text('Importar configuración'),
title: Text(AppLocalizations.of(context).backupImportTitle),
subtitle: Text(AppLocalizations.of(context).backupImportSubtitle),
onTap: () => _importar(context),
),
@@ -1297,14 +1300,14 @@ class _SeccionInfo extends StatelessWidget {
final version =
snap.hasData
? 'v${snap.data!.version}+${snap.data!.buildNumber}'
: 'Cargando versión...';
: AppLocalizations.of(ctx).appVersionLoading;
return ListTile(
contentPadding: EdgeInsets.zero,
leading: const PluriIcon(
glyph: PluriIconGlyph.settings,
variant: PluriIconVariant.filled,
),
title: const Text('PluriWave'),
title: Text(AppLocalizations.of(ctx).appTitle),
subtitle: Text(
AppLocalizations.of(ctx).appVersionSubtitle(version),
),
@@ -1321,7 +1324,7 @@ class _SeccionInfo extends StatelessWidget {
AppLocalizations.of(ctx).savedFavoritesTitle,
),
trailing: Text(
snap.data?.toString() ?? '',
snap.data?.toString() ?? AppLocalizations.of(ctx).dash,
style: Theme.of(ctx).textTheme.bodyLarge,
),
),
@@ -1329,8 +1332,8 @@ class _SeccionInfo extends StatelessWidget {
ListTile(
contentPadding: EdgeInsets.zero,
leading: const Icon(Icons.help_outline_rounded),
title: Text(_helpTitle(ctx)),
subtitle: Text(_helpSubtitle(ctx)),
title: Text(AppLocalizations.of(ctx).helpTitle),
subtitle: Text(AppLocalizations.of(ctx).helpSubtitle),
trailing: const Icon(Icons.chevron_right_rounded),
onTap: () => PluriOnboardingDialog.mostrar(ctx),
),
@@ -1343,12 +1346,14 @@ class _SeccionInfo extends StatelessWidget {
),
trailing: const Icon(Icons.check_circle, color: Colors.green),
),
const ListTile(
ListTile(
contentPadding: EdgeInsets.zero,
leading: Icon(Icons.music_note_outlined),
title: Text('Audio en background'),
subtitle: Text('Continúa al apagar la pantalla'),
trailing: Icon(Icons.check_circle, color: Colors.green),
leading: const Icon(Icons.music_note_outlined),
title: Text(AppLocalizations.of(ctx).backgroundAudioTitle),
subtitle: Text(
AppLocalizations.of(ctx).backgroundAudioSubtitle,
),
trailing: const Icon(Icons.check_circle, color: Colors.green),
),
],
),
@@ -1357,28 +1362,6 @@ class _SeccionInfo extends StatelessWidget {
}
}
String _helpTitle(BuildContext context) => switch (Localizations.localeOf(
context,
).languageCode) {
'es' => 'Ayuda y tutorial',
'fr' => 'Aide et tutoriel',
'de' => 'Hilfe und Tutorial',
'it' => 'Aiuto e tutorial',
'pt' => 'Ajuda e tutorial',
_ => 'Help and tutorial',
};
String _helpSubtitle(BuildContext context) => switch (Localizations.localeOf(
context,
).languageCode) {
'es' => 'Repasá funciones, consejos y novedades de PluriWave.',
'fr' => 'Revoyez les fonctions, conseils et nouveautés de PluriWave.',
'de' => 'Funktionen, Tipps und Neuigkeiten von PluriWave ansehen.',
'it' => 'Rivedi funzioni, consigli e novità di PluriWave.',
'pt' => 'Revê funções, dicas e novidades do PluriWave.',
_ => 'Review PluriWave features, tips and whats new.',
};
String _formatearDuracionTimer(Duration duracion) {
final horas = duracion.inHours;
final minutos = duracion.inMinutes.remainder(60);