|
| 1 | +# PoExtractor |
| 2 | + |
| 3 | +This utility extracts translatable strings from the C# code and from the Razor templates to POT (portable object template) files. It is designed to follow conventions used in the OrchardCore project. |
| 4 | + |
| 5 | +## Usage |
| 6 | + |
| 7 | +`PoExtractor.exe inputpath outputpath` |
| 8 | + |
| 9 | +Extracts all translatable strings from the projects at specified input path and saves generated POT files at the specified output path. It creates one POT file per a project. |
| 10 | + |
| 11 | +## Limitations |
| 12 | + |
| 13 | +PoExtractor assumes, the code follows several conventions |
| 14 | + |
| 15 | +* `IStringLocalizer` or a derived class is accessed via property named `T` |
| 16 | +* context of the localizable string is full name (with namespace) of the containing class for C# code |
| 17 | +* context of the localizable string is dot-delimited relative path to view for Razor templates |
| 18 | + |
| 19 | +## Example |
| 20 | + |
| 21 | +C# code: |
| 22 | +```csharp |
| 23 | +namespace OrchardCore.ContentFields.Fields { |
| 24 | + public class LinkFieldDisplayDriver : ContentFieldDisplayDriver<LinkField> { |
| 25 | + public LinkFieldDisplayDriver(IStringLocalizer<LinkFieldDisplayDriver> localizer) { |
| 26 | + T = localizer; |
| 27 | + } |
| 28 | + |
| 29 | + public IStringLocalizer T { get; set; } |
| 30 | + |
| 31 | + public override async Task<IDisplayResult> UpdateAsync(LinkField field, IUpdateModel updater, UpdateFieldEditorContext context) { |
| 32 | + bool modelUpdated = await updater.TryUpdateModelAsync(field, Prefix, f => f.Url, f => f.Text); |
| 33 | + |
| 34 | + if (modelUpdated) |
| 35 | + { |
| 36 | + var settings = context.PartFieldDefinition.Settings.ToObject<LinkFieldSettings>(); |
| 37 | + |
| 38 | + if (settings.Required && String.IsNullOrWhiteSpace(field.Url)) |
| 39 | + { |
| 40 | + updater.ModelState.AddModelError(Prefix, T["The url is required for {0}.", context.PartFieldDefinition.DisplayName()]); |
| 41 | + } |
| 42 | + } |
| 43 | + |
| 44 | + return Edit(field, context); |
| 45 | + } |
| 46 | + } |
| 47 | +} |
| 48 | +``` |
| 49 | + |
| 50 | +Razor view: |
| 51 | +```html |
| 52 | +@model OrchardCore.ContentFields.ViewModels.EditLinkFieldViewModel |
| 53 | + |
| 54 | +<div class="row"> |
| 55 | + <fieldset class="form-group col-md-12"> |
| 56 | + <label asp-for="Url">@Model.PartFieldDefinition.DisplayName()</label> |
| 57 | + </fieldset> |
| 58 | + <fieldset class="form-group col-md-6" asp-validation-class-for="Url"> |
| 59 | + <input asp-for="Url" class="form-control content-preview-text" placeholder="@settings.UrlPlaceholder" required="@isRequired" /> |
| 60 | + </fieldset> |
| 61 | + <fieldset class="form-group col-md-6" asp-validation-class-for="Text"> |
| 62 | + <label asp-for="Text" @if (settings.LinkTextMode == LinkTextMode.Required) { <text> class="required" </text> }>@T["Link text"]</label> |
| 63 | + <input asp-for="Text" type="text" class="form-control content-preview-text" placeholder="@settings.TextPlaceholder" required="@isTextRequired" /> |
| 64 | + </fieldset> |
| 65 | +</div> |
| 66 | + |
| 67 | +``` |
| 68 | + |
| 69 | +Generated POT file: |
| 70 | +``` |
| 71 | +#: OrchardCore.ContentFields\Drivers\LinkFieldDriver.cs:59 |
| 72 | +#. updater.ModelState.AddModelError(Prefix, T["The url is required for {0}.", context.PartFieldDefinition.DisplayName()]); |
| 73 | +msgctxt "OrchardCore.ContentFields.Fields.LinkFieldDisplayDriver" |
| 74 | +msgid "The url is required for {0}." |
| 75 | +msgstr "" |
| 76 | +
|
| 77 | +#: OrchardCore.ContentFields\Views\LinkField.Edit.cshtml:32 |
| 78 | +#. <label asp-for="Text" @if (settings.LinkTextMode == LinkTextMode.Required) { <text> class="required" </text> }>@T["Link text"]</label> |
| 79 | +msgctxt "OrchardCore.ContentFields.Views.LinkField.Edit" |
| 80 | +msgid "Link text" |
| 81 | +msgstr "" |
| 82 | +``` |
0 commit comments