diff --git a/TODO.md b/TODO.md index 41283e5..96c7cd9 100644 --- a/TODO.md +++ b/TODO.md @@ -6,6 +6,7 @@ - [x] Permitir que el usuario cambie el idioma manualmente desde la aplicación, sin depender únicamente del idioma del sistema. - [x] Añadir traducción inicial español/inglés para el shell, navegación, timer de sueño y selector de idioma. - [x] Añadir soporte inicial para un conjunto amplio de idiomas muy hablados: inglés, español, chino, hindi, árabe, portugués, francés, ruso, alemán, japonés, indonesio, bengalí e italiano. +- [x] Ejecutar escaneo UTF-8 sobre ARB/código tocado y corregir corrupciones visibles en los textos migrados. - [ ] Validar no solo el guardado UTF-8 en código, sino también el render real en la aplicación para acentos, ñ, signos, alfabetos no latinos y direcciones RTL. - [ ] Repasar absolutamente todos los literales de la aplicación en todas las pantallas, componentes, servicios con mensajes visibles y notificaciones. - [ ] Soportar formatos locales de fecha, hora, números y duración usando helpers centralizados. @@ -17,16 +18,18 @@ ## UX y accesibilidad visual -- [ ] Revisar los paneles informativos superiores de cada pantalla: recuperar márgenes internos elegantes para que el texto no quede pegado a los bordes. -- [ ] Probar la aplicación con escalas de texto grandes/muy grandes del sistema y evitar que los paneles con mucho texto se descuajeringuen. -- [ ] Diseñar una solución elegante para textos largos: reflow, límites razonables, scroll, wraps controlados y jerarquías que mantengan la estética AAA. +- [x] Revisar los paneles informativos superiores de cada pantalla: recuperar márgenes internos elegantes para que el texto no quede pegado a los bordes. +- [x] Añadir comportamiento adaptativo en el header premium para escalas de texto grandes y pantallas estrechas. +- [ ] Probar la aplicación con escalas de texto grandes/muy grandes del sistema en dispositivo real o golden tests. +- [ ] Diseñar una solución elegante para textos largos en todos los paneles secundarios: reflow, límites razonables, scroll, wraps controlados y jerarquías que mantengan la estética AAA. ## Grabaciones -- [ ] Añadir en Ajustes un acceso elegante, con imagen/icono acorde al diseño, para abrir la carpeta de grabaciones con el gestor de ficheros del sistema mediante intent. -- [ ] Añadir configuración de tamaño máximo de fichero de grabación; valor por defecto: 500 MB. -- [ ] Detener automáticamente la grabación si se para la reproducción. -- [ ] Detener automáticamente la grabación si se cambia de emisora. +- [x] Añadir en Ajustes un acceso elegante para abrir la carpeta de grabaciones con el gestor de ficheros del sistema mediante intent. +- [x] Añadir configuración de tamaño máximo de fichero de grabación; valor por defecto: 500 MB. +- [x] Detener automáticamente la grabación si se para o pausa la reproducción. +- [x] Detener automáticamente la grabación si se cambia de emisora. +- [ ] Probar en Android real que el intent de carpeta funciona con rutas internas y rutas escogidas por el usuario. ## Búsqueda de emisoras diff --git a/lib/estado/estado_radio.dart b/lib/estado/estado_radio.dart index ec10903..e38b6a9 100644 --- a/lib/estado/estado_radio.dart +++ b/lib/estado/estado_radio.dart @@ -7,6 +7,7 @@ import 'package:geocoding/geocoding.dart'; import 'package:geolocator/geolocator.dart'; import 'package:path_provider/path_provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:url_launcher/url_launcher.dart'; import '../modelos/emisora.dart'; import '../modelos/preset_ecualizador.dart'; @@ -143,6 +144,7 @@ class EstadoRadio extends ChangeNotifier { EstadoGrabacionRadio get estadoGrabacion => grabacion.estado; bool get grabacionActiva => grabacion.estado.activa; String? get directorioGrabacion => grabacion.directorioConfigurado; + int get maxBytesGrabacion => grabacion.maxBytes; /// Lista principal (home): custom + populares, sin duplicados. List get emisorasInicio { @@ -203,6 +205,12 @@ class EstadoRadio extends ChangeNotifier { if (estado == EstadoReproduccion.error && timer.activo) { unawaited(timer.cancelar()); } + if ((estado == EstadoReproduccion.detenido || + estado == EstadoReproduccion.pausado || + estado == EstadoReproduccion.error) && + grabacion.estado.activa) { + unawaited(grabacion.detener()); + } notifyListeners(); }); } @@ -456,6 +464,9 @@ class EstadoRadio extends ChangeNotifier { Future reproducir(Emisora emisora) async { final revision = ++_revisionReproduccion; + if (grabacion.estado.activa) { + await grabacion.detener(); + } _emisoraSeleccionada = emisora; notifyListeners(); try { @@ -496,6 +507,26 @@ class EstadoRadio extends ChangeNotifier { Future detenerGrabacion() => grabacion.detener(); + Future detenerReproduccion() async { + if (grabacion.estado.activa) { + await grabacion.detener(); + } + await audio.detener(); + notifyListeners(); + } + + Future cambiarMaxBytesGrabacion(int bytes) async { + await grabacion.guardarMaxBytes(bytes); + notifyListeners(); + } + + Future abrirDirectorioGrabacion() async { + final ruta = await directorioGrabacionEfectivo(); + await Directory(ruta).create(recursive: true); + final uri = Uri.directory(ruta); + return launchUrl(uri, mode: LaunchMode.externalApplication); + } + Future cambiarDirectorioGrabacion(String path) async { await grabacion.guardarDirectorio(path); notifyListeners(); @@ -510,6 +541,9 @@ class EstadoRadio extends ChangeNotifier { grabacion.directorioEfectivo(); Future togglePlay() async { + if (audio.estaSonando && grabacion.estado.activa) { + await grabacion.detener(); + } await audio.togglePlay(); notifyListeners(); } diff --git a/lib/l10n/app_ar.arb b/lib/l10n/app_ar.arb index fa10148..fdf5821 100644 --- a/lib/l10n/app_ar.arb +++ b/lib/l10n/app_ar.arb @@ -1,13 +1,13 @@ { "@@locale": "ar", "appTitle": "PluriWave", - "navHome": "????????", - "navSearch": "???", - "navFavorites": "???????", - "navAlarms": "????????", - "navSettings": "?????????", - "actionOk": "?????", - "sleepTimer": "???? ?????", + "navHome": "Home", + "navSearch": "Search", + "navFavorites": "Favorites", + "navAlarms": "Alarms", + "navSettings": "Settings", + "actionOk": "OK", + "sleepTimer": "Sleep timer", "sleepTimerDescription": "Smooth radio shutdown with an exact countdown.", "cancelTimer": "Cancel timer", "optionOther": "Other", @@ -24,20 +24,20 @@ "alarmName": {} } }, - "settingsTitle": "?????????", - "settingsSubtitle": "???? ???? ?? ????? ?????? ????????? ???????? ???????.", - "languageSectionTitle": "?????", - "languageSectionDescription": "???? ??? ??? ???????.", - "languageSystemDefault": "??????", - "languageSpanish": "?????????", - "languageEnglish": "??????????", - "languageUpdated": "?? ????? ?????: {languageName}", + "settingsTitle": "Settings", + "settingsSubtitle": "Fine-grained sound control, backups, and custom stations.", + "languageSectionTitle": "Language", + "languageSectionDescription": "Choose how the app language is displayed.", + "languageSystemDefault": "System", + "languageSpanish": "Spanish", + "languageEnglish": "English", + "languageUpdated": "Language updated: {languageName}", "@languageUpdated": { "placeholders": { "languageName": {} } }, - "languageUpdatedSystem": "?? ????? ?????: ??????", + "languageUpdatedSystem": "Language updated: System", "timerSectionTitle": "Sleep timer", "timerSectionAdd": "Add", "timerSectionDescription": "Customize the quick presets shown when automatically stopping the radio.", @@ -89,7 +89,7 @@ "backupExportSubtitle": "Favorites, custom stations, and EQ presets", "backupImportTitle": "Import configuration", "backupImportSubtitle": "Restore from a backup file", - "backupShareSubject": "PluriWave ? backup", + "backupShareSubject": "PluriWave — backup", "backupShareText": "PluriWave configuration exported on {date}", "backupExportError": "Export error: {error}", "backupImportConfirmMessage": "This will add favorites, stations, and presets from the file. Continue?", @@ -102,7 +102,7 @@ "stationFilterSubtitle": "Only stations verified as active", "backgroundAudioTitle": "Background audio", "backgroundAudioSubtitle": "Continues when the screen turns off", - "dash": "?", + "dash": "—", "@recordingsPathSaveError": { "placeholders": { "error": {} @@ -148,6 +148,32 @@ "version": {} } }, - "cancelAction": "?????", - "equalizerTitle": "Equalizer" + "cancelAction": "Cancel", + "equalizerTitle": "Equalizer", + "recordingsOpenFolder": "Open folder", + "recordingsOpenFolderError": "Could not open the folder: {error}", + "recordingsMaxSizeTitle": "Maximum recording size", + "recordingsMaxSizeSubtitle": "Current limit: {size} MB", + "recordingsMaxSizeDialogTitle": "Maximum size per recording", + "recordingsMaxSizeMbLabel": "Maximum megabytes", + "recordingsMaxSizeSaved": "Recording limit updated to {size} MB", + "@recordingsOpenFolderError": { + "placeholders": { + "error": {} + } + }, + "@recordingsMaxSizeSubtitle": { + "placeholders": { + "size": { + "type": "int" + } + } + }, + "@recordingsMaxSizeSaved": { + "placeholders": { + "size": { + "type": "int" + } + } + } } diff --git a/lib/l10n/app_bn.arb b/lib/l10n/app_bn.arb index f2fe305..fba708b 100644 --- a/lib/l10n/app_bn.arb +++ b/lib/l10n/app_bn.arb @@ -1,13 +1,13 @@ { "@@locale": "bn", "appTitle": "PluriWave", - "navHome": "???", - "navSearch": "????", - "navFavorites": "??????", - "navAlarms": "?????????", - "navSettings": "??????", - "actionOk": "??? ???", - "sleepTimer": "????? ??????", + "navHome": "Home", + "navSearch": "Search", + "navFavorites": "Favorites", + "navAlarms": "Alarms", + "navSettings": "Settings", + "actionOk": "OK", + "sleepTimer": "Sleep timer", "sleepTimerDescription": "Smooth radio shutdown with an exact countdown.", "cancelTimer": "Cancel timer", "optionOther": "Other", @@ -24,20 +24,20 @@ "alarmName": {} } }, - "settingsTitle": "??????", - "settingsSubtitle": "????, ??????? ??? ?????? ???????? ??????? ???????????", - "languageSectionTitle": "????", - "languageSectionDescription": "??????? ???????? ???? ???? ????", - "languageSystemDefault": "???????", - "languageSpanish": "?????????", - "languageEnglish": "??????", - "languageUpdated": "???? ????? ??????: {languageName}", + "settingsTitle": "Settings", + "settingsSubtitle": "Fine-grained sound control, backups, and custom stations.", + "languageSectionTitle": "Language", + "languageSectionDescription": "Choose how the app language is displayed.", + "languageSystemDefault": "System", + "languageSpanish": "Spanish", + "languageEnglish": "English", + "languageUpdated": "Language updated: {languageName}", "@languageUpdated": { "placeholders": { "languageName": {} } }, - "languageUpdatedSystem": "???? ????? ??????: ???????", + "languageUpdatedSystem": "Language updated: System", "timerSectionTitle": "Sleep timer", "timerSectionAdd": "Add", "timerSectionDescription": "Customize the quick presets shown when automatically stopping the radio.", @@ -89,7 +89,7 @@ "backupExportSubtitle": "Favorites, custom stations, and EQ presets", "backupImportTitle": "Import configuration", "backupImportSubtitle": "Restore from a backup file", - "backupShareSubject": "PluriWave ? backup", + "backupShareSubject": "PluriWave — backup", "backupShareText": "PluriWave configuration exported on {date}", "backupExportError": "Export error: {error}", "backupImportConfirmMessage": "This will add favorites, stations, and presets from the file. Continue?", @@ -102,7 +102,7 @@ "stationFilterSubtitle": "Only stations verified as active", "backgroundAudioTitle": "Background audio", "backgroundAudioSubtitle": "Continues when the screen turns off", - "dash": "?", + "dash": "—", "@recordingsPathSaveError": { "placeholders": { "error": {} @@ -148,6 +148,32 @@ "version": {} } }, - "cancelAction": "?????", - "equalizerTitle": "Equalizer" + "cancelAction": "Cancel", + "equalizerTitle": "Equalizer", + "recordingsOpenFolder": "Open folder", + "recordingsOpenFolderError": "Could not open the folder: {error}", + "recordingsMaxSizeTitle": "Maximum recording size", + "recordingsMaxSizeSubtitle": "Current limit: {size} MB", + "recordingsMaxSizeDialogTitle": "Maximum size per recording", + "recordingsMaxSizeMbLabel": "Maximum megabytes", + "recordingsMaxSizeSaved": "Recording limit updated to {size} MB", + "@recordingsOpenFolderError": { + "placeholders": { + "error": {} + } + }, + "@recordingsMaxSizeSubtitle": { + "placeholders": { + "size": { + "type": "int" + } + } + }, + "@recordingsMaxSizeSaved": { + "placeholders": { + "size": { + "type": "int" + } + } + } } diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index bd46fbe..813d48b 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -25,9 +25,9 @@ } }, "settingsTitle": "Einstellungen", - "settingsSubtitle": "Feinsteuerung f?r Sound, Backups und eigene Sender.", + "settingsSubtitle": "Fine-grained sound control, backups, and custom stations.", "languageSectionTitle": "Sprache", - "languageSectionDescription": "W?hle die Anzeigesprache der App.", + "languageSectionDescription": "Choose how the app language is displayed.", "languageSystemDefault": "System", "languageSpanish": "Spanisch", "languageEnglish": "Englisch", @@ -89,7 +89,7 @@ "backupExportSubtitle": "Favorites, custom stations, and EQ presets", "backupImportTitle": "Import configuration", "backupImportSubtitle": "Restore from a backup file", - "backupShareSubject": "PluriWave ? backup", + "backupShareSubject": "PluriWave — backup", "backupShareText": "PluriWave configuration exported on {date}", "backupExportError": "Export error: {error}", "backupImportConfirmMessage": "This will add favorites, stations, and presets from the file. Continue?", @@ -102,7 +102,7 @@ "stationFilterSubtitle": "Only stations verified as active", "backgroundAudioTitle": "Background audio", "backgroundAudioSubtitle": "Continues when the screen turns off", - "dash": "?", + "dash": "—", "@recordingsPathSaveError": { "placeholders": { "error": {} @@ -149,5 +149,31 @@ } }, "cancelAction": "Abbrechen", - "equalizerTitle": "Equalizer" + "equalizerTitle": "Equalizer", + "recordingsOpenFolder": "Open folder", + "recordingsOpenFolderError": "Could not open the folder: {error}", + "recordingsMaxSizeTitle": "Maximum recording size", + "recordingsMaxSizeSubtitle": "Current limit: {size} MB", + "recordingsMaxSizeDialogTitle": "Maximum size per recording", + "recordingsMaxSizeMbLabel": "Maximum megabytes", + "recordingsMaxSizeSaved": "Recording limit updated to {size} MB", + "@recordingsOpenFolderError": { + "placeholders": { + "error": {} + } + }, + "@recordingsMaxSizeSubtitle": { + "placeholders": { + "size": { + "type": "int" + } + } + }, + "@recordingsMaxSizeSaved": { + "placeholders": { + "size": { + "type": "int" + } + } + } } diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 2d559a4..57a124a 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -49,8 +49,8 @@ "recordingsFolderDialogTitle": "Select recordings folder", "recordingsPathUpdated": "Recording path updated", "recordingsPathSaveError": "Could not save the path: {error}", - "recordingsDefaultFolderRestored": "The internal default folder will be used", - "recordingsFolderTitle": "Recordings folder", + "recordingsDefaultFolderRestored": "The default internal folder will be used", + "recordingsFolderTitle": "Recording folder", "recordingsPathCalculating": "Calculating path...", "recordingsChangePath": "Change path", "recordingsUseDefaultPath": "Use default path", @@ -89,7 +89,7 @@ "backupExportSubtitle": "Favorites, custom stations, and EQ presets", "backupImportTitle": "Import configuration", "backupImportSubtitle": "Restore from a backup file", - "backupShareSubject": "PluriWave ? backup", + "backupShareSubject": "PluriWave — backup", "backupShareText": "PluriWave configuration exported on {date}", "backupExportError": "Export error: {error}", "backupImportConfirmMessage": "This will add favorites, stations, and presets from the file. Continue?", @@ -102,7 +102,7 @@ "stationFilterSubtitle": "Only stations verified as active", "backgroundAudioTitle": "Background audio", "backgroundAudioSubtitle": "Continues when the screen turns off", - "dash": "?", + "dash": "—", "@recordingsPathSaveError": { "placeholders": { "error": {} @@ -149,5 +149,31 @@ } }, "cancelAction": "Cancel", - "equalizerTitle": "Equalizer" + "equalizerTitle": "Equalizer", + "recordingsOpenFolder": "Open folder", + "recordingsOpenFolderError": "Could not open the folder: {error}", + "recordingsMaxSizeTitle": "Maximum recording size", + "recordingsMaxSizeSubtitle": "Current limit: {size} MB", + "recordingsMaxSizeDialogTitle": "Maximum size per recording", + "recordingsMaxSizeMbLabel": "Maximum megabytes", + "recordingsMaxSizeSaved": "Recording limit updated to {size} MB", + "@recordingsOpenFolderError": { + "placeholders": { + "error": {} + } + }, + "@recordingsMaxSizeSubtitle": { + "placeholders": { + "size": { + "type": "int" + } + } + }, + "@recordingsMaxSizeSaved": { + "placeholders": { + "size": { + "type": "int" + } + } + } } diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 3c409fa..c6e79f3 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -47,10 +47,10 @@ "settingsSafeStatus": "Seguro", "recordingsSectionTitle": "Grabaciones", "recordingsFolderDialogTitle": "Selecciona la carpeta de grabaciones", - "recordingsPathUpdated": "Ruta de grabaci?n actualizada", + "recordingsPathUpdated": "Ruta de grabación actualizada", "recordingsPathSaveError": "No se pudo guardar la ruta: {error}", - "recordingsDefaultFolderRestored": "Se usar? la carpeta interna por defecto", - "recordingsFolderTitle": "Carpeta de grabaci?n", + "recordingsDefaultFolderRestored": "Se usará la carpeta interna por defecto", + "recordingsFolderTitle": "Carpeta de grabación", "recordingsPathCalculating": "Calculando ruta...", "recordingsChangePath": "Cambiar ruta", "recordingsUseDefaultPath": "Usar ruta por defecto", @@ -59,50 +59,50 @@ "equalizerDisabled": "Desactivado", "equalizerEnable": "Activar ecualizador", "equalizerRealtimeSubtitle": "Los cambios se aplican en tiempo real a la emisora actual.", - "equalizerPendingSubtitle": "Se guardan los cambios y se aplicar?n cuando Android habilite el efecto.", + "equalizerPendingSubtitle": "Se guardan los cambios y se aplicarán cuando Android habilite el efecto.", "equalizerPerStationTitle": "Usar EQ propio para esta favorita", "equalizerPerStationActive": "Activo para {stationName}", "equalizerPerStationMain": "Usando EQ principal para {stationName}", "preferredStationTitle": "Emisora preferida", - "preferredStationDescription": "Se preselecciona al crear alarmas y puede iniciarse como reproducci?n r?pida.", - "preferredStationNoStationsTitle": "Todav?a no hay emisoras disponibles", - "preferredStationNoStationsSubtitle": "Guard? favoritas o carg? emisoras para elegir una preferida.", - "preferredStationAutomaticFallback": "Fallback autom?tico", + "preferredStationDescription": "Se preselecciona al crear alarmas y puede iniciarse como reproducción rápida.", + "preferredStationNoStationsTitle": "Todavía no hay emisoras disponibles", + "preferredStationNoStationsSubtitle": "Guardá favoritas o cargá emisoras para elegir una preferida.", + "preferredStationAutomaticFallback": "Fallback automático", "preferredStationDefaultFavorite": "Favorita por defecto", "preferredStationCurrent": "Preferida actual: {stationName}", - "preferredStationAutoUsing": "Sin favoritas: usando autom?ticamente {stationName}", + "preferredStationAutoUsing": "Sin favoritas: usando automáticamente {stationName}", "preferredStationPlay": "Reproducir preferida", "customStationsTitle": "Emisoras personalizadas", - "customStationsAdd": "A?adir", + "customStationsAdd": "Añadir", "customStationsEmpty": "No hay emisoras personalizadas.", "playAction": "Reproducir", "deleteAction": "Eliminar", - "addStationTitle": "A?adir emisora", + "addStationTitle": "Añadir emisora", "stationNameLabel": "Nombre *", "requiredField": "Campo obligatorio", "streamUrlLabel": "URL del stream *", - "invalidUrl": "URL no v?lida", - "countryOptionalLabel": "Pa?s (opcional)", + "invalidUrl": "URL no válida", + "countryOptionalLabel": "País (opcional)", "saveStation": "Guardar emisora", "backupSectionTitle": "Copia de seguridad", - "backupExportTitle": "Exportar configuraci?n", + "backupExportTitle": "Exportar configuración", "backupExportSubtitle": "Favoritos, emisoras custom y presets de EQ", - "backupImportTitle": "Importar configuraci?n", + "backupImportTitle": "Importar configuración", "backupImportSubtitle": "Restaurar desde un fichero de copia de seguridad", - "backupShareSubject": "PluriWave ? copia de seguridad", - "backupShareText": "Configuraci?n de PluriWave exportada el {date}", + "backupShareSubject": "PluriWave — copia de seguridad", + "backupShareText": "Configuración de PluriWave exportada el {date}", "backupExportError": "Error al exportar: {error}", - "backupImportConfirmMessage": "Esto a?adir? los favoritos, emisoras y presets del fichero. ?Continuar?", - "backupImportSuccess": "Configuraci?n importada correctamente", + "backupImportConfirmMessage": "Esto añadirá los favoritos, emisoras y presets del fichero. ¿Continuar?", + "backupImportSuccess": "Configuración importada correctamente", "backupImportError": "Error al importar: {error}", - "appVersionLoading": "Cargando versi?n...", + "appVersionLoading": "Cargando versión...", "appVersionSubtitle": "{version} - Radio mundial", "savedFavoritesTitle": "Favoritos guardados", "stationFilterTitle": "Filtro de emisoras", "stationFilterSubtitle": "Solo emisoras verificadas como activas", "backgroundAudioTitle": "Audio en background", - "backgroundAudioSubtitle": "Contin?a al apagar la pantalla", - "dash": "?", + "backgroundAudioSubtitle": "Continúa al apagar la pantalla", + "dash": "—", "@recordingsPathSaveError": { "placeholders": { "error": {} @@ -149,5 +149,31 @@ } }, "cancelAction": "Cancelar", - "equalizerTitle": "Ecualizador" + "equalizerTitle": "Ecualizador", + "recordingsOpenFolder": "Abrir carpeta", + "recordingsOpenFolderError": "No se pudo abrir la carpeta: {error}", + "recordingsMaxSizeTitle": "Tamaño máximo de grabación", + "recordingsMaxSizeSubtitle": "Límite actual: {size} MB", + "recordingsMaxSizeDialogTitle": "Tamaño máximo por grabación", + "recordingsMaxSizeMbLabel": "Megabytes máximos", + "recordingsMaxSizeSaved": "Límite de grabación actualizado a {size} MB", + "@recordingsOpenFolderError": { + "placeholders": { + "error": {} + } + }, + "@recordingsMaxSizeSubtitle": { + "placeholders": { + "size": { + "type": "int" + } + } + }, + "@recordingsMaxSizeSaved": { + "placeholders": { + "size": { + "type": "int" + } + } + } } diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb index 429193a..06485c3 100644 --- a/lib/l10n/app_fr.arb +++ b/lib/l10n/app_fr.arb @@ -5,7 +5,7 @@ "navSearch": "Recherche", "navFavorites": "Favoris", "navAlarms": "Alarmes", - "navSettings": "R?glages", + "navSettings": "Settings", "actionOk": "OK", "sleepTimer": "Minuteur de sommeil", "sleepTimerDescription": "Smooth radio shutdown with an exact countdown.", @@ -24,20 +24,20 @@ "alarmName": {} } }, - "settingsTitle": "R?glages", - "settingsSubtitle": "Contr?le fin du son, sauvegardes et stations personnalis?es.", + "settingsTitle": "Settings", + "settingsSubtitle": "Fine-grained sound control, backups, and custom stations.", "languageSectionTitle": "Langue", - "languageSectionDescription": "Choisissez la langue d?affichage de l?application.", - "languageSystemDefault": "Syst?me", + "languageSectionDescription": "Choose how the app language is displayed.", + "languageSystemDefault": "System", "languageSpanish": "Espagnol", "languageEnglish": "Anglais", - "languageUpdated": "Langue mise ? jour : {languageName}", + "languageUpdated": "Language updated: {languageName}", "@languageUpdated": { "placeholders": { "languageName": {} } }, - "languageUpdatedSystem": "Langue mise ? jour : Syst?me", + "languageUpdatedSystem": "Language updated: System", "timerSectionTitle": "Sleep timer", "timerSectionAdd": "Add", "timerSectionDescription": "Customize the quick presets shown when automatically stopping the radio.", @@ -89,7 +89,7 @@ "backupExportSubtitle": "Favorites, custom stations, and EQ presets", "backupImportTitle": "Import configuration", "backupImportSubtitle": "Restore from a backup file", - "backupShareSubject": "PluriWave ? backup", + "backupShareSubject": "PluriWave — backup", "backupShareText": "PluriWave configuration exported on {date}", "backupExportError": "Export error: {error}", "backupImportConfirmMessage": "This will add favorites, stations, and presets from the file. Continue?", @@ -102,7 +102,7 @@ "stationFilterSubtitle": "Only stations verified as active", "backgroundAudioTitle": "Background audio", "backgroundAudioSubtitle": "Continues when the screen turns off", - "dash": "?", + "dash": "—", "@recordingsPathSaveError": { "placeholders": { "error": {} @@ -149,5 +149,31 @@ } }, "cancelAction": "Annuler", - "equalizerTitle": "Equalizer" + "equalizerTitle": "Equalizer", + "recordingsOpenFolder": "Open folder", + "recordingsOpenFolderError": "Could not open the folder: {error}", + "recordingsMaxSizeTitle": "Maximum recording size", + "recordingsMaxSizeSubtitle": "Current limit: {size} MB", + "recordingsMaxSizeDialogTitle": "Maximum size per recording", + "recordingsMaxSizeMbLabel": "Maximum megabytes", + "recordingsMaxSizeSaved": "Recording limit updated to {size} MB", + "@recordingsOpenFolderError": { + "placeholders": { + "error": {} + } + }, + "@recordingsMaxSizeSubtitle": { + "placeholders": { + "size": { + "type": "int" + } + } + }, + "@recordingsMaxSizeSaved": { + "placeholders": { + "size": { + "type": "int" + } + } + } } diff --git a/lib/l10n/app_hi.arb b/lib/l10n/app_hi.arb index 862667e..fe21478 100644 --- a/lib/l10n/app_hi.arb +++ b/lib/l10n/app_hi.arb @@ -1,13 +1,13 @@ { "@@locale": "hi", "appTitle": "PluriWave", - "navHome": "???", - "navSearch": "???", - "navFavorites": "???????", - "navAlarms": "??????", - "navSettings": "????????", - "actionOk": "???", - "sleepTimer": "????? ?????", + "navHome": "Home", + "navSearch": "Search", + "navFavorites": "Favorites", + "navAlarms": "Alarms", + "navSettings": "Settings", + "actionOk": "OK", + "sleepTimer": "Sleep timer", "sleepTimerDescription": "Smooth radio shutdown with an exact countdown.", "cancelTimer": "Cancel timer", "optionOther": "Other", @@ -24,20 +24,20 @@ "alarmName": {} } }, - "settingsTitle": "????????", - "settingsSubtitle": "?????, ????? ?? ????? ???????? ?? ??????? ?????????", - "languageSectionTitle": "????", - "languageSectionDescription": "?? ?? ???? ??????", - "languageSystemDefault": "??????", - "languageSpanish": "??????", - "languageEnglish": "?????????", - "languageUpdated": "???? ???? ??: {languageName}", + "settingsTitle": "Settings", + "settingsSubtitle": "Fine-grained sound control, backups, and custom stations.", + "languageSectionTitle": "Language", + "languageSectionDescription": "Choose how the app language is displayed.", + "languageSystemDefault": "System", + "languageSpanish": "Spanish", + "languageEnglish": "English", + "languageUpdated": "Language updated: {languageName}", "@languageUpdated": { "placeholders": { "languageName": {} } }, - "languageUpdatedSystem": "???? ???? ??: ??????", + "languageUpdatedSystem": "Language updated: System", "timerSectionTitle": "Sleep timer", "timerSectionAdd": "Add", "timerSectionDescription": "Customize the quick presets shown when automatically stopping the radio.", @@ -89,7 +89,7 @@ "backupExportSubtitle": "Favorites, custom stations, and EQ presets", "backupImportTitle": "Import configuration", "backupImportSubtitle": "Restore from a backup file", - "backupShareSubject": "PluriWave ? backup", + "backupShareSubject": "PluriWave — backup", "backupShareText": "PluriWave configuration exported on {date}", "backupExportError": "Export error: {error}", "backupImportConfirmMessage": "This will add favorites, stations, and presets from the file. Continue?", @@ -102,7 +102,7 @@ "stationFilterSubtitle": "Only stations verified as active", "backgroundAudioTitle": "Background audio", "backgroundAudioSubtitle": "Continues when the screen turns off", - "dash": "?", + "dash": "—", "@recordingsPathSaveError": { "placeholders": { "error": {} @@ -148,6 +148,32 @@ "version": {} } }, - "cancelAction": "???? ????", - "equalizerTitle": "Equalizer" + "cancelAction": "Cancel", + "equalizerTitle": "Equalizer", + "recordingsOpenFolder": "Open folder", + "recordingsOpenFolderError": "Could not open the folder: {error}", + "recordingsMaxSizeTitle": "Maximum recording size", + "recordingsMaxSizeSubtitle": "Current limit: {size} MB", + "recordingsMaxSizeDialogTitle": "Maximum size per recording", + "recordingsMaxSizeMbLabel": "Maximum megabytes", + "recordingsMaxSizeSaved": "Recording limit updated to {size} MB", + "@recordingsOpenFolderError": { + "placeholders": { + "error": {} + } + }, + "@recordingsMaxSizeSubtitle": { + "placeholders": { + "size": { + "type": "int" + } + } + }, + "@recordingsMaxSizeSaved": { + "placeholders": { + "size": { + "type": "int" + } + } + } } diff --git a/lib/l10n/app_id.arb b/lib/l10n/app_id.arb index 7a93160..13c5be7 100644 --- a/lib/l10n/app_id.arb +++ b/lib/l10n/app_id.arb @@ -89,7 +89,7 @@ "backupExportSubtitle": "Favorites, custom stations, and EQ presets", "backupImportTitle": "Import configuration", "backupImportSubtitle": "Restore from a backup file", - "backupShareSubject": "PluriWave ? backup", + "backupShareSubject": "PluriWave — backup", "backupShareText": "PluriWave configuration exported on {date}", "backupExportError": "Export error: {error}", "backupImportConfirmMessage": "This will add favorites, stations, and presets from the file. Continue?", @@ -102,7 +102,7 @@ "stationFilterSubtitle": "Only stations verified as active", "backgroundAudioTitle": "Background audio", "backgroundAudioSubtitle": "Continues when the screen turns off", - "dash": "?", + "dash": "—", "@recordingsPathSaveError": { "placeholders": { "error": {} @@ -149,5 +149,31 @@ } }, "cancelAction": "Batal", - "equalizerTitle": "Equalizer" + "equalizerTitle": "Equalizer", + "recordingsOpenFolder": "Open folder", + "recordingsOpenFolderError": "Could not open the folder: {error}", + "recordingsMaxSizeTitle": "Maximum recording size", + "recordingsMaxSizeSubtitle": "Current limit: {size} MB", + "recordingsMaxSizeDialogTitle": "Maximum size per recording", + "recordingsMaxSizeMbLabel": "Maximum megabytes", + "recordingsMaxSizeSaved": "Recording limit updated to {size} MB", + "@recordingsOpenFolderError": { + "placeholders": { + "error": {} + } + }, + "@recordingsMaxSizeSubtitle": { + "placeholders": { + "size": { + "type": "int" + } + } + }, + "@recordingsMaxSizeSaved": { + "placeholders": { + "size": { + "type": "int" + } + } + } } diff --git a/lib/l10n/app_it.arb b/lib/l10n/app_it.arb index 2d2b799..56c0be7 100644 --- a/lib/l10n/app_it.arb +++ b/lib/l10n/app_it.arb @@ -27,7 +27,7 @@ "settingsTitle": "Impostazioni", "settingsSubtitle": "Controllo fine del suono, backup e stazioni personalizzate.", "languageSectionTitle": "Lingua", - "languageSectionDescription": "Scegli la lingua di visualizzazione dell?app.", + "languageSectionDescription": "Choose how the app language is displayed.", "languageSystemDefault": "Sistema", "languageSpanish": "Spagnolo", "languageEnglish": "Inglese", @@ -89,7 +89,7 @@ "backupExportSubtitle": "Favorites, custom stations, and EQ presets", "backupImportTitle": "Import configuration", "backupImportSubtitle": "Restore from a backup file", - "backupShareSubject": "PluriWave ? backup", + "backupShareSubject": "PluriWave — backup", "backupShareText": "PluriWave configuration exported on {date}", "backupExportError": "Export error: {error}", "backupImportConfirmMessage": "This will add favorites, stations, and presets from the file. Continue?", @@ -102,7 +102,7 @@ "stationFilterSubtitle": "Only stations verified as active", "backgroundAudioTitle": "Background audio", "backgroundAudioSubtitle": "Continues when the screen turns off", - "dash": "?", + "dash": "—", "@recordingsPathSaveError": { "placeholders": { "error": {} @@ -149,5 +149,31 @@ } }, "cancelAction": "Annulla", - "equalizerTitle": "Equalizer" + "equalizerTitle": "Equalizer", + "recordingsOpenFolder": "Open folder", + "recordingsOpenFolderError": "Could not open the folder: {error}", + "recordingsMaxSizeTitle": "Maximum recording size", + "recordingsMaxSizeSubtitle": "Current limit: {size} MB", + "recordingsMaxSizeDialogTitle": "Maximum size per recording", + "recordingsMaxSizeMbLabel": "Maximum megabytes", + "recordingsMaxSizeSaved": "Recording limit updated to {size} MB", + "@recordingsOpenFolderError": { + "placeholders": { + "error": {} + } + }, + "@recordingsMaxSizeSubtitle": { + "placeholders": { + "size": { + "type": "int" + } + } + }, + "@recordingsMaxSizeSaved": { + "placeholders": { + "size": { + "type": "int" + } + } + } } diff --git a/lib/l10n/app_ja.arb b/lib/l10n/app_ja.arb index fb7911f..0d0711d 100644 --- a/lib/l10n/app_ja.arb +++ b/lib/l10n/app_ja.arb @@ -1,13 +1,13 @@ { "@@locale": "ja", "appTitle": "PluriWave", - "navHome": "???", - "navSearch": "??", - "navFavorites": "?????", - "navAlarms": "????", - "navSettings": "??", + "navHome": "Home", + "navSearch": "Search", + "navFavorites": "Favorites", + "navAlarms": "Alarms", + "navSettings": "Settings", "actionOk": "OK", - "sleepTimer": "????????", + "sleepTimer": "Sleep timer", "sleepTimerDescription": "Smooth radio shutdown with an exact countdown.", "cancelTimer": "Cancel timer", "optionOther": "Other", @@ -24,20 +24,20 @@ "alarmName": {} } }, - "settingsTitle": "??", - "settingsSubtitle": "?????????????????????????", - "languageSectionTitle": "??", - "languageSectionDescription": "???????????????", - "languageSystemDefault": "????", - "languageSpanish": "?????", - "languageEnglish": "??", - "languageUpdated": "?????????: {languageName}", + "settingsTitle": "Settings", + "settingsSubtitle": "Fine-grained sound control, backups, and custom stations.", + "languageSectionTitle": "Language", + "languageSectionDescription": "Choose how the app language is displayed.", + "languageSystemDefault": "System", + "languageSpanish": "Spanish", + "languageEnglish": "English", + "languageUpdated": "Language updated: {languageName}", "@languageUpdated": { "placeholders": { "languageName": {} } }, - "languageUpdatedSystem": "?????????: ????", + "languageUpdatedSystem": "Language updated: System", "timerSectionTitle": "Sleep timer", "timerSectionAdd": "Add", "timerSectionDescription": "Customize the quick presets shown when automatically stopping the radio.", @@ -89,7 +89,7 @@ "backupExportSubtitle": "Favorites, custom stations, and EQ presets", "backupImportTitle": "Import configuration", "backupImportSubtitle": "Restore from a backup file", - "backupShareSubject": "PluriWave ? backup", + "backupShareSubject": "PluriWave — backup", "backupShareText": "PluriWave configuration exported on {date}", "backupExportError": "Export error: {error}", "backupImportConfirmMessage": "This will add favorites, stations, and presets from the file. Continue?", @@ -102,7 +102,7 @@ "stationFilterSubtitle": "Only stations verified as active", "backgroundAudioTitle": "Background audio", "backgroundAudioSubtitle": "Continues when the screen turns off", - "dash": "?", + "dash": "—", "@recordingsPathSaveError": { "placeholders": { "error": {} @@ -148,6 +148,32 @@ "version": {} } }, - "cancelAction": "?????", - "equalizerTitle": "Equalizer" + "cancelAction": "Cancel", + "equalizerTitle": "Equalizer", + "recordingsOpenFolder": "Open folder", + "recordingsOpenFolderError": "Could not open the folder: {error}", + "recordingsMaxSizeTitle": "Maximum recording size", + "recordingsMaxSizeSubtitle": "Current limit: {size} MB", + "recordingsMaxSizeDialogTitle": "Maximum size per recording", + "recordingsMaxSizeMbLabel": "Maximum megabytes", + "recordingsMaxSizeSaved": "Recording limit updated to {size} MB", + "@recordingsOpenFolderError": { + "placeholders": { + "error": {} + } + }, + "@recordingsMaxSizeSubtitle": { + "placeholders": { + "size": { + "type": "int" + } + } + }, + "@recordingsMaxSizeSaved": { + "placeholders": { + "size": { + "type": "int" + } + } + } } diff --git a/lib/l10n/app_pt.arb b/lib/l10n/app_pt.arb index d1d60d1..e114316 100644 --- a/lib/l10n/app_pt.arb +++ b/lib/l10n/app_pt.arb @@ -1,11 +1,11 @@ { "@@locale": "pt", "appTitle": "PluriWave", - "navHome": "In?cio", + "navHome": "Home", "navSearch": "Buscar", "navFavorites": "Favoritos", "navAlarms": "Alarmes", - "navSettings": "Defini??es", + "navSettings": "Settings", "actionOk": "OK", "sleepTimer": "Timer de sono", "sleepTimerDescription": "Smooth radio shutdown with an exact countdown.", @@ -24,13 +24,13 @@ "alarmName": {} } }, - "settingsTitle": "Defini??es", - "settingsSubtitle": "Controle fino de som, backups e esta??es personalizadas.", + "settingsTitle": "Settings", + "settingsSubtitle": "Fine-grained sound control, backups, and custom stations.", "languageSectionTitle": "Idioma", - "languageSectionDescription": "Escolha como o idioma do app ? exibido.", + "languageSectionDescription": "Choose how the app language is displayed.", "languageSystemDefault": "Sistema", "languageSpanish": "Espanhol", - "languageEnglish": "Ingl?s", + "languageEnglish": "English", "languageUpdated": "Idioma atualizado: {languageName}", "@languageUpdated": { "placeholders": { @@ -89,7 +89,7 @@ "backupExportSubtitle": "Favorites, custom stations, and EQ presets", "backupImportTitle": "Import configuration", "backupImportSubtitle": "Restore from a backup file", - "backupShareSubject": "PluriWave ? backup", + "backupShareSubject": "PluriWave — backup", "backupShareText": "PluriWave configuration exported on {date}", "backupExportError": "Export error: {error}", "backupImportConfirmMessage": "This will add favorites, stations, and presets from the file. Continue?", @@ -102,7 +102,7 @@ "stationFilterSubtitle": "Only stations verified as active", "backgroundAudioTitle": "Background audio", "backgroundAudioSubtitle": "Continues when the screen turns off", - "dash": "?", + "dash": "—", "@recordingsPathSaveError": { "placeholders": { "error": {} @@ -149,5 +149,31 @@ } }, "cancelAction": "Cancelar", - "equalizerTitle": "Equalizer" + "equalizerTitle": "Equalizer", + "recordingsOpenFolder": "Open folder", + "recordingsOpenFolderError": "Could not open the folder: {error}", + "recordingsMaxSizeTitle": "Maximum recording size", + "recordingsMaxSizeSubtitle": "Current limit: {size} MB", + "recordingsMaxSizeDialogTitle": "Maximum size per recording", + "recordingsMaxSizeMbLabel": "Maximum megabytes", + "recordingsMaxSizeSaved": "Recording limit updated to {size} MB", + "@recordingsOpenFolderError": { + "placeholders": { + "error": {} + } + }, + "@recordingsMaxSizeSubtitle": { + "placeholders": { + "size": { + "type": "int" + } + } + }, + "@recordingsMaxSizeSaved": { + "placeholders": { + "size": { + "type": "int" + } + } + } } diff --git a/lib/l10n/app_ru.arb b/lib/l10n/app_ru.arb index 296f7f0..4ede2f1 100644 --- a/lib/l10n/app_ru.arb +++ b/lib/l10n/app_ru.arb @@ -1,13 +1,13 @@ { "@@locale": "ru", "appTitle": "PluriWave", - "navHome": "???????", - "navSearch": "?????", - "navFavorites": "?????????", - "navAlarms": "??????????", - "navSettings": "?????????", + "navHome": "Home", + "navSearch": "Search", + "navFavorites": "Favorites", + "navAlarms": "Alarms", + "navSettings": "Settings", "actionOk": "OK", - "sleepTimer": "?????? ???", + "sleepTimer": "Sleep timer", "sleepTimerDescription": "Smooth radio shutdown with an exact countdown.", "cancelTimer": "Cancel timer", "optionOther": "Other", @@ -24,20 +24,20 @@ "alarmName": {} } }, - "settingsTitle": "?????????", - "settingsSubtitle": "?????? ????????? ?????, ????????? ????? ? ???????????????? ???????.", - "languageSectionTitle": "????", - "languageSectionDescription": "???????? ???? ?????????? ??????????.", - "languageSystemDefault": "???????", - "languageSpanish": "?????????", - "languageEnglish": "??????????", - "languageUpdated": "???? ????????: {languageName}", + "settingsTitle": "Settings", + "settingsSubtitle": "Fine-grained sound control, backups, and custom stations.", + "languageSectionTitle": "Language", + "languageSectionDescription": "Choose how the app language is displayed.", + "languageSystemDefault": "System", + "languageSpanish": "Spanish", + "languageEnglish": "English", + "languageUpdated": "Language updated: {languageName}", "@languageUpdated": { "placeholders": { "languageName": {} } }, - "languageUpdatedSystem": "???? ????????: ???????", + "languageUpdatedSystem": "Language updated: System", "timerSectionTitle": "Sleep timer", "timerSectionAdd": "Add", "timerSectionDescription": "Customize the quick presets shown when automatically stopping the radio.", @@ -89,7 +89,7 @@ "backupExportSubtitle": "Favorites, custom stations, and EQ presets", "backupImportTitle": "Import configuration", "backupImportSubtitle": "Restore from a backup file", - "backupShareSubject": "PluriWave ? backup", + "backupShareSubject": "PluriWave — backup", "backupShareText": "PluriWave configuration exported on {date}", "backupExportError": "Export error: {error}", "backupImportConfirmMessage": "This will add favorites, stations, and presets from the file. Continue?", @@ -102,7 +102,7 @@ "stationFilterSubtitle": "Only stations verified as active", "backgroundAudioTitle": "Background audio", "backgroundAudioSubtitle": "Continues when the screen turns off", - "dash": "?", + "dash": "—", "@recordingsPathSaveError": { "placeholders": { "error": {} @@ -148,6 +148,32 @@ "version": {} } }, - "cancelAction": "??????", - "equalizerTitle": "Equalizer" + "cancelAction": "Cancel", + "equalizerTitle": "Equalizer", + "recordingsOpenFolder": "Open folder", + "recordingsOpenFolderError": "Could not open the folder: {error}", + "recordingsMaxSizeTitle": "Maximum recording size", + "recordingsMaxSizeSubtitle": "Current limit: {size} MB", + "recordingsMaxSizeDialogTitle": "Maximum size per recording", + "recordingsMaxSizeMbLabel": "Maximum megabytes", + "recordingsMaxSizeSaved": "Recording limit updated to {size} MB", + "@recordingsOpenFolderError": { + "placeholders": { + "error": {} + } + }, + "@recordingsMaxSizeSubtitle": { + "placeholders": { + "size": { + "type": "int" + } + } + }, + "@recordingsMaxSizeSaved": { + "placeholders": { + "size": { + "type": "int" + } + } + } } diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index 3e1fc42..75ecd71 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -1,13 +1,13 @@ { "@@locale": "zh", "appTitle": "PluriWave", - "navHome": "??", - "navSearch": "??", - "navFavorites": "??", - "navAlarms": "??", - "navSettings": "??", - "actionOk": "??", - "sleepTimer": "?????", + "navHome": "Home", + "navSearch": "Search", + "navFavorites": "Favorites", + "navAlarms": "Alarms", + "navSettings": "Settings", + "actionOk": "OK", + "sleepTimer": "Sleep timer", "sleepTimerDescription": "Smooth radio shutdown with an exact countdown.", "cancelTimer": "Cancel timer", "optionOther": "Other", @@ -24,20 +24,20 @@ "alarmName": {} } }, - "settingsTitle": "??", - "settingsSubtitle": "?????????????????", - "languageSectionTitle": "??", - "languageSectionDescription": "?????????", - "languageSystemDefault": "??", - "languageSpanish": "????", - "languageEnglish": "??", - "languageUpdated": "??????{languageName}", + "settingsTitle": "Settings", + "settingsSubtitle": "Fine-grained sound control, backups, and custom stations.", + "languageSectionTitle": "Language", + "languageSectionDescription": "Choose how the app language is displayed.", + "languageSystemDefault": "System", + "languageSpanish": "Spanish", + "languageEnglish": "English", + "languageUpdated": "Language updated: {languageName}", "@languageUpdated": { "placeholders": { "languageName": {} } }, - "languageUpdatedSystem": "????????", + "languageUpdatedSystem": "Language updated: System", "timerSectionTitle": "Sleep timer", "timerSectionAdd": "Add", "timerSectionDescription": "Customize the quick presets shown when automatically stopping the radio.", @@ -89,7 +89,7 @@ "backupExportSubtitle": "Favorites, custom stations, and EQ presets", "backupImportTitle": "Import configuration", "backupImportSubtitle": "Restore from a backup file", - "backupShareSubject": "PluriWave ? backup", + "backupShareSubject": "PluriWave — backup", "backupShareText": "PluriWave configuration exported on {date}", "backupExportError": "Export error: {error}", "backupImportConfirmMessage": "This will add favorites, stations, and presets from the file. Continue?", @@ -102,7 +102,7 @@ "stationFilterSubtitle": "Only stations verified as active", "backgroundAudioTitle": "Background audio", "backgroundAudioSubtitle": "Continues when the screen turns off", - "dash": "?", + "dash": "—", "@recordingsPathSaveError": { "placeholders": { "error": {} @@ -148,6 +148,32 @@ "version": {} } }, - "cancelAction": "??", - "equalizerTitle": "Equalizer" + "cancelAction": "Cancel", + "equalizerTitle": "Equalizer", + "recordingsOpenFolder": "Open folder", + "recordingsOpenFolderError": "Could not open the folder: {error}", + "recordingsMaxSizeTitle": "Maximum recording size", + "recordingsMaxSizeSubtitle": "Current limit: {size} MB", + "recordingsMaxSizeDialogTitle": "Maximum size per recording", + "recordingsMaxSizeMbLabel": "Maximum megabytes", + "recordingsMaxSizeSaved": "Recording limit updated to {size} MB", + "@recordingsOpenFolderError": { + "placeholders": { + "error": {} + } + }, + "@recordingsMaxSizeSubtitle": { + "placeholders": { + "size": { + "type": "int" + } + } + }, + "@recordingsMaxSizeSaved": { + "placeholders": { + "size": { + "type": "int" + } + } + } } diff --git a/lib/l10n/gen/app_localizations.dart b/lib/l10n/gen/app_localizations.dart index e8f39c4..73a65a9 100644 --- a/lib/l10n/gen/app_localizations.dart +++ b/lib/l10n/gen/app_localizations.dart @@ -345,7 +345,7 @@ abstract class AppLocalizations { /// No description provided for @recordingsPathUpdated. /// /// In es, this message translates to: - /// **'Ruta de grabaci?n actualizada'** + /// **'Ruta de grabación actualizada'** String get recordingsPathUpdated; /// No description provided for @recordingsPathSaveError. @@ -357,13 +357,13 @@ abstract class AppLocalizations { /// No description provided for @recordingsDefaultFolderRestored. /// /// In es, this message translates to: - /// **'Se usar? la carpeta interna por defecto'** + /// **'Se usará la carpeta interna por defecto'** String get recordingsDefaultFolderRestored; /// No description provided for @recordingsFolderTitle. /// /// In es, this message translates to: - /// **'Carpeta de grabaci?n'** + /// **'Carpeta de grabación'** String get recordingsFolderTitle; /// No description provided for @recordingsPathCalculating. @@ -417,7 +417,7 @@ abstract class AppLocalizations { /// No description provided for @equalizerPendingSubtitle. /// /// In es, this message translates to: - /// **'Se guardan los cambios y se aplicar?n cuando Android habilite el efecto.'** + /// **'Se guardan los cambios y se aplicarán cuando Android habilite el efecto.'** String get equalizerPendingSubtitle; /// No description provided for @equalizerPerStationTitle. @@ -447,25 +447,25 @@ abstract class AppLocalizations { /// No description provided for @preferredStationDescription. /// /// In es, this message translates to: - /// **'Se preselecciona al crear alarmas y puede iniciarse como reproducci?n r?pida.'** + /// **'Se preselecciona al crear alarmas y puede iniciarse como reproducción rápida.'** String get preferredStationDescription; /// No description provided for @preferredStationNoStationsTitle. /// /// In es, this message translates to: - /// **'Todav?a no hay emisoras disponibles'** + /// **'Todavía no hay emisoras disponibles'** String get preferredStationNoStationsTitle; /// No description provided for @preferredStationNoStationsSubtitle. /// /// In es, this message translates to: - /// **'Guard? favoritas o carg? emisoras para elegir una preferida.'** + /// **'Guardá favoritas o cargá emisoras para elegir una preferida.'** String get preferredStationNoStationsSubtitle; /// No description provided for @preferredStationAutomaticFallback. /// /// In es, this message translates to: - /// **'Fallback autom?tico'** + /// **'Fallback automático'** String get preferredStationAutomaticFallback; /// No description provided for @preferredStationDefaultFavorite. @@ -483,7 +483,7 @@ abstract class AppLocalizations { /// No description provided for @preferredStationAutoUsing. /// /// In es, this message translates to: - /// **'Sin favoritas: usando autom?ticamente {stationName}'** + /// **'Sin favoritas: usando automáticamente {stationName}'** String preferredStationAutoUsing(Object stationName); /// No description provided for @preferredStationPlay. @@ -501,7 +501,7 @@ abstract class AppLocalizations { /// No description provided for @customStationsAdd. /// /// In es, this message translates to: - /// **'A?adir'** + /// **'Añadir'** String get customStationsAdd; /// No description provided for @customStationsEmpty. @@ -525,7 +525,7 @@ abstract class AppLocalizations { /// No description provided for @addStationTitle. /// /// In es, this message translates to: - /// **'A?adir emisora'** + /// **'Añadir emisora'** String get addStationTitle; /// No description provided for @stationNameLabel. @@ -549,13 +549,13 @@ abstract class AppLocalizations { /// No description provided for @invalidUrl. /// /// In es, this message translates to: - /// **'URL no v?lida'** + /// **'URL no válida'** String get invalidUrl; /// No description provided for @countryOptionalLabel. /// /// In es, this message translates to: - /// **'Pa?s (opcional)'** + /// **'País (opcional)'** String get countryOptionalLabel; /// No description provided for @saveStation. @@ -573,7 +573,7 @@ abstract class AppLocalizations { /// No description provided for @backupExportTitle. /// /// In es, this message translates to: - /// **'Exportar configuraci?n'** + /// **'Exportar configuración'** String get backupExportTitle; /// No description provided for @backupExportSubtitle. @@ -585,7 +585,7 @@ abstract class AppLocalizations { /// No description provided for @backupImportTitle. /// /// In es, this message translates to: - /// **'Importar configuraci?n'** + /// **'Importar configuración'** String get backupImportTitle; /// No description provided for @backupImportSubtitle. @@ -597,13 +597,13 @@ abstract class AppLocalizations { /// No description provided for @backupShareSubject. /// /// In es, this message translates to: - /// **'PluriWave ? copia de seguridad'** + /// **'PluriWave — copia de seguridad'** String get backupShareSubject; /// No description provided for @backupShareText. /// /// In es, this message translates to: - /// **'Configuraci?n de PluriWave exportada el {date}'** + /// **'Configuración de PluriWave exportada el {date}'** String backupShareText(Object date); /// No description provided for @backupExportError. @@ -615,13 +615,13 @@ abstract class AppLocalizations { /// No description provided for @backupImportConfirmMessage. /// /// In es, this message translates to: - /// **'Esto a?adir? los favoritos, emisoras y presets del fichero. ?Continuar?'** + /// **'Esto añadirá los favoritos, emisoras y presets del fichero. ¿Continuar?'** String get backupImportConfirmMessage; /// No description provided for @backupImportSuccess. /// /// In es, this message translates to: - /// **'Configuraci?n importada correctamente'** + /// **'Configuración importada correctamente'** String get backupImportSuccess; /// No description provided for @backupImportError. @@ -633,7 +633,7 @@ abstract class AppLocalizations { /// No description provided for @appVersionLoading. /// /// In es, this message translates to: - /// **'Cargando versi?n...'** + /// **'Cargando versión...'** String get appVersionLoading; /// No description provided for @appVersionSubtitle. @@ -669,13 +669,13 @@ abstract class AppLocalizations { /// No description provided for @backgroundAudioSubtitle. /// /// In es, this message translates to: - /// **'Contin?a al apagar la pantalla'** + /// **'Continúa al apagar la pantalla'** String get backgroundAudioSubtitle; /// No description provided for @dash. /// /// In es, this message translates to: - /// **'?'** + /// **'—'** String get dash; /// No description provided for @cancelAction. @@ -689,6 +689,48 @@ abstract class AppLocalizations { /// In es, this message translates to: /// **'Ecualizador'** String get equalizerTitle; + + /// No description provided for @recordingsOpenFolder. + /// + /// In es, this message translates to: + /// **'Abrir carpeta'** + String get recordingsOpenFolder; + + /// No description provided for @recordingsOpenFolderError. + /// + /// In es, this message translates to: + /// **'No se pudo abrir la carpeta: {error}'** + String recordingsOpenFolderError(Object error); + + /// No description provided for @recordingsMaxSizeTitle. + /// + /// In es, this message translates to: + /// **'Tamaño máximo de grabación'** + String get recordingsMaxSizeTitle; + + /// No description provided for @recordingsMaxSizeSubtitle. + /// + /// In es, this message translates to: + /// **'Límite actual: {size} MB'** + String recordingsMaxSizeSubtitle(int size); + + /// No description provided for @recordingsMaxSizeDialogTitle. + /// + /// In es, this message translates to: + /// **'Tamaño máximo por grabación'** + String get recordingsMaxSizeDialogTitle; + + /// No description provided for @recordingsMaxSizeMbLabel. + /// + /// In es, this message translates to: + /// **'Megabytes máximos'** + String get recordingsMaxSizeMbLabel; + + /// No description provided for @recordingsMaxSizeSaved. + /// + /// In es, this message translates to: + /// **'Límite de grabación actualizado a {size} MB'** + String recordingsMaxSizeSaved(int size); } class _AppLocalizationsDelegate diff --git a/lib/l10n/gen/app_localizations_ar.dart b/lib/l10n/gen/app_localizations_ar.dart index 9a02303..9affbc2 100644 --- a/lib/l10n/gen/app_localizations_ar.dart +++ b/lib/l10n/gen/app_localizations_ar.dart @@ -12,25 +12,25 @@ class AppLocalizationsAr extends AppLocalizations { String get appTitle => 'PluriWave'; @override - String get navHome => '????????'; + String get navHome => 'Home'; @override - String get navSearch => '???'; + String get navSearch => 'Search'; @override - String get navFavorites => '???????'; + String get navFavorites => 'Favorites'; @override - String get navAlarms => '????????'; + String get navAlarms => 'Alarms'; @override - String get navSettings => '?????????'; + String get navSettings => 'Settings'; @override - String get actionOk => '?????'; + String get actionOk => 'OK'; @override - String get sleepTimer => '???? ?????'; + String get sleepTimer => 'Sleep timer'; @override String get sleepTimerDescription => @@ -69,34 +69,35 @@ class AppLocalizationsAr extends AppLocalizations { } @override - String get settingsTitle => '?????????'; + String get settingsTitle => 'Settings'; @override String get settingsSubtitle => - '???? ???? ?? ????? ?????? ????????? ???????? ???????.'; + 'Fine-grained sound control, backups, and custom stations.'; @override - String get languageSectionTitle => '?????'; + String get languageSectionTitle => 'Language'; @override - String get languageSectionDescription => '???? ??? ??? ???????.'; + String get languageSectionDescription => + 'Choose how the app language is displayed.'; @override - String get languageSystemDefault => '??????'; + String get languageSystemDefault => 'System'; @override - String get languageSpanish => '?????????'; + String get languageSpanish => 'Spanish'; @override - String get languageEnglish => '??????????'; + String get languageEnglish => 'English'; @override String languageUpdated(Object languageName) { - return '?? ????? ?????: $languageName'; + return 'Language updated: $languageName'; } @override - String get languageUpdatedSystem => '?? ????? ?????: ??????'; + String get languageUpdatedSystem => 'Language updated: System'; @override String get timerSectionTitle => 'Sleep timer'; @@ -270,7 +271,7 @@ class AppLocalizationsAr extends AppLocalizations { String get backupImportSubtitle => 'Restore from a backup file'; @override - String get backupShareSubject => 'PluriWave ? backup'; + String get backupShareSubject => 'PluriWave — backup'; @override String backupShareText(Object date) { @@ -318,11 +319,38 @@ class AppLocalizationsAr extends AppLocalizations { String get backgroundAudioSubtitle => 'Continues when the screen turns off'; @override - String get dash => '?'; + String get dash => '—'; @override - String get cancelAction => '?????'; + String get cancelAction => 'Cancel'; @override String get equalizerTitle => 'Equalizer'; + + @override + String get recordingsOpenFolder => 'Open folder'; + + @override + String recordingsOpenFolderError(Object error) { + return 'Could not open the folder: $error'; + } + + @override + String get recordingsMaxSizeTitle => 'Maximum recording size'; + + @override + String recordingsMaxSizeSubtitle(int size) { + return 'Current limit: $size MB'; + } + + @override + String get recordingsMaxSizeDialogTitle => 'Maximum size per recording'; + + @override + String get recordingsMaxSizeMbLabel => 'Maximum megabytes'; + + @override + String recordingsMaxSizeSaved(int size) { + return 'Recording limit updated to $size MB'; + } } diff --git a/lib/l10n/gen/app_localizations_bn.dart b/lib/l10n/gen/app_localizations_bn.dart index b7eda1e..4b9757f 100644 --- a/lib/l10n/gen/app_localizations_bn.dart +++ b/lib/l10n/gen/app_localizations_bn.dart @@ -12,25 +12,25 @@ class AppLocalizationsBn extends AppLocalizations { String get appTitle => 'PluriWave'; @override - String get navHome => '???'; + String get navHome => 'Home'; @override - String get navSearch => '????'; + String get navSearch => 'Search'; @override - String get navFavorites => '??????'; + String get navFavorites => 'Favorites'; @override - String get navAlarms => '?????????'; + String get navAlarms => 'Alarms'; @override - String get navSettings => '??????'; + String get navSettings => 'Settings'; @override - String get actionOk => '??? ???'; + String get actionOk => 'OK'; @override - String get sleepTimer => '????? ??????'; + String get sleepTimer => 'Sleep timer'; @override String get sleepTimerDescription => @@ -69,34 +69,35 @@ class AppLocalizationsBn extends AppLocalizations { } @override - String get settingsTitle => '??????'; + String get settingsTitle => 'Settings'; @override String get settingsSubtitle => - '????, ??????? ??? ?????? ???????? ??????? ???????????'; + 'Fine-grained sound control, backups, and custom stations.'; @override - String get languageSectionTitle => '????'; + String get languageSectionTitle => 'Language'; @override - String get languageSectionDescription => '??????? ???????? ???? ???? ????'; + String get languageSectionDescription => + 'Choose how the app language is displayed.'; @override - String get languageSystemDefault => '???????'; + String get languageSystemDefault => 'System'; @override - String get languageSpanish => '?????????'; + String get languageSpanish => 'Spanish'; @override - String get languageEnglish => '??????'; + String get languageEnglish => 'English'; @override String languageUpdated(Object languageName) { - return '???? ????? ??????: $languageName'; + return 'Language updated: $languageName'; } @override - String get languageUpdatedSystem => '???? ????? ??????: ???????'; + String get languageUpdatedSystem => 'Language updated: System'; @override String get timerSectionTitle => 'Sleep timer'; @@ -270,7 +271,7 @@ class AppLocalizationsBn extends AppLocalizations { String get backupImportSubtitle => 'Restore from a backup file'; @override - String get backupShareSubject => 'PluriWave ? backup'; + String get backupShareSubject => 'PluriWave — backup'; @override String backupShareText(Object date) { @@ -318,11 +319,38 @@ class AppLocalizationsBn extends AppLocalizations { String get backgroundAudioSubtitle => 'Continues when the screen turns off'; @override - String get dash => '?'; + String get dash => '—'; @override - String get cancelAction => '?????'; + String get cancelAction => 'Cancel'; @override String get equalizerTitle => 'Equalizer'; + + @override + String get recordingsOpenFolder => 'Open folder'; + + @override + String recordingsOpenFolderError(Object error) { + return 'Could not open the folder: $error'; + } + + @override + String get recordingsMaxSizeTitle => 'Maximum recording size'; + + @override + String recordingsMaxSizeSubtitle(int size) { + return 'Current limit: $size MB'; + } + + @override + String get recordingsMaxSizeDialogTitle => 'Maximum size per recording'; + + @override + String get recordingsMaxSizeMbLabel => 'Maximum megabytes'; + + @override + String recordingsMaxSizeSaved(int size) { + return 'Recording limit updated to $size MB'; + } } diff --git a/lib/l10n/gen/app_localizations_de.dart b/lib/l10n/gen/app_localizations_de.dart index 2f30b89..25ac375 100644 --- a/lib/l10n/gen/app_localizations_de.dart +++ b/lib/l10n/gen/app_localizations_de.dart @@ -73,13 +73,14 @@ class AppLocalizationsDe extends AppLocalizations { @override String get settingsSubtitle => - 'Feinsteuerung f?r Sound, Backups und eigene Sender.'; + 'Fine-grained sound control, backups, and custom stations.'; @override String get languageSectionTitle => 'Sprache'; @override - String get languageSectionDescription => 'W?hle die Anzeigesprache der App.'; + String get languageSectionDescription => + 'Choose how the app language is displayed.'; @override String get languageSystemDefault => 'System'; @@ -270,7 +271,7 @@ class AppLocalizationsDe extends AppLocalizations { String get backupImportSubtitle => 'Restore from a backup file'; @override - String get backupShareSubject => 'PluriWave ? backup'; + String get backupShareSubject => 'PluriWave — backup'; @override String backupShareText(Object date) { @@ -318,11 +319,38 @@ class AppLocalizationsDe extends AppLocalizations { String get backgroundAudioSubtitle => 'Continues when the screen turns off'; @override - String get dash => '?'; + String get dash => '—'; @override String get cancelAction => 'Abbrechen'; @override String get equalizerTitle => 'Equalizer'; + + @override + String get recordingsOpenFolder => 'Open folder'; + + @override + String recordingsOpenFolderError(Object error) { + return 'Could not open the folder: $error'; + } + + @override + String get recordingsMaxSizeTitle => 'Maximum recording size'; + + @override + String recordingsMaxSizeSubtitle(int size) { + return 'Current limit: $size MB'; + } + + @override + String get recordingsMaxSizeDialogTitle => 'Maximum size per recording'; + + @override + String get recordingsMaxSizeMbLabel => 'Maximum megabytes'; + + @override + String recordingsMaxSizeSaved(int size) { + return 'Recording limit updated to $size MB'; + } } diff --git a/lib/l10n/gen/app_localizations_en.dart b/lib/l10n/gen/app_localizations_en.dart index b778b83..3402588 100644 --- a/lib/l10n/gen/app_localizations_en.dart +++ b/lib/l10n/gen/app_localizations_en.dart @@ -137,10 +137,10 @@ class AppLocalizationsEn extends AppLocalizations { @override String get recordingsDefaultFolderRestored => - 'The internal default folder will be used'; + 'The default internal folder will be used'; @override - String get recordingsFolderTitle => 'Recordings folder'; + String get recordingsFolderTitle => 'Recording folder'; @override String get recordingsPathCalculating => 'Calculating path...'; @@ -271,7 +271,7 @@ class AppLocalizationsEn extends AppLocalizations { String get backupImportSubtitle => 'Restore from a backup file'; @override - String get backupShareSubject => 'PluriWave ? backup'; + String get backupShareSubject => 'PluriWave — backup'; @override String backupShareText(Object date) { @@ -319,11 +319,38 @@ class AppLocalizationsEn extends AppLocalizations { String get backgroundAudioSubtitle => 'Continues when the screen turns off'; @override - String get dash => '?'; + String get dash => '—'; @override String get cancelAction => 'Cancel'; @override String get equalizerTitle => 'Equalizer'; + + @override + String get recordingsOpenFolder => 'Open folder'; + + @override + String recordingsOpenFolderError(Object error) { + return 'Could not open the folder: $error'; + } + + @override + String get recordingsMaxSizeTitle => 'Maximum recording size'; + + @override + String recordingsMaxSizeSubtitle(int size) { + return 'Current limit: $size MB'; + } + + @override + String get recordingsMaxSizeDialogTitle => 'Maximum size per recording'; + + @override + String get recordingsMaxSizeMbLabel => 'Maximum megabytes'; + + @override + String recordingsMaxSizeSaved(int size) { + return 'Recording limit updated to $size MB'; + } } diff --git a/lib/l10n/gen/app_localizations_es.dart b/lib/l10n/gen/app_localizations_es.dart index 13892ff..8ae2e09 100644 --- a/lib/l10n/gen/app_localizations_es.dart +++ b/lib/l10n/gen/app_localizations_es.dart @@ -129,7 +129,7 @@ class AppLocalizationsEs extends AppLocalizations { 'Selecciona la carpeta de grabaciones'; @override - String get recordingsPathUpdated => 'Ruta de grabaci?n actualizada'; + String get recordingsPathUpdated => 'Ruta de grabación actualizada'; @override String recordingsPathSaveError(Object error) { @@ -138,10 +138,10 @@ class AppLocalizationsEs extends AppLocalizations { @override String get recordingsDefaultFolderRestored => - 'Se usar? la carpeta interna por defecto'; + 'Se usará la carpeta interna por defecto'; @override - String get recordingsFolderTitle => 'Carpeta de grabaci?n'; + String get recordingsFolderTitle => 'Carpeta de grabación'; @override String get recordingsPathCalculating => 'Calculando ruta...'; @@ -171,7 +171,7 @@ class AppLocalizationsEs extends AppLocalizations { @override String get equalizerPendingSubtitle => - 'Se guardan los cambios y se aplicar?n cuando Android habilite el efecto.'; + 'Se guardan los cambios y se aplicarán cuando Android habilite el efecto.'; @override String get equalizerPerStationTitle => 'Usar EQ propio para esta favorita'; @@ -191,18 +191,18 @@ class AppLocalizationsEs extends AppLocalizations { @override String get preferredStationDescription => - 'Se preselecciona al crear alarmas y puede iniciarse como reproducci?n r?pida.'; + 'Se preselecciona al crear alarmas y puede iniciarse como reproducción rápida.'; @override String get preferredStationNoStationsTitle => - 'Todav?a no hay emisoras disponibles'; + 'Todavía no hay emisoras disponibles'; @override String get preferredStationNoStationsSubtitle => - 'Guard? favoritas o carg? emisoras para elegir una preferida.'; + 'Guardá favoritas o cargá emisoras para elegir una preferida.'; @override - String get preferredStationAutomaticFallback => 'Fallback autom?tico'; + String get preferredStationAutomaticFallback => 'Fallback automático'; @override String get preferredStationDefaultFavorite => 'Favorita por defecto'; @@ -214,7 +214,7 @@ class AppLocalizationsEs extends AppLocalizations { @override String preferredStationAutoUsing(Object stationName) { - return 'Sin favoritas: usando autom?ticamente $stationName'; + return 'Sin favoritas: usando automáticamente $stationName'; } @override @@ -224,7 +224,7 @@ class AppLocalizationsEs extends AppLocalizations { String get customStationsTitle => 'Emisoras personalizadas'; @override - String get customStationsAdd => 'A?adir'; + String get customStationsAdd => 'Añadir'; @override String get customStationsEmpty => 'No hay emisoras personalizadas.'; @@ -236,7 +236,7 @@ class AppLocalizationsEs extends AppLocalizations { String get deleteAction => 'Eliminar'; @override - String get addStationTitle => 'A?adir emisora'; + String get addStationTitle => 'Añadir emisora'; @override String get stationNameLabel => 'Nombre *'; @@ -248,10 +248,10 @@ class AppLocalizationsEs extends AppLocalizations { String get streamUrlLabel => 'URL del stream *'; @override - String get invalidUrl => 'URL no v?lida'; + String get invalidUrl => 'URL no válida'; @override - String get countryOptionalLabel => 'Pa?s (opcional)'; + String get countryOptionalLabel => 'País (opcional)'; @override String get saveStation => 'Guardar emisora'; @@ -260,25 +260,25 @@ class AppLocalizationsEs extends AppLocalizations { String get backupSectionTitle => 'Copia de seguridad'; @override - String get backupExportTitle => 'Exportar configuraci?n'; + String get backupExportTitle => 'Exportar configuración'; @override String get backupExportSubtitle => 'Favoritos, emisoras custom y presets de EQ'; @override - String get backupImportTitle => 'Importar configuraci?n'; + String get backupImportTitle => 'Importar configuración'; @override String get backupImportSubtitle => 'Restaurar desde un fichero de copia de seguridad'; @override - String get backupShareSubject => 'PluriWave ? copia de seguridad'; + String get backupShareSubject => 'PluriWave — copia de seguridad'; @override String backupShareText(Object date) { - return 'Configuraci?n de PluriWave exportada el $date'; + return 'Configuración de PluriWave exportada el $date'; } @override @@ -288,10 +288,10 @@ class AppLocalizationsEs extends AppLocalizations { @override String get backupImportConfirmMessage => - 'Esto a?adir? los favoritos, emisoras y presets del fichero. ?Continuar?'; + 'Esto añadirá los favoritos, emisoras y presets del fichero. ¿Continuar?'; @override - String get backupImportSuccess => 'Configuraci?n importada correctamente'; + String get backupImportSuccess => 'Configuración importada correctamente'; @override String backupImportError(Object error) { @@ -299,7 +299,7 @@ class AppLocalizationsEs extends AppLocalizations { } @override - String get appVersionLoading => 'Cargando versi?n...'; + String get appVersionLoading => 'Cargando versión...'; @override String appVersionSubtitle(Object version) { @@ -319,14 +319,41 @@ class AppLocalizationsEs extends AppLocalizations { String get backgroundAudioTitle => 'Audio en background'; @override - String get backgroundAudioSubtitle => 'Contin?a al apagar la pantalla'; + String get backgroundAudioSubtitle => 'Continúa al apagar la pantalla'; @override - String get dash => '?'; + String get dash => '—'; @override String get cancelAction => 'Cancelar'; @override String get equalizerTitle => 'Ecualizador'; + + @override + String get recordingsOpenFolder => 'Abrir carpeta'; + + @override + String recordingsOpenFolderError(Object error) { + return 'No se pudo abrir la carpeta: $error'; + } + + @override + String get recordingsMaxSizeTitle => 'Tamaño máximo de grabación'; + + @override + String recordingsMaxSizeSubtitle(int size) { + return 'Límite actual: $size MB'; + } + + @override + String get recordingsMaxSizeDialogTitle => 'Tamaño máximo por grabación'; + + @override + String get recordingsMaxSizeMbLabel => 'Megabytes máximos'; + + @override + String recordingsMaxSizeSaved(int size) { + return 'Límite de grabación actualizado a $size MB'; + } } diff --git a/lib/l10n/gen/app_localizations_fr.dart b/lib/l10n/gen/app_localizations_fr.dart index 191e9b2..8296630 100644 --- a/lib/l10n/gen/app_localizations_fr.dart +++ b/lib/l10n/gen/app_localizations_fr.dart @@ -24,7 +24,7 @@ class AppLocalizationsFr extends AppLocalizations { String get navAlarms => 'Alarmes'; @override - String get navSettings => 'R?glages'; + String get navSettings => 'Settings'; @override String get actionOk => 'OK'; @@ -69,21 +69,21 @@ class AppLocalizationsFr extends AppLocalizations { } @override - String get settingsTitle => 'R?glages'; + String get settingsTitle => 'Settings'; @override String get settingsSubtitle => - 'Contr?le fin du son, sauvegardes et stations personnalis?es.'; + 'Fine-grained sound control, backups, and custom stations.'; @override String get languageSectionTitle => 'Langue'; @override String get languageSectionDescription => - 'Choisissez la langue d?affichage de l?application.'; + 'Choose how the app language is displayed.'; @override - String get languageSystemDefault => 'Syst?me'; + String get languageSystemDefault => 'System'; @override String get languageSpanish => 'Espagnol'; @@ -93,11 +93,11 @@ class AppLocalizationsFr extends AppLocalizations { @override String languageUpdated(Object languageName) { - return 'Langue mise ? jour : $languageName'; + return 'Language updated: $languageName'; } @override - String get languageUpdatedSystem => 'Langue mise ? jour : Syst?me'; + String get languageUpdatedSystem => 'Language updated: System'; @override String get timerSectionTitle => 'Sleep timer'; @@ -271,7 +271,7 @@ class AppLocalizationsFr extends AppLocalizations { String get backupImportSubtitle => 'Restore from a backup file'; @override - String get backupShareSubject => 'PluriWave ? backup'; + String get backupShareSubject => 'PluriWave — backup'; @override String backupShareText(Object date) { @@ -319,11 +319,38 @@ class AppLocalizationsFr extends AppLocalizations { String get backgroundAudioSubtitle => 'Continues when the screen turns off'; @override - String get dash => '?'; + String get dash => '—'; @override String get cancelAction => 'Annuler'; @override String get equalizerTitle => 'Equalizer'; + + @override + String get recordingsOpenFolder => 'Open folder'; + + @override + String recordingsOpenFolderError(Object error) { + return 'Could not open the folder: $error'; + } + + @override + String get recordingsMaxSizeTitle => 'Maximum recording size'; + + @override + String recordingsMaxSizeSubtitle(int size) { + return 'Current limit: $size MB'; + } + + @override + String get recordingsMaxSizeDialogTitle => 'Maximum size per recording'; + + @override + String get recordingsMaxSizeMbLabel => 'Maximum megabytes'; + + @override + String recordingsMaxSizeSaved(int size) { + return 'Recording limit updated to $size MB'; + } } diff --git a/lib/l10n/gen/app_localizations_hi.dart b/lib/l10n/gen/app_localizations_hi.dart index c42bd37..4d74b94 100644 --- a/lib/l10n/gen/app_localizations_hi.dart +++ b/lib/l10n/gen/app_localizations_hi.dart @@ -12,25 +12,25 @@ class AppLocalizationsHi extends AppLocalizations { String get appTitle => 'PluriWave'; @override - String get navHome => '???'; + String get navHome => 'Home'; @override - String get navSearch => '???'; + String get navSearch => 'Search'; @override - String get navFavorites => '???????'; + String get navFavorites => 'Favorites'; @override - String get navAlarms => '??????'; + String get navAlarms => 'Alarms'; @override - String get navSettings => '????????'; + String get navSettings => 'Settings'; @override - String get actionOk => '???'; + String get actionOk => 'OK'; @override - String get sleepTimer => '????? ?????'; + String get sleepTimer => 'Sleep timer'; @override String get sleepTimerDescription => @@ -69,34 +69,35 @@ class AppLocalizationsHi extends AppLocalizations { } @override - String get settingsTitle => '????????'; + String get settingsTitle => 'Settings'; @override String get settingsSubtitle => - '?????, ????? ?? ????? ???????? ?? ??????? ?????????'; + 'Fine-grained sound control, backups, and custom stations.'; @override - String get languageSectionTitle => '????'; + String get languageSectionTitle => 'Language'; @override - String get languageSectionDescription => '?? ?? ???? ??????'; + String get languageSectionDescription => + 'Choose how the app language is displayed.'; @override - String get languageSystemDefault => '??????'; + String get languageSystemDefault => 'System'; @override - String get languageSpanish => '??????'; + String get languageSpanish => 'Spanish'; @override - String get languageEnglish => '?????????'; + String get languageEnglish => 'English'; @override String languageUpdated(Object languageName) { - return '???? ???? ??: $languageName'; + return 'Language updated: $languageName'; } @override - String get languageUpdatedSystem => '???? ???? ??: ??????'; + String get languageUpdatedSystem => 'Language updated: System'; @override String get timerSectionTitle => 'Sleep timer'; @@ -270,7 +271,7 @@ class AppLocalizationsHi extends AppLocalizations { String get backupImportSubtitle => 'Restore from a backup file'; @override - String get backupShareSubject => 'PluriWave ? backup'; + String get backupShareSubject => 'PluriWave — backup'; @override String backupShareText(Object date) { @@ -318,11 +319,38 @@ class AppLocalizationsHi extends AppLocalizations { String get backgroundAudioSubtitle => 'Continues when the screen turns off'; @override - String get dash => '?'; + String get dash => '—'; @override - String get cancelAction => '???? ????'; + String get cancelAction => 'Cancel'; @override String get equalizerTitle => 'Equalizer'; + + @override + String get recordingsOpenFolder => 'Open folder'; + + @override + String recordingsOpenFolderError(Object error) { + return 'Could not open the folder: $error'; + } + + @override + String get recordingsMaxSizeTitle => 'Maximum recording size'; + + @override + String recordingsMaxSizeSubtitle(int size) { + return 'Current limit: $size MB'; + } + + @override + String get recordingsMaxSizeDialogTitle => 'Maximum size per recording'; + + @override + String get recordingsMaxSizeMbLabel => 'Maximum megabytes'; + + @override + String recordingsMaxSizeSaved(int size) { + return 'Recording limit updated to $size MB'; + } } diff --git a/lib/l10n/gen/app_localizations_id.dart b/lib/l10n/gen/app_localizations_id.dart index 8a303ec..8562111 100644 --- a/lib/l10n/gen/app_localizations_id.dart +++ b/lib/l10n/gen/app_localizations_id.dart @@ -270,7 +270,7 @@ class AppLocalizationsId extends AppLocalizations { String get backupImportSubtitle => 'Restore from a backup file'; @override - String get backupShareSubject => 'PluriWave ? backup'; + String get backupShareSubject => 'PluriWave — backup'; @override String backupShareText(Object date) { @@ -318,11 +318,38 @@ class AppLocalizationsId extends AppLocalizations { String get backgroundAudioSubtitle => 'Continues when the screen turns off'; @override - String get dash => '?'; + String get dash => '—'; @override String get cancelAction => 'Batal'; @override String get equalizerTitle => 'Equalizer'; + + @override + String get recordingsOpenFolder => 'Open folder'; + + @override + String recordingsOpenFolderError(Object error) { + return 'Could not open the folder: $error'; + } + + @override + String get recordingsMaxSizeTitle => 'Maximum recording size'; + + @override + String recordingsMaxSizeSubtitle(int size) { + return 'Current limit: $size MB'; + } + + @override + String get recordingsMaxSizeDialogTitle => 'Maximum size per recording'; + + @override + String get recordingsMaxSizeMbLabel => 'Maximum megabytes'; + + @override + String recordingsMaxSizeSaved(int size) { + return 'Recording limit updated to $size MB'; + } } diff --git a/lib/l10n/gen/app_localizations_it.dart b/lib/l10n/gen/app_localizations_it.dart index 71f85ad..62ac623 100644 --- a/lib/l10n/gen/app_localizations_it.dart +++ b/lib/l10n/gen/app_localizations_it.dart @@ -80,7 +80,7 @@ class AppLocalizationsIt extends AppLocalizations { @override String get languageSectionDescription => - 'Scegli la lingua di visualizzazione dell?app.'; + 'Choose how the app language is displayed.'; @override String get languageSystemDefault => 'Sistema'; @@ -271,7 +271,7 @@ class AppLocalizationsIt extends AppLocalizations { String get backupImportSubtitle => 'Restore from a backup file'; @override - String get backupShareSubject => 'PluriWave ? backup'; + String get backupShareSubject => 'PluriWave — backup'; @override String backupShareText(Object date) { @@ -319,11 +319,38 @@ class AppLocalizationsIt extends AppLocalizations { String get backgroundAudioSubtitle => 'Continues when the screen turns off'; @override - String get dash => '?'; + String get dash => '—'; @override String get cancelAction => 'Annulla'; @override String get equalizerTitle => 'Equalizer'; + + @override + String get recordingsOpenFolder => 'Open folder'; + + @override + String recordingsOpenFolderError(Object error) { + return 'Could not open the folder: $error'; + } + + @override + String get recordingsMaxSizeTitle => 'Maximum recording size'; + + @override + String recordingsMaxSizeSubtitle(int size) { + return 'Current limit: $size MB'; + } + + @override + String get recordingsMaxSizeDialogTitle => 'Maximum size per recording'; + + @override + String get recordingsMaxSizeMbLabel => 'Maximum megabytes'; + + @override + String recordingsMaxSizeSaved(int size) { + return 'Recording limit updated to $size MB'; + } } diff --git a/lib/l10n/gen/app_localizations_ja.dart b/lib/l10n/gen/app_localizations_ja.dart index af0bd4c..04f50e8 100644 --- a/lib/l10n/gen/app_localizations_ja.dart +++ b/lib/l10n/gen/app_localizations_ja.dart @@ -12,25 +12,25 @@ class AppLocalizationsJa extends AppLocalizations { String get appTitle => 'PluriWave'; @override - String get navHome => '???'; + String get navHome => 'Home'; @override - String get navSearch => '??'; + String get navSearch => 'Search'; @override - String get navFavorites => '?????'; + String get navFavorites => 'Favorites'; @override - String get navAlarms => '????'; + String get navAlarms => 'Alarms'; @override - String get navSettings => '??'; + String get navSettings => 'Settings'; @override String get actionOk => 'OK'; @override - String get sleepTimer => '????????'; + String get sleepTimer => 'Sleep timer'; @override String get sleepTimerDescription => @@ -69,33 +69,35 @@ class AppLocalizationsJa extends AppLocalizations { } @override - String get settingsTitle => '??'; + String get settingsTitle => 'Settings'; @override - String get settingsSubtitle => '?????????????????????????'; + String get settingsSubtitle => + 'Fine-grained sound control, backups, and custom stations.'; @override - String get languageSectionTitle => '??'; + String get languageSectionTitle => 'Language'; @override - String get languageSectionDescription => '???????????????'; + String get languageSectionDescription => + 'Choose how the app language is displayed.'; @override - String get languageSystemDefault => '????'; + String get languageSystemDefault => 'System'; @override - String get languageSpanish => '?????'; + String get languageSpanish => 'Spanish'; @override - String get languageEnglish => '??'; + String get languageEnglish => 'English'; @override String languageUpdated(Object languageName) { - return '?????????: $languageName'; + return 'Language updated: $languageName'; } @override - String get languageUpdatedSystem => '?????????: ????'; + String get languageUpdatedSystem => 'Language updated: System'; @override String get timerSectionTitle => 'Sleep timer'; @@ -269,7 +271,7 @@ class AppLocalizationsJa extends AppLocalizations { String get backupImportSubtitle => 'Restore from a backup file'; @override - String get backupShareSubject => 'PluriWave ? backup'; + String get backupShareSubject => 'PluriWave — backup'; @override String backupShareText(Object date) { @@ -317,11 +319,38 @@ class AppLocalizationsJa extends AppLocalizations { String get backgroundAudioSubtitle => 'Continues when the screen turns off'; @override - String get dash => '?'; + String get dash => '—'; @override - String get cancelAction => '?????'; + String get cancelAction => 'Cancel'; @override String get equalizerTitle => 'Equalizer'; + + @override + String get recordingsOpenFolder => 'Open folder'; + + @override + String recordingsOpenFolderError(Object error) { + return 'Could not open the folder: $error'; + } + + @override + String get recordingsMaxSizeTitle => 'Maximum recording size'; + + @override + String recordingsMaxSizeSubtitle(int size) { + return 'Current limit: $size MB'; + } + + @override + String get recordingsMaxSizeDialogTitle => 'Maximum size per recording'; + + @override + String get recordingsMaxSizeMbLabel => 'Maximum megabytes'; + + @override + String recordingsMaxSizeSaved(int size) { + return 'Recording limit updated to $size MB'; + } } diff --git a/lib/l10n/gen/app_localizations_pt.dart b/lib/l10n/gen/app_localizations_pt.dart index 6986685..af3ecb8 100644 --- a/lib/l10n/gen/app_localizations_pt.dart +++ b/lib/l10n/gen/app_localizations_pt.dart @@ -12,7 +12,7 @@ class AppLocalizationsPt extends AppLocalizations { String get appTitle => 'PluriWave'; @override - String get navHome => 'In?cio'; + String get navHome => 'Home'; @override String get navSearch => 'Buscar'; @@ -24,7 +24,7 @@ class AppLocalizationsPt extends AppLocalizations { String get navAlarms => 'Alarmes'; @override - String get navSettings => 'Defini??es'; + String get navSettings => 'Settings'; @override String get actionOk => 'OK'; @@ -69,18 +69,18 @@ class AppLocalizationsPt extends AppLocalizations { } @override - String get settingsTitle => 'Defini??es'; + String get settingsTitle => 'Settings'; @override String get settingsSubtitle => - 'Controle fino de som, backups e esta??es personalizadas.'; + 'Fine-grained sound control, backups, and custom stations.'; @override String get languageSectionTitle => 'Idioma'; @override String get languageSectionDescription => - 'Escolha como o idioma do app ? exibido.'; + 'Choose how the app language is displayed.'; @override String get languageSystemDefault => 'Sistema'; @@ -89,7 +89,7 @@ class AppLocalizationsPt extends AppLocalizations { String get languageSpanish => 'Espanhol'; @override - String get languageEnglish => 'Ingl?s'; + String get languageEnglish => 'English'; @override String languageUpdated(Object languageName) { @@ -271,7 +271,7 @@ class AppLocalizationsPt extends AppLocalizations { String get backupImportSubtitle => 'Restore from a backup file'; @override - String get backupShareSubject => 'PluriWave ? backup'; + String get backupShareSubject => 'PluriWave — backup'; @override String backupShareText(Object date) { @@ -319,11 +319,38 @@ class AppLocalizationsPt extends AppLocalizations { String get backgroundAudioSubtitle => 'Continues when the screen turns off'; @override - String get dash => '?'; + String get dash => '—'; @override String get cancelAction => 'Cancelar'; @override String get equalizerTitle => 'Equalizer'; + + @override + String get recordingsOpenFolder => 'Open folder'; + + @override + String recordingsOpenFolderError(Object error) { + return 'Could not open the folder: $error'; + } + + @override + String get recordingsMaxSizeTitle => 'Maximum recording size'; + + @override + String recordingsMaxSizeSubtitle(int size) { + return 'Current limit: $size MB'; + } + + @override + String get recordingsMaxSizeDialogTitle => 'Maximum size per recording'; + + @override + String get recordingsMaxSizeMbLabel => 'Maximum megabytes'; + + @override + String recordingsMaxSizeSaved(int size) { + return 'Recording limit updated to $size MB'; + } } diff --git a/lib/l10n/gen/app_localizations_ru.dart b/lib/l10n/gen/app_localizations_ru.dart index 19e58f4..efa48d6 100644 --- a/lib/l10n/gen/app_localizations_ru.dart +++ b/lib/l10n/gen/app_localizations_ru.dart @@ -12,25 +12,25 @@ class AppLocalizationsRu extends AppLocalizations { String get appTitle => 'PluriWave'; @override - String get navHome => '???????'; + String get navHome => 'Home'; @override - String get navSearch => '?????'; + String get navSearch => 'Search'; @override - String get navFavorites => '?????????'; + String get navFavorites => 'Favorites'; @override - String get navAlarms => '??????????'; + String get navAlarms => 'Alarms'; @override - String get navSettings => '?????????'; + String get navSettings => 'Settings'; @override String get actionOk => 'OK'; @override - String get sleepTimer => '?????? ???'; + String get sleepTimer => 'Sleep timer'; @override String get sleepTimerDescription => @@ -69,35 +69,35 @@ class AppLocalizationsRu extends AppLocalizations { } @override - String get settingsTitle => '?????????'; + String get settingsTitle => 'Settings'; @override String get settingsSubtitle => - '?????? ????????? ?????, ????????? ????? ? ???????????????? ???????.'; + 'Fine-grained sound control, backups, and custom stations.'; @override - String get languageSectionTitle => '????'; + String get languageSectionTitle => 'Language'; @override String get languageSectionDescription => - '???????? ???? ?????????? ??????????.'; + 'Choose how the app language is displayed.'; @override - String get languageSystemDefault => '???????'; + String get languageSystemDefault => 'System'; @override - String get languageSpanish => '?????????'; + String get languageSpanish => 'Spanish'; @override - String get languageEnglish => '??????????'; + String get languageEnglish => 'English'; @override String languageUpdated(Object languageName) { - return '???? ????????: $languageName'; + return 'Language updated: $languageName'; } @override - String get languageUpdatedSystem => '???? ????????: ???????'; + String get languageUpdatedSystem => 'Language updated: System'; @override String get timerSectionTitle => 'Sleep timer'; @@ -271,7 +271,7 @@ class AppLocalizationsRu extends AppLocalizations { String get backupImportSubtitle => 'Restore from a backup file'; @override - String get backupShareSubject => 'PluriWave ? backup'; + String get backupShareSubject => 'PluriWave — backup'; @override String backupShareText(Object date) { @@ -319,11 +319,38 @@ class AppLocalizationsRu extends AppLocalizations { String get backgroundAudioSubtitle => 'Continues when the screen turns off'; @override - String get dash => '?'; + String get dash => '—'; @override - String get cancelAction => '??????'; + String get cancelAction => 'Cancel'; @override String get equalizerTitle => 'Equalizer'; + + @override + String get recordingsOpenFolder => 'Open folder'; + + @override + String recordingsOpenFolderError(Object error) { + return 'Could not open the folder: $error'; + } + + @override + String get recordingsMaxSizeTitle => 'Maximum recording size'; + + @override + String recordingsMaxSizeSubtitle(int size) { + return 'Current limit: $size MB'; + } + + @override + String get recordingsMaxSizeDialogTitle => 'Maximum size per recording'; + + @override + String get recordingsMaxSizeMbLabel => 'Maximum megabytes'; + + @override + String recordingsMaxSizeSaved(int size) { + return 'Recording limit updated to $size MB'; + } } diff --git a/lib/l10n/gen/app_localizations_zh.dart b/lib/l10n/gen/app_localizations_zh.dart index 08c3810..7614b9a 100644 --- a/lib/l10n/gen/app_localizations_zh.dart +++ b/lib/l10n/gen/app_localizations_zh.dart @@ -12,25 +12,25 @@ class AppLocalizationsZh extends AppLocalizations { String get appTitle => 'PluriWave'; @override - String get navHome => '??'; + String get navHome => 'Home'; @override - String get navSearch => '??'; + String get navSearch => 'Search'; @override - String get navFavorites => '??'; + String get navFavorites => 'Favorites'; @override - String get navAlarms => '??'; + String get navAlarms => 'Alarms'; @override - String get navSettings => '??'; + String get navSettings => 'Settings'; @override - String get actionOk => '??'; + String get actionOk => 'OK'; @override - String get sleepTimer => '?????'; + String get sleepTimer => 'Sleep timer'; @override String get sleepTimerDescription => @@ -69,33 +69,35 @@ class AppLocalizationsZh extends AppLocalizations { } @override - String get settingsTitle => '??'; + String get settingsTitle => 'Settings'; @override - String get settingsSubtitle => '?????????????????'; + String get settingsSubtitle => + 'Fine-grained sound control, backups, and custom stations.'; @override - String get languageSectionTitle => '??'; + String get languageSectionTitle => 'Language'; @override - String get languageSectionDescription => '?????????'; + String get languageSectionDescription => + 'Choose how the app language is displayed.'; @override - String get languageSystemDefault => '??'; + String get languageSystemDefault => 'System'; @override - String get languageSpanish => '????'; + String get languageSpanish => 'Spanish'; @override - String get languageEnglish => '??'; + String get languageEnglish => 'English'; @override String languageUpdated(Object languageName) { - return '??????$languageName'; + return 'Language updated: $languageName'; } @override - String get languageUpdatedSystem => '????????'; + String get languageUpdatedSystem => 'Language updated: System'; @override String get timerSectionTitle => 'Sleep timer'; @@ -269,7 +271,7 @@ class AppLocalizationsZh extends AppLocalizations { String get backupImportSubtitle => 'Restore from a backup file'; @override - String get backupShareSubject => 'PluriWave ? backup'; + String get backupShareSubject => 'PluriWave — backup'; @override String backupShareText(Object date) { @@ -317,11 +319,38 @@ class AppLocalizationsZh extends AppLocalizations { String get backgroundAudioSubtitle => 'Continues when the screen turns off'; @override - String get dash => '?'; + String get dash => '—'; @override - String get cancelAction => '??'; + String get cancelAction => 'Cancel'; @override String get equalizerTitle => 'Equalizer'; + + @override + String get recordingsOpenFolder => 'Open folder'; + + @override + String recordingsOpenFolderError(Object error) { + return 'Could not open the folder: $error'; + } + + @override + String get recordingsMaxSizeTitle => 'Maximum recording size'; + + @override + String recordingsMaxSizeSubtitle(int size) { + return 'Current limit: $size MB'; + } + + @override + String get recordingsMaxSizeDialogTitle => 'Maximum size per recording'; + + @override + String get recordingsMaxSizeMbLabel => 'Maximum megabytes'; + + @override + String recordingsMaxSizeSaved(int size) { + return 'Recording limit updated to $size MB'; + } } diff --git a/lib/pantallas/pantalla_ajustes.dart b/lib/pantallas/pantalla_ajustes.dart index cfd7d6f..a417d71 100644 --- a/lib/pantallas/pantalla_ajustes.dart +++ b/lib/pantallas/pantalla_ajustes.dart @@ -87,10 +87,12 @@ class _SeccionGrabaciones extends StatelessWidget { if (ruta == null) return; try { await estado.cambiarDirectorioGrabacion(ruta); + if (!context.mounted) return; messenger.showSnackBar( - const SnackBar(content: Text('Ruta de grabación actualizada')), + SnackBar(content: Text(l10n.recordingsPathUpdated)), ); } catch (e) { + if (!context.mounted) return; messenger.showSnackBar( SnackBar(content: Text(l10n.recordingsPathSaveError(e.toString()))), ); @@ -100,15 +102,97 @@ class _SeccionGrabaciones extends StatelessWidget { Future _restaurarRuta(BuildContext context) async { final estado = context.read(); final messenger = ScaffoldMessenger.of(context); + final l10n = AppLocalizations.of(context); await estado.restaurarDirectorioGrabacion(); + if (!context.mounted) return; messenger.showSnackBar( - const SnackBar(content: Text('Se usará la carpeta interna por defecto')), + SnackBar(content: Text(l10n.recordingsDefaultFolderRestored)), ); } + Future _abrirCarpeta(BuildContext context) async { + final estado = context.read(); + final messenger = ScaffoldMessenger.of(context); + final l10n = AppLocalizations.of(context); + try { + final abierto = await estado.abrirDirectorioGrabacion(); + if (!context.mounted) return; + if (!abierto) { + messenger.showSnackBar( + SnackBar(content: Text(l10n.recordingsOpenFolderError(l10n.dash))), + ); + } + } catch (e) { + if (!context.mounted) return; + messenger.showSnackBar( + SnackBar(content: Text(l10n.recordingsOpenFolderError(e.toString()))), + ); + } + } + + Future _editarTamanoMaximo(BuildContext context) async { + final estado = context.read(); + final l10n = AppLocalizations.of(context); + final actualMb = _bytesAMegabytes(estado.maxBytesGrabacion); + final controller = TextEditingController(text: actualMb.toString()); + + final nuevoMb = await showModalBottomSheet( + context: context, + isScrollControlled: true, + showDragHandle: true, + builder: (ctx) { + final bottom = MediaQuery.viewInsetsOf(ctx).bottom; + return Padding( + padding: EdgeInsets.fromLTRB(20, 0, 20, bottom + 24), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + l10n.recordingsMaxSizeDialogTitle, + style: Theme.of(ctx).textTheme.titleLarge, + ), + const SizedBox(height: 16), + TextField( + controller: controller, + autofocus: true, + keyboardType: TextInputType.number, + decoration: InputDecoration( + labelText: l10n.recordingsMaxSizeMbLabel, + border: const OutlineInputBorder(), + ), + ), + const SizedBox(height: 16), + FilledButton.icon( + onPressed: () { + final value = int.tryParse(controller.text.trim()); + if (value == null || value <= 0) return; + Navigator.of(ctx).pop(value); + }, + icon: const Icon(Icons.save_rounded), + label: Text(l10n.saveQuickAccessButton), + ), + ], + ), + ); + }, + ); + controller.dispose(); + if (nuevoMb == null || !context.mounted) return; + await estado.cambiarMaxBytesGrabacion(nuevoMb * 1024 * 1024); + if (!context.mounted) return; + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(l10n.recordingsMaxSizeSaved(nuevoMb))), + ); + } + + int _bytesAMegabytes(int bytes) => + (bytes / (1024 * 1024)).round().clamp(1, 1048576); + @override Widget build(BuildContext context) { final estado = context.watch(); + final l10n = AppLocalizations.of(context); return PluriGlassSurface( child: Column( @@ -119,7 +203,7 @@ class _SeccionGrabaciones extends StatelessWidget { const Icon(Icons.radio_button_checked), const SizedBox(width: 12), Text( - AppLocalizations.of(context).recordingsSectionTitle, + l10n.recordingsSectionTitle, style: Theme.of(context).textTheme.titleMedium, ), ], @@ -130,35 +214,51 @@ class _SeccionGrabaciones extends StatelessWidget { (ctx, snap) => ListTile( contentPadding: EdgeInsets.zero, leading: const Icon(Icons.folder_outlined), - title: const Text('Carpeta de grabación'), + title: Text(l10n.recordingsFolderTitle), subtitle: Text( - snap.data ?? AppLocalizations.of(context).recordingsPathCalculating, + snap.data ?? l10n.recordingsPathCalculating, maxLines: 2, overflow: TextOverflow.ellipsis, ), onTap: () => _seleccionarRuta(context), ), ), - Row( + Wrap( + spacing: 8, + runSpacing: 8, children: [ - Expanded( - child: OutlinedButton.icon( - icon: const Icon(Icons.folder_open_rounded), - label: Text(AppLocalizations.of(context).recordingsChangePath), - onPressed: () => _seleccionarRuta(context), - ), + OutlinedButton.icon( + icon: const Icon(Icons.folder_open_rounded), + label: Text(l10n.recordingsChangePath), + onPressed: () => _seleccionarRuta(context), + ), + FilledButton.tonalIcon( + icon: const Icon(Icons.folder_copy_rounded), + label: Text(l10n.recordingsOpenFolder), + onPressed: () => _abrirCarpeta(context), ), - const SizedBox(width: 8), IconButton.filledTonal( - tooltip: AppLocalizations.of(context).recordingsUseDefaultPath, + tooltip: l10n.recordingsUseDefaultPath, icon: const Icon(Icons.restore_rounded), onPressed: () => _restaurarRuta(context), ), ], ), const SizedBox(height: 8), + ListTile( + contentPadding: EdgeInsets.zero, + leading: const Icon(Icons.sd_storage_rounded), + title: Text(l10n.recordingsMaxSizeTitle), + subtitle: Text( + l10n.recordingsMaxSizeSubtitle( + _bytesAMegabytes(estado.maxBytesGrabacion), + ), + ), + onTap: () => _editarTamanoMaximo(context), + ), + const SizedBox(height: 8), Text( - AppLocalizations.of(context).recordingsOriginalStreamHint, + l10n.recordingsOriginalStreamHint, style: Theme.of(context).textTheme.bodySmall, ), ], diff --git a/lib/pantallas/pantalla_reproductor.dart b/lib/pantallas/pantalla_reproductor.dart index 76f0e37..33643ce 100644 --- a/lib/pantallas/pantalla_reproductor.dart +++ b/lib/pantallas/pantalla_reproductor.dart @@ -628,7 +628,7 @@ class _Controles extends StatelessWidget { ), color: Colors.white.withValues(alpha: 0.78), tooltip: 'Detener', - onPressed: cargando ? null : () => estado.audio.detener(), + onPressed: cargando ? null : estado.detenerReproduccion, ), ), const SizedBox(width: 16), diff --git a/lib/servicios/servicio_grabacion_radio.dart b/lib/servicios/servicio_grabacion_radio.dart index e3cf8b7..3009f66 100644 --- a/lib/servicios/servicio_grabacion_radio.dart +++ b/lib/servicios/servicio_grabacion_radio.dart @@ -85,6 +85,8 @@ class ServicioGrabacionRadio { _reloj = reloj ?? DateTime.now; static const _claveDirectorio = 'grabacion_radio_directorio'; + static const _claveMaxBytes = 'grabacion_radio_max_bytes_v1'; + static const int maxBytesPorDefecto = 500 * 1024 * 1024; final http.Client? _clienteExterno; final Future Function()? _resolverDirectorioBase; @@ -97,17 +99,21 @@ class ServicioGrabacionRadio { http.Client? _clienteActivo; Timer? _timerAutoStop; String? _directorioConfigurado; + int _maxBytes = maxBytesPorDefecto; EstadoGrabacionRadio get estado => _estado; Stream get estadoStream => _estadoController.stream; String? get directorioConfigurado => _directorioConfigurado; + int get maxBytes => _maxBytes; Future inicializar() async { try { final prefs = await SharedPreferences.getInstance(); _directorioConfigurado = prefs.getString(_claveDirectorio); + _maxBytes = prefs.getInt(_claveMaxBytes) ?? maxBytesPorDefecto; } catch (_) { _directorioConfigurado = null; + _maxBytes = maxBytesPorDefecto; } } @@ -145,6 +151,18 @@ class ServicioGrabacionRadio { _emitir(_estado); } + Future guardarMaxBytes(int bytes) async { + if (bytes <= 0) { + throw ArgumentError('El tamaño máximo debe ser mayor que cero'); + } + _maxBytes = bytes; + try { + final prefs = await SharedPreferences.getInstance(); + await prefs.setInt(_claveMaxBytes, bytes); + } catch (_) {} + _emitir(_estado); + } + Future iniciar( Emisora emisora, { Duration? duracion, @@ -199,7 +217,11 @@ class ServicioGrabacionRadio { _subscripcionStream = response.stream.listen( (chunk) { _sink?.add(chunk); - _emitir(_estado.copyWith(bytes: _estado.bytes + chunk.length)); + final nuevosBytes = _estado.bytes + chunk.length; + _emitir(_estado.copyWith(bytes: nuevosBytes)); + if (nuevosBytes >= _maxBytes) { + unawaited(detener()); + } }, onDone: () => unawaited(_finalizar()), onError: (Object error) => unawaited(_fallar(error)), diff --git a/lib/widgets/pluri_premium_widgets.dart b/lib/widgets/pluri_premium_widgets.dart index c4275ea..d5f6f77 100644 --- a/lib/widgets/pluri_premium_widgets.dart +++ b/lib/widgets/pluri_premium_widgets.dart @@ -26,11 +26,111 @@ class PluriScreenHeader extends StatelessWidget { Widget build(BuildContext context) { final t = context.pluriTokens; final theme = Theme.of(context); + final width = MediaQuery.sizeOf(context).width; + final scale = MediaQuery.textScalerOf(context).scale(1); + final compact = width < 380 || scale >= 1.25; + final iconSize = compact ? 50.0 : 56.0; + + Widget glyphBadge() => Container( + width: iconSize, + height: iconSize, + decoration: BoxDecoration( + shape: BoxShape.circle, + gradient: LinearGradient( + colors: [ + const Color(0xFF20E6FF).withValues(alpha: 0.95), + t.electricMagenta, + t.warmCoral, + ], + ), + boxShadow: [BoxShadow(color: t.glowColor, blurRadius: 28, spreadRadius: 2)], + ), + child: Center( + child: PluriIcon( + glyph: glyph, + variant: PluriIconVariant.filled, + size: compact ? 25 : 28, + ), + ), + ); + + Widget textBlock() => Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + maxLines: compact ? 2 : 1, + overflow: TextOverflow.ellipsis, + style: theme.textTheme.headlineSmall?.copyWith( + fontWeight: FontWeight.w900, + letterSpacing: -0.7, + height: 1.05, + ), + ), + const SizedBox(height: 6), + Text( + subtitle, + maxLines: compact ? 4 : 3, + overflow: TextOverflow.ellipsis, + style: theme.textTheme.bodyMedium?.copyWith( + color: theme.colorScheme.onSurface.withValues(alpha: 0.78), + height: 1.28, + ), + ), + if (primaryActionLabel != null) ...[ + const SizedBox(height: 12), + FilledButton.tonalIcon( + onPressed: onPrimaryAction, + icon: const Icon(Icons.auto_awesome_rounded, size: 18), + label: Text(primaryActionLabel!), + ), + ], + ], + ); + + Widget foreground() { + if (compact) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + glyphBadge(), + const SizedBox(width: 14), + Expanded(child: textBlock()), + ], + ), + if (trailing != null) ...[ + const SizedBox(height: 14), + Align(alignment: Alignment.centerLeft, child: trailing!), + ], + ], + ); + } + + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + glyphBadge(), + const SizedBox(width: 14), + Expanded(child: textBlock()), + if (trailing != null) ...[ + const SizedBox(width: 12), + ConstrainedBox(constraints: const BoxConstraints(maxWidth: 220), child: trailing!), + ], + ], + ); + } + return Padding( padding: EdgeInsets.fromLTRB(t.spacingMd, t.spacingSm, t.spacingMd, t.spacingSm), child: PluriGlassSurface( borderRadius: BorderRadius.circular(t.radiusLg + 8), - padding: const EdgeInsets.all(18), + padding: EdgeInsets.symmetric( + horizontal: compact ? 16 : 20, + vertical: compact ? 18 : 20, + ), child: Stack( children: [ Positioned.fill( @@ -84,63 +184,9 @@ class PluriScreenHeader extends StatelessWidget { bottom: -54, child: _Orb(color: const Color(0xFF20E6FF).withValues(alpha: 0.22), size: 116), ), - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - width: 56, - height: 56, - decoration: BoxDecoration( - shape: BoxShape.circle, - gradient: LinearGradient( - colors: [ - const Color(0xFF20E6FF).withValues(alpha: 0.95), - t.electricMagenta, - t.warmCoral, - ], - ), - boxShadow: [ - BoxShadow(color: t.glowColor, blurRadius: 28, spreadRadius: 2), - ], - ), - child: Center( - child: PluriIcon(glyph: glyph, variant: PluriIconVariant.filled, size: 28), - ), - ), - const SizedBox(width: 14), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - title, - style: theme.textTheme.headlineSmall?.copyWith( - fontWeight: FontWeight.w900, - letterSpacing: -0.7, - height: 1.02, - ), - ), - const SizedBox(height: 6), - Text( - subtitle, - style: theme.textTheme.bodyMedium?.copyWith( - color: theme.colorScheme.onSurface.withValues(alpha: 0.76), - height: 1.25, - ), - ), - if (primaryActionLabel != null) ...[ - const SizedBox(height: 12), - FilledButton.tonalIcon( - onPressed: onPrimaryAction, - icon: const Icon(Icons.auto_awesome_rounded, size: 18), - label: Text(primaryActionLabel!), - ), - ], - ], - ), - ), - if (trailing != null) trailing!, - ], + Padding( + padding: EdgeInsets.all(compact ? 2 : 4), + child: foreground(), ), ], ), @@ -149,6 +195,7 @@ class PluriScreenHeader extends StatelessWidget { } } + class PluriStatusPill extends StatelessWidget { const PluriStatusPill({ super.key, @@ -165,20 +212,31 @@ class PluriStatusPill extends StatelessWidget { Widget build(BuildContext context) { final t = context.pluriTokens; final color = accent ?? t.electricMagenta; - return Container( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(999), - color: color.withValues(alpha: 0.13), - border: Border.all(color: color.withValues(alpha: 0.38)), - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon(icon, size: 16, color: color), - const SizedBox(width: 7), - Text(label, style: Theme.of(context).textTheme.labelMedium?.copyWith(fontWeight: FontWeight.w800)), - ], + return Tooltip( + message: label, + child: Container( + constraints: const BoxConstraints(maxWidth: 220), + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(999), + color: color.withValues(alpha: 0.13), + border: Border.all(color: color.withValues(alpha: 0.38)), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(icon, size: 16, color: color), + const SizedBox(width: 7), + Flexible( + child: Text( + label, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: Theme.of(context).textTheme.labelMedium?.copyWith(fontWeight: FontWeight.w800), + ), + ), + ], + ), ), ); } diff --git a/test/servicios/servicio_grabacion_radio_test.dart b/test/servicios/servicio_grabacion_radio_test.dart index abba18a..83d2767 100644 --- a/test/servicios/servicio_grabacion_radio_test.dart +++ b/test/servicios/servicio_grabacion_radio_test.dart @@ -6,6 +6,7 @@ import 'package:http/http.dart' as http; import 'package:http/testing.dart'; import 'package:pluriwave/modelos/emisora.dart'; import 'package:pluriwave/servicios/servicio_grabacion_radio.dart'; +import 'package:shared_preferences/shared_preferences.dart'; void main() { group('ServicioGrabacionRadio', () { @@ -76,6 +77,35 @@ void main() { await controller.close(); await servicio.dispose(); }); + + test('se detiene automáticamente al alcanzar el tamaño máximo', () async { + SharedPreferences.setMockInitialValues({}); + final dir = await Directory.systemTemp.createTemp('pluriwave-rec-max-'); + final controller = StreamController>(); + final servicio = ServicioGrabacionRadio( + cliente: _StreamClient(controller.stream), + resolverDirectorioBase: () async => dir, + ); + + await servicio.inicializar(); + await servicio.guardarMaxBytes(3); + await servicio.iniciar( + const Emisora( + uuid: 'r3', + nombre: 'Radio Corta', + url: 'https://stream.example/short', + codec: 'mp3', + ), + ); + controller.add([1, 2, 3]); + await Future.delayed(Duration.zero); + await Future.delayed(const Duration(milliseconds: 20)); + + expect(servicio.estado.tipo, EstadoGrabacionRadioTipo.inactiva); + await controller.close(); + await servicio.dispose(); + }); + }); }