Farolero v0.2.0 — renombrado + i18n 18 idiomas

Renombrado de 'El Impostor' a 'Farolero'.
Package: es.freetimelab.farolero
18 idiomas: es, en, fr, pt, de, it, ru, ja, ko, zh, zh_TW, ar, hi, tr, pl, nl, ca, eu
Bancos de palabras: es (1000), en (1000), fr (1000)
Pantalla de ajustes con selector de idioma
13138 líneas Dart, 0 issues
This commit is contained in:
ShanaiaBot
2026-04-04 01:25:29 +02:00
parent 1bca50af1d
commit 5a9f592259
31 changed files with 58 additions and 53 deletions

View File

@@ -1,20 +1,26 @@
# El Impostor — Juego de deducción social # Farolero 🎭
Juego de fiesta para Android donde un grupo de jugadores debe encontrar al impostor. Juego de deducción social para Android. ¿Quién finge saber la palabra secreta?
Todos conocen la palabra secreta menos el impostor, que debe fingir conocerla.
## Características ## Características
- 3-20 jugadores, 1-4 impostores - 3-20 jugadores, 1-4 impostores
- Modo 1 móvil (pasa y mira) + multimóvil (Nearby Connections) - Modo 1 móvil (pasa y mira) + multimóvil (Nearby Connections)
- QR para conectar dispositivos (Bluetooth/WiFi Direct, sin internet) - 1000+ palabras en castellano, inglés y francés (10 categorías)
- 1000+ palabras en castellano organizadas por categorías - 18 idiomas de interfaz
- Notas privadas por jugador - Notas privadas por jugador
- Votación simultánea desde cada dispositivo - Votación simultánea desde cada dispositivo
- Pista opcional para el impostor
- 100% offline, sin servidor externo - 100% offline, sin servidor externo
## Stack
- Flutter (Dart)
- Google Nearby Connections (P2P)
- Package: es.freetimelab.farolero
## Build
```bash
flutter build apk --release
flutter build appbundle --release
```
## Desarrollado por ## Desarrollado por
FreeTTimeLab (freetimelab.es) FreeTTimeLab (freetimelab.es)
## Licencia
Propietario — todos los derechos reservados

View File

@@ -5,7 +5,7 @@ plugins {
} }
android { android {
namespace = "es.freetimelab.elimpostor" namespace = "es.freetimelab.farolero"
compileSdk = flutter.compileSdkVersion compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion ndkVersion = flutter.ndkVersion
@@ -19,7 +19,7 @@ android {
} }
defaultConfig { defaultConfig {
applicationId = "es.freetimelab.elimpostor" applicationId = "es.freetimelab.farolero"
minSdk = flutter.minSdkVersion minSdk = flutter.minSdkVersion
targetSdk = 34 targetSdk = 34
versionCode = flutter.versionCode versionCode = flutter.versionCode

View File

@@ -14,7 +14,7 @@
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.CAMERA" />
<application <application
android:label="El Impostor" android:label="Farolero"
android:name="${applicationName}" android:name="${applicationName}"
android:icon="@mipmap/ic_launcher"> android:icon="@mipmap/ic_launcher">
<activity <activity

View File

@@ -1,5 +1,4 @@
arb-dir: lib/l10n arb-dir: lib/l10n
template-arb-file: app_es.arb template-arb-file: app_es.arb
output-localization-file: app_localizations.dart output-localization-file: app_localizations.dart
output-class: AppLocalizations
output-dir: lib/l10n/generated output-dir: lib/l10n/generated

View File

@@ -1,7 +1,7 @@
{ {
"@@locale": "de", "@@locale": "de",
"appTitle": "Der Hochstapler", "appTitle": "Farolero",
"subtitle": "Soziales Deduktionsspiel", "subtitle": "Soziales Deduktionsspiel",
"loadingWords": "Wörter werden geladen...", "loadingWords": "Wörter werden geladen...",
"playersRange": "3-20 Spieler • Ohne Internet", "playersRange": "3-20 Spieler • Ohne Internet",

View File

@@ -1,6 +1,6 @@
{ {
"@@locale": "en", "@@locale": "en",
"appTitle": "The Impostor", "appTitle": "Farolero",
"subtitle": "Social deduction game", "subtitle": "Social deduction game",
"loadingWords": "Loading words...", "loadingWords": "Loading words...",
"playersRange": "3-20 players • No internet needed", "playersRange": "3-20 players • No internet needed",
@@ -122,7 +122,7 @@
"freeNote": "Free note", "freeNote": "Free note",
"freeNoteHint": "Personal notes...", "freeNoteHint": "Personal notes...",
"rulesTitle": "📖 How to play", "rulesTitle": "📖 How to play",
"rulesWhatIsTitle": "🎭 What is The Impostor?", "rulesWhatIsTitle": "🎭 What is Farolero?",
"rulesWhatIsBody": "A social deduction game for 3-20 players. Everyone receives a secret word... except the impostor! Your mission: figure out who's faking it.", "rulesWhatIsBody": "A social deduction game for 3-20 players. Everyone receives a secret word... except the impostor! Your mission: figure out who's faking it.",
"rulesHowToPlayTitle": "🔍 How do you play?", "rulesHowToPlayTitle": "🔍 How do you play?",
"rulesHowToPlayBody": "1. Roles are dealt: everyone receives the same word, except the impostor(s).\n\n2. Discussion: taking turns, each player describes the word WITHOUT saying it directly. The impostor must pretend they know it.\n\n3. Voting: once the discussion ends, everyone votes on who they think the impostor is.\n\n4. Elimination: the player with the most votes is eliminated and it is revealed whether they were the impostor or not.\n\n5. If they were the impostor, they can try to guess the word. If they get it right, the impostors win!", "rulesHowToPlayBody": "1. Roles are dealt: everyone receives the same word, except the impostor(s).\n\n2. Discussion: taking turns, each player describes the word WITHOUT saying it directly. The impostor must pretend they know it.\n\n3. Voting: once the discussion ends, everyone votes on who they think the impostor is.\n\n4. Elimination: the player with the most votes is eliminated and it is revealed whether they were the impostor or not.\n\n5. If they were the impostor, they can try to guess the word. If they get it right, the impostors win!",

View File

@@ -1,7 +1,7 @@
{ {
"@@locale": "es", "@@locale": "es",
"appTitle": "El Impostor", "appTitle": "Farolero",
"subtitle": "Juego de deducción social", "subtitle": "Juego de deducción social",
"loadingWords": "Cargando palabras...", "loadingWords": "Cargando palabras...",
"playersRange": "3-20 jugadores • Sin internet", "playersRange": "3-20 jugadores • Sin internet",
@@ -185,7 +185,7 @@
"freeNoteHint": "Apuntes personales...", "freeNoteHint": "Apuntes personales...",
"rulesTitle": "📖 Cómo jugar", "rulesTitle": "📖 Cómo jugar",
"rulesWhatIsTitle": "🎭 ¿Qué es El Impostor?", "rulesWhatIsTitle": "🎭 ¿Qué es Farolero?",
"rulesWhatIsBody": "Un juego de deducción social para 3-20 jugadores. Todos reciben una palabra secreta... ¡excepto el impostor! Tu misión: descubrir quién finge.", "rulesWhatIsBody": "Un juego de deducción social para 3-20 jugadores. Todos reciben una palabra secreta... ¡excepto el impostor! Tu misión: descubrir quién finge.",
"rulesHowToPlayTitle": "🔍 ¿Cómo se juega?", "rulesHowToPlayTitle": "🔍 ¿Cómo se juega?",
"rulesHowToPlayBody": "1. Se reparten los roles: todos reciben la misma palabra, excepto el/los impostores.\n\n2. Debate: por turnos, cada jugador describe la palabra SIN decirla directamente. El impostor debe fingir que la conoce.\n\n3. Votación: al terminar el debate, todos votan a quién creen que es el impostor.\n\n4. Eliminación: el más votado queda eliminado y se revela si era impostor o no.\n\n5. Si era impostor, puede intentar adivinar la palabra. Si acierta, ¡los impostores ganan!", "rulesHowToPlayBody": "1. Se reparten los roles: todos reciben la misma palabra, excepto el/los impostores.\n\n2. Debate: por turnos, cada jugador describe la palabra SIN decirla directamente. El impostor debe fingir que la conoce.\n\n3. Votación: al terminar el debate, todos votan a quién creen que es el impostor.\n\n4. Eliminación: el más votado queda eliminado y se revela si era impostor o no.\n\n5. Si era impostor, puede intentar adivinar la palabra. Si acierta, ¡los impostores ganan!",

View File

@@ -1,7 +1,7 @@
{ {
"@@locale": "fr", "@@locale": "fr",
"appTitle": "L'Imposteur", "appTitle": "Farolero",
"subtitle": "Jeu de déduction sociale", "subtitle": "Jeu de déduction sociale",
"loadingWords": "Chargement des mots...", "loadingWords": "Chargement des mots...",
"playersRange": "3-20 joueurs • Sans internet", "playersRange": "3-20 joueurs • Sans internet",

View File

@@ -1,7 +1,7 @@
{ {
"@@locale": "it", "@@locale": "it",
"appTitle": "L'Impostore", "appTitle": "Farolero",
"subtitle": "Gioco di deduzione sociale", "subtitle": "Gioco di deduzione sociale",
"loadingWords": "Caricamento parole...", "loadingWords": "Caricamento parole...",
"playersRange": "3-20 giocatori • Senza internet", "playersRange": "3-20 giocatori • Senza internet",

View File

@@ -132,7 +132,7 @@ abstract class AppLocalizations {
/// No description provided for @appTitle. /// No description provided for @appTitle.
/// ///
/// In es, this message translates to: /// In es, this message translates to:
/// **'El Impostor'** /// **'Farolero'**
String get appTitle; String get appTitle;
/// No description provided for @subtitle. /// No description provided for @subtitle.
@@ -798,7 +798,7 @@ abstract class AppLocalizations {
/// No description provided for @rulesWhatIsTitle. /// No description provided for @rulesWhatIsTitle.
/// ///
/// In es, this message translates to: /// In es, this message translates to:
/// **'🎭 ¿Qué es El Impostor?'** /// **'🎭 ¿Qué es Farolero?'**
String get rulesWhatIsTitle; String get rulesWhatIsTitle;
/// No description provided for @rulesWhatIsBody. /// No description provided for @rulesWhatIsBody.

View File

@@ -9,7 +9,7 @@ class AppLocalizationsDe extends AppLocalizations {
AppLocalizationsDe([String locale = 'de']) : super(locale); AppLocalizationsDe([String locale = 'de']) : super(locale);
@override @override
String get appTitle => 'Der Hochstapler'; String get appTitle => 'Farolero';
@override @override
String get subtitle => 'Soziales Deduktionsspiel'; String get subtitle => 'Soziales Deduktionsspiel';

View File

@@ -9,7 +9,7 @@ class AppLocalizationsEn extends AppLocalizations {
AppLocalizationsEn([String locale = 'en']) : super(locale); AppLocalizationsEn([String locale = 'en']) : super(locale);
@override @override
String get appTitle => 'The Impostor'; String get appTitle => 'Farolero';
@override @override
String get subtitle => 'Social deduction game'; String get subtitle => 'Social deduction game';
@@ -365,7 +365,7 @@ class AppLocalizationsEn extends AppLocalizations {
String get rulesTitle => '📖 How to play'; String get rulesTitle => '📖 How to play';
@override @override
String get rulesWhatIsTitle => '🎭 What is The Impostor?'; String get rulesWhatIsTitle => '🎭 What is Farolero?';
@override @override
String get rulesWhatIsBody => String get rulesWhatIsBody =>

View File

@@ -9,7 +9,7 @@ class AppLocalizationsEs extends AppLocalizations {
AppLocalizationsEs([String locale = 'es']) : super(locale); AppLocalizationsEs([String locale = 'es']) : super(locale);
@override @override
String get appTitle => 'El Impostor'; String get appTitle => 'Farolero';
@override @override
String get subtitle => 'Juego de deducción social'; String get subtitle => 'Juego de deducción social';
@@ -366,7 +366,7 @@ class AppLocalizationsEs extends AppLocalizations {
String get rulesTitle => '📖 Cómo jugar'; String get rulesTitle => '📖 Cómo jugar';
@override @override
String get rulesWhatIsTitle => '🎭 ¿Qué es El Impostor?'; String get rulesWhatIsTitle => '🎭 ¿Qué es Farolero?';
@override @override
String get rulesWhatIsBody => String get rulesWhatIsBody =>

View File

@@ -9,7 +9,7 @@ class AppLocalizationsFr extends AppLocalizations {
AppLocalizationsFr([String locale = 'fr']) : super(locale); AppLocalizationsFr([String locale = 'fr']) : super(locale);
@override @override
String get appTitle => 'L\'Imposteur'; String get appTitle => 'Farolero';
@override @override
String get subtitle => 'Jeu de déduction sociale'; String get subtitle => 'Jeu de déduction sociale';

View File

@@ -9,7 +9,7 @@ class AppLocalizationsIt extends AppLocalizations {
AppLocalizationsIt([String locale = 'it']) : super(locale); AppLocalizationsIt([String locale = 'it']) : super(locale);
@override @override
String get appTitle => 'L\'Impostore'; String get appTitle => 'Farolero';
@override @override
String get subtitle => 'Gioco di deduzione sociale'; String get subtitle => 'Gioco di deduzione sociale';

View File

@@ -1,7 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:el_impostor/l10n/generated/app_localizations.dart'; import 'package:farolero/l10n/generated/app_localizations.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'estado/estado_juego.dart'; import 'estado/estado_juego.dart';
import 'servicios/servicio_idioma.dart'; import 'servicios/servicio_idioma.dart';
@@ -18,11 +18,11 @@ void main() {
systemNavigationBarColor: TemaApp.colorFondo, systemNavigationBarColor: TemaApp.colorFondo,
), ),
); );
runApp(const ElImpostorApp()); runApp(const FaroleroApp());
} }
class ElImpostorApp extends StatelessWidget { class FaroleroApp extends StatelessWidget {
const ElImpostorApp({super.key}); const FaroleroApp({super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -38,7 +38,7 @@ class ElImpostorApp extends StatelessWidget {
child: Consumer<ServicioIdioma>( child: Consumer<ServicioIdioma>(
builder: (context, servicioIdioma, _) { builder: (context, servicioIdioma, _) {
return MaterialApp( return MaterialApp(
title: 'El Impostor', title: 'Farolero',
theme: TemaApp.obtenerTema(), theme: TemaApp.obtenerTema(),
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
locale: servicioIdioma.locale, locale: servicioIdioma.locale,
@@ -74,7 +74,7 @@ class PantallaCarga extends StatelessWidget {
const Text('🎭', style: TextStyle(fontSize: 72)), const Text('🎭', style: TextStyle(fontSize: 72)),
const SizedBox(height: 24), const SizedBox(height: 24),
Text( Text(
l10n?.appTitle ?? 'El Impostor', l10n?.appTitle ?? 'Farolero',
style: Theme.of(context).textTheme.headlineLarge, style: Theme.of(context).textTheme.headlineLarge,
), ),
const SizedBox(height: 16), const SizedBox(height: 16),

View File

@@ -1,7 +1,7 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:math'; import 'dart:math';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:el_impostor/l10n/generated/app_localizations.dart'; import 'package:farolero/l10n/generated/app_localizations.dart';
/// Categorías disponibles en el banco de palabras /// Categorías disponibles en el banco de palabras
class BancoPalabras { class BancoPalabras {

View File

@@ -1,5 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:el_impostor/l10n/generated/app_localizations.dart'; import 'package:farolero/l10n/generated/app_localizations.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../estado/estado_juego.dart'; import '../estado/estado_juego.dart';
import '../tema/tema_app.dart'; import '../tema/tema_app.dart';

View File

@@ -1,5 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:el_impostor/l10n/generated/app_localizations.dart'; import 'package:farolero/l10n/generated/app_localizations.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../servicios/servicio_idioma.dart'; import '../servicios/servicio_idioma.dart';
import '../tema/tema_app.dart'; import '../tema/tema_app.dart';
@@ -120,7 +120,7 @@ class _PantallaAjustesState extends State<PantallaAjustes> {
onPressed: () { onPressed: () {
showLicensePage( showLicensePage(
context: context, context: context,
applicationName: 'El Impostor', applicationName: 'Farolero',
applicationVersion: '1.0.0', applicationVersion: '1.0.0',
); );
}, },

View File

@@ -1,5 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:el_impostor/l10n/generated/app_localizations.dart'; import 'package:farolero/l10n/generated/app_localizations.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../estado/estado_juego.dart'; import '../estado/estado_juego.dart';
import '../modelos/palabra.dart'; import '../modelos/palabra.dart';

View File

@@ -1,6 +1,6 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:el_impostor/l10n/generated/app_localizations.dart'; import 'package:farolero/l10n/generated/app_localizations.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../estado/estado_juego.dart'; import '../estado/estado_juego.dart';
import '../tema/tema_app.dart'; import '../tema/tema_app.dart';

View File

@@ -1,5 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:el_impostor/l10n/generated/app_localizations.dart'; import 'package:farolero/l10n/generated/app_localizations.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../estado/estado_juego.dart'; import '../estado/estado_juego.dart';
import '../modelos/palabra.dart'; import '../modelos/palabra.dart';

View File

@@ -1,5 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:el_impostor/l10n/generated/app_localizations.dart'; import 'package:farolero/l10n/generated/app_localizations.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../estado/estado_juego.dart'; import '../estado/estado_juego.dart';
import '../servicios/servicio_notas.dart'; import '../servicios/servicio_notas.dart';

View File

@@ -1,5 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:el_impostor/l10n/generated/app_localizations.dart'; import 'package:farolero/l10n/generated/app_localizations.dart';
import '../tema/tema_app.dart'; import '../tema/tema_app.dart';
import 'pantalla_ajustes.dart'; import 'pantalla_ajustes.dart';
import 'pantalla_crear_partida.dart'; import 'pantalla_crear_partida.dart';

View File

@@ -1,5 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:el_impostor/l10n/generated/app_localizations.dart'; import 'package:farolero/l10n/generated/app_localizations.dart';
import '../tema/tema_app.dart'; import '../tema/tema_app.dart';
class PantallaReglas extends StatelessWidget { class PantallaReglas extends StatelessWidget {

View File

@@ -1,5 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:el_impostor/l10n/generated/app_localizations.dart'; import 'package:farolero/l10n/generated/app_localizations.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../estado/estado_juego.dart'; import '../estado/estado_juego.dart';
import '../modelos/partida.dart'; import '../modelos/partida.dart';

View File

@@ -1,5 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:el_impostor/l10n/generated/app_localizations.dart'; import 'package:farolero/l10n/generated/app_localizations.dart';
import '../tema/tema_app.dart'; import '../tema/tema_app.dart';
class PantallaUnirse extends StatelessWidget { class PantallaUnirse extends StatelessWidget {

View File

@@ -1,5 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:el_impostor/l10n/generated/app_localizations.dart'; import 'package:farolero/l10n/generated/app_localizations.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../estado/estado_juego.dart'; import '../estado/estado_juego.dart';
import '../modelos/palabra.dart'; import '../modelos/palabra.dart';

View File

@@ -1,5 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:el_impostor/l10n/generated/app_localizations.dart'; import 'package:farolero/l10n/generated/app_localizations.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../estado/estado_juego.dart'; import '../estado/estado_juego.dart';
import '../tema/tema_app.dart'; import '../tema/tema_app.dart';

View File

@@ -1,5 +1,5 @@
name: el_impostor name: farolero
description: "El Impostor - Juego de deducción social" description: "Farolero — Juego de deducción social. ¿Quién finge saber?"
publish_to: 'none' publish_to: 'none'
version: 1.0.0+1 version: 1.0.0+1

View File

@@ -1,9 +1,9 @@
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:el_impostor/main.dart'; import 'package:farolero/main.dart';
void main() { void main() {
testWidgets('App carga correctamente', (WidgetTester tester) async { testWidgets('App carga correctamente', (WidgetTester tester) async {
await tester.pumpWidget(const ElImpostorApp()); await tester.pumpWidget(const FaroleroApp());
expect(find.text('El Impostor'), findsOneWidget); expect(find.text('El Impostor'), findsOneWidget);
}); });
} }