From ce3a3d3c055ff21a41adfb6e5cdada1713242250 Mon Sep 17 00:00:00 2001 From: skymike03 Date: Mon, 11 Aug 2025 19:16:36 +0200 Subject: [PATCH] v1.9.8.6 - default language automatic on batocera on first start , and add some missing translations on loading menu and controls mapping --- ports/RGSX/__main__.py | 24 +++++++------ ports/RGSX/config.py | 2 +- ports/RGSX/controls_mapper.py | 3 +- ports/RGSX/language.py | 67 ++++++++++++++++++++++++++++++----- ports/RGSX/languages/de.json | 9 ++++- ports/RGSX/languages/en.json | 10 +++--- ports/RGSX/languages/es.json | 11 +++++- ports/RGSX/languages/fr.json | 34 +++++++++++------- 8 files changed, 117 insertions(+), 43 deletions(-) diff --git a/ports/RGSX/__main__.py b/ports/RGSX/__main__.py index ceb9475..90b6792 100644 --- a/ports/RGSX/__main__.py +++ b/ports/RGSX/__main__.py @@ -668,7 +668,7 @@ async def main(): elif config.menu_state == "loading": if loading_step == "none": loading_step = "test_internet" - config.current_loading_system = "Test de connexion..." + config.current_loading_system = _("loading_test_internet") config.loading_progress = 0.0 config.needs_redraw = True logger.debug(f"Étape chargement : {loading_step}, progress={config.loading_progress}") @@ -676,13 +676,13 @@ async def main(): #logger.debug("Exécution de test_internet()") if test_internet(): loading_step = "check_ota" - config.current_loading_system = "Verification Mise à jour en cours... Patientez..." + config.current_loading_system = _("loading_check_updates") config.loading_progress = 20.0 config.needs_redraw = True logger.debug(f"Étape chargement : {loading_step}, progress={config.loading_progress}") else: config.menu_state = "error" - config.error_message = "Pas de connexion Internet. Vérifiez votre réseau." + config.error_message = _("error_no_internet") config.needs_redraw = True logger.debug(f"Erreur : {config.error_message}") elif loading_step == "check_ota": @@ -691,12 +691,13 @@ async def main(): logger.debug(f"Résultat de check_for_updates : success={success}, message={message}") if not success: config.menu_state = "error" - config.error_message = message + # Garder message (déjà fourni par check_for_updates), sinon fallback + config.error_message = message or _("error_check_updates_failed") config.needs_redraw = True logger.debug(f"Erreur OTA : {message}") else: loading_step = "check_data" - config.current_loading_system = "Téléchargement des jeux et images ..." + config.current_loading_system = _("loading_downloading_games_images") config.loading_progress = 50.0 config.needs_redraw = True logger.debug(f"Étape chargement : {loading_step}, progress={config.loading_progress}") @@ -704,7 +705,7 @@ async def main(): games_data_dir = os.path.join(config.APP_FOLDER, "games") is_data_empty = not os.path.exists(games_data_dir) or not any(os.scandir(games_data_dir)) if is_data_empty: - config.current_loading_system = "Téléchargement du Dossier Data initial..." + config.current_loading_system = _("loading_download_data") config.loading_progress = 30.0 config.needs_redraw = True logger.debug("Dossier Data vide, début du téléchargement du ZIP") @@ -733,7 +734,7 @@ async def main(): await asyncio.sleep(0) logger.debug(f"ZIP téléchargé : {zip_path}") - config.current_loading_system = "Extraction du Dossier Data initial..." + config.current_loading_system = _("loading_extracting_data") config.loading_progress = 60.0 config.needs_redraw = True dest_dir = config.APP_FOLDER @@ -747,7 +748,8 @@ async def main(): except Exception as e: logger.error(f"Erreur lors du téléchargement/extraction du Dossier Data : {str(e)}") config.menu_state = "error" - config.error_message = f"Échec du téléchargement/extraction du Dossier Data : {str(e)}" + # Message UI générique (les détails restent dans les logs) + config.error_message = _("error_extract_data_failed") config.needs_redraw = True loading_step = "load_sources" if os.path.exists(zip_path): @@ -757,13 +759,13 @@ async def main(): os.remove(zip_path) logger.debug(f"Fichier ZIP {zip_path} supprimé") loading_step = "load_sources" - config.current_loading_system = "Chargement des systèmes..." + config.current_loading_system = _("loading_load_systems") config.loading_progress = 80.0 config.needs_redraw = True logger.debug(f"Étape chargement : {loading_step}, progress={config.loading_progress}") else: loading_step = "load_sources" - config.current_loading_system = "Chargement des systèmes..." + config.current_loading_system = _("loading_load_systems") config.loading_progress = 80.0 config.needs_redraw = True logger.debug(f"Dossier Data non vide, passage à {loading_step}") @@ -771,7 +773,7 @@ async def main(): sources = load_sources() if not sources: config.menu_state = "error" - config.error_message = "Échec du chargement de sources.json" + config.error_message = _("error_sources_load_failed") config.needs_redraw = True logger.debug("Erreur : Échec du chargement de sources.json") else: diff --git a/ports/RGSX/config.py b/ports/RGSX/config.py index 3ac2f01..86ca272 100644 --- a/ports/RGSX/config.py +++ b/ports/RGSX/config.py @@ -4,7 +4,7 @@ import sys import logging # Version actuelle de l'application -app_version = "1.9.8.5" +app_version = "1.9.8.6" def get_application_root(): """Détermine le dossier de l'application de manière portable.""" diff --git a/ports/RGSX/controls_mapper.py b/ports/RGSX/controls_mapper.py index 90e4225..7ba45d5 100644 --- a/ports/RGSX/controls_mapper.py +++ b/ports/RGSX/controls_mapper.py @@ -28,7 +28,7 @@ ACTION_DEFS = [ {"name": "page_up"}, {"name": "page_down"}, {"name": "history"}, - {"name": "progress"}, + {"name": "delete_history"}, {"name": "delete"}, {"name": "space"}, ] @@ -43,7 +43,6 @@ def get_actions(lang=None): actions.append({"name": name, "display": display, "description": description}) return actions -# ...existing code... # Mappage des valeurs SDL vers les constantes Pygame SDL_TO_PYGAME_KEY = { diff --git a/ports/RGSX/language.py b/ports/RGSX/language.py index 25cd7ac..64354f3 100644 --- a/ports/RGSX/language.py +++ b/ports/RGSX/language.py @@ -3,6 +3,7 @@ import json import pygame #type: ignore import logging import config +import subprocess logger = logging.getLogger(__name__) @@ -12,6 +13,18 @@ current_language = DEFAULT_LANGUAGE translations = {} show_language_selector_on_startup = False +# Mapping optionnel pour normaliser les locales Batocera -> codes 2 lettres +BATOCERA_LOCALE_MAP = { + "en_US": "en", + "en_GB": "en", + "fr_FR": "fr", + "de_DE": "de", + "es_ES": "es", + "it_IT": "it", + "tr_TR": "tr", + "zh_CN": "zh", +} + def load_language(lang_code=None): """Charge les traductions pour la langue spécifiée ou la langue par défaut.""" global current_language, translations @@ -316,6 +329,40 @@ def update_valid_states(): VALID_STATES.append("language_select") logger.debug("État language_select ajouté aux états valides") +def detect_batocera_language(): + """Tente de lire la langue système de Batocera et retourne un code à 2 lettres, sinon None.""" + try: + batocera_conf = "/userdata/system/batocera.conf" + if not os.path.exists(batocera_conf): + logger.debug("batocera.conf introuvable, détection Batocera ignorée") + return None + + # batocera-settings-get system.language -> ex: en_US, fr_FR, ... + res = subprocess.run( + ["batocera-settings-get", "system.language"], + capture_output=True, + text=True, + timeout=3, + ) + if res.returncode != 0: + logger.warning(f"Lecture batocera-settings-get échouée (code {res.returncode}): {res.stderr.strip()}") + return None + + locale_val = res.stdout.strip() + if not locale_val: + logger.warning("Langue Batocera vide") + return None + + lang2 = BATOCERA_LOCALE_MAP.get(locale_val, locale_val.split("_")[0].lower()) + logger.info(f"Langue Batocera détectée: {locale_val} -> {lang2}") + return lang2 + except FileNotFoundError: + logger.debug("Commande batocera-settings-get introuvable") + return None + except Exception as e: + logger.error(f"Erreur lors de la détection de la langue Batocera: {e}") + return None + def initialize_language(): """Initialise la langue au démarrage de l'application.""" global show_language_selector_on_startup @@ -323,19 +370,23 @@ def initialize_language(): # Vérifier si le fichier de préférence de langue existe language_file_exists = os.path.exists(config.LANGUAGE_CONFIG_PATH) - # Si le fichier n'existe pas, créer un fichier avec le français par défaut if not language_file_exists: - logger.info("Aucun fichier de préférence de langue trouvé, création avec le français par défaut") - save_language_preference(DEFAULT_LANGUAGE) - show_language_selector_on_startup = False # Ne pas afficher le sélecteur au démarrage + # Tentative de détection Batocera + detected = detect_batocera_language() + if detected: + logger.info(f"Préférence de langue initialisée depuis Batocera: {detected}") + save_language_preference(detected) + else: + logger.info(f"Aucune préférence trouvée, utilisation de la langue par défaut: {DEFAULT_LANGUAGE}") + save_language_preference(DEFAULT_LANGUAGE) + show_language_selector_on_startup = False else: - # Le fichier existe, charger normalement - show_language_selector_on_startup = False # Ne jamais afficher le sélecteur au démarrage - + show_language_selector_on_startup = False # Comportement actuel + # Charger la préférence de langue lang_code = load_language_preference() - # Charger la langue par défaut ou préférée + # Charger la langue préférée (avec fallback interne déjà géré) if load_language(lang_code): logger.info(f"Langue chargée au démarrage: {lang_code}") else: diff --git a/ports/RGSX/languages/de.json b/ports/RGSX/languages/de.json index bc370c6..096d873 100644 --- a/ports/RGSX/languages/de.json +++ b/ports/RGSX/languages/de.json @@ -17,6 +17,14 @@ "loading_extract_initial": "Extrahieren des initialen Datenordners...", "loading_systems": "Systeme werden geladen...", "loading_progress": "Fortschritt: {0}%", + "loading_test_internet": "Verbindung wird getestet...", + "loading_check_updates": "Aktualisierungen werden geprüft... Bitte warten...", + "error_check_updates_failed": "Überprüfung auf Updates fehlgeschlagen.", + "loading_downloading_games_images": "Spiele und Bilder werden heruntergeladen...", + "loading_extracting_data": "Der initiale Datenordner wird entpackt...", + "loading_load_systems": "Systeme werden geladen...", + "error_extract_data_failed": "Herunterladen oder Entpacken des initialen Datenordners fehlgeschlagen.", + "error_sources_load_failed": "sources.json konnte nicht geladen werden", "error_no_internet": "Keine Internetverbindung. Überprüfe dein Netzwerk.", "error_load_sources": "Fehler beim Laden von sources.json", @@ -118,7 +126,6 @@ "controls_desc_space": "Leerzeichen hinzufügen (z.B.: RT, Leertaste)", "controls_desc_start": "Pausenmenü öffnen (z.B.: Start, AltGr)", - "footer_version": "RGSX v{0} - {1}: Optionen - {2}: Verlauf - {3}: Filtern", "action_retry": "Wiederholen", "action_quit": "Beenden", diff --git a/ports/RGSX/languages/en.json b/ports/RGSX/languages/en.json index 13eaee7..2cc979d 100644 --- a/ports/RGSX/languages/en.json +++ b/ports/RGSX/languages/en.json @@ -12,16 +12,15 @@ "loading_test_connection": "Testing connection...", "loading_update_check": "Checking for updates... Please wait...", - "loading_download_data": "Downloading games and images...", - "loading_download_initial": "Downloading initial Data Folder...", - "loading_extract_initial": "Extracting initial Data Folder...", + "loading_download_data": "Downloading initial Data folder...", + "loading_extract_initial": "Extracting initial Data folder...", "loading_systems": "Loading systems...", "loading_progress": "Progress: {0}%", - "error_no_internet": "No internet connection. Please check your network.", + "error_no_internet": "No Internet connection. Check your network.", "error_load_sources": "Failed to load sources.json", "error_controls_mapping": "Failed to map controls", - "error_download_data": "Failed to download/extract Data Folder: {0}", + "error_download_data": "Failed to download or extract the initial Data folder.", "error_api_key": "Please enter your API key (premium only) in the file {0}", "error_api_key_extended": "Please enter your API key (premium only) in the file /userdata/saves/ports/rgsx/1fichierAPI.txt by opening it in a text editor and pasting your API key", "error_invalid_download_data": "Invalid download data", @@ -118,7 +117,6 @@ "controls_desc_space": "Add space (e.g. RT, Space)", "controls_desc_start": "Open pause menu (e.g. Start, AltGr)", - "footer_version": "RGSX v{0} - {1}: Options - {2}: History - {3}: Filter", "action_retry": "Retry", "action_quit": "Quit", diff --git a/ports/RGSX/languages/es.json b/ports/RGSX/languages/es.json index 5d091ee..a422b14 100644 --- a/ports/RGSX/languages/es.json +++ b/ports/RGSX/languages/es.json @@ -17,6 +17,16 @@ "loading_extract_initial": "Extrayendo la carpeta de datos inicial...", "loading_systems": "Cargando sistemas...", "loading_progress": "Progreso: {0}%", + + "loading_test_internet": "Probando la conexión...", + "loading_check_updates": "Buscando actualizaciones... Espere...", + "error_check_updates_failed": "Error al comprobar actualizaciones.", + "loading_downloading_games_images": "Descargando juegos e imágenes...", + "loading_extracting_data": "Extrayendo la carpeta de datos inicial...", + "loading_load_systems": "Cargando sistemas...", + "error_extract_data_failed": "Error al descargar o extraer la carpeta de datos inicial.", + "error_sources_load_failed": "Error al cargar sources.json", + "error_no_internet": "Sin conexión a Internet. Verifica tu red.", "error_load_sources": "Error al cargar sources.json", @@ -118,7 +128,6 @@ "controls_desc_space": "Añadir espacio (ej: RT, Espacio)", "controls_desc_start": "Abrir el menú de pausa (ej: Start, AltGr)", - "footer_version": "RGSX v{0} - {1} : Opciones - {2} : Historial - {3} : Filtrar", "action_retry": "Reintentar", "action_quit": "Salir", diff --git a/ports/RGSX/languages/fr.json b/ports/RGSX/languages/fr.json index b65f991..b0d4b3c 100644 --- a/ports/RGSX/languages/fr.json +++ b/ports/RGSX/languages/fr.json @@ -6,13 +6,22 @@ "disclaimer_line4": "RGSX n'est pas responsable des contenus téléchargés,", "disclaimer_line5": "et n'heberge pas de ROMs.", - "loading_test_connection": "Test de connexion...", - "loading_update_check": "Verification Mise à jour en cours... Patientez...", - "loading_download_data": "Téléchargement des jeux et images ...", - "loading_download_initial": "Téléchargement du Dossier Data initial...", - "loading_extract_initial": "Extraction du Dossier Data initial...", + "loading_test_connection": "Test de la connexion...", + "loading_update_check": "Vérification des mises à jour... Veuillez patienter...", + "loading_download_data": "Téléchargement des jeux et images...", + "loading_download_initial": "Téléchargement du dossier de données initial...", + "loading_extract_initial": "Extraction du dossier de données initial...", "loading_systems": "Chargement des systèmes...", "loading_progress": "Progression : {0}%", + "loading_test_internet": "Test de la connexion...", + "loading_check_updates": "Vérification des mises à jour... Veuillez patienter...", + "error_check_updates_failed": "Échec de la vérification des mises à jour.", + "loading_downloading_games_images": "Téléchargement des jeux et images...", + "loading_extracting_data": "Extraction du dossier de données initial...", + "loading_load_systems": "Chargement des systèmes...", + "error_extract_data_failed": "Échec du téléchargement ou de l'extraction du dossier de données initial.", + "error_sources_load_failed": "Échec du chargement de sources.json", + "error_no_internet": "Pas de connexion Internet. Vérifiez votre réseau.", "error_load_sources": "Échec du chargement de sources.json", @@ -100,21 +109,20 @@ "controls_action_start": "Aide / Réglages", "controls_desc_confirm": "Valider (ex: A, Entrée)", - "controls_desc_cancel": "Annuler/Retour (ex: B, RetourArrière)", + "controls_desc_cancel": "Annuler/Retour (ex: B, Echap)", "controls_desc_up": "Naviguer vers le haut", "controls_desc_down": "Naviguer vers le bas", "controls_desc_left": "Naviguer à gauche", "controls_desc_right": "Naviguer à droite", - "controls_desc_page_up": "Page précédente/Défilement Rapide Haut (ex: PageUp, LB)", - "controls_desc_page_down": "Page suivante/Défilement Rapide Bas (ex: PageDown, RB)", - "controls_desc_delete_history": "Effacer Historique (ex: X)", + "controls_desc_page_up": "Défilement Rapide - (ex: PageUp, LB)", + "controls_desc_page_down": "Défilement Rapide + (ex: PageDown, RB)", "controls_desc_history": "Ouvrir l'historique (ex: H, Y)", - "controls_desc_filter": "Ouvrir filtre (ex: F, Select)", - "controls_desc_delete": "Supprimer caractère (ex: LT, Suppr)", - "controls_desc_space": "Ajouter espace (ex: RT, Espace)", + "controls_desc_delete_history": "Effacer Historique (ex: X)", + "controls_desc_filter": "Mode Filtre : Ouvrir/Valider (ex: F, Select)", + "controls_desc_delete": "Mode Filtre : Supprimer caractère (ex: LT, Suppr)", + "controls_desc_space": "Mode Filtre : Ajouter espace (ex: RT, Espace)", "controls_desc_start": "Ouvrir le menu pause (ex: Start, AltGr)", - "footer_version": "RGSX v{0} - {1} : Options - {2}: Historique - {3} : Filtrer", "action_retry": "Retenter", "action_quit": "Quitter",