-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Localization #7596
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
sebastienros
merged 8 commits into
OrchardCMS:dev
from
LaserSrl:OrchardCMS/devLocalization
Apr 3, 2017
Merged
Localization #7596
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
d6b44c8
Step 1 of merge of localization into dev.
MatteoPiovanelli 207ec40
Step 2 of merge of localization into dev.
MatteoPiovanelli 48d5d6e
Step 3 of merge of localization into dev.
MatteoPiovanelli d2bd4d0
Implemented Cloning for TaxonomyPart
MatteoPiovanelli ff79ea4
Add Autocomplete for taxonomy Localization
LorenzoFrediani-Laser 08781d1
Fix for new translation and fix to change container on content update.
GiuseppeMusso-Laser 89e562d
Fix localization during the first saving.
GiuseppeMusso-Laser 0ca26d1
Localization on TaxonomyField: default value setting on TryToLocalize…
GiuseppeMusso-Laser File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
83 changes: 83 additions & 0 deletions
83
...ard.Web/Modules/Orchard.Blogs/BlogsLocalizationExtensions/Handlers/BlogPostPartHandler.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| using System.Collections.Generic; | ||
| using System.Linq; | ||
| using System.Web.Routing; | ||
|
|
||
| using Orchard.Autoroute.Models; | ||
| using Orchard.Autoroute.Services; | ||
| using Orchard.Blogs.Models; | ||
| using Orchard.ContentManagement; | ||
| using Orchard.ContentManagement.Aspects; | ||
| using Orchard.ContentManagement.Handlers; | ||
| using Orchard.Core.Common.Models; | ||
| using Orchard.Core.Title.Models; | ||
| using Orchard.Environment.Extensions; | ||
| using Orchard.Localization; | ||
| using Orchard.Localization.Models; | ||
| using Orchard.Localization.Services; | ||
| using Orchard.UI.Notify; | ||
|
|
||
| namespace Orchard.Blogs.BlogsLocalizationExtensions.Handlers { | ||
| [OrchardFeature("Orchard.Blogs.LocalizationExtensions")] | ||
| public class BlogPostPartHandler : ContentHandler { | ||
| private readonly IContentManager _contentManager; | ||
| private readonly IAutorouteService _routeService; | ||
| private readonly ILocalizationService _localizationService; | ||
|
|
||
| public BlogPostPartHandler(RequestContext requestContext, IContentManager contentManager, IAutorouteService routeService, ILocalizationService localizationService, INotifier notifier) { | ||
| _contentManager = contentManager; | ||
| _routeService = routeService; | ||
| _localizationService = localizationService; | ||
| Notifier = notifier; | ||
| T = NullLocalizer.Instance; | ||
| //move posts when created, updated or published | ||
| //changed OnCreating and OnUpdating in OnCreated and OnUpdated so LocalizationPart is already populated | ||
| OnCreated<BlogPostPart>((context, part) => MigrateBlogPost(context.ContentItem)); | ||
| OnUpdated<BlogPostPart>((context, part) => MigrateBlogPost(context.ContentItem)); | ||
| OnPublishing<BlogPostPart>((context, part) => MigrateBlogPost(context.ContentItem)); | ||
| } | ||
|
|
||
| public INotifier Notifier { get; set; } | ||
|
|
||
| public Localizer T { get; set; } | ||
|
|
||
| //This Method checks the blog post's culture and it's parent blog's culture and moves it to the correct blog if they aren't equal. | ||
| private void MigrateBlogPost(ContentItem blogPost) { | ||
| if (!blogPost.Has<LocalizationPart>() || !blogPost.Has<BlogPostPart>()) { | ||
| return; | ||
| } | ||
| //bolgPost just cloned for translation, never saved | ||
| if (blogPost.As<CommonPart>().Container == null) { | ||
| return; | ||
| } | ||
| var blog = _contentManager.Get(blogPost.As<CommonPart>().Container.Id); | ||
| if (!blog.Has<LocalizationPart>() || blog.As<LocalizationPart>().Culture == null) { | ||
| return; | ||
| } | ||
|
|
||
| //get our 2 cultures for comparison | ||
| var blogCulture = blog.As<LocalizationPart>().Culture; | ||
| var blogPostCulture = blogPost.As<LocalizationPart>().Culture; | ||
|
|
||
| //if the post is a different culture than the parent blog change the post's parent blog to the right localization... | ||
| if (blogPostCulture != null && (blogPostCulture.Id != blogCulture.Id)) { | ||
| //Get the id of the current blog | ||
| var blogids = new HashSet<int> { blog.As<BlogPart>().ContentItem.Id }; | ||
|
|
||
| //seek for same culture blog | ||
| var realBlog = _localizationService.GetLocalizations(blog).SingleOrDefault(w => w.As<LocalizationPart>().Culture == blogPostCulture); | ||
| if (realBlog.Has<LocalizationPart>() && realBlog.As<LocalizationPart>().Culture.Id == blogPostCulture.Id) { | ||
| blogPost.As<ICommonPart>().Container = realBlog; | ||
| if (blogPost.Has<AutoroutePart>()) { | ||
| _routeService.RemoveAliases(blogPost.As<AutoroutePart>()); | ||
| blogPost.As<AutoroutePart>().DisplayAlias = _routeService.GenerateAlias(blogPost.As<AutoroutePart>()); | ||
| _routeService.PublishAlias(blogPost.As<AutoroutePart>()); | ||
| } | ||
| Notifier.Information(T("Your Post has been moved under the \"{0}\" Blog", realBlog.As<TitlePart>().Title)); | ||
| return; | ||
| } | ||
|
|
||
| return; | ||
| } | ||
| } | ||
| } | ||
| } |
22 changes: 22 additions & 0 deletions
22
src/Orchard.Web/Modules/Orchard.Blogs/BlogsLocalizationExtensions/Migrations/Migrations.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.Linq; | ||
| using System.Web; | ||
| using Orchard.ContentManagement.MetaData; | ||
| using Orchard.Data.Migration; | ||
| using Orchard.Environment.Extensions; | ||
|
|
||
| namespace Orchard.Blogs.BlogsLocalizationExtensions.Migrations { | ||
| [OrchardFeature("Orchard.Blogs.LocalizationExtensions")] | ||
| public class Migrations : DataMigrationImpl { | ||
| public int Create() { | ||
| ContentDefinitionManager.AlterTypeDefinition("Blog", | ||
| cfg => cfg | ||
| .WithPart("LocalizationPart")); | ||
| ContentDefinitionManager.AlterTypeDefinition("BlogPost", | ||
| cfg => cfg | ||
| .WithPart("LocalizationPart")); | ||
| return 1; | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
27 changes: 27 additions & 0 deletions
27
src/Orchard.Web/Modules/Orchard.Localization/Extensions/MetaDataExtensions.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| using System.Globalization; | ||
| using Orchard.ContentManagement.MetaData.Builders; | ||
| using Orchard.Environment.Extensions; | ||
|
|
||
| namespace Orchard.Localization.Extensions { | ||
| [OrchardFeature("Orchard.Localization.CultureNeutralPartsAndFields")] | ||
| public static class MetaDataExtensions { | ||
| /// <summary> | ||
| /// Sets the ContentField being built as CultureNeutral. This field will then be synchronized across elements of a localization set. | ||
| /// </summary> | ||
| /// <param name="builder"></param> | ||
| /// <param name="cultureNeutral"></param> | ||
| /// <returns></returns> | ||
| public static ContentPartFieldDefinitionBuilder CultureNeutral(this ContentPartFieldDefinitionBuilder builder, bool cultureNeutral = true) { | ||
| return builder.WithSetting("LocalizationCultureNeutralitySettings.CultureNeutral", cultureNeutral.ToString(CultureInfo.InvariantCulture)); | ||
| } | ||
| /// <summary> | ||
| /// Sets the ContentPart being built as CultureNeutral. This part will then be synchronized across elements of a localization set. | ||
| /// </summary> | ||
| /// <param name="builder"></param> | ||
| /// <param name="cultureNeutral"></param> | ||
| /// <returns></returns> | ||
| public static ContentTypePartDefinitionBuilder CultureNeutral(this ContentTypePartDefinitionBuilder builder, bool cultureNeutral = true) { | ||
| return builder.WithSetting("LocalizationCultureNeutralitySettings.CultureNeutral", cultureNeutral.ToString(CultureInfo.InvariantCulture)); | ||
| } | ||
| } | ||
| } |
99 changes: 99 additions & 0 deletions
99
...Orchard.Web/Modules/Orchard.Localization/Handlers/LocalizationCultureNeutralityHandler.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| using System.Collections.Generic; | ||
| using System.Linq; | ||
| using Orchard.ContentManagement; | ||
| using Orchard.ContentManagement.Drivers; | ||
| using Orchard.ContentManagement.Handlers; | ||
| using Orchard.Environment.Extensions; | ||
| using Orchard.Localization.Models; | ||
| using Orchard.Localization.Services; | ||
| using Orchard.Localization.Settings; | ||
|
|
||
| namespace Orchard.Localization.Handlers { | ||
| [OrchardFeature("Orchard.Localization.CultureNeutralPartsAndFields")] | ||
| public class LocalizationCultureNeutralityHandler : ContentHandler { | ||
| private readonly ILocalizationService _localizationService; | ||
| private readonly IEnumerable<IContentFieldDriver> _fieldDrivers; | ||
| private readonly IEnumerable<IContentPartDriver> _partDrivers; | ||
| public LocalizationCultureNeutralityHandler(ILocalizationService localizationService, | ||
| IEnumerable<IContentFieldDriver> fieldDrivers, | ||
| IEnumerable<IContentPartDriver> partDrivers) { | ||
| _localizationService = localizationService; | ||
| _fieldDrivers = fieldDrivers; | ||
| _partDrivers = partDrivers; | ||
|
|
||
| OnPublished<IContent>(SynchronizeOnPublish); | ||
| } | ||
|
|
||
| protected void SynchronizeOnPublish(PublishContentContext context, IContent part) { | ||
| //Conditions to try and start a synchronization: | ||
| // && The content item is localizable | ||
| // - The content item has a LocalizationPart | ||
| // - We can check this on either the type or the item itself | ||
| // && The part has the CultureNeutral setting set to true | ||
| //After eventually synchronizing the part, we check whether we should be synchronizing any of its fields | ||
| // - Go through all the fields and check the CultureNeutral setting. | ||
| var locPart = part.ContentItem.As<LocalizationPart>(); | ||
| if (locPart != null) { | ||
| //given the LocalizationPart, get the localization set (all the ContentItems on which we'll try to synchronize) | ||
| var lSet = GetSynchronizationSet(locPart); | ||
| //cycle through all parts | ||
| foreach (var pa in part.ContentItem.Parts) { | ||
| if (pa.Settings.GetModel<LocalizationCultureNeutralitySettings>().CultureNeutral) { | ||
| Synchronize(pa, locPart, lSet); | ||
| } | ||
| foreach (var field in pa.Fields.Where(fi => fi.PartFieldDefinition.Settings.GetModel<LocalizationCultureNeutralitySettings>().CultureNeutral)) { | ||
| Synchronize(field, locPart, lSet); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// This method attempts to synchronize a part across the localization set | ||
| /// </summary> | ||
| /// <param name="part">The part that has just been published and that we wish to use to update all corresponding parts from | ||
| /// the other elements of the localization set.</param> | ||
| /// <param name="localizationPart">The localization part of the ContentItem that was just published.</param> | ||
| /// <param name="lSet">The localization set for the synchronization</param> | ||
| private void Synchronize(ContentPart part, LocalizationPart localizationPart, List<LocalizationPart> lSet) { | ||
| if (lSet.Count > 0) { | ||
| var partDrivers = _partDrivers.Where(cpd => cpd.GetPartInfo().FirstOrDefault().PartName == part.PartDefinition.Name); | ||
| //use cloning | ||
| foreach (var target in lSet.Select(lp => lp.ContentItem)) { | ||
| var context = new CloneContentContext(localizationPart.ContentItem, target); | ||
| partDrivers.Invoke(driver => driver.Cloning(context), context.Logger); | ||
| partDrivers.Invoke(driver => driver.Cloned(context), context.Logger); | ||
| } | ||
| } | ||
| } | ||
| /// <summary> | ||
| /// This method attempts to synchronize a field across the localization set | ||
| /// </summary> | ||
| /// <param name="field">The field that has just been published and that we wish to use to update all corresponding parts from | ||
| /// the other elements of the localization set.</param> | ||
| /// <param name="localizationPart">The localization part of the ContentItem that was just published.</param> | ||
| /// <param name="lSet">The localization set for the synchronization</param> | ||
| private void Synchronize(ContentField field, LocalizationPart localizationPart, List<LocalizationPart> lSet) { | ||
| if (lSet.Count > 0) { | ||
| var fieldDrivers = _fieldDrivers.Where(cfd => cfd.GetFieldInfo().FirstOrDefault().FieldTypeName == field.FieldDefinition.Name); | ||
| //use cloning | ||
| foreach (var target in lSet.Select(lp => lp.ContentItem)) { | ||
| var context = new CloneContentContext(localizationPart.ContentItem, target); | ||
| context.FieldName = field.Name; | ||
| fieldDrivers.Invoke(driver => driver.Cloning(context), context.Logger); | ||
| fieldDrivers.Invoke(driver => driver.Cloned(context), context.Logger); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private List<LocalizationPart> GetSynchronizationSet(LocalizationPart lPart) { | ||
| var lSet = _localizationService.GetLocalizations( | ||
| content: lPart.ContentItem, | ||
| versionOptions: VersionOptions.Published).ToList(); | ||
| lSet.AddRange(_localizationService.GetLocalizations( | ||
| content: lPart.ContentItem, | ||
| versionOptions: VersionOptions.Latest)); | ||
| return lSet.Distinct().Where(lp => lp.Id != lPart.Id).ToList(); | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@MatteoPiovanelli-Laser @sebastienros
I just found this during merging 1.10.x to dev and I have to admit that I looked at this PR and didn't notice this, but this is really bad. We can't put a reference like this in a module that provides low-level functionality (it's not a dependency, so it doesn't break anything, but still).
What's really strange is that two years later, @HermesSbicego-Laser committed a change that removes this, then two commits later I merged 1.10.x into dev, which readded that change. I don't know how the difftool would think that that should happen, but re-adding removed code by accident (without noticing) is even worse. This is not the first time it happens (and merging from 1.10.x to dev caused a lot of different problems in other cases too) - suggestions are welcome. I'll try to sort out the correct logic for LocalizationService...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update: I made a mistake, Hermes didn't remove this (I was looking at the wrong diff). Nevertheless, this TermPart-related logic has to be removed somehow without breaking Taxonomy Localization.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the TermPart condition in this commit: a5a24d0, so there's no type filter in the query. This way it doesn't Taxonomies localization and I don't think filtering on content type matters anyway.