Feature: Implement translation service #1

Merged
Egamorf merged 2 commits from feature/implement-translation-service into main 2025-02-17 22:12:56 +01:00
13 changed files with 81 additions and 68 deletions
Showing only changes of commit fc7cce4ce6 - Show all commits

23
.gitignore vendored
View File

@@ -414,3 +414,26 @@ FodyWeavers.xsd
# JetBrains Rider # JetBrains Rider
*.sln.iml *.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

View File

@@ -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.");
}

View File

@@ -7,7 +7,7 @@
<# <#
var path = Path.GetDirectoryName(Host.TemplateFile); 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); var json = File.ReadAllText(localPath);
@@ -121,8 +121,8 @@
// Generate the class // Generate the class
#> #>
using System; namespace GameIdeas.Resources;
namespace ArgosV2.Resources;
public class Translations (TranslationService translationService) public class Translations (TranslationService translationService)
{ {
<# <#

View File

@@ -1,7 +1,7 @@
using System.Globalization; using System.Globalization;
using System.Text.Json; using System.Text.Json;
namespace ArgosV2.Resources; namespace GameIdeas.Resources;
public class TranslationService public class TranslationService
{ {

View File

@@ -1,16 +1,13 @@
using ArgosV2.AppInsight.Logging;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Abstractions;
namespace ArgosV2.Server.WebAPI.Controllers; namespace GameIdeas.WebAPI.Controllers;
[Route("api/[controller]")]
[ApiController] [ApiController]
public class TranslationsController (ITelemetryService telemetryClient) : ControllerBase [Route("api/[controller]")]
public class TranslationsController (ILogger<TranslationsController> Logger) : ControllerBase
{ {
[Authorize] [HttpGet]
[HttpGet]
public async Task<IActionResult> GetTranslations() public async Task<IActionResult> GetTranslations()
{ {
var dictionary = new Dictionary<string, string>(); var dictionary = new Dictionary<string, string>();
@@ -31,7 +28,7 @@ public class TranslationsController (ITelemetryService telemetryClient) : Contro
} }
catch(Exception ex) catch(Exception ex)
{ {
telemetryClient.TrackException<TranslationsController>(ex); Logger.LogError(ex, "Internal translations error");
} }
return Ok(dictionary); return Ok(dictionary);

View File

@@ -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<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecast> 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();
}
}
}

View File

@@ -1,3 +1,3 @@
{ {
"GamesIdeas": "Game Ideas"
} }

View File

@@ -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 Accept: application/json
### ###

View File

@@ -7,15 +7,15 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Content Remove="Files\GameIdeas.fr.json" /> <EmbeddedResource Include="Files\GameIdeas.fr.json" />
</ItemGroup>
<ItemGroup>
<Compile Include="Files\GameIdeas.fr.json" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.0" /> <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\GameIdeas.Resources\GameIdeas.Resources.csproj" />
</ItemGroup>
</Project> </Project>

View File

@@ -1,3 +1,6 @@
using GameIdeas.Resources;
using System.Resources;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
// Add services to the container. // Add services to the container.
@@ -6,6 +9,9 @@ builder.Services.AddControllers();
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi // Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi(); builder.Services.AddOpenApi();
builder.Services.AddSingleton<TranslationService>();
builder.Services.AddSingleton<Translations>();
var app = builder.Build(); var app = builder.Build();
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.
@@ -14,6 +20,21 @@ if (app.Environment.IsDevelopment())
app.MapOpenApi(); app.MapOpenApi();
} }
var filesDirectory = Path.Combine(Directory.GetCurrentDirectory(), "Files");
var translationFiles = Directory.GetFiles(filesDirectory, "*.json");
var dictionary = new Dictionary<string, string>();
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<TranslationService>().Initialize(dictionary);
var resourcesKey = app.Services.GetRequiredService<Translations>();
ResourcesKey.Initialize(resourcesKey);
app.UseAuthorization(); app.UseAuthorization();
app.MapControllers(); app.MapControllers();

View File

@@ -5,7 +5,7 @@
"commandName": "Project", "commandName": "Project",
"dotnetRunMessages": true, "dotnetRunMessages": true,
"launchBrowser": false, "launchBrowser": false,
"applicationUrl": "http://localhost:5190", "applicationUrl": "http://localhost:8000",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} }

View File

@@ -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; }
}
}

0
workflows/build.yaml Normal file
View File