From fc7cce4ce610b72a77d17d1a0a9ea8cbc336df85 Mon Sep 17 00:00:00 2001 From: Maxime Adler Date: Mon, 17 Feb 2025 13:49:01 +0100 Subject: [PATCH 1/2] Add translation service for web api --- .gitignore | 23 +++++++++++++ .../CreateStaticResourceKey.cs | 18 ++++++++++ .../CreateStaticResourceKey.tt | 6 ++-- .../GameIdeas.Resources/TranslationService.cs | 2 +- .../Controllers/TranslationsController.cs | 15 ++++----- .../Controllers/WeatherForecastController.cs | 33 ------------------- .../GameIdeas.WebAPI/Files/GameIdeas.fr.json | 2 +- .../GameIdeas.WebAPI/GameIdeas.API.http | 4 +-- .../GameIdeas.WebAPI/GameIdeas.WebAPI.csproj | 10 +++--- .../Server/GameIdeas.WebAPI/Program.cs | 21 ++++++++++++ .../Properties/launchSettings.json | 2 +- .../GameIdeas.WebAPI/WeatherForecast.cs | 13 -------- workflows/build.yaml | 0 13 files changed, 81 insertions(+), 68 deletions(-) delete mode 100644 src/GameIdeas/Server/GameIdeas.WebAPI/Controllers/WeatherForecastController.cs delete mode 100644 src/GameIdeas/Server/GameIdeas.WebAPI/WeatherForecast.cs create mode 100644 workflows/build.yaml diff --git a/.gitignore b/.gitignore index 77575d5..2e36d2a 100644 --- a/.gitignore +++ b/.gitignore @@ -414,3 +414,26 @@ FodyWeavers.xsd # JetBrains Rider *.sln.iml +# Created by https://www.toptal.com/developers/gitignore/api/visualstudiocode +# Edit at https://www.toptal.com/developers/gitignore?templates=visualstudiocode + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history +.ionide + +# End of https://www.toptal.com/developers/gitignore/api/visualstudiocode \ No newline at end of file diff --git a/src/GameIdeas/GameIdeas.Resources/CreateStaticResourceKey.cs b/src/GameIdeas/GameIdeas.Resources/CreateStaticResourceKey.cs index 8b13789..d1c2bdd 100644 --- a/src/GameIdeas/GameIdeas.Resources/CreateStaticResourceKey.cs +++ b/src/GameIdeas/GameIdeas.Resources/CreateStaticResourceKey.cs @@ -1 +1,19 @@ +namespace GameIdeas.Resources; + +public class Translations (TranslationService translationService) +{ + public string GamesIdeas => translationService.Translate(nameof(GamesIdeas)); +} + +public static class ResourcesKey +{ + private static Translations? _instance; + + public static void Initialize(Translations translations) + { + _instance = translations; + } + + public static string GamesIdeas => _instance?.GamesIdeas ?? throw new InvalidOperationException("ResourcesKey.GamesIdeas is not initialized."); +} \ No newline at end of file diff --git a/src/GameIdeas/GameIdeas.Resources/CreateStaticResourceKey.tt b/src/GameIdeas/GameIdeas.Resources/CreateStaticResourceKey.tt index 0c818ae..3840c6e 100644 --- a/src/GameIdeas/GameIdeas.Resources/CreateStaticResourceKey.tt +++ b/src/GameIdeas/GameIdeas.Resources/CreateStaticResourceKey.tt @@ -7,7 +7,7 @@ <# var path = Path.GetDirectoryName(Host.TemplateFile); - var localPath = Host.ResolvePath(Path.Combine(path,"../../Server/GameIdeas.API/Files/GameIdeas.fr.json")); + var localPath = Host.ResolvePath(Path.Combine(path,"../../GameIdeas/Server/GameIdeas.WebAPI/Files/GameIdeas.fr.json")); var json = File.ReadAllText(localPath); @@ -121,8 +121,8 @@ // Generate the class #> -using System; -namespace ArgosV2.Resources; +namespace GameIdeas.Resources; + public class Translations (TranslationService translationService) { <# diff --git a/src/GameIdeas/GameIdeas.Resources/TranslationService.cs b/src/GameIdeas/GameIdeas.Resources/TranslationService.cs index 04e35da..8fe81fd 100644 --- a/src/GameIdeas/GameIdeas.Resources/TranslationService.cs +++ b/src/GameIdeas/GameIdeas.Resources/TranslationService.cs @@ -1,7 +1,7 @@ using System.Globalization; using System.Text.Json; -namespace ArgosV2.Resources; +namespace GameIdeas.Resources; public class TranslationService { diff --git a/src/GameIdeas/Server/GameIdeas.WebAPI/Controllers/TranslationsController.cs b/src/GameIdeas/Server/GameIdeas.WebAPI/Controllers/TranslationsController.cs index 9dbd2e0..4fdabc4 100644 --- a/src/GameIdeas/Server/GameIdeas.WebAPI/Controllers/TranslationsController.cs +++ b/src/GameIdeas/Server/GameIdeas.WebAPI/Controllers/TranslationsController.cs @@ -1,16 +1,13 @@ -using ArgosV2.AppInsight.Logging; -using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -using Microsoft.IdentityModel.Abstractions; -namespace ArgosV2.Server.WebAPI.Controllers; +namespace GameIdeas.WebAPI.Controllers; -[Route("api/[controller]")] [ApiController] -public class TranslationsController (ITelemetryService telemetryClient) : ControllerBase +[Route("api/[controller]")] + +public class TranslationsController (ILogger Logger) : ControllerBase { - [Authorize] - [HttpGet] + [HttpGet] public async Task GetTranslations() { var dictionary = new Dictionary(); @@ -31,7 +28,7 @@ public class TranslationsController (ITelemetryService telemetryClient) : Contro } catch(Exception ex) { - telemetryClient.TrackException(ex); + Logger.LogError(ex, "Internal translations error"); } return Ok(dictionary); diff --git a/src/GameIdeas/Server/GameIdeas.WebAPI/Controllers/WeatherForecastController.cs b/src/GameIdeas/Server/GameIdeas.WebAPI/Controllers/WeatherForecastController.cs deleted file mode 100644 index 078c26d..0000000 --- a/src/GameIdeas/Server/GameIdeas.WebAPI/Controllers/WeatherForecastController.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace GameIdeas.API.Controllers -{ - [ApiController] - [Route("[controller]")] - public class WeatherForecastController : ControllerBase - { - private static readonly string[] Summaries = new[] - { - "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" - }; - - private readonly ILogger _logger; - - public WeatherForecastController(ILogger logger) - { - _logger = logger; - } - - [HttpGet(Name = "GetWeatherForecast")] - public IEnumerable Get() - { - return Enumerable.Range(1, 5).Select(index => new WeatherForecast - { - Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)), - TemperatureC = Random.Shared.Next(-20, 55), - Summary = Summaries[Random.Shared.Next(Summaries.Length)] - }) - .ToArray(); - } - } -} diff --git a/src/GameIdeas/Server/GameIdeas.WebAPI/Files/GameIdeas.fr.json b/src/GameIdeas/Server/GameIdeas.WebAPI/Files/GameIdeas.fr.json index 29091fa..83fbcd7 100644 --- a/src/GameIdeas/Server/GameIdeas.WebAPI/Files/GameIdeas.fr.json +++ b/src/GameIdeas/Server/GameIdeas.WebAPI/Files/GameIdeas.fr.json @@ -1,3 +1,3 @@ { - + "GamesIdeas": "Game Ideas" } \ No newline at end of file diff --git a/src/GameIdeas/Server/GameIdeas.WebAPI/GameIdeas.API.http b/src/GameIdeas/Server/GameIdeas.WebAPI/GameIdeas.API.http index 687eebb..8b29540 100644 --- a/src/GameIdeas/Server/GameIdeas.WebAPI/GameIdeas.API.http +++ b/src/GameIdeas/Server/GameIdeas.WebAPI/GameIdeas.API.http @@ -1,6 +1,6 @@ -@GameIdeas.API_HostAddress = http://localhost:5190 +@GameIdeas.API_HostAddress = http://localhost:8000 -GET {{GameIdeas.API_HostAddress}}/weatherforecast/ +GET {{GameIdeas.API_HostAddress}}/translations Accept: application/json ### diff --git a/src/GameIdeas/Server/GameIdeas.WebAPI/GameIdeas.WebAPI.csproj b/src/GameIdeas/Server/GameIdeas.WebAPI/GameIdeas.WebAPI.csproj index 7e05fd7..ef7a3c8 100644 --- a/src/GameIdeas/Server/GameIdeas.WebAPI/GameIdeas.WebAPI.csproj +++ b/src/GameIdeas/Server/GameIdeas.WebAPI/GameIdeas.WebAPI.csproj @@ -7,15 +7,15 @@ - - - - - + + + + + diff --git a/src/GameIdeas/Server/GameIdeas.WebAPI/Program.cs b/src/GameIdeas/Server/GameIdeas.WebAPI/Program.cs index 0989786..325080b 100644 --- a/src/GameIdeas/Server/GameIdeas.WebAPI/Program.cs +++ b/src/GameIdeas/Server/GameIdeas.WebAPI/Program.cs @@ -1,3 +1,6 @@ +using GameIdeas.Resources; +using System.Resources; + var builder = WebApplication.CreateBuilder(args); // Add services to the container. @@ -6,6 +9,9 @@ builder.Services.AddControllers(); // Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi builder.Services.AddOpenApi(); +builder.Services.AddSingleton(); +builder.Services.AddSingleton(); + var app = builder.Build(); // Configure the HTTP request pipeline. @@ -14,6 +20,21 @@ if (app.Environment.IsDevelopment()) app.MapOpenApi(); } +var filesDirectory = Path.Combine(Directory.GetCurrentDirectory(), "Files"); +var translationFiles = Directory.GetFiles(filesDirectory, "*.json"); +var dictionary = new Dictionary(); +foreach (var file in translationFiles) +{ + var name = file.Split('.'); + var culture = name[^2]; + var content = await File.ReadAllTextAsync(file); + dictionary.Add(culture, content); +} + +app.Services.GetRequiredService().Initialize(dictionary); +var resourcesKey = app.Services.GetRequiredService(); +ResourcesKey.Initialize(resourcesKey); + app.UseAuthorization(); app.MapControllers(); diff --git a/src/GameIdeas/Server/GameIdeas.WebAPI/Properties/launchSettings.json b/src/GameIdeas/Server/GameIdeas.WebAPI/Properties/launchSettings.json index 4218f4b..e33eff1 100644 --- a/src/GameIdeas/Server/GameIdeas.WebAPI/Properties/launchSettings.json +++ b/src/GameIdeas/Server/GameIdeas.WebAPI/Properties/launchSettings.json @@ -5,7 +5,7 @@ "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": false, - "applicationUrl": "http://localhost:5190", + "applicationUrl": "http://localhost:8000", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } diff --git a/src/GameIdeas/Server/GameIdeas.WebAPI/WeatherForecast.cs b/src/GameIdeas/Server/GameIdeas.WebAPI/WeatherForecast.cs deleted file mode 100644 index a90cd84..0000000 --- a/src/GameIdeas/Server/GameIdeas.WebAPI/WeatherForecast.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace GameIdeas.API -{ - public class WeatherForecast - { - public DateOnly Date { get; set; } - - public int TemperatureC { get; set; } - - public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); - - public string? Summary { get; set; } - } -} diff --git a/workflows/build.yaml b/workflows/build.yaml new file mode 100644 index 0000000..e69de29 -- 2.39.5 From 68c56ca05faa94ea73055919a14ce4f0d636c89d Mon Sep 17 00:00:00 2001 From: Maxime Adler Date: Mon, 17 Feb 2025 22:07:34 +0100 Subject: [PATCH 2/2] Add cors policy --- .../GameIdeas.BlazorApp.csproj | 10 +++++-- .../Layout/MainLayout.razor | 1 + .../Layout/MainLayout.razor.cs | 24 +++++++++++++++++ .../Client/GameIdeas.BlazorApp/Program.cs | 21 ++++++++++++--- .../Client/GameIdeas.BlazorApp/_Imports.razor | 4 +-- .../wwwroot/sample-data/weather.json | 27 ------------------- .../Server/GameIdeas.WebAPI/Program.cs | 9 +++++-- 7 files changed, 60 insertions(+), 36 deletions(-) create mode 100644 src/GameIdeas/Client/GameIdeas.BlazorApp/Layout/MainLayout.razor.cs delete mode 100644 src/GameIdeas/Client/GameIdeas.BlazorApp/wwwroot/sample-data/weather.json diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/GameIdeas.BlazorApp.csproj b/src/GameIdeas/Client/GameIdeas.BlazorApp/GameIdeas.BlazorApp.csproj index 2ede3a0..c1da829 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/GameIdeas.BlazorApp.csproj +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/GameIdeas.BlazorApp.csproj @@ -4,11 +4,17 @@ net9.0 enable enable + 5637e3c4-2341-4bdb-85ec-c75faeee9847 - - + + + + + + + diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Layout/MainLayout.razor b/src/GameIdeas/Client/GameIdeas.BlazorApp/Layout/MainLayout.razor index 76eb725..7cd63fe 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Layout/MainLayout.razor +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Layout/MainLayout.razor @@ -1,4 +1,5 @@ @inherits LayoutComponentBase +