ToB企服应用市场:ToB评测及商务社交产业平台

标题: dotnet CultureInfo遇到欧洲如俄文小数点是逗号想转点的解决办法 [打印本页]

作者: 缠丝猫    时间: 2025-1-22 20:02
标题: dotnet CultureInfo遇到欧洲如俄文小数点是逗号想转点的解决办法
如题,当CultureInfo是俄文(ru-RU)时,浮点数中的点是用逗号表达的,如1.1会显示成1,1,造成很多的麻烦,当然假如全系统中全部采纳逗号作为浮点也没问题,只要用户担当就可以,但有时须要继承用点号,那么解决办法如下。
1. 修改DefaultThreadCurrentCulture

我们知道CultureInfo.CurrentCulture静态变量是跟踪线程的,每个现场都有独立的CultureInfo.CurrentCulture值,它会决定当火线程的文化区域,包括时间、数字等的显示格式,这一步处理就会解决大部分浮点是逗号的问题。
  1. var cultureInfo = new CultureInfo("ru-RU");
  2. cultureInfo.NumberFormat.NumberDecimalSeparator = ".";
  3. CultureInfo.DefaultThreadCurrentCulture = CultureInfo.ReadOnly(cultureInfo);
  4. CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.ReadOnly(cultureInfo);
复制代码
2. aspnetcore中心件修改CultureInfo

这一步是今天想写这个文章的原因,由于找了很长时间才发现是这里导致的问题,虽然经过上面一步的修改,我们大部分业务代码不会再用逗号了,但是当我们在aspnetcore中启用了RequestLocalizationMiddleware,就会导致例如返回json时浮点数tostring或者拼接等还是逗号的问题。
修改的办法也很简单,启动时加如下代码就可以。
  1. services.Configure<RequestLocalizationOptions>(options=>{
  2.   var cultures = options.SupportedCultures.Where(e => e.NumberFormat.NumberDecimalSeparator != ".").ToList();
  3.   foreach(var c in cultures)
  4.   {
  5.     c.NumberFormat.NumberDecimalSeparator = ".";
  6.   }
  7. });
复制代码
原因是由于aspnetcore中的这个中心件代码导致的,为了说明问题简化了代码(代码来自微软官方github),注意Invoke和SetCurrentThreadCulture方法是关键问题所在。
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT license.
  3. using System.Globalization;
  4. using System.Linq;
  5. using Microsoft.AspNetCore.Builder;
  6. using Microsoft.AspNetCore.Http;
  7. using Microsoft.Extensions.Logging;
  8. using Microsoft.Extensions.Options;
  9. using Microsoft.Extensions.Primitives;
  10. namespace Microsoft.AspNetCore.Localization;
  11. /// <summary>
  12. /// Enables automatic setting of the culture for <see cref="HttpRequest"/>s based on information
  13. /// sent by the client in headers and logic provided by the application.
  14. /// </summary>
  15. public class RequestLocalizationMiddleware
  16. {
  17.     private const int MaxCultureFallbackDepth = 5;
  18.     private readonly RequestDelegate _next;
  19.     private readonly RequestLocalizationOptions _options;
  20.     private readonly ILogger _logger;
  21.     /// <summary>
  22.     /// Creates a new <see cref="RequestLocalizationMiddleware"/>.
  23.     /// </summary>
  24.     /// <param name="next">The <see cref="RequestDelegate"/> representing the next middleware in the pipeline.</param>
  25.     /// <param name="options">The <see cref="RequestLocalizationOptions"/> representing the options for the
  26.     /// <see cref="RequestLocalizationMiddleware"/>.</param>
  27.     /// <param name="loggerFactory">The <see cref="ILoggerFactory"/> used for logging.</param>
  28.     public RequestLocalizationMiddleware(RequestDelegate next, IOptions<RequestLocalizationOptions> options, ILoggerFactory loggerFactory)
  29.     {
  30.         ArgumentNullException.ThrowIfNull(options);
  31.         _next = next ?? throw new ArgumentNullException(nameof(next));
  32.         _logger = loggerFactory?.CreateLogger<RequestLocalizationMiddleware>() ?? throw new ArgumentNullException(nameof(loggerFactory));
  33.         _options = options.Value;
  34.     }
  35.     /// <summary>
  36.     /// Invokes the logic of the middleware.
  37.     /// </summary>
  38.     /// <param name="context">The <see cref="HttpContext"/>.</param>
  39.     /// <returns>A <see cref="Task"/> that completes when the middleware has completed processing.</returns>
  40.     public async Task Invoke(HttpContext context)
  41.     {
  42.         ArgumentNullException.ThrowIfNull(context);
  43.         var requestCulture = _options.DefaultRequestCulture;
  44. ...
  45.         if (_options.RequestCultureProviders != null)
  46.         {
  47.             foreach (var provider in _options.RequestCultureProviders)
  48.             {
  49. ...
  50.                 CultureInfo? cultureInfo = null;
  51.                 CultureInfo? uiCultureInfo = null;
  52.                 if (_options.SupportedCultures != null)
  53.                 {
  54.                     cultureInfo = GetCultureInfo(
  55.                         cultures,
  56.                         _options.SupportedCultures,
  57.                         _options.FallBackToParentCultures);
  58.                     if (cultureInfo == null)
  59.                     {
  60.                         _logger.UnsupportedCultures(provider.GetType().Name, cultures);
  61.                     }
  62.                 }
  63. ...
  64.                 cultureInfo ??= _options.DefaultRequestCulture.Culture;
  65.                 uiCultureInfo ??= _options.DefaultRequestCulture.UICulture;
  66.                 var result = new RequestCulture(cultureInfo, uiCultureInfo);
  67.                 requestCulture = result;
  68.                 winningProvider = provider;
  69.                 break;
  70.             }
  71.         }
  72. ...
  73.         SetCurrentThreadCulture(requestCulture);
  74. ...
  75.         await _next(context);
  76.     }
  77.     private static void SetCurrentThreadCulture(RequestCulture requestCulture)
  78.     {
  79.         CultureInfo.CurrentCulture = requestCulture.Culture;
  80.         CultureInfo.CurrentUICulture = requestCulture.UICulture;
  81.     }
  82. ...
  83. }
复制代码



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4