From 7ac2bfbcea6321870be84bf584937b93ca95f9a8 Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Wed, 21 Sep 2011 22:03:28 -0700 Subject: [PATCH] #18075: Fixing localization resolution in alternates Work Item: 18075 --HG-- branch : 1.x --- .../Descriptors/DefaultShapeTableManager.cs | 11 +++++- .../Descriptors/ShapeDescriptor.cs | 2 + .../Implementation/DefaultDisplayManager.cs | 3 ++ .../DisplayManagement/Shapes/ShapeMetadata.cs | 3 ++ .../Mvc/ViewEngines/Razor/WebViewPage.cs | 39 +++++++++++++++++-- 5 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src/Orchard/DisplayManagement/Descriptors/DefaultShapeTableManager.cs b/src/Orchard/DisplayManagement/Descriptors/DefaultShapeTableManager.cs index 4d2b9b48c..6cf6bad9d 100644 --- a/src/Orchard/DisplayManagement/Descriptors/DefaultShapeTableManager.cs +++ b/src/Orchard/DisplayManagement/Descriptors/DefaultShapeTableManager.cs @@ -47,7 +47,8 @@ namespace Orchard.DisplayManagement.Descriptors { var alterations = alterationSets .SelectMany(shapeAlterations => shapeAlterations) .Where(alteration => IsModuleOrRequestedTheme(alteration, themeName)) - .OrderByDependenciesAndPriorities(AlterationHasDependency, GetPriority); + .OrderByDependenciesAndPriorities(AlterationHasDependency, GetPriority) + .ToList(); var descriptors = alterations.GroupBy(alteration => alteration.ShapeType, StringComparer.OrdinalIgnoreCase) .Select(group => group.Aggregate( @@ -57,6 +58,14 @@ namespace Orchard.DisplayManagement.Descriptors { return descriptor; })).ToList(); + foreach(var descriptor in descriptors) { + foreach(var alteration in alterations.Where(a => a.ShapeType == descriptor.ShapeType).ToList()) { + var local = new ShapeDescriptor { ShapeType = descriptor.ShapeType }; + alteration.Alter(local); + descriptor.BindingSources.Add(local.BindingSource); + } + } + var result = new ShapeTable { Descriptors = descriptors.ToDictionary(sd => sd.ShapeType, StringComparer.OrdinalIgnoreCase), Bindings = descriptors.SelectMany(sd => sd.Bindings).ToDictionary(kv => kv.Key, kv => kv.Value, StringComparer.OrdinalIgnoreCase), diff --git a/src/Orchard/DisplayManagement/Descriptors/ShapeDescriptor.cs b/src/Orchard/DisplayManagement/Descriptors/ShapeDescriptor.cs index 1c0f4c3db..ccb848457 100644 --- a/src/Orchard/DisplayManagement/Descriptors/ShapeDescriptor.cs +++ b/src/Orchard/DisplayManagement/Descriptors/ShapeDescriptor.cs @@ -12,6 +12,7 @@ namespace Orchard.DisplayManagement.Descriptors { Displaying = Enumerable.Empty>(); Displayed = Enumerable.Empty>(); Wrappers = new List(); + BindingSources = new List(); Bindings = new Dictionary(StringComparer.OrdinalIgnoreCase); Placement = ctx => new PlacementInfo {Location = DefaultPlacement}; } @@ -47,6 +48,7 @@ namespace Orchard.DisplayManagement.Descriptors { public string DefaultPlacement { get; set; } public IList Wrappers { get; set; } + public IList BindingSources { get; set; } } public class ShapeBinding { diff --git a/src/Orchard/DisplayManagement/Implementation/DefaultDisplayManager.cs b/src/Orchard/DisplayManagement/Implementation/DefaultDisplayManager.cs index 5d00298dc..cec8f4657 100644 --- a/src/Orchard/DisplayManagement/Implementation/DefaultDisplayManager.cs +++ b/src/Orchard/DisplayManagement/Implementation/DefaultDisplayManager.cs @@ -68,6 +68,9 @@ namespace Orchard.DisplayManagement.Implementation { shapeBinding.ShapeDescriptor.Displaying.Invoke(action => action(displayingContext), Logger); } + // copy all binding sources (all templates for this shape) in order to use them as Localization scopes + shapeMetadata.BindingSources = shapeBinding.ShapeDescriptor.BindingSources; + // invoking ShapeMetadata displaying events shapeMetadata.Displaying.Invoke(action => action(displayingContext), Logger); diff --git a/src/Orchard/DisplayManagement/Shapes/ShapeMetadata.cs b/src/Orchard/DisplayManagement/Shapes/ShapeMetadata.cs index f514d0411..60cbcecb8 100644 --- a/src/Orchard/DisplayManagement/Shapes/ShapeMetadata.cs +++ b/src/Orchard/DisplayManagement/Shapes/ShapeMetadata.cs @@ -9,6 +9,7 @@ namespace Orchard.DisplayManagement.Shapes { public ShapeMetadata() { Wrappers = new List(); Alternates = new List(); + BindingSources = new List(); Displaying = Enumerable.Empty>(); Displayed = Enumerable.Empty>(); } @@ -27,6 +28,8 @@ namespace Orchard.DisplayManagement.Shapes { public IEnumerable> Displaying { get; private set; } public IEnumerable> Displayed { get; private set; } + public IList BindingSources { get; set; } + public void OnDisplaying(Action action) { var existing = Displaying ?? Enumerable.Empty>(); Displaying = existing.Concat(new[] { action }); diff --git a/src/Orchard/Mvc/ViewEngines/Razor/WebViewPage.cs b/src/Orchard/Mvc/ViewEngines/Razor/WebViewPage.cs index 90e937255..3f2683888 100644 --- a/src/Orchard/Mvc/ViewEngines/Razor/WebViewPage.cs +++ b/src/Orchard/Mvc/ViewEngines/Razor/WebViewPage.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.WebPages; @@ -22,7 +23,40 @@ namespace Orchard.Mvc.ViewEngines.Razor { private object _layout; private WorkContext _workContext; - public Localizer T { get { return _localizer; } } + public Localizer T { + get { + // first time used, create it + if(_localizer == NullLocalizer.Instance) { + + // if the Model is a shape, get localization scopes from binding sources + // e.g., Logon.cshtml in a theme, overriging Users/Logon.cshtml, needs T to + // fallback to the one in Users + var shape = Model as IShape; + if(shape != null && shape.Metadata.BindingSources.Count > 1) { + var localizers = shape.Metadata.BindingSources.Reverse().Select(scope => LocalizationUtilities.Resolve(ViewContext, scope)).ToList(); + _localizer = (text, args) => { + foreach(var localizer in localizers) { + var hint = localizer(text, args); + // if not localized using this scope, use next scope + if(hint.Text != text) { + return hint; + } + } + + // no localization found, return default value + return new LocalizedString(text, VirtualPath, text, args); + }; + } + else { + // not a shape, use the VirtualPath as scope + _localizer = LocalizationUtilities.Resolve(ViewContext, VirtualPath); + } + } + + return _localizer; + } + } + public dynamic Display { get { return _display; } } // review: (heskew) is it going to be a problem? public new dynamic Layout { get { return _layout; } } @@ -82,8 +116,7 @@ namespace Orchard.Mvc.ViewEngines.Razor { _workContext = ViewContext.GetWorkContext(); _workContext.Resolve().InjectUnsetProperties(this); - - _localizer = LocalizationUtilities.Resolve(ViewContext, VirtualPath); + _display = DisplayHelperFactory.CreateHelper(ViewContext, this); _layout = _workContext.Layout; }