diff --git a/src/Orchard.Web/Core/Localization/Controllers/AdminController.cs b/src/Orchard.Web/Core/Localization/Controllers/AdminController.cs index 0eafb5cf6..9411eda95 100644 --- a/src/Orchard.Web/Core/Localization/Controllers/AdminController.cs +++ b/src/Orchard.Web/Core/Localization/Controllers/AdminController.cs @@ -9,7 +9,6 @@ using Orchard.Localization; using Orchard.Localization.Services; using Orchard.Mvc.Results; using Orchard.Mvc.ViewModels; -using Orchard.UI.Notify; namespace Orchard.Core.Localization.Controllers { [ValidateInput(false)] @@ -32,9 +31,15 @@ namespace Orchard.Core.Localization.Controllers { public ActionResult Translate(int id, string to) { var contentItem = _contentManager.Get(id, VersionOptions.Latest); + // only support translations from the site culture, at the moment at least if (contentItem == null) return new NotFoundResult(); + if (!contentItem.Is() || contentItem.As().MasterContentItem != null) { + var metadata = _contentManager.GetItemMetadata(contentItem); + return RedirectToAction(Convert.ToString(metadata.EditorRouteValues["action"]), metadata.EditorRouteValues); + } + var siteCultures = _cultureManager.ListCultures().Where(s => s != _localizationService.GetContentCulture(contentItem)); var model = new AddLocalizationViewModel { Id = id, diff --git a/src/Orchard.Web/Core/Localization/Drivers/LocalizationDriver.cs b/src/Orchard.Web/Core/Localization/Drivers/LocalizationDriver.cs index c22671eca..1b269b850 100644 --- a/src/Orchard.Web/Core/Localization/Drivers/LocalizationDriver.cs +++ b/src/Orchard.Web/Core/Localization/Drivers/LocalizationDriver.cs @@ -4,40 +4,67 @@ using System.Web; using JetBrains.Annotations; using Orchard.ContentManagement; using Orchard.ContentManagement.Drivers; -using Orchard.Core.Common; using Orchard.Core.Localization.Models; using Orchard.Core.Localization.Services; using Orchard.Core.Localization.ViewModels; using Orchard.Localization.Services; -using Orchard.Settings; namespace Orchard.Core.Localization.Drivers { [UsedImplicitly] public class LocalizationDriver : ContentPartDriver { + private const string TemplatePrefix = "Localization"; private readonly ICultureManager _cultureManager; private readonly ILocalizationService _localizationService; - public LocalizationDriver(IOrchardServices services, ICultureManager cultureManager, ILocalizationService localizationService) { + public LocalizationDriver(ICultureManager cultureManager, ILocalizationService localizationService) { _cultureManager = cultureManager; _localizationService = localizationService; - Services = services; } - protected virtual ISite CurrentSite { get; private set; } - public IOrchardServices Services { get; set; } - protected override DriverResult Display(Localized part, string displayType) { var model = new ContentLocalizationsViewModel(part) { - Localizations = _localizationService.GetLocalizations(part.ContentItem) - .Select(c => { - var localized = c.ContentItem.As(); - if (localized.Culture == null) - localized.Culture = _cultureManager.GetCultureByName(_cultureManager.GetCurrentCulture(new HttpContextWrapper(HttpContext.Current))); - return c; - }).ToList() + Localizations = GetDisplayLocalizations(part) }; - - return ContentPartTemplate(model, "Parts/Localization.ContentTranslations").LongestMatch(displayType, "Summary", "SummaryAdmin").Location("primary", "5"); + + return ContentPartTemplate(model, "Parts/Localization.ContentTranslations", TemplatePrefix).LongestMatch(displayType, "Summary", "SummaryAdmin").Location("primary", "5"); + } + + protected override DriverResult Editor(Localized part) { + var localizations = GetEditorLocalizations(part).ToList(); + var model = new EditLocalizationViewModel { + SelectedCulture = part.Culture != null ? part.Culture.Culture : null, + SiteCultures = _cultureManager.ListCultures().Where(s => s != _cultureManager.GetSiteCulture() && !localizations.Select(l => l.Culture.Culture).Contains(s)), + MasterContentItem = part.MasterContentItem, + ContentLocalizations = new ContentLocalizationsViewModel(part) { Localizations = localizations } + }; + + return ContentPartTemplate(model, "Parts/Localization.Translation", TemplatePrefix).Location("primary", "1"); + } + + protected override DriverResult Editor(Localized part, IUpdateModel updater) { + var model = new EditLocalizationViewModel(); + if (updater != null && updater.TryUpdateModel(model, TemplatePrefix, null, null)) { + _localizationService.SetContentCulture(part, model.SelectedCulture); + } + + return Editor(part); + } + + private IEnumerable GetDisplayLocalizations(Localized part) { + return _localizationService.GetLocalizations(part.ContentItem) + .Select(c => { + var localized = c.ContentItem.As(); + if (localized.Culture == null) { + localized.Culture = _cultureManager.GetCultureByName(_cultureManager.GetCurrentCulture(new HttpContextWrapper(HttpContext.Current))); + } + return c; + }).ToList(); + } + + private IEnumerable GetEditorLocalizations(Localized part) { + return _localizationService.GetLocalizations(part.ContentItem) + .Select(c => c.ContentItem.As()) + .Where(l => l.MasterContentItem != null).ToList(); } } } \ No newline at end of file diff --git a/src/Orchard.Web/Core/Localization/Handlers/LocalizationHandler.cs b/src/Orchard.Web/Core/Localization/Handlers/LocalizationHandler.cs index 04596ba31..e731f92fa 100644 --- a/src/Orchard.Web/Core/Localization/Handlers/LocalizationHandler.cs +++ b/src/Orchard.Web/Core/Localization/Handlers/LocalizationHandler.cs @@ -22,8 +22,6 @@ namespace Orchard.Core.Localization.Handlers { OnInitializing(InitializePart); - OnLoaded(LazyLoadHandlers); - OnIndexed((context, localized) => context.DocumentIndex .Add("culture", CultureInfo.GetCultureInfo(localized.Culture != null ? localized.Culture.Culture : _cultureManager.GetSiteCulture()).LCID) .Store() @@ -32,11 +30,6 @@ namespace Orchard.Core.Localization.Handlers { public Localizer T { get; set; } - void LazyLoadHandlers(LoadContentContext context, Localized localized) { - localized.CultureField.Loader(ctx => _cultureManager.GetCultureById(localized.Record.CultureId)); - localized.MasterContentItemField.Loader(ctx => _contentManager.Get(localized.Record.MasterContentItemId)); - } - void InitializePart(InitializingContentContext context, Localized localized) { localized.CultureField.Setter(cultureRecord => { localized.Record.CultureId = cultureRecord.Id; @@ -46,6 +39,8 @@ namespace Orchard.Core.Localization.Handlers { localized.Record.MasterContentItemId = masterContentItem.ContentItem.Id; return masterContentItem; }); + localized.CultureField.Loader(ctx => _cultureManager.GetCultureById(localized.Record.CultureId)); + localized.MasterContentItemField.Loader(ctx => _contentManager.Get(localized.Record.MasterContentItemId)); } } } \ No newline at end of file diff --git a/src/Orchard.Web/Core/Localization/Services/ILocalizationService.cs b/src/Orchard.Web/Core/Localization/Services/ILocalizationService.cs index b53b6fc5c..c11ebcb32 100644 --- a/src/Orchard.Web/Core/Localization/Services/ILocalizationService.cs +++ b/src/Orchard.Web/Core/Localization/Services/ILocalizationService.cs @@ -6,6 +6,7 @@ namespace Orchard.Core.Localization.Services { public interface ILocalizationService : IDependency { Localized GetLocalizedContentItem(IContent masterContentItem, string culture); string GetContentCulture(IContent contentItem); + void SetContentCulture(IContent contentItem, string culture); IEnumerable GetLocalizations(IContent contentItem); } } diff --git a/src/Orchard.Web/Core/Localization/Services/LocalizationService.cs b/src/Orchard.Web/Core/Localization/Services/LocalizationService.cs index 82e7a257b..7bdc5e6d4 100644 --- a/src/Orchard.Web/Core/Localization/Services/LocalizationService.cs +++ b/src/Orchard.Web/Core/Localization/Services/LocalizationService.cs @@ -4,7 +4,6 @@ using System.Linq; using Orchard.ContentManagement; using Orchard.Core.Localization.Models; using Orchard.Localization.Services; -using Orchard.Tasks.Scheduling; namespace Orchard.Core.Localization.Services { public class LocalizationService : ILocalizationService { @@ -25,11 +24,20 @@ namespace Orchard.Core.Localization.Services { } string ILocalizationService.GetContentCulture(IContent content) { - return content.Is() && content.As().Culture != null - ? content.As().Culture.Culture + var localized = content.As(); + return localized != null && localized.Culture != null + ? localized.Culture.Culture : _cultureManager.GetSiteCulture(); } + void ILocalizationService.SetContentCulture(IContent content, string culture) { + var localized = content.As(); + if (localized == null || localized.MasterContentItem == null) + return; + + localized.Culture = _cultureManager.GetCultureByName(culture); + } + IEnumerable ILocalizationService.GetLocalizations(IContent content) { var localized = content.As(); diff --git a/src/Orchard.Web/Core/Localization/Styles/admin.css b/src/Orchard.Web/Core/Localization/Styles/admin.css index 6895e51c0..7da94d32e 100644 --- a/src/Orchard.Web/Core/Localization/Styles/admin.css +++ b/src/Orchard.Web/Core/Localization/Styles/admin.css @@ -1,25 +1,45 @@ -.content-localization { - margin:1.44em 0 0; -} -.content-localization .content-localizations li, +.content-localization .content-localizations li, .content-localization .add-localization { font-size:1.4em; } +.content-localization .culture-selected { + margin-bottom:.5em; +} .content-localization .content-localizations { font-size:.9em; } .content-localization .content-localizations>* { display:inline; } -.content-localization .content-localizations li { +.content-localization .content-localizations .localizations li { border-bottom:0; display:inline; margin-left:.5em; padding:0; } .content-localization .content-localizations li::after { - content:", "; + content:","; } .content-localization .content-localizations li:last-child::after { content:""; +} +.culture-selection fieldset { + padding-top:0; +} +.culture-selection div { + font-size:1.4em; +} +.culture-selection dl { + margin:.2em 0; +} +.culture-selection dt { + color:#4C4C4C; + font-weight:bold; +} +.culture-selection dt, .culture-selection dd, .culture-selection ul { + display:inline; +} +.culture-selection .content-localization .content-localizations { + clear:none; + float:none; } \ No newline at end of file diff --git a/src/Orchard.Web/Core/Localization/ViewModels/ContentLocalizationsViewModel.cs b/src/Orchard.Web/Core/Localization/ViewModels/ContentLocalizationsViewModel.cs index eff2149dd..2ee7efeda 100644 --- a/src/Orchard.Web/Core/Localization/ViewModels/ContentLocalizationsViewModel.cs +++ b/src/Orchard.Web/Core/Localization/ViewModels/ContentLocalizationsViewModel.cs @@ -1,14 +1,15 @@ using System.Collections.Generic; -using Orchard.ContentManagement; using Orchard.Core.Localization.Models; namespace Orchard.Core.Localization.ViewModels { public class ContentLocalizationsViewModel { - public ContentLocalizationsViewModel(IContent part) { - Id = part.ContentItem.Id; + public ContentLocalizationsViewModel(Localized part) { + MasterId = part.MasterContentItem != null + ? part.MasterContentItem.ContentItem.Id + : part.Id; } - public int Id { get; private set; } + public int? MasterId { get; private set; } public IEnumerable Localizations { get; set; } } } \ No newline at end of file diff --git a/src/Orchard.Web/Core/Localization/ViewModels/EditLocalizationViewModel.cs b/src/Orchard.Web/Core/Localization/ViewModels/EditLocalizationViewModel.cs new file mode 100644 index 000000000..9dd435a8b --- /dev/null +++ b/src/Orchard.Web/Core/Localization/ViewModels/EditLocalizationViewModel.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; +using Orchard.ContentManagement; +using Orchard.Mvc.ViewModels; + +namespace Orchard.Core.Localization.ViewModels { + public class EditLocalizationViewModel : BaseViewModel { + public string SelectedCulture { get; set; } + public IEnumerable SiteCultures { get; set; } + public IContent MasterContentItem { get; set; } + public ContentLocalizationsViewModel ContentLocalizations { get; set; } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Core/Localization/ViewModels/SelectLocalizationsViewModel.cs b/src/Orchard.Web/Core/Localization/ViewModels/SelectLocalizationsViewModel.cs deleted file mode 100644 index d581664a2..000000000 --- a/src/Orchard.Web/Core/Localization/ViewModels/SelectLocalizationsViewModel.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Orchard.Core.Localization.Models; - -namespace Orchard.Core.Localization.ViewModels { - public class SelectLocalizationsViewModel { - public SelectLocalizationsViewModel(Localized part) { - - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Core/Localization/Views/DisplayTemplates/Parts/Localization.ContentTranslations.SummaryAdmin.ascx b/src/Orchard.Web/Core/Localization/Views/DisplayTemplates/Parts/Localization.ContentTranslations.SummaryAdmin.ascx index 371bb6823..e9d3522e4 100644 --- a/src/Orchard.Web/Core/Localization/Views/DisplayTemplates/Parts/Localization.ContentTranslations.SummaryAdmin.ascx +++ b/src/Orchard.Web/Core/Localization/Views/DisplayTemplates/Parts/Localization.ContentTranslations.SummaryAdmin.ascx @@ -4,7 +4,7 @@
<% if (Model.Localizations.Count() > 0) { %> <%--//todo: need this info in the view model--%> -

<%:T("Translations:") %>

<%:Html.UnorderedList(Model.Localizations, (c, i) => Html.ItemDisplayLink(c.Culture.Culture, c), "localizations") %>
<% +

<%:T("Translations:") %>

<%:Html.UnorderedList(Model.Localizations, (c, i) => Html.ItemEditLink(c.Culture.Culture, c), "localizations") %>
<% } %> -
<%:Html.ActionLink(T("+ New translation").Text, "translate", "admin", new { area = "Localization", id = Model.Id }, null)%>
+
<%:Html.ActionLink(T("+ New translation").Text, "translate", "admin", new { area = "Localization", id = Model.MasterId }, null)%>
\ No newline at end of file diff --git a/src/Orchard.Web/Core/Localization/Views/DisplayTemplates/Parts/Localization.ContentTranslations.ascx b/src/Orchard.Web/Core/Localization/Views/DisplayTemplates/Parts/Localization.ContentTranslations.ascx index 1389d7a38..7511aac14 100644 --- a/src/Orchard.Web/Core/Localization/Views/DisplayTemplates/Parts/Localization.ContentTranslations.ascx +++ b/src/Orchard.Web/Core/Localization/Views/DisplayTemplates/Parts/Localization.ContentTranslations.ascx @@ -6,5 +6,5 @@ <%--//todo: need this info in the view model--%>
<%:Html.UnorderedList(Model.Localizations, (c, i) => Html.ItemDisplayLink(c.Culture.Culture, c), "localizations") %>
<% } %> -
<%:Html.ActionLink(T("+ New translation").Text, "translate", "admin", new { area = "Localization", id = Model.Id }, null)%>
+
<%:Html.ActionLink(T("+ New translation").Text, "translate", "admin", new { area = "Localization", id = Model.MasterId }, null)%>
\ No newline at end of file diff --git a/src/Orchard.Web/Core/Localization/Views/EditorTemplates/Parts/Localization.Translation.ascx b/src/Orchard.Web/Core/Localization/Views/EditorTemplates/Parts/Localization.Translation.ascx new file mode 100644 index 000000000..5c388f609 --- /dev/null +++ b/src/Orchard.Web/Core/Localization/Views/EditorTemplates/Parts/Localization.Translation.ascx @@ -0,0 +1,24 @@ +<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl" %> +<% +Html.RegisterStyle("admin.css"); +Html.RegisterStyle("base.css"); +if (Model.ContentLocalizations.MasterId > 0) { %> +
<% + if (Model.MasterContentItem != null) { %> +
+ +
<%:T("This is the {0} variation of {1}.", + Html.DropDownList("SelectedCulture", new SelectList(Model.SiteCultures, Model.SelectedCulture)), + Html.ItemEditLink(Model.MasterContentItem)) %>
+
<% + } + if (Model.ContentLocalizations.Localizations.Count() > 0) { //todo: find a good place for this info on the content edit page %> +
+
<%:Model.MasterContentItem != null ? T("Other translations:") : T("Translations:") %>
+
+ <%:Html.UnorderedList(Model.ContentLocalizations.Localizations, (c, i) => Html.ItemEditLink(c.Culture.Culture, c), "localizations") %> +
+
<% + } %> +
<% +} %> \ No newline at end of file diff --git a/src/Orchard.Web/Core/Orchard.Core.csproj b/src/Orchard.Web/Core/Orchard.Core.csproj index 5aa40ce5a..18367777d 100644 --- a/src/Orchard.Web/Core/Orchard.Core.csproj +++ b/src/Orchard.Web/Core/Orchard.Core.csproj @@ -80,6 +80,7 @@ + @@ -93,7 +94,6 @@ - @@ -233,6 +233,7 @@ +