v0.2.0: i18n 18 idiomas + pantalla ajustes + bancos multiidioma

Internacionalización completa:
- 18 ficheros .arb: es, en, fr, pt, de, it, ru, ja, ko, zh, zh_TW, ar, hi, tr, pl, nl, ca, eu
- Todos los strings extraídos de todas las pantallas
- Detección automática de idioma del sistema
- Selector manual en pantalla de ajustes

Pantalla de ajustes nueva:
- Selector de idioma con banderas emoji
- Vibración ON/OFF
- Acerca de (versión, desarrollador)

Bancos de palabras multiidioma:
- palabras.json (castellano, 1000 palabras)
- palabras_en.json (inglés, 1000 palabras)
- palabras_fr.json (francés, 1000 palabras)
- Fallback a castellano si no hay banco del idioma

13138 líneas Dart, 39 ficheros, 0 issues en flutter analyze
This commit is contained in:
ShanaiaBot
2026-04-04 01:18:09 +02:00
parent de2c8ffa18
commit 1bca50af1d
56 changed files with 14389 additions and 201 deletions

View File

@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:el_impostor/l10n/generated/app_localizations.dart';
import 'package:provider/provider.dart';
import '../estado/estado_juego.dart';
import '../modelos/palabra.dart';
@@ -17,6 +18,7 @@ class _PantallaVerPalabraState extends State<PantallaVerPalabra> {
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
final estado = context.watch<EstadoJuego>();
final partida = estado.partida;
if (partida == null) return const SizedBox.shrink();
@@ -26,7 +28,7 @@ class _PantallaVerPalabraState extends State<PantallaVerPalabra> {
return Scaffold(
appBar: AppBar(
title: const Text('Ver tu palabra'),
title: Text(l10n.seeYourWord),
automaticallyImplyLeading: false,
),
body: Padding(
@@ -34,13 +36,13 @@ class _PantallaVerPalabraState extends State<PantallaVerPalabra> {
child: Column(
children: [
Text(
'Cada jugador debe ver su palabra en secreto',
l10n.eachPlayerMustSee,
style: Theme.of(context).textTheme.bodyMedium,
textAlign: TextAlign.center,
),
const SizedBox(height: 8),
Text(
'Ronda ${partida.rondaActual}',
l10n.roundNumber(partida.rondaActual),
style: Theme.of(context).textTheme.titleMedium?.copyWith(
color: TemaApp.colorNaranja,
),
@@ -69,7 +71,7 @@ class _PantallaVerPalabraState extends State<PantallaVerPalabra> {
),
title: Text(jugador.nombre),
subtitle: Text(
haVisto ? 'Ya ha visto su palabra' : 'Pulsa para ver',
haVisto ? l10n.alreadySeen : l10n.tapToSee,
),
trailing: haVisto
? const Icon(Icons.check_circle,
@@ -102,8 +104,8 @@ class _PantallaVerPalabraState extends State<PantallaVerPalabra> {
: null,
icon: const Icon(Icons.forum),
label: Text(todosHanVisto
? 'Todos han visto → Iniciar debate'
: 'Faltan ${partida.jugadores.length - _hanVisto.length} jugadores'),
? l10n.allSeenStartDebate
: l10n.playersRemaining(partida.jugadores.length - _hanVisto.length)),
),
),
],
@@ -163,6 +165,8 @@ class _PantallaRevelarPalabraState extends State<_PantallaRevelarPalabra> {
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
return Scaffold(
appBar: AppBar(title: Text(widget.nombre)),
body: Center(
@@ -208,8 +212,8 @@ class _PantallaRevelarPalabraState extends State<_PantallaRevelarPalabra> {
const SizedBox(height: 16),
Text(
widget.esImpostor
? '¡Eres el impostor!'
: 'Tu palabra es:',
? l10n.youAreImpostor
: l10n.yourWordIs,
style: Theme.of(context)
.textTheme
.titleLarge
@@ -236,7 +240,7 @@ class _PantallaRevelarPalabraState extends State<_PantallaRevelarPalabra> {
if (widget.esImpostor && widget.pistaActiva) ...[
const SizedBox(height: 12),
Text(
'Pista: ${BancoPalabras.nombreBonitoCategoria(widget.categoria)}',
l10n.clueCategory(BancoPalabras.nombreBonitoCategoria(widget.categoria, l10n)),
style: Theme.of(context)
.textTheme
.bodyLarge
@@ -252,13 +256,13 @@ class _PantallaRevelarPalabraState extends State<_PantallaRevelarPalabra> {
const Text('🔒', style: TextStyle(fontSize: 48)),
const SizedBox(height: 16),
Text(
'Mantén pulsado para ver tu palabra',
l10n.holdToSeeWord,
style: Theme.of(context).textTheme.titleMedium,
textAlign: TextAlign.center,
),
const SizedBox(height: 8),
Text(
'Asegúrate de que nadie más mira',
l10n.makeSureNoOneLooks,
style: Theme.of(context).textTheme.bodyMedium,
),
],
@@ -291,8 +295,8 @@ class _PantallaRevelarPalabraState extends State<_PantallaRevelarPalabra> {
child: Center(
child: Text(
_manteniendo
? '👁️ Mostrando...'
: '👆 Mantén pulsado para ver',
? l10n.showingWord
: l10n.holdToSee,
style: const TextStyle(
color: Colors.white,
fontSize: 18,
@@ -313,7 +317,7 @@ class _PantallaRevelarPalabraState extends State<_PantallaRevelarPalabra> {
Navigator.pop(context);
},
icon: const Icon(Icons.check),
label: const Text('He visto mi palabra'),
label: Text(l10n.seenMyWord),
),
),
],