使用 Core 2.2 本地化的 Razor 页面不起作用

Posted

技术标签:

【中文标题】使用 Core 2.2 本地化的 Razor 页面不起作用【英文标题】:Razor Page using Core 2.2 Localization not working 【发布时间】:2019-09-17 21:26:00 【问题描述】:

我有一个 .NET Core 2.2 项目

我的启动中有以下代码

配置服务方法

services.AddLocalization(options => options.ResourcesPath = "Resources");
services.AddMvc()
    .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
    .AddDataAnnotationsLocalization();

配置方式

       app.UseStaticFiles();
        app.UseCookiePolicy();
        var supportedCultures = new[]
        
            new CultureInfo("en-US"),
            new CultureInfo("es-ES"),
        ;
        app.UseRequestLocalization(new RequestLocalizationOptions
        
            DefaultRequestCulture = new RequestCulture("en-US"),
            // Formatting numbers, dates, etc.
            SupportedCultures = supportedCultures,
            // UI strings that we have localized.
            SupportedUICultures = supportedCultures
        );
        app.UseStaticFiles();
        app.UseStaticFiles();
        app.UseMvc();

我在我的索引 Page.cshtml 中有

 @page
 @using Microsoft.AspNetCore.Mvc.Localization
 @model IndexModel
 @inject IViewLocalizer Localizer
 @
     ViewData["Title"] = "Error";
 
 <h3>Welcome to ASP.NET Localization</h3>
 <p>This is Localization</p>
 <h2>@Localizer["Overview"]</h2>

我在我的 Index.cshtml.cs 中使用以下方法

    private readonly IStringLocalizer<IndexModel> Localizer;
    public IndexModel(IStringLocalizer<IndexModel> localizer)
    
        Localizer = localizer;
    

我已经创建了一个资源文件

\Resources\Index.es.resx

这目前有一个概览键。

我加载应用程序并尝试将文化更改为

 https://localhost:44345/?culture=es-ES

但字符串并没有像我预期的那样改变!

【问题讨论】:

您需要更改浏览器的语言才能使代码正常工作 很酷,但我们希望用户能够选择?最终我需要一个下拉列表! 那么我认为您可以重新加载页面,以便用户看到更改 我正在通过将 ?culture=es-ES 添加到 url 来更改上面的 url,但它不会改变语言 生病检查 QueryStringRequestCultureProvider 【参考方案1】:

我用的是dotnet core2.1,步骤应该是一样的。

创建路线文化提供者:
public class RouteValueRequestCultureProvider : IRequestCultureProvider
    
        private readonly CultureInfo[] _cultures;

        public RouteValueRequestCultureProvider(CultureInfo[] cultures)
        
            _cultures = cultures;
        

        /// <summary>
        /// get culture route value from path string, 
        /// </summary>
        /// <param name="httpContext"></param>
        /// <returns>ProviderCultureResult depends on path culture route parameter, or default culture</returns>
        public Task<ProviderCultureResult> DetermineProviderCultureResult(HttpContext httpContext)
        
            var defaultCulture = "en";

            var path = httpContext.Request.Path;

            if (string.IsNullOrWhiteSpace(path))
            
                return Task.FromResult(new ProviderCultureResult(defaultCulture));
            

            var routeValues = httpContext.Request.Path.Value.Split('/');
            if (routeValues.Count() <= 1)
            
                return Task.FromResult(new ProviderCultureResult(defaultCulture));
            

            if (!_cultures.Any(x => x.Name.ToLower() == routeValues[1].ToLower()))
            
                return Task.FromResult(new ProviderCultureResult(defaultCulture));
            

            return Task.FromResult(new ProviderCultureResult(routeValues[1]));
        
    

RouteValueRequestCultureProvider 添加到文化提供者列表的顶部:
services.Configure<RequestLocalizationOptions>(ops =>
            
                ops.DefaultRequestCulture = new RequestCulture("en");
                ops.SupportedCultures = cultures.OrderBy(x=>x.EnglishName).ToList();
                ops.SupportedUICultures = cultures.OrderBy(x => x.EnglishName).ToList();

                // add RouteValueRequestCultureProvider to the beginning of the providers list. 
                ops.RequestCultureProviders.Insert(0, 
                    new RouteValueRequestCultureProvider(cultures));
            );

为路由创建一个文化模板,所以我们得到的 url 为:

http://mywebaddress.com/en-ES/

public class CultureTemplateRouteModelConvention : IPageRouteModelConvention
    
        public void Apply(PageRouteModel model)
        
            var selectorCount = model.Selectors.Count;
            for (var i = 0; i < selectorCount; i++)
            
                var selector = model.Selectors[i];
                model.Selectors.Add(new SelectorModel
                
                    AttributeRouteModel = new AttributeRouteModel
                    
                        Order = -1,
                        Template = AttributeRouteModel.CombineTemplates(
                      "culture?",
                      selector.AttributeRouteModel.Template),
                    
                );
            
        
    

配置服务以使用文化路线模板:
services.AddMvc()
        .AddRazorPagesOptions(o => 
            o.Conventions.Add(new CultureTemplateRouteModelConvention());
        );

查看完整教程here。

要创建语言下拉菜单,您可以按照here 的说明手动创建它,也可以使用this nugget package 以更少的代码自动创建它:)

【讨论】:

这根本不能回答问题【参考方案2】:

剃须刀页面的本地化应位于Pages 文件夹中。所以Index razor 页面的本地化应该位于

\Resources\Pages\Index.es.resx

【讨论】:

【参考方案3】:

在链接教程中,您使用的是共享资源,因此您不应在 Resources for Pages 等中创建子文件夹,而只需将每个 resx 文件命名为 ViewResource.xx.resx。

【讨论】:

以上是关于使用 Core 2.2 本地化的 Razor 页面不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Asp .NET Core 2.2 Razor 页面布局和局部

ASP.NET Core 2.2 Razor 页面中的自定义路由

Asp .Net Core 2.2 Razor Pages Ajax Call Post 不工作

使用 Razor 时如何在每个请求处传输 JWT 令牌(.NET CORE 2.2 MVC)

如何在asp.net core razor pages 2.2中设置日期格式和文化

使用 ASP NET Core 2.0 Razor 页面进行路由