2
votes

I'm trying to add localization to my ASP.NET Core 3.1 MVC project, unfortunately I could not find any article or tutorial that shows how to do it in an easy way.

Each and everyone is having some issues that I could not understand.

Could anyone please show me an easy way to do this? ok, I tried to do syncfusion.com/blogs/post/… but I faced an issue with this (options.RequestCultureProviders = new[] { new RouteDataRequestCultureProvider { IndexOfCulture = 1, IndexofUICulture = 1 } };) it says that RequestCultureProviders doesn't have IndexofUICulture......

I have reached this level:

    @using Microsoft.AspNetCore.Localization
@using Microsoft.Extensions.Localization 
@using System.Resources 
@model Index
@inject IStringLocalizer<Index> localizer 
@inject IHtmlLocalizer<Index> htmlLocalizer
@{
    ViewData["Title"] = "M-POS";
    //Microsoft.AspNetCore.Localization.IRequestCultureFeature requestCultureFeature;
    var requestCulture = CultureInfo.CurrentCulture;
    

}
    <div class="text-center">
        <h1 class="display-4">@localizer["Welcome"]</h1>
        <p>@localizer["Learn"]</p>


        <table class="table culture-table">
            <tr>
                <td style="width:50%;">Culture</td>
                <td>@requestCulture.DisplayName {@requestCulture.Name}</td>
            </tr>
            <tr>
                <td>UI Culture</td>
                <td>@requestCulture.Name</td>
            </tr>
            <tr>
                <td>UICulture Parent</td>
                <td>@requestCulture.Parent</td>
            </tr>
            <tr>
                <td>Date</td>
                <td>@DateTime.Now.ToLongDateString()</td>
            </tr>
            <tr>
                <td>Currency</td>
                <td>
                    @(12345.00.ToString("c"))
                </td>
            </tr>
            <tr>
                <td>Currency</td>
                <td>
                    @(12345.00.ToString("c"))
                </td>
            </tr>
            <tr>
                <td>Number</td>
                <td>
                    @(123.45m.ToString("F2"))
                </td>
            </tr>
        </table>
    </div>

and then I have a folder called Resources inside that folder I have a file called Resource.resx and Resource.en-US.resx and the StartUp.cs file is like that:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.EntityFrameworkCore;
using POS3.Data;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Models;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.AspNetCore.Mvc.Razor;
using System.Globalization;
using Microsoft.AspNetCore.Localization;
using Microsoft.Extensions.Options;
using Microsoft.AspNetCore.Localization.Routing;
using Microsoft.AspNetCore.Routing;
using Microsoft.CodeAnalysis.Options;

using Microsoft.AspNetCore.Http;
using System.Xml.Linq;

namespace POS3
{
    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.AddDbContext<ApplicationDbContext>(options =>
              options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

            services.AddDefaultIdentity<UserAccount>()
                .AddRoles<IdentityRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>();

            services.AddRazorPages();
            //localization startup

            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
            services.AddLocalization(options => options.ResourcesPath = "Resources");
            services.AddMvc().AddViewLocalization();
            services.AddMvc()
            .AddViewLocalization(options => options.ResourcesPath = "Resources")
            .AddDataAnnotationsLocalization();

            

            services.Configure<RequestLocalizationOptions>(options =>
            {
                var supportedCultures = new[]
                 {
                    
                    new CultureInfo("ar-SA"),
                    new CultureInfo("en-US")
                };
                options.DefaultRequestCulture = new RequestCulture("en-US");
                options.SupportedCultures = supportedCultures;
                options.SupportedUICultures = supportedCultures;
            });

            //services.Configure<RequestLocalizationOptions>(options =>
            //{
            //    var supportedCultures = new[]
            //    {
            //    new CultureInfo("en-US"),
            //    new CultureInfo("ar-SA"),
            //    new CultureInfo("es"),
            //};

            //    options.DefaultRequestCulture = new RequestCulture("en-US");
            //    options.SupportedCultures = supportedCultures;
            //    options.SupportedCultures = supportedCultures;
            //    //options.RequestCultureProviders = new[] { new RouteDataRequestCultureProvider { IndexOfCulture = 1, IndexOfCulture = 1 } };
            //});




            services.AddMvcCore();
            services.AddAuthorization(options => {
                options.AddPolicy("readonlypolicy",
                    builder => builder.RequireRole("Admin", "Manager", "Cashier", "User", "Super User"));
                options.AddPolicy("writepolicy",
                    builder => builder.RequireRole("Admin", "Manager", "Super User"));
            });

            

              


            services.Configure<IdentityOptions>(options =>
            {
                // Default Password settings.
                options.Password.RequireDigit = false;
                options.Password.RequiredLength = 6;
                options.Password.RequiredUniqueChars = 1;
                options.Password.RequireNonAlphanumeric = false;
                options.Password.RequireUppercase = false;
                options.Password.RequireLowercase = false;
            });

            services.AddControllersWithViews();
            services.AddRazorPages();
            services.AddControllers(config =>
            {
                
                var policy = new AuthorizationPolicyBuilder()
                                 .RequireAuthenticatedUser()
                                 .Build();
                config.Filters.Add(new AuthorizeFilter(policy));
            });

            services.Configure<PasswordHasherOptions>(options =>
            options.CompatibilityMode = PasswordHasherCompatibilityMode.IdentityV2
            );
            


            //services.AddSingleton<IEmailSender, EmailSender>();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
           
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseDatabaseErrorPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/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();

            //configer localization
            


            var localizationOptions = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>().Value;
            app.UseRequestLocalization(localizationOptions);

            app.UseAuthentication();
            app.UseAuthorization();           
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
                
                endpoints.MapRazorPages();
            });

           
        }
    }
}

now I can't see resource.en-US.resx file values I think I'm missing something.

1
Hi, @MansourHamoud, I already post the code to solve your question. It works on me. If the answer solved your question, please mark it for helping more people. If not, we may be able to continue to explore solutions. Thank you for your time and efforts. - Michael Wang

1 Answers

1
votes

Q1: an issue with this (options.RequestCultureProviders = new[] { new RouteDataRequestCultureProvider { IndexOfCulture = 1, IndexofUICulture = 1 } };) it says that RequestCultureProviders doesn't have IndexofUICulture......

Download the samples you will find RouteDataRequestCultureProvider.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Localization;

namespace LocalizationSampleSingleResxFile
{
    public class RouteDataRequestCultureProvider : RequestCultureProvider
    {
        public int IndexOfCulture;
        public int IndexofUICulture;

        public override Task<ProviderCultureResult> DetermineProviderCultureResult(HttpContext httpContext)
        {
            if (httpContext == null)
                throw new ArgumentNullException(nameof(httpContext));

            string culture = null;
            string uiCulture = null;

            culture = uiCulture = httpContext.Request.Path.Value.Split('/')[IndexOfCulture]?.ToString();

            var providerResultCulture = new ProviderCultureResult(culture, uiCulture);

            return Task.FromResult(providerResultCulture);
        }
    }
}

Q2: Change name of your resource

You already named en-US, so your resource file name must format with en-US.
enter image description here
Index.cshtml:
enter image description here

Screenshots of test:
enter image description here


Globalization and localization in ASP.NET Core
Adding Localisation to an ASP.NET Core application
How to Use Localization in an ASP.NET Core Web API