From a7ed20918bc314bd50bcaa0646bab7d635c002a4 Mon Sep 17 00:00:00 2001 From: Kevin Jump Date: Thu, 31 Mar 2022 22:36:34 +0100 Subject: [PATCH 1/3] Move SupplemenataryLocalizedTextSources to Backoffice and use File provider. --- .../UmbracoBuilder.Services.cs | 20 +--- .../UmbracoBuilder.LocalizedText.cs | 94 +++++++++++++++++++ .../UmbracoBuilderExtensions.cs | 3 +- 3 files changed, 97 insertions(+), 20 deletions(-) create mode 100644 src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilder.LocalizedText.cs diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Services.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Services.cs index 915b815033..187b3f0e31 100644 --- a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Services.cs +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Services.cs @@ -116,31 +116,13 @@ namespace Umbraco.Cms.Infrastructure.DependencyInjection private static LocalizedTextServiceFileSources SourcesFactory(IServiceProvider container) { var hostingEnvironment = container.GetRequiredService(); - var globalSettings = container.GetRequiredService>().Value; var mainLangFolder = new DirectoryInfo(hostingEnvironment.MapPathContentRoot(WebPath.Combine(Constants.SystemDirectories.Umbraco, "config", "lang"))); - var appPlugins = new DirectoryInfo(hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.AppPlugins)); - var configLangFolder = new DirectoryInfo(hostingEnvironment.MapPathContentRoot(WebPath.Combine(Constants.SystemDirectories.Config, "lang"))); - - var pluginLangFolders = appPlugins.Exists == false - ? Enumerable.Empty() - : appPlugins.GetDirectories() - // Check for both Lang & lang to support case sensitive file systems. - .SelectMany(x => x.GetDirectories("?ang", SearchOption.AllDirectories).Where(x => x.Name.InvariantEquals("lang"))) - .SelectMany(x => x.GetFiles("*.xml", SearchOption.TopDirectoryOnly)) - .Select(x => new LocalizedTextServiceSupplementaryFileSource(x, false)); - - // user defined langs that overwrite the default, these should not be used by plugin creators - var userLangFolders = configLangFolder.Exists == false - ? Enumerable.Empty() - : configLangFolder - .GetFiles("*.user.xml", SearchOption.TopDirectoryOnly) - .Select(x => new LocalizedTextServiceSupplementaryFileSource(x, true)); return new LocalizedTextServiceFileSources( container.GetRequiredService>(), container.GetRequiredService(), mainLangFolder, - pluginLangFolders.Concat(userLangFolders)); + container.GetServices()); } } } diff --git a/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilder.LocalizedText.cs b/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilder.LocalizedText.cs new file mode 100644 index 0000000000..5deccd14f0 --- /dev/null +++ b/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilder.LocalizedText.cs @@ -0,0 +1,94 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; + +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.FileProviders; + +using Umbraco.Cms.Core.DependencyInjection; +using Umbraco.Cms.Core.Routing; +using Umbraco.Cms.Core.Services.Implement; + +using IHostingEnvironment = Umbraco.Cms.Core.Hosting.IHostingEnvironment; + +namespace Umbraco.Extensions +{ + /// + /// Extension methods for for the Umbraco back office + /// + public static partial class UmbracoBuilderExtensions + { + /// + /// Add the SupplementaryLocalizedTextFilesSources + /// + /// + /// + private static IUmbracoBuilder AddSupplemenataryLocalizedTextFileSources(this IUmbracoBuilder builder) + { + builder.Services.AddTransient(sp => + { + return GetSupplementaryFileSources( + sp.GetRequiredService(), + sp.GetRequiredService()); + }); + + return builder; + } + + + /// + /// Loads the suplimentary localization files from plugins and user config + /// + private static IEnumerable GetSupplementaryFileSources( + IHostingEnvironment hostingEnvironment, + IWebHostEnvironment webHostEnvironment) + { + var webFileProvider = webHostEnvironment.WebRootFileProvider; + var contentFileProvider = webHostEnvironment.ContentRootFileProvider; + + // plugins in /app_plugins + var pluginLangFolders = GetPluginLanguageFileSources(contentFileProvider, Cms.Core.Constants.SystemDirectories.AppPlugins, false); + + // files in /wwwroot/app_plugins (or any virtual location that maps to this) + var razorPluginFolders = GetPluginLanguageFileSources(webFileProvider, Cms.Core.Constants.SystemDirectories.AppPlugins, false); + + // user defined langs that overwrite the default, these should not be used by plugin creators + var configLangFolder = new DirectoryInfo(hostingEnvironment.MapPathContentRoot(WebPath.Combine(Cms.Core.Constants.SystemDirectories.Config, "lang"))); + + var userLangFolders = configLangFolder.Exists == false + ? Enumerable.Empty() + : configLangFolder + .GetFiles("*.user.xml", SearchOption.TopDirectoryOnly) + .Select(x => new LocalizedTextServiceSupplementaryFileSource(x, true)); + + // returned in order where userLangFolders takes precedence over plugins + return pluginLangFolders + .Concat(razorPluginFolders) + .Concat(userLangFolders); + } + + + /// + /// Loads the suplimentary localaization files via the file provider. + /// + /// + /// locates all *.xml files in the lang folder of any sub folder of the one provided. + /// e.g /app_plugins/plugin-name/lang/*.xml + /// + private static IEnumerable GetPluginLanguageFileSources( + IFileProvider fileProvider, string folder, bool overwriteCoreKeys) + { + // locate all the *.xml files inside Lang folders inside folders of the main folder + // e.g. /app_plugins/plugin-name/lang/*.xml + + return fileProvider.GetDirectoryContents(folder) + .Where(x => x.IsDirectory) + .SelectMany(x => fileProvider.GetDirectoryContents(WebPath.Combine(folder, x.Name))) + .Where(x => x.IsDirectory && x.Name.InvariantEquals("lang")) + .Select(x => new DirectoryInfo(x.PhysicalPath)) + .SelectMany(x => x.GetFiles("*.xml", SearchOption.TopDirectoryOnly)) + .Select(x => new LocalizedTextServiceSupplementaryFileSource(x, overwriteCoreKeys)); + } + } +} diff --git a/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs index 63027a3c9e..df09e9a9b2 100644 --- a/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs @@ -56,7 +56,8 @@ namespace Umbraco.Extensions .AddLogViewer() .AddExamine() .AddExamineIndexes() - .AddControllersWithAmbiguousConstructors(); + .AddControllersWithAmbiguousConstructors() + .AddSupplemenataryLocalizedTextFileSources(); public static IUmbracoBuilder AddUnattendedInstallInstallCreateUser(this IUmbracoBuilder builder) { From e64f051f8b0aa3d2a97a7ed770be61060cf380cb Mon Sep 17 00:00:00 2001 From: Kevin Jump Date: Fri, 1 Apr 2022 09:55:28 +0100 Subject: [PATCH 2/3] Make the user defined languages also use the FileProvider. --- .../UmbracoBuilder.LocalizedText.cs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilder.LocalizedText.cs b/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilder.LocalizedText.cs index 5deccd14f0..e17fd59564 100644 --- a/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilder.LocalizedText.cs +++ b/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilder.LocalizedText.cs @@ -7,6 +7,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.FileProviders; using Umbraco.Cms.Core.DependencyInjection; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Routing; using Umbraco.Cms.Core.Services.Implement; @@ -29,7 +30,6 @@ namespace Umbraco.Extensions builder.Services.AddTransient(sp => { return GetSupplementaryFileSources( - sp.GetRequiredService(), sp.GetRequiredService()); }); @@ -41,7 +41,6 @@ namespace Umbraco.Extensions /// Loads the suplimentary localization files from plugins and user config /// private static IEnumerable GetSupplementaryFileSources( - IHostingEnvironment hostingEnvironment, IWebHostEnvironment webHostEnvironment) { var webFileProvider = webHostEnvironment.WebRootFileProvider; @@ -54,15 +53,15 @@ namespace Umbraco.Extensions var razorPluginFolders = GetPluginLanguageFileSources(webFileProvider, Cms.Core.Constants.SystemDirectories.AppPlugins, false); // user defined langs that overwrite the default, these should not be used by plugin creators - var configLangFolder = new DirectoryInfo(hostingEnvironment.MapPathContentRoot(WebPath.Combine(Cms.Core.Constants.SystemDirectories.Config, "lang"))); + var userConfigLangFolder = Cms.Core.Constants.SystemDirectories.Config + .TrimStart(Cms.Core.Constants.CharArrays.Tilde); - var userLangFolders = configLangFolder.Exists == false - ? Enumerable.Empty() - : configLangFolder - .GetFiles("*.user.xml", SearchOption.TopDirectoryOnly) + var userLangFolders = contentFileProvider.GetDirectoryContents(userConfigLangFolder) + .Where(x => x.IsDirectory && x.Name.InvariantEquals("lang")) + .Select(x => new DirectoryInfo(x.PhysicalPath)) + .SelectMany(x => x.GetFiles("*.user.xml", SearchOption.TopDirectoryOnly)) .Select(x => new LocalizedTextServiceSupplementaryFileSource(x, true)); - // returned in order where userLangFolders takes precedence over plugins return pluginLangFolders .Concat(razorPluginFolders) .Concat(userLangFolders); From c13f01b402d10b4712f9b40176d0e8a791cb719c Mon Sep 17 00:00:00 2001 From: Nikolaj Geisle <70372949+Zeegaan@users.noreply.github.com> Date: Thu, 21 Apr 2022 09:10:33 +0200 Subject: [PATCH 3/3] Update src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilder.LocalizedText.cs --- .../DependencyInjection/UmbracoBuilder.LocalizedText.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilder.LocalizedText.cs b/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilder.LocalizedText.cs index e17fd59564..e5f30ded32 100644 --- a/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilder.LocalizedText.cs +++ b/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilder.LocalizedText.cs @@ -7,11 +7,8 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.FileProviders; using Umbraco.Cms.Core.DependencyInjection; -using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Routing; -using Umbraco.Cms.Core.Services.Implement; - -using IHostingEnvironment = Umbraco.Cms.Core.Hosting.IHostingEnvironment; +using Umbraco.Cms.Core.Services; namespace Umbraco.Extensions {