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:
@@ -1,6 +1,7 @@
|
||||
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 {
|
||||
@@ -8,19 +9,34 @@ class BancoPalabras {
|
||||
|
||||
BancoPalabras(this.categorias);
|
||||
|
||||
static BancoPalabras? _instancia;
|
||||
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;
|
||||
}
|
||||
|
||||
static Future<BancoPalabras> cargar() async {
|
||||
if (_instancia != null) return _instancia!;
|
||||
final jsonStr = await rootBundle.loadString('assets/palabras.json');
|
||||
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);
|
||||
}
|
||||
_instancia = BancoPalabras(mapa);
|
||||
return _instancia!;
|
||||
_instancias[idioma] = BancoPalabras(mapa);
|
||||
return _instancias[idioma]!;
|
||||
}
|
||||
|
||||
List<String> get nombresCategorias => categorias.keys.toList();
|
||||
@@ -44,7 +60,25 @@ class BancoPalabras {
|
||||
return null;
|
||||
}
|
||||
|
||||
static String nombreBonitoCategoria(String clave) {
|
||||
/// 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',
|
||||
|
||||
Reference in New Issue
Block a user