# Text Templating In ABP Framework, `text template` is a mixture of text blocks and control logic that can generate a `string` result. An open source package [Scriban](https://github.com/lunet-io/scriban) is used for the control logic and [Abp.Localization](Localization.md) is used to make content easily localizable. The generated string can be text of any kind, such as a web page, an e-mail content etc. > **stored content** ```html
{{L "PasswordResetInfoInEmail"}}
``` ### Localization You can localize your Text Templates by choosing two different method. - `Inline Localization` - `Multiple Content Localization` #### Inline Localization Inline localized Text Templates is using only one content resource, and it is using the `Abp.Localization` to get content in different languages/cultures. > Example Inline Localized Text Template: > > ForgotPasswordEmail.tpl ```html{{L "PasswordResetInfoInEmail"}}
``` #### Multiple Content Localization You can store your Text Templates for any culture in different content resource. > Example Multiple Content Localization > ForgotPasswordEmail / en.tpl ```htmlHello, this is a password changing email.
``` > ForgotPasswordEmail / tr.tpl ```htmlMerhaba, bu bir şifre yenileme e postasıdır.
``` ### Layout System It is typical to use the same layout for some different Text Templates. So, you can define a layout template. A text template can be layout for different text templates and also a text template may use a layout. A layout Text Template must have `{{content}}` area to render the child content. _(just like the `RenderBody()` in the MVC)_ > Example Email Layout Text Template ```html {{content}} ``` ## Definition a Text Template First of all, create a class that inherited from `TemplateDefinitionProvider` abstract class and create `Define` method that derived from the base class. `Define` method requires a context that is `ITemplateDefinitionContext`. This `context` is a storage for template definitions and we will add our template definitions to the context. > **NOTE!** For default, ABP uses **Virtual File System** for text templates. Do not forget to register your files as an `Embedded Resource`. Please check the [Virtual File System Documentation](Virtual-File-System.md) for more details. > All given examples are for `Virtual File Text Template Definitions`. ```csharp public class MyTemplateDefinitionProvider : TemplateDefinitionProvider { public override void Define(ITemplateDefinitionContext context) { // Layout Text Template context.Add( new TemplateDefinition( name: "MySampleTemplateLayout", // Template Definition Name isLayout: true ).WithVirtualFilePath("/SampleTemplates/SampleTemplateLayout.tpl", true) ); // Inline Localized Text Template context.Add( new TemplateDefinition( name: "ForgotPasswordEmail", localizationResource: typeof(MyLocalizationResource), layout: TestTemplates.TestTemplateLayout1 ).WithVirtualFilePath("/SampleTemplates/ForgotPasswordEmail.tpl", true) ); // Multiple File Localized Text Template context.Add( new TemplateDefinition( name: "ForgotPasswordEmail", defaultCultureName: "en" ).WithVirtualFilePath("/SampleTemplates/ForgotPasswordEmail", false) ); } } ``` As you see in the given example, all Text Templates are added with `(ITemplateDefinitionContext)context.Add` method. This method requires a `TemplateDefinition` object. Then we call `WithVirtualFilePath` method with chaining for the describe where is the virtual files. `WithVirtualFilePath` is requires one `tpl` file path for the `Inline Localized` Text Templates. If your Text Tempalte is `Multi Localized` you should create a folder and store each different culture files under that. So you can send the folder path as a parameter to `WithVirtualFilePath`. > Inline Localized File ``` / Folder / ForgotPasswordEmail.tpl ``` > Multi Content Localization ``` / Folder / ForgotPasswordEmail / en.tpl / Folder / ForgotPasswordEmail / tr.tpl ``` ## Rendering When one template is registered, it is easy to render and get the result with `ITemplateRenderer` service. `ITemplateRenderer` service has one method that named `RenderAsync` and to render your content and it is requires some parametres. - `templateName` (string) **_Not Null_** - `model` (object) **_Can Be Null_** - `cultureName` (string) **_Can Be Null_** - `globalContext` (dictionary) **_Can Be Null_** `templateName` is exactly same with Template Definition Name. `model` is a dynamic object. This is using to put dynamic data into template. For more information, please look at [Scriban Documentation](https://github.com/lunet-io/scriban). `cultureName` is your rendering destination culture. When it is not exist, it will use the default culture. > If `cultureName` has a language tag it will try to find exact culture with tag, if it is not exist it will use the language family. > If you try to render content with _"es-MX"_ it will search your template with _"es-MX"_ culture, when it fails to find, it will try to render _"es"_ culture content. If still can't find it will render the default culture content that you defined. `globalContext` = TODO ## Template Definition Manager When you want to get your `Template Definitions`, you can use a singleton service that named `Template Definition Manager` in runtime. To use it, inject `ITemplateDefinitionManager` service. It has three method that you can get your Template Definitions. - `Get` - `GetOrNull` - `GetAll` `Get` and `GetOrNull` requires a string parameter that name of template definition. `Get` will throw error when it is not exist but `GetOrNull` returns `null`. `GetAll` returns you all registered template definitions. ## Template Content Contributor