Merge branch origin/dev-v8 into dev-v8
This commit is contained in:
@@ -23,6 +23,7 @@ namespace Umbraco.Web.Composing.CompositionRoots
|
||||
container.Register<TagMapperProfile>();
|
||||
container.Register<TemplateMapperProfile>();
|
||||
container.Register<UserMapperProfile>();
|
||||
container.Register<LanguageMapperProfile>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,6 +285,10 @@ namespace Umbraco.Web.Editors
|
||||
{
|
||||
"backOfficeAssetsApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl<BackOfficeAssetsController>(
|
||||
controller => controller.GetSupportedMomentLocales())
|
||||
},
|
||||
{
|
||||
"languageApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl<LanguageController>(
|
||||
controller => controller.GetAllLanguages())
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Web.Http;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Web.Models;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.WebApi;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
{
|
||||
@@ -12,6 +19,7 @@ namespace Umbraco.Web.Editors
|
||||
/// Backoffice controller supporting the dashboard for language administration.
|
||||
/// </summary>
|
||||
[PluginController("UmbracoApi")]
|
||||
[PrefixlessBodyModelValidator]
|
||||
public class LanguageController : UmbracoAuthorizedJsonController
|
||||
{
|
||||
/// <summary>
|
||||
@@ -19,10 +27,12 @@ namespace Umbraco.Web.Editors
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
public IEnumerable<Culture> GetAllCultures()
|
||||
public IDictionary<string, string> GetAllCultures()
|
||||
{
|
||||
return CultureInfo.GetCultures(CultureTypes.AllCultures)
|
||||
.Select(x => new Culture {IsoCode = x.Name, Name = x.DisplayName});
|
||||
return
|
||||
CultureInfo.GetCultures(CultureTypes.AllCultures)
|
||||
.Where(x => !x.Name.IsNullOrWhiteSpace())
|
||||
.OrderBy(x => x.DisplayName).ToDictionary(x => x.Name, x => x.DisplayName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -32,52 +42,125 @@ namespace Umbraco.Web.Editors
|
||||
[HttpGet]
|
||||
public IEnumerable<Language> GetAllLanguages()
|
||||
{
|
||||
var allLanguages = Services.LocalizationService.GetAllLanguages();
|
||||
var allLanguages = Services.LocalizationService.GetAllLanguages().OrderBy(x => x.Id).ToList();
|
||||
var langs = Mapper.Map<IEnumerable<Language>>(allLanguages).ToList();
|
||||
|
||||
return allLanguages.Select(x => new Language
|
||||
//if there's only one language, by default it is the default
|
||||
if (langs.Count == 1)
|
||||
{
|
||||
Id = x.Id,
|
||||
IsoCode = x.IsoCode,
|
||||
Name = x.CultureInfo.DisplayName,
|
||||
IsDefaultVariantLanguage = x.IsDefaultVariantLanguage,
|
||||
Mandatory = x.Mandatory
|
||||
});
|
||||
langs[0].IsDefaultVariantLanguage = true;
|
||||
langs[0].Mandatory = true;
|
||||
}
|
||||
else if (allLanguages.All(x => !x.IsDefaultVariantLanguage))
|
||||
{
|
||||
//if no language has the default flag, then the defaul language is the one with the lowest id
|
||||
langs[0].IsDefaultVariantLanguage = true;
|
||||
langs[0].Mandatory = true;
|
||||
}
|
||||
|
||||
return langs.OrderBy(x => x.Name);
|
||||
}
|
||||
|
||||
|
||||
[HttpGet]
|
||||
public Language GetLanguage(int id)
|
||||
{
|
||||
var lang = Services.LocalizationService.GetLanguageById(id);
|
||||
if (lang == null)
|
||||
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
|
||||
|
||||
var model = Mapper.Map<Language>(lang);
|
||||
|
||||
//if there's only one language, by default it is the default
|
||||
var allLangs = Services.LocalizationService.GetAllLanguages().OrderBy(x => x.Id).ToList();
|
||||
if (!lang.IsDefaultVariantLanguage)
|
||||
{
|
||||
if (allLangs.Count == 1)
|
||||
{
|
||||
model.IsDefaultVariantLanguage = true;
|
||||
model.Mandatory = true;
|
||||
}
|
||||
else if (allLangs.All(x => !x.IsDefaultVariantLanguage))
|
||||
{
|
||||
//if no language has the default flag, then the defaul language is the one with the lowest id
|
||||
model.IsDefaultVariantLanguage = allLangs[0].Id == lang.Id;
|
||||
model.Mandatory = allLangs[0].Id == lang.Id;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a language with a given ID
|
||||
/// </summary>
|
||||
[HttpDelete]
|
||||
[HttpPost]
|
||||
public void DeleteLanguage(int id)
|
||||
public IHttpActionResult DeleteLanguage(int id)
|
||||
{
|
||||
var language = Services.LocalizationService.GetLanguageById(id);
|
||||
if (language == null)
|
||||
if (language == null) return NotFound();
|
||||
|
||||
var totalLangs = Services.LocalizationService.GetAllLanguages().Count();
|
||||
|
||||
if (language.IsDefaultVariantLanguage || totalLangs == 1)
|
||||
{
|
||||
throw new EntityNotFoundException(id, $"Could not find language by id: '{id}'.");
|
||||
var message = $"Language '{language.IsoCode}' is currently set to 'default' or it is the only installed language and can not be deleted.";
|
||||
throw new HttpResponseException(Request.CreateNotificationValidationErrorResponse(message));
|
||||
}
|
||||
|
||||
Services.LocalizationService.Delete(language);
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves a bulk set of languages with default/mandatory settings and returns the full set of languages configured.
|
||||
/// Creates or saves a language
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
public IEnumerable<Language> SaveLanguages(IEnumerable<Language> languages)
|
||||
public Language SaveLanguage(Language language)
|
||||
{
|
||||
foreach (var l in languages)
|
||||
if (!ModelState.IsValid)
|
||||
throw new HttpResponseException(Request.CreateValidationErrorResponse(ModelState));
|
||||
|
||||
var found = Services.LocalizationService.GetLanguageByIsoCode(language.IsoCode);
|
||||
|
||||
if (found != null && language.Id != found.Id)
|
||||
{
|
||||
var language = Services.LocalizationService.GetLanguageByIsoCode(l.IsoCode);
|
||||
if (language == null)
|
||||
{
|
||||
language = new Core.Models.Language(l.IsoCode);
|
||||
}
|
||||
language.Mandatory = l.Mandatory;
|
||||
language.IsDefaultVariantLanguage = l.IsDefaultVariantLanguage;
|
||||
Services.LocalizationService.Save(language);
|
||||
//someone is trying to create a language that alraedy exist
|
||||
ModelState.AddModelError("IsoCode", "The language " + language.IsoCode + " already exists");
|
||||
throw new HttpResponseException(Request.CreateValidationErrorResponse(ModelState));
|
||||
}
|
||||
|
||||
return GetAllLanguages();
|
||||
if (found == null)
|
||||
{
|
||||
CultureInfo culture;
|
||||
try
|
||||
{
|
||||
culture = CultureInfo.GetCultureInfo(language.IsoCode);
|
||||
}
|
||||
catch (CultureNotFoundException)
|
||||
{
|
||||
ModelState.AddModelError("IsoCode", "No Culture found with name " + language.IsoCode);
|
||||
throw new HttpResponseException(Request.CreateValidationErrorResponse(ModelState));
|
||||
}
|
||||
|
||||
//create it
|
||||
var newLang = new Umbraco.Core.Models.Language(culture.Name)
|
||||
{
|
||||
CultureName = culture.DisplayName,
|
||||
IsDefaultVariantLanguage = language.IsDefaultVariantLanguage,
|
||||
Mandatory = language.Mandatory
|
||||
};
|
||||
Services.LocalizationService.Save(newLang);
|
||||
return Mapper.Map<Language>(newLang);
|
||||
}
|
||||
|
||||
found.Mandatory = language.Mandatory;
|
||||
found.IsDefaultVariantLanguage = language.IsDefaultVariantLanguage;
|
||||
Services.LocalizationService.Save(found);
|
||||
return Mapper.Map<Language>(found);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
28
src/Umbraco.Web/Models/ContentEditing/Language.cs
Normal file
28
src/Umbraco.Web/Models/ContentEditing/Language.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Umbraco.Web.Models.ContentEditing
|
||||
{
|
||||
[DataContract(Name = "language", Namespace = "")]
|
||||
public class Language
|
||||
{
|
||||
[DataMember(Name = "id")]
|
||||
public int Id { get; set; }
|
||||
|
||||
[DataMember(Name = "culture", IsRequired = true)]
|
||||
[Required(AllowEmptyStrings = false)]
|
||||
public string IsoCode { get; set; }
|
||||
|
||||
[DataMember(Name = "name")]
|
||||
[ReadOnly(true)]
|
||||
public string Name { get; set; }
|
||||
|
||||
[DataMember(Name = "isDefault")]
|
||||
public bool IsDefaultVariantLanguage { get; set; }
|
||||
|
||||
[DataMember(Name = "isMandatory")]
|
||||
public bool Mandatory { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace Umbraco.Web.Models
|
||||
{
|
||||
public class Culture
|
||||
{
|
||||
public string IsoCode { get; set; }
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
using System.Globalization;
|
||||
|
||||
namespace Umbraco.Web.Models
|
||||
{
|
||||
public class Language
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string IsoCode { get; set; }
|
||||
public string Name { get; set; }
|
||||
public bool IsDefaultVariantLanguage { get; set; }
|
||||
public bool Mandatory { get; set; }
|
||||
}
|
||||
}
|
||||
17
src/Umbraco.Web/Models/Mapping/LanguageMapperProfile.cs
Normal file
17
src/Umbraco.Web/Models/Mapping/LanguageMapperProfile.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System.Globalization;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
using Language = Umbraco.Web.Models.ContentEditing.Language;
|
||||
|
||||
namespace Umbraco.Web.Models.Mapping
|
||||
{
|
||||
internal class LanguageMapperProfile : Profile
|
||||
{
|
||||
public LanguageMapperProfile()
|
||||
{
|
||||
CreateMap<ILanguage, Language>()
|
||||
.ForMember(l => l.Name, expression => expression.MapFrom(x => x.CultureInfo.DisplayName));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,7 @@ namespace Umbraco.Web.Trees
|
||||
|
||||
//this will load in a custom UI instead of the dashboard for the root node
|
||||
root.RoutePath = string.Format("{0}/{1}/{2}", Constants.Applications.Settings, Constants.Trees.Languages, "overview");
|
||||
root.Icon = "icon-flag-alt";
|
||||
root.Icon = "icon-globe";
|
||||
root.HasChildren = false;
|
||||
root.MenuUrl = null;
|
||||
|
||||
|
||||
@@ -72,6 +72,9 @@
|
||||
<PackageReference Include="Examine" Version="1.0.0-beta024" />
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.7.2" />
|
||||
<PackageReference Include="LightInject" Version="5.1.2" />
|
||||
<PackageReference Include="Examine" Version="1.0.0-beta025" />
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.5.1" />
|
||||
<PackageReference Include="LightInject" Version="5.0.3" />
|
||||
<PackageReference Include="LightInject.Annotation" Version="1.1.0" />
|
||||
<PackageReference Include="LightInject.Mvc" Version="2.0.0" />
|
||||
<PackageReference Include="LightInject.Web" Version="2.0.0" />
|
||||
@@ -216,6 +219,7 @@
|
||||
<Compile Include="Models\BackOfficeTourStep.cs" />
|
||||
<Compile Include="Models\ContentEditing\AssignedContentPermissions.cs" />
|
||||
<Compile Include="Models\ContentEditing\AssignedUserGroupPermissions.cs" />
|
||||
<Compile Include="Models\ContentEditing\BackOfficePreview.cs" />
|
||||
<Compile Include="Models\ContentEditing\CodeFileDisplay.cs" />
|
||||
<Compile Include="Models\ContentEditing\ContentRedirectUrl.cs" />
|
||||
<Compile Include="Media\ImageUrlProviderCollectionBuilder.cs" />
|
||||
@@ -239,14 +243,14 @@
|
||||
<Compile Include="Models\ContentEditing\UserInvite.cs" />
|
||||
<Compile Include="Models\ContentEditing\UserProfile.cs" />
|
||||
<Compile Include="Models\ContentEditing\UserSave.cs" />
|
||||
<Compile Include="Models\Culture.cs" />
|
||||
<Compile Include="Models\Language.cs" />
|
||||
<Compile Include="Models\ContentEditing\Language.cs" />
|
||||
<Compile Include="Models\Mapping\ActionButtonsResolver.cs" />
|
||||
<Compile Include="Models\Mapping\AuditMapperProfile.cs" />
|
||||
<Compile Include="Models\Mapping\AutoMapperExtensions.cs" />
|
||||
<Compile Include="Models\Mapping\ContentChildOfListViewResolver.cs" />
|
||||
<Compile Include="Models\Mapping\ContentUrlResolver.cs" />
|
||||
<Compile Include="Models\Mapping\DefaultTemplateResolver.cs" />
|
||||
<Compile Include="Models\Mapping\LanguageMapperProfile.cs" />
|
||||
<Compile Include="Models\Mapping\MediaChildOfListViewResolver.cs" />
|
||||
<Compile Include="Models\Mapping\CodeFileMapperProfile.cs" />
|
||||
<Compile Include="Models\Mapping\ContentTreeNodeUrlResolver.cs" />
|
||||
|
||||
Reference in New Issue
Block a user