0

In trying to localize my application, the query string localization has worked and accept language header also working, but routing is not working. Here is my code:

Startup.cs

public static IServiceCollection AddLocalizationServices(this IServiceCollection services, IConfiguration _config)
{
    string defaultCulture = _config.GetValue<string>("DefaultCulture");
    services.AddLocalization(options => options.ResourcesPath = "Resources");
    services.Configure<RequestLocalizationOptions>(
        options =>
        {
            var supportedCultures = new[]
            {
                new CultureInfo("en"),
                new CultureInfo("ar")
            };

            options.DefaultRequestCulture = new RequestCulture(culture: defaultCulture, uiCulture: defaultCulture);
            options.SupportedCultures = supportedCultures;
            options.SupportedUICultures = supportedCultures;

            options.RequestCultureProviders.Insert(0, new RouteDataRequestCultureProvider()
            {
                Options = options,
                RouteDataStringKey = "lang",
                UIRouteDataStringKey = "lang"
            });
            options.RequestCultureProviders.Insert(1, new QueryStringRequestCultureProvider());
            //options.RequestCultureProviders.Insert(2, new CookieRequestCultureProvider());
            options.RequestCultureProviders.Insert(3, new AcceptLanguageHeaderRequestCultureProvider());
        });

    services.Configure<RouteOptions>(options =>
    {
        options.ConstraintMap.Add("lang", typeof(LanguageRouteConstraint));
    });

    return services;
}

public static IApplicationBuilder AddLocalizationBuilder(this IApplicationBuilder app)
{
    var locOptions = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();
    app.UseRequestLocalization(locOptions.Value);

    return app;
}

public void ConfigureServices(IServiceCollection services)
{
    services.AddLocalizationServices(_config);

    services.AddControllersWithViews()
        .AddDataAnnotationsLocalization(options =>
        {
            options.DataAnnotationLocalizerProvider = (type, factory) =>
            {
                var assemblyName = new AssemblyName(typeof(ValidationResource).GetTypeInfo().Assembly.FullName);
                return factory.Create("ValidationResource", assemblyName.Name);
            };
        });
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        //app.ConfigureExceptionHandler();
    }
    else
    {
        //Global error handling instead of try, catch
        app.ConfigureExceptionHandler();

        //app.UseHsts();
    }

    app.AddLocalizationBuilder();

    //app.UseHttpsRedirection();

    app.UseRouting();

    app.UseAuthorization();

    string defaultCulture = _config.GetValue<string>("DefaultCulture");
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{lang:lang}/{controller=Home}/{action=Index}/{id?}");

        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{*catchall}",
            defaults: new { controller = "Home", action = "RedirectToDefaultLanguage", lang = defaultCulture });
    });
}

_ViewImports.cshtml

@using CoreCMS.MVC
@using CoreCMS.Data
@using Microsoft.Extensions.Localization

@inject IStringLocalizer<SharedResource> _loc

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Index.cshtml

@_loc["Title"]

When trying to access website with the following url : http://localhost:14896/en or http://localhost:14896/ar the culture not working but when using this url http://localhost:14896/?culture=ar or http://localhost:14896/?culture=en the culture is working well

Jackdaw
  • 7,626
  • 5
  • 15
  • 33
Ahmad Alaa
  • 767
  • 9
  • 30
  • the code seems fine and should work as long as the route value of `lang` is present in the request. So the first step is try debugging to see if there is actually a route value whose key is `lang`. Also you can try examining the request culture as well (examined via the `CultureInfo.CurrentCulture`) to see if it's actually set as soon as possible, verify that there is not any other code that modifies it to something else. – King King Mar 08 '21 at 13:43
  • i have debugged the app, and the lang route is presents the value from the url without any issue, and there are no other code modifies something else, the routing is working good in all situations except the routing ! – Ahmad Alaa Mar 08 '21 at 13:49
  • to test it, you can place an inline-middleware right after `app.AddLocalizationBuilder()` like this `app.Use((context,next) => { /* examine the CultureInfo.CurrentCulture here */ return next();})`. That way you are at least sure that the middleware before worked or not. – King King Mar 08 '21 at 13:55
  • i have tested the culture in the controller and i found that its not changing for the requested culture when using routing – Ahmad Alaa Mar 08 '21 at 15:26
  • I'm not so sure about how the `IRequestCultureProvider` are used but if possible you can try clearing all the providers first and add just the `RouteDataRequestCultureProvider` to see if it works. This is fairly strange because almost the config code is standard and the `RouteDataRequestCultureProvider` itself is a built-in provider, options looks fine ... – King King Mar 08 '21 at 15:28
  • when i change the current culture manually based on lang route, it works fine : Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(lang); Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(lang); – Ahmad Alaa Mar 08 '21 at 15:32
  • I have cleared all providers and just kept the route provider, i have do everything you can expect or you can not, so do you think that i need to change the culture manually based on the routing parameter !? – Ahmad Alaa Mar 08 '21 at 15:38
  • if you don't have time to solve this issue, of course that's a good work-around (you can even write an inline-middelware as I commented before and set the culture in there manually). But later you should try to fix the issue, it's fairly ridiculous. BTW here is the code for `RouteDataRequestCultureProvider` https://github.com/dotnet/aspnetcore/blob/c925f99cddac0df90ed0bc4a07ecda6b054a0b02/src/Middleware/Localization.Routing/src/RouteDataRequestCultureProvider.cs it's pretty simple and that's why it's hard to fail strangely as in your case. – King King Mar 08 '21 at 15:44
  • Hi guys, `RouteDataRequestCultureProvider` [code](https://github.com/dotnet/aspnetcore/blob/c925f99cddac0df90ed0bc4a07ecda6b054a0b02/src/Middleware/Localization.Routing/src/RouteDataRequestCultureProvider.cs) works fine for query string paremeter, like in your example - `?culture=en`. You should create custom implementation of interface `RequestCultureProvider` for your issue. Take a look this [answer](https://stackoverflow.com/a/65799495/3520507) – DarkSideMoon Mar 09 '21 at 09:08
  • @DarkSideMoon the implementation is just simple, get the route value and set the corresponding culture. The default `RouteDataRequestCultureProvider` is just enough. BTW the OP configures its route data key as `lang` (not `culture` as used by default). It should just work, and of course this is so strange when it's not working on his side. Sometimes we cannot help because of something stupid simple hidden on the OP's side. – King King Mar 10 '21 at 02:08

0 Answers0