From 6b5bc7cebd938ff96288a371c87900dd7ee7af8f Mon Sep 17 00:00:00 2001 From: Kevin Jump Date: Fri, 29 Apr 2022 11:58:44 +0100 Subject: [PATCH] Updated for v10 - Get lang files via FileProviders (and support Razor Class Libraries) (#12313) * Update localized to get the physical paths on .net 6 * Update src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilder.LocalizedText.cs Co-authored-by: Ronald Barendse * Minor amends for variable naming and to resolve warnings on use of explicit types. Co-authored-by: Ronald Barendse Co-authored-by: Andy Butland --- .../UmbracoBuilder.Services.cs | 4 +- .../UmbracoBuilder.LocalizedText.cs | 65 +++++++++++++------ 2 files changed, 46 insertions(+), 23 deletions(-) diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Services.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Services.cs index c9d132c296..7fa36bc910 100644 --- a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Services.cs +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Services.cs @@ -45,7 +45,7 @@ namespace Umbraco.Cms.Infrastructure.DependencyInjection builder.Services.AddUnique(); builder.Services.AddUnique(); builder.Services.AddUnique(); - builder.Services.AddTransient(SourcesFactory); + builder.Services.AddTransient(LocalizedTextServiceFileSourcesFactory); builder.Services.AddUnique(factory => CreatePackageRepository(factory, "createdPackages.config")); builder.Services.AddUnique(); builder.Services.AddSingleton(); @@ -77,7 +77,7 @@ namespace Umbraco.Cms.Infrastructure.DependencyInjection factory.GetRequiredService(), packageRepoFileName); - private static LocalizedTextServiceFileSources SourcesFactory(IServiceProvider container) + private static LocalizedTextServiceFileSources LocalizedTextServiceFileSourcesFactory(IServiceProvider container) { var hostingEnvironment = container.GetRequiredService(); var mainLangFolder = new DirectoryInfo(hostingEnvironment.MapPathContentRoot(WebPath.Combine(Constants.SystemDirectories.Umbraco, "config", "lang"))); diff --git a/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilder.LocalizedText.cs b/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilder.LocalizedText.cs index e5f30ded32..ff817e2f1c 100644 --- a/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilder.LocalizedText.cs +++ b/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilder.LocalizedText.cs @@ -18,10 +18,8 @@ namespace Umbraco.Extensions public static partial class UmbracoBuilderExtensions { /// - /// Add the SupplementaryLocalizedTextFilesSources + /// Adds the supplementary localized texxt file sources from the various physical and virtual locations supported. /// - /// - /// private static IUmbracoBuilder AddSupplemenataryLocalizedTextFileSources(this IUmbracoBuilder builder) { builder.Services.AddTransient(sp => @@ -40,28 +38,24 @@ namespace Umbraco.Extensions private static IEnumerable GetSupplementaryFileSources( IWebHostEnvironment webHostEnvironment) { - var webFileProvider = webHostEnvironment.WebRootFileProvider; - var contentFileProvider = webHostEnvironment.ContentRootFileProvider; + IFileProvider webFileProvider = webHostEnvironment.WebRootFileProvider; + IFileProvider 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); + // gets all langs files in /app_plugins real or virtual locations + IEnumerable pluginLangFileSources = GetPluginLanguageFileSources(webFileProvider, Cms.Core.Constants.SystemDirectories.AppPlugins, false); // user defined langs that overwrite the default, these should not be used by plugin creators var userConfigLangFolder = Cms.Core.Constants.SystemDirectories.Config .TrimStart(Cms.Core.Constants.CharArrays.Tilde); - var userLangFolders = contentFileProvider.GetDirectoryContents(userConfigLangFolder) + IEnumerable userLangFileSources = 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)); - return pluginLangFolders - .Concat(razorPluginFolders) - .Concat(userLangFolders); + return pluginLangFileSources + .Concat(userLangFileSources); } @@ -77,14 +71,43 @@ namespace Umbraco.Extensions { // locate all the *.xml files inside Lang folders inside folders of the main folder // e.g. /app_plugins/plugin-name/lang/*.xml + var fileSources = new List(); - 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)); + var pluginFolders = fileProvider.GetDirectoryContents(folder) + .Where(x => x.IsDirectory).ToList(); + + foreach (IFileInfo pluginFolder in pluginFolders) + { + // get the full virtual path for the plugin folder + var pluginFolderPath = WebPath.Combine(folder, pluginFolder.Name); + + // get any lang folders in this plugin + IEnumerable langFolders = fileProvider.GetDirectoryContents(pluginFolderPath) + .Where(x => x.IsDirectory && x.Name.InvariantEquals("lang")); + + // loop through the lang folder(s) + // - there could be multiple on case sensitive file system + foreach (var langFolder in langFolders) + { + // get the full 'virtual' path of the lang folder + var langFolderPath = WebPath.Combine(pluginFolderPath, langFolder.Name); + + // request all the files out of the path, these will have physicalPath set. + var files = fileProvider.GetDirectoryContents(langFolderPath) + .Where(x => x.Name.InvariantEndsWith(".xml") && !string.IsNullOrEmpty(x.PhysicalPath)) + .Select(x => new FileInfo(x.PhysicalPath)) + .Select(x => new LocalizedTextServiceSupplementaryFileSource(x, overwriteCoreKeys)) + .ToList(); + + // add any to our results + if (files.Count > 0) + { + fileSources.AddRange(files); + } + } + } + + return fileSources; } } }