diff --git a/src/Umbraco.Web.UI.Client/src/views/languages/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/languages/edit.controller.js index bc5c421b7b..79972725fc 100644 --- a/src/Umbraco.Web.UI.Client/src/views/languages/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/languages/edit.controller.js @@ -112,6 +112,11 @@ if (formHelper.submitForm({ scope: $scope })) { vm.page.saveButtonState = "busy"; + // Handle selection of no fall-back language (should pass null) + if (!vm.language.fallbackLanguage.id) { + vm.language.fallbackLanguage = null; + } + // We need to attach the ISO code to the fall-back language to pass // server-side validation. if (vm.language.fallbackLanguage) { diff --git a/src/Umbraco.Web/Editors/LanguageController.cs b/src/Umbraco.Web/Editors/LanguageController.cs index 418c8401ff..76a40ac329 100644 --- a/src/Umbraco.Web/Editors/LanguageController.cs +++ b/src/Umbraco.Web/Editors/LanguageController.cs @@ -148,6 +148,13 @@ namespace Umbraco.Web.Editors found.Mandatory = language.Mandatory; found.IsDefaultVariantLanguage = language.IsDefaultVariantLanguage; AssociateFallbackLanguage(language, found); + + if (UpdatedFallbackLanguageCreatesCircularPath(found)) + { + ModelState.AddModelError("FallbackLanguage", "The selected fall back language '" + found.FallbackLanguage.CultureName + "' would create a circular path."); + throw new HttpResponseException(Request.CreateValidationErrorResponse(ModelState)); + } + Services.LocalizationService.Save(found); return Mapper.Map(found); } @@ -156,6 +163,7 @@ namespace Umbraco.Web.Editors { if (submittedLanguage.FallbackLanguage == null) { + languageToCreateOrUpdate.FallbackLanguage = null; return; } @@ -166,5 +174,27 @@ namespace Umbraco.Web.Editors CultureName = fallbackLanguageCulture.DisplayName }; } + + private bool UpdatedFallbackLanguageCreatesCircularPath(ILanguage language) + { + if (language.FallbackLanguage == null) + { + return false; + } + + var languages = Services.LocalizationService.GetAllLanguages().ToArray(); + var fallbackLanguage = language.FallbackLanguage; + while (fallbackLanguage != null) + { + if (fallbackLanguage.Id == language.Id) + { + return true; + } + + fallbackLanguage = languages.Single(x => x.Id == fallbackLanguage.Id).FallbackLanguage; + } + + return false; + } } }