diff --git a/framework/src/Volo.Abp.Emailing/Volo.Abp.Emailing.csproj b/framework/src/Volo.Abp.Emailing/Volo.Abp.Emailing.csproj index a91be8faf5..c93b84ea0b 100644 --- a/framework/src/Volo.Abp.Emailing/Volo.Abp.Emailing.csproj +++ b/framework/src/Volo.Abp.Emailing/Volo.Abp.Emailing.csproj @@ -14,6 +14,12 @@ + + + + + + diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/AbpEmailingModule.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/AbpEmailingModule.cs index d4b6c4e2e8..aecb3df7fd 100644 --- a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/AbpEmailingModule.cs +++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/AbpEmailingModule.cs @@ -1,4 +1,7 @@ using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Emailing.Templates; +using Volo.Abp.Emailing.Templates.Virtual; +using Volo.Abp.Localization; using Volo.Abp.Modularity; using Volo.Abp.Settings; using Volo.Abp.VirtualFileSystem; @@ -7,7 +10,8 @@ namespace Volo.Abp.Emailing { [DependsOn( typeof(AbpSettingsModule), - typeof(AbpVirtualFileSystemModule) + typeof(AbpVirtualFileSystemModule), + typeof(AbpLocalizationModule) )] public class AbpEmailingModule : AbpModule { @@ -18,6 +22,23 @@ namespace Volo.Abp.Emailing options.DefinitionProviders.Add(); }); + context.Services.Configure(options => + { + options.FileSets.AddEmbedded(); + }); + + context.Services.Configure(options => + { + options.Templates + .Add( + new EmailTemplateDefinition(StandardEmailTemplates.DefaultLayout, isLayout: true, layout: null) + .SetVirtualFilePath("/Volo/Abp/Emailing/Templates/DefaultLayout.html") + ).Add( + new EmailTemplateDefinition(StandardEmailTemplates.SimpleMessage) + .SetVirtualFilePath("/Volo/Abp/Emailing/Templates/SimpleMessageTemplate.html") + ); + }); + context.Services.AddAssemblyOf(); } } diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/DefaultLayout.html b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/DefaultLayout.html new file mode 100644 index 0000000000..107fbb5230 --- /dev/null +++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/DefaultLayout.html @@ -0,0 +1,9 @@ + + + + + + + {{#content}} + + \ No newline at end of file diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplate.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplate.cs index 1d4c29053f..ad6f8c4839 100644 --- a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplate.cs +++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplate.cs @@ -1,12 +1,42 @@ -namespace Volo.Abp.Emailing.Templates +using System.Text; + +namespace Volo.Abp.Emailing.Templates { public class EmailTemplate { - public string Content { get; } + 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 EmailTemplate(string content) + public virtual void Replace(string name, string value) { - Content = content; + ContentBuilder.Replace("{{" + name + "}}", value); } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateDefinition.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateDefinition.cs index d852070e8a..9ef2ae3b1b 100644 --- a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateDefinition.cs +++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateDefinition.cs @@ -1,12 +1,21 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; 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 Dictionary Properties { get; } /// @@ -23,10 +32,13 @@ namespace Volo.Abp.Emailing.Templates set => Properties[name] = value; } - public EmailTemplateDefinition([NotNull]string name) + public EmailTemplateDefinition([NotNull]string name, Type localizationResource = null, bool isLayout = false, string layout = DefaultLayoutPlaceHolder) { Name = Check.NotNullOrWhiteSpace(name, nameof(name)); Properties = new Dictionary(); + LocalizationResource = localizationResource; + IsLayout = isLayout; + Layout = layout; } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateDefinitionDictionary.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateDefinitionDictionary.cs index 09bc33ec97..aa36232156 100644 --- a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateDefinitionDictionary.cs +++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateDefinitionDictionary.cs @@ -4,6 +4,19 @@ namespace Volo.Abp.Emailing.Templates { public class EmailTemplateDefinitionDictionary : Dictionary { + 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; + } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateOptions.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateOptions.cs index d9bf02aae9..6d10bd562e 100644 --- a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateOptions.cs +++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateOptions.cs @@ -5,18 +5,22 @@ namespace Volo.Abp.Emailing.Templates { public class EmailTemplateOptions { - public List Providers { get; } + public List Providers { get; } public EmailTemplateDefinitionDictionary Templates { get; } + public string DefaultLayout { get; set; } + public EmailTemplateOptions() { - Providers = new List + Providers = new List { - new VirtualFileEmailTemplateProvider() + new VirtualFileEmailTemplateProviderContributor() }; Templates = new EmailTemplateDefinitionDictionary(); + + DefaultLayout = StandardEmailTemplates.DefaultLayout; } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateProvider.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateProvider.cs new file mode 100644 index 0000000000..c5fb44e0ed --- /dev/null +++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateProvider.cs @@ -0,0 +1,91 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +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 IServiceProvider ServiceProvider { get; } + protected ITemplateLocalizer TemplateLocalizer { get; } + protected EmailTemplateOptions Options { get; } + + public EmailTemplateProvider( + IOptions options, + IServiceProvider serviceProvider, + ITemplateLocalizer templateLocalizer) + { + ServiceProvider = serviceProvider; + TemplateLocalizer = templateLocalizer; + Options = options.Value; + } + + public async Task GetAsync(string name) + { + using (var scope = ServiceProvider.CreateScope()) + { + return await GetInternalAsync(scope.ServiceProvider, name); + } + } + + protected virtual async Task GetInternalAsync(IServiceProvider serviceProvider, string name) + { + var context = new EmailTemplateProviderContributorContext(name, serviceProvider); + + foreach (var provider in Options.Providers) + { + await provider.ProvideAsync(context); + } + + if (context.Template == null) + { + throw new AbpException($"Could not found the template: {name}"); + } + + await SetLayoutAsync(serviceProvider, context); + await LocalizeAsync(serviceProvider, context); + + return context.Template; + } + + protected virtual async Task SetLayoutAsync(IServiceProvider serviceProvider, EmailTemplateProviderContributorContext context) + { + var layout = context.Template.Definition.Layout; + + if (layout.IsNullOrEmpty()) + { + return; + } + + if (layout == EmailTemplateDefinition.DefaultLayoutPlaceHolder) + { + layout = Options.DefaultLayout; + } + + var layoutTemplate = await GetInternalAsync(serviceProvider, layout); + context.Template.SetLayout(layoutTemplate); + } + + protected virtual Task LocalizeAsync(IServiceProvider serviceProvider, EmailTemplateProviderContributorContext context) + { + if (context.Template.Definition.LocalizationResource == null) + { + return Task.CompletedTask; + } + + var localizer = serviceProvider + .GetRequiredService() + .Create(context.Template.Definition.LocalizationResource); + + context.Template.SetContent( + TemplateLocalizer.Localize(localizer, context.Template.Content) + ); + + return Task.CompletedTask; + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateProviderContext.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateProviderContributorContext.cs similarity index 64% rename from framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateProviderContext.cs rename to framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateProviderContributorContext.cs index c1fbc311ba..9893ddc789 100644 --- a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateProviderContext.cs +++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateProviderContributorContext.cs @@ -3,7 +3,7 @@ using Volo.Abp.DependencyInjection; namespace Volo.Abp.Emailing.Templates { - public class EmailTemplateProviderContext : IServiceProviderAccessor + public class EmailTemplateProviderContributorContext : IServiceProviderAccessor { public string Name { get; } @@ -11,7 +11,7 @@ namespace Volo.Abp.Emailing.Templates public EmailTemplate Template { get; set; } - public EmailTemplateProviderContext(string name, IServiceProvider serviceProvider) + public EmailTemplateProviderContributorContext(string name, IServiceProvider serviceProvider) { Name = name; ServiceProvider = serviceProvider; diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateStore.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateStore.cs deleted file mode 100644 index 231c86f653..0000000000 --- a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateStore.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; -using Volo.Abp.DependencyInjection; - -namespace Volo.Abp.Emailing.Templates -{ - public class EmailTemplateStore : IEmailTemplateStore, ITransientDependency - { - protected IServiceProvider ServiceProvider { get; } - protected EmailTemplateOptions Options { get; } - - public EmailTemplateStore(IOptions options, IServiceProvider serviceProvider) - { - ServiceProvider = serviceProvider; - Options = options.Value; - } - - public async Task GetAsync(string name) - { - using (var scope = ServiceProvider.CreateScope()) - { - var context = new EmailTemplateProviderContext(name, scope.ServiceProvider); - foreach (var provider in Options.Providers) - { - await provider.ProvideAsync(context); - } - - if (context.Template == null) - { - //TODO: Return a default email template! - throw new NotImplementedException(); - } - - return context.Template; - } - } - } -} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/IEmailTemplateProvider.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/IEmailTemplateProvider.cs index 4c05e04f30..aad1fe4f05 100644 --- a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/IEmailTemplateProvider.cs +++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/IEmailTemplateProvider.cs @@ -4,6 +4,6 @@ namespace Volo.Abp.Emailing.Templates { public interface IEmailTemplateProvider { - Task ProvideAsync(EmailTemplateProviderContext context); + Task GetAsync(string name); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/IEmailTemplateProviderContributor.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/IEmailTemplateProviderContributor.cs new file mode 100644 index 0000000000..6bc63f9661 --- /dev/null +++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/IEmailTemplateProviderContributor.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace Volo.Abp.Emailing.Templates +{ + public interface IEmailTemplateProviderContributor + { + Task ProvideAsync(EmailTemplateProviderContributorContext contributorContext); + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/IEmailTemplateStore.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/IEmailTemplateStore.cs deleted file mode 100644 index ae35725fff..0000000000 --- a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/IEmailTemplateStore.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Threading.Tasks; - -namespace Volo.Abp.Emailing.Templates -{ - public interface IEmailTemplateStore - { - Task GetAsync(string name); - } -} diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/SimpleMessageTemplate.html b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/SimpleMessageTemplate.html new file mode 100644 index 0000000000..6454b0b93a --- /dev/null +++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/SimpleMessageTemplate.html @@ -0,0 +1 @@ +{{message}} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/StandardEmailTemplates.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/StandardEmailTemplates.cs new file mode 100644 index 0000000000..7e8cbedc68 --- /dev/null +++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/StandardEmailTemplates.cs @@ -0,0 +1,8 @@ +namespace Volo.Abp.Emailing.Templates +{ + public static class StandardEmailTemplates + { + public const string DefaultLayout = "Abp.DefaultLayout"; + public const string SimpleMessage = "Abp.SimpleMessage"; + } +} diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/Virtual/EmailTemplateDefinitionExtensions.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/Virtual/EmailTemplateDefinitionExtensions.cs index 2bcd3984d1..cb49491b0f 100644 --- a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/Virtual/EmailTemplateDefinitionExtensions.cs +++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/Virtual/EmailTemplateDefinitionExtensions.cs @@ -4,13 +4,13 @@ { public static EmailTemplateDefinition SetVirtualFilePath(this EmailTemplateDefinition emailTemplateDefinition, string path) { - emailTemplateDefinition[VirtualFileEmailTemplateProvider.VirtualFilePathKey] = path; + emailTemplateDefinition[VirtualFileEmailTemplateProviderContributor.VirtualFilePathKey] = path; return emailTemplateDefinition; } public static string GetVirtualFilePathOrNull(this EmailTemplateDefinition emailTemplateDefinition) { - return emailTemplateDefinition[VirtualFileEmailTemplateProvider.VirtualFilePathKey] as string; + return emailTemplateDefinition[VirtualFileEmailTemplateProviderContributor.VirtualFilePathKey] as string; } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/Virtual/VirtualFileEmailTemplateProvider.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/Virtual/VirtualFileEmailTemplateProviderContributor.cs similarity index 64% rename from framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/Virtual/VirtualFileEmailTemplateProvider.cs rename to framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/Virtual/VirtualFileEmailTemplateProviderContributor.cs index f5c3dece34..d54f4c94cb 100644 --- a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/Virtual/VirtualFileEmailTemplateProvider.cs +++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/Virtual/VirtualFileEmailTemplateProviderContributor.cs @@ -7,39 +7,39 @@ using Volo.Abp.VirtualFileSystem; namespace Volo.Abp.Emailing.Templates.Virtual { - public class VirtualFileEmailTemplateProvider : IEmailTemplateProvider + public class VirtualFileEmailTemplateProviderContributor : IEmailTemplateProviderContributor { public const string VirtualFilePathKey = "VirtualFilePath"; - public Task ProvideAsync(EmailTemplateProviderContext context) + public Task ProvideAsync(EmailTemplateProviderContributorContext contributorContext) { - var templateDefinition = FindTemplateDefinition(context); + var templateDefinition = FindTemplateDefinition(contributorContext); if (templateDefinition == null) { return Task.CompletedTask; } - var fileInfo = FindVirtualFileInfo(context, templateDefinition); + var fileInfo = FindVirtualFileInfo(contributorContext, templateDefinition); if (fileInfo == null) { return Task.CompletedTask; } - context.Template = new EmailTemplate(fileInfo.ReadAsString()); + contributorContext.Template = new EmailTemplate(fileInfo.ReadAsString(), templateDefinition); return Task.CompletedTask; } - protected virtual EmailTemplateDefinition FindTemplateDefinition(EmailTemplateProviderContext context) + protected virtual EmailTemplateDefinition FindTemplateDefinition(EmailTemplateProviderContributorContext contributorContext) { - return context + return contributorContext .ServiceProvider .GetRequiredService>() .Value .Templates - .GetOrDefault(context.Name); + .GetOrDefault(contributorContext.Name); } - protected virtual IFileInfo FindVirtualFileInfo(EmailTemplateProviderContext context, EmailTemplateDefinition templateDefinition) + protected virtual IFileInfo FindVirtualFileInfo(EmailTemplateProviderContributorContext contributorContext, EmailTemplateDefinition templateDefinition) { var virtualFilePath = templateDefinition?.GetVirtualFilePathOrNull(); if (virtualFilePath == null) @@ -47,7 +47,7 @@ namespace Volo.Abp.Emailing.Templates.Virtual return null; } - var virtualFileProvider = context.ServiceProvider.GetRequiredService(); + var virtualFileProvider = contributorContext.ServiceProvider.GetRequiredService(); var fileInfo = virtualFileProvider.GetFileInfo(virtualFilePath); if (fileInfo?.Exists != true) diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/ITemplateLocalizer.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/ITemplateLocalizer.cs new file mode 100644 index 0000000000..3214e00309 --- /dev/null +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/ITemplateLocalizer.cs @@ -0,0 +1,9 @@ +using Microsoft.Extensions.Localization; + +namespace Volo.Abp.Localization +{ + public interface ITemplateLocalizer + { + string Localize(IStringLocalizer localizer, string text); + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/TemplateLocalizer.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/TemplateLocalizer.cs new file mode 100644 index 0000000000..5c4220c45f --- /dev/null +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/TemplateLocalizer.cs @@ -0,0 +1,18 @@ +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)] + ); + } + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/EmailTemplateStore_Tests.cs b/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/EmailTemplateStore_Tests.cs index 023b6404f4..a09fb48ed1 100644 --- a/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/EmailTemplateStore_Tests.cs +++ b/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/EmailTemplateStore_Tests.cs @@ -7,17 +7,17 @@ namespace Volo.Abp.Emailing { public class EmailTemplateStore_Tests : AbpIntegratedTest { - private readonly IEmailTemplateStore _emailTemplateStore; + private readonly IEmailTemplateProvider _emailTemplateProvider; public EmailTemplateStore_Tests() { - _emailTemplateStore = GetRequiredService(); + _emailTemplateProvider = GetRequiredService(); } [Fact] public async Task Should_Get_Registered_Template() { - var template = await _emailTemplateStore.GetAsync("template1"); + var template = await _emailTemplateProvider.GetAsync("template1"); template.Content.ShouldContain("This is a test template!"); } } diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TemplateLocalizer_Tests.cs b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TemplateLocalizer_Tests.cs new file mode 100644 index 0000000000..2f8fd66726 --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TemplateLocalizer_Tests.cs @@ -0,0 +1,62 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Localization; +using Shouldly; +using Volo.Abp.Localization.TestResources.Source; +using Volo.Abp.Modularity; +using Volo.Abp.VirtualFileSystem; +using Xunit; + +namespace Volo.Abp.Localization +{ + public class TemplateLocalizer_Tests : AbpIntegratedTest + { + private readonly ITemplateLocalizer _templateLocalizer; + private readonly IStringLocalizer _testResource; + + public TemplateLocalizer_Tests() + { + _testResource = GetRequiredService>(); + _templateLocalizer = GetRequiredService(); + } + + [Fact] + public void Should_Localize() + { + using (AbpCultureHelper.Use("en")) + { + _templateLocalizer.Localize(_testResource, "

{{#L:CarPlural}} {{#L:Universe}}

") + .ShouldBe("

Cars Universe

"); + } + } + + [Fact] + public void Should_Work_Even_If_No_Text_To_Localize() + { + using (AbpCultureHelper.Use("en")) + { + _templateLocalizer.Localize(_testResource, "

test

") + .ShouldBe("

test

"); + } + } + + [DependsOn(typeof(AbpTestBaseModule))] + [DependsOn(typeof(AbpLocalizationModule))] + public class TestModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.Configure(options => + { + options.FileSets.AddEmbedded(); + }); + + context.Services.Configure(options => + { + options.Resources + .Add("en") + .AddVirtualJson("/Volo/Abp/Localization/TestResources/Source"); + }); + } + } + } +} diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/en.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/en.json index 974f7081d0..0388b6efe2 100644 --- a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/en.json +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/en.json @@ -4,6 +4,7 @@ "Hello {0}.": "Hello {0}.", "Car": "Car", "CarPlural": "Cars", - "MaxLenghtErrorMessage": "This field's length can be maximum of '{0}' chars" + "MaxLenghtErrorMessage": "This field's length can be maximum of '{0}' chars", + "Universe": "Universe" } } \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/tr.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/tr.json index ff92ed51bd..fa2d23246b 100644 --- a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/tr.json +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/tr.json @@ -3,6 +3,7 @@ "texts": { "Hello {0}.": "Merhaba {0}.", "Car": "Araba", - "CarPlural": "Araba" + "CarPlural": "Araba", + "Universe": "Evren" } } \ No newline at end of file