【问题标题】:IViewLocalizer returns the wrong languageIViewLocalizer 返回错误的语言
【发布时间】:2017-05-08 16:44:53
【问题描述】:

我正在尝试构建一个应该以英语和德语提供的 ASP.NET Core 应用程序。我的问题是IViewLocalizer 总是返回德语文本,即使文化设置为英语。如何获得适合当前文化的文本?

Startup.cs

public void ConfigureServices(IServiceCollection services)
{       
    services.AddLocalization(opt => opt.ResourcesPath = "Resources");
    services.AddMvc()
        .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix);
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    var cultures = new[] { new CultureInfo("en"), new CultureInfo("de") };
    app.UseRequestLocalization(new RequestLocalizationOptions 
    {
        DefaultRequestCulture = new RequestCulture("en"),
        SupportedCultures = cultures,
        SupportedUICultures = cultures                
    });

    app.UseMvc(routes =>
    {
          routes.MapRoute(
               name: "default",
               template: "{controller=Home}/{action=Index}/{id?}");
    });
}

HomeController.cs

public class HomeController : Controller
{
    public IActionResult Index()
    {
        return View();
    }
}

索引.cshtml

<!DOCTYPE html>
@using Microsoft.AspNetCore.Mvc.Localization;
@inject IViewLocalizer Localizer
<html>
    <body>
        <h1>@Localizer["Hello, World!"]</h1>
        <ul>
            <li>CurrentCulture: @System.Globalization.CultureInfo.CurrentCulture</li>
            <li>CurrentUICulture: @System.Globalization.CultureInfo.CurrentUICulture</li>
        </ul>
    </body>
</html>

资源文件位于Resources\Views.Home.Index.de.resx

预期输出:

你好世界! CurrentCulture: zh CurrentUICulture: zh

页面输出:

你好世界! CurrentCulture: zh CurrentUICulture: zh

请求标头:

GET / HTTP/1.1
Host: localhost:61904
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8,es;q=0.6,de;q=0.4

【问题讨论】:

标签: c# localization asp.net-core asp.net-core-mvc


【解决方案1】:

从昨天开始我就遇到了同样的问题。 看起来 LocalizationProvider 未能设置正确的文化。 实现自定义 LocalizationProvider 后,IViewLocalizer 开始完美地适用于 ViewsViewComponents

我还必须通过以下方式在 url 中实现语言:

http://somedomain.com/&lt;2-letter-iso-language-name&gt;/controller/action

这是我所做的:

Startup.cs

public static string defaultCulture = "uk-UA";

public static List<CultureInfo> supportedCultures
{
    get
    {
        return new List<CultureInfo> {
            new CultureInfo("en-US"),
            new CultureInfo("uk-UA"),
            new CultureInfo("de-DE") };
    }
}

ConfigureServices 方法中,我添加了CultureToUrlActionFilter()。它从 url 检索 2 个字母的语言代码并设置正确的CultureInfo。如果 Url 包含不允许的文化代码,则会重定向到默认文化。

public void ConfigureServices(IServiceCollection services)
{
    services
        .AddLocalization(options => options.ResourcesPath = "Resources")
        .AddMvc(options => { options.Filters.Add(new CultureToUrlActionFilter()); })
        .AddViewLocalization()
        .AddDataAnnotationsLocalization();
}

在 Configure 方法中,我设置了自定义本地化提供程序并将其作为第一个插入到提供程序队列中:

var options = new RequestLocalizationOptions() { 
    DefaultRequestCulture = new RequestCulture(defaultCulture),
    SupportedCultures = supportedCultures, 
    SupportedUICultures = supportedCultures };
options.RequestCultureProviders.Insert(0, new UrlCultureProvider());
app.UseRequestLocalization(options);

如果网址在域名后不包含文化代码,我会重定向到http://somedomain/&lt;2-letter-culture-code&gt;(到默认文化)。网址必须始终指定文化。

路线:

app.UseMvc(routes => {
     routes.MapRoute("home_empty", "", defaults: new { culture="", controller = "Home", action = "Redirect" });
     routes.MapRoute("home", "{culture}", defaults: new { controller = "Home", action = "Index" });

我在 HomeController 中进行重定向,重定向操作

HomeController.cs

public IActionResult Redirect() { 
    return RedirectToAction("Index", new { culture = Startup.defaultCulture }); 
}

UrlCultureProvider.cs

using Microsoft.AspNetCore.Localization;
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using System.Globalization;

namespace astika.Models
{
public class UrlCultureProvider: IRequestCultureProvider {

    public Task<ProviderCultureResult> DetermineProviderCultureResult(HttpContext httpContext)
    {
        if (httpContext == null) throw new ArgumentNullException(nameof(httpContext));
        var pathSegments = httpContext.Request.Path.Value.Trim('/').Split('/');

        string url_culture = pathSegments[0].ToLower();

        CultureInfo ci = Startup.supportedCultures.Find(x => x.TwoLetterISOLanguageName.ToLower() == url_culture);
        if (ci == null) ci = new CultureInfo(Startup.defaultCulture);

        CultureInfo.CurrentCulture = CultureInfo.CurrentUICulture = ci; 

        var result = new ProviderCultureResult(ci.Name, ci.Name);
        return Task.FromResult(result);
    }
}
}

CultureToUrlActionFilter.cs

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Routing;
using System;
using System.Globalization;

namespace astika.Models
{
public class CultureToUrlActionFilter : IActionFilter
{
    public void OnActionExecuted(ActionExecutedContext context) { }

    public void OnActionExecuting(ActionExecutingContext context)
    {
        bool redirect = false;
        string culture = context.RouteData.Values["culture"].ToString().ToLower();

        redirect = String.IsNullOrEmpty(culture);

        if (!redirect)
        {
            try
            {
                CultureInfo ci = new CultureInfo(culture);
                redirect = Startup.supportedCultures.FindIndex(x => x.TwoLetterISOLanguageName.ToLower() == culture) < 0;
            }
            catch
            {
                redirect = true;
            }
        }


        if (redirect)
        {
            CultureInfo cid = new CultureInfo(Startup.defaultCulture);
            context.Result = new RedirectToRouteResult(new RouteValueDictionary(new { culture = cid.TwoLetterISOLanguageName, controller = "Home", action = "Index" }));
        }
    }
}
}

resx 文件都位于同一个文件夹中 /Resources/Views.Home.Index.en.resx /Resources/Views.Home.Index.de.resx /Resources/Views.Shared.Components.Navigation.Default.en.resx 等等

【讨论】:

【解决方案2】:

如果有人在使用 ASP.NET core 1.1 或更高版本时遇到此问题,请尝试将 &lt;NeutralLanguage&gt;YOUR_DEFAULT_LANGUAGE&lt;/NeutralLanguage&gt; 添加到您的 .csproj 中,如下所示:

<PropertyGroup>
<TargetFramework>netcoreapp1.1</TargetFramework>
<ApplicationIcon />
<Win32Resource />
<NeutralLanguage>en</NeutralLanguage>
</PropertyGroup>

它解决了我的问题,现在可以正常工作了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-18
    • 2014-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多