Compare commits

...
5 Commits
Author SHA1 Message Date
FreeTLab 633d156892 chore(deps): refresh the lockfile after running the suite
Build & Deploy Farolero / Análisis de código (push) Failing after 7s
Build & Deploy Farolero / Build APK + AAB release (push) Skipped
2026-07-25 20:36:49 +02:00
FreeTLab 4167319da8 feat(palabras): give every word its own impostor clue
The clue used to be the category name, which is the same for a hundred
words. Each of the 1000 words now carries a single associated trait:
Perro -> Fiel, Cebolla -> Hace llorar, Egipto -> Piramides.

18000 clues across the 18 languages. Files move to version 3; the loader
already reads both formats.

Verification caught 79 clues that contained the word they were meant to
hide and gave it away. Eight were exact matches caused by homonyms that do
not exist in Spanish: Schach and Xake mean both chess and check, and the
same happened with the Arabic 5G and the Chinese Apple and Spam. The other
71 contained the word as a substring, such as Libro -> "Pagine e
segnalibro". All rewritten.

banco_pistas_test guards it: per language it checks 10x100 words, no empty
clue and no clue containing its own word. One-character words are skipped
because any sentence contains them; the Turkish title for the film IT is a
bare "O".
2026-07-25 20:36:48 +02:00
FreeTLab b1b12cc8af feat(i18n): fill the translation backlog and add the new strings
40 keys existed only in app_es.arb and fell back to Spanish everywhere else
(15 of them in English). Most were multi-device screens: hostGame, votar,
clueIs, whoDoYouThinkIsTheImpostor, waitingPlayersSeeWord.

Adds those plus the new keys for impostor awareness, the adjusted impostor
count, the eliminated-player notice and the reconnection screen.

51 keys across the 18 supported languages.
2026-07-25 20:36:39 +02:00
FreeTLab 863690168c feat(multidispositivo): reconnection, impostor awareness and protocol fixes
Fixes
- SnapshotPartidaOnline no longer serializes esImpostor unless the game is
  over. Every phase change was broadcasting the impostor roles in clear to
  all clients.
- The impostor clue travels in its own field and only when the game enables
  it. It used to be sent as the category key ("todas" when no category was
  picked) and was overwritten by each phase snapshot.
- Eliminated players can no longer vote nor be voted for, on both the client
  screen and the host listener.
- Nearby listeners are removed on dispose; votes are no longer dispatched
  twice; votacionResultado no longer triggers two navigations.
- _jugadoresHostControlados handed the secret word to the host's own
  impostors in the payload.
- Impostor cap unified as maxImpostoresPara(n) for both modes, and the
  silent clamp in multi-device now reports the effective number.
- palabraAleatoria uses Random.secure.

Impostors know each other
- ConfigPartida.impostoresSeConocen, on by default. companerosImpostores is
  nullable: null means nothing to show, an empty list means "you are the
  only impostor".

Reconnection
- IdentidadDispositivo persists a stable device id; the host uses it as the
  clientId so a phone that drops and returns is the same client. Falls back
  to the endpointId for clients that do not send one.
- Usuario.absorbidoDe records the original owner when the host takes over a
  disconnected player, and they are handed back automatically on return.
- New solicitarResync/resync messages: the host replies with the current
  phase plus that client's own players, and the client jumps straight to the
  running phase.
- Readiness is keyed by clientId instead of endpointId, and a disconnected
  client no longer blocks the round.
- The retry gives up after three minutes, only reconnects to the host it
  belonged to, and is cancelled correctly while shutting down.

Per-word clue support
- The word bank loader accepts both the old list-of-strings format and the
  new one carrying a clue per word, falling back to the category clue.

Not verified on real devices: Nearby reconnection timing still needs two
Android phones.
2026-07-25 20:36:32 +02:00
FreeTLab bad641653c fix(test): make the suite runnable without device plugins
crearPartida clears the notes, which goes through SharedPreferences, and
ServicioNearby.dispose called notifyListeners after tearing the notifier
down. Both failed on plugin channels that do not exist in the test host.

Suite goes from 25 passing / 8 failing to a green run.
2026-07-25 20:36:15 +02:00
81 changed files with 78046 additions and 20422 deletions
+4054 -1054
View File
File diff suppressed because it is too large Load Diff
+4054 -1054
View File
File diff suppressed because it is too large Load Diff
+4054 -1054
View File
File diff suppressed because it is too large Load Diff
+4054 -1054
View File
File diff suppressed because it is too large Load Diff
+4054 -1054
View File
File diff suppressed because it is too large Load Diff
+4054 -1054
View File
File diff suppressed because it is too large Load Diff
+4054 -1054
View File
File diff suppressed because it is too large Load Diff
+4054 -1054
View File
File diff suppressed because it is too large Load Diff
+4054 -1054
View File
File diff suppressed because it is too large Load Diff
+4054 -1054
View File
File diff suppressed because it is too large Load Diff
+4054 -1054
View File
File diff suppressed because it is too large Load Diff
+4054 -1054
View File
File diff suppressed because it is too large Load Diff
+4054 -1054
View File
File diff suppressed because it is too large Load Diff
+4054 -1054
View File
File diff suppressed because it is too large Load Diff
+4054 -1054
View File
File diff suppressed because it is too large Load Diff
+4054 -1054
View File
File diff suppressed because it is too large Load Diff
+4054 -1054
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+50 -32
View File
@@ -42,6 +42,36 @@ class EstadoJuego extends ChangeNotifier {
notifyListeners();
}
/// Máximo de impostores admitido para un número de jugadores dado.
/// Es la misma regla en modo un solo móvil y en multidispositivo.
static int maxImpostoresPara(int numJugadores) =>
(numJugadores ~/ 3).clamp(1, 4);
/// Asigna impostores con un generador seguro y reparte la palabra al resto.
void _repartirRoles(
List<Jugador> jugadores,
ConfigPartida config,
String palabra,
) {
final rng = Random.secure();
final numImpostores = config.numImpostores.clamp(
1,
maxImpostoresPara(jugadores.length),
);
final impostoresElegidos = <int>{};
while (impostoresElegidos.length < numImpostores) {
impostoresElegidos.add(rng.nextInt(jugadores.length));
}
for (final i in impostoresElegidos) {
jugadores[i].esImpostor = true;
}
for (final jugador in jugadores) {
if (!jugador.esImpostor) {
jugador.palabra = palabra;
}
}
}
/// Crea una nueva partida con la configuración dada y lista de jugadores
void crearPartida({
required ConfigPartida config,
@@ -60,29 +90,14 @@ class EstadoJuego extends ChangeNotifier {
return Jugador(id: 'j${e.key}', nombre: e.value);
}).toList();
// Asignar impostores usando Random seguro (no predecible)
final rng = Random.secure();
final numImpostores = config.numImpostores.clamp(1, jugadores.length ~/ 3);
final impostoresElegidos = <int>{};
while (impostoresElegidos.length < numImpostores) {
impostoresElegidos.add(rng.nextInt(jugadores.length));
}
for (final i in impostoresElegidos) {
jugadores[i].esImpostor = true;
}
// Asignar palabras
for (final j in jugadores) {
if (!j.esImpostor) {
j.palabra = palabra;
}
}
_repartirRoles(jugadores, config, palabra);
_partida = Partida(
config: config,
jugadores: jugadores,
palabraSecreta: palabra,
categoriaReal: categoriaReal,
pistaImpostor: _banco!.pistaDePalabra(palabra, categoria: categoriaReal),
);
_votos.clear();
@@ -117,27 +132,14 @@ class EstadoJuego extends ChangeNotifier {
);
}).toList();
final rng = Random.secure();
final numImpostores = config.numImpostores.clamp(1, jugadores.length ~/ 3);
final impostoresElegidos = <int>{};
while (impostoresElegidos.length < numImpostores) {
impostoresElegidos.add(rng.nextInt(jugadores.length));
}
for (final i in impostoresElegidos) {
jugadores[i].esImpostor = true;
}
for (final jugador in jugadores) {
if (!jugador.esImpostor) {
jugador.palabra = palabra;
}
}
_repartirRoles(jugadores, config, palabra);
_partida = Partida(
config: config,
jugadores: jugadores,
palabraSecreta: palabra,
categoriaReal: categoriaReal,
pistaImpostor: _banco!.pistaDePalabra(palabra, categoria: categoriaReal),
);
_votos.clear();
@@ -145,6 +147,22 @@ class EstadoJuego extends ChangeNotifier {
notifyListeners();
}
/// Nombres del resto de impostores para un jugador dado.
///
/// Devuelve `null` cuando no hay nada que mostrar (el jugador no es impostor
/// o la partida no permite que se conozcan) y una lista —posiblemente vacía,
/// si es el único impostor— cuando sí procede mostrarlo.
List<String>? companerosImpostoresDe(String jugadorId) {
final partida = _partida;
if (partida == null || !partida.config.impostoresSeConocen) return null;
final indice = partida.jugadores.indexWhere((j) => j.id == jugadorId);
if (indice < 0 || !partida.jugadores[indice].esImpostor) return null;
return partida.jugadores
.where((j) => j.esImpostor && j.id != jugadorId)
.map((j) => j.nombre)
.toList();
}
/// Avanza a la fase de debate
void iniciarDebate() {
if (_partida == null) return;
+52 -1
View File
@@ -317,5 +317,56 @@
"type": "String"
}
}
}
},
"debate": "🗣️ نقاش",
"scanToJoin": "امسح رمز QR للانضمام",
"connectedPlayers": "اللاعبون المتصلون",
"hostGame": "إدارة الجولة",
"waitingPlayersSeeWord": "بانتظار أن يرى الجميع كلمتهم...",
"activePlayers": "اللاعبون النشطون",
"playersVoted": "صوّتوا",
"waitingVoting": "بانتظار الأصوات...",
"waitingForPlayers": "بانتظار اللاعبين...",
"needMorePlayers": "يلزم {count} لاعبين إضافيين",
"starting": "جارٍ البدء...",
"enterNameAndScan": "اكتب اسمك وامسح رمز QR الخاص بالمضيف",
"yourName": "اسمك",
"nameRequired": "اكتب اسمك",
"connectingTo": "جارٍ الاتصال بـ",
"scanQR": "مسح رمز QR",
"scanHostQR": "وجّه الكاميرا إلى رمز QR للمضيف",
"connectedWaiting": "تم الاتصال!",
"waitingForHost": "بانتظار أن يبدأ المضيف الجولة...",
"enterNameToSearch": "اكتب اسمك للبحث عن جولات قريبة",
"searchGames": "البحث عن جولات",
"searchingGames": "جارٍ البحث عن جولات قريبة...",
"noGamesFound": "لم يتم العثور على جولات",
"noGamesFoundHint": "تأكد من أن المضيف قد فتح الغرفة وأنكم قريبون",
"orScanQR": "لا تظهر؟ امسح رمز QR للمضيف",
"iveSeenIt": "لقد رأيتها",
"clueIs": "التلميح: {category}",
"debatePhaseActive": "مرحلة النقاش جارية",
"debateInstructions": "تحدثوا فيما بينكم وقولوا من تظنون أنه المحتال. عندما تكونون جاهزين، اطلبوا التصويت.",
"solicitarVotacion": "طلب التصويت",
"votacionSolicitada": "تم طلب التصويت",
"whoDoYouThinkIsTheImpostor": "من هو المحتال؟",
"selectOnePlayer": "اختر لاعبًا للتصويت",
"votar": "تصويت",
"selectYourProfile": "ملفك الشخصي",
"selectProfile": "اختر ملفًا شخصيًا",
"createNewUser": "إنشاء مستخدم جديد",
"userNameRequired": "لا يمكن ترك الاسم فارغًا",
"profileSelected": "تم اختيار الملف الشخصي",
"availableProfiles": "الملفات الشخصية المتاحة",
"impostorsKnowEachOther": "🎭 المحتالون يعرفون بعضهم",
"impostorsKnowEachOtherDescription": "سيرى كل محتال أسماء الآخرين",
"impostorsKnowEachOtherNeedsTwo": "ينطبق فقط عند وجود محتالَين أو أكثر",
"otherImpostorsTitle": "{count, plural, =1{المحتال الآخر} other{المحتالون الآخرون}}",
"youAreTheOnlyImpostor": "أنت المحتال الوحيد",
"impostorsAdjusted": "تم ضبط عدد المحتالين إلى {count} حسب عدد اللاعبين",
"eliminatedCannotVote": "لقد خرجت: لم تعد تصوّت",
"reconnecting": "جارٍ إعادة الاتصال...",
"reconnectingHint": "انقطع الاتصال بالمضيف. مكانك في الجولة محفوظ.",
"leaveGame": "مغادرة الجولة",
"playerRejoined": "عاد {name} إلى الجولة"
}
+52 -1
View File
@@ -317,5 +317,56 @@
"type": "String"
}
}
}
},
"debate": "🗣️ Debat",
"scanToJoin": "Escaneja el QR per unir-te",
"connectedPlayers": "Jugadors connectats",
"hostGame": "Gestor de partida",
"waitingPlayersSeeWord": "Esperant que tothom vegi la seva paraula...",
"activePlayers": "Jugadors actius",
"playersVoted": "Han votat",
"waitingVoting": "Esperant els vots...",
"waitingForPlayers": "Esperant jugadors...",
"needMorePlayers": "Falten {count} jugadors més",
"starting": "Iniciant...",
"enterNameAndScan": "Escriu el teu nom i escaneja el QR de l'amfitrió",
"yourName": "El teu nom",
"nameRequired": "Escriu el teu nom",
"connectingTo": "Connectant a",
"scanQR": "Escanejar QR",
"scanHostQR": "Apunta al QR de l'amfitrió",
"connectedWaiting": "Connectat!",
"waitingForHost": "Esperant que l'amfitrió iniciï la partida...",
"enterNameToSearch": "Escriu el teu nom per buscar partides properes",
"searchGames": "Buscar partides",
"searchingGames": "Buscant partides properes...",
"noGamesFound": "No s'han trobat partides",
"noGamesFoundHint": "Assegura't que l'amfitrió té la sala oberta i que sou a prop",
"orScanQR": "No apareix? Escaneja el QR de l'amfitrió",
"iveSeenIt": "Ja l'he vista",
"clueIs": "La pista és: {category}",
"debatePhaseActive": "Fase de debat activa",
"debateInstructions": "Parleu entre vosaltres i digueu qui creieu que és l'impostor. Quan estigueu llestos, demaneu la votació.",
"solicitarVotacion": "Demanar votació",
"votacionSolicitada": "Votació demanada",
"whoDoYouThinkIsTheImpostor": "Qui és l'impostor?",
"selectOnePlayer": "Selecciona un jugador per votar",
"votar": "Votar",
"selectYourProfile": "El teu perfil",
"selectProfile": "Selecciona un perfil",
"createNewUser": "Crear nou usuari",
"userNameRequired": "El nom no pot estar buit",
"profileSelected": "Perfil seleccionat",
"availableProfiles": "Perfils disponibles",
"impostorsKnowEachOther": "🎭 Els impostors es coneixen",
"impostorsKnowEachOtherDescription": "Cada impostor veurà els noms de la resta",
"impostorsKnowEachOtherNeedsTwo": "Només s'aplica amb 2 o més impostors",
"otherImpostorsTitle": "{count, plural, =1{L'altre impostor} other{Els altres impostors}}",
"youAreTheOnlyImpostor": "Ets l'únic impostor",
"impostorsAdjusted": "Impostors ajustats a {count} pel nombre de jugadors",
"eliminatedCannotVote": "Estàs eliminat: ja no votes",
"reconnecting": "Reconnectant...",
"reconnectingHint": "S'ha perdut la connexió amb l'amfitrió. El teu lloc a la partida es manté.",
"leaveGame": "Sortir de la partida",
"playerRejoined": "{name} ha tornat a la partida"
}
+52 -1
View File
@@ -317,5 +317,56 @@
"type": "String"
}
}
}
},
"debate": "🗣️ Diskussion",
"scanToJoin": "Scanne den QR-Code zum Beitreten",
"connectedPlayers": "Verbundene Spieler",
"hostGame": "Spielleitung",
"waitingPlayersSeeWord": "Warten, bis alle ihr Wort gesehen haben ...",
"activePlayers": "Aktive Spieler",
"playersVoted": "Haben abgestimmt",
"waitingVoting": "Warten auf die Stimmen ...",
"waitingForPlayers": "Warten auf Spieler ...",
"needMorePlayers": "Es fehlen noch {count} Spieler",
"starting": "Wird gestartet ...",
"enterNameAndScan": "Gib deinen Namen ein und scanne den QR-Code des Hosts",
"yourName": "Dein Name",
"nameRequired": "Gib deinen Namen ein",
"connectingTo": "Verbinde mit",
"scanQR": "QR-Code scannen",
"scanHostQR": "Richte die Kamera auf den QR-Code des Hosts",
"connectedWaiting": "Verbunden!",
"waitingForHost": "Warten, bis der Host das Spiel startet ...",
"enterNameToSearch": "Gib deinen Namen ein, um Spiele in der Nähe zu finden",
"searchGames": "Spiele suchen",
"searchingGames": "Suche nach Spielen in der Nähe ...",
"noGamesFound": "Keine Spiele gefunden",
"noGamesFoundHint": "Stelle sicher, dass der Host den Raum geöffnet hat und ihr in der Nähe seid",
"orScanQR": "Wird nicht angezeigt? Scanne den QR-Code des Hosts",
"iveSeenIt": "Ich habe es gesehen",
"clueIs": "Der Hinweis lautet: {category}",
"debatePhaseActive": "Diskussionsphase läuft",
"debateInstructions": "Sprecht miteinander und sagt, wen ihr für den Betrüger haltet. Wenn ihr bereit seid, fordert die Abstimmung an.",
"solicitarVotacion": "Abstimmung anfordern",
"votacionSolicitada": "Abstimmung angefordert",
"whoDoYouThinkIsTheImpostor": "Wer ist der Betrüger?",
"selectOnePlayer": "Wähle einen Spieler zum Abstimmen",
"votar": "Abstimmen",
"selectYourProfile": "Dein Profil",
"selectProfile": "Wähle ein Profil",
"createNewUser": "Neuen Benutzer erstellen",
"userNameRequired": "Der Name darf nicht leer sein",
"profileSelected": "Profil ausgewählt",
"availableProfiles": "Verfügbare Profile",
"impostorsKnowEachOther": "🎭 Betrüger kennen einander",
"impostorsKnowEachOtherDescription": "Jeder Betrüger sieht die Namen der anderen",
"impostorsKnowEachOtherNeedsTwo": "Gilt nur ab 2 Betrügern",
"otherImpostorsTitle": "{count, plural, =1{Der andere Betrüger} other{Die anderen Betrüger}}",
"youAreTheOnlyImpostor": "Du bist der einzige Betrüger",
"impostorsAdjusted": "Betrüger auf {count} angepasst — abhängig von der Spielerzahl",
"eliminatedCannotVote": "Du bist ausgeschieden du stimmst nicht mehr ab",
"reconnecting": "Verbindung wird wiederhergestellt ...",
"reconnectingHint": "Verbindung zum Host verloren. Dein Platz im Spiel bleibt reserviert.",
"leaveGame": "Spiel verlassen",
"playerRejoined": "{name} ist zurück im Spiel"
}
+27 -1
View File
@@ -349,5 +349,31 @@
"type": "String"
}
}
}
},
"debate": "🗣️ Debate",
"hostGame": "Game manager",
"waitingPlayersSeeWord": "Waiting for everyone to see their word...",
"activePlayers": "Active players",
"playersVoted": "Have voted",
"waitingVoting": "Waiting for votes...",
"iveSeenIt": "I've seen it",
"clueIs": "The clue is: {category}",
"debatePhaseActive": "Debate phase in progress",
"debateInstructions": "Talk to each other and say who you think the impostor is. When you're ready, call for a vote.",
"solicitarVotacion": "Call for a vote",
"votacionSolicitada": "Vote requested",
"whoDoYouThinkIsTheImpostor": "Who is the impostor?",
"selectOnePlayer": "Select a player to vote for",
"votar": "Vote",
"impostorsKnowEachOther": "🎭 Impostors know each other",
"impostorsKnowEachOtherDescription": "Each impostor will see the names of the others",
"impostorsKnowEachOtherNeedsTwo": "Only applies with 2 or more impostors",
"otherImpostorsTitle": "{count, plural, =1{The other impostor} other{The other impostors}}",
"youAreTheOnlyImpostor": "You are the only impostor",
"impostorsAdjusted": "Impostors adjusted to {count} for this number of players",
"eliminatedCannotVote": "You're eliminated — you no longer vote",
"reconnecting": "Reconnecting...",
"reconnectingHint": "Lost connection to the host. Your place in the game is being held.",
"leaveGame": "Leave the game",
"playerRejoined": "{name} has rejoined the game"
}
+32
View File
@@ -385,5 +385,37 @@
"type": "String"
}
}
},
"impostorsKnowEachOther": "🎭 Los impostores se conocen",
"impostorsKnowEachOtherDescription": "Cada impostor verá los nombres del resto",
"impostorsKnowEachOtherNeedsTwo": "Solo se aplica con 2 o más impostores",
"otherImpostorsTitle": "{count, plural, =1{El otro impostor} other{Los otros impostores}}",
"@otherImpostorsTitle": {
"placeholders": {
"count": {
"type": "num"
}
}
},
"youAreTheOnlyImpostor": "Eres el único impostor",
"impostorsAdjusted": "Impostores ajustados a {count} por el número de jugadores",
"@impostorsAdjusted": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"eliminatedCannotVote": "Estás eliminado: ya no votas",
"reconnecting": "Reconectando...",
"reconnectingHint": "Se perdió la conexión con el host. Tu sitio en la partida se mantiene.",
"leaveGame": "Salir de la partida",
"playerRejoined": "{name} ha vuelto a la partida",
"@playerRejoined": {
"placeholders": {
"name": {
"type": "String"
}
}
}
}
+52 -1
View File
@@ -317,5 +317,56 @@
"type": "String"
}
}
}
},
"debate": "🗣️ Eztabaida",
"scanToJoin": "Eskaneatu QR kodea batzeko",
"connectedPlayers": "Konektatutako jokalariak",
"hostGame": "Partidaren kudeatzailea",
"waitingPlayersSeeWord": "Denek beren hitza ikusi arte itxaroten...",
"activePlayers": "Jokalari aktiboak",
"playersVoted": "Bozkatu dute",
"waitingVoting": "Botoen zain...",
"waitingForPlayers": "Jokalarien zain...",
"needMorePlayers": "{count} jokalari gehiago behar dira",
"starting": "Hasten...",
"enterNameAndScan": "Idatzi zure izena eta eskaneatu ostalariaren QR kodea",
"yourName": "Zure izena",
"nameRequired": "Idatzi zure izena",
"connectingTo": "Konektatzen",
"scanQR": "Eskaneatu QR kodea",
"scanHostQR": "Apuntatu ostalariaren QR kodera",
"connectedWaiting": "Konektatuta!",
"waitingForHost": "Ostalariak partida hasi arte itxaroten...",
"enterNameToSearch": "Idatzi zure izena inguruko partidak bilatzeko",
"searchGames": "Bilatu partidak",
"searchingGames": "Inguruko partidak bilatzen...",
"noGamesFound": "Ez da partidarik aurkitu",
"noGamesFoundHint": "Ziurtatu ostalariak gela irekita duela eta gertu zaudetela",
"orScanQR": "Ez da agertzen? Eskaneatu ostalariaren QR kodea",
"iveSeenIt": "Ikusi dut",
"clueIs": "Arrastoa: {category}",
"debatePhaseActive": "Eztabaida fasea martxan",
"debateInstructions": "Hitz egin elkarrekin eta esan nor uste duzuen dela inpostorea. Prest zaudetenean, eskatu bozketa.",
"solicitarVotacion": "Bozketa eskatu",
"votacionSolicitada": "Bozketa eskatuta",
"whoDoYouThinkIsTheImpostor": "Nor da inpostorea?",
"selectOnePlayer": "Hautatu jokalari bat bozkatzeko",
"votar": "Bozkatu",
"selectYourProfile": "Zure profila",
"selectProfile": "Hautatu profil bat",
"createNewUser": "Sortu erabiltzaile berria",
"userNameRequired": "Izena ezin da hutsik egon",
"profileSelected": "Profila hautatuta",
"availableProfiles": "Profil erabilgarriak",
"impostorsKnowEachOther": "🎭 Inpostoreek elkar ezagutzen dute",
"impostorsKnowEachOtherDescription": "Inpostore bakoitzak besteen izenak ikusiko ditu",
"impostorsKnowEachOtherNeedsTwo": "2 inpostore edo gehiagorekin soilik",
"otherImpostorsTitle": "{count, plural, =1{Beste inpostorea} other{Beste inpostoreak}}",
"youAreTheOnlyImpostor": "Zu zara inpostore bakarra",
"impostorsAdjusted": "Inpostoreak {count}era doituta jokalari kopuruagatik",
"eliminatedCannotVote": "Kanporatuta zaude: ez duzu gehiago bozkatzen",
"reconnecting": "Berriz konektatzen...",
"reconnectingHint": "Ostalariarekiko konexioa galdu da. Partidan duzun lekua gordeta dago.",
"leaveGame": "Partidatik irten",
"playerRejoined": "{name} partidara itzuli da"
}
+52 -1
View File
@@ -317,5 +317,56 @@
"type": "String"
}
}
}
},
"debate": "🗣️ Débat",
"scanToJoin": "Scannez le QR code pour rejoindre",
"connectedPlayers": "Joueurs connectés",
"hostGame": "Gestion de la partie",
"waitingPlayersSeeWord": "En attente que chacun voie son mot...",
"activePlayers": "Joueurs actifs",
"playersVoted": "Ont voté",
"waitingVoting": "En attente des votes...",
"waitingForPlayers": "En attente de joueurs...",
"needMorePlayers": "Il manque encore {count} joueurs",
"starting": "Démarrage...",
"enterNameAndScan": "Saisissez votre nom et scannez le QR code de l'hôte",
"yourName": "Votre nom",
"nameRequired": "Saisissez votre nom",
"connectingTo": "Connexion à",
"scanQR": "Scanner le QR code",
"scanHostQR": "Visez le QR code de l'hôte",
"connectedWaiting": "Connecté !",
"waitingForHost": "En attente que l'hôte lance la partie...",
"enterNameToSearch": "Saisissez votre nom pour chercher des parties à proximité",
"searchGames": "Chercher des parties",
"searchingGames": "Recherche de parties à proximité...",
"noGamesFound": "Aucune partie trouvée",
"noGamesFoundHint": "Assurez-vous que l'hôte a ouvert le salon et que vous êtes à proximité",
"orScanQR": "Rien n'apparaît ? Scannez le QR code de l'hôte",
"iveSeenIt": "Je l'ai vu",
"clueIs": "L'indice est : {category}",
"debatePhaseActive": "Phase de débat en cours",
"debateInstructions": "Discutez entre vous et dites qui vous pensez être l'imposteur. Quand vous êtes prêts, demandez le vote.",
"solicitarVotacion": "Demander le vote",
"votacionSolicitada": "Vote demandé",
"whoDoYouThinkIsTheImpostor": "Qui est l'imposteur ?",
"selectOnePlayer": "Sélectionnez un joueur pour voter",
"votar": "Voter",
"selectYourProfile": "Votre profil",
"selectProfile": "Sélectionnez un profil",
"createNewUser": "Créer un nouvel utilisateur",
"userNameRequired": "Le nom ne peut pas être vide",
"profileSelected": "Profil sélectionné",
"availableProfiles": "Profils disponibles",
"impostorsKnowEachOther": "🎭 Les imposteurs se connaissent",
"impostorsKnowEachOtherDescription": "Chaque imposteur verra les noms des autres",
"impostorsKnowEachOtherNeedsTwo": "S'applique uniquement à partir de 2 imposteurs",
"otherImpostorsTitle": "{count, plural, =1{L'autre imposteur} other{Les autres imposteurs}}",
"youAreTheOnlyImpostor": "Vous êtes le seul imposteur",
"impostorsAdjusted": "Imposteurs ajustés à {count} selon le nombre de joueurs",
"eliminatedCannotVote": "Vous êtes éliminé : vous ne votez plus",
"reconnecting": "Reconnexion...",
"reconnectingHint": "Connexion à l'hôte perdue. Votre place dans la partie est conservée.",
"leaveGame": "Quitter la partie",
"playerRejoined": "{name} a rejoint la partie"
}
+52 -1
View File
@@ -317,5 +317,56 @@
"type": "String"
}
}
}
},
"debate": "🗣️ बहस",
"scanToJoin": "शामिल होने के लिए QR स्कैन करें",
"connectedPlayers": "जुड़े हुए खिलाड़ी",
"hostGame": "गेम प्रबंधक",
"waitingPlayersSeeWord": "सभी के अपना शब्द देखने की प्रतीक्षा...",
"activePlayers": "सक्रिय खिलाड़ी",
"playersVoted": "मतदान कर चुके",
"waitingVoting": "वोटों की प्रतीक्षा...",
"waitingForPlayers": "खिलाड़ियों की प्रतीक्षा...",
"needMorePlayers": "{count} और खिलाड़ी चाहिए",
"starting": "शुरू हो रहा है...",
"enterNameAndScan": "अपना नाम लिखें और होस्ट का QR स्कैन करें",
"yourName": "आपका नाम",
"nameRequired": "अपना नाम लिखें",
"connectingTo": "कनेक्ट हो रहा है",
"scanQR": "QR स्कैन करें",
"scanHostQR": "होस्ट के QR पर कैमरा रखें",
"connectedWaiting": "कनेक्ट हो गया!",
"waitingForHost": "होस्ट के खेल शुरू करने की प्रतीक्षा...",
"enterNameToSearch": "आस-पास के गेम खोजने के लिए अपना नाम लिखें",
"searchGames": "गेम खोजें",
"searchingGames": "आस-पास के गेम खोजे जा रहे हैं...",
"noGamesFound": "कोई गेम नहीं मिला",
"noGamesFoundHint": "सुनिश्चित करें कि होस्ट का कमरा खुला है और आप पास हैं",
"orScanQR": "दिख नहीं रहा? होस्ट का QR स्कैन करें",
"iveSeenIt": "मैंने देख लिया",
"clueIs": "संकेत: {category}",
"debatePhaseActive": "बहस का चरण जारी है",
"debateInstructions": "आपस में बात करें और बताएं कि आपको कौन धोखेबाज़ लगता है। तैयार होने पर मतदान का अनुरोध करें।",
"solicitarVotacion": "मतदान का अनुरोध करें",
"votacionSolicitada": "मतदान का अनुरोध भेजा गया",
"whoDoYouThinkIsTheImpostor": "धोखेबाज़ कौन है?",
"selectOnePlayer": "वोट देने के लिए एक खिलाड़ी चुनें",
"votar": "वोट दें",
"selectYourProfile": "आपकी प्रोफ़ाइल",
"selectProfile": "एक प्रोफ़ाइल चुनें",
"createNewUser": "नया उपयोगकर्ता बनाएं",
"userNameRequired": "नाम खाली नहीं हो सकता",
"profileSelected": "प्रोफ़ाइल चुनी गई",
"availableProfiles": "उपलब्ध प्रोफ़ाइल",
"impostorsKnowEachOther": "🎭 धोखेबाज़ एक-दूसरे को जानते हैं",
"impostorsKnowEachOtherDescription": "हर धोखेबाज़ को बाकी के नाम दिखेंगे",
"impostorsKnowEachOtherNeedsTwo": "केवल 2 या अधिक धोखेबाज़ों पर लागू",
"otherImpostorsTitle": "{count, plural, =1{दूसरा धोखेबाज़} other{अन्य धोखेबाज़}}",
"youAreTheOnlyImpostor": "आप अकेले धोखेबाज़ हैं",
"impostorsAdjusted": "खिलाड़ियों की संख्या के अनुसार धोखेबाज़ {count} कर दिए गए",
"eliminatedCannotVote": "आप बाहर हो चुके हैं: अब आप वोट नहीं देते",
"reconnecting": "फिर से कनेक्ट हो रहा है...",
"reconnectingHint": "होस्ट से कनेक्शन टूट गया। खेल में आपकी जगह सुरक्षित है।",
"leaveGame": "खेल छोड़ें",
"playerRejoined": "{name} खेल में वापस आ गए"
}
+52 -1
View File
@@ -317,5 +317,56 @@
"type": "String"
}
}
}
},
"debate": "🗣️ Dibattito",
"scanToJoin": "Scansiona il QR per unirti",
"connectedPlayers": "Giocatori connessi",
"hostGame": "Gestione partita",
"waitingPlayersSeeWord": "In attesa che tutti vedano la propria parola...",
"activePlayers": "Giocatori attivi",
"playersVoted": "Hanno votato",
"waitingVoting": "In attesa dei voti...",
"waitingForPlayers": "In attesa di giocatori...",
"needMorePlayers": "Mancano ancora {count} giocatori",
"starting": "Avvio...",
"enterNameAndScan": "Scrivi il tuo nome e scansiona il QR dell'host",
"yourName": "Il tuo nome",
"nameRequired": "Scrivi il tuo nome",
"connectingTo": "Connessione a",
"scanQR": "Scansiona QR",
"scanHostQR": "Inquadra il QR dell'host",
"connectedWaiting": "Connesso!",
"waitingForHost": "In attesa che l'host avvii la partita...",
"enterNameToSearch": "Scrivi il tuo nome per cercare partite vicine",
"searchGames": "Cerca partite",
"searchingGames": "Ricerca di partite vicine...",
"noGamesFound": "Nessuna partita trovata",
"noGamesFoundHint": "Assicurati che l'host abbia la stanza aperta e che siate vicini",
"orScanQR": "Non compare? Scansiona il QR dell'host",
"iveSeenIt": "L'ho vista",
"clueIs": "L'indizio è: {category}",
"debatePhaseActive": "Fase di dibattito in corso",
"debateInstructions": "Parlate tra voi e dite chi pensate sia l'impostore. Quando siete pronti, chiedete la votazione.",
"solicitarVotacion": "Chiedi la votazione",
"votacionSolicitada": "Votazione richiesta",
"whoDoYouThinkIsTheImpostor": "Chi è l'impostore?",
"selectOnePlayer": "Seleziona un giocatore per votare",
"votar": "Vota",
"selectYourProfile": "Il tuo profilo",
"selectProfile": "Seleziona un profilo",
"createNewUser": "Crea nuovo utente",
"userNameRequired": "Il nome non può essere vuoto",
"profileSelected": "Profilo selezionato",
"availableProfiles": "Profili disponibili",
"impostorsKnowEachOther": "🎭 Gli impostori si conoscono",
"impostorsKnowEachOtherDescription": "Ogni impostore vedrà i nomi degli altri",
"impostorsKnowEachOtherNeedsTwo": "Si applica solo con 2 o più impostori",
"otherImpostorsTitle": "{count, plural, =1{L'altro impostore} other{Gli altri impostori}}",
"youAreTheOnlyImpostor": "Sei l'unico impostore",
"impostorsAdjusted": "Impostori regolati a {count} in base al numero di giocatori",
"eliminatedCannotVote": "Sei eliminato: non voti più",
"reconnecting": "Riconnessione...",
"reconnectingHint": "Connessione con l'host persa. Il tuo posto nella partita resta riservato.",
"leaveGame": "Esci dalla partita",
"playerRejoined": "{name} è tornato in partita"
}
+52 -1
View File
@@ -317,5 +317,56 @@
"type": "String"
}
}
}
},
"debate": "🗣️ 議論",
"scanToJoin": "QRコードをスキャンして参加",
"connectedPlayers": "接続中のプレイヤー",
"hostGame": "ゲーム管理",
"waitingPlayersSeeWord": "全員が単語を確認するのを待っています...",
"activePlayers": "参加中のプレイヤー",
"playersVoted": "投票済み",
"waitingVoting": "投票を待っています...",
"waitingForPlayers": "プレイヤーを待っています...",
"needMorePlayers": "あと{count}人のプレイヤーが必要です",
"starting": "開始しています...",
"enterNameAndScan": "名前を入力してホストのQRコードをスキャン",
"yourName": "あなたの名前",
"nameRequired": "名前を入力してください",
"connectingTo": "接続中:",
"scanQR": "QRコードをスキャン",
"scanHostQR": "ホストのQRコードにかざしてください",
"connectedWaiting": "接続しました!",
"waitingForHost": "ホストがゲームを開始するのを待っています...",
"enterNameToSearch": "名前を入力して近くのゲームを検索",
"searchGames": "ゲームを検索",
"searchingGames": "近くのゲームを検索しています...",
"noGamesFound": "ゲームが見つかりません",
"noGamesFoundHint": "ホストがルームを開いていて、近くにいることを確認してください",
"orScanQR": "表示されませんか?ホストのQRコードをスキャン",
"iveSeenIt": "確認しました",
"clueIs": "ヒント:{category}",
"debatePhaseActive": "議論フェーズ進行中",
"debateInstructions": "お互いに話し合い、誰がインポスターだと思うか伝えましょう。準備ができたら投票を要求してください。",
"solicitarVotacion": "投票を要求",
"votacionSolicitada": "投票をリクエストしました",
"whoDoYouThinkIsTheImpostor": "インポスターは誰?",
"selectOnePlayer": "投票するプレイヤーを選択",
"votar": "投票する",
"selectYourProfile": "あなたのプロフィール",
"selectProfile": "プロフィールを選択",
"createNewUser": "新しいユーザーを作成",
"userNameRequired": "名前は空にできません",
"profileSelected": "プロフィールを選択しました",
"availableProfiles": "利用可能なプロフィール",
"impostorsKnowEachOther": "🎭 インポスター同士が分かる",
"impostorsKnowEachOtherDescription": "各インポスターに他のインポスターの名前が表示されます",
"impostorsKnowEachOtherNeedsTwo": "インポスターが2人以上のときのみ有効",
"otherImpostorsTitle": "{count, plural, =1{他のインポスター} other{他のインポスター}}",
"youAreTheOnlyImpostor": "あなたが唯一のインポスターです",
"impostorsAdjusted": "プレイヤー数に合わせてインポスターを{count}人に調整しました",
"eliminatedCannotVote": "あなたは脱落しました。投票はできません",
"reconnecting": "再接続しています...",
"reconnectingHint": "ホストとの接続が切れました。ゲーム内のあなたの席は確保されています。",
"leaveGame": "ゲームから退出",
"playerRejoined": "{name} がゲームに復帰しました"
}
+52 -1
View File
@@ -317,5 +317,56 @@
"type": "String"
}
}
}
},
"debate": "🗣️ 토론",
"scanToJoin": "QR 코드를 스캔해 참여하세요",
"connectedPlayers": "접속한 플레이어",
"hostGame": "게임 관리",
"waitingPlayersSeeWord": "모두가 단어를 확인하기를 기다리는 중...",
"activePlayers": "활동 중인 플레이어",
"playersVoted": "투표 완료",
"waitingVoting": "투표를 기다리는 중...",
"waitingForPlayers": "플레이어를 기다리는 중...",
"needMorePlayers": "{count}명이 더 필요합니다",
"starting": "시작하는 중...",
"enterNameAndScan": "이름을 입력하고 호스트의 QR 코드를 스캔하세요",
"yourName": "이름",
"nameRequired": "이름을 입력하세요",
"connectingTo": "연결 중:",
"scanQR": "QR 코드 스캔",
"scanHostQR": "호스트의 QR 코드를 비추세요",
"connectedWaiting": "연결되었습니다!",
"waitingForHost": "호스트가 게임을 시작하기를 기다리는 중...",
"enterNameToSearch": "이름을 입력해 근처 게임을 찾으세요",
"searchGames": "게임 찾기",
"searchingGames": "근처 게임을 찾는 중...",
"noGamesFound": "게임을 찾을 수 없습니다",
"noGamesFoundHint": "호스트가 방을 열어 두었고 서로 가까이 있는지 확인하세요",
"orScanQR": "보이지 않나요? 호스트의 QR 코드를 스캔하세요",
"iveSeenIt": "확인했습니다",
"clueIs": "힌트: {category}",
"debatePhaseActive": "토론 단계 진행 중",
"debateInstructions": "서로 이야기하며 누가 임포스터라고 생각하는지 말해 보세요. 준비되면 투표를 요청하세요.",
"solicitarVotacion": "투표 요청",
"votacionSolicitada": "투표를 요청했습니다",
"whoDoYouThinkIsTheImpostor": "임포스터는 누구일까요?",
"selectOnePlayer": "투표할 플레이어를 선택하세요",
"votar": "투표하기",
"selectYourProfile": "내 프로필",
"selectProfile": "프로필을 선택하세요",
"createNewUser": "새 사용자 만들기",
"userNameRequired": "이름은 비워 둘 수 없습니다",
"profileSelected": "프로필을 선택했습니다",
"availableProfiles": "사용 가능한 프로필",
"impostorsKnowEachOther": "🎭 임포스터끼리 서로 압니다",
"impostorsKnowEachOtherDescription": "각 임포스터가 다른 임포스터의 이름을 봅니다",
"impostorsKnowEachOtherNeedsTwo": "임포스터가 2명 이상일 때만 적용됩니다",
"otherImpostorsTitle": "{count, plural, =1{다른 임포스터} other{다른 임포스터들}}",
"youAreTheOnlyImpostor": "당신이 유일한 임포스터입니다",
"impostorsAdjusted": "플레이어 수에 맞춰 임포스터를 {count}명으로 조정했습니다",
"eliminatedCannotVote": "탈락했습니다. 더 이상 투표할 수 없습니다",
"reconnecting": "다시 연결하는 중...",
"reconnectingHint": "호스트와의 연결이 끊겼습니다. 게임 내 자리는 유지됩니다.",
"leaveGame": "게임 나가기",
"playerRejoined": "{name} 님이 게임에 복귀했습니다"
}
+52 -1
View File
@@ -317,5 +317,56 @@
"type": "String"
}
}
}
},
"debate": "🗣️ Discussie",
"scanToJoin": "Scan de QR-code om deel te nemen",
"connectedPlayers": "Verbonden spelers",
"hostGame": "Spelbeheer",
"waitingPlayersSeeWord": "Wachten tot iedereen zijn woord heeft gezien...",
"activePlayers": "Actieve spelers",
"playersVoted": "Hebben gestemd",
"waitingVoting": "Wachten op stemmen...",
"waitingForPlayers": "Wachten op spelers...",
"needMorePlayers": "Er zijn nog {count} spelers nodig",
"starting": "Starten...",
"enterNameAndScan": "Voer je naam in en scan de QR-code van de host",
"yourName": "Je naam",
"nameRequired": "Voer je naam in",
"connectingTo": "Verbinden met",
"scanQR": "QR-code scannen",
"scanHostQR": "Richt op de QR-code van de host",
"connectedWaiting": "Verbonden!",
"waitingForHost": "Wachten tot de host het spel start...",
"enterNameToSearch": "Voer je naam in om spellen in de buurt te zoeken",
"searchGames": "Spellen zoeken",
"searchingGames": "Zoeken naar spellen in de buurt...",
"noGamesFound": "Geen spellen gevonden",
"noGamesFoundHint": "Zorg dat de host de ruimte open heeft en dat jullie dichtbij zijn",
"orScanQR": "Zie je niets? Scan de QR-code van de host",
"iveSeenIt": "Ik heb het gezien",
"clueIs": "De hint is: {category}",
"debatePhaseActive": "Discussiefase bezig",
"debateInstructions": "Praat met elkaar en zeg wie jullie denken dat de bedrieger is. Vraag om een stemming als jullie klaar zijn.",
"solicitarVotacion": "Stemming aanvragen",
"votacionSolicitada": "Stemming aangevraagd",
"whoDoYouThinkIsTheImpostor": "Wie is de bedrieger?",
"selectOnePlayer": "Kies een speler om op te stemmen",
"votar": "Stemmen",
"selectYourProfile": "Je profiel",
"selectProfile": "Kies een profiel",
"createNewUser": "Nieuwe gebruiker aanmaken",
"userNameRequired": "De naam mag niet leeg zijn",
"profileSelected": "Profiel geselecteerd",
"availableProfiles": "Beschikbare profielen",
"impostorsKnowEachOther": "🎭 Bedriegers kennen elkaar",
"impostorsKnowEachOtherDescription": "Elke bedrieger ziet de namen van de anderen",
"impostorsKnowEachOtherNeedsTwo": "Geldt alleen bij 2 of meer bedriegers",
"otherImpostorsTitle": "{count, plural, =1{De andere bedrieger} other{De andere bedriegers}}",
"youAreTheOnlyImpostor": "Jij bent de enige bedrieger",
"impostorsAdjusted": "Bedriegers aangepast naar {count} op basis van het aantal spelers",
"eliminatedCannotVote": "Je bent uitgeschakeld je stemt niet meer",
"reconnecting": "Opnieuw verbinden...",
"reconnectingHint": "Verbinding met de host verbroken. Je plek in het spel blijft behouden.",
"leaveGame": "Spel verlaten",
"playerRejoined": "{name} is terug in het spel"
}
+52 -1
View File
@@ -317,5 +317,56 @@
"type": "String"
}
}
}
},
"debate": "🗣️ Dyskusja",
"scanToJoin": "Zeskanuj kod QR, aby dołączyć",
"connectedPlayers": "Połączeni gracze",
"hostGame": "Zarządzanie grą",
"waitingPlayersSeeWord": "Czekamy, aż wszyscy zobaczą swoje słowo...",
"activePlayers": "Aktywni gracze",
"playersVoted": "Zagłosowali",
"waitingVoting": "Czekamy na głosy...",
"waitingForPlayers": "Czekamy na graczy...",
"needMorePlayers": "Brakuje jeszcze {count} graczy",
"starting": "Uruchamianie...",
"enterNameAndScan": "Wpisz swoje imię i zeskanuj kod QR gospodarza",
"yourName": "Twoje imię",
"nameRequired": "Wpisz swoje imię",
"connectingTo": "Łączenie z",
"scanQR": "Zeskanuj kod QR",
"scanHostQR": "Wyceluj w kod QR gospodarza",
"connectedWaiting": "Połączono!",
"waitingForHost": "Czekamy, aż gospodarz rozpocznie grę...",
"enterNameToSearch": "Wpisz swoje imię, aby znaleźć gry w pobliżu",
"searchGames": "Szukaj gier",
"searchingGames": "Szukanie gier w pobliżu...",
"noGamesFound": "Nie znaleziono gier",
"noGamesFoundHint": "Upewnij się, że gospodarz ma otwarty pokój i jesteście blisko siebie",
"orScanQR": "Nie widzisz gry? Zeskanuj kod QR gospodarza",
"iveSeenIt": "Już zobaczyłem",
"clueIs": "Wskazówka: {category}",
"debatePhaseActive": "Trwa faza dyskusji",
"debateInstructions": "Porozmawiajcie ze sobą i powiedzcie, kto waszym zdaniem jest oszustem. Gdy będziecie gotowi, poproście o głosowanie.",
"solicitarVotacion": "Poproś o głosowanie",
"votacionSolicitada": "Poproszono o głosowanie",
"whoDoYouThinkIsTheImpostor": "Kto jest oszustem?",
"selectOnePlayer": "Wybierz gracza, na którego głosujesz",
"votar": "Głosuj",
"selectYourProfile": "Twój profil",
"selectProfile": "Wybierz profil",
"createNewUser": "Utwórz nowego użytkownika",
"userNameRequired": "Imię nie może być puste",
"profileSelected": "Wybrano profil",
"availableProfiles": "Dostępne profile",
"impostorsKnowEachOther": "🎭 Oszuści znają się nawzajem",
"impostorsKnowEachOtherDescription": "Każdy oszust zobaczy imiona pozostałych",
"impostorsKnowEachOtherNeedsTwo": "Działa tylko przy 2 lub więcej oszustach",
"otherImpostorsTitle": "{count, plural, =1{Drugi oszust} other{Pozostali oszuści}}",
"youAreTheOnlyImpostor": "Jesteś jedynym oszustem",
"impostorsAdjusted": "Liczba oszustów dostosowana do {count} z powodu liczby graczy",
"eliminatedCannotVote": "Jesteś wyeliminowany już nie głosujesz",
"reconnecting": "Ponowne łączenie...",
"reconnectingHint": "Utracono połączenie z gospodarzem. Twoje miejsce w grze jest zachowane.",
"leaveGame": "Opuść grę",
"playerRejoined": "{name} wrócił(a) do gry"
}
+52 -1
View File
@@ -317,5 +317,56 @@
"type": "String"
}
}
}
},
"debate": "🗣️ Debate",
"scanToJoin": "Digitaliza o QR para entrares",
"connectedPlayers": "Jogadores ligados",
"hostGame": "Gestor de jogo",
"waitingPlayersSeeWord": "À espera de que todos vejam a sua palavra...",
"activePlayers": "Jogadores ativos",
"playersVoted": "Já votaram",
"waitingVoting": "À espera dos votos...",
"waitingForPlayers": "À espera de jogadores...",
"needMorePlayers": "Faltam {count} jogadores",
"starting": "A iniciar...",
"enterNameAndScan": "Escreve o teu nome e digitaliza o QR do anfitrião",
"yourName": "O teu nome",
"nameRequired": "Escreve o teu nome",
"connectingTo": "A ligar a",
"scanQR": "Digitalizar QR",
"scanHostQR": "Aponta para o QR do anfitrião",
"connectedWaiting": "Ligado!",
"waitingForHost": "À espera de que o anfitrião inicie o jogo...",
"enterNameToSearch": "Escreve o teu nome para procurar jogos por perto",
"searchGames": "Procurar jogos",
"searchingGames": "A procurar jogos por perto...",
"noGamesFound": "Não foram encontrados jogos",
"noGamesFoundHint": "Certifica-te de que o anfitrião tem a sala aberta e estão perto",
"orScanQR": "Não aparece? Digitaliza o QR do anfitrião",
"iveSeenIt": "Já a vi",
"clueIs": "A pista é: {category}",
"debatePhaseActive": "Fase de debate a decorrer",
"debateInstructions": "Falem entre vocês e digam quem acham que é o impostor. Quando estiverem prontos, peçam a votação.",
"solicitarVotacion": "Pedir votação",
"votacionSolicitada": "Votação pedida",
"whoDoYouThinkIsTheImpostor": "Quem é o impostor?",
"selectOnePlayer": "Seleciona um jogador para votar",
"votar": "Votar",
"selectYourProfile": "O teu perfil",
"selectProfile": "Seleciona um perfil",
"createNewUser": "Criar novo utilizador",
"userNameRequired": "O nome não pode estar vazio",
"profileSelected": "Perfil selecionado",
"availableProfiles": "Perfis disponíveis",
"impostorsKnowEachOther": "🎭 Os impostores conhecem-se",
"impostorsKnowEachOtherDescription": "Cada impostor verá os nomes dos restantes",
"impostorsKnowEachOtherNeedsTwo": "Só se aplica com 2 ou mais impostores",
"otherImpostorsTitle": "{count, plural, =1{O outro impostor} other{Os outros impostores}}",
"youAreTheOnlyImpostor": "És o único impostor",
"impostorsAdjusted": "Impostores ajustados para {count} pelo número de jogadores",
"eliminatedCannotVote": "Estás eliminado: já não votas",
"reconnecting": "A religar...",
"reconnectingHint": "Perdeu-se a ligação ao anfitrião. O teu lugar no jogo mantém-se.",
"leaveGame": "Sair do jogo",
"playerRejoined": "{name} voltou ao jogo"
}
+52 -1
View File
@@ -317,5 +317,56 @@
"type": "String"
}
}
}
},
"debate": "🗣️ Обсуждение",
"scanToJoin": "Отсканируйте QR-код, чтобы присоединиться",
"connectedPlayers": "Подключённые игроки",
"hostGame": "Управление игрой",
"waitingPlayersSeeWord": "Ждём, пока все увидят своё слово...",
"activePlayers": "Активные игроки",
"playersVoted": "Проголосовали",
"waitingVoting": "Ждём голоса...",
"waitingForPlayers": "Ждём игроков...",
"needMorePlayers": "Нужно ещё {count} игроков",
"starting": "Запуск...",
"enterNameAndScan": "Введите имя и отсканируйте QR-код ведущего",
"yourName": "Ваше имя",
"nameRequired": "Введите ваше имя",
"connectingTo": "Подключение к",
"scanQR": "Сканировать QR-код",
"scanHostQR": "Наведите на QR-код ведущего",
"connectedWaiting": "Подключено!",
"waitingForHost": "Ждём, пока ведущий начнёт игру...",
"enterNameToSearch": "Введите имя, чтобы найти игры поблизости",
"searchGames": "Найти игры",
"searchingGames": "Поиск игр поблизости...",
"noGamesFound": "Игры не найдены",
"noGamesFoundHint": "Убедитесь, что ведущий открыл комнату и вы находитесь рядом",
"orScanQR": "Не отображается? Отсканируйте QR-код ведущего",
"iveSeenIt": "Я посмотрел",
"clueIs": "Подсказка: {category}",
"debatePhaseActive": "Идёт этап обсуждения",
"debateInstructions": "Обсудите между собой и скажите, кто, по-вашему, самозванец. Когда будете готовы, запросите голосование.",
"solicitarVotacion": "Запросить голосование",
"votacionSolicitada": "Голосование запрошено",
"whoDoYouThinkIsTheImpostor": "Кто самозванец?",
"selectOnePlayer": "Выберите игрока для голосования",
"votar": "Голосовать",
"selectYourProfile": "Ваш профиль",
"selectProfile": "Выберите профиль",
"createNewUser": "Создать нового пользователя",
"userNameRequired": "Имя не может быть пустым",
"profileSelected": "Профиль выбран",
"availableProfiles": "Доступные профили",
"impostorsKnowEachOther": "🎭 Самозванцы знают друг друга",
"impostorsKnowEachOtherDescription": "Каждый самозванец увидит имена остальных",
"impostorsKnowEachOtherNeedsTwo": "Работает только при 2 и более самозванцах",
"otherImpostorsTitle": "{count, plural, =1{Другой самозванец} other{Другие самозванцы}}",
"youAreTheOnlyImpostor": "Вы единственный самозванец",
"impostorsAdjusted": "Число самозванцев изменено на {count} из-за количества игроков",
"eliminatedCannotVote": "Вы выбыли — вы больше не голосуете",
"reconnecting": "Переподключение...",
"reconnectingHint": "Соединение с ведущим потеряно. Ваше место в игре сохраняется.",
"leaveGame": "Выйти из игры",
"playerRejoined": "{name} вернулся в игру"
}
+52 -1
View File
@@ -317,5 +317,56 @@
"type": "String"
}
}
}
},
"debate": "🗣️ Tartışma",
"scanToJoin": "Katılmak için QR kodu okut",
"connectedPlayers": "Bağlı oyuncular",
"hostGame": "Oyun yönetimi",
"waitingPlayersSeeWord": "Herkesin kelimesini görmesi bekleniyor...",
"activePlayers": "Aktif oyuncular",
"playersVoted": "Oy verdi",
"waitingVoting": "Oylar bekleniyor...",
"waitingForPlayers": "Oyuncular bekleniyor...",
"needMorePlayers": "{count} oyuncu daha gerekli",
"starting": "Başlatılıyor...",
"enterNameAndScan": "Adını yaz ve sunucunun QR kodunu okut",
"yourName": "Adın",
"nameRequired": "Adını yaz",
"connectingTo": "Bağlanılıyor:",
"scanQR": "QR kodu okut",
"scanHostQR": "Sunucunun QR koduna doğrult",
"connectedWaiting": "Bağlandı!",
"waitingForHost": "Sunucunun oyunu başlatması bekleniyor...",
"enterNameToSearch": "Yakındaki oyunları aramak için adını yaz",
"searchGames": "Oyun ara",
"searchingGames": "Yakındaki oyunlar aranıyor...",
"noGamesFound": "Oyun bulunamadı",
"noGamesFoundHint": "Sunucunun odayı açık tuttuğundan ve yakın olduğunuzdan emin ol",
"orScanQR": "Görünmüyor mu? Sunucunun QR kodunu okut",
"iveSeenIt": "Gördüm",
"clueIs": "İpucu: {category}",
"debatePhaseActive": "Tartışma aşaması sürüyor",
"debateInstructions": "Birbirinizle konuşun ve sahtekârın kim olduğunu düşündüğünüzü söyleyin. Hazır olduğunuzda oylama isteyin.",
"solicitarVotacion": "Oylama iste",
"votacionSolicitada": "Oylama istendi",
"whoDoYouThinkIsTheImpostor": "Sahtekâr kim?",
"selectOnePlayer": "Oy vermek için bir oyuncu seç",
"votar": "Oy ver",
"selectYourProfile": "Profilin",
"selectProfile": "Bir profil seç",
"createNewUser": "Yeni kullanıcı oluştur",
"userNameRequired": "Ad boş olamaz",
"profileSelected": "Profil seçildi",
"availableProfiles": "Kullanılabilir profiller",
"impostorsKnowEachOther": "🎭 Sahtekârlar birbirini tanır",
"impostorsKnowEachOtherDescription": "Her sahtekâr diğerlerinin adlarını görür",
"impostorsKnowEachOtherNeedsTwo": "Yalnızca 2 veya daha fazla sahtekârla geçerli",
"otherImpostorsTitle": "{count, plural, =1{Diğer sahtekâr} other{Diğer sahtekârlar}}",
"youAreTheOnlyImpostor": "Tek sahtekâr sensin",
"impostorsAdjusted": "Oyuncu sayısına göre sahtekâr sayısı {count} olarak ayarlandı",
"eliminatedCannotVote": "Elendin: artık oy vermiyorsun",
"reconnecting": "Yeniden bağlanılıyor...",
"reconnectingHint": "Sunucuyla bağlantı koptu. Oyundaki yerin korunuyor.",
"leaveGame": "Oyundan ayrıl",
"playerRejoined": "{name} oyuna geri döndü"
}
+52 -1
View File
@@ -317,5 +317,56 @@
"type": "String"
}
}
}
},
"debate": "🗣️ 讨论",
"scanToJoin": "扫描二维码加入",
"connectedPlayers": "已连接的玩家",
"hostGame": "游戏管理",
"waitingPlayersSeeWord": "等待所有人查看自己的词语…",
"activePlayers": "在场玩家",
"playersVoted": "已投票",
"waitingVoting": "等待投票…",
"waitingForPlayers": "等待玩家…",
"needMorePlayers": "还需要 {count} 名玩家",
"starting": "正在开始…",
"enterNameAndScan": "输入你的名字并扫描房主的二维码",
"yourName": "你的名字",
"nameRequired": "请输入你的名字",
"connectingTo": "正在连接",
"scanQR": "扫描二维码",
"scanHostQR": "对准房主的二维码",
"connectedWaiting": "已连接!",
"waitingForHost": "等待房主开始游戏…",
"enterNameToSearch": "输入你的名字以搜索附近的游戏",
"searchGames": "搜索游戏",
"searchingGames": "正在搜索附近的游戏…",
"noGamesFound": "未找到游戏",
"noGamesFoundHint": "请确认房主已开启房间,且你们距离较近",
"orScanQR": "没有显示?扫描房主的二维码",
"iveSeenIt": "我看过了",
"clueIs": "提示:{category}",
"debatePhaseActive": "讨论阶段进行中",
"debateInstructions": "互相讨论,说出你认为谁是卧底。准备好后请求投票。",
"solicitarVotacion": "请求投票",
"votacionSolicitada": "已请求投票",
"whoDoYouThinkIsTheImpostor": "谁是卧底?",
"selectOnePlayer": "选择要投票的玩家",
"votar": "投票",
"selectYourProfile": "你的资料",
"selectProfile": "选择一个资料",
"createNewUser": "创建新用户",
"userNameRequired": "名字不能为空",
"profileSelected": "已选择资料",
"availableProfiles": "可用资料",
"impostorsKnowEachOther": "🎭 卧底互相知晓",
"impostorsKnowEachOtherDescription": "每个卧底都会看到其他卧底的名字",
"impostorsKnowEachOtherNeedsTwo": "仅在 2 名或以上卧底时生效",
"otherImpostorsTitle": "{count, plural, =1{另一名卧底} other{其他卧底}}",
"youAreTheOnlyImpostor": "你是唯一的卧底",
"impostorsAdjusted": "已根据玩家人数将卧底调整为 {count} 名",
"eliminatedCannotVote": "你已出局,不能再投票",
"reconnecting": "正在重新连接…",
"reconnectingHint": "与房主的连接已断开。你在游戏中的位置仍为你保留。",
"leaveGame": "退出游戏",
"playerRejoined": "{name} 已重新加入游戏"
}
+52 -1
View File
@@ -317,5 +317,56 @@
"type": "String"
}
}
}
},
"debate": "🗣️ 討論",
"scanToJoin": "掃描 QR Code 加入",
"connectedPlayers": "已連線的玩家",
"hostGame": "遊戲管理",
"waitingPlayersSeeWord": "等待所有人查看自己的詞語…",
"activePlayers": "在場玩家",
"playersVoted": "已投票",
"waitingVoting": "等待投票…",
"waitingForPlayers": "等待玩家…",
"needMorePlayers": "還需要 {count} 名玩家",
"starting": "正在開始…",
"enterNameAndScan": "輸入你的名字並掃描房主的 QR Code",
"yourName": "你的名字",
"nameRequired": "請輸入你的名字",
"connectingTo": "正在連線",
"scanQR": "掃描 QR Code",
"scanHostQR": "對準房主的 QR Code",
"connectedWaiting": "已連線!",
"waitingForHost": "等待房主開始遊戲…",
"enterNameToSearch": "輸入你的名字以搜尋附近的遊戲",
"searchGames": "搜尋遊戲",
"searchingGames": "正在搜尋附近的遊戲…",
"noGamesFound": "找不到遊戲",
"noGamesFoundHint": "請確認房主已開啟房間,且你們距離較近",
"orScanQR": "沒有顯示?掃描房主的 QR Code",
"iveSeenIt": "我看過了",
"clueIs": "提示:{category}",
"debatePhaseActive": "討論階段進行中",
"debateInstructions": "互相討論,說出你認為誰是臥底。準備好後請求投票。",
"solicitarVotacion": "請求投票",
"votacionSolicitada": "已請求投票",
"whoDoYouThinkIsTheImpostor": "誰是臥底?",
"selectOnePlayer": "選擇要投票的玩家",
"votar": "投票",
"selectYourProfile": "你的個人檔案",
"selectProfile": "選擇一個個人檔案",
"createNewUser": "建立新使用者",
"userNameRequired": "名字不能為空",
"profileSelected": "已選擇個人檔案",
"availableProfiles": "可用的個人檔案",
"impostorsKnowEachOther": "🎭 臥底互相知曉",
"impostorsKnowEachOtherDescription": "每個臥底都會看到其他臥底的名字",
"impostorsKnowEachOtherNeedsTwo": "僅在 2 名或以上臥底時生效",
"otherImpostorsTitle": "{count, plural, =1{另一名臥底} other{其他臥底}}",
"youAreTheOnlyImpostor": "你是唯一的臥底",
"impostorsAdjusted": "已根據玩家人數將臥底調整為 {count} 名",
"eliminatedCannotVote": "你已出局,不能再投票",
"reconnecting": "正在重新連線…",
"reconnectingHint": "與房主的連線已中斷。你在遊戲中的位置仍為你保留。",
"leaveGame": "退出遊戲",
"playerRejoined": "{name} 已重新加入遊戲"
}
+315 -53
View File
@@ -147,35 +147,34 @@ abstract class AppLocalizations {
/// **'Cargando palabras...'**
String get loadingWords;
/// No description provided for @matchRewards.
///
/// In en, this message translates to:
/// **'Game rewards'**
/// In es, this message translates to:
/// **'Recompensas de partida'**
String get matchRewards;
/// No description provided for @newMedals.
///
/// In en, this message translates to:
/// **'New medals'**
/// In es, this message translates to:
/// **'Nuevas medallas'**
String get newMedals;
/// No description provided for @noNewMedalsKeepFire.
///
/// In en, this message translates to:
/// **'No new medals this time. Keep building your fire.'**
/// In es, this message translates to:
/// **'Sin medallas nuevas esta vez. Sigue acumulando fuego.'**
String get noNewMedalsKeepFire;
/// No description provided for @calculatingRewards.
///
/// In en, this message translates to:
/// **'Calculating rewards...'**
/// In es, this message translates to:
/// **'Calculando recompensas...'**
String get calculatingRewards;
/// No description provided for @fireLabel.
///
/// In en, this message translates to:
/// **'Fire'**
/// In es, this message translates to:
/// **'Fuego'**
String get fireLabel;
/// No description provided for @playersRange.
@@ -520,19 +519,6 @@ abstract class AppLocalizations {
/// **'Jugadores en debate'**
String get playersInDebate;
/// No description provided for @voteOf.
///
/// In en, this message translates to:
/// **'Vote from {name}'**
String voteOf(String name);
/// No description provided for @firstTurnInstruction.
///
/// In en, this message translates to:
/// **'{name} starts by saying their word.'**
String firstTurnInstruction(String name);
/// No description provided for @activePlayersInfo.
///
/// In es, this message translates to:
@@ -1277,79 +1263,377 @@ abstract class AppLocalizations {
/// **'Perfiles disponibles'**
String get availableProfiles;
String get play;
String get history;
String get mainTagline;
/// No description provided for @scanThisCodeFromAnotherPhone.
///
/// In es, this message translates to:
/// **'Escanea este código desde otro móvil'**
String get scanThisCodeFromAnotherPhone;
/// No description provided for @gameUsers.
///
/// In es, this message translates to:
/// **'Usuarios de la partida'**
String get gameUsers;
/// No description provided for @selectedPlayers.
///
/// In es, this message translates to:
/// **'Jugadores seleccionados'**
String get selectedPlayers;
/// No description provided for @connectedPhones.
///
/// In es, this message translates to:
/// **'Móviles conectados'**
String get connectedPhones;
/// No description provided for @selectedOnThisPhone.
///
/// In es, this message translates to:
/// **'Seleccionado en este móvil'**
String get selectedOnThisPhone;
/// No description provided for @selectedByAnotherDevice.
///
/// In es, this message translates to:
/// **'Seleccionado en otro dispositivo'**
String get selectedByAnotherDevice;
/// No description provided for @available.
///
/// In es, this message translates to:
/// **'Disponible'**
String get available;
/// No description provided for @notAvailable.
///
/// In es, this message translates to:
/// **'No disponible'**
String get notAvailable;
/// No description provided for @release.
///
/// In es, this message translates to:
/// **'Liberar'**
String get release;
/// No description provided for @select.
///
/// In es, this message translates to:
/// **'Seleccionar'**
String get select;
/// No description provided for @delete.
///
/// In es, this message translates to:
/// **'Eliminar'**
String get delete;
/// No description provided for @selectAtLeastThreeUsersToStart.
///
/// In es, this message translates to:
/// **'Selecciona al menos 3 usuarios para iniciar.'**
String get selectAtLeastThreeUsersToStart;
/// No description provided for @hostPhoneMustSelectUser.
///
/// In es, this message translates to:
/// **'El móvil servidor debe seleccionar al menos un usuario.'**
String get hostPhoneMustSelectUser;
/// No description provided for @roomNoLongerInLobby.
///
/// In es, this message translates to:
/// **'La sala ya no está en el lobby.'**
String get roomNoLongerInLobby;
/// No description provided for @completeUserSelectionToStart.
///
/// In es, this message translates to:
/// **'Completa la selección de usuarios para iniciar.'**
String get completeUserSelectionToStart;
/// No description provided for @preparingSecureRoom.
///
/// In es, this message translates to:
/// **'Preparando la sala segura'**
String get preparingSecureRoom;
/// No description provided for @searchingNearbyBluetoothGames.
///
/// In es, this message translates to:
/// **'Buscando partidas cercanas por Bluetooth'**
String get searchingNearbyBluetoothGames;
/// No description provided for @tapToJoin.
///
/// In es, this message translates to:
/// **'Toca para unirte'**
String get tapToJoin;
/// No description provided for @bluetoothLocationPermissionsRequired.
///
/// In es, this message translates to:
/// **'Se necesitan permisos de Bluetooth y ubicación para buscar partidas.'**
String get bluetoothLocationPermissionsRequired;
/// No description provided for @bluetoothLocationPermissionsShort.
///
/// In es, this message translates to:
/// **'Se necesitan permisos de Bluetooth y ubicación'**
String get bluetoothLocationPermissionsShort;
/// No description provided for @couldNotStartSearch.
///
/// In es, this message translates to:
/// **'No se pudo iniciar la búsqueda. Verifica Bluetooth y ubicación.'**
String get couldNotStartSearch;
/// No description provided for @couldNotConnectToHost.
///
/// In es, this message translates to:
/// **'No se pudo conectar a {host}'**
String couldNotConnectToHost(String host);
/// No description provided for @room.
///
/// In es, this message translates to:
/// **'Sala'**
String get room;
/// No description provided for @singleDeviceSubtitle.
///
/// In es, this message translates to:
/// **'Partida en este dispositivo'**
String get singleDeviceSubtitle;
/// No description provided for @singleDeviceDescription.
///
/// In es, this message translates to:
/// **'Ideal para jugar todos juntos pasando el móvil. Configuración rápida y directa.'**
String get singleDeviceDescription;
/// No description provided for @multiDeviceSubtitle.
///
/// In es, this message translates to:
/// **'Cada jugador en su móvil'**
String get multiDeviceSubtitle;
/// No description provided for @multiDeviceDescription.
///
/// In es, this message translates to:
/// **'Crea una sala premium, comparte el QR y gestiona usuarios desde el lobby.'**
String get multiDeviceDescription;
/// No description provided for @singleDeviceGameLabel.
///
/// In es, this message translates to:
/// **'Partida en este dispositivo'**
String get singleDeviceGameLabel;
/// No description provided for @multiDeviceGameLabel.
///
/// In es, this message translates to:
/// **'Partida multidispositivo'**
String get multiDeviceGameLabel;
/// No description provided for @mainDeviceUser.
///
/// In es, this message translates to:
/// **'Usuario principal del dispositivo'**
String get mainDeviceUser;
/// No description provided for @couldNotCreateRoom.
///
/// In es, this message translates to:
/// **'No se pudo crear la sala. Verifica Bluetooth.'**
String get couldNotCreateRoom;
/// No description provided for @cannotStartWithReason.
///
/// In es, this message translates to:
/// **'No se puede iniciar: {reason}'**
String cannotStartWithReason(String reason);
/// No description provided for @invalidRoom.
///
/// In es, this message translates to:
/// **'sala inválida'**
String get invalidRoom;
/// No description provided for @defaultPlayerName.
///
/// In es, this message translates to:
/// **'Jugador'**
String get defaultPlayerName;
/// No description provided for @play.
///
/// In es, this message translates to:
/// **'Jugar'**
String get play;
/// No description provided for @history.
///
/// In es, this message translates to:
/// **'Historial'**
String get history;
/// No description provided for @mainTagline.
///
/// In es, this message translates to:
/// **'Descubre al impostor antes de que sea tarde'**
String get mainTagline;
/// No description provided for @deviceProfile.
///
/// In es, this message translates to:
/// **'Perfil del dispositivo'**
String get deviceProfile;
/// No description provided for @profileName.
///
/// In es, this message translates to:
/// **'Nombre'**
String get profileName;
/// No description provided for @profileNick.
///
/// In es, this message translates to:
/// **'Nick'**
String get profileNick;
/// No description provided for @save.
///
/// In es, this message translates to:
/// **'Guardar'**
String get save;
/// No description provided for @automaticLanguage.
///
/// In es, this message translates to:
/// **'Automático'**
String get automaticLanguage;
/// No description provided for @noSavedGames.
///
/// In es, this message translates to:
/// **'Todavía no hay partidas guardadas.'**
String get noSavedGames;
/// No description provided for @errorNoGame.
///
/// In es, this message translates to:
/// **'Error: sin partida'**
String get errorNoGame;
/// No description provided for @disconnectedPlayersWarning.
///
/// In es, this message translates to:
/// **'Hay jugadores con el dispositivo desconectado.'**
String get disconnectedPlayersWarning;
/// No description provided for @assumeOnThisPhone.
///
/// In es, this message translates to:
/// **'Asumir en este móvil'**
String get assumeOnThisPhone;
/// No description provided for @noResult.
///
/// In es, this message translates to:
/// **'Sin resultado'**
String get noResult;
/// No description provided for @historyGameSummary.
///
/// In es, this message translates to:
/// **'\$players jugadores • \$impostors impostor(es) • \$rounds ronda(s)\n\$word • \$category'**
String historyGameSummary(
int players,
int impostors,
int rounds,
String word,
String category,
);
/// No description provided for @voteOf.
///
/// In es, this message translates to:
/// **'Voto de {name}'**
String voteOf(String name);
/// No description provided for @firstTurnInstruction.
///
/// In es, this message translates to:
/// **'Empieza {name} diciendo su palabra.'**
String firstTurnInstruction(String name);
/// No description provided for @impostorsKnowEachOther.
///
/// In es, this message translates to:
/// **'🎭 Los impostores se conocen'**
String get impostorsKnowEachOther;
/// No description provided for @impostorsKnowEachOtherDescription.
///
/// In es, this message translates to:
/// **'Cada impostor verá los nombres del resto'**
String get impostorsKnowEachOtherDescription;
/// No description provided for @impostorsKnowEachOtherNeedsTwo.
///
/// In es, this message translates to:
/// **'Solo se aplica con 2 o más impostores'**
String get impostorsKnowEachOtherNeedsTwo;
/// No description provided for @otherImpostorsTitle.
///
/// In es, this message translates to:
/// **'{count, plural, =1{El otro impostor} other{Los otros impostores}}'**
String otherImpostorsTitle(num count);
/// No description provided for @youAreTheOnlyImpostor.
///
/// In es, this message translates to:
/// **'Eres el único impostor'**
String get youAreTheOnlyImpostor;
/// No description provided for @impostorsAdjusted.
///
/// In es, this message translates to:
/// **'Impostores ajustados a {count} por el número de jugadores'**
String impostorsAdjusted(int count);
/// No description provided for @eliminatedCannotVote.
///
/// In es, this message translates to:
/// **'Estás eliminado: ya no votas'**
String get eliminatedCannotVote;
/// No description provided for @reconnecting.
///
/// In es, this message translates to:
/// **'Reconectando...'**
String get reconnecting;
/// No description provided for @reconnectingHint.
///
/// In es, this message translates to:
/// **'Se perdió la conexión con el host. Tu sitio en la partida se mantiene.'**
String get reconnectingHint;
/// No description provided for @leaveGame.
///
/// In es, this message translates to:
/// **'Salir de la partida'**
String get leaveGame;
/// No description provided for @playerRejoined.
///
/// In es, this message translates to:
/// **'{name} ha vuelto a la partida'**
String playerRejoined(String name);
}
class _AppLocalizationsDelegate
@@ -1443,26 +1727,4 @@ AppLocalizations lookupAppLocalizations(Locale locale) {
'on GitHub with a reproducible sample app and the gen-l10n configuration '
'that was used.',
);
String get deviceProfile;
String get profileName;
String get profileNick;
String get save;
String get automaticLanguage;
String get noSavedGames;
String get errorNoGame;
String get disconnectedPlayersWarning;
String get assumeOnThisPhone;
String get noResult;
String historyGameSummary(int players, int impostors, int rounds, String word, String category);
}
}
+132 -70
View File
@@ -18,19 +18,20 @@ class AppLocalizationsAr extends AppLocalizations {
String get loadingWords => 'جارٍ تحميل الكلمات...';
@override
String get matchRewards => "مكافآت المباراة";
String get matchRewards => 'مكافآت المباراة';
@override
String get newMedals => "ميداليات جديدة";
String get newMedals => 'ميداليات جديدة';
@override
String get noNewMedalsKeepFire => "لا توجد ميداليات جديدة هذه المرة. واصل إشعال حماسك.";
String get noNewMedalsKeepFire =>
'لا توجد ميداليات جديدة هذه المرة. واصل إشعال حماسك.';
@override
String get calculatingRewards => "جارٍ حساب المكافآت...";
String get calculatingRewards => 'جارٍ حساب المكافآت...';
@override
String get fireLabel => "النار";
String get fireLabel => 'النار';
@override
String get playersRange => '3-20 لاعبًا • بدون إنترنت';
@@ -125,7 +126,7 @@ class AppLocalizationsAr extends AppLocalizations {
String get impostorClueDescription => 'المنتحل يعرف الفئة';
@override
String get debate => '🗣️ Debate';
String get debate => '🗣️ نقاش';
@override
String get debateTime => '⏱️ وقت النقاش';
@@ -213,16 +214,6 @@ class AppLocalizationsAr extends AppLocalizations {
@override
String get playersInDebate => 'اللاعبون في النقاش';
@override
String voteOf(String name) {
return "تصويت $name";
}
@override
String firstTurnInstruction(String name) {
return "يبدأ $name بقول كلمته.";
}
@override
String activePlayersInfo(int active, int impostors) {
return '$active نشطون • $impostors منتحل(ون) مختبئون';
@@ -500,128 +491,126 @@ class AppLocalizationsAr extends AppLocalizations {
String get licenses => 'التراخيص';
@override
String get scanToJoin => 'Escanea el QR para unirte';
String get scanToJoin => 'امسح رمز QR للانضمام';
@override
String get connectedPlayers => 'Jugadores conectados';
String get connectedPlayers => 'اللاعبون المتصلون';
@override
String get hostGame => 'Gestor de partida';
String get hostGame => 'إدارة الجولة';
@override
String get waitingPlayersSeeWord => 'Esperando que todos vean su palabra...';
String get waitingPlayersSeeWord => 'بانتظار أن يرى الجميع كلمتهم...';
@override
String get activePlayers => 'Jugadores activos';
String get activePlayers => 'اللاعبون النشطون';
@override
String get playersVoted => 'Han votado';
String get playersVoted => 'صوّتوا';
@override
String get waitingVoting => 'Esperando que voten...';
String get waitingVoting => 'بانتظار الأصوات...';
@override
String get waitingForPlayers => 'Esperando jugadores...';
String get waitingForPlayers => 'بانتظار اللاعبين...';
@override
String needMorePlayers(int count) {
return 'Faltan $count jugadores más';
return 'يلزم $count لاعبين إضافيين';
}
@override
String get starting => 'Iniciando...';
String get starting => 'جارٍ البدء...';
@override
String get enterNameAndScan => 'Escribe tu nombre y escanea el QR del host';
String get enterNameAndScan => 'اكتب اسمك وامسح رمز QR الخاص بالمضيف';
@override
String get yourName => 'Tu nombre';
String get yourName => 'اسمك';
@override
String get nameRequired => 'Escribe tu nombre';
String get nameRequired => 'اكتب اسمك';
@override
String get connectingTo => 'Conectando a';
String get connectingTo => 'جارٍ الاتصال بـ';
@override
String get scanQR => 'Escanear QR';
String get scanQR => 'مسح رمز QR';
@override
String get scanHostQR => 'Apunta al QR del host';
String get scanHostQR => 'وجّه الكاميرا إلى رمز QR للمضيف';
@override
String get connectedWaiting => '¡Conectado!';
String get connectedWaiting => 'تم الاتصال!';
@override
String get waitingForHost => 'Esperando a que el host inicie la partida...';
String get waitingForHost => 'بانتظار أن يبدأ المضيف الجولة...';
@override
String get enterNameToSearch =>
'Escribe tu nombre para buscar partidas cercanas';
String get enterNameToSearch => 'اكتب اسمك للبحث عن جولات قريبة';
@override
String get searchGames => 'Buscar partidas';
String get searchGames => 'البحث عن جولات';
@override
String get searchingGames => 'Buscando partidas cercanas...';
String get searchingGames => 'جارٍ البحث عن جولات قريبة...';
@override
String get noGamesFound => 'No se encontraron partidas';
String get noGamesFound => 'لم يتم العثور على جولات';
@override
String get noGamesFoundHint =>
'Asegúrate de que el host tiene la sala abierta y estáis cerca';
String get noGamesFoundHint => 'تأكد من أن المضيف قد فتح الغرفة وأنكم قريبون';
@override
String get orScanQR => '¿No aparece? Escanea el QR del host';
String get orScanQR => 'لا تظهر؟ امسح رمز QR للمضيف';
@override
String get iveSeenIt => 'Ya la he visto';
String get iveSeenIt => 'لقد رأيتها';
@override
String clueIs(String category) {
return 'La pista es: $category';
return 'التلميح: $category';
}
@override
String get debatePhaseActive => 'Fase de debate activa';
String get debatePhaseActive => 'مرحلة النقاش جارية';
@override
String get debateInstructions =>
'Hablad entre vosotros y decid quién creéis que es el impostor. Cuando estéis listos, solicitad la votación.';
'تحدثوا فيما بينكم وقولوا من تظنون أنه المحتال. عندما تكونون جاهزين، اطلبوا التصويت.';
@override
String get solicitarVotacion => 'Solicitar votación';
String get solicitarVotacion => 'طلب التصويت';
@override
String get votacionSolicitada => 'Votación solicitada';
String get votacionSolicitada => 'تم طلب التصويت';
@override
String get whoDoYouThinkIsTheImpostor => '¿Quién es el impostor?';
String get whoDoYouThinkIsTheImpostor => 'من هو المحتال؟';
@override
String get selectOnePlayer => 'Selecciona a un jugador para votar';
String get selectOnePlayer => 'اختر لاعبًا للتصويت';
@override
String get votar => 'Votar';
String get votar => 'تصويت';
@override
String get selectYourProfile => 'Tu perfil';
String get selectYourProfile => 'ملفك الشخصي';
@override
String get selectProfile => 'Selecciona un perfil';
String get selectProfile => 'اختر ملفًا شخصيًا';
@override
String get createNewUser => 'Crear nuevo usuario';
String get createNewUser => 'إنشاء مستخدم جديد';
@override
String get userNameRequired => 'El nombre no puede estar vacio';
String get userNameRequired => 'لا يمكن ترك الاسم فارغًا';
@override
String get profileSelected => 'Perfil seleccionado';
String get profileSelected => 'تم اختيار الملف الشخصي';
@override
String get availableProfiles => 'Perfiles disponibles';
String get availableProfiles => 'الملفات الشخصية المتاحة';
@override
String get scanThisCodeFromAnotherPhone => 'امسح هذا الرمز من هاتف آخر';
@@ -657,34 +646,41 @@ class AppLocalizationsAr extends AppLocalizations {
String get delete => 'حذف';
@override
String get selectAtLeastThreeUsersToStart => 'Select at least 3 users to start.';
String get selectAtLeastThreeUsersToStart =>
'Select at least 3 users to start.';
@override
String get hostPhoneMustSelectUser => 'The host phone must select at least one user.';
String get hostPhoneMustSelectUser =>
'The host phone must select at least one user.';
@override
String get roomNoLongerInLobby => 'The room is no longer in the lobby.';
@override
String get completeUserSelectionToStart => 'Complete user selection to start.';
String get completeUserSelectionToStart =>
'Complete user selection to start.';
@override
String get preparingSecureRoom => 'Preparing the secure room';
@override
String get searchingNearbyBluetoothGames => 'Searching nearby games over Bluetooth';
String get searchingNearbyBluetoothGames =>
'Searching nearby games over Bluetooth';
@override
String get tapToJoin => 'Tap to join';
@override
String get bluetoothLocationPermissionsRequired => 'Bluetooth and location permissions are required to search for games.';
String get bluetoothLocationPermissionsRequired =>
'Bluetooth and location permissions are required to search for games.';
@override
String get bluetoothLocationPermissionsShort => 'Bluetooth and location permissions are required';
String get bluetoothLocationPermissionsShort =>
'Bluetooth and location permissions are required';
@override
String get couldNotStartSearch => 'Could not start the search. Check Bluetooth and location.';
String get couldNotStartSearch =>
'Could not start the search. Check Bluetooth and location.';
@override
String couldNotConnectToHost(String host) {
@@ -698,13 +694,15 @@ class AppLocalizationsAr extends AppLocalizations {
String get singleDeviceSubtitle => 'Game on this device';
@override
String get singleDeviceDescription => 'Ideal for playing together by passing the phone around. Fast, direct setup.';
String get singleDeviceDescription =>
'Ideal for playing together by passing the phone around. Fast, direct setup.';
@override
String get multiDeviceSubtitle => 'Each player on their phone';
@override
String get multiDeviceDescription => 'Create a premium room, share the QR code and manage users from the lobby.';
String get multiDeviceDescription =>
'Create a premium room, share the QR code and manage users from the lobby.';
@override
String get singleDeviceGameLabel => 'Game on this device';
@@ -716,7 +714,8 @@ class AppLocalizationsAr extends AppLocalizations {
String get mainDeviceUser => 'Main device user';
@override
String get couldNotCreateRoom => 'Could not create the room. Check Bluetooth.';
String get couldNotCreateRoom =>
'Could not create the room. Check Bluetooth.';
@override
String cannotStartWithReason(String reason) {
@@ -728,6 +727,7 @@ class AppLocalizationsAr extends AppLocalizations {
@override
String get defaultPlayerName => 'لاعب';
@override
String get play => 'العب';
@@ -768,8 +768,70 @@ class AppLocalizationsAr extends AppLocalizations {
String get noResult => 'لا توجد نتيجة';
@override
String historyGameSummary(int players, int impostors, int rounds, String word, String category) {
return '$players لاعبون • $impostors محتالون • $rounds جولات\n$word$category';
String historyGameSummary(
int players,
int impostors,
int rounds,
String word,
String category,
) {
return '\$players لاعبون • \$impostors محتالون • \$rounds جولات\n\$word • \$category';
}
}
@override
String voteOf(String name) {
return 'تصويت $name';
}
@override
String firstTurnInstruction(String name) {
return 'يبدأ $name بقول كلمته.';
}
@override
String get impostorsKnowEachOther => '🎭 المحتالون يعرفون بعضهم';
@override
String get impostorsKnowEachOtherDescription => 'سيرى كل محتال أسماء الآخرين';
@override
String get impostorsKnowEachOtherNeedsTwo =>
'ينطبق فقط عند وجود محتالَين أو أكثر';
@override
String otherImpostorsTitle(num count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: 'المحتالون الآخرون',
one: 'المحتال الآخر',
);
return '$_temp0';
}
@override
String get youAreTheOnlyImpostor => 'أنت المحتال الوحيد';
@override
String impostorsAdjusted(int count) {
return 'تم ضبط عدد المحتالين إلى $count حسب عدد اللاعبين';
}
@override
String get eliminatedCannotVote => 'لقد خرجت: لم تعد تصوّت';
@override
String get reconnecting => 'جارٍ إعادة الاتصال...';
@override
String get reconnectingHint =>
'انقطع الاتصال بالمضيف. مكانك في الجولة محفوظ.';
@override
String get leaveGame => 'مغادرة الجولة';
@override
String playerRejoined(String name) {
return 'عاد $name إلى الجولة';
}
}
+136 -67
View File
@@ -18,19 +18,20 @@ class AppLocalizationsCa extends AppLocalizations {
String get loadingWords => 'Carregant paraules...';
@override
String get matchRewards => "Recompenses de partida";
String get matchRewards => 'Recompenses de partida';
@override
String get newMedals => "Noves medalles";
String get newMedals => 'Noves medalles';
@override
String get noNewMedalsKeepFire => "Sense medalles noves aquesta vegada. Continua acumulant foc.";
String get noNewMedalsKeepFire =>
'Sense medalles noves aquesta vegada. Continua acumulant foc.';
@override
String get calculatingRewards => "Calculant recompenses...";
String get calculatingRewards => 'Calculant recompenses...';
@override
String get fireLabel => "Foc";
String get fireLabel => 'Foc';
@override
String get playersRange => '3-20 jugadors • Sense internet';
@@ -125,7 +126,7 @@ class AppLocalizationsCa extends AppLocalizations {
String get impostorClueDescription => 'L\'impostor coneix la categoria';
@override
String get debate => '🗣️ Debate';
String get debate => '🗣️ Debat';
@override
String get debateTime => '⏱️ Temps de debat';
@@ -214,16 +215,6 @@ class AppLocalizationsCa extends AppLocalizations {
@override
String get playersInDebate => 'Jugadors en debat';
@override
String voteOf(String name) {
return "Vot de $name";
}
@override
String firstTurnInstruction(String name) {
return "Comença $name dient la seva paraula.";
}
@override
String activePlayersInfo(int active, int impostors) {
return '$active actius • $impostors impostor(s) ocults';
@@ -503,131 +494,134 @@ class AppLocalizationsCa extends AppLocalizations {
String get licenses => 'Llicències';
@override
String get scanToJoin => 'Escanea el QR para unirte';
String get scanToJoin => 'Escaneja el QR per unir-te';
@override
String get connectedPlayers => 'Jugadores conectados';
String get connectedPlayers => 'Jugadors connectats';
@override
String get hostGame => 'Gestor de partida';
@override
String get waitingPlayersSeeWord => 'Esperando que todos vean su palabra...';
String get waitingPlayersSeeWord =>
'Esperant que tothom vegi la seva paraula...';
@override
String get activePlayers => 'Jugadores activos';
String get activePlayers => 'Jugadors actius';
@override
String get playersVoted => 'Han votado';
String get playersVoted => 'Han votat';
@override
String get waitingVoting => 'Esperando que voten...';
String get waitingVoting => 'Esperant els vots...';
@override
String get waitingForPlayers => 'Esperando jugadores...';
String get waitingForPlayers => 'Esperant jugadors...';
@override
String needMorePlayers(int count) {
return 'Faltan $count jugadores más';
return 'Falten $count jugadors més';
}
@override
String get starting => 'Iniciando...';
String get starting => 'Iniciant...';
@override
String get enterNameAndScan => 'Escribe tu nombre y escanea el QR del host';
String get enterNameAndScan =>
'Escriu el teu nom i escaneja el QR de l\'amfitrió';
@override
String get yourName => 'Tu nombre';
String get yourName => 'El teu nom';
@override
String get nameRequired => 'Escribe tu nombre';
String get nameRequired => 'Escriu el teu nom';
@override
String get connectingTo => 'Conectando a';
String get connectingTo => 'Connectant a';
@override
String get scanQR => 'Escanear QR';
String get scanQR => 'Escanejar QR';
@override
String get scanHostQR => 'Apunta al QR del host';
String get scanHostQR => 'Apunta al QR de l\'amfitrió';
@override
String get connectedWaiting => '¡Conectado!';
String get connectedWaiting => 'Connectat!';
@override
String get waitingForHost => 'Esperando a que el host inicie la partida...';
String get waitingForHost => 'Esperant que l\'amfitrió iniciï la partida...';
@override
String get enterNameToSearch =>
'Escribe tu nombre para buscar partidas cercanas';
'Escriu el teu nom per buscar partides properes';
@override
String get searchGames => 'Buscar partidas';
String get searchGames => 'Buscar partides';
@override
String get searchingGames => 'Buscando partidas cercanas...';
String get searchingGames => 'Buscant partides properes...';
@override
String get noGamesFound => 'No se encontraron partidas';
String get noGamesFound => 'No s\'han trobat partides';
@override
String get noGamesFoundHint =>
'Asegúrate de que el host tiene la sala abierta y estáis cerca';
'Assegura\'t que l\'amfitrió té la sala oberta i que sou a prop';
@override
String get orScanQR => '¿No aparece? Escanea el QR del host';
String get orScanQR => 'No apareix? Escaneja el QR de l\'amfitrió';
@override
String get iveSeenIt => 'Ya la he visto';
String get iveSeenIt => 'Ja l\'he vista';
@override
String clueIs(String category) {
return 'La pista es: $category';
return 'La pista és: $category';
}
@override
String get debatePhaseActive => 'Fase de debate activa';
String get debatePhaseActive => 'Fase de debat activa';
@override
String get debateInstructions =>
'Hablad entre vosotros y decid quién creéis que es el impostor. Cuando estéis listos, solicitad la votación.';
'Parleu entre vosaltres i digueu qui creieu que és l\'impostor. Quan estigueu llestos, demaneu la votació.';
@override
String get solicitarVotacion => 'Solicitar votación';
String get solicitarVotacion => 'Demanar votació';
@override
String get votacionSolicitada => 'Votación solicitada';
String get votacionSolicitada => 'Votació demanada';
@override
String get whoDoYouThinkIsTheImpostor => '¿Quién es el impostor?';
String get whoDoYouThinkIsTheImpostor => 'Qui és l\'impostor?';
@override
String get selectOnePlayer => 'Selecciona a un jugador para votar';
String get selectOnePlayer => 'Selecciona un jugador per votar';
@override
String get votar => 'Votar';
@override
String get selectYourProfile => 'Tu perfil';
String get selectYourProfile => 'El teu perfil';
@override
String get selectProfile => 'Selecciona un perfil';
@override
String get createNewUser => 'Crear nuevo usuario';
String get createNewUser => 'Crear nou usuari';
@override
String get userNameRequired => 'El nombre no puede estar vacio';
String get userNameRequired => 'El nom no pot estar buit';
@override
String get profileSelected => 'Perfil seleccionado';
String get profileSelected => 'Perfil seleccionat';
@override
String get availableProfiles => 'Perfiles disponibles';
String get availableProfiles => 'Perfils disponibles';
@override
String get scanThisCodeFromAnotherPhone => 'Escaneja aquest codi des dun altre mòbil';
String get scanThisCodeFromAnotherPhone =>
'Escaneja aquest codi des dun altre mòbil';
@override
String get gameUsers => 'Usuaris de la partida';
@@ -660,34 +654,41 @@ class AppLocalizationsCa extends AppLocalizations {
String get delete => 'Elimina';
@override
String get selectAtLeastThreeUsersToStart => 'Selecciona almenys 3 usuaris per començar.';
String get selectAtLeastThreeUsersToStart =>
'Selecciona almenys 3 usuaris per començar.';
@override
String get hostPhoneMustSelectUser => 'El mòbil servidor ha de seleccionar almenys un usuari.';
String get hostPhoneMustSelectUser =>
'El mòbil servidor ha de seleccionar almenys un usuari.';
@override
String get roomNoLongerInLobby => 'La sala ja no és al lobby.';
@override
String get completeUserSelectionToStart => 'Completa la selecció dusuaris per començar.';
String get completeUserSelectionToStart =>
'Completa la selecció dusuaris per començar.';
@override
String get preparingSecureRoom => 'Preparant la sala segura';
@override
String get searchingNearbyBluetoothGames => 'Cercant partides properes per Bluetooth';
String get searchingNearbyBluetoothGames =>
'Cercant partides properes per Bluetooth';
@override
String get tapToJoin => 'Toca per unir-thi';
@override
String get bluetoothLocationPermissionsRequired => 'Calen permisos de Bluetooth i ubicació per cercar partides.';
String get bluetoothLocationPermissionsRequired =>
'Calen permisos de Bluetooth i ubicació per cercar partides.';
@override
String get bluetoothLocationPermissionsShort => 'Calen permisos de Bluetooth i ubicació';
String get bluetoothLocationPermissionsShort =>
'Calen permisos de Bluetooth i ubicació';
@override
String get couldNotStartSearch => 'No sha pogut iniciar la cerca. Verifica el Bluetooth i la ubicació.';
String get couldNotStartSearch =>
'No sha pogut iniciar la cerca. Verifica el Bluetooth i la ubicació.';
@override
String couldNotConnectToHost(String host) {
@@ -701,13 +702,15 @@ class AppLocalizationsCa extends AppLocalizations {
String get singleDeviceSubtitle => 'Partida en aquest dispositiu';
@override
String get singleDeviceDescription => 'Ideal per jugar tots junts passant el mòbil. Configuració ràpida i directa.';
String get singleDeviceDescription =>
'Ideal per jugar tots junts passant el mòbil. Configuració ràpida i directa.';
@override
String get multiDeviceSubtitle => 'Cada jugador al seu mòbil';
@override
String get multiDeviceDescription => 'Crea una sala premium, comparteix el QR i gestiona usuaris des del lobby.';
String get multiDeviceDescription =>
'Crea una sala premium, comparteix el QR i gestiona usuaris des del lobby.';
@override
String get singleDeviceGameLabel => 'Partida en aquest dispositiu';
@@ -719,7 +722,8 @@ class AppLocalizationsCa extends AppLocalizations {
String get mainDeviceUser => 'Usuari principal del dispositiu';
@override
String get couldNotCreateRoom => 'No sha pogut crear la sala. Verifica el Bluetooth.';
String get couldNotCreateRoom =>
'No sha pogut crear la sala. Verifica el Bluetooth.';
@override
String cannotStartWithReason(String reason) {
@@ -731,6 +735,7 @@ class AppLocalizationsCa extends AppLocalizations {
@override
String get defaultPlayerName => 'Jugador';
@override
String get play => 'Jugar';
@@ -762,7 +767,8 @@ class AppLocalizationsCa extends AppLocalizations {
String get errorNoGame => 'Error: no hi ha partida';
@override
String get disconnectedPlayersWarning => 'Hi ha jugadors amb el dispositiu desconnectat.';
String get disconnectedPlayersWarning =>
'Hi ha jugadors amb el dispositiu desconnectat.';
@override
String get assumeOnThisPhone => 'Assumir en aquest mòbil';
@@ -771,8 +777,71 @@ class AppLocalizationsCa extends AppLocalizations {
String get noResult => 'Sense resultat';
@override
String historyGameSummary(int players, int impostors, int rounds, String word, String category) {
return '$players jugadors • $impostors impostor(s) • $rounds ronda(es)\n$word$category';
String historyGameSummary(
int players,
int impostors,
int rounds,
String word,
String category,
) {
return '\$players jugadors • \$impostors impostor(s) • \$rounds ronda(es)\n\$word • \$category';
}
}
@override
String voteOf(String name) {
return 'Vot de $name';
}
@override
String firstTurnInstruction(String name) {
return 'Comença $name dient la seva paraula.';
}
@override
String get impostorsKnowEachOther => '🎭 Els impostors es coneixen';
@override
String get impostorsKnowEachOtherDescription =>
'Cada impostor veurà els noms de la resta';
@override
String get impostorsKnowEachOtherNeedsTwo =>
'Només s\'aplica amb 2 o més impostors';
@override
String otherImpostorsTitle(num count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: 'Els altres impostors',
one: 'L\'altre impostor',
);
return '$_temp0';
}
@override
String get youAreTheOnlyImpostor => 'Ets l\'únic impostor';
@override
String impostorsAdjusted(int count) {
return 'Impostors ajustats a $count pel nombre de jugadors';
}
@override
String get eliminatedCannotVote => 'Estàs eliminat: ja no votes';
@override
String get reconnecting => 'Reconnectant...';
@override
String get reconnectingHint =>
'S\'ha perdut la connexió amb l\'amfitrió. El teu lloc a la partida es manté.';
@override
String get leaveGame => 'Sortir de la partida';
@override
String playerRejoined(String name) {
return '$name ha tornat a la partida';
}
}
+139 -70
View File
@@ -18,19 +18,20 @@ class AppLocalizationsDe extends AppLocalizations {
String get loadingWords => 'Wörter werden geladen...';
@override
String get matchRewards => "Spielbelohnungen";
String get matchRewards => 'Spielbelohnungen';
@override
String get newMedals => "Neue Medaillen";
String get newMedals => 'Neue Medaillen';
@override
String get noNewMedalsKeepFire => "Diesmal keine neuen Medaillen. Baue dein Feuer weiter aus.";
String get noNewMedalsKeepFire =>
'Diesmal keine neuen Medaillen. Baue dein Feuer weiter aus.';
@override
String get calculatingRewards => "Belohnungen werden berechnet...";
String get calculatingRewards => 'Belohnungen werden berechnet...';
@override
String get fireLabel => "Feuer";
String get fireLabel => 'Feuer';
@override
String get playersRange => '3-20 Spieler • Ohne Internet';
@@ -126,7 +127,7 @@ class AppLocalizationsDe extends AppLocalizations {
String get impostorClueDescription => 'Der Hochstapler kennt die Kategorie';
@override
String get debate => '🗣️ Debate';
String get debate => '🗣️ Diskussion';
@override
String get debateTime => '⏱️ Diskussionszeit';
@@ -216,16 +217,6 @@ class AppLocalizationsDe extends AppLocalizations {
@override
String get playersInDebate => 'Spieler in der Diskussion';
@override
String voteOf(String name) {
return "Stimme von $name";
}
@override
String firstTurnInstruction(String name) {
return "$name beginnt und sagt sein/ihr Wort.";
}
@override
String activePlayersInfo(int active, int impostors) {
return '$active aktiv • $impostors versteckte(r) Hochstapler';
@@ -506,131 +497,134 @@ class AppLocalizationsDe extends AppLocalizations {
String get licenses => 'Lizenzen';
@override
String get scanToJoin => 'Escanea el QR para unirte';
String get scanToJoin => 'Scanne den QR-Code zum Beitreten';
@override
String get connectedPlayers => 'Jugadores conectados';
String get connectedPlayers => 'Verbundene Spieler';
@override
String get hostGame => 'Gestor de partida';
String get hostGame => 'Spielleitung';
@override
String get waitingPlayersSeeWord => 'Esperando que todos vean su palabra...';
String get waitingPlayersSeeWord =>
'Warten, bis alle ihr Wort gesehen haben ...';
@override
String get activePlayers => 'Jugadores activos';
String get activePlayers => 'Aktive Spieler';
@override
String get playersVoted => 'Han votado';
String get playersVoted => 'Haben abgestimmt';
@override
String get waitingVoting => 'Esperando que voten...';
String get waitingVoting => 'Warten auf die Stimmen ...';
@override
String get waitingForPlayers => 'Esperando jugadores...';
String get waitingForPlayers => 'Warten auf Spieler ...';
@override
String needMorePlayers(int count) {
return 'Faltan $count jugadores más';
return 'Es fehlen noch $count Spieler';
}
@override
String get starting => 'Iniciando...';
String get starting => 'Wird gestartet ...';
@override
String get enterNameAndScan => 'Escribe tu nombre y escanea el QR del host';
String get enterNameAndScan =>
'Gib deinen Namen ein und scanne den QR-Code des Hosts';
@override
String get yourName => 'Tu nombre';
String get yourName => 'Dein Name';
@override
String get nameRequired => 'Escribe tu nombre';
String get nameRequired => 'Gib deinen Namen ein';
@override
String get connectingTo => 'Conectando a';
String get connectingTo => 'Verbinde mit';
@override
String get scanQR => 'Escanear QR';
String get scanQR => 'QR-Code scannen';
@override
String get scanHostQR => 'Apunta al QR del host';
String get scanHostQR => 'Richte die Kamera auf den QR-Code des Hosts';
@override
String get connectedWaiting => '¡Conectado!';
String get connectedWaiting => 'Verbunden!';
@override
String get waitingForHost => 'Esperando a que el host inicie la partida...';
String get waitingForHost => 'Warten, bis der Host das Spiel startet ...';
@override
String get enterNameToSearch =>
'Escribe tu nombre para buscar partidas cercanas';
'Gib deinen Namen ein, um Spiele in der Nähe zu finden';
@override
String get searchGames => 'Buscar partidas';
String get searchGames => 'Spiele suchen';
@override
String get searchingGames => 'Buscando partidas cercanas...';
String get searchingGames => 'Suche nach Spielen in der Nähe ...';
@override
String get noGamesFound => 'No se encontraron partidas';
String get noGamesFound => 'Keine Spiele gefunden';
@override
String get noGamesFoundHint =>
'Asegúrate de que el host tiene la sala abierta y estáis cerca';
'Stelle sicher, dass der Host den Raum geöffnet hat und ihr in der Nähe seid';
@override
String get orScanQR => '¿No aparece? Escanea el QR del host';
String get orScanQR => 'Wird nicht angezeigt? Scanne den QR-Code des Hosts';
@override
String get iveSeenIt => 'Ya la he visto';
String get iveSeenIt => 'Ich habe es gesehen';
@override
String clueIs(String category) {
return 'La pista es: $category';
return 'Der Hinweis lautet: $category';
}
@override
String get debatePhaseActive => 'Fase de debate activa';
String get debatePhaseActive => 'Diskussionsphase läuft';
@override
String get debateInstructions =>
'Hablad entre vosotros y decid quién creéis que es el impostor. Cuando estéis listos, solicitad la votación.';
'Sprecht miteinander und sagt, wen ihr für den Betrüger haltet. Wenn ihr bereit seid, fordert die Abstimmung an.';
@override
String get solicitarVotacion => 'Solicitar votación';
String get solicitarVotacion => 'Abstimmung anfordern';
@override
String get votacionSolicitada => 'Votación solicitada';
String get votacionSolicitada => 'Abstimmung angefordert';
@override
String get whoDoYouThinkIsTheImpostor => '¿Quién es el impostor?';
String get whoDoYouThinkIsTheImpostor => 'Wer ist der Betrüger?';
@override
String get selectOnePlayer => 'Selecciona a un jugador para votar';
String get selectOnePlayer => 'Wähle einen Spieler zum Abstimmen';
@override
String get votar => 'Votar';
String get votar => 'Abstimmen';
@override
String get selectYourProfile => 'Tu perfil';
String get selectYourProfile => 'Dein Profil';
@override
String get selectProfile => 'Selecciona un perfil';
String get selectProfile => 'Wähle ein Profil';
@override
String get createNewUser => 'Crear nuevo usuario';
String get createNewUser => 'Neuen Benutzer erstellen';
@override
String get userNameRequired => 'El nombre no puede estar vacio';
String get userNameRequired => 'Der Name darf nicht leer sein';
@override
String get profileSelected => 'Perfil seleccionado';
String get profileSelected => 'Profil ausgewählt';
@override
String get availableProfiles => 'Perfiles disponibles';
String get availableProfiles => 'Verfügbare Profile';
@override
String get scanThisCodeFromAnotherPhone => 'Scanne diesen Code mit einem anderen Handy';
String get scanThisCodeFromAnotherPhone =>
'Scanne diesen Code mit einem anderen Handy';
@override
String get gameUsers => 'Spielbenutzer';
@@ -663,34 +657,41 @@ class AppLocalizationsDe extends AppLocalizations {
String get delete => 'Löschen';
@override
String get selectAtLeastThreeUsersToStart => 'Wähle mindestens 3 Benutzer aus, um zu starten.';
String get selectAtLeastThreeUsersToStart =>
'Wähle mindestens 3 Benutzer aus, um zu starten.';
@override
String get hostPhoneMustSelectUser => 'Das Host-Handy muss mindestens einen Benutzer auswählen.';
String get hostPhoneMustSelectUser =>
'Das Host-Handy muss mindestens einen Benutzer auswählen.';
@override
String get roomNoLongerInLobby => 'Der Raum ist nicht mehr in der Lobby.';
@override
String get completeUserSelectionToStart => 'Schließe die Benutzerauswahl ab, um zu starten.';
String get completeUserSelectionToStart =>
'Schließe die Benutzerauswahl ab, um zu starten.';
@override
String get preparingSecureRoom => 'Sicherer Raum wird vorbereitet';
@override
String get searchingNearbyBluetoothGames => 'Suche nach Spielen in der Nähe per Bluetooth';
String get searchingNearbyBluetoothGames =>
'Suche nach Spielen in der Nähe per Bluetooth';
@override
String get tapToJoin => 'Tippen zum Beitreten';
@override
String get bluetoothLocationPermissionsRequired => 'Bluetooth- und Standortberechtigungen sind erforderlich, um Spiele zu suchen.';
String get bluetoothLocationPermissionsRequired =>
'Bluetooth- und Standortberechtigungen sind erforderlich, um Spiele zu suchen.';
@override
String get bluetoothLocationPermissionsShort => 'Bluetooth- und Standortberechtigungen sind erforderlich';
String get bluetoothLocationPermissionsShort =>
'Bluetooth- und Standortberechtigungen sind erforderlich';
@override
String get couldNotStartSearch => 'Suche konnte nicht gestartet werden. Prüfe Bluetooth und Standort.';
String get couldNotStartSearch =>
'Suche konnte nicht gestartet werden. Prüfe Bluetooth und Standort.';
@override
String couldNotConnectToHost(String host) {
@@ -704,13 +705,15 @@ class AppLocalizationsDe extends AppLocalizations {
String get singleDeviceSubtitle => 'Spiel auf diesem Gerät';
@override
String get singleDeviceDescription => 'Ideal, um gemeinsam zu spielen, indem das Handy weitergegeben wird. Schnelle, direkte Einrichtung.';
String get singleDeviceDescription =>
'Ideal, um gemeinsam zu spielen, indem das Handy weitergegeben wird. Schnelle, direkte Einrichtung.';
@override
String get multiDeviceSubtitle => 'Jeder Spieler auf seinem Handy';
@override
String get multiDeviceDescription => 'Erstelle einen Premium-Raum, teile den QR-Code und verwalte Benutzer in der Lobby.';
String get multiDeviceDescription =>
'Erstelle einen Premium-Raum, teile den QR-Code und verwalte Benutzer in der Lobby.';
@override
String get singleDeviceGameLabel => 'Spiel auf diesem Gerät';
@@ -722,7 +725,8 @@ class AppLocalizationsDe extends AppLocalizations {
String get mainDeviceUser => 'Hauptbenutzer des Geräts';
@override
String get couldNotCreateRoom => 'Raum konnte nicht erstellt werden. Prüfe Bluetooth.';
String get couldNotCreateRoom =>
'Raum konnte nicht erstellt werden. Prüfe Bluetooth.';
@override
String cannotStartWithReason(String reason) {
@@ -734,6 +738,7 @@ class AppLocalizationsDe extends AppLocalizations {
@override
String get defaultPlayerName => 'Spieler';
@override
String get play => 'Spielen';
@@ -765,7 +770,8 @@ class AppLocalizationsDe extends AppLocalizations {
String get errorNoGame => 'Fehler: Keine Partie';
@override
String get disconnectedPlayersWarning => 'Einige Spieler haben ein getrenntes Gerät.';
String get disconnectedPlayersWarning =>
'Einige Spieler haben ein getrenntes Gerät.';
@override
String get assumeOnThisPhone => 'Auf diesem Handy übernehmen';
@@ -774,8 +780,71 @@ class AppLocalizationsDe extends AppLocalizations {
String get noResult => 'Kein Ergebnis';
@override
String historyGameSummary(int players, int impostors, int rounds, String word, String category) {
return '$players Spieler • $impostors Verräter • $rounds Runden\n$word$category';
String historyGameSummary(
int players,
int impostors,
int rounds,
String word,
String category,
) {
return '\$players Spieler • \$impostors Verräter • \$rounds Runden\n\$word • \$category';
}
}
@override
String voteOf(String name) {
return 'Stimme von $name';
}
@override
String firstTurnInstruction(String name) {
return '$name beginnt und sagt sein/ihr Wort.';
}
@override
String get impostorsKnowEachOther => '🎭 Betrüger kennen einander';
@override
String get impostorsKnowEachOtherDescription =>
'Jeder Betrüger sieht die Namen der anderen';
@override
String get impostorsKnowEachOtherNeedsTwo => 'Gilt nur ab 2 Betrügern';
@override
String otherImpostorsTitle(num count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: 'Die anderen Betrüger',
one: 'Der andere Betrüger',
);
return '$_temp0';
}
@override
String get youAreTheOnlyImpostor => 'Du bist der einzige Betrüger';
@override
String impostorsAdjusted(int count) {
return 'Betrüger auf $count angepasst — abhängig von der Spielerzahl';
}
@override
String get eliminatedCannotVote =>
'Du bist ausgeschieden du stimmst nicht mehr ab';
@override
String get reconnecting => 'Verbindung wird wiederhergestellt ...';
@override
String get reconnectingHint =>
'Verbindung zum Host verloren. Dein Platz im Spiel bleibt reserviert.';
@override
String get leaveGame => 'Spiel verlassen';
@override
String playerRejoined(String name) {
return '$name ist zurück im Spiel';
}
}
+112 -44
View File
@@ -18,19 +18,20 @@ class AppLocalizationsEn extends AppLocalizations {
String get loadingWords => 'Loading words...';
@override
String get matchRewards => "Game rewards";
String get matchRewards => 'Game rewards';
@override
String get newMedals => "New medals";
String get newMedals => 'New medals';
@override
String get noNewMedalsKeepFire => "No new medals this time. Keep building your fire.";
String get noNewMedalsKeepFire =>
'No new medals this time. Keep building your fire.';
@override
String get calculatingRewards => "Calculating rewards...";
String get calculatingRewards => 'Calculating rewards...';
@override
String get fireLabel => "Fire";
String get fireLabel => 'Fire';
@override
String get playersRange => '3-20 players • No internet needed';
@@ -213,16 +214,6 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get playersInDebate => 'Players in discussion';
@override
String voteOf(String name) {
return "Vote from $name";
}
@override
String firstTurnInstruction(String name) {
return "$name starts by saying their word.";
}
@override
String activePlayersInfo(int active, int impostors) {
return '$active active • $impostors hidden impostor(s)';
@@ -507,19 +498,20 @@ class AppLocalizationsEn extends AppLocalizations {
String get connectedPlayers => 'Connected players';
@override
String get hostGame => 'Gestor de partida';
String get hostGame => 'Game manager';
@override
String get waitingPlayersSeeWord => 'Esperando que todos vean su palabra...';
String get waitingPlayersSeeWord =>
'Waiting for everyone to see their word...';
@override
String get activePlayers => 'Jugadores activos';
String get activePlayers => 'Active players';
@override
String get playersVoted => 'Han votado';
String get playersVoted => 'Have voted';
@override
String get waitingVoting => 'Esperando que voten...';
String get waitingVoting => 'Waiting for votes...';
@override
String get waitingForPlayers => 'Waiting for players...';
@@ -576,34 +568,34 @@ class AppLocalizationsEn extends AppLocalizations {
String get orScanQR => 'Not showing up? Scan the host\'s QR code';
@override
String get iveSeenIt => 'Ya la he visto';
String get iveSeenIt => 'I\'ve seen it';
@override
String clueIs(String category) {
return 'La pista es: $category';
return 'The clue is: $category';
}
@override
String get debatePhaseActive => 'Fase de debate activa';
String get debatePhaseActive => 'Debate phase in progress';
@override
String get debateInstructions =>
'Hablad entre vosotros y decid quién creéis que es el impostor. Cuando estéis listos, solicitad la votación.';
'Talk to each other and say who you think the impostor is. When you\'re ready, call for a vote.';
@override
String get solicitarVotacion => 'Solicitar votación';
String get solicitarVotacion => 'Call for a vote';
@override
String get votacionSolicitada => 'Votación solicitada';
String get votacionSolicitada => 'Vote requested';
@override
String get whoDoYouThinkIsTheImpostor => '¿Quién es el impostor?';
String get whoDoYouThinkIsTheImpostor => 'Who is the impostor?';
@override
String get selectOnePlayer => 'Selecciona a un jugador para votar';
String get selectOnePlayer => 'Select a player to vote for';
@override
String get votar => 'Votar';
String get votar => 'Vote';
@override
String get selectYourProfile => 'Your profile';
@@ -624,7 +616,8 @@ class AppLocalizationsEn extends AppLocalizations {
String get availableProfiles => 'Available profiles';
@override
String get scanThisCodeFromAnotherPhone => 'Scan this code from another phone';
String get scanThisCodeFromAnotherPhone =>
'Scan this code from another phone';
@override
String get gameUsers => 'Game users';
@@ -657,34 +650,41 @@ class AppLocalizationsEn extends AppLocalizations {
String get delete => 'Delete';
@override
String get selectAtLeastThreeUsersToStart => 'Select at least 3 users to start.';
String get selectAtLeastThreeUsersToStart =>
'Select at least 3 users to start.';
@override
String get hostPhoneMustSelectUser => 'The host phone must select at least one user.';
String get hostPhoneMustSelectUser =>
'The host phone must select at least one user.';
@override
String get roomNoLongerInLobby => 'The room is no longer in the lobby.';
@override
String get completeUserSelectionToStart => 'Complete user selection to start.';
String get completeUserSelectionToStart =>
'Complete user selection to start.';
@override
String get preparingSecureRoom => 'Preparing the secure room';
@override
String get searchingNearbyBluetoothGames => 'Searching nearby games over Bluetooth';
String get searchingNearbyBluetoothGames =>
'Searching nearby games over Bluetooth';
@override
String get tapToJoin => 'Tap to join';
@override
String get bluetoothLocationPermissionsRequired => 'Bluetooth and location permissions are required to search for games.';
String get bluetoothLocationPermissionsRequired =>
'Bluetooth and location permissions are required to search for games.';
@override
String get bluetoothLocationPermissionsShort => 'Bluetooth and location permissions are required';
String get bluetoothLocationPermissionsShort =>
'Bluetooth and location permissions are required';
@override
String get couldNotStartSearch => 'Could not start the search. Check Bluetooth and location.';
String get couldNotStartSearch =>
'Could not start the search. Check Bluetooth and location.';
@override
String couldNotConnectToHost(String host) {
@@ -698,13 +698,15 @@ class AppLocalizationsEn extends AppLocalizations {
String get singleDeviceSubtitle => 'Game on this device';
@override
String get singleDeviceDescription => 'Ideal for playing together by passing the phone around. Fast, direct setup.';
String get singleDeviceDescription =>
'Ideal for playing together by passing the phone around. Fast, direct setup.';
@override
String get multiDeviceSubtitle => 'Each player on their phone';
@override
String get multiDeviceDescription => 'Create a premium room, share the QR code and manage users from the lobby.';
String get multiDeviceDescription =>
'Create a premium room, share the QR code and manage users from the lobby.';
@override
String get singleDeviceGameLabel => 'Game on this device';
@@ -716,7 +718,8 @@ class AppLocalizationsEn extends AppLocalizations {
String get mainDeviceUser => 'Main device user';
@override
String get couldNotCreateRoom => 'Could not create the room. Check Bluetooth.';
String get couldNotCreateRoom =>
'Could not create the room. Check Bluetooth.';
@override
String cannotStartWithReason(String reason) {
@@ -728,6 +731,7 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get defaultPlayerName => 'Player';
@override
String get play => 'Play';
@@ -759,7 +763,8 @@ class AppLocalizationsEn extends AppLocalizations {
String get errorNoGame => 'Error: no game';
@override
String get disconnectedPlayersWarning => 'Some players have a disconnected device.';
String get disconnectedPlayersWarning =>
'Some players have a disconnected device.';
@override
String get assumeOnThisPhone => 'Take over on this phone';
@@ -768,8 +773,71 @@ class AppLocalizationsEn extends AppLocalizations {
String get noResult => 'No result';
@override
String historyGameSummary(int players, int impostors, int rounds, String word, String category) {
return '$players players • $impostors impostor(s) • $rounds round(s)\n$word$category';
String historyGameSummary(
int players,
int impostors,
int rounds,
String word,
String category,
) {
return '\$players players • \$impostors impostor(s) • \$rounds round(s)\n\$word • \$category';
}
}
@override
String voteOf(String name) {
return 'Vote from $name';
}
@override
String firstTurnInstruction(String name) {
return '$name starts by saying their word.';
}
@override
String get impostorsKnowEachOther => '🎭 Impostors know each other';
@override
String get impostorsKnowEachOtherDescription =>
'Each impostor will see the names of the others';
@override
String get impostorsKnowEachOtherNeedsTwo =>
'Only applies with 2 or more impostors';
@override
String otherImpostorsTitle(num count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: 'The other impostors',
one: 'The other impostor',
);
return '$_temp0';
}
@override
String get youAreTheOnlyImpostor => 'You are the only impostor';
@override
String impostorsAdjusted(int count) {
return 'Impostors adjusted to $count for this number of players';
}
@override
String get eliminatedCannotVote => 'You\'re eliminated — you no longer vote';
@override
String get reconnecting => 'Reconnecting...';
@override
String get reconnectingHint =>
'Lost connection to the host. Your place in the game is being held.';
@override
String get leaveGame => 'Leave the game';
@override
String playerRejoined(String name) {
return '$name has rejoined the game';
}
}
+97 -30
View File
@@ -18,19 +18,20 @@ class AppLocalizationsEs extends AppLocalizations {
String get loadingWords => 'Cargando palabras...';
@override
String get matchRewards => "Recompensas de partida";
String get matchRewards => 'Recompensas de partida';
@override
String get newMedals => "Nuevas medallas";
String get newMedals => 'Nuevas medallas';
@override
String get noNewMedalsKeepFire => "Sin medallas nuevas esta vez. Sigue acumulando fuego.";
String get noNewMedalsKeepFire =>
'Sin medallas nuevas esta vez. Sigue acumulando fuego.';
@override
String get calculatingRewards => "Calculando recompensas...";
String get calculatingRewards => 'Calculando recompensas...';
@override
String get fireLabel => "Fuego";
String get fireLabel => 'Fuego';
@override
String get playersRange => '3-20 jugadores • Sin internet';
@@ -213,16 +214,6 @@ class AppLocalizationsEs extends AppLocalizations {
@override
String get playersInDebate => 'Jugadores en debate';
@override
String voteOf(String name) {
return "Voto de $name";
}
@override
String firstTurnInstruction(String name) {
return "Empieza $name diciendo su palabra.";
}
@override
String activePlayersInfo(int active, int impostors) {
return '$active activos • $impostors impostor(es) ocultos';
@@ -626,7 +617,8 @@ class AppLocalizationsEs extends AppLocalizations {
String get availableProfiles => 'Perfiles disponibles';
@override
String get scanThisCodeFromAnotherPhone => 'Escanea este código desde otro móvil';
String get scanThisCodeFromAnotherPhone =>
'Escanea este código desde otro móvil';
@override
String get gameUsers => 'Usuarios de la partida';
@@ -659,34 +651,41 @@ class AppLocalizationsEs extends AppLocalizations {
String get delete => 'Eliminar';
@override
String get selectAtLeastThreeUsersToStart => 'Selecciona al menos 3 usuarios para iniciar.';
String get selectAtLeastThreeUsersToStart =>
'Selecciona al menos 3 usuarios para iniciar.';
@override
String get hostPhoneMustSelectUser => 'El móvil servidor debe seleccionar al menos un usuario.';
String get hostPhoneMustSelectUser =>
'El móvil servidor debe seleccionar al menos un usuario.';
@override
String get roomNoLongerInLobby => 'La sala ya no está en el lobby.';
@override
String get completeUserSelectionToStart => 'Completa la selección de usuarios para iniciar.';
String get completeUserSelectionToStart =>
'Completa la selección de usuarios para iniciar.';
@override
String get preparingSecureRoom => 'Preparando la sala segura';
@override
String get searchingNearbyBluetoothGames => 'Buscando partidas cercanas por Bluetooth';
String get searchingNearbyBluetoothGames =>
'Buscando partidas cercanas por Bluetooth';
@override
String get tapToJoin => 'Toca para unirte';
@override
String get bluetoothLocationPermissionsRequired => 'Se necesitan permisos de Bluetooth y ubicación para buscar partidas.';
String get bluetoothLocationPermissionsRequired =>
'Se necesitan permisos de Bluetooth y ubicación para buscar partidas.';
@override
String get bluetoothLocationPermissionsShort => 'Se necesitan permisos de Bluetooth y ubicación';
String get bluetoothLocationPermissionsShort =>
'Se necesitan permisos de Bluetooth y ubicación';
@override
String get couldNotStartSearch => 'No se pudo iniciar la búsqueda. Verifica Bluetooth y ubicación.';
String get couldNotStartSearch =>
'No se pudo iniciar la búsqueda. Verifica Bluetooth y ubicación.';
@override
String couldNotConnectToHost(String host) {
@@ -700,13 +699,15 @@ class AppLocalizationsEs extends AppLocalizations {
String get singleDeviceSubtitle => 'Partida en este dispositivo';
@override
String get singleDeviceDescription => 'Ideal para jugar todos juntos pasando el móvil. Configuración rápida y directa.';
String get singleDeviceDescription =>
'Ideal para jugar todos juntos pasando el móvil. Configuración rápida y directa.';
@override
String get multiDeviceSubtitle => 'Cada jugador en su móvil';
@override
String get multiDeviceDescription => 'Crea una sala premium, comparte el QR y gestiona usuarios desde el lobby.';
String get multiDeviceDescription =>
'Crea una sala premium, comparte el QR y gestiona usuarios desde el lobby.';
@override
String get singleDeviceGameLabel => 'Partida en este dispositivo';
@@ -718,7 +719,8 @@ class AppLocalizationsEs extends AppLocalizations {
String get mainDeviceUser => 'Usuario principal del dispositivo';
@override
String get couldNotCreateRoom => 'No se pudo crear la sala. Verifica Bluetooth.';
String get couldNotCreateRoom =>
'No se pudo crear la sala. Verifica Bluetooth.';
@override
String cannotStartWithReason(String reason) {
@@ -730,6 +732,7 @@ class AppLocalizationsEs extends AppLocalizations {
@override
String get defaultPlayerName => 'Jugador';
@override
String get play => 'Jugar';
@@ -761,7 +764,8 @@ class AppLocalizationsEs extends AppLocalizations {
String get errorNoGame => 'Error: sin partida';
@override
String get disconnectedPlayersWarning => 'Hay jugadores con el dispositivo desconectado.';
String get disconnectedPlayersWarning =>
'Hay jugadores con el dispositivo desconectado.';
@override
String get assumeOnThisPhone => 'Asumir en este móvil';
@@ -770,8 +774,71 @@ class AppLocalizationsEs extends AppLocalizations {
String get noResult => 'Sin resultado';
@override
String historyGameSummary(int players, int impostors, int rounds, String word, String category) {
return '$players jugadores • $impostors impostor(es) • $rounds ronda(s)\n$word$category';
String historyGameSummary(
int players,
int impostors,
int rounds,
String word,
String category,
) {
return '\$players jugadores • \$impostors impostor(es) • \$rounds ronda(s)\n\$word • \$category';
}
}
@override
String voteOf(String name) {
return 'Voto de $name';
}
@override
String firstTurnInstruction(String name) {
return 'Empieza $name diciendo su palabra.';
}
@override
String get impostorsKnowEachOther => '🎭 Los impostores se conocen';
@override
String get impostorsKnowEachOtherDescription =>
'Cada impostor verá los nombres del resto';
@override
String get impostorsKnowEachOtherNeedsTwo =>
'Solo se aplica con 2 o más impostores';
@override
String otherImpostorsTitle(num count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: 'Los otros impostores',
one: 'El otro impostor',
);
return '$_temp0';
}
@override
String get youAreTheOnlyImpostor => 'Eres el único impostor';
@override
String impostorsAdjusted(int count) {
return 'Impostores ajustados a $count por el número de jugadores';
}
@override
String get eliminatedCannotVote => 'Estás eliminado: ya no votas';
@override
String get reconnecting => 'Reconectando...';
@override
String get reconnectingHint =>
'Se perdió la conexión con el host. Tu sitio en la partida se mantiene.';
@override
String get leaveGame => 'Salir de la partida';
@override
String playerRejoined(String name) {
return '$name ha vuelto a la partida';
}
}
+140 -70
View File
@@ -18,19 +18,20 @@ class AppLocalizationsEu extends AppLocalizations {
String get loadingWords => 'Hitzak kargatzen...';
@override
String get matchRewards => "Partidako sariak";
String get matchRewards => 'Partidako sariak';
@override
String get newMedals => "Domina berriak";
String get newMedals => 'Domina berriak';
@override
String get noNewMedalsKeepFire => "Oraingoan ez dago domina berririk. Jarraitu sua pilatzen.";
String get noNewMedalsKeepFire =>
'Oraingoan ez dago domina berririk. Jarraitu sua pilatzen.';
@override
String get calculatingRewards => "Sariak kalkulatzen...";
String get calculatingRewards => 'Sariak kalkulatzen...';
@override
String get fireLabel => "Sua";
String get fireLabel => 'Sua';
@override
String get playersRange => '3-20 jokalari • Internetik gabe';
@@ -126,7 +127,7 @@ class AppLocalizationsEu extends AppLocalizations {
String get impostorClueDescription => 'Inpostoreak kategoria ezagutzen du';
@override
String get debate => '🗣️ Debate';
String get debate => '🗣️ Eztabaida';
@override
String get debateTime => '⏱️ Eztabaida-denbora';
@@ -216,16 +217,6 @@ class AppLocalizationsEu extends AppLocalizations {
@override
String get playersInDebate => 'Eztabaidan diren jokalariak';
@override
String voteOf(String name) {
return "$name(r)en botoa";
}
@override
String firstTurnInstruction(String name) {
return "$name hasiko da bere hitza esanez.";
}
@override
String activePlayersInfo(int active, int impostors) {
return '$active aktibo • $impostors inpostore ezkutu';
@@ -505,131 +496,134 @@ class AppLocalizationsEu extends AppLocalizations {
String get licenses => 'Lizentziak';
@override
String get scanToJoin => 'Escanea el QR para unirte';
String get scanToJoin => 'Eskaneatu QR kodea batzeko';
@override
String get connectedPlayers => 'Jugadores conectados';
String get connectedPlayers => 'Konektatutako jokalariak';
@override
String get hostGame => 'Gestor de partida';
String get hostGame => 'Partidaren kudeatzailea';
@override
String get waitingPlayersSeeWord => 'Esperando que todos vean su palabra...';
String get waitingPlayersSeeWord =>
'Denek beren hitza ikusi arte itxaroten...';
@override
String get activePlayers => 'Jugadores activos';
String get activePlayers => 'Jokalari aktiboak';
@override
String get playersVoted => 'Han votado';
String get playersVoted => 'Bozkatu dute';
@override
String get waitingVoting => 'Esperando que voten...';
String get waitingVoting => 'Botoen zain...';
@override
String get waitingForPlayers => 'Esperando jugadores...';
String get waitingForPlayers => 'Jokalarien zain...';
@override
String needMorePlayers(int count) {
return 'Faltan $count jugadores más';
return '$count jokalari gehiago behar dira';
}
@override
String get starting => 'Iniciando...';
String get starting => 'Hasten...';
@override
String get enterNameAndScan => 'Escribe tu nombre y escanea el QR del host';
String get enterNameAndScan =>
'Idatzi zure izena eta eskaneatu ostalariaren QR kodea';
@override
String get yourName => 'Tu nombre';
String get yourName => 'Zure izena';
@override
String get nameRequired => 'Escribe tu nombre';
String get nameRequired => 'Idatzi zure izena';
@override
String get connectingTo => 'Conectando a';
String get connectingTo => 'Konektatzen';
@override
String get scanQR => 'Escanear QR';
String get scanQR => 'Eskaneatu QR kodea';
@override
String get scanHostQR => 'Apunta al QR del host';
String get scanHostQR => 'Apuntatu ostalariaren QR kodera';
@override
String get connectedWaiting => '¡Conectado!';
String get connectedWaiting => 'Konektatuta!';
@override
String get waitingForHost => 'Esperando a que el host inicie la partida...';
String get waitingForHost => 'Ostalariak partida hasi arte itxaroten...';
@override
String get enterNameToSearch =>
'Escribe tu nombre para buscar partidas cercanas';
'Idatzi zure izena inguruko partidak bilatzeko';
@override
String get searchGames => 'Buscar partidas';
String get searchGames => 'Bilatu partidak';
@override
String get searchingGames => 'Buscando partidas cercanas...';
String get searchingGames => 'Inguruko partidak bilatzen...';
@override
String get noGamesFound => 'No se encontraron partidas';
String get noGamesFound => 'Ez da partidarik aurkitu';
@override
String get noGamesFoundHint =>
'Asegúrate de que el host tiene la sala abierta y estáis cerca';
'Ziurtatu ostalariak gela irekita duela eta gertu zaudetela';
@override
String get orScanQR => '¿No aparece? Escanea el QR del host';
String get orScanQR => 'Ez da agertzen? Eskaneatu ostalariaren QR kodea';
@override
String get iveSeenIt => 'Ya la he visto';
String get iveSeenIt => 'Ikusi dut';
@override
String clueIs(String category) {
return 'La pista es: $category';
return 'Arrastoa: $category';
}
@override
String get debatePhaseActive => 'Fase de debate activa';
String get debatePhaseActive => 'Eztabaida fasea martxan';
@override
String get debateInstructions =>
'Hablad entre vosotros y decid quién creéis que es el impostor. Cuando estéis listos, solicitad la votación.';
'Hitz egin elkarrekin eta esan nor uste duzuen dela inpostorea. Prest zaudetenean, eskatu bozketa.';
@override
String get solicitarVotacion => 'Solicitar votación';
String get solicitarVotacion => 'Bozketa eskatu';
@override
String get votacionSolicitada => 'Votación solicitada';
String get votacionSolicitada => 'Bozketa eskatuta';
@override
String get whoDoYouThinkIsTheImpostor => '¿Quién es el impostor?';
String get whoDoYouThinkIsTheImpostor => 'Nor da inpostorea?';
@override
String get selectOnePlayer => 'Selecciona a un jugador para votar';
String get selectOnePlayer => 'Hautatu jokalari bat bozkatzeko';
@override
String get votar => 'Votar';
String get votar => 'Bozkatu';
@override
String get selectYourProfile => 'Tu perfil';
String get selectYourProfile => 'Zure profila';
@override
String get selectProfile => 'Selecciona un perfil';
String get selectProfile => 'Hautatu profil bat';
@override
String get createNewUser => 'Crear nuevo usuario';
String get createNewUser => 'Sortu erabiltzaile berria';
@override
String get userNameRequired => 'El nombre no puede estar vacio';
String get userNameRequired => 'Izena ezin da hutsik egon';
@override
String get profileSelected => 'Perfil seleccionado';
String get profileSelected => 'Profila hautatuta';
@override
String get availableProfiles => 'Perfiles disponibles';
String get availableProfiles => 'Profil erabilgarriak';
@override
String get scanThisCodeFromAnotherPhone => 'Eskaneatu kode hau beste mugikor batetik';
String get scanThisCodeFromAnotherPhone =>
'Eskaneatu kode hau beste mugikor batetik';
@override
String get gameUsers => 'Partidako erabiltzaileak';
@@ -662,34 +656,41 @@ class AppLocalizationsEu extends AppLocalizations {
String get delete => 'Ezabatu';
@override
String get selectAtLeastThreeUsersToStart => 'Select at least 3 users to start.';
String get selectAtLeastThreeUsersToStart =>
'Select at least 3 users to start.';
@override
String get hostPhoneMustSelectUser => 'The host phone must select at least one user.';
String get hostPhoneMustSelectUser =>
'The host phone must select at least one user.';
@override
String get roomNoLongerInLobby => 'The room is no longer in the lobby.';
@override
String get completeUserSelectionToStart => 'Complete user selection to start.';
String get completeUserSelectionToStart =>
'Complete user selection to start.';
@override
String get preparingSecureRoom => 'Preparing the secure room';
@override
String get searchingNearbyBluetoothGames => 'Searching nearby games over Bluetooth';
String get searchingNearbyBluetoothGames =>
'Searching nearby games over Bluetooth';
@override
String get tapToJoin => 'Tap to join';
@override
String get bluetoothLocationPermissionsRequired => 'Bluetooth and location permissions are required to search for games.';
String get bluetoothLocationPermissionsRequired =>
'Bluetooth and location permissions are required to search for games.';
@override
String get bluetoothLocationPermissionsShort => 'Bluetooth and location permissions are required';
String get bluetoothLocationPermissionsShort =>
'Bluetooth and location permissions are required';
@override
String get couldNotStartSearch => 'Could not start the search. Check Bluetooth and location.';
String get couldNotStartSearch =>
'Could not start the search. Check Bluetooth and location.';
@override
String couldNotConnectToHost(String host) {
@@ -703,13 +704,15 @@ class AppLocalizationsEu extends AppLocalizations {
String get singleDeviceSubtitle => 'Game on this device';
@override
String get singleDeviceDescription => 'Ideal for playing together by passing the phone around. Fast, direct setup.';
String get singleDeviceDescription =>
'Ideal for playing together by passing the phone around. Fast, direct setup.';
@override
String get multiDeviceSubtitle => 'Each player on their phone';
@override
String get multiDeviceDescription => 'Create a premium room, share the QR code and manage users from the lobby.';
String get multiDeviceDescription =>
'Create a premium room, share the QR code and manage users from the lobby.';
@override
String get singleDeviceGameLabel => 'Game on this device';
@@ -721,7 +724,8 @@ class AppLocalizationsEu extends AppLocalizations {
String get mainDeviceUser => 'Main device user';
@override
String get couldNotCreateRoom => 'Could not create the room. Check Bluetooth.';
String get couldNotCreateRoom =>
'Could not create the room. Check Bluetooth.';
@override
String cannotStartWithReason(String reason) {
@@ -733,6 +737,7 @@ class AppLocalizationsEu extends AppLocalizations {
@override
String get defaultPlayerName => 'Jokalaria';
@override
String get play => 'Jokatu';
@@ -764,7 +769,8 @@ class AppLocalizationsEu extends AppLocalizations {
String get errorNoGame => 'Errorea: partidarik ez';
@override
String get disconnectedPlayersWarning => 'Jokalari batzuek gailua deskonektatuta dute.';
String get disconnectedPlayersWarning =>
'Jokalari batzuek gailua deskonektatuta dute.';
@override
String get assumeOnThisPhone => 'Hartu mugikor honetan';
@@ -773,8 +779,72 @@ class AppLocalizationsEu extends AppLocalizations {
String get noResult => 'Emaitzarik ez';
@override
String historyGameSummary(int players, int impostors, int rounds, String word, String category) {
return '$players jokalari • $impostors inpostore • $rounds txanda\n$word$category';
String historyGameSummary(
int players,
int impostors,
int rounds,
String word,
String category,
) {
return '\$players jokalari • \$impostors inpostore • \$rounds txanda\n\$word • \$category';
}
}
@override
String voteOf(String name) {
return '$name(r)en botoa';
}
@override
String firstTurnInstruction(String name) {
return '$name hasiko da bere hitza esanez.';
}
@override
String get impostorsKnowEachOther => '🎭 Inpostoreek elkar ezagutzen dute';
@override
String get impostorsKnowEachOtherDescription =>
'Inpostore bakoitzak besteen izenak ikusiko ditu';
@override
String get impostorsKnowEachOtherNeedsTwo =>
'2 inpostore edo gehiagorekin soilik';
@override
String otherImpostorsTitle(num count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: 'Beste inpostoreak',
one: 'Beste inpostorea',
);
return '$_temp0';
}
@override
String get youAreTheOnlyImpostor => 'Zu zara inpostore bakarra';
@override
String impostorsAdjusted(int count) {
return 'Inpostoreak ${count}era doituta jokalari kopuruagatik';
}
@override
String get eliminatedCannotVote =>
'Kanporatuta zaude: ez duzu gehiago bozkatzen';
@override
String get reconnecting => 'Berriz konektatzen...';
@override
String get reconnectingHint =>
'Ostalariarekiko konexioa galdu da. Partidan duzun lekua gordeta dago.';
@override
String get leaveGame => 'Partidatik irten';
@override
String playerRejoined(String name) {
return '$name partidara itzuli da';
}
}
+140 -71
View File
@@ -18,19 +18,20 @@ class AppLocalizationsFr extends AppLocalizations {
String get loadingWords => 'Chargement des mots...';
@override
String get matchRewards => "Récompenses de partie";
String get matchRewards => 'Récompenses de partie';
@override
String get newMedals => "Nouvelles médailles";
String get newMedals => 'Nouvelles médailles';
@override
String get noNewMedalsKeepFire => "Pas de nouvelles médailles cette fois. Continue à entretenir ta flamme.";
String get noNewMedalsKeepFire =>
'Pas de nouvelles médailles cette fois. Continue à entretenir ta flamme.';
@override
String get calculatingRewards => "Calcul des récompenses...";
String get calculatingRewards => 'Calcul des récompenses...';
@override
String get fireLabel => "Flamme";
String get fireLabel => 'Flamme';
@override
String get playersRange => '3-20 joueurs • Sans internet';
@@ -125,7 +126,7 @@ class AppLocalizationsFr extends AppLocalizations {
String get impostorClueDescription => 'L\'imposteur connaît la catégorie';
@override
String get debate => '🗣️ Debate';
String get debate => '🗣️ Débat';
@override
String get debateTime => '⏱️ Temps de débat';
@@ -214,16 +215,6 @@ class AppLocalizationsFr extends AppLocalizations {
@override
String get playersInDebate => 'Joueurs en débat';
@override
String voteOf(String name) {
return "Vote de $name";
}
@override
String firstTurnInstruction(String name) {
return "$name commence en disant son mot.";
}
@override
String activePlayersInfo(int active, int impostors) {
return '$active actifs • $impostors imposteur(s) caché(s)';
@@ -503,131 +494,133 @@ class AppLocalizationsFr extends AppLocalizations {
String get licenses => 'Licences';
@override
String get scanToJoin => 'Escanea el QR para unirte';
String get scanToJoin => 'Scannez le QR code pour rejoindre';
@override
String get connectedPlayers => 'Jugadores conectados';
String get connectedPlayers => 'Joueurs connectés';
@override
String get hostGame => 'Gestor de partida';
String get hostGame => 'Gestion de la partie';
@override
String get waitingPlayersSeeWord => 'Esperando que todos vean su palabra...';
String get waitingPlayersSeeWord => 'En attente que chacun voie son mot...';
@override
String get activePlayers => 'Jugadores activos';
String get activePlayers => 'Joueurs actifs';
@override
String get playersVoted => 'Han votado';
String get playersVoted => 'Ont voté';
@override
String get waitingVoting => 'Esperando que voten...';
String get waitingVoting => 'En attente des votes...';
@override
String get waitingForPlayers => 'Esperando jugadores...';
String get waitingForPlayers => 'En attente de joueurs...';
@override
String needMorePlayers(int count) {
return 'Faltan $count jugadores más';
return 'Il manque encore $count joueurs';
}
@override
String get starting => 'Iniciando...';
String get starting => 'Démarrage...';
@override
String get enterNameAndScan => 'Escribe tu nombre y escanea el QR del host';
String get enterNameAndScan =>
'Saisissez votre nom et scannez le QR code de l\'hôte';
@override
String get yourName => 'Tu nombre';
String get yourName => 'Votre nom';
@override
String get nameRequired => 'Escribe tu nombre';
String get nameRequired => 'Saisissez votre nom';
@override
String get connectingTo => 'Conectando a';
String get connectingTo => 'Connexion à';
@override
String get scanQR => 'Escanear QR';
String get scanQR => 'Scanner le QR code';
@override
String get scanHostQR => 'Apunta al QR del host';
String get scanHostQR => 'Visez le QR code de l\'hôte';
@override
String get connectedWaiting => '¡Conectado!';
String get connectedWaiting => 'Connecté !';
@override
String get waitingForHost => 'Esperando a que el host inicie la partida...';
String get waitingForHost => 'En attente que l\'hôte lance la partie...';
@override
String get enterNameToSearch =>
'Escribe tu nombre para buscar partidas cercanas';
'Saisissez votre nom pour chercher des parties à proximité';
@override
String get searchGames => 'Buscar partidas';
String get searchGames => 'Chercher des parties';
@override
String get searchingGames => 'Buscando partidas cercanas...';
String get searchingGames => 'Recherche de parties à proximité...';
@override
String get noGamesFound => 'No se encontraron partidas';
String get noGamesFound => 'Aucune partie trouvée';
@override
String get noGamesFoundHint =>
'Asegúrate de que el host tiene la sala abierta y estáis cerca';
'Assurez-vous que l\'hôte a ouvert le salon et que vous êtes à proximité';
@override
String get orScanQR => '¿No aparece? Escanea el QR del host';
String get orScanQR => 'Rien n\'apparaît ? Scannez le QR code de l\'hôte';
@override
String get iveSeenIt => 'Ya la he visto';
String get iveSeenIt => 'Je l\'ai vu';
@override
String clueIs(String category) {
return 'La pista es: $category';
return 'L\'indice est : $category';
}
@override
String get debatePhaseActive => 'Fase de debate activa';
String get debatePhaseActive => 'Phase de débat en cours';
@override
String get debateInstructions =>
'Hablad entre vosotros y decid quién creéis que es el impostor. Cuando estéis listos, solicitad la votación.';
'Discutez entre vous et dites qui vous pensez être l\'imposteur. Quand vous êtes prêts, demandez le vote.';
@override
String get solicitarVotacion => 'Solicitar votación';
String get solicitarVotacion => 'Demander le vote';
@override
String get votacionSolicitada => 'Votación solicitada';
String get votacionSolicitada => 'Vote demandé';
@override
String get whoDoYouThinkIsTheImpostor => '¿Quién es el impostor?';
String get whoDoYouThinkIsTheImpostor => 'Qui est l\'imposteur ?';
@override
String get selectOnePlayer => 'Selecciona a un jugador para votar';
String get selectOnePlayer => 'Sélectionnez un joueur pour voter';
@override
String get votar => 'Votar';
String get votar => 'Voter';
@override
String get selectYourProfile => 'Tu perfil';
String get selectYourProfile => 'Votre profil';
@override
String get selectProfile => 'Selecciona un perfil';
String get selectProfile => 'Sélectionnez un profil';
@override
String get createNewUser => 'Crear nuevo usuario';
String get createNewUser => 'Créer un nouvel utilisateur';
@override
String get userNameRequired => 'El nombre no puede estar vacio';
String get userNameRequired => 'Le nom ne peut pas être vide';
@override
String get profileSelected => 'Perfil seleccionado';
String get profileSelected => 'Profil sélection';
@override
String get availableProfiles => 'Perfiles disponibles';
String get availableProfiles => 'Profils disponibles';
@override
String get scanThisCodeFromAnotherPhone => 'Scanne ce code depuis un autre mobile';
String get scanThisCodeFromAnotherPhone =>
'Scanne ce code depuis un autre mobile';
@override
String get gameUsers => 'Utilisateurs de la partie';
@@ -660,34 +653,41 @@ class AppLocalizationsFr extends AppLocalizations {
String get delete => 'Supprimer';
@override
String get selectAtLeastThreeUsersToStart => 'Sélectionne au moins 3 utilisateurs pour commencer.';
String get selectAtLeastThreeUsersToStart =>
'Sélectionne au moins 3 utilisateurs pour commencer.';
@override
String get hostPhoneMustSelectUser => 'Le mobile hôte doit sélectionner au moins un utilisateur.';
String get hostPhoneMustSelectUser =>
'Le mobile hôte doit sélectionner au moins un utilisateur.';
@override
String get roomNoLongerInLobby => 'Le salon nest plus dans le lobby.';
@override
String get completeUserSelectionToStart => 'Termine la sélection des utilisateurs pour commencer.';
String get completeUserSelectionToStart =>
'Termine la sélection des utilisateurs pour commencer.';
@override
String get preparingSecureRoom => 'Préparation du salon sécurisé';
@override
String get searchingNearbyBluetoothGames => 'Recherche de parties proches par Bluetooth';
String get searchingNearbyBluetoothGames =>
'Recherche de parties proches par Bluetooth';
@override
String get tapToJoin => 'Touche pour rejoindre';
@override
String get bluetoothLocationPermissionsRequired => 'Les autorisations Bluetooth et localisation sont nécessaires pour rechercher des parties.';
String get bluetoothLocationPermissionsRequired =>
'Les autorisations Bluetooth et localisation sont nécessaires pour rechercher des parties.';
@override
String get bluetoothLocationPermissionsShort => 'Autorisations Bluetooth et localisation nécessaires';
String get bluetoothLocationPermissionsShort =>
'Autorisations Bluetooth et localisation nécessaires';
@override
String get couldNotStartSearch => 'Impossible de lancer la recherche. Vérifie le Bluetooth et la localisation.';
String get couldNotStartSearch =>
'Impossible de lancer la recherche. Vérifie le Bluetooth et la localisation.';
@override
String couldNotConnectToHost(String host) {
@@ -701,13 +701,15 @@ class AppLocalizationsFr extends AppLocalizations {
String get singleDeviceSubtitle => 'Partie sur cet appareil';
@override
String get singleDeviceDescription => 'Idéal pour jouer ensemble en se passant le mobile. Configuration rapide et directe.';
String get singleDeviceDescription =>
'Idéal pour jouer ensemble en se passant le mobile. Configuration rapide et directe.';
@override
String get multiDeviceSubtitle => 'Chaque joueur sur son mobile';
@override
String get multiDeviceDescription => 'Crée un salon premium, partage le QR et gère les utilisateurs depuis le lobby.';
String get multiDeviceDescription =>
'Crée un salon premium, partage le QR et gère les utilisateurs depuis le lobby.';
@override
String get singleDeviceGameLabel => 'Partie sur cet appareil';
@@ -719,7 +721,8 @@ class AppLocalizationsFr extends AppLocalizations {
String get mainDeviceUser => 'Utilisateur principal de lappareil';
@override
String get couldNotCreateRoom => 'Impossible de créer le salon. Vérifie le Bluetooth.';
String get couldNotCreateRoom =>
'Impossible de créer le salon. Vérifie le Bluetooth.';
@override
String cannotStartWithReason(String reason) {
@@ -731,6 +734,7 @@ class AppLocalizationsFr extends AppLocalizations {
@override
String get defaultPlayerName => 'Joueur';
@override
String get play => 'Jouer';
@@ -738,7 +742,8 @@ class AppLocalizationsFr extends AppLocalizations {
String get history => 'Historique';
@override
String get mainTagline => 'Découvre limposteur avant quil ne soit trop tard';
String get mainTagline =>
'Découvre limposteur avant quil ne soit trop tard';
@override
String get deviceProfile => 'Profil de lappareil';
@@ -762,7 +767,8 @@ class AppLocalizationsFr extends AppLocalizations {
String get errorNoGame => 'Erreur : aucune partie';
@override
String get disconnectedPlayersWarning => 'Des joueurs ont un appareil déconnecté.';
String get disconnectedPlayersWarning =>
'Des joueurs ont un appareil déconnecté.';
@override
String get assumeOnThisPhone => 'Reprendre sur ce mobile';
@@ -771,8 +777,71 @@ class AppLocalizationsFr extends AppLocalizations {
String get noResult => 'Aucun résultat';
@override
String historyGameSummary(int players, int impostors, int rounds, String word, String category) {
return '$players joueurs • $impostors imposteur(s) • $rounds manche(s)\n$word$category';
String historyGameSummary(
int players,
int impostors,
int rounds,
String word,
String category,
) {
return '\$players joueurs • \$impostors imposteur(s) • \$rounds manche(s)\n\$word • \$category';
}
}
@override
String voteOf(String name) {
return 'Vote de $name';
}
@override
String firstTurnInstruction(String name) {
return '$name commence en disant son mot.';
}
@override
String get impostorsKnowEachOther => '🎭 Les imposteurs se connaissent';
@override
String get impostorsKnowEachOtherDescription =>
'Chaque imposteur verra les noms des autres';
@override
String get impostorsKnowEachOtherNeedsTwo =>
'S\'applique uniquement à partir de 2 imposteurs';
@override
String otherImpostorsTitle(num count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: 'Les autres imposteurs',
one: 'L\'autre imposteur',
);
return '$_temp0';
}
@override
String get youAreTheOnlyImpostor => 'Vous êtes le seul imposteur';
@override
String impostorsAdjusted(int count) {
return 'Imposteurs ajustés à $count selon le nombre de joueurs';
}
@override
String get eliminatedCannotVote => 'Vous êtes éliminé : vous ne votez plus';
@override
String get reconnecting => 'Reconnexion...';
@override
String get reconnectingHint =>
'Connexion à l\'hôte perdue. Votre place dans la partie est conservée.';
@override
String get leaveGame => 'Quitter la partie';
@override
String playerRejoined(String name) {
return '$name a rejoint la partie';
}
}
+137 -71
View File
@@ -18,19 +18,20 @@ class AppLocalizationsHi extends AppLocalizations {
String get loadingWords => 'शब्द लोड हो रहे हैं...';
@override
String get matchRewards => "गेम पुरस्कार";
String get matchRewards => 'गेम पुरस्कार';
@override
String get newMedals => "नई पदक";
String get newMedals => 'नई पदक';
@override
String get noNewMedalsKeepFire => "इस बार कोई नया पदक नहीं। अपनी आग बढ़ाते रहें।";
String get noNewMedalsKeepFire =>
'इस बार कोई नया पदक नहीं। अपनी आग बढ़ाते रहें।';
@override
String get calculatingRewards => "पुरस्कार गिने जा रहे हैं...";
String get calculatingRewards => 'पुरस्कार गिने जा रहे हैं...';
@override
String get fireLabel => "आग";
String get fireLabel => 'आग';
@override
String get playersRange => '3-20 खिलाड़ी • इंटरनेट की ज़रूरत नहीं';
@@ -125,7 +126,7 @@ class AppLocalizationsHi extends AppLocalizations {
String get impostorClueDescription => 'धोखेबाज़ को श्रेणी पता होगी';
@override
String get debate => '🗣️ Debate';
String get debate => '🗣️ बहस';
@override
String get debateTime => '⏱️ बहस का समय';
@@ -213,16 +214,6 @@ class AppLocalizationsHi extends AppLocalizations {
@override
String get playersInDebate => 'बहस में खिलाड़ी';
@override
String voteOf(String name) {
return "$name का वोट";
}
@override
String firstTurnInstruction(String name) {
return "$name अपनी शब्द बोलकर शुरू करता है।";
}
@override
String activePlayersInfo(int active, int impostors) {
return '$active सक्रिय • $impostors धोखेबाज़ छिपे हुए';
@@ -502,131 +493,131 @@ class AppLocalizationsHi extends AppLocalizations {
String get licenses => 'लाइसेंस';
@override
String get scanToJoin => 'Escanea el QR para unirte';
String get scanToJoin => 'शामिल होने के लिए QR स्कैन करें';
@override
String get connectedPlayers => 'Jugadores conectados';
String get connectedPlayers => 'जुड़े हुए खिलाड़ी';
@override
String get hostGame => 'Gestor de partida';
String get hostGame => 'गेम प्रबंधक';
@override
String get waitingPlayersSeeWord => 'Esperando que todos vean su palabra...';
String get waitingPlayersSeeWord => 'सभी के अपना शब्द देखने की प्रतीक्षा...';
@override
String get activePlayers => 'Jugadores activos';
String get activePlayers => 'सक्रिय खिलाड़ी';
@override
String get playersVoted => 'Han votado';
String get playersVoted => 'मतदान कर चुके';
@override
String get waitingVoting => 'Esperando que voten...';
String get waitingVoting => 'वोटों की प्रतीक्षा...';
@override
String get waitingForPlayers => 'Esperando jugadores...';
String get waitingForPlayers => 'खिलाड़ियों की प्रतीक्षा...';
@override
String needMorePlayers(int count) {
return 'Faltan $count jugadores más';
return '$count और खिलाड़ी चाहिए';
}
@override
String get starting => 'Iniciando...';
String get starting => 'शुरू हो रहा है...';
@override
String get enterNameAndScan => 'Escribe tu nombre y escanea el QR del host';
String get enterNameAndScan => 'अपना नाम लिखें और होस्ट का QR स्कैन करें';
@override
String get yourName => 'Tu nombre';
String get yourName => 'आपका नाम';
@override
String get nameRequired => 'Escribe tu nombre';
String get nameRequired => 'अपना नाम लिखें';
@override
String get connectingTo => 'Conectando a';
String get connectingTo => 'कनेक्ट हो रहा है';
@override
String get scanQR => 'Escanear QR';
String get scanQR => 'QR स्कैन करें';
@override
String get scanHostQR => 'Apunta al QR del host';
String get scanHostQR => 'होस्ट के QR पर कैमरा रखें';
@override
String get connectedWaiting => '¡Conectado!';
String get connectedWaiting => 'कनेक्ट हो गया!';
@override
String get waitingForHost => 'Esperando a que el host inicie la partida...';
String get waitingForHost => 'होस्ट के खेल शुरू करने की प्रतीक्षा...';
@override
String get enterNameToSearch =>
'Escribe tu nombre para buscar partidas cercanas';
String get enterNameToSearch => 'आस-पास के गेम खोजने के लिए अपना नाम लिखें';
@override
String get searchGames => 'Buscar partidas';
String get searchGames => 'गेम खोजें';
@override
String get searchingGames => 'Buscando partidas cercanas...';
String get searchingGames => 'आस-पास के गेम खोजे जा रहे हैं...';
@override
String get noGamesFound => 'No se encontraron partidas';
String get noGamesFound => 'कोई गेम नहीं मिला';
@override
String get noGamesFoundHint =>
'Asegúrate de que el host tiene la sala abierta y estáis cerca';
'सुनिश्चित करें कि होस्ट का कमरा खुला है और आप पास हैं';
@override
String get orScanQR => '¿No aparece? Escanea el QR del host';
String get orScanQR => 'दिख नहीं रहा? होस्ट का QR स्कैन करें';
@override
String get iveSeenIt => 'Ya la he visto';
String get iveSeenIt => 'मैंने देख लिया';
@override
String clueIs(String category) {
return 'La pista es: $category';
return 'संकेत: $category';
}
@override
String get debatePhaseActive => 'Fase de debate activa';
String get debatePhaseActive => 'बहस का चरण जारी है';
@override
String get debateInstructions =>
'Hablad entre vosotros y decid quién creéis que es el impostor. Cuando estéis listos, solicitad la votación.';
'आपस में बात करें और बताएं कि आपको कौन धोखेबाज़ लगता है। तैयार होने पर मतदान का अनुरोध करें।';
@override
String get solicitarVotacion => 'Solicitar votación';
String get solicitarVotacion => 'मतदान का अनुरोध करें';
@override
String get votacionSolicitada => 'Votación solicitada';
String get votacionSolicitada => 'मतदान का अनुरोध भेजा गया';
@override
String get whoDoYouThinkIsTheImpostor => '¿Quién es el impostor?';
String get whoDoYouThinkIsTheImpostor => 'धोखेबाज़ कौन है?';
@override
String get selectOnePlayer => 'Selecciona a un jugador para votar';
String get selectOnePlayer => 'वोट देने के लिए एक खिलाड़ी चुनें';
@override
String get votar => 'Votar';
String get votar => 'वोट दें';
@override
String get selectYourProfile => 'Tu perfil';
String get selectYourProfile => 'आपकी प्रोफ़ाइल';
@override
String get selectProfile => 'Selecciona un perfil';
String get selectProfile => 'एक प्रोफ़ाइल चुनें';
@override
String get createNewUser => 'Crear nuevo usuario';
String get createNewUser => 'नया उपयोगकर्ता बनाएं';
@override
String get userNameRequired => 'El nombre no puede estar vacio';
String get userNameRequired => 'नाम खाली नहीं हो सकता';
@override
String get profileSelected => 'Perfil seleccionado';
String get profileSelected => 'प्रोफ़ाइल चुनी गई';
@override
String get availableProfiles => 'Perfiles disponibles';
String get availableProfiles => 'उपलब्ध प्रोफ़ाइल';
@override
String get scanThisCodeFromAnotherPhone => 'इस कोड को दूसरे फ़ोन से स्कैन करें';
String get scanThisCodeFromAnotherPhone =>
'इस कोड को दूसरे फ़ोन से स्कैन करें';
@override
String get gameUsers => 'गेम उपयोगकर्ता';
@@ -659,34 +650,41 @@ class AppLocalizationsHi extends AppLocalizations {
String get delete => 'हटाएँ';
@override
String get selectAtLeastThreeUsersToStart => 'Select at least 3 users to start.';
String get selectAtLeastThreeUsersToStart =>
'Select at least 3 users to start.';
@override
String get hostPhoneMustSelectUser => 'The host phone must select at least one user.';
String get hostPhoneMustSelectUser =>
'The host phone must select at least one user.';
@override
String get roomNoLongerInLobby => 'The room is no longer in the lobby.';
@override
String get completeUserSelectionToStart => 'Complete user selection to start.';
String get completeUserSelectionToStart =>
'Complete user selection to start.';
@override
String get preparingSecureRoom => 'Preparing the secure room';
@override
String get searchingNearbyBluetoothGames => 'Searching nearby games over Bluetooth';
String get searchingNearbyBluetoothGames =>
'Searching nearby games over Bluetooth';
@override
String get tapToJoin => 'Tap to join';
@override
String get bluetoothLocationPermissionsRequired => 'Bluetooth and location permissions are required to search for games.';
String get bluetoothLocationPermissionsRequired =>
'Bluetooth and location permissions are required to search for games.';
@override
String get bluetoothLocationPermissionsShort => 'Bluetooth and location permissions are required';
String get bluetoothLocationPermissionsShort =>
'Bluetooth and location permissions are required';
@override
String get couldNotStartSearch => 'Could not start the search. Check Bluetooth and location.';
String get couldNotStartSearch =>
'Could not start the search. Check Bluetooth and location.';
@override
String couldNotConnectToHost(String host) {
@@ -700,13 +698,15 @@ class AppLocalizationsHi extends AppLocalizations {
String get singleDeviceSubtitle => 'Game on this device';
@override
String get singleDeviceDescription => 'Ideal for playing together by passing the phone around. Fast, direct setup.';
String get singleDeviceDescription =>
'Ideal for playing together by passing the phone around. Fast, direct setup.';
@override
String get multiDeviceSubtitle => 'Each player on their phone';
@override
String get multiDeviceDescription => 'Create a premium room, share the QR code and manage users from the lobby.';
String get multiDeviceDescription =>
'Create a premium room, share the QR code and manage users from the lobby.';
@override
String get singleDeviceGameLabel => 'Game on this device';
@@ -718,7 +718,8 @@ class AppLocalizationsHi extends AppLocalizations {
String get mainDeviceUser => 'Main device user';
@override
String get couldNotCreateRoom => 'Could not create the room. Check Bluetooth.';
String get couldNotCreateRoom =>
'Could not create the room. Check Bluetooth.';
@override
String cannotStartWithReason(String reason) {
@@ -730,6 +731,7 @@ class AppLocalizationsHi extends AppLocalizations {
@override
String get defaultPlayerName => 'खिलाड़ी';
@override
String get play => 'खेलें';
@@ -761,7 +763,8 @@ class AppLocalizationsHi extends AppLocalizations {
String get errorNoGame => 'त्रुटि: कोई गेम नहीं';
@override
String get disconnectedPlayersWarning => 'कुछ खिलाड़ियों का डिवाइस डिसकनेक्ट है।';
String get disconnectedPlayersWarning =>
'कुछ खिलाड़ियों का डिवाइस डिसकनेक्ट है।';
@override
String get assumeOnThisPhone => 'इस फ़ोन पर संभालें';
@@ -770,8 +773,71 @@ class AppLocalizationsHi extends AppLocalizations {
String get noResult => 'कोई परिणाम नहीं';
@override
String historyGameSummary(int players, int impostors, int rounds, String word, String category) {
return '$players खिलाड़ी • $impostors इम्पोस्टर • $rounds राउंड\n$word$category';
String historyGameSummary(
int players,
int impostors,
int rounds,
String word,
String category,
) {
return '\$players खिलाड़ी • \$impostors इम्पोस्टर • \$rounds राउंड\n\$word • \$category';
}
}
@override
String voteOf(String name) {
return '$name का वोट';
}
@override
String firstTurnInstruction(String name) {
return '$name अपनी शब्द बोलकर शुरू करता है।';
}
@override
String get impostorsKnowEachOther => '🎭 धोखेबाज़ एक-दूसरे को जानते हैं';
@override
String get impostorsKnowEachOtherDescription =>
'हर धोखेबाज़ को बाकी के नाम दिखेंगे';
@override
String get impostorsKnowEachOtherNeedsTwo =>
'केवल 2 या अधिक धोखेबाज़ों पर लागू';
@override
String otherImpostorsTitle(num count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: 'अन्य धोखेबाज़',
one: 'दूसरा धोखेबाज़',
);
return '$_temp0';
}
@override
String get youAreTheOnlyImpostor => 'आप अकेले धोखेबाज़ हैं';
@override
String impostorsAdjusted(int count) {
return 'खिलाड़ियों की संख्या के अनुसार धोखेबाज़ $count कर दिए गए';
}
@override
String get eliminatedCannotVote => 'आप बाहर हो चुके हैं: अब आप वोट नहीं देते';
@override
String get reconnecting => 'फिर से कनेक्ट हो रहा है...';
@override
String get reconnectingHint =>
'होस्ट से कनेक्शन टूट गया। खेल में आपकी जगह सुरक्षित है।';
@override
String get leaveGame => 'खेल छोड़ें';
@override
String playerRejoined(String name) {
return '$name खेल में वापस आ गए';
}
}
+139 -70
View File
@@ -18,19 +18,20 @@ class AppLocalizationsIt extends AppLocalizations {
String get loadingWords => 'Caricamento parole...';
@override
String get matchRewards => "Ricompense partita";
String get matchRewards => 'Ricompense partita';
@override
String get newMedals => "Nuove medaglie";
String get newMedals => 'Nuove medaglie';
@override
String get noNewMedalsKeepFire => "Nessuna nuova medaglia questa volta. Continua ad alimentare il fuoco.";
String get noNewMedalsKeepFire =>
'Nessuna nuova medaglia questa volta. Continua ad alimentare il fuoco.';
@override
String get calculatingRewards => "Calcolo ricompense...";
String get calculatingRewards => 'Calcolo ricompense...';
@override
String get fireLabel => "Fuoco";
String get fireLabel => 'Fuoco';
@override
String get playersRange => '3-20 giocatori • Senza internet';
@@ -125,7 +126,7 @@ class AppLocalizationsIt extends AppLocalizations {
String get impostorClueDescription => 'L\'impostore conosce la categoria';
@override
String get debate => '🗣️ Debate';
String get debate => '🗣️ Dibattito';
@override
String get debateTime => '⏱️ Tempo di discussione';
@@ -214,16 +215,6 @@ class AppLocalizationsIt extends AppLocalizations {
@override
String get playersInDebate => 'Giocatori in discussione';
@override
String voteOf(String name) {
return "Voto di $name";
}
@override
String firstTurnInstruction(String name) {
return "$name inizia dicendo la sua parola.";
}
@override
String activePlayersInfo(int active, int impostors) {
return '$active attivi • $impostors impostore/i nascosti';
@@ -503,131 +494,134 @@ class AppLocalizationsIt extends AppLocalizations {
String get licenses => 'Licenze';
@override
String get scanToJoin => 'Escanea el QR para unirte';
String get scanToJoin => 'Scansiona il QR per unirti';
@override
String get connectedPlayers => 'Jugadores conectados';
String get connectedPlayers => 'Giocatori connessi';
@override
String get hostGame => 'Gestor de partida';
String get hostGame => 'Gestione partita';
@override
String get waitingPlayersSeeWord => 'Esperando que todos vean su palabra...';
String get waitingPlayersSeeWord =>
'In attesa che tutti vedano la propria parola...';
@override
String get activePlayers => 'Jugadores activos';
String get activePlayers => 'Giocatori attivi';
@override
String get playersVoted => 'Han votado';
String get playersVoted => 'Hanno votato';
@override
String get waitingVoting => 'Esperando que voten...';
String get waitingVoting => 'In attesa dei voti...';
@override
String get waitingForPlayers => 'Esperando jugadores...';
String get waitingForPlayers => 'In attesa di giocatori...';
@override
String needMorePlayers(int count) {
return 'Faltan $count jugadores más';
return 'Mancano ancora $count giocatori';
}
@override
String get starting => 'Iniciando...';
String get starting => 'Avvio...';
@override
String get enterNameAndScan => 'Escribe tu nombre y escanea el QR del host';
String get enterNameAndScan =>
'Scrivi il tuo nome e scansiona il QR dell\'host';
@override
String get yourName => 'Tu nombre';
String get yourName => 'Il tuo nome';
@override
String get nameRequired => 'Escribe tu nombre';
String get nameRequired => 'Scrivi il tuo nome';
@override
String get connectingTo => 'Conectando a';
String get connectingTo => 'Connessione a';
@override
String get scanQR => 'Escanear QR';
String get scanQR => 'Scansiona QR';
@override
String get scanHostQR => 'Apunta al QR del host';
String get scanHostQR => 'Inquadra il QR dell\'host';
@override
String get connectedWaiting => '¡Conectado!';
String get connectedWaiting => 'Connesso!';
@override
String get waitingForHost => 'Esperando a que el host inicie la partida...';
String get waitingForHost => 'In attesa che l\'host avvii la partita...';
@override
String get enterNameToSearch =>
'Escribe tu nombre para buscar partidas cercanas';
'Scrivi il tuo nome per cercare partite vicine';
@override
String get searchGames => 'Buscar partidas';
String get searchGames => 'Cerca partite';
@override
String get searchingGames => 'Buscando partidas cercanas...';
String get searchingGames => 'Ricerca di partite vicine...';
@override
String get noGamesFound => 'No se encontraron partidas';
String get noGamesFound => 'Nessuna partita trovata';
@override
String get noGamesFoundHint =>
'Asegúrate de que el host tiene la sala abierta y estáis cerca';
'Assicurati che l\'host abbia la stanza aperta e che siate vicini';
@override
String get orScanQR => '¿No aparece? Escanea el QR del host';
String get orScanQR => 'Non compare? Scansiona il QR dell\'host';
@override
String get iveSeenIt => 'Ya la he visto';
String get iveSeenIt => 'L\'ho vista';
@override
String clueIs(String category) {
return 'La pista es: $category';
return 'L\'indizio è: $category';
}
@override
String get debatePhaseActive => 'Fase de debate activa';
String get debatePhaseActive => 'Fase di dibattito in corso';
@override
String get debateInstructions =>
'Hablad entre vosotros y decid quién creéis que es el impostor. Cuando estéis listos, solicitad la votación.';
'Parlate tra voi e dite chi pensate sia l\'impostore. Quando siete pronti, chiedete la votazione.';
@override
String get solicitarVotacion => 'Solicitar votación';
String get solicitarVotacion => 'Chiedi la votazione';
@override
String get votacionSolicitada => 'Votación solicitada';
String get votacionSolicitada => 'Votazione richiesta';
@override
String get whoDoYouThinkIsTheImpostor => '¿Quién es el impostor?';
String get whoDoYouThinkIsTheImpostor => 'Chi è l\'impostore?';
@override
String get selectOnePlayer => 'Selecciona a un jugador para votar';
String get selectOnePlayer => 'Seleziona un giocatore per votare';
@override
String get votar => 'Votar';
String get votar => 'Vota';
@override
String get selectYourProfile => 'Tu perfil';
String get selectYourProfile => 'Il tuo profilo';
@override
String get selectProfile => 'Selecciona un perfil';
String get selectProfile => 'Seleziona un profilo';
@override
String get createNewUser => 'Crear nuevo usuario';
String get createNewUser => 'Crea nuovo utente';
@override
String get userNameRequired => 'El nombre no puede estar vacio';
String get userNameRequired => 'Il nome non può essere vuoto';
@override
String get profileSelected => 'Perfil seleccionado';
String get profileSelected => 'Profilo selezionato';
@override
String get availableProfiles => 'Perfiles disponibles';
String get availableProfiles => 'Profili disponibili';
@override
String get scanThisCodeFromAnotherPhone => 'Scansiona questo codice da un altro telefono';
String get scanThisCodeFromAnotherPhone =>
'Scansiona questo codice da un altro telefono';
@override
String get gameUsers => 'Utenti della partita';
@@ -660,34 +654,41 @@ class AppLocalizationsIt extends AppLocalizations {
String get delete => 'Elimina';
@override
String get selectAtLeastThreeUsersToStart => 'Seleziona almeno 3 utenti per iniziare.';
String get selectAtLeastThreeUsersToStart =>
'Seleziona almeno 3 utenti per iniziare.';
@override
String get hostPhoneMustSelectUser => 'Il telefono host deve selezionare almeno un utente.';
String get hostPhoneMustSelectUser =>
'Il telefono host deve selezionare almeno un utente.';
@override
String get roomNoLongerInLobby => 'La stanza non è più nella lobby.';
@override
String get completeUserSelectionToStart => 'Completa la selezione utenti per iniziare.';
String get completeUserSelectionToStart =>
'Completa la selezione utenti per iniziare.';
@override
String get preparingSecureRoom => 'Preparazione della stanza sicura';
@override
String get searchingNearbyBluetoothGames => 'Ricerca di partite vicine via Bluetooth';
String get searchingNearbyBluetoothGames =>
'Ricerca di partite vicine via Bluetooth';
@override
String get tapToJoin => 'Tocca per unirti';
@override
String get bluetoothLocationPermissionsRequired => 'Sono necessari i permessi Bluetooth e posizione per cercare partite.';
String get bluetoothLocationPermissionsRequired =>
'Sono necessari i permessi Bluetooth e posizione per cercare partite.';
@override
String get bluetoothLocationPermissionsShort => 'Sono necessari i permessi Bluetooth e posizione';
String get bluetoothLocationPermissionsShort =>
'Sono necessari i permessi Bluetooth e posizione';
@override
String get couldNotStartSearch => 'Impossibile avviare la ricerca. Verifica Bluetooth e posizione.';
String get couldNotStartSearch =>
'Impossibile avviare la ricerca. Verifica Bluetooth e posizione.';
@override
String couldNotConnectToHost(String host) {
@@ -701,13 +702,15 @@ class AppLocalizationsIt extends AppLocalizations {
String get singleDeviceSubtitle => 'Partita su questo dispositivo';
@override
String get singleDeviceDescription => 'Ideale per giocare insieme passandosi il telefono. Configurazione rapida e diretta.';
String get singleDeviceDescription =>
'Ideale per giocare insieme passandosi il telefono. Configurazione rapida e diretta.';
@override
String get multiDeviceSubtitle => 'Ogni giocatore sul proprio telefono';
@override
String get multiDeviceDescription => 'Crea una stanza premium, condividi il QR e gestisci gli utenti dalla lobby.';
String get multiDeviceDescription =>
'Crea una stanza premium, condividi il QR e gestisci gli utenti dalla lobby.';
@override
String get singleDeviceGameLabel => 'Partita su questo dispositivo';
@@ -719,7 +722,8 @@ class AppLocalizationsIt extends AppLocalizations {
String get mainDeviceUser => 'Utente principale del dispositivo';
@override
String get couldNotCreateRoom => 'Impossibile creare la stanza. Verifica Bluetooth.';
String get couldNotCreateRoom =>
'Impossibile creare la stanza. Verifica Bluetooth.';
@override
String cannotStartWithReason(String reason) {
@@ -731,6 +735,7 @@ class AppLocalizationsIt extends AppLocalizations {
@override
String get defaultPlayerName => 'Giocatore';
@override
String get play => 'Gioca';
@@ -762,7 +767,8 @@ class AppLocalizationsIt extends AppLocalizations {
String get errorNoGame => 'Errore: nessuna partita';
@override
String get disconnectedPlayersWarning => 'Alcuni giocatori hanno il dispositivo disconnesso.';
String get disconnectedPlayersWarning =>
'Alcuni giocatori hanno il dispositivo disconnesso.';
@override
String get assumeOnThisPhone => 'Assumi su questo telefono';
@@ -771,8 +777,71 @@ class AppLocalizationsIt extends AppLocalizations {
String get noResult => 'Nessun risultato';
@override
String historyGameSummary(int players, int impostors, int rounds, String word, String category) {
return '$players giocatori • $impostors impostore/i • $rounds round\n$word$category';
String historyGameSummary(
int players,
int impostors,
int rounds,
String word,
String category,
) {
return '\$players giocatori • \$impostors impostore/i • \$rounds round\n\$word • \$category';
}
}
@override
String voteOf(String name) {
return 'Voto di $name';
}
@override
String firstTurnInstruction(String name) {
return '$name inizia dicendo la sua parola.';
}
@override
String get impostorsKnowEachOther => '🎭 Gli impostori si conoscono';
@override
String get impostorsKnowEachOtherDescription =>
'Ogni impostore vedrà i nomi degli altri';
@override
String get impostorsKnowEachOtherNeedsTwo =>
'Si applica solo con 2 o più impostori';
@override
String otherImpostorsTitle(num count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: 'Gli altri impostori',
one: 'L\'altro impostore',
);
return '$_temp0';
}
@override
String get youAreTheOnlyImpostor => 'Sei l\'unico impostore';
@override
String impostorsAdjusted(int count) {
return 'Impostori regolati a $count in base al numero di giocatori';
}
@override
String get eliminatedCannotVote => 'Sei eliminato: non voti più';
@override
String get reconnecting => 'Riconnessione...';
@override
String get reconnectingHint =>
'Connessione con l\'host persa. Il tuo posto nella partita resta riservato.';
@override
String get leaveGame => 'Esci dalla partita';
@override
String playerRejoined(String name) {
return '$name è tornato in partita';
}
}
+129 -70
View File
@@ -18,19 +18,19 @@ class AppLocalizationsJa extends AppLocalizations {
String get loadingWords => 'ワードを読み込み中...';
@override
String get matchRewards => "ゲーム報酬";
String get matchRewards => 'ゲーム報酬';
@override
String get newMedals => "新しいメダル";
String get newMedals => '新しいメダル';
@override
String get noNewMedalsKeepFire => "今回は新しいメダルはありません。炎を積み上げ続けましょう。";
String get noNewMedalsKeepFire => '今回は新しいメダルはありません。炎を積み上げ続けましょう。';
@override
String get calculatingRewards => "報酬を計算中...";
String get calculatingRewards => '報酬を計算中...';
@override
String get fireLabel => "";
String get fireLabel => '';
@override
String get playersRange => '3-20人 • インターネット不要';
@@ -125,7 +125,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get impostorClueDescription => 'インポスターにカテゴリーが表示されます';
@override
String get debate => '🗣️ Debate';
String get debate => '🗣️ 議論';
@override
String get debateTime => '⏱️ 議論の時間';
@@ -213,16 +213,6 @@ class AppLocalizationsJa extends AppLocalizations {
@override
String get playersInDebate => '議論中のプレイヤー';
@override
String voteOf(String name) {
return "$name の投票";
}
@override
String firstTurnInstruction(String name) {
return "$name が自分のワードを言って始めます。";
}
@override
String activePlayersInfo(int active, int impostors) {
return '$active 人参加中 • $impostors 人のインポスターが潜伏中';
@@ -500,128 +490,126 @@ class AppLocalizationsJa extends AppLocalizations {
String get licenses => 'ライセンス';
@override
String get scanToJoin => 'Escanea el QR para unirte';
String get scanToJoin => 'QRコードをスキャンして参加';
@override
String get connectedPlayers => 'Jugadores conectados';
String get connectedPlayers => '接続中のプレイヤー';
@override
String get hostGame => 'Gestor de partida';
String get hostGame => 'ゲーム管理';
@override
String get waitingPlayersSeeWord => 'Esperando que todos vean su palabra...';
String get waitingPlayersSeeWord => '全員が単語を確認するのを待っています...';
@override
String get activePlayers => 'Jugadores activos';
String get activePlayers => '参加中のプレイヤー';
@override
String get playersVoted => 'Han votado';
String get playersVoted => '投票済み';
@override
String get waitingVoting => 'Esperando que voten...';
String get waitingVoting => '投票を待っています...';
@override
String get waitingForPlayers => 'Esperando jugadores...';
String get waitingForPlayers => 'プレイヤーを待っています...';
@override
String needMorePlayers(int count) {
return 'Faltan $count jugadores más';
return 'あと$count人のプレイヤーが必要です';
}
@override
String get starting => 'Iniciando...';
String get starting => '開始しています...';
@override
String get enterNameAndScan => 'Escribe tu nombre y escanea el QR del host';
String get enterNameAndScan => '名前を入力してホストのQRコードをスキャン';
@override
String get yourName => 'Tu nombre';
String get yourName => 'あなたの名前';
@override
String get nameRequired => 'Escribe tu nombre';
String get nameRequired => '名前を入力してください';
@override
String get connectingTo => 'Conectando a';
String get connectingTo => '接続中:';
@override
String get scanQR => 'Escanear QR';
String get scanQR => 'QRコードをスキャン';
@override
String get scanHostQR => 'Apunta al QR del host';
String get scanHostQR => 'ホストのQRコードにかざしてください';
@override
String get connectedWaiting => '¡Conectado!';
String get connectedWaiting => '接続しました!';
@override
String get waitingForHost => 'Esperando a que el host inicie la partida...';
String get waitingForHost => 'ホストがゲームを開始するのを待っています...';
@override
String get enterNameToSearch =>
'Escribe tu nombre para buscar partidas cercanas';
String get enterNameToSearch => '名前を入力して近くのゲームを検索';
@override
String get searchGames => 'Buscar partidas';
String get searchGames => 'ゲームを検索';
@override
String get searchingGames => 'Buscando partidas cercanas...';
String get searchingGames => '近くのゲームを検索しています...';
@override
String get noGamesFound => 'No se encontraron partidas';
String get noGamesFound => 'ゲームが見つかりません';
@override
String get noGamesFoundHint =>
'Asegúrate de que el host tiene la sala abierta y estáis cerca';
String get noGamesFoundHint => 'ホストがルームを開いていて、近くにいることを確認してください';
@override
String get orScanQR => '¿No aparece? Escanea el QR del host';
String get orScanQR => '表示されませんか?ホストのQRコードをスキャン';
@override
String get iveSeenIt => 'Ya la he visto';
String get iveSeenIt => '確認しました';
@override
String clueIs(String category) {
return 'La pista es: $category';
return 'ヒント:$category';
}
@override
String get debatePhaseActive => 'Fase de debate activa';
String get debatePhaseActive => '議論フェーズ進行中';
@override
String get debateInstructions =>
'Hablad entre vosotros y decid quién creéis que es el impostor. Cuando estéis listos, solicitad la votación.';
'お互いに話し合い、誰がインポスターだと思うか伝えましょう。準備ができたら投票を要求してください。';
@override
String get solicitarVotacion => 'Solicitar votación';
String get solicitarVotacion => '投票を要求';
@override
String get votacionSolicitada => 'Votación solicitada';
String get votacionSolicitada => '投票をリクエストしました';
@override
String get whoDoYouThinkIsTheImpostor => '¿Quién es el impostor?';
String get whoDoYouThinkIsTheImpostor => 'インポスターは誰?';
@override
String get selectOnePlayer => 'Selecciona a un jugador para votar';
String get selectOnePlayer => '投票するプレイヤーを選択';
@override
String get votar => 'Votar';
String get votar => '投票する';
@override
String get selectYourProfile => 'Tu perfil';
String get selectYourProfile => 'あなたのプロフィール';
@override
String get selectProfile => 'Selecciona un perfil';
String get selectProfile => 'プロフィールを選択';
@override
String get createNewUser => 'Crear nuevo usuario';
String get createNewUser => '新しいユーザーを作成';
@override
String get userNameRequired => 'El nombre no puede estar vacio';
String get userNameRequired => '名前は空にできません';
@override
String get profileSelected => 'Perfil seleccionado';
String get profileSelected => 'プロフィールを選択しました';
@override
String get availableProfiles => 'Perfiles disponibles';
String get availableProfiles => '利用可能なプロフィール';
@override
String get scanThisCodeFromAnotherPhone => '別のスマートフォンでこのコードをスキャン';
@@ -657,34 +645,41 @@ class AppLocalizationsJa extends AppLocalizations {
String get delete => '削除';
@override
String get selectAtLeastThreeUsersToStart => 'Select at least 3 users to start.';
String get selectAtLeastThreeUsersToStart =>
'Select at least 3 users to start.';
@override
String get hostPhoneMustSelectUser => 'The host phone must select at least one user.';
String get hostPhoneMustSelectUser =>
'The host phone must select at least one user.';
@override
String get roomNoLongerInLobby => 'The room is no longer in the lobby.';
@override
String get completeUserSelectionToStart => 'Complete user selection to start.';
String get completeUserSelectionToStart =>
'Complete user selection to start.';
@override
String get preparingSecureRoom => 'Preparing the secure room';
@override
String get searchingNearbyBluetoothGames => 'Searching nearby games over Bluetooth';
String get searchingNearbyBluetoothGames =>
'Searching nearby games over Bluetooth';
@override
String get tapToJoin => 'Tap to join';
@override
String get bluetoothLocationPermissionsRequired => 'Bluetooth and location permissions are required to search for games.';
String get bluetoothLocationPermissionsRequired =>
'Bluetooth and location permissions are required to search for games.';
@override
String get bluetoothLocationPermissionsShort => 'Bluetooth and location permissions are required';
String get bluetoothLocationPermissionsShort =>
'Bluetooth and location permissions are required';
@override
String get couldNotStartSearch => 'Could not start the search. Check Bluetooth and location.';
String get couldNotStartSearch =>
'Could not start the search. Check Bluetooth and location.';
@override
String couldNotConnectToHost(String host) {
@@ -698,13 +693,15 @@ class AppLocalizationsJa extends AppLocalizations {
String get singleDeviceSubtitle => 'Game on this device';
@override
String get singleDeviceDescription => 'Ideal for playing together by passing the phone around. Fast, direct setup.';
String get singleDeviceDescription =>
'Ideal for playing together by passing the phone around. Fast, direct setup.';
@override
String get multiDeviceSubtitle => 'Each player on their phone';
@override
String get multiDeviceDescription => 'Create a premium room, share the QR code and manage users from the lobby.';
String get multiDeviceDescription =>
'Create a premium room, share the QR code and manage users from the lobby.';
@override
String get singleDeviceGameLabel => 'Game on this device';
@@ -716,7 +713,8 @@ class AppLocalizationsJa extends AppLocalizations {
String get mainDeviceUser => 'Main device user';
@override
String get couldNotCreateRoom => 'Could not create the room. Check Bluetooth.';
String get couldNotCreateRoom =>
'Could not create the room. Check Bluetooth.';
@override
String cannotStartWithReason(String reason) {
@@ -728,6 +726,7 @@ class AppLocalizationsJa extends AppLocalizations {
@override
String get defaultPlayerName => 'プレイヤー';
@override
String get play => 'プレイ';
@@ -768,8 +767,68 @@ class AppLocalizationsJa extends AppLocalizations {
String get noResult => '結果なし';
@override
String historyGameSummary(int players, int impostors, int rounds, String word, String category) {
return '$players人 • インポスター$impostors人$roundsラウンド\n$word$category';
String historyGameSummary(
int players,
int impostors,
int rounds,
String word,
String category,
) {
return '\$players人 • インポスター\$impostors人 • \$roundsラウンド\n\$word • \$category';
}
}
@override
String voteOf(String name) {
return '$name の投票';
}
@override
String firstTurnInstruction(String name) {
return '$name が自分のワードを言って始めます。';
}
@override
String get impostorsKnowEachOther => '🎭 インポスター同士が分かる';
@override
String get impostorsKnowEachOtherDescription => '各インポスターに他のインポスターの名前が表示されます';
@override
String get impostorsKnowEachOtherNeedsTwo => 'インポスターが2人以上のときのみ有効';
@override
String otherImpostorsTitle(num count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '他のインポスター',
one: '他のインポスター',
);
return '$_temp0';
}
@override
String get youAreTheOnlyImpostor => 'あなたが唯一のインポスターです';
@override
String impostorsAdjusted(int count) {
return 'プレイヤー数に合わせてインポスターを$count人に調整しました';
}
@override
String get eliminatedCannotVote => 'あなたは脱落しました。投票はできません';
@override
String get reconnecting => '再接続しています...';
@override
String get reconnectingHint => 'ホストとの接続が切れました。ゲーム内のあなたの席は確保されています。';
@override
String get leaveGame => 'ゲームから退出';
@override
String playerRejoined(String name) {
return '$name がゲームに復帰しました';
}
}
+129 -70
View File
@@ -18,19 +18,19 @@ class AppLocalizationsKo extends AppLocalizations {
String get loadingWords => '단어 불러오는 중...';
@override
String get matchRewards => "게임 보상";
String get matchRewards => '게임 보상';
@override
String get newMedals => "새 메달";
String get newMedals => '새 메달';
@override
String get noNewMedalsKeepFire => "이번에는 새 메달이 없습니다. 불꽃을 계속 키우세요.";
String get noNewMedalsKeepFire => '이번에는 새 메달이 없습니다. 불꽃을 계속 키우세요.';
@override
String get calculatingRewards => "보상 계산 중...";
String get calculatingRewards => '보상 계산 중...';
@override
String get fireLabel => "불꽃";
String get fireLabel => '불꽃';
@override
String get playersRange => '3-20명 • 인터넷 불필요';
@@ -125,7 +125,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get impostorClueDescription => '임포스터가 카테고리를 알 수 있습니다';
@override
String get debate => '🗣️ Debate';
String get debate => '🗣️ 토론';
@override
String get debateTime => '⏱️ 토론 시간';
@@ -213,16 +213,6 @@ class AppLocalizationsKo extends AppLocalizations {
@override
String get playersInDebate => '토론 중인 플레이어';
@override
String voteOf(String name) {
return "$name의 투표";
}
@override
String firstTurnInstruction(String name) {
return "$name님이 자신의 단어를 말하며 시작합니다.";
}
@override
String activePlayersInfo(int active, int impostors) {
return '$active명 참여 중 • $impostors명의 임포스터 잠복 중';
@@ -500,128 +490,126 @@ class AppLocalizationsKo extends AppLocalizations {
String get licenses => '라이선스';
@override
String get scanToJoin => 'Escanea el QR para unirte';
String get scanToJoin => 'QR 코드를 스캔해 참여하세요';
@override
String get connectedPlayers => 'Jugadores conectados';
String get connectedPlayers => '접속한 플레이어';
@override
String get hostGame => 'Gestor de partida';
String get hostGame => '게임 관리';
@override
String get waitingPlayersSeeWord => 'Esperando que todos vean su palabra...';
String get waitingPlayersSeeWord => '모두가 단어를 확인하기를 기다리는 중...';
@override
String get activePlayers => 'Jugadores activos';
String get activePlayers => '활동 중인 플레이어';
@override
String get playersVoted => 'Han votado';
String get playersVoted => '투표 완료';
@override
String get waitingVoting => 'Esperando que voten...';
String get waitingVoting => '투표를 기다리는 중...';
@override
String get waitingForPlayers => 'Esperando jugadores...';
String get waitingForPlayers => '플레이어를 기다리는 중...';
@override
String needMorePlayers(int count) {
return 'Faltan $count jugadores más';
return '$count명이 더 필요합니다';
}
@override
String get starting => 'Iniciando...';
String get starting => '시작하는 중...';
@override
String get enterNameAndScan => 'Escribe tu nombre y escanea el QR del host';
String get enterNameAndScan => '이름을 입력하고 호스트의 QR 코드를 스캔하세요';
@override
String get yourName => 'Tu nombre';
String get yourName => '이름';
@override
String get nameRequired => 'Escribe tu nombre';
String get nameRequired => '이름을 입력하세요';
@override
String get connectingTo => 'Conectando a';
String get connectingTo => '연결 중:';
@override
String get scanQR => 'Escanear QR';
String get scanQR => 'QR 코드 스캔';
@override
String get scanHostQR => 'Apunta al QR del host';
String get scanHostQR => '호스트의 QR 코드를 비추세요';
@override
String get connectedWaiting => '¡Conectado!';
String get connectedWaiting => '연결되었습니다!';
@override
String get waitingForHost => 'Esperando a que el host inicie la partida...';
String get waitingForHost => '호스트가 게임을 시작하기를 기다리는 중...';
@override
String get enterNameToSearch =>
'Escribe tu nombre para buscar partidas cercanas';
String get enterNameToSearch => '이름을 입력해 근처 게임을 찾으세요';
@override
String get searchGames => 'Buscar partidas';
String get searchGames => '게임 찾기';
@override
String get searchingGames => 'Buscando partidas cercanas...';
String get searchingGames => '근처 게임을 찾는 중...';
@override
String get noGamesFound => 'No se encontraron partidas';
String get noGamesFound => '게임을 찾을 수 없습니다';
@override
String get noGamesFoundHint =>
'Asegúrate de que el host tiene la sala abierta y estáis cerca';
String get noGamesFoundHint => '호스트가 방을 열어 두었고 서로 가까이 있는지 확인하세요';
@override
String get orScanQR => '¿No aparece? Escanea el QR del host';
String get orScanQR => '보이지 않나요? 호스트의 QR 코드를 스캔하세요';
@override
String get iveSeenIt => 'Ya la he visto';
String get iveSeenIt => '확인했습니다';
@override
String clueIs(String category) {
return 'La pista es: $category';
return '힌트: $category';
}
@override
String get debatePhaseActive => 'Fase de debate activa';
String get debatePhaseActive => '토론 단계 진행 중';
@override
String get debateInstructions =>
'Hablad entre vosotros y decid quién creéis que es el impostor. Cuando estéis listos, solicitad la votación.';
'서로 이야기하며 누가 임포스터라고 생각하는지 말해 보세요. 준비되면 투표를 요청하세요.';
@override
String get solicitarVotacion => 'Solicitar votación';
String get solicitarVotacion => '투표 요청';
@override
String get votacionSolicitada => 'Votación solicitada';
String get votacionSolicitada => '투표를 요청했습니다';
@override
String get whoDoYouThinkIsTheImpostor => '¿Quién es el impostor?';
String get whoDoYouThinkIsTheImpostor => '임포스터는 누구일까요?';
@override
String get selectOnePlayer => 'Selecciona a un jugador para votar';
String get selectOnePlayer => '투표할 플레이어를 선택하세요';
@override
String get votar => 'Votar';
String get votar => '투표하기';
@override
String get selectYourProfile => 'Tu perfil';
String get selectYourProfile => '내 프로필';
@override
String get selectProfile => 'Selecciona un perfil';
String get selectProfile => '프로필을 선택하세요';
@override
String get createNewUser => 'Crear nuevo usuario';
String get createNewUser => '새 사용자 만들기';
@override
String get userNameRequired => 'El nombre no puede estar vacio';
String get userNameRequired => '이름은 비워 둘 수 없습니다';
@override
String get profileSelected => 'Perfil seleccionado';
String get profileSelected => '프로필을 선택했습니다';
@override
String get availableProfiles => 'Perfiles disponibles';
String get availableProfiles => '사용 가능한 프로필';
@override
String get scanThisCodeFromAnotherPhone => '다른 휴대폰에서 이 코드를 스캔하세요';
@@ -657,34 +645,41 @@ class AppLocalizationsKo extends AppLocalizations {
String get delete => '삭제';
@override
String get selectAtLeastThreeUsersToStart => 'Select at least 3 users to start.';
String get selectAtLeastThreeUsersToStart =>
'Select at least 3 users to start.';
@override
String get hostPhoneMustSelectUser => 'The host phone must select at least one user.';
String get hostPhoneMustSelectUser =>
'The host phone must select at least one user.';
@override
String get roomNoLongerInLobby => 'The room is no longer in the lobby.';
@override
String get completeUserSelectionToStart => 'Complete user selection to start.';
String get completeUserSelectionToStart =>
'Complete user selection to start.';
@override
String get preparingSecureRoom => 'Preparing the secure room';
@override
String get searchingNearbyBluetoothGames => 'Searching nearby games over Bluetooth';
String get searchingNearbyBluetoothGames =>
'Searching nearby games over Bluetooth';
@override
String get tapToJoin => 'Tap to join';
@override
String get bluetoothLocationPermissionsRequired => 'Bluetooth and location permissions are required to search for games.';
String get bluetoothLocationPermissionsRequired =>
'Bluetooth and location permissions are required to search for games.';
@override
String get bluetoothLocationPermissionsShort => 'Bluetooth and location permissions are required';
String get bluetoothLocationPermissionsShort =>
'Bluetooth and location permissions are required';
@override
String get couldNotStartSearch => 'Could not start the search. Check Bluetooth and location.';
String get couldNotStartSearch =>
'Could not start the search. Check Bluetooth and location.';
@override
String couldNotConnectToHost(String host) {
@@ -698,13 +693,15 @@ class AppLocalizationsKo extends AppLocalizations {
String get singleDeviceSubtitle => 'Game on this device';
@override
String get singleDeviceDescription => 'Ideal for playing together by passing the phone around. Fast, direct setup.';
String get singleDeviceDescription =>
'Ideal for playing together by passing the phone around. Fast, direct setup.';
@override
String get multiDeviceSubtitle => 'Each player on their phone';
@override
String get multiDeviceDescription => 'Create a premium room, share the QR code and manage users from the lobby.';
String get multiDeviceDescription =>
'Create a premium room, share the QR code and manage users from the lobby.';
@override
String get singleDeviceGameLabel => 'Game on this device';
@@ -716,7 +713,8 @@ class AppLocalizationsKo extends AppLocalizations {
String get mainDeviceUser => 'Main device user';
@override
String get couldNotCreateRoom => 'Could not create the room. Check Bluetooth.';
String get couldNotCreateRoom =>
'Could not create the room. Check Bluetooth.';
@override
String cannotStartWithReason(String reason) {
@@ -728,6 +726,7 @@ class AppLocalizationsKo extends AppLocalizations {
@override
String get defaultPlayerName => '플레이어';
@override
String get play => '플레이';
@@ -768,8 +767,68 @@ class AppLocalizationsKo extends AppLocalizations {
String get noResult => '결과 없음';
@override
String historyGameSummary(int players, int impostors, int rounds, String word, String category) {
return '플레이어 $players명 • 임포스터 $impostors명$rounds라운드\n$word$category';
String historyGameSummary(
int players,
int impostors,
int rounds,
String word,
String category,
) {
return '플레이어 \$players명 • 임포스터 \$impostors명 • \$rounds라운드\n\$word • \$category';
}
}
@override
String voteOf(String name) {
return '$name의 투표';
}
@override
String firstTurnInstruction(String name) {
return '$name님이 자신의 단어를 말하며 시작합니다.';
}
@override
String get impostorsKnowEachOther => '🎭 임포스터끼리 서로 압니다';
@override
String get impostorsKnowEachOtherDescription => '각 임포스터가 다른 임포스터의 이름을 봅니다';
@override
String get impostorsKnowEachOtherNeedsTwo => '임포스터가 2명 이상일 때만 적용됩니다';
@override
String otherImpostorsTitle(num count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '다른 임포스터들',
one: '다른 임포스터',
);
return '$_temp0';
}
@override
String get youAreTheOnlyImpostor => '당신이 유일한 임포스터입니다';
@override
String impostorsAdjusted(int count) {
return '플레이어 수에 맞춰 임포스터를 $count명으로 조정했습니다';
}
@override
String get eliminatedCannotVote => '탈락했습니다. 더 이상 투표할 수 없습니다';
@override
String get reconnecting => '다시 연결하는 중...';
@override
String get reconnectingHint => '호스트와의 연결이 끊겼습니다. 게임 내 자리는 유지됩니다.';
@override
String get leaveGame => '게임 나가기';
@override
String playerRejoined(String name) {
return '$name 님이 게임에 복귀했습니다';
}
}
+140 -70
View File
@@ -18,19 +18,20 @@ class AppLocalizationsNl extends AppLocalizations {
String get loadingWords => 'Woorden laden...';
@override
String get matchRewards => "Spelbeloningen";
String get matchRewards => 'Spelbeloningen';
@override
String get newMedals => "Nieuwe medailles";
String get newMedals => 'Nieuwe medailles';
@override
String get noNewMedalsKeepFire => "Deze keer geen nieuwe medailles. Blijf je vuur opbouwen.";
String get noNewMedalsKeepFire =>
'Deze keer geen nieuwe medailles. Blijf je vuur opbouwen.';
@override
String get calculatingRewards => "Beloningen berekenen...";
String get calculatingRewards => 'Beloningen berekenen...';
@override
String get fireLabel => "Vuur";
String get fireLabel => 'Vuur';
@override
String get playersRange => '3-20 spelers • Zonder internet';
@@ -125,7 +126,7 @@ class AppLocalizationsNl extends AppLocalizations {
String get impostorClueDescription => 'De bedrieger kent de categorie';
@override
String get debate => '🗣️ Debate';
String get debate => '🗣️ Discussie';
@override
String get debateTime => '⏱️ Debattijd';
@@ -214,16 +215,6 @@ class AppLocalizationsNl extends AppLocalizations {
@override
String get playersInDebate => 'Spelers in debat';
@override
String voteOf(String name) {
return "Stem van $name";
}
@override
String firstTurnInstruction(String name) {
return "$name begint door het woord te zeggen.";
}
@override
String activePlayersInfo(int active, int impostors) {
return '$active actief • $impostors verborgen bedrieger(s)';
@@ -503,131 +494,134 @@ class AppLocalizationsNl extends AppLocalizations {
String get licenses => 'Licenties';
@override
String get scanToJoin => 'Escanea el QR para unirte';
String get scanToJoin => 'Scan de QR-code om deel te nemen';
@override
String get connectedPlayers => 'Jugadores conectados';
String get connectedPlayers => 'Verbonden spelers';
@override
String get hostGame => 'Gestor de partida';
String get hostGame => 'Spelbeheer';
@override
String get waitingPlayersSeeWord => 'Esperando que todos vean su palabra...';
String get waitingPlayersSeeWord =>
'Wachten tot iedereen zijn woord heeft gezien...';
@override
String get activePlayers => 'Jugadores activos';
String get activePlayers => 'Actieve spelers';
@override
String get playersVoted => 'Han votado';
String get playersVoted => 'Hebben gestemd';
@override
String get waitingVoting => 'Esperando que voten...';
String get waitingVoting => 'Wachten op stemmen...';
@override
String get waitingForPlayers => 'Esperando jugadores...';
String get waitingForPlayers => 'Wachten op spelers...';
@override
String needMorePlayers(int count) {
return 'Faltan $count jugadores más';
return 'Er zijn nog $count spelers nodig';
}
@override
String get starting => 'Iniciando...';
String get starting => 'Starten...';
@override
String get enterNameAndScan => 'Escribe tu nombre y escanea el QR del host';
String get enterNameAndScan =>
'Voer je naam in en scan de QR-code van de host';
@override
String get yourName => 'Tu nombre';
String get yourName => 'Je naam';
@override
String get nameRequired => 'Escribe tu nombre';
String get nameRequired => 'Voer je naam in';
@override
String get connectingTo => 'Conectando a';
String get connectingTo => 'Verbinden met';
@override
String get scanQR => 'Escanear QR';
String get scanQR => 'QR-code scannen';
@override
String get scanHostQR => 'Apunta al QR del host';
String get scanHostQR => 'Richt op de QR-code van de host';
@override
String get connectedWaiting => '¡Conectado!';
String get connectedWaiting => 'Verbonden!';
@override
String get waitingForHost => 'Esperando a que el host inicie la partida...';
String get waitingForHost => 'Wachten tot de host het spel start...';
@override
String get enterNameToSearch =>
'Escribe tu nombre para buscar partidas cercanas';
'Voer je naam in om spellen in de buurt te zoeken';
@override
String get searchGames => 'Buscar partidas';
String get searchGames => 'Spellen zoeken';
@override
String get searchingGames => 'Buscando partidas cercanas...';
String get searchingGames => 'Zoeken naar spellen in de buurt...';
@override
String get noGamesFound => 'No se encontraron partidas';
String get noGamesFound => 'Geen spellen gevonden';
@override
String get noGamesFoundHint =>
'Asegúrate de que el host tiene la sala abierta y estáis cerca';
'Zorg dat de host de ruimte open heeft en dat jullie dichtbij zijn';
@override
String get orScanQR => '¿No aparece? Escanea el QR del host';
String get orScanQR => 'Zie je niets? Scan de QR-code van de host';
@override
String get iveSeenIt => 'Ya la he visto';
String get iveSeenIt => 'Ik heb het gezien';
@override
String clueIs(String category) {
return 'La pista es: $category';
return 'De hint is: $category';
}
@override
String get debatePhaseActive => 'Fase de debate activa';
String get debatePhaseActive => 'Discussiefase bezig';
@override
String get debateInstructions =>
'Hablad entre vosotros y decid quién creéis que es el impostor. Cuando estéis listos, solicitad la votación.';
'Praat met elkaar en zeg wie jullie denken dat de bedrieger is. Vraag om een stemming als jullie klaar zijn.';
@override
String get solicitarVotacion => 'Solicitar votación';
String get solicitarVotacion => 'Stemming aanvragen';
@override
String get votacionSolicitada => 'Votación solicitada';
String get votacionSolicitada => 'Stemming aangevraagd';
@override
String get whoDoYouThinkIsTheImpostor => '¿Quién es el impostor?';
String get whoDoYouThinkIsTheImpostor => 'Wie is de bedrieger?';
@override
String get selectOnePlayer => 'Selecciona a un jugador para votar';
String get selectOnePlayer => 'Kies een speler om op te stemmen';
@override
String get votar => 'Votar';
String get votar => 'Stemmen';
@override
String get selectYourProfile => 'Tu perfil';
String get selectYourProfile => 'Je profiel';
@override
String get selectProfile => 'Selecciona un perfil';
String get selectProfile => 'Kies een profiel';
@override
String get createNewUser => 'Crear nuevo usuario';
String get createNewUser => 'Nieuwe gebruiker aanmaken';
@override
String get userNameRequired => 'El nombre no puede estar vacio';
String get userNameRequired => 'De naam mag niet leeg zijn';
@override
String get profileSelected => 'Perfil seleccionado';
String get profileSelected => 'Profiel geselecteerd';
@override
String get availableProfiles => 'Perfiles disponibles';
String get availableProfiles => 'Beschikbare profielen';
@override
String get scanThisCodeFromAnotherPhone => 'Scan deze code met een andere telefoon';
String get scanThisCodeFromAnotherPhone =>
'Scan deze code met een andere telefoon';
@override
String get gameUsers => 'Spelgebruikers';
@@ -660,34 +654,41 @@ class AppLocalizationsNl extends AppLocalizations {
String get delete => 'Verwijderen';
@override
String get selectAtLeastThreeUsersToStart => 'Select at least 3 users to start.';
String get selectAtLeastThreeUsersToStart =>
'Select at least 3 users to start.';
@override
String get hostPhoneMustSelectUser => 'The host phone must select at least one user.';
String get hostPhoneMustSelectUser =>
'The host phone must select at least one user.';
@override
String get roomNoLongerInLobby => 'The room is no longer in the lobby.';
@override
String get completeUserSelectionToStart => 'Complete user selection to start.';
String get completeUserSelectionToStart =>
'Complete user selection to start.';
@override
String get preparingSecureRoom => 'Preparing the secure room';
@override
String get searchingNearbyBluetoothGames => 'Searching nearby games over Bluetooth';
String get searchingNearbyBluetoothGames =>
'Searching nearby games over Bluetooth';
@override
String get tapToJoin => 'Tap to join';
@override
String get bluetoothLocationPermissionsRequired => 'Bluetooth and location permissions are required to search for games.';
String get bluetoothLocationPermissionsRequired =>
'Bluetooth and location permissions are required to search for games.';
@override
String get bluetoothLocationPermissionsShort => 'Bluetooth and location permissions are required';
String get bluetoothLocationPermissionsShort =>
'Bluetooth and location permissions are required';
@override
String get couldNotStartSearch => 'Could not start the search. Check Bluetooth and location.';
String get couldNotStartSearch =>
'Could not start the search. Check Bluetooth and location.';
@override
String couldNotConnectToHost(String host) {
@@ -701,13 +702,15 @@ class AppLocalizationsNl extends AppLocalizations {
String get singleDeviceSubtitle => 'Game on this device';
@override
String get singleDeviceDescription => 'Ideal for playing together by passing the phone around. Fast, direct setup.';
String get singleDeviceDescription =>
'Ideal for playing together by passing the phone around. Fast, direct setup.';
@override
String get multiDeviceSubtitle => 'Each player on their phone';
@override
String get multiDeviceDescription => 'Create a premium room, share the QR code and manage users from the lobby.';
String get multiDeviceDescription =>
'Create a premium room, share the QR code and manage users from the lobby.';
@override
String get singleDeviceGameLabel => 'Game on this device';
@@ -719,7 +722,8 @@ class AppLocalizationsNl extends AppLocalizations {
String get mainDeviceUser => 'Main device user';
@override
String get couldNotCreateRoom => 'Could not create the room. Check Bluetooth.';
String get couldNotCreateRoom =>
'Could not create the room. Check Bluetooth.';
@override
String cannotStartWithReason(String reason) {
@@ -731,6 +735,7 @@ class AppLocalizationsNl extends AppLocalizations {
@override
String get defaultPlayerName => 'Speler';
@override
String get play => 'Spelen';
@@ -762,7 +767,8 @@ class AppLocalizationsNl extends AppLocalizations {
String get errorNoGame => 'Fout: geen spel';
@override
String get disconnectedPlayersWarning => 'Sommige spelers hebben een losgekoppeld apparaat.';
String get disconnectedPlayersWarning =>
'Sommige spelers hebben een losgekoppeld apparaat.';
@override
String get assumeOnThisPhone => 'Overnemen op deze mobiel';
@@ -771,8 +777,72 @@ class AppLocalizationsNl extends AppLocalizations {
String get noResult => 'Geen resultaat';
@override
String historyGameSummary(int players, int impostors, int rounds, String word, String category) {
return '$players spelers • $impostors impostor(s) • $rounds ronde(s)\n$word$category';
String historyGameSummary(
int players,
int impostors,
int rounds,
String word,
String category,
) {
return '\$players spelers • \$impostors impostor(s) • \$rounds ronde(s)\n\$word • \$category';
}
}
@override
String voteOf(String name) {
return 'Stem van $name';
}
@override
String firstTurnInstruction(String name) {
return '$name begint door het woord te zeggen.';
}
@override
String get impostorsKnowEachOther => '🎭 Bedriegers kennen elkaar';
@override
String get impostorsKnowEachOtherDescription =>
'Elke bedrieger ziet de namen van de anderen';
@override
String get impostorsKnowEachOtherNeedsTwo =>
'Geldt alleen bij 2 of meer bedriegers';
@override
String otherImpostorsTitle(num count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: 'De andere bedriegers',
one: 'De andere bedrieger',
);
return '$_temp0';
}
@override
String get youAreTheOnlyImpostor => 'Jij bent de enige bedrieger';
@override
String impostorsAdjusted(int count) {
return 'Bedriegers aangepast naar $count op basis van het aantal spelers';
}
@override
String get eliminatedCannotVote =>
'Je bent uitgeschakeld je stemt niet meer';
@override
String get reconnecting => 'Opnieuw verbinden...';
@override
String get reconnectingHint =>
'Verbinding met de host verbroken. Je plek in het spel blijft behouden.';
@override
String get leaveGame => 'Spel verlaten';
@override
String playerRejoined(String name) {
return '$name is terug in het spel';
}
}
+137 -70
View File
@@ -18,19 +18,20 @@ class AppLocalizationsPl extends AppLocalizations {
String get loadingWords => 'Ładowanie słów...';
@override
String get matchRewards => "Nagrody za grę";
String get matchRewards => 'Nagrody za grę';
@override
String get newMedals => "Nowe medale";
String get newMedals => 'Nowe medale';
@override
String get noNewMedalsKeepFire => "Tym razem bez nowych medali. Podtrzymuj swój ogień.";
String get noNewMedalsKeepFire =>
'Tym razem bez nowych medali. Podtrzymuj swój ogień.';
@override
String get calculatingRewards => "Obliczanie nagród...";
String get calculatingRewards => 'Obliczanie nagród...';
@override
String get fireLabel => "Ogień";
String get fireLabel => 'Ogień';
@override
String get playersRange => '3-20 graczy • Bez internetu';
@@ -125,7 +126,7 @@ class AppLocalizationsPl extends AppLocalizations {
String get impostorClueDescription => 'Oszust zna kategorię';
@override
String get debate => '🗣️ Debate';
String get debate => '🗣️ Dyskusja';
@override
String get debateTime => '⏱️ Czas debaty';
@@ -214,16 +215,6 @@ class AppLocalizationsPl extends AppLocalizations {
@override
String get playersInDebate => 'Gracze w debacie';
@override
String voteOf(String name) {
return "Głos gracza $name";
}
@override
String firstTurnInstruction(String name) {
return "$name zaczyna, mówiąc swoje słowo.";
}
@override
String activePlayersInfo(int active, int impostors) {
return '$active aktywnych • $impostors ukrytych oszustów';
@@ -503,128 +494,129 @@ class AppLocalizationsPl extends AppLocalizations {
String get licenses => 'Licencje';
@override
String get scanToJoin => 'Escanea el QR para unirte';
String get scanToJoin => 'Zeskanuj kod QR, aby dołączyć';
@override
String get connectedPlayers => 'Jugadores conectados';
String get connectedPlayers => 'Połączeni gracze';
@override
String get hostGame => 'Gestor de partida';
String get hostGame => 'Zarządzanie grą';
@override
String get waitingPlayersSeeWord => 'Esperando que todos vean su palabra...';
String get waitingPlayersSeeWord =>
'Czekamy, aż wszyscy zobaczą swoje słowo...';
@override
String get activePlayers => 'Jugadores activos';
String get activePlayers => 'Aktywni gracze';
@override
String get playersVoted => 'Han votado';
String get playersVoted => 'Zagłosowali';
@override
String get waitingVoting => 'Esperando que voten...';
String get waitingVoting => 'Czekamy na głosy...';
@override
String get waitingForPlayers => 'Esperando jugadores...';
String get waitingForPlayers => 'Czekamy na graczy...';
@override
String needMorePlayers(int count) {
return 'Faltan $count jugadores más';
return 'Brakuje jeszcze $count graczy';
}
@override
String get starting => 'Iniciando...';
String get starting => 'Uruchamianie...';
@override
String get enterNameAndScan => 'Escribe tu nombre y escanea el QR del host';
String get enterNameAndScan =>
'Wpisz swoje imię i zeskanuj kod QR gospodarza';
@override
String get yourName => 'Tu nombre';
String get yourName => 'Twoje imię';
@override
String get nameRequired => 'Escribe tu nombre';
String get nameRequired => 'Wpisz swoje imię';
@override
String get connectingTo => 'Conectando a';
String get connectingTo => 'Łączenie z';
@override
String get scanQR => 'Escanear QR';
String get scanQR => 'Zeskanuj kod QR';
@override
String get scanHostQR => 'Apunta al QR del host';
String get scanHostQR => 'Wyceluj w kod QR gospodarza';
@override
String get connectedWaiting => '¡Conectado!';
String get connectedWaiting => 'Połączono!';
@override
String get waitingForHost => 'Esperando a que el host inicie la partida...';
String get waitingForHost => 'Czekamy, aż gospodarz rozpocznie grę...';
@override
String get enterNameToSearch =>
'Escribe tu nombre para buscar partidas cercanas';
String get enterNameToSearch => 'Wpisz swoje imię, aby znaleźć gry w pobliżu';
@override
String get searchGames => 'Buscar partidas';
String get searchGames => 'Szukaj gier';
@override
String get searchingGames => 'Buscando partidas cercanas...';
String get searchingGames => 'Szukanie gier w pobliżu...';
@override
String get noGamesFound => 'No se encontraron partidas';
String get noGamesFound => 'Nie znaleziono gier';
@override
String get noGamesFoundHint =>
'Asegúrate de que el host tiene la sala abierta y estáis cerca';
'Upewnij się, że gospodarz ma otwarty pokój i jesteście blisko siebie';
@override
String get orScanQR => '¿No aparece? Escanea el QR del host';
String get orScanQR => 'Nie widzisz gry? Zeskanuj kod QR gospodarza';
@override
String get iveSeenIt => 'Ya la he visto';
String get iveSeenIt => 'Już zobaczyłem';
@override
String clueIs(String category) {
return 'La pista es: $category';
return 'Wskazówka: $category';
}
@override
String get debatePhaseActive => 'Fase de debate activa';
String get debatePhaseActive => 'Trwa faza dyskusji';
@override
String get debateInstructions =>
'Hablad entre vosotros y decid quién creéis que es el impostor. Cuando estéis listos, solicitad la votación.';
'Porozmawiajcie ze sobą i powiedzcie, kto waszym zdaniem jest oszustem. Gdy będziecie gotowi, poproście o głosowanie.';
@override
String get solicitarVotacion => 'Solicitar votación';
String get solicitarVotacion => 'Poproś o głosowanie';
@override
String get votacionSolicitada => 'Votación solicitada';
String get votacionSolicitada => 'Poproszono o głosowanie';
@override
String get whoDoYouThinkIsTheImpostor => '¿Quién es el impostor?';
String get whoDoYouThinkIsTheImpostor => 'Kto jest oszustem?';
@override
String get selectOnePlayer => 'Selecciona a un jugador para votar';
String get selectOnePlayer => 'Wybierz gracza, na którego głosujesz';
@override
String get votar => 'Votar';
String get votar => 'Głosuj';
@override
String get selectYourProfile => 'Tu perfil';
String get selectYourProfile => 'Twój profil';
@override
String get selectProfile => 'Selecciona un perfil';
String get selectProfile => 'Wybierz profil';
@override
String get createNewUser => 'Crear nuevo usuario';
String get createNewUser => 'Utwórz nowego użytkownika';
@override
String get userNameRequired => 'El nombre no puede estar vacio';
String get userNameRequired => 'Imię nie może być puste';
@override
String get profileSelected => 'Perfil seleccionado';
String get profileSelected => 'Wybrano profil';
@override
String get availableProfiles => 'Perfiles disponibles';
String get availableProfiles => 'Dostępne profile';
@override
String get scanThisCodeFromAnotherPhone => 'Zeskanuj ten kod innym telefonem';
@@ -660,34 +652,41 @@ class AppLocalizationsPl extends AppLocalizations {
String get delete => 'Usuń';
@override
String get selectAtLeastThreeUsersToStart => 'Select at least 3 users to start.';
String get selectAtLeastThreeUsersToStart =>
'Select at least 3 users to start.';
@override
String get hostPhoneMustSelectUser => 'The host phone must select at least one user.';
String get hostPhoneMustSelectUser =>
'The host phone must select at least one user.';
@override
String get roomNoLongerInLobby => 'The room is no longer in the lobby.';
@override
String get completeUserSelectionToStart => 'Complete user selection to start.';
String get completeUserSelectionToStart =>
'Complete user selection to start.';
@override
String get preparingSecureRoom => 'Preparing the secure room';
@override
String get searchingNearbyBluetoothGames => 'Searching nearby games over Bluetooth';
String get searchingNearbyBluetoothGames =>
'Searching nearby games over Bluetooth';
@override
String get tapToJoin => 'Tap to join';
@override
String get bluetoothLocationPermissionsRequired => 'Bluetooth and location permissions are required to search for games.';
String get bluetoothLocationPermissionsRequired =>
'Bluetooth and location permissions are required to search for games.';
@override
String get bluetoothLocationPermissionsShort => 'Bluetooth and location permissions are required';
String get bluetoothLocationPermissionsShort =>
'Bluetooth and location permissions are required';
@override
String get couldNotStartSearch => 'Could not start the search. Check Bluetooth and location.';
String get couldNotStartSearch =>
'Could not start the search. Check Bluetooth and location.';
@override
String couldNotConnectToHost(String host) {
@@ -701,13 +700,15 @@ class AppLocalizationsPl extends AppLocalizations {
String get singleDeviceSubtitle => 'Game on this device';
@override
String get singleDeviceDescription => 'Ideal for playing together by passing the phone around. Fast, direct setup.';
String get singleDeviceDescription =>
'Ideal for playing together by passing the phone around. Fast, direct setup.';
@override
String get multiDeviceSubtitle => 'Each player on their phone';
@override
String get multiDeviceDescription => 'Create a premium room, share the QR code and manage users from the lobby.';
String get multiDeviceDescription =>
'Create a premium room, share the QR code and manage users from the lobby.';
@override
String get singleDeviceGameLabel => 'Game on this device';
@@ -719,7 +720,8 @@ class AppLocalizationsPl extends AppLocalizations {
String get mainDeviceUser => 'Main device user';
@override
String get couldNotCreateRoom => 'Could not create the room. Check Bluetooth.';
String get couldNotCreateRoom =>
'Could not create the room. Check Bluetooth.';
@override
String cannotStartWithReason(String reason) {
@@ -731,6 +733,7 @@ class AppLocalizationsPl extends AppLocalizations {
@override
String get defaultPlayerName => 'Gracz';
@override
String get play => 'Graj';
@@ -762,7 +765,8 @@ class AppLocalizationsPl extends AppLocalizations {
String get errorNoGame => 'Błąd: brak gry';
@override
String get disconnectedPlayersWarning => 'Niektórzy gracze mają rozłączone urządzenie.';
String get disconnectedPlayersWarning =>
'Niektórzy gracze mają rozłączone urządzenie.';
@override
String get assumeOnThisPhone => 'Przejmij na tym telefonie';
@@ -771,8 +775,71 @@ class AppLocalizationsPl extends AppLocalizations {
String get noResult => 'Brak wyniku';
@override
String historyGameSummary(int players, int impostors, int rounds, String word, String category) {
return '$players graczy • $impostors impostor(ów) • $rounds rund\n$word$category';
String historyGameSummary(
int players,
int impostors,
int rounds,
String word,
String category,
) {
return '\$players graczy • \$impostors impostor(ów) • \$rounds rund\n\$word • \$category';
}
}
@override
String voteOf(String name) {
return 'Głos gracza $name';
}
@override
String firstTurnInstruction(String name) {
return '$name zaczyna, mówiąc swoje słowo.';
}
@override
String get impostorsKnowEachOther => '🎭 Oszuści znają się nawzajem';
@override
String get impostorsKnowEachOtherDescription =>
'Każdy oszust zobaczy imiona pozostałych';
@override
String get impostorsKnowEachOtherNeedsTwo =>
'Działa tylko przy 2 lub więcej oszustach';
@override
String otherImpostorsTitle(num count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: 'Pozostali oszuści',
one: 'Drugi oszust',
);
return '$_temp0';
}
@override
String get youAreTheOnlyImpostor => 'Jesteś jedynym oszustem';
@override
String impostorsAdjusted(int count) {
return 'Liczba oszustów dostosowana do $count z powodu liczby graczy';
}
@override
String get eliminatedCannotVote => 'Jesteś wyeliminowany już nie głosujesz';
@override
String get reconnecting => 'Ponowne łączenie...';
@override
String get reconnectingHint =>
'Utracono połączenie z gospodarzem. Twoje miejsce w grze jest zachowane.';
@override
String get leaveGame => 'Opuść grę';
@override
String playerRejoined(String name) {
return '$name wrócił(a) do gry';
}
}
+137 -68
View File
@@ -18,19 +18,20 @@ class AppLocalizationsPt extends AppLocalizations {
String get loadingWords => 'Carregando palavras...';
@override
String get matchRewards => "Recompensas da partida";
String get matchRewards => 'Recompensas da partida';
@override
String get newMedals => "Novas medalhas";
String get newMedals => 'Novas medalhas';
@override
String get noNewMedalsKeepFire => "Sem medalhas novas desta vez. Continua a acumular fogo.";
String get noNewMedalsKeepFire =>
'Sem medalhas novas desta vez. Continua a acumular fogo.';
@override
String get calculatingRewards => "Calculando recompensas...";
String get calculatingRewards => 'Calculando recompensas...';
@override
String get fireLabel => "Fogo";
String get fireLabel => 'Fogo';
@override
String get playersRange => '3-20 jogadores • Sem internet';
@@ -215,16 +216,6 @@ class AppLocalizationsPt extends AppLocalizations {
@override
String get playersInDebate => 'Jogadores no debate';
@override
String voteOf(String name) {
return "Voto de $name";
}
@override
String firstTurnInstruction(String name) {
return "$name começa dizendo a sua palavra.";
}
@override
String activePlayersInfo(int active, int impostors) {
return '$active ativos • $impostors impostor(es) ocultos';
@@ -504,131 +495,134 @@ class AppLocalizationsPt extends AppLocalizations {
String get licenses => 'Licenças';
@override
String get scanToJoin => 'Escanea el QR para unirte';
String get scanToJoin => 'Digitaliza o QR para entrares';
@override
String get connectedPlayers => 'Jugadores conectados';
String get connectedPlayers => 'Jogadores ligados';
@override
String get hostGame => 'Gestor de partida';
String get hostGame => 'Gestor de jogo';
@override
String get waitingPlayersSeeWord => 'Esperando que todos vean su palabra...';
String get waitingPlayersSeeWord =>
'À espera de que todos vejam a sua palavra...';
@override
String get activePlayers => 'Jugadores activos';
String get activePlayers => 'Jogadores ativos';
@override
String get playersVoted => 'Han votado';
String get playersVoted => ' votaram';
@override
String get waitingVoting => 'Esperando que voten...';
String get waitingVoting => 'À espera dos votos...';
@override
String get waitingForPlayers => 'Esperando jugadores...';
String get waitingForPlayers => 'À espera de jogadores...';
@override
String needMorePlayers(int count) {
return 'Faltan $count jugadores más';
return 'Faltam $count jogadores';
}
@override
String get starting => 'Iniciando...';
String get starting => 'A iniciar...';
@override
String get enterNameAndScan => 'Escribe tu nombre y escanea el QR del host';
String get enterNameAndScan =>
'Escreve o teu nome e digitaliza o QR do anfitrião';
@override
String get yourName => 'Tu nombre';
String get yourName => 'O teu nome';
@override
String get nameRequired => 'Escribe tu nombre';
String get nameRequired => 'Escreve o teu nome';
@override
String get connectingTo => 'Conectando a';
String get connectingTo => 'A ligar a';
@override
String get scanQR => 'Escanear QR';
String get scanQR => 'Digitalizar QR';
@override
String get scanHostQR => 'Apunta al QR del host';
String get scanHostQR => 'Aponta para o QR do anfitrião';
@override
String get connectedWaiting => '¡Conectado!';
String get connectedWaiting => 'Ligado!';
@override
String get waitingForHost => 'Esperando a que el host inicie la partida...';
String get waitingForHost => 'À espera de que o anfitrião inicie o jogo...';
@override
String get enterNameToSearch =>
'Escribe tu nombre para buscar partidas cercanas';
'Escreve o teu nome para procurar jogos por perto';
@override
String get searchGames => 'Buscar partidas';
String get searchGames => 'Procurar jogos';
@override
String get searchingGames => 'Buscando partidas cercanas...';
String get searchingGames => 'A procurar jogos por perto...';
@override
String get noGamesFound => 'No se encontraron partidas';
String get noGamesFound => 'Não foram encontrados jogos';
@override
String get noGamesFoundHint =>
'Asegúrate de que el host tiene la sala abierta y estáis cerca';
'Certifica-te de que o anfitrião tem a sala aberta e estão perto';
@override
String get orScanQR => '¿No aparece? Escanea el QR del host';
String get orScanQR => 'Não aparece? Digitaliza o QR do anfitrião';
@override
String get iveSeenIt => 'Ya la he visto';
String get iveSeenIt => 'Já a vi';
@override
String clueIs(String category) {
return 'La pista es: $category';
return 'A pista é: $category';
}
@override
String get debatePhaseActive => 'Fase de debate activa';
String get debatePhaseActive => 'Fase de debate a decorrer';
@override
String get debateInstructions =>
'Hablad entre vosotros y decid quién creéis que es el impostor. Cuando estéis listos, solicitad la votación.';
'Falem entre vos e digam quem acham que é o impostor. Quando estiverem prontos, peçam a votação.';
@override
String get solicitarVotacion => 'Solicitar votación';
String get solicitarVotacion => 'Pedir votação';
@override
String get votacionSolicitada => 'Votación solicitada';
String get votacionSolicitada => 'Votação pedida';
@override
String get whoDoYouThinkIsTheImpostor => '¿Quién es el impostor?';
String get whoDoYouThinkIsTheImpostor => 'Quem é o impostor?';
@override
String get selectOnePlayer => 'Selecciona a un jugador para votar';
String get selectOnePlayer => 'Seleciona um jogador para votar';
@override
String get votar => 'Votar';
@override
String get selectYourProfile => 'Tu perfil';
String get selectYourProfile => 'O teu perfil';
@override
String get selectProfile => 'Selecciona un perfil';
String get selectProfile => 'Seleciona um perfil';
@override
String get createNewUser => 'Crear nuevo usuario';
String get createNewUser => 'Criar novo utilizador';
@override
String get userNameRequired => 'El nombre no puede estar vacio';
String get userNameRequired => 'O nome não pode estar vazio';
@override
String get profileSelected => 'Perfil seleccionado';
String get profileSelected => 'Perfil selecionado';
@override
String get availableProfiles => 'Perfiles disponibles';
String get availableProfiles => 'Perfis disponíveis';
@override
String get scanThisCodeFromAnotherPhone => 'Escaneia este código noutro telemóvel';
String get scanThisCodeFromAnotherPhone =>
'Escaneia este código noutro telemóvel';
@override
String get gameUsers => 'Utilizadores da partida';
@@ -661,34 +655,41 @@ class AppLocalizationsPt extends AppLocalizations {
String get delete => 'Eliminar';
@override
String get selectAtLeastThreeUsersToStart => 'Seleciona pelo menos 3 utilizadores para começar.';
String get selectAtLeastThreeUsersToStart =>
'Seleciona pelo menos 3 utilizadores para começar.';
@override
String get hostPhoneMustSelectUser => 'O telemóvel anfitrião deve selecionar pelo menos um utilizador.';
String get hostPhoneMustSelectUser =>
'O telemóvel anfitrião deve selecionar pelo menos um utilizador.';
@override
String get roomNoLongerInLobby => 'A sala já não está no lobby.';
@override
String get completeUserSelectionToStart => 'Completa a seleção de utilizadores para começar.';
String get completeUserSelectionToStart =>
'Completa a seleção de utilizadores para começar.';
@override
String get preparingSecureRoom => 'A preparar a sala segura';
@override
String get searchingNearbyBluetoothGames => 'A procurar partidas próximas por Bluetooth';
String get searchingNearbyBluetoothGames =>
'A procurar partidas próximas por Bluetooth';
@override
String get tapToJoin => 'Toca para entrar';
@override
String get bluetoothLocationPermissionsRequired => 'São necessárias permissões de Bluetooth e localização para procurar partidas.';
String get bluetoothLocationPermissionsRequired =>
'São necessárias permissões de Bluetooth e localização para procurar partidas.';
@override
String get bluetoothLocationPermissionsShort => 'São necessárias permissões de Bluetooth e localização';
String get bluetoothLocationPermissionsShort =>
'São necessárias permissões de Bluetooth e localização';
@override
String get couldNotStartSearch => 'Não foi possível iniciar a procura. Verifica o Bluetooth e a localização.';
String get couldNotStartSearch =>
'Não foi possível iniciar a procura. Verifica o Bluetooth e a localização.';
@override
String couldNotConnectToHost(String host) {
@@ -702,13 +703,15 @@ class AppLocalizationsPt extends AppLocalizations {
String get singleDeviceSubtitle => 'Partida neste dispositivo';
@override
String get singleDeviceDescription => 'Ideal para jogar todos juntos passando o telemóvel. Configuração rápida e direta.';
String get singleDeviceDescription =>
'Ideal para jogar todos juntos passando o telemóvel. Configuração rápida e direta.';
@override
String get multiDeviceSubtitle => 'Cada jogador no seu telemóvel';
@override
String get multiDeviceDescription => 'Cria uma sala premium, partilha o QR e gere utilizadores no lobby.';
String get multiDeviceDescription =>
'Cria uma sala premium, partilha o QR e gere utilizadores no lobby.';
@override
String get singleDeviceGameLabel => 'Partida neste dispositivo';
@@ -720,7 +723,8 @@ class AppLocalizationsPt extends AppLocalizations {
String get mainDeviceUser => 'Utilizador principal do dispositivo';
@override
String get couldNotCreateRoom => 'Não foi possível criar a sala. Verifica o Bluetooth.';
String get couldNotCreateRoom =>
'Não foi possível criar a sala. Verifica o Bluetooth.';
@override
String cannotStartWithReason(String reason) {
@@ -732,6 +736,7 @@ class AppLocalizationsPt extends AppLocalizations {
@override
String get defaultPlayerName => 'Jogador';
@override
String get play => 'Jogar';
@@ -763,7 +768,8 @@ class AppLocalizationsPt extends AppLocalizations {
String get errorNoGame => 'Erro: sem partida';
@override
String get disconnectedPlayersWarning => 'Há jogadores com o dispositivo desligado.';
String get disconnectedPlayersWarning =>
'Há jogadores com o dispositivo desligado.';
@override
String get assumeOnThisPhone => 'Assumir neste telemóvel';
@@ -772,8 +778,71 @@ class AppLocalizationsPt extends AppLocalizations {
String get noResult => 'Sem resultado';
@override
String historyGameSummary(int players, int impostors, int rounds, String word, String category) {
return '$players jogadores • $impostors impostor(es) • $rounds ronda(s)\n$word$category';
String historyGameSummary(
int players,
int impostors,
int rounds,
String word,
String category,
) {
return '\$players jogadores • \$impostors impostor(es) • \$rounds ronda(s)\n\$word • \$category';
}
}
@override
String voteOf(String name) {
return 'Voto de $name';
}
@override
String firstTurnInstruction(String name) {
return '$name começa dizendo a sua palavra.';
}
@override
String get impostorsKnowEachOther => '🎭 Os impostores conhecem-se';
@override
String get impostorsKnowEachOtherDescription =>
'Cada impostor verá os nomes dos restantes';
@override
String get impostorsKnowEachOtherNeedsTwo =>
'Só se aplica com 2 ou mais impostores';
@override
String otherImpostorsTitle(num count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: 'Os outros impostores',
one: 'O outro impostor',
);
return '$_temp0';
}
@override
String get youAreTheOnlyImpostor => 'És o único impostor';
@override
String impostorsAdjusted(int count) {
return 'Impostores ajustados para $count pelo número de jogadores';
}
@override
String get eliminatedCannotVote => 'Estás eliminado: já não votas';
@override
String get reconnecting => 'A religar...';
@override
String get reconnectingHint =>
'Perdeu-se a ligação ao anfitrião. O teu lugar no jogo mantém-se.';
@override
String get leaveGame => 'Sair do jogo';
@override
String playerRejoined(String name) {
return '$name voltou ao jogo';
}
}
+137 -71
View File
@@ -18,19 +18,20 @@ class AppLocalizationsRu extends AppLocalizations {
String get loadingWords => 'Загрузка слов...';
@override
String get matchRewards => "Награды за игру";
String get matchRewards => 'Награды за игру';
@override
String get newMedals => "Новые медали";
String get newMedals => 'Новые медали';
@override
String get noNewMedalsKeepFire => "В этот раз новых медалей нет. Продолжай разжигать огонь.";
String get noNewMedalsKeepFire =>
'В этот раз новых медалей нет. Продолжай разжигать огонь.';
@override
String get calculatingRewards => "Подсчёт наград...";
String get calculatingRewards => 'Подсчёт наград...';
@override
String get fireLabel => "Огонь";
String get fireLabel => 'Огонь';
@override
String get playersRange => '3-20 игроков • Без интернета';
@@ -125,7 +126,7 @@ class AppLocalizationsRu extends AppLocalizations {
String get impostorClueDescription => 'Самозванец знает категорию';
@override
String get debate => '🗣️ Debate';
String get debate => '🗣️ Обсуждение';
@override
String get debateTime => '⏱️ Время обсуждения';
@@ -214,16 +215,6 @@ class AppLocalizationsRu extends AppLocalizations {
@override
String get playersInDebate => 'Игроки в обсуждении';
@override
String voteOf(String name) {
return "Голос игрока $name";
}
@override
String firstTurnInstruction(String name) {
return "$name начинает, называя своё слово.";
}
@override
String activePlayersInfo(int active, int impostors) {
return '$active активных • $impostors скрытый(-х) самозванец(-ев)';
@@ -503,131 +494,131 @@ class AppLocalizationsRu extends AppLocalizations {
String get licenses => 'Лицензии';
@override
String get scanToJoin => 'Escanea el QR para unirte';
String get scanToJoin => 'Отсканируйте QR-код, чтобы присоединиться';
@override
String get connectedPlayers => 'Jugadores conectados';
String get connectedPlayers => 'Подключённые игроки';
@override
String get hostGame => 'Gestor de partida';
String get hostGame => 'Управление игрой';
@override
String get waitingPlayersSeeWord => 'Esperando que todos vean su palabra...';
String get waitingPlayersSeeWord => 'Ждём, пока все увидят своё слово...';
@override
String get activePlayers => 'Jugadores activos';
String get activePlayers => 'Активные игроки';
@override
String get playersVoted => 'Han votado';
String get playersVoted => 'Проголосовали';
@override
String get waitingVoting => 'Esperando que voten...';
String get waitingVoting => 'Ждём голоса...';
@override
String get waitingForPlayers => 'Esperando jugadores...';
String get waitingForPlayers => 'Ждём игроков...';
@override
String needMorePlayers(int count) {
return 'Faltan $count jugadores más';
return 'Нужно ещё $count игроков';
}
@override
String get starting => 'Iniciando...';
String get starting => 'Запуск...';
@override
String get enterNameAndScan => 'Escribe tu nombre y escanea el QR del host';
String get enterNameAndScan => 'Введите имя и отсканируйте QR-код ведущего';
@override
String get yourName => 'Tu nombre';
String get yourName => 'Ваше имя';
@override
String get nameRequired => 'Escribe tu nombre';
String get nameRequired => 'Введите ваше имя';
@override
String get connectingTo => 'Conectando a';
String get connectingTo => 'Подключение к';
@override
String get scanQR => 'Escanear QR';
String get scanQR => 'Сканировать QR-код';
@override
String get scanHostQR => 'Apunta al QR del host';
String get scanHostQR => 'Наведите на QR-код ведущего';
@override
String get connectedWaiting => '¡Conectado!';
String get connectedWaiting => 'Подключено!';
@override
String get waitingForHost => 'Esperando a que el host inicie la partida...';
String get waitingForHost => 'Ждём, пока ведущий начнёт игру...';
@override
String get enterNameToSearch =>
'Escribe tu nombre para buscar partidas cercanas';
String get enterNameToSearch => 'Введите имя, чтобы найти игры поблизости';
@override
String get searchGames => 'Buscar partidas';
String get searchGames => 'Найти игры';
@override
String get searchingGames => 'Buscando partidas cercanas...';
String get searchingGames => 'Поиск игр поблизости...';
@override
String get noGamesFound => 'No se encontraron partidas';
String get noGamesFound => 'Игры не найдены';
@override
String get noGamesFoundHint =>
'Asegúrate de que el host tiene la sala abierta y estáis cerca';
'Убедитесь, что ведущий открыл комнату и вы находитесь рядом';
@override
String get orScanQR => '¿No aparece? Escanea el QR del host';
String get orScanQR => 'Не отображается? Отсканируйте QR-код ведущего';
@override
String get iveSeenIt => 'Ya la he visto';
String get iveSeenIt => 'Я посмотрел';
@override
String clueIs(String category) {
return 'La pista es: $category';
return 'Подсказка: $category';
}
@override
String get debatePhaseActive => 'Fase de debate activa';
String get debatePhaseActive => 'Идёт этап обсуждения';
@override
String get debateInstructions =>
'Hablad entre vosotros y decid quién creéis que es el impostor. Cuando estéis listos, solicitad la votación.';
'Обсудите между собой и скажите, кто, по-вашему, самозванец. Когда будете готовы, запросите голосование.';
@override
String get solicitarVotacion => 'Solicitar votación';
String get solicitarVotacion => 'Запросить голосование';
@override
String get votacionSolicitada => 'Votación solicitada';
String get votacionSolicitada => 'Голосование запрошено';
@override
String get whoDoYouThinkIsTheImpostor => '¿Quién es el impostor?';
String get whoDoYouThinkIsTheImpostor => 'Кто самозванец?';
@override
String get selectOnePlayer => 'Selecciona a un jugador para votar';
String get selectOnePlayer => 'Выберите игрока для голосования';
@override
String get votar => 'Votar';
String get votar => 'Голосовать';
@override
String get selectYourProfile => 'Tu perfil';
String get selectYourProfile => 'Ваш профиль';
@override
String get selectProfile => 'Selecciona un perfil';
String get selectProfile => 'Выберите профиль';
@override
String get createNewUser => 'Crear nuevo usuario';
String get createNewUser => 'Создать нового пользователя';
@override
String get userNameRequired => 'El nombre no puede estar vacio';
String get userNameRequired => 'Имя не может быть пустым';
@override
String get profileSelected => 'Perfil seleccionado';
String get profileSelected => 'Профиль выбран';
@override
String get availableProfiles => 'Perfiles disponibles';
String get availableProfiles => 'Доступные профили';
@override
String get scanThisCodeFromAnotherPhone => 'Отсканируйте этот код с другого телефона';
String get scanThisCodeFromAnotherPhone =>
'Отсканируйте этот код с другого телефона';
@override
String get gameUsers => 'Пользователи игры';
@@ -660,34 +651,41 @@ class AppLocalizationsRu extends AppLocalizations {
String get delete => 'Удалить';
@override
String get selectAtLeastThreeUsersToStart => 'Select at least 3 users to start.';
String get selectAtLeastThreeUsersToStart =>
'Select at least 3 users to start.';
@override
String get hostPhoneMustSelectUser => 'The host phone must select at least one user.';
String get hostPhoneMustSelectUser =>
'The host phone must select at least one user.';
@override
String get roomNoLongerInLobby => 'The room is no longer in the lobby.';
@override
String get completeUserSelectionToStart => 'Complete user selection to start.';
String get completeUserSelectionToStart =>
'Complete user selection to start.';
@override
String get preparingSecureRoom => 'Preparing the secure room';
@override
String get searchingNearbyBluetoothGames => 'Searching nearby games over Bluetooth';
String get searchingNearbyBluetoothGames =>
'Searching nearby games over Bluetooth';
@override
String get tapToJoin => 'Tap to join';
@override
String get bluetoothLocationPermissionsRequired => 'Bluetooth and location permissions are required to search for games.';
String get bluetoothLocationPermissionsRequired =>
'Bluetooth and location permissions are required to search for games.';
@override
String get bluetoothLocationPermissionsShort => 'Bluetooth and location permissions are required';
String get bluetoothLocationPermissionsShort =>
'Bluetooth and location permissions are required';
@override
String get couldNotStartSearch => 'Could not start the search. Check Bluetooth and location.';
String get couldNotStartSearch =>
'Could not start the search. Check Bluetooth and location.';
@override
String couldNotConnectToHost(String host) {
@@ -701,13 +699,15 @@ class AppLocalizationsRu extends AppLocalizations {
String get singleDeviceSubtitle => 'Game on this device';
@override
String get singleDeviceDescription => 'Ideal for playing together by passing the phone around. Fast, direct setup.';
String get singleDeviceDescription =>
'Ideal for playing together by passing the phone around. Fast, direct setup.';
@override
String get multiDeviceSubtitle => 'Each player on their phone';
@override
String get multiDeviceDescription => 'Create a premium room, share the QR code and manage users from the lobby.';
String get multiDeviceDescription =>
'Create a premium room, share the QR code and manage users from the lobby.';
@override
String get singleDeviceGameLabel => 'Game on this device';
@@ -719,7 +719,8 @@ class AppLocalizationsRu extends AppLocalizations {
String get mainDeviceUser => 'Main device user';
@override
String get couldNotCreateRoom => 'Could not create the room. Check Bluetooth.';
String get couldNotCreateRoom =>
'Could not create the room. Check Bluetooth.';
@override
String cannotStartWithReason(String reason) {
@@ -731,6 +732,7 @@ class AppLocalizationsRu extends AppLocalizations {
@override
String get defaultPlayerName => 'Игрок';
@override
String get play => 'Играть';
@@ -762,7 +764,8 @@ class AppLocalizationsRu extends AppLocalizations {
String get errorNoGame => 'Ошибка: нет игры';
@override
String get disconnectedPlayersWarning => 'У некоторых игроков устройство отключено.';
String get disconnectedPlayersWarning =>
'У некоторых игроков устройство отключено.';
@override
String get assumeOnThisPhone => 'Взять на этом телефоне';
@@ -771,8 +774,71 @@ class AppLocalizationsRu extends AppLocalizations {
String get noResult => 'Нет результата';
@override
String historyGameSummary(int players, int impostors, int rounds, String word, String category) {
return '$players игроков • $impostors самозванцев • $rounds раундов\n$word$category';
String historyGameSummary(
int players,
int impostors,
int rounds,
String word,
String category,
) {
return '\$players игроков • \$impostors самозванцев • \$rounds раундов\n\$word • \$category';
}
}
@override
String voteOf(String name) {
return 'Голос игрока $name';
}
@override
String firstTurnInstruction(String name) {
return '$name начинает, называя своё слово.';
}
@override
String get impostorsKnowEachOther => '🎭 Самозванцы знают друг друга';
@override
String get impostorsKnowEachOtherDescription =>
'Каждый самозванец увидит имена остальных';
@override
String get impostorsKnowEachOtherNeedsTwo =>
'Работает только при 2 и более самозванцах';
@override
String otherImpostorsTitle(num count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: 'Другие самозванцы',
one: 'Другой самозванец',
);
return '$_temp0';
}
@override
String get youAreTheOnlyImpostor => 'Вы единственный самозванец';
@override
String impostorsAdjusted(int count) {
return 'Число самозванцев изменено на $count из-за количества игроков';
}
@override
String get eliminatedCannotVote => 'Вы выбыли — вы больше не голосуете';
@override
String get reconnecting => 'Переподключение...';
@override
String get reconnectingHint =>
'Соединение с ведущим потеряно. Ваше место в игре сохраняется.';
@override
String get leaveGame => 'Выйти из игры';
@override
String playerRejoined(String name) {
return '$name вернулся в игру';
}
}
+138 -71
View File
@@ -18,19 +18,20 @@ class AppLocalizationsTr extends AppLocalizations {
String get loadingWords => 'Kelimeler yükleniyor...';
@override
String get matchRewards => "Oyun ödülleri";
String get matchRewards => 'Oyun ödülleri';
@override
String get newMedals => "Yeni madalyalar";
String get newMedals => 'Yeni madalyalar';
@override
String get noNewMedalsKeepFire => "Bu kez yeni madalya yok. Ateşini büyütmeye devam et.";
String get noNewMedalsKeepFire =>
'Bu kez yeni madalya yok. Ateşini büyütmeye devam et.';
@override
String get calculatingRewards => "Ödüller hesaplanıyor...";
String get calculatingRewards => 'Ödüller hesaplanıyor...';
@override
String get fireLabel => "Ateş";
String get fireLabel => 'Ateş';
@override
String get playersRange => '3-20 oyuncu • İnternet gerektirmez';
@@ -125,7 +126,7 @@ class AppLocalizationsTr extends AppLocalizations {
String get impostorClueDescription => 'Sahtekar kategoriyi bilir';
@override
String get debate => '🗣️ Debate';
String get debate => '🗣️ Tartışma';
@override
String get debateTime => '⏱️ Tartışma süresi';
@@ -213,16 +214,6 @@ class AppLocalizationsTr extends AppLocalizations {
@override
String get playersInDebate => 'Tartışmadaki oyuncular';
@override
String voteOf(String name) {
return "$name için oy";
}
@override
String firstTurnInstruction(String name) {
return "$name kelimesini söyleyerek başlar.";
}
@override
String activePlayersInfo(int active, int impostors) {
return '$active aktif • $impostors gizli sahtekar';
@@ -502,131 +493,132 @@ class AppLocalizationsTr extends AppLocalizations {
String get licenses => 'Lisanslar';
@override
String get scanToJoin => 'Escanea el QR para unirte';
String get scanToJoin => 'Katılmak için QR kodu okut';
@override
String get connectedPlayers => 'Jugadores conectados';
String get connectedPlayers => 'Bağlı oyuncular';
@override
String get hostGame => 'Gestor de partida';
String get hostGame => 'Oyun yönetimi';
@override
String get waitingPlayersSeeWord => 'Esperando que todos vean su palabra...';
String get waitingPlayersSeeWord =>
'Herkesin kelimesini görmesi bekleniyor...';
@override
String get activePlayers => 'Jugadores activos';
String get activePlayers => 'Aktif oyuncular';
@override
String get playersVoted => 'Han votado';
String get playersVoted => 'Oy verdi';
@override
String get waitingVoting => 'Esperando que voten...';
String get waitingVoting => 'Oylar bekleniyor...';
@override
String get waitingForPlayers => 'Esperando jugadores...';
String get waitingForPlayers => 'Oyuncular bekleniyor...';
@override
String needMorePlayers(int count) {
return 'Faltan $count jugadores más';
return '$count oyuncu daha gerekli';
}
@override
String get starting => 'Iniciando...';
String get starting => 'Başlatılıyor...';
@override
String get enterNameAndScan => 'Escribe tu nombre y escanea el QR del host';
String get enterNameAndScan => 'Adını yaz ve sunucunun QR kodunu okut';
@override
String get yourName => 'Tu nombre';
String get yourName => 'Adın';
@override
String get nameRequired => 'Escribe tu nombre';
String get nameRequired => 'Adını yaz';
@override
String get connectingTo => 'Conectando a';
String get connectingTo => 'Bağlanılıyor:';
@override
String get scanQR => 'Escanear QR';
String get scanQR => 'QR kodu okut';
@override
String get scanHostQR => 'Apunta al QR del host';
String get scanHostQR => 'Sunucunun QR koduna doğrult';
@override
String get connectedWaiting => '¡Conectado!';
String get connectedWaiting => 'Bağlandı!';
@override
String get waitingForHost => 'Esperando a que el host inicie la partida...';
String get waitingForHost => 'Sunucunun oyunu başlatması bekleniyor...';
@override
String get enterNameToSearch =>
'Escribe tu nombre para buscar partidas cercanas';
String get enterNameToSearch => 'Yakındaki oyunları aramak için adını yaz';
@override
String get searchGames => 'Buscar partidas';
String get searchGames => 'Oyun ara';
@override
String get searchingGames => 'Buscando partidas cercanas...';
String get searchingGames => 'Yakındaki oyunlar aranıyor...';
@override
String get noGamesFound => 'No se encontraron partidas';
String get noGamesFound => 'Oyun bulunamadı';
@override
String get noGamesFoundHint =>
'Asegúrate de que el host tiene la sala abierta y estáis cerca';
'Sunucunun odayı açık tuttuğundan ve yakın olduğunuzdan emin ol';
@override
String get orScanQR => '¿No aparece? Escanea el QR del host';
String get orScanQR => 'Görünmüyor mu? Sunucunun QR kodunu okut';
@override
String get iveSeenIt => 'Ya la he visto';
String get iveSeenIt => 'Gördüm';
@override
String clueIs(String category) {
return 'La pista es: $category';
return 'İpucu: $category';
}
@override
String get debatePhaseActive => 'Fase de debate activa';
String get debatePhaseActive => 'Tartışma aşaması sürüyor';
@override
String get debateInstructions =>
'Hablad entre vosotros y decid quién creéis que es el impostor. Cuando estéis listos, solicitad la votación.';
'Birbirinizle konuşun ve sahtekârın kim olduğunu düşündüğünüzü söyleyin. Hazır olduğunuzda oylama isteyin.';
@override
String get solicitarVotacion => 'Solicitar votación';
String get solicitarVotacion => 'Oylama iste';
@override
String get votacionSolicitada => 'Votación solicitada';
String get votacionSolicitada => 'Oylama istendi';
@override
String get whoDoYouThinkIsTheImpostor => '¿Quién es el impostor?';
String get whoDoYouThinkIsTheImpostor => 'Sahtekâr kim?';
@override
String get selectOnePlayer => 'Selecciona a un jugador para votar';
String get selectOnePlayer => 'Oy vermek için bir oyuncu seç';
@override
String get votar => 'Votar';
String get votar => 'Oy ver';
@override
String get selectYourProfile => 'Tu perfil';
String get selectYourProfile => 'Profilin';
@override
String get selectProfile => 'Selecciona un perfil';
String get selectProfile => 'Bir profil seç';
@override
String get createNewUser => 'Crear nuevo usuario';
String get createNewUser => 'Yeni kullanıcı oluştur';
@override
String get userNameRequired => 'El nombre no puede estar vacio';
String get userNameRequired => 'Ad boş olamaz';
@override
String get profileSelected => 'Perfil seleccionado';
String get profileSelected => 'Profil seçildi';
@override
String get availableProfiles => 'Perfiles disponibles';
String get availableProfiles => 'Kullanılabilir profiller';
@override
String get scanThisCodeFromAnotherPhone => 'Bu kodu başka bir telefondan tarayın';
String get scanThisCodeFromAnotherPhone =>
'Bu kodu başka bir telefondan tarayın';
@override
String get gameUsers => 'Oyun kullanıcıları';
@@ -659,34 +651,41 @@ class AppLocalizationsTr extends AppLocalizations {
String get delete => 'Sil';
@override
String get selectAtLeastThreeUsersToStart => 'Select at least 3 users to start.';
String get selectAtLeastThreeUsersToStart =>
'Select at least 3 users to start.';
@override
String get hostPhoneMustSelectUser => 'The host phone must select at least one user.';
String get hostPhoneMustSelectUser =>
'The host phone must select at least one user.';
@override
String get roomNoLongerInLobby => 'The room is no longer in the lobby.';
@override
String get completeUserSelectionToStart => 'Complete user selection to start.';
String get completeUserSelectionToStart =>
'Complete user selection to start.';
@override
String get preparingSecureRoom => 'Preparing the secure room';
@override
String get searchingNearbyBluetoothGames => 'Searching nearby games over Bluetooth';
String get searchingNearbyBluetoothGames =>
'Searching nearby games over Bluetooth';
@override
String get tapToJoin => 'Tap to join';
@override
String get bluetoothLocationPermissionsRequired => 'Bluetooth and location permissions are required to search for games.';
String get bluetoothLocationPermissionsRequired =>
'Bluetooth and location permissions are required to search for games.';
@override
String get bluetoothLocationPermissionsShort => 'Bluetooth and location permissions are required';
String get bluetoothLocationPermissionsShort =>
'Bluetooth and location permissions are required';
@override
String get couldNotStartSearch => 'Could not start the search. Check Bluetooth and location.';
String get couldNotStartSearch =>
'Could not start the search. Check Bluetooth and location.';
@override
String couldNotConnectToHost(String host) {
@@ -700,13 +699,15 @@ class AppLocalizationsTr extends AppLocalizations {
String get singleDeviceSubtitle => 'Game on this device';
@override
String get singleDeviceDescription => 'Ideal for playing together by passing the phone around. Fast, direct setup.';
String get singleDeviceDescription =>
'Ideal for playing together by passing the phone around. Fast, direct setup.';
@override
String get multiDeviceSubtitle => 'Each player on their phone';
@override
String get multiDeviceDescription => 'Create a premium room, share the QR code and manage users from the lobby.';
String get multiDeviceDescription =>
'Create a premium room, share the QR code and manage users from the lobby.';
@override
String get singleDeviceGameLabel => 'Game on this device';
@@ -718,7 +719,8 @@ class AppLocalizationsTr extends AppLocalizations {
String get mainDeviceUser => 'Main device user';
@override
String get couldNotCreateRoom => 'Could not create the room. Check Bluetooth.';
String get couldNotCreateRoom =>
'Could not create the room. Check Bluetooth.';
@override
String cannotStartWithReason(String reason) {
@@ -730,6 +732,7 @@ class AppLocalizationsTr extends AppLocalizations {
@override
String get defaultPlayerName => 'Oyuncu';
@override
String get play => 'Oyna';
@@ -761,7 +764,8 @@ class AppLocalizationsTr extends AppLocalizations {
String get errorNoGame => 'Hata: oyun yok';
@override
String get disconnectedPlayersWarning => 'Bazı oyuncuların cihazı bağlantısız.';
String get disconnectedPlayersWarning =>
'Bazı oyuncuların cihazı bağlantısız.';
@override
String get assumeOnThisPhone => 'Bu telefonda devral';
@@ -770,8 +774,71 @@ class AppLocalizationsTr extends AppLocalizations {
String get noResult => 'Sonuç yok';
@override
String historyGameSummary(int players, int impostors, int rounds, String word, String category) {
return '$players oyuncu • $impostors sahtekar • $rounds tur\n$word$category';
String historyGameSummary(
int players,
int impostors,
int rounds,
String word,
String category,
) {
return '\$players oyuncu • \$impostors sahtekar • \$rounds tur\n\$word • \$category';
}
}
@override
String voteOf(String name) {
return '$name için oy';
}
@override
String firstTurnInstruction(String name) {
return '$name kelimesini söyleyerek başlar.';
}
@override
String get impostorsKnowEachOther => '🎭 Sahtekârlar birbirini tanır';
@override
String get impostorsKnowEachOtherDescription =>
'Her sahtekâr diğerlerinin adlarını görür';
@override
String get impostorsKnowEachOtherNeedsTwo =>
'Yalnızca 2 veya daha fazla sahtekârla geçerli';
@override
String otherImpostorsTitle(num count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: 'Diğer sahtekârlar',
one: 'Diğer sahtekâr',
);
return '$_temp0';
}
@override
String get youAreTheOnlyImpostor => 'Tek sahtekâr sensin';
@override
String impostorsAdjusted(int count) {
return 'Oyuncu sayısına göre sahtekâr sayısı $count olarak ayarlandı';
}
@override
String get eliminatedCannotVote => 'Elendin: artık oy vermiyorsun';
@override
String get reconnecting => 'Yeniden bağlanılıyor...';
@override
String get reconnectingHint =>
'Sunucuyla bağlantı koptu. Oyundaki yerin korunuyor.';
@override
String get leaveGame => 'Oyundan ayrıl';
@override
String playerRejoined(String name) {
return '$name oyuna geri döndü';
}
}
+352 -83
View File
@@ -18,19 +18,19 @@ class AppLocalizationsZh extends AppLocalizations {
String get loadingWords => '正在加载词汇...';
@override
String get matchRewards => "游戏奖励";
String get matchRewards => '游戏奖励';
@override
String get newMedals => "新奖牌";
String get newMedals => '新奖牌';
@override
String get noNewMedalsKeepFire => "这次没有新奖牌。继续积累火焰。";
String get noNewMedalsKeepFire => '这次没有新奖牌。继续积累火焰。';
@override
String get calculatingRewards => "正在计算奖励...";
String get calculatingRewards => '正在计算奖励...';
@override
String get fireLabel => "火焰";
String get fireLabel => '火焰';
@override
String get playersRange => '3-20名玩家 • 无需联网';
@@ -125,7 +125,7 @@ class AppLocalizationsZh extends AppLocalizations {
String get impostorClueDescription => '冒牌者可以知道分类';
@override
String get debate => '🗣️ Debate';
String get debate => '🗣️ 讨论';
@override
String get debateTime => '⏱️ 讨论时间';
@@ -213,16 +213,6 @@ class AppLocalizationsZh extends AppLocalizations {
@override
String get playersInDebate => '参与讨论的玩家';
@override
String voteOf(String name) {
return "$name 的投票";
}
@override
String firstTurnInstruction(String name) {
return "$name 先说出自己的词。";
}
@override
String activePlayersInfo(int active, int impostors) {
return '$active 名在场 • $impostors 名冒牌者潜伏中';
@@ -499,128 +489,125 @@ class AppLocalizationsZh extends AppLocalizations {
String get licenses => '许可证';
@override
String get scanToJoin => 'Escanea el QR para unirte';
String get scanToJoin => '扫描二维码加入';
@override
String get connectedPlayers => 'Jugadores conectados';
String get connectedPlayers => '已连接的玩家';
@override
String get hostGame => 'Gestor de partida';
String get hostGame => '游戏管理';
@override
String get waitingPlayersSeeWord => 'Esperando que todos vean su palabra...';
String get waitingPlayersSeeWord => '等待所有人查看自己的词语…';
@override
String get activePlayers => 'Jugadores activos';
String get activePlayers => '在场玩家';
@override
String get playersVoted => 'Han votado';
String get playersVoted => '已投票';
@override
String get waitingVoting => 'Esperando que voten...';
String get waitingVoting => '等待投票…';
@override
String get waitingForPlayers => 'Esperando jugadores...';
String get waitingForPlayers => '等待玩家…';
@override
String needMorePlayers(int count) {
return 'Faltan $count jugadores más';
return '还需要 $count 名玩家';
}
@override
String get starting => 'Iniciando...';
String get starting => '正在开始…';
@override
String get enterNameAndScan => 'Escribe tu nombre y escanea el QR del host';
String get enterNameAndScan => '输入你的名字并扫描房主的二维码';
@override
String get yourName => 'Tu nombre';
String get yourName => '你的名字';
@override
String get nameRequired => 'Escribe tu nombre';
String get nameRequired => '请输入你的名字';
@override
String get connectingTo => 'Conectando a';
String get connectingTo => '正在连接';
@override
String get scanQR => 'Escanear QR';
String get scanQR => '扫描二维码';
@override
String get scanHostQR => 'Apunta al QR del host';
String get scanHostQR => '对准房主的二维码';
@override
String get connectedWaiting => '¡Conectado!';
String get connectedWaiting => '已连接!';
@override
String get waitingForHost => 'Esperando a que el host inicie la partida...';
String get waitingForHost => '等待房主开始游戏…';
@override
String get enterNameToSearch =>
'Escribe tu nombre para buscar partidas cercanas';
String get enterNameToSearch => '输入你的名字以搜索附近的游戏';
@override
String get searchGames => 'Buscar partidas';
String get searchGames => '搜索游戏';
@override
String get searchingGames => 'Buscando partidas cercanas...';
String get searchingGames => '正在搜索附近的游戏…';
@override
String get noGamesFound => 'No se encontraron partidas';
String get noGamesFound => '未找到游戏';
@override
String get noGamesFoundHint =>
'Asegúrate de que el host tiene la sala abierta y estáis cerca';
String get noGamesFoundHint => '请确认房主已开启房间,且你们距离较近';
@override
String get orScanQR => '¿No aparece? Escanea el QR del host';
String get orScanQR => '没有显示?扫描房主的二维码';
@override
String get iveSeenIt => 'Ya la he visto';
String get iveSeenIt => '我看过了';
@override
String clueIs(String category) {
return 'La pista es: $category';
return '提示:$category';
}
@override
String get debatePhaseActive => 'Fase de debate activa';
String get debatePhaseActive => '讨论阶段进行中';
@override
String get debateInstructions =>
'Hablad entre vosotros y decid quién creéis que es el impostor. Cuando estéis listos, solicitad la votación.';
String get debateInstructions => '互相讨论,说出你认为谁是卧底。准备好后请求投票。';
@override
String get solicitarVotacion => 'Solicitar votación';
String get solicitarVotacion => '请求投票';
@override
String get votacionSolicitada => 'Votación solicitada';
String get votacionSolicitada => '已请求投票';
@override
String get whoDoYouThinkIsTheImpostor => '¿Quién es el impostor?';
String get whoDoYouThinkIsTheImpostor => '谁是卧底?';
@override
String get selectOnePlayer => 'Selecciona a un jugador para votar';
String get selectOnePlayer => '选择要投票的玩家';
@override
String get votar => 'Votar';
String get votar => '投票';
@override
String get selectYourProfile => 'Tu perfil';
String get selectYourProfile => '你的资料';
@override
String get selectProfile => 'Selecciona un perfil';
String get selectProfile => '选择一个资料';
@override
String get createNewUser => 'Crear nuevo usuario';
String get createNewUser => '创建新用户';
@override
String get userNameRequired => 'El nombre no puede estar vacio';
String get userNameRequired => '名字不能为空';
@override
String get profileSelected => 'Perfil seleccionado';
String get profileSelected => '已选择资料';
@override
String get availableProfiles => 'Perfiles disponibles';
String get availableProfiles => '可用资料';
@override
String get scanThisCodeFromAnotherPhone => '用另一部手机扫描此代码';
@@ -656,34 +643,41 @@ class AppLocalizationsZh extends AppLocalizations {
String get delete => '删除';
@override
String get selectAtLeastThreeUsersToStart => 'Select at least 3 users to start.';
String get selectAtLeastThreeUsersToStart =>
'Select at least 3 users to start.';
@override
String get hostPhoneMustSelectUser => 'The host phone must select at least one user.';
String get hostPhoneMustSelectUser =>
'The host phone must select at least one user.';
@override
String get roomNoLongerInLobby => 'The room is no longer in the lobby.';
@override
String get completeUserSelectionToStart => 'Complete user selection to start.';
String get completeUserSelectionToStart =>
'Complete user selection to start.';
@override
String get preparingSecureRoom => 'Preparing the secure room';
@override
String get searchingNearbyBluetoothGames => 'Searching nearby games over Bluetooth';
String get searchingNearbyBluetoothGames =>
'Searching nearby games over Bluetooth';
@override
String get tapToJoin => 'Tap to join';
@override
String get bluetoothLocationPermissionsRequired => 'Bluetooth and location permissions are required to search for games.';
String get bluetoothLocationPermissionsRequired =>
'Bluetooth and location permissions are required to search for games.';
@override
String get bluetoothLocationPermissionsShort => 'Bluetooth and location permissions are required';
String get bluetoothLocationPermissionsShort =>
'Bluetooth and location permissions are required';
@override
String get couldNotStartSearch => 'Could not start the search. Check Bluetooth and location.';
String get couldNotStartSearch =>
'Could not start the search. Check Bluetooth and location.';
@override
String couldNotConnectToHost(String host) {
@@ -697,13 +691,15 @@ class AppLocalizationsZh extends AppLocalizations {
String get singleDeviceSubtitle => 'Game on this device';
@override
String get singleDeviceDescription => 'Ideal for playing together by passing the phone around. Fast, direct setup.';
String get singleDeviceDescription =>
'Ideal for playing together by passing the phone around. Fast, direct setup.';
@override
String get multiDeviceSubtitle => 'Each player on their phone';
@override
String get multiDeviceDescription => 'Create a premium room, share the QR code and manage users from the lobby.';
String get multiDeviceDescription =>
'Create a premium room, share the QR code and manage users from the lobby.';
@override
String get singleDeviceGameLabel => 'Game on this device';
@@ -715,7 +711,8 @@ class AppLocalizationsZh extends AppLocalizations {
String get mainDeviceUser => 'Main device user';
@override
String get couldNotCreateRoom => 'Could not create the room. Check Bluetooth.';
String get couldNotCreateRoom =>
'Could not create the room. Check Bluetooth.';
@override
String cannotStartWithReason(String reason) {
@@ -727,6 +724,7 @@ class AppLocalizationsZh extends AppLocalizations {
@override
String get defaultPlayerName => '玩家';
@override
String get play => '开始';
@@ -767,10 +765,70 @@ class AppLocalizationsZh extends AppLocalizations {
String get noResult => '无结果';
@override
String historyGameSummary(int players, int impostors, int rounds, String word, String category) {
return '$players 名玩家 • $impostors 名冒牌者 • $rounds 回合\n$word$category';
String historyGameSummary(
int players,
int impostors,
int rounds,
String word,
String category,
) {
return '\$players 名玩家 • \$impostors 名冒牌者 • \$rounds 回合\n\$word • \$category';
}
@override
String voteOf(String name) {
return '$name 的投票';
}
@override
String firstTurnInstruction(String name) {
return '$name 先说出自己的词。';
}
@override
String get impostorsKnowEachOther => '🎭 卧底互相知晓';
@override
String get impostorsKnowEachOtherDescription => '每个卧底都会看到其他卧底的名字';
@override
String get impostorsKnowEachOtherNeedsTwo => '仅在 2 名或以上卧底时生效';
@override
String otherImpostorsTitle(num count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '其他卧底',
one: '另一名卧底',
);
return '$_temp0';
}
@override
String get youAreTheOnlyImpostor => '你是唯一的卧底';
@override
String impostorsAdjusted(int count) {
return '已根据玩家人数将卧底调整为 $count';
}
@override
String get eliminatedCannotVote => '你已出局,不能再投票';
@override
String get reconnecting => '正在重新连接…';
@override
String get reconnectingHint => '与房主的连接已断开。你在游戏中的位置仍为你保留。';
@override
String get leaveGame => '退出游戏';
@override
String playerRejoined(String name) {
return '$name 已重新加入游戏';
}
}
/// The translations for Chinese, as used in Taiwan (`zh_TW`).
@@ -786,6 +844,21 @@ class AppLocalizationsZhTw extends AppLocalizationsZh {
@override
String get loadingWords => '正在載入詞彙...';
@override
String get matchRewards => '遊戲獎勵';
@override
String get newMedals => '新獎牌';
@override
String get noNewMedalsKeepFire => '這次沒有新獎牌。繼續累積火焰。';
@override
String get calculatingRewards => '正在計算獎勵...';
@override
String get fireLabel => '火焰';
@override
String get playersRange => '3-20 位玩家 • 無需網路';
@@ -878,6 +951,9 @@ class AppLocalizationsZhTw extends AppLocalizationsZh {
@override
String get impostorClueDescription => '冒牌者可以知道類別';
@override
String get debate => '🗣️ 討論';
@override
String get debateTime => '⏱️ 討論時間';
@@ -1238,6 +1314,128 @@ class AppLocalizationsZhTw extends AppLocalizationsZh {
@override
String get licenses => '授權條款';
@override
String get scanToJoin => '掃描 QR Code 加入';
@override
String get connectedPlayers => '已連線的玩家';
@override
String get hostGame => '遊戲管理';
@override
String get waitingPlayersSeeWord => '等待所有人查看自己的詞語…';
@override
String get activePlayers => '在場玩家';
@override
String get playersVoted => '已投票';
@override
String get waitingVoting => '等待投票…';
@override
String get waitingForPlayers => '等待玩家…';
@override
String needMorePlayers(int count) {
return '還需要 $count 名玩家';
}
@override
String get starting => '正在開始…';
@override
String get enterNameAndScan => '輸入你的名字並掃描房主的 QR Code';
@override
String get yourName => '你的名字';
@override
String get nameRequired => '請輸入你的名字';
@override
String get connectingTo => '正在連線';
@override
String get scanQR => '掃描 QR Code';
@override
String get scanHostQR => '對準房主的 QR Code';
@override
String get connectedWaiting => '已連線!';
@override
String get waitingForHost => '等待房主開始遊戲…';
@override
String get enterNameToSearch => '輸入你的名字以搜尋附近的遊戲';
@override
String get searchGames => '搜尋遊戲';
@override
String get searchingGames => '正在搜尋附近的遊戲…';
@override
String get noGamesFound => '找不到遊戲';
@override
String get noGamesFoundHint => '請確認房主已開啟房間,且你們距離較近';
@override
String get orScanQR => '沒有顯示?掃描房主的 QR Code';
@override
String get iveSeenIt => '我看過了';
@override
String clueIs(String category) {
return '提示:$category';
}
@override
String get debatePhaseActive => '討論階段進行中';
@override
String get debateInstructions => '互相討論,說出你認為誰是臥底。準備好後請求投票。';
@override
String get solicitarVotacion => '請求投票';
@override
String get votacionSolicitada => '已請求投票';
@override
String get whoDoYouThinkIsTheImpostor => '誰是臥底?';
@override
String get selectOnePlayer => '選擇要投票的玩家';
@override
String get votar => '投票';
@override
String get selectYourProfile => '你的個人檔案';
@override
String get selectProfile => '選擇一個個人檔案';
@override
String get createNewUser => '建立新使用者';
@override
String get userNameRequired => '名字不能為空';
@override
String get profileSelected => '已選擇個人檔案';
@override
String get availableProfiles => '可用的個人檔案';
@override
String get scanThisCodeFromAnotherPhone => '用另一部手机扫描此代码';
@@ -1272,34 +1470,41 @@ class AppLocalizationsZhTw extends AppLocalizationsZh {
String get delete => '删除';
@override
String get selectAtLeastThreeUsersToStart => 'Select at least 3 users to start.';
String get selectAtLeastThreeUsersToStart =>
'Select at least 3 users to start.';
@override
String get hostPhoneMustSelectUser => 'The host phone must select at least one user.';
String get hostPhoneMustSelectUser =>
'The host phone must select at least one user.';
@override
String get roomNoLongerInLobby => 'The room is no longer in the lobby.';
@override
String get completeUserSelectionToStart => 'Complete user selection to start.';
String get completeUserSelectionToStart =>
'Complete user selection to start.';
@override
String get preparingSecureRoom => 'Preparing the secure room';
@override
String get searchingNearbyBluetoothGames => 'Searching nearby games over Bluetooth';
String get searchingNearbyBluetoothGames =>
'Searching nearby games over Bluetooth';
@override
String get tapToJoin => 'Tap to join';
@override
String get bluetoothLocationPermissionsRequired => 'Bluetooth and location permissions are required to search for games.';
String get bluetoothLocationPermissionsRequired =>
'Bluetooth and location permissions are required to search for games.';
@override
String get bluetoothLocationPermissionsShort => 'Bluetooth and location permissions are required';
String get bluetoothLocationPermissionsShort =>
'Bluetooth and location permissions are required';
@override
String get couldNotStartSearch => 'Could not start the search. Check Bluetooth and location.';
String get couldNotStartSearch =>
'Could not start the search. Check Bluetooth and location.';
@override
String couldNotConnectToHost(String host) {
@@ -1313,13 +1518,15 @@ class AppLocalizationsZhTw extends AppLocalizationsZh {
String get singleDeviceSubtitle => 'Game on this device';
@override
String get singleDeviceDescription => 'Ideal for playing together by passing the phone around. Fast, direct setup.';
String get singleDeviceDescription =>
'Ideal for playing together by passing the phone around. Fast, direct setup.';
@override
String get multiDeviceSubtitle => 'Each player on their phone';
@override
String get multiDeviceDescription => 'Create a premium room, share the QR code and manage users from the lobby.';
String get multiDeviceDescription =>
'Create a premium room, share the QR code and manage users from the lobby.';
@override
String get singleDeviceGameLabel => 'Game on this device';
@@ -1331,7 +1538,8 @@ class AppLocalizationsZhTw extends AppLocalizationsZh {
String get mainDeviceUser => 'Main device user';
@override
String get couldNotCreateRoom => 'Could not create the room. Check Bluetooth.';
String get couldNotCreateRoom =>
'Could not create the room. Check Bluetooth.';
@override
String cannotStartWithReason(String reason) {
@@ -1352,6 +1560,7 @@ class AppLocalizationsZhTw extends AppLocalizationsZh {
@override
String get mainTagline => '在太晚之前找出冒牌者';
@override
String get deviceProfile => '裝置個人檔案';
@@ -1383,8 +1592,68 @@ class AppLocalizationsZhTw extends AppLocalizationsZh {
String get noResult => '無結果';
@override
String historyGameSummary(int players, int impostors, int rounds, String word, String category) {
return '$players 位玩家 • $impostors 位冒牌者 • $rounds 回合\n$word$category';
String historyGameSummary(
int players,
int impostors,
int rounds,
String word,
String category,
) {
return '\$players 位玩家 • \$impostors 位冒牌者 • \$rounds 回合\n\$word • \$category';
}
}
@override
String voteOf(String name) {
return '$name 的投票';
}
@override
String firstTurnInstruction(String name) {
return '$name 先說出自己的詞。';
}
@override
String get impostorsKnowEachOther => '🎭 臥底互相知曉';
@override
String get impostorsKnowEachOtherDescription => '每個臥底都會看到其他臥底的名字';
@override
String get impostorsKnowEachOtherNeedsTwo => '僅在 2 名或以上臥底時生效';
@override
String otherImpostorsTitle(num count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '其他臥底',
one: '另一名臥底',
);
return '$_temp0';
}
@override
String get youAreTheOnlyImpostor => '你是唯一的臥底';
@override
String impostorsAdjusted(int count) {
return '已根據玩家人數將臥底調整為 $count';
}
@override
String get eliminatedCannotVote => '你已出局,不能再投票';
@override
String get reconnecting => '正在重新連線…';
@override
String get reconnectingHint => '與房主的連線已中斷。你在遊戲中的位置仍為你保留。';
@override
String get leaveGame => '退出遊戲';
@override
String playerRejoined(String name) {
return '$name 已重新加入遊戲';
}
}
@@ -18,11 +18,19 @@ class JugadorInicioPartida {
final bool esImpostor;
final String? palabra;
/// Nombres del resto de impostores.
///
/// `null` significa que no hay nada que mostrar (el jugador no es impostor o
/// la partida no permite que se conozcan). Una lista vacía significa que sí
/// procede mostrarlo y que es el único impostor.
final List<String>? companerosImpostores;
const JugadorInicioPartida({
required this.jugadorId,
required this.nombre,
required this.esImpostor,
required this.palabra,
this.companerosImpostores,
});
Map<String, dynamic> toJson() => {
@@ -30,14 +38,20 @@ class JugadorInicioPartida {
'nombre': nombre,
'esImpostor': esImpostor,
if (palabra != null) 'palabra': palabra,
if (companerosImpostores != null)
'companerosImpostores': companerosImpostores,
};
factory JugadorInicioPartida.fromJson(Map<String, dynamic> json) {
final companeros = json['companerosImpostores'] as List<dynamic>?;
return JugadorInicioPartida(
jugadorId: json['jugadorId'] as String,
nombre: json['nombre'] as String,
esImpostor: json['esImpostor'] as bool? ?? false,
palabra: json['palabra'] as String?,
companerosImpostores: companeros
?.map((nombre) => nombre.toString())
.toList(),
);
}
}
@@ -82,9 +96,16 @@ class InicioPartidaMultijugador {
required String palabraSecreta,
required String categoria,
required Map<String, bool> impostoresPorJugadorId,
bool impostoresSeConocen = false,
}) {
final payloads = <String, InicioPartidaCliente>{};
final nombresImpostores = <String, String>{
for (final asignacion in asignaciones)
if (impostoresPorJugadorId[asignacion.jugadorId] ?? false)
asignacion.jugadorId: asignacion.nombre,
};
for (final asignacion in asignaciones) {
final esImpostor = impostoresPorJugadorId[asignacion.jugadorId] ?? false;
final payloadActual = payloads[asignacion.clientId];
@@ -93,6 +114,12 @@ class InicioPartidaMultijugador {
nombre: asignacion.nombre,
esImpostor: esImpostor,
palabra: esImpostor ? null : palabraSecreta,
companerosImpostores: esImpostor && impostoresSeConocen
? (nombresImpostores.entries
.where((entry) => entry.key != asignacion.jugadorId)
.map((entry) => entry.value)
.toList())
: null,
);
if (payloadActual == null) {
+67 -9
View File
@@ -3,13 +3,30 @@ import 'dart:math';
import 'package:flutter/services.dart';
import 'package:farolero/l10n/generated/app_localizations.dart';
/// Una palabra del banco junto con la pista que verá el impostor.
class EntradaPalabra {
final String palabra;
/// Pista específica de esta palabra. Si es null se usa la de la categoría.
final String? pista;
const EntradaPalabra({required this.palabra, this.pista});
}
/// Categorías disponibles en el banco de palabras.
class BancoPalabras {
final Map<String, List<String>> categorias;
final Map<String, String> pistasPorCategoria;
BancoPalabras(this.categorias, {Map<String, String>? pistasPorCategoria})
: pistasPorCategoria = pistasPorCategoria ?? {};
/// Pista por palabra, cuando el banco la aporta.
final Map<String, String> pistasPorPalabra;
BancoPalabras(
this.categorias, {
Map<String, String>? pistasPorCategoria,
Map<String, String>? pistasPorPalabra,
}) : pistasPorCategoria = pistasPorCategoria ?? {},
pistasPorPalabra = pistasPorPalabra ?? {};
static final Map<String, BancoPalabras> _instancias = {};
@@ -37,19 +54,42 @@ class BancoPalabras {
final cats = data['categorias'] as Map<String, dynamic>;
final mapa = <String, List<String>>{};
final pistas = <String, String>{};
final pistasPalabra = <String, String>{};
for (final entrada in cats.entries) {
final valor = entrada.value;
final listaCruda = valor is Map<String, dynamic>
? valor['palabras'] as List
: valor as List;
if (valor is Map<String, dynamic>) {
mapa[entrada.key] = List<String>.from(valor['palabras'] as List);
final pista = valor['pista'];
if (pista is String && pista.isNotEmpty) pistas[entrada.key] = pista;
} else {
mapa[entrada.key] = List<String>.from(valor as List);
}
final palabras = <String>[];
for (final elemento in listaCruda) {
// Formato v2: "Perro". Formato v3: {"palabra": "Perro", "pista": "..."}
if (elemento is Map) {
final palabra = elemento['palabra'] as String?;
if (palabra == null || palabra.isEmpty) continue;
palabras.add(palabra);
final pistaPalabra = elemento['pista'];
if (pistaPalabra is String && pistaPalabra.isNotEmpty) {
pistasPalabra[palabra] = pistaPalabra;
}
} else {
palabras.add(elemento as String);
}
}
mapa[entrada.key] = palabras;
}
_instancias[idioma] = BancoPalabras(mapa, pistasPorCategoria: pistas);
_instancias[idioma] = BancoPalabras(
mapa,
pistasPorCategoria: pistas,
pistasPorPalabra: pistasPalabra,
);
return _instancias[idioma]!;
}
@@ -57,7 +97,7 @@ class BancoPalabras {
/// Obtiene una palabra aleatoria de la categoría dada (o de todas si es null).
String palabraAleatoria(String? categoria) {
final rng = Random();
final rng = Random.secure();
if (categoria == null || categoria == 'todas') {
final todasPalabras = categorias.values.expand((l) => l).toList();
return todasPalabras[rng.nextInt(todasPalabras.length)];
@@ -77,6 +117,16 @@ class BancoPalabras {
/// Devuelve la pista localizada de una categoría si el banco la trae.
String? pistaDeCategoria(String categoria) => pistasPorCategoria[categoria];
/// Pista que verá el impostor para una palabra concreta. Prioriza la pista
/// específica de la palabra y cae a la de su categoría si no existe.
String? pistaDePalabra(String palabra, {String? categoria}) {
final especifica = pistasPorPalabra[palabra];
if (especifica != null && especifica.isNotEmpty) return especifica;
final clave = categoria ?? categoriaDepalabra(palabra);
if (clave == null) return null;
return pistasPorCategoria[clave];
}
/// Devuelve el nombre localizado de la categoría usando AppLocalizations.
static String nombreBonitoCategoria(String clave, [AppLocalizations? l10n]) {
if (l10n != null) {
@@ -132,9 +182,17 @@ class BancoPalabrasTraducidas {
final banco = await BancoPalabras.cargar(idioma: idioma);
final mapa = <String, List<EntradaPalabraTraducida>>{};
for (final categoria in banco.categorias.entries) {
final pista = banco.pistaDeCategoria(categoria.key) ?? categoria.key;
final pistaImpostor =
banco.pistaDeCategoria(categoria.key) ?? categoria.key;
mapa[categoria.key] = categoria.value
.map((palabra) => EntradaPalabraTraducida(palabra: palabra, pista: pista))
.map(
(palabra) => EntradaPalabraTraducida(
palabra: palabra,
pista:
banco.pistaDePalabra(palabra, categoria: categoria.key) ??
pistaImpostor,
),
)
.toList();
}
+16 -1
View File
@@ -8,12 +8,16 @@ class ConfigPartida {
final bool pistaImpostor;
final int? tiempoDebateSegundos; // null = sin límite
/// Cuando hay más de un impostor, cada impostor ve los nombres del resto.
final bool impostoresSeConocen;
const ConfigPartida({
this.modoMultimovil = false,
this.categoria = 'todas',
this.numImpostores = 1,
this.pistaImpostor = false,
this.tiempoDebateSegundos,
this.impostoresSeConocen = true,
});
}
@@ -49,6 +53,10 @@ class Partida {
final List<Jugador> jugadores;
final String palabraSecreta;
final String categoriaReal;
/// Pista que ve el impostor. Es específica de la palabra cuando el banco la
/// aporta; si no, cae al nombre de la categoría.
final String pistaImpostor;
FaseJuego fase;
int rondaActual;
final List<ResultadoVotacion> historialVotaciones;
@@ -59,11 +67,18 @@ class Partida {
required this.jugadores,
required this.palabraSecreta,
required this.categoriaReal,
String? pistaImpostor,
this.fase = FaseJuego.verPalabra,
this.rondaActual = 1,
List<ResultadoVotacion>? historialVotaciones,
this.ganador,
}) : historialVotaciones = historialVotaciones ?? [];
}) : pistaImpostor = pistaImpostor ?? categoriaReal,
historialVotaciones = historialVotaciones ?? [];
/// Nombres de los impostores, para que cada impostor sepa quiénes son sus
/// compañeros cuando la partida lo permite.
List<String> get nombresImpostores =>
jugadores.where((j) => j.esImpostor).map((j) => j.nombre).toList();
List<Jugador> get jugadoresActivos =>
jugadores.where((j) => !j.eliminado).toList();
+37
View File
@@ -154,10 +154,24 @@ class EstadoSalaMultijugador {
}
ResultadoOperacionSala registrarCliente(ClienteSala cliente) {
final existente = clientes[cliente.clientId];
if (existente != null) {
// Reconexión: el clientId es estable, el endpointId no. Conservamos lo
// que ya sabíamos del cliente y solo refrescamos por dónde se le habla.
clientes[cliente.clientId] = existente.copiar(
endpointId: cliente.endpointId,
nombre: cliente.nombre,
conectado: true,
);
return const ResultadoOperacionSala.ok();
}
clientes[cliente.clientId] = cliente;
return const ResultadoOperacionSala.ok();
}
/// True si ese cliente ya estuvo en la sala y vuelve tras una caída.
bool esReconexion(String clientId) => clientes.containsKey(clientId);
ResultadoOperacionSala crearUsuario(Usuario usuario) {
if (fase != FaseSalaMultijugador.lobby) {
return const ResultadoOperacionSala.error('sala_cerrada');
@@ -274,6 +288,8 @@ class EstadoSalaMultijugador {
if (entry.value.clienteIdSeleccionado == clientIdOrigen) {
usuarios[entry.key] = entry.value.copiar(
clienteIdSeleccionado: clientIdDestino,
// Se recuerda de quién eran para poder devolvérselos si vuelve.
absorbidoDe: entry.value.absorbidoDe ?? clientIdOrigen,
);
reasignados++;
}
@@ -281,6 +297,27 @@ class EstadoSalaMultijugador {
return reasignados;
}
/// Usuarios que el host absorbió de un cliente concreto.
List<Usuario> usuariosAbsorbidosDe(String clientId) => usuarios.values
.where((usuario) => usuario.absorbidoDe == clientId)
.toList();
/// Devuelve a su dueño original los usuarios que el host había absorbido.
/// Se usa cuando ese dispositivo se reconecta.
int devolverUsuariosAbsorbidos(String clientId) {
if (!clientes.containsKey(clientId)) return 0;
var devueltos = 0;
for (final entry in usuarios.entries.toList()) {
if (entry.value.absorbidoDe != clientId) continue;
usuarios[entry.key] = entry.value.copiar(
clienteIdSeleccionado: clientId,
limpiarAbsorbidoDe: true,
);
devueltos++;
}
return devueltos;
}
ResultadoOperacionSala validarInicio() {
if (fase != FaseSalaMultijugador.lobby) {
return const ResultadoOperacionSala.error('sala_cerrada');
+18 -3
View File
@@ -14,6 +14,11 @@ class SnapshotPartidaOnline {
final List<String> impostores;
final String? mensaje;
/// Whether impostor roles may travel over the wire. While the game is running
/// the host must never broadcast who the impostors are: every client would be
/// able to read it straight from the payload.
final bool revelarImpostores;
const SnapshotPartidaOnline({
required this.roomId,
required this.fase,
@@ -26,6 +31,7 @@ class SnapshotPartidaOnline {
this.historialVotaciones = const [],
this.impostores = const [],
this.mensaje,
this.revelarImpostores = false,
});
factory SnapshotPartidaOnline.desdePartida(
@@ -57,6 +63,7 @@ class SnapshotPartidaOnline {
.toList()
: const [],
mensaje: mensaje,
revelarImpostores: revelarImpostores,
);
}
@@ -67,7 +74,9 @@ class SnapshotPartidaOnline {
'categoria': categoria,
if (palabraSecreta != null) 'palabraSecreta': palabraSecreta,
if (ganador != null) 'ganador': ganador,
'jugadoresTodos': jugadores.map(_jugadorToJson).toList(),
'jugadoresTodos': jugadores
.map((jugador) => _jugadorToJson(jugador, revelarImpostores))
.toList(),
if (resultadoActual != null)
'resultadoActual': _resultadoToJson(resultadoActual!),
'historialVotaciones':
@@ -101,13 +110,19 @@ class SnapshotPartidaOnline {
.map((nombre) => nombre.toString())
.toList(),
mensaje: json['mensaje'] as String?,
revelarImpostores: jugadoresData.any(
(data) => (data as Map<String, dynamic>).containsKey('esImpostor'),
),
);
}
static Map<String, dynamic> _jugadorToJson(Jugador jugador) => {
static Map<String, dynamic> _jugadorToJson(
Jugador jugador,
bool revelarImpostores,
) => {
'id': jugador.id,
'nombre': jugador.nombre,
'esImpostor': jugador.esImpostor,
if (revelarImpostores) 'esImpostor': jugador.esImpostor,
'eliminado': jugador.eliminado,
};
+12
View File
@@ -7,6 +7,10 @@ class Usuario {
final String? foto;
final String? creadoPorClienteId;
final String? clienteIdSeleccionado;
/// Cliente que controlaba a este usuario antes de que el host lo absorbiera
/// por desconexión. Permite devolvérselo si ese dispositivo vuelve.
final String? absorbidoDe;
final int fuego;
final List<String> medallas;
@@ -18,6 +22,7 @@ class Usuario {
this.foto,
this.creadoPorClienteId,
this.clienteIdSeleccionado,
this.absorbidoDe,
this.fuego = 0,
this.medallas = const [],
});
@@ -33,9 +38,11 @@ class Usuario {
String? foto,
String? creadoPorClienteId,
String? clienteIdSeleccionado,
String? absorbidoDe,
int? fuego,
List<String>? medallas,
bool liberarSeleccion = false,
bool limpiarAbsorbidoDe = false,
}) {
return Usuario(
id: id ?? this.id,
@@ -47,6 +54,9 @@ class Usuario {
clienteIdSeleccionado: liberarSeleccion
? null
: (clienteIdSeleccionado ?? this.clienteIdSeleccionado),
absorbidoDe: limpiarAbsorbidoDe
? null
: (absorbidoDe ?? this.absorbidoDe),
fuego: fuego ?? this.fuego,
medallas: medallas ?? this.medallas,
);
@@ -61,6 +71,7 @@ class Usuario {
if (creadoPorClienteId != null) 'creadoPorClienteId': creadoPorClienteId,
if (clienteIdSeleccionado != null)
'clienteIdSeleccionado': clienteIdSeleccionado,
if (absorbidoDe != null) 'absorbidoDe': absorbidoDe,
if (fuego > 0) 'fuego': fuego,
if (medallas.isNotEmpty) 'medallas': medallas,
};
@@ -73,6 +84,7 @@ class Usuario {
foto: json['foto'] as String?,
creadoPorClienteId: json['creadoPorClienteId'] as String?,
clienteIdSeleccionado: json['clienteIdSeleccionado'] as String?,
absorbidoDe: json['absorbidoDe'] as String?,
fuego: (json['fuego'] as num?)?.toInt() ?? 0,
medallas: (json['medallas'] as List<dynamic>? ?? const [])
.map((valor) => valor.toString())
+38 -3
View File
@@ -34,6 +34,7 @@ class _PantallaCrearPartidaState extends State<PantallaCrearPartida> {
String _categoria = 'todas';
int _numImpostores = 1;
bool _pistaImpostor = false;
bool _impostoresSeConocen = true;
int? _tiempoDebate;
final List<String> _jugadores = [];
final _controladorNombre = TextEditingController();
@@ -65,8 +66,11 @@ class _PantallaCrearPartidaState extends State<PantallaCrearPartida> {
});
}
int get _maxImpostores =>
_modoMultimovil ? 4 : (_jugadores.length / 3).floor().clamp(1, 4);
/// En multidispositivo el número real de jugadores se conoce en el lobby, así
/// que aquí se permite el tope global; al iniciar se ajusta y se avisa.
int get _maxImpostores => _modoMultimovil
? 4
: EstadoJuego.maxImpostoresPara(_jugadores.length);
List<String> _etiquetasTiempo(AppLocalizations l10n) => [
l10n.noLimit,
@@ -139,6 +143,7 @@ class _PantallaCrearPartidaState extends State<PantallaCrearPartida> {
numImpostores: _numImpostores,
pistaImpostor: _pistaImpostor,
tiempoDebateSegundos: _tiempoDebate,
impostoresSeConocen: _impostoresSeConocen,
),
nombresJugadores: _jugadores,
);
@@ -228,11 +233,23 @@ class _PantallaCrearPartidaState extends State<PantallaCrearPartida> {
numImpostores: _numImpostores,
pistaImpostor: _pistaImpostor,
tiempoDebateSegundos: _tiempoDebate,
impostoresSeConocen: _impostoresSeConocen,
),
sala: sala,
);
final partida = estado.partida!;
// El tope de impostores depende de cuántos jugadores hay, y eso
// solo se sabe aquí. Si se recorta, hay que decirlo.
if (partida.impostoresTotales < _numImpostores) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
l10n.impostorsAdjusted(partida.impostoresTotales),
),
),
);
}
final asignaciones = partida.jugadores.map((jugador) {
final usuarioSala = sala.usuarios[jugador.id];
final clientId = usuarioSala?.clienteIdSeleccionado;
@@ -261,9 +278,12 @@ class _PantallaCrearPartidaState extends State<PantallaCrearPartida> {
nearby.enviarInicioPartidaMulti(
asignaciones: asignaciones,
palabraSecreta: partida.palabraSecreta,
categoria: _categoria,
categoria: partida.categoriaReal,
impostoresPorJugadorId: impostores,
jugadoresTodos: jugadoresTodos,
impostoresSeConocen: _impostoresSeConocen,
// La pista solo sale del host si la partida la tiene activada.
pistaImpostor: _pistaImpostor ? partida.pistaImpostor : null,
);
Navigator.pushReplacement(
@@ -596,6 +616,21 @@ class _PantallaCrearPartidaState extends State<PantallaCrearPartida> {
contentPadding: EdgeInsets.zero,
),
// Los impostores se reconocen entre ellos
SwitchListTile(
title: Text(l10n.impostorsKnowEachOther),
subtitle: Text(
_numImpostores > 1
? l10n.impostorsKnowEachOtherDescription
: l10n.impostorsKnowEachOtherNeedsTwo,
),
value: _impostoresSeConocen,
onChanged: _numImpostores > 1
? (v) => setState(() => _impostoresSeConocen = v)
: null,
contentPadding: EdgeInsets.zero,
),
// Temporizador
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
+4 -4
View File
@@ -15,7 +15,7 @@ class PantallaDebateCliente extends StatefulWidget {
final int? tiempoDebateSegundos;
final String? primerTurnoNombre;
final String? partidaId;
final String? pistaCategoria;
final String? pistaImpostor;
final List<Jugador> jugadores;
final List<JugadorInicioPartida> jugadoresControlados;
final VoidCallback onSolicitarVotacion;
@@ -25,7 +25,7 @@ class PantallaDebateCliente extends StatefulWidget {
this.tiempoDebateSegundos,
this.primerTurnoNombre,
this.partidaId,
this.pistaCategoria,
this.pistaImpostor,
this.jugadores = const [],
this.jugadoresControlados = const [],
required this.onSolicitarVotacion,
@@ -55,7 +55,7 @@ class _PantallaDebateClienteState extends State<PantallaDebateCliente> {
jugadores: widget.jugadores,
jugadoresControlados: widget.jugadoresControlados,
partidaId: widget.partidaId,
pistaCategoria: widget.pistaCategoria,
pistaImpostor: widget.pistaImpostor,
onVotos: _enviarVotos,
),
),
@@ -133,7 +133,7 @@ class _PantallaDebateClienteState extends State<PantallaDebateCliente> {
: () => mostrarRevisionPalabraOnline(
context: context,
jugadoresControlados: widget.jugadoresControlados,
pistaCategoria: widget.pistaCategoria,
pistaImpostor: widget.pistaImpostor,
),
),
IconButton(
@@ -21,13 +21,13 @@ import 'pantalla_revision_palabra.dart';
class PantallaFinPartidaOnline extends StatefulWidget {
final SnapshotPartidaOnline snapshot;
final List<JugadorInicioPartida> jugadoresControlados;
final String? pistaCategoria;
final String? pistaImpostor;
const PantallaFinPartidaOnline({
super.key,
required this.snapshot,
required this.jugadoresControlados,
this.pistaCategoria,
this.pistaImpostor,
});
@override
@@ -202,7 +202,7 @@ class _PantallaFinPartidaOnlineState extends State<PantallaFinPartidaOnline> {
: () => mostrarRevisionPalabraOnline(
context: context,
jugadoresControlados: widget.jugadoresControlados,
pistaCategoria: widget.pistaCategoria,
pistaImpostor: widget.pistaImpostor,
),
),
IconButton(
+142 -44
View File
@@ -9,6 +9,7 @@ import '../modelos/inicio_partida_multijugador.dart';
import '../modelos/jugador.dart';
import '../modelos/palabra.dart';
import '../modelos/partida.dart';
import '../modelos/sala_multijugador.dart';
import '../modelos/snapshot_partida_online.dart';
import '../servicios/servicio_historial_partidas.dart';
import '../servicios/servicio_nearby.dart';
@@ -40,6 +41,8 @@ class _PantallaGestorHostState extends State<PantallaGestorHost> {
String? _primerTurnoNombre;
final Map<String, bool> _clientesListos = {};
final Map<String, String> _votosRecibidos = {};
OnMensajeCallback? _listenerMensajes;
ServicioNearby? _nearby;
@override
void initState() {
@@ -65,28 +68,118 @@ class _PantallaGestorHostState extends State<PantallaGestorHost> {
void _registrarListeners() {
final nearby = context.read<ServicioNearby>();
nearby.onMensaje((endpointId, mensaje) {
_nearby = nearby;
_listenerMensajes = (endpointId, mensaje) {
if (!mounted) return;
if (mensaje.tipo == TipoMensaje.listo) {
setState(() => _clientesListos[endpointId] = true);
// Se indexa por clientId, no por endpointId: el endpoint cambia en
// cada reconexión y si no perderíamos el "ya la he visto".
final clientId = _clientIdDe(endpointId) ?? endpointId;
setState(() => _clientesListos[clientId] = true);
} else if (mensaje.tipo == TipoMensaje.unirse) {
// Con la partida ya en marcha, un `unirse` solo puede ser un móvil
// que vuelve tras caerse.
final nombre = mensaje.datos['nombre'] as String?;
if (nombre != null) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(AppLocalizations.of(context)!.playerRejoined(nombre)),
),
);
}
} else if (mensaje.tipo == TipoMensaje.solicitarResync) {
_responderResync(endpointId);
} else if (mensaje.tipo == TipoMensaje.voto) {
final votanteId = mensaje.datos['votanteId'] as String?;
final votoId =
mensaje.datos['votadoId'] as String? ??
mensaje.datos['votoporId'] as String?;
if (votanteId != null && votoId != null) {
context.read<EstadoJuego>().registrarVoto(votanteId, votoId);
setState(() => _votosRecibidos[votanteId] = votoId);
}
if (votanteId == null || votoId == null) return;
// Un jugador eliminado ya no vota, venga de donde venga el mensaje.
final partida = context.read<EstadoJuego>().partida;
final sigueVivo =
partida?.jugadoresActivos.any((j) => j.id == votanteId) ?? false;
if (!sigueVivo) return;
context.read<EstadoJuego>().registrarVoto(votanteId, votoId);
setState(() => _votosRecibidos[votanteId] = votoId);
}
});
};
nearby.onMensaje(_listenerMensajes!);
}
@override
void dispose() {
_timer?.cancel();
final listener = _listenerMensajes;
if (listener != null) _nearby?.removeMensajeListener(listener);
super.dispose();
}
String? _clientIdDe(String endpointId) {
return context
.read<ServicioNearby>()
.estadoSala
?.clientePorEndpoint(endpointId)
?.clientId;
}
/// Jugadores de la partida que controla un cliente concreto, con su palabra,
/// su rol y sus compañeros. Es lo que necesita un móvil para volver a jugar.
List<JugadorInicioPartida> _jugadoresDeCliente(
Partida partida,
EstadoSalaMultijugador sala,
String clientId,
) {
final estado = context.read<EstadoJuego>();
return sala
.usuariosPorCliente(clientId)
.where((usuario) => partida.jugadores.any((j) => j.id == usuario.id))
.map((usuario) {
final jugador = partida.jugadores.firstWhere(
(j) => j.id == usuario.id,
);
return JugadorInicioPartida(
jugadorId: jugador.id,
nombre: jugador.nombre,
esImpostor: jugador.esImpostor,
palabra: jugador.esImpostor ? null : partida.palabraSecreta,
companerosImpostores: estado.companerosImpostoresDe(jugador.id),
);
})
.toList();
}
/// Responde a un móvil que vuelve tras una caída con el estado completo:
/// en qué fase va la partida y qué jugadores le tocan.
Future<void> _responderResync(String endpointId) async {
final nearby = context.read<ServicioNearby>();
final estado = context.read<EstadoJuego>();
final partida = estado.partida;
final sala = nearby.estadoSala;
if (partida == null || sala == null) return;
final clientId = _clientIdDe(endpointId);
if (clientId == null) return;
final datos = _snapshot(fase: partida.fase.name).toJson();
datos['fase'] = partida.fase.name;
datos['jugadores'] = _jugadoresDeCliente(partida, sala, clientId)
.map((jugador) => jugador.toJson())
.toList();
if (partida.config.pistaImpostor) {
datos['pistaImpostor'] = partida.pistaImpostor;
}
if (partida.config.tiempoDebateSegundos != null) {
datos['tiempoDebateSegundos'] = partida.config.tiempoDebateSegundos;
}
if (_primerTurnoNombre != null) {
datos['primerTurnoNombre'] = _primerTurnoNombre;
}
await nearby.enviarResync(endpointId, datos);
if (mounted) setState(() {});
}
String _formatearTiempo(int segundos) {
final min = segundos ~/ 60;
final seg = segundos % 60;
@@ -152,8 +245,16 @@ class _PantallaGestorHostState extends State<PantallaGestorHost> {
);
}
// Solo bloquean los clientes que siguen conectados: un móvil caído no
// puede impedir que avance la partida.
final clientesPendientes =
nearby.estadoSala?.clientes.values
.where((cliente) => !cliente.esHost && cliente.conectado)
.map((cliente) => cliente.clientId) ??
const <String>[];
final todosListos =
_hostListo && _clientesListos.length >= nearby.jugadores.length;
_hostListo &&
clientesPendientes.every((id) => _clientesListos[id] == true);
final todosVotaron = estado.todosHanVotado();
return Scaffold(
@@ -172,8 +273,8 @@ class _PantallaGestorHostState extends State<PantallaGestorHost> {
partida,
nearby,
),
pistaCategoria: partida.config.pistaImpostor
? partida.categoriaReal
pistaImpostor: partida.config.pistaImpostor
? partida.pistaImpostor
: null,
),
),
@@ -287,7 +388,16 @@ class _PantallaGestorHostState extends State<PantallaGestorHost> {
texto: AppLocalizations.of(context)!.assumeOnThisPhone,
icono: Icons.person_add_alt_1,
assetIconPath: 'assets/ui/generated/actions/action_add_player.webp',
onPressed: () => nearby.asumirUsuariosDesconectados(),
onPressed: () async {
// Son jugadores nuevos para este móvil: sus palabras están
// sin ver y sus votos sin emitir.
final fase = context.read<EstadoJuego>().partida?.fase;
await nearby.asumirUsuariosDesconectados();
if (!mounted) return;
setState(() {
if (fase == FaseJuego.verPalabra) _hostListo = false;
});
},
),
),
),
@@ -422,7 +532,9 @@ class _PantallaGestorHostState extends State<PantallaGestorHost> {
(jugador) => _buildJugadorTile(
jugador.nombre,
false,
_clientesListos[jugador.endpointId] ?? false,
_clientesListos[_clientIdDe(jugador.endpointId) ??
jugador.endpointId] ??
false,
),
),
const SizedBox(height: 12),
@@ -451,22 +563,7 @@ class _PantallaGestorHostState extends State<PantallaGestorHost> {
) {
final sala = nearby.estadoSala;
if (sala == null) return const [];
return sala
.usuariosPorCliente(sala.hostClientId)
.where((usuario) => partida.jugadores.any((j) => j.id == usuario.id))
.map((usuario) {
final jugador = partida.jugadores.firstWhere(
(j) => j.id == usuario.id,
);
return JugadorInicioPartida(
jugadorId: jugador.id,
nombre: jugador.nombre,
esImpostor: jugador.esImpostor,
palabra: jugador.palabra ?? partida.palabraSecreta,
);
})
.toList();
return _jugadoresDeCliente(partida, sala, sala.hostClientId);
}
void _mostrarPalabraHost(BuildContext context) {
@@ -483,8 +580,8 @@ class _PantallaGestorHostState extends State<PantallaGestorHost> {
MaterialPageRoute(
builder: (_) => PantallaPalabrasCliente(
jugadores: jugadoresHost,
pistaCategoria: partida.config.pistaImpostor
? partida.categoriaReal
pistaImpostor: partida.config.pistaImpostor
? partida.pistaImpostor
: null,
onTodosVistos: () {
setState(() => _hostListo = true);
@@ -508,7 +605,8 @@ class _PantallaGestorHostState extends State<PantallaGestorHost> {
esImpostor: hostLocal.esImpostor,
palabra: partida.palabraSecreta,
pistaActiva: partida.config.pistaImpostor,
categoria: partida.categoriaReal,
pista: partida.pistaImpostor,
companerosImpostores: estado.companerosImpostoresDe(hostLocal.id),
onVisto: () => setState(() => _hostListo = true),
),
),
@@ -767,8 +865,8 @@ class _PantallaGestorHostState extends State<PantallaGestorHost> {
jugadores: partida.jugadoresActivos,
jugadoresControlados: jugadoresHost,
partidaId: context.read<ServicioNearby>().roomId,
pistaCategoria: partida.config.pistaImpostor
? partida.categoriaReal
pistaImpostor: partida.config.pistaImpostor
? partida.pistaImpostor
: null,
onVotos: (votos) {
for (final entry in votos.entries) {
@@ -1029,7 +1127,8 @@ class _PantallaRevelarPalabraHost extends StatefulWidget {
final bool esImpostor;
final String palabra;
final bool pistaActiva;
final String categoria;
final String pista;
final List<String>? companerosImpostores;
final VoidCallback onVisto;
const _PantallaRevelarPalabraHost({
@@ -1037,7 +1136,8 @@ class _PantallaRevelarPalabraHost extends StatefulWidget {
required this.esImpostor,
required this.palabra,
required this.pistaActiva,
required this.categoria,
required this.pista,
required this.companerosImpostores,
required this.onVisto,
});
@@ -1120,15 +1220,13 @@ class _PantallaRevelarPalabraHostState
],
if (widget.esImpostor && widget.pistaActiva) ...[
const SizedBox(height: 12),
Text(
l10n.clueCategory(
BancoPalabras.nombreBonitoCategoria(
widget.categoria,
l10n,
),
),
style: Theme.of(context).textTheme.bodyLarge
?.copyWith(color: TemaApp.colorNaranja),
PistaImpostorFarolero(pista: widget.pista),
],
if (widget.esImpostor &&
widget.companerosImpostores != null) ...[
const SizedBox(height: 12),
CompanerosImpostorFarolero(
nombres: widget.companerosImpostores!,
),
],
],
+4 -4
View File
@@ -10,14 +10,14 @@ import 'package:farolero/tema/tema_app.dart';
class PantallaPalabraCliente extends StatefulWidget {
final String palabra;
final bool esImpostor;
final String? pistaCategoria;
final String? pistaImpostor;
final VoidCallback onVisto;
const PantallaPalabraCliente({
super.key,
required this.palabra,
required this.esImpostor,
this.pistaCategoria,
this.pistaImpostor,
required this.onVisto,
});
@@ -124,7 +124,7 @@ class _PantallaPalabraClienteState extends State<PantallaPalabraCliente> {
const SizedBox(height: 16),
// Pista para impostores
if (widget.esImpostor && widget.pistaCategoria != null) ...[
if (widget.esImpostor && widget.pistaImpostor != null) ...[
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
@@ -138,7 +138,7 @@ class _PantallaPalabraClienteState extends State<PantallaPalabraCliente> {
const SizedBox(width: 8),
Flexible(
child: Text(
'\u{1F3AD} ${l10n.clueIs(widget.pistaCategoria!)}',
'\u{1F3AD} ${l10n.clueIs(widget.pistaImpostor!)}',
style: const TextStyle(color: TemaApp.colorAcento),
),
),
+11 -7
View File
@@ -7,13 +7,13 @@ import 'package:farolero/tema/tema_app.dart';
/// Reveal secuencial para clientes que manejan uno o varios jugadores.
class PantallaPalabrasCliente extends StatefulWidget {
final List<JugadorInicioPartida> jugadores;
final String? pistaCategoria;
final String? pistaImpostor;
final VoidCallback onTodosVistos;
const PantallaPalabrasCliente({
super.key,
required this.jugadores,
this.pistaCategoria,
this.pistaImpostor,
required this.onTodosVistos,
});
@@ -113,12 +113,16 @@ class _PantallaPalabrasClienteState extends State<PantallaPalabrasCliente> {
),
),
),
if (_visible && actual.esImpostor && widget.pistaCategoria != null) ...[
if (_visible && actual.esImpostor && widget.pistaImpostor != null) ...[
const SizedBox(height: 12),
Text(
l10n.clueIs(widget.pistaCategoria!),
style: const TextStyle(color: TemaApp.colorNaranja),
textAlign: TextAlign.center,
PistaImpostorFarolero(pista: widget.pistaImpostor!),
],
if (_visible &&
actual.esImpostor &&
actual.companerosImpostores != null) ...[
const SizedBox(height: 12),
CompanerosImpostorFarolero(
nombres: actual.companerosImpostores!,
),
],
const SizedBox(height: 12),
+6 -6
View File
@@ -16,13 +16,13 @@ import 'package:provider/provider.dart';
class PantallaResultadoOnline extends StatefulWidget {
final SnapshotPartidaOnline snapshot;
final List<JugadorInicioPartida> jugadoresControlados;
final String? pistaCategoria;
final String? pistaImpostor;
const PantallaResultadoOnline({
super.key,
required this.snapshot,
required this.jugadoresControlados,
this.pistaCategoria,
this.pistaImpostor,
});
@override
@@ -86,7 +86,7 @@ class _PantallaResultadoOnlineState extends State<PantallaResultadoOnline> {
tiempoDebateSegundos: datos['tiempoDebateSegundos'] as int?,
primerTurnoNombre: datos['primerTurnoNombre'] as String?,
partidaId: snapshot.roomId,
pistaCategoria: widget.pistaCategoria,
pistaImpostor: widget.pistaImpostor,
jugadores: snapshot.jugadores,
jugadoresControlados: widget.jugadoresControlados,
onSolicitarVotacion: _solicitarVotacion,
@@ -103,7 +103,7 @@ class _PantallaResultadoOnlineState extends State<PantallaResultadoOnline> {
jugadores: snapshot.jugadores,
jugadoresControlados: widget.jugadoresControlados,
partidaId: snapshot.roomId,
pistaCategoria: widget.pistaCategoria,
pistaImpostor: widget.pistaImpostor,
onVotos: _enviarVotos,
),
),
@@ -117,7 +117,7 @@ class _PantallaResultadoOnlineState extends State<PantallaResultadoOnline> {
builder: (_) => PantallaFinPartidaOnline(
snapshot: snapshot,
jugadoresControlados: widget.jugadoresControlados,
pistaCategoria: widget.pistaCategoria,
pistaImpostor: widget.pistaImpostor,
),
),
);
@@ -197,7 +197,7 @@ class _PantallaResultadoOnlineState extends State<PantallaResultadoOnline> {
: () => mostrarRevisionPalabraOnline(
context: context,
jugadoresControlados: widget.jugadoresControlados,
pistaCategoria: widget.pistaCategoria,
pistaImpostor: widget.pistaImpostor,
),
),
IconButton(
+12 -9
View File
@@ -7,7 +7,7 @@ import 'package:farolero/tema/tema_app.dart';
Future<void> mostrarRevisionPalabraOnline({
required BuildContext context,
required List<JugadorInicioPartida> jugadoresControlados,
String? pistaCategoria,
String? pistaImpostor,
}) async {
if (jugadoresControlados.isEmpty) return;
@@ -45,18 +45,18 @@ Future<void> mostrarRevisionPalabraOnline({
context: context,
builder: (dialogContext) => _DialogoRevisionPalabra(
jugador: jugador,
pistaCategoria: pistaCategoria,
pistaImpostor: pistaImpostor,
),
);
}
class _DialogoRevisionPalabra extends StatelessWidget {
final JugadorInicioPartida jugador;
final String? pistaCategoria;
final String? pistaImpostor;
const _DialogoRevisionPalabra({
required this.jugador,
required this.pistaCategoria,
required this.pistaImpostor,
});
@override
@@ -106,12 +106,15 @@ class _DialogoRevisionPalabra extends StatelessWidget {
)
else
TarjetaPalabraFarolero(palabra: jugador.palabra ?? ''),
if (jugador.esImpostor && pistaCategoria != null) ...[
if (jugador.esImpostor && pistaImpostor != null) ...[
const SizedBox(height: 12),
Text(
l10n.clueIs(pistaCategoria!),
style: const TextStyle(color: TemaApp.colorNaranja),
textAlign: TextAlign.center,
PistaImpostorFarolero(pista: pistaImpostor!),
],
if (jugador.esImpostor &&
jugador.companerosImpostores != null) ...[
const SizedBox(height: 12),
CompanerosImpostorFarolero(
nombres: jugador.companerosImpostores!,
),
],
],
+118 -10
View File
@@ -3,6 +3,7 @@ import 'package:mobile_scanner/mobile_scanner.dart';
import 'package:provider/provider.dart';
import 'package:farolero/l10n/generated/app_localizations.dart';
import '../modelos/jugador.dart';
import '../modelos/partida.dart';
import '../modelos/inicio_partida_multijugador.dart';
import '../modelos/snapshot_partida_online.dart';
import '../modelos/usuario.dart';
@@ -41,10 +42,12 @@ class _PantallaUnirseState extends State<PantallaUnirse> {
// Estado del juego recibido del host
String? _palabraRecibida;
bool _esImpostor = false;
String? _pistaCategoria;
String? _pistaImpostor;
String? _partidaId;
final List<Jugador> _jugadores = [];
final List<JugadorInicioPartida> _jugadoresControlados = [];
OnMensajeCallback? _listenerMensajes;
ServicioNearby? _nearby;
@override
void initState() {
@@ -61,7 +64,8 @@ class _PantallaUnirseState extends State<PantallaUnirse> {
void _registrarListenerPartida() {
final nearby = context.read<ServicioNearby>();
nearby.onMensaje((endpointId, mensaje) {
_nearby = nearby;
_listenerMensajes = (endpointId, mensaje) {
if (!mounted) return;
if (mensaje.tipo == TipoMensaje.partidaInicio) {
// El host ha iniciado la partida — nos ha enviado nuestra palabra
@@ -105,7 +109,9 @@ class _PantallaUnirseState extends State<PantallaUnirse> {
);
}
}
_pistaCategoria = mensaje.datos['categoria'] as String?;
// La pista solo llega si la partida la tiene activada; la categoría
// no vale como pista porque puede ser 'todas'.
_pistaImpostor = mensaje.datos['pistaImpostor'] as String?;
_partidaId = (mensaje.datos['roomId'] as String?) ??
nearby.roomId ??
(mensaje.datos['clientId'] as String?) ??
@@ -115,6 +121,8 @@ class _PantallaUnirseState extends State<PantallaUnirse> {
if (mounted && (_jugadoresControlados.isNotEmpty || _palabraRecibida != null)) {
_navegarAPalabra();
}
} else if (mensaje.tipo == TipoMensaje.resync) {
_aplicarResync(mensaje.datos);
} else if (mensaje.tipo == TipoMensaje.fase) {
final fase = mensaje.datos['fase'] as String?;
_actualizarSnapshotSiExiste(mensaje.datos);
@@ -128,7 +136,43 @@ class _PantallaUnirseState extends State<PantallaUnirse> {
_actualizarSnapshotSiExiste(mensaje.datos);
if (mounted) _navegarFinPartida(mensaje.datos);
}
};
nearby.onMensaje(_listenerMensajes!);
}
/// Reincorpora este móvil a una partida ya empezada tras una caída.
///
/// El host manda el estado completo, así que se reconstruye todo —jugadores
/// controlados, pista, censo— antes de saltar a la pantalla de la fase en
/// curso. Se descartan las rutas viejas: la pila de antes ya no vale.
void _aplicarResync(Map<String, dynamic> datos) {
final controlados = (datos['jugadores'] as List<dynamic>? ?? const [])
.map((json) => JugadorInicioPartida.fromJson(
json as Map<String, dynamic>,
))
.toList();
setState(() {
_jugadoresControlados
..clear()
..addAll(controlados);
_pistaImpostor = datos['pistaImpostor'] as String? ?? _pistaImpostor;
_partidaId = (datos['roomId'] as String?) ??
_partidaId ??
context.read<ServicioNearby>().roomId;
});
_actualizarSnapshotSiExiste(datos);
if (!mounted) return;
Navigator.of(context).popUntil((route) => route.isFirst);
final fase = datos['fase'] as String?;
if (fase == null || fase == FaseJuego.verPalabra.name) {
// Aún no ha empezado el debate: que vuelva a ver su palabra.
if (_jugadoresControlados.isNotEmpty) _navegarAPalabra();
return;
}
_navegarSegunFase(fase, datos);
}
void _navegarAPalabra() {
@@ -137,7 +181,7 @@ class _PantallaUnirseState extends State<PantallaUnirse> {
MaterialPageRoute(
builder: (_) => PantallaPalabrasCliente(
jugadores: List.unmodifiable(_jugadoresControlados),
pistaCategoria: _pistaCategoria,
pistaImpostor: _pistaImpostor,
onTodosVistos: () {
final nearby = context.read<ServicioNearby>();
if (nearby.hostEndpointId != null) {
@@ -159,7 +203,7 @@ class _PantallaUnirseState extends State<PantallaUnirse> {
builder: (_) => PantallaPalabraCliente(
palabra: _palabraRecibida ?? '',
esImpostor: _esImpostor,
pistaCategoria: _pistaCategoria,
pistaImpostor: _pistaImpostor,
onVisto: () {
// Enviar "listo" al host y volver a la espera
final nearby = context.read<ServicioNearby>();
@@ -190,7 +234,7 @@ class _PantallaUnirseState extends State<PantallaUnirse> {
_partidaId = (datos['roomId'] as String?) ??
_partidaId ??
context.read<ServicioNearby>().roomId;
_pistaCategoria = (datos['categoria'] as String?) ?? _pistaCategoria;
});
}
@@ -206,7 +250,7 @@ class _PantallaUnirseState extends State<PantallaUnirse> {
primerTurnoNombre:
datosFase?['primerTurnoNombre'] as String?,
partidaId: _partidaId ?? context.read<ServicioNearby>().roomId,
pistaCategoria: _pistaCategoria,
pistaImpostor: _pistaImpostor,
jugadores: List.unmodifiable(_jugadores),
jugadoresControlados: List.unmodifiable(_jugadoresControlados),
onSolicitarVotacion: () {
@@ -232,7 +276,7 @@ class _PantallaUnirseState extends State<PantallaUnirse> {
jugadores: _jugadores,
jugadoresControlados: List.unmodifiable(_jugadoresControlados),
partidaId: _partidaId ?? context.read<ServicioNearby>().roomId,
pistaCategoria: _pistaCategoria,
pistaImpostor: _pistaImpostor,
onVotos: (votos) {
final nearby = context.read<ServicioNearby>();
if (nearby.hostEndpointId != null) {
@@ -273,7 +317,7 @@ class _PantallaUnirseState extends State<PantallaUnirse> {
builder: (_) => PantallaResultadoOnline(
snapshot: snapshot,
jugadoresControlados: List.unmodifiable(_jugadoresControlados),
pistaCategoria: _pistaCategoria,
pistaImpostor: _pistaImpostor,
),
),
);
@@ -287,13 +331,15 @@ class _PantallaUnirseState extends State<PantallaUnirse> {
builder: (_) => PantallaFinPartidaOnline(
snapshot: snapshot,
jugadoresControlados: List.unmodifiable(_jugadoresControlados),
pistaCategoria: _pistaCategoria,
pistaImpostor: _pistaImpostor,
),
),
);
}
@override
void dispose() {
final listener = _listenerMensajes;
if (listener != null) _nearby?.removeMensajeListener(listener);
_nombreController.dispose();
super.dispose();
}
@@ -419,6 +465,10 @@ class _PantallaUnirseState extends State<PantallaUnirse> {
final l10n = AppLocalizations.of(context)!;
final nearby = context.watch<ServicioNearby>();
if (nearby.reconectando && !nearby.conectado) {
return _buildReconectando(context, l10n, nearby);
}
// Si estamos conectados → pantalla de espera
if (nearby.conectado && !nearby.esHost) {
return _buildPantallaEspera(context, l10n);
@@ -704,6 +754,64 @@ class _PantallaUnirseState extends State<PantallaUnirse> {
);
}
// ==================== RECONEXIÓN ====================
Widget _buildReconectando(
BuildContext context,
AppLocalizations l10n,
ServicioNearby nearby,
) {
return Scaffold(
appBar: AppBar(
title: Text(_salaSeleccionada ?? l10n.joinGameTitle),
automaticallyImplyLeading: false,
actions: [
IconButton(
tooltip: l10n.leaveGame,
icon: IconoFarolero(Icons.close),
onPressed: () async {
await nearby.desconectar();
if (!context.mounted) return;
setState(() {
_buscando = false;
_conectando = false;
});
},
),
],
),
body: FondoFarolero(
intenso: true,
child: Center(
child: Padding(
padding: const EdgeInsets.all(32),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const _JoinLobbySignalArt(height: 180),
const SizedBox(height: 16),
EncabezadoFarolero(
icono: Icons.wifi_tethering_off,
titulo: l10n.reconnecting,
subtitulo: l10n.reconnectingHint,
color: TemaApp.colorNaranja,
trailing: const SizedBox(
width: 24,
height: 24,
child: CircularProgressIndicator(
strokeWidth: 2.4,
color: TemaApp.colorNaranja,
),
),
),
],
),
),
),
),
);
}
// ==================== ESPERA ====================
Widget _buildPantallaEspera(BuildContext context, AppLocalizations l10n) {
+13 -8
View File
@@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
import 'package:farolero/l10n/generated/app_localizations.dart';
import 'package:provider/provider.dart';
import '../estado/estado_juego.dart';
import '../modelos/palabra.dart';
import '../tema/componentes_farolero.dart';
import '../tema/tema_app.dart';
import 'pantalla_debate.dart';
@@ -104,7 +103,8 @@ class _PantallaVerPalabraState extends State<PantallaVerPalabra> {
esImpostor: jugador.esImpostor,
palabra: partida.palabraSecreta,
pistaActiva: partida.config.pistaImpostor,
categoria: partida.categoriaReal,
pista: partida.pistaImpostor,
companerosImpostores: estado.companerosImpostoresDe(jugador.id),
onVisto: () {
setState(() => _hanVisto.add(jugadorId));
},
@@ -119,7 +119,8 @@ class _PantallaRevelarPalabra extends StatefulWidget {
final bool esImpostor;
final String palabra;
final bool pistaActiva;
final String categoria;
final String pista;
final List<String>? companerosImpostores;
final VoidCallback onVisto;
const _PantallaRevelarPalabra({
@@ -127,7 +128,8 @@ class _PantallaRevelarPalabra extends StatefulWidget {
required this.esImpostor,
required this.palabra,
required this.pistaActiva,
required this.categoria,
required this.pista,
required this.companerosImpostores,
required this.onVisto,
});
@@ -191,10 +193,13 @@ class _PantallaRevelarPalabraState extends State<_PantallaRevelarPalabra> {
],
if (widget.esImpostor && widget.pistaActiva) ...[
const SizedBox(height: 12),
Text(
l10n.clueCategory(BancoPalabras.nombreBonitoCategoria(widget.categoria, l10n)),
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.bodyLarge?.copyWith(color: TemaApp.colorNaranja),
PistaImpostorFarolero(pista: widget.pista),
],
if (widget.esImpostor &&
widget.companerosImpostores != null) ...[
const SizedBox(height: 12),
CompanerosImpostorFarolero(
nombres: widget.companerosImpostores!,
),
],
],
+40 -80
View File
@@ -2,15 +2,10 @@ import 'package:flutter/material.dart';
import 'package:farolero/l10n/generated/app_localizations.dart';
import 'package:farolero/modelos/inicio_partida_multijugador.dart';
import 'package:farolero/modelos/jugador.dart';
import 'package:farolero/modelos/partida.dart';
import 'package:farolero/modelos/snapshot_partida_online.dart';
import 'package:farolero/pantallas/pantalla_notas_online.dart';
import 'package:farolero/pantallas/pantalla_revision_palabra.dart';
import 'package:farolero/pantallas/pantalla_resultado_online.dart';
import 'package:farolero/servicios/servicio_nearby.dart';
import 'package:farolero/tema/componentes_farolero.dart';
import 'package:farolero/tema/tema_app.dart';
import 'package:provider/provider.dart';
/// Pantalla de votación para cliente multidispositivo.
/// Un cliente puede manejar uno o varios jugadores, por eso se recoge un voto
@@ -19,7 +14,7 @@ class PantallaVotacionCliente extends StatefulWidget {
final List<Jugador> jugadores;
final List<JugadorInicioPartida> jugadoresControlados;
final String? partidaId;
final String? pistaCategoria;
final String? pistaImpostor;
final Function(Map<String, String> votos) onVotos;
const PantallaVotacionCliente({
@@ -27,7 +22,7 @@ class PantallaVotacionCliente extends StatefulWidget {
required this.jugadores,
this.jugadoresControlados = const [],
this.partidaId,
this.pistaCategoria,
this.pistaImpostor,
required this.onVotos,
});
@@ -37,75 +32,31 @@ class PantallaVotacionCliente extends StatefulWidget {
class _PantallaVotacionClienteState extends State<PantallaVotacionCliente> {
final Map<String, String> _votosPorVotante = {};
OnMensajeCallback? _listener;
ServicioNearby? _nearby;
List<JugadorInicioPartida> get _votantes => widget.jugadoresControlados;
/// Solo los jugadores vivos pueden ser votados.
List<Jugador> get _votables =>
widget.jugadores.where((jugador) => !jugador.eliminado).toList();
/// Y solo los jugadores vivos que controla este dispositivo pueden votar.
List<JugadorInicioPartida> get _votantes => widget.jugadoresControlados
.where(
(controlado) =>
_votables.any((jugador) => jugador.id == controlado.jugadorId),
)
.toList();
/// Protocolo antiguo: el cliente no recibió jugadores controlados y emite un
/// único voto sin identificar al votante.
bool get _modoLegacy => widget.jugadoresControlados.isEmpty;
/// Todos los jugadores de este dispositivo están eliminados: no vota nadie.
bool get _sinVotantesVivos => !_modoLegacy && _votantes.isEmpty;
bool get _votacionCompleta {
if (_votantes.isEmpty) return _votosPorVotante.containsKey('_legacy');
return _votantes.every((votante) => _votosPorVotante[votante.jugadorId] != null);
}
@override
void initState() {
super.initState();
_listener = (endpointId, mensaje) {
if (mensaje.tipo != TipoMensaje.votacionResultado || !mounted) return;
if (mensaje.datos.containsKey('jugadoresTodos')) {
final snapshot = SnapshotPartidaOnline.fromJson(mensaje.datos);
Navigator.of(context).pushReplacement(
MaterialPageRoute(
builder: (_) => PantallaResultadoOnline(
snapshot: snapshot,
jugadoresControlados: widget.jugadoresControlados,
pistaCategoria: widget.pistaCategoria,
),
),
);
} else {
final votosRaw = mensaje.datos['votos'] as Map<dynamic, dynamic>? ?? {};
final snapshot = SnapshotPartidaOnline(
roomId: widget.partidaId,
fase: 'resultado',
ronda: 1,
categoria: '',
jugadores: widget.jugadores,
resultadoActual: ResultadoVotacion(
eliminadoId: mensaje.datos['eliminadoId'] as String? ?? '',
eliminadoNombre: mensaje.datos['eliminadoNombre'] as String? ?? '?',
eraImpostor: mensaje.datos['eraImpostor'] as bool? ?? false,
votos: votosRaw.map(
(key, value) => MapEntry(key.toString(), value.toString()),
),
),
);
Navigator.of(context).pushReplacement(
MaterialPageRoute(
builder: (_) => PantallaResultadoOnline(
snapshot: snapshot,
jugadoresControlados: widget.jugadoresControlados,
pistaCategoria: widget.pistaCategoria,
),
),
);
}
};
WidgetsBinding.instance.addPostFrameCallback((_) {
final listener = _listener;
if (listener != null && mounted) {
_nearby = context.read<ServicioNearby>();
_nearby!.onMensaje(listener);
}
});
}
@override
void dispose() {
final listener = _listener;
if (listener != null) {
_nearby?.removeMensajeListener(listener);
}
super.dispose();
if (_sinVotantesVivos) return false;
if (_modoLegacy) return _votosPorVotante.containsKey('_legacy');
return _votantes.every(
(votante) => _votosPorVotante[votante.jugadorId] != null,
);
}
@override
@@ -128,7 +79,7 @@ class _PantallaVotacionClienteState extends State<PantallaVotacionCliente> {
: () => mostrarRevisionPalabraOnline(
context: context,
jugadoresControlados: widget.jugadoresControlados,
pistaCategoria: widget.pistaCategoria,
pistaImpostor: widget.pistaImpostor,
),
),
IconButton(
@@ -172,7 +123,15 @@ class _PantallaVotacionClienteState extends State<PantallaVotacionCliente> {
),
const SizedBox(height: 16),
Expanded(
child: _votantes.isEmpty
child: _sinVotantesVivos
? Center(
child: EstadoVacioFarolero(
icono: Icons.hourglass_empty,
titulo: l10n.eliminatedCannotVote,
subtitulo: l10n.waitingVoting,
),
)
: _modoLegacy
? _buildSelectorLegacy()
: ListView.builder(
itemCount: _votantes.length,
@@ -200,15 +159,16 @@ class _PantallaVotacionClienteState extends State<PantallaVotacionCliente> {
bool get _puedeAbrirNotas {
return widget.partidaId != null &&
widget.jugadores.isNotEmpty &&
_votables.isNotEmpty &&
widget.jugadoresControlados.isNotEmpty;
}
Widget _buildSelectorLegacy() {
final votables = _votables;
return ListView.builder(
itemCount: widget.jugadores.length,
itemCount: votables.length,
itemBuilder: (context, index) {
final jugador = widget.jugadores[index];
final jugador = votables[index];
final selected = _votosPorVotante['_legacy'] == jugador.id;
return _buildJugadorVotable(
jugador: jugador,
@@ -236,7 +196,7 @@ class _PantallaVotacionClienteState extends State<PantallaVotacionCliente> {
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 8),
...widget.jugadores.asMap().entries.map((entry) {
..._votables.asMap().entries.map((entry) {
final jugador = entry.value;
final selected = _votosPorVotante[votante.jugadorId] == jugador.id;
return _buildJugadorVotable(
+47
View File
@@ -0,0 +1,47 @@
import 'dart:math';
import 'package:shared_preferences/shared_preferences.dart';
/// Identificador estable de este dispositivo.
///
/// Nearby Connections asigna un `endpointId` nuevo en cada conexión, así que no
/// sirve para reconocer a un móvil que se reconecta. Este id se guarda en disco
/// y sobrevive a caídas de conexión, cierres de la app y reinicios.
class IdentidadDispositivo {
static const _clave = 'dispositivo.id';
static String? _cache;
/// Devuelve el id del dispositivo, creándolo la primera vez.
static Future<String> obtener() async {
final cacheado = _cache;
if (cacheado != null) return cacheado;
final prefs = await SharedPreferences.getInstance();
final guardado = prefs.getString(_clave);
if (guardado != null && guardado.isNotEmpty) {
_cache = guardado;
return guardado;
}
final nuevo = _generar();
await prefs.setString(_clave, nuevo);
_cache = nuevo;
return nuevo;
}
/// Id ya cargado en memoria, si existe. Útil donde no se puede esperar.
static String? get cacheado => _cache;
static String _generar() {
final rng = Random.secure();
final bytes = List<int>.generate(8, (_) => rng.nextInt(256));
final hex = bytes
.map((b) => b.toRadixString(16).padLeft(2, '0'))
.join();
return 'dev-$hex';
}
/// Solo para pruebas: fija el id en memoria sin tocar disco.
static void fijarParaPruebas(String? id) => _cache = id;
}
+184 -12
View File
@@ -5,6 +5,7 @@ import 'package:nearby_connections/nearby_connections.dart';
import '../modelos/inicio_partida_multijugador.dart';
import '../modelos/sala_multijugador.dart';
import '../modelos/usuario.dart';
import 'identidad_dispositivo.dart';
/// Tipos de mensajes en el protocolo P2P.
enum TipoMensaje {
@@ -26,6 +27,10 @@ enum TipoMensaje {
eliminarUsuario,
errorOperacion,
usuarioNuevo,
// Reconexión: el cliente pide el estado de la partida en curso y el host se
// lo devuelve completo.
solicitarResync,
resync,
// Compatibilidad con versiones previas del protocolo.
usuarioEliminado,
usuariosActualizados,
@@ -94,6 +99,17 @@ class ServicioNearby extends ChangeNotifier {
final Map<String, Usuario> _usuariosPool = {};
Timer? _heartbeatTimer;
String? _miDeviceId;
bool _reconectando = false;
bool _partidaEnCursoAlEntrar = false;
bool _cerrando = false;
String? _nombreHostConectado;
Timer? _limiteReconexion;
/// Cuánto se insiste en volver antes de rendirse. Sin tope, un móvil cuyo
/// host se ha ido se quedaría escaneando y gastando batería para siempre.
static const _ventanaReconexion = Duration(minutes: 3);
String? _palabraRecibida;
bool? _soyImpostor;
String? _faseActual;
@@ -102,6 +118,13 @@ class ServicioNearby extends ChangeNotifier {
bool get esHost => _esHost;
bool get conectado => _conectado;
/// El cliente perdió la conexión y está intentando volver por su cuenta.
bool get reconectando => _reconectando;
/// Al registrarse, el host indicó que ya había una partida empezada.
bool get partidaEnCursoAlEntrar => _partidaEnCursoAlEntrar;
String? get miDeviceId => _miDeviceId;
bool get buscando => _buscando;
bool get anunciando => _anunciando;
String? get miEndpointId => _miEndpointId;
@@ -231,6 +254,7 @@ class ServicioNearby extends ChangeNotifier {
_miNombre = miNombre;
_roomId = DateTime.now().microsecondsSinceEpoch.toString();
_miClientId = _hostClientId;
_miDeviceId = await IdentidadDispositivo.obtener();
_estadoSala = EstadoSalaMultijugador.crear(
roomId: _roomId!,
nombreSala: nombreSala,
@@ -295,6 +319,7 @@ class ServicioNearby extends ChangeNotifier {
_miAvatar = miAvatar;
_miFuego = miFuego;
_miMedallas = miMedallas;
_miDeviceId ??= await IdentidadDispositivo.obtener();
try {
final resultado = await Nearby().startDiscovery(
@@ -330,6 +355,8 @@ class ServicioNearby extends ChangeNotifier {
_miAvatar = miAvatar;
_miFuego = miFuego;
_miMedallas = miMedallas;
_miDeviceId ??= await IdentidadDispositivo.obtener();
_nombreHostConectado = _hostsEncontrados[endpointId];
try {
await Nearby().requestConnection(
miNombre,
@@ -364,6 +391,10 @@ class ServicioNearby extends ChangeNotifier {
} else {
_hostEndpointId = endpointId;
_conectado = true;
_reconectando = false;
_buscando = false;
_limiteReconexion?.cancel();
_limiteReconexion = null;
_iniciarHeartbeatCliente();
enviarMensaje(
endpointId,
@@ -375,6 +406,7 @@ class ServicioNearby extends ChangeNotifier {
if (_miAvatar != null) 'avatar': _miAvatar,
'fuego': _miFuego,
'medallas': _miMedallas,
if (_miDeviceId != null) 'deviceId': _miDeviceId,
},
),
);
@@ -406,10 +438,49 @@ class ServicioNearby extends ChangeNotifier {
_conectado = false;
_hostEndpointId = null;
_heartbeatTimer?.cancel();
// Conservamos clientId y deviceId: son la llave para que el host nos
// reconozca cuando volvamos.
_iniciarReconexionCliente();
}
notifyListeners();
}
/// Relanza el descubrimiento tras una caída para volver a la misma sala.
Future<void> _iniciarReconexionCliente() async {
if (_esHost || _cerrando || _miNombre == null) return;
_reconectando = true;
_limiteReconexion?.cancel();
_limiteReconexion = Timer(_ventanaReconexion, cancelarReconexion);
notifyListeners();
try {
await Nearby().stopDiscovery();
} catch (_) {}
// Entre el await y aquí el usuario puede haber salido.
if (_cerrando || !_reconectando) return;
try {
_buscando = await Nearby().startDiscovery(
_miNombre!,
Strategy.P2P_STAR,
onEndpointFound: _onEndpointEncontrado,
onEndpointLost: _onEndpointPerdido,
serviceId: _serviceId,
);
} catch (e) {
debugPrint('Error reiniciando descubrimiento: $e');
}
notifyListeners();
}
/// Corta el reintento automático (por ejemplo si el usuario sale a menú).
Future<void> cancelarReconexion() async {
_limiteReconexion?.cancel();
_limiteReconexion = null;
if (!_reconectando) return;
_reconectando = false;
await pararBusqueda();
}
void _iniciarHeartbeatCliente() {
_heartbeatTimer?.cancel();
@@ -436,9 +507,30 @@ class ServicioNearby extends ChangeNotifier {
) {
debugPrint('Host encontrado: $endpointName ($endpointId)');
_hostsEncontrados[endpointId] = endpointName;
// Volvemos solos, pero solo a nuestro host: si hay otra partida cerca no
// queremos aterrizar en la sala equivocada.
final esNuestroHost =
_nombreHostConectado == null || _nombreHostConectado == endpointName;
if (_reconectando && !_conectado && esNuestroHost) {
_reconectarA(endpointId);
}
notifyListeners();
}
Future<void> _reconectarA(String endpointId) async {
try {
await Nearby().requestConnection(
_miNombre ?? 'Jugador',
endpointId,
onConnectionInitiated: _onConexionIniciada,
onConnectionResult: _onResultadoConexion,
onDisconnected: _onDesconexion,
);
} catch (e) {
debugPrint('Error reconectando a $endpointId: $e');
}
}
void _onEndpointPerdido(String? endpointId) {
debugPrint('Endpoint perdido: $endpointId');
if (endpointId != null) {
@@ -494,7 +586,8 @@ class ServicioNearby extends ChangeNotifier {
_registrarClienteRemoto(endpointId, mensaje);
break;
case TipoMensaje.voto:
_notificarMensaje(endpointId, mensaje);
// El reparto a los listeners lo hace _procesarMensaje al final; hacerlo
// aquí también entregaba cada voto dos veces.
break;
case TipoMensaje.listo:
final jugador = _jugadores[endpointId];
@@ -522,6 +615,9 @@ class ServicioNearby extends ChangeNotifier {
case TipoMensaje.usuariosActualizados:
_handleUsuariosActualizados(mensaje);
break;
case TipoMensaje.solicitarResync:
// Lo resuelve la pantalla gestora, que es quien tiene la partida.
break;
default:
break;
}
@@ -535,22 +631,45 @@ class ServicioNearby extends ChangeNotifier {
final medallas = (mensaje.datos['medallas'] as List<dynamic>? ?? const [])
.map((valor) => valor.toString())
.toList();
final clientId = endpointId;
// El clientId debe sobrevivir a la reconexión, y el endpointId no lo hace:
// Nearby asigna uno nuevo cada vez. Con clientes antiguos que no mandan
// deviceId se cae al comportamiento de siempre.
final deviceId = mensaje.datos['deviceId'] as String?;
final clientId = deviceId ?? endpointId;
final sala = _estadoSala;
final esReconexion = sala?.esReconexion(clientId) ?? false;
// Si el mismo dispositivo tenía otro endpoint abierto, se descarta.
_jugadores.removeWhere(
(id, _) =>
id != endpointId &&
sala?.clientePorEndpoint(id)?.clientId == clientId,
);
_jugadores[endpointId] = JugadorConectado(
endpointId: endpointId,
nombre: nombre,
);
_estadoSala?.registrarCliente(
sala?.registrarCliente(
ClienteSala(clientId: clientId, endpointId: endpointId, nombre: nombre),
);
_crearUsuarioAutomaticoCliente(
clientId: clientId,
nombre: nombre,
nick: nick,
avatar: avatar,
fuego: fuego,
medallas: medallas,
);
if (esReconexion) {
// Vuelve un móvil que se había caído: recupera los jugadores que el host
// le había absorbido mientras tanto.
sala?.devolverUsuariosAbsorbidos(clientId);
} else {
_crearUsuarioAutomaticoCliente(
clientId: clientId,
nombre: nombre,
nick: nick,
avatar: avatar,
fuego: fuego,
medallas: medallas,
);
}
final partidaEnCurso = sala?.fase == FaseSalaMultijugador.enPartida;
enviarMensaje(
endpointId,
@@ -560,11 +679,13 @@ class ServicioNearby extends ChangeNotifier {
'clientId': clientId,
'sala': _nombreSala,
'roomId': _roomId,
'reconexion': esReconexion,
'partidaEnCurso': partidaEnCurso,
'jugadores': _jugadores.values
.map((j) => {'nombre': j.nombre, 'endpointId': j.endpointId})
.toList(),
'usuarios': _usuariosPool.values.map((u) => u.toJson()).toList(),
if (_estadoSala != null) 'estadoSala': _estadoSala!.toJson(),
if (sala != null) 'estadoSala': sala.toJson(),
},
),
);
@@ -736,6 +857,20 @@ class ServicioNearby extends ChangeNotifier {
if (estadoSalaJson != null) {
_sincronizarSala(EstadoSalaMultijugador.fromJson(estadoSalaJson));
}
_partidaEnCursoAlEntrar =
mensaje.datos['partidaEnCurso'] as bool? ?? false;
if (_partidaEnCursoAlEntrar) {
// Entramos con la partida ya empezada: pedimos el estado completo en
// vez de quedarnos esperando en el lobby.
solicitarResync();
}
notifyListeners();
break;
case TipoMensaje.resync:
_faseActual = mensaje.datos['fase'] as String?;
_datosPartida = mensaje.datos;
final pista = mensaje.datos['pistaImpostor'] as String?;
if (pista != null) _datosPartida!['pistaImpostor'] = pista;
notifyListeners();
break;
case TipoMensaje.estadoSala:
@@ -944,12 +1079,15 @@ class ServicioNearby extends ChangeNotifier {
required String categoria,
required Map<String, bool> impostoresPorJugadorId,
required List<Map<String, dynamic>> jugadoresTodos,
bool impostoresSeConocen = false,
String? pistaImpostor,
}) async {
final payloads = InicioPartidaMultijugador.crearPayloadsPorCliente(
asignaciones: asignaciones,
palabraSecreta: palabraSecreta,
categoria: categoria,
impostoresPorJugadorId: impostoresPorJugadorId,
impostoresSeConocen: impostoresSeConocen,
);
for (final payload in payloads.values) {
@@ -958,6 +1096,8 @@ class ServicioNearby extends ChangeNotifier {
final datos = payload.toJson();
datos['jugadoresTodos'] = jugadoresTodos;
datos['roomId'] = _roomId;
// Solo viaja si la partida tiene la pista activada.
if (pistaImpostor != null) datos['pistaImpostor'] = pistaImpostor;
await enviarMensaje(
endpointId,
MensajeP2P(tipo: TipoMensaje.partidaInicio, datos: datos),
@@ -965,6 +1105,30 @@ class ServicioNearby extends ChangeNotifier {
}
}
/// El cliente pide al host el estado completo de la partida en curso.
Future<void> solicitarResync() async {
final hostId = _hostEndpointId;
if (_esHost || hostId == null) return;
await enviarMensaje(
hostId,
MensajeP2P(
tipo: TipoMensaje.solicitarResync,
datos: {if (_miClientId != null) 'clientId': _miClientId},
),
);
}
/// El host responde a un cliente concreto con el estado completo.
Future<void> enviarResync(
String endpointId,
Map<String, dynamic> datos,
) async {
await enviarMensaje(
endpointId,
MensajeP2P(tipo: TipoMensaje.resync, datos: datos),
);
}
Future<void> enviarCambioFase(
String fase, [
Map<String, dynamic>? extra,
@@ -988,7 +1152,10 @@ class ServicioNearby extends ChangeNotifier {
// ==================== LIMPIEZA ====================
Future<void> desconectar() async {
_cerrando = true;
_heartbeatTimer?.cancel();
_limiteReconexion?.cancel();
_limiteReconexion = null;
try {
await Nearby().stopAllEndpoints();
if (_anunciando) await Nearby().stopAdvertising();
@@ -1020,6 +1187,10 @@ class ServicioNearby extends ChangeNotifier {
_hostsEncontrados.clear();
_usuariosPool.clear();
_heartbeatTimer = null;
_reconectando = false;
_partidaEnCursoAlEntrar = false;
_nombreHostConectado = null;
_cerrando = false;
notifyListeners();
}
@@ -1045,6 +1216,7 @@ class ServicioNearby extends ChangeNotifier {
@override
void dispose() {
_heartbeatTimer?.cancel();
_limiteReconexion?.cancel();
desconectar();
super.dispose();
}
+81
View File
@@ -3,6 +3,7 @@ import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import '../l10n/generated/app_localizations.dart';
import '../modelos/gamificacion_usuario.dart';
import 'tema_app.dart';
@@ -1072,6 +1073,86 @@ class TarjetaPalabraFarolero extends StatelessWidget {
}
}
/// Pista que ve el impostor cuando la partida la tiene activada.
class PistaImpostorFarolero extends StatelessWidget {
final String pista;
const PistaImpostorFarolero({super.key, required this.pista});
@override
Widget build(BuildContext context) {
return Text(
AppLocalizations.of(context)!.clueIs(pista),
textAlign: TextAlign.center,
style: Theme.of(
context,
).textTheme.bodyLarge?.copyWith(color: TemaApp.colorNaranja),
);
}
}
/// Panel con el resto de impostores. Solo se muestra a un impostor y solo
/// cuando la partida permite que se conozcan entre ellos.
class CompanerosImpostorFarolero extends StatelessWidget {
final List<String> nombres;
const CompanerosImpostorFarolero({super.key, required this.nombres});
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
if (nombres.isEmpty) {
return Text(
l10n.youAreTheOnlyImpostor,
textAlign: TextAlign.center,
style: Theme.of(
context,
).textTheme.bodyMedium?.copyWith(color: TemaApp.colorTextoSecundario),
);
}
return Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12),
decoration: TemaApp.decoracionPanel(
color: TemaApp.colorAcento.withValues(alpha: 0.16),
borderColor: TemaApp.colorAcento.withValues(alpha: 0.65),
),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconoFarolero(
Icons.groups,
color: TemaApp.colorAcento,
size: 20,
),
const SizedBox(width: 8),
Flexible(
child: Text(
l10n.otherImpostorsTitle(nombres.length),
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleSmall,
),
),
],
),
const SizedBox(height: 6),
Text(
nombres.join(' · '),
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleMedium?.copyWith(
color: TemaApp.colorAcento,
fontWeight: FontWeight.w700,
),
),
],
),
);
}
}
class AvatarFarolero extends StatelessWidget {
final String texto;
final String? assetPath;
+30 -6
View File
@@ -49,6 +49,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.19.1"
confetti:
dependency: "direct main"
description:
name: confetti
sha256: "79376a99648efbc3f23582f5784ced0fe239922bd1a0fb41f582051eba750751"
url: "https://pub.dev"
source: hosted
version: "0.8.0"
crypto:
dependency: transitive
description:
@@ -86,6 +94,14 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_animate:
dependency: "direct main"
description:
name: flutter_animate
sha256: "7befe2d3252728afb77aecaaea1dec88a89d35b9b1d2eea6d04479e8af9117b5"
url: "https://pub.dev"
source: hosted
version: "4.5.2"
flutter_lints:
dependency: "direct dev"
description:
@@ -99,6 +115,14 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_shaders:
dependency: transitive
description:
name: flutter_shaders
sha256: "34794acadd8275d971e02df03afee3dee0f98dbfb8c4837082ad0034f612a3e2"
url: "https://pub.dev"
source: hosted
version: "0.1.3"
flutter_test:
dependency: "direct dev"
description: flutter
@@ -201,10 +225,10 @@ packages:
dependency: transitive
description:
name: matcher
sha256: "12956d0ad8390bbcc63ca2e1469c0619946ccb52809807067a7020d57e647aa6"
sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861
url: "https://pub.dev"
source: hosted
version: "0.12.18"
version: "0.12.19"
material_color_utilities:
dependency: transitive
description:
@@ -217,10 +241,10 @@ packages:
dependency: transitive
description:
name: meta
sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394"
sha256: "1741988757a65eb6b36abe716829688cf01910bbf91c34354ff7ec1c3de2b349"
url: "https://pub.dev"
source: hosted
version: "1.17.0"
version: "1.18.0"
mobile_scanner:
dependency: "direct main"
description:
@@ -518,10 +542,10 @@ packages:
dependency: transitive
description:
name: test_api
sha256: "93167629bfc610f71560ab9312acdda4959de4df6fac7492c89ff0d3886f6636"
sha256: "949a932224383300f01be9221c39180316445ecb8e7547f70a41a35bf421fb9e"
url: "https://pub.dev"
source: hosted
version: "0.7.9"
version: "0.7.11"
typed_data:
dependency: transitive
description:
+80
View File
@@ -0,0 +1,80 @@
import 'dart:convert';
import 'dart:io';
import 'package:flutter_test/flutter_test.dart';
/// Guardas sobre los ficheros de palabras. Son datos, no código, y una pista
/// mal escrita le regala la partida al impostor sin que falle nada.
void main() {
final ficheros = Directory('assets/words')
.listSync()
.whereType<File>()
.where((f) => f.path.endsWith('.json'))
.toList();
test('hay un fichero de palabras por idioma soportado', () {
expect(ficheros.length, 18);
});
for (final fichero in ficheros) {
final nombre = fichero.uri.pathSegments.last;
final datos =
json.decode(fichero.readAsStringSync()) as Map<String, dynamic>;
final categorias = datos['categorias'] as Map<String, dynamic>;
group(nombre, () {
test('declara el formato con pista por palabra', () {
expect(datos['version'], 3);
});
test('tiene 10 categorías de 100 palabras', () {
expect(categorias.length, 10);
for (final categoria in categorias.entries) {
final palabras =
(categoria.value as Map<String, dynamic>)['palabras'] as List;
expect(palabras.length, 100, reason: categoria.key);
}
});
test('cada palabra trae una pista no vacía', () {
for (final categoria in categorias.entries) {
final palabras =
(categoria.value as Map<String, dynamic>)['palabras'] as List;
for (final entrada in palabras) {
expect(
entrada,
isA<Map<String, dynamic>>(),
reason: '${categoria.key}: entrada en formato antiguo',
);
final mapa = entrada as Map<String, dynamic>;
expect((mapa['palabra'] as String).trim(), isNotEmpty);
expect(
(mapa['pista'] as String?)?.trim(),
isNotEmpty,
reason: '${categoria.key}: ${mapa['palabra']} sin pista',
);
}
}
});
test('ninguna pista contiene la palabra que debe ocultar', () {
final fugas = <String>[];
for (final categoria in categorias.entries) {
final palabras =
(categoria.value as Map<String, dynamic>)['palabras'] as List;
for (final entrada in palabras.cast<Map<String, dynamic>>()) {
final palabra = (entrada['palabra'] as String).toLowerCase();
final pista = (entrada['pista'] as String).toLowerCase();
// Las palabras de una sola letra dan falsos positivos: cualquier
// frase las contiene y no revelan nada.
if (palabra.length < 2) continue;
if (pista.contains(palabra)) {
fugas.add('${categoria.key}: "$palabra" -> "$pista"');
}
}
}
expect(fugas, isEmpty, reason: fugas.join('\n'));
});
});
}
}
@@ -1,9 +1,12 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:farolero/estado/estado_juego.dart';
import 'package:farolero/modelos/partida.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
// crearPartida limpia las notas, y eso pasa por SharedPreferences.
setUp(() => SharedPreferences.setMockInitialValues({}));
group('EstadoJuego crearPartida with host local', () {
late EstadoJuego estado;
+156
View File
@@ -0,0 +1,156 @@
import 'package:farolero/modelos/sala_multijugador.dart';
import 'package:farolero/modelos/usuario.dart';
import 'package:flutter_test/flutter_test.dart';
EstadoSalaMultijugador _salaConCliente() {
final sala = EstadoSalaMultijugador.crear(
roomId: 'r1',
nombreSala: 'Sala',
hostClientId: 'host',
hostNombre: 'Ana',
);
sala.registrarCliente(
const ClienteSala(
clientId: 'dev-beto',
endpointId: 'ep-1',
nombre: 'Beto',
),
);
sala.usuarios['u-beto'] = Usuario(
id: 'u-beto',
nombre: 'Beto',
creadoPorClienteId: 'dev-beto',
clienteIdSeleccionado: 'dev-beto',
);
return sala;
}
void main() {
group('Reconexión de un cliente', () {
test('el mismo clientId con endpoint nuevo no crea un cliente duplicado', () {
final sala = _salaConCliente();
sala.registrarCliente(
const ClienteSala(
clientId: 'dev-beto',
endpointId: 'ep-2',
nombre: 'Beto',
),
);
expect(sala.clientes.length, 2, reason: 'host + Beto, sin duplicados');
expect(sala.clientes['dev-beto']!.endpointId, 'ep-2');
expect(sala.clientes['dev-beto']!.conectado, isTrue);
});
test('esReconexion distingue a quien vuelve de quien llega nuevo', () {
final sala = _salaConCliente();
expect(sala.esReconexion('dev-beto'), isTrue);
expect(sala.esReconexion('dev-cris'), isFalse);
});
test('en partida, desconectarse no libera a sus jugadores', () {
final sala = _salaConCliente();
sala.fase = FaseSalaMultijugador.enPartida;
sala.desconectarCliente('dev-beto');
expect(sala.usuarios['u-beto']!.clienteIdSeleccionado, 'dev-beto');
expect(sala.clientes['dev-beto']!.conectado, isFalse);
});
test('en lobby, desconectarse sí libera a sus jugadores', () {
final sala = _salaConCliente();
sala.desconectarCliente('dev-beto');
expect(sala.usuarios['u-beto']!.estaDisponible, isTrue);
});
});
group('Absorción por el host y devolución', () {
test('el host absorbe y queda constancia de quién era el dueño', () {
final sala = _salaConCliente();
sala.fase = FaseSalaMultijugador.enPartida;
sala.desconectarCliente('dev-beto');
final reasignados = sala.reasignarUsuariosDeCliente(
clientIdOrigen: 'dev-beto',
clientIdDestino: 'host',
);
expect(reasignados, 1);
expect(sala.usuarios['u-beto']!.clienteIdSeleccionado, 'host');
expect(sala.usuarios['u-beto']!.absorbidoDe, 'dev-beto');
expect(sala.usuariosAbsorbidosDe('dev-beto').single.id, 'u-beto');
});
test('al volver el móvil recupera a sus jugadores', () {
final sala = _salaConCliente();
sala.fase = FaseSalaMultijugador.enPartida;
sala.desconectarCliente('dev-beto');
sala.reasignarUsuariosDeCliente(
clientIdOrigen: 'dev-beto',
clientIdDestino: 'host',
);
sala.registrarCliente(
const ClienteSala(
clientId: 'dev-beto',
endpointId: 'ep-2',
nombre: 'Beto',
),
);
final devueltos = sala.devolverUsuariosAbsorbidos('dev-beto');
expect(devueltos, 1);
expect(sala.usuarios['u-beto']!.clienteIdSeleccionado, 'dev-beto');
expect(sala.usuarios['u-beto']!.absorbidoDe, isNull);
expect(sala.usuariosPorCliente('host'), isEmpty);
});
test('una doble absorción no pierde al dueño original', () {
final sala = _salaConCliente();
sala.fase = FaseSalaMultijugador.enPartida;
sala.reasignarUsuariosDeCliente(
clientIdOrigen: 'dev-beto',
clientIdDestino: 'host',
);
// El host vuelve a pasar por el mismo camino: no debe reescribir el
// origen a 'host' y dejar al usuario huérfano.
sala.reasignarUsuariosDeCliente(
clientIdOrigen: 'host',
clientIdDestino: 'host',
);
expect(sala.usuarios['u-beto']!.absorbidoDe, 'dev-beto');
});
test('no se devuelve nada a un cliente que no está en la sala', () {
final sala = _salaConCliente();
sala.reasignarUsuariosDeCliente(
clientIdOrigen: 'dev-beto',
clientIdDestino: 'host',
);
expect(sala.devolverUsuariosAbsorbidos('dev-fantasma'), 0);
});
});
group('Serialización', () {
test('absorbidoDe sobrevive al viaje JSON', () {
final sala = _salaConCliente();
sala.fase = FaseSalaMultijugador.enPartida;
sala.reasignarUsuariosDeCliente(
clientIdOrigen: 'dev-beto',
clientIdDestino: 'host',
);
final reparsed = EstadoSalaMultijugador.fromJson(sala.toJson());
expect(reparsed.usuarios['u-beto']!.absorbidoDe, 'dev-beto');
expect(reparsed.clientes['dev-beto']!.endpointId, 'ep-1');
});
});
}
+198
View File
@@ -0,0 +1,198 @@
import 'package:farolero/estado/estado_juego.dart';
import 'package:farolero/modelos/inicio_partida_multijugador.dart';
import 'package:farolero/modelos/jugador.dart';
import 'package:farolero/modelos/palabra.dart';
import 'package:farolero/modelos/partida.dart';
import 'package:farolero/modelos/snapshot_partida_online.dart';
import 'package:flutter_test/flutter_test.dart';
Partida _partidaConImpostores() => Partida(
config: const ConfigPartida(numImpostores: 2),
jugadores: [
Jugador(id: 'j1', nombre: 'Ana', esImpostor: true),
Jugador(id: 'j2', nombre: 'Beto'),
Jugador(id: 'j3', nombre: 'Cris', esImpostor: true),
Jugador(id: 'j4', nombre: 'Dani'),
],
palabraSecreta: 'Camión',
categoriaReal: 'objetos',
);
void main() {
group('SnapshotPartidaOnline no filtra los roles', () {
test('durante la partida no envía esImpostor de nadie', () {
final json = SnapshotPartidaOnline.desdePartida(
_partidaConImpostores(),
fase: 'debate',
).toJson();
final jugadores = json['jugadoresTodos'] as List<dynamic>;
for (final jugador in jugadores) {
expect(
(jugador as Map<String, dynamic>).containsKey('esImpostor'),
isFalse,
reason: 'el rol no puede viajar en el snapshot de fase',
);
}
expect(json.containsKey('impostores'), isFalse);
expect(json.containsKey('palabraSecreta'), isFalse);
});
test('al final de la partida sí revela roles y palabra', () {
final json = SnapshotPartidaOnline.desdePartida(
_partidaConImpostores(),
fase: 'finPartida',
revelarImpostores: true,
revelarPalabra: true,
).toJson();
final jugadores = (json['jugadoresTodos'] as List<dynamic>)
.cast<Map<String, dynamic>>();
expect(jugadores.every((j) => j.containsKey('esImpostor')), isTrue);
expect(json['impostores'], ['Ana', 'Cris']);
expect(json['palabraSecreta'], 'Camión');
});
test('el snapshot de fase se reparsea sin marcar impostores', () {
final snapshot = SnapshotPartidaOnline.fromJson(
SnapshotPartidaOnline.desdePartida(
_partidaConImpostores(),
fase: 'votacion',
).toJson(),
);
expect(snapshot.jugadores.any((j) => j.esImpostor), isFalse);
expect(snapshot.revelarImpostores, isFalse);
});
});
group('Los impostores se conocen entre ellos', () {
final asignaciones = const [
AsignacionJugador(
jugadorId: 'j1',
nombre: 'Ana',
clientId: 'host',
endpointId: null,
),
AsignacionJugador(
jugadorId: 'j2',
nombre: 'Beto',
clientId: 'c2',
endpointId: 'e2',
),
AsignacionJugador(
jugadorId: 'j3',
nombre: 'Cris',
clientId: 'c3',
endpointId: 'e3',
),
];
const impostores = {'j1': true, 'j2': false, 'j3': true};
test('cada impostor recibe los nombres del resto, nunca el suyo', () {
final payloads = InicioPartidaMultijugador.crearPayloadsPorCliente(
asignaciones: asignaciones,
palabraSecreta: 'Camión',
categoria: 'objetos',
impostoresPorJugadorId: impostores,
impostoresSeConocen: true,
);
expect(payloads['host']!.jugadores.single.companerosImpostores, ['Cris']);
expect(payloads['c3']!.jugadores.single.companerosImpostores, ['Ana']);
});
test('un jugador normal nunca recibe la lista', () {
final payloads = InicioPartidaMultijugador.crearPayloadsPorCliente(
asignaciones: asignaciones,
palabraSecreta: 'Camión',
categoria: 'objetos',
impostoresPorJugadorId: impostores,
impostoresSeConocen: true,
);
expect(payloads['c2']!.jugadores.single.companerosImpostores, isNull);
});
test('con la opción desactivada nadie recibe la lista', () {
final payloads = InicioPartidaMultijugador.crearPayloadsPorCliente(
asignaciones: asignaciones,
palabraSecreta: 'Camión',
categoria: 'objetos',
impostoresPorJugadorId: impostores,
impostoresSeConocen: false,
);
for (final payload in payloads.values) {
for (final jugador in payload.jugadores) {
expect(jugador.companerosImpostores, isNull);
}
}
});
test('la lista vacía sobrevive al viaje JSON y no se vuelve null', () {
const jugador = JugadorInicioPartida(
jugadorId: 'j1',
nombre: 'Ana',
esImpostor: true,
palabra: null,
companerosImpostores: [],
);
final reparsed = JugadorInicioPartida.fromJson(jugador.toJson());
expect(reparsed.companerosImpostores, isEmpty);
expect(reparsed.companerosImpostores, isNotNull);
});
});
group('Pistas del banco de palabras', () {
test('prioriza la pista de la palabra sobre la de la categoría', () {
final banco = BancoPalabras(
{
'objetos': ['Camión', 'Silla'],
},
pistasPorCategoria: {'objetos': 'Objetos'},
pistasPorPalabra: {'Camión': 'Se conduce y transporta carga'},
);
expect(banco.pistaDePalabra('Camión'), 'Se conduce y transporta carga');
expect(banco.pistaDePalabra('Silla'), 'Objetos');
});
test('sin pista de palabra ni de categoría devuelve null', () {
final banco = BancoPalabras({
'objetos': ['Silla'],
});
expect(banco.pistaDePalabra('Silla'), isNull);
});
});
group('Tope de impostores', () {
test('es el mismo en ambos modos de juego', () {
expect(EstadoJuego.maxImpostoresPara(3), 1);
expect(EstadoJuego.maxImpostoresPara(5), 1);
expect(EstadoJuego.maxImpostoresPara(6), 2);
expect(EstadoJuego.maxImpostoresPara(12), 4);
expect(EstadoJuego.maxImpostoresPara(20), 4);
});
});
group('Partida', () {
test('la pista cae a la categoría cuando no se aporta una específica', () {
final partida = Partida(
config: const ConfigPartida(),
jugadores: [Jugador(id: 'j1', nombre: 'Ana')],
palabraSecreta: 'Camión',
categoriaReal: 'objetos',
);
expect(partida.pistaImpostor, 'objetos');
});
test('nombresImpostores lista solo a los impostores', () {
expect(_partidaConImpostores().nombresImpostores, ['Ana', 'Cris']);
});
});
}
-3
View File
@@ -12,9 +12,6 @@ void main() {
servicio = ServicioNearby();
});
tearDown(() {
servicio.dispose();
});
test('should start with empty user pool', () {
expect(servicio.usuarios, isEmpty);