using System.Net.Http.Json; using Microsoft.JSInterop; namespace TuringMachine.Client.Services; public record LanguageInfo(string Code, string DisplayName, string FlagIcon); public class LocalizationService { private readonly HttpClient _http; private readonly IJSRuntime _js; private Dictionary _translations = new(); public static readonly List AvailableLanguages = new() { new("en-US", "English", "img/flags/us.svg"), new("ko-KR", "한국어", "img/flags/kr.svg") }; public string CurrentLanguage { get; private set; } = "en-US"; public LanguageInfo CurrentLanguageInfo => AvailableLanguages.Find(l => l.Code == CurrentLanguage) ?? AvailableLanguages[0]; public event Action? OnLanguageChanged; public string this[string key] => _translations.TryGetValue(key, out var value) ? value : key; public string this[string key, params object[] args] { get { var template = this[key]; try { return string.Format(template, args); } catch { return template; } } } public LocalizationService(HttpClient http, IJSRuntime js) { _http = http; _js = js; } public async Task InitializeAsync() { try { var saved = await _js.InvokeAsync("localStorage.getItem", "lang"); CurrentLanguage = string.IsNullOrEmpty(saved) ? "en-US" : saved; } catch { CurrentLanguage = "en-US"; } await LoadTranslationsAsync(CurrentLanguage); } public async Task SetLanguageAsync(string lang) { if (lang == CurrentLanguage) return; CurrentLanguage = lang; await LoadTranslationsAsync(lang); try { await _js.InvokeVoidAsync("localStorage.setItem", "lang", lang); await _js.InvokeVoidAsync("setDocumentTitle", this["app.title"]); } catch { } OnLanguageChanged?.Invoke(); } private async Task LoadTranslationsAsync(string lang) { try { var dict = await _http.GetFromJsonAsync>($"i18n/{lang}.json"); _translations = dict ?? new(); } catch { _translations = new(); } } }