feat(i18n): add localization foundation
This commit is contained in:
+74
-44
@@ -3,6 +3,8 @@ import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'estado/estado_radio.dart';
|
||||
import 'estado/estado_alarmas.dart';
|
||||
import 'estado/estado_idioma.dart';
|
||||
import 'l10n/gen/app_localizations.dart';
|
||||
import 'modelos/alarma_musical.dart';
|
||||
import 'pantallas/pantalla_alarmas.dart';
|
||||
import 'pantallas/pantalla_alarma_sonando.dart';
|
||||
@@ -27,14 +29,21 @@ class PluriWaveApp extends StatelessWidget {
|
||||
providers: [
|
||||
ChangeNotifierProvider(create: (_) => EstadoRadio()),
|
||||
ChangeNotifierProvider(create: (_) => EstadoAlarmas()),
|
||||
ChangeNotifierProvider(create: (_) => EstadoIdioma()),
|
||||
],
|
||||
child: MaterialApp(
|
||||
title: 'PluriWave',
|
||||
debugShowCheckedModeBanner: false,
|
||||
theme: PluriWaveTheme.dark(),
|
||||
darkTheme: PluriWaveTheme.dark(),
|
||||
themeMode: ThemeMode.dark,
|
||||
home: const _PaginaPrincipal(),
|
||||
child: Consumer<EstadoIdioma>(
|
||||
builder:
|
||||
(context, estadoIdioma, _) => MaterialApp(
|
||||
title: 'PluriWave',
|
||||
debugShowCheckedModeBanner: false,
|
||||
theme: PluriWaveTheme.dark(),
|
||||
darkTheme: PluriWaveTheme.dark(),
|
||||
themeMode: ThemeMode.dark,
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
supportedLocales: AppLocalizations.supportedLocales,
|
||||
locale: estadoIdioma.localeSeleccionado,
|
||||
home: const _PaginaPrincipal(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -63,27 +72,12 @@ class _PaginaPrincipalState extends State<_PaginaPrincipal> {
|
||||
PantallaAjustes(),
|
||||
];
|
||||
|
||||
static const _navItems = [
|
||||
PluriNavItem(
|
||||
glyph: PluriIconGlyph.home,
|
||||
label: 'Inicio',
|
||||
),
|
||||
PluriNavItem(
|
||||
glyph: PluriIconGlyph.search,
|
||||
label: 'Buscar',
|
||||
),
|
||||
PluriNavItem(
|
||||
glyph: PluriIconGlyph.favorites,
|
||||
label: 'Favoritos',
|
||||
),
|
||||
PluriNavItem(
|
||||
glyph: PluriIconGlyph.alarm,
|
||||
label: 'Alarmas',
|
||||
),
|
||||
PluriNavItem(
|
||||
glyph: PluriIconGlyph.settings,
|
||||
label: 'Ajustes',
|
||||
),
|
||||
List<PluriNavItem> _navItems(AppLocalizations l10n) => [
|
||||
PluriNavItem(glyph: PluriIconGlyph.home, label: l10n.navHome),
|
||||
PluriNavItem(glyph: PluriIconGlyph.search, label: l10n.navSearch),
|
||||
PluriNavItem(glyph: PluriIconGlyph.favorites, label: l10n.navFavorites),
|
||||
PluriNavItem(glyph: PluriIconGlyph.alarm, label: l10n.navAlarms),
|
||||
PluriNavItem(glyph: PluriIconGlyph.settings, label: l10n.navSettings),
|
||||
];
|
||||
|
||||
@override
|
||||
@@ -101,7 +95,10 @@ class _PaginaPrincipalState extends State<_PaginaPrincipal> {
|
||||
SnackBar(
|
||||
content: Text(msg),
|
||||
duration: const Duration(seconds: 3),
|
||||
action: SnackBarAction(label: 'OK', onPressed: () {}),
|
||||
action: SnackBarAction(
|
||||
label: AppLocalizations.of(context).actionOk,
|
||||
onPressed: () {},
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
@@ -133,13 +130,15 @@ class _PaginaPrincipalState extends State<_PaginaPrincipal> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = AppLocalizations.of(context);
|
||||
|
||||
return PluriWaveScaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('PluriWave'),
|
||||
title: Text(l10n.appTitle),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.bedtime_outlined),
|
||||
tooltip: 'Timer de sueño',
|
||||
tooltip: l10n.sleepTimer,
|
||||
onPressed: () => _mostrarTimerDialog(context),
|
||||
),
|
||||
],
|
||||
@@ -177,7 +176,7 @@ class _PaginaPrincipalState extends State<_PaginaPrincipal> {
|
||||
children: [
|
||||
const MiniReproductor(),
|
||||
PluriBottomNavigation(
|
||||
items: _navItems,
|
||||
items: _navItems(l10n),
|
||||
selectedIndex: _indice,
|
||||
onSelected: (i) => setState(() => _indice = i),
|
||||
),
|
||||
@@ -212,7 +211,11 @@ class _PaginaPrincipalState extends State<_PaginaPrincipal> {
|
||||
setState(() => _indice = 3);
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Omitida esta ejecución de ${alarma.nombre}.'),
|
||||
content: Text(
|
||||
AppLocalizations.of(context).skipCurrentAlarmExecution(
|
||||
alarma.nombre,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
return;
|
||||
@@ -252,12 +255,12 @@ class _PaginaPrincipalState extends State<_PaginaPrincipal> {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Timer de sueño',
|
||||
AppLocalizations.of(ctx).sleepTimer,
|
||||
style: Theme.of(ctx).textTheme.titleLarge,
|
||||
),
|
||||
const SizedBox(height: PluriLayout.sectionGap),
|
||||
Text(
|
||||
'Apagado suave de la radio con cuenta atrás exacta.',
|
||||
AppLocalizations.of(ctx).sleepTimerDescription,
|
||||
style: Theme.of(ctx).textTheme.bodySmall,
|
||||
),
|
||||
const SizedBox(height: PluriLayout.panelGap),
|
||||
@@ -280,7 +283,9 @@ class _PaginaPrincipalState extends State<_PaginaPrincipal> {
|
||||
estado.cancelarTimer();
|
||||
Navigator.pop(ctx);
|
||||
},
|
||||
child: const Text('Cancelar timer'),
|
||||
child: Text(
|
||||
AppLocalizations.of(ctx).cancelTimer,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -308,7 +313,9 @@ class _PaginaPrincipalState extends State<_PaginaPrincipal> {
|
||||
),
|
||||
ActionChip(
|
||||
avatar: const Icon(Icons.tune_rounded, size: 18),
|
||||
label: const Text('Otro'),
|
||||
label: Text(
|
||||
AppLocalizations.of(ctx).optionOther,
|
||||
),
|
||||
onPressed: () async {
|
||||
final duracion =
|
||||
await _pedirDuracionPersonalizada(ctx);
|
||||
@@ -382,7 +389,11 @@ class _TimerPersonalizadoSheetState extends State<_TimerPersonalizadoSheet> {
|
||||
);
|
||||
if (duracion <= Duration.zero) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('Elegí una duración mayor que cero.')),
|
||||
SnackBar(
|
||||
content: Text(
|
||||
AppLocalizations.of(context).durationGreaterThanZero,
|
||||
),
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -403,30 +414,49 @@ class _TimerPersonalizadoSheetState extends State<_TimerPersonalizadoSheet> {
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Text(
|
||||
'Duración personalizada',
|
||||
AppLocalizations.of(context).customDurationTitle,
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
const SizedBox(height: PluriLayout.sectionGap),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(child: _campoTiempo(_horasCtrl, 'Horas')),
|
||||
Expanded(
|
||||
child: _campoTiempo(
|
||||
_horasCtrl,
|
||||
AppLocalizations.of(context).hoursLabel,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: PluriLayout.compactGap),
|
||||
Expanded(child: _campoTiempo(_minutosCtrl, 'Minutos')),
|
||||
Expanded(
|
||||
child: _campoTiempo(
|
||||
_minutosCtrl,
|
||||
AppLocalizations.of(context).minutesLabel,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: PluriLayout.compactGap),
|
||||
Expanded(child: _campoTiempo(_segundosCtrl, 'Segundos')),
|
||||
Expanded(
|
||||
child: _campoTiempo(
|
||||
_segundosCtrl,
|
||||
AppLocalizations.of(context).secondsLabel,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: PluriLayout.compactGap),
|
||||
SwitchListTile.adaptive(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
title: const Text('Guardar como acceso rápido'),
|
||||
title: Text(
|
||||
AppLocalizations.of(context).saveQuickAccess,
|
||||
),
|
||||
value: _guardarPreset,
|
||||
onChanged: (value) => setState(() => _guardarPreset = value),
|
||||
),
|
||||
const SizedBox(height: PluriLayout.sectionGap),
|
||||
FilledButton.icon(
|
||||
icon: const Icon(Icons.bedtime_rounded),
|
||||
label: const Text('Iniciar timer'),
|
||||
label: Text(
|
||||
AppLocalizations.of(context).startTimer,
|
||||
),
|
||||
onPressed: _confirmar,
|
||||
),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user