简体   繁体   中英

Use localized Razor pages as e-mail templates

I am developing a .NET Core project where I send Razor pages as e-mail templates. I followed this tutorial: https://scottsauber.com/2018/07/07/walkthrough-creating-an-html-email-template-with-razor-and-razor-class-libraries-and-rendering-it-from-a-net-standard-class-library/ The only thing I couldn't find was how to send a localized e-mail by passing the needed language as a parameter (example):

public async Task<string> RenderViewToStringAsync<TModel>(string viewName, TModel model, string lang)

I found some stuff online about POs and resx files but everything required a Startup implementation. The razor pages is not the main project, the main project is just an API, while the front-end is handled by another Angular project.

How can I implement localization in a Razor Class Library without a Startup file?

This is the project files

在此处输入图片说明

I see at least two options for you:

  1. Use different resource files for different cultures.
  2. Use different cshtml file for different cultures.

Optoin 1 - Use different resource files for different cultures

Follow these steps:

  1. In API project, register IStringLocalizerFactory and IStringLocalizer<> :

     services.AddSingleton<IStringLocalizerFactory, ResourceManagerStringLocalizerFactory>(); services.AddScoped(typeof(IStringLocalizer<>), typeof(StringLocalizer<>)); services.AddScoped<IRegisterAccountService, RegisterAccountService>(); services.AddScoped<IRazorViewToStringRenderer, RazorViewToStringRenderer>();
  2. Create a Resources.Resx file in Razor View Library and set its custom tool to PublicResXFileCodeGenerator . Then for each language, create the resource file like Resources.fa-IR.Resx and clear the custom tool to not generate code for the language files. Then add resource name and value, for example for fa-IR :

     Name Value Comment ========================================= Welcome خوش آمدید
  3. Inject string localizer to the views that you want:

     @using Microsoft.Extensions.Localization @inject IStringLocalizer<RazorHtmlEmails.RazorClassLib.SharedResources> SR

In above example, RazorHtmlEmails.RazorClassLib is namespace of the resource.

  1. Use SR["resource key in resource file"] whenever you want to show a string from resource file:

     @SR["Welcome"]
  2. Add culture as parameter to RenderViewToStringAsync of IRazorViewToStringRenderer :

     Task<string> RenderViewToStringAsync<TModel> (string viewName, TModel model, string culture);
  3. Add culture to implementation of RenderViewToStringAsync in RazorViewToStringRenderer :

     public async Task<string> RenderViewToStringAsync<TModel> (string viewName, TModel model, string culture) { Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(culture); Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(culture); ...
  4. Use it:

     string body = await _razorViewToStringRenderer.RenderViewToStringAsync( "/Views/Emails/ConfirmAccount/ConfirmAccountEmail.cshtml", confirmAccountModel, "fa-IR");

Option 2 - Use different cshtml file for different cultures

If you don't want to use resource files and you want to have different cshtml files for different cultures, just use naming convention. For example create a template.fa-IR.cshtml for Persian language and then when rendering, use that view:

string body = await _razorViewToStringRenderer.RenderViewToStringAsync(
    "/Views/Emails/ConfirmAccount/ConfirmAccountEmail.fa-IR.cshtml", 
    confirmAccountModel);

As an addition to the accepted answer, this is how you can have the translation effect from the resources in the e-mail subject:

Edit RegisterAccountService class like this:

private readonly IStringLocalizer<RazorHtmlEmails.RazorClassLib.SharedResources> _localizer;

Replace RazorHtmlEmails.RazorClassLib.SharedResources with your namespace, then:

public RegisterAccountService(IRazorViewToStringRenderer razorViewToStringRenderer, IStringLocalizer<RazorHtmlEmails.RazorClassLib.SharedResources> localizer)
    {
        _razorViewToStringRenderer = razorViewToStringRenderer;
        _localizer = localizer;
    }

and apply:

SendEmail(toAddresses, "donotreply@contoso.com", _localizer["My_Email_Subject_Translation"].Value, body);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM