OrchardCMS / OrchardCore

Orchard Core is an open-source modular and multi-tenant application framework built with ASP.NET Core, and a content management system (CMS) built on top of that framework.
https://orchardcore.net
BSD 3-Clause "New" or "Revised" License
7.46k stars 2.41k forks source link

Localizing widgets on layers #4961

Open PaulEpitomy opened 5 years ago

PaulEpitomy commented 5 years ago

I cannot find a way to localize widgets that are contained in layers, I've performed the following: -

  1. Add LocalizablePart to Liquid widget
  2. Re-save the widget and add the localizable contents

At this point I just see multiple copies in the front end.

To get around this I have modified LayerService to de-dup based on the current culture

        public async Task<IEnumerable<ContentItem>> GetLayerWidgetsAsync(
            Expression<Func<ContentItemIndex, bool>> predicate)
        {
            var widgets = await _session
                .Query<ContentItem, LayerMetadataIndex>()
                .With(predicate)
                .ListAsync();

            widgets = (await _contentLocalizationManager.DeduplicateContentItemsAsync(widgets)).Values;

            return widgets;
        }

and in LayerFilter, changed the cache key to include the culture

                var widgets = await _memoryCache.GetOrCreateAsync($"OrchardCore.Layers.LayerFilter:AllWidgets-{Thread.CurrentThread.CurrentUICulture}", entry =>
                {
                    entry.AddExpirationToken(_signal.GetToken(LayerMetadataHandler.LayerChangeToken));
                    return _layerService.GetLayerWidgetsMetadataAsync(x => x.Published);
                });

Is there a better way to handle widget localization?

sebastienros commented 5 years ago

We might need to update the layer filter to take the ILocalizable aspect into account if widgets have them. And if a Layer aggregates its widgets, we need to ensure that all version are stored there. Probably what you have done. Ideally without referencing the localization module. Just by resolving the culture of each widget using the aspect, and then ignoring the ones that are not for the ambient culture.

Another option might be to create custom layers for each widget. Could be much simpler and flexible.

PaulEpitomy commented 5 years ago

I did think about custom layers but we have 7 layers at present and ~10 languages so this would result in 70 layers, so I'm not sure how practical that would be.

I can create a PR if it helps, could you elaborate on "And if a Layer aggregates its widgets, we need to ensure that all version are stored there", as I'm not sure I understand?

I present I'm only referencing the OrchardCore.ContentLocalization.Abstractions so think that's Ok?

sebastienros commented 5 years ago

That would work, please try to create a PR

PaulEpitomy commented 5 years ago

Possible fix #4968 that may require additional work for GraphQL, should GraphQL filter widgets by culture or not?