diff --git a/content/strings/en.json b/content/strings/en.json index ea243b9..f6dc3ac 100644 --- a/content/strings/en.json +++ b/content/strings/en.json @@ -27,11 +27,22 @@ "prompt.press_key": "Press any key to continue...", "box.opening": "Opening {0}...", + "box.opened": "{0} opened! (Rarity: {1})", + "box.opened_short": "{0} opened!", + "box.shimmer": "Something shimmers...", "box.found": "You found: {0}!", "box.found_box": "Inside was... another box! {0}!", "box.empty": "The box is empty! How philosophical.", "box.no_boxes": "You have no boxes. How did you manage that?", "box.auto_open": "{0} opens automatically!", + "loot.received": "You received:", + "loot.title": "Loot!", + "loot.name": "Name", + "loot.rarity": "Rarity", + "loot.category": "Category", + "ui.feature_unlocked": "NEW FEATURE UNLOCKED: {0}", + "prompt.what_do": "What do you do?", + "prompt.invalid_choice": "Please enter a number between 1 and {0}.", "box.starter": "Starter Box", "box.starter.desc": "Your first box. The beginning of everything. Or nothing. Probably something though.", diff --git a/content/strings/fr.json b/content/strings/fr.json index 3eeca14..1ad5a63 100644 --- a/content/strings/fr.json +++ b/content/strings/fr.json @@ -27,11 +27,22 @@ "prompt.press_key": "Appuie sur une touche pour continuer...", "box.opening": "Ouverture de {0}...", + "box.opened": "{0} ouverte ! (Rarete : {1})", + "box.opened_short": "{0} ouverte !", + "box.shimmer": "Quelque chose scintille...", "box.found": "Tu as trouve : {0} !", "box.found_box": "A l'interieur il y avait... une autre boite ! {0} !", "box.empty": "La boite est vide ! Philosophique.", "box.no_boxes": "Tu n'as aucune boite. Comment t'as fait ?", "box.auto_open": "{0} s'ouvre automatiquement !", + "loot.received": "Tu as recu :", + "loot.title": "Butin !", + "loot.name": "Nom", + "loot.rarity": "Rarete", + "loot.category": "Categorie", + "ui.feature_unlocked": "NOUVELLE FONCTIONNALITE : {0}", + "prompt.what_do": "Que fais-tu ?", + "prompt.invalid_choice": "Entre un nombre entre 1 et {0}.", "box.starter": "Boite de depart", "box.starter.desc": "Ta premiere boite. Le debut de tout. Ou de rien. Probablement de quelque chose quand meme.", diff --git a/src/OpenTheBox/Program.cs b/src/OpenTheBox/Program.cs index 15ab677..0754a79 100644 --- a/src/OpenTheBox/Program.cs +++ b/src/OpenTheBox/Program.cs @@ -28,7 +28,7 @@ public static class Program _saveManager = new SaveManager(); _loc = new LocalizationManager(Locale.EN); _renderContext = new RenderContext(); - _renderer = RendererFactory.Create(_renderContext); + _renderer = RendererFactory.Create(_renderContext, _loc); await MainMenuLoop(); } @@ -127,7 +127,7 @@ public static class Program ); _simulation = new GameSimulation(_registry); _renderContext = RenderContext.FromGameState(_state); - _renderer = RendererFactory.Create(_renderContext); + _renderer = RendererFactory.Create(_renderContext, _loc); } private static void ChangeLanguage() @@ -141,7 +141,7 @@ public static class Program if (_state != null) _state.CurrentLocale = newLocale; - _renderer = RendererFactory.Create(_renderContext); + _renderer = RendererFactory.Create(_renderContext, _loc); } private static async Task GameLoop() @@ -264,7 +264,7 @@ public static class Program case UIFeatureUnlockedEvent uiEvt: _renderContext.Unlock(uiEvt.Feature); - _renderer = RendererFactory.Create(_renderContext); + _renderer = RendererFactory.Create(_renderContext, _loc); var featureKey = $"meta.{uiEvt.Feature.ToString().ToLower()}"; _renderer.ShowUIFeatureUnlocked( _loc.Get("meta.unlocked", _loc.Get(featureKey))); diff --git a/src/OpenTheBox/Rendering/BasicRenderer.cs b/src/OpenTheBox/Rendering/BasicRenderer.cs index d91b0af..aab87ff 100644 --- a/src/OpenTheBox/Rendering/BasicRenderer.cs +++ b/src/OpenTheBox/Rendering/BasicRenderer.cs @@ -1,4 +1,5 @@ using OpenTheBox.Core; +using OpenTheBox.Localization; namespace OpenTheBox.Rendering; @@ -7,7 +8,7 @@ namespace OpenTheBox.Rendering; /// No colors, no frames, no fancy stuff. This is the "stone age" of the UI, /// deliberately ugly and minimal. /// -public sealed class BasicRenderer : IRenderer +public sealed class BasicRenderer(LocalizationManager loc) : IRenderer { public void ShowMessage(string message) { @@ -21,15 +22,15 @@ public sealed class BasicRenderer : IRenderer public void ShowBoxOpening(string boxName, string rarity) { - Console.WriteLine($"Opening {boxName}..."); + Console.WriteLine(loc.Get("box.opening", boxName)); Console.WriteLine("..."); Console.WriteLine("......"); - Console.WriteLine($"Box opened! (Rarity: {rarity})"); + Console.WriteLine(loc.Get("box.opened", boxName, rarity)); } public void ShowLootReveal(List<(string name, string rarity, string category)> items) { - Console.WriteLine("You received:"); + Console.WriteLine(loc.Get("loot.received")); for (int i = 0; i < items.Count; i++) { var (name, rarity, category) = items[i]; @@ -53,7 +54,7 @@ public sealed class BasicRenderer : IRenderer { return choice - 1; } - Console.WriteLine($"Please enter a number between 1 and {options.Count}."); + Console.WriteLine(loc.Get("prompt.invalid_choice", options.Count)); } } @@ -80,7 +81,7 @@ public sealed class BasicRenderer : IRenderer public int ShowAdventureChoice(List options) { - Console.WriteLine("What do you do?"); + Console.WriteLine(loc.Get("prompt.what_do")); for (int i = 0; i < options.Count; i++) { Console.WriteLine($" {i + 1}. {options[i]}"); @@ -94,14 +95,14 @@ public sealed class BasicRenderer : IRenderer { return choice - 1; } - Console.WriteLine($"Please enter a number between 1 and {options.Count}."); + Console.WriteLine(loc.Get("prompt.invalid_choice", options.Count)); } } public void ShowUIFeatureUnlocked(string featureName) { Console.WriteLine("========================================"); - Console.WriteLine($" NEW FEATURE UNLOCKED: {featureName}"); + Console.WriteLine($" {loc.Get("ui.feature_unlocked", featureName)}"); Console.WriteLine("========================================"); } @@ -112,7 +113,7 @@ public sealed class BasicRenderer : IRenderer public void WaitForKeyPress(string? message = null) { - Console.WriteLine(message ?? "Press any key to continue..."); + Console.WriteLine(message ?? loc.Get("prompt.press_key")); Console.ReadKey(intercept: true); Console.WriteLine(); } diff --git a/src/OpenTheBox/Rendering/RendererFactory.cs b/src/OpenTheBox/Rendering/RendererFactory.cs index 5f5d636..8a3dfa1 100644 --- a/src/OpenTheBox/Rendering/RendererFactory.cs +++ b/src/OpenTheBox/Rendering/RendererFactory.cs @@ -1,3 +1,5 @@ +using OpenTheBox.Localization; + namespace OpenTheBox.Rendering; /// @@ -11,7 +13,7 @@ public static class RendererFactory /// If the context has any Spectre-capable feature unlocked, a /// is returned; otherwise the plain is used. /// - public static IRenderer Create(RenderContext context) + public static IRenderer Create(RenderContext context, LocalizationManager loc) { bool hasAnySpectreFeature = context.HasColors || @@ -29,9 +31,9 @@ public static class RendererFactory if (hasAnySpectreFeature) { - return new SpectreRenderer(context); + return new SpectreRenderer(context, loc); } - return new BasicRenderer(); + return new BasicRenderer(loc); } } diff --git a/src/OpenTheBox/Rendering/SpectreRenderer.cs b/src/OpenTheBox/Rendering/SpectreRenderer.cs index 9f344b8..92a6cac 100644 --- a/src/OpenTheBox/Rendering/SpectreRenderer.cs +++ b/src/OpenTheBox/Rendering/SpectreRenderer.cs @@ -1,6 +1,7 @@ using OpenTheBox.Core; using OpenTheBox.Core.Characters; using OpenTheBox.Core.Enums; +using OpenTheBox.Localization; using OpenTheBox.Rendering.Panels; using Spectre.Console; @@ -48,26 +49,26 @@ public sealed class SpectreRenderer : IRenderer AnsiConsole.Status() .Spinner(Spinner.Known.Star) .SpinnerStyle(new Style(RarityColorValue(rarity))) - .Start($"Opening [bold {color}]{Markup.Escape(boxName)}[/]...", ctx => + .Start(Markup.Escape(_loc.Get("box.opening", boxName)), ctx => { Thread.Sleep(1500); - ctx.Status($"[bold {color}]Something shimmers...[/]"); + ctx.Status($"[bold {color}]{Markup.Escape(_loc.Get("box.shimmer"))}[/]"); Thread.Sleep(1000); }); - AnsiConsole.MarkupLine($"[bold {color}]{Markup.Escape(boxName)}[/] opened!"); + AnsiConsole.MarkupLine($"[bold {color}]{Markup.Escape(_loc.Get("box.opened_short", boxName))}[/]"); } else if (_context.HasColors) { string color = RarityColor(rarity); - AnsiConsole.MarkupLine($"Opening [bold {color}]{Markup.Escape(boxName)}[/]..."); + AnsiConsole.MarkupLine($"[bold {color}]{Markup.Escape(_loc.Get("box.opening", boxName))}[/]"); Thread.Sleep(800); - AnsiConsole.MarkupLine($"[bold {color}]{Markup.Escape(boxName)}[/] opened!"); + AnsiConsole.MarkupLine($"[bold {color}]{Markup.Escape(_loc.Get("box.opened_short", boxName))}[/]"); } else { - Console.WriteLine($"Opening {boxName}..."); + Console.WriteLine(_loc.Get("box.opening", boxName)); Thread.Sleep(500); - Console.WriteLine($"{boxName} opened! (Rarity: {rarity})"); + Console.WriteLine(_loc.Get("box.opened", boxName, rarity)); } } @@ -79,10 +80,10 @@ public sealed class SpectreRenderer : IRenderer { var table = new Table() .Border(TableBorder.Rounded) - .Title("[bold yellow]Loot![/]") - .AddColumn(new TableColumn("[bold]Name[/]").Centered()) - .AddColumn(new TableColumn("[bold]Rarity[/]").Centered()) - .AddColumn(new TableColumn("[bold]Category[/]").Centered()); + .Title($"[bold yellow]{Markup.Escape(_loc.Get("loot.title"))}[/]") + .AddColumn(new TableColumn($"[bold]{Markup.Escape(_loc.Get("loot.name"))}[/]").Centered()) + .AddColumn(new TableColumn($"[bold]{Markup.Escape(_loc.Get("loot.rarity"))}[/]").Centered()) + .AddColumn(new TableColumn($"[bold]{Markup.Escape(_loc.Get("loot.category"))}[/]").Centered()); foreach (var (name, rarity, category) in items) { @@ -97,7 +98,7 @@ public sealed class SpectreRenderer : IRenderer } else if (_context.HasColors) { - AnsiConsole.MarkupLine("[bold yellow]You received:[/]"); + AnsiConsole.MarkupLine($"[bold yellow]{Markup.Escape(_loc.Get("loot.received"))}[/]"); foreach (var (name, rarity, category) in items) { string color = RarityColor(rarity); @@ -106,7 +107,7 @@ public sealed class SpectreRenderer : IRenderer } else { - Console.WriteLine("You received:"); + Console.WriteLine(_loc.Get("loot.received")); foreach (var (name, rarity, category) in items) { Console.WriteLine($" - {name} [{rarity}] ({category})"); @@ -155,13 +156,14 @@ public sealed class SpectreRenderer : IRenderer return choice - 1; } + string errorMsg = _loc.Get("prompt.invalid_choice", options.Count); if (_context.HasColors) { - AnsiConsole.MarkupLine($"[red]Please enter a number between 1 and {options.Count}.[/]"); + AnsiConsole.MarkupLine($"[red]{Markup.Escape(errorMsg)}[/]"); } else { - Console.WriteLine($"Please enter a number between 1 and {options.Count}."); + Console.WriteLine(errorMsg); } } } @@ -222,14 +224,14 @@ public sealed class SpectreRenderer : IRenderer { string selected = AnsiConsole.Prompt( new SelectionPrompt() - .Title("[bold yellow]What do you do?[/]") + .Title($"[bold yellow]{Markup.Escape(_loc.Get("prompt.what_do"))}[/]") .PageSize(10) .AddChoices(options)); return options.IndexOf(selected); } - return ShowSelection("What do you do?", options); + return ShowSelection(_loc.Get("prompt.what_do"), options); } // ── UI feature unlock announcement ────────────────────────────────── @@ -238,14 +240,14 @@ public sealed class SpectreRenderer : IRenderer { if (_context.HasColors) { - AnsiConsole.Write(new Rule($"[bold yellow]NEW FEATURE UNLOCKED[/]").RuleStyle("yellow")); + AnsiConsole.Write(new Rule($"[bold yellow]{Markup.Escape(_loc.Get("ui.feature_unlocked", featureName))}[/]").RuleStyle("yellow")); AnsiConsole.Write(new FigletText(featureName).Color(Color.Yellow).Centered()); AnsiConsole.Write(new Rule().RuleStyle("yellow")); } else { Console.WriteLine("========================================"); - Console.WriteLine($" NEW FEATURE UNLOCKED: {featureName}"); + Console.WriteLine($" {_loc.Get("ui.feature_unlocked", featureName)}"); Console.WriteLine("========================================"); } } @@ -268,13 +270,14 @@ public sealed class SpectreRenderer : IRenderer public void WaitForKeyPress(string? message = null) { + string text = message ?? _loc.Get("prompt.press_key"); if (_context.HasColors) { - AnsiConsole.MarkupLine($"[dim]{Markup.Escape(message ?? "Press any key to continue...")}[/]"); + AnsiConsole.MarkupLine($"[dim]{Markup.Escape(text)}[/]"); } else { - Console.WriteLine(message ?? "Press any key to continue..."); + Console.WriteLine(text); } Console.ReadKey(intercept: true); @@ -290,10 +293,12 @@ public sealed class SpectreRenderer : IRenderer // ── Construction ──────────────────────────────────────────────────── private RenderContext _context; + private readonly LocalizationManager _loc; - public SpectreRenderer(RenderContext context) + public SpectreRenderer(RenderContext context, LocalizationManager loc) { _context = context; + _loc = loc; } ///