mirror of https://github.com/abpframework/abp.git
47 changed files with 85 additions and 971 deletions
@ -1,18 +0,0 @@ |
|||||
using Volo.Abp.Collections; |
|
||||
|
|
||||
namespace Volo.Abp.Emailing.Templates |
|
||||
{ |
|
||||
public class AbpEmailTemplateOptions |
|
||||
{ |
|
||||
public string DefaultLayout { get; set; } |
|
||||
|
|
||||
public ITypeList<IEmailTemplateDefinitionProvider> DefinitionProviders { get; } |
|
||||
|
|
||||
public AbpEmailTemplateOptions() |
|
||||
{ |
|
||||
DefaultLayout = StandardEmailTemplates.DefaultLayout; |
|
||||
|
|
||||
DefinitionProviders = new TypeList<IEmailTemplateDefinitionProvider>(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,16 +1,26 @@ |
|||||
using Volo.Abp.Emailing.Templates.VirtualFiles; |
using Volo.Abp.TextTemplating; |
||||
|
|
||||
namespace Volo.Abp.Emailing.Templates |
namespace Volo.Abp.Emailing.Templates |
||||
{ |
{ |
||||
public class DefaultEmailTemplateProvider : EmailTemplateDefinitionProvider |
public class DefaultEmailTemplateProvider : TemplateDefinitionProvider |
||||
{ |
{ |
||||
public override void Define(IEmailTemplateDefinitionContext context) |
public override void Define(ITemplateDefinitionContext context) |
||||
{ |
{ |
||||
context.Add(new EmailTemplateDefinition(StandardEmailTemplates.DefaultLayout, defaultCultureName: "en", isLayout: true, layout: null) |
context.Add( |
||||
.AddTemplateVirtualFiles("/Volo/Abp/Emailing/Templates/DefaultEmailTemplates/Layout")); |
new TemplateDefinition( |
||||
|
StandardEmailTemplates.DefaultLayout, |
||||
|
defaultCultureName: "en", |
||||
|
isLayout: true, |
||||
|
layout: null |
||||
|
).AddVirtualFiles("/Volo/Abp/Emailing/Templates/DefaultEmailTemplates/Layout") |
||||
|
); |
||||
|
|
||||
context.Add(new EmailTemplateDefinition(StandardEmailTemplates.SimpleMessage, defaultCultureName: "en") |
context.Add( |
||||
.AddTemplateVirtualFiles("/Volo/Abp/Emailing/Templates/DefaultEmailTemplates/Message")); |
new TemplateDefinition( |
||||
|
StandardEmailTemplates.SimpleMessage, |
||||
|
defaultCultureName: "en" |
||||
|
).AddVirtualFiles("/Volo/Abp/Emailing/Templates/DefaultEmailTemplates/Message") |
||||
|
); |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
@ -1,42 +0,0 @@ |
|||||
using System.Text; |
|
||||
|
|
||||
namespace Volo.Abp.Emailing.Templates |
|
||||
{ |
|
||||
public class EmailTemplate |
|
||||
{ |
|
||||
public EmailTemplateDefinition Definition { get; } |
|
||||
|
|
||||
public string Content => ContentBuilder.ToString(); |
|
||||
|
|
||||
protected StringBuilder ContentBuilder { get; set; } |
|
||||
|
|
||||
public EmailTemplate(string content, EmailTemplateDefinition definition) |
|
||||
{ |
|
||||
ContentBuilder = new StringBuilder(content); |
|
||||
Definition = definition; |
|
||||
} |
|
||||
|
|
||||
public virtual void SetLayout(EmailTemplate layoutTemplate) |
|
||||
{ |
|
||||
if (!layoutTemplate.Definition.IsLayout) |
|
||||
{ |
|
||||
throw new AbpException($"Given template is not a layout template: {layoutTemplate.Definition.Name}"); |
|
||||
} |
|
||||
|
|
||||
var newStrBuilder = new StringBuilder(layoutTemplate.Content); |
|
||||
newStrBuilder.Replace("{{#content}}", ContentBuilder.ToString()); |
|
||||
|
|
||||
ContentBuilder = newStrBuilder; |
|
||||
} |
|
||||
|
|
||||
public virtual void SetContent(string content) |
|
||||
{ |
|
||||
ContentBuilder = new StringBuilder(content); |
|
||||
} |
|
||||
|
|
||||
public virtual void Replace(string name, string value) |
|
||||
{ |
|
||||
ContentBuilder.Replace("{{" + name + "}}", value); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,22 +0,0 @@ |
|||||
using System.Collections.Generic; |
|
||||
using System.Linq; |
|
||||
|
|
||||
namespace Volo.Abp.Emailing.Templates |
|
||||
{ |
|
||||
public class EmailTemplateContributorList : List<IEmailTemplateContributor> |
|
||||
{ |
|
||||
public string GetOrNull(string cultureName) |
|
||||
{ |
|
||||
foreach (var contributor in this.AsQueryable().Reverse()) |
|
||||
{ |
|
||||
var templateString = contributor.GetOrNull(cultureName); |
|
||||
if (templateString != null) |
|
||||
{ |
|
||||
return templateString; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return null; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,36 +0,0 @@ |
|||||
using System; |
|
||||
using JetBrains.Annotations; |
|
||||
|
|
||||
namespace Volo.Abp.Emailing.Templates |
|
||||
{ |
|
||||
public class EmailTemplateDefinition |
|
||||
{ |
|
||||
public const string DefaultLayoutPlaceHolder = "_"; |
|
||||
|
|
||||
public string Name { get; } |
|
||||
|
|
||||
public bool IsLayout { get; } |
|
||||
|
|
||||
public string Layout { get; set; } |
|
||||
|
|
||||
public Type LocalizationResource { get; set; } |
|
||||
|
|
||||
public EmailTemplateContributorList Contributors { get; } |
|
||||
|
|
||||
public string DefaultCultureName { get; } |
|
||||
|
|
||||
public bool SingleTemplateFile { get; } |
|
||||
|
|
||||
public EmailTemplateDefinition([NotNull] string name, Type localizationResource = null, bool isLayout = false, |
|
||||
string layout = DefaultLayoutPlaceHolder, string defaultCultureName = null, bool singleTemplateFile = false) |
|
||||
{ |
|
||||
Name = Check.NotNullOrWhiteSpace(name, nameof(name)); |
|
||||
LocalizationResource = localizationResource; |
|
||||
Contributors = new EmailTemplateContributorList(); |
|
||||
IsLayout = isLayout; |
|
||||
Layout = layout; |
|
||||
DefaultCultureName = defaultCultureName; |
|
||||
SingleTemplateFile = singleTemplateFile; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,38 +0,0 @@ |
|||||
using System.Collections.Generic; |
|
||||
using System.Collections.Immutable; |
|
||||
|
|
||||
namespace Volo.Abp.Emailing.Templates |
|
||||
{ |
|
||||
public class EmailTemplateDefinitionContext : IEmailTemplateDefinitionContext |
|
||||
{ |
|
||||
protected Dictionary<string, EmailTemplateDefinition> EmailTemplates { get; } |
|
||||
|
|
||||
public EmailTemplateDefinitionContext(Dictionary<string, EmailTemplateDefinition> emailTemplates) |
|
||||
{ |
|
||||
EmailTemplates = emailTemplates; |
|
||||
} |
|
||||
|
|
||||
public virtual EmailTemplateDefinition GetOrNull(string name) |
|
||||
{ |
|
||||
return EmailTemplates.GetOrDefault(name); |
|
||||
} |
|
||||
|
|
||||
public virtual IReadOnlyList<EmailTemplateDefinition> GetAll() |
|
||||
{ |
|
||||
return EmailTemplates.Values.ToImmutableList(); |
|
||||
} |
|
||||
|
|
||||
public virtual void Add(params EmailTemplateDefinition[] definitions) |
|
||||
{ |
|
||||
if (definitions.IsNullOrEmpty()) |
|
||||
{ |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
foreach (var definition in definitions) |
|
||||
{ |
|
||||
EmailTemplates[definition.Name] = definition; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,22 +0,0 @@ |
|||||
using System.Collections.Generic; |
|
||||
|
|
||||
namespace Volo.Abp.Emailing.Templates |
|
||||
{ |
|
||||
public class EmailTemplateDefinitionDictionary : Dictionary<string, EmailTemplateDefinition> |
|
||||
{ |
|
||||
public EmailTemplateDefinitionDictionary Add(EmailTemplateDefinition emailTemplateDefinition) |
|
||||
{ |
|
||||
if (ContainsKey(emailTemplateDefinition.Name)) |
|
||||
{ |
|
||||
throw new AbpException( |
|
||||
"There is already an email template definition with given name: " + |
|
||||
emailTemplateDefinition.Name |
|
||||
); |
|
||||
} |
|
||||
|
|
||||
this[emailTemplateDefinition.Name] = emailTemplateDefinition; |
|
||||
|
|
||||
return this; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,74 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Collections.Immutable; |
|
||||
using System.Linq; |
|
||||
using Microsoft.Extensions.DependencyInjection; |
|
||||
using Microsoft.Extensions.Options; |
|
||||
using Volo.Abp.DependencyInjection; |
|
||||
|
|
||||
namespace Volo.Abp.Emailing.Templates |
|
||||
{ |
|
||||
public class EmailTemplateDefinitionManager : IEmailTemplateDefinitionManager, ISingletonDependency |
|
||||
{ |
|
||||
protected Lazy<IDictionary<string, EmailTemplateDefinition>> EmailTemplateDefinitions { get; } |
|
||||
|
|
||||
protected AbpEmailTemplateOptions Options { get; } |
|
||||
|
|
||||
protected IServiceProvider ServiceProvider { get; } |
|
||||
|
|
||||
public EmailTemplateDefinitionManager( |
|
||||
IOptions<AbpEmailTemplateOptions> options, |
|
||||
IServiceProvider serviceProvider) |
|
||||
{ |
|
||||
ServiceProvider = serviceProvider; |
|
||||
Options = options.Value; |
|
||||
|
|
||||
EmailTemplateDefinitions = |
|
||||
new Lazy<IDictionary<string, EmailTemplateDefinition>>(CreateEmailTemplateDefinitions, true); |
|
||||
} |
|
||||
|
|
||||
public virtual EmailTemplateDefinition Get(string name) |
|
||||
{ |
|
||||
Check.NotNull(name, nameof(name)); |
|
||||
|
|
||||
var template = GetOrNull(name); |
|
||||
|
|
||||
if (template == null) |
|
||||
{ |
|
||||
throw new AbpException("Undefined template: " + name); |
|
||||
} |
|
||||
|
|
||||
return template; |
|
||||
} |
|
||||
|
|
||||
public virtual IReadOnlyList<EmailTemplateDefinition> GetAll() |
|
||||
{ |
|
||||
return EmailTemplateDefinitions.Value.Values.ToImmutableList(); |
|
||||
} |
|
||||
|
|
||||
public virtual EmailTemplateDefinition GetOrNull(string name) |
|
||||
{ |
|
||||
return EmailTemplateDefinitions.Value.GetOrDefault(name); |
|
||||
} |
|
||||
|
|
||||
protected virtual IDictionary<string, EmailTemplateDefinition> CreateEmailTemplateDefinitions() |
|
||||
{ |
|
||||
var templates = new Dictionary<string, EmailTemplateDefinition>(); |
|
||||
|
|
||||
using (var scope = ServiceProvider.CreateScope()) |
|
||||
{ |
|
||||
var providers = Options |
|
||||
.DefinitionProviders |
|
||||
.Select(p => scope.ServiceProvider.GetRequiredService(p) as IEmailTemplateDefinitionProvider) |
|
||||
.ToList(); |
|
||||
|
|
||||
foreach (var provider in providers) |
|
||||
{ |
|
||||
provider.Define(new EmailTemplateDefinitionContext(templates)); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return templates; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,9 +0,0 @@ |
|||||
using Volo.Abp.DependencyInjection; |
|
||||
|
|
||||
namespace Volo.Abp.Emailing.Templates |
|
||||
{ |
|
||||
public abstract class EmailTemplateDefinitionProvider : IEmailTemplateDefinitionProvider, ITransientDependency |
|
||||
{ |
|
||||
public abstract void Define(IEmailTemplateDefinitionContext context); |
|
||||
} |
|
||||
} |
|
||||
@ -1,18 +0,0 @@ |
|||||
using System; |
|
||||
|
|
||||
namespace Volo.Abp.Emailing.Templates |
|
||||
{ |
|
||||
public class EmailTemplateInitializationContext |
|
||||
{ |
|
||||
public EmailTemplateDefinition EmailTemplateDefinition { get; } |
|
||||
|
|
||||
public IServiceProvider ServiceProvider { get; } |
|
||||
|
|
||||
public EmailTemplateInitializationContext(EmailTemplateDefinition emailTemplateDefinition, |
|
||||
IServiceProvider serviceProvider) |
|
||||
{ |
|
||||
EmailTemplateDefinition = emailTemplateDefinition; |
|
||||
ServiceProvider = serviceProvider; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,121 +0,0 @@ |
|||||
using System; |
|
||||
using System.Globalization; |
|
||||
using System.Threading.Tasks; |
|
||||
using Microsoft.Extensions.Localization; |
|
||||
using Microsoft.Extensions.Options; |
|
||||
using Volo.Abp.DependencyInjection; |
|
||||
using Volo.Abp.Localization; |
|
||||
|
|
||||
namespace Volo.Abp.Emailing.Templates |
|
||||
{ |
|
||||
public class EmailTemplateProvider : IEmailTemplateProvider, ITransientDependency |
|
||||
{ |
|
||||
protected IEmailTemplateDefinitionManager EmailTemplateDefinitionManager; |
|
||||
protected ITemplateLocalizer TemplateLocalizer { get; } |
|
||||
protected AbpEmailTemplateOptions Options { get; } |
|
||||
protected IStringLocalizerFactory StringLocalizerFactory; |
|
||||
|
|
||||
public EmailTemplateProvider(IEmailTemplateDefinitionManager emailTemplateDefinitionManager, |
|
||||
ITemplateLocalizer templateLocalizer, IStringLocalizerFactory stringLocalizerFactory, |
|
||||
IOptions<AbpEmailTemplateOptions> options) |
|
||||
{ |
|
||||
EmailTemplateDefinitionManager = emailTemplateDefinitionManager; |
|
||||
TemplateLocalizer = templateLocalizer; |
|
||||
StringLocalizerFactory = stringLocalizerFactory; |
|
||||
Options = options.Value; |
|
||||
} |
|
||||
|
|
||||
public async Task<EmailTemplate> GetAsync(string name) |
|
||||
{ |
|
||||
return await GetAsync(name, CultureInfo.CurrentUICulture.Name); |
|
||||
} |
|
||||
|
|
||||
public async Task<EmailTemplate> GetAsync(string name, string cultureName) |
|
||||
{ |
|
||||
return await GetInternalAsync(name, cultureName); |
|
||||
} |
|
||||
|
|
||||
protected virtual async Task<EmailTemplate> GetInternalAsync(string name, string cultureName) |
|
||||
{ |
|
||||
var emailTemplateDefinition = EmailTemplateDefinitionManager.GetOrNull(name); |
|
||||
if (emailTemplateDefinition == null) |
|
||||
{ |
|
||||
// TODO: Localized message
|
|
||||
throw new AbpException($"email template {name} not definition"); |
|
||||
} |
|
||||
|
|
||||
var emailTemplateString = emailTemplateDefinition.Contributors.GetOrNull(cultureName); |
|
||||
if (emailTemplateString == null && emailTemplateDefinition.DefaultCultureName != null) |
|
||||
{ |
|
||||
emailTemplateString = |
|
||||
emailTemplateDefinition.Contributors.GetOrNull(emailTemplateDefinition.DefaultCultureName); |
|
||||
if (emailTemplateString != null) |
|
||||
{ |
|
||||
cultureName = emailTemplateDefinition.DefaultCultureName; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (emailTemplateString != null) |
|
||||
{ |
|
||||
var emailTemplate = new EmailTemplate(emailTemplateString, emailTemplateDefinition); |
|
||||
|
|
||||
await SetLayoutAsync(emailTemplateDefinition, emailTemplate, cultureName); |
|
||||
|
|
||||
if (emailTemplateDefinition.SingleTemplateFile) |
|
||||
{ |
|
||||
await LocalizeAsync(emailTemplateDefinition, emailTemplate, cultureName); |
|
||||
} |
|
||||
|
|
||||
return emailTemplate; |
|
||||
} |
|
||||
|
|
||||
// TODO: Localized message
|
|
||||
throw new AbpException($"{cultureName} template not exist!"); |
|
||||
} |
|
||||
|
|
||||
protected virtual async Task SetLayoutAsync(EmailTemplateDefinition emailTemplateDefinition, |
|
||||
EmailTemplate emailTemplate, string cultureName) |
|
||||
{ |
|
||||
var layout = emailTemplateDefinition.Layout; |
|
||||
if (layout.IsNullOrWhiteSpace()) |
|
||||
{ |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if (layout == EmailTemplateDefinition.DefaultLayoutPlaceHolder) |
|
||||
{ |
|
||||
layout = Options.DefaultLayout; |
|
||||
} |
|
||||
|
|
||||
var layoutTemplate = await GetInternalAsync(layout, cultureName); |
|
||||
|
|
||||
emailTemplate.SetLayout(layoutTemplate); |
|
||||
} |
|
||||
|
|
||||
protected virtual Task LocalizeAsync(EmailTemplateDefinition emailTemplateDefinition, |
|
||||
EmailTemplate emailTemplate, string cultureName) |
|
||||
{ |
|
||||
if (emailTemplateDefinition.LocalizationResource == null) |
|
||||
{ |
|
||||
return Task.CompletedTask; |
|
||||
} |
|
||||
|
|
||||
var localizer = StringLocalizerFactory.Create(emailTemplateDefinition.LocalizationResource); |
|
||||
if (cultureName != null) |
|
||||
{ |
|
||||
using (CultureHelper.Use(new CultureInfo(cultureName))) |
|
||||
{ |
|
||||
emailTemplate.SetContent(TemplateLocalizer.Localize(localizer, emailTemplate.Content)); |
|
||||
} |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
emailTemplate.SetContent( |
|
||||
TemplateLocalizer.Localize(localizer, emailTemplate.Content) |
|
||||
); |
|
||||
} |
|
||||
|
|
||||
return Task.CompletedTask; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,9 +0,0 @@ |
|||||
namespace Volo.Abp.Emailing.Templates |
|
||||
{ |
|
||||
public interface IEmailTemplateContributor |
|
||||
{ |
|
||||
void Initialize(EmailTemplateInitializationContext context); |
|
||||
|
|
||||
string GetOrNull(string cultureName); |
|
||||
} |
|
||||
} |
|
||||
@ -1,9 +0,0 @@ |
|||||
namespace Volo.Abp.Emailing.Templates |
|
||||
{ |
|
||||
public interface IEmailTemplateDefinitionContext |
|
||||
{ |
|
||||
EmailTemplateDefinition GetOrNull(string name); |
|
||||
|
|
||||
void Add(params EmailTemplateDefinition[] definitions); |
|
||||
} |
|
||||
} |
|
||||
@ -1,15 +0,0 @@ |
|||||
using System.Collections.Generic; |
|
||||
using JetBrains.Annotations; |
|
||||
|
|
||||
namespace Volo.Abp.Emailing.Templates |
|
||||
{ |
|
||||
public interface IEmailTemplateDefinitionManager |
|
||||
{ |
|
||||
[NotNull] |
|
||||
EmailTemplateDefinition Get([NotNull] string name); |
|
||||
|
|
||||
IReadOnlyList<EmailTemplateDefinition> GetAll(); |
|
||||
|
|
||||
EmailTemplateDefinition GetOrNull(string name); |
|
||||
} |
|
||||
} |
|
||||
@ -1,7 +0,0 @@ |
|||||
namespace Volo.Abp.Emailing.Templates |
|
||||
{ |
|
||||
public interface IEmailTemplateDefinitionProvider |
|
||||
{ |
|
||||
void Define(IEmailTemplateDefinitionContext context); |
|
||||
} |
|
||||
} |
|
||||
@ -1,11 +0,0 @@ |
|||||
using System.Threading.Tasks; |
|
||||
|
|
||||
namespace Volo.Abp.Emailing.Templates |
|
||||
{ |
|
||||
public interface IEmailTemplateProvider |
|
||||
{ |
|
||||
Task<EmailTemplate> GetAsync(string name); |
|
||||
|
|
||||
Task<EmailTemplate> GetAsync(string name, string cultureName); |
|
||||
} |
|
||||
} |
|
||||
@ -1,9 +0,0 @@ |
|||||
using System.Threading.Tasks; |
|
||||
|
|
||||
namespace Volo.Abp.Emailing.Templates |
|
||||
{ |
|
||||
public interface ITemplateRender |
|
||||
{ |
|
||||
Task<string> RenderAsync(string template, object model = null); |
|
||||
} |
|
||||
} |
|
||||
@ -1,15 +0,0 @@ |
|||||
using System.Threading.Tasks; |
|
||||
using Scriban; |
|
||||
using Volo.Abp.DependencyInjection; |
|
||||
|
|
||||
namespace Volo.Abp.Emailing.Templates |
|
||||
{ |
|
||||
public class TemplateRender : ITemplateRender, ITransientDependency |
|
||||
{ |
|
||||
public async Task<string> RenderAsync(string template, object model = null) |
|
||||
{ |
|
||||
var scribanTemplate = Template.Parse(template); |
|
||||
return await scribanTemplate.RenderAsync(model); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,19 +0,0 @@ |
|||||
namespace Volo.Abp.Emailing.Templates.VirtualFiles |
|
||||
{ |
|
||||
public static class EmailTemplateDefinitionExtensions |
|
||||
{ |
|
||||
public static EmailTemplateDefinition AddTemplateVirtualFile( |
|
||||
this EmailTemplateDefinition emailTemplateDefinition, string path) |
|
||||
{ |
|
||||
emailTemplateDefinition.Contributors.Add(new SingleVirtualFileEmailTemplateContributor(path)); |
|
||||
return emailTemplateDefinition; |
|
||||
} |
|
||||
|
|
||||
public static EmailTemplateDefinition AddTemplateVirtualFiles( |
|
||||
this EmailTemplateDefinition emailTemplateDefinition, string path) |
|
||||
{ |
|
||||
emailTemplateDefinition.Contributors.Add(new MultipleVirtualFilesEmailTemplateContributor(path)); |
|
||||
return emailTemplateDefinition; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,68 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using Microsoft.Extensions.DependencyInjection; |
|
||||
using Microsoft.Extensions.FileProviders; |
|
||||
using Volo.Abp.VirtualFileSystem; |
|
||||
|
|
||||
namespace Volo.Abp.Emailing.Templates.VirtualFiles |
|
||||
{ |
|
||||
public class MultipleVirtualFilesEmailTemplateContributor : IEmailTemplateContributor |
|
||||
{ |
|
||||
private readonly string _virtualPath; |
|
||||
|
|
||||
private IVirtualFileProvider _virtualFileProvider; |
|
||||
|
|
||||
private Dictionary<string, string> _templateDictionary; |
|
||||
|
|
||||
private readonly object _syncObj = new object(); |
|
||||
|
|
||||
public MultipleVirtualFilesEmailTemplateContributor(string virtualPath) |
|
||||
{ |
|
||||
_virtualPath = virtualPath; |
|
||||
} |
|
||||
|
|
||||
public void Initialize(EmailTemplateInitializationContext context) |
|
||||
{ |
|
||||
_virtualFileProvider = context.ServiceProvider.GetRequiredService<IVirtualFileProvider>(); |
|
||||
} |
|
||||
|
|
||||
public string GetOrNull(string cultureName) |
|
||||
{ |
|
||||
return GetTemplateDictionary().GetOrDefault(cultureName); |
|
||||
} |
|
||||
|
|
||||
private Dictionary<string, string> GetTemplateDictionary() |
|
||||
{ |
|
||||
var dictionaries = _templateDictionary; |
|
||||
if (dictionaries != null) |
|
||||
{ |
|
||||
return dictionaries; |
|
||||
} |
|
||||
|
|
||||
lock (_syncObj) |
|
||||
{ |
|
||||
dictionaries = _templateDictionary; |
|
||||
if (dictionaries != null) |
|
||||
{ |
|
||||
return dictionaries; |
|
||||
} |
|
||||
|
|
||||
_templateDictionary = new Dictionary<string, string>(); |
|
||||
foreach (var file in _virtualFileProvider.GetDirectoryContents(_virtualPath)) |
|
||||
{ |
|
||||
if (file.IsDirectory) |
|
||||
{ |
|
||||
continue; |
|
||||
} |
|
||||
|
|
||||
// TODO: How to normalize file names?
|
|
||||
_templateDictionary.Add(file.Name.RemovePostFix(".tpl"), file.ReadAsString()); |
|
||||
} |
|
||||
|
|
||||
dictionaries = _templateDictionary; |
|
||||
} |
|
||||
|
|
||||
return dictionaries; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,34 +0,0 @@ |
|||||
using Microsoft.Extensions.DependencyInjection; |
|
||||
using Microsoft.Extensions.FileProviders; |
|
||||
using Volo.Abp.VirtualFileSystem; |
|
||||
|
|
||||
namespace Volo.Abp.Emailing.Templates.VirtualFiles |
|
||||
{ |
|
||||
public class SingleVirtualFileEmailTemplateContributor : IEmailTemplateContributor |
|
||||
{ |
|
||||
private readonly string _virtualPath; |
|
||||
|
|
||||
private IVirtualFileProvider _virtualFileProvider; |
|
||||
|
|
||||
public SingleVirtualFileEmailTemplateContributor(string virtualPath) |
|
||||
{ |
|
||||
_virtualPath = virtualPath; |
|
||||
} |
|
||||
|
|
||||
public void Initialize(EmailTemplateInitializationContext context) |
|
||||
{ |
|
||||
_virtualFileProvider = context.ServiceProvider.GetRequiredService<IVirtualFileProvider>(); |
|
||||
} |
|
||||
|
|
||||
public string GetOrNull(string cultureName) |
|
||||
{ |
|
||||
var file = _virtualFileProvider.GetFileInfo(_virtualPath); |
|
||||
if (file == null || !file.Exists || file.IsDirectory) |
|
||||
{ |
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
return file.ReadAsString(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,18 +0,0 @@ |
|||||
using System.Text.RegularExpressions; |
|
||||
using Microsoft.Extensions.Localization; |
|
||||
using Volo.Abp.DependencyInjection; |
|
||||
|
|
||||
namespace Volo.Abp.Localization |
|
||||
{ |
|
||||
public class TemplateLocalizer : ITemplateLocalizer, ITransientDependency |
|
||||
{ |
|
||||
public string Localize(IStringLocalizer localizer, string text) |
|
||||
{ |
|
||||
return new Regex("\\{\\{#L:.+?\\}\\}") |
|
||||
.Replace( |
|
||||
text, |
|
||||
match => localizer[match.Value.Substring(5, match.Length - 7)] |
|
||||
); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,65 +0,0 @@ |
|||||
using System.Collections.Generic; |
|
||||
using System.Threading.Tasks; |
|
||||
using Shouldly; |
|
||||
using Volo.Abp.Emailing.Templates; |
|
||||
using Volo.Abp.Testing; |
|
||||
using Xunit; |
|
||||
|
|
||||
namespace Volo.Abp.Emailing |
|
||||
{ |
|
||||
public class EmailTemplateRender_Tests : AbpIntegratedTest<AbpEmailingTestModule> |
|
||||
{ |
|
||||
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) |
|
||||
{ |
|
||||
options.UseAutofac(); |
|
||||
} |
|
||||
|
|
||||
private readonly ITemplateRender _templateRender; |
|
||||
|
|
||||
public EmailTemplateRender_Tests() |
|
||||
{ |
|
||||
_templateRender = GetRequiredService<ITemplateRender>(); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public async Task RenderAsync() |
|
||||
{ |
|
||||
var template = "Hello {{email}} {{ for order in orders }}{{ order.id }}:{{ order.name }},{{ end }}"; |
|
||||
|
|
||||
var model = new ModelClass |
|
||||
{ |
|
||||
Email = "john@abp.io", |
|
||||
Orders = new List<ModelClass.Order> |
|
||||
{ |
|
||||
new ModelClass.Order |
|
||||
{ |
|
||||
Id = "1", |
|
||||
Name = "iphone" |
|
||||
}, |
|
||||
new ModelClass.Order |
|
||||
{ |
|
||||
Id = "2", |
|
||||
Name = "ipad" |
|
||||
} |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
var result = await _templateRender.RenderAsync(template, model); |
|
||||
result.ShouldBe("Hello john@abp.io 1:iphone,2:ipad,"); |
|
||||
} |
|
||||
|
|
||||
public class ModelClass |
|
||||
{ |
|
||||
public string Email { get; set; } |
|
||||
|
|
||||
public List<Order> Orders { get; set; } |
|
||||
|
|
||||
public class Order |
|
||||
{ |
|
||||
public string Id { get; set; } |
|
||||
|
|
||||
public string Name { get; set; } |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,54 +0,0 @@ |
|||||
using System; |
|
||||
using System.Threading.Tasks; |
|
||||
using Shouldly; |
|
||||
using Volo.Abp.Emailing.Templates; |
|
||||
using Volo.Abp.Testing; |
|
||||
using Xunit; |
|
||||
|
|
||||
namespace Volo.Abp.Emailing |
|
||||
{ |
|
||||
public class EmailTemplateStore_Tests : AbpIntegratedTest<AbpEmailingTestModule> |
|
||||
{ |
|
||||
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) |
|
||||
{ |
|
||||
options.UseAutofac(); |
|
||||
} |
|
||||
|
|
||||
private readonly IEmailTemplateProvider _emailTemplateProvider; |
|
||||
|
|
||||
public EmailTemplateStore_Tests() |
|
||||
{ |
|
||||
_emailTemplateProvider = GetRequiredService<IEmailTemplateProvider>(); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public async Task Should_Get_Registered_Template() |
|
||||
{ |
|
||||
var template = await _emailTemplateProvider.GetAsync("template1", "tr"); |
|
||||
template.Content.ShouldContain("Lütfen aşağıdaki bağlantıya tıklayarak e-posta adresinizi onaylayın."); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public async Task Should_Get_Default_Culture_Template() |
|
||||
{ |
|
||||
var template = await _emailTemplateProvider.GetAsync("template1", "zh-Hans"); |
|
||||
template.Content.ShouldContain("Please confirm your email address by clicking the link below."); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public async Task Should_Get_Registered_Template_With_Layout() |
|
||||
{ |
|
||||
var template = await _emailTemplateProvider.GetAsync("template2", "en"); |
|
||||
|
|
||||
template.Content.ShouldContain($"<body>{Environment.NewLine} " + "Please confirm your email address by clicking the link below."); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
[Fact] |
|
||||
public async Task Should_Get_Registered_Template_With_Localize() |
|
||||
{ |
|
||||
var template = await _emailTemplateProvider.GetAsync("template3", "tr"); |
|
||||
template.Content.ShouldContain("Merhaba Abp"); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,10 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Text; |
|
||||
|
|
||||
namespace Volo.Abp.Emailing.Localization |
|
||||
{ |
|
||||
public class AbpEmailingTestResource |
|
||||
{ |
|
||||
} |
|
||||
} |
|
||||
@ -1,6 +0,0 @@ |
|||||
{ |
|
||||
"culture": "cs", |
|
||||
"texts": { |
|
||||
"hello": "ahoj" |
|
||||
} |
|
||||
} |
|
||||
@ -1,6 +0,0 @@ |
|||||
{ |
|
||||
"culture": "en", |
|
||||
"texts": { |
|
||||
"hello": "hello" |
|
||||
} |
|
||||
} |
|
||||
@ -1,6 +0,0 @@ |
|||||
{ |
|
||||
"culture": "pl", |
|
||||
"texts": { |
|
||||
"hello": "witaj" |
|
||||
} |
|
||||
} |
|
||||
@ -1,6 +0,0 @@ |
|||||
{ |
|
||||
"culture": "pt-BR", |
|
||||
"texts": { |
|
||||
"hello": "Olá" |
|
||||
} |
|
||||
} |
|
||||
@ -1,6 +0,0 @@ |
|||||
{ |
|
||||
"culture": "tr", |
|
||||
"texts": { |
|
||||
"hello": "Merhaba" |
|
||||
} |
|
||||
} |
|
||||
@ -1,6 +0,0 @@ |
|||||
{ |
|
||||
"culture": "vi", |
|
||||
"texts": { |
|
||||
"hello": "xin chào" |
|
||||
} |
|
||||
} |
|
||||
@ -1,6 +0,0 @@ |
|||||
{ |
|
||||
"culture": "zh-Hant", |
|
||||
"texts": { |
|
||||
"hello": "哈囉" |
|
||||
} |
|
||||
} |
|
||||
@ -1,24 +0,0 @@ |
|||||
using Volo.Abp.Emailing.Localization; |
|
||||
using Volo.Abp.Emailing.Templates; |
|
||||
using Volo.Abp.Emailing.Templates.VirtualFiles; |
|
||||
|
|
||||
namespace Volo.Abp.Emailing |
|
||||
{ |
|
||||
public class TestEmailTemplateProvider : EmailTemplateDefinitionProvider |
|
||||
{ |
|
||||
public override void Define(IEmailTemplateDefinitionContext context) |
|
||||
{ |
|
||||
var template1 = new EmailTemplateDefinition("template1", defaultCultureName: "en", layout: null) |
|
||||
.AddTemplateVirtualFiles("/Volo/Abp/Emailing/TestTemplates/Template1"); |
|
||||
context.Add(template1); |
|
||||
|
|
||||
var template2 = new EmailTemplateDefinition("template2", layout: StandardEmailTemplates.DefaultLayout) |
|
||||
.AddTemplateVirtualFiles("/Volo/Abp/Emailing/TestTemplates/Template2"); |
|
||||
context.Add(template2); |
|
||||
|
|
||||
var template3 = new EmailTemplateDefinition("template3", layout: null, singleTemplateFile: true, localizationResource: typeof(AbpEmailingTestResource)) |
|
||||
.AddTemplateVirtualFile("/Volo/Abp/Emailing/TestTemplates/Template3/Template.tpl"); |
|
||||
context.Add(template3); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,4 +0,0 @@ |
|||||
Please confirm your email address by clicking the link below. |
|
||||
We may need to send you critical information about our service and it is important that we have an accurate email address. |
|
||||
|
|
||||
<a href="#">Confirm email address</a> |
|
||||
@ -1,4 +0,0 @@ |
|||||
Lütfen aşağıdaki bağlantıya tıklayarak e-posta adresinizi onaylayın. |
|
||||
Size hizmetimizle ilgili kritik bilgileri göndermemiz gerekebilir ve doğru bir e-posta adresimizin olması önemlidir. |
|
||||
|
|
||||
<a href="#">E-posta adresini onayla</a> |
|
||||
@ -1,4 +0,0 @@ |
|||||
Please confirm your email address by clicking the link below. |
|
||||
We may need to send you critical information about our service and it is important that we have an accurate email address. |
|
||||
|
|
||||
<a href="#">Confirm email address</a> |
|
||||
@ -1 +0,0 @@ |
|||||
{{#L:hello}} Abp |
|
||||
@ -1,63 +0,0 @@ |
|||||
using Microsoft.Extensions.DependencyInjection; |
|
||||
using Microsoft.Extensions.Localization; |
|
||||
using Shouldly; |
|
||||
using Volo.Abp.Localization.TestResources.Source; |
|
||||
using Volo.Abp.Modularity; |
|
||||
using Volo.Abp.Testing; |
|
||||
using Volo.Abp.VirtualFileSystem; |
|
||||
using Xunit; |
|
||||
|
|
||||
namespace Volo.Abp.Localization |
|
||||
{ |
|
||||
public class TemplateLocalizer_Tests : AbpIntegratedTest<TemplateLocalizer_Tests.TestModule> |
|
||||
{ |
|
||||
private readonly ITemplateLocalizer _templateLocalizer; |
|
||||
private readonly IStringLocalizer<LocalizationTestResource> _testResource; |
|
||||
|
|
||||
public TemplateLocalizer_Tests() |
|
||||
{ |
|
||||
_testResource = GetRequiredService<IStringLocalizer<LocalizationTestResource>>(); |
|
||||
_templateLocalizer = GetRequiredService<ITemplateLocalizer>(); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Should_Localize() |
|
||||
{ |
|
||||
using (CultureHelper.Use("en")) |
|
||||
{ |
|
||||
_templateLocalizer.Localize(_testResource, "<p>{{#L:CarPlural}} <b>{{#L:Universe}}</b></p>") |
|
||||
.ShouldBe("<p>Cars <b>Universe</b></p>"); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Should_Work_Even_If_No_Text_To_Localize() |
|
||||
{ |
|
||||
using (CultureHelper.Use("en")) |
|
||||
{ |
|
||||
_templateLocalizer.Localize(_testResource, "<p>test</p>") |
|
||||
.ShouldBe("<p>test</p>"); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
[DependsOn(typeof(AbpTestBaseModule))] |
|
||||
[DependsOn(typeof(AbpLocalizationModule))] |
|
||||
public class TestModule : AbpModule |
|
||||
{ |
|
||||
public override void ConfigureServices(ServiceConfigurationContext context) |
|
||||
{ |
|
||||
Configure<AbpVirtualFileSystemOptions>(options => |
|
||||
{ |
|
||||
options.FileSets.AddEmbedded<AbpLocalization_Tests.TestModule>(); |
|
||||
}); |
|
||||
|
|
||||
Configure<AbpLocalizationOptions>(options => |
|
||||
{ |
|
||||
options.Resources |
|
||||
.Add<LocalizationTestResource>("en") |
|
||||
.AddVirtualJson("/Volo/Abp/Localization/TestResources/Source"); |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue