Как создать локализованные маршруты и селектор языка в ASP. NET Core 3.1? - PullRequest
0 голосов
/ 02 апреля 2020

Как ладья ie, я бы хотел сделать 3 вещи:

  1. Создание локализованных маршрутов, таких как: www.mywebsite.com/fr/controller/action/ скрытие культуры в URL, если задана культура по умолчанию (EN) www.mywebsite.com/controller/action/

  2. Сохранить предпочтения культуры пользователя в кулинаре ie, чтобы автоматически использовать его при следующем посещении

  3. Создать селектор языка

Я могу заставить эти 3 пункта работать отдельно, но я не могу использовать их все вместе. Я действительно не знаю, как поступить. (используя контроллер или фильтр ...)

Для маршрутов, которые я сделал ниже, похоже, работает, за исключением того, что язык по умолчанию все еще появляется в URL. Мне кажется, это не совсем чисто, я уверен, что есть лучший способ добиться этого.

    public class CultureFilter : IRequestCultureProvider
{
    private readonly CultureInfo defaultCulture;
    private readonly CultureInfo defaultUICulture;

    public CultureFilter(RequestCulture requestCulture)
    {
        this.defaultCulture = requestCulture.Culture;
        this.defaultUICulture = requestCulture.UICulture;
    }

    public Task<ProviderCultureResult> DetermineProviderCultureResult(HttpContext httpContext)
    {
        //Parsing language from url path, which looks like "/en/home/index"
        PathString url = httpContext.Request.Path;

        // Test any culture in route
        if (url.ToString().Length <= 1)
        {
            // Set default Culture and default UICulture
            return Task.FromResult<ProviderCultureResult>(new ProviderCultureResult(this.defaultCulture.TwoLetterISOLanguageName, this.defaultUICulture.TwoLetterISOLanguageName));
        }

        var parts = httpContext.Request.Path.Value.Split('/');
        var culture = parts[1];

        // Test if the culture is properly formatted
        if (!Regex.IsMatch(culture, @"^[a-z]{2}(-[A-Z]{2})*$"))
        {
            // Set default Culture and default UICulture
            return Task.FromResult<ProviderCultureResult>(new ProviderCultureResult(this.defaultCulture.TwoLetterISOLanguageName, this.defaultUICulture.TwoLetterISOLanguageName));
        }

        // Set Culture and UICulture from route culture parameter
        return Task.FromResult<ProviderCultureResult>(new ProviderCultureResult(culture, culture));
    }
}

Для повара ie я добавляю идею использовать контроллер, вызываемый в моем переключателе языка, но опять же, Я уверен, что это не правильный способ сделать это. И мое значение повара ie довольно странное.

Может быть, для обработки этих трех точек будет достаточно простого фильтра?

public class CultureController : Controller
{
    [HttpPost]
    public IActionResult SelectCulture(string culture, string returnUrl)
    {
        Response.Cookies.Append(
            CookieRequestCultureProvider.DefaultCookieName,
            CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
            new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) }
        );

        return LocalRedirect(returnUrl);
    }
}

Startup.cs

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddRouting(options => options.LowercaseUrls = true);
        services.AddLocalization(options => options.ResourcesPath = "Resources");

        services
            .AddControllersWithViews()
            .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
            .AddDataAnnotationsLocalization();

        services.Configure<RequestLocalizationOptions>(options =>
        {
            var cultures = new[]
            {
                new CultureInfo("en"),
                new CultureInfo("fr"),
                new CultureInfo("es")
            };

            options.DefaultRequestCulture = new RequestCulture(culture: "en", uiCulture: "en");
            options.SupportedCultures = cultures;
            options.SupportedUICultures = cultures;

            options.RequestCultureProviders.Insert(0, new CultureFilter(options.DefaultRequestCulture));
        });
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseRequestLocalization();

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Static/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseRouting();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "localization",
                pattern: "{culture=en}/{controller=Static}/{action=Index}/{id?}");

            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Static}/{action=Index}/{id?}");
        });
    }
}

Спасибо за вашу помощь.

...