使用本地化的 Razor 页面作为电子邮件模板

Posted

技术标签:

【中文标题】使用本地化的 Razor 页面作为电子邮件模板【英文标题】:Use localized Razor pages as e-mail templates 【发布时间】:2020-05-26 06:39:45 【问题描述】:

我正在开发一个 .NET Core 项目,我将 Razor 页面作为电子邮件模板发送。我遵循了本教程: 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/ 我唯一找不到的是如何通过将所需语言作为参数传递来发送本地化电子邮件(示例):

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

我在网上找到了一些关于 POsresx 文件的资料,但一切都需要 Startup 实现。剃须刀页面不是主项目,主项目只是一个 API,而前端由另一个 Angular 项目处理。

如何在没有启动文件的 Razor 类库中实现本地化?

这是项目文件

【问题讨论】:

【参考方案1】:

我看到至少有两种选择:

    为不同的文化使用不同的资源文件。 针对不同的文化使用不同的 cshtml 文件。

选项 1 - 为不同的文化使用不同的资源文件

按照以下步骤操作:

    在API项目中,注册IStringLocalizerFactoryIStringLocalizer&lt;&gt;

     services.AddSingleton<IStringLocalizerFactory, ResourceManagerStringLocalizerFactory>();
     services.AddScoped(typeof(IStringLocalizer<>), typeof(StringLocalizer<>));
     services.AddScoped<IRegisterAccountService, RegisterAccountService>();
     services.AddScoped<IRazorViewToStringRenderer, RazorViewToStringRenderer>();
    

    在 Razor 视图库中创建 Resources.Resx 文件,并将其自定义工具设置为 PublicResXFileCodeGenerator。然后为每种语言创建资源文件,如Resources.fa-IR.Resx 并清除自定义工具以不为语言文件生成代码。然后添加资源名称和值,例如fa-IR

     Name        Value            Comment
     =========================================
     Welcome     خوش آمدید              
    

    将字符串定位器注入您想要的视图:

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

在上面的例子中,RazorHtmlEmails.RazorClassLib 是资源的命名空间。

    只要你想显示资源文件中的字符串,就使用SR["resource key in resource file"]

     @SR["Welcome"]
    

    将文化作为参数添加到RenderViewToStringAsync of IRazorViewToStringRenderer

     Task<string> RenderViewToStringAsync<TModel>
         (string viewName, TModel model, string culture);
    

    RazorViewToStringRenderer 中为RenderViewToStringAsync 的实施添加文化:

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

    使用它:

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

选项 2 - 为不同的文化使用不同的 cshtml 文件

如果您不想使用资源文件并且想要为不同的文化提供不同的 cshtml 文件,只需使用命名约定即可。例如,为波斯语创建一个 template.fa-IR.cshtml,然后在渲染时使用该视图:

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

【讨论】:

css 渲染是否正确,这也适用于 javascript 吗? @spmoolman 它像任何其他渲染器一样工作。无论您如何渲染(使用 t4、字符串格式等),如果您渲染的字符串按预期工作,那么当您使用 Razor 渲染它时它也会工作。对于 js,它不应该在电子邮件中工作(无论你如何渲染),因为它可能会引入一些漏洞。 谢谢@Reza Aghaei【参考方案2】:

作为已接受答案的补充,您可以通过电子邮件主题中的资源获得翻译效果:

像这样编辑RegisterAccountService类:

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

用你的命名空间替换RazorHtmlEmails.RazorClassLib.SharedResources,然后:

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

并申请:

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

【讨论】:

以上是关于使用本地化的 Razor 页面作为电子邮件模板的主要内容,如果未能解决你的问题,请参考以下文章

无法在 Razor 页面中调用 onPost

播放框架 1.x 上的电子邮件模板国际化/本地化

FluentEmail - 适用于 .NET 和 .NET Core 的邮件发送库

Nancy:如何在没有上下文的情况下呈现 Html

单击 Razor Pages Asp 发送电子邮件和重定向

asp.net MVC Razor 文本框控件验证