From 56f07364c20f8300a1de3e8cc9ddaab0eb18cbfb Mon Sep 17 00:00:00 2001 From: freetlab Date: Sat, 25 Jul 2026 23:59:09 +0200 Subject: [PATCH] feat: confirm before leaving a game, and fix untranslated strings Exit confirmation - A dialog in the app's own style now guards every in-game screen. The safe action is the prominent one, so a stray tap keeps you in the game. - Eleven screens covered, against both the system back gesture and the close buttons. The message adapts: a single-device game is lost, a host ends it for everyone, a client can rejoin. - The two screens the host also opens from the manager take a flag so that back there just closes them instead of offering to quit. Translations - 21 keys were still holding the English text in Arabic, Basque, Hindi, Japanese, Korean, Dutch, Polish, Russian, Turkish and both Chinese variants: 231 strings, covering the whole multi-device flow, permissions and the mode picker. Nothing failed, the app just showed English. - The permissions dialog was hardcoded in Spanish; it is localized now. - Portuguese used Spanish gerunds where pt-PT takes "a + infinitive". Checked what looked untranslated but is not: Animals and Notes are correct Catalan, Configuration and Vibration correct French, Version correct German. Those are whitelisted in the new test rather than silently rewritten. l10n_cobertura_test guards all of it: no missing or orphan keys, no empty values, no English left outside the whitelist, and placeholders preserved. --- lib/l10n/app_ar.arb | 58 ++++-- lib/l10n/app_ca.arb | 16 +- lib/l10n/app_de.arb | 16 +- lib/l10n/app_en.arb | 16 +- lib/l10n/app_es.arb | 16 +- lib/l10n/app_eu.arb | 58 ++++-- lib/l10n/app_fr.arb | 16 +- lib/l10n/app_hi.arb | 58 ++++-- lib/l10n/app_it.arb | 16 +- lib/l10n/app_ja.arb | 58 ++++-- lib/l10n/app_ko.arb | 58 ++++-- lib/l10n/app_nl.arb | 58 ++++-- lib/l10n/app_pl.arb | 58 ++++-- lib/l10n/app_pt.arb | 22 +- lib/l10n/app_ru.arb | 58 ++++-- lib/l10n/app_tr.arb | 58 ++++-- lib/l10n/app_zh.arb | 58 ++++-- lib/l10n/app_zh_TW.arb | 58 ++++-- lib/l10n/generated/app_localizations.dart | 84 ++++++++ lib/l10n/generated/app_localizations_ar.dart | 90 ++++++--- lib/l10n/generated/app_localizations_ca.dart | 46 +++++ lib/l10n/generated/app_localizations_de.dart | 45 +++++ lib/l10n/generated/app_localizations_en.dart | 45 +++++ lib/l10n/generated/app_localizations_es.dart | 45 +++++ lib/l10n/generated/app_localizations_eu.dart | 89 ++++++-- lib/l10n/generated/app_localizations_fr.dart | 47 +++++ lib/l10n/generated/app_localizations_hi.dart | 88 ++++++-- lib/l10n/generated/app_localizations_it.dart | 46 +++++ lib/l10n/generated/app_localizations_ja.dart | 92 ++++++--- lib/l10n/generated/app_localizations_ko.dart | 91 ++++++--- lib/l10n/generated/app_localizations_nl.dart | 88 ++++++-- lib/l10n/generated/app_localizations_pl.dart | 87 ++++++-- lib/l10n/generated/app_localizations_pt.dart | 51 ++++- lib/l10n/generated/app_localizations_ru.dart | 88 ++++++-- lib/l10n/generated/app_localizations_tr.dart | 86 ++++++-- lib/l10n/generated/app_localizations_zh.dart | 188 +++++++++++------ lib/pantallas/pantalla_adivinanza.dart | 54 ++--- lib/pantallas/pantalla_debate.dart | 148 +++++++------- lib/pantallas/pantalla_debate_cliente.dart | 202 ++++++++++--------- lib/pantallas/pantalla_gestor_host.dart | 15 +- lib/pantallas/pantalla_lobby_host.dart | 7 + lib/pantallas/pantalla_palabras_cliente.dart | 12 +- lib/pantallas/pantalla_resultado.dart | 74 +++---- lib/pantallas/pantalla_resultado_online.dart | 52 ++--- lib/pantallas/pantalla_ver_palabra.dart | 118 +++++------ lib/pantallas/pantalla_votacion.dart | 8 +- lib/pantallas/pantalla_votacion_cliente.dart | 12 +- lib/servicios/servicio_permisos.dart | 32 +-- lib/tema/dialogo_confirmacion.dart | 170 ++++++++++++++++ test/l10n_cobertura_test.dart | 110 ++++++++++ 50 files changed, 2313 insertions(+), 853 deletions(-) create mode 100644 lib/tema/dialogo_confirmacion.dart create mode 100644 test/l10n_cobertura_test.dart diff --git a/lib/l10n/app_ar.arb b/lib/l10n/app_ar.arb index 865728b..e8b0ef1 100644 --- a/lib/l10n/app_ar.arb +++ b/lib/l10n/app_ar.arb @@ -246,28 +246,28 @@ "release": "تحرير", "select": "اختيار", "delete": "حذف", - "selectAtLeastThreeUsersToStart": "Select at least 3 users to start.", - "hostPhoneMustSelectUser": "The host phone must select at least one user.", - "roomNoLongerInLobby": "The room is no longer in the lobby.", - "completeUserSelectionToStart": "Complete user selection to start.", - "preparingSecureRoom": "Preparing the secure room", - "searchingNearbyBluetoothGames": "Searching nearby games over Bluetooth", - "tapToJoin": "Tap to join", - "bluetoothLocationPermissionsRequired": "Bluetooth and location permissions are required to search for games.", - "bluetoothLocationPermissionsShort": "Bluetooth and location permissions are required", - "couldNotStartSearch": "Could not start the search. Check Bluetooth and location.", - "couldNotConnectToHost": "Could not connect to {host}", + "selectAtLeastThreeUsersToStart": "اختر 3 مستخدمين على الأقل للبدء.", + "hostPhoneMustSelectUser": "يجب أن يختار هاتف المضيف مستخدمًا واحدًا على الأقل.", + "roomNoLongerInLobby": "لم تعد الغرفة في ردهة الانتظار.", + "completeUserSelectionToStart": "أكمل اختيار المستخدمين للبدء.", + "preparingSecureRoom": "جارٍ تجهيز الغرفة الآمنة", + "searchingNearbyBluetoothGames": "البحث عن جولات قريبة عبر البلوتوث", + "tapToJoin": "اضغط للانضمام", + "bluetoothLocationPermissionsRequired": "يلزم إذنا البلوتوث والموقع للبحث عن جولات.", + "bluetoothLocationPermissionsShort": "يلزم إذنا البلوتوث والموقع", + "couldNotStartSearch": "تعذّر بدء البحث. تحقق من البلوتوث والموقع.", + "couldNotConnectToHost": "تعذّر الاتصال بـ {host}", "room": "غرفة", - "singleDeviceSubtitle": "Game on this device", - "singleDeviceDescription": "Ideal for playing together by passing the phone around. Fast, direct setup.", - "multiDeviceSubtitle": "Each player on their phone", - "multiDeviceDescription": "Create a premium room, share the QR code and manage users from the lobby.", - "singleDeviceGameLabel": "Game on this device", - "multiDeviceGameLabel": "Multi-device game", - "mainDeviceUser": "Main device user", - "couldNotCreateRoom": "Could not create the room. Check Bluetooth.", - "cannotStartWithReason": "Cannot start: {reason}", - "invalidRoom": "invalid room", + "singleDeviceSubtitle": "اللعب على هذا الجهاز", + "singleDeviceDescription": "مثالي للعب معًا بتمرير الهاتف. إعداد سريع ومباشر.", + "multiDeviceSubtitle": "كل لاعب على هاتفه", + "multiDeviceDescription": "أنشئ غرفة مميزة، وشارك رمز QR، وأدر المستخدمين من ردهة الانتظار.", + "singleDeviceGameLabel": "اللعب على هذا الجهاز", + "multiDeviceGameLabel": "لعب متعدد الأجهزة", + "mainDeviceUser": "المستخدم الرئيسي للجهاز", + "couldNotCreateRoom": "تعذّر إنشاء الغرفة. تحقق من البلوتوث.", + "cannotStartWithReason": "تعذّر البدء: {reason}", + "invalidRoom": "غرفة غير صالحة", "defaultPlayerName": "لاعب", "play": "العب", "history": "السجل", @@ -368,5 +368,19 @@ "reconnecting": "جارٍ إعادة الاتصال...", "reconnectingHint": "انقطع الاتصال بالمضيف. مكانك في الجولة محفوظ.", "leaveGame": "مغادرة الجولة", - "playerRejoined": "عاد {name} إلى الجولة" + "playerRejoined": "عاد {name} إلى الجولة", + "leaveGameTitle": "هل تريد مغادرة الجولة؟", + "leaveGameSingleDevice": "ستفقد الجولة الجارية ولن يمكن استعادتها.", + "leaveGameHost": "أنت المضيف: إذا غادرت ستنتهي الجولة لجميع اللاعبين.", + "leaveGameClient": "ستغادر الجولة. يمكنك العودة ما دام المضيف يبقيها مفتوحة.", + "stayInGame": "متابعة اللعب", + "permissionsNeededTitle": "أذونات مطلوبة", + "permissionsNeededBody": "لوضع اللعب الجماعي نحتاج إلى:", + "openAppSettingsQuestion": "هل تريد فتح إعدادات التطبيق؟", + "openSettings": "فتح الإعدادات", + "permissionLocation": "الموقع", + "permissionBluetoothAdvertise": "بلوتوث (الإعلان)", + "permissionBluetoothConnect": "بلوتوث (الاتصال)", + "permissionBluetoothScan": "بلوتوث (المسح)", + "permissionNearbyWifi": "واي فاي قريب" } diff --git a/lib/l10n/app_ca.arb b/lib/l10n/app_ca.arb index 4ecc022..be8a39e 100644 --- a/lib/l10n/app_ca.arb +++ b/lib/l10n/app_ca.arb @@ -368,5 +368,19 @@ "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" + "playerRejoined": "{name} ha tornat a la partida", + "leaveGameTitle": "Vols sortir de la partida?", + "leaveGameSingleDevice": "Es perdrà la partida en curs i no la podràs recuperar.", + "leaveGameHost": "Ets l'amfitrió: si surts, la partida s'acaba per a tots els jugadors.", + "leaveGameClient": "Sortiràs de la partida. Hi podràs tornar mentre l'amfitrió la mantingui oberta.", + "stayInGame": "Continuar jugant", + "permissionsNeededTitle": "Permisos necessaris", + "permissionsNeededBody": "Per al mode multijugador necessitem:", + "openAppSettingsQuestion": "Vols obrir la configuració de l'aplicació?", + "openSettings": "Obrir configuració", + "permissionLocation": "Ubicació", + "permissionBluetoothAdvertise": "Bluetooth (anunciar)", + "permissionBluetoothConnect": "Bluetooth (connectar)", + "permissionBluetoothScan": "Bluetooth (escanejar)", + "permissionNearbyWifi": "Wi-Fi proper" } diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index a9a704c..21d0d36 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -368,5 +368,19 @@ "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" + "playerRejoined": "{name} ist zurück im Spiel", + "leaveGameTitle": "Spiel wirklich verlassen?", + "leaveGameSingleDevice": "Das laufende Spiel geht verloren und lässt sich nicht wiederherstellen.", + "leaveGameHost": "Du bist der Host: Wenn du gehst, endet das Spiel für alle.", + "leaveGameClient": "Du verlässt das Spiel. Du kannst zurückkommen, solange der Host es offen hält.", + "stayInGame": "Weiterspielen", + "permissionsNeededTitle": "Berechtigungen erforderlich", + "permissionsNeededBody": "Für den Mehrspielermodus brauchen wir:", + "openAppSettingsQuestion": "Die App-Einstellungen öffnen?", + "openSettings": "Einstellungen öffnen", + "permissionLocation": "Standort", + "permissionBluetoothAdvertise": "Bluetooth (sichtbar machen)", + "permissionBluetoothConnect": "Bluetooth (verbinden)", + "permissionBluetoothScan": "Bluetooth (suchen)", + "permissionNearbyWifi": "Wi-Fi in der Nähe" } diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index df09ab7..f274f92 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -375,5 +375,19 @@ "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" + "playerRejoined": "{name} has rejoined the game", + "leaveGameTitle": "Leave the game?", + "leaveGameSingleDevice": "The game in progress will be lost and cannot be recovered.", + "leaveGameHost": "You are the host: if you leave, the game ends for everyone.", + "leaveGameClient": "You will leave the game. You can rejoin while the host keeps it open.", + "stayInGame": "Keep playing", + "permissionsNeededTitle": "Permissions needed", + "permissionsNeededBody": "For multiplayer mode we need:", + "openAppSettingsQuestion": "Open the app settings?", + "openSettings": "Open settings", + "permissionLocation": "Location", + "permissionBluetoothAdvertise": "Bluetooth (advertise)", + "permissionBluetoothConnect": "Bluetooth (connect)", + "permissionBluetoothScan": "Bluetooth (scan)", + "permissionNearbyWifi": "Nearby Wi-Fi" } diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 39e960d..aca98cf 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -417,5 +417,19 @@ "type": "String" } } - } + }, + "leaveGameTitle": "¿Salir de la partida?", + "leaveGameSingleDevice": "Se perderá la partida en curso y no podrás recuperarla.", + "leaveGameHost": "Eres el anfitrión: si sales, la partida termina para todos los jugadores.", + "leaveGameClient": "Saldrás de la partida. Podrás volver mientras el anfitrión la mantenga abierta.", + "stayInGame": "Seguir jugando", + "permissionsNeededTitle": "Permisos necesarios", + "permissionsNeededBody": "Para el modo multijugador necesitamos:", + "openAppSettingsQuestion": "¿Abrir la configuración de la app?", + "openSettings": "Abrir configuración", + "permissionLocation": "Ubicación", + "permissionBluetoothAdvertise": "Bluetooth (anunciar)", + "permissionBluetoothConnect": "Bluetooth (conectar)", + "permissionBluetoothScan": "Bluetooth (escanear)", + "permissionNearbyWifi": "Wi-Fi cercano" } diff --git a/lib/l10n/app_eu.arb b/lib/l10n/app_eu.arb index 53eaefc..d26d7e3 100644 --- a/lib/l10n/app_eu.arb +++ b/lib/l10n/app_eu.arb @@ -246,28 +246,28 @@ "release": "Askatu", "select": "Hautatu", "delete": "Ezabatu", - "selectAtLeastThreeUsersToStart": "Select at least 3 users to start.", - "hostPhoneMustSelectUser": "The host phone must select at least one user.", - "roomNoLongerInLobby": "The room is no longer in the lobby.", - "completeUserSelectionToStart": "Complete user selection to start.", - "preparingSecureRoom": "Preparing the secure room", - "searchingNearbyBluetoothGames": "Searching nearby games over Bluetooth", - "tapToJoin": "Tap to join", - "bluetoothLocationPermissionsRequired": "Bluetooth and location permissions are required to search for games.", - "bluetoothLocationPermissionsShort": "Bluetooth and location permissions are required", - "couldNotStartSearch": "Could not start the search. Check Bluetooth and location.", - "couldNotConnectToHost": "Could not connect to {host}", + "selectAtLeastThreeUsersToStart": "Hautatu gutxienez 3 erabiltzaile hasteko.", + "hostPhoneMustSelectUser": "Ostalariaren mugikorrak gutxienez erabiltzaile bat hautatu behar du.", + "roomNoLongerInLobby": "Gela jada ez dago lobbyan.", + "completeUserSelectionToStart": "Osatu erabiltzaileen hautaketa hasteko.", + "preparingSecureRoom": "Gela segurua prestatzen", + "searchingNearbyBluetoothGames": "Inguruko partidak bilatzen Bluetooth bidez", + "tapToJoin": "Sakatu batzeko", + "bluetoothLocationPermissionsRequired": "Bluetooth eta kokapen baimenak behar dira partidak bilatzeko.", + "bluetoothLocationPermissionsShort": "Bluetooth eta kokapen baimenak behar dira", + "couldNotStartSearch": "Ezin izan da bilaketa hasi. Egiaztatu Bluetooth eta kokapena.", + "couldNotConnectToHost": "Ezin izan da {host}(e)ra konektatu", "room": "Gela", - "singleDeviceSubtitle": "Game on this device", - "singleDeviceDescription": "Ideal for playing together by passing the phone around. Fast, direct setup.", - "multiDeviceSubtitle": "Each player on their phone", - "multiDeviceDescription": "Create a premium room, share the QR code and manage users from the lobby.", - "singleDeviceGameLabel": "Game on this device", - "multiDeviceGameLabel": "Multi-device game", - "mainDeviceUser": "Main device user", - "couldNotCreateRoom": "Could not create the room. Check Bluetooth.", - "cannotStartWithReason": "Cannot start: {reason}", - "invalidRoom": "invalid room", + "singleDeviceSubtitle": "Partida gailu honetan", + "singleDeviceDescription": "Ezin hobea denok elkarrekin jokatzeko mugikorra pasatuz. Konfigurazio azkarra eta zuzena.", + "multiDeviceSubtitle": "Jokalari bakoitza bere mugikorrean", + "multiDeviceDescription": "Sortu gela premium bat, partekatu QR kodea eta kudeatu erabiltzaileak lobbytik.", + "singleDeviceGameLabel": "Partida gailu honetan", + "multiDeviceGameLabel": "Gailu anitzeko partida", + "mainDeviceUser": "Gailuaren erabiltzaile nagusia", + "couldNotCreateRoom": "Ezin izan da gela sortu. Egiaztatu Bluetooth.", + "cannotStartWithReason": "Ezin da hasi: {reason}", + "invalidRoom": "gela baliogabea", "defaultPlayerName": "Jokalaria", "play": "Jokatu", "history": "Historia", @@ -368,5 +368,19 @@ "reconnecting": "Berriz konektatzen...", "reconnectingHint": "Ostalariarekiko konexioa galdu da. Partidan duzun lekua gordeta dago.", "leaveGame": "Partidatik irten", - "playerRejoined": "{name} partidara itzuli da" + "playerRejoined": "{name} partidara itzuli da", + "leaveGameTitle": "Partidatik irten nahi duzu?", + "leaveGameSingleDevice": "Abian den partida galduko da eta ezin izango duzu berreskuratu.", + "leaveGameHost": "Zu zara ostalaria: irtenez gero, partida jokalari guztientzat amaituko da.", + "leaveGameClient": "Partidatik aterako zara. Itzuli ahal izango zara ostalariak zabalik mantentzen duen bitartean.", + "stayInGame": "Jokatzen jarraitu", + "permissionsNeededTitle": "Baimenak behar dira", + "permissionsNeededBody": "Jokalari anitzeko modurako hau behar dugu:", + "openAppSettingsQuestion": "Aplikazioaren ezarpenak ireki nahi dituzu?", + "openSettings": "Ireki ezarpenak", + "permissionLocation": "Kokapena", + "permissionBluetoothAdvertise": "Bluetooth (iragarri)", + "permissionBluetoothConnect": "Bluetooth (konektatu)", + "permissionBluetoothScan": "Bluetooth (eskaneatu)", + "permissionNearbyWifi": "Inguruko Wi-Fi" } diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb index 02900ca..86bda6f 100644 --- a/lib/l10n/app_fr.arb +++ b/lib/l10n/app_fr.arb @@ -368,5 +368,19 @@ "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" + "playerRejoined": "{name} a rejoint la partie", + "leaveGameTitle": "Quitter la partie ?", + "leaveGameSingleDevice": "La partie en cours sera perdue et ne pourra pas être récupérée.", + "leaveGameHost": "Vous êtes l'hôte : si vous partez, la partie se termine pour tout le monde.", + "leaveGameClient": "Vous quitterez la partie. Vous pourrez revenir tant que l'hôte la laisse ouverte.", + "stayInGame": "Continuer à jouer", + "permissionsNeededTitle": "Autorisations nécessaires", + "permissionsNeededBody": "Pour le mode multijoueur, nous avons besoin de :", + "openAppSettingsQuestion": "Ouvrir les paramètres de l'application ?", + "openSettings": "Ouvrir les paramètres", + "permissionLocation": "Localisation", + "permissionBluetoothAdvertise": "Bluetooth (diffusion)", + "permissionBluetoothConnect": "Bluetooth (connexion)", + "permissionBluetoothScan": "Bluetooth (recherche)", + "permissionNearbyWifi": "Wi-Fi à proximité" } diff --git a/lib/l10n/app_hi.arb b/lib/l10n/app_hi.arb index 4352628..d80bec0 100644 --- a/lib/l10n/app_hi.arb +++ b/lib/l10n/app_hi.arb @@ -246,28 +246,28 @@ "release": "छोड़ें", "select": "चुनें", "delete": "हटाएँ", - "selectAtLeastThreeUsersToStart": "Select at least 3 users to start.", - "hostPhoneMustSelectUser": "The host phone must select at least one user.", - "roomNoLongerInLobby": "The room is no longer in the lobby.", - "completeUserSelectionToStart": "Complete user selection to start.", - "preparingSecureRoom": "Preparing the secure room", - "searchingNearbyBluetoothGames": "Searching nearby games over Bluetooth", - "tapToJoin": "Tap to join", - "bluetoothLocationPermissionsRequired": "Bluetooth and location permissions are required to search for games.", - "bluetoothLocationPermissionsShort": "Bluetooth and location permissions are required", - "couldNotStartSearch": "Could not start the search. Check Bluetooth and location.", - "couldNotConnectToHost": "Could not connect to {host}", + "selectAtLeastThreeUsersToStart": "शुरू करने के लिए कम से कम 3 उपयोगकर्ता चुनें।", + "hostPhoneMustSelectUser": "होस्ट फ़ोन को कम से कम एक उपयोगकर्ता चुनना होगा।", + "roomNoLongerInLobby": "कमरा अब लॉबी में नहीं है।", + "completeUserSelectionToStart": "शुरू करने के लिए उपयोगकर्ताओं का चयन पूरा करें।", + "preparingSecureRoom": "सुरक्षित कमरा तैयार किया जा रहा है", + "searchingNearbyBluetoothGames": "ब्लूटूथ से आस-पास के गेम खोजे जा रहे हैं", + "tapToJoin": "शामिल होने के लिए टैप करें", + "bluetoothLocationPermissionsRequired": "गेम खोजने के लिए ब्लूटूथ और लोकेशन की अनुमति चाहिए।", + "bluetoothLocationPermissionsShort": "ब्लूटूथ और लोकेशन की अनुमति चाहिए", + "couldNotStartSearch": "खोज शुरू नहीं हो सकी। ब्लूटूथ और लोकेशन जाँचें।", + "couldNotConnectToHost": "{host} से कनेक्ट नहीं हो सका", "room": "कक्ष", - "singleDeviceSubtitle": "Game on this device", - "singleDeviceDescription": "Ideal for playing together by passing the phone around. Fast, direct setup.", - "multiDeviceSubtitle": "Each player on their phone", - "multiDeviceDescription": "Create a premium room, share the QR code and manage users from the lobby.", - "singleDeviceGameLabel": "Game on this device", - "multiDeviceGameLabel": "Multi-device game", - "mainDeviceUser": "Main device user", - "couldNotCreateRoom": "Could not create the room. Check Bluetooth.", - "cannotStartWithReason": "Cannot start: {reason}", - "invalidRoom": "invalid room", + "singleDeviceSubtitle": "इसी डिवाइस पर खेल", + "singleDeviceDescription": "फ़ोन एक-दूसरे को देकर साथ खेलने के लिए बढ़िया। सेटअप तेज़ और सीधा।", + "multiDeviceSubtitle": "हर खिलाड़ी अपने फ़ोन पर", + "multiDeviceDescription": "एक प्रीमियम कमरा बनाएँ, QR साझा करें और लॉबी से उपयोगकर्ता संभालें।", + "singleDeviceGameLabel": "इसी डिवाइस पर खेल", + "multiDeviceGameLabel": "मल्टी-डिवाइस खेल", + "mainDeviceUser": "डिवाइस का मुख्य उपयोगकर्ता", + "couldNotCreateRoom": "कमरा नहीं बन सका। ब्लूटूथ जाँचें।", + "cannotStartWithReason": "शुरू नहीं हो सकता: {reason}", + "invalidRoom": "अमान्य कमरा", "defaultPlayerName": "खिलाड़ी", "play": "खेलें", "history": "इतिहास", @@ -368,5 +368,19 @@ "reconnecting": "फिर से कनेक्ट हो रहा है...", "reconnectingHint": "होस्ट से कनेक्शन टूट गया। खेल में आपकी जगह सुरक्षित है।", "leaveGame": "खेल छोड़ें", - "playerRejoined": "{name} खेल में वापस आ गए" + "playerRejoined": "{name} खेल में वापस आ गए", + "leaveGameTitle": "खेल छोड़ना है?", + "leaveGameSingleDevice": "चल रहा खेल ख़त्म हो जाएगा और वापस नहीं मिलेगा।", + "leaveGameHost": "आप होस्ट हैं: आपके जाने पर सभी खिलाड़ियों का खेल ख़त्म हो जाएगा।", + "leaveGameClient": "आप खेल से बाहर निकल जाएँगे। जब तक होस्ट इसे खुला रखे, आप लौट सकते हैं।", + "stayInGame": "खेलते रहें", + "permissionsNeededTitle": "अनुमतियाँ चाहिए", + "permissionsNeededBody": "मल्टीप्लेयर मोड के लिए हमें चाहिए:", + "openAppSettingsQuestion": "क्या ऐप की सेटिंग खोलें?", + "openSettings": "सेटिंग खोलें", + "permissionLocation": "लोकेशन", + "permissionBluetoothAdvertise": "ब्लूटूथ (प्रसारण)", + "permissionBluetoothConnect": "ब्लूटूथ (कनेक्ट)", + "permissionBluetoothScan": "ब्लूटूथ (स्कैन)", + "permissionNearbyWifi": "आस-पास का वाई-फ़ाई" } diff --git a/lib/l10n/app_it.arb b/lib/l10n/app_it.arb index f98adf8..0365fa4 100644 --- a/lib/l10n/app_it.arb +++ b/lib/l10n/app_it.arb @@ -368,5 +368,19 @@ "reconnecting": "Riconnessione...", "reconnectingHint": "Connessione con l'host persa. Il tuo posto nella partita resta riservato.", "leaveGame": "Esci dalla partita", - "playerRejoined": "{name} è tornato in partita" + "playerRejoined": "{name} è tornato in partita", + "leaveGameTitle": "Vuoi uscire dalla partita?", + "leaveGameSingleDevice": "La partita in corso andrà persa e non potrà essere recuperata.", + "leaveGameHost": "Sei l'host: se esci, la partita finisce per tutti i giocatori.", + "leaveGameClient": "Uscirai dalla partita. Potrai rientrare finché l'host la tiene aperta.", + "stayInGame": "Continua a giocare", + "permissionsNeededTitle": "Autorizzazioni necessarie", + "permissionsNeededBody": "Per la modalità multigiocatore servono:", + "openAppSettingsQuestion": "Vuoi aprire le impostazioni dell'app?", + "openSettings": "Apri impostazioni", + "permissionLocation": "Posizione", + "permissionBluetoothAdvertise": "Bluetooth (annuncio)", + "permissionBluetoothConnect": "Bluetooth (connessione)", + "permissionBluetoothScan": "Bluetooth (scansione)", + "permissionNearbyWifi": "Wi-Fi nelle vicinanze" } diff --git a/lib/l10n/app_ja.arb b/lib/l10n/app_ja.arb index ee886fe..6d5fd13 100644 --- a/lib/l10n/app_ja.arb +++ b/lib/l10n/app_ja.arb @@ -246,28 +246,28 @@ "release": "解除", "select": "選択", "delete": "削除", - "selectAtLeastThreeUsersToStart": "Select at least 3 users to start.", - "hostPhoneMustSelectUser": "The host phone must select at least one user.", - "roomNoLongerInLobby": "The room is no longer in the lobby.", - "completeUserSelectionToStart": "Complete user selection to start.", - "preparingSecureRoom": "Preparing the secure room", - "searchingNearbyBluetoothGames": "Searching nearby games over Bluetooth", - "tapToJoin": "Tap to join", - "bluetoothLocationPermissionsRequired": "Bluetooth and location permissions are required to search for games.", - "bluetoothLocationPermissionsShort": "Bluetooth and location permissions are required", - "couldNotStartSearch": "Could not start the search. Check Bluetooth and location.", - "couldNotConnectToHost": "Could not connect to {host}", + "selectAtLeastThreeUsersToStart": "開始するには3人以上のユーザーを選んでください。", + "hostPhoneMustSelectUser": "ホストの端末は少なくとも1人のユーザーを選ぶ必要があります。", + "roomNoLongerInLobby": "ルームはすでにロビーにありません。", + "completeUserSelectionToStart": "開始するにはユーザーの選択を完了してください。", + "preparingSecureRoom": "安全なルームを準備しています", + "searchingNearbyBluetoothGames": "Bluetoothで近くのゲームを検索しています", + "tapToJoin": "タップして参加", + "bluetoothLocationPermissionsRequired": "ゲームを検索するにはBluetoothと位置情報の許可が必要です。", + "bluetoothLocationPermissionsShort": "Bluetoothと位置情報の許可が必要です", + "couldNotStartSearch": "検索を開始できませんでした。Bluetoothと位置情報を確認してください。", + "couldNotConnectToHost": "{host} に接続できませんでした", "room": "ルーム", - "singleDeviceSubtitle": "Game on this device", - "singleDeviceDescription": "Ideal for playing together by passing the phone around. Fast, direct setup.", - "multiDeviceSubtitle": "Each player on their phone", - "multiDeviceDescription": "Create a premium room, share the QR code and manage users from the lobby.", - "singleDeviceGameLabel": "Game on this device", - "multiDeviceGameLabel": "Multi-device game", - "mainDeviceUser": "Main device user", - "couldNotCreateRoom": "Could not create the room. Check Bluetooth.", - "cannotStartWithReason": "Cannot start: {reason}", - "invalidRoom": "invalid room", + "singleDeviceSubtitle": "この端末でプレイ", + "singleDeviceDescription": "端末を回しながらみんなで遊ぶのに最適。設定はすばやく簡単。", + "multiDeviceSubtitle": "プレイヤーごとに自分の端末で", + "multiDeviceDescription": "プレミアムなルームを作り、QRコードを共有し、ロビーからユーザーを管理します。", + "singleDeviceGameLabel": "この端末でのゲーム", + "multiDeviceGameLabel": "マルチデバイスのゲーム", + "mainDeviceUser": "この端末のメインユーザー", + "couldNotCreateRoom": "ルームを作成できませんでした。Bluetoothを確認してください。", + "cannotStartWithReason": "開始できません: {reason}", + "invalidRoom": "無効なルーム", "defaultPlayerName": "プレイヤー", "play": "プレイ", "history": "履歴", @@ -368,5 +368,19 @@ "reconnecting": "再接続しています...", "reconnectingHint": "ホストとの接続が切れました。ゲーム内のあなたの席は確保されています。", "leaveGame": "ゲームから退出", - "playerRejoined": "{name} がゲームに復帰しました" + "playerRejoined": "{name} がゲームに復帰しました", + "leaveGameTitle": "ゲームから退出しますか?", + "leaveGameSingleDevice": "進行中のゲームは失われ、元に戻せません。", + "leaveGameHost": "あなたはホストです。退出すると全員のゲームが終了します。", + "leaveGameClient": "ゲームから退出します。ホストが開いている間は戻れます。", + "stayInGame": "ゲームを続ける", + "permissionsNeededTitle": "必要な権限", + "permissionsNeededBody": "マルチプレイには次の権限が必要です:", + "openAppSettingsQuestion": "アプリの設定を開きますか?", + "openSettings": "設定を開く", + "permissionLocation": "位置情報", + "permissionBluetoothAdvertise": "Bluetooth(アドバタイズ)", + "permissionBluetoothConnect": "Bluetooth(接続)", + "permissionBluetoothScan": "Bluetooth(スキャン)", + "permissionNearbyWifi": "近くのWi-Fi" } diff --git a/lib/l10n/app_ko.arb b/lib/l10n/app_ko.arb index b122b32..887aa3b 100644 --- a/lib/l10n/app_ko.arb +++ b/lib/l10n/app_ko.arb @@ -246,28 +246,28 @@ "release": "해제", "select": "선택", "delete": "삭제", - "selectAtLeastThreeUsersToStart": "Select at least 3 users to start.", - "hostPhoneMustSelectUser": "The host phone must select at least one user.", - "roomNoLongerInLobby": "The room is no longer in the lobby.", - "completeUserSelectionToStart": "Complete user selection to start.", - "preparingSecureRoom": "Preparing the secure room", - "searchingNearbyBluetoothGames": "Searching nearby games over Bluetooth", - "tapToJoin": "Tap to join", - "bluetoothLocationPermissionsRequired": "Bluetooth and location permissions are required to search for games.", - "bluetoothLocationPermissionsShort": "Bluetooth and location permissions are required", - "couldNotStartSearch": "Could not start the search. Check Bluetooth and location.", - "couldNotConnectToHost": "Could not connect to {host}", + "selectAtLeastThreeUsersToStart": "시작하려면 사용자를 3명 이상 선택하세요.", + "hostPhoneMustSelectUser": "호스트 기기는 사용자를 최소 한 명 선택해야 합니다.", + "roomNoLongerInLobby": "방이 더 이상 대기실에 없습니다.", + "completeUserSelectionToStart": "시작하려면 사용자 선택을 마치세요.", + "preparingSecureRoom": "보안 방을 준비하는 중", + "searchingNearbyBluetoothGames": "블루투스로 근처 게임을 찾는 중", + "tapToJoin": "눌러서 참여하기", + "bluetoothLocationPermissionsRequired": "게임을 찾으려면 블루투스와 위치 권한이 필요합니다.", + "bluetoothLocationPermissionsShort": "블루투스와 위치 권한이 필요합니다", + "couldNotStartSearch": "검색을 시작할 수 없습니다. 블루투스와 위치를 확인하세요.", + "couldNotConnectToHost": "{host}에 연결할 수 없습니다", "room": "방", - "singleDeviceSubtitle": "Game on this device", - "singleDeviceDescription": "Ideal for playing together by passing the phone around. Fast, direct setup.", - "multiDeviceSubtitle": "Each player on their phone", - "multiDeviceDescription": "Create a premium room, share the QR code and manage users from the lobby.", - "singleDeviceGameLabel": "Game on this device", - "multiDeviceGameLabel": "Multi-device game", - "mainDeviceUser": "Main device user", - "couldNotCreateRoom": "Could not create the room. Check Bluetooth.", - "cannotStartWithReason": "Cannot start: {reason}", - "invalidRoom": "invalid room", + "singleDeviceSubtitle": "이 기기에서 진행", + "singleDeviceDescription": "휴대전화를 돌려 가며 함께 놀기에 좋습니다. 설정이 빠르고 간단합니다.", + "multiDeviceSubtitle": "각자 자기 휴대전화로", + "multiDeviceDescription": "프리미엄 방을 만들고 QR 코드를 공유하며 대기실에서 사용자를 관리하세요.", + "singleDeviceGameLabel": "이 기기에서 하는 게임", + "multiDeviceGameLabel": "여러 기기로 하는 게임", + "mainDeviceUser": "이 기기의 주 사용자", + "couldNotCreateRoom": "방을 만들 수 없습니다. 블루투스를 확인하세요.", + "cannotStartWithReason": "시작할 수 없습니다: {reason}", + "invalidRoom": "잘못된 방", "defaultPlayerName": "플레이어", "play": "플레이", "history": "기록", @@ -368,5 +368,19 @@ "reconnecting": "다시 연결하는 중...", "reconnectingHint": "호스트와의 연결이 끊겼습니다. 게임 내 자리는 유지됩니다.", "leaveGame": "게임 나가기", - "playerRejoined": "{name} 님이 게임에 복귀했습니다" + "playerRejoined": "{name} 님이 게임에 복귀했습니다", + "leaveGameTitle": "게임에서 나갈까요?", + "leaveGameSingleDevice": "진행 중인 게임이 사라지며 되돌릴 수 없습니다.", + "leaveGameHost": "당신은 호스트입니다. 나가면 모두의 게임이 끝납니다.", + "leaveGameClient": "게임에서 나갑니다. 호스트가 열어 두는 동안에는 다시 들어올 수 있습니다.", + "stayInGame": "계속 하기", + "permissionsNeededTitle": "필요한 권한", + "permissionsNeededBody": "멀티플레이 모드에는 다음 권한이 필요합니다:", + "openAppSettingsQuestion": "앱 설정을 열까요?", + "openSettings": "설정 열기", + "permissionLocation": "위치", + "permissionBluetoothAdvertise": "블루투스(광고)", + "permissionBluetoothConnect": "블루투스(연결)", + "permissionBluetoothScan": "블루투스(검색)", + "permissionNearbyWifi": "근처 Wi-Fi" } diff --git a/lib/l10n/app_nl.arb b/lib/l10n/app_nl.arb index 3bd20f5..8923292 100644 --- a/lib/l10n/app_nl.arb +++ b/lib/l10n/app_nl.arb @@ -246,28 +246,28 @@ "release": "Vrijgeven", "select": "Selecteren", "delete": "Verwijderen", - "selectAtLeastThreeUsersToStart": "Select at least 3 users to start.", - "hostPhoneMustSelectUser": "The host phone must select at least one user.", - "roomNoLongerInLobby": "The room is no longer in the lobby.", - "completeUserSelectionToStart": "Complete user selection to start.", - "preparingSecureRoom": "Preparing the secure room", - "searchingNearbyBluetoothGames": "Searching nearby games over Bluetooth", - "tapToJoin": "Tap to join", - "bluetoothLocationPermissionsRequired": "Bluetooth and location permissions are required to search for games.", - "bluetoothLocationPermissionsShort": "Bluetooth and location permissions are required", - "couldNotStartSearch": "Could not start the search. Check Bluetooth and location.", - "couldNotConnectToHost": "Could not connect to {host}", + "selectAtLeastThreeUsersToStart": "Selecteer minstens 3 gebruikers om te starten.", + "hostPhoneMustSelectUser": "De host-telefoon moet minstens één gebruiker selecteren.", + "roomNoLongerInLobby": "De ruimte is niet meer in de lobby.", + "completeUserSelectionToStart": "Voltooi de gebruikersselectie om te starten.", + "preparingSecureRoom": "Beveiligde ruimte voorbereiden", + "searchingNearbyBluetoothGames": "Zoeken naar spellen in de buurt via Bluetooth", + "tapToJoin": "Tik om deel te nemen", + "bluetoothLocationPermissionsRequired": "Bluetooth- en locatietoestemming zijn nodig om spellen te zoeken.", + "bluetoothLocationPermissionsShort": "Bluetooth- en locatietoestemming zijn nodig", + "couldNotStartSearch": "Kon het zoeken niet starten. Controleer Bluetooth en locatie.", + "couldNotConnectToHost": "Kon geen verbinding maken met {host}", "room": "Kamer", - "singleDeviceSubtitle": "Game on this device", - "singleDeviceDescription": "Ideal for playing together by passing the phone around. Fast, direct setup.", - "multiDeviceSubtitle": "Each player on their phone", - "multiDeviceDescription": "Create a premium room, share the QR code and manage users from the lobby.", - "singleDeviceGameLabel": "Game on this device", - "multiDeviceGameLabel": "Multi-device game", - "mainDeviceUser": "Main device user", - "couldNotCreateRoom": "Could not create the room. Check Bluetooth.", - "cannotStartWithReason": "Cannot start: {reason}", - "invalidRoom": "invalid room", + "singleDeviceSubtitle": "Spel op dit toestel", + "singleDeviceDescription": "Ideaal om samen te spelen door de telefoon door te geven. Snel en direct ingesteld.", + "multiDeviceSubtitle": "Elke speler op zijn eigen telefoon", + "multiDeviceDescription": "Maak een premium ruimte, deel de QR-code en beheer gebruikers vanuit de lobby.", + "singleDeviceGameLabel": "Spel op dit toestel", + "multiDeviceGameLabel": "Spel met meerdere toestellen", + "mainDeviceUser": "Hoofdgebruiker van dit toestel", + "couldNotCreateRoom": "Kon de ruimte niet aanmaken. Controleer Bluetooth.", + "cannotStartWithReason": "Kan niet starten: {reason}", + "invalidRoom": "ongeldige ruimte", "defaultPlayerName": "Speler", "play": "Spelen", "history": "Geschiedenis", @@ -368,5 +368,19 @@ "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" + "playerRejoined": "{name} is terug in het spel", + "leaveGameTitle": "Het spel verlaten?", + "leaveGameSingleDevice": "Het lopende spel gaat verloren en kan niet worden hersteld.", + "leaveGameHost": "Jij bent de host: als je weggaat, eindigt het spel voor iedereen.", + "leaveGameClient": "Je verlaat het spel. Je kunt terugkomen zolang de host het openhoudt.", + "stayInGame": "Verder spelen", + "permissionsNeededTitle": "Toestemmingen nodig", + "permissionsNeededBody": "Voor de multiplayermodus hebben we nodig:", + "openAppSettingsQuestion": "De app-instellingen openen?", + "openSettings": "Instellingen openen", + "permissionLocation": "Locatie", + "permissionBluetoothAdvertise": "Bluetooth (zichtbaar maken)", + "permissionBluetoothConnect": "Bluetooth (verbinden)", + "permissionBluetoothScan": "Bluetooth (scannen)", + "permissionNearbyWifi": "Wi-Fi in de buurt" } diff --git a/lib/l10n/app_pl.arb b/lib/l10n/app_pl.arb index 5b425c0..45d6821 100644 --- a/lib/l10n/app_pl.arb +++ b/lib/l10n/app_pl.arb @@ -246,28 +246,28 @@ "release": "Zwolnij", "select": "Wybierz", "delete": "Usuń", - "selectAtLeastThreeUsersToStart": "Select at least 3 users to start.", - "hostPhoneMustSelectUser": "The host phone must select at least one user.", - "roomNoLongerInLobby": "The room is no longer in the lobby.", - "completeUserSelectionToStart": "Complete user selection to start.", - "preparingSecureRoom": "Preparing the secure room", - "searchingNearbyBluetoothGames": "Searching nearby games over Bluetooth", - "tapToJoin": "Tap to join", - "bluetoothLocationPermissionsRequired": "Bluetooth and location permissions are required to search for games.", - "bluetoothLocationPermissionsShort": "Bluetooth and location permissions are required", - "couldNotStartSearch": "Could not start the search. Check Bluetooth and location.", - "couldNotConnectToHost": "Could not connect to {host}", + "selectAtLeastThreeUsersToStart": "Wybierz co najmniej 3 użytkowników, aby rozpocząć.", + "hostPhoneMustSelectUser": "Telefon gospodarza musi wybrać przynajmniej jednego użytkownika.", + "roomNoLongerInLobby": "Pokój nie jest już w poczekalni.", + "completeUserSelectionToStart": "Dokończ wybór użytkowników, aby rozpocząć.", + "preparingSecureRoom": "Przygotowywanie bezpiecznego pokoju", + "searchingNearbyBluetoothGames": "Szukanie gier w pobliżu przez Bluetooth", + "tapToJoin": "Dotknij, aby dołączyć", + "bluetoothLocationPermissionsRequired": "Do wyszukiwania gier potrzebne są uprawnienia Bluetooth i lokalizacji.", + "bluetoothLocationPermissionsShort": "Potrzebne są uprawnienia Bluetooth i lokalizacji", + "couldNotStartSearch": "Nie udało się rozpocząć wyszukiwania. Sprawdź Bluetooth i lokalizację.", + "couldNotConnectToHost": "Nie udało się połączyć z {host}", "room": "Pokój", - "singleDeviceSubtitle": "Game on this device", - "singleDeviceDescription": "Ideal for playing together by passing the phone around. Fast, direct setup.", - "multiDeviceSubtitle": "Each player on their phone", - "multiDeviceDescription": "Create a premium room, share the QR code and manage users from the lobby.", - "singleDeviceGameLabel": "Game on this device", - "multiDeviceGameLabel": "Multi-device game", - "mainDeviceUser": "Main device user", - "couldNotCreateRoom": "Could not create the room. Check Bluetooth.", - "cannotStartWithReason": "Cannot start: {reason}", - "invalidRoom": "invalid room", + "singleDeviceSubtitle": "Gra na tym urządzeniu", + "singleDeviceDescription": "Idealne do wspólnej gry, podając telefon dalej. Szybka i prosta konfiguracja.", + "multiDeviceSubtitle": "Każdy gracz na swoim telefonie", + "multiDeviceDescription": "Utwórz pokój premium, udostępnij kod QR i zarządzaj graczami z poczekalni.", + "singleDeviceGameLabel": "Gra na tym urządzeniu", + "multiDeviceGameLabel": "Gra na wielu urządzeniach", + "mainDeviceUser": "Główny użytkownik urządzenia", + "couldNotCreateRoom": "Nie udało się utworzyć pokoju. Sprawdź Bluetooth.", + "cannotStartWithReason": "Nie można rozpocząć: {reason}", + "invalidRoom": "nieprawidłowy pokój", "defaultPlayerName": "Gracz", "play": "Graj", "history": "Historia", @@ -368,5 +368,19 @@ "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" + "playerRejoined": "{name} wrócił(a) do gry", + "leaveGameTitle": "Opuścić grę?", + "leaveGameSingleDevice": "Trwająca gra zostanie utracona i nie da się jej odzyskać.", + "leaveGameHost": "Jesteś gospodarzem: jeśli wyjdziesz, gra kończy się dla wszystkich.", + "leaveGameClient": "Opuścisz grę. Możesz wrócić, dopóki gospodarz jej nie zamknie.", + "stayInGame": "Graj dalej", + "permissionsNeededTitle": "Wymagane uprawnienia", + "permissionsNeededBody": "Do trybu wieloosobowego potrzebujemy:", + "openAppSettingsQuestion": "Otworzyć ustawienia aplikacji?", + "openSettings": "Otwórz ustawienia", + "permissionLocation": "Lokalizacja", + "permissionBluetoothAdvertise": "Bluetooth (rozgłaszanie)", + "permissionBluetoothConnect": "Bluetooth (łączenie)", + "permissionBluetoothScan": "Bluetooth (skanowanie)", + "permissionNearbyWifi": "Wi-Fi w pobliżu" } diff --git a/lib/l10n/app_pt.arb b/lib/l10n/app_pt.arb index 6cfea57..af48a78 100644 --- a/lib/l10n/app_pt.arb +++ b/lib/l10n/app_pt.arb @@ -6,7 +6,7 @@ "matchRewards": "Recompensas da partida", "newMedals": "Novas medalhas", "noNewMedalsKeepFire": "Sem medalhas novas desta vez. Continua a acumular fogo.", - "calculatingRewards": "Calculando recompensas...", + "calculatingRewards": "A calcular recompensas...", "fireLabel": "Fogo", "playersRange": "3-20 jogadores • Sem internet", "createGame": "Criar partida", @@ -85,7 +85,7 @@ }, "holdToSeeWord": "Mantenha pressionado para ver sua palavra", "makeSureNoOneLooks": "Certifique-se de que ninguém mais está olhando", - "showingWord": "👁️ Mostrando...", + "showingWord": "👁️ A mostrar...", "holdToSee": "👆 Mantenha pressionado para ver", "seenMyWord": "Já vi minha palavra", "debateRound": "Debate - Rodada {round}", @@ -133,7 +133,7 @@ "tapToReveal": "Toque para revelar o resultado", "revealResult": "Revelar resultado", "result": "Resultado", - "revealing": "Revelando...", + "revealing": "A revelar...", "wasImpostor": "Era IMPOSTOR! 🎉", "wasInnocent": "Era INOCENTE 😱", "votesThisRound": "Votos desta rodada", @@ -368,5 +368,19 @@ "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" + "playerRejoined": "{name} voltou ao jogo", + "leaveGameTitle": "Sair do jogo?", + "leaveGameSingleDevice": "O jogo em curso perde-se e não poderá ser recuperado.", + "leaveGameHost": "És o anfitrião: se saíres, o jogo termina para todos os jogadores.", + "leaveGameClient": "Vais sair do jogo. Podes voltar enquanto o anfitrião o mantiver aberto.", + "stayInGame": "Continuar a jogar", + "permissionsNeededTitle": "Permissões necessárias", + "permissionsNeededBody": "Para o modo multijogador precisamos de:", + "openAppSettingsQuestion": "Abrir as definições da aplicação?", + "openSettings": "Abrir definições", + "permissionLocation": "Localização", + "permissionBluetoothAdvertise": "Bluetooth (anunciar)", + "permissionBluetoothConnect": "Bluetooth (ligar)", + "permissionBluetoothScan": "Bluetooth (procurar)", + "permissionNearbyWifi": "Wi-Fi por perto" } diff --git a/lib/l10n/app_ru.arb b/lib/l10n/app_ru.arb index 648d4c1..036e650 100644 --- a/lib/l10n/app_ru.arb +++ b/lib/l10n/app_ru.arb @@ -246,28 +246,28 @@ "release": "Освободить", "select": "Выбрать", "delete": "Удалить", - "selectAtLeastThreeUsersToStart": "Select at least 3 users to start.", - "hostPhoneMustSelectUser": "The host phone must select at least one user.", - "roomNoLongerInLobby": "The room is no longer in the lobby.", - "completeUserSelectionToStart": "Complete user selection to start.", - "preparingSecureRoom": "Preparing the secure room", - "searchingNearbyBluetoothGames": "Searching nearby games over Bluetooth", - "tapToJoin": "Tap to join", - "bluetoothLocationPermissionsRequired": "Bluetooth and location permissions are required to search for games.", - "bluetoothLocationPermissionsShort": "Bluetooth and location permissions are required", - "couldNotStartSearch": "Could not start the search. Check Bluetooth and location.", - "couldNotConnectToHost": "Could not connect to {host}", + "selectAtLeastThreeUsersToStart": "Выберите не менее 3 пользователей, чтобы начать.", + "hostPhoneMustSelectUser": "Телефон ведущего должен выбрать хотя бы одного пользователя.", + "roomNoLongerInLobby": "Комната больше не в лобби.", + "completeUserSelectionToStart": "Завершите выбор пользователей, чтобы начать.", + "preparingSecureRoom": "Подготовка защищённой комнаты", + "searchingNearbyBluetoothGames": "Поиск игр поблизости через Bluetooth", + "tapToJoin": "Нажмите, чтобы присоединиться", + "bluetoothLocationPermissionsRequired": "Для поиска игр нужны разрешения Bluetooth и геолокации.", + "bluetoothLocationPermissionsShort": "Нужны разрешения Bluetooth и геолокации", + "couldNotStartSearch": "Не удалось начать поиск. Проверьте Bluetooth и геолокацию.", + "couldNotConnectToHost": "Не удалось подключиться к {host}", "room": "Комната", - "singleDeviceSubtitle": "Game on this device", - "singleDeviceDescription": "Ideal for playing together by passing the phone around. Fast, direct setup.", - "multiDeviceSubtitle": "Each player on their phone", - "multiDeviceDescription": "Create a premium room, share the QR code and manage users from the lobby.", - "singleDeviceGameLabel": "Game on this device", - "multiDeviceGameLabel": "Multi-device game", - "mainDeviceUser": "Main device user", - "couldNotCreateRoom": "Could not create the room. Check Bluetooth.", - "cannotStartWithReason": "Cannot start: {reason}", - "invalidRoom": "invalid room", + "singleDeviceSubtitle": "Игра на этом устройстве", + "singleDeviceDescription": "Идеально, чтобы играть вместе, передавая телефон. Быстрая и простая настройка.", + "multiDeviceSubtitle": "Каждый игрок на своём телефоне", + "multiDeviceDescription": "Создайте премиум-комнату, поделитесь QR-кодом и управляйте игроками из лобби.", + "singleDeviceGameLabel": "Игра на этом устройстве", + "multiDeviceGameLabel": "Игра на нескольких устройствах", + "mainDeviceUser": "Основной пользователь устройства", + "couldNotCreateRoom": "Не удалось создать комнату. Проверьте Bluetooth.", + "cannotStartWithReason": "Невозможно начать: {reason}", + "invalidRoom": "недопустимая комната", "defaultPlayerName": "Игрок", "play": "Играть", "history": "История", @@ -368,5 +368,19 @@ "reconnecting": "Переподключение...", "reconnectingHint": "Соединение с ведущим потеряно. Ваше место в игре сохраняется.", "leaveGame": "Выйти из игры", - "playerRejoined": "{name} вернулся в игру" + "playerRejoined": "{name} вернулся в игру", + "leaveGameTitle": "Выйти из игры?", + "leaveGameSingleDevice": "Текущая партия будет потеряна без возможности восстановления.", + "leaveGameHost": "Вы ведущий: если вы выйдете, игра закончится для всех.", + "leaveGameClient": "Вы выйдете из игры. Вы сможете вернуться, пока ведущий её не закрыл.", + "stayInGame": "Продолжить игру", + "permissionsNeededTitle": "Нужны разрешения", + "permissionsNeededBody": "Для многопользовательского режима нужны:", + "openAppSettingsQuestion": "Открыть настройки приложения?", + "openSettings": "Открыть настройки", + "permissionLocation": "Геолокация", + "permissionBluetoothAdvertise": "Bluetooth (объявление)", + "permissionBluetoothConnect": "Bluetooth (подключение)", + "permissionBluetoothScan": "Bluetooth (сканирование)", + "permissionNearbyWifi": "Wi-Fi поблизости" } diff --git a/lib/l10n/app_tr.arb b/lib/l10n/app_tr.arb index ad89dbf..76236e1 100644 --- a/lib/l10n/app_tr.arb +++ b/lib/l10n/app_tr.arb @@ -246,28 +246,28 @@ "release": "Bırak", "select": "Seç", "delete": "Sil", - "selectAtLeastThreeUsersToStart": "Select at least 3 users to start.", - "hostPhoneMustSelectUser": "The host phone must select at least one user.", - "roomNoLongerInLobby": "The room is no longer in the lobby.", - "completeUserSelectionToStart": "Complete user selection to start.", - "preparingSecureRoom": "Preparing the secure room", - "searchingNearbyBluetoothGames": "Searching nearby games over Bluetooth", - "tapToJoin": "Tap to join", - "bluetoothLocationPermissionsRequired": "Bluetooth and location permissions are required to search for games.", - "bluetoothLocationPermissionsShort": "Bluetooth and location permissions are required", - "couldNotStartSearch": "Could not start the search. Check Bluetooth and location.", - "couldNotConnectToHost": "Could not connect to {host}", + "selectAtLeastThreeUsersToStart": "Başlamak için en az 3 kullanıcı seç.", + "hostPhoneMustSelectUser": "Sunucu telefonu en az bir kullanıcı seçmeli.", + "roomNoLongerInLobby": "Oda artık lobide değil.", + "completeUserSelectionToStart": "Başlamak için kullanıcı seçimini tamamla.", + "preparingSecureRoom": "Güvenli oda hazırlanıyor", + "searchingNearbyBluetoothGames": "Bluetooth ile yakındaki oyunlar aranıyor", + "tapToJoin": "Katılmak için dokun", + "bluetoothLocationPermissionsRequired": "Oyun aramak için Bluetooth ve konum izinleri gerekli.", + "bluetoothLocationPermissionsShort": "Bluetooth ve konum izinleri gerekli", + "couldNotStartSearch": "Arama başlatılamadı. Bluetooth ve konumu kontrol et.", + "couldNotConnectToHost": "{host} bağlantısı kurulamadı", "room": "Oda", - "singleDeviceSubtitle": "Game on this device", - "singleDeviceDescription": "Ideal for playing together by passing the phone around. Fast, direct setup.", - "multiDeviceSubtitle": "Each player on their phone", - "multiDeviceDescription": "Create a premium room, share the QR code and manage users from the lobby.", - "singleDeviceGameLabel": "Game on this device", - "multiDeviceGameLabel": "Multi-device game", - "mainDeviceUser": "Main device user", - "couldNotCreateRoom": "Could not create the room. Check Bluetooth.", - "cannotStartWithReason": "Cannot start: {reason}", - "invalidRoom": "invalid room", + "singleDeviceSubtitle": "Bu cihazda oyun", + "singleDeviceDescription": "Telefonu elden ele dolaştırarak birlikte oynamak için ideal. Hızlı ve doğrudan kurulum.", + "multiDeviceSubtitle": "Her oyuncu kendi telefonunda", + "multiDeviceDescription": "Premium bir oda oluştur, QR kodu paylaş ve kullanıcıları lobiden yönet.", + "singleDeviceGameLabel": "Bu cihazda oyun", + "multiDeviceGameLabel": "Çok cihazlı oyun", + "mainDeviceUser": "Cihazın ana kullanıcısı", + "couldNotCreateRoom": "Oda oluşturulamadı. Bluetooth'u kontrol et.", + "cannotStartWithReason": "Başlatılamıyor: {reason}", + "invalidRoom": "geçersiz oda", "defaultPlayerName": "Oyuncu", "play": "Oyna", "history": "Geçmiş", @@ -368,5 +368,19 @@ "reconnecting": "Yeniden bağlanılıyor...", "reconnectingHint": "Sunucuyla bağlantı koptu. Oyundaki yerin korunuyor.", "leaveGame": "Oyundan ayrıl", - "playerRejoined": "{name} oyuna geri döndü" + "playerRejoined": "{name} oyuna geri döndü", + "leaveGameTitle": "Oyundan çıkılsın mı?", + "leaveGameSingleDevice": "Devam eden oyun kaybolur ve geri getirilemez.", + "leaveGameHost": "Sunucu sensin: çıkarsan oyun herkes için biter.", + "leaveGameClient": "Oyundan çıkacaksın. Sunucu odayı açık tuttuğu sürece geri dönebilirsin.", + "stayInGame": "Oynamaya devam et", + "permissionsNeededTitle": "Gerekli izinler", + "permissionsNeededBody": "Çok oyunculu mod için şunlar gerekli:", + "openAppSettingsQuestion": "Uygulama ayarları açılsın mı?", + "openSettings": "Ayarları aç", + "permissionLocation": "Konum", + "permissionBluetoothAdvertise": "Bluetooth (yayın)", + "permissionBluetoothConnect": "Bluetooth (bağlanma)", + "permissionBluetoothScan": "Bluetooth (tarama)", + "permissionNearbyWifi": "Yakındaki Wi-Fi" } diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index 70bab93..64c8dfa 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -246,28 +246,28 @@ "release": "释放", "select": "选择", "delete": "删除", - "selectAtLeastThreeUsersToStart": "Select at least 3 users to start.", - "hostPhoneMustSelectUser": "The host phone must select at least one user.", - "roomNoLongerInLobby": "The room is no longer in the lobby.", - "completeUserSelectionToStart": "Complete user selection to start.", - "preparingSecureRoom": "Preparing the secure room", - "searchingNearbyBluetoothGames": "Searching nearby games over Bluetooth", - "tapToJoin": "Tap to join", - "bluetoothLocationPermissionsRequired": "Bluetooth and location permissions are required to search for games.", - "bluetoothLocationPermissionsShort": "Bluetooth and location permissions are required", - "couldNotStartSearch": "Could not start the search. Check Bluetooth and location.", - "couldNotConnectToHost": "Could not connect to {host}", + "selectAtLeastThreeUsersToStart": "至少选择 3 名用户才能开始。", + "hostPhoneMustSelectUser": "房主的手机必须至少选择一名用户。", + "roomNoLongerInLobby": "房间已不在等候大厅。", + "completeUserSelectionToStart": "完成用户选择后才能开始。", + "preparingSecureRoom": "正在准备安全房间", + "searchingNearbyBluetoothGames": "正在通过蓝牙搜索附近的游戏", + "tapToJoin": "点击加入", + "bluetoothLocationPermissionsRequired": "搜索游戏需要蓝牙和定位权限。", + "bluetoothLocationPermissionsShort": "需要蓝牙和定位权限", + "couldNotStartSearch": "无法开始搜索。请检查蓝牙和定位。", + "couldNotConnectToHost": "无法连接到 {host}", "room": "房间", - "singleDeviceSubtitle": "Game on this device", - "singleDeviceDescription": "Ideal for playing together by passing the phone around. Fast, direct setup.", - "multiDeviceSubtitle": "Each player on their phone", - "multiDeviceDescription": "Create a premium room, share the QR code and manage users from the lobby.", - "singleDeviceGameLabel": "Game on this device", - "multiDeviceGameLabel": "Multi-device game", - "mainDeviceUser": "Main device user", - "couldNotCreateRoom": "Could not create the room. Check Bluetooth.", - "cannotStartWithReason": "Cannot start: {reason}", - "invalidRoom": "invalid room", + "singleDeviceSubtitle": "在这台设备上游戏", + "singleDeviceDescription": "适合大家传着手机一起玩。设置快速直接。", + "multiDeviceSubtitle": "每位玩家用自己的手机", + "multiDeviceDescription": "创建高级房间,分享二维码,并在大厅管理用户。", + "singleDeviceGameLabel": "本机游戏", + "multiDeviceGameLabel": "多设备游戏", + "mainDeviceUser": "本机主用户", + "couldNotCreateRoom": "无法创建房间。请检查蓝牙。", + "cannotStartWithReason": "无法开始:{reason}", + "invalidRoom": "无效的房间", "defaultPlayerName": "玩家", "play": "开始", "history": "历史", @@ -368,5 +368,19 @@ "reconnecting": "正在重新连接…", "reconnectingHint": "与房主的连接已断开。你在游戏中的位置仍为你保留。", "leaveGame": "退出游戏", - "playerRejoined": "{name} 已重新加入游戏" + "playerRejoined": "{name} 已重新加入游戏", + "leaveGameTitle": "要退出游戏吗?", + "leaveGameSingleDevice": "正在进行的游戏将会丢失,且无法恢复。", + "leaveGameHost": "你是房主:一旦退出,所有玩家的游戏都会结束。", + "leaveGameClient": "你将退出这局游戏。只要房主还开着,你随时可以回来。", + "stayInGame": "继续游戏", + "permissionsNeededTitle": "需要权限", + "permissionsNeededBody": "多人游戏模式需要以下权限:", + "openAppSettingsQuestion": "要打开应用设置吗?", + "openSettings": "打开设置", + "permissionLocation": "定位", + "permissionBluetoothAdvertise": "蓝牙(广播)", + "permissionBluetoothConnect": "蓝牙(连接)", + "permissionBluetoothScan": "蓝牙(扫描)", + "permissionNearbyWifi": "附近的 Wi-Fi" } diff --git a/lib/l10n/app_zh_TW.arb b/lib/l10n/app_zh_TW.arb index d0dd1c8..d9c6904 100644 --- a/lib/l10n/app_zh_TW.arb +++ b/lib/l10n/app_zh_TW.arb @@ -246,28 +246,28 @@ "release": "释放", "select": "选择", "delete": "删除", - "selectAtLeastThreeUsersToStart": "Select at least 3 users to start.", - "hostPhoneMustSelectUser": "The host phone must select at least one user.", - "roomNoLongerInLobby": "The room is no longer in the lobby.", - "completeUserSelectionToStart": "Complete user selection to start.", - "preparingSecureRoom": "Preparing the secure room", - "searchingNearbyBluetoothGames": "Searching nearby games over Bluetooth", - "tapToJoin": "Tap to join", - "bluetoothLocationPermissionsRequired": "Bluetooth and location permissions are required to search for games.", - "bluetoothLocationPermissionsShort": "Bluetooth and location permissions are required", - "couldNotStartSearch": "Could not start the search. Check Bluetooth and location.", - "couldNotConnectToHost": "Could not connect to {host}", + "selectAtLeastThreeUsersToStart": "至少選擇 3 名使用者才能開始。", + "hostPhoneMustSelectUser": "房主的手機必須至少選擇一名使用者。", + "roomNoLongerInLobby": "房間已不在等候大廳。", + "completeUserSelectionToStart": "完成使用者選擇後才能開始。", + "preparingSecureRoom": "正在準備安全房間", + "searchingNearbyBluetoothGames": "正在透過藍牙搜尋附近的遊戲", + "tapToJoin": "點擊加入", + "bluetoothLocationPermissionsRequired": "搜尋遊戲需要藍牙和定位權限。", + "bluetoothLocationPermissionsShort": "需要藍牙和定位權限", + "couldNotStartSearch": "無法開始搜尋。請檢查藍牙和定位。", + "couldNotConnectToHost": "無法連線到 {host}", "room": "房间", - "singleDeviceSubtitle": "Game on this device", - "singleDeviceDescription": "Ideal for playing together by passing the phone around. Fast, direct setup.", - "multiDeviceSubtitle": "Each player on their phone", - "multiDeviceDescription": "Create a premium room, share the QR code and manage users from the lobby.", - "singleDeviceGameLabel": "Game on this device", - "multiDeviceGameLabel": "Multi-device game", - "mainDeviceUser": "Main device user", - "couldNotCreateRoom": "Could not create the room. Check Bluetooth.", - "cannotStartWithReason": "Cannot start: {reason}", - "invalidRoom": "invalid room", + "singleDeviceSubtitle": "在這台裝置上遊戲", + "singleDeviceDescription": "適合大家傳著手機一起玩。設定快速直接。", + "multiDeviceSubtitle": "每位玩家用自己的手機", + "multiDeviceDescription": "建立高級房間,分享 QR Code,並在大廳管理使用者。", + "singleDeviceGameLabel": "本機遊戲", + "multiDeviceGameLabel": "多裝置遊戲", + "mainDeviceUser": "本機主要使用者", + "couldNotCreateRoom": "無法建立房間。請檢查藍牙。", + "cannotStartWithReason": "無法開始:{reason}", + "invalidRoom": "無效的房間", "defaultPlayerName": "玩家", "play": "開始", "history": "紀錄", @@ -368,5 +368,19 @@ "reconnecting": "正在重新連線…", "reconnectingHint": "與房主的連線已中斷。你在遊戲中的位置仍為你保留。", "leaveGame": "退出遊戲", - "playerRejoined": "{name} 已重新加入遊戲" + "playerRejoined": "{name} 已重新加入遊戲", + "leaveGameTitle": "要退出遊戲嗎?", + "leaveGameSingleDevice": "正在進行的遊戲將會遺失,且無法復原。", + "leaveGameHost": "你是房主:一旦退出,所有玩家的遊戲都會結束。", + "leaveGameClient": "你將退出這局遊戲。只要房主還開著,你隨時可以回來。", + "stayInGame": "繼續遊戲", + "permissionsNeededTitle": "需要權限", + "permissionsNeededBody": "多人遊戲模式需要以下權限:", + "openAppSettingsQuestion": "要開啟應用程式設定嗎?", + "openSettings": "開啟設定", + "permissionLocation": "定位", + "permissionBluetoothAdvertise": "藍牙(廣播)", + "permissionBluetoothConnect": "藍牙(連線)", + "permissionBluetoothScan": "藍牙(掃描)", + "permissionNearbyWifi": "附近的 Wi-Fi" } diff --git a/lib/l10n/generated/app_localizations.dart b/lib/l10n/generated/app_localizations.dart index 1e42c6c..c80bdb1 100644 --- a/lib/l10n/generated/app_localizations.dart +++ b/lib/l10n/generated/app_localizations.dart @@ -1634,6 +1634,90 @@ abstract class AppLocalizations { /// In es, this message translates to: /// **'{name} ha vuelto a la partida'** String playerRejoined(String name); + + /// No description provided for @leaveGameTitle. + /// + /// In es, this message translates to: + /// **'¿Salir de la partida?'** + String get leaveGameTitle; + + /// No description provided for @leaveGameSingleDevice. + /// + /// In es, this message translates to: + /// **'Se perderá la partida en curso y no podrás recuperarla.'** + String get leaveGameSingleDevice; + + /// No description provided for @leaveGameHost. + /// + /// In es, this message translates to: + /// **'Eres el anfitrión: si sales, la partida termina para todos los jugadores.'** + String get leaveGameHost; + + /// No description provided for @leaveGameClient. + /// + /// In es, this message translates to: + /// **'Saldrás de la partida. Podrás volver mientras el anfitrión la mantenga abierta.'** + String get leaveGameClient; + + /// No description provided for @stayInGame. + /// + /// In es, this message translates to: + /// **'Seguir jugando'** + String get stayInGame; + + /// No description provided for @permissionsNeededTitle. + /// + /// In es, this message translates to: + /// **'Permisos necesarios'** + String get permissionsNeededTitle; + + /// No description provided for @permissionsNeededBody. + /// + /// In es, this message translates to: + /// **'Para el modo multijugador necesitamos:'** + String get permissionsNeededBody; + + /// No description provided for @openAppSettingsQuestion. + /// + /// In es, this message translates to: + /// **'¿Abrir la configuración de la app?'** + String get openAppSettingsQuestion; + + /// No description provided for @openSettings. + /// + /// In es, this message translates to: + /// **'Abrir configuración'** + String get openSettings; + + /// No description provided for @permissionLocation. + /// + /// In es, this message translates to: + /// **'Ubicación'** + String get permissionLocation; + + /// No description provided for @permissionBluetoothAdvertise. + /// + /// In es, this message translates to: + /// **'Bluetooth (anunciar)'** + String get permissionBluetoothAdvertise; + + /// No description provided for @permissionBluetoothConnect. + /// + /// In es, this message translates to: + /// **'Bluetooth (conectar)'** + String get permissionBluetoothConnect; + + /// No description provided for @permissionBluetoothScan. + /// + /// In es, this message translates to: + /// **'Bluetooth (escanear)'** + String get permissionBluetoothScan; + + /// No description provided for @permissionNearbyWifi. + /// + /// In es, this message translates to: + /// **'Wi-Fi cercano'** + String get permissionNearbyWifi; } class _AppLocalizationsDelegate diff --git a/lib/l10n/generated/app_localizations_ar.dart b/lib/l10n/generated/app_localizations_ar.dart index 6c3ede5..a1314db 100644 --- a/lib/l10n/generated/app_localizations_ar.dart +++ b/lib/l10n/generated/app_localizations_ar.dart @@ -647,83 +647,80 @@ class AppLocalizationsAr extends AppLocalizations { @override String get selectAtLeastThreeUsersToStart => - 'Select at least 3 users to start.'; + 'اختر 3 مستخدمين على الأقل للبدء.'; @override String get hostPhoneMustSelectUser => - 'The host phone must select at least one user.'; + 'يجب أن يختار هاتف المضيف مستخدمًا واحدًا على الأقل.'; @override - String get roomNoLongerInLobby => 'The room is no longer in the lobby.'; + String get roomNoLongerInLobby => 'لم تعد الغرفة في ردهة الانتظار.'; @override - String get completeUserSelectionToStart => - 'Complete user selection to start.'; + String get completeUserSelectionToStart => 'أكمل اختيار المستخدمين للبدء.'; @override - String get preparingSecureRoom => 'Preparing the secure room'; + String get preparingSecureRoom => 'جارٍ تجهيز الغرفة الآمنة'; @override String get searchingNearbyBluetoothGames => - 'Searching nearby games over Bluetooth'; + 'البحث عن جولات قريبة عبر البلوتوث'; @override - String get tapToJoin => 'Tap to join'; + String get tapToJoin => 'اضغط للانضمام'; @override 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 => 'يلزم إذنا البلوتوث والموقع'; @override String get couldNotStartSearch => - 'Could not start the search. Check Bluetooth and location.'; + 'تعذّر بدء البحث. تحقق من البلوتوث والموقع.'; @override String couldNotConnectToHost(String host) { - return 'Could not connect to $host'; + return 'تعذّر الاتصال بـ $host'; } @override String get room => 'غرفة'; @override - String get singleDeviceSubtitle => 'Game on this device'; + String get singleDeviceSubtitle => 'اللعب على هذا الجهاز'; @override String get singleDeviceDescription => - 'Ideal for playing together by passing the phone around. Fast, direct setup.'; + 'مثالي للعب معًا بتمرير الهاتف. إعداد سريع ومباشر.'; @override - String get multiDeviceSubtitle => 'Each player on their phone'; + String get multiDeviceSubtitle => 'كل لاعب على هاتفه'; @override String get multiDeviceDescription => - 'Create a premium room, share the QR code and manage users from the lobby.'; + 'أنشئ غرفة مميزة، وشارك رمز QR، وأدر المستخدمين من ردهة الانتظار.'; @override - String get singleDeviceGameLabel => 'Game on this device'; + String get singleDeviceGameLabel => 'اللعب على هذا الجهاز'; @override - String get multiDeviceGameLabel => 'Multi-device game'; + String get multiDeviceGameLabel => 'لعب متعدد الأجهزة'; @override - String get mainDeviceUser => 'Main device user'; + String get mainDeviceUser => 'المستخدم الرئيسي للجهاز'; @override - String get couldNotCreateRoom => - 'Could not create the room. Check Bluetooth.'; + String get couldNotCreateRoom => 'تعذّر إنشاء الغرفة. تحقق من البلوتوث.'; @override String cannotStartWithReason(String reason) { - return 'Cannot start: $reason'; + return 'تعذّر البدء: $reason'; } @override - String get invalidRoom => 'invalid room'; + String get invalidRoom => 'غرفة غير صالحة'; @override String get defaultPlayerName => 'لاعب'; @@ -834,4 +831,49 @@ class AppLocalizationsAr extends AppLocalizations { String playerRejoined(String name) { return 'عاد $name إلى الجولة'; } + + @override + String get leaveGameTitle => 'هل تريد مغادرة الجولة؟'; + + @override + String get leaveGameSingleDevice => + 'ستفقد الجولة الجارية ولن يمكن استعادتها.'; + + @override + String get leaveGameHost => + 'أنت المضيف: إذا غادرت ستنتهي الجولة لجميع اللاعبين.'; + + @override + String get leaveGameClient => + 'ستغادر الجولة. يمكنك العودة ما دام المضيف يبقيها مفتوحة.'; + + @override + String get stayInGame => 'متابعة اللعب'; + + @override + String get permissionsNeededTitle => 'أذونات مطلوبة'; + + @override + String get permissionsNeededBody => 'لوضع اللعب الجماعي نحتاج إلى:'; + + @override + String get openAppSettingsQuestion => 'هل تريد فتح إعدادات التطبيق؟'; + + @override + String get openSettings => 'فتح الإعدادات'; + + @override + String get permissionLocation => 'الموقع'; + + @override + String get permissionBluetoothAdvertise => 'بلوتوث (الإعلان)'; + + @override + String get permissionBluetoothConnect => 'بلوتوث (الاتصال)'; + + @override + String get permissionBluetoothScan => 'بلوتوث (المسح)'; + + @override + String get permissionNearbyWifi => 'واي فاي قريب'; } diff --git a/lib/l10n/generated/app_localizations_ca.dart b/lib/l10n/generated/app_localizations_ca.dart index b85c799..d71b5a0 100644 --- a/lib/l10n/generated/app_localizations_ca.dart +++ b/lib/l10n/generated/app_localizations_ca.dart @@ -844,4 +844,50 @@ class AppLocalizationsCa extends AppLocalizations { String playerRejoined(String name) { return '$name ha tornat a la partida'; } + + @override + String get leaveGameTitle => 'Vols sortir de la partida?'; + + @override + String get leaveGameSingleDevice => + 'Es perdrà la partida en curs i no la podràs recuperar.'; + + @override + String get leaveGameHost => + 'Ets l\'amfitrió: si surts, la partida s\'acaba per a tots els jugadors.'; + + @override + String get leaveGameClient => + 'Sortiràs de la partida. Hi podràs tornar mentre l\'amfitrió la mantingui oberta.'; + + @override + String get stayInGame => 'Continuar jugant'; + + @override + String get permissionsNeededTitle => 'Permisos necessaris'; + + @override + String get permissionsNeededBody => 'Per al mode multijugador necessitem:'; + + @override + String get openAppSettingsQuestion => + 'Vols obrir la configuració de l\'aplicació?'; + + @override + String get openSettings => 'Obrir configuració'; + + @override + String get permissionLocation => 'Ubicació'; + + @override + String get permissionBluetoothAdvertise => 'Bluetooth (anunciar)'; + + @override + String get permissionBluetoothConnect => 'Bluetooth (connectar)'; + + @override + String get permissionBluetoothScan => 'Bluetooth (escanejar)'; + + @override + String get permissionNearbyWifi => 'Wi-Fi proper'; } diff --git a/lib/l10n/generated/app_localizations_de.dart b/lib/l10n/generated/app_localizations_de.dart index a1dbc7f..5a6ad7e 100644 --- a/lib/l10n/generated/app_localizations_de.dart +++ b/lib/l10n/generated/app_localizations_de.dart @@ -847,4 +847,49 @@ class AppLocalizationsDe extends AppLocalizations { String playerRejoined(String name) { return '$name ist zurück im Spiel'; } + + @override + String get leaveGameTitle => 'Spiel wirklich verlassen?'; + + @override + String get leaveGameSingleDevice => + 'Das laufende Spiel geht verloren und lässt sich nicht wiederherstellen.'; + + @override + String get leaveGameHost => + 'Du bist der Host: Wenn du gehst, endet das Spiel für alle.'; + + @override + String get leaveGameClient => + 'Du verlässt das Spiel. Du kannst zurückkommen, solange der Host es offen hält.'; + + @override + String get stayInGame => 'Weiterspielen'; + + @override + String get permissionsNeededTitle => 'Berechtigungen erforderlich'; + + @override + String get permissionsNeededBody => 'Für den Mehrspielermodus brauchen wir:'; + + @override + String get openAppSettingsQuestion => 'Die App-Einstellungen öffnen?'; + + @override + String get openSettings => 'Einstellungen öffnen'; + + @override + String get permissionLocation => 'Standort'; + + @override + String get permissionBluetoothAdvertise => 'Bluetooth (sichtbar machen)'; + + @override + String get permissionBluetoothConnect => 'Bluetooth (verbinden)'; + + @override + String get permissionBluetoothScan => 'Bluetooth (suchen)'; + + @override + String get permissionNearbyWifi => 'Wi-Fi in der Nähe'; } diff --git a/lib/l10n/generated/app_localizations_en.dart b/lib/l10n/generated/app_localizations_en.dart index 7d039b4..fa83745 100644 --- a/lib/l10n/generated/app_localizations_en.dart +++ b/lib/l10n/generated/app_localizations_en.dart @@ -840,4 +840,49 @@ class AppLocalizationsEn extends AppLocalizations { String playerRejoined(String name) { return '$name has rejoined the game'; } + + @override + String get leaveGameTitle => 'Leave the game?'; + + @override + String get leaveGameSingleDevice => + 'The game in progress will be lost and cannot be recovered.'; + + @override + String get leaveGameHost => + 'You are the host: if you leave, the game ends for everyone.'; + + @override + String get leaveGameClient => + 'You will leave the game. You can rejoin while the host keeps it open.'; + + @override + String get stayInGame => 'Keep playing'; + + @override + String get permissionsNeededTitle => 'Permissions needed'; + + @override + String get permissionsNeededBody => 'For multiplayer mode we need:'; + + @override + String get openAppSettingsQuestion => 'Open the app settings?'; + + @override + String get openSettings => 'Open settings'; + + @override + String get permissionLocation => 'Location'; + + @override + String get permissionBluetoothAdvertise => 'Bluetooth (advertise)'; + + @override + String get permissionBluetoothConnect => 'Bluetooth (connect)'; + + @override + String get permissionBluetoothScan => 'Bluetooth (scan)'; + + @override + String get permissionNearbyWifi => 'Nearby Wi-Fi'; } diff --git a/lib/l10n/generated/app_localizations_es.dart b/lib/l10n/generated/app_localizations_es.dart index 69c2c55..41e644e 100644 --- a/lib/l10n/generated/app_localizations_es.dart +++ b/lib/l10n/generated/app_localizations_es.dart @@ -841,4 +841,49 @@ class AppLocalizationsEs extends AppLocalizations { String playerRejoined(String name) { return '$name ha vuelto a la partida'; } + + @override + String get leaveGameTitle => '¿Salir de la partida?'; + + @override + String get leaveGameSingleDevice => + 'Se perderá la partida en curso y no podrás recuperarla.'; + + @override + String get leaveGameHost => + 'Eres el anfitrión: si sales, la partida termina para todos los jugadores.'; + + @override + String get leaveGameClient => + 'Saldrás de la partida. Podrás volver mientras el anfitrión la mantenga abierta.'; + + @override + String get stayInGame => 'Seguir jugando'; + + @override + String get permissionsNeededTitle => 'Permisos necesarios'; + + @override + String get permissionsNeededBody => 'Para el modo multijugador necesitamos:'; + + @override + String get openAppSettingsQuestion => '¿Abrir la configuración de la app?'; + + @override + String get openSettings => 'Abrir configuración'; + + @override + String get permissionLocation => 'Ubicación'; + + @override + String get permissionBluetoothAdvertise => 'Bluetooth (anunciar)'; + + @override + String get permissionBluetoothConnect => 'Bluetooth (conectar)'; + + @override + String get permissionBluetoothScan => 'Bluetooth (escanear)'; + + @override + String get permissionNearbyWifi => 'Wi-Fi cercano'; } diff --git a/lib/l10n/generated/app_localizations_eu.dart b/lib/l10n/generated/app_localizations_eu.dart index f127935..8c754cf 100644 --- a/lib/l10n/generated/app_localizations_eu.dart +++ b/lib/l10n/generated/app_localizations_eu.dart @@ -657,83 +657,83 @@ class AppLocalizationsEu extends AppLocalizations { @override String get selectAtLeastThreeUsersToStart => - 'Select at least 3 users to start.'; + 'Hautatu gutxienez 3 erabiltzaile hasteko.'; @override String get hostPhoneMustSelectUser => - 'The host phone must select at least one user.'; + 'Ostalariaren mugikorrak gutxienez erabiltzaile bat hautatu behar du.'; @override - String get roomNoLongerInLobby => 'The room is no longer in the lobby.'; + String get roomNoLongerInLobby => 'Gela jada ez dago lobbyan.'; @override String get completeUserSelectionToStart => - 'Complete user selection to start.'; + 'Osatu erabiltzaileen hautaketa hasteko.'; @override - String get preparingSecureRoom => 'Preparing the secure room'; + String get preparingSecureRoom => 'Gela segurua prestatzen'; @override String get searchingNearbyBluetoothGames => - 'Searching nearby games over Bluetooth'; + 'Inguruko partidak bilatzen Bluetooth bidez'; @override - String get tapToJoin => 'Tap to join'; + String get tapToJoin => 'Sakatu batzeko'; @override String get bluetoothLocationPermissionsRequired => - 'Bluetooth and location permissions are required to search for games.'; + 'Bluetooth eta kokapen baimenak behar dira partidak bilatzeko.'; @override String get bluetoothLocationPermissionsShort => - 'Bluetooth and location permissions are required'; + 'Bluetooth eta kokapen baimenak behar dira'; @override String get couldNotStartSearch => - 'Could not start the search. Check Bluetooth and location.'; + 'Ezin izan da bilaketa hasi. Egiaztatu Bluetooth eta kokapena.'; @override String couldNotConnectToHost(String host) { - return 'Could not connect to $host'; + return 'Ezin izan da $host(e)ra konektatu'; } @override String get room => 'Gela'; @override - String get singleDeviceSubtitle => 'Game on this device'; + String get singleDeviceSubtitle => 'Partida gailu honetan'; @override String get singleDeviceDescription => - 'Ideal for playing together by passing the phone around. Fast, direct setup.'; + 'Ezin hobea denok elkarrekin jokatzeko mugikorra pasatuz. Konfigurazio azkarra eta zuzena.'; @override - String get multiDeviceSubtitle => 'Each player on their phone'; + String get multiDeviceSubtitle => 'Jokalari bakoitza bere mugikorrean'; @override String get multiDeviceDescription => - 'Create a premium room, share the QR code and manage users from the lobby.'; + 'Sortu gela premium bat, partekatu QR kodea eta kudeatu erabiltzaileak lobbytik.'; @override - String get singleDeviceGameLabel => 'Game on this device'; + String get singleDeviceGameLabel => 'Partida gailu honetan'; @override - String get multiDeviceGameLabel => 'Multi-device game'; + String get multiDeviceGameLabel => 'Gailu anitzeko partida'; @override - String get mainDeviceUser => 'Main device user'; + String get mainDeviceUser => 'Gailuaren erabiltzaile nagusia'; @override String get couldNotCreateRoom => - 'Could not create the room. Check Bluetooth.'; + 'Ezin izan da gela sortu. Egiaztatu Bluetooth.'; @override String cannotStartWithReason(String reason) { - return 'Cannot start: $reason'; + return 'Ezin da hasi: $reason'; } @override - String get invalidRoom => 'invalid room'; + String get invalidRoom => 'gela baliogabea'; @override String get defaultPlayerName => 'Jokalaria'; @@ -847,4 +847,51 @@ class AppLocalizationsEu extends AppLocalizations { String playerRejoined(String name) { return '$name partidara itzuli da'; } + + @override + String get leaveGameTitle => 'Partidatik irten nahi duzu?'; + + @override + String get leaveGameSingleDevice => + 'Abian den partida galduko da eta ezin izango duzu berreskuratu.'; + + @override + String get leaveGameHost => + 'Zu zara ostalaria: irtenez gero, partida jokalari guztientzat amaituko da.'; + + @override + String get leaveGameClient => + 'Partidatik aterako zara. Itzuli ahal izango zara ostalariak zabalik mantentzen duen bitartean.'; + + @override + String get stayInGame => 'Jokatzen jarraitu'; + + @override + String get permissionsNeededTitle => 'Baimenak behar dira'; + + @override + String get permissionsNeededBody => + 'Jokalari anitzeko modurako hau behar dugu:'; + + @override + String get openAppSettingsQuestion => + 'Aplikazioaren ezarpenak ireki nahi dituzu?'; + + @override + String get openSettings => 'Ireki ezarpenak'; + + @override + String get permissionLocation => 'Kokapena'; + + @override + String get permissionBluetoothAdvertise => 'Bluetooth (iragarri)'; + + @override + String get permissionBluetoothConnect => 'Bluetooth (konektatu)'; + + @override + String get permissionBluetoothScan => 'Bluetooth (eskaneatu)'; + + @override + String get permissionNearbyWifi => 'Inguruko Wi-Fi'; } diff --git a/lib/l10n/generated/app_localizations_fr.dart b/lib/l10n/generated/app_localizations_fr.dart index 5e2ce9c..30e0514 100644 --- a/lib/l10n/generated/app_localizations_fr.dart +++ b/lib/l10n/generated/app_localizations_fr.dart @@ -844,4 +844,51 @@ class AppLocalizationsFr extends AppLocalizations { String playerRejoined(String name) { return '$name a rejoint la partie'; } + + @override + String get leaveGameTitle => 'Quitter la partie ?'; + + @override + String get leaveGameSingleDevice => + 'La partie en cours sera perdue et ne pourra pas être récupérée.'; + + @override + String get leaveGameHost => + 'Vous êtes l\'hôte : si vous partez, la partie se termine pour tout le monde.'; + + @override + String get leaveGameClient => + 'Vous quitterez la partie. Vous pourrez revenir tant que l\'hôte la laisse ouverte.'; + + @override + String get stayInGame => 'Continuer à jouer'; + + @override + String get permissionsNeededTitle => 'Autorisations nécessaires'; + + @override + String get permissionsNeededBody => + 'Pour le mode multijoueur, nous avons besoin de :'; + + @override + String get openAppSettingsQuestion => + 'Ouvrir les paramètres de l\'application ?'; + + @override + String get openSettings => 'Ouvrir les paramètres'; + + @override + String get permissionLocation => 'Localisation'; + + @override + String get permissionBluetoothAdvertise => 'Bluetooth (diffusion)'; + + @override + String get permissionBluetoothConnect => 'Bluetooth (connexion)'; + + @override + String get permissionBluetoothScan => 'Bluetooth (recherche)'; + + @override + String get permissionNearbyWifi => 'Wi-Fi à proximité'; } diff --git a/lib/l10n/generated/app_localizations_hi.dart b/lib/l10n/generated/app_localizations_hi.dart index 6c9e58d..3a572f0 100644 --- a/lib/l10n/generated/app_localizations_hi.dart +++ b/lib/l10n/generated/app_localizations_hi.dart @@ -651,83 +651,82 @@ class AppLocalizationsHi extends AppLocalizations { @override String get selectAtLeastThreeUsersToStart => - 'Select at least 3 users to start.'; + 'शुरू करने के लिए कम से कम 3 उपयोगकर्ता चुनें।'; @override String get hostPhoneMustSelectUser => - 'The host phone must select at least one user.'; + 'होस्ट फ़ोन को कम से कम एक उपयोगकर्ता चुनना होगा।'; @override - String get roomNoLongerInLobby => 'The room is no longer in the lobby.'; + String get roomNoLongerInLobby => 'कमरा अब लॉबी में नहीं है।'; @override String get completeUserSelectionToStart => - 'Complete user selection to start.'; + 'शुरू करने के लिए उपयोगकर्ताओं का चयन पूरा करें।'; @override - String get preparingSecureRoom => 'Preparing the secure room'; + String get preparingSecureRoom => 'सुरक्षित कमरा तैयार किया जा रहा है'; @override String get searchingNearbyBluetoothGames => - 'Searching nearby games over Bluetooth'; + 'ब्लूटूथ से आस-पास के गेम खोजे जा रहे हैं'; @override - String get tapToJoin => 'Tap to join'; + String get tapToJoin => 'शामिल होने के लिए टैप करें'; @override String get bluetoothLocationPermissionsRequired => - 'Bluetooth and location permissions are required to search for games.'; + 'गेम खोजने के लिए ब्लूटूथ और लोकेशन की अनुमति चाहिए।'; @override String get bluetoothLocationPermissionsShort => - 'Bluetooth and location permissions are required'; + 'ब्लूटूथ और लोकेशन की अनुमति चाहिए'; @override String get couldNotStartSearch => - 'Could not start the search. Check Bluetooth and location.'; + 'खोज शुरू नहीं हो सकी। ब्लूटूथ और लोकेशन जाँचें।'; @override String couldNotConnectToHost(String host) { - return 'Could not connect to $host'; + return '$host से कनेक्ट नहीं हो सका'; } @override String get room => 'कक्ष'; @override - String get singleDeviceSubtitle => 'Game on this device'; + String get singleDeviceSubtitle => 'इसी डिवाइस पर खेल'; @override String get singleDeviceDescription => - 'Ideal for playing together by passing the phone around. Fast, direct setup.'; + 'फ़ोन एक-दूसरे को देकर साथ खेलने के लिए बढ़िया। सेटअप तेज़ और सीधा।'; @override - String get multiDeviceSubtitle => 'Each player on their phone'; + String get multiDeviceSubtitle => 'हर खिलाड़ी अपने फ़ोन पर'; @override String get multiDeviceDescription => - 'Create a premium room, share the QR code and manage users from the lobby.'; + 'एक प्रीमियम कमरा बनाएँ, QR साझा करें और लॉबी से उपयोगकर्ता संभालें।'; @override - String get singleDeviceGameLabel => 'Game on this device'; + String get singleDeviceGameLabel => 'इसी डिवाइस पर खेल'; @override - String get multiDeviceGameLabel => 'Multi-device game'; + String get multiDeviceGameLabel => 'मल्टी-डिवाइस खेल'; @override - String get mainDeviceUser => 'Main device user'; + String get mainDeviceUser => 'डिवाइस का मुख्य उपयोगकर्ता'; @override - String get couldNotCreateRoom => - 'Could not create the room. Check Bluetooth.'; + String get couldNotCreateRoom => 'कमरा नहीं बन सका। ब्लूटूथ जाँचें।'; @override String cannotStartWithReason(String reason) { - return 'Cannot start: $reason'; + return 'शुरू नहीं हो सकता: $reason'; } @override - String get invalidRoom => 'invalid room'; + String get invalidRoom => 'अमान्य कमरा'; @override String get defaultPlayerName => 'खिलाड़ी'; @@ -840,4 +839,49 @@ class AppLocalizationsHi extends AppLocalizations { String playerRejoined(String name) { return '$name खेल में वापस आ गए'; } + + @override + String get leaveGameTitle => 'खेल छोड़ना है?'; + + @override + String get leaveGameSingleDevice => + 'चल रहा खेल ख़त्म हो जाएगा और वापस नहीं मिलेगा।'; + + @override + String get leaveGameHost => + 'आप होस्ट हैं: आपके जाने पर सभी खिलाड़ियों का खेल ख़त्म हो जाएगा।'; + + @override + String get leaveGameClient => + 'आप खेल से बाहर निकल जाएँगे। जब तक होस्ट इसे खुला रखे, आप लौट सकते हैं।'; + + @override + String get stayInGame => 'खेलते रहें'; + + @override + String get permissionsNeededTitle => 'अनुमतियाँ चाहिए'; + + @override + String get permissionsNeededBody => 'मल्टीप्लेयर मोड के लिए हमें चाहिए:'; + + @override + String get openAppSettingsQuestion => 'क्या ऐप की सेटिंग खोलें?'; + + @override + String get openSettings => 'सेटिंग खोलें'; + + @override + String get permissionLocation => 'लोकेशन'; + + @override + String get permissionBluetoothAdvertise => 'ब्लूटूथ (प्रसारण)'; + + @override + String get permissionBluetoothConnect => 'ब्लूटूथ (कनेक्ट)'; + + @override + String get permissionBluetoothScan => 'ब्लूटूथ (स्कैन)'; + + @override + String get permissionNearbyWifi => 'आस-पास का वाई-फ़ाई'; } diff --git a/lib/l10n/generated/app_localizations_it.dart b/lib/l10n/generated/app_localizations_it.dart index 3fe4a40..1a8f825 100644 --- a/lib/l10n/generated/app_localizations_it.dart +++ b/lib/l10n/generated/app_localizations_it.dart @@ -844,4 +844,50 @@ class AppLocalizationsIt extends AppLocalizations { String playerRejoined(String name) { return '$name è tornato in partita'; } + + @override + String get leaveGameTitle => 'Vuoi uscire dalla partita?'; + + @override + String get leaveGameSingleDevice => + 'La partita in corso andrà persa e non potrà essere recuperata.'; + + @override + String get leaveGameHost => + 'Sei l\'host: se esci, la partita finisce per tutti i giocatori.'; + + @override + String get leaveGameClient => + 'Uscirai dalla partita. Potrai rientrare finché l\'host la tiene aperta.'; + + @override + String get stayInGame => 'Continua a giocare'; + + @override + String get permissionsNeededTitle => 'Autorizzazioni necessarie'; + + @override + String get permissionsNeededBody => 'Per la modalità multigiocatore servono:'; + + @override + String get openAppSettingsQuestion => + 'Vuoi aprire le impostazioni dell\'app?'; + + @override + String get openSettings => 'Apri impostazioni'; + + @override + String get permissionLocation => 'Posizione'; + + @override + String get permissionBluetoothAdvertise => 'Bluetooth (annuncio)'; + + @override + String get permissionBluetoothConnect => 'Bluetooth (connessione)'; + + @override + String get permissionBluetoothScan => 'Bluetooth (scansione)'; + + @override + String get permissionNearbyWifi => 'Wi-Fi nelle vicinanze'; } diff --git a/lib/l10n/generated/app_localizations_ja.dart b/lib/l10n/generated/app_localizations_ja.dart index f421f07..1c740cd 100644 --- a/lib/l10n/generated/app_localizations_ja.dart +++ b/lib/l10n/generated/app_localizations_ja.dart @@ -645,84 +645,76 @@ class AppLocalizationsJa extends AppLocalizations { String get delete => '削除'; @override - String get selectAtLeastThreeUsersToStart => - 'Select at least 3 users to start.'; + String get selectAtLeastThreeUsersToStart => '開始するには3人以上のユーザーを選んでください。'; @override - String get hostPhoneMustSelectUser => - 'The host phone must select at least one user.'; + String get hostPhoneMustSelectUser => 'ホストの端末は少なくとも1人のユーザーを選ぶ必要があります。'; @override - String get roomNoLongerInLobby => 'The room is no longer in the lobby.'; + String get roomNoLongerInLobby => 'ルームはすでにロビーにありません。'; @override - String get completeUserSelectionToStart => - 'Complete user selection to start.'; + String get completeUserSelectionToStart => '開始するにはユーザーの選択を完了してください。'; @override - String get preparingSecureRoom => 'Preparing the secure room'; + String get preparingSecureRoom => '安全なルームを準備しています'; @override - String get searchingNearbyBluetoothGames => - 'Searching nearby games over Bluetooth'; + String get searchingNearbyBluetoothGames => 'Bluetoothで近くのゲームを検索しています'; @override - String get tapToJoin => 'Tap to join'; + String get tapToJoin => 'タップして参加'; @override String get bluetoothLocationPermissionsRequired => - 'Bluetooth and location permissions are required to search for games.'; + 'ゲームを検索するにはBluetoothと位置情報の許可が必要です。'; @override - String get bluetoothLocationPermissionsShort => - 'Bluetooth and location permissions are required'; + String get bluetoothLocationPermissionsShort => 'Bluetoothと位置情報の許可が必要です'; @override - String get couldNotStartSearch => - 'Could not start the search. Check Bluetooth and location.'; + String get couldNotStartSearch => '検索を開始できませんでした。Bluetoothと位置情報を確認してください。'; @override String couldNotConnectToHost(String host) { - return 'Could not connect to $host'; + return '$host に接続できませんでした'; } @override String get room => 'ルーム'; @override - String get singleDeviceSubtitle => 'Game on this device'; + String get singleDeviceSubtitle => 'この端末でプレイ'; @override - String get singleDeviceDescription => - 'Ideal for playing together by passing the phone around. Fast, direct setup.'; + String get singleDeviceDescription => '端末を回しながらみんなで遊ぶのに最適。設定はすばやく簡単。'; @override - String get multiDeviceSubtitle => 'Each player on their phone'; + String get multiDeviceSubtitle => 'プレイヤーごとに自分の端末で'; @override String get multiDeviceDescription => - 'Create a premium room, share the QR code and manage users from the lobby.'; + 'プレミアムなルームを作り、QRコードを共有し、ロビーからユーザーを管理します。'; @override - String get singleDeviceGameLabel => 'Game on this device'; + String get singleDeviceGameLabel => 'この端末でのゲーム'; @override - String get multiDeviceGameLabel => 'Multi-device game'; + String get multiDeviceGameLabel => 'マルチデバイスのゲーム'; @override - String get mainDeviceUser => 'Main device user'; + String get mainDeviceUser => 'この端末のメインユーザー'; @override - String get couldNotCreateRoom => - 'Could not create the room. Check Bluetooth.'; + String get couldNotCreateRoom => 'ルームを作成できませんでした。Bluetoothを確認してください。'; @override String cannotStartWithReason(String reason) { - return 'Cannot start: $reason'; + return '開始できません: $reason'; } @override - String get invalidRoom => 'invalid room'; + String get invalidRoom => '無効なルーム'; @override String get defaultPlayerName => 'プレイヤー'; @@ -831,4 +823,46 @@ class AppLocalizationsJa extends AppLocalizations { String playerRejoined(String name) { return '$name がゲームに復帰しました'; } + + @override + String get leaveGameTitle => 'ゲームから退出しますか?'; + + @override + String get leaveGameSingleDevice => '進行中のゲームは失われ、元に戻せません。'; + + @override + String get leaveGameHost => 'あなたはホストです。退出すると全員のゲームが終了します。'; + + @override + String get leaveGameClient => 'ゲームから退出します。ホストが開いている間は戻れます。'; + + @override + String get stayInGame => 'ゲームを続ける'; + + @override + String get permissionsNeededTitle => '必要な権限'; + + @override + String get permissionsNeededBody => 'マルチプレイには次の権限が必要です:'; + + @override + String get openAppSettingsQuestion => 'アプリの設定を開きますか?'; + + @override + String get openSettings => '設定を開く'; + + @override + String get permissionLocation => '位置情報'; + + @override + String get permissionBluetoothAdvertise => 'Bluetooth(アドバタイズ)'; + + @override + String get permissionBluetoothConnect => 'Bluetooth(接続)'; + + @override + String get permissionBluetoothScan => 'Bluetooth(スキャン)'; + + @override + String get permissionNearbyWifi => '近くのWi-Fi'; } diff --git a/lib/l10n/generated/app_localizations_ko.dart b/lib/l10n/generated/app_localizations_ko.dart index c4ee5cc..071b790 100644 --- a/lib/l10n/generated/app_localizations_ko.dart +++ b/lib/l10n/generated/app_localizations_ko.dart @@ -645,84 +645,77 @@ class AppLocalizationsKo extends AppLocalizations { String get delete => '삭제'; @override - String get selectAtLeastThreeUsersToStart => - 'Select at least 3 users to start.'; + String get selectAtLeastThreeUsersToStart => '시작하려면 사용자를 3명 이상 선택하세요.'; @override - String get hostPhoneMustSelectUser => - 'The host phone must select at least one user.'; + String get hostPhoneMustSelectUser => '호스트 기기는 사용자를 최소 한 명 선택해야 합니다.'; @override - String get roomNoLongerInLobby => 'The room is no longer in the lobby.'; + String get roomNoLongerInLobby => '방이 더 이상 대기실에 없습니다.'; @override - String get completeUserSelectionToStart => - 'Complete user selection to start.'; + String get completeUserSelectionToStart => '시작하려면 사용자 선택을 마치세요.'; @override - String get preparingSecureRoom => 'Preparing the secure room'; + String get preparingSecureRoom => '보안 방을 준비하는 중'; @override - String get searchingNearbyBluetoothGames => - 'Searching nearby games over Bluetooth'; + String get searchingNearbyBluetoothGames => '블루투스로 근처 게임을 찾는 중'; @override - String get tapToJoin => 'Tap to join'; + String get tapToJoin => '눌러서 참여하기'; @override 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 => '블루투스와 위치 권한이 필요합니다'; @override - String get couldNotStartSearch => - 'Could not start the search. Check Bluetooth and location.'; + String get couldNotStartSearch => '검색을 시작할 수 없습니다. 블루투스와 위치를 확인하세요.'; @override String couldNotConnectToHost(String host) { - return 'Could not connect to $host'; + return '$host에 연결할 수 없습니다'; } @override String get room => '방'; @override - String get singleDeviceSubtitle => 'Game on this device'; + String get singleDeviceSubtitle => '이 기기에서 진행'; @override String get singleDeviceDescription => - 'Ideal for playing together by passing the phone around. Fast, direct setup.'; + '휴대전화를 돌려 가며 함께 놀기에 좋습니다. 설정이 빠르고 간단합니다.'; @override - String get multiDeviceSubtitle => 'Each player on their phone'; + String get multiDeviceSubtitle => '각자 자기 휴대전화로'; @override String get multiDeviceDescription => - 'Create a premium room, share the QR code and manage users from the lobby.'; + '프리미엄 방을 만들고 QR 코드를 공유하며 대기실에서 사용자를 관리하세요.'; @override - String get singleDeviceGameLabel => 'Game on this device'; + String get singleDeviceGameLabel => '이 기기에서 하는 게임'; @override - String get multiDeviceGameLabel => 'Multi-device game'; + String get multiDeviceGameLabel => '여러 기기로 하는 게임'; @override - String get mainDeviceUser => 'Main device user'; + String get mainDeviceUser => '이 기기의 주 사용자'; @override - String get couldNotCreateRoom => - 'Could not create the room. Check Bluetooth.'; + String get couldNotCreateRoom => '방을 만들 수 없습니다. 블루투스를 확인하세요.'; @override String cannotStartWithReason(String reason) { - return 'Cannot start: $reason'; + return '시작할 수 없습니다: $reason'; } @override - String get invalidRoom => 'invalid room'; + String get invalidRoom => '잘못된 방'; @override String get defaultPlayerName => '플레이어'; @@ -831,4 +824,46 @@ class AppLocalizationsKo extends AppLocalizations { String playerRejoined(String name) { return '$name 님이 게임에 복귀했습니다'; } + + @override + String get leaveGameTitle => '게임에서 나갈까요?'; + + @override + String get leaveGameSingleDevice => '진행 중인 게임이 사라지며 되돌릴 수 없습니다.'; + + @override + String get leaveGameHost => '당신은 호스트입니다. 나가면 모두의 게임이 끝납니다.'; + + @override + String get leaveGameClient => '게임에서 나갑니다. 호스트가 열어 두는 동안에는 다시 들어올 수 있습니다.'; + + @override + String get stayInGame => '계속 하기'; + + @override + String get permissionsNeededTitle => '필요한 권한'; + + @override + String get permissionsNeededBody => '멀티플레이 모드에는 다음 권한이 필요합니다:'; + + @override + String get openAppSettingsQuestion => '앱 설정을 열까요?'; + + @override + String get openSettings => '설정 열기'; + + @override + String get permissionLocation => '위치'; + + @override + String get permissionBluetoothAdvertise => '블루투스(광고)'; + + @override + String get permissionBluetoothConnect => '블루투스(연결)'; + + @override + String get permissionBluetoothScan => '블루투스(검색)'; + + @override + String get permissionNearbyWifi => '근처 Wi-Fi'; } diff --git a/lib/l10n/generated/app_localizations_nl.dart b/lib/l10n/generated/app_localizations_nl.dart index 749d4f9..f6bd071 100644 --- a/lib/l10n/generated/app_localizations_nl.dart +++ b/lib/l10n/generated/app_localizations_nl.dart @@ -655,83 +655,83 @@ class AppLocalizationsNl extends AppLocalizations { @override String get selectAtLeastThreeUsersToStart => - 'Select at least 3 users to start.'; + 'Selecteer minstens 3 gebruikers om te starten.'; @override String get hostPhoneMustSelectUser => - 'The host phone must select at least one user.'; + 'De host-telefoon moet minstens één gebruiker selecteren.'; @override - String get roomNoLongerInLobby => 'The room is no longer in the lobby.'; + String get roomNoLongerInLobby => 'De ruimte is niet meer in de lobby.'; @override String get completeUserSelectionToStart => - 'Complete user selection to start.'; + 'Voltooi de gebruikersselectie om te starten.'; @override - String get preparingSecureRoom => 'Preparing the secure room'; + String get preparingSecureRoom => 'Beveiligde ruimte voorbereiden'; @override String get searchingNearbyBluetoothGames => - 'Searching nearby games over Bluetooth'; + 'Zoeken naar spellen in de buurt via Bluetooth'; @override - String get tapToJoin => 'Tap to join'; + String get tapToJoin => 'Tik om deel te nemen'; @override String get bluetoothLocationPermissionsRequired => - 'Bluetooth and location permissions are required to search for games.'; + 'Bluetooth- en locatietoestemming zijn nodig om spellen te zoeken.'; @override String get bluetoothLocationPermissionsShort => - 'Bluetooth and location permissions are required'; + 'Bluetooth- en locatietoestemming zijn nodig'; @override String get couldNotStartSearch => - 'Could not start the search. Check Bluetooth and location.'; + 'Kon het zoeken niet starten. Controleer Bluetooth en locatie.'; @override String couldNotConnectToHost(String host) { - return 'Could not connect to $host'; + return 'Kon geen verbinding maken met $host'; } @override String get room => 'Kamer'; @override - String get singleDeviceSubtitle => 'Game on this device'; + String get singleDeviceSubtitle => 'Spel op dit toestel'; @override String get singleDeviceDescription => - 'Ideal for playing together by passing the phone around. Fast, direct setup.'; + 'Ideaal om samen te spelen door de telefoon door te geven. Snel en direct ingesteld.'; @override - String get multiDeviceSubtitle => 'Each player on their phone'; + String get multiDeviceSubtitle => 'Elke speler op zijn eigen telefoon'; @override String get multiDeviceDescription => - 'Create a premium room, share the QR code and manage users from the lobby.'; + 'Maak een premium ruimte, deel de QR-code en beheer gebruikers vanuit de lobby.'; @override - String get singleDeviceGameLabel => 'Game on this device'; + String get singleDeviceGameLabel => 'Spel op dit toestel'; @override - String get multiDeviceGameLabel => 'Multi-device game'; + String get multiDeviceGameLabel => 'Spel met meerdere toestellen'; @override - String get mainDeviceUser => 'Main device user'; + String get mainDeviceUser => 'Hoofdgebruiker van dit toestel'; @override String get couldNotCreateRoom => - 'Could not create the room. Check Bluetooth.'; + 'Kon de ruimte niet aanmaken. Controleer Bluetooth.'; @override String cannotStartWithReason(String reason) { - return 'Cannot start: $reason'; + return 'Kan niet starten: $reason'; } @override - String get invalidRoom => 'invalid room'; + String get invalidRoom => 'ongeldige ruimte'; @override String get defaultPlayerName => 'Speler'; @@ -845,4 +845,50 @@ class AppLocalizationsNl extends AppLocalizations { String playerRejoined(String name) { return '$name is terug in het spel'; } + + @override + String get leaveGameTitle => 'Het spel verlaten?'; + + @override + String get leaveGameSingleDevice => + 'Het lopende spel gaat verloren en kan niet worden hersteld.'; + + @override + String get leaveGameHost => + 'Jij bent de host: als je weggaat, eindigt het spel voor iedereen.'; + + @override + String get leaveGameClient => + 'Je verlaat het spel. Je kunt terugkomen zolang de host het openhoudt.'; + + @override + String get stayInGame => 'Verder spelen'; + + @override + String get permissionsNeededTitle => 'Toestemmingen nodig'; + + @override + String get permissionsNeededBody => + 'Voor de multiplayermodus hebben we nodig:'; + + @override + String get openAppSettingsQuestion => 'De app-instellingen openen?'; + + @override + String get openSettings => 'Instellingen openen'; + + @override + String get permissionLocation => 'Locatie'; + + @override + String get permissionBluetoothAdvertise => 'Bluetooth (zichtbaar maken)'; + + @override + String get permissionBluetoothConnect => 'Bluetooth (verbinden)'; + + @override + String get permissionBluetoothScan => 'Bluetooth (scannen)'; + + @override + String get permissionNearbyWifi => 'Wi-Fi in de buurt'; } diff --git a/lib/l10n/generated/app_localizations_pl.dart b/lib/l10n/generated/app_localizations_pl.dart index 30f178a..bce2b37 100644 --- a/lib/l10n/generated/app_localizations_pl.dart +++ b/lib/l10n/generated/app_localizations_pl.dart @@ -653,83 +653,83 @@ class AppLocalizationsPl extends AppLocalizations { @override String get selectAtLeastThreeUsersToStart => - 'Select at least 3 users to start.'; + 'Wybierz co najmniej 3 użytkowników, aby rozpocząć.'; @override String get hostPhoneMustSelectUser => - 'The host phone must select at least one user.'; + 'Telefon gospodarza musi wybrać przynajmniej jednego użytkownika.'; @override - String get roomNoLongerInLobby => 'The room is no longer in the lobby.'; + String get roomNoLongerInLobby => 'Pokój nie jest już w poczekalni.'; @override String get completeUserSelectionToStart => - 'Complete user selection to start.'; + 'Dokończ wybór użytkowników, aby rozpocząć.'; @override - String get preparingSecureRoom => 'Preparing the secure room'; + String get preparingSecureRoom => 'Przygotowywanie bezpiecznego pokoju'; @override String get searchingNearbyBluetoothGames => - 'Searching nearby games over Bluetooth'; + 'Szukanie gier w pobliżu przez Bluetooth'; @override - String get tapToJoin => 'Tap to join'; + String get tapToJoin => 'Dotknij, aby dołączyć'; @override String get bluetoothLocationPermissionsRequired => - 'Bluetooth and location permissions are required to search for games.'; + 'Do wyszukiwania gier potrzebne są uprawnienia Bluetooth i lokalizacji.'; @override String get bluetoothLocationPermissionsShort => - 'Bluetooth and location permissions are required'; + 'Potrzebne są uprawnienia Bluetooth i lokalizacji'; @override String get couldNotStartSearch => - 'Could not start the search. Check Bluetooth and location.'; + 'Nie udało się rozpocząć wyszukiwania. Sprawdź Bluetooth i lokalizację.'; @override String couldNotConnectToHost(String host) { - return 'Could not connect to $host'; + return 'Nie udało się połączyć z $host'; } @override String get room => 'Pokój'; @override - String get singleDeviceSubtitle => 'Game on this device'; + String get singleDeviceSubtitle => 'Gra na tym urządzeniu'; @override String get singleDeviceDescription => - 'Ideal for playing together by passing the phone around. Fast, direct setup.'; + 'Idealne do wspólnej gry, podając telefon dalej. Szybka i prosta konfiguracja.'; @override - String get multiDeviceSubtitle => 'Each player on their phone'; + String get multiDeviceSubtitle => 'Każdy gracz na swoim telefonie'; @override String get multiDeviceDescription => - 'Create a premium room, share the QR code and manage users from the lobby.'; + 'Utwórz pokój premium, udostępnij kod QR i zarządzaj graczami z poczekalni.'; @override - String get singleDeviceGameLabel => 'Game on this device'; + String get singleDeviceGameLabel => 'Gra na tym urządzeniu'; @override - String get multiDeviceGameLabel => 'Multi-device game'; + String get multiDeviceGameLabel => 'Gra na wielu urządzeniach'; @override - String get mainDeviceUser => 'Main device user'; + String get mainDeviceUser => 'Główny użytkownik urządzenia'; @override String get couldNotCreateRoom => - 'Could not create the room. Check Bluetooth.'; + 'Nie udało się utworzyć pokoju. Sprawdź Bluetooth.'; @override String cannotStartWithReason(String reason) { - return 'Cannot start: $reason'; + return 'Nie można rozpocząć: $reason'; } @override - String get invalidRoom => 'invalid room'; + String get invalidRoom => 'nieprawidłowy pokój'; @override String get defaultPlayerName => 'Gracz'; @@ -842,4 +842,49 @@ class AppLocalizationsPl extends AppLocalizations { String playerRejoined(String name) { return '$name wrócił(a) do gry'; } + + @override + String get leaveGameTitle => 'Opuścić grę?'; + + @override + String get leaveGameSingleDevice => + 'Trwająca gra zostanie utracona i nie da się jej odzyskać.'; + + @override + String get leaveGameHost => + 'Jesteś gospodarzem: jeśli wyjdziesz, gra kończy się dla wszystkich.'; + + @override + String get leaveGameClient => + 'Opuścisz grę. Możesz wrócić, dopóki gospodarz jej nie zamknie.'; + + @override + String get stayInGame => 'Graj dalej'; + + @override + String get permissionsNeededTitle => 'Wymagane uprawnienia'; + + @override + String get permissionsNeededBody => 'Do trybu wieloosobowego potrzebujemy:'; + + @override + String get openAppSettingsQuestion => 'Otworzyć ustawienia aplikacji?'; + + @override + String get openSettings => 'Otwórz ustawienia'; + + @override + String get permissionLocation => 'Lokalizacja'; + + @override + String get permissionBluetoothAdvertise => 'Bluetooth (rozgłaszanie)'; + + @override + String get permissionBluetoothConnect => 'Bluetooth (łączenie)'; + + @override + String get permissionBluetoothScan => 'Bluetooth (skanowanie)'; + + @override + String get permissionNearbyWifi => 'Wi-Fi w pobliżu'; } diff --git a/lib/l10n/generated/app_localizations_pt.dart b/lib/l10n/generated/app_localizations_pt.dart index 433ff71..9cbad93 100644 --- a/lib/l10n/generated/app_localizations_pt.dart +++ b/lib/l10n/generated/app_localizations_pt.dart @@ -28,7 +28,7 @@ class AppLocalizationsPt extends AppLocalizations { 'Sem medalhas novas desta vez. Continua a acumular fogo.'; @override - String get calculatingRewards => 'Calculando recompensas...'; + String get calculatingRewards => 'A calcular recompensas...'; @override String get fireLabel => 'Fogo'; @@ -194,7 +194,7 @@ class AppLocalizationsPt extends AppLocalizations { 'Certifique-se de que ninguém mais está olhando'; @override - String get showingWord => '👁️ Mostrando...'; + String get showingWord => '👁️ A mostrar...'; @override String get holdToSee => '👆 Mantenha pressionado para ver'; @@ -263,7 +263,7 @@ class AppLocalizationsPt extends AppLocalizations { String get result => 'Resultado'; @override - String get revealing => 'Revelando...'; + String get revealing => 'A revelar...'; @override String get wasImpostor => 'Era IMPOSTOR! 🎉'; @@ -845,4 +845,49 @@ class AppLocalizationsPt extends AppLocalizations { String playerRejoined(String name) { return '$name voltou ao jogo'; } + + @override + String get leaveGameTitle => 'Sair do jogo?'; + + @override + String get leaveGameSingleDevice => + 'O jogo em curso perde-se e não poderá ser recuperado.'; + + @override + String get leaveGameHost => + 'És o anfitrião: se saíres, o jogo termina para todos os jogadores.'; + + @override + String get leaveGameClient => + 'Vais sair do jogo. Podes voltar enquanto o anfitrião o mantiver aberto.'; + + @override + String get stayInGame => 'Continuar a jogar'; + + @override + String get permissionsNeededTitle => 'Permissões necessárias'; + + @override + String get permissionsNeededBody => 'Para o modo multijogador precisamos de:'; + + @override + String get openAppSettingsQuestion => 'Abrir as definições da aplicação?'; + + @override + String get openSettings => 'Abrir definições'; + + @override + String get permissionLocation => 'Localização'; + + @override + String get permissionBluetoothAdvertise => 'Bluetooth (anunciar)'; + + @override + String get permissionBluetoothConnect => 'Bluetooth (ligar)'; + + @override + String get permissionBluetoothScan => 'Bluetooth (procurar)'; + + @override + String get permissionNearbyWifi => 'Wi-Fi por perto'; } diff --git a/lib/l10n/generated/app_localizations_ru.dart b/lib/l10n/generated/app_localizations_ru.dart index 4342e2c..20ae87f 100644 --- a/lib/l10n/generated/app_localizations_ru.dart +++ b/lib/l10n/generated/app_localizations_ru.dart @@ -652,83 +652,83 @@ class AppLocalizationsRu extends AppLocalizations { @override String get selectAtLeastThreeUsersToStart => - 'Select at least 3 users to start.'; + 'Выберите не менее 3 пользователей, чтобы начать.'; @override String get hostPhoneMustSelectUser => - 'The host phone must select at least one user.'; + 'Телефон ведущего должен выбрать хотя бы одного пользователя.'; @override - String get roomNoLongerInLobby => 'The room is no longer in the lobby.'; + String get roomNoLongerInLobby => 'Комната больше не в лобби.'; @override String get completeUserSelectionToStart => - 'Complete user selection to start.'; + 'Завершите выбор пользователей, чтобы начать.'; @override - String get preparingSecureRoom => 'Preparing the secure room'; + String get preparingSecureRoom => 'Подготовка защищённой комнаты'; @override String get searchingNearbyBluetoothGames => - 'Searching nearby games over Bluetooth'; + 'Поиск игр поблизости через Bluetooth'; @override - String get tapToJoin => 'Tap to join'; + String get tapToJoin => 'Нажмите, чтобы присоединиться'; @override String get bluetoothLocationPermissionsRequired => - 'Bluetooth and location permissions are required to search for games.'; + 'Для поиска игр нужны разрешения Bluetooth и геолокации.'; @override String get bluetoothLocationPermissionsShort => - 'Bluetooth and location permissions are required'; + 'Нужны разрешения Bluetooth и геолокации'; @override String get couldNotStartSearch => - 'Could not start the search. Check Bluetooth and location.'; + 'Не удалось начать поиск. Проверьте Bluetooth и геолокацию.'; @override String couldNotConnectToHost(String host) { - return 'Could not connect to $host'; + return 'Не удалось подключиться к $host'; } @override String get room => 'Комната'; @override - String get singleDeviceSubtitle => 'Game on this device'; + String get singleDeviceSubtitle => 'Игра на этом устройстве'; @override String get singleDeviceDescription => - 'Ideal for playing together by passing the phone around. Fast, direct setup.'; + 'Идеально, чтобы играть вместе, передавая телефон. Быстрая и простая настройка.'; @override - String get multiDeviceSubtitle => 'Each player on their phone'; + String get multiDeviceSubtitle => 'Каждый игрок на своём телефоне'; @override String get multiDeviceDescription => - 'Create a premium room, share the QR code and manage users from the lobby.'; + 'Создайте премиум-комнату, поделитесь QR-кодом и управляйте игроками из лобби.'; @override - String get singleDeviceGameLabel => 'Game on this device'; + String get singleDeviceGameLabel => 'Игра на этом устройстве'; @override - String get multiDeviceGameLabel => 'Multi-device game'; + String get multiDeviceGameLabel => 'Игра на нескольких устройствах'; @override - String get mainDeviceUser => 'Main device user'; + String get mainDeviceUser => 'Основной пользователь устройства'; @override String get couldNotCreateRoom => - 'Could not create the room. Check Bluetooth.'; + 'Не удалось создать комнату. Проверьте Bluetooth.'; @override String cannotStartWithReason(String reason) { - return 'Cannot start: $reason'; + return 'Невозможно начать: $reason'; } @override - String get invalidRoom => 'invalid room'; + String get invalidRoom => 'недопустимая комната'; @override String get defaultPlayerName => 'Игрок'; @@ -841,4 +841,50 @@ class AppLocalizationsRu extends AppLocalizations { String playerRejoined(String name) { return '$name вернулся в игру'; } + + @override + String get leaveGameTitle => 'Выйти из игры?'; + + @override + String get leaveGameSingleDevice => + 'Текущая партия будет потеряна без возможности восстановления.'; + + @override + String get leaveGameHost => + 'Вы ведущий: если вы выйдете, игра закончится для всех.'; + + @override + String get leaveGameClient => + 'Вы выйдете из игры. Вы сможете вернуться, пока ведущий её не закрыл.'; + + @override + String get stayInGame => 'Продолжить игру'; + + @override + String get permissionsNeededTitle => 'Нужны разрешения'; + + @override + String get permissionsNeededBody => + 'Для многопользовательского режима нужны:'; + + @override + String get openAppSettingsQuestion => 'Открыть настройки приложения?'; + + @override + String get openSettings => 'Открыть настройки'; + + @override + String get permissionLocation => 'Геолокация'; + + @override + String get permissionBluetoothAdvertise => 'Bluetooth (объявление)'; + + @override + String get permissionBluetoothConnect => 'Bluetooth (подключение)'; + + @override + String get permissionBluetoothScan => 'Bluetooth (сканирование)'; + + @override + String get permissionNearbyWifi => 'Wi-Fi поблизости'; } diff --git a/lib/l10n/generated/app_localizations_tr.dart b/lib/l10n/generated/app_localizations_tr.dart index 87723ec..0bfcd33 100644 --- a/lib/l10n/generated/app_localizations_tr.dart +++ b/lib/l10n/generated/app_localizations_tr.dart @@ -652,83 +652,83 @@ class AppLocalizationsTr extends AppLocalizations { @override String get selectAtLeastThreeUsersToStart => - 'Select at least 3 users to start.'; + 'Başlamak için en az 3 kullanıcı seç.'; @override String get hostPhoneMustSelectUser => - 'The host phone must select at least one user.'; + 'Sunucu telefonu en az bir kullanıcı seçmeli.'; @override - String get roomNoLongerInLobby => 'The room is no longer in the lobby.'; + String get roomNoLongerInLobby => 'Oda artık lobide değil.'; @override String get completeUserSelectionToStart => - 'Complete user selection to start.'; + 'Başlamak için kullanıcı seçimini tamamla.'; @override - String get preparingSecureRoom => 'Preparing the secure room'; + String get preparingSecureRoom => 'Güvenli oda hazırlanıyor'; @override String get searchingNearbyBluetoothGames => - 'Searching nearby games over Bluetooth'; + 'Bluetooth ile yakındaki oyunlar aranıyor'; @override - String get tapToJoin => 'Tap to join'; + String get tapToJoin => 'Katılmak için dokun'; @override String get bluetoothLocationPermissionsRequired => - 'Bluetooth and location permissions are required to search for games.'; + 'Oyun aramak için Bluetooth ve konum izinleri gerekli.'; @override String get bluetoothLocationPermissionsShort => - 'Bluetooth and location permissions are required'; + 'Bluetooth ve konum izinleri gerekli'; @override String get couldNotStartSearch => - 'Could not start the search. Check Bluetooth and location.'; + 'Arama başlatılamadı. Bluetooth ve konumu kontrol et.'; @override String couldNotConnectToHost(String host) { - return 'Could not connect to $host'; + return '$host bağlantısı kurulamadı'; } @override String get room => 'Oda'; @override - String get singleDeviceSubtitle => 'Game on this device'; + String get singleDeviceSubtitle => 'Bu cihazda oyun'; @override String get singleDeviceDescription => - 'Ideal for playing together by passing the phone around. Fast, direct setup.'; + 'Telefonu elden ele dolaştırarak birlikte oynamak için ideal. Hızlı ve doğrudan kurulum.'; @override - String get multiDeviceSubtitle => 'Each player on their phone'; + String get multiDeviceSubtitle => 'Her oyuncu kendi telefonunda'; @override String get multiDeviceDescription => - 'Create a premium room, share the QR code and manage users from the lobby.'; + 'Premium bir oda oluştur, QR kodu paylaş ve kullanıcıları lobiden yönet.'; @override - String get singleDeviceGameLabel => 'Game on this device'; + String get singleDeviceGameLabel => 'Bu cihazda oyun'; @override - String get multiDeviceGameLabel => 'Multi-device game'; + String get multiDeviceGameLabel => 'Çok cihazlı oyun'; @override - String get mainDeviceUser => 'Main device user'; + String get mainDeviceUser => 'Cihazın ana kullanıcısı'; @override String get couldNotCreateRoom => - 'Could not create the room. Check Bluetooth.'; + 'Oda oluşturulamadı. Bluetooth\'u kontrol et.'; @override String cannotStartWithReason(String reason) { - return 'Cannot start: $reason'; + return 'Başlatılamıyor: $reason'; } @override - String get invalidRoom => 'invalid room'; + String get invalidRoom => 'geçersiz oda'; @override String get defaultPlayerName => 'Oyuncu'; @@ -841,4 +841,48 @@ class AppLocalizationsTr extends AppLocalizations { String playerRejoined(String name) { return '$name oyuna geri döndü'; } + + @override + String get leaveGameTitle => 'Oyundan çıkılsın mı?'; + + @override + String get leaveGameSingleDevice => + 'Devam eden oyun kaybolur ve geri getirilemez.'; + + @override + String get leaveGameHost => 'Sunucu sensin: çıkarsan oyun herkes için biter.'; + + @override + String get leaveGameClient => + 'Oyundan çıkacaksın. Sunucu odayı açık tuttuğu sürece geri dönebilirsin.'; + + @override + String get stayInGame => 'Oynamaya devam et'; + + @override + String get permissionsNeededTitle => 'Gerekli izinler'; + + @override + String get permissionsNeededBody => 'Çok oyunculu mod için şunlar gerekli:'; + + @override + String get openAppSettingsQuestion => 'Uygulama ayarları açılsın mı?'; + + @override + String get openSettings => 'Ayarları aç'; + + @override + String get permissionLocation => 'Konum'; + + @override + String get permissionBluetoothAdvertise => 'Bluetooth (yayın)'; + + @override + String get permissionBluetoothConnect => 'Bluetooth (bağlanma)'; + + @override + String get permissionBluetoothScan => 'Bluetooth (tarama)'; + + @override + String get permissionNearbyWifi => 'Yakındaki Wi-Fi'; } diff --git a/lib/l10n/generated/app_localizations_zh.dart b/lib/l10n/generated/app_localizations_zh.dart index b559ef9..83cc9cd 100644 --- a/lib/l10n/generated/app_localizations_zh.dart +++ b/lib/l10n/generated/app_localizations_zh.dart @@ -643,84 +643,74 @@ class AppLocalizationsZh extends AppLocalizations { String get delete => '删除'; @override - String get selectAtLeastThreeUsersToStart => - 'Select at least 3 users to start.'; + String get selectAtLeastThreeUsersToStart => '至少选择 3 名用户才能开始。'; @override - String get hostPhoneMustSelectUser => - 'The host phone must select at least one user.'; + String get hostPhoneMustSelectUser => '房主的手机必须至少选择一名用户。'; @override - String get roomNoLongerInLobby => 'The room is no longer in the lobby.'; + String get roomNoLongerInLobby => '房间已不在等候大厅。'; @override - String get completeUserSelectionToStart => - 'Complete user selection to start.'; + String get completeUserSelectionToStart => '完成用户选择后才能开始。'; @override - String get preparingSecureRoom => 'Preparing the secure room'; + String get preparingSecureRoom => '正在准备安全房间'; @override - String get searchingNearbyBluetoothGames => - 'Searching nearby games over Bluetooth'; + String get searchingNearbyBluetoothGames => '正在通过蓝牙搜索附近的游戏'; @override - String get tapToJoin => 'Tap to join'; + String get tapToJoin => '点击加入'; @override - String get bluetoothLocationPermissionsRequired => - 'Bluetooth and location permissions are required to search for games.'; + String get bluetoothLocationPermissionsRequired => '搜索游戏需要蓝牙和定位权限。'; @override - String get bluetoothLocationPermissionsShort => - 'Bluetooth and location permissions are required'; + String get bluetoothLocationPermissionsShort => '需要蓝牙和定位权限'; @override - String get couldNotStartSearch => - 'Could not start the search. Check Bluetooth and location.'; + String get couldNotStartSearch => '无法开始搜索。请检查蓝牙和定位。'; @override String couldNotConnectToHost(String host) { - return 'Could not connect to $host'; + return '无法连接到 $host'; } @override String get room => '房间'; @override - String get singleDeviceSubtitle => 'Game on this device'; + String get singleDeviceSubtitle => '在这台设备上游戏'; @override - String get singleDeviceDescription => - 'Ideal for playing together by passing the phone around. Fast, direct setup.'; + String get singleDeviceDescription => '适合大家传着手机一起玩。设置快速直接。'; @override - String get multiDeviceSubtitle => 'Each player on their phone'; + String get multiDeviceSubtitle => '每位玩家用自己的手机'; @override - String get multiDeviceDescription => - 'Create a premium room, share the QR code and manage users from the lobby.'; + String get multiDeviceDescription => '创建高级房间,分享二维码,并在大厅管理用户。'; @override - String get singleDeviceGameLabel => 'Game on this device'; + String get singleDeviceGameLabel => '本机游戏'; @override - String get multiDeviceGameLabel => 'Multi-device game'; + String get multiDeviceGameLabel => '多设备游戏'; @override - String get mainDeviceUser => 'Main device user'; + String get mainDeviceUser => '本机主用户'; @override - String get couldNotCreateRoom => - 'Could not create the room. Check Bluetooth.'; + String get couldNotCreateRoom => '无法创建房间。请检查蓝牙。'; @override String cannotStartWithReason(String reason) { - return 'Cannot start: $reason'; + return '无法开始:$reason'; } @override - String get invalidRoom => 'invalid room'; + String get invalidRoom => '无效的房间'; @override String get defaultPlayerName => '玩家'; @@ -829,6 +819,48 @@ class AppLocalizationsZh extends AppLocalizations { String playerRejoined(String name) { return '$name 已重新加入游戏'; } + + @override + String get leaveGameTitle => '要退出游戏吗?'; + + @override + String get leaveGameSingleDevice => '正在进行的游戏将会丢失,且无法恢复。'; + + @override + String get leaveGameHost => '你是房主:一旦退出,所有玩家的游戏都会结束。'; + + @override + String get leaveGameClient => '你将退出这局游戏。只要房主还开着,你随时可以回来。'; + + @override + String get stayInGame => '继续游戏'; + + @override + String get permissionsNeededTitle => '需要权限'; + + @override + String get permissionsNeededBody => '多人游戏模式需要以下权限:'; + + @override + String get openAppSettingsQuestion => '要打开应用设置吗?'; + + @override + String get openSettings => '打开设置'; + + @override + String get permissionLocation => '定位'; + + @override + String get permissionBluetoothAdvertise => '蓝牙(广播)'; + + @override + String get permissionBluetoothConnect => '蓝牙(连接)'; + + @override + String get permissionBluetoothScan => '蓝牙(扫描)'; + + @override + String get permissionNearbyWifi => '附近的 Wi-Fi'; } /// The translations for Chinese, as used in Taiwan (`zh_TW`). @@ -1470,84 +1502,74 @@ class AppLocalizationsZhTw extends AppLocalizationsZh { String get delete => '删除'; @override - String get selectAtLeastThreeUsersToStart => - 'Select at least 3 users to start.'; + String get selectAtLeastThreeUsersToStart => '至少選擇 3 名使用者才能開始。'; @override - String get hostPhoneMustSelectUser => - 'The host phone must select at least one user.'; + String get hostPhoneMustSelectUser => '房主的手機必須至少選擇一名使用者。'; @override - String get roomNoLongerInLobby => 'The room is no longer in the lobby.'; + String get roomNoLongerInLobby => '房間已不在等候大廳。'; @override - String get completeUserSelectionToStart => - 'Complete user selection to start.'; + String get completeUserSelectionToStart => '完成使用者選擇後才能開始。'; @override - String get preparingSecureRoom => 'Preparing the secure room'; + String get preparingSecureRoom => '正在準備安全房間'; @override - String get searchingNearbyBluetoothGames => - 'Searching nearby games over Bluetooth'; + String get searchingNearbyBluetoothGames => '正在透過藍牙搜尋附近的遊戲'; @override - String get tapToJoin => 'Tap to join'; + String get tapToJoin => '點擊加入'; @override - String get bluetoothLocationPermissionsRequired => - 'Bluetooth and location permissions are required to search for games.'; + String get bluetoothLocationPermissionsRequired => '搜尋遊戲需要藍牙和定位權限。'; @override - String get bluetoothLocationPermissionsShort => - 'Bluetooth and location permissions are required'; + String get bluetoothLocationPermissionsShort => '需要藍牙和定位權限'; @override - String get couldNotStartSearch => - 'Could not start the search. Check Bluetooth and location.'; + String get couldNotStartSearch => '無法開始搜尋。請檢查藍牙和定位。'; @override String couldNotConnectToHost(String host) { - return 'Could not connect to $host'; + return '無法連線到 $host'; } @override String get room => '房间'; @override - String get singleDeviceSubtitle => 'Game on this device'; + String get singleDeviceSubtitle => '在這台裝置上遊戲'; @override - String get singleDeviceDescription => - 'Ideal for playing together by passing the phone around. Fast, direct setup.'; + String get singleDeviceDescription => '適合大家傳著手機一起玩。設定快速直接。'; @override - String get multiDeviceSubtitle => 'Each player on their phone'; + String get multiDeviceSubtitle => '每位玩家用自己的手機'; @override - String get multiDeviceDescription => - 'Create a premium room, share the QR code and manage users from the lobby.'; + String get multiDeviceDescription => '建立高級房間,分享 QR Code,並在大廳管理使用者。'; @override - String get singleDeviceGameLabel => 'Game on this device'; + String get singleDeviceGameLabel => '本機遊戲'; @override - String get multiDeviceGameLabel => 'Multi-device game'; + String get multiDeviceGameLabel => '多裝置遊戲'; @override - String get mainDeviceUser => 'Main device user'; + String get mainDeviceUser => '本機主要使用者'; @override - String get couldNotCreateRoom => - 'Could not create the room. Check Bluetooth.'; + String get couldNotCreateRoom => '無法建立房間。請檢查藍牙。'; @override String cannotStartWithReason(String reason) { - return 'Cannot start: $reason'; + return '無法開始:$reason'; } @override - String get invalidRoom => 'invalid room'; + String get invalidRoom => '無效的房間'; @override String get defaultPlayerName => '玩家'; @@ -1656,4 +1678,46 @@ class AppLocalizationsZhTw extends AppLocalizationsZh { String playerRejoined(String name) { return '$name 已重新加入遊戲'; } + + @override + String get leaveGameTitle => '要退出遊戲嗎?'; + + @override + String get leaveGameSingleDevice => '正在進行的遊戲將會遺失,且無法復原。'; + + @override + String get leaveGameHost => '你是房主:一旦退出,所有玩家的遊戲都會結束。'; + + @override + String get leaveGameClient => '你將退出這局遊戲。只要房主還開著,你隨時可以回來。'; + + @override + String get stayInGame => '繼續遊戲'; + + @override + String get permissionsNeededTitle => '需要權限'; + + @override + String get permissionsNeededBody => '多人遊戲模式需要以下權限:'; + + @override + String get openAppSettingsQuestion => '要開啟應用程式設定嗎?'; + + @override + String get openSettings => '開啟設定'; + + @override + String get permissionLocation => '定位'; + + @override + String get permissionBluetoothAdvertise => '藍牙(廣播)'; + + @override + String get permissionBluetoothConnect => '藍牙(連線)'; + + @override + String get permissionBluetoothScan => '藍牙(掃描)'; + + @override + String get permissionNearbyWifi => '附近的 Wi-Fi'; } diff --git a/lib/pantallas/pantalla_adivinanza.dart b/lib/pantallas/pantalla_adivinanza.dart index 1ac992e..8c3052a 100644 --- a/lib/pantallas/pantalla_adivinanza.dart +++ b/lib/pantallas/pantalla_adivinanza.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import '../tema/dialogo_confirmacion.dart'; import 'package:farolero/l10n/generated/app_localizations.dart'; import 'package:provider/provider.dart'; import '../estado/estado_juego.dart'; @@ -53,31 +54,34 @@ class _PantallaAdivinanzaState extends State { final partida = estado.partida; if (partida == null) return const SizedBox.shrink(); - return Scaffold( - appBar: AppBar( - title: Text(l10n.impostorGuessTitle), - automaticallyImplyLeading: false, - ), - body: FondoFarolero( - intenso: true, - child: SafeArea( - child: Center( - child: SingleChildScrollView( - padding: const EdgeInsets.all(24), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const ArteGameplayFarolero.fase(height: 132), - const SizedBox(height: 12), - TarjetaFaseFarolero( - icono: Icons.theater_comedy, - assetIconPath: 'assets/ui/generated/actions/action_impostor_mask.webp', - titulo: l10n.impostorCanGuess, - subtitulo: l10n.ifCorrectImpostorsWin, - color: TemaApp.colorAcento, - child: _buildContenido(context, l10n, estado, partida.palabraSecreta), - ), - ], + return GuardiaSalidaPartida( + contexto: ContextoSalida.unDispositivo, + child: Scaffold( + appBar: AppBar( + title: Text(l10n.impostorGuessTitle), + automaticallyImplyLeading: false, + ), + body: FondoFarolero( + intenso: true, + child: SafeArea( + child: Center( + child: SingleChildScrollView( + padding: const EdgeInsets.all(24), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const ArteGameplayFarolero.fase(height: 132), + const SizedBox(height: 12), + TarjetaFaseFarolero( + icono: Icons.theater_comedy, + assetIconPath: 'assets/ui/generated/actions/action_impostor_mask.webp', + titulo: l10n.impostorCanGuess, + subtitulo: l10n.ifCorrectImpostorsWin, + color: TemaApp.colorAcento, + child: _buildContenido(context, l10n, estado, partida.palabraSecreta), + ), + ], + ), ), ), ), diff --git a/lib/pantallas/pantalla_debate.dart b/lib/pantallas/pantalla_debate.dart index 8aefa02..c2543ad 100644 --- a/lib/pantallas/pantalla_debate.dart +++ b/lib/pantallas/pantalla_debate.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import '../tema/dialogo_confirmacion.dart'; import 'package:flutter/material.dart'; import 'package:farolero/l10n/generated/app_localizations.dart'; import 'package:provider/provider.dart'; @@ -67,85 +68,88 @@ class _PantallaDebateState extends State { final tieneTemporizador = partida.config.tiempoDebateSegundos != null; - return Scaffold( - appBar: AppBar( - title: Text(l10n.debateRound(partida.rondaActual)), - automaticallyImplyLeading: false, - ), - body: FondoFarolero( - intenso: true, - child: SafeArea( - child: Padding( - padding: const EdgeInsets.all(16), - child: Column( - children: [ - const ArteGameplayFarolero.fase(height: 110), - const SizedBox(height: 10), - if (tieneTemporizador) ...[ - TemporizadorFarolero( - etiqueta: _tiempoAgotado ? l10n.timeUp : l10n.timeRemaining, - tiempo: _formatearTiempo(_segundosRestantes), - agotado: _tiempoAgotado, - ), - const SizedBox(height: 16), - ], - Expanded( - child: TarjetaFaseFarolero( - icono: Icons.forum, - assetIconPath: 'assets/ui/generated/actions/action_rules_book.webp', - titulo: l10n.playersInDebate, - subtitulo: l10n.activePlayersInfo( - partida.jugadoresActivos.length, - partida.impostoresActivos.length, + return GuardiaSalidaPartida( + contexto: ContextoSalida.unDispositivo, + child: Scaffold( + appBar: AppBar( + title: Text(l10n.debateRound(partida.rondaActual)), + automaticallyImplyLeading: false, + ), + body: FondoFarolero( + intenso: true, + child: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + children: [ + const ArteGameplayFarolero.fase(height: 110), + const SizedBox(height: 10), + if (tieneTemporizador) ...[ + TemporizadorFarolero( + etiqueta: _tiempoAgotado ? l10n.timeUp : l10n.timeRemaining, + tiempo: _formatearTiempo(_segundosRestantes), + agotado: _tiempoAgotado, ), - child: Expanded( - child: ListView.separated( - itemCount: partida.jugadores.length, - separatorBuilder: (context, index) => const SizedBox(height: 8), - itemBuilder: (context, index) { - final jugador = partida.jugadores[index]; - return EstadoJugadorFarolero( - nombre: '${index + 1}. ${jugador.nombre}', - subtitulo: jugador.eliminado ? l10n.eliminated : null, - icono: jugador.eliminado ? Icons.person_off : Icons.record_voice_over, - assetIconPath: jugador.eliminado ? null : 'assets/ui/generated/actions/action_players_group.webp', - destacado: !jugador.eliminado, - completado: !jugador.eliminado, - ); - }, + const SizedBox(height: 16), + ], + Expanded( + child: TarjetaFaseFarolero( + icono: Icons.forum, + assetIconPath: 'assets/ui/generated/actions/action_rules_book.webp', + titulo: l10n.playersInDebate, + subtitulo: l10n.activePlayersInfo( + partida.jugadoresActivos.length, + partida.impostoresActivos.length, ), - ), - ), - ), - const SizedBox(height: 16), - Row( - children: [ - Expanded( - child: BotonFarolero.oscuro( - texto: l10n.notes, - icono: Icons.edit_note, - assetIconPath: 'assets/ui/generated/actions/action_notes_quill.webp', - onPressed: () { - Navigator.push( - context, - MaterialPageRoute(builder: (_) => const PantallaNotas()), + child: Expanded( + child: ListView.separated( + itemCount: partida.jugadores.length, + separatorBuilder: (context, index) => const SizedBox(height: 8), + itemBuilder: (context, index) { + final jugador = partida.jugadores[index]; + return EstadoJugadorFarolero( + nombre: '${index + 1}. ${jugador.nombre}', + subtitulo: jugador.eliminado ? l10n.eliminated : null, + icono: jugador.eliminado ? Icons.person_off : Icons.record_voice_over, + assetIconPath: jugador.eliminado ? null : 'assets/ui/generated/actions/action_players_group.webp', + destacado: !jugador.eliminado, + completado: !jugador.eliminado, ); }, + ), ), ), - const SizedBox(width: 12), - Expanded( - flex: 2, - child: BotonFarolero( - texto: l10n.goToVoting, - icono: Icons.how_to_vote, - assetIconPath: 'assets/ui/generated/actions/action_vote_mask.webp', - onPressed: _irAVotacion, + ), + const SizedBox(height: 16), + Row( + children: [ + Expanded( + child: BotonFarolero.oscuro( + texto: l10n.notes, + icono: Icons.edit_note, + assetIconPath: 'assets/ui/generated/actions/action_notes_quill.webp', + onPressed: () { + Navigator.push( + context, + MaterialPageRoute(builder: (_) => const PantallaNotas()), + ); + }, + ), ), - ), - ], - ), - ], + const SizedBox(width: 12), + Expanded( + flex: 2, + child: BotonFarolero( + texto: l10n.goToVoting, + icono: Icons.how_to_vote, + assetIconPath: 'assets/ui/generated/actions/action_vote_mask.webp', + onPressed: _irAVotacion, + ), + ), + ], + ), + ], + ), ), ), ), diff --git a/lib/pantallas/pantalla_debate_cliente.dart b/lib/pantallas/pantalla_debate_cliente.dart index 8170f0c..6e80c2f 100644 --- a/lib/pantallas/pantalla_debate_cliente.dart +++ b/lib/pantallas/pantalla_debate_cliente.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import '../tema/dialogo_confirmacion.dart'; import 'package:flutter/material.dart'; import 'package:farolero/l10n/generated/app_localizations.dart'; import 'package:farolero/modelos/inicio_partida_multijugador.dart'; @@ -117,110 +118,113 @@ class _PantallaDebateClienteState extends State { Widget build(BuildContext context) { final l10n = AppLocalizations.of(context)!; - return Scaffold( - backgroundColor: TemaApp.colorFondo, - appBar: AppBar( - title: Text(l10n.debate), - automaticallyImplyLeading: false, - backgroundColor: Colors.transparent, - elevation: 0, - actions: [ - IconButton( - tooltip: l10n.seeYourWord, - icon: IconoFarolero(Icons.visibility), - onPressed: widget.jugadoresControlados.isEmpty - ? null - : () => mostrarRevisionPalabraOnline( - context: context, - jugadoresControlados: widget.jugadoresControlados, - pistaImpostor: widget.pistaImpostor, - ), - ), - IconButton( - tooltip: l10n.notesTitle, - icon: IconoFarolero(Icons.edit_note), - onPressed: _puedeAbrirNotas - ? () => Navigator.push( - context, - MaterialPageRoute( - builder: (_) => PantallaNotasOnline( - partidaId: widget.partidaId!, - jugadores: widget.jugadores, - autoresControlados: widget.jugadoresControlados, - ), + return GuardiaSalidaPartida( + contexto: ContextoSalida.cliente, + child: Scaffold( + backgroundColor: TemaApp.colorFondo, + appBar: AppBar( + title: Text(l10n.debate), + automaticallyImplyLeading: false, + backgroundColor: Colors.transparent, + elevation: 0, + actions: [ + IconButton( + tooltip: l10n.seeYourWord, + icon: IconoFarolero(Icons.visibility), + onPressed: widget.jugadoresControlados.isEmpty + ? null + : () => mostrarRevisionPalabraOnline( + context: context, + jugadoresControlados: widget.jugadoresControlados, + pistaImpostor: widget.pistaImpostor, ), - ) - : null, - ), - ], - ), - body: FondoFarolero( - intenso: true, - child: SafeArea( - top: false, - child: SingleChildScrollView( - padding: const EdgeInsets.all(24), - child: Column( - children: [ - const ArteGameplayFarolero.fase(height: 124), - const SizedBox(height: 12), - TarjetaFaseFarolero( - icono: Icons.forum, - assetIconPath: 'assets/ui/generated/actions/action_rules_book.webp', - titulo: l10n.debate, - subtitulo: l10n.debateInstructions, - child: Column( - children: [ - if (widget.tiempoDebateSegundos != null) ...[ - TemporizadorFarolero( - etiqueta: _segundosRestantes == 0 - ? l10n.timeUp - : l10n.timeRemaining, - tiempo: _formatearTiempo(_segundosRestantes), - agotado: _segundosRestantes == 0, - ), - const SizedBox(height: 16), - ] else ...[ - Text( - l10n.debatePhaseActive, - style: Theme.of(context).textTheme.titleLarge, - textAlign: TextAlign.center, - ), - const SizedBox(height: 16), - ], - if (widget.primerTurnoNombre != null) ...[ - EstadoJugadorFarolero( - nombre: l10n.firstTurnInstruction( - widget.primerTurnoNombre!, + ), + IconButton( + tooltip: l10n.notesTitle, + icon: IconoFarolero(Icons.edit_note), + onPressed: _puedeAbrirNotas + ? () => Navigator.push( + context, + MaterialPageRoute( + builder: (_) => PantallaNotasOnline( + partidaId: widget.partidaId!, + jugadores: widget.jugadores, + autoresControlados: widget.jugadoresControlados, ), - destacado: true, - completado: true, - icono: Icons.record_voice_over, - assetIconPath: 'assets/ui/generated/actions/action_players_group.webp', ), - const SizedBox(height: 12), + ) + : null, + ), + ], + ), + body: FondoFarolero( + intenso: true, + child: SafeArea( + top: false, + child: SingleChildScrollView( + padding: const EdgeInsets.all(24), + child: Column( + children: [ + const ArteGameplayFarolero.fase(height: 124), + const SizedBox(height: 12), + TarjetaFaseFarolero( + icono: Icons.forum, + assetIconPath: 'assets/ui/generated/actions/action_rules_book.webp', + titulo: l10n.debate, + subtitulo: l10n.debateInstructions, + child: Column( + children: [ + if (widget.tiempoDebateSegundos != null) ...[ + TemporizadorFarolero( + etiqueta: _segundosRestantes == 0 + ? l10n.timeUp + : l10n.timeRemaining, + tiempo: _formatearTiempo(_segundosRestantes), + agotado: _segundosRestantes == 0, + ), + const SizedBox(height: 16), + ] else ...[ + Text( + l10n.debatePhaseActive, + style: Theme.of(context).textTheme.titleLarge, + textAlign: TextAlign.center, + ), + const SizedBox(height: 16), + ], + if (widget.primerTurnoNombre != null) ...[ + EstadoJugadorFarolero( + nombre: l10n.firstTurnInstruction( + widget.primerTurnoNombre!, + ), + destacado: true, + completado: true, + icono: Icons.record_voice_over, + assetIconPath: 'assets/ui/generated/actions/action_players_group.webp', + ), + const SizedBox(height: 12), + ], + BotonFarolero.secundario( + texto: _votacionSolicitada + ? l10n.votacionSolicitada + : l10n.solicitarVotacion, + icono: _votacionSolicitada + ? Icons.hourglass_empty + : Icons.how_to_vote, + assetIconPath: _votacionSolicitada + ? null + : 'assets/ui/generated/actions/action_vote_mask.webp', + onPressed: _votacionSolicitada + ? null + : () { + setState(() => _votacionSolicitada = true); + widget.onSolicitarVotacion(); + }, + ), ], - BotonFarolero.secundario( - texto: _votacionSolicitada - ? l10n.votacionSolicitada - : l10n.solicitarVotacion, - icono: _votacionSolicitada - ? Icons.hourglass_empty - : Icons.how_to_vote, - assetIconPath: _votacionSolicitada - ? null - : 'assets/ui/generated/actions/action_vote_mask.webp', - onPressed: _votacionSolicitada - ? null - : () { - setState(() => _votacionSolicitada = true); - widget.onSolicitarVotacion(); - }, - ), - ], + ), ), - ), - ], + ], + ), ), ), ), diff --git a/lib/pantallas/pantalla_gestor_host.dart b/lib/pantallas/pantalla_gestor_host.dart index 95da5e9..027e93c 100644 --- a/lib/pantallas/pantalla_gestor_host.dart +++ b/lib/pantallas/pantalla_gestor_host.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import '../tema/dialogo_confirmacion.dart'; import 'dart:math'; import 'package:flutter/material.dart'; import 'package:farolero/l10n/generated/app_localizations.dart'; @@ -257,7 +258,9 @@ class _PantallaGestorHostState extends State { clientesPendientes.every((id) => _clientesListos[id] == true); final todosVotaron = estado.todosHanVotado(); - return Scaffold( + return GuardiaSalidaPartida( + contexto: ContextoSalida.host, + child: Scaffold( appBar: AppBar( title: Text(l10n.hostGame), automaticallyImplyLeading: false, @@ -299,8 +302,15 @@ class _PantallaGestorHostState extends State { ), ), IconButton( + tooltip: l10n.leaveGame, icon: IconoFarolero(Icons.close), onPressed: () async { + if (!await confirmarSalirDePartida( + context, + ContextoSalida.host, + )) { + return; + } await nearby.desconectar(); widget.onPartidaFin(); }, @@ -340,6 +350,7 @@ class _PantallaGestorHostState extends State { ), ), ), + ), ); } @@ -580,6 +591,7 @@ class _PantallaGestorHostState extends State { context, MaterialPageRoute( builder: (_) => PantallaPalabrasCliente( + protegerSalida: false, jugadores: jugadoresHost, pistaImpostor: partida.config.pistaImpostor ? partida.pistaImpostor @@ -863,6 +875,7 @@ class _PantallaGestorHostState extends State { context, MaterialPageRoute( builder: (_) => PantallaVotacionCliente( + protegerSalida: false, jugadores: partida.jugadoresActivos, jugadoresControlados: jugadoresHost, partidaId: context.read().roomId, diff --git a/lib/pantallas/pantalla_lobby_host.dart b/lib/pantallas/pantalla_lobby_host.dart index c2d2583..2e87428 100644 --- a/lib/pantallas/pantalla_lobby_host.dart +++ b/lib/pantallas/pantalla_lobby_host.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import '../tema/dialogo_confirmacion.dart'; import 'package:provider/provider.dart'; import 'package:qr_flutter/qr_flutter.dart'; import 'package:farolero/l10n/generated/app_localizations.dart'; @@ -42,6 +43,12 @@ class _PantallaLobbyHostState extends State { leading: IconButton( icon: IconoFarolero(Icons.close), onPressed: () async { + if (!await confirmarSalirDePartida( + context, + ContextoSalida.host, + )) { + return; + } await nearby.desconectar(); if (context.mounted) Navigator.pop(context); }, diff --git a/lib/pantallas/pantalla_palabras_cliente.dart b/lib/pantallas/pantalla_palabras_cliente.dart index 77ea9e2..ca5416b 100644 --- a/lib/pantallas/pantalla_palabras_cliente.dart +++ b/lib/pantallas/pantalla_palabras_cliente.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:farolero/tema/dialogo_confirmacion.dart'; import 'package:farolero/l10n/generated/app_localizations.dart'; import 'package:farolero/modelos/inicio_partida_multijugador.dart'; import 'package:farolero/tema/componentes_farolero.dart'; @@ -10,11 +11,16 @@ class PantallaPalabrasCliente extends StatefulWidget { final String? pistaImpostor; final VoidCallback onTodosVistos; + /// El host abre esta pantalla desde el gestor: allí el atrás solo + /// debe cerrarla, no ofrecer abandonar la partida. + final bool protegerSalida; + const PantallaPalabrasCliente({ super.key, required this.jugadores, this.pistaImpostor, required this.onTodosVistos, + this.protegerSalida = true, }); @override @@ -47,7 +53,10 @@ class _PantallaPalabrasClienteState extends State { final l10n = AppLocalizations.of(context)!; final actual = _actual; - return Scaffold( + return GuardiaSalidaPartida( + contexto: ContextoSalida.cliente, + activo: widget.protegerSalida, + child: Scaffold( body: FondoFarolero( intenso: true, child: SafeArea( @@ -147,6 +156,7 @@ class _PantallaPalabrasClienteState extends State { ), ), ), + ), ); } } diff --git a/lib/pantallas/pantalla_resultado.dart b/lib/pantallas/pantalla_resultado.dart index eb63f9a..2878e40 100644 --- a/lib/pantallas/pantalla_resultado.dart +++ b/lib/pantallas/pantalla_resultado.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import '../tema/dialogo_confirmacion.dart'; import 'package:farolero/l10n/generated/app_localizations.dart'; import 'package:provider/provider.dart'; import '../estado/estado_juego.dart'; @@ -59,43 +60,46 @@ class _PantallaResultadoState extends State final estado = context.read(); final partida = estado.partida; - return Scaffold( - appBar: AppBar( - title: Text(l10n.result), - automaticallyImplyLeading: false, - ), - body: FondoFarolero( - intenso: true, - respetarBarras: true, - child: Center( - child: SingleChildScrollView( - padding: const EdgeInsets.all(32), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - // Animación de suspense - if (!_revelado) ...[ - const ArteGameplayFarolero.resultado(height: 152), - const SizedBox(height: 16), - Text( - l10n.revealing, - style: Theme.of(context).textTheme.headlineMedium, - ), - const SizedBox(height: 24), - const CircularProgressIndicator(color: TemaApp.colorAcento), - ], - - if (_revelado) ...[ - FadeTransition( - opacity: _animOpacidad, - child: ResultadoRondaFarolero( - resultado: widget.resultado, - jugadores: partida?.jugadores ?? const [], - acciones: _construirBotones(context, estado), + return GuardiaSalidaPartida( + contexto: ContextoSalida.unDispositivo, + child: Scaffold( + appBar: AppBar( + title: Text(l10n.result), + automaticallyImplyLeading: false, + ), + body: FondoFarolero( + intenso: true, + respetarBarras: true, + child: Center( + child: SingleChildScrollView( + padding: const EdgeInsets.all(32), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + // Animación de suspense + if (!_revelado) ...[ + const ArteGameplayFarolero.resultado(height: 152), + const SizedBox(height: 16), + Text( + l10n.revealing, + style: Theme.of(context).textTheme.headlineMedium, ), - ), + const SizedBox(height: 24), + const CircularProgressIndicator(color: TemaApp.colorAcento), + ], + + if (_revelado) ...[ + FadeTransition( + opacity: _animOpacidad, + child: ResultadoRondaFarolero( + resultado: widget.resultado, + jugadores: partida?.jugadores ?? const [], + acciones: _construirBotones(context, estado), + ), + ), + ], ], - ], + ), ), ), ), diff --git a/lib/pantallas/pantalla_resultado_online.dart b/lib/pantallas/pantalla_resultado_online.dart index bc0da1b..4a3cd4e 100644 --- a/lib/pantallas/pantalla_resultado_online.dart +++ b/lib/pantallas/pantalla_resultado_online.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import '../tema/dialogo_confirmacion.dart'; import 'package:farolero/l10n/generated/app_localizations.dart'; import '../modelos/inicio_partida_multijugador.dart'; import '../modelos/snapshot_partida_online.dart'; @@ -158,30 +159,33 @@ class _PantallaResultadoOnlineState extends State { final l10n = AppLocalizations.of(context)!; final resultado = _snapshot.resultadoActual; - return Scaffold( - backgroundColor: TemaApp.colorFondo, - appBar: AppBar( - title: Text(_snapshot.fase == 'adivinanza' - ? l10n.impostorGuessTitle - : l10n.result), - automaticallyImplyLeading: false, - backgroundColor: Colors.transparent, - elevation: 0, - actions: _acciones(context, l10n), - ), - body: FondoFarolero( - intenso: true, - child: SafeArea( - top: false, - child: SingleChildScrollView( - padding: const EdgeInsets.all(24), - child: resultado == null - ? _buildEsperaAdivinanza(context, l10n) - : ResultadoRondaFarolero( - resultado: resultado, - jugadores: _snapshot.jugadores, - mensaje: _snapshot.mensaje, - ), + return GuardiaSalidaPartida( + contexto: ContextoSalida.cliente, + child: Scaffold( + backgroundColor: TemaApp.colorFondo, + appBar: AppBar( + title: Text(_snapshot.fase == 'adivinanza' + ? l10n.impostorGuessTitle + : l10n.result), + automaticallyImplyLeading: false, + backgroundColor: Colors.transparent, + elevation: 0, + actions: _acciones(context, l10n), + ), + body: FondoFarolero( + intenso: true, + child: SafeArea( + top: false, + child: SingleChildScrollView( + padding: const EdgeInsets.all(24), + child: resultado == null + ? _buildEsperaAdivinanza(context, l10n) + : ResultadoRondaFarolero( + resultado: resultado, + jugadores: _snapshot.jugadores, + mensaje: _snapshot.mensaje, + ), + ), ), ), ), diff --git a/lib/pantallas/pantalla_ver_palabra.dart b/lib/pantallas/pantalla_ver_palabra.dart index 5a4f7e3..c2d0d4b 100644 --- a/lib/pantallas/pantalla_ver_palabra.dart +++ b/lib/pantallas/pantalla_ver_palabra.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import '../tema/dialogo_confirmacion.dart'; import 'package:farolero/l10n/generated/app_localizations.dart'; import 'package:provider/provider.dart'; import '../estado/estado_juego.dart'; @@ -25,64 +26,67 @@ class _PantallaVerPalabraState extends State { final todosHanVisto = partida.jugadores.every((j) => _hanVisto.contains(j.id)); - return Scaffold( - appBar: AppBar( - title: Text(l10n.seeYourWord), - automaticallyImplyLeading: false, - ), - body: FondoFarolero( - intenso: true, - child: SafeArea( - child: Padding( - padding: const EdgeInsets.all(16), - child: Column( - children: [ - const ArteGameplayFarolero.fase(height: 110), - const SizedBox(height: 10), - TarjetaFaseFarolero( - icono: Icons.visibility, - assetIconPath: 'assets/ui/generated/actions/action_reveal_word.webp', - titulo: l10n.roundNumber(partida.rondaActual), - subtitulo: l10n.eachPlayerMustSee, - ), - const SizedBox(height: 16), - Expanded( - child: ListView.separated( - itemCount: partida.jugadores.length, - separatorBuilder: (context, index) => const SizedBox(height: 10), - itemBuilder: (context, index) { - final jugador = partida.jugadores[index]; - final haVisto = _hanVisto.contains(jugador.id); - return EstadoJugadorFarolero( - nombre: '${index + 1}. ${jugador.nombre}', - subtitulo: haVisto ? l10n.alreadySeen : l10n.tapToSee, - icono: haVisto ? Icons.check_circle : Icons.visibility, - assetIconPath: haVisto ? null : 'assets/ui/generated/actions/action_reveal_word.webp', - destacado: haVisto, - completado: haVisto, - onTap: haVisto ? null : () => _mostrarPalabra(context, jugador.id), - ); - }, + return GuardiaSalidaPartida( + contexto: ContextoSalida.unDispositivo, + child: Scaffold( + appBar: AppBar( + title: Text(l10n.seeYourWord), + automaticallyImplyLeading: false, + ), + body: FondoFarolero( + intenso: true, + child: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + children: [ + const ArteGameplayFarolero.fase(height: 110), + const SizedBox(height: 10), + TarjetaFaseFarolero( + icono: Icons.visibility, + assetIconPath: 'assets/ui/generated/actions/action_reveal_word.webp', + titulo: l10n.roundNumber(partida.rondaActual), + subtitulo: l10n.eachPlayerMustSee, ), - ), - const SizedBox(height: 16), - BotonFarolero( - texto: todosHanVisto - ? l10n.allSeenStartDebate - : l10n.playersRemaining(partida.jugadores.length - _hanVisto.length), - icono: Icons.forum, - assetIconPath: 'assets/ui/generated/actions/action_rules_book.webp', - onPressed: todosHanVisto - ? () { - estado.iniciarDebate(); - Navigator.pushReplacement( - context, - MaterialPageRoute(builder: (_) => const PantallaDebate()), - ); - } - : null, - ), - ], + const SizedBox(height: 16), + Expanded( + child: ListView.separated( + itemCount: partida.jugadores.length, + separatorBuilder: (context, index) => const SizedBox(height: 10), + itemBuilder: (context, index) { + final jugador = partida.jugadores[index]; + final haVisto = _hanVisto.contains(jugador.id); + return EstadoJugadorFarolero( + nombre: '${index + 1}. ${jugador.nombre}', + subtitulo: haVisto ? l10n.alreadySeen : l10n.tapToSee, + icono: haVisto ? Icons.check_circle : Icons.visibility, + assetIconPath: haVisto ? null : 'assets/ui/generated/actions/action_reveal_word.webp', + destacado: haVisto, + completado: haVisto, + onTap: haVisto ? null : () => _mostrarPalabra(context, jugador.id), + ); + }, + ), + ), + const SizedBox(height: 16), + BotonFarolero( + texto: todosHanVisto + ? l10n.allSeenStartDebate + : l10n.playersRemaining(partida.jugadores.length - _hanVisto.length), + icono: Icons.forum, + assetIconPath: 'assets/ui/generated/actions/action_rules_book.webp', + onPressed: todosHanVisto + ? () { + estado.iniciarDebate(); + Navigator.pushReplacement( + context, + MaterialPageRoute(builder: (_) => const PantallaDebate()), + ); + } + : null, + ), + ], + ), ), ), ), diff --git a/lib/pantallas/pantalla_votacion.dart b/lib/pantallas/pantalla_votacion.dart index 287c4f5..50c7a81 100644 --- a/lib/pantallas/pantalla_votacion.dart +++ b/lib/pantallas/pantalla_votacion.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import '../tema/dialogo_confirmacion.dart'; import 'package:farolero/l10n/generated/app_localizations.dart'; import 'package:provider/provider.dart'; import '../estado/estado_juego.dart'; @@ -25,7 +26,12 @@ class _PantallaVotacionState extends State { final activos = partida.jugadoresActivos; final todosVotaron = estado.todosHanVotado(); - return _construirVotacionUnMovil(context, estado, partida, activos, todosVotaron); + return GuardiaSalidaPartida( + contexto: ContextoSalida.unDispositivo, + child: _construirVotacionUnMovil( + context, estado, partida, activos, todosVotaron, + ), + ); } Widget _construirVotacionUnMovil( diff --git a/lib/pantallas/pantalla_votacion_cliente.dart b/lib/pantallas/pantalla_votacion_cliente.dart index 7634b32..f536816 100644 --- a/lib/pantallas/pantalla_votacion_cliente.dart +++ b/lib/pantallas/pantalla_votacion_cliente.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:farolero/tema/dialogo_confirmacion.dart'; import 'package:farolero/l10n/generated/app_localizations.dart'; import 'package:farolero/modelos/inicio_partida_multijugador.dart'; import 'package:farolero/modelos/jugador.dart'; @@ -17,6 +18,10 @@ class PantallaVotacionCliente extends StatefulWidget { final String? pistaImpostor; final Function(Map votos) onVotos; + /// El host abre esta pantalla desde el gestor: allí el atrás solo + /// debe cerrarla, no ofrecer abandonar la partida. + final bool protegerSalida; + const PantallaVotacionCliente({ super.key, required this.jugadores, @@ -24,6 +29,7 @@ class PantallaVotacionCliente extends StatefulWidget { this.partidaId, this.pistaImpostor, required this.onVotos, + this.protegerSalida = true, }); @override @@ -63,7 +69,10 @@ class _PantallaVotacionClienteState extends State { Widget build(BuildContext context) { final l10n = AppLocalizations.of(context)!; - return Scaffold( + return GuardiaSalidaPartida( + contexto: ContextoSalida.cliente, + activo: widget.protegerSalida, + child: Scaffold( backgroundColor: TemaApp.colorFondo, appBar: AppBar( title: Text(l10n.voting), @@ -155,6 +164,7 @@ class _PantallaVotacionClienteState extends State { ), ), ), + ), ); } diff --git a/lib/servicios/servicio_permisos.dart b/lib/servicios/servicio_permisos.dart index 7457581..426c0bc 100644 --- a/lib/servicios/servicio_permisos.dart +++ b/lib/servicios/servicio_permisos.dart @@ -1,4 +1,5 @@ import 'dart:io'; +import 'package:farolero/l10n/generated/app_localizations.dart'; import 'package:flutter/material.dart'; import 'package:permission_handler/permission_handler.dart'; @@ -24,11 +25,14 @@ class ServicioPermisos { // Solicitar todos final resultados = await permisos.request(); + if (!context.mounted) return false; + final l10n = AppLocalizations.of(context)!; + // Verificar cuáles fueron denegados final denegados = []; for (final entry in resultados.entries) { if (!entry.value.isGranted) { - denegados.add(_nombrePermiso(entry.key)); + denegados.add(_nombrePermiso(entry.key, l10n)); } } @@ -39,20 +43,20 @@ class ServicioPermisos { final abrirConfig = await showDialog( context: context, builder: (ctx) => AlertDialog( - title: const Text('Permisos necesarios'), + title: Text(l10n.permissionsNeededTitle), content: Text( - 'Para el modo multijugador necesitamos:\n\n' + '${l10n.permissionsNeededBody}\n\n' '${denegados.map((d) => '• $d').join('\n')}\n\n' - '¿Abrir configuración de la app?', + '${l10n.openAppSettingsQuestion}', ), actions: [ TextButton( onPressed: () => Navigator.pop(ctx, false), - child: const Text('Cancelar'), + child: Text(l10n.cancel), ), TextButton( onPressed: () => Navigator.pop(ctx, true), - child: const Text('Abrir configuración'), + child: Text(l10n.openSettings), ), ], ), @@ -66,12 +70,16 @@ class ServicioPermisos { return false; } - static String _nombrePermiso(Permission p) { - if (p == Permission.locationWhenInUse) return 'Ubicación'; - if (p == Permission.bluetoothAdvertise) return 'Bluetooth (anunciar)'; - if (p == Permission.bluetoothConnect) return 'Bluetooth (conectar)'; - if (p == Permission.bluetoothScan) return 'Bluetooth (escanear)'; - if (p == Permission.nearbyWifiDevices) return 'Wi-Fi cercano'; + static String _nombrePermiso(Permission p, AppLocalizations l10n) { + if (p == Permission.locationWhenInUse) return l10n.permissionLocation; + if (p == Permission.bluetoothAdvertise) { + return l10n.permissionBluetoothAdvertise; + } + if (p == Permission.bluetoothConnect) { + return l10n.permissionBluetoothConnect; + } + if (p == Permission.bluetoothScan) return l10n.permissionBluetoothScan; + if (p == Permission.nearbyWifiDevices) return l10n.permissionNearbyWifi; return p.toString(); } } diff --git a/lib/tema/dialogo_confirmacion.dart b/lib/tema/dialogo_confirmacion.dart new file mode 100644 index 0000000..405bca0 --- /dev/null +++ b/lib/tema/dialogo_confirmacion.dart @@ -0,0 +1,170 @@ +import 'package:flutter/material.dart'; + +import '../l10n/generated/app_localizations.dart'; +import 'componentes_farolero.dart'; +import 'tema_app.dart'; + +/// Quién está saliendo, que determina qué se pierde y por tanto qué se avisa. +enum ContextoSalida { + /// Un solo móvil: la partida vive en este dispositivo y se pierde entera. + unDispositivo, + + /// El host de una partida multidispositivo: al salir la corta para todos. + host, + + /// Un cliente: solo se va él y puede volver mientras la sala siga abierta. + cliente, +} + +/// Diálogo de confirmación con el estilo de la app. +/// +/// Devuelve `true` solo si el jugador confirma. Cerrarlo tocando fuera o con +/// el gesto de atrás cuenta como cancelar, que es lo que interesa cuando lo +/// que se está evitando es precisamente una salida accidental. +Future confirmarFarolero({ + required BuildContext context, + required String titulo, + required String mensaje, + required String textoConfirmar, + required String textoCancelar, + IconData icono = Icons.warning_amber_rounded, + IconData iconoConfirmar = Icons.logout, + IconData iconoCancelar = Icons.play_arrow, +}) async { + final confirmado = await showDialog( + context: context, + barrierDismissible: true, + builder: (dialogContext) => Dialog( + backgroundColor: TemaApp.colorSuperficie, + insetPadding: const EdgeInsets.symmetric(horizontal: 28, vertical: 24), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(24), + side: BorderSide( + color: TemaApp.colorNaranja.withValues(alpha: 0.45), + ), + ), + child: Padding( + padding: const EdgeInsets.fromLTRB(24, 28, 24, 24), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + width: 72, + height: 72, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: TemaApp.colorAcento.withValues(alpha: 0.16), + border: Border.all( + color: TemaApp.colorAcento.withValues(alpha: 0.65), + width: 2, + ), + ), + child: IconoFarolero( + icono, + color: TemaApp.colorNaranja, + size: 38, + ), + ), + const SizedBox(height: 18), + Text( + titulo, + textAlign: TextAlign.center, + style: Theme.of(dialogContext).textTheme.titleLarge?.copyWith( + color: TemaApp.colorDorado, + ), + ), + const SizedBox(height: 10), + Text( + mensaje, + textAlign: TextAlign.center, + style: Theme.of(dialogContext).textTheme.bodyMedium?.copyWith( + color: TemaApp.colorTextoSecundario, + height: 1.35, + ), + ), + const SizedBox(height: 26), + // La acción segura va primero y destacada: si alguien llega aquí + // sin querer, lo cómodo tiene que ser quedarse. + BotonFarolero( + texto: textoCancelar, + icono: iconoCancelar, + onPressed: () => Navigator.of(dialogContext).pop(false), + ), + const SizedBox(height: 12), + BotonFarolero.oscuro( + texto: textoConfirmar, + icono: iconoConfirmar, + onPressed: () => Navigator.of(dialogContext).pop(true), + ), + ], + ), + ), + ), + ); + return confirmado ?? false; +} + +/// Pregunta antes de abandonar una partida en curso. +Future confirmarSalirDePartida( + BuildContext context, + ContextoSalida contexto, +) { + final l10n = AppLocalizations.of(context)!; + return confirmarFarolero( + context: context, + titulo: l10n.leaveGameTitle, + mensaje: switch (contexto) { + ContextoSalida.unDispositivo => l10n.leaveGameSingleDevice, + ContextoSalida.host => l10n.leaveGameHost, + ContextoSalida.cliente => l10n.leaveGameClient, + }, + textoConfirmar: l10n.leaveGame, + textoCancelar: l10n.stayInGame, + ); +} + +/// Envuelve una pantalla de partida para que el gesto o botón de atrás no la +/// abandone sin preguntar. +/// +/// Se encarga solo del atrás del sistema; los botones de cerrar de cada +/// pantalla llaman a [confirmarSalirDePartida] por su cuenta, porque además de +/// confirmar tienen que desconectar y navegar. +class GuardiaSalidaPartida extends StatelessWidget { + final Widget child; + final ContextoSalida contexto; + + /// Qué hacer cuando el jugador confirma que quiere salir. Si es null se deja + /// que la ruta se cierre con normalidad. + final VoidCallback? onSalirConfirmado; + + /// Permite desactivar la guarda sin sacar el widget del árbol, por ejemplo + /// cuando la partida ya ha terminado. + final bool activo; + + const GuardiaSalidaPartida({ + super.key, + required this.child, + required this.contexto, + this.onSalirConfirmado, + this.activo = true, + }); + + @override + Widget build(BuildContext context) { + return PopScope( + canPop: !activo, + onPopInvokedWithResult: (didPop, result) async { + if (didPop) return; + final salir = await confirmarSalirDePartida(context, contexto); + if (!salir || !context.mounted) return; + final alSalir = onSalirConfirmado; + if (alSalir != null) { + alSalir(); + } else if (Navigator.of(context).canPop()) { + Navigator.of(context).pop(); + } + }, + child: child, + ); + } +} diff --git a/test/l10n_cobertura_test.dart b/test/l10n_cobertura_test.dart new file mode 100644 index 0000000..8f9bc99 --- /dev/null +++ b/test/l10n_cobertura_test.dart @@ -0,0 +1,110 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:flutter_test/flutter_test.dart'; + +/// Guardas sobre los ficheros de traducción. +/// +/// El fallo que motivó estos tests: 21 claves se quedaron con el texto inglés +/// dentro de árabe, japonés, coreano, chino, ruso, turco, hindi, neerlandés, +/// polaco y euskera. Nada fallaba: la app mostraba inglés y ya está. +void main() { + const idiomaPlantilla = 'es'; + + /// Coincidencias reales entre idiomas: palabras que se escriben igual y por + /// tanto no son un descuido. Cada entrada es "idioma:clave". + const coincidenciasLegitimas = { + // Nombre de la app y rangos numéricos, iguales en todas partes. + 'de:appTitle', 'en:appTitle', 'fr:appTitle', 'it:appTitle', + // "Animals", "Professions", "Impostors", "Notes" son catalán correcto. + 'ca:categoryAnimals', 'ca:categoryProfessions', 'ca:impostors', + 'ca:notes', 'ca:notesTitle', + // "Vibration", "Version", "Name" son alemán correcto. + 'de:vibration', 'de:version', 'de:profileName', + // "Sports", "Configuration", "Notes", "Vibration", "Version" son francés. + 'fr:categorySports', 'fr:configuration', 'fr:notes', 'fr:notesTitle', + 'fr:vibration', 'fr:version', + // "Round" se usa tal cual en italiano. + 'it:roundNumber', 'it:roundElimination', + }; + + Map cargar(String idioma) { + final fichero = File('lib/l10n/app_$idioma.arb'); + final datos = json.decode(fichero.readAsStringSync()) as Map; + return { + for (final e in datos.entries) + if (!e.key.startsWith('@') && e.value is String) + e.key: e.value as String, + }; + } + + final idiomas = Directory('lib/l10n') + .listSync() + .whereType() + .where((f) => f.path.endsWith('.arb')) + .map((f) => f.uri.pathSegments.last.replaceAll(RegExp(r'^app_|\.arb$'), '')) + .toList() + ..sort(); + + final plantilla = cargar(idiomaPlantilla); + final ingles = cargar('en'); + + test('están los 18 idiomas soportados', () { + expect(idiomas.length, 18); + }); + + for (final idioma in idiomas) { + group('app_$idioma.arb', () { + final valores = cargar(idioma); + + test('no le falta ninguna clave de la plantilla', () { + final faltan = plantilla.keys.where((k) => !valores.containsKey(k)); + expect(faltan, isEmpty, reason: 'sin traducir: ${faltan.join(", ")}'); + }); + + test('no tiene claves que la plantilla no conozca', () { + final sobran = valores.keys.where((k) => !plantilla.containsKey(k)); + expect(sobran, isEmpty, reason: 'huérfanas: ${sobran.join(", ")}'); + }); + + test('ningún valor está vacío', () { + final vacios = valores.entries + .where((e) => e.value.trim().isEmpty) + .map((e) => e.key); + expect(vacios, isEmpty); + }); + + if (idioma != 'en' && idioma != idiomaPlantilla) { + test('no se ha quedado el texto en inglés', () { + final enIngles = valores.entries + .where((e) => + ingles[e.key] == e.value && + plantilla[e.key] != e.value && + !coincidenciasLegitimas.contains('$idioma:${e.key}')) + .map((e) => '${e.key} = "${e.value}"') + .toList(); + expect(enIngles, isEmpty, reason: enIngles.join('\n')); + }); + } + + test('conserva los marcadores de posición de la plantilla', () { + final patron = RegExp(r'\{(\w+)\}'); + final fallos = []; + for (final entrada in valores.entries) { + final esperados = patron + .allMatches(plantilla[entrada.key] ?? '') + .map((m) => m.group(1)!) + .toSet(); + final presentes = + patron.allMatches(entrada.value).map((m) => m.group(1)!).toSet(); + // Los plurales ICU declaran el contador fuera de las llaves simples. + if (entrada.value.contains(', plural,')) continue; + if (!presentes.containsAll(esperados)) { + fallos.add('${entrada.key}: faltan ${esperados.difference(presentes)}'); + } + } + expect(fallos, isEmpty, reason: fallos.join('\n')); + }); + }); + } +}