Browse Source

Refactored text templating and added more tests.

pull/3792/head
Halil İbrahim Kalkan 6 years ago
parent
commit
0311092ae1
  1. 7
      framework/src/Volo.Abp.Core/Volo/Abp/Localization/CultureHelper.cs
  2. 4
      framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateDefinition.cs
  3. 120
      framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateRenderer.cs
  4. 3
      framework/test/Volo.Abp.TextTemplating.Tests/Volo.Abp.TextTemplating.Tests.csproj
  5. 12
      framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/AbpTextTemplatingTestModule.cs
  6. 6
      framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/Localization/TestLocalizationSource.cs
  7. 6
      framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/Localization/en.json
  8. 6
      framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/Localization/tr.json
  9. 2
      framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/ForgotPasswordEmail.tpl
  10. 1
      framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/TestTemplateLayout1.tpl
  11. 2
      framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/WelcomeEmail/en.tpl
  12. 2
      framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/WelcomeEmail/tr.tpl
  13. 24
      framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TemplateRenderer_Tests.cs
  14. 17
      framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TestTemplateDefinitionProvider.cs
  15. 6
      framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/VirtualFileTemplateContributor_Tests.cs

7
framework/src/Volo.Abp.Core/Volo/Abp/Localization/CultureHelper.cs

@ -10,7 +10,12 @@ namespace Volo.Abp.Localization
{
Check.NotNull(culture, nameof(culture));
return Use(new CultureInfo(culture), uiCulture == null ? null : new CultureInfo(uiCulture));
return Use(
new CultureInfo(culture),
uiCulture == null
? null
: new CultureInfo(uiCulture)
);
}
public static IDisposable Use([NotNull] CultureInfo culture, CultureInfo uiCulture = null)

4
framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateDefinition.cs

@ -5,8 +5,6 @@ namespace Volo.Abp.TextTemplating
{
public class TemplateDefinition
{
public const string DefaultLayoutPlaceHolder = "_";
[NotNull]
public string Name { get; }
@ -27,7 +25,7 @@ namespace Volo.Abp.TextTemplating
[NotNull] string name,
[CanBeNull] Type localizationResource = null,
bool isLayout = false,
string layout = DefaultLayoutPlaceHolder,
string layout = null,
string defaultCultureName = null)
{
Name = Check.NotNullOrWhiteSpace(name, nameof(name));

120
framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateRenderer.cs

@ -1,9 +1,13 @@
using System.Text.RegularExpressions;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.Extensions.Localization;
using Scriban;
using Scriban.Runtime;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Localization;
namespace Volo.Abp.TextTemplating
{
@ -14,8 +18,8 @@ namespace Volo.Abp.TextTemplating
private readonly IStringLocalizerFactory _stringLocalizerFactory;
public TemplateRenderer(
ITemplateContentProvider templateContentProvider,
ITemplateDefinitionManager templateDefinitionManager,
ITemplateContentProvider templateContentProvider,
ITemplateDefinitionManager templateDefinitionManager,
IStringLocalizerFactory stringLocalizerFactory)
{
_templateContentProvider = templateContentProvider;
@ -30,43 +34,111 @@ namespace Volo.Abp.TextTemplating
{
Check.NotNullOrWhiteSpace(templateName, nameof(templateName));
var templateDefinition = _templateDefinitionManager.Get(templateName);
var content = await _templateContentProvider.GetContentOrNullAsync(
templateDefinition,
cultureName
);
if (cultureName == null)
{
cultureName = CultureInfo.CurrentUICulture.Name;
}
if (templateDefinition.LocalizationResource != null)
using (CultureHelper.Use(cultureName))
{
var localizer = _stringLocalizerFactory.Create(templateDefinition.LocalizationResource);
content = Localize(localizer, content);
return await RenderInternalAsync(
templateName,
new Dictionary<string, object>(),
model
);
}
}
var renderedContent = await Template.Parse(content).RenderAsync(model);
private async Task<string> RenderInternalAsync(
string templateName,
Dictionary<string, object> globalContext,
object model = null)
{
var templateDefinition = _templateDefinitionManager.Get(templateName);
var renderedContent = await RenderSingleTemplateAsync(
templateDefinition,
globalContext,
model
);
if (templateDefinition.Layout != null)
{
renderedContent = await RenderAsync(
globalContext["content"] = renderedContent;
renderedContent = await RenderInternalAsync(
templateDefinition.Layout,
new
{
content = renderedContent
},
cultureName: cultureName
globalContext
);
}
return renderedContent;
}
public string Localize(IStringLocalizer localizer, string text)
private async Task<string> RenderSingleTemplateAsync(
TemplateDefinition templateDefinition,
Dictionary<string, object> globalContext,
object model = null)
{
var rawTemplateContent = await _templateContentProvider
.GetContentOrNullAsync(
templateDefinition
);
return await RenderTemplateContentWithScribanAsync(
templateDefinition,
rawTemplateContent,
globalContext,
model
);
}
protected virtual async Task<string> RenderTemplateContentWithScribanAsync(
TemplateDefinition templateDefinition,
string templateContent,
Dictionary<string, object> globalContext,
object model = null)
{
var context = CreateScribanTemplateContext(
templateDefinition,
globalContext,
model
);
return await Template
.Parse(templateContent)
.RenderAsync(context);
}
protected virtual TemplateContext CreateScribanTemplateContext(
TemplateDefinition templateDefinition,
Dictionary<string, object> globalContext,
object model = null)
{
return new Regex("\\{\\{#L:.+?\\}\\}")
.Replace(
text,
match => localizer[match.Value.Substring(5, match.Length - 7)]
var context = new TemplateContext();
var scriptObject = new ScriptObject();
scriptObject.Import(globalContext);
if (model != null)
{
scriptObject["model"] = model;
}
if (templateDefinition.LocalizationResource != null)
{
var localizer = _stringLocalizerFactory.Create(templateDefinition.LocalizationResource);
scriptObject.Import(
"l",
new Func<string, string>(
name => localizer[name]
)
);
}
context.PushGlobal(scriptObject);
return context;
}
}
}

3
framework/test/Volo.Abp.TextTemplating.Tests/Volo.Abp.TextTemplating.Tests.csproj

@ -8,11 +8,14 @@
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Volo\Abp\TextTemplating\Localization\**\*.json" />
<None Remove="Volo\Abp\TextTemplating\Localization\**\*.json" />
<EmbeddedResource Include="Volo\Abp\TextTemplating\SampleTemplates\**\*.tpl" />
<None Remove="Volo\Abp\TextTemplating\SampleTemplates\**\*.tpl" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Volo.Abp.Localization\Volo.Abp.Localization.csproj" />
<ProjectReference Include="..\AbpTestBase\AbpTestBase.csproj" />
<ProjectReference Include="..\..\src\Volo.Abp.TextTemplating\Volo.Abp.TextTemplating.csproj" />
<ProjectReference Include="..\..\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" />

12
framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/AbpTextTemplatingTestModule.cs

@ -1,5 +1,7 @@
using Volo.Abp.Autofac;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.TextTemplating.Localization;
using Volo.Abp.VirtualFileSystem;
namespace Volo.Abp.TextTemplating
@ -7,7 +9,8 @@ namespace Volo.Abp.TextTemplating
[DependsOn(
typeof(AbpTextTemplatingModule),
typeof(AbpTestBaseModule),
typeof(AbpAutofacModule)
typeof(AbpAutofacModule),
typeof(AbpLocalizationModule)
)]
public class AbpTextTemplatingTestModule : AbpModule
{
@ -17,6 +20,13 @@ namespace Volo.Abp.TextTemplating
{
options.FileSets.AddEmbedded<AbpTextTemplatingTestModule>("Volo.Abp.TextTemplating");
});
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Add<TestLocalizationSource>("en")
.AddVirtualJson("/Localization");
});
}
}
}

6
framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/Localization/TestLocalizationSource.cs

@ -0,0 +1,6 @@
namespace Volo.Abp.TextTemplating.Localization
{
public class TestLocalizationSource
{
}
}

6
framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/Localization/en.json

@ -0,0 +1,6 @@
{
"culture": "en",
"texts": {
"HelloText": "Hello"
}
}

6
framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/Localization/tr.json

@ -0,0 +1,6 @@
{
"culture": "tr",
"texts": {
"HelloText": "Merhaba"
}
}

2
framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/ForgotPasswordEmail.tpl

@ -1 +1 @@
Please click to the following link to get an email to reset your password!
{{l "HelloText"}}. Please click to the following link to get an email to reset your password!

1
framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/TestTemplateLayout1.tpl

@ -0,0 +1 @@
*BEGIN*{{content}}*END*

2
framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/WelcomeEmail/en.tpl

@ -1 +1 @@
Welcome {{name}} to the abp.io!
Welcome {{model.name}} to the abp.io!

2
framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/WelcomeEmail/tr.tpl

@ -1 +1 @@
Merhaba {{name}}, abp.io'ya hoşgeldiniz!
Merhaba {{model.name}}, abp.io'ya hoşgeldiniz!

24
framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TemplateRenderer_Tests.cs

@ -14,16 +14,6 @@ namespace Volo.Abp.TextTemplating
_templateRenderer = GetRequiredService<ITemplateRenderer>();
}
[Fact]
public async Task Should_Get_Rendered_Non_Localized_Template_Content()
{
var content = await _templateRenderer.RenderAsync(
TestTemplates.ForgotPasswordEmail
);
content.ShouldBe("Please click to the following link to get an email to reset your password!");
}
[Fact]
public async Task Should_Get_Rendered_Localized_Template_Content_With_Different_Cultures()
{
@ -86,6 +76,20 @@ namespace Volo.Abp.TextTemplating
)).ShouldBe("Welcome John to the abp.io!");
}
[Fact]
public async Task Should_Get_Rendered_Inline_Localized_Template()
{
(await _templateRenderer.RenderAsync(
TestTemplates.ForgotPasswordEmail,
cultureName: "en"
)).ShouldBe("*BEGIN*Hello. Please click to the following link to get an email to reset your password!*END*");
(await _templateRenderer.RenderAsync(
TestTemplates.ForgotPasswordEmail,
cultureName: "tr"
)).ShouldBe("*BEGIN*Merhaba. Please click to the following link to get an email to reset your password!*END*");
}
private class WelcomeEmailModel
{
public string Name { get; set; }

17
framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TestTemplateDefinitionProvider.cs

@ -1,4 +1,6 @@
namespace Volo.Abp.TextTemplating
using Volo.Abp.TextTemplating.Localization;
namespace Volo.Abp.TextTemplating
{
public class TestTemplateDefinitionProvider : TemplateDefinitionProvider
{
@ -13,13 +15,18 @@
context.Add(
new TemplateDefinition(
TestTemplates.ForgotPasswordEmail
TestTemplates.ForgotPasswordEmail,
localizationResource: typeof(TestLocalizationSource),
layout: TestTemplates.TestTemplateLayout1
).AddVirtualFiles("/SampleTemplates/ForgotPasswordEmail.tpl")
);
context.Add(new TemplateDefinition(
TestTemplates.TestTemplateLayout1
));
context.Add(
new TemplateDefinition(
TestTemplates.TestTemplateLayout1,
isLayout: true
).AddVirtualFiles("/SampleTemplates/TestTemplateLayout1.tpl")
);
}
}
}

6
framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/VirtualFileTemplateContributor_Tests.cs

@ -21,11 +21,11 @@ namespace Volo.Abp.TextTemplating.VirtualFiles
contributor
.GetOrNull("en")
.ShouldBe("Welcome {{name}} to the abp.io!");
.ShouldBe("Welcome {{model.name}} to the abp.io!");
contributor
.GetOrNull("tr")
.ShouldBe("Merhaba {{name}}, abp.io'ya hoşgeldiniz!");
.ShouldBe("Merhaba {{model.name}}, abp.io'ya hoşgeldiniz!");
}
[Fact]
@ -44,7 +44,7 @@ namespace Volo.Abp.TextTemplating.VirtualFiles
contributor
.GetOrNull()
.ShouldBe("Please click to the following link to get an email to reset your password!");
.ShouldBe("{{l \"HelloText\"}}. Please click to the following link to get an email to reset your password!");
}
}
}

Loading…
Cancel
Save