diff --git a/src/Web/Grand.Web.Store/Areas/Store/Views/Currency/List.cshtml b/src/Web/Grand.Web.Store/Areas/Store/Views/Currency/List.cshtml
index 5a658fb1f..0d5be7c31 100644
--- a/src/Web/Grand.Web.Store/Areas/Store/Views/Currency/List.cshtml
+++ b/src/Web/Grand.Web.Store/Areas/Store/Views/Currency/List.cshtml
@@ -1,4 +1,3 @@
-@inject AdminAreaSettings adminAreaSettings
@{
ViewBag.Title = Loc["Admin.Configuration.Currencies"];
Layout = Constants.LayoutStore;
@@ -41,15 +40,10 @@
display_kendoui_grid_error(e);
this.cancelChanges();
},
- pageSize: @(adminAreaSettings.DefaultGridPageSize),
serverPaging: false,
serverFiltering: false,
serverSorting: false
},
- pageable: {
- refresh: true,
- pageSizes: [@(adminAreaSettings.GridPageSizes)]
- },
scrollable: false,
columns: [
{
@@ -72,14 +66,6 @@
title: "@Loc["Admin.Configuration.Currencies.Fields.CurrencyCode"]",
width: 100
},
- {
- field: "Published",
- title: "@Loc["Admin.Configuration.Currencies.Fields.Published"]",
- width: 80,
- headerAttributes: { style: "text-align:center" },
- attributes: { style: "text-align:center" },
- template: '# if(Published) {# #} else {# #} #'
- },
{
field: "LimitedToStores",
title: "@Loc["Admin.Configuration.Currencies.Fields.LimitedToStores"]",
diff --git a/src/Web/Grand.Web.Store/Areas/Store/Views/Language/List.cshtml b/src/Web/Grand.Web.Store/Areas/Store/Views/Language/List.cshtml
new file mode 100644
index 000000000..4efb6c7ee
--- /dev/null
+++ b/src/Web/Grand.Web.Store/Areas/Store/Views/Language/List.cshtml
@@ -0,0 +1,207 @@
+@{
+ ViewBag.Title = Loc["Admin.Configuration.Languages"];
+ Layout = Constants.LayoutStore;
+}
+
+
+
+
diff --git a/src/Web/Grand.Web.Store/Controllers/LanguageController.cs b/src/Web/Grand.Web.Store/Controllers/LanguageController.cs
new file mode 100644
index 000000000..6e3cab67b
--- /dev/null
+++ b/src/Web/Grand.Web.Store/Controllers/LanguageController.cs
@@ -0,0 +1,157 @@
+using Grand.Business.Core.Interfaces.Common.Localization;
+using Grand.Business.Core.Interfaces.Common.Stores;
+using Grand.Domain.Permissions;
+using Grand.Infrastructure;
+using Grand.Web.Common.DataSource;
+using Grand.Web.Common.Security.Authorization;
+using Grand.Web.Store.Models;
+using Microsoft.AspNetCore.Mvc;
+
+namespace Grand.Web.Store.Controllers;
+
+[PermissionAuthorize(PermissionSystemName.Languages)]
+public class LanguageController(
+ ILanguageService languageService,
+ ITranslationService translationService,
+ IStoreService storeService,
+ IContextAccessor contextAccessor) : BaseStoreController
+{
+ private string CurrentStoreId => contextAccessor.WorkContext.CurrentCustomer.StaffStoreId;
+
+ public IActionResult Index()
+ {
+ return RedirectToAction("List");
+ }
+
+ [PermissionAuthorizeAction(PermissionActionName.List)]
+ public IActionResult List()
+ {
+ return View();
+ }
+
+ [HttpPost]
+ [PermissionAuthorizeAction(PermissionActionName.List)]
+ public async Task ListData()
+ {
+ var storeId = CurrentStoreId;
+
+ var store = await storeService.GetStoreById(storeId);
+ var defaultLanguageId = store?.DefaultLanguageId;
+
+ var languages = await languageService.GetAllLanguages(showHidden: false);
+
+ var items = languages
+ .Select(l => new StoreLanguageModel {
+ Id = l.Id,
+ Name = l.Name,
+ LanguageCulture = l.LanguageCulture,
+ FlagImageFileName = l.FlagImageFileName,
+ Published = l.Published,
+ DisplayOrder = l.DisplayOrder,
+ LimitedToStores = l.LimitedToStores,
+ IsAssignedToCurrentStore = !l.LimitedToStores || l.Stores.Contains(storeId),
+ IsDefaultStoreLanguage = l.Id == defaultLanguageId,
+ CanManage = l.LimitedToStores
+ })
+ .ToList();
+
+ var gridModel = new DataSourceResult {
+ Data = items,
+ Total = items.Count
+ };
+
+ return Json(gridModel);
+ }
+
+ [HttpPost]
+ [PermissionAuthorizeAction(PermissionActionName.Edit)]
+ public async Task AssignStore(string id)
+ {
+ var language = await languageService.GetLanguageById(id);
+ if (language == null)
+ return Json(new { success = false, message = translationService.GetResource("Admin.Configuration.Languages.NotFound") });
+
+ if (!language.LimitedToStores)
+ return Json(new { success = false, message = translationService.GetResource("Admin.Configuration.Languages.CannotModifyGlobal") });
+
+ var storeId = CurrentStoreId;
+ if (!language.Stores.Contains(storeId))
+ {
+ language.Stores.Add(storeId);
+ await languageService.UpdateLanguage(language);
+ }
+
+ return Json(new { success = true });
+ }
+
+ [HttpPost]
+ [PermissionAuthorizeAction(PermissionActionName.Edit)]
+ public async Task UnassignStore(string id)
+ {
+ var language = await languageService.GetLanguageById(id);
+ if (language == null)
+ return Json(new { success = false, message = translationService.GetResource("Admin.Configuration.Languages.NotFound") });
+
+ if (!language.LimitedToStores)
+ return Json(new { success = false, message = translationService.GetResource("Admin.Configuration.Languages.CannotModifyGlobal") });
+
+ var storeId = CurrentStoreId;
+
+ var store = await storeService.GetStoreById(storeId);
+ if (store?.DefaultLanguageId == language.Id)
+ return Json(new { success = false, message = translationService.GetResource("Admin.Configuration.Languages.CantUnassignDefault") });
+
+ if (language.Stores.Remove(storeId))
+ await languageService.UpdateLanguage(language);
+
+ return Json(new { success = true });
+ }
+
+ [HttpPost]
+ [PermissionAuthorizeAction(PermissionActionName.Edit)]
+ public async Task SetDefaultLanguage(string id)
+ {
+ var language = await languageService.GetLanguageById(id);
+ if (language == null)
+ return Json(new { success = false, message = translationService.GetResource("Admin.Configuration.Languages.NotFound") });
+
+ if (!language.Published)
+ return Json(new { success = false, message = translationService.GetResource("Admin.Configuration.Languages.NotPublished") });
+
+ var storeId = CurrentStoreId;
+
+ if (language.LimitedToStores && !language.Stores.Contains(storeId))
+ return Json(new { success = false, message = translationService.GetResource("Admin.Configuration.Languages.NotAssignedToStore") });
+
+ var store = await storeService.GetStoreById(storeId);
+ if (store == null)
+ return Json(new { success = false, message = translationService.GetResource("Admin.Configuration.Stores.NotFound") });
+
+ store.DefaultLanguageId = language.Id;
+ await storeService.UpdateStore(store);
+
+ return Json(new { success = true });
+ }
+
+ [HttpPost]
+ [PermissionAuthorizeAction(PermissionActionName.Edit)]
+ public async Task UnsetDefaultLanguage(string id)
+ {
+ var language = await languageService.GetLanguageById(id);
+ if (language == null)
+ return Json(new { success = false, message = translationService.GetResource("Admin.Configuration.Languages.NotFound") });
+
+ var storeId = CurrentStoreId;
+ var store = await storeService.GetStoreById(storeId);
+ if (store == null)
+ return Json(new { success = false, message = translationService.GetResource("Admin.Configuration.Stores.NotFound") });
+
+ if (store.DefaultLanguageId != language.Id)
+ return Json(new { success = false, message = translationService.GetResource("Admin.Configuration.Languages.NotDefaultLanguage") });
+
+ store.DefaultLanguageId = string.Empty;
+ await storeService.UpdateStore(store);
+
+ return Json(new { success = true });
+ }
+}
diff --git a/src/Web/Grand.Web.Store/Models/StoreLanguageModel.cs b/src/Web/Grand.Web.Store/Models/StoreLanguageModel.cs
new file mode 100644
index 000000000..c023c7b30
--- /dev/null
+++ b/src/Web/Grand.Web.Store/Models/StoreLanguageModel.cs
@@ -0,0 +1,16 @@
+namespace Grand.Web.Store.Models;
+
+public class StoreLanguageModel
+{
+ public string Id { get; set; }
+ public string Name { get; set; }
+ public string LanguageCulture { get; set; }
+ public string FlagImageFileName { get; set; }
+ public bool Published { get; set; }
+ public int DisplayOrder { get; set; }
+ public bool LimitedToStores { get; set; }
+ public bool IsAssignedToCurrentStore { get; set; }
+ public bool IsPrimaryStoreLanguage { get; set; }
+ public bool IsDefaultStoreLanguage { get; set; }
+ public bool CanManage { get; set; }
+}
diff --git a/src/Web/Grand.Web/App_Data/Resources/DefaultLanguage.xml b/src/Web/Grand.Web/App_Data/Resources/DefaultLanguage.xml
index 94f18f262..f6b3c4e7a 100644
Binary files a/src/Web/Grand.Web/App_Data/Resources/DefaultLanguage.xml and b/src/Web/Grand.Web/App_Data/Resources/DefaultLanguage.xml differ