mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Rewrote Localizaton controller and driver
This commit is contained in:
@@ -37,58 +37,32 @@ namespace Orchard.Localization.Controllers {
|
||||
public IOrchardServices Services { get; set; }
|
||||
|
||||
public ActionResult Translate(int id, string to) {
|
||||
var contentItem = _contentManager.Get(id, VersionOptions.Latest);
|
||||
|
||||
if (contentItem == null)
|
||||
var masterContentItem = _contentManager.Get(id, VersionOptions.Latest);
|
||||
if (masterContentItem == null)
|
||||
return HttpNotFound();
|
||||
|
||||
var lp = contentItem.As<LocalizationPart>();
|
||||
|
||||
if (lp == null)
|
||||
var masterLocalizationPart = masterContentItem.As<LocalizationPart>();
|
||||
if (masterLocalizationPart == null)
|
||||
return HttpNotFound();
|
||||
|
||||
string contentItemCulture = _localizationService.GetContentCulture(contentItem);
|
||||
var localizations = _localizationService.GetLocalizations(lp, VersionOptions.Latest);
|
||||
// Check is current item stll exists, and redirect.
|
||||
var existingTranslation = _localizationService.GetLocalizedContentItem(masterContentItem, to);
|
||||
if (existingTranslation != null) {
|
||||
var existingTranslationMetadata = _contentManager.GetItemMetadata(existingTranslation);
|
||||
return RedirectToAction(
|
||||
Convert.ToString(existingTranslationMetadata.EditorRouteValues["action"]),
|
||||
existingTranslationMetadata.EditorRouteValues);
|
||||
}
|
||||
|
||||
var contentItemTranslation = _contentManager.New(masterContentItem.ContentType);
|
||||
|
||||
var contentItemTranslationPart = contentItemTranslation.As<LocalizationPart>();
|
||||
|
||||
contentItemTranslationPart.MasterContentItem = masterContentItem;
|
||||
|
||||
var content = _contentManager.BuildEditor(contentItemTranslation);
|
||||
|
||||
var siteCultures = _cultureManager.ListCultures();
|
||||
|
||||
var missingCultures = siteCultures.Where(s =>
|
||||
s != contentItemCulture
|
||||
&& !localizations.Any(l => s == l.Culture.Culture))
|
||||
.ToList();
|
||||
|
||||
string selectedCulture = null;
|
||||
|
||||
if (!String.IsNullOrEmpty(to)) {
|
||||
|
||||
if (!siteCultures.Any(c => String.Equals(c, to, StringComparison.OrdinalIgnoreCase)))
|
||||
return HttpNotFound();
|
||||
|
||||
var existingLocalization = String.Equals(contentItemCulture, to, StringComparison.OrdinalIgnoreCase)
|
||||
? lp
|
||||
: localizations.FirstOrDefault(l => string.Equals(l.Culture.Culture, to, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (existingLocalization != null) {
|
||||
var metadata = _contentManager.GetItemMetadata(existingLocalization);
|
||||
return RedirectToAction(Convert.ToString(metadata.EditorRouteValues["action"]), metadata.EditorRouteValues);
|
||||
}
|
||||
|
||||
selectedCulture = missingCultures.SingleOrDefault(s => string.Equals(s, to, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
if (lp.Culture != null)
|
||||
lp.Culture.Culture = null;
|
||||
var model = new AddLocalizationViewModel {
|
||||
Id = id,
|
||||
SelectedCulture = selectedCulture,
|
||||
MissingCultures = missingCultures,
|
||||
Content = _contentManager.BuildEditor(contentItem)
|
||||
};
|
||||
|
||||
// Cancel transaction so that the LocalizationPart is not modified.
|
||||
Services.TransactionManager.Cancel();
|
||||
|
||||
return View(model);
|
||||
return View(content);
|
||||
}
|
||||
|
||||
[HttpPost, ActionName("Translate")]
|
||||
@@ -107,64 +81,47 @@ namespace Orchard.Localization.Controllers {
|
||||
}
|
||||
|
||||
public ActionResult TranslatePOST(int id, Action<ContentItem> conditionallyPublish) {
|
||||
var contentItem = _contentManager.Get(id, VersionOptions.Latest);
|
||||
var originalLp = contentItem.As<LocalizationPart>();
|
||||
|
||||
if (contentItem == null)
|
||||
var masterContentItem = _contentManager.Get(id, VersionOptions.Latest);
|
||||
if (masterContentItem == null)
|
||||
return HttpNotFound();
|
||||
|
||||
var model = new AddLocalizationViewModel();
|
||||
TryUpdateModel(model);
|
||||
var masterLocalizationPart = masterContentItem.As<LocalizationPart>();
|
||||
if (masterLocalizationPart == null)
|
||||
return HttpNotFound();
|
||||
|
||||
ContentItem contentItemTranslation;
|
||||
var existingTranslation = _localizationService.GetLocalizedContentItem(contentItem, model.SelectedCulture);
|
||||
var model = new EditLocalizationViewModel();
|
||||
TryUpdateModel(model, "Localization");
|
||||
|
||||
var existingTranslation = _localizationService.GetLocalizedContentItem(masterContentItem, model.SelectedCulture);
|
||||
if (existingTranslation != null) {
|
||||
// edit existing
|
||||
contentItemTranslation = _contentManager.Get(existingTranslation.ContentItem.Id, VersionOptions.DraftRequired);
|
||||
} else {
|
||||
// create
|
||||
contentItemTranslation = _contentManager.New(contentItem.ContentType);
|
||||
|
||||
var translationLp = contentItemTranslation.As<LocalizationPart>();
|
||||
|
||||
translationLp.MasterContentItem = originalLp.MasterContentItem ?? contentItem;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(model.SelectedCulture))
|
||||
{
|
||||
translationLp.Culture = _cultureManager.GetCultureByName(model.SelectedCulture);
|
||||
}
|
||||
|
||||
_contentManager.Create(contentItemTranslation, VersionOptions.Draft);
|
||||
var existingTranslationMetadata = _contentManager.GetItemMetadata(existingTranslation);
|
||||
return RedirectToAction(
|
||||
Convert.ToString(existingTranslationMetadata.EditorRouteValues["action"]),
|
||||
existingTranslationMetadata.EditorRouteValues);
|
||||
}
|
||||
|
||||
model.Content = _contentManager.UpdateEditor(contentItemTranslation, this);
|
||||
var contentItemTranslation = _contentManager.New(masterContentItem.ContentType);
|
||||
|
||||
var contentItemTranslationPart = contentItemTranslation.As<LocalizationPart>();
|
||||
|
||||
contentItemTranslationPart.MasterContentItem = masterContentItem;
|
||||
|
||||
_contentManager.Create(contentItemTranslation, VersionOptions.Draft);
|
||||
|
||||
var content = _contentManager.UpdateEditor(contentItemTranslation, this);
|
||||
|
||||
if (!ModelState.IsValid) {
|
||||
Services.TransactionManager.Cancel();
|
||||
model.MissingCultures = _cultureManager.ListCultures().Where(s => s != _localizationService.GetContentCulture(contentItem) && s != _cultureManager.GetSiteCulture());
|
||||
|
||||
var culture = originalLp.Culture;
|
||||
|
||||
if (culture != null) {
|
||||
culture.Culture = null;
|
||||
}
|
||||
model.Content = _contentManager.BuildEditor(contentItem);
|
||||
return View(model);
|
||||
return View(content);
|
||||
}
|
||||
|
||||
if (existingTranslation != null) {
|
||||
Services.Notifier.Information(T("Edited content item translation."));
|
||||
}
|
||||
else {
|
||||
conditionallyPublish(contentItemTranslation);
|
||||
conditionallyPublish(contentItemTranslation);
|
||||
|
||||
Services.Notifier.Information(T("Created content item translation."));
|
||||
}
|
||||
Services.Notifier.Information(T("Created content item translation."));
|
||||
|
||||
var metadata = _contentManager.GetItemMetadata(model.Content.ContentItem);
|
||||
|
||||
//todo: (heskew) if null, redirect to somewhere better than nowhere
|
||||
return metadata.EditorRouteValues == null ? null : RedirectToRoute(metadata.EditorRouteValues);
|
||||
var metadata = _contentManager.GetItemMetadata(contentItemTranslation);
|
||||
return RedirectToAction(Convert.ToString(metadata.EditorRouteValues["action"]), metadata.EditorRouteValues);
|
||||
}
|
||||
|
||||
bool IUpdateModel.TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) {
|
||||
|
@@ -39,10 +39,33 @@ namespace Orchard.Localization.Drivers {
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(LocalizationPart part, dynamic shapeHelper) {
|
||||
var localizations = GetEditorLocalizations(part).ToList();
|
||||
List<LocalizationPart> localizations = GetEditorLocalizations(part).ToList();
|
||||
|
||||
var siteCultures = _cultureManager.ListCultures().ToList();
|
||||
|
||||
List<string> missingCultures;
|
||||
|
||||
if (part.MasterContentItem != null) {
|
||||
var localizationPart = part.MasterContentItem.As<LocalizationPart>();
|
||||
missingCultures =
|
||||
siteCultures.Where(s => GetEditorLocalizations(localizationPart).All(l => l.Culture.Culture != s))
|
||||
.ToList();
|
||||
|
||||
missingCultures.Remove(localizationPart.Culture.Culture);
|
||||
}
|
||||
else {
|
||||
missingCultures =
|
||||
siteCultures.Where(s => GetEditorLocalizations(part).All(l => l.Culture.Culture != s))
|
||||
.ToList();
|
||||
|
||||
if (part.Culture != null)
|
||||
missingCultures.Remove(part.Culture.Culture);
|
||||
}
|
||||
|
||||
var model = new EditLocalizationViewModel {
|
||||
SelectedCulture = GetCulture(part),
|
||||
SiteCultures = _cultureManager.ListCultures().Where(s => !localizations.Any(l => l.Culture.Culture == s)).ToList(),
|
||||
SiteCultures = siteCultures,
|
||||
MissingCultures = missingCultures,
|
||||
ContentItem = part,
|
||||
MasterContentItem = part.MasterContentItem,
|
||||
ContentLocalizations = new ContentLocalizationsViewModel(part) { Localizations = localizations }
|
||||
@@ -84,7 +107,7 @@ namespace Orchard.Localization.Drivers {
|
||||
return c;
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
|
||||
protected override void Importing(LocalizationPart part, ContentManagement.Handlers.ImportContentContext context) {
|
||||
var masterContentItem = context.Attribute(part.PartDefinition.Name, "MasterContentItem");
|
||||
if (masterContentItem != null) {
|
||||
|
@@ -98,7 +98,6 @@
|
||||
<Compile Include="Services\LocalizationService.cs" />
|
||||
<Compile Include="Services\TransliterationService.cs" />
|
||||
<Compile Include="Events\TransliterationSlugEventHandler.cs" />
|
||||
<Compile Include="ViewModels\AddLocalizationViewModel.cs" />
|
||||
<Compile Include="ViewModels\ContentLocalizationsViewModel.cs" />
|
||||
<Compile Include="ViewModels\EditLocalizationViewModel.cs" />
|
||||
<Compile Include="ViewModels\CreateTransliterationViewModel.cs" />
|
||||
@@ -117,9 +116,6 @@
|
||||
<ItemGroup>
|
||||
<Content Include="Views\Admin\Translate.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Views\CultureSelection.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Views\EditorTemplates\Parts\Localization.ContentTranslations.Edit.cshtml" />
|
||||
</ItemGroup>
|
||||
|
@@ -1,13 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Orchard.ContentManagement;
|
||||
|
||||
namespace Orchard.Localization.ViewModels {
|
||||
public class AddLocalizationViewModel {
|
||||
public int Id { get; set; }
|
||||
[Required]
|
||||
public string SelectedCulture { get; set; }
|
||||
public IEnumerable<string> MissingCultures { get; set; }
|
||||
public IContent Content { get; set; }
|
||||
}
|
||||
}
|
@@ -5,6 +5,7 @@ namespace Orchard.Localization.ViewModels {
|
||||
public class EditLocalizationViewModel {
|
||||
public string SelectedCulture { get; set; }
|
||||
public IEnumerable<string> SiteCultures { get; set; }
|
||||
public IEnumerable<string> MissingCultures { get; set; }
|
||||
public IContent ContentItem { get; set; }
|
||||
public IContent MasterContentItem { get; set; }
|
||||
public ContentLocalizationsViewModel ContentLocalizations { get; set; }
|
||||
|
@@ -1,54 +1,8 @@
|
||||
@model AddLocalizationViewModel
|
||||
@using Orchard.Localization.ViewModels;
|
||||
@{
|
||||
dynamic content = Model.Content;
|
||||
content.Zones.Content.Add(New.Partial(TemplateName: "CultureSelection", Model: Model), "0");
|
||||
|
||||
Layout.Title = T("Translate Content").ToString();
|
||||
}
|
||||
|
||||
@using (Html.BeginFormAntiForgeryPost()) {
|
||||
@Html.ValidationSummary()
|
||||
@Display(Model.Content)
|
||||
}
|
||||
@using (Script.Foot()) {
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
// grab the slug input
|
||||
var slug = $("#Autoroute_CurrentUrl");
|
||||
if (slug) {
|
||||
// grab the current culture
|
||||
var culture = $("#SelectedCulture");
|
||||
var currentCulture = culture.val();
|
||||
// when the culture is changed update the slug
|
||||
culture.change(function () {
|
||||
var slugValue = slug.val();
|
||||
var newCulture = $(this).val();
|
||||
if (slugValue && slugValue.match(currentCulture + "$")) {
|
||||
slug.val(slugValue.replace(new RegExp(currentCulture + "$", "i"), newCulture));
|
||||
currentCulture = newCulture;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var culture = $("#SelectedCulture");
|
||||
culture.change(function () {
|
||||
var optionDirectionality = $("option:selected", this).attr("data-content-dir");
|
||||
var contentZone = $(".zone-content");
|
||||
if (contentZone.hasClass(optionDirectionality))
|
||||
return;
|
||||
|
||||
var oldClass = optionDirectionality === "ltr" ? "rtl" : "";
|
||||
|
||||
contentZone.removeClass("content-" + oldClass);
|
||||
contentZone.addClass("content-" + optionDirectionality);
|
||||
|
||||
$(document).trigger("localization.ui.directionalitychanged", optionDirectionality);
|
||||
});
|
||||
})(jQuery);
|
||||
//]]>
|
||||
</script>
|
||||
@Display(Model)
|
||||
}
|
@@ -1,31 +0,0 @@
|
||||
@using System.Globalization
|
||||
@using System.Text
|
||||
@model Orchard.Localization.ViewModels.AddLocalizationViewModel
|
||||
@{
|
||||
Style.Require("LocalizationAdmin");
|
||||
}
|
||||
<fieldset class="localization culture-selection">
|
||||
<label for="SelectedCulture">@T("Content Localization")</label>
|
||||
<div>
|
||||
@T("This is the <em>{0}</em> variation of {1}",
|
||||
BuildSelectedCultureList(Html.FieldIdFor(m => m.SelectedCulture), Html.FieldNameFor(m => m.SelectedCulture), Model.MissingCultures, Model.SelectedCulture),
|
||||
Html.ItemEditLink(Model.Content))
|
||||
</div>
|
||||
</fieldset>
|
||||
@functions{
|
||||
private string BuildSelectedCultureList(string id, string name, IEnumerable<string> siteCultures, string culture) {
|
||||
TagBuilder selectTag = new TagBuilder("select");
|
||||
selectTag.Attributes["id"] = id;
|
||||
selectTag.Attributes["name"] = name;
|
||||
|
||||
foreach (var siteCulture in siteCultures) {
|
||||
TagBuilder optionTag = new TagBuilder("option");
|
||||
optionTag.Attributes["data-content-dir"] = CultureInfo.GetCultureInfo(siteCulture).TextInfo.IsRightToLeft ? "rtl" : "ltr";
|
||||
optionTag.Attributes["value"] = siteCulture;
|
||||
optionTag.SetInnerText(siteCulture);
|
||||
selectTag.InnerHtml += optionTag.ToString();
|
||||
}
|
||||
|
||||
return selectTag.ToString();
|
||||
}
|
||||
}
|
@@ -1,61 +1,66 @@
|
||||
@model Orchard.Localization.ViewModels.EditLocalizationViewModel
|
||||
@using System.Globalization
|
||||
@using System.Linq;
|
||||
@{
|
||||
Style.Require("LocalizationAdmin");
|
||||
var siteCultures = Model.SiteCultures.ToList();
|
||||
}
|
||||
<fieldset class="localization culture-selection">
|
||||
@if (Model.ContentItem.ContentItem.Id == 0 && Model.SelectedCulture == null && Model.ContentLocalizations.Localizations.Count() == 0) {
|
||||
/* If this is a new item */
|
||||
<fieldset class="localization culture-selection">
|
||||
<label for="SelectedCulture">@T("Content Localization")</label>
|
||||
<div>
|
||||
<label for="@Html.FieldIdFor(m => m.SelectedCulture)">@T("Content Localization")</label>
|
||||
<div>
|
||||
@*Brand new content item*@
|
||||
@if (Model.ContentItem.ContentItem.Id == 0) {
|
||||
if (Model.MasterContentItem == null) {
|
||||
@T("This is the <em>{0}</em> variation of the content",
|
||||
BuildSelectedCultureList(
|
||||
Html.FieldIdFor(m => m.SelectedCulture),
|
||||
Html.FieldNameFor(m => m.SelectedCulture),
|
||||
siteCultures,
|
||||
Model.SelectedCulture))
|
||||
</div>
|
||||
</fieldset>
|
||||
}
|
||||
|
||||
@if (Model.ContentItem.ContentItem.Id > 0 && Model.SelectedCulture != null && Model.ContentLocalizations.Localizations.Count() == 0) {
|
||||
<fieldset class="culture-selected">
|
||||
<label for="SelectedCulture">@T("Content Localization")</label>
|
||||
<div>
|
||||
@T("This is the <em>{0}</em> variation of content.",
|
||||
Html.Encode(Model.SelectedCulture))
|
||||
</div>
|
||||
@Html.Hidden("SelectedCulture", Model.SelectedCulture)
|
||||
</fieldset>
|
||||
}
|
||||
|
||||
@if (Model.ContentItem.ContentItem.Id > 0 && Model.SelectedCulture != null && Model.ContentLocalizations.Localizations.Count() > 0) {
|
||||
<fieldset class="culture-selected">
|
||||
<label for="SelectedCulture">@T("Content Localization")</label>
|
||||
<div>
|
||||
@T("This is the <em>{0}</em> variation of {1}.",
|
||||
Html.Encode(Model.SelectedCulture),
|
||||
Html.ItemEditLink(Model.MasterContentItem ?? Model.ContentItem))
|
||||
</div>
|
||||
@Html.Hidden("SelectedCulture", Model.SelectedCulture)
|
||||
</fieldset>
|
||||
if (Model.ContentLocalizations.Localizations.Count() > 0) {
|
||||
<dl class="content-localization">
|
||||
<dt>@T("Other translations:")</dt>
|
||||
<dd class="content-localizations">
|
||||
@Html.UnorderedList(Model.ContentLocalizations.Localizations, (c, i) => Html.ItemEditLink(c.Culture.Culture, c), "localizations")
|
||||
</dd>
|
||||
</dl>
|
||||
BuildSelectedCultureList(
|
||||
Html.FieldIdFor(m => m.SelectedCulture),
|
||||
Html.FieldNameFor(m => m.SelectedCulture),
|
||||
Model.SiteCultures,
|
||||
Model.SelectedCulture))
|
||||
}
|
||||
else {
|
||||
@T("This is the <em>{0}</em> variation of {1}",
|
||||
BuildSelectedCultureList(
|
||||
Html.FieldIdFor(m => m.SelectedCulture),
|
||||
Html.FieldNameFor(m => m.SelectedCulture),
|
||||
Model.MissingCultures,
|
||||
Model.SelectedCulture),
|
||||
Html.ItemEditLink(Model.MasterContentItem))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@if (Model.SelectedCulture != null && !siteCultures.All(c => c == Model.SelectedCulture || Model.ContentLocalizations.Localizations.Any(l => c == l.Culture.Culture))) {
|
||||
<div class="add-localization">@Html.ActionLink(T("+ New translation").Text, "Translate", "Admin", new { area = "Orchard.Localization", id = Model.ContentItem.Id }, null)</div>
|
||||
}
|
||||
@if (Model.ContentItem.ContentItem.Id > 0) {
|
||||
//if (Model.MasterContentItem == null) {
|
||||
@T("This is the <em>{0}</em> variation of the content",
|
||||
Html.Encode(Model.SelectedCulture))
|
||||
@*}
|
||||
else {
|
||||
@T("This is the <em>{0}</em> variation of {1}",
|
||||
Html.Encode(Model.SelectedCulture),
|
||||
Html.ItemEditLink(Model.MasterContentItem))
|
||||
}*@
|
||||
|
||||
if (Model.ContentLocalizations.Localizations.Any()) {
|
||||
<dl class="content-localization">
|
||||
<dt>@T("Other translations:")</dt>
|
||||
<dd class="content-localizations">
|
||||
@Html.UnorderedList(Model.ContentLocalizations.Localizations, (c, i) =>
|
||||
Html.ItemEditLink(c.Culture.Culture, c), "localizations")
|
||||
</dd>
|
||||
</dl>
|
||||
}
|
||||
|
||||
if (Model.MissingCultures.Any()) {
|
||||
var contentItemId = Model.MasterContentItem != null ? Model.MasterContentItem.Id : Model.ContentItem.Id;
|
||||
|
||||
<div class="add-localization">@Html.ActionLink(T("+ New translation").Text, "Translate", "Admin", new { area = "Orchard.Localization", id = contentItemId }, null)</div>
|
||||
}
|
||||
|
||||
@Html.Hidden(Html.FieldNameFor(m => m.SelectedCulture), Model.SelectedCulture)
|
||||
}
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
|
||||
|
||||
@functions{
|
||||
private string BuildSelectedCultureList(string id, string name, IEnumerable<string> siteCultures, string culture) {
|
||||
TagBuilder selectTag = new TagBuilder("select");
|
||||
@@ -65,7 +70,10 @@
|
||||
foreach (var siteCulture in siteCultures) {
|
||||
TagBuilder optionTag = new TagBuilder("option");
|
||||
optionTag.Attributes["data-content-dir"] = CultureInfo.GetCultureInfo(siteCulture).TextInfo.IsRightToLeft ? "rtl" : "ltr";
|
||||
//optionTag.Attributes["value"] = siteCulture;
|
||||
|
||||
if (siteCulture == culture) {
|
||||
optionTag.Attributes["selected"] = "selected";
|
||||
}
|
||||
optionTag.SetInnerText(siteCulture);
|
||||
selectTag.InnerHtml += optionTag.ToString();
|
||||
}
|
||||
|
Reference in New Issue
Block a user