diff --git a/src/Umbraco.Web/Editors/LanguageController.cs b/src/Umbraco.Web/Editors/LanguageController.cs
new file mode 100644
index 0000000000..20932f6bf9
--- /dev/null
+++ b/src/Umbraco.Web/Editors/LanguageController.cs
@@ -0,0 +1,83 @@
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Web.Http;
+using Umbraco.Core.Persistence;
+using Umbraco.Web.Models;
+using Umbraco.Web.Mvc;
+
+namespace Umbraco.Web.Editors
+{
+ ///
+ /// Backoffice controller supporting the dashboard for language administration.
+ ///
+ [PluginController("UmbracoApi")]
+ public class LanguageController : UmbracoAuthorizedJsonController
+ {
+ ///
+ /// Returns all cultures available for creating languages.
+ ///
+ ///
+ [HttpGet]
+ public IEnumerable GetAllCultures()
+ {
+ return CultureInfo.GetCultures(CultureTypes.AllCultures)
+ .Select(x => new Culture {IsoCode = x.Name, Name = x.DisplayName});
+ }
+
+ ///
+ /// Returns all currently configured languages.
+ ///
+ ///
+ [HttpGet]
+ public IEnumerable GetAllLanguages()
+ {
+ var allLanguages = Services.LocalizationService.GetAllLanguages();
+
+ return allLanguages.Select(x => new Language
+ {
+ Id = x.Id,
+ IsoCode = x.IsoCode,
+ Name = x.CultureInfo.DisplayName,
+ IsDefaultVariantLanguage = x.IsDefaultVariantLanguage,
+ Mandatory = x.Mandatory
+ });
+ }
+
+ ///
+ /// Deletes a language with a given ID
+ ///
+ [HttpDelete]
+ [HttpPost]
+ public void DeleteLanguage(int id)
+ {
+ var language = Services.LocalizationService.GetLanguageById(id);
+ if (language == null)
+ {
+ throw new EntityNotFoundException(id, $"Could not find language by id: '{id}'.");
+ }
+ Services.LocalizationService.Delete(language);
+ }
+
+ ///
+ /// Saves a bulk set of languages with default/mandatory settings and returns the full set of languages configured.
+ ///
+ [HttpPost]
+ public IEnumerable SaveLanguages(IEnumerable languages)
+ {
+ foreach (var l in languages)
+ {
+ 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);
+ }
+
+ return GetAllLanguages();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Models/Culture.cs b/src/Umbraco.Web/Models/Culture.cs
new file mode 100644
index 0000000000..16ebc6bc2a
--- /dev/null
+++ b/src/Umbraco.Web/Models/Culture.cs
@@ -0,0 +1,8 @@
+namespace Umbraco.Web.Models
+{
+ public class Culture
+ {
+ public string IsoCode { get; set; }
+ public string Name { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Models/Language.cs b/src/Umbraco.Web/Models/Language.cs
new file mode 100644
index 0000000000..4fdf418eef
--- /dev/null
+++ b/src/Umbraco.Web/Models/Language.cs
@@ -0,0 +1,13 @@
+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; }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index 20358b3d4d..5551354d56 100644
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -136,6 +136,7 @@
+
@@ -221,6 +222,8 @@
+
+