2

I would like to make a route system in ASP.NET Core in which urls are translated as same as this question How to create multilingual translated routes in Laravel

The goal is to translate the part of the url path which is after the language code, and generate urls in the user language.

For example:

/fr/produit

Will become in english:

/en/product

I have the following configuration:

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

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {   
        services.Configure<RequestLocalizationOptions>(options =>
        {
            var translations = services.BuildServiceProvider().GetService<TranslationsDbContext>();
            var supportedCultures = translations.Cultures
                .ToList()
                .Select(x => new CultureInfo(x.Name))
                .ToArray();

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

            options.RequestCultureProviders = new RequestCultureProvider[]
            {
                new RouteDataRequestCultureProvider()
                {
                    RouteDataStringKey = "lang",
                    UIRouteDataStringKey = "lang",
                    Options = options
                },
                new CookieRequestCultureProvider(),
                new AcceptLanguageHeaderRequestCultureProvider()
            }; 
        });

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

        services.AddDbContextPool<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));

        services.AddDbContext<TranslationsDbContext>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("TranslationsConnection")));

        services.AddIdentity<User, IdentityRole<Guid>>()
            .AddEntityFrameworkStores<ApplicationDbContext>();

        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        services.AddSingleton<IStringLocalizerFactory, EFStringLocalizerFactory>();
        services.AddScoped<IStringLocalizer, StringLocalizer>();

        services
            .AddMvc()
            .AddDataAnnotationsLocalization();

    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env,
        ApplicationDbContext dbContext, TranslationsDbContext translationsDbContext,
        UserManager<User> userManager, RoleManager<IdentityRole<Guid>> roleManager)
    { 
        app.UseRequestLocalization();

        app.UseWhen(
            context => !context.Request.Path.StartsWithSegments("/api"),
            a => a.UseLocalizedStatusCodePagesWithReExecute("/{0}/error/{1}")
        );

        app.UseResponseCompression();

        app.UseCookiePolicy();

        app.UseAuthentication();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "localized",
                template: "{lang:lang}/{controller=Home}/{action=Index}/{id?}"
            );
            routes.MapRoute(
                name: "catchAll",
                template: "{*catchall}",
                defaults: new { controller = "Home", action = "RedirectToDefaultLanguage" }
            );
        });
    }
}

public class LanguageRouteConstraint : IRouteConstraint
{
    public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
    {
        if (!values.ContainsKey("lang"))
        {
            return false;
        }

        var lang = values["lang"].ToString();

        return lang == "fr" || lang == "en" || lang == "de";
    }
}

The language code is correctly handled by the application.

However, after many research I see that I can use IApplicationModelConvention to customize how routing works. But I don't understand how I can use this interface to work with my existing configuration.

frank_lbt
  • 426
  • 1
  • 7
  • 21
  • What have you tried? Did you at least do some research? How about something like this? https://stackoverflow.com/questions/47079689/route-localization-in-asp-net-core-2 – Camilo Terevinto Mar 09 '19 at 15:07
  • In fact this comment https://stackoverflow.com/questions/47079689/route-localization-in-asp-net-core-2#comment95593052_48087051 seems to give the correct solution. But it's not compatible with my existing configuration. – frank_lbt Mar 10 '19 at 18:09

0 Answers0