Try your search with a different keyword or use * as a wildcard.
using System.Linq.Expressions;
using System.Reflection;
using Nop.Core;
using Nop.Core.Caching;
using Nop.Core.Domain.Localization;
using Nop.Data;
namespace Nop.Services.Localization;
///
/// Provides information about localizable entities
///
public partial class LocalizedEntityService : ILocalizedEntityService
{
#region Fields
protected readonly IRepository _localizedPropertyRepository;
protected readonly IStaticCacheManager _staticCacheManager;
protected readonly LocalizationSettings _localizationSettings;
#endregion
#region Ctor
public LocalizedEntityService(IRepository localizedPropertyRepository,
IStaticCacheManager staticCacheManager,
LocalizationSettings localizationSettings)
{
_localizedPropertyRepository = localizedPropertyRepository;
_staticCacheManager = staticCacheManager;
_localizationSettings = localizationSettings;
}
#endregion
#region Utilities
///
/// Gets localized properties
///
/// Entity identifier
/// Locale key group
///
/// A task that represents the asynchronous operation
/// The task result contains the localized properties
///
protected virtual async Task> GetLocalizedPropertiesAsync(int entityId, string localeKeyGroup)
{
if (entityId == 0 || string.IsNullOrEmpty(localeKeyGroup))
return new List();
var query = from lp in _localizedPropertyRepository.Table
orderby lp.Id
where lp.EntityId == entityId &&
lp.LocaleKeyGroup == localeKeyGroup
select lp;
var props = await query.ToListAsync();
return props;
}
///
/// Gets all cached localized properties
///
///
/// A task that represents the asynchronous operation
/// The task result contains the cached localized properties
///
protected virtual async Task> GetAllLocalizedPropertiesAsync()
{
return await _localizedPropertyRepository.GetAllAsync(query =>
{
return from lp in query
select lp;
}, cache => default);
}
///
/// Gets all cached localized properties by language
///
///
/// A task that represents the asynchronous operation
/// The task result contains the uncached localized properties
///
protected virtual async Task> GetAllLocalizedPropertiesAsync(int languageId)
{
// do not cache here
return await _localizedPropertyRepository.GetAllAsync(query => query.Where(lp => lp.LanguageId == languageId));
}
///
/// Deletes a localized property
///
/// Localized property
/// A task that represents the asynchronous operation
protected virtual async Task DeleteLocalizedPropertyAsync(LocalizedProperty localizedProperty)
{
await _localizedPropertyRepository.DeleteAsync(localizedProperty);
}
///
/// Inserts a localized property
///
/// Localized property
/// A task that represents the asynchronous operation
protected virtual async Task InsertLocalizedPropertyAsync(LocalizedProperty localizedProperty)
{
await _localizedPropertyRepository.InsertAsync(localizedProperty);
}
///
/// Updates the localized property
///
/// Localized property
/// A task that represents the asynchronous operation
protected virtual async Task UpdateLocalizedPropertyAsync(LocalizedProperty localizedProperty)
{
await _localizedPropertyRepository.UpdateAsync(localizedProperty);
}
#endregion
#region Methods
///
/// Find localized properties
///
/// Entity identifier
/// Locale key group
/// Locale key
///
/// A task that represents the asynchronous operation
/// The task result contains the found localized properties
///
public virtual async Task> GetEntityLocalizedPropertiesAsync(int entityId, string localeKeyGroup, string localeKey)
{
var key = _staticCacheManager.PrepareKeyForDefaultCache(NopLocalizationDefaults.LocalizedPropertiesCacheKey,
entityId, localeKeyGroup, localeKey);
return await _staticCacheManager.GetAsync(key, async () =>
{
var source = _localizationSettings.LoadAllLocalizedPropertiesOnStartup
//load all records (we know they are cached)
? (await GetAllLocalizedPropertiesAsync()).AsQueryable()
//gradual loading
: _localizedPropertyRepository.Table;
var query = from lp in source
where lp.EntityId == entityId &&
lp.LocaleKeyGroup == localeKeyGroup &&
lp.LocaleKey == localeKey
select lp;
return await query.ToListAsync();
});
}
///
/// Find localized value
///
/// Language identifier
/// Entity identifier
/// Locale key group
/// Locale key
///
/// A task that represents the asynchronous operation
/// The task result contains the found localized value
///
public virtual async Task GetLocalizedValueAsync(int languageId, int entityId, string localeKeyGroup, string localeKey)
{
if (_localizationSettings.LoadAllLocalizedPropertiesOnStartup)
{
//value tuples aren't json-serializable by default, so we use a string key
static string formatKey(string keyGroup, string key, int id) => $"{keyGroup}:{key}:{id}";
var localizedValues = await _staticCacheManager.GetAsync(
_staticCacheManager.PrepareKeyForDefaultCache(NopLocalizationDefaults.LocalizedPropertyLookupCacheKey, languageId),
async () => (await GetAllLocalizedPropertiesAsync(languageId))
.GroupBy(p => formatKey(p.LocaleKeyGroup, p.LocaleKey, p.EntityId))
.ToDictionary(g => g.Key, g => g.First().LocaleValue));
return localizedValues.TryGetValue(formatKey(localeKeyGroup, localeKey, entityId), out var localeValue)
? localeValue
: string.Empty;
}
//gradual loading
var key = _staticCacheManager.PrepareKeyForDefaultCache(NopLocalizationDefaults.LocalizedPropertyCacheKey
, languageId, entityId, localeKeyGroup, localeKey);
return await _staticCacheManager.GetAsync(key, async () =>
{
var query = from lp in _localizedPropertyRepository.Table
where lp.LanguageId == languageId &&
lp.EntityId == entityId &&
lp.LocaleKeyGroup == localeKeyGroup &&
lp.LocaleKey == localeKey
select lp.LocaleValue;
//little hack here. nulls aren't cacheable so set it to ""
return await query.FirstOrDefaultAsync() ?? string.Empty;
});
}
///
/// Save localized value
///
/// Type
/// Entity
/// Key selector
/// Locale value
/// Language ID
/// A task that represents the asynchronous operation
public virtual async Task SaveLocalizedValueAsync(T entity,
Expression> keySelector,
string localeValue,
int languageId) where T : BaseEntity, ILocalizedEntity
{
await SaveLocalizedValueAsync(entity, keySelector, localeValue, languageId);
}
///
/// Save localized value
///
/// Type
/// Property type
/// Entity
/// Key selector
/// Locale value
/// Language ID
/// A task that represents the asynchronous operation
public virtual async Task SaveLocalizedValueAsync(T entity,
Expression> keySelector,
TPropType localeValue,
int languageId) where T : BaseEntity, ILocalizedEntity
{
ArgumentNullException.ThrowIfNull(entity);
if (languageId == 0)
throw new ArgumentOutOfRangeException(nameof(languageId), "Language ID should not be 0");
if (keySelector.Body is not MemberExpression member)
{
throw new ArgumentException(string.Format(
"Expression '{0}' refers to a method, not a property.",
keySelector));
}
var propInfo = member.Member as PropertyInfo ?? throw new ArgumentException(string.Format(
"Expression '{0}' refers to a field, not a property.",
keySelector));
//load localized value (check whether it's a cacheable entity. In such cases we load its original entity type)
var localeKeyGroup = entity.GetType().Name;
var localeKey = propInfo.Name;
var props = await GetLocalizedPropertiesAsync(entity.Id, localeKeyGroup);
var prop = props.FirstOrDefault(lp => lp.LanguageId == languageId &&
lp.LocaleKey.Equals(localeKey, StringComparison.InvariantCultureIgnoreCase)); //should be culture invariant
var localeValueStr = CommonHelper.To(localeValue);
if (prop != null)
{
if (string.IsNullOrWhiteSpace(localeValueStr))
{
//delete
await DeleteLocalizedPropertyAsync(prop);
}
else
{
//update
prop.LocaleValue = localeValueStr;
await UpdateLocalizedPropertyAsync(prop);
}
}
else
{
if (string.IsNullOrWhiteSpace(localeValueStr))
return;
//insert
prop = new LocalizedProperty
{
EntityId = entity.Id,
LanguageId = languageId,
LocaleKey = localeKey,
LocaleKeyGroup = localeKeyGroup,
LocaleValue = localeValueStr
};
await InsertLocalizedPropertyAsync(prop);
}
}
#endregion
}