epik/i18n/
mod.rs

1// Internationalization support
2use serde::{Deserialize, Serialize};
3use std::collections::HashMap;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
6pub enum Language {
7    English,
8    Italian,
9    French,
10    German,
11    Spanish,
12}
13
14impl Language {
15    pub fn all() -> Vec<Language> {
16        vec![
17            Language::English,
18            Language::Italian,
19            Language::French,
20            Language::German,
21            Language::Spanish,
22        ]
23    }
24
25    pub fn name(&self) -> &'static str {
26        match self {
27            Language::English => "English",
28            Language::Italian => "Italiano",
29            Language::French => "Français",
30            Language::German => "Deutsch",
31            Language::Spanish => "Español",
32        }
33    }
34
35    pub fn code(&self) -> &'static str {
36        match self {
37            Language::English => "en",
38            Language::Italian => "it",
39            Language::French => "fr",
40            Language::German => "de",
41            Language::Spanish => "es",
42        }
43    }
44}
45
46impl Default for Language {
47    fn default() -> Self {
48        Language::English
49    }
50}
51
52#[derive(Debug, Clone)]
53pub struct Localizer {
54    current_language: Language,
55    strings: HashMap<Language, HashMap<String, String>>,
56}
57
58impl Default for Localizer {
59    fn default() -> Self {
60        Self::new()
61    }
62}
63
64impl Localizer {
65    pub fn new() -> Self {
66        let mut localizer = Self {
67            current_language: Language::default(),
68            strings: HashMap::new(),
69        };
70
71        // Load English strings
72        localizer.load_english();
73        // Load Italian strings
74        localizer.load_italian();
75        // Load French strings
76        localizer.load_french();
77        // Load German strings
78        localizer.load_german();
79        // Load Spanish strings
80        localizer.load_spanish();
81
82        localizer
83    }
84
85    fn load_english(&mut self) {
86        let mut en = HashMap::new();
87
88        // Common
89        en.insert("app_name".to_string(), "Epik Launcher".to_string());
90        en.insert("loading".to_string(), "Loading...".to_string());
91        en.insert("error".to_string(), "Error".to_string());
92        en.insert("success".to_string(), "Success".to_string());
93
94        // Authentication
95        en.insert("login".to_string(), "Login".to_string());
96        en.insert("logout".to_string(), "Logout".to_string());
97        en.insert("device_code".to_string(), "Device Code".to_string());
98
99        // Navigation
100        en.insert("library".to_string(), "Library".to_string());
101        en.insert("downloads".to_string(), "Downloads".to_string());
102        en.insert("import".to_string(), "Import".to_string());
103        en.insert("settings".to_string(), "Settings".to_string());
104
105        // Game actions
106        en.insert("install".to_string(), "Install".to_string());
107        en.insert("launch".to_string(), "Launch".to_string());
108        en.insert("uninstall".to_string(), "Uninstall".to_string());
109        en.insert("verify".to_string(), "Verify".to_string());
110        en.insert("repair".to_string(), "Repair".to_string());
111        en.insert("cancel".to_string(), "Cancel".to_string());
112
113        // Downloads
114        en.insert(
115            "no_downloads".to_string(),
116            "No active downloads".to_string(),
117        );
118        en.insert("download_speed".to_string(), "Speed".to_string());
119        en.insert("files".to_string(), "Files".to_string());
120
121        // Settings
122        en.insert(
123            "general_settings".to_string(),
124            "General Settings".to_string(),
125        );
126        en.insert(
127            "download_settings".to_string(),
128            "Download Settings".to_string(),
129        );
130        en.insert(
131            "wine_settings".to_string(),
132            "Wine/Proton Settings".to_string(),
133        );
134        en.insert(
135            "advanced_settings".to_string(),
136            "Advanced Settings".to_string(),
137        );
138        en.insert("save".to_string(), "Save".to_string());
139        en.insert(
140            "reset_defaults".to_string(),
141            "Reset to Defaults".to_string(),
142        );
143
144        // Library
145        en.insert("import_game".to_string(), "Import Game".to_string());
146        en.insert("no_games_found".to_string(), "No games found".to_string());
147        en.insert(
148            "library_empty".to_string(),
149            "Your library is empty or not yet loaded".to_string(),
150        );
151        en.insert("get".to_string(), "Get".to_string());
152        en.insert("play".to_string(), "▶ Play".to_string());
153        en.insert("installing".to_string(), "⏳ Installing...".to_string());
154        en.insert("installed".to_string(), "Installed".to_string());
155        en.insert("not_installed".to_string(), "Not installed".to_string());
156        en.insert("view_details".to_string(), "View details".to_string());
157        en.insert("cloud_saves".to_string(), "Cloud Saves".to_string());
158        en.insert(
159            "update_available".to_string(),
160            "Update available".to_string(),
161        );
162        en.insert("wine_prefix".to_string(), "Wine Prefix".to_string());
163        en.insert("select_wine".to_string(), "Select Wine".to_string());
164        en.insert("custom".to_string(), "Custom".to_string());
165
166        // Settings details
167        en.insert("close".to_string(), "Close".to_string());
168        en.insert(
169            "auto_update_games".to_string(),
170            "Auto-update games".to_string(),
171        );
172        en.insert(
173            "auto_update_desc".to_string(),
174            "Automatically check and download updates".to_string(),
175        );
176        en.insert("start_minimized".to_string(), "Start minimized".to_string());
177        en.insert(
178            "start_minimized_desc".to_string(),
179            "Start the launcher minimized to system tray".to_string(),
180        );
181        en.insert(
182            "close_to_tray".to_string(),
183            "Close to system tray".to_string(),
184        );
185        en.insert(
186            "close_to_tray_desc".to_string(),
187            "Minimize to tray instead of closing".to_string(),
188        );
189        en.insert("language".to_string(), "Language".to_string());
190        en.insert("theme".to_string(), "Theme".to_string());
191        en.insert(
192            "max_concurrent".to_string(),
193            "Max concurrent downloads".to_string(),
194        );
195        en.insert(
196            "download_threads".to_string(),
197            "Download threads per game".to_string(),
198        );
199        en.insert(
200            "download_threads_desc".to_string(),
201            "More threads = faster downloads but more CPU usage".to_string(),
202        );
203        en.insert(
204            "bandwidth_limit".to_string(),
205            "Enable bandwidth limiting".to_string(),
206        );
207        en.insert(
208            "max_speed".to_string(),
209            "Maximum download speed".to_string(),
210        );
211        en.insert("cdn_region".to_string(), "CDN Region".to_string());
212        en.insert(
213            "auto_detect_wine".to_string(),
214            "Auto-detect Wine/Proton".to_string(),
215        );
216        en.insert(
217            "auto_detect_wine_desc".to_string(),
218            "Automatically find Wine and Proton installations".to_string(),
219        );
220        en.insert(
221            "wine_prefix_per_game".to_string(),
222            "Separate Wine prefix per game".to_string(),
223        );
224        en.insert(
225            "wine_prefix_desc".to_string(),
226            "Each game gets its own Wine prefix (recommended)".to_string(),
227        );
228        en.insert("enable_dxvk".to_string(), "Enable DXVK".to_string());
229        en.insert(
230            "dxvk_desc".to_string(),
231            "Vulkan-based Direct3D implementation".to_string(),
232        );
233        en.insert("enable_esync".to_string(), "Enable Esync".to_string());
234        en.insert(
235            "esync_desc".to_string(),
236            "Improved synchronization for better performance".to_string(),
237        );
238        en.insert("log_level".to_string(), "Log Level".to_string());
239        en.insert(
240            "enable_telemetry".to_string(),
241            "Enable anonymous telemetry".to_string(),
242        );
243        en.insert(
244            "telemetry_desc".to_string(),
245            "Help improve Epik by sending anonymous usage data".to_string(),
246        );
247        en.insert("log_to_file".to_string(), "Write logs to file".to_string());
248        en.insert(
249            "log_to_file_desc".to_string(),
250            "Store launcher logs in data/logs/epik.log".to_string(),
251        );
252        en.insert("crash_reporting".to_string(), "Crash reporting".to_string());
253        en.insert(
254            "crash_reporting_desc".to_string(),
255            "Generate crash reports on unexpected errors".to_string(),
256        );
257        en.insert(
258            "privacy_mode".to_string(),
259            "Privacy mode (hide library)".to_string(),
260        );
261        en.insert(
262            "privacy_mode_desc".to_string(),
263            "Hide titles and covers when sharing your screen".to_string(),
264        );
265        en.insert("hidden_game_title".to_string(), "Hidden game".to_string());
266        en.insert("current_file".to_string(), "Current".to_string());
267
268        // Stats
269        en.insert("statistics".to_string(), "Statistics".to_string());
270        en.insert("playtime".to_string(), "Playtime".to_string());
271        en.insert("total_playtime".to_string(), "Total Playtime".to_string());
272        en.insert("launches".to_string(), "Launches".to_string());
273        en.insert("last_played".to_string(), "Last Played".to_string());
274        en.insert("first_played".to_string(), "First Played".to_string());
275        en.insert("play_sessions".to_string(), "Play Sessions".to_string());
276        en.insert("hours".to_string(), "hours".to_string());
277        en.insert("minutes".to_string(), "minutes".to_string());
278        en.insert("never".to_string(), "Never".to_string());
279        en.insert("session_history".to_string(), "Session History".to_string());
280        en.insert("duration".to_string(), "Duration".to_string());
281        en.insert(
282            "no_stats".to_string(),
283            "No statistics available yet".to_string(),
284        );
285
286        // Achievements
287        en.insert("achievements".to_string(), "Achievements".to_string());
288        en.insert("unlocked".to_string(), "Unlocked".to_string());
289        en.insert("locked".to_string(), "Locked".to_string());
290        en.insert("completion".to_string(), "Completion".to_string());
291        en.insert(
292            "no_achievements".to_string(),
293            "No achievements data available".to_string(),
294        );
295
296        // Game Details
297        en.insert("description".to_string(), "Description".to_string());
298        en.insert("screenshots".to_string(), "Screenshots".to_string());
299        en.insert(
300            "no_description".to_string(),
301            "Description not available yet".to_string(),
302        );
303        en.insert(
304            "no_screenshots".to_string(),
305            "Screenshots not available".to_string(),
306        );
307        en.insert(
308            "system_requirements".to_string(),
309            "System Requirements".to_string(),
310        );
311        en.insert(
312            "no_requirements".to_string(),
313            "System requirements not available".to_string(),
314        );
315        en.insert("version".to_string(), "Version".to_string());
316        en.insert("developer".to_string(), "Developer".to_string());
317        en.insert("publisher".to_string(), "Publisher".to_string());
318        en.insert("release_date".to_string(), "Release Date".to_string());
319
320        self.strings.insert(Language::English, en);
321    }
322
323    fn load_italian(&mut self) {
324        let mut it = HashMap::new();
325
326        // Common
327        it.insert("app_name".to_string(), "Epik Launcher".to_string());
328        it.insert("loading".to_string(), "Caricamento...".to_string());
329        it.insert("error".to_string(), "Errore".to_string());
330        it.insert("success".to_string(), "Successo".to_string());
331
332        // Authentication
333        it.insert("login".to_string(), "Accedi".to_string());
334        it.insert("logout".to_string(), "Esci".to_string());
335        it.insert("device_code".to_string(), "Codice Dispositivo".to_string());
336
337        // Navigation
338        it.insert("library".to_string(), "Libreria".to_string());
339        it.insert("downloads".to_string(), "Download".to_string());
340        it.insert("import".to_string(), "Importa".to_string());
341        it.insert("settings".to_string(), "Impostazioni".to_string());
342
343        // Game actions
344        it.insert("install".to_string(), "Installa".to_string());
345        it.insert("launch".to_string(), "Avvia".to_string());
346        it.insert("uninstall".to_string(), "Disinstalla".to_string());
347        it.insert("verify".to_string(), "Verifica".to_string());
348        it.insert("repair".to_string(), "Ripara".to_string());
349        it.insert("cancel".to_string(), "Annulla".to_string());
350
351        // Downloads
352        it.insert(
353            "no_downloads".to_string(),
354            "Nessun download attivo".to_string(),
355        );
356        it.insert("download_speed".to_string(), "Velocità".to_string());
357        it.insert("files".to_string(), "File".to_string());
358
359        // Settings
360        it.insert(
361            "general_settings".to_string(),
362            "Impostazioni Generali".to_string(),
363        );
364        it.insert(
365            "download_settings".to_string(),
366            "Impostazioni Download".to_string(),
367        );
368        it.insert(
369            "wine_settings".to_string(),
370            "Impostazioni Wine/Proton".to_string(),
371        );
372        it.insert(
373            "advanced_settings".to_string(),
374            "Impostazioni Avanzate".to_string(),
375        );
376        it.insert("save".to_string(), "Salva".to_string());
377        it.insert(
378            "reset_defaults".to_string(),
379            "Ripristina Predefinite".to_string(),
380        );
381
382        // Library
383        it.insert("import_game".to_string(), "Importa Gioco".to_string());
384        it.insert(
385            "no_games_found".to_string(),
386            "Nessun gioco trovato".to_string(),
387        );
388        it.insert(
389            "library_empty".to_string(),
390            "La tua libreria è vuota o non ancora caricata".to_string(),
391        );
392        it.insert("get".to_string(), "Scarica".to_string());
393        it.insert("play".to_string(), "▶ Gioca".to_string());
394        it.insert(
395            "installing".to_string(),
396            "⏳ Installazione in corso...".to_string(),
397        );
398        it.insert("installed".to_string(), "Installato".to_string());
399        it.insert("not_installed".to_string(), "Non installato".to_string());
400        it.insert(
401            "view_details".to_string(),
402            "Visualizza dettagli".to_string(),
403        );
404        it.insert("cloud_saves".to_string(), "Cloud Saves".to_string());
405        it.insert(
406            "update_available".to_string(),
407            "Aggiornamento disponibile".to_string(),
408        );
409        it.insert("wine_prefix".to_string(), "Prefix Wine".to_string());
410        it.insert("select_wine".to_string(), "Seleziona Wine".to_string());
411        it.insert("custom".to_string(), "Personalizzato".to_string());
412
413        // Settings details
414        it.insert("close".to_string(), "Chiudi".to_string());
415        it.insert(
416            "auto_update_games".to_string(),
417            "Aggiorna automaticamente i giochi".to_string(),
418        );
419        it.insert(
420            "auto_update_desc".to_string(),
421            "Controlla e scarica automaticamente gli aggiornamenti".to_string(),
422        );
423        it.insert(
424            "start_minimized".to_string(),
425            "Avvia minimizzato".to_string(),
426        );
427        it.insert(
428            "start_minimized_desc".to_string(),
429            "Avvia il launcher minimizzato nella system tray".to_string(),
430        );
431        it.insert(
432            "close_to_tray".to_string(),
433            "Chiudi nella system tray".to_string(),
434        );
435        it.insert(
436            "close_to_tray_desc".to_string(),
437            "Minimizza nella tray invece di chiudere".to_string(),
438        );
439        it.insert("language".to_string(), "Lingua".to_string());
440        it.insert("theme".to_string(), "Tema".to_string());
441        it.insert(
442            "max_concurrent".to_string(),
443            "Download simultanei massimi".to_string(),
444        );
445        it.insert(
446            "download_threads".to_string(),
447            "Thread di download per gioco".to_string(),
448        );
449        it.insert(
450            "download_threads_desc".to_string(),
451            "Più thread = download più veloci ma maggiore uso CPU".to_string(),
452        );
453        it.insert(
454            "bandwidth_limit".to_string(),
455            "Abilita limitazione banda".to_string(),
456        );
457        it.insert(
458            "max_speed".to_string(),
459            "Velocità massima di download".to_string(),
460        );
461        it.insert("cdn_region".to_string(), "Regione CDN".to_string());
462        it.insert(
463            "auto_detect_wine".to_string(),
464            "Rileva automaticamente Wine/Proton".to_string(),
465        );
466        it.insert(
467            "auto_detect_wine_desc".to_string(),
468            "Trova automaticamente le installazioni di Wine e Proton".to_string(),
469        );
470        it.insert(
471            "wine_prefix_per_game".to_string(),
472            "Prefix Wine separato per gioco".to_string(),
473        );
474        it.insert(
475            "wine_prefix_desc".to_string(),
476            "Ogni gioco ha il proprio prefix Wine (consigliato)".to_string(),
477        );
478        it.insert("enable_dxvk".to_string(), "Abilita DXVK".to_string());
479        it.insert(
480            "dxvk_desc".to_string(),
481            "Implementazione Direct3D basata su Vulkan".to_string(),
482        );
483        it.insert("enable_esync".to_string(), "Abilita Esync".to_string());
484        it.insert(
485            "esync_desc".to_string(),
486            "Sincronizzazione migliorata per prestazioni migliori".to_string(),
487        );
488        it.insert("log_level".to_string(), "Livello Log".to_string());
489        it.insert(
490            "enable_telemetry".to_string(),
491            "Abilita telemetria anonima".to_string(),
492        );
493        it.insert(
494            "telemetry_desc".to_string(),
495            "Aiuta a migliorare Epik inviando dati anonimi di utilizzo".to_string(),
496        );
497        it.insert("log_to_file".to_string(), "Scrivi log su file".to_string());
498        it.insert(
499            "log_to_file_desc".to_string(),
500            "Salva i log in data/logs/epik.log".to_string(),
501        );
502        it.insert("crash_reporting".to_string(), "Crash reporting".to_string());
503        it.insert(
504            "crash_reporting_desc".to_string(),
505            "Genera report in caso di errori imprevisti".to_string(),
506        );
507        it.insert(
508            "privacy_mode".to_string(),
509            "Modalità privacy (nascondi libreria)".to_string(),
510        );
511        it.insert(
512            "privacy_mode_desc".to_string(),
513            "Nasconde titoli e cover quando condividi lo schermo".to_string(),
514        );
515        it.insert(
516            "hidden_game_title".to_string(),
517            "Gioco nascosto".to_string(),
518        );
519        it.insert("current_file".to_string(), "Corrente".to_string());
520
521        // Stats
522        it.insert("statistics".to_string(), "Statistiche".to_string());
523        it.insert("playtime".to_string(), "Tempo di gioco".to_string());
524        it.insert("total_playtime".to_string(), "Tempo Totale".to_string());
525        it.insert("launches".to_string(), "Avvii".to_string());
526        it.insert("last_played".to_string(), "Ultima Partita".to_string());
527        it.insert("first_played".to_string(), "Prima Partita".to_string());
528        it.insert("play_sessions".to_string(), "Sessioni di Gioco".to_string());
529        it.insert("hours".to_string(), "ore".to_string());
530        it.insert("minutes".to_string(), "minuti".to_string());
531        it.insert("never".to_string(), "Mai".to_string());
532        it.insert(
533            "session_history".to_string(),
534            "Storico Sessioni".to_string(),
535        );
536        it.insert("duration".to_string(), "Durata".to_string());
537        it.insert(
538            "no_stats".to_string(),
539            "Nessuna statistica disponibile".to_string(),
540        );
541
542        // Achievements
543        it.insert("achievements".to_string(), "Obiettivi".to_string());
544        it.insert("unlocked".to_string(), "Sbloccato".to_string());
545        it.insert("locked".to_string(), "Bloccato".to_string());
546        it.insert("completion".to_string(), "Completamento".to_string());
547        it.insert(
548            "no_achievements".to_string(),
549            "Nessun obiettivo disponibile".to_string(),
550        );
551
552        // Game Details
553        it.insert("description".to_string(), "Descrizione".to_string());
554        it.insert("screenshots".to_string(), "Screenshot".to_string());
555        it.insert(
556            "no_description".to_string(),
557            "Descrizione non disponibile".to_string(),
558        );
559        it.insert(
560            "no_screenshots".to_string(),
561            "Screenshot non disponibili".to_string(),
562        );
563        it.insert(
564            "system_requirements".to_string(),
565            "Requisiti di Sistema".to_string(),
566        );
567        it.insert(
568            "no_requirements".to_string(),
569            "Requisiti di sistema non disponibili".to_string(),
570        );
571        it.insert("version".to_string(), "Versione".to_string());
572        it.insert("developer".to_string(), "Sviluppatore".to_string());
573        it.insert("publisher".to_string(), "Editore".to_string());
574        it.insert("release_date".to_string(), "Data di Rilascio".to_string());
575
576        self.strings.insert(Language::Italian, it);
577    }
578
579    fn load_french(&mut self) {
580        let mut fr = HashMap::new();
581        fr.insert("app_name".to_string(), "Epik Launcher".to_string());
582        fr.insert("loading".to_string(), "Chargement...".to_string());
583        fr.insert("error".to_string(), "Erreur".to_string());
584        fr.insert("success".to_string(), "Succès".to_string());
585        fr.insert("login".to_string(), "Connexion".to_string());
586        fr.insert("logout".to_string(), "Déconnexion".to_string());
587        fr.insert("library".to_string(), "Bibliothèque".to_string());
588        fr.insert("downloads".to_string(), "Téléchargements".to_string());
589        fr.insert("import".to_string(), "Importer".to_string());
590        fr.insert("settings".to_string(), "Paramètres".to_string());
591        fr.insert("install".to_string(), "Installer".to_string());
592        fr.insert("launch".to_string(), "Lancer".to_string());
593        fr.insert("uninstall".to_string(), "Désinstaller".to_string());
594        fr.insert("cancel".to_string(), "Annuler".to_string());
595        fr.insert("play".to_string(), "▶ Jouer".to_string());
596        fr.insert("installing".to_string(), "⏳ Installation...".to_string());
597        fr.insert("installed".to_string(), "Installé".to_string());
598        fr.insert("language".to_string(), "Langue".to_string());
599        fr.insert("statistics".to_string(), "Statistiques".to_string());
600        fr.insert("playtime".to_string(), "Temps de Jeu".to_string());
601        fr.insert("total_playtime".to_string(), "Temps Total".to_string());
602        fr.insert("launches".to_string(), "Lancements".to_string());
603        fr.insert("last_played".to_string(), "Dernière Partie".to_string());
604        fr.insert("achievements".to_string(), "Succès".to_string());
605        fr.insert("unlocked".to_string(), "Déverrouillé".to_string());
606        fr.insert("locked".to_string(), "Verrouillé".to_string());
607        fr.insert("description".to_string(), "Description".to_string());
608        fr.insert("version".to_string(), "Version".to_string());
609        fr.insert("developer".to_string(), "Développeur".to_string());
610        fr.insert("publisher".to_string(), "Éditeur".to_string());
611        fr.insert(
612            "log_to_file".to_string(),
613            "Écrire les logs sur fichier".to_string(),
614        );
615        fr.insert(
616            "log_to_file_desc".to_string(),
617            "Enregistrer les logs dans data/logs/epik.log".to_string(),
618        );
619        fr.insert(
620            "crash_reporting".to_string(),
621            "Rapports de crash".to_string(),
622        );
623        fr.insert(
624            "crash_reporting_desc".to_string(),
625            "Générer un rapport en cas d'erreur imprévue".to_string(),
626        );
627        fr.insert(
628            "privacy_mode".to_string(),
629            "Mode confidentialité (masquer la bibliothèque)".to_string(),
630        );
631        fr.insert(
632            "privacy_mode_desc".to_string(),
633            "Masque titres et couvertures lors du partage d'écran".to_string(),
634        );
635        fr.insert("hidden_game_title".to_string(), "Jeu masqué".to_string());
636        self.strings.insert(Language::French, fr);
637    }
638
639    fn load_german(&mut self) {
640        let mut de = HashMap::new();
641        de.insert("app_name".to_string(), "Epik Launcher".to_string());
642        de.insert("loading".to_string(), "Wird geladen...".to_string());
643        de.insert("error".to_string(), "Fehler".to_string());
644        de.insert("success".to_string(), "Erfolg".to_string());
645        de.insert("login".to_string(), "Anmelden".to_string());
646        de.insert("logout".to_string(), "Abmelden".to_string());
647        de.insert("library".to_string(), "Bibliothek".to_string());
648        de.insert("downloads".to_string(), "Downloads".to_string());
649        de.insert("import".to_string(), "Importieren".to_string());
650        de.insert("settings".to_string(), "Einstellungen".to_string());
651        de.insert("install".to_string(), "Installieren".to_string());
652        de.insert("launch".to_string(), "Starten".to_string());
653        de.insert("uninstall".to_string(), "Deinstallieren".to_string());
654        de.insert("cancel".to_string(), "Abbrechen".to_string());
655        de.insert("play".to_string(), "▶ Spielen".to_string());
656        de.insert(
657            "installing".to_string(),
658            "⏳ Installation läuft...".to_string(),
659        );
660        de.insert("installed".to_string(), "Installiert".to_string());
661        de.insert("language".to_string(), "Sprache".to_string());
662        de.insert("statistics".to_string(), "Statistiken".to_string());
663        de.insert("playtime".to_string(), "Spielzeit".to_string());
664        de.insert("total_playtime".to_string(), "Gesamtspielzeit".to_string());
665        de.insert("launches".to_string(), "Starts".to_string());
666        de.insert("last_played".to_string(), "Zuletzt gespielt".to_string());
667        de.insert("achievements".to_string(), "Erfolge".to_string());
668        de.insert("unlocked".to_string(), "Freigeschaltet".to_string());
669        de.insert("locked".to_string(), "Gesperrt".to_string());
670        de.insert("description".to_string(), "Beschreibung".to_string());
671        de.insert("version".to_string(), "Version".to_string());
672        de.insert("developer".to_string(), "Entwickler".to_string());
673        de.insert("publisher".to_string(), "Herausgeber".to_string());
674        de.insert(
675            "log_to_file".to_string(),
676            "Logs in Datei schreiben".to_string(),
677        );
678        de.insert(
679            "log_to_file_desc".to_string(),
680            "Logs in data/logs/epik.log speichern".to_string(),
681        );
682        de.insert("crash_reporting".to_string(), "Crash-Reporting".to_string());
683        de.insert(
684            "crash_reporting_desc".to_string(),
685            "Erzeuge Bericht bei unerwarteten Fehlern".to_string(),
686        );
687        de.insert(
688            "privacy_mode".to_string(),
689            "Privatsphäre-Modus (Bibliothek ausblenden)".to_string(),
690        );
691        de.insert(
692            "privacy_mode_desc".to_string(),
693            "Blendet Titel und Cover beim Bildschirmteilen aus".to_string(),
694        );
695        de.insert(
696            "hidden_game_title".to_string(),
697            "Verstecktes Spiel".to_string(),
698        );
699        self.strings.insert(Language::German, de);
700    }
701
702    fn load_spanish(&mut self) {
703        let mut es = HashMap::new();
704        es.insert("app_name".to_string(), "Epik Launcher".to_string());
705        es.insert("loading".to_string(), "Cargando...".to_string());
706        es.insert("error".to_string(), "Error".to_string());
707        es.insert("success".to_string(), "Éxito".to_string());
708        es.insert("login".to_string(), "Iniciar Sesión".to_string());
709        es.insert("logout".to_string(), "Cerrar Sesión".to_string());
710        es.insert("library".to_string(), "Biblioteca".to_string());
711        es.insert("downloads".to_string(), "Descargas".to_string());
712        es.insert("import".to_string(), "Importar".to_string());
713        es.insert("settings".to_string(), "Configuración".to_string());
714        es.insert("install".to_string(), "Instalar".to_string());
715        es.insert("launch".to_string(), "Iniciar".to_string());
716        es.insert("uninstall".to_string(), "Desinstalar".to_string());
717        es.insert("cancel".to_string(), "Cancelar".to_string());
718        es.insert("play".to_string(), "▶ Jugar".to_string());
719        es.insert("installing".to_string(), "⏳ Instalando...".to_string());
720        es.insert("installed".to_string(), "Instalado".to_string());
721        es.insert("language".to_string(), "Idioma".to_string());
722        es.insert("statistics".to_string(), "Estadísticas".to_string());
723        es.insert("playtime".to_string(), "Tiempo de Juego".to_string());
724        es.insert("total_playtime".to_string(), "Tiempo Total".to_string());
725        es.insert("launches".to_string(), "Inicios".to_string());
726        es.insert("last_played".to_string(), "Última Partida".to_string());
727        es.insert("achievements".to_string(), "Logros".to_string());
728        es.insert("unlocked".to_string(), "Desbloqueado".to_string());
729        es.insert("locked".to_string(), "Bloqueado".to_string());
730        es.insert("description".to_string(), "Descripción".to_string());
731        es.insert("version".to_string(), "Versión".to_string());
732        es.insert("developer".to_string(), "Desarrollador".to_string());
733        es.insert("publisher".to_string(), "Editorial".to_string());
734        es.insert(
735            "log_to_file".to_string(),
736            "Guardar registros en archivo".to_string(),
737        );
738        es.insert(
739            "log_to_file_desc".to_string(),
740            "Guardar registros en data/logs/epik.log".to_string(),
741        );
742        es.insert(
743            "crash_reporting".to_string(),
744            "Reporte de fallos".to_string(),
745        );
746        es.insert(
747            "crash_reporting_desc".to_string(),
748            "Generar un informe ante errores inesperados".to_string(),
749        );
750        es.insert(
751            "privacy_mode".to_string(),
752            "Modo privacidad (ocultar biblioteca)".to_string(),
753        );
754        es.insert(
755            "privacy_mode_desc".to_string(),
756            "Oculta títulos y portadas al compartir pantalla".to_string(),
757        );
758        es.insert("hidden_game_title".to_string(), "Juego oculto".to_string());
759        self.strings.insert(Language::Spanish, es);
760    }
761
762    pub fn set_language(&mut self, language: Language) {
763        self.current_language = language;
764    }
765
766    pub fn get_language(&self) -> Language {
767        self.current_language
768    }
769
770    pub fn t(&self, key: &str) -> String {
771        self.strings
772            .get(&self.current_language)
773            .and_then(|lang_map| lang_map.get(key))
774            .cloned()
775            .unwrap_or_else(|| {
776                // Fallback to English
777                self.strings
778                    .get(&Language::English)
779                    .and_then(|lang_map| lang_map.get(key))
780                    .cloned()
781                    .unwrap_or_else(|| key.to_string())
782            })
783    }
784}
785
786#[cfg(test)]
787mod tests {
788    use super::*;
789
790    #[test]
791    fn test_english_translation() {
792        let localizer = Localizer::new();
793        assert_eq!(localizer.t("library"), "Library");
794        assert_eq!(localizer.t("install"), "Install");
795    }
796
797    #[test]
798    fn test_italian_translation() {
799        let mut localizer = Localizer::new();
800        localizer.set_language(Language::Italian);
801        assert_eq!(localizer.t("library"), "Libreria");
802        assert_eq!(localizer.t("install"), "Installa");
803    }
804
805    #[test]
806    fn test_french_translation() {
807        let mut localizer = Localizer::new();
808        localizer.set_language(Language::French);
809        assert_eq!(localizer.t("library"), "Bibliothèque");
810        assert_eq!(localizer.t("launch"), "Lancer");
811    }
812
813    #[test]
814    fn test_german_translation() {
815        let mut localizer = Localizer::new();
816        localizer.set_language(Language::German);
817        assert_eq!(localizer.t("library"), "Bibliothek");
818        assert_eq!(localizer.t("launch"), "Starten");
819    }
820
821    #[test]
822    fn test_spanish_translation() {
823        let mut localizer = Localizer::new();
824        localizer.set_language(Language::Spanish);
825        assert_eq!(localizer.t("library"), "Biblioteca");
826        assert_eq!(localizer.t("launch"), "Iniciar");
827    }
828
829    #[test]
830    fn test_all_languages() {
831        let languages = Language::all();
832        assert_eq!(languages.len(), 5);
833        assert!(languages.contains(&Language::English));
834        assert!(languages.contains(&Language::Italian));
835        assert!(languages.contains(&Language::French));
836        assert!(languages.contains(&Language::German));
837        assert!(languages.contains(&Language::Spanish));
838    }
839
840    #[test]
841    fn test_language_codes() {
842        assert_eq!(Language::English.code(), "en");
843        assert_eq!(Language::Italian.code(), "it");
844        assert_eq!(Language::French.code(), "fr");
845        assert_eq!(Language::German.code(), "de");
846        assert_eq!(Language::Spanish.code(), "es");
847    }
848
849    #[test]
850    fn test_language_names() {
851        assert_eq!(Language::English.name(), "English");
852        assert_eq!(Language::Italian.name(), "Italiano");
853        assert_eq!(Language::French.name(), "Français");
854        assert_eq!(Language::German.name(), "Deutsch");
855        assert_eq!(Language::Spanish.name(), "Español");
856    }
857
858    #[test]
859    fn test_fallback_to_english() {
860        let mut localizer = Localizer::new();
861        localizer.set_language(Language::Italian);
862        // Test with a key that doesn't exist
863        assert_eq!(localizer.t("nonexistent_key"), "nonexistent_key");
864    }
865}