From 583383aee1e89900c5b590dbd0e975ce5cadae3f Mon Sep 17 00:00:00 2001 From: Hisham Bin Ateya Date: Fri, 27 May 2022 15:33:48 +0300 Subject: [PATCH 1/5] Pager should inherits from LocalizableComponent --- .../Modules/Controls/ActionDialog.razor | 6 +- .../Modules/Controls/ActionLink.razor | 2 +- Oqtane.Client/Modules/Controls/Label.razor | 4 +- .../Modules/Controls/LocalizableComponent.cs | 53 +++++++- Oqtane.Client/Modules/Controls/Pager.razor | 10 +- Oqtane.Client/Modules/Controls/Section.razor | 4 +- Oqtane.Client/Modules/Controls/TabPanel.razor | 4 +- .../Resources/Modules/Controls/Pager.resx | 123 ++++++++++++++++++ 8 files changed, 185 insertions(+), 21 deletions(-) create mode 100644 Oqtane.Client/Resources/Modules/Controls/Pager.resx diff --git a/Oqtane.Client/Modules/Controls/ActionDialog.razor b/Oqtane.Client/Modules/Controls/ActionDialog.razor index 4e21b91a..e902c3ba 100644 --- a/Oqtane.Client/Modules/Controls/ActionDialog.razor +++ b/Oqtane.Client/Modules/Controls/ActionDialog.razor @@ -105,9 +105,9 @@ _iconSpan = $" "; } - Text = Localize(nameof(Text), Text); - Header = Localize(nameof(Header), Header); - Message = Localize(nameof(Message), Message); + Text = LocalizeResource(nameof(Text), Text); + Header = LocalizeResource(nameof(Header), Header); + Message = LocalizeResource(nameof(Message), Message); _permissions = (string.IsNullOrEmpty(Permissions)) ? ModuleState.Permissions : Permissions; _authorized = IsAuthorized(); diff --git a/Oqtane.Client/Modules/Controls/ActionLink.razor b/Oqtane.Client/Modules/Controls/ActionLink.razor index 0ba0dfbe..efad4f65 100644 --- a/Oqtane.Client/Modules/Controls/ActionLink.razor +++ b/Oqtane.Client/Modules/Controls/ActionLink.razor @@ -116,7 +116,7 @@ } _permissions = (string.IsNullOrEmpty(Permissions)) ? ModuleState.Permissions : Permissions; - _text = Localize(nameof(Text), _text); + _text = LocalizeResource(nameof(Text), _text); _url = (ModuleId == -1) ? EditUrl(Action, _parameters) : EditUrl(ModuleId, Action, _parameters); _authorized = IsAuthorized(); } diff --git a/Oqtane.Client/Modules/Controls/Label.razor b/Oqtane.Client/Modules/Controls/Label.razor index a1f8bf3f..b63ce1c0 100644 --- a/Oqtane.Client/Modules/Controls/Label.razor +++ b/Oqtane.Client/Modules/Controls/Label.razor @@ -35,7 +35,7 @@ else if (!string.IsNullOrEmpty(HelpText)) { - _helptext = Localize(nameof(HelpText), HelpText); + _helptext = LocalizeResource(nameof(HelpText), HelpText); _labelclass = "form-label"; var spanclass = (!string.IsNullOrEmpty(Class)) ? " " + Class : ""; @@ -47,7 +47,7 @@ else _labelclass = "form-label" + labelclass; } - var text = Localize("Text", String.Empty); + var text = LocalizeResource("Text", String.Empty); if (!string.IsNullOrEmpty(text)) { ChildContent =@@text; diff --git a/Oqtane.Client/Modules/Controls/LocalizableComponent.cs b/Oqtane.Client/Modules/Controls/LocalizableComponent.cs index 711504c6..be60eb76 100644 --- a/Oqtane.Client/Modules/Controls/LocalizableComponent.cs +++ b/Oqtane.Client/Modules/Controls/LocalizableComponent.cs @@ -9,6 +9,7 @@ namespace Oqtane.Modules.Controls public class LocalizableComponent : ModuleControlBase { private IStringLocalizer _localizer; + private IStringLocalizer _resourceLocalizer; [Parameter] public string ResourceKey { get; set; } @@ -18,9 +19,27 @@ namespace Oqtane.Modules.Controls protected bool IsLocalizable { get; private set; } - protected string Localize(string name) => _localizer?[name] ?? name; + protected string Localize(string name) + { + if (_localizer == null) + { + _localizer = CreateLocalizer(); + } - protected string Localize(string propertyName, string propertyValue) + return _localizer[name]; + } + + protected string Localize(string name, params object[] arguments) + { + if (_localizer == null) + { + _localizer = CreateLocalizer(); + } + + return _localizer[name, arguments]; + } + + protected string LocalizeResource(string propertyName, string propertyValue) { if (!IsLocalizable) { @@ -28,7 +47,7 @@ namespace Oqtane.Modules.Controls } var key = $"{ResourceKey}.{propertyName}"; - var value = Localize(key); + var value = _resourceLocalizer?[key] ?? key; if (value == key) { @@ -53,12 +72,12 @@ namespace Oqtane.Modules.Controls { IsLocalizable = false; - if (string.IsNullOrEmpty(ResourceType)) + if (String.IsNullOrEmpty(ResourceType)) { ResourceType = ModuleState?.ModuleType; } - if (!String.IsNullOrEmpty(ResourceKey) && !string.IsNullOrEmpty(ResourceType)) + if (!String.IsNullOrEmpty(ResourceKey) && !String.IsNullOrEmpty(ResourceType)) { var moduleType = Type.GetType(ResourceType); if (moduleType != null) @@ -66,12 +85,34 @@ namespace Oqtane.Modules.Controls using (var scope = ServiceActivator.GetScope()) { var localizerFactory = scope.ServiceProvider.GetService(); - _localizer = localizerFactory.Create(moduleType); + _resourceLocalizer = localizerFactory.Create(moduleType); IsLocalizable = true; } } } } + + private IStringLocalizer CreateLocalizer() + { + using (var scope = ServiceActivator.GetScope()) + { + var controlType = GetType(); + var controlTypeName = controlType.Name; + + // Remove `1 if the control is generic type + if (controlTypeName.EndsWith("`1")) + { + controlTypeName = controlTypeName.TrimEnd('`', '1'); + } + + var baseName = controlType.FullName[0..controlType.FullName.IndexOf(controlTypeName)].Substring("Oqtane.".Length); + var localizerFactory = scope.ServiceProvider.GetService(); + + _localizer = localizerFactory.Create(baseName + controlTypeName, controlType.Assembly.GetName().Name); + } + + return _localizer; + } } } diff --git a/Oqtane.Client/Modules/Controls/Pager.razor b/Oqtane.Client/Modules/Controls/Pager.razor index 583ab65f..5ae4cc97 100644 --- a/Oqtane.Client/Modules/Controls/Pager.razor +++ b/Oqtane.Client/Modules/Controls/Pager.razor @@ -1,6 +1,6 @@ @namespace Oqtane.Modules.Controls -@inherits ModuleControlBase -@inject IStringLocalizer Localizer +@inherits LocalizableComponent + @typeparam TableItem @if (ItemList != null) @@ -49,7 +49,7 @@ UpdateList(_pages))>
  • - @Localizer["PageOfPages", @_page, @_pages] + @Localize("PageOfPages", _page, _pages)
  • } @@ -157,7 +157,7 @@ UpdateList(_pages))>
  • - @Localizer["PageOfPages", @_page, @_pages] + @Localize("PageOfPages", _page, _pages)
  • } @@ -208,7 +208,7 @@ [Parameter] public string RowClass { get; set; } // class for row element - ie. for Table or
    for Grid - [Parameter] + [Parameter] public string ColumnClass { get; set; } // class for column element - only applicable to Grid format [Parameter] diff --git a/Oqtane.Client/Modules/Controls/Section.razor b/Oqtane.Client/Modules/Controls/Section.razor index 3620d893..e0fa42ef 100644 --- a/Oqtane.Client/Modules/Controls/Section.razor +++ b/Oqtane.Client/Modules/Controls/Section.razor @@ -49,7 +49,7 @@ base.OnParametersSet(); _heading = !string.IsNullOrEmpty(Heading) - ? Localize(nameof(Heading), Heading) - : Localize(nameof(Name), Name); + ? LocalizeResource(nameof(Heading), Heading) + : LocalizeResource(nameof(Name), Name); } } diff --git a/Oqtane.Client/Modules/Controls/TabPanel.razor b/Oqtane.Client/Modules/Controls/TabPanel.razor index de41b392..c38b9fc7 100644 --- a/Oqtane.Client/Modules/Controls/TabPanel.razor +++ b/Oqtane.Client/Modules/Controls/TabPanel.razor @@ -38,11 +38,11 @@ else if (string.IsNullOrEmpty(Heading)) { - Heading = Localize(nameof(Name), Name); + Heading = LocalizeResource(nameof(Name), Name); } else { - Heading = Localize(nameof(Heading), Heading); + Heading = LocalizeResource(nameof(Heading), Heading); } } diff --git a/Oqtane.Client/Resources/Modules/Controls/Pager.resx b/Oqtane.Client/Resources/Modules/Controls/Pager.resx new file mode 100644 index 00000000..710d041d --- /dev/null +++ b/Oqtane.Client/Resources/Modules/Controls/Pager.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Page {0} of {1} + + \ No newline at end of file From aa98508e576c98f004d2c7d295baea34da9a635b Mon Sep 17 00:00:00 2001 From: Hisham Bin Ateya Date: Fri, 27 May 2022 15:37:13 +0300 Subject: [PATCH 2/5] Remove the entry from SharedResources --- Oqtane.Client/Resources/SharedResources.resx | 3 --- 1 file changed, 3 deletions(-) diff --git a/Oqtane.Client/Resources/SharedResources.resx b/Oqtane.Client/Resources/SharedResources.resx index 4d41d1a6..774b533a 100644 --- a/Oqtane.Client/Resources/SharedResources.resx +++ b/Oqtane.Client/Resources/SharedResources.resx @@ -327,7 +327,4 @@ Show - - Page {0} of {1} - \ No newline at end of file From a83ed40ec4b8d3176959f9e781272f0654623b2b Mon Sep 17 00:00:00 2001 From: Hisham Bin Ateya Date: Tue, 31 May 2022 10:40:42 +0300 Subject: [PATCH 3/5] Avoid breaking changes --- .../Modules/Controls/ActionDialog.razor | 6 +- .../Modules/Controls/ActionLink.razor | 2 +- Oqtane.Client/Modules/Controls/Label.razor | 4 +- .../Modules/Controls/LocalizableComponent.cs | 66 ++++++++----------- Oqtane.Client/Modules/Controls/Pager.razor | 4 +- Oqtane.Client/Modules/Controls/Section.razor | 4 +- Oqtane.Client/Modules/Controls/TabPanel.razor | 4 +- 7 files changed, 39 insertions(+), 51 deletions(-) diff --git a/Oqtane.Client/Modules/Controls/ActionDialog.razor b/Oqtane.Client/Modules/Controls/ActionDialog.razor index e902c3ba..4e21b91a 100644 --- a/Oqtane.Client/Modules/Controls/ActionDialog.razor +++ b/Oqtane.Client/Modules/Controls/ActionDialog.razor @@ -105,9 +105,9 @@ _iconSpan = $" "; } - Text = LocalizeResource(nameof(Text), Text); - Header = LocalizeResource(nameof(Header), Header); - Message = LocalizeResource(nameof(Message), Message); + Text = Localize(nameof(Text), Text); + Header = Localize(nameof(Header), Header); + Message = Localize(nameof(Message), Message); _permissions = (string.IsNullOrEmpty(Permissions)) ? ModuleState.Permissions : Permissions; _authorized = IsAuthorized(); diff --git a/Oqtane.Client/Modules/Controls/ActionLink.razor b/Oqtane.Client/Modules/Controls/ActionLink.razor index efad4f65..0ba0dfbe 100644 --- a/Oqtane.Client/Modules/Controls/ActionLink.razor +++ b/Oqtane.Client/Modules/Controls/ActionLink.razor @@ -116,7 +116,7 @@ } _permissions = (string.IsNullOrEmpty(Permissions)) ? ModuleState.Permissions : Permissions; - _text = LocalizeResource(nameof(Text), _text); + _text = Localize(nameof(Text), _text); _url = (ModuleId == -1) ? EditUrl(Action, _parameters) : EditUrl(ModuleId, Action, _parameters); _authorized = IsAuthorized(); } diff --git a/Oqtane.Client/Modules/Controls/Label.razor b/Oqtane.Client/Modules/Controls/Label.razor index b63ce1c0..a1f8bf3f 100644 --- a/Oqtane.Client/Modules/Controls/Label.razor +++ b/Oqtane.Client/Modules/Controls/Label.razor @@ -35,7 +35,7 @@ else if (!string.IsNullOrEmpty(HelpText)) { - _helptext = LocalizeResource(nameof(HelpText), HelpText); + _helptext = Localize(nameof(HelpText), HelpText); _labelclass = "form-label"; var spanclass = (!string.IsNullOrEmpty(Class)) ? " " + Class : ""; @@ -47,7 +47,7 @@ else _labelclass = "form-label" + labelclass; } - var text = LocalizeResource("Text", String.Empty); + var text = Localize("Text", String.Empty); if (!string.IsNullOrEmpty(text)) { ChildContent =@@text; diff --git a/Oqtane.Client/Modules/Controls/LocalizableComponent.cs b/Oqtane.Client/Modules/Controls/LocalizableComponent.cs index be60eb76..e1ad4545 100644 --- a/Oqtane.Client/Modules/Controls/LocalizableComponent.cs +++ b/Oqtane.Client/Modules/Controls/LocalizableComponent.cs @@ -19,27 +19,37 @@ namespace Oqtane.Modules.Controls protected bool IsLocalizable { get; private set; } - protected string Localize(string name) + protected IStringLocalizer T { - if (_localizer == null) + get { - _localizer = CreateLocalizer(); - } + if (_resourceLocalizer == null) + { + using (var scope = ServiceActivator.GetScope()) + { + var controlType = GetType(); + var controlTypeName = controlType.Name; - return _localizer[name]; + // Remove `1 if the control is generic type + if (controlTypeName.EndsWith("`1")) + { + controlTypeName = controlTypeName.TrimEnd('`', '1'); + } + + var baseName = controlType.FullName[0..controlType.FullName.IndexOf(controlTypeName)].Substring("Oqtane.".Length); + var localizerFactory = scope.ServiceProvider.GetService(); + + _resourceLocalizer = localizerFactory.Create(baseName + controlTypeName, controlType.Assembly.GetName().Name); + } + } + + return _resourceLocalizer; + } } - protected string Localize(string name, params object[] arguments) - { - if (_localizer == null) - { - _localizer = CreateLocalizer(); - } + protected string Localize(string name) => _localizer?[name] ?? name; - return _localizer[name, arguments]; - } - - protected string LocalizeResource(string propertyName, string propertyValue) + protected string Localize(string propertyName, string propertyValue) { if (!IsLocalizable) { @@ -47,7 +57,7 @@ namespace Oqtane.Modules.Controls } var key = $"{ResourceKey}.{propertyName}"; - var value = _resourceLocalizer?[key] ?? key; + var value = Localize(key); if (value == key) { @@ -85,34 +95,12 @@ namespace Oqtane.Modules.Controls using (var scope = ServiceActivator.GetScope()) { var localizerFactory = scope.ServiceProvider.GetService(); - _resourceLocalizer = localizerFactory.Create(moduleType); + _localizer = localizerFactory.Create(moduleType); IsLocalizable = true; } } } } - - private IStringLocalizer CreateLocalizer() - { - using (var scope = ServiceActivator.GetScope()) - { - var controlType = GetType(); - var controlTypeName = controlType.Name; - - // Remove `1 if the control is generic type - if (controlTypeName.EndsWith("`1")) - { - controlTypeName = controlTypeName.TrimEnd('`', '1'); - } - - var baseName = controlType.FullName[0..controlType.FullName.IndexOf(controlTypeName)].Substring("Oqtane.".Length); - var localizerFactory = scope.ServiceProvider.GetService(); - - _localizer = localizerFactory.Create(baseName + controlTypeName, controlType.Assembly.GetName().Name); - } - - return _localizer; - } } } diff --git a/Oqtane.Client/Modules/Controls/Pager.razor b/Oqtane.Client/Modules/Controls/Pager.razor index 5ae4cc97..25485ebd 100644 --- a/Oqtane.Client/Modules/Controls/Pager.razor +++ b/Oqtane.Client/Modules/Controls/Pager.razor @@ -49,7 +49,7 @@ UpdateList(_pages))>
  • - @Localize("PageOfPages", _page, _pages) + @T["PageOfPages", _page, _pages]
  • } @@ -157,7 +157,7 @@ UpdateList(_pages))>
  • - @Localize("PageOfPages", _page, _pages) + @T["PageOfPages", _page, _pages]
  • } diff --git a/Oqtane.Client/Modules/Controls/Section.razor b/Oqtane.Client/Modules/Controls/Section.razor index e0fa42ef..3620d893 100644 --- a/Oqtane.Client/Modules/Controls/Section.razor +++ b/Oqtane.Client/Modules/Controls/Section.razor @@ -49,7 +49,7 @@ base.OnParametersSet(); _heading = !string.IsNullOrEmpty(Heading) - ? LocalizeResource(nameof(Heading), Heading) - : LocalizeResource(nameof(Name), Name); + ? Localize(nameof(Heading), Heading) + : Localize(nameof(Name), Name); } } diff --git a/Oqtane.Client/Modules/Controls/TabPanel.razor b/Oqtane.Client/Modules/Controls/TabPanel.razor index c38b9fc7..de41b392 100644 --- a/Oqtane.Client/Modules/Controls/TabPanel.razor +++ b/Oqtane.Client/Modules/Controls/TabPanel.razor @@ -38,11 +38,11 @@ else if (string.IsNullOrEmpty(Heading)) { - Heading = LocalizeResource(nameof(Name), Name); + Heading = Localize(nameof(Name), Name); } else { - Heading = LocalizeResource(nameof(Heading), Heading); + Heading = Localize(nameof(Heading), Heading); } } From 1abae5597679d96d278ce624260d77512b2ee06e Mon Sep 17 00:00:00 2001 From: Hisham Bin Ateya Date: Tue, 31 May 2022 11:59:17 +0300 Subject: [PATCH 4/5] Remove magic string --- .../Modules/Controls/LocalizableComponent.cs | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/Oqtane.Client/Modules/Controls/LocalizableComponent.cs b/Oqtane.Client/Modules/Controls/LocalizableComponent.cs index e1ad4545..46e5d03f 100644 --- a/Oqtane.Client/Modules/Controls/LocalizableComponent.cs +++ b/Oqtane.Client/Modules/Controls/LocalizableComponent.cs @@ -1,4 +1,5 @@ using System; +using System.Text; using Microsoft.AspNetCore.Components; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Localization; @@ -29,17 +30,20 @@ namespace Oqtane.Modules.Controls { var controlType = GetType(); var controlTypeName = controlType.Name; + var assemblyName = controlType.Assembly.GetName().Name; - // Remove `1 if the control is generic type + // Trim "`1" suffix (for generic type) to make it consistent like normal control types if (controlTypeName.EndsWith("`1")) { controlTypeName = controlTypeName.TrimEnd('`', '1'); } - var baseName = controlType.FullName[0..controlType.FullName.IndexOf(controlTypeName)].Substring("Oqtane.".Length); + controlTypeName = controlType.FullName[..(controlType.FullName.IndexOf(controlTypeName) + controlTypeName.Length)]; + + var baseName = GetBaseName(controlTypeName, assemblyName); var localizerFactory = scope.ServiceProvider.GetService(); - _resourceLocalizer = localizerFactory.Create(baseName + controlTypeName, controlType.Assembly.GetName().Name); + _resourceLocalizer = localizerFactory.Create(baseName, assemblyName); } } @@ -102,5 +106,26 @@ namespace Oqtane.Modules.Controls } } } + + private static string GetBaseName(string typeName, string assemblyName) + { + var baseName = new StringBuilder(typeName); + + var tokens = assemblyName.Split("."); + + foreach (var token in tokens) + { + var index = baseName.ToString().IndexOf(token); + + if (index == -1) + { + continue; + } + + baseName.Remove(index, token.Length + 1); + } + + return baseName.ToString(); + } } } From b22f8a0b02eaaeefb8a4ced837eace89ffa67357 Mon Sep 17 00:00:00 2001 From: Hisham Bin Ateya Date: Wed, 8 Jun 2022 00:12:10 +0300 Subject: [PATCH 5/5] Remove generic type suffix properly --- Oqtane.Client/Modules/Controls/LocalizableComponent.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Oqtane.Client/Modules/Controls/LocalizableComponent.cs b/Oqtane.Client/Modules/Controls/LocalizableComponent.cs index 46e5d03f..44f1a403 100644 --- a/Oqtane.Client/Modules/Controls/LocalizableComponent.cs +++ b/Oqtane.Client/Modules/Controls/LocalizableComponent.cs @@ -32,10 +32,10 @@ namespace Oqtane.Modules.Controls var controlTypeName = controlType.Name; var assemblyName = controlType.Assembly.GetName().Name; - // Trim "`1" suffix (for generic type) to make it consistent like normal control types - if (controlTypeName.EndsWith("`1")) + if (controlType.IsGenericType) { - controlTypeName = controlTypeName.TrimEnd('`', '1'); + // Trim generic type suffix + controlTypeName = controlTypeName[..controlTypeName.IndexOf('`')]; } controlTypeName = controlType.FullName[..(controlType.FullName.IndexOf(controlTypeName) + controlTypeName.Length)];