From b5098662fc03c33b6bb137002cf1076e23ef32dd Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Mon, 1 Jul 2024 10:21:42 -0500 Subject: [PATCH 1/9] cleanup: Remove json file --- src/HostApplication/appsettings.Development.json | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 src/HostApplication/appsettings.Development.json diff --git a/src/HostApplication/appsettings.Development.json b/src/HostApplication/appsettings.Development.json deleted file mode 100644 index 7d7d7f5d..00000000 --- a/src/HostApplication/appsettings.Development.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Debug", - "System": "Information", - "Microsoft": "Information" - } - } -} \ No newline at end of file From f1f8fcce9923f8477f02f05fd9e42bb65b590c62 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Mon, 1 Jul 2024 10:22:14 -0500 Subject: [PATCH 2/9] refactor: Reduce code width --- src/HostApplication/Extensions/AuthenticationJwtBearer.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/HostApplication/Extensions/AuthenticationJwtBearer.cs b/src/HostApplication/Extensions/AuthenticationJwtBearer.cs index 7b0c1c3e..e0bcf598 100644 --- a/src/HostApplication/Extensions/AuthenticationJwtBearer.cs +++ b/src/HostApplication/Extensions/AuthenticationJwtBearer.cs @@ -2,7 +2,9 @@ public static class AuthenticationJwtBearer { - public static IServiceCollection AddAuthenticationJwtBearer(this IServiceCollection services, AppSettings settings) + public static IServiceCollection AddAuthenticationJwtBearer( + this IServiceCollection services, + AppSettings settings) { services.AddAuthentication(options => { From 01d16a40089971f9d453b884feff201e48d1993f Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Mon, 1 Jul 2024 10:23:45 -0500 Subject: [PATCH 3/9] chore: Add appsettings.json to the solution file --- DentallApp.sln | 1 + 1 file changed, 1 insertion(+) diff --git a/DentallApp.sln b/DentallApp.sln index 62818c68..49cc5172 100644 --- a/DentallApp.sln +++ b/DentallApp.sln @@ -42,6 +42,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Elements", "Soluti .env.example = .env.example tests\IntegrationTests\.env.test = tests\IntegrationTests\.env.test tests\IntegrationTests\.env.test.example = tests\IntegrationTests\.env.test.example + src\HostApplication\appsettings.json = src\HostApplication\appsettings.json Directory.Build.props = Directory.Build.props Directory.Packages.props = Directory.Packages.props EndProjectSection From ba32ab3896d5e616d823b0c44cc0d29a011c14d2 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Mon, 1 Jul 2024 10:24:26 -0500 Subject: [PATCH 4/9] chore: Update sample file --- .env.example | 1 - 1 file changed, 1 deletion(-) diff --git a/.env.example b/.env.example index 7a240d97..55fe0762 100644 --- a/.env.example +++ b/.env.example @@ -6,7 +6,6 @@ FRONTEND_APP_BASE_URL=http://localhost:80/ MAX_DAYS_IN_CALENDAR=60 BUSINESS_NAME=World Dental CO DENTAL_SERVICES_IMAGES_PATH=/app/dental_services -LANGUAGE=es PLUGINS=" Plugin.ChatBot.dll Plugin.AppointmentReminders.dll From 33763f0010f77361f31edf9bfcb3d0d49d291cfd Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Mon, 1 Jul 2024 10:25:07 -0500 Subject: [PATCH 5/9] Update global usings --- src/HostApplication/GlobalUsings.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/HostApplication/GlobalUsings.cs b/src/HostApplication/GlobalUsings.cs index d94d36ca..da43772e 100644 --- a/src/HostApplication/GlobalUsings.cs +++ b/src/HostApplication/GlobalUsings.cs @@ -16,11 +16,13 @@ global using DentallApp.Shared.Configuration; global using System.Reflection; +global using System.Globalization; global using System.Net; global using System.Text; global using System.Text.Encodings.Web; global using System.Text.Json.Serialization; +global using Microsoft.AspNetCore.Localization; global using Microsoft.AspNetCore.Mvc.ApplicationParts; global using Microsoft.AspNetCore.Authentication; global using Microsoft.AspNetCore.Authentication.JwtBearer; From f0d927426d35cae713c933c87193ef15346e7028 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Mon, 1 Jul 2024 10:29:30 -0500 Subject: [PATCH 6/9] feat: Implement a strategy to select the language for each request --- .../Extensions/LanguageExtensions.cs | 26 +++++++++++++++++++ src/HostApplication/Program.cs | 4 +-- src/HostApplication/appsettings.json | 13 +++++++--- src/Shared/Configuration/AppSettings.cs | 1 - 4 files changed, 37 insertions(+), 7 deletions(-) create mode 100644 src/HostApplication/Extensions/LanguageExtensions.cs diff --git a/src/HostApplication/Extensions/LanguageExtensions.cs b/src/HostApplication/Extensions/LanguageExtensions.cs new file mode 100644 index 00000000..c929d8c9 --- /dev/null +++ b/src/HostApplication/Extensions/LanguageExtensions.cs @@ -0,0 +1,26 @@ +namespace DentallApp.HostApplication.Extensions; + +public static class LanguageExtensions +{ + public static IServiceCollection ConfigureLanguages( + this IServiceCollection services, + IConfiguration configuration) + { + services.Configure(options => + { + var languages = configuration + .GetRequiredSection("Languages") + .Get() ?? []; + + List supportedCultures = []; + foreach(var language in languages) + supportedCultures.Add(new CultureInfo(language)); + + var defaultLanguage = configuration.GetValue("DefaultLanguage"); + options.DefaultRequestCulture = new RequestCulture(defaultLanguage); + options.SupportedCultures = supportedCultures; + options.SupportedUICultures = supportedCultures; + }); + return services; + } +} diff --git a/src/HostApplication/Program.cs b/src/HostApplication/Program.cs index 1bfcadae..f702156d 100644 --- a/src/HostApplication/Program.cs +++ b/src/HostApplication/Program.cs @@ -25,6 +25,7 @@ builder.Services.AddSwagger(); builder.Services.AddAuthenticationJwtBearer(appSettings); builder.Services.AddValidators(); +builder.Services.ConfigureLanguages(builder.Configuration); builder.Services .AddExceptionHandler() @@ -44,8 +45,7 @@ app.UseExceptionHandler("/"); } -app.UseRequestLocalization(appSettings.Language); - +app.UseRequestLocalization(); app.UseWebSockets() .UsePathBase(new PathString("/api")) .UseRouting() diff --git a/src/HostApplication/appsettings.json b/src/HostApplication/appsettings.json index 6fb79de1..eac9b113 100644 --- a/src/HostApplication/appsettings.json +++ b/src/HostApplication/appsettings.json @@ -1,6 +1,11 @@ { - "MicrosoftAppType": "", - "MicrosoftAppId": "", - "MicrosoftAppPassword": "", - "MicrosoftAppTenantId": "" + "MicrosoftAppType": "", + "MicrosoftAppId": "", + "MicrosoftAppPassword": "", + "MicrosoftAppTenantId": "", + "DefaultLanguage": "es", + "Languages": [ + "es", + "en" + ] } \ No newline at end of file diff --git a/src/Shared/Configuration/AppSettings.cs b/src/Shared/Configuration/AppSettings.cs index 17c6c223..edb260c7 100644 --- a/src/Shared/Configuration/AppSettings.cs +++ b/src/Shared/Configuration/AppSettings.cs @@ -7,7 +7,6 @@ public class AppSettings { public string BusinessName { get; set; } = string.Empty; public string DentalServicesImagesPath { get; set; } = string.Empty; - public string Language { get; set; } = string.Empty; public string AccessTokenKey { get; set; } = string.Empty; public double AccessTokenExpires { get; set; } From d227f3e77f5981867c567cebaf51f484fdf186ae Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Mon, 1 Jul 2024 11:49:19 -0500 Subject: [PATCH 7/9] Update global usings --- src/HostApplication/GlobalUsings.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/HostApplication/GlobalUsings.cs b/src/HostApplication/GlobalUsings.cs index da43772e..3f97621b 100644 --- a/src/HostApplication/GlobalUsings.cs +++ b/src/HostApplication/GlobalUsings.cs @@ -33,6 +33,8 @@ global using Microsoft.Extensions.Options; global using Microsoft.Extensions.DependencyInjection.Extensions; global using Microsoft.OpenApi.Models; +global using Microsoft.OpenApi.Any; +global using Swashbuckle.AspNetCore.SwaggerGen; global using EntityFramework.Exceptions.Common; global using DotEnv.Core; From 6d7b35e5364287963b39ce3b33ce12a9d60a12df Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Mon, 1 Jul 2024 11:51:07 -0500 Subject: [PATCH 8/9] refactor: Add methods such as GetLanguages and GetDefaultLanguage --- .../Extensions/LanguageExtensions.cs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/HostApplication/Extensions/LanguageExtensions.cs b/src/HostApplication/Extensions/LanguageExtensions.cs index c929d8c9..65f34454 100644 --- a/src/HostApplication/Extensions/LanguageExtensions.cs +++ b/src/HostApplication/Extensions/LanguageExtensions.cs @@ -3,24 +3,29 @@ public static class LanguageExtensions { public static IServiceCollection ConfigureLanguages( - this IServiceCollection services, + this IServiceCollection services, IConfiguration configuration) { services.Configure(options => { - var languages = configuration - .GetRequiredSection("Languages") - .Get() ?? []; - List supportedCultures = []; - foreach(var language in languages) + var languages = configuration.GetLanguages(); + foreach (var language in languages) supportedCultures.Add(new CultureInfo(language)); - var defaultLanguage = configuration.GetValue("DefaultLanguage"); + var defaultLanguage = configuration.GetDefaultLanguage(); options.DefaultRequestCulture = new RequestCulture(defaultLanguage); options.SupportedCultures = supportedCultures; options.SupportedUICultures = supportedCultures; }); return services; } + + public static string[] GetLanguages(this IConfiguration configuration) + => configuration + .GetRequiredSection("Languages") + .Get() ?? []; + + public static string GetDefaultLanguage(this IConfiguration configuration) + => configuration.GetValue("DefaultLanguage") ?? "es"; } From a967325db46e8de2b799a5ca2ceb3ba86b23ddb8 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Mon, 1 Jul 2024 11:54:59 -0500 Subject: [PATCH 9/9] feat: Integrate 'Accept-Language' parameter in all endpoints from Swagger UI --- src/HostApplication/Extensions/SwaggerGen.cs | 32 ++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/HostApplication/Extensions/SwaggerGen.cs b/src/HostApplication/Extensions/SwaggerGen.cs index 43889de2..dcaa358b 100644 --- a/src/HostApplication/Extensions/SwaggerGen.cs +++ b/src/HostApplication/Extensions/SwaggerGen.cs @@ -5,7 +5,8 @@ public static class SwaggerGen public static IServiceCollection AddSwagger(this IServiceCollection services) { services.AddSwaggerGen(options => - { + { + options.OperationFilter(); options.EnableAnnotations(); options.SwaggerDoc("v1", new OpenApiInfo { Title = "DentallApi", Version = "v1" }); options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme @@ -27,7 +28,7 @@ public static IServiceCollection AddSwagger(this IServiceCollection services) Id = "Bearer" } }, - new string[] { } + Array.Empty() } }); var coreAssemblyName = typeof(GetDependentsByCurrentUserIdUseCase).Assembly.GetName().Name; @@ -44,4 +45,31 @@ public static IServiceCollection AddSwagger(this IServiceCollection services) }); return services; } + + private class AcceptLanguageHeaderParameter(IConfiguration configuration) : IOperationFilter + { + public void Apply(OpenApiOperation operation, OperationFilterContext context) + { + operation.Parameters ??= []; + var languageOptions = new List(); + var languages = configuration.GetLanguages(); + var defaultLanguage = configuration.GetDefaultLanguage(); + foreach (var language in languages) + languageOptions.Add(new OpenApiString(language)); + + operation.Parameters.Add(new OpenApiParameter + { + Name = "Accept-Language", + Description = "Language preference for the response.", + In = ParameterLocation.Header, + Required = false, + Schema = new OpenApiSchema + { + Type = "string", + Default = new OpenApiString(defaultLanguage), + Enum = languageOptions + } + }); + } + } }