Files
farolero/lib/modelos/palabra.dart
ShanaiaBot 1bca50af1d 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
2026-04-04 01:18:09 +02:00

98 lines
3.2 KiB
Dart

import 'dart:convert';
import 'dart:math';
import 'package:flutter/services.dart';
import 'package:el_impostor/l10n/generated/app_localizations.dart';
/// Categorías disponibles en el banco de palabras
class BancoPalabras {
final Map<String, List<String>> categorias;
BancoPalabras(this.categorias);
static final Map<String, BancoPalabras> _instancias = {};
static Future<BancoPalabras> cargar({String idioma = 'es'}) async {
if (_instancias.containsKey(idioma)) return _instancias[idioma]!;
// Intentar cargar el banco del idioma solicitado, fallback a castellano
String jsonStr;
try {
final archivo = idioma == 'es'
? 'assets/palabras.json'
: 'assets/palabras_$idioma.json';
jsonStr = await rootBundle.loadString(archivo);
} catch (_) {
// Fallback a castellano si no existe el banco para ese idioma
if (idioma != 'es') {
return cargar(idioma: 'es');
}
rethrow;
}
final data = json.decode(jsonStr) as Map<String, dynamic>;
final cats = data['categorias'] as Map<String, dynamic>;
final mapa = <String, List<String>>{};
for (final entrada in cats.entries) {
mapa[entrada.key] = List<String>.from(entrada.value);
}
_instancias[idioma] = BancoPalabras(mapa);
return _instancias[idioma]!;
}
List<String> get nombresCategorias => categorias.keys.toList();
/// Obtiene una palabra aleatoria de la categoría dada (o de todas si es null)
String palabraAleatoria(String? categoria) {
final rng = Random();
if (categoria == null || categoria == 'todas') {
final todasPalabras = categorias.values.expand((l) => l).toList();
return todasPalabras[rng.nextInt(todasPalabras.length)];
}
final lista = categorias[categoria]!;
return lista[rng.nextInt(lista.length)];
}
/// Devuelve la categoría a la que pertenece una palabra
String? categoriaDepalabra(String palabra) {
for (final entrada in categorias.entries) {
if (entrada.value.contains(palabra)) return entrada.key;
}
return null;
}
/// Devuelve el nombre localizado de la categoría usando AppLocalizations
static String nombreBonitoCategoria(String clave, [AppLocalizations? l10n]) {
if (l10n != null) {
final nombres = {
'todas': l10n.categoryAll,
'animales': l10n.categoryAnimals,
'comida': l10n.categoryFood,
'paises': l10n.categoryCountries,
'deportes': l10n.categorySports,
'profesiones': l10n.categoryProfessions,
'objetos': l10n.categoryObjects,
'lugares': l10n.categoryPlaces,
'peliculas': l10n.categoryMovies,
'musica': l10n.categoryMusic,
'tecnologia': l10n.categoryTechnology,
};
return nombres[clave] ?? clave;
}
// Fallback a castellano si no hay l10n
const nombres = {
'todas': 'Todas',
'animales': 'Animales',
'comida': 'Comida',
'paises': 'Países',
'deportes': 'Deportes',
'profesiones': 'Profesiones',
'objetos': 'Objetos',
'lugares': 'Lugares',
'peliculas': 'Películas',
'musica': 'Música',
'tecnologia': 'Tecnología',
};
return nombres[clave] ?? clave;
}
}