1
0
forked from Mirrors/RGSX
Files
RGSX/language.py

348 lines
15 KiB
Python

import os
import json
import pygame #type: ignore
import logging
import config
logger = logging.getLogger(__name__)
# Langue par défaut et variables globales
DEFAULT_LANGUAGE = "fr"
current_language = DEFAULT_LANGUAGE
translations = {}
show_language_selector_on_startup = False
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
if lang_code is None:
lang_code = DEFAULT_LANGUAGE
lang_file = os.path.join(config.APP_FOLDER, "languages", f"{lang_code}.json")
try:
if not os.path.exists(lang_file):
if lang_code != DEFAULT_LANGUAGE:
logger.warning(f"Fichier de langue {lang_code} non trouvé, utilisation de la langue par défaut")
return load_language(DEFAULT_LANGUAGE)
else:
logger.error(f"Fichier de langue par défaut {lang_file} non trouvé")
return False
with open(lang_file, 'r', encoding='utf-8') as f:
translations = json.load(f)
current_language = lang_code
#logger.debug(f"Langue {lang_code} chargée avec succès ({len(translations)} traductions)")
return True
except Exception as e:
logger.error(f"Erreur lors du chargement de la langue {lang_code}: {str(e)}")
if lang_code != DEFAULT_LANGUAGE:
logger.warning(f"Tentative de chargement de la langue par défaut")
return load_language(DEFAULT_LANGUAGE)
return False
def get_text(key, default=None):
"""Récupère la traduction correspondant à la clé."""
if not translations:
load_language()
if key in translations:
return translations[key]
# Si la clé n'existe pas, retourner la valeur par défaut ou la clé elle-même
if default is not None:
return default
logger.warning(f"Clé de traduction '{key}' non trouvée dans la langue {current_language}")
return key
def get_available_languages():
"""Récupère la liste des langues disponibles."""
languages_dir = os.path.join(config.APP_FOLDER, "languages")
if not os.path.exists(languages_dir):
logger.warning(f"Dossier des langues {languages_dir} non trouvé")
return []
languages = []
for file in os.listdir(languages_dir):
if file.endswith(".json"):
lang_code = os.path.splitext(file)[0]
languages.append(lang_code)
return languages
def set_language(lang_code):
"""Change la langue courante et sauvegarde la préférence."""
if load_language(lang_code):
config.current_language = lang_code
save_language_preference(lang_code)
return True
return False
def save_language_preference(lang_code):
"""Sauvegarde la préférence de langue dans un fichier."""
try:
# S'assurer que le dossier existe
os.makedirs(os.path.dirname(config.LANGUAGE_CONFIG_PATH), exist_ok=True)
# Sauvegarder la préférence
with open(config.LANGUAGE_CONFIG_PATH, 'w', encoding='utf-8') as f:
json.dump({"language": lang_code}, f)
logger.debug(f"Préférence de langue sauvegardée: {lang_code}")
return True
except Exception as e:
logger.error(f"Erreur lors de la sauvegarde de la préférence de langue: {str(e)}")
return False
def load_language_preference():
"""Charge la préférence de langue depuis le fichier."""
global show_language_selector_on_startup
try:
if not os.path.exists(config.LANGUAGE_CONFIG_PATH):
logger.info("Aucune préférence de langue trouvée, utilisation du français par défaut")
# Créer le fichier avec le français par défaut
save_language_preference(DEFAULT_LANGUAGE)
return DEFAULT_LANGUAGE
with open(config.LANGUAGE_CONFIG_PATH, 'r', encoding='utf-8') as f:
data = json.load(f)
lang_code = data.get("language", DEFAULT_LANGUAGE)
return lang_code
except json.JSONDecodeError:
logger.warning("Fichier de préférence de langue corrompu, utilisation du français par défaut")
# Recréer le fichier avec le français par défaut
save_language_preference(DEFAULT_LANGUAGE)
return DEFAULT_LANGUAGE
except Exception as e:
logger.error(f"Erreur lors du chargement de la préférence de langue: {str(e)}")
# Recréer le fichier avec le français par défaut
save_language_preference(DEFAULT_LANGUAGE)
return DEFAULT_LANGUAGE
def get_language_name(lang_code):
"""Retourne le nom de la langue à partir du code."""
language_names = {
"fr": "Français",
"en": "English",
"es": "Español",
"de": "Deutsch",
"it": "Italiano",
"pt": "Português",
"ja": "日本語",
"zh": "中文",
"ru": "Русский"
}
return language_names.get(lang_code, lang_code)
def draw_language_selector(screen, selected_language_index):
"""Affiche le sélecteur de langue."""
from display import THEME_COLORS, OVERLAY
# Obtenir les langues disponibles
available_languages = get_available_languages()
if not available_languages:
logger.error("Aucune langue disponible")
return
# Afficher l'overlay
screen.blit(OVERLAY, (0, 0))
# Titre
title_text = _("language_select_title")
title_surface = config.font.render(title_text, True, THEME_COLORS["text"])
title_rect = title_surface.get_rect(center=(config.screen_width // 2, config.screen_height // 4))
# Fond du titre
title_bg_rect = title_rect.inflate(40, 20)
pygame.draw.rect(screen, THEME_COLORS["button_idle"], title_bg_rect, border_radius=10)
pygame.draw.rect(screen, THEME_COLORS["border"], title_bg_rect, 2, border_radius=10)
screen.blit(title_surface, title_rect)
# Options de langue
button_height = 60
button_width = 300
button_spacing = 20
total_height = len(available_languages) * (button_height + button_spacing) - button_spacing
start_y = (config.screen_height - total_height) // 2
for i, lang_code in enumerate(available_languages):
# Obtenir le nom de la langue
lang_name = get_language_name(lang_code)
# Position du bouton
button_x = (config.screen_width - button_width) // 2
button_y = start_y + i * (button_height + button_spacing)
# Dessiner le bouton
button_color = THEME_COLORS["button_hover"] if i == selected_language_index else THEME_COLORS["button_idle"]
pygame.draw.rect(screen, button_color, (button_x, button_y, button_width, button_height), border_radius=10)
pygame.draw.rect(screen, THEME_COLORS["border"], (button_x, button_y, button_width, button_height), 2, border_radius=10)
# Texte du bouton
text_surface = config.font.render(lang_name, True, THEME_COLORS["text"])
text_rect = text_surface.get_rect(center=(button_x + button_width // 2, button_y + button_height // 2))
screen.blit(text_surface, text_rect)
# Instructions
instruction_text = _("language_select_instruction")
instruction_surface = config.small_font.render(instruction_text, True, THEME_COLORS["text"])
instruction_rect = instruction_surface.get_rect(center=(config.screen_width // 2, config.screen_height - 50))
screen.blit(instruction_surface, instruction_rect)
def handle_language_menu_events(event, screen):
"""Gère les événements du menu de sélection de langue avec support clavier et manette."""
available_languages = get_available_languages()
if not available_languages:
logger.error("Aucune langue disponible")
config.menu_state = "platform" # Toujours revenir à platform en cas d'erreur
config.needs_redraw = True
return
# Navigation avec les touches du clavier
if event.type == pygame.KEYDOWN:
# Navigation vers le haut
if event.key == pygame.K_UP:
config.selected_language_index = (config.selected_language_index - 1) % len(available_languages)
config.needs_redraw = True
logger.debug(f"Navigation vers le haut dans le sélecteur de langue: {config.selected_language_index}")
# Navigation vers le bas
elif event.key == pygame.K_DOWN:
config.selected_language_index = (config.selected_language_index + 1) % len(available_languages)
config.needs_redraw = True
logger.debug(f"Navigation vers le bas dans le sélecteur de langue: {config.selected_language_index}")
# Sélection de la langue
elif event.key == pygame.K_RETURN:
lang_code = available_languages[config.selected_language_index]
if set_language(lang_code):
logger.info(f"Langue changée pour {lang_code}")
config.current_language = lang_code
# Déterminer l'état suivant en fonction du contexte
if config.previous_menu_state is None:
# Premier démarrage - passer à l'état loading pour charger les plateformes
config.menu_state = "loading"
logger.debug("Premier démarrage: passage à l'état loading après sélection de la langue")
elif config.previous_menu_state == "pause_menu":
# Si on vient du menu pause, retourner au menu pause avec un message
config.menu_state = "restart_popup"
config.popup_message = _("language_changed").format(lang_code)
config.popup_timer = 2000 # 2 secondes
config.previous_menu_state = "platform" # Pour revenir à l'écran principal après le popup
logger.debug("Message de confirmation de changement de langue affiché, retour au menu pause")
else:
# Autre cas, retourner à l'état précédent avec un message
config.menu_state = "platform" # Toujours revenir à platform pour éviter les problèmes
logger.debug(f"Retour à l'écran principal après sélection de la langue")
else:
# Retour au menu pause en cas d'erreur
config.menu_state = "platform" # Toujours revenir à platform en cas d'erreur
config.needs_redraw = True
logger.debug(f"Sélection de la langue: {lang_code}")
# Annulation (seulement si on n'est pas au démarrage)
elif event.key == pygame.K_ESCAPE and config.previous_menu_state is not None:
config.menu_state = "pause_menu"
config.needs_redraw = True
logger.debug("Annulation de la sélection de langue, retour au menu pause")
# Support de la manette
elif event.type == pygame.JOYBUTTONDOWN:
# Sélection avec le bouton A (généralement 0)
if event.button == 0: # Bouton A
lang_code = available_languages[config.selected_language_index]
if set_language(lang_code):
logger.info(f"Langue changée pour {lang_code} (manette)")
config.current_language = lang_code
# Déterminer l'état suivant en fonction du contexte
if config.previous_menu_state is None:
# Premier démarrage - passer à l'état loading pour charger les plateformes
config.menu_state = "loading"
logger.debug("Premier démarrage: passage à l'état loading après sélection de la langue (manette)")
else:
config.menu_state = "platform"
else:
config.menu_state = "platform"
config.needs_redraw = True
# Annulation avec le bouton B (généralement 1)
elif event.button == 1 and config.previous_menu_state is not None: # Bouton B
config.menu_state = "pause_menu"
config.needs_redraw = True
logger.debug("Annulation de la sélection de langue (manette), retour au menu pause")
# Navigation avec le D-pad
elif event.type == pygame.JOYHATMOTION:
if event.value == (0, 1): # Haut
config.selected_language_index = (config.selected_language_index - 1) % len(available_languages)
config.needs_redraw = True
logger.debug(f"Navigation vers le haut dans le sélecteur de langue (D-pad): {config.selected_language_index}")
elif event.value == (0, -1): # Bas
config.selected_language_index = (config.selected_language_index + 1) % len(available_languages)
config.needs_redraw = True
logger.debug(f"Navigation vers le bas dans le sélecteur de langue (D-pad): {config.selected_language_index}")
# Navigation avec les joysticks analogiques
elif event.type == pygame.JOYAXISMOTION:
# Joystick gauche vertical (généralement axe 1)
if event.axis == 1 and abs(event.value) > 0.5:
if event.value < -0.5: # Haut
config.selected_language_index = (config.selected_language_index - 1) % len(available_languages)
config.needs_redraw = True
logger.debug(f"Navigation vers le haut dans le sélecteur de langue (joystick): {config.selected_language_index}")
elif event.value > 0.5: # Bas
config.selected_language_index = (config.selected_language_index + 1) % len(available_languages)
config.needs_redraw = True
logger.debug(f"Navigation vers le bas dans le sélecteur de langue (joystick): {config.selected_language_index}")
def update_valid_states():
"""Ajoute l'état language_select à la liste des états valides."""
from controls import VALID_STATES
if "language_select" not in VALID_STATES:
VALID_STATES.append("language_select")
logger.debug("État language_select ajouté aux états valides")
def initialize_language():
"""Initialise la langue au démarrage de l'application."""
global show_language_selector_on_startup
# 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
else:
# Le fichier existe, charger normalement
show_language_selector_on_startup = False # Ne jamais afficher le sélecteur au démarrage
# Charger la préférence de langue
lang_code = load_language_preference()
# Charger la langue par défaut ou préférée
if load_language(lang_code):
logger.info(f"Langue chargée au démarrage: {lang_code}")
else:
logger.warning(f"Impossible de charger la langue {lang_code}, utilisation de la langue par défaut")
load_language(DEFAULT_LANGUAGE)
return True
# Alias pour faciliter l'utilisation
_ = get_text