mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-04-05 21:01:35 +08:00
Starting to get some content localization hooked up.
- can create new translations and content items (in manage content) link to other localizations of the content - still a bit buggy when creating a new translation to override an existing translation - the ux is still, definately, a bid ol' wip --HG-- branch : dev
This commit is contained in:
parent
801c46ea04
commit
23b101a644
@ -88,7 +88,7 @@ namespace Orchard.Tests.Localization {
|
||||
}
|
||||
|
||||
public class TestCultureSelector : ICultureSelector {
|
||||
public CultureSelectorResult GetCulture(HttpContext context) {
|
||||
public CultureSelectorResult GetCulture(HttpContextBase context) {
|
||||
return new CultureSelectorResult { Priority = 1, CultureName = "en-US" };
|
||||
}
|
||||
}
|
||||
|
@ -1,31 +1,44 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Core.Contents.ViewModels;
|
||||
using Orchard.Core.Localization.Models;
|
||||
using Orchard.Core.Localization.Services;
|
||||
using Orchard.Core.Localization.ViewModels;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Localization.Services;
|
||||
using Orchard.Mvc.Results;
|
||||
using Orchard.Mvc.ViewModels;
|
||||
|
||||
namespace Orchard.Core.Localization.Controllers {
|
||||
[ValidateInput(false)]
|
||||
public class AdminController : Controller, IUpdateModel {
|
||||
private readonly IContentManager _contentManager;
|
||||
private readonly ICultureManager _cultureManager;
|
||||
private readonly ILocalizationService _localizationService;
|
||||
|
||||
public AdminController(IOrchardServices orchardServices, IContentManager contentManager) {
|
||||
public AdminController(IOrchardServices orchardServices, IContentManager contentManager, ICultureManager cultureManager, ILocalizationService localizationService) {
|
||||
_contentManager = contentManager;
|
||||
_cultureManager = cultureManager;
|
||||
_localizationService = localizationService;
|
||||
Services = orchardServices;
|
||||
}
|
||||
|
||||
public IOrchardServices Services { get; set; }
|
||||
|
||||
public ActionResult Translate(int id, string from) {
|
||||
public ActionResult Translate(int id, string to) {
|
||||
var contentItem = _contentManager.Get(id, VersionOptions.Latest);
|
||||
|
||||
if (contentItem == null)
|
||||
return new NotFoundResult();
|
||||
|
||||
var model = new EditItemViewModel {
|
||||
var siteCultures = _cultureManager.ListCultures().Where(s => s != _localizationService.GetContentCulture(contentItem));
|
||||
var model = new AddLocalizationViewModel {
|
||||
Id = id,
|
||||
SelectedCulture = siteCultures.Any(s => s == to)
|
||||
? to
|
||||
: _cultureManager.GetCurrentCulture(HttpContext), // could be null but the person doing the translating might be translating into their current culture
|
||||
SiteCultures = siteCultures,
|
||||
Content = _contentManager.BuildEditorModel(contentItem)
|
||||
};
|
||||
|
||||
@ -40,21 +53,37 @@ namespace Orchard.Core.Localization.Controllers {
|
||||
if (contentItem == null)
|
||||
return new NotFoundResult();
|
||||
|
||||
var viewModel = new EditItemViewModel();
|
||||
if (TryUpdateModel(viewModel))
|
||||
viewModel.Content = _contentManager.UpdateEditorModel(contentItem, this);
|
||||
var viewModel = new AddLocalizationViewModel();
|
||||
TryUpdateModel(viewModel);
|
||||
|
||||
ContentItem contentItemTranslation;
|
||||
var existingTranslation = _localizationService.GetLocalizedContentItem(contentItem, viewModel.SelectedCulture);
|
||||
if (existingTranslation != null) { // edit existing
|
||||
contentItemTranslation = existingTranslation.ContentItem;
|
||||
}
|
||||
else { // create
|
||||
contentItemTranslation = _contentManager.New(contentItem.ContentType);
|
||||
var localized = contentItemTranslation.As<Localized>();
|
||||
localized.MasterContentItem = contentItem;
|
||||
localized.Culture = _cultureManager.GetCultureByName(viewModel.SelectedCulture);
|
||||
_contentManager.Create(contentItemTranslation, VersionOptions.Draft);
|
||||
}
|
||||
|
||||
if (ModelState.IsValid)
|
||||
viewModel.Content = _contentManager.UpdateEditorModel(contentItemTranslation, this);
|
||||
|
||||
//todo: create translation here
|
||||
if (!ModelState.IsValid) {
|
||||
Services.TransactionManager.Cancel();
|
||||
viewModel.SiteCultures = _cultureManager.ListCultures().Where(s => s != _localizationService.GetContentCulture(contentItem));
|
||||
PrepareEditorViewModel(viewModel.Content);
|
||||
return View(viewModel);
|
||||
}
|
||||
_contentManager.Publish(contentItem);
|
||||
|
||||
_contentManager.Publish(contentItemTranslation);
|
||||
|
||||
var metadata = _contentManager.GetItemMetadata(viewModel.Content.Item);
|
||||
if (metadata.EditorRouteValues == null)
|
||||
return null;
|
||||
return null; //todo: (heskew) redirect to somewhere better than nowhere
|
||||
|
||||
return RedirectToRoute(metadata.EditorRouteValues);
|
||||
}
|
||||
|
@ -1,35 +1,50 @@
|
||||
using JetBrains.Annotations;
|
||||
using Orchard.ContentManagement;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using JetBrains.Annotations;
|
||||
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;
|
||||
|
||||
namespace Orchard.Core.Localization.Drivers {
|
||||
[UsedImplicitly]
|
||||
public class LocalizationDriver : ContentPartDriver<Localized> {
|
||||
public LocalizationDriver(IOrchardServices services) {
|
||||
private readonly ICultureManager _cultureManager;
|
||||
private readonly ILocalizationService _localizationService;
|
||||
|
||||
public LocalizationDriver(IOrchardServices services, ICultureManager cultureManager, ILocalizationService localizationService) {
|
||||
_cultureManager = cultureManager;
|
||||
_localizationService = localizationService;
|
||||
Services = services;
|
||||
}
|
||||
|
||||
public IOrchardServices Services { get; set; }
|
||||
|
||||
protected override DriverResult Display(Localized part, string displayType) {
|
||||
// for viewing or adding translation
|
||||
if (!Services.Authorizer.Authorize(Permissions.ChangeOwner)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var model = new ContentTranslationsViewModel(part);
|
||||
var model = new ContentLocalizationsViewModel(part) {
|
||||
CanLocalize = _cultureManager.ListCultures()
|
||||
.Where(s => s != _cultureManager.GetCurrentCulture(new HttpContextWrapper(HttpContext.Current)) && s != _localizationService.GetContentCulture(part.ContentItem))
|
||||
.Count() > 0,
|
||||
Localizations = _localizationService.GetLocalizations(part.ContentItem)
|
||||
};
|
||||
return ContentPartTemplate(model, "Parts/Localization.ContentTranslations").LongestMatch(displayType, "Summary", "SummaryAdmin").Location("primary", "5");
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(Localized part) {
|
||||
var model = new LocalizationEditorViewModel();
|
||||
// ContentTranslations: for when there are drafts of translations
|
||||
// CultureSelection: for a new translation
|
||||
|
||||
//var model = new SelectTranslationsViewModel(part);
|
||||
//if (part.ContentItem.Is<Localized>())
|
||||
|
||||
return ContentPartTemplate(model, "Parts/Localization.IsLocalized").Location("primary", "before.3");
|
||||
return ContentPartTemplate(new SelectLocalizationsViewModel(part), "Parts/Localization.ContentTranslations").Location("secondary", "5");
|
||||
}
|
||||
}
|
||||
|
||||
public class LocalizationEditorViewModel {}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Core.Localization.Models;
|
||||
|
||||
namespace Orchard.Core.Localization.Services {
|
||||
public interface ILocalizationService : IDependency {
|
||||
Localized GetLocalizedContentItem(IContent masterContentItem, string culture);
|
||||
string GetContentCulture(IContent contentItem);
|
||||
IEnumerable<IContent> GetLocalizations(IContent contentItem);
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Core.Localization.Models;
|
||||
using Orchard.Localization.Services;
|
||||
|
||||
namespace Orchard.Core.Localization.Services {
|
||||
public class LocalizationService : ILocalizationService {
|
||||
private readonly IContentManager _contentManager;
|
||||
private readonly ICultureManager _cultureManager;
|
||||
|
||||
public LocalizationService(IContentManager contentManager, ICultureManager cultureManager) {
|
||||
_contentManager = contentManager;
|
||||
_cultureManager = cultureManager;
|
||||
}
|
||||
|
||||
Localized ILocalizationService.GetLocalizedContentItem(IContent content, string culture) {
|
||||
return _contentManager.Query(content.ContentItem.ContentType).Join<LocalizedRecord>()
|
||||
.List()
|
||||
.Select(i => i.As<Localized>())
|
||||
.Where(l => l.MasterContentItem != null && l.MasterContentItem.ContentItem.Id == content.ContentItem.Id && string.Equals(l.Culture.Culture, culture, StringComparison.OrdinalIgnoreCase))
|
||||
.SingleOrDefault();
|
||||
}
|
||||
|
||||
string ILocalizationService.GetContentCulture(IContent content) {
|
||||
return content.Is<Localized>() && content.As<Localized>().Culture != null
|
||||
? content.As<Localized>().Culture.Culture
|
||||
: _cultureManager.GetSiteCulture();
|
||||
}
|
||||
|
||||
IEnumerable<IContent> ILocalizationService.GetLocalizations(IContent content) {
|
||||
var localized = content.As<Localized>();
|
||||
|
||||
if (localized.MasterContentItem != null)
|
||||
return _contentManager.Query(content.ContentItem.ContentType).Join<LocalizedRecord>()
|
||||
.List()
|
||||
.Select(i => i.As<Localized>())
|
||||
.Where(l => l.Id != content.ContentItem.Id && (l.Id == localized.MasterContentItem.ContentItem.Id || l.MasterContentItem != null && l.MasterContentItem.ContentItem.Id == localized.MasterContentItem.ContentItem.Id));
|
||||
|
||||
return _contentManager.Query(content.ContentItem.ContentType).Join<LocalizedRecord>()
|
||||
.List()
|
||||
.Select(i => i.As<Localized>())
|
||||
.Where(l => l.MasterContentItem != null && l.MasterContentItem.ContentItem.Id == content.ContentItem.Id);
|
||||
}
|
||||
}
|
||||
}
|
23
src/Orchard.Web/Core/Localization/Styles/admin.css
Normal file
23
src/Orchard.Web/Core/Localization/Styles/admin.css
Normal file
@ -0,0 +1,23 @@
|
||||
.content-localization .content-localizations li,
|
||||
.content-localization .add-localization {
|
||||
font-size:1.4em;
|
||||
}
|
||||
.content-localization .content-localizations {
|
||||
font-size:.9em;
|
||||
margin:1.44em 0 .44em;
|
||||
}
|
||||
.content-localization .content-localizations>* {
|
||||
display:inline;
|
||||
}
|
||||
.content-localization .content-localizations li {
|
||||
border-bottom:0;
|
||||
display:inline;
|
||||
margin-left:.5em;
|
||||
padding:0;
|
||||
}
|
||||
.content-localization .content-localizations li::after {
|
||||
content:", ";
|
||||
}
|
||||
.content-localization .content-localizations li:last-child::after {
|
||||
content:"";
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.Mvc.ViewModels;
|
||||
|
||||
namespace Orchard.Core.Localization.ViewModels {
|
||||
public class AddLocalizationViewModel : BaseViewModel {
|
||||
public int Id { get; set; }
|
||||
public string SelectedCulture { get; set; }
|
||||
public IEnumerable<string> SiteCultures { get; set; }
|
||||
public ContentItemViewModel Content { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.ContentManagement;
|
||||
|
||||
namespace Orchard.Core.Localization.ViewModels {
|
||||
public class ContentLocalizationsViewModel {
|
||||
public ContentLocalizationsViewModel(IContent part) {
|
||||
Id = part.ContentItem.Id;
|
||||
}
|
||||
|
||||
public int Id { get; private set; }
|
||||
public bool CanLocalize { get; set; }
|
||||
public IEnumerable<IContent> Localizations { get; set; }
|
||||
}
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
using Orchard.Core.Localization.Models;
|
||||
|
||||
namespace Orchard.Core.Localization.ViewModels {
|
||||
public class ContentTranslationsViewModel {
|
||||
public ContentTranslationsViewModel(Localized part) {
|
||||
public class SelectLocalizationsViewModel {
|
||||
public SelectLocalizationsViewModel(Localized part) {
|
||||
|
||||
}
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<EditItemViewModel>" %>
|
||||
<%@ Import Namespace="Orchard.Core.Contents.ViewModels" %>
|
||||
<h1><%:Html.TitleForPage(T("Translate Content").ToString())%></h1>
|
||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<AddLocalizationViewModel>" %>
|
||||
<%@ Import Namespace="Orchard.Core.Localization.ViewModels" %><%
|
||||
Model.Content.Zones.AddRenderPartial("primary:before", "CultureSelection", Model); %>
|
||||
<h1><%:Html.TitleForPage(T("Translate Content").ToString()) %></h1>
|
||||
<% using (Html.BeginFormAntiForgeryPost()) { %>
|
||||
<%:Html.ValidationSummary() %>
|
||||
<%:Html.EditorForItem(m=>m.Content) %>
|
||||
<%} %>
|
||||
<%} %>
|
@ -0,0 +1,5 @@
|
||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<Orchard.Core.Localization.ViewModels.AddLocalizationViewModel>" %>
|
||||
<fieldset class="localization culture-selection">
|
||||
<label for="SelectedCulture"><%:T("Translating to") %></label>
|
||||
<%:Html.DropDownList("SelectedCulture", new SelectList(Model.SiteCultures, Model.SelectedCulture)) %>
|
||||
</fieldset>
|
@ -1,4 +1,16 @@
|
||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<Orchard.Core.Localization.ViewModels.ContentTranslationsViewModel>" %>
|
||||
<div class="content-translations">
|
||||
[translate content]
|
||||
</div>
|
||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<Orchard.Core.Localization.ViewModels.ContentLocalizationsViewModel>" %>
|
||||
<%@ Import Namespace="Orchard.Core.Localization.Models" %>
|
||||
<%@ Import Namespace="Orchard.ContentManagement" %>
|
||||
<%
|
||||
Html.RegisterStyle("admin.css"); %>
|
||||
<% if (Model.Localizations.Count() > 0 || Model.CanLocalize) { %>
|
||||
<div class="content-localization"><%
|
||||
if (Model.Localizations.Count() > 0) { %>
|
||||
<%--//todo: need this info in the view model--%>
|
||||
<div class="content-localizations"><h4><%:T("Other localizations:") %></h4><%:Html.UnorderedList(Model.Localizations, (c, i) => Html.ItemDisplayLink(c.ContentItem.As<Localized>().Culture != null ? c.ContentItem.As<Localized>().Culture.Culture : "[site's default culture]", c), "localizations") %></div><%
|
||||
}
|
||||
if (Model.CanLocalize) { %>
|
||||
<div class="add-localization"><%:Html.ActionLink(T("+ New translation").Text, "translate", "admin", new { area = "Localization", id = Model.Id }, null)%></div><%
|
||||
} %>
|
||||
</div><%
|
||||
} %>
|
@ -0,0 +1,5 @@
|
||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<Orchard.Core.Localization.ViewModels.SelectLocalizationsViewModel>" %>
|
||||
<fieldset class="localization translations">
|
||||
<legend>Publish also in</legend>
|
||||
[translations to publish]
|
||||
</fieldset>
|
@ -1,4 +0,0 @@
|
||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<Orchard.Core.Localization.Drivers.LocalizationEditorViewModel>" %>
|
||||
<fieldset class="content-translations">
|
||||
[do the translate content]
|
||||
</fieldset>
|
@ -82,12 +82,16 @@
|
||||
<Compile Include="Contents\ViewModels\EditItemViewModel.cs" />
|
||||
<Compile Include="Contents\ViewModels\ListContentsViewModel.cs" />
|
||||
<Compile Include="Contents\ViewModels\ListContentTypesViewModel.cs" />
|
||||
<Compile Include="Localization\Services\ILocalizationService.cs" />
|
||||
<Compile Include="Localization\Services\LocalizationService.cs" />
|
||||
<Compile Include="Localization\ViewModels\ContentLocalizationsViewModel.cs" />
|
||||
<Compile Include="Localization\ViewModels\SelectLocalizationsViewModel.cs" />
|
||||
<Compile Include="Reports\AdminMenu.cs" />
|
||||
<Compile Include="Reports\Controllers\AdminController.cs" />
|
||||
<Compile Include="Reports\Routes.cs" />
|
||||
<Compile Include="Localization\Controllers\AdminController.cs" />
|
||||
<Compile Include="Localization\DataMigrations\LocalizationDataMigration.cs" />
|
||||
<Compile Include="Localization\ViewModels\ContentTranslationsViewModel.cs" />
|
||||
<Compile Include="Localization\ViewModels\AddLocalizationViewModel.cs" />
|
||||
<Compile Include="Localization\Drivers\LocalizationDriver.cs" />
|
||||
<Compile Include="Navigation\DataMigrations\NavigationDataMigration.cs" />
|
||||
<Compile Include="Reports\ViewModels\DisplayReportViewModel.cs" />
|
||||
@ -239,13 +243,15 @@
|
||||
<Content Include="Contents\Views\EditorTemplates\Items\Contents.Item.ascx" />
|
||||
<Content Include="Contents\Views\Item\Preview.aspx" />
|
||||
<Content Include="Contents\Views\Item\Display.aspx" />
|
||||
<Content Include="Localization\Styles\admin.css" />
|
||||
<Content Include="Localization\Views\EditorTemplates\Parts\Localization.ContentTranslations.ascx" />
|
||||
<Content Include="Reports\Module.txt" />
|
||||
<Content Include="Reports\Views\Admin\Display.aspx" />
|
||||
<Content Include="Reports\Views\Admin\Index.aspx" />
|
||||
<Content Include="Localization\Module.txt" />
|
||||
<Content Include="Localization\Views\Admin\Translate.ascx" />
|
||||
<Content Include="Localization\Views\DisplayTemplates\Parts\Localization.ContentTranslations.SummaryAdmin.ascx" />
|
||||
<Content Include="Localization\Views\EditorTemplates\Parts\Localization.CultureSelection.ascx" />
|
||||
<Content Include="Localization\Views\CultureSelection.ascx" />
|
||||
<Content Include="Routable\Module.txt" />
|
||||
<Content Include="Routable\Scripts\jquery.slugify.js" />
|
||||
<Content Include="Routable\Views\EditorTemplates\Parts\Routable.IsRoutable.ascx" />
|
||||
|
@ -59,7 +59,7 @@ namespace Orchard.Core.Settings.Controllers {
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var viewModel = new SiteCulturesViewModel {
|
||||
CurrentCulture = CultureInfo.CurrentCulture.Name,
|
||||
CurrentCulture = _cultureManager.GetCurrentCulture(HttpContext),
|
||||
SiteCultures = _cultureManager.ListCultures(),
|
||||
};
|
||||
viewModel.AvailableSystemCultures = CultureInfo.GetCultures(CultureTypes.SpecificCultures)
|
||||
|
@ -48,7 +48,7 @@ namespace Orchard.Localization.Services {
|
||||
}
|
||||
}
|
||||
|
||||
public string GetCurrentCulture(HttpContext requestContext) {
|
||||
public string GetCurrentCulture(HttpContextBase requestContext) {
|
||||
var requestCulture = _cultureSelectors
|
||||
.Select(x => x.GetCulture(requestContext))
|
||||
.Where(x => x != null)
|
||||
@ -70,6 +70,10 @@ namespace Orchard.Localization.Services {
|
||||
return _cultureRepository.Get(id);
|
||||
}
|
||||
|
||||
public CultureRecord GetCultureByName(string cultureName) {
|
||||
return _cultureRepository.Get(cr => cr.Culture == cultureName);
|
||||
}
|
||||
|
||||
public string GetSiteCulture() {
|
||||
return CurrentSite == null ? null : CurrentSite.SiteCulture;
|
||||
}
|
||||
|
@ -7,8 +7,9 @@ namespace Orchard.Localization.Services {
|
||||
IEnumerable<string> ListCultures();
|
||||
void AddCulture(string cultureName);
|
||||
void DeleteCulture(string cultureName);
|
||||
string GetCurrentCulture(HttpContext requestContext);
|
||||
string GetCurrentCulture(HttpContextBase requestContext);
|
||||
CultureRecord GetCultureById(int id);
|
||||
CultureRecord GetCultureByName(string cultureName);
|
||||
string GetSiteCulture();
|
||||
bool IsValidCulture(string cultureName);
|
||||
}
|
||||
|
@ -7,6 +7,6 @@ namespace Orchard.Localization.Services {
|
||||
}
|
||||
|
||||
public interface ICultureSelector : IDependency {
|
||||
CultureSelectorResult GetCulture(HttpContext context);
|
||||
CultureSelectorResult GetCulture(HttpContextBase context);
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ namespace Orchard.Localization.Services {
|
||||
public class SiteCultureSelector : ICultureSelector {
|
||||
protected virtual ISite CurrentSite { get; [UsedImplicitly] private set; }
|
||||
|
||||
public CultureSelectorResult GetCulture(HttpContext context) {
|
||||
public CultureSelectorResult GetCulture(HttpContextBase context) {
|
||||
string currentCultureName = CurrentSite.SiteCulture;
|
||||
|
||||
if (String.IsNullOrEmpty(currentCultureName)) {
|
||||
|
@ -23,7 +23,7 @@ namespace Orchard.Localization {
|
||||
public LocalizedString Get(string textHint, params object[] args) {
|
||||
Logger.Debug("{0} localizing '{1}'", _scope, textHint);
|
||||
|
||||
string currentCulture = _cultureManager.GetCurrentCulture(HttpContext.Current);
|
||||
string currentCulture = _cultureManager.GetCurrentCulture(new HttpContextWrapper(HttpContext.Current));
|
||||
var localizedFormat = _resourceManager.GetLocalizedString(_scope, textHint, currentCulture);
|
||||
|
||||
return args.Length == 0
|
||||
|
Loading…
Reference in New Issue
Block a user