Skip to content

Commit 034c388

Browse files
authored
Localized content (#781)
* #775 support content localization
1 parent 3bf6bf6 commit 034c388

File tree

50 files changed

+5636
-54
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+5636
-54
lines changed

src/Modules/SimplCommerce.Module.Catalog/Areas/Catalog/Components/CategoryMenuViewComponent.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,19 @@
55
using SimplCommerce.Infrastructure.Web;
66
using SimplCommerce.Module.Catalog.Areas.Catalog.ViewModels;
77
using SimplCommerce.Module.Catalog.Models;
8+
using SimplCommerce.Module.Core.Services;
89

910
namespace SimplCommerce.Module.Catalog.Areas.Catalog.Components
1011
{
1112
public class CategoryMenuViewComponent : ViewComponent
1213
{
1314
private readonly IRepository<Category> _categoryRepository;
15+
private readonly IContentLocalizationService _contentLocalizationService;
1416

15-
public CategoryMenuViewComponent(IRepository<Category> categoryRepository)
17+
public CategoryMenuViewComponent(IRepository<Category> categoryRepository, IContentLocalizationService contentLocalizationService)
1618
{
1719
_categoryRepository = categoryRepository;
20+
_contentLocalizationService = contentLocalizationService;
1821
}
1922

2023
public IViewComponentResult Invoke()
@@ -37,7 +40,7 @@ private CategoryMenuItem Map(Category category)
3740
var categoryMenuItem = new CategoryMenuItem
3841
{
3942
Id = category.Id,
40-
Name = category.Name,
43+
Name = _contentLocalizationService.GetLocalizedProperty(category, nameof(category.Name), category.Name),
4144
Slug = category.Slug
4245
};
4346

src/Modules/SimplCommerce.Module.Catalog/Areas/Catalog/Components/ProductWidgetViewComponent.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,17 @@ public class ProductWidgetViewComponent : ViewComponent
1717
private readonly IRepository<Product> _productRepository;
1818
private readonly IMediaService _mediaService;
1919
private readonly IProductPricingService _productPricingService;
20+
private readonly IContentLocalizationService _contentLocalizationService;
2021

21-
public ProductWidgetViewComponent(IRepository<Product> productRepository, IMediaService mediaService, IProductPricingService productPricingService)
22+
public ProductWidgetViewComponent(IRepository<Product> productRepository,
23+
IMediaService mediaService,
24+
IProductPricingService productPricingService,
25+
IContentLocalizationService contentLocalizationService)
2226
{
2327
_productRepository = productRepository;
2428
_mediaService = mediaService;
2529
_productPricingService = productPricingService;
30+
_contentLocalizationService = contentLocalizationService;
2631
}
2732

2833
public IViewComponentResult Invoke(WidgetInstanceViewModel widgetInstance)
@@ -55,6 +60,7 @@ public IViewComponentResult Invoke(WidgetInstanceViewModel widgetInstance)
5560

5661
foreach (var product in model.Products)
5762
{
63+
product.Name = _contentLocalizationService.GetLocalizedProperty(nameof(Product), product.Id, nameof(product.Name), product.Name);
5864
product.ThumbnailUrl = _mediaService.GetThumbnailUrl(product.ThumbnailImage);
5965
product.CalculatedProductPrice = _productPricingService.CalculateProductPrice(product);
6066
}

src/Modules/SimplCommerce.Module.Catalog/Areas/Catalog/Components/SimpleProductWidgetViewComponent.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,17 @@ public class SimpleProductWidgetViewComponent : ViewComponent
1616
private readonly IRepository<Product> _productRepository;
1717
private readonly IMediaService _mediaService;
1818
private readonly IProductPricingService _productPricingService;
19+
private readonly IContentLocalizationService _contentLocalizationService;
1920

20-
public SimpleProductWidgetViewComponent(IRepository<Product> productRepository, IMediaService mediaService, IProductPricingService productPricingService)
21+
public SimpleProductWidgetViewComponent(IRepository<Product> productRepository,
22+
IMediaService mediaService,
23+
IProductPricingService productPricingService,
24+
IContentLocalizationService contentLocalizationService)
2125
{
2226
_productRepository = productRepository;
2327
_mediaService = mediaService;
2428
_productPricingService = productPricingService;
29+
_contentLocalizationService = contentLocalizationService;
2530
}
2631

2732
public IViewComponentResult Invoke(WidgetInstanceViewModel widgetInstance)
@@ -40,6 +45,7 @@ public IViewComponentResult Invoke(WidgetInstanceViewModel widgetInstance)
4045
if (product != null)
4146
{
4247
var productThumbnail = ProductThumbnail.FromProduct(product);
48+
productThumbnail.Name = _contentLocalizationService.GetLocalizedProperty(nameof(Product), productThumbnail.Id, nameof(product.Name), productThumbnail.Name);
4349
productThumbnail.ThumbnailUrl = _mediaService.GetThumbnailUrl(product.ThumbnailImage);
4450
productThumbnail.CalculatedProductPrice = _productPricingService.CalculateProductPrice(product);
4551
model.Products.Add(productThumbnail);

src/Modules/SimplCommerce.Module.Catalog/Areas/Catalog/Controllers/BrandController.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,22 @@ public class BrandController : Controller
2020
private readonly IRepository<Product> _productRepository;
2121
private readonly IRepository<Brand> _brandRepository;
2222
private readonly IProductPricingService _productPricingService;
23+
private readonly IContentLocalizationService _contentLocalizationService;
2324

2425
public BrandController(IRepository<Product> productRepository,
2526
IMediaService mediaService,
2627
IRepository<Category> categoryRepository,
2728
IRepository<Brand> brandRepository,
2829
IProductPricingService productPricingService,
29-
IConfiguration config)
30+
IConfiguration config,
31+
IContentLocalizationService contentLocalizationService)
3032
{
3133
_productRepository = productRepository;
3234
_mediaService = mediaService;
3335
_categoryRepository = categoryRepository;
3436
_brandRepository = brandRepository;
3537
_productPricingService = productPricingService;
38+
_contentLocalizationService = contentLocalizationService;
3639
_pageSize = config.GetValue<int>("Catalog.ProductPageSize");
3740
}
3841

@@ -98,6 +101,7 @@ public IActionResult BrandDetail(long id, SearchOption searchOption)
98101

99102
foreach (var product in products)
100103
{
104+
product.Name = _contentLocalizationService.GetLocalizedProperty(nameof(Product), product.Id, nameof(product.Name), product.Name);
101105
product.ThumbnailUrl = _mediaService.GetThumbnailUrl(product.ThumbnailImage);
102106
product.CalculatedProductPrice = _productPricingService.CalculateProductPrice(product);
103107
}

src/Modules/SimplCommerce.Module.Catalog/Areas/Catalog/Controllers/CategoryController.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,22 @@ public class CategoryController : Controller
2020
private readonly IRepository<Product> _productRepository;
2121
private readonly IRepository<Brand> _brandRepository;
2222
private readonly IProductPricingService _productPricingService;
23+
private readonly IContentLocalizationService _contentLocalizationService;
2324

2425
public CategoryController(IRepository<Product> productRepository,
2526
IMediaService mediaService,
2627
IRepository<Category> categoryRepository,
2728
IRepository<Brand> brandRepository,
2829
IProductPricingService productPricingService,
30+
IContentLocalizationService contentLocalizationService,
2931
IConfiguration config)
3032
{
3133
_productRepository = productRepository;
3234
_mediaService = mediaService;
3335
_categoryRepository = categoryRepository;
3436
_brandRepository = brandRepository;
3537
_productPricingService = productPricingService;
38+
_contentLocalizationService = contentLocalizationService;
3639
_pageSize = config.GetValue<int>("Catalog.ProductPageSize");
3740
}
3841

@@ -48,7 +51,7 @@ public IActionResult CategoryDetail(long id, SearchOption searchOption)
4851
{
4952
CategoryId = category.Id,
5053
ParentCategorId = category.ParentId,
51-
CategoryName = category.Name,
54+
CategoryName = _contentLocalizationService.GetLocalizedProperty(category, nameof(category.Name), category.Name),
5255
CategorySlug = category.Slug,
5356
CategoryMetaTitle = category.MetaTitle,
5457
CategoryMetaKeywords = category.MetaKeywords,
@@ -109,6 +112,7 @@ public IActionResult CategoryDetail(long id, SearchOption searchOption)
109112

110113
foreach (var product in products)
111114
{
115+
product.Name = _contentLocalizationService.GetLocalizedProperty(nameof(Product), product.Id, nameof(product.Name), product.Name);
112116
product.ThumbnailUrl = _mediaService.GetThumbnailUrl(product.ThumbnailImage);
113117
product.CalculatedProductPrice = _productPricingService.CalculateProductPrice(product);
114118
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
using System.Linq;
2+
using System.Threading.Tasks;
3+
using Microsoft.AspNetCore.Authorization;
4+
using Microsoft.AspNetCore.Mvc;
5+
using Microsoft.EntityFrameworkCore;
6+
using SimplCommerce.Infrastructure.Data;
7+
using SimplCommerce.Infrastructure.Localization;
8+
using SimplCommerce.Module.Catalog.Areas.Catalog.ViewModels;
9+
using SimplCommerce.Module.Catalog.Models;
10+
11+
namespace SimplCommerce.Module.Catalog.Areas.Catalog.Controllers
12+
{
13+
[Area("Catalog")]
14+
[Authorize(Roles = "admin")]
15+
[Route("api/category-translations")]
16+
public class CategoryTranslationApiController : Controller
17+
{
18+
private readonly IRepository<Category> _categoryRepository;
19+
private readonly IRepository<LocalizedContentProperty> _localizedContentPropertyRepository;
20+
21+
public CategoryTranslationApiController(IRepository<Category> categoryRepository, IRepository<LocalizedContentProperty> localizedContentPropertyRepository)
22+
{
23+
_categoryRepository = categoryRepository;
24+
_localizedContentPropertyRepository = localizedContentPropertyRepository;
25+
}
26+
27+
[HttpGet("{id}")]
28+
public async Task<IActionResult> Get(long id, string culture)
29+
{
30+
var category = await _categoryRepository.Query().FirstOrDefaultAsync(x => x.Id == id);
31+
if (category == null)
32+
{
33+
return NotFound();
34+
}
35+
36+
var entityType = category.GetType().Name;
37+
38+
var localizeProperties = _localizedContentPropertyRepository.Query().Where(x => x.EntityId == category.Id
39+
&& x.EntityType == entityType && x.CultureId == culture);
40+
41+
var model = new CategoryTranslationForm
42+
{
43+
DefaultCultureName = category.Name,
44+
Name = localizeProperties.FirstOrDefault(x => x.ProperyName == nameof(category.Name))?.Value,
45+
Description = localizeProperties.FirstOrDefault(x => x.ProperyName == nameof(category.Description))?.Value,
46+
};
47+
48+
return Ok(model);
49+
}
50+
51+
[HttpPut("{id}")]
52+
public async Task<IActionResult> Put(long id, string culture, [FromBody] CategoryTranslationForm model)
53+
{
54+
if (ModelState.IsValid)
55+
{
56+
var category = await _categoryRepository.Query().FirstOrDefaultAsync(x => x.Id == id);
57+
if (category == null)
58+
{
59+
return NotFound();
60+
}
61+
62+
var entityType = category.GetType().Name;
63+
64+
var localizeProperties = _localizedContentPropertyRepository.Query().Where(x => x.EntityId == category.Id
65+
&& x.EntityType == entityType && x.CultureId == culture);
66+
67+
var localizedName = CreateOrUpdateTranslation(localizeProperties, category, nameof(category.Name), culture);
68+
localizedName.Value = model.Name;
69+
70+
var localizedDescription = CreateOrUpdateTranslation(localizeProperties, category, nameof(category.Description), culture);
71+
localizedDescription.Value = model.Description;
72+
73+
await _localizedContentPropertyRepository.SaveChangesAsync();
74+
75+
return Accepted();
76+
}
77+
78+
return BadRequest(ModelState);
79+
}
80+
81+
private LocalizedContentProperty CreateOrUpdateTranslation(IQueryable<LocalizedContentProperty> localizedContentProperties, Category category, string propertyName, string culture)
82+
{
83+
var localizedProperty = localizedContentProperties.FirstOrDefault(x => x.ProperyName == propertyName);
84+
if (localizedProperty == null)
85+
{
86+
localizedProperty = new LocalizedContentProperty
87+
{
88+
CultureId = culture,
89+
EntityId = category.Id,
90+
EntityType = category.GetType().Name,
91+
ProperyName = propertyName
92+
};
93+
94+
_localizedContentPropertyRepository.Add(localizedProperty);
95+
}
96+
97+
return localizedProperty;
98+
}
99+
}
100+
}

src/Modules/SimplCommerce.Module.Catalog/Areas/Catalog/Controllers/ProductController.cs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,19 @@ public class ProductController : Controller
2323
private readonly IRepository<Product> _productRepository;
2424
private readonly IMediator _mediator;
2525
private readonly IProductPricingService _productPricingService;
26+
private readonly IContentLocalizationService _contentLocalizationService;
2627

27-
public ProductController(IRepository<Product> productRepository, IMediaService mediaService, IMediator mediator, IProductPricingService productPricingService)
28+
public ProductController(IRepository<Product> productRepository,
29+
IMediaService mediaService,
30+
IMediator mediator,
31+
IProductPricingService productPricingService,
32+
IContentLocalizationService contentLocalizationService)
2833
{
2934
_productRepository = productRepository;
3035
_mediaService = mediaService;
3136
_mediator = mediator;
3237
_productPricingService = productPricingService;
38+
_contentLocalizationService = contentLocalizationService;
3339
}
3440

3541
[HttpGet("product/product-overview")]
@@ -50,13 +56,13 @@ public async Task<IActionResult> ProductOverview(long id)
5056
var model = new ProductDetail
5157
{
5258
Id = product.Id,
53-
Name = product.Name,
59+
Name = _contentLocalizationService.GetLocalizedProperty(product, nameof(product.Name), product.Name),
5460
CalculatedProductPrice = _productPricingService.CalculateProductPrice(product),
5561
IsCallForPricing = product.IsCallForPricing,
5662
IsAllowToOrder = product.IsAllowToOrder,
5763
StockTrackingIsEnabled = product.StockTrackingIsEnabled,
5864
StockQuantity = product.StockQuantity,
59-
ShortDescription = product.ShortDescription,
65+
ShortDescription = _contentLocalizationService.GetLocalizedProperty(product, nameof(product.ShortDescription), product.ShortDescription),
6066
ReviewsCount = product.ReviewsCount,
6167
RatingAverage = product.RatingAverage,
6268
};
@@ -86,18 +92,18 @@ public async Task<IActionResult> ProductDetail(long id)
8692
var model = new ProductDetail
8793
{
8894
Id = product.Id,
89-
Name = product.Name,
95+
Name = _contentLocalizationService.GetLocalizedProperty(product, nameof(product.Name), product.Name),
9096
CalculatedProductPrice = _productPricingService.CalculateProductPrice(product),
9197
IsCallForPricing = product.IsCallForPricing,
9298
IsAllowToOrder = product.IsAllowToOrder,
9399
StockTrackingIsEnabled = product.StockTrackingIsEnabled,
94100
StockQuantity = product.StockQuantity,
95-
ShortDescription = product.ShortDescription,
101+
ShortDescription = _contentLocalizationService.GetLocalizedProperty(product, nameof(product.ShortDescription), product.ShortDescription),
96102
MetaTitle = product.MetaTitle,
97103
MetaKeywords = product.MetaKeywords,
98104
MetaDescription = product.MetaDescription,
99-
Description = product.Description,
100-
Specification = product.Specification,
105+
Description = _contentLocalizationService.GetLocalizedProperty(product, nameof(product.Description), product.Description),
106+
Specification = _contentLocalizationService.GetLocalizedProperty(product, nameof(product.Specification), product.Specification),
101107
ReviewsCount = product.ReviewsCount,
102108
RatingAverage = product.RatingAverage,
103109
Attributes = product.AttributeValues.Select(x => new ProductDetailAttribute { Name = x.Attribute.Name, Value = x.Value }).ToList(),
@@ -184,7 +190,7 @@ private void MapRelatedProductToProductVm(Product product, ProductDetail model)
184190
{
185191
var linkedProduct = productLink.LinkedProduct;
186192
var productThumbnail = ProductThumbnail.FromProduct(linkedProduct);
187-
193+
productThumbnail.Name = _contentLocalizationService.GetLocalizedProperty(nameof(Product), productThumbnail.Id, nameof(product.Name), productThumbnail.Name);
188194
productThumbnail.ThumbnailUrl = _mediaService.GetThumbnailUrl(linkedProduct.ThumbnailImage);
189195
productThumbnail.CalculatedProductPrice = _productPricingService.CalculateProductPrice(linkedProduct);
190196

0 commit comments

Comments
 (0)