diff --git a/src/Umbraco.Abstractions/Services/IPropertyValidationService.cs b/src/Umbraco.Abstractions/Services/IPropertyValidationService.cs index 399bdd64d2..8eb7106974 100644 --- a/src/Umbraco.Abstractions/Services/IPropertyValidationService.cs +++ b/src/Umbraco.Abstractions/Services/IPropertyValidationService.cs @@ -4,7 +4,14 @@ namespace Umbraco.Core.Services { public interface IPropertyValidationService { + /// + /// Validates the content item's properties pass validation rules + /// bool IsPropertyDataValid(IContent content, out IProperty[] invalidProperties, CultureImpact impact); + + /// + /// Gets a value indicating whether the property has valid values. + /// bool IsPropertyValid(IProperty property, string culture = "*", string segment = "*"); } -} \ No newline at end of file +} diff --git a/src/Umbraco.Core/Services/LocalizedTextServiceExtensions.cs b/src/Umbraco.Abstractions/Services/LocalizedTextServiceExtensions.cs similarity index 71% rename from src/Umbraco.Core/Services/LocalizedTextServiceExtensions.cs rename to src/Umbraco.Abstractions/Services/LocalizedTextServiceExtensions.cs index ce5b3ef8c4..92854c5a2b 100644 --- a/src/Umbraco.Core/Services/LocalizedTextServiceExtensions.cs +++ b/src/Umbraco.Abstractions/Services/LocalizedTextServiceExtensions.cs @@ -69,24 +69,7 @@ namespace Umbraco.Core.Services .ToDictionary(keyvals => keyvals.index, keyvals => keyvals.value); } - private static ICultureDictionary _cultureDictionary; - - /// - /// TODO: We need to refactor how we work with ICultureDictionary - this is supposed to be the 'fast' way to - /// do readonly access to the Dictionary without using the ILocalizationService. See TODO Notes in `DefaultCultureDictionary` - /// Also NOTE that the ICultureDictionary is based on the ILocalizationService not the ILocalizedTextService (which is used - /// only for the localization files - not the dictionary) - /// - /// - /// - /// - internal static string UmbracoDictionaryTranslate(this ILocalizedTextService manager, string text) - { - var cultureDictionary = CultureDictionary; - return manager.UmbracoDictionaryTranslate(text, cultureDictionary); - } - - private static string UmbracoDictionaryTranslate(this ILocalizedTextService manager, string text, ICultureDictionary cultureDictionary) + public static string UmbracoDictionaryTranslate(this ILocalizedTextService manager, ICultureDictionary cultureDictionary, string text) { if (text == null) return null; @@ -105,7 +88,5 @@ namespace Umbraco.Core.Services return value.StartsWith("[") ? text : value; } - private static ICultureDictionary CultureDictionary - => _cultureDictionary ?? (_cultureDictionary = Current.CultureDictionaryFactory.CreateDictionary()); } } diff --git a/src/Umbraco.Core/Services/PublicAccessServiceExtensions.cs b/src/Umbraco.Abstractions/Services/PublicAccessServiceExtensions.cs similarity index 92% rename from src/Umbraco.Core/Services/PublicAccessServiceExtensions.cs rename to src/Umbraco.Abstractions/Services/PublicAccessServiceExtensions.cs index b0dc979ebf..cb2a5f4956 100644 --- a/src/Umbraco.Core/Services/PublicAccessServiceExtensions.cs +++ b/src/Umbraco.Abstractions/Services/PublicAccessServiceExtensions.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Web.Security; using Umbraco.Core.Models; namespace Umbraco.Core.Services @@ -53,11 +52,6 @@ namespace Umbraco.Core.Services return HasAccess(entry, username, currentMemberRoles); } - public static bool HasAccess(this IPublicAccessService publicAccessService, string path, MembershipUser member, RoleProvider roleProvider) - { - return publicAccessService.HasAccess(path, member.UserName, roleProvider.GetRolesForUser); - } - /// /// Checks if the member with the specified username has access to the path which is also based on the passed in roles for the member /// diff --git a/src/Umbraco.Core/Services/UserServiceExtensions.cs b/src/Umbraco.Abstractions/Services/UserServiceExtensions.cs similarity index 68% rename from src/Umbraco.Core/Services/UserServiceExtensions.cs rename to src/Umbraco.Abstractions/Services/UserServiceExtensions.cs index 31c446352e..480222b351 100644 --- a/src/Umbraco.Core/Services/UserServiceExtensions.cs +++ b/src/Umbraco.Abstractions/Services/UserServiceExtensions.cs @@ -1,6 +1,5 @@ using System; using System.Linq; -using System.Web.Security; using Umbraco.Core.Models.Membership; namespace Umbraco.Core.Services @@ -69,40 +68,5 @@ namespace Umbraco.Core.Services userService.ReplaceUserGroupPermissions(groupId, new char[] { }); } - /// - /// Maps a custom provider's information to an umbraco user account - /// - /// - /// - /// - /// To maintain compatibility we have to check the login name if the provider key lookup fails but otherwise - /// we'll store the provider user key in the login column. - /// - internal static IUser CreateUserMappingForCustomProvider(this IUserService userService, MembershipUser member) - { - if (member == null) throw new ArgumentNullException("member"); - - - var valToLookup = member.ProviderUserKey == null ? member.UserName : member.ProviderUserKey.ToString(); - var found = userService.GetByUsername(valToLookup); - if (found == null && member.ProviderUserKey != null) - { - //try by username - found = userService.GetByUsername(member.UserName); - } - - if (found == null) - { - var user = new User( - member.UserName, - member.Email ?? Guid.NewGuid().ToString("N") + "@example.com", //email cannot be empty - member.ProviderUserKey == null ? member.UserName : member.ProviderUserKey.ToString(), - Guid.NewGuid().ToString("N")); //pass cannot be empty - userService.Save(user); - return user; - } - - return found; - } } } diff --git a/src/Umbraco.Core/Composing/CompositionExtensions/Services.cs b/src/Umbraco.Core/Composing/CompositionExtensions/Services.cs index a207e2197a..ba8442f8d7 100644 --- a/src/Umbraco.Core/Composing/CompositionExtensions/Services.cs +++ b/src/Umbraco.Core/Composing/CompositionExtensions/Services.cs @@ -27,6 +27,7 @@ namespace Umbraco.Core.Composing.CompositionExtensions composition.RegisterUnique(); // register the services + composition.RegisterUnique(); composition.RegisterUnique(); composition.RegisterUnique(); composition.RegisterUnique(); diff --git a/src/Umbraco.Core/CompositionExtensions.cs b/src/Umbraco.Core/CompositionExtensions.cs index 2d8254a3c0..1fd1de0c08 100644 --- a/src/Umbraco.Core/CompositionExtensions.cs +++ b/src/Umbraco.Core/CompositionExtensions.cs @@ -91,7 +91,7 @@ namespace Umbraco.Core public static void SetCultureDictionaryFactory(this Composition composition) where T : ICultureDictionaryFactory { - composition.RegisterUnique(); + composition.RegisterUnique(); } /// diff --git a/src/Umbraco.Core/Services/Implement/ContentService.cs b/src/Umbraco.Core/Services/Implement/ContentService.cs index f255956971..82678f2889 100644 --- a/src/Umbraco.Core/Services/Implement/ContentService.cs +++ b/src/Umbraco.Core/Services/Implement/ContentService.cs @@ -8,7 +8,6 @@ using Umbraco.Core.Exceptions; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; -using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Scoping; @@ -27,7 +26,7 @@ namespace Umbraco.Core.Services.Implement private readonly IContentTypeRepository _contentTypeRepository; private readonly IDocumentBlueprintRepository _documentBlueprintRepository; private readonly ILanguageRepository _languageRepository; - private readonly IPropertyValidationService _propertyValidationService; + private readonly Lazy _propertyValidationService; private IQuery _queryNotTrashed; #region Constructors @@ -36,7 +35,7 @@ namespace Umbraco.Core.Services.Implement IEventMessagesFactory eventMessagesFactory, IDocumentRepository documentRepository, IEntityRepository entityRepository, IAuditRepository auditRepository, IContentTypeRepository contentTypeRepository, IDocumentBlueprintRepository documentBlueprintRepository, ILanguageRepository languageRepository, - IPropertyValidationService propertyValidationService) + Lazy propertyValidationService) : base(provider, logger, eventMessagesFactory) { _documentRepository = documentRepository; @@ -1404,7 +1403,7 @@ namespace Umbraco.Core.Services.Implement //publish the culture values and validate the property values, if validation fails, log the invalid properties so the develeper has an idea of what has failed IProperty[] invalidProperties = null; var impact = CultureImpact.Explicit(culture, IsDefaultCulture(allLangs, culture)); - var tryPublish = d.PublishCulture(impact) && _propertyValidationService.IsPropertyDataValid(d, out invalidProperties, impact); + var tryPublish = d.PublishCulture(impact) && _propertyValidationService.Value.IsPropertyDataValid(d, out invalidProperties, impact); if (invalidProperties != null && invalidProperties.Length > 0) Logger.Warn("Scheduled publishing will fail for document {DocumentId} and culture {Culture} because of invalid properties {InvalidProperties}", d.Id, culture, string.Join(",", invalidProperties.Select(x => x.Alias))); @@ -1505,12 +1504,12 @@ namespace Umbraco.Core.Services.Implement return culturesToPublish.All(culture => { var impact = CultureImpact.Create(culture, IsDefaultCulture(allLangs, culture), content); - return content.PublishCulture(impact) && _propertyValidationService.IsPropertyDataValid(content, out _, impact); + return content.PublishCulture(impact) && _propertyValidationService.Value.IsPropertyDataValid(content, out _, impact); }); } return content.PublishCulture(CultureImpact.Invariant) - && _propertyValidationService.IsPropertyDataValid(content, out _, CultureImpact.Invariant); + && _propertyValidationService.Value.IsPropertyDataValid(content, out _, CultureImpact.Invariant); } // utility 'ShouldPublish' func used by SaveAndPublishBranch @@ -2603,7 +2602,7 @@ namespace Umbraco.Core.Services.Implement //validate the property values IProperty[] invalidProperties = null; - if (!impactsToPublish.All(x => _propertyValidationService.IsPropertyDataValid(content, out invalidProperties, x))) + if (!impactsToPublish.All(x => _propertyValidationService.Value.IsPropertyDataValid(content, out invalidProperties, x))) return new PublishResult(PublishResultType.FailedPublishContentInvalid, evtMsgs, content) { InvalidProperties = invalidProperties diff --git a/src/Umbraco.Abstractions/Services/PropertyValidationService.cs b/src/Umbraco.Core/Services/Implement/PropertyValidationService.cs similarity index 96% rename from src/Umbraco.Abstractions/Services/PropertyValidationService.cs rename to src/Umbraco.Core/Services/Implement/PropertyValidationService.cs index bd9e3190b7..10cc4bce23 100644 --- a/src/Umbraco.Abstractions/Services/PropertyValidationService.cs +++ b/src/Umbraco.Core/Services/Implement/PropertyValidationService.cs @@ -15,9 +15,7 @@ namespace Umbraco.Core.Services _dataTypeService = dataTypeService; } - /// - /// Validates the content item's properties pass validation rules - /// + /// public bool IsPropertyDataValid(IContent content, out IProperty[] invalidProperties, CultureImpact impact) { // select invalid properties @@ -50,9 +48,7 @@ namespace Umbraco.Core.Services return invalidProperties.Length == 0; } - /// - /// Gets a value indicating whether the property has valid values. - /// + /// public bool IsPropertyValid(IProperty property, string culture = "*", string segment = "*") { //NOTE - the pvalue and vvalues logic in here is borrowed directly from the Property.Values setter so if you are wondering what that's all about, look there. diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 056e1a086b..a52d18b7e3 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -235,7 +235,7 @@ - + @@ -793,7 +793,6 @@ - @@ -801,7 +800,6 @@ - diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs index 9cc80dc891..ac14ba3fbb 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs @@ -152,10 +152,13 @@ namespace Umbraco.Tests.TestHelpers var runtimeState = Mock.Of(); var idkMap = new IdkMap(scopeProvider); + var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty())); + var localizationService = GetLazyService(factory, c => new LocalizationService(scopeProvider, logger, eventMessagesFactory, GetRepo(c), GetRepo(c), GetRepo(c))); var userService = GetLazyService(factory, c => new UserService(scopeProvider, logger, eventMessagesFactory, runtimeState, GetRepo(c), GetRepo(c),globalSettings)); var dataTypeService = GetLazyService(factory, c => new DataTypeService(scopeProvider, logger, eventMessagesFactory, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c))); - var contentService = GetLazyService(factory, c => new ContentService(scopeProvider, logger, eventMessagesFactory, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c))); + var propertyValidationService = new Lazy(() => new PropertyValidationService(propertyEditorCollection, dataTypeService.Value)); + var contentService = GetLazyService(factory, c => new ContentService(scopeProvider, logger, eventMessagesFactory, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), propertyValidationService)); var notificationService = GetLazyService(factory, c => new NotificationService(scopeProvider, userService.Value, contentService.Value, localizationService.Value, logger, ioHelper, GetRepo(c), globalSettings, umbracoSettings.Content)); var serverRegistrationService = GetLazyService(factory, c => new ServerRegistrationService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); var memberGroupService = GetLazyService(factory, c => new MemberGroupService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); @@ -170,8 +173,7 @@ namespace Umbraco.Tests.TestHelpers var macroService = GetLazyService(factory, c => new MacroService(scopeProvider, logger, eventMessagesFactory, GetRepo(c), GetRepo(c))); var packagingService = GetLazyService(factory, c => - { - var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty())); + { var compiledPackageXmlParser = new CompiledPackageXmlParser(new ConflictingPackageData(macroService.Value, fileService.Value), globalSettings); return new PackagingService( auditService.Value, diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 44f19f4540..a321ce90cc 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -42,6 +42,8 @@ using Umbraco.Web.Composing.CompositionExtensions; using Umbraco.Web.Sections; using Current = Umbraco.Core.Composing.Current; using FileSystems = Umbraco.Core.IO.FileSystems; +using Umbraco.Web.Dictionary; +using Umbraco.Core.Dictionary; namespace Umbraco.Tests.Testing { @@ -131,7 +133,7 @@ namespace Umbraco.Tests.Testing // get/merge the attributes marking the method and/or the classes Options = TestOptionAttributeBase.GetTestOptions(); - // FIXME: align to runtimes & components - don't redo everything here + // FIXME: align to runtimes & components - don't redo everything here !!!! Yes this is getting painful var (logger, profiler) = GetLoggers(Options.Logger); var proflogger = new ProfilingLogger(logger, profiler); @@ -233,7 +235,8 @@ namespace Umbraco.Tests.Testing Composition.RegisterUnique(); Composition.RegisterUnique(); Composition.RegisterUnique(); - + Composition.SetCultureDictionaryFactory(); + Composition.Register(f => f.GetInstance().CreateDictionary(), Lifetime.Singleton); // register back office sections in the order we want them rendered Composition.WithCollectionBuilder().Append() .Append() diff --git a/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs b/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs index d77867152a..83d9623f14 100644 --- a/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs +++ b/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs @@ -21,8 +21,6 @@ using Umbraco.Tests.Testing; using Umbraco.Web; using Umbraco.Web.Editors; using Umbraco.Web.Models.ContentEditing; -using Umbraco.Web.PublishedCache; - using Task = System.Threading.Tasks.Task; using Umbraco.Core.Dictionary; using Umbraco.Web.PropertyEditors; @@ -260,6 +258,7 @@ namespace Umbraco.Tests.Web.Controllers var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty())); var controller = new ContentController( + Factory.GetInstance(), propertyEditorCollection, Factory.GetInstance(), umbracoContextAccessor, @@ -293,6 +292,7 @@ namespace Umbraco.Tests.Web.Controllers { var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty())); var controller = new ContentController( + Factory.GetInstance(), propertyEditorCollection, Factory.GetInstance(), umbracoContextAccessor, @@ -334,6 +334,7 @@ namespace Umbraco.Tests.Web.Controllers var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty())); var controller = new ContentController( + Factory.GetInstance(), propertyEditorCollection, Factory.GetInstance(), umbracoContextAccessor, @@ -380,6 +381,7 @@ namespace Umbraco.Tests.Web.Controllers var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty())); var controller = new ContentController( + Factory.GetInstance(), propertyEditorCollection, Factory.GetInstance(), umbracoContextAccessor, @@ -418,6 +420,7 @@ namespace Umbraco.Tests.Web.Controllers var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty())); var controller = new ContentController( + Factory.GetInstance(), propertyEditorCollection, Factory.GetInstance(), umbracoContextAccessor, @@ -462,6 +465,7 @@ namespace Umbraco.Tests.Web.Controllers var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty())); var controller = new ContentController( + Factory.GetInstance(), propertyEditorCollection, Factory.GetInstance(), umbracoContextAccessor, diff --git a/src/Umbraco.Web/Dictionary/UmbracoCultureDictionary.cs b/src/Umbraco.Web/Dictionary/UmbracoCultureDictionary.cs index 92c1412638..f11b2dcfcb 100644 --- a/src/Umbraco.Web/Dictionary/UmbracoCultureDictionary.cs +++ b/src/Umbraco.Web/Dictionary/UmbracoCultureDictionary.cs @@ -24,22 +24,23 @@ namespace Umbraco.Web.Dictionary private readonly IAppCache _requestCache; private readonly CultureInfo _specificCulture; - public DefaultCultureDictionary() - : this(Current.Services.LocalizationService, Current.AppCaches.RequestCache) - { } - + /// + /// Default constructor which will use the current thread's culture + /// + /// + /// public DefaultCultureDictionary(ILocalizationService localizationService, IAppCache requestCache) { _localizationService = localizationService ?? throw new ArgumentNullException(nameof(localizationService)); _requestCache = requestCache ?? throw new ArgumentNullException(nameof(requestCache)); } - public DefaultCultureDictionary(CultureInfo specificCulture) - : this(Current.Services.LocalizationService, Current.AppCaches.RequestCache) - { - _specificCulture = specificCulture ?? throw new ArgumentNullException(nameof(specificCulture)); - } - + /// + /// Constructor for testing to specify a static culture + /// + /// + /// + /// public DefaultCultureDictionary(CultureInfo specificCulture, ILocalizationService localizationService, IAppCache requestCache) { _localizationService = localizationService ?? throw new ArgumentNullException(nameof(localizationService)); diff --git a/src/Umbraco.Web/Dictionary/UmbracoCultureDictionaryFactory.cs b/src/Umbraco.Web/Dictionary/UmbracoCultureDictionaryFactory.cs index c46132f3c0..d66bd99f83 100644 --- a/src/Umbraco.Web/Dictionary/UmbracoCultureDictionaryFactory.cs +++ b/src/Umbraco.Web/Dictionary/UmbracoCultureDictionaryFactory.cs @@ -1,4 +1,7 @@ -namespace Umbraco.Web.Dictionary +using Umbraco.Core.Cache; +using Umbraco.Core.Services; + +namespace Umbraco.Web.Dictionary { /// /// A culture dictionary factory used to create an Umbraco.Core.Dictionary.ICultureDictionary. @@ -8,9 +11,18 @@ /// internal class DefaultCultureDictionaryFactory : Umbraco.Core.Dictionary.ICultureDictionaryFactory { + private readonly ILocalizationService _localizationService; + private readonly AppCaches _appCaches; + + public DefaultCultureDictionaryFactory(ILocalizationService localizationService, AppCaches appCaches) + { + _localizationService = localizationService; + _appCaches = appCaches; + } + public Umbraco.Core.Dictionary.ICultureDictionary CreateDictionary() { - return new DefaultCultureDictionary(); + return new DefaultCultureDictionary(_localizationService, _appCaches.RequestCache); } } } diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index 9c2cc399fa..ed81a96196 100644 --- a/src/Umbraco.Web/Editors/ContentController.cs +++ b/src/Umbraco.Web/Editors/ContentController.cs @@ -15,7 +15,6 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; -using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Services; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Models.Mapping; @@ -37,6 +36,7 @@ using Umbraco.Core.Persistence; using Umbraco.Core.Security; using Umbraco.Web.Routing; using Constants = Umbraco.Core.Constants; +using Umbraco.Core.Dictionary; namespace Umbraco.Web.Editors { @@ -57,8 +57,8 @@ namespace Umbraco.Web.Editors public object Domains { get; private set; } - public ContentController(PropertyEditorCollection propertyEditors, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper) + public ContentController(ICultureDictionary cultureDictionary, PropertyEditorCollection propertyEditors, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) + : base(cultureDictionary, globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper) { _propertyEditors = propertyEditors ?? throw new ArgumentNullException(nameof(propertyEditors)); _allLangs = new Lazy>(() => Services.LocalizationService.GetAllLanguages().ToDictionary(x => x.IsoCode, x => x, StringComparer.InvariantCultureIgnoreCase)); @@ -357,10 +357,10 @@ namespace Umbraco.Web.Editors var emptyContent = Services.ContentService.Create("", parentId, contentType.Alias, Security.GetUserId().ResultOr(0)); var mapped = MapToDisplay(emptyContent); // translate the content type name if applicable - mapped.ContentTypeName = Services.TextService.UmbracoDictionaryTranslate(mapped.ContentTypeName); + mapped.ContentTypeName = Services.TextService.UmbracoDictionaryTranslate(CultureDictionary, mapped.ContentTypeName); // if your user type doesn't have access to the Settings section it would not get this property mapped if (mapped.DocumentType != null) - mapped.DocumentType.Name = Services.TextService.UmbracoDictionaryTranslate(mapped.DocumentType.Name); + mapped.DocumentType.Name = Services.TextService.UmbracoDictionaryTranslate(CultureDictionary, mapped.DocumentType.Name); //remove the listview app if it exists mapped.ContentApps = mapped.ContentApps.Where(x => x.Alias != "umbListView").ToList(); diff --git a/src/Umbraco.Web/Editors/ContentControllerBase.cs b/src/Umbraco.Web/Editors/ContentControllerBase.cs index 83167eb9ae..610f668997 100644 --- a/src/Umbraco.Web/Editors/ContentControllerBase.cs +++ b/src/Umbraco.Web/Editors/ContentControllerBase.cs @@ -6,6 +6,7 @@ using System.Web.Http; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; +using Umbraco.Core.Dictionary; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Editors; @@ -26,9 +27,12 @@ namespace Umbraco.Web.Editors [JsonDateTimeFormatAttribute] public abstract class ContentControllerBase : BackOfficeNotificationsController { - protected ContentControllerBase(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) + protected ICultureDictionary CultureDictionary { get; } + + protected ContentControllerBase(ICultureDictionary cultureDictionary, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper) { + CultureDictionary = cultureDictionary; } protected HttpResponseMessage HandleContentNotFound(object id, bool throwException = true) diff --git a/src/Umbraco.Web/Editors/ContentTypeController.cs b/src/Umbraco.Web/Editors/ContentTypeController.cs index dc95e1e74e..d4e153ea9e 100644 --- a/src/Umbraco.Web/Editors/ContentTypeController.cs +++ b/src/Umbraco.Web/Editors/ContentTypeController.cs @@ -52,14 +52,14 @@ namespace Umbraco.Web.Editors private readonly IScopeProvider _scopeProvider; public ContentTypeController(IEntityXmlSerializer serializer, - ICultureDictionaryFactory cultureDictionaryFactory, + ICultureDictionary cultureDictionary, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, PropertyEditorCollection propertyEditors, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper, IScopeProvider scopeProvider) - : base(cultureDictionaryFactory, globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper) + : base(cultureDictionary, globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper) { _serializer = serializer; _propertyEditors = propertyEditors; @@ -438,8 +438,8 @@ namespace Umbraco.Web.Editors var localizedTextService = Services.TextService; foreach (var basic in basics) { - basic.Name = localizedTextService.UmbracoDictionaryTranslate(basic.Name); - basic.Description = localizedTextService.UmbracoDictionaryTranslate(basic.Description); + basic.Name = localizedTextService.UmbracoDictionaryTranslate(CultureDictionary, basic.Name); + basic.Description = localizedTextService.UmbracoDictionaryTranslate(CultureDictionary, basic.Description); } //map the blueprints diff --git a/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs b/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs index 2b3990c7a1..138ef7e43d 100644 --- a/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs +++ b/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs @@ -28,16 +28,13 @@ namespace Umbraco.Web.Editors public abstract class ContentTypeControllerBase : UmbracoAuthorizedJsonController where TContentType : class, IContentTypeComposition { - private readonly ICultureDictionaryFactory _cultureDictionaryFactory; - private ICultureDictionary _cultureDictionary; - - protected ContentTypeControllerBase(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) + protected ContentTypeControllerBase(ICultureDictionary cultureDictionary, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper) { - _cultureDictionaryFactory = cultureDictionaryFactory; + CultureDictionary = cultureDictionary; } - + protected ICultureDictionary CultureDictionary { get; } /// /// Returns the available composite content types for a given content type @@ -551,9 +548,6 @@ namespace Umbraco.Web.Editors forDisplay.Errors = ModelState.ToErrorDictionary(); return new HttpResponseException(Request.CreateValidationErrorResponse(forDisplay)); - } - - private ICultureDictionary CultureDictionary - => _cultureDictionary ?? (_cultureDictionary = _cultureDictionaryFactory.CreateDictionary()); + } } } diff --git a/src/Umbraco.Web/Editors/MediaController.cs b/src/Umbraco.Web/Editors/MediaController.cs index ba5d64cde7..2f973382b5 100644 --- a/src/Umbraco.Web/Editors/MediaController.cs +++ b/src/Umbraco.Web/Editors/MediaController.cs @@ -36,6 +36,7 @@ using Umbraco.Web.ContentApps; using Umbraco.Web.Editors.Binders; using Umbraco.Web.Editors.Filters; using Constants = Umbraco.Core.Constants; +using Umbraco.Core.Dictionary; namespace Umbraco.Web.Editors { @@ -48,8 +49,8 @@ namespace Umbraco.Web.Editors [MediaControllerControllerConfiguration] public class MediaController : ContentControllerBase { - public MediaController(PropertyEditorCollection propertyEditors, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper) + public MediaController(ICultureDictionary cultureDictionary, PropertyEditorCollection propertyEditors, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) + : base(cultureDictionary, globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper) { _propertyEditors = propertyEditors ?? throw new ArgumentNullException(nameof(propertyEditors)); } diff --git a/src/Umbraco.Web/Editors/MediaTypeController.cs b/src/Umbraco.Web/Editors/MediaTypeController.cs index c8e3e202ae..f05a840ad6 100644 --- a/src/Umbraco.Web/Editors/MediaTypeController.cs +++ b/src/Umbraco.Web/Editors/MediaTypeController.cs @@ -36,8 +36,8 @@ namespace Umbraco.Web.Editors [MediaTypeControllerControllerConfiguration] public class MediaTypeController : ContentTypeControllerBase { - public MediaTypeController(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) - : base(cultureDictionaryFactory, globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper) + public MediaTypeController(ICultureDictionary cultureDictionary, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) + : base(cultureDictionary, globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper) { } diff --git a/src/Umbraco.Web/Editors/MemberController.cs b/src/Umbraco.Web/Editors/MemberController.cs index 7fd293d9b5..8bf7f20b38 100644 --- a/src/Umbraco.Web/Editors/MemberController.cs +++ b/src/Umbraco.Web/Editors/MemberController.cs @@ -30,6 +30,7 @@ using Umbraco.Web.ContentApps; using Umbraco.Web.Editors.Binders; using Umbraco.Web.Editors.Filters; using Constants = Umbraco.Core.Constants; +using Umbraco.Core.Dictionary; namespace Umbraco.Web.Editors { @@ -38,12 +39,12 @@ namespace Umbraco.Web.Editors /// access to ALL of the methods on this controller will need access to the member application. /// [PluginController("UmbracoApi")] - [UmbracoApplicationAuthorizeAttribute(Constants.Applications.Members)] + [UmbracoApplicationAuthorize(Constants.Applications.Members)] [OutgoingNoHyphenGuidFormat] public class MemberController : ContentControllerBase { - public MemberController(PropertyEditorCollection propertyEditors, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper) + public MemberController(ICultureDictionary cultureDictionary, PropertyEditorCollection propertyEditors, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) + : base(cultureDictionary, globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper) { _propertyEditors = propertyEditors ?? throw new ArgumentNullException(nameof(propertyEditors)); } diff --git a/src/Umbraco.Web/Editors/MemberTypeController.cs b/src/Umbraco.Web/Editors/MemberTypeController.cs index fffead9155..4907fa74b3 100644 --- a/src/Umbraco.Web/Editors/MemberTypeController.cs +++ b/src/Umbraco.Web/Editors/MemberTypeController.cs @@ -29,8 +29,8 @@ namespace Umbraco.Web.Editors [UmbracoTreeAuthorize(new string[] { Constants.Trees.MemberTypes, Constants.Trees.Members})] public class MemberTypeController : ContentTypeControllerBase { - public MemberTypeController(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) - : base(cultureDictionaryFactory, globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper) + public MemberTypeController(ICultureDictionary cultureDictionary, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) + : base(cultureDictionary, globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper) { } diff --git a/src/Umbraco.Web/Models/Mapping/ContentMapDefinition.cs b/src/Umbraco.Web/Models/Mapping/ContentMapDefinition.cs index d3b4353f2f..fd76ce4943 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentMapDefinition.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentMapDefinition.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using Umbraco.Core; +using Umbraco.Core.Dictionary; using Umbraco.Core.Logging; using Umbraco.Core.Mapping; using Umbraco.Core.Models; @@ -18,6 +19,7 @@ namespace Umbraco.Web.Models.Mapping internal class ContentMapDefinition : IMapDefinition { private readonly CommonMapper _commonMapper; + private readonly ICultureDictionary _cultureDictionary; private readonly ILocalizedTextService _localizedTextService; private readonly IContentService _contentService; private readonly IContentTypeService _contentTypeService; @@ -32,11 +34,12 @@ namespace Umbraco.Web.Models.Mapping private readonly ContentBasicSavedStateMapper _basicStateMapper; private readonly ContentVariantMapper _contentVariantMapper; - public ContentMapDefinition(CommonMapper commonMapper, ILocalizedTextService localizedTextService, IContentService contentService, IContentTypeService contentTypeService, + public ContentMapDefinition(CommonMapper commonMapper, ICultureDictionary cultureDictionary, ILocalizedTextService localizedTextService, IContentService contentService, IContentTypeService contentTypeService, IFileService fileService, IUmbracoContextAccessor umbracoContextAccessor, IPublishedRouter publishedRouter, ILocalizationService localizationService, ILogger logger, IUserService userService) { _commonMapper = commonMapper; + _cultureDictionary = cultureDictionary; _localizedTextService = localizedTextService; _contentService = contentService; _contentTypeService = contentTypeService; @@ -47,7 +50,7 @@ namespace Umbraco.Web.Models.Mapping _logger = logger; _userService = userService; - _tabsAndPropertiesMapper = new TabsAndPropertiesMapper(localizedTextService); + _tabsAndPropertiesMapper = new TabsAndPropertiesMapper(cultureDictionary, localizedTextService); _stateMapper = new ContentSavedStateMapper(); _basicStateMapper = new ContentBasicSavedStateMapper(); _contentVariantMapper = new ContentVariantMapper(_localizationService); @@ -75,7 +78,7 @@ namespace Umbraco.Web.Models.Mapping target.ContentApps = _commonMapper.GetContentApps(source); target.ContentTypeId = source.ContentType.Id; target.ContentTypeAlias = source.ContentType.Alias; - target.ContentTypeName = _localizedTextService.UmbracoDictionaryTranslate(source.ContentType.Name); + target.ContentTypeName = _localizedTextService.UmbracoDictionaryTranslate(_cultureDictionary, source.ContentType.Name); target.DocumentType = _commonMapper.GetContentType(source, context); target.Icon = source.ContentType.Icon; target.Id = source.Id; @@ -231,7 +234,7 @@ namespace Umbraco.Web.Models.Mapping return contentType.AllowedTemplates .Where(t => t.Alias.IsNullOrWhiteSpace() == false && t.Name.IsNullOrWhiteSpace() == false) - .ToDictionary(t => t.Alias, t => _localizedTextService.UmbracoDictionaryTranslate(t.Name)); + .ToDictionary(t => t.Alias, t => _localizedTextService.UmbracoDictionaryTranslate(_cultureDictionary, t.Name)); } private string GetDefaultTemplate(IContent source) diff --git a/src/Umbraco.Web/Models/Mapping/ContentPropertyDisplayMapper.cs b/src/Umbraco.Web/Models/Mapping/ContentPropertyDisplayMapper.cs index 12278e97ea..e4d7007f73 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentPropertyDisplayMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentPropertyDisplayMapper.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Logging; +using Umbraco.Core.Dictionary; +using Umbraco.Core.Logging; using Umbraco.Core.Mapping; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; @@ -12,11 +13,13 @@ namespace Umbraco.Web.Models.Mapping /// internal class ContentPropertyDisplayMapper : ContentPropertyBasicMapper { + private readonly ICultureDictionary _cultureDictionary; private readonly ILocalizedTextService _textService; - public ContentPropertyDisplayMapper(IDataTypeService dataTypeService, IEntityService entityService, ILocalizedTextService textService, ILogger logger, PropertyEditorCollection propertyEditors) + public ContentPropertyDisplayMapper(ICultureDictionary cultureDictionary, IDataTypeService dataTypeService, IEntityService entityService, ILocalizedTextService textService, ILogger logger, PropertyEditorCollection propertyEditors) : base(dataTypeService, entityService, logger, propertyEditors) { + _cultureDictionary = cultureDictionary; _textService = textService; } public override void Map(IProperty originalProp, ContentPropertyDisplay dest, MapperContext context) @@ -59,8 +62,8 @@ namespace Umbraco.Web.Models.Mapping } //Translate - dest.Label = _textService.UmbracoDictionaryTranslate(dest.Label); - dest.Description = _textService.UmbracoDictionaryTranslate(dest.Description); + dest.Label = _textService.UmbracoDictionaryTranslate(_cultureDictionary, dest.Label); + dest.Description = _textService.UmbracoDictionaryTranslate(_cultureDictionary, dest.Description); } } } diff --git a/src/Umbraco.Web/Models/Mapping/ContentPropertyMapDefinition.cs b/src/Umbraco.Web/Models/Mapping/ContentPropertyMapDefinition.cs index 5d659fbf9e..d55791f068 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentPropertyMapDefinition.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentPropertyMapDefinition.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Logging; +using Umbraco.Core.Dictionary; +using Umbraco.Core.Logging; using Umbraco.Core.Mapping; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; @@ -17,11 +18,11 @@ namespace Umbraco.Web.Models.Mapping private readonly ContentPropertyDtoMapper _contentPropertyDtoConverter; private readonly ContentPropertyDisplayMapper _contentPropertyDisplayMapper; - public ContentPropertyMapDefinition(IDataTypeService dataTypeService, IEntityService entityService, ILocalizedTextService textService, ILogger logger, PropertyEditorCollection propertyEditors) + public ContentPropertyMapDefinition(ICultureDictionary cultureDictionary, IDataTypeService dataTypeService, IEntityService entityService, ILocalizedTextService textService, ILogger logger, PropertyEditorCollection propertyEditors) { _contentPropertyBasicConverter = new ContentPropertyBasicMapper(dataTypeService, entityService, logger, propertyEditors); _contentPropertyDtoConverter = new ContentPropertyDtoMapper(dataTypeService, entityService, logger, propertyEditors); - _contentPropertyDisplayMapper = new ContentPropertyDisplayMapper(dataTypeService, entityService, textService, logger, propertyEditors); + _contentPropertyDisplayMapper = new ContentPropertyDisplayMapper(cultureDictionary, dataTypeService, entityService, textService, logger, propertyEditors); } public void DefineMaps(UmbracoMapper mapper) diff --git a/src/Umbraco.Web/Models/Mapping/MediaMapDefinition.cs b/src/Umbraco.Web/Models/Mapping/MediaMapDefinition.cs index 80bdc7ade4..67617807fc 100644 --- a/src/Umbraco.Web/Models/Mapping/MediaMapDefinition.cs +++ b/src/Umbraco.Web/Models/Mapping/MediaMapDefinition.cs @@ -1,6 +1,7 @@ using System.Linq; using Umbraco.Core; using Umbraco.Core.Composing; +using Umbraco.Core.Dictionary; using Umbraco.Core.Logging; using Umbraco.Core.Mapping; using Umbraco.Core.Models; @@ -21,7 +22,7 @@ namespace Umbraco.Web.Models.Mapping private readonly IMediaTypeService _mediaTypeService; private readonly TabsAndPropertiesMapper _tabsAndPropertiesMapper; - public MediaMapDefinition(ILogger logger, CommonMapper commonMapper, IMediaService mediaService, IMediaTypeService mediaTypeService, + public MediaMapDefinition(ICultureDictionary cultureDictionary, ILogger logger, CommonMapper commonMapper, IMediaService mediaService, IMediaTypeService mediaTypeService, ILocalizedTextService localizedTextService) { _logger = logger; @@ -29,7 +30,7 @@ namespace Umbraco.Web.Models.Mapping _mediaService = mediaService; _mediaTypeService = mediaTypeService; - _tabsAndPropertiesMapper = new TabsAndPropertiesMapper(localizedTextService); + _tabsAndPropertiesMapper = new TabsAndPropertiesMapper(cultureDictionary, localizedTextService); } public void DefineMaps(UmbracoMapper mapper) diff --git a/src/Umbraco.Web/Models/Mapping/MemberTabsAndPropertiesMapper.cs b/src/Umbraco.Web/Models/Mapping/MemberTabsAndPropertiesMapper.cs index 4173e9a943..46689de71b 100644 --- a/src/Umbraco.Web/Models/Mapping/MemberTabsAndPropertiesMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/MemberTabsAndPropertiesMapper.cs @@ -10,6 +10,7 @@ using Umbraco.Core.Models.Membership; using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Web.Models.ContentEditing; +using Umbraco.Core.Dictionary; namespace Umbraco.Web.Models.Mapping { @@ -26,15 +27,13 @@ namespace Umbraco.Web.Models.Mapping private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly ILocalizedTextService _localizedTextService; private readonly IMemberTypeService _memberTypeService; - private readonly IMemberService _memberService; private readonly IUserService _userService; - public MemberTabsAndPropertiesMapper(IUmbracoContextAccessor umbracoContextAccessor, ILocalizedTextService localizedTextService, IMemberService memberService, IUserService userService, IMemberTypeService memberTypeService) - : base(localizedTextService) + public MemberTabsAndPropertiesMapper(ICultureDictionary cultureDictionary, IUmbracoContextAccessor umbracoContextAccessor, ILocalizedTextService localizedTextService, IUserService userService, IMemberTypeService memberTypeService) + : base(cultureDictionary, localizedTextService) { _umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor)); _localizedTextService = localizedTextService ?? throw new ArgumentNullException(nameof(localizedTextService)); - _memberService = memberService ?? throw new ArgumentNullException(nameof(memberService)); _userService = userService ?? throw new ArgumentNullException(nameof(userService)); _memberTypeService = memberTypeService ?? throw new ArgumentNullException(nameof(memberTypeService)); } @@ -123,7 +122,7 @@ namespace Umbraco.Web.Models.Mapping { Alias = $"{Constants.PropertyEditors.InternalGenericPropertiesPrefix}doctype", Label = _localizedTextService.Localize("content/membertype"), - Value = _localizedTextService.UmbracoDictionaryTranslate(member.ContentType.Name), + Value = _localizedTextService.UmbracoDictionaryTranslate(CultureDictionary, member.ContentType.Name), View = Current.PropertyEditors[Constants.PropertyEditors.Aliases.Label].GetValueEditor().View }, GetLoginProperty(_memberTypeService, member, _localizedTextService), diff --git a/src/Umbraco.Web/Models/Mapping/TabsAndPropertiesMapper.cs b/src/Umbraco.Web/Models/Mapping/TabsAndPropertiesMapper.cs index 70a001735a..32432d74b1 100644 --- a/src/Umbraco.Web/Models/Mapping/TabsAndPropertiesMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/TabsAndPropertiesMapper.cs @@ -7,22 +7,25 @@ using Umbraco.Core.Models; using Umbraco.Core.Services; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Composing; +using Umbraco.Core.Dictionary; namespace Umbraco.Web.Models.Mapping { internal abstract class TabsAndPropertiesMapper { + protected ICultureDictionary CultureDictionary { get; } protected ILocalizedTextService LocalizedTextService { get; } protected IEnumerable IgnoreProperties { get; set; } - protected TabsAndPropertiesMapper(ILocalizedTextService localizedTextService) + protected TabsAndPropertiesMapper(ICultureDictionary cultureDictionary, ILocalizedTextService localizedTextService) { + CultureDictionary = cultureDictionary ?? throw new ArgumentNullException(nameof(cultureDictionary)); LocalizedTextService = localizedTextService ?? throw new ArgumentNullException(nameof(localizedTextService)); IgnoreProperties = new List(); } - protected TabsAndPropertiesMapper(ILocalizedTextService localizedTextService, IEnumerable ignoreProperties) - : this(localizedTextService) + protected TabsAndPropertiesMapper(ICultureDictionary cultureDictionary, ILocalizedTextService localizedTextService, IEnumerable ignoreProperties) + : this(cultureDictionary, localizedTextService) { IgnoreProperties = ignoreProperties ?? throw new ArgumentNullException(nameof(ignoreProperties)); } @@ -115,8 +118,8 @@ namespace Umbraco.Web.Models.Mapping internal class TabsAndPropertiesMapper : TabsAndPropertiesMapper where TSource : IContentBase { - public TabsAndPropertiesMapper(ILocalizedTextService localizedTextService) - : base(localizedTextService) + public TabsAndPropertiesMapper(ICultureDictionary cultureDictionary, ILocalizedTextService localizedTextService) + : base(cultureDictionary, localizedTextService) { } public virtual IEnumerable> Map(TSource source, MapperContext context) @@ -159,7 +162,7 @@ namespace Umbraco.Web.Models.Mapping { Id = groupId, Alias = groupName, - Label = LocalizedTextService.UmbracoDictionaryTranslate(groupName), + Label = LocalizedTextService.UmbracoDictionaryTranslate(CultureDictionary, groupName), Properties = mappedProperties, IsActive = false }); diff --git a/src/Umbraco.Web/Runtime/WebFinalComposer.cs b/src/Umbraco.Web/Runtime/WebFinalComposer.cs index c69ae1af1a..f0178413a0 100644 --- a/src/Umbraco.Web/Runtime/WebFinalComposer.cs +++ b/src/Umbraco.Web/Runtime/WebFinalComposer.cs @@ -1,4 +1,6 @@ -using Umbraco.Core.Composing; +using Umbraco.Core; +using Umbraco.Core.Composing; +using Umbraco.Core.Dictionary; namespace Umbraco.Web.Runtime { @@ -7,5 +9,16 @@ namespace Umbraco.Web.Runtime [ComposeAfter(typeof(IUserComposer))] [ComposeAfter(typeof(ICoreComposer))] public class WebFinalComposer : ComponentComposer - { } + { + + public override void Compose(Composition composition) + { + base.Compose(composition); + + // now that user composers have had a chance to register their own factory, we can add the result of the factory + // to the container. + composition.Register(f => f.GetInstance().CreateDictionary(), Lifetime.Singleton); + } + + } } diff --git a/src/Umbraco.Web/Runtime/WebInitialComposer.cs b/src/Umbraco.Web/Runtime/WebInitialComposer.cs index 87c0f46fba..046b8381d2 100644 --- a/src/Umbraco.Web/Runtime/WebInitialComposer.cs +++ b/src/Umbraco.Web/Runtime/WebInitialComposer.cs @@ -202,7 +202,7 @@ namespace Umbraco.Web.Runtime composition.RegisterUnique(); - composition.RegisterUnique(); + composition.SetCultureDictionaryFactory(); // register *all* checks, except those marked [HideFromTypeFinder] of course composition.WithCollectionBuilder()