OrchardCore icon indicating copy to clipboard operation
OrchardCore copied to clipboard

Support both .resx and .po files

Open Skrypt opened this issue 5 years ago • 15 comments

From @jrestall

@tomlindhe I assume you need to keep the PO localization working for other modules, otherwise you could just disable the OrchardCore.Localization module and it'll go back to using the ResourceManagerStringLocalizerFactory by default. I'm no expert but one idea to support both could be to create a custom IStringLocalizerFactory (also IHtmlLocalizerFactory) that delegates to either the ResourceManagerStringLocalizerFactory or PortableObjectStringLocalizerFactory depending on some logic.

The OrchardCore.Localization modules calls AddPortableObjectLocalization() in OrchardCore.Localization.Core.ServiceCollectionExtensions and replaces the service that is harvesting localization files (.po) when we enable it. We do this so that the OrchardCore.Localization.Core module be used as standalone solution for using .po file. We replace the service in OrchardCore.Localization module for being able to have .po files in each modules by specifying a ModularPoFileLocationProvider() :

Orchard.Localization.Startup.cs

            // Override the default localization file locations with Orchard specific ones
            services.Replace(ServiceDescriptor.Singleton<ILocalizationFileLocationProvider, ModularPoFileLocationProvider>());

So as as soon as the OrchardCore.Localization module is enabled it breaks the .resx ressources because we are changing the folder and files that it's supposed to harvest and also because we are changing these in the AddPortableObjectLocalization() "this is where we lose .resx support" method.

Orchard.Localization.Core.ServiceCollectionExtensions.cs

            services.AddSingleton<IStringLocalizerFactory, PortableObjectStringLocalizerFactory>();

            services.AddSingleton<IHtmlLocalizerFactory, PortableObjectHtmlLocalizerFactory>();

One solution would be that if only one module needs to use .resx files ; in his startup.cs file then I think he could do something like :

        //This basically remove all Orchard Core custom implementations for .po files
        public override int Order => 99999; //a really high number

        public override void ConfigureServices(IServiceCollection services)
        {
            var serviceDescriptor = services.FirstOrDefault(s => s.ServiceType.FullName.Contains("IStringLocalizerFactory") && s.ImplementationType.FullName == "OrchardCore.Localization.PortableObject.PortableObjectStringLocalizerFactory");
            if (serviceDescriptor != null) { services.Remove(serviceDescriptor); };
            

            serviceDescriptor = services.FirstOrDefault(s => s.ServiceType.FullName.Contains("IHtmlLocalizerFactory") && s.ImplementationType.FullName == "OrchardCore.Localization.PortableObject.PortableObjectHtmlLocalizerFactory");
            if (serviceDescriptor != null) { services.Remove(serviceDescriptor); };
            
            services.RemoveAll<ILocalizationFileLocationProvider>(); //maybe not necessary but why not
         }

I think this would reset it all to default.

Skrypt avatar Oct 20 '18 17:10 Skrypt