diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpAspNetCoreMvcQueryStringCultureReplacement.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpAspNetCoreMvcQueryStringCultureReplacement.cs new file mode 100644 index 0000000000..900d1c5de7 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpAspNetCoreMvcQueryStringCultureReplacement.cs @@ -0,0 +1,33 @@ +using System; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.AspNetCore.Mvc.Localization +{ + public class AbpAspNetCoreMvcQueryStringCultureReplacement : IQueryStringCultureReplacement, ITransientDependency + { + public virtual Task ReplaceAsync(QueryStringCultureReplacementContext context) + { + if (!string.IsNullOrWhiteSpace(context.ReturnUrl)) + { + if (context.ReturnUrl.Contains("culture=", StringComparison.OrdinalIgnoreCase) && + context.ReturnUrl.Contains("ui-Culture=", StringComparison.OrdinalIgnoreCase)) + { + context.ReturnUrl = Regex.Replace( + context.ReturnUrl, + "culture=[A-Za-z-]+?&", + $"culture={context.RequestCulture.Culture}&", + RegexOptions.Compiled | RegexOptions.IgnoreCase); + + context.ReturnUrl = Regex.Replace( + context.ReturnUrl, "ui-culture=[A-Za-z-]+?$", + $"ui-culture={context.RequestCulture.UICulture}", + RegexOptions.Compiled | RegexOptions.IgnoreCase); + } + } + + return Task.CompletedTask; + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpLanguagesController.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpLanguagesController.cs index 6b73aa26da..b0fa63e4f5 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpLanguagesController.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpLanguagesController.cs @@ -1,6 +1,7 @@ using Microsoft.AspNetCore.Localization; using Microsoft.AspNetCore.Mvc; using System; +using System.Threading.Tasks; using Microsoft.AspNetCore.RequestLocalization; using Volo.Abp.Localization; @@ -12,8 +13,15 @@ namespace Volo.Abp.AspNetCore.Mvc.Localization [ApiExplorerSettings(IgnoreApi = true)] public class AbpLanguagesController : AbpController { + protected IQueryStringCultureReplacement QueryStringCultureReplacement { get; } + + public AbpLanguagesController(IQueryStringCultureReplacement queryStringCultureReplacement) + { + QueryStringCultureReplacement = queryStringCultureReplacement; + } + [HttpGet] - public IActionResult Switch(string culture, string uiCulture = "", string returnUrl = "") + public virtual async Task Switch(string culture, string uiCulture = "", string returnUrl = "") { if (!CultureHelper.IsValidCultureCode(culture)) { @@ -25,15 +33,18 @@ namespace Volo.Abp.AspNetCore.Mvc.Localization new RequestCulture(culture, uiCulture) ); - if (!string.IsNullOrWhiteSpace(returnUrl)) + var context = new QueryStringCultureReplacementContext(HttpContext, new RequestCulture(culture, uiCulture), returnUrl); + await QueryStringCultureReplacement.ReplaceAsync(context); + + if (!string.IsNullOrWhiteSpace(context.ReturnUrl)) { - return Redirect(GetRedirectUrl(returnUrl)); + return Redirect(GetRedirectUrl(context.ReturnUrl)); } return Redirect("~/"); } - private string GetRedirectUrl(string returnUrl) + protected virtual string GetRedirectUrl(string returnUrl) { if (returnUrl.IsNullOrEmpty()) { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/IQueryStringCultureReplacement.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/IQueryStringCultureReplacement.cs new file mode 100644 index 0000000000..7cd8113060 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/IQueryStringCultureReplacement.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace Volo.Abp.AspNetCore.Mvc.Localization +{ + public interface IQueryStringCultureReplacement + { + Task ReplaceAsync(QueryStringCultureReplacementContext context); + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/QueryStringCultureReplacementContext.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/QueryStringCultureReplacementContext.cs new file mode 100644 index 0000000000..11437a91ce --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/QueryStringCultureReplacementContext.cs @@ -0,0 +1,21 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Localization; + +namespace Volo.Abp.AspNetCore.Mvc.Localization +{ + public class QueryStringCultureReplacementContext + { + public HttpContext HttpContext { get; } + + public RequestCulture RequestCulture { get; } + + public string ReturnUrl { get; set; } + + public QueryStringCultureReplacementContext(HttpContext httpContext, RequestCulture requestCulture, string returnUrl) + { + HttpContext = httpContext; + RequestCulture = requestCulture; + ReturnUrl = returnUrl; + } + } +}