fix(i18n): normalize translations and fallbacks
Build & Deploy PluriWave / Análisis de código (push) Successful in 38s
Build & Deploy PluriWave / Build APK + AAB release (push) Successful in 2m34s

This commit is contained in:
2026-06-03 21:20:08 +02:00
parent a5475ce118
commit 089b8b4227
46 changed files with 17720 additions and 4869 deletions
+34 -13
View File
@@ -1,9 +1,12 @@
import 'dart:async';
import 'dart:developer' as developer;
import 'dart:ui' show Locale;
import 'package:audio_service/audio_service.dart';
import 'package:just_audio/just_audio.dart';
import '../l10n/display_names.dart';
import '../l10n/gen/app_localizations.dart';
import '../modelos/emisora.dart';
import '../modelos/preset_ecualizador.dart';
@@ -31,6 +34,10 @@ class ServicioAudio {
Emisora? get emisoraActual => _handler.emisoraActual;
void configurarLocalizaciones(AppLocalizations l10n) {
_handler.configurarLocalizaciones(l10n);
}
Stream<EstadoReproduccion> get estadoStream =>
_handler.playbackState.map((s) {
if (s.processingState == AudioProcessingState.error) {
@@ -50,7 +57,10 @@ class ServicioAudio {
Future<void> reproducir(Emisora emisora) async {
final item = MediaItem(
id: emisora.url,
title: emisora.nombre,
title: localizedStationName(
lookupAppLocalizations(const Locale('es')),
emisora.nombre,
),
artist: emisora.pais ?? '',
album: 'PluriWave',
artUri:
@@ -118,6 +128,7 @@ class PluriWaveAudioHandler extends BaseAudioHandler with SeekHandler {
Emisora? emisoraActual;
double _volumen = 1.0;
double get volumen => _volumen;
AppLocalizations? _l10n;
AndroidEqualizer? get ecualizador => _eq;
bool _eqDisponible = false;
@@ -135,6 +146,16 @@ class PluriWaveAudioHandler extends BaseAudioHandler with SeekHandler {
_conectarStreamsPlayer();
}
AppLocalizations get _textos {
final actual = _l10n;
if (actual != null) return actual;
return lookupAppLocalizations(const Locale('es'));
}
void configurarLocalizaciones(AppLocalizations l10n) {
_l10n = l10n;
}
AudioPlayer _crearPlayer() {
return AudioPlayer(
audioPipeline: AudioPipeline(androidAudioEffects: [_eq]),
@@ -192,7 +213,7 @@ class PluriWaveAudioHandler extends BaseAudioHandler with SeekHandler {
mensaje = _mensajeAmigable(error);
} else {
codigoLog = 'Error desconocido: $error';
mensaje = 'Error de reproducción';
mensaje = _textos.audioErrorGeneric;
}
developer.log(
@@ -219,30 +240,30 @@ class PluriWaveAudioHandler extends BaseAudioHandler with SeekHandler {
final code = e.code;
if (code >= 2000 && code < 3000) {
if (code == 2001) return 'Sin conexión a internet';
if (code == 2002) return 'La URL de la radio no es válida';
if (code == 2003) return 'La radio no está disponible (error 404)';
if (code == 2004) return 'Tiempo de espera agotado al conectar';
return 'No se puede conectar a la radio';
if (code == 2001) return _textos.audioErrorNoInternet;
if (code == 2002) return _textos.audioErrorInvalidUrl;
if (code == 2003) return _textos.audioErrorNotFound;
if (code == 2004) return _textos.audioErrorTimeout;
return _textos.audioErrorCannotConnect;
}
if (code >= 3000 && code < 4000) {
return 'Formato de stream no compatible';
return _textos.audioErrorUnsupportedFormat;
}
if (code >= 4000 && code < 5000) {
return 'Error al decodificar el stream de audio';
return _textos.audioErrorDecode;
}
final msg = e.message ?? '';
if (msg.contains('Cleartext') || msg.contains('cleartext')) {
return 'Esta radio usa HTTP sin cifrar (no permitido)';
return _textos.audioErrorCleartext;
}
if (msg.contains('CERTIFICATE') || msg.contains('HandshakeException')) {
return 'Certificado SSL inválido en la radio';
return _textos.audioErrorSsl;
}
return 'No se puede reproducir esta radio';
return _textos.audioErrorCannotPlay;
}
AudioProcessingState _mapProcState(ProcessingState state) {
@@ -300,7 +321,7 @@ class PluriWaveAudioHandler extends BaseAudioHandler with SeekHandler {
playbackState.value.copyWith(
processingState: AudioProcessingState.error,
playing: false,
errorMessage: 'Error inesperado al reproducir',
errorMessage: _textos.audioErrorUnexpectedPlayback,
),
);
emisoraActual = null;