Khusniddin Koychiev
Khusniddin Koychiev

Reputation: 23

ASP.NET Core localize .cs file in Razor Pages

There is a project on ASP.NET 5.0 with Identity. Need help in how to translate messages in .cs files Razor Page.

Startup.cs looks like that

namespace localizeTest
{
    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.AddLocalization(opt => { opt.ResourcesPath = "Resources"; });
            services.AddMvc().AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix).AddDataAnnotationsLocalization();

            services.Configure<RequestLocalizationOptions>(
            opt =>
            {
                var suppoortedCulteres = new List<CultureInfo>
                {
                    new CultureInfo("ru"),
                    new CultureInfo("en")
                };
                opt.DefaultRequestCulture = new RequestCulture("ru");
                opt.SupportedCultures = suppoortedCulteres;
                opt.SupportedUICultures = suppoortedCulteres;
            }
            );

            services.AddDNTCaptcha(options =>
            {
                options.UseCookieStorageProvider();
            });

            string connection = Configuration["ConnectionStrings:DefaultConnection"];
            ServerVersion vesrion = ServerVersion.AutoDetect(connection);

            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseMySql(connection, vesrion));
            services.AddDatabaseDeveloperPageExceptionFilter();

            services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
                .AddEntityFrameworkStores<ApplicationDbContext>();
            services.AddControllersWithViews();

            services.AddRazorPages();
        }

        // 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.UseMigrationsEndPoint();
            }
            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();

            app.UseAuthentication();
            app.UseAuthorization();
            app.UseRequestLocalization(app.ApplicationServices.GetRequiredService<IOptions<RequestLocalizationOptions>>().Value);


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

In the Resources folder created two files:

/Areas/Identity/Pages/Account/Login.en.resx

/Areas/Identity/Pages/Account/Login.ru.resx

Sample page Areas/Identity/Pages/Account/Login.cshtml

@page
@model LoginModel
@inject Microsoft.AspNetCore.Mvc.Localization.IViewLocalizer localizer

@{
    ViewData["Title"] = localizer["Login"];
}

<div class="container">
    <div class="row h-100">
        <div class="col-12 col-md-10 mx-auto my-auto">
            <div class="card auth-card">
                <div class="card-body">
                    <h1 class="mb-4">@ViewData["Title"]</h1>
                    <h4 class="pb-2">@localizer["Welcome"]</h4>
                    <form id="account" method="post">
                        <div asp-validation-summary="All" class="text-danger"></div>
                        <div class="form-group">
                            <label asp-for="Input.Email">@localizer["Email"]</label>
                            <input asp-for="Input.Email" class="form-control" placeholder="@localizer["YourEmail"]" required="">
                            <span asp-validation-for="Input.Email" class="text-danger"></span>
                        </div>

                        <div class="form-group">
                            <label asp-for="Input.Password">@localizer["Password"]</label>
                            <input asp-for="Input.Password" class="form-control" placeholder="@localizer["YourPassword"]" required="">
                            <span asp-validation-for="Input.Password" class="text-danger"></span>
                        </div>

                        <div class="form-group">
                            <div class="custom-control custom-checkbox">
                                <input class="custom-control-input" asp-for="Input.RememberMe">
                                <label class="custom-control-label" asp-for="Input.RememberMe">@localizer["RememberMe"]</label>
                            </div>
                        </div>

                        <div class="form-group">
                            <button type="submit" class="btn btn-primary">@localizer["SignIn"]</button>
                        </div>

                        <div class="form-group">
                            <p>
                                <a id="forgot-password" asp-page="./ForgotPassword">@localizer["ForgotPass"]</a>
                            </p>
                            <p>
                                <a asp-page="./Register" asp-route-returnUrl="@Model.ReturnUrl">@localizer["ЗарегестрироватьсяКакНовый"]</a>
                            </p>
                            <p>
                                <a id="resend-confirmation" asp-page="./ResendEmailConfirmation">@localizer["EmailConf"]</a>
                            </p>
                        </div>

                    </form>
                </div>
            </div>
        </div>
    </div>
</div>

@section Scripts {
    <partial name="_ValidationScriptsPartial" />
}

Good, localize in Page View work it!

But, localize in Page Model not work. File Areas/Identity/Pages/Account/Login.cshtml.cs

namespace localizeTest.Areas.Identity.Pages.Account
{
    [AllowAnonymous]
    public class LoginModel : PageModel
    {
        private readonly UserManager<IdentityUser> _userManager;
        private readonly SignInManager<IdentityUser> _signInManager;
        private readonly ILogger<LoginModel> _logger;
        private readonly IStringLocalizer<LoginModel> _stringLocalizer;

        public LoginModel(SignInManager<IdentityUser> signInManager, 
            ILogger<LoginModel> logger,
            UserManager<IdentityUser> userManager, 
            IStringLocalizer<LoginModel> stringLocalizer)
        {
            _userManager = userManager;
            _signInManager = signInManager;
            _logger = logger;
            _stringLocalizer = stringLocalizer;
        }

        [BindProperty]
        public InputModel Input { get; set; }

        public IList<AuthenticationScheme> ExternalLogins { get; set; }

        public string ReturnUrl { get; set; }

        [TempData]
        public string ErrorMessage { get; set; }

        public class InputModel
        {
            [Display(Name = "Email")]
            [Required(ErrorMessage = "{0} is required")]
            [EmailAddress]
            public string Email { get; set; }

            [Display(Name = "Password")]
            [Required(ErrorMessage = "{0} is required")]
            [DataType(DataType.Password)]
            public string Password { get; set; }

            [Display(Name = "RememberMe")]
            public bool RememberMe { get; set; }
        }

        public async Task OnGetAsync(string returnUrl = null)
        {
            if (!string.IsNullOrEmpty(ErrorMessage))
            {
                ModelState.AddModelError(string.Empty, ErrorMessage);
            }

            returnUrl ??= Url.Content("~/Books/List");

            // Clear the existing external cookie to ensure a clean login process
            await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);

            ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();

            ReturnUrl = returnUrl;
        }

        public async Task<IActionResult> OnPostAsync(string returnUrl = null)
        {
            returnUrl ??= Url.Content("~/Books/List");

            string WrongLoggin = _stringLocalizer["НеВерныйЛогин"].Value;

            ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
        
            if (ModelState.IsValid)
            {
                // This doesn't count login failures towards account lockout
                // To enable password failures to trigger account lockout, set lockoutOnFailure: true
                var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false);
                if (result.Succeeded)
                {
                    _logger.LogInformation("User logged in.");
                    return LocalRedirect(returnUrl);
                }
                if (result.RequiresTwoFactor)
                {
                    return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, RememberMe = Input.RememberMe });
                }
                if (result.IsLockedOut)
                {
                    _logger.LogWarning("User account locked out.");
                    return RedirectToPage("./Lockout");
                }
                else
                {
                    ModelState.AddModelError(string.Empty, WrongLoggin);
                    return Page();
                }
            }

            // If we got this far, something failed, redisplay form
            return Page();
        }
    }
}

How to translate text in .cs files, how to make it work?

[Display(Name = "How Translate With Text?")]

[Required(ErrorMessage = "How {0} Translate with Text?")]

Img Login Ru

Img Login En

I tried examples as for pages of controllers.

Created resources with the name LoginModel+InnerModel.en.resx and LoginModel+InnerModel.ru.resx.

But it did't give results.

P.S. Sorry for Google translate, but i need help.

P.S.2. Localization made on the example of this video

Upvotes: 2

Views: 783

Answers (1)

Yinqiu
Yinqiu

Reputation: 7190

First you need to add AddDataAnnotationsLocalization in your Stratup,

 services.AddLocalization(options => options.ResourcesPath = "Resources");
        services.AddRazorPages().AddDataAnnotationsLocalization();

Then you need to name your resource file like

Areas.Identity.Pages.Account.LoginModel+InputModel.en-US.resx

For any nested model in LoginModel, you need to use + instead of .

For the details you can see the doc: DataAnnotations localization.

Upvotes: 1

Related Questions