From 249482d7a1cc74f0fe0fa2a29524d3c99e1b13ea Mon Sep 17 00:00:00 2001 From: Jasmin Savard Date: Tue, 31 Jan 2023 00:06:58 -0500 Subject: [PATCH 01/40] User Localization settings --- .../Drivers/UserLocalizationDisplayDriver.cs | 61 +++++++++++++++++++ .../Models/UserLocalizationSettings.cs | 9 +++ .../UserLocalizationClaimsProvider.cs | 36 +++++++++++ .../UserLocalizationRequestCultureProvider.cs | 51 ++++++++++++++++ .../Localization/UserLocalizationStartup.cs | 43 +++++++++++++ .../ViewModel/UserLocalizationViewModel.cs | 13 ++++ .../OrchardCore.Users/Manifest.cs | 8 +++ .../Drivers/UserTimeZoneDisplayDriver.cs | 2 +- .../{Startup.cs => UserTimeZoneStartup.cs} | 2 +- .../Views/UserCulture.Edit.cshtml | 12 ++++ 10 files changed, 235 insertions(+), 2 deletions(-) create mode 100644 src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs create mode 100644 src/OrchardCore.Modules/OrchardCore.Users/Localization/Models/UserLocalizationSettings.cs create mode 100644 src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationClaimsProvider.cs create mode 100644 src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs create mode 100644 src/OrchardCore.Modules/OrchardCore.Users/Localization/UserLocalizationStartup.cs create mode 100644 src/OrchardCore.Modules/OrchardCore.Users/Localization/ViewModel/UserLocalizationViewModel.cs rename src/OrchardCore.Modules/OrchardCore.Users/TimeZone/{Startup.cs => UserTimeZoneStartup.cs} (94%) create mode 100644 src/OrchardCore.Modules/OrchardCore.Users/Views/UserCulture.Edit.cshtml diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs new file mode 100644 index 00000000000..8e2a896f400 --- /dev/null +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs @@ -0,0 +1,61 @@ +using System.Globalization; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc.Rendering; +using OrchardCore.DisplayManagement.Entities; +using OrchardCore.DisplayManagement.Handlers; +using OrchardCore.DisplayManagement.ModelBinding; +using OrchardCore.DisplayManagement.Views; +using OrchardCore.Localization; +using OrchardCore.Users.Localization.Models; +using OrchardCore.Users.Localization.ViewModels; +using OrchardCore.Users.Models; + +namespace OrchardCore.Users.Localization.Drivers; + +public class UserLocalizationDisplayDriver : SectionDisplayDriver +{ + private readonly ILocalizationService _localizationService; + private readonly IHttpContextAccessor _httpContextAccessor; + + public UserLocalizationDisplayDriver( + ILocalizationService localizationService, + IHttpContextAccessor httpContextAccessor + ) + { + _localizationService = localizationService; + _httpContextAccessor = httpContextAccessor; + } + + public override Task EditAsync(UserLocalizationSettings section, BuildEditorContext context) + { + return Task.FromResult(Initialize("UserCulture_Edit", async model => + { + var supportedCultures = await _localizationService.GetSupportedCulturesAsync(); + var currentUserCulture = _httpContextAccessor.HttpContext.User.FindFirstValue("culture"); + + model.Culture = section.Culture; + model.SupportedCultures = supportedCultures.Select(culture => + new SelectListItem() + { + Text = CultureInfo.GetCultureInfo(culture).DisplayName + " (" + culture + ")", + Value = culture, + Selected = currentUserCulture == culture + }); + }).Location("Content:2")); + } + + public override async Task UpdateAsync(User model, UserLocalizationSettings section, IUpdateModel updater, BuildEditorContext context) + { + var viewModel = new UserLocalizationViewModel(); + + if (await context.Updater.TryUpdateModelAsync(viewModel, Prefix)) + { + section.Culture = viewModel.Culture; + } + + return await EditAsync(section, context); + } +} diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Models/UserLocalizationSettings.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Models/UserLocalizationSettings.cs new file mode 100644 index 00000000000..6856c3fa386 --- /dev/null +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Models/UserLocalizationSettings.cs @@ -0,0 +1,9 @@ +namespace OrchardCore.Users.Localization.Models; + +/// +/// Provides a model for the IEntity property. +/// +public class UserLocalizationSettings +{ + public string Culture { get; set; } +} diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationClaimsProvider.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationClaimsProvider.cs new file mode 100644 index 00000000000..6d125b8551b --- /dev/null +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationClaimsProvider.cs @@ -0,0 +1,36 @@ +using System.Security.Claims; +using OrchardCore.Users.Localization.Models; +using OrchardCore.Entities; +using OrchardCore.Users; +using OrchardCore.Users.Models; +using OrchardCore.Users.Services; +using System.Threading.Tasks; +using System; + +namespace OrchardCore.Users.Localization.Providers; + +public class UserLocalizationClaimsProvider : IUserClaimsProvider +{ + public Task GenerateAsync(IUser user, ClaimsIdentity claims) + { + ArgumentNullException.ThrowIfNull(user); + ArgumentNullException.ThrowIfNull(claims); + + if (user is not User u) + { + return Task.CompletedTask; + } + + if (u.Has()) + { + var localizationSetting = u.As(); + + if (!String.IsNullOrEmpty(localizationSetting.Culture)) + { + claims.AddClaim(new Claim("culture", localizationSetting.Culture)); + } + } + + return Task.CompletedTask; + } +} diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs new file mode 100644 index 00000000000..98b9ab3c8e9 --- /dev/null +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs @@ -0,0 +1,51 @@ +using System; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Localization; +using Microsoft.Extensions.DependencyInjection; +using OrchardCore.Localization; + +namespace OrchardCore.Users.Localization.Providers; + +public class UserLocalizationRequestCultureProvider : RequestCultureProvider +{ + public override async Task DetermineProviderCultureResult(HttpContext httpContext) + { + ArgumentNullException.ThrowIfNull(httpContext); + + if (httpContext?.User?.Identity?.IsAuthenticated == false) + { + return null; + } + + string userCulture = null; + var claimCulture = httpContext.User.FindFirstValue("culture"); + + if (!String.IsNullOrWhiteSpace(claimCulture)) + { + userCulture = claimCulture; + } + + if (userCulture == null) + { + // No values specified for either so no match + return null; + } + + var localizationService = httpContext.RequestServices.GetService(); + + var supportedCulture = await localizationService.GetSupportedCulturesAsync(); + + // We verify that the userCulture is still a supportedCulture + if (!supportedCulture.Contains(userCulture)) + { + return null; + } + + var requestCulture = new ProviderCultureResult(userCulture); + + return requestCulture; + } +} diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/UserLocalizationStartup.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/UserLocalizationStartup.cs new file mode 100644 index 00000000000..3e7fd9cbdae --- /dev/null +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/UserLocalizationStartup.cs @@ -0,0 +1,43 @@ +using System; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using OrchardCore.DisplayManagement.Handlers; +using OrchardCore.Localization; +using OrchardCore.Modules; +using OrchardCore.Users.Localization.Drivers; +using OrchardCore.Users.Localization.Providers; +using OrchardCore.Users.Models; +using OrchardCore.Users.Services; + +namespace OrchardCore.Users.Localization; + +[Feature("OrchardCore.Users.Localization")] +public class UserLocalizationStartup : StartupBase +{ + public override void Configure(IApplicationBuilder app, IEndpointRouteBuilder routes, IServiceProvider serviceProvider) + { + var localizationService = serviceProvider.GetService(); + + var defaultCulture = localizationService.GetDefaultCultureAsync().GetAwaiter().GetResult(); + var supportedCultures = localizationService.GetSupportedCulturesAsync().GetAwaiter().GetResult(); + + var cultureOptions = serviceProvider.GetService>().Value; + + var requestLocalizationOptions = new OrchardCoreRequestLocalizationOptions(ignoreSystemSettings: cultureOptions.IgnoreSystemSettings) + .SetDefaultCulture(defaultCulture) + .AddSupportedCultures(supportedCultures) + .AddSupportedUICultures(supportedCultures); + + requestLocalizationOptions.RequestCultureProviders.Insert(0, new UserLocalizationRequestCultureProvider()); + + app.UseRequestLocalization(requestLocalizationOptions); + } + + public override void ConfigureServices(IServiceCollection services) + { + services.AddScoped, UserLocalizationDisplayDriver>(); + services.AddScoped(); + } +} diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/ViewModel/UserLocalizationViewModel.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/ViewModel/UserLocalizationViewModel.cs new file mode 100644 index 00000000000..af452081f68 --- /dev/null +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/ViewModel/UserLocalizationViewModel.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; +using Microsoft.AspNetCore.Mvc.ModelBinding; +using Microsoft.AspNetCore.Mvc.Rendering; + +namespace OrchardCore.Users.Localization.ViewModels; + +public class UserLocalizationViewModel +{ + public string Culture { get; set; } + + [BindNever] + public IEnumerable SupportedCultures { get; set; } = new List(); +} diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Manifest.cs b/src/OrchardCore.Modules/OrchardCore.Users/Manifest.cs index 4d135311211..9da627f1eb0 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Manifest.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Manifest.cs @@ -56,6 +56,14 @@ Category = "Settings" )] +[assembly: Feature( + Id = "OrchardCore.Users.Localization", + Name = "User Localization", + Description = "Provides a way to set the culture per user.", + Dependencies = new[] { "OrchardCore.Users", "OrchardCore.Localization" }, + Category = "Settings" +)] + [assembly: Feature( Id = "OrchardCore.Users.CustomUserSettings", Name = "Custom User Settings", diff --git a/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Drivers/UserTimeZoneDisplayDriver.cs b/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Drivers/UserTimeZoneDisplayDriver.cs index 87873c4e287..0bd0ffe6a39 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Drivers/UserTimeZoneDisplayDriver.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Drivers/UserTimeZoneDisplayDriver.cs @@ -24,7 +24,7 @@ public override IDisplayResult Edit(UserTimeZone userTimeZone, BuildEditorContex return Initialize("UserTimeZone_Edit", model => { model.TimeZoneId = userTimeZone.TimeZoneId; - }).Location("Content:2"); + }).Location("Content:3"); } public override async Task UpdateAsync(User user, UserTimeZone userTimeZone, IUpdateModel updater, BuildEditorContext context) diff --git a/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Startup.cs b/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/UserTimeZoneStartup.cs similarity index 94% rename from src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Startup.cs rename to src/OrchardCore.Modules/OrchardCore.Users/TimeZone/UserTimeZoneStartup.cs index c624f88a8fe..024e8c8bffc 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Startup.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/UserTimeZoneStartup.cs @@ -11,7 +11,7 @@ namespace OrchardCore.Users.TimeZone { [Feature("OrchardCore.Users.TimeZone")] - public class Startup : StartupBase + public class UserTimeZoneStartup : StartupBase { public override void Configure(IApplicationBuilder builder, IEndpointRouteBuilder routes, IServiceProvider serviceProvider) { diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Views/UserCulture.Edit.cshtml b/src/OrchardCore.Modules/OrchardCore.Users/Views/UserCulture.Edit.cshtml new file mode 100644 index 00000000000..f5c82d8fc6b --- /dev/null +++ b/src/OrchardCore.Modules/OrchardCore.Users/Views/UserCulture.Edit.cshtml @@ -0,0 +1,12 @@ +@using OrchardCore.Users.Localization.ViewModels +@model UserLocalizationViewModel + + +
+ + + + @T["Determines the default culture used by this user."] +
From 78156fd279d2e6c1e4fe7ccea6fed2e98937d1e4 Mon Sep 17 00:00:00 2001 From: Jasmin Savard Date: Tue, 31 Jan 2023 03:37:09 -0500 Subject: [PATCH 02/40] React to comment --- .../Localization/UserLocalizationStartup.cs | 26 +++---------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/UserLocalizationStartup.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/UserLocalizationStartup.cs index 3e7fd9cbdae..413c5678ae7 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/UserLocalizationStartup.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/UserLocalizationStartup.cs @@ -1,10 +1,6 @@ -using System; using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; using OrchardCore.DisplayManagement.Handlers; -using OrchardCore.Localization; using OrchardCore.Modules; using OrchardCore.Users.Localization.Drivers; using OrchardCore.Users.Localization.Providers; @@ -16,28 +12,12 @@ namespace OrchardCore.Users.Localization; [Feature("OrchardCore.Users.Localization")] public class UserLocalizationStartup : StartupBase { - public override void Configure(IApplicationBuilder app, IEndpointRouteBuilder routes, IServiceProvider serviceProvider) - { - var localizationService = serviceProvider.GetService(); - - var defaultCulture = localizationService.GetDefaultCultureAsync().GetAwaiter().GetResult(); - var supportedCultures = localizationService.GetSupportedCulturesAsync().GetAwaiter().GetResult(); - - var cultureOptions = serviceProvider.GetService>().Value; - - var requestLocalizationOptions = new OrchardCoreRequestLocalizationOptions(ignoreSystemSettings: cultureOptions.IgnoreSystemSettings) - .SetDefaultCulture(defaultCulture) - .AddSupportedCultures(supportedCultures) - .AddSupportedUICultures(supportedCultures); - - requestLocalizationOptions.RequestCultureProviders.Insert(0, new UserLocalizationRequestCultureProvider()); - - app.UseRequestLocalization(requestLocalizationOptions); - } - public override void ConfigureServices(IServiceCollection services) { services.AddScoped, UserLocalizationDisplayDriver>(); services.AddScoped(); + + services.Configure(options => + options.RequestCultureProviders.Insert(0, new UserLocalizationRequestCultureProvider())); } } From b8974b9656a67de6454485fc74f3610eb67bd1e3 Mon Sep 17 00:00:00 2001 From: Jasmin Savard Date: Tue, 31 Jan 2023 04:10:28 -0500 Subject: [PATCH 03/40] Something that works --- src/OrchardCore.Modules/OrchardCore.Localization/Startup.cs | 2 +- .../Providers/UserLocalizationRequestCultureProvider.cs | 2 +- .../OrchardCore.Users/Localization/UserLocalizationStartup.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Localization/Startup.cs b/src/OrchardCore.Modules/OrchardCore.Localization/Startup.cs index 99326bc1d16..f76602cc923 100644 --- a/src/OrchardCore.Modules/OrchardCore.Localization/Startup.cs +++ b/src/OrchardCore.Modules/OrchardCore.Localization/Startup.cs @@ -25,7 +25,7 @@ namespace OrchardCore.Localization /// public class Startup : StartupBase { - public override int ConfigureOrder => -100; + public override int ConfigureOrder => 100; /// public override void ConfigureServices(IServiceCollection services) diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs index 98b9ab3c8e9..d5c44bbfa2a 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs @@ -17,7 +17,7 @@ public override async Task DetermineProviderCultureResult if (httpContext?.User?.Identity?.IsAuthenticated == false) { - return null; + return await NullProviderCultureResult; } string userCulture = null; diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/UserLocalizationStartup.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/UserLocalizationStartup.cs index 413c5678ae7..41c8e8b5376 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/UserLocalizationStartup.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/UserLocalizationStartup.cs @@ -18,6 +18,6 @@ public override void ConfigureServices(IServiceCollection services) services.AddScoped(); services.Configure(options => - options.RequestCultureProviders.Insert(0, new UserLocalizationRequestCultureProvider())); + options.AddInitialRequestCultureProvider(new UserLocalizationRequestCultureProvider())); } } From 4ed3b3b39eeefe0aa79c3cfa9758669f5d1c9145 Mon Sep 17 00:00:00 2001 From: Jasmin Savard Date: Tue, 31 Jan 2023 04:12:11 -0500 Subject: [PATCH 04/40] await NullProviderCultureResult; --- .../Providers/UserLocalizationRequestCultureProvider.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs index d5c44bbfa2a..07bf9a1f654 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs @@ -31,7 +31,7 @@ public override async Task DetermineProviderCultureResult if (userCulture == null) { // No values specified for either so no match - return null; + return await NullProviderCultureResult; } var localizationService = httpContext.RequestServices.GetService(); @@ -41,7 +41,7 @@ public override async Task DetermineProviderCultureResult // We verify that the userCulture is still a supportedCulture if (!supportedCulture.Contains(userCulture)) { - return null; + return await NullProviderCultureResult; } var requestCulture = new ProviderCultureResult(userCulture); From 2b9b92682e0829a4f97b9e8a037d97685143119c Mon Sep 17 00:00:00 2001 From: Jasmin Savard Date: Wed, 1 Feb 2023 15:39:47 -0500 Subject: [PATCH 05/40] return default --- .../Providers/UserLocalizationRequestCultureProvider.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs index 07bf9a1f654..052bb3df152 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs @@ -17,7 +17,7 @@ public override async Task DetermineProviderCultureResult if (httpContext?.User?.Identity?.IsAuthenticated == false) { - return await NullProviderCultureResult; + return default; } string userCulture = null; @@ -31,7 +31,7 @@ public override async Task DetermineProviderCultureResult if (userCulture == null) { // No values specified for either so no match - return await NullProviderCultureResult; + return default; } var localizationService = httpContext.RequestServices.GetService(); @@ -41,7 +41,7 @@ public override async Task DetermineProviderCultureResult // We verify that the userCulture is still a supportedCulture if (!supportedCulture.Contains(userCulture)) { - return await NullProviderCultureResult; + return default; } var requestCulture = new ProviderCultureResult(userCulture); From 42606756a24b4ccd1f8d9f6536787f19989c3ee5 Mon Sep 17 00:00:00 2001 From: Hisham Bin Ateya Date: Fri, 12 Jan 2024 15:52:29 +0300 Subject: [PATCH 06/40] Set the user default culture to the localization default culture if not set --- .../Localization/Drivers/UserLocalizationDisplayDriver.cs | 8 +++++++- .../OrchardCore.Users/Views/UserCulture.Edit.cshtml | 6 ++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs index 8e2a896f400..6a6e88d68c3 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs @@ -33,12 +33,18 @@ public override Task EditAsync(UserLocalizationSettings section, { return Task.FromResult(Initialize("UserCulture_Edit", async model => { + var defaultCulture = await _localizationService.GetDefaultCultureAsync(); var supportedCultures = await _localizationService.GetSupportedCulturesAsync(); var currentUserCulture = _httpContextAccessor.HttpContext.User.FindFirstValue("culture"); + if (currentUserCulture == null) + { + currentUserCulture = defaultCulture; + } + model.Culture = section.Culture; model.SupportedCultures = supportedCultures.Select(culture => - new SelectListItem() + new SelectListItem { Text = CultureInfo.GetCultureInfo(culture).DisplayName + " (" + culture + ")", Value = culture, diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Views/UserCulture.Edit.cshtml b/src/OrchardCore.Modules/OrchardCore.Users/Views/UserCulture.Edit.cshtml index f5c82d8fc6b..a03a6a35525 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Views/UserCulture.Edit.cshtml +++ b/src/OrchardCore.Modules/OrchardCore.Users/Views/UserCulture.Edit.cshtml @@ -3,10 +3,8 @@
- - + + @T["Determines the default culture used by this user."]
From 619834fac309b5b4ff6b5a9c0765d45c28032af2 Mon Sep 17 00:00:00 2001 From: Hisham Bin Ateya Date: Fri, 12 Jan 2024 16:27:37 +0300 Subject: [PATCH 07/40] Set the user default time zone to the site settings default time zone if not set --- .../Drivers/UserTimeZoneDisplayDriver.cs | 17 ++++++++++++++--- .../Views/UserTimeZone.Edit.cshtml | 1 - 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Drivers/UserTimeZoneDisplayDriver.cs b/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Drivers/UserTimeZoneDisplayDriver.cs index 0bd0ffe6a39..2ecf1ba512e 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Drivers/UserTimeZoneDisplayDriver.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Drivers/UserTimeZoneDisplayDriver.cs @@ -3,6 +3,7 @@ using OrchardCore.DisplayManagement.Handlers; using OrchardCore.DisplayManagement.ModelBinding; using OrchardCore.DisplayManagement.Views; +using OrchardCore.Settings; using OrchardCore.Users.Models; using OrchardCore.Users.TimeZone.Models; using OrchardCore.Users.TimeZone.Services; @@ -13,17 +14,27 @@ namespace OrchardCore.Users.TimeZone.Drivers public class UserTimeZoneDisplayDriver : SectionDisplayDriver { private readonly UserTimeZoneService _userTimeZoneService; + private readonly ISiteService _siteService; - public UserTimeZoneDisplayDriver(UserTimeZoneService userTimeZoneService) + public UserTimeZoneDisplayDriver(UserTimeZoneService userTimeZoneService, ISiteService siteService) { _userTimeZoneService = userTimeZoneService; + _siteService = siteService; } public override IDisplayResult Edit(UserTimeZone userTimeZone, BuildEditorContext context) { - return Initialize("UserTimeZone_Edit", model => + return Initialize("UserTimeZone_Edit", async model => { - model.TimeZoneId = userTimeZone.TimeZoneId; + var timeZoneId = userTimeZone.TimeZoneId; + if (timeZoneId == null) + { + var siteSettings = await _siteService.GetSiteSettingsAsync(); + + timeZoneId = siteSettings.TimeZoneId; + } + + model.TimeZoneId = timeZoneId; }).Location("Content:3"); } diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Views/UserTimeZone.Edit.cshtml b/src/OrchardCore.Modules/OrchardCore.Users/Views/UserTimeZone.Edit.cshtml index fd5656eeab8..06dd1509fb2 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Views/UserTimeZone.Edit.cshtml +++ b/src/OrchardCore.Modules/OrchardCore.Users/Views/UserTimeZone.Edit.cshtml @@ -4,7 +4,6 @@
- @foreach (var timeZone in Clock.GetTimeZones()) - { - - } - + @T["Determines the time zone used when displaying and editing dates and times."]
From 7a3879266d480a6d97fd18647930c694c4f97895 Mon Sep 17 00:00:00 2001 From: Hisham Bin Ateya Date: Fri, 12 Jan 2024 21:16:52 +0300 Subject: [PATCH 14/40] Remove extra whitespace --- .../OrchardCore.Users/Views/UserCulture.Edit.cshtml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Views/UserCulture.Edit.cshtml b/src/OrchardCore.Modules/OrchardCore.Users/Views/UserCulture.Edit.cshtml index a03a6a35525..a9337af4b96 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Views/UserCulture.Edit.cshtml +++ b/src/OrchardCore.Modules/OrchardCore.Users/Views/UserCulture.Edit.cshtml @@ -1,7 +1,6 @@ @using OrchardCore.Users.Localization.ViewModels @model UserLocalizationViewModel -
From 245bc8bdcccd0eb5846b7a732962f72e0db592f9 Mon Sep 17 00:00:00 2001 From: Hisham Bin Ateya Date: Mon, 15 Jan 2024 11:21:19 +0300 Subject: [PATCH 15/40] Add release note --- src/docs/releases/1.9.0.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/docs/releases/1.9.0.md b/src/docs/releases/1.9.0.md index 0a3dcf025b5..b9f7700b61b 100644 --- a/src/docs/releases/1.9.0.md +++ b/src/docs/releases/1.9.0.md @@ -22,6 +22,13 @@ Introducing a new "Azure AI Search" module, designed to empower you in the admin Added new extensions to make registering custom deployment step easier - - services.AddDeployment(); - - services.AddDeployment(); - - services.AddDeploymentWithoutSource(); +- services.AddDeployment(); +- services.AddDeployment(); +- services.AddDeploymentWithoutSource(); + +## Users Module + +Added new localization settings that allow the user to set his/her default culture and time zone. + +!!! note + The newly added settings override the current admin localization culture and time zone settings. From a59918801d0ac984bf6fc0b295a9bd8c37d0af78 Mon Sep 17 00:00:00 2001 From: Hisham Bin Ateya Date: Mon, 15 Jan 2024 11:23:48 +0300 Subject: [PATCH 16/40] Fix indentation --- .../Drivers/UserLocalizationDisplayDriver.cs | 12 ++++++------ .../TimeZone/Drivers/UserTimeZoneDisplayDriver.cs | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs index 6a6e88d68c3..abba9509548 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs @@ -44,12 +44,12 @@ public override Task EditAsync(UserLocalizationSettings section, model.Culture = section.Culture; model.SupportedCultures = supportedCultures.Select(culture => - new SelectListItem - { - Text = CultureInfo.GetCultureInfo(culture).DisplayName + " (" + culture + ")", - Value = culture, - Selected = currentUserCulture == culture - }); + new SelectListItem + { + Text = CultureInfo.GetCultureInfo(culture).DisplayName + " (" + culture + ")", + Value = culture, + Selected = currentUserCulture == culture + }); }).Location("Content:2")); } diff --git a/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Drivers/UserTimeZoneDisplayDriver.cs b/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Drivers/UserTimeZoneDisplayDriver.cs index 6eda0477126..2035f913d82 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Drivers/UserTimeZoneDisplayDriver.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Drivers/UserTimeZoneDisplayDriver.cs @@ -41,12 +41,12 @@ public override IDisplayResult Edit(UserTimeZone userTimeZone, BuildEditorContex model.TimeZoneId = timeZoneId; model.TimeZones = _clock.GetTimeZones().Select(tz => - new SelectListItem - { - Text = tz.ToString(), - Value = tz.TimeZoneId, - Selected = tz.TimeZoneId == timeZoneId - }); + new SelectListItem + { + Text = tz.ToString(), + Value = tz.TimeZoneId, + Selected = tz.TimeZoneId == timeZoneId + }); }).Location("Content:3"); } From 376b00a6bc76dcc54ed04ee9465f5d8f6ec698b8 Mon Sep 17 00:00:00 2001 From: Hisham Bin Ateya Date: Mon, 15 Jan 2024 11:48:33 +0300 Subject: [PATCH 17/40] Refactoring --- .../Providers/UserLocalizationClaimsProvider.cs | 6 +++--- .../UserLocalizationRequestCultureProvider.cs | 10 ++-------- .../TimeZone/Drivers/UserTimeZoneDisplayDriver.cs | 2 +- .../TimeZone/Services/UserTimeZoneService.cs | 2 +- 4 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationClaimsProvider.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationClaimsProvider.cs index 230406bc8ac..78fe6a2017f 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationClaimsProvider.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationClaimsProvider.cs @@ -15,14 +15,14 @@ public Task GenerateAsync(IUser user, ClaimsIdentity claims) ArgumentNullException.ThrowIfNull(user); ArgumentNullException.ThrowIfNull(claims); - if (user is not User u) + if (user is not User currentUser) { return Task.CompletedTask; } - if (u.Has()) + if (currentUser.Has()) { - var localizationSetting = u.As(); + var localizationSetting = currentUser.As(); if (!string.IsNullOrEmpty(localizationSetting.Culture)) { diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs index 3dc8f1bde1e..20f08fff476 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs @@ -17,15 +17,9 @@ public override Task DetermineProviderCultureResult(HttpC return NullProviderCultureResult; } - string userCulture = null; - var claimCulture = httpContext.User.FindFirstValue("culture"); + var userCulture = httpContext.User.FindFirstValue("culture"); - if (!string.IsNullOrWhiteSpace(claimCulture)) - { - userCulture = claimCulture; - } - - if (userCulture == null) + if (string.IsNullOrWhiteSpace(userCulture)) { return NullProviderCultureResult; } diff --git a/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Drivers/UserTimeZoneDisplayDriver.cs b/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Drivers/UserTimeZoneDisplayDriver.cs index 2035f913d82..d818748c3dc 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Drivers/UserTimeZoneDisplayDriver.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Drivers/UserTimeZoneDisplayDriver.cs @@ -59,7 +59,7 @@ public override async Task UpdateAsync(User user, UserTimeZone u userTimeZone.TimeZoneId = model.TimeZoneId; // Remove the cache entry, don't update it, as the form might still fail validation for other reasons. - await _userTimeZoneService.UpdateUserTimeZoneAsync(user); + await _userTimeZoneService.ClearUserTimeZoneCacheAsync(user); } return await EditAsync(userTimeZone, context); diff --git a/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Services/UserTimeZoneService.cs b/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Services/UserTimeZoneService.cs index eff639784c5..d649918fc86 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Services/UserTimeZoneService.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Services/UserTimeZoneService.cs @@ -44,7 +44,7 @@ public async Task GetUserTimeZoneAsync() return _clock.GetTimeZone(currentTimeZoneId); } - public Task UpdateUserTimeZoneAsync(User user) + public Task ClearUserTimeZoneCacheAsync(User user) { var userName = user?.UserName; From a103b5f61cfd53eb4e8d75a483d1596041b19cb7 Mon Sep 17 00:00:00 2001 From: Hisham Bin Ateya Date: Mon, 15 Jan 2024 11:59:24 +0300 Subject: [PATCH 18/40] CultureClaimType as constant --- .../Localization/Drivers/UserLocalizationDisplayDriver.cs | 8 +++----- .../Providers/UserLocalizationClaimsProvider.cs | 4 +++- .../Providers/UserLocalizationRequestCultureProvider.cs | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs index abba9509548..7891e4081d2 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs @@ -10,6 +10,7 @@ using OrchardCore.DisplayManagement.Views; using OrchardCore.Localization; using OrchardCore.Users.Localization.Models; +using OrchardCore.Users.Localization.Providers; using OrchardCore.Users.Localization.ViewModels; using OrchardCore.Users.Models; @@ -20,10 +21,7 @@ public class UserLocalizationDisplayDriver : SectionDisplayDriver EditAsync(UserLocalizationSettings section, { var defaultCulture = await _localizationService.GetDefaultCultureAsync(); var supportedCultures = await _localizationService.GetSupportedCulturesAsync(); - var currentUserCulture = _httpContextAccessor.HttpContext.User.FindFirstValue("culture"); + var currentUserCulture = _httpContextAccessor.HttpContext.User.FindFirstValue(UserLocalizationClaimsProvider.CultureClaimType); if (currentUserCulture == null) { diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationClaimsProvider.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationClaimsProvider.cs index 78fe6a2017f..6fc78ec4968 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationClaimsProvider.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationClaimsProvider.cs @@ -10,6 +10,8 @@ namespace OrchardCore.Users.Localization.Providers; public class UserLocalizationClaimsProvider : IUserClaimsProvider { + internal const string CultureClaimType = "culture"; + public Task GenerateAsync(IUser user, ClaimsIdentity claims) { ArgumentNullException.ThrowIfNull(user); @@ -26,7 +28,7 @@ public Task GenerateAsync(IUser user, ClaimsIdentity claims) if (!string.IsNullOrEmpty(localizationSetting.Culture)) { - claims.AddClaim(new Claim("culture", localizationSetting.Culture)); + claims.AddClaim(new Claim(CultureClaimType, localizationSetting.Culture)); } } diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs index 20f08fff476..d0d926670ab 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs @@ -17,7 +17,7 @@ public override Task DetermineProviderCultureResult(HttpC return NullProviderCultureResult; } - var userCulture = httpContext.User.FindFirstValue("culture"); + var userCulture = httpContext.User.FindFirstValue(UserLocalizationClaimsProvider.CultureClaimType); if (string.IsNullOrWhiteSpace(userCulture)) { From 2a04a1bc74d6f5de02cee0c9275b0f0a78049ea0 Mon Sep 17 00:00:00 2001 From: Hisham Bin Ateya Date: Mon, 15 Jan 2024 12:40:15 +0300 Subject: [PATCH 19/40] Add comment on ConfigureOrder --- src/OrchardCore.Modules/OrchardCore.Localization/Startup.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/OrchardCore.Modules/OrchardCore.Localization/Startup.cs b/src/OrchardCore.Modules/OrchardCore.Localization/Startup.cs index f76602cc923..674539f0e07 100644 --- a/src/OrchardCore.Modules/OrchardCore.Localization/Startup.cs +++ b/src/OrchardCore.Modules/OrchardCore.Localization/Startup.cs @@ -25,6 +25,7 @@ namespace OrchardCore.Localization /// public class Startup : StartupBase { + // Don't change this order to lower value because this will break the user default culture if OrchardCore.Users.Localization feature is enabled public override int ConfigureOrder => 100; /// From 64102fdf272759d756429a20caeed02725c99e85 Mon Sep 17 00:00:00 2001 From: Hisham Bin Ateya Date: Tue, 16 Jan 2024 00:22:50 +0300 Subject: [PATCH 20/40] Add GetCulture() extension method --- .../Drivers/UserLocalizationDisplayDriver.cs | 2 +- .../Localization/Extensions/ClaimsPrincipleExtensions.cs | 9 +++++++++ .../Providers/UserLocalizationRequestCultureProvider.cs | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 src/OrchardCore.Modules/OrchardCore.Users/Localization/Extensions/ClaimsPrincipleExtensions.cs diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs index 7891e4081d2..d6033d230d1 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs @@ -33,7 +33,7 @@ public override Task EditAsync(UserLocalizationSettings section, { var defaultCulture = await _localizationService.GetDefaultCultureAsync(); var supportedCultures = await _localizationService.GetSupportedCulturesAsync(); - var currentUserCulture = _httpContextAccessor.HttpContext.User.FindFirstValue(UserLocalizationClaimsProvider.CultureClaimType); + var currentUserCulture = _httpContextAccessor.HttpContext.User.GetCulture(); if (currentUserCulture == null) { diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Extensions/ClaimsPrincipleExtensions.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Extensions/ClaimsPrincipleExtensions.cs new file mode 100644 index 00000000000..0282cf17e44 --- /dev/null +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Extensions/ClaimsPrincipleExtensions.cs @@ -0,0 +1,9 @@ +using OrchardCore.Users.Localization.Providers; + +namespace System.Security.Claims; + +public static class ClaimsPrincipleExtensions +{ + public static string GetCulture(this ClaimsPrincipal principal) + => principal.FindFirstValue(UserLocalizationClaimsProvider.CultureClaimType); +} diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs index d0d926670ab..6c921df8e41 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs @@ -17,7 +17,7 @@ public override Task DetermineProviderCultureResult(HttpC return NullProviderCultureResult; } - var userCulture = httpContext.User.FindFirstValue(UserLocalizationClaimsProvider.CultureClaimType); + var userCulture = httpContext.User.GetCulture(); if (string.IsNullOrWhiteSpace(userCulture)) { From 362e1a5d136e67e196bbc0d0a21b7589fd98b9b3 Mon Sep 17 00:00:00 2001 From: Hisham Bin Ateya Date: Tue, 16 Jan 2024 02:08:15 +0300 Subject: [PATCH 21/40] Address the feedback --- src/OrchardCore.Modules/OrchardCore.Localization/Startup.cs | 2 +- src/docs/releases/1.9.0.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Localization/Startup.cs b/src/OrchardCore.Modules/OrchardCore.Localization/Startup.cs index 674539f0e07..0a8d4af4e47 100644 --- a/src/OrchardCore.Modules/OrchardCore.Localization/Startup.cs +++ b/src/OrchardCore.Modules/OrchardCore.Localization/Startup.cs @@ -25,7 +25,7 @@ namespace OrchardCore.Localization /// public class Startup : StartupBase { - // Don't change this order to lower value because this will break the user default culture if OrchardCore.Users.Localization feature is enabled + // Don't change this order to a lower value because this will break the user default culture if OrchardCore.Users.Localization feature is enabled. public override int ConfigureOrder => 100; /// diff --git a/src/docs/releases/1.9.0.md b/src/docs/releases/1.9.0.md index b9f7700b61b..f5210c825f6 100644 --- a/src/docs/releases/1.9.0.md +++ b/src/docs/releases/1.9.0.md @@ -28,7 +28,7 @@ Added new extensions to make registering custom deployment step easier ## Users Module -Added new localization settings that allow the user to set his/her default culture and time zone. +Added new localization settings in the User Localization feature that allow the user to set their default culture and time zone. !!! note - The newly added settings override the current admin localization culture and time zone settings. + The newly added settings override the current admin localization culture and time zone settings if the User Localization feature is enabled. From 6fc7e32f7d4c4093d18a5e7d58c5a83be0328989 Mon Sep 17 00:00:00 2001 From: Hisham Bin Ateya Date: Tue, 16 Jan 2024 22:39:50 +0300 Subject: [PATCH 22/40] Remove unnecessary Configure() method --- .../OrchardCore.Users/TimeZone/Startup.cs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Startup.cs b/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Startup.cs index cea1178fabf..afe39bde4c0 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Startup.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Startup.cs @@ -1,6 +1,3 @@ -using System; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; using OrchardCore.DisplayManagement.Handlers; using OrchardCore.Modules; @@ -13,10 +10,6 @@ namespace OrchardCore.Users.TimeZone; [Feature("OrchardCore.Users.TimeZone")] public class Startup : StartupBase { - public override void Configure(IApplicationBuilder builder, IEndpointRouteBuilder routes, IServiceProvider serviceProvider) - { - } - public override void ConfigureServices(IServiceCollection services) { services.AddScoped(); From 4d5cd8bf9187f0afa50d8faae67fb0740e25ff79 Mon Sep 17 00:00:00 2001 From: Hisham Bin Ateya Date: Tue, 16 Jan 2024 22:45:03 +0300 Subject: [PATCH 23/40] Set the configuration order on OrchardCore.Users.Localization --- src/OrchardCore.Modules/OrchardCore.Localization/Startup.cs | 1 - .../OrchardCore.Users/Localization/Startup.cs | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Localization/Startup.cs b/src/OrchardCore.Modules/OrchardCore.Localization/Startup.cs index 0a8d4af4e47..f76602cc923 100644 --- a/src/OrchardCore.Modules/OrchardCore.Localization/Startup.cs +++ b/src/OrchardCore.Modules/OrchardCore.Localization/Startup.cs @@ -25,7 +25,6 @@ namespace OrchardCore.Localization /// public class Startup : StartupBase { - // Don't change this order to a lower value because this will break the user default culture if OrchardCore.Users.Localization feature is enabled. public override int ConfigureOrder => 100; /// diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Startup.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Startup.cs index c04a2a09d0d..a6eab2010e2 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Startup.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Startup.cs @@ -12,6 +12,8 @@ namespace OrchardCore.Users.Localization; [Feature("OrchardCore.Users.Localization")] public class Startup : StartupBase { + public override int ConfigureOrder => -200; + public override void ConfigureServices(IServiceCollection services) { services.AddScoped, UserLocalizationDisplayDriver>(); From f6da84b2e6615d1f1a5de7c8f96cf5639a37fcc7 Mon Sep 17 00:00:00 2001 From: Hisham Bin Ateya Date: Wed, 17 Jan 2024 00:23:28 +0300 Subject: [PATCH 24/40] Remove ConfigureOrder from OrchardCore.Users.Localization --- src/OrchardCore.Modules/OrchardCore.Localization/Startup.cs | 1 + .../OrchardCore.Users/Localization/Startup.cs | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Localization/Startup.cs b/src/OrchardCore.Modules/OrchardCore.Localization/Startup.cs index f76602cc923..0a8d4af4e47 100644 --- a/src/OrchardCore.Modules/OrchardCore.Localization/Startup.cs +++ b/src/OrchardCore.Modules/OrchardCore.Localization/Startup.cs @@ -25,6 +25,7 @@ namespace OrchardCore.Localization /// public class Startup : StartupBase { + // Don't change this order to a lower value because this will break the user default culture if OrchardCore.Users.Localization feature is enabled. public override int ConfigureOrder => 100; /// diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Startup.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Startup.cs index a6eab2010e2..c04a2a09d0d 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Startup.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Startup.cs @@ -12,8 +12,6 @@ namespace OrchardCore.Users.Localization; [Feature("OrchardCore.Users.Localization")] public class Startup : StartupBase { - public override int ConfigureOrder => -200; - public override void ConfigureServices(IServiceCollection services) { services.AddScoped, UserLocalizationDisplayDriver>(); From 2b6a88a5572deb8e36064f3a23fcd75ed76b3f2c Mon Sep 17 00:00:00 2001 From: Hisham Bin Ateya Date: Wed, 17 Jan 2024 00:30:30 +0300 Subject: [PATCH 25/40] Revert changes from OC.Localization --- src/OrchardCore.Modules/OrchardCore.Localization/Startup.cs | 3 +-- .../Modules/Extensions/ServiceCollectionExtensions.cs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Localization/Startup.cs b/src/OrchardCore.Modules/OrchardCore.Localization/Startup.cs index 0a8d4af4e47..99326bc1d16 100644 --- a/src/OrchardCore.Modules/OrchardCore.Localization/Startup.cs +++ b/src/OrchardCore.Modules/OrchardCore.Localization/Startup.cs @@ -25,8 +25,7 @@ namespace OrchardCore.Localization /// public class Startup : StartupBase { - // Don't change this order to a lower value because this will break the user default culture if OrchardCore.Users.Localization feature is enabled. - public override int ConfigureOrder => 100; + public override int ConfigureOrder => -100; /// public override void ConfigureServices(IServiceCollection services) diff --git a/src/OrchardCore/OrchardCore/Modules/Extensions/ServiceCollectionExtensions.cs b/src/OrchardCore/OrchardCore/Modules/Extensions/ServiceCollectionExtensions.cs index 062580b6f07..29f86e69c5b 100644 --- a/src/OrchardCore/OrchardCore/Modules/Extensions/ServiceCollectionExtensions.cs +++ b/src/OrchardCore/OrchardCore/Modules/Extensions/ServiceCollectionExtensions.cs @@ -520,7 +520,7 @@ private static void AddAuthentication(OrchardCoreBuilder builder) .Configure(app => { app.UseAuthentication(); - }); + }, order: -150); } /// From f7436d50f4cc9851ff42675cee0d70ad83f46f7b Mon Sep 17 00:00:00 2001 From: Hisham Bin Ateya Date: Tue, 23 Jan 2024 14:34:47 +0300 Subject: [PATCH 26/40] Set the User Localization feature priority --- src/OrchardCore.Modules/OrchardCore.Users/Manifest.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Manifest.cs b/src/OrchardCore.Modules/OrchardCore.Users/Manifest.cs index 9da627f1eb0..e9611b3afbf 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Manifest.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Manifest.cs @@ -61,7 +61,8 @@ Name = "User Localization", Description = "Provides a way to set the culture per user.", Dependencies = new[] { "OrchardCore.Users", "OrchardCore.Localization" }, - Category = "Settings" + Category = "Settings", + Priority = "-1" )] [assembly: Feature( From 67afc77ab6e19553f964a0c576f93b22bacd4c31 Mon Sep 17 00:00:00 2001 From: Jasmin Savard Date: Wed, 24 Jan 2024 23:43:34 -0500 Subject: [PATCH 27/40] Fix issue with default culture not selected When currentUserCulture is null or supportedCulture doesn't contain currentUserCulture. --- .../Localization/Drivers/UserLocalizationDisplayDriver.cs | 2 +- .../OrchardCore.Users/Views/UserCulture.Edit.cshtml | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs index d6033d230d1..6f2fd640801 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs @@ -35,7 +35,7 @@ public override Task EditAsync(UserLocalizationSettings section, var supportedCultures = await _localizationService.GetSupportedCulturesAsync(); var currentUserCulture = _httpContextAccessor.HttpContext.User.GetCulture(); - if (currentUserCulture == null) + if (currentUserCulture == null || !supportedCultures.Contains(currentUserCulture)) { currentUserCulture = defaultCulture; } diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Views/UserCulture.Edit.cshtml b/src/OrchardCore.Modules/OrchardCore.Users/Views/UserCulture.Edit.cshtml index a9337af4b96..53eb6c48d17 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Views/UserCulture.Edit.cshtml +++ b/src/OrchardCore.Modules/OrchardCore.Users/Views/UserCulture.Edit.cshtml @@ -3,7 +3,12 @@
- + @T["Determines the default culture used by this user."]
From 7df022486a3b7cefb20d358d698f87cbde27679e Mon Sep 17 00:00:00 2001 From: Jasmin Savard Date: Thu, 25 Jan 2024 00:05:40 -0500 Subject: [PATCH 28/40] Revert Timezone changes --- .../Drivers/UserTimeZoneDisplayDriver.cs | 68 ++++------- .../TimeZone/Models/UserTimeZone.cs | 9 +- .../TimeZone/Services/UserTimeZoneSelector.cs | 36 +++--- .../TimeZone/Services/UserTimeZoneService.cs | 111 +++++++++--------- .../OrchardCore.Users/TimeZone/Startup.cs | 25 ++-- .../ViewModel/UserTimeZoneViewModel.cs | 16 +-- src/docs/releases/1.9.0.md | 4 +- 7 files changed, 128 insertions(+), 141 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Drivers/UserTimeZoneDisplayDriver.cs b/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Drivers/UserTimeZoneDisplayDriver.cs index d818748c3dc..87873c4e287 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Drivers/UserTimeZoneDisplayDriver.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Drivers/UserTimeZoneDisplayDriver.cs @@ -1,67 +1,45 @@ -using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc.Rendering; using OrchardCore.DisplayManagement.Entities; using OrchardCore.DisplayManagement.Handlers; using OrchardCore.DisplayManagement.ModelBinding; using OrchardCore.DisplayManagement.Views; -using OrchardCore.Modules; -using OrchardCore.Settings; using OrchardCore.Users.Models; using OrchardCore.Users.TimeZone.Models; using OrchardCore.Users.TimeZone.Services; using OrchardCore.Users.TimeZone.ViewModels; -namespace OrchardCore.Users.TimeZone.Drivers; - -public class UserTimeZoneDisplayDriver : SectionDisplayDriver +namespace OrchardCore.Users.TimeZone.Drivers { - private readonly UserTimeZoneService _userTimeZoneService; - private readonly ISiteService _siteService; - private readonly IClock _clock; - - public UserTimeZoneDisplayDriver(UserTimeZoneService userTimeZoneService, ISiteService siteService, IClock clock) + public class UserTimeZoneDisplayDriver : SectionDisplayDriver { - _userTimeZoneService = userTimeZoneService; - _siteService = siteService; - _clock = clock; - } + private readonly UserTimeZoneService _userTimeZoneService; - public override IDisplayResult Edit(UserTimeZone userTimeZone, BuildEditorContext context) - { - return Initialize("UserTimeZone_Edit", async model => + public UserTimeZoneDisplayDriver(UserTimeZoneService userTimeZoneService) { - var timeZoneId = userTimeZone.TimeZoneId; - if (timeZoneId == null) - { - var siteSettings = await _siteService.GetSiteSettingsAsync(); + _userTimeZoneService = userTimeZoneService; + } - timeZoneId = siteSettings.TimeZoneId; - } + public override IDisplayResult Edit(UserTimeZone userTimeZone, BuildEditorContext context) + { + return Initialize("UserTimeZone_Edit", model => + { + model.TimeZoneId = userTimeZone.TimeZoneId; + }).Location("Content:2"); + } - model.TimeZoneId = timeZoneId; - model.TimeZones = _clock.GetTimeZones().Select(tz => - new SelectListItem - { - Text = tz.ToString(), - Value = tz.TimeZoneId, - Selected = tz.TimeZoneId == timeZoneId - }); - }).Location("Content:3"); - } + public override async Task UpdateAsync(User user, UserTimeZone userTimeZone, IUpdateModel updater, BuildEditorContext context) + { + var model = new UserTimeZoneViewModel(); - public override async Task UpdateAsync(User user, UserTimeZone userTimeZone, IUpdateModel updater, BuildEditorContext context) - { - var model = new UserTimeZoneViewModel(); + if (await context.Updater.TryUpdateModelAsync(model, Prefix)) + { + userTimeZone.TimeZoneId = model.TimeZoneId; - if (await context.Updater.TryUpdateModelAsync(model, Prefix)) - { - userTimeZone.TimeZoneId = model.TimeZoneId; + // Remove the cache entry, don't update it, as the form might still fail validation for other reasons. + await _userTimeZoneService.UpdateUserTimeZoneAsync(user); + } - // Remove the cache entry, don't update it, as the form might still fail validation for other reasons. - await _userTimeZoneService.ClearUserTimeZoneCacheAsync(user); + return await EditAsync(userTimeZone, context); } - - return await EditAsync(userTimeZone, context); } } diff --git a/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Models/UserTimeZone.cs b/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Models/UserTimeZone.cs index 9e094fc8ebf..541cc1a9414 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Models/UserTimeZone.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Models/UserTimeZone.cs @@ -1,6 +1,7 @@ -namespace OrchardCore.Users.TimeZone.Models; - -public class UserTimeZone +namespace OrchardCore.Users.TimeZone.Models { - public string TimeZoneId { get; set; } + public class UserTimeZone + { + public string TimeZoneId { get; set; } + } } diff --git a/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Services/UserTimeZoneSelector.cs b/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Services/UserTimeZoneSelector.cs index 6dcd429809b..b066149fe78 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Services/UserTimeZoneSelector.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Services/UserTimeZoneSelector.cs @@ -1,23 +1,27 @@ using System.Threading.Tasks; using OrchardCore.Modules; -namespace OrchardCore.Users.TimeZone.Services; - -/// -/// Provides the time zone defined for the currently logged-in user for the current scope (request). -/// -public class UserTimeZoneSelector : ITimeZoneSelector +namespace OrchardCore.Users.TimeZone.Services { - private readonly UserTimeZoneService _userTimeZoneService; - - public UserTimeZoneSelector(UserTimeZoneService userTimeZoneService) + /// + /// Provides the timezone defined for the currently logged-in user for the current scope (request). + /// + public class UserTimeZoneSelector : ITimeZoneSelector { - _userTimeZoneService = userTimeZoneService; - } + private readonly UserTimeZoneService _userTimeZoneService; - public Task GetTimeZoneAsync() => Task.FromResult(new TimeZoneSelectorResult - { - Priority = 100, - TimeZoneId = async () => (await _userTimeZoneService.GetUserTimeZoneAsync())?.TimeZoneId - }); + public UserTimeZoneSelector(UserTimeZoneService userTimeZoneService) + { + _userTimeZoneService = userTimeZoneService; + } + + public Task GetTimeZoneAsync() + { + return Task.FromResult(new TimeZoneSelectorResult + { + Priority = 100, + TimeZoneId = async () => (await _userTimeZoneService.GetUserTimeZoneAsync())?.TimeZoneId + }); + } + } } diff --git a/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Services/UserTimeZoneService.cs b/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Services/UserTimeZoneService.cs index d649918fc86..21969a4f9f3 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Services/UserTimeZoneService.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Services/UserTimeZoneService.cs @@ -8,77 +8,80 @@ using OrchardCore.Users.Models; using OrchardCore.Users.TimeZone.Models; -namespace OrchardCore.Users.TimeZone.Services; - -public class UserTimeZoneService +namespace OrchardCore.Users.TimeZone.Services { - private const string CacheKey = "UserTimeZone/"; - - private readonly TimeSpan _slidingExpiration = TimeSpan.FromMinutes(1); - private readonly IClock _clock; - private readonly IDistributedCache _distributedCache; - private readonly IHttpContextAccessor _httpContextAccessor; - private readonly UserManager _userManager; - - public UserTimeZoneService( - IClock clock, - IDistributedCache distributedCache, - IHttpContextAccessor httpContextAccessor, - UserManager userManager) + public class UserTimeZoneService { - _clock = clock; - _distributedCache = distributedCache; - _httpContextAccessor = httpContextAccessor; - _userManager = userManager; - } - - public async Task GetUserTimeZoneAsync() - { - var currentTimeZoneId = await GetCurrentUserTimeZoneIdAsync(); - - if (string.IsNullOrEmpty(currentTimeZoneId)) + private const string CacheKey = "UserTimeZone/"; + private readonly TimeSpan _slidingExpiration = TimeSpan.FromMinutes(1); + + private readonly IClock _clock; + private readonly IDistributedCache _distributedCache; + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly UserManager _userManager; + + public UserTimeZoneService( + IClock clock, + IDistributedCache distributedCache, + IHttpContextAccessor httpContextAccessor, + UserManager userManager + ) { - return null; + _clock = clock; + _distributedCache = distributedCache; + _httpContextAccessor = httpContextAccessor; + _userManager = userManager; } - return _clock.GetTimeZone(currentTimeZoneId); - } + public async Task GetUserTimeZoneAsync() + { + var currentTimeZoneId = await GetCurrentUserTimeZoneIdAsync(); + if (string.IsNullOrEmpty(currentTimeZoneId)) + { + return null; + } - public Task ClearUserTimeZoneCacheAsync(User user) - { - var userName = user?.UserName; + return _clock.GetTimeZone(currentTimeZoneId); + } - return string.IsNullOrEmpty(userName) - ? Task.CompletedTask - : _distributedCache.RemoveAsync(GetCacheKey(userName)); - } + public Task UpdateUserTimeZoneAsync(User user) + { + var userName = user?.UserName; - public async Task GetCurrentUserTimeZoneIdAsync() - { - var userName = _httpContextAccessor.HttpContext.User?.Identity?.Name; + if (!string.IsNullOrEmpty(userName)) + { + return _distributedCache.RemoveAsync(GetCacheKey(userName)); + } - if (string.IsNullOrEmpty(userName)) - { - return null; + return Task.CompletedTask; } - var key = GetCacheKey(userName); - var timeZoneId = await _distributedCache.GetStringAsync(key); - - if (string.IsNullOrEmpty(timeZoneId)) + public async Task GetCurrentUserTimeZoneIdAsync() { - var user = await _userManager.FindByNameAsync(userName) as User; + var userName = _httpContextAccessor.HttpContext.User?.Identity?.Name; - timeZoneId = user.As()?.TimeZoneId; + if (string.IsNullOrEmpty(userName)) + { + return null; + } + + var key = GetCacheKey(userName); + var timeZoneId = await _distributedCache.GetStringAsync(key); - if (!string.IsNullOrEmpty(timeZoneId)) + if (string.IsNullOrEmpty(timeZoneId)) { - await _distributedCache.SetStringAsync(key, timeZoneId, new DistributedCacheEntryOptions { SlidingExpiration = _slidingExpiration }); + var user = await _userManager.FindByNameAsync(userName) as User; + timeZoneId = user.As()?.TimeZoneId; + + if (!string.IsNullOrEmpty(timeZoneId)) + { + await _distributedCache.SetStringAsync(key, timeZoneId, new DistributedCacheEntryOptions { SlidingExpiration = _slidingExpiration }); + } } + + return timeZoneId; } - return timeZoneId; + private static string GetCacheKey(string userName) => CacheKey + userName; } - - private static string GetCacheKey(string userName) => CacheKey + userName; } diff --git a/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Startup.cs b/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Startup.cs index afe39bde4c0..c624f88a8fe 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Startup.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/Startup.cs @@ -1,3 +1,6 @@ +using System; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; using OrchardCore.DisplayManagement.Handlers; using OrchardCore.Modules; @@ -5,15 +8,21 @@ using OrchardCore.Users.TimeZone.Drivers; using OrchardCore.Users.TimeZone.Services; -namespace OrchardCore.Users.TimeZone; - -[Feature("OrchardCore.Users.TimeZone")] -public class Startup : StartupBase +namespace OrchardCore.Users.TimeZone { - public override void ConfigureServices(IServiceCollection services) + [Feature("OrchardCore.Users.TimeZone")] + public class Startup : StartupBase { - services.AddScoped(); - services.AddScoped(); - services.AddScoped, UserTimeZoneDisplayDriver>(); + public override void Configure(IApplicationBuilder builder, IEndpointRouteBuilder routes, IServiceProvider serviceProvider) + { + } + + public override void ConfigureServices(IServiceCollection services) + { + services.AddScoped(); + services.AddScoped(); + + services.AddScoped, UserTimeZoneDisplayDriver>(); + } } } diff --git a/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/ViewModel/UserTimeZoneViewModel.cs b/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/ViewModel/UserTimeZoneViewModel.cs index d9e093fa86a..40cfea11adb 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/ViewModel/UserTimeZoneViewModel.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/TimeZone/ViewModel/UserTimeZoneViewModel.cs @@ -1,13 +1,7 @@ -using System.Collections.Generic; -using Microsoft.AspNetCore.Mvc.ModelBinding; -using Microsoft.AspNetCore.Mvc.Rendering; - -namespace OrchardCore.Users.TimeZone.ViewModels; - -public class UserTimeZoneViewModel +namespace OrchardCore.Users.TimeZone.ViewModels { - public string TimeZoneId { get; set; } - - [BindNever] - public IEnumerable TimeZones { get; set; } = new List(); + public class UserTimeZoneViewModel + { + public string TimeZoneId { get; set; } + } } diff --git a/src/docs/releases/1.9.0.md b/src/docs/releases/1.9.0.md index e173147c5ea..2da5316d85a 100644 --- a/src/docs/releases/1.9.0.md +++ b/src/docs/releases/1.9.0.md @@ -41,7 +41,5 @@ Added new extensions to make registering custom deployment step easier ## Users Module -Added new localization settings in the User Localization feature that allow the user to set their default culture and time zone. +Added new user localization feature that allows to set default culture per user in the admin UI. -!!! note - The newly added settings override the current admin localization culture and time zone settings if the User Localization feature is enabled. From 089b172df2dde592616635afc82cfaef985c7789 Mon Sep 17 00:00:00 2001 From: Jasmin Savard Date: Thu, 25 Jan 2024 00:07:13 -0500 Subject: [PATCH 29/40] Revert changes timezone --- .../OrchardCore.Users/Views/UserTimeZone.Edit.cshtml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Views/UserTimeZone.Edit.cshtml b/src/OrchardCore.Modules/OrchardCore.Users/Views/UserTimeZone.Edit.cshtml index 0c9cbd86161..fd5656eeab8 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Views/UserTimeZone.Edit.cshtml +++ b/src/OrchardCore.Modules/OrchardCore.Users/Views/UserTimeZone.Edit.cshtml @@ -1,8 +1,17 @@ @model UserTimeZoneViewModel +@inject OrchardCore.Modules.IClock Clock
- + @T["Determines the time zone used when displaying and editing dates and times."]
From a835a8809a44a97ef5ea2941727ca94d2bcae0af Mon Sep 17 00:00:00 2001 From: Jasmin Savard Date: Fri, 26 Jan 2024 01:06:54 -0500 Subject: [PATCH 30/40] Simplify --- .../Drivers/UserLocalizationDisplayDriver.cs | 16 ++-------------- .../Views/UserCulture.Edit.cshtml | 9 +++------ 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs index 6f2fd640801..95f80a6214a 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs @@ -1,6 +1,5 @@ using System.Globalization; using System.Linq; -using System.Security.Claims; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Rendering; @@ -10,7 +9,6 @@ using OrchardCore.DisplayManagement.Views; using OrchardCore.Localization; using OrchardCore.Users.Localization.Models; -using OrchardCore.Users.Localization.Providers; using OrchardCore.Users.Localization.ViewModels; using OrchardCore.Users.Models; @@ -19,34 +17,24 @@ namespace OrchardCore.Users.Localization.Drivers; public class UserLocalizationDisplayDriver : SectionDisplayDriver { private readonly ILocalizationService _localizationService; - private readonly IHttpContextAccessor _httpContextAccessor; - public UserLocalizationDisplayDriver(ILocalizationService localizationService, IHttpContextAccessor httpContextAccessor) + public UserLocalizationDisplayDriver(ILocalizationService localizationService) { _localizationService = localizationService; - _httpContextAccessor = httpContextAccessor; } public override Task EditAsync(UserLocalizationSettings section, BuildEditorContext context) { return Task.FromResult(Initialize("UserCulture_Edit", async model => { - var defaultCulture = await _localizationService.GetDefaultCultureAsync(); var supportedCultures = await _localizationService.GetSupportedCulturesAsync(); - var currentUserCulture = _httpContextAccessor.HttpContext.User.GetCulture(); - - if (currentUserCulture == null || !supportedCultures.Contains(currentUserCulture)) - { - currentUserCulture = defaultCulture; - } model.Culture = section.Culture; model.SupportedCultures = supportedCultures.Select(culture => new SelectListItem { Text = CultureInfo.GetCultureInfo(culture).DisplayName + " (" + culture + ")", - Value = culture, - Selected = currentUserCulture == culture + Value = culture }); }).Location("Content:2")); } diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Views/UserCulture.Edit.cshtml b/src/OrchardCore.Modules/OrchardCore.Users/Views/UserCulture.Edit.cshtml index 53eb6c48d17..7ccdd8b1a40 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Views/UserCulture.Edit.cshtml +++ b/src/OrchardCore.Modules/OrchardCore.Users/Views/UserCulture.Edit.cshtml @@ -2,12 +2,9 @@ @model UserLocalizationViewModel
- - + @T["Determines the default culture used by this user."] From 6ace93d985415eb30de256d818988bca55868f4a Mon Sep 17 00:00:00 2001 From: Jasmin Savard Date: Fri, 26 Jan 2024 01:09:24 -0500 Subject: [PATCH 31/40] cleanup using --- .../Localization/Drivers/UserLocalizationDisplayDriver.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs index 95f80a6214a..1d4aa4e00e1 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs @@ -1,7 +1,6 @@ using System.Globalization; using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Rendering; using OrchardCore.DisplayManagement.Entities; using OrchardCore.DisplayManagement.Handlers; From 839721b3321c86c1454851d89cbfe07c83538ddc Mon Sep 17 00:00:00 2001 From: Jasmin Savard Date: Mon, 29 Jan 2024 16:50:59 -0500 Subject: [PATCH 32/40] Try to support Invariant Culture --- .../Drivers/UserLocalizationDisplayDriver.cs | 19 ++++++++++++++----- .../UserLocalizationClaimsProvider.cs | 4 ++-- .../ViewModel/UserLocalizationViewModel.cs | 4 ++-- .../OrchardCore.Users/Manifest.cs | 2 +- .../Views/UserCulture.Edit.cshtml | 9 ++++----- 5 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs index 1d4aa4e00e1..dd1e402f568 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.Extensions.Localization; using OrchardCore.DisplayManagement.Entities; using OrchardCore.DisplayManagement.Handlers; using OrchardCore.DisplayManagement.ModelBinding; @@ -16,10 +17,14 @@ namespace OrchardCore.Users.Localization.Drivers; public class UserLocalizationDisplayDriver : SectionDisplayDriver { private readonly ILocalizationService _localizationService; + protected readonly IStringLocalizer S; - public UserLocalizationDisplayDriver(ILocalizationService localizationService) + public UserLocalizationDisplayDriver( + ILocalizationService localizationService, + IStringLocalizer localizer) { _localizationService = localizationService; + S = localizer; } public override Task EditAsync(UserLocalizationSettings section, BuildEditorContext context) @@ -28,13 +33,17 @@ public override Task EditAsync(UserLocalizationSettings section, { var supportedCultures = await _localizationService.GetSupportedCulturesAsync(); - model.Culture = section.Culture; - model.SupportedCultures = supportedCultures.Select(culture => + var cultureList = supportedCultures.Select(culture => new SelectListItem { Text = CultureInfo.GetCultureInfo(culture).DisplayName + " (" + culture + ")", Value = culture - }); + }).ToList(); + + cultureList.Insert(0, new SelectListItem(){ Text = S["Use site's culture"], Value = "none" }); + + model.SelectedCulture = section.Culture; + model.CultureList = cultureList; }).Location("Content:2")); } @@ -44,7 +53,7 @@ public override async Task UpdateAsync(User model, UserLocalizat if (await context.Updater.TryUpdateModelAsync(viewModel, Prefix)) { - section.Culture = viewModel.Culture; + section.Culture = viewModel.SelectedCulture; } return await EditAsync(section, context); diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationClaimsProvider.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationClaimsProvider.cs index 6fc78ec4968..7fc7aad81e0 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationClaimsProvider.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationClaimsProvider.cs @@ -26,9 +26,9 @@ public Task GenerateAsync(IUser user, ClaimsIdentity claims) { var localizationSetting = currentUser.As(); - if (!string.IsNullOrEmpty(localizationSetting.Culture)) + if (localizationSetting.Culture != "none") { - claims.AddClaim(new Claim(CultureClaimType, localizationSetting.Culture)); + claims.AddClaim(new Claim(CultureClaimType, localizationSetting.Culture ?? "")); } } diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/ViewModel/UserLocalizationViewModel.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/ViewModel/UserLocalizationViewModel.cs index af452081f68..2264b399aeb 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/ViewModel/UserLocalizationViewModel.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/ViewModel/UserLocalizationViewModel.cs @@ -6,8 +6,8 @@ namespace OrchardCore.Users.Localization.ViewModels; public class UserLocalizationViewModel { - public string Culture { get; set; } + public string SelectedCulture { get; set; } [BindNever] - public IEnumerable SupportedCultures { get; set; } = new List(); + public IEnumerable CultureList { get; set; } = new List(); } diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Manifest.cs b/src/OrchardCore.Modules/OrchardCore.Users/Manifest.cs index e9611b3afbf..29b77d9699c 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Manifest.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Manifest.cs @@ -62,7 +62,7 @@ Description = "Provides a way to set the culture per user.", Dependencies = new[] { "OrchardCore.Users", "OrchardCore.Localization" }, Category = "Settings", - Priority = "-1" + Priority = "-1" // Added to avoid changing the order in the localization module. )] [assembly: Feature( diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Views/UserCulture.Edit.cshtml b/src/OrchardCore.Modules/OrchardCore.Users/Views/UserCulture.Edit.cshtml index 7ccdd8b1a40..e5c358bd9d2 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Views/UserCulture.Edit.cshtml +++ b/src/OrchardCore.Modules/OrchardCore.Users/Views/UserCulture.Edit.cshtml @@ -1,11 +1,10 @@ @using OrchardCore.Users.Localization.ViewModels @model UserLocalizationViewModel -
- - - + @T["Determines the default culture used by this user."]
From f50d427efdcd50257f494fc6199e3d38df0e49c3 Mon Sep 17 00:00:00 2001 From: Jasmin Savard Date: Mon, 29 Jan 2024 19:15:47 -0500 Subject: [PATCH 33/40] Support InvariatCulture --- .../Localization/Drivers/UserLocalizationDisplayDriver.cs | 7 ++++++- .../Providers/UserLocalizationClaimsProvider.cs | 2 +- .../Providers/UserLocalizationRequestCultureProvider.cs | 6 +++--- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs index dd1e402f568..50b3d646780 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs @@ -40,7 +40,12 @@ public override Task EditAsync(UserLocalizationSettings section, Value = culture }).ToList(); - cultureList.Insert(0, new SelectListItem(){ Text = S["Use site's culture"], Value = "none" }); + cultureList.Insert(0, new SelectListItem() { Text = S["Use site's culture"], Value = "none" }); + + if (cultureList.Where(c => c.Value == "").Any()) + { + cultureList.Where(c => c.Value == "").FirstOrDefault().Value = "invariant"; + } model.SelectedCulture = section.Culture; model.CultureList = cultureList; diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationClaimsProvider.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationClaimsProvider.cs index 7fc7aad81e0..0f2961794d0 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationClaimsProvider.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationClaimsProvider.cs @@ -28,7 +28,7 @@ public Task GenerateAsync(IUser user, ClaimsIdentity claims) if (localizationSetting.Culture != "none") { - claims.AddClaim(new Claim(CultureClaimType, localizationSetting.Culture ?? "")); + claims.AddClaim(new Claim(CultureClaimType, localizationSetting.Culture == "invariant" ? "" : localizationSetting.Culture)); } } diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs index 6c921df8e41..c07bba5e7f3 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs @@ -17,13 +17,13 @@ public override Task DetermineProviderCultureResult(HttpC return NullProviderCultureResult; } - var userCulture = httpContext.User.GetCulture(); + var userCulture = httpContext.User.GetCulture(); // String.Empty here means that it did not find the Culture Claim. - if (string.IsNullOrWhiteSpace(userCulture)) + if (String.IsNullOrWhiteSpace(userCulture)) { return NullProviderCultureResult; } - return Task.FromResult(new ProviderCultureResult(userCulture)); + return Task.FromResult(new ProviderCultureResult(userCulture == "invariant" ? "" : userCulture)); } } From d90704d085c7e2a0f61f0518f90e204e3f11deb4 Mon Sep 17 00:00:00 2001 From: Jasmin Savard Date: Mon, 29 Jan 2024 19:22:29 -0500 Subject: [PATCH 34/40] Constants --- .../OrchardCore.Users/Localization/Constants.cs | 7 +++++++ .../Localization/Drivers/UserLocalizationDisplayDriver.cs | 3 ++- .../Providers/UserLocalizationClaimsProvider.cs | 2 +- .../Providers/UserLocalizationRequestCultureProvider.cs | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 src/OrchardCore.Modules/OrchardCore.Users/Localization/Constants.cs diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Constants.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Constants.cs new file mode 100644 index 00000000000..1639dd31efd --- /dev/null +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Constants.cs @@ -0,0 +1,7 @@ +namespace OrchardCore.Users.Localization +{ + public static class Constants + { + public const string Invariant = "invariant"; + } +} diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs index 50b3d646780..14cff7eb00b 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs @@ -42,9 +42,10 @@ public override Task EditAsync(UserLocalizationSettings section, cultureList.Insert(0, new SelectListItem() { Text = S["Use site's culture"], Value = "none" }); + // If Invariant Culture is installed as a supported culture we bind it to a different culture code than String.Empty. if (cultureList.Where(c => c.Value == "").Any()) { - cultureList.Where(c => c.Value == "").FirstOrDefault().Value = "invariant"; + cultureList.Where(c => c.Value == "").FirstOrDefault().Value = Constants.Invariant; } model.SelectedCulture = section.Culture; diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationClaimsProvider.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationClaimsProvider.cs index 0f2961794d0..c29e85fba50 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationClaimsProvider.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationClaimsProvider.cs @@ -28,7 +28,7 @@ public Task GenerateAsync(IUser user, ClaimsIdentity claims) if (localizationSetting.Culture != "none") { - claims.AddClaim(new Claim(CultureClaimType, localizationSetting.Culture == "invariant" ? "" : localizationSetting.Culture)); + claims.AddClaim(new Claim(CultureClaimType, localizationSetting.Culture == Constants.Invariant ? "" : localizationSetting.Culture)); } } diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs index c07bba5e7f3..a828f5b1cf9 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs @@ -24,6 +24,6 @@ public override Task DetermineProviderCultureResult(HttpC return NullProviderCultureResult; } - return Task.FromResult(new ProviderCultureResult(userCulture == "invariant" ? "" : userCulture)); + return Task.FromResult(new ProviderCultureResult(userCulture == Constants.Invariant ? "" : userCulture)); } } From 6cfc3247ee0626fb3a6ab675a15a0972e4cbf6b3 Mon Sep 17 00:00:00 2001 From: Jasmin Savard Date: Wed, 31 Jan 2024 22:29:35 -0500 Subject: [PATCH 35/40] Update src/docs/releases/1.9.0.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Zoltán Lehóczky --- src/docs/releases/1.9.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/docs/releases/1.9.0.md b/src/docs/releases/1.9.0.md index 3284c752f54..1dec439b2f4 100644 --- a/src/docs/releases/1.9.0.md +++ b/src/docs/releases/1.9.0.md @@ -91,5 +91,5 @@ public class AdminMenu : INavigationProvider ## Users Module -Added new user localization feature that allows to set default culture per user in the admin UI. +Added a new User Localization feature that allows to be able to configure the culture per user from the admin UI. From 98f21f47aaaa6be8cc8c54a08fc03e8018032cbf Mon Sep 17 00:00:00 2001 From: Jasmin Savard Date: Wed, 31 Jan 2024 22:34:37 -0500 Subject: [PATCH 36/40] Constants => UserLocalizationConstants --- .../Localization/Drivers/UserLocalizationDisplayDriver.cs | 2 +- .../Localization/Providers/UserLocalizationClaimsProvider.cs | 2 +- .../Providers/UserLocalizationRequestCultureProvider.cs | 2 +- .../Localization/{Constants.cs => UserLocalizationConstants.cs} | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename src/OrchardCore.Modules/OrchardCore.Users/Localization/{Constants.cs => UserLocalizationConstants.cs} (68%) diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs index 14cff7eb00b..9d07457de8c 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs @@ -45,7 +45,7 @@ public override Task EditAsync(UserLocalizationSettings section, // If Invariant Culture is installed as a supported culture we bind it to a different culture code than String.Empty. if (cultureList.Where(c => c.Value == "").Any()) { - cultureList.Where(c => c.Value == "").FirstOrDefault().Value = Constants.Invariant; + cultureList.Where(c => c.Value == "").FirstOrDefault().Value = UserLocalizationConstants.Invariant; } model.SelectedCulture = section.Culture; diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationClaimsProvider.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationClaimsProvider.cs index c29e85fba50..c98bc4f3649 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationClaimsProvider.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationClaimsProvider.cs @@ -28,7 +28,7 @@ public Task GenerateAsync(IUser user, ClaimsIdentity claims) if (localizationSetting.Culture != "none") { - claims.AddClaim(new Claim(CultureClaimType, localizationSetting.Culture == Constants.Invariant ? "" : localizationSetting.Culture)); + claims.AddClaim(new Claim(CultureClaimType, localizationSetting.Culture == UserLocalizationConstants.Invariant ? "" : localizationSetting.Culture)); } } diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs index a828f5b1cf9..d57fae3f923 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Providers/UserLocalizationRequestCultureProvider.cs @@ -24,6 +24,6 @@ public override Task DetermineProviderCultureResult(HttpC return NullProviderCultureResult; } - return Task.FromResult(new ProviderCultureResult(userCulture == Constants.Invariant ? "" : userCulture)); + return Task.FromResult(new ProviderCultureResult(userCulture == UserLocalizationConstants.Invariant ? "" : userCulture)); } } diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Constants.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/UserLocalizationConstants.cs similarity index 68% rename from src/OrchardCore.Modules/OrchardCore.Users/Localization/Constants.cs rename to src/OrchardCore.Modules/OrchardCore.Users/Localization/UserLocalizationConstants.cs index 1639dd31efd..611c89cabf7 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Constants.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/UserLocalizationConstants.cs @@ -1,6 +1,6 @@ namespace OrchardCore.Users.Localization { - public static class Constants + public static class UserLocalizationConstants { public const string Invariant = "invariant"; } From 979584e8319f9e04c77325d7f2292fde771d900a Mon Sep 17 00:00:00 2001 From: Jasmin Savard Date: Wed, 31 Jan 2024 22:50:07 -0500 Subject: [PATCH 37/40] Add doc --- src/docs/reference/modules/Users/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/docs/reference/modules/Users/README.md b/src/docs/reference/modules/Users/README.md index 14e223d3961..c2c3fa4c398 100644 --- a/src/docs/reference/modules/Users/README.md +++ b/src/docs/reference/modules/Users/README.md @@ -15,11 +15,16 @@ The module contains the following features apart from the base feature: - Two-Factor Authentication Services: Provices Two-factor core services. This feature cannot be manually enabled or disable as it is enabled by dependency on demand. - Two-Factor Email Method: Allows users to two-factor authenticate using an email. - Two-Factor Authenticator App Method: Allows users to two-factor authenticate using any Authenticator App. +- User Localization: Allows ability to configure user culture per user from admin UI. ## Two-factor Authentication Starting with version 1.7, OrchardCore is shipped with everything you need to secure your app with two-factor authentication. To use two-factor authentication, simply enable "Two-Factor Email Method" and/or "Two-Factor Authenticator App Method" features. You can configure the process based on your need by navigating to `Security` >> `Settings` >> `User Login`. Click on the "Two-Factor Authentication" tab and update the settings as needed. +## User Localization + +This feature adds a `RequestCultureProvider` that will retrieve the current user culture from it's claims. This feature will set a new user claim with a `CultureClaimType` named "culture". The feature adds the ability to configure the culture per user from the admin UI. It also have a culture option to fallback to other ASP.NET Request Culture Providers by simply setting the user culture to "Use site's culture" which will also be the selected default value. + ## Custom Paths If you want to specify custom paths to access the authentication related urls, you can change them by using this option in the appsettings.json: From 1eff31deafb0ec34333c2a0b04da23878255c67d Mon Sep 17 00:00:00 2001 From: Jasmin Savard Date: Mon, 12 Feb 2024 12:09:45 -0500 Subject: [PATCH 38/40] Update src/docs/reference/modules/Users/README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Zoltán Lehóczky --- src/docs/reference/modules/Users/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/docs/reference/modules/Users/README.md b/src/docs/reference/modules/Users/README.md index c2c3fa4c398..05de03d4dc1 100644 --- a/src/docs/reference/modules/Users/README.md +++ b/src/docs/reference/modules/Users/README.md @@ -23,7 +23,9 @@ Starting with version 1.7, OrchardCore is shipped with everything you need to se ## User Localization -This feature adds a `RequestCultureProvider` that will retrieve the current user culture from it's claims. This feature will set a new user claim with a `CultureClaimType` named "culture". The feature adds the ability to configure the culture per user from the admin UI. It also have a culture option to fallback to other ASP.NET Request Culture Providers by simply setting the user culture to "Use site's culture" which will also be the selected default value. +The feature adds the ability to configure the culture per user from the admin UI. + +This feature adds a `RequestCultureProvider` to retrieve the current user culture from its claims. This feature will set a new user claim with a `CultureClaimType` named "culture". It also has a culture option to fall back to other ASP.NET Request Culture Providers by simply setting the user culture to "Use site's culture" which will also be the selected default value. ## Custom Paths From 3b986b1c69b8c31771074aa39b5cf084f6e1bea4 Mon Sep 17 00:00:00 2001 From: Jasmin Savard Date: Mon, 12 Feb 2024 12:16:05 -0500 Subject: [PATCH 39/40] Update src/OrchardCore.Modules/OrchardCore.Users/Localization/ViewModel/UserLocalizationViewModel.cs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sébastien Ros --- .../Localization/ViewModel/UserLocalizationViewModel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/ViewModel/UserLocalizationViewModel.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/ViewModel/UserLocalizationViewModel.cs index 2264b399aeb..4641d53d1dc 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/ViewModel/UserLocalizationViewModel.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/ViewModel/UserLocalizationViewModel.cs @@ -9,5 +9,5 @@ public class UserLocalizationViewModel public string SelectedCulture { get; set; } [BindNever] - public IEnumerable CultureList { get; set; } = new List(); + public List CultureList { get; set; } = []; } From bf7246c0a1882835620f29ac9317a80a9b3fd951 Mon Sep 17 00:00:00 2001 From: Jasmin Savard Date: Mon, 12 Feb 2024 12:20:15 -0500 Subject: [PATCH 40/40] Update src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sébastien Ros --- .../Localization/Drivers/UserLocalizationDisplayDriver.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs index 9d07457de8c..3f849bdf7cc 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Localization/Drivers/UserLocalizationDisplayDriver.cs @@ -43,9 +43,10 @@ public override Task EditAsync(UserLocalizationSettings section, cultureList.Insert(0, new SelectListItem() { Text = S["Use site's culture"], Value = "none" }); // If Invariant Culture is installed as a supported culture we bind it to a different culture code than String.Empty. - if (cultureList.Where(c => c.Value == "").Any()) + var emptyCulture = cultureList.FirstOrDefault(c => c.Value == ""); + if (emptyCulture != null) { - cultureList.Where(c => c.Value == "").FirstOrDefault().Value = UserLocalizationConstants.Invariant; + emptyCulture.Value = UserLocalizationConstants.Invariant; } model.SelectedCulture = section.Culture;