using System.Globalization; namespace LMEMappeCatastaliApp.Services; public sealed class AppLocalizationService { public const string LanguagePreferenceKey = "app_language"; public const string MeasurementPreferenceKey = "measurement_system"; private static readonly HashSet SupportedLanguages = new(StringComparer.OrdinalIgnoreCase) { "auto", "it", "en" }; private static readonly HashSet SupportedMeasurementSystems = new(StringComparer.OrdinalIgnoreCase) { "auto", "metric", "imperial" }; private static readonly Dictionary> Strings = new(StringComparer.OrdinalIgnoreCase) { ["it"] = new(StringComparer.Ordinal) { ["settings.localization.title"] = "Lingua e misure", ["settings.language"] = "Lingua", ["settings.language.auto"] = "Automatica", ["settings.language.it"] = "Italiano", ["settings.language.en"] = "English", ["settings.measurements"] = "Sistema di misura", ["settings.measurements.auto"] = "Automatico in base all'area", ["settings.measurements.metric"] = "Metrico", ["settings.measurements.imperial"] = "Imperiale", ["settings.pro.title"] = "Abbonamento Pro", ["settings.pro.status"] = "Stato", ["settings.pro.active"] = "Pro attivo", ["settings.pro.base"] = "Base gratuita", ["settings.pro.offline"] = "Offline: le funzioni Pro restano disponibili durante il periodo di tolleranza senza cancellare i dati.", ["settings.pro.restore"] = "Ripristina acquisti", ["settings.pro.manage"] = "Gestisci abbonamento", ["settings.pro.monthly"] = "Pro mensile", ["settings.pro.yearly"] = "Pro annuale", ["settings.pro.note"] = "Il prodotto LME Pro si configura nella Play Console con piano mensile e annuale.", ["settings.pro.manual.code"] = "Codice licenza manuale", ["settings.pro.manual.help"] = "Incolla il codice cifrato ricevuto. Nome, email e scadenza vengono letti solo dopo la verifica crittografica.", ["settings.pro.manual.activate"] = "Attiva codice", ["settings.pro.manual.remove"] = "Rimuovi licenza", ["settings.pro.manual.expires"] = "Scadenza", ["settings.pro.manual.valid"] = "Licenza manuale valida", ["settings.pro.manual.expired"] = "Licenza manuale scaduta: funzionalita Base attive", ["settings.pro.manual.activated"] = "Licenza manuale attivata.", ["settings.pro.manual.invalid"] = "Codice licenza non valido.", ["settings.pro.manual.removed"] = "Licenza manuale rimossa.", ["menu.quickHelp"] = "Guida rapida", ["menu.map"] = "Mappa", ["menu.search"] = "Cerca localita", ["menu.cadastre"] = "Ricerca catastale", ["menu.data"] = "Dati e disegni", ["menu.projects"] = "Progetti", ["menu.export"] = "Esporta", ["menu.tools"] = "Strumenti avanzati", ["menu.settings"] = "Impostazioni", ["panel.settings.title"] = "Impostazioni", ["panel.settings.eyebrow"] = "Mappa, GPS, Pro e servizi ufficiali", ["measure.area"] = "Misura area", ["measure.distance"] = "Misura distanza", ["measure.circle"] = "Misura cerchio", ["measure.rectangle"] = "Disegna rettangolo", ["measure.poi"] = "Aggiungi POI" }, ["en"] = new(StringComparer.Ordinal) { ["settings.localization.title"] = "Language and units", ["settings.language"] = "Language", ["settings.language.auto"] = "Automatic", ["settings.language.it"] = "Italiano", ["settings.language.en"] = "English", ["settings.measurements"] = "Measurement system", ["settings.measurements.auto"] = "Automatic by region", ["settings.measurements.metric"] = "Metric", ["settings.measurements.imperial"] = "Imperial", ["settings.pro.title"] = "Pro subscription", ["settings.pro.status"] = "Status", ["settings.pro.active"] = "Pro active", ["settings.pro.base"] = "Free base plan", ["settings.pro.offline"] = "Offline: Pro features remain available during the grace period without deleting user data.", ["settings.pro.restore"] = "Restore purchases", ["settings.pro.manage"] = "Manage subscription", ["settings.pro.monthly"] = "Monthly Pro", ["settings.pro.yearly"] = "Yearly Pro", ["settings.pro.note"] = "Create the LME Pro product in Play Console with monthly and yearly base plans.", ["settings.pro.manual.code"] = "Manual license code", ["settings.pro.manual.help"] = "Paste the encrypted code you received. Name, email and expiry are read only after cryptographic verification.", ["settings.pro.manual.activate"] = "Activate code", ["settings.pro.manual.remove"] = "Remove license", ["settings.pro.manual.expires"] = "Expires", ["settings.pro.manual.valid"] = "Manual license valid", ["settings.pro.manual.expired"] = "Manual license expired: Base features active", ["settings.pro.manual.activated"] = "Manual license activated.", ["settings.pro.manual.invalid"] = "Invalid license code.", ["settings.pro.manual.removed"] = "Manual license removed.", ["menu.quickHelp"] = "Quick help", ["menu.map"] = "Map", ["menu.search"] = "Search place", ["menu.cadastre"] = "Cadastral search", ["menu.data"] = "Data and drawings", ["menu.projects"] = "Projects", ["menu.export"] = "Export", ["menu.tools"] = "Advanced tools", ["menu.settings"] = "Settings", ["panel.settings.title"] = "Settings", ["panel.settings.eyebrow"] = "Map, GPS, Pro and official services", ["measure.area"] = "Measure area", ["measure.distance"] = "Measure distance", ["measure.circle"] = "Measure circle", ["measure.rectangle"] = "Draw rectangle", ["measure.poi"] = "Add POI" } }; public string LanguagePreference { get; private set; } = "auto"; public string MeasurementPreference { get; private set; } = "auto"; public CultureInfo Culture => new(ResolveLanguage()); public string MeasurementSystem => MeasurementPreference == "auto" ? ResolveAutomaticMeasurementSystem() : MeasurementPreference; public void Load() { LanguagePreference = NormalizeLanguage(Preferences.Default.Get(LanguagePreferenceKey, "auto")); MeasurementPreference = NormalizeMeasurementSystem(Preferences.Default.Get(MeasurementPreferenceKey, "auto")); } public void SetLanguage(string? language) { LanguagePreference = NormalizeLanguage(language); Preferences.Default.Set(LanguagePreferenceKey, LanguagePreference); ApplyCulture(); } public void SetMeasurementSystem(string? measurementSystem) { MeasurementPreference = NormalizeMeasurementSystem(measurementSystem); Preferences.Default.Set(MeasurementPreferenceKey, MeasurementPreference); } public void ApplyCulture() { var culture = Culture; CultureInfo.DefaultThreadCurrentCulture = culture; CultureInfo.DefaultThreadCurrentUICulture = culture; } public string T(string key) { var language = ResolveLanguage(); if (Strings.TryGetValue(language, out var table) && table.TryGetValue(key, out var value)) { return value; } return Strings["it"].TryGetValue(key, out var fallback) ? fallback : key; } private string ResolveLanguage() { if (LanguagePreference != "auto") { return LanguagePreference; } var twoLetter = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName; return Strings.ContainsKey(twoLetter) ? twoLetter : "en"; } private static string ResolveAutomaticMeasurementSystem() { var region = RegionInfo.CurrentRegion.TwoLetterISORegionName; return region is "US" or "LR" or "MM" ? "imperial" : "metric"; } private static string NormalizeLanguage(string? language) => !string.IsNullOrWhiteSpace(language) && SupportedLanguages.Contains(language) ? language.ToLowerInvariant() : "auto"; private static string NormalizeMeasurementSystem(string? measurementSystem) => !string.IsNullOrWhiteSpace(measurementSystem) && SupportedMeasurementSystems.Contains(measurementSystem) ? measurementSystem.ToLowerInvariant() : "auto"; }