Try your search with a different keyword or use * as a wildcard.
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Xml;
using Nop.Core;
using Nop.Core.Caching;
using Nop.Core.Configuration;
using Nop.Core.Domain.Localization;
using Nop.Core.Domain.Security;
using Nop.Data;
using Nop.Services.Configuration;
using Nop.Services.ExportImport;
using Nop.Services.Logging;
using Nop.Services.Plugins;
namespace Nop.Services.Localization;
///
/// Provides information about localization
///
public partial class LocalizationService : ILocalizationService
{
#region Fields
protected readonly ILanguageService _languageService;
protected readonly ILocalizedEntityService _localizedEntityService;
protected readonly ILogger _logger;
protected readonly IRepository _lsrRepository;
protected readonly ISettingService _settingService;
protected readonly IStaticCacheManager _staticCacheManager;
protected readonly IWorkContext _workContext;
protected readonly LocalizationSettings _localizationSettings;
#endregion
#region Ctor
public LocalizationService(ILanguageService languageService,
ILocalizedEntityService localizedEntityService,
ILogger logger,
IRepository lsrRepository,
ISettingService settingService,
IStaticCacheManager staticCacheManager,
IWorkContext workContext,
LocalizationSettings localizationSettings)
{
_languageService = languageService;
_localizedEntityService = localizedEntityService;
_logger = logger;
_lsrRepository = lsrRepository;
_settingService = settingService;
_staticCacheManager = staticCacheManager;
_workContext = workContext;
_localizationSettings = localizationSettings;
}
#endregion
#region Utilities
///
/// Gets all locale string resources by language identifier
///
/// Language identifier
///
/// A task that represents the asynchronous operation
/// The task result contains the locale string resources
///
protected virtual async Task> GetAllResourcesAsync(int languageId)
{
var locales = await _lsrRepository.GetAllAsync(query =>
{
return from l in query
orderby l.ResourceName
where l.LanguageId == languageId
select l;
});
return locales;
}
protected virtual HashSet<(string name, string value)> LoadLocaleResourcesFromStream(StreamReader xmlStreamReader, string language)
{
var result = new HashSet<(string name, string value)>();
using (var xmlReader = XmlReader.Create(xmlStreamReader))
while (xmlReader.ReadToFollowing("Language"))
{
if (xmlReader.NodeType != XmlNodeType.Element)
continue;
using var languageReader = xmlReader.ReadSubtree();
while (languageReader.ReadToFollowing("LocaleResource"))
if (xmlReader.NodeType == XmlNodeType.Element && xmlReader.GetAttribute("Name") is string name)
{
using var lrReader = languageReader.ReadSubtree();
if (lrReader.ReadToFollowing("Value") && lrReader.NodeType == XmlNodeType.Element)
result.Add((name.ToLowerInvariant(), lrReader.ReadString()));
}
break;
}
return result;
}
protected virtual Dictionary> ResourceValuesToDictionary(IEnumerable locales)
{
//format: >
var dictionary = new Dictionary>();
foreach (var locale in locales)
{
var resourceName = locale.ResourceName.ToLowerInvariant();
if (!dictionary.ContainsKey(resourceName))
dictionary.Add(resourceName, new KeyValuePair(locale.Id, locale.ResourceValue));
}
return dictionary;
}
protected virtual async Task> UpdateLocaleResourceAsync(IDictionary resources, int? languageId = null, bool clearCache = true)
{
var localResources = new Dictionary(resources, StringComparer.InvariantCultureIgnoreCase);
var keys = localResources.Keys.Select(key => key.ToLowerInvariant()).ToArray();
var resourcesToUpdate = await _lsrRepository.GetAllAsync(query =>
{
var rez = query.Where(p => !languageId.HasValue || p.LanguageId == languageId)
.Where(p => keys.Contains(p.ResourceName.ToLower()));
return rez;
});
var existsResources = new List();
foreach (var localeStringResource in resourcesToUpdate.ToList())
{
var newValue = localResources[localeStringResource.ResourceName];
if (localeStringResource.ResourceValue.Equals(newValue))
resourcesToUpdate.Remove(localeStringResource);
localeStringResource.ResourceValue = newValue;
existsResources.Add(localeStringResource.ResourceName);
}
await _lsrRepository.UpdateAsync(resourcesToUpdate);
//clear cache
if (clearCache)
await _staticCacheManager.RemoveByPrefixAsync(NopEntityCacheDefaults.Prefix);
return localResources.Where(item => !existsResources.Contains(item.Key, StringComparer.InvariantCultureIgnoreCase))
.ToDictionary(p => p.Key, p => p.Value);
}
protected virtual IDictionary UpdateLocaleResource(IDictionary resources, int? languageId = null, bool clearCache = true)
{
var localResources = new Dictionary(resources, StringComparer.InvariantCultureIgnoreCase);
var keys = localResources.Keys.Select(key => key.ToLowerInvariant()).ToArray();
var resourcesToUpdate = _lsrRepository.GetAll(query =>
{
var rez = query.Where(p => !languageId.HasValue || p.LanguageId == languageId)
.Where(p => keys.Contains(p.ResourceName.ToLower()));
return rez;
});
var existsResources = new List();
foreach (var localeStringResource in resourcesToUpdate.ToList())
{
var newValue = localResources[localeStringResource.ResourceName];
if (localeStringResource.ResourceValue.Equals(newValue))
resourcesToUpdate.Remove(localeStringResource);
localeStringResource.ResourceValue = newValue;
existsResources.Add(localeStringResource.ResourceName);
}
_lsrRepository.Update(resourcesToUpdate);
//clear cache
if (clearCache)
_staticCacheManager.RemoveByPrefix(NopEntityCacheDefaults.Prefix);
return localResources.Where(item => !existsResources.Contains(item.Key, StringComparer.InvariantCultureIgnoreCase))
.ToDictionary(p => p.Key, p => p.Value);
}
#endregion
#region Methods
///
/// Deletes a locale string resource
///
/// Locale string resource
/// A task that represents the asynchronous operation
public virtual async Task DeleteLocaleStringResourceAsync(LocaleStringResource localeStringResource)
{
await _lsrRepository.DeleteAsync(localeStringResource);
}
///
/// Deletes a locale string resource
///
/// Locale string resource
public virtual void DeleteLocaleStringResource(LocaleStringResource localeStringResource)
{
_lsrRepository.Delete(localeStringResource);
}
///
/// Gets a locale string resource
///
/// Locale string resource identifier
///
/// A task that represents the asynchronous operation
/// The task result contains the locale string resource
///
public virtual async Task GetLocaleStringResourceByIdAsync(int localeStringResourceId)
{
return await _lsrRepository.GetByIdAsync(localeStringResourceId, cache => default);
}
///
/// Gets a locale string resource
///
/// A string representing a resource name
/// Language identifier
/// A value indicating whether to log error if locale string resource is not found
///
/// A task that represents the asynchronous operation
/// The task result contains the locale string resource
///
public virtual async Task GetLocaleStringResourceByNameAsync(string resourceName, int languageId,
bool logIfNotFound = true)
{
var query = from lsr in _lsrRepository.Table
orderby lsr.ResourceName
where lsr.LanguageId == languageId && lsr.ResourceName == resourceName.ToLowerInvariant()
select lsr;
var localeStringResource = await query.FirstOrDefaultAsync();
if (localeStringResource == null && logIfNotFound)
await _logger.WarningAsync($"Resource string ({resourceName}) not found. Language ID = {languageId}");
return localeStringResource;
}
///
/// Gets a locale string resource
///
/// A string representing a resource name
/// Language identifier
/// A value indicating whether to log error if locale string resource is not found
///
/// The locale string resource
///
public virtual LocaleStringResource GetLocaleStringResourceByName(string resourceName, int languageId,
bool logIfNotFound = true)
{
var query = from lsr in _lsrRepository.Table
orderby lsr.ResourceName
where lsr.LanguageId == languageId && lsr.ResourceName == resourceName.ToLowerInvariant()
select lsr;
var localeStringResource = query.FirstOrDefault();
if (localeStringResource == null && logIfNotFound)
_logger.Warning($"Resource string ({resourceName}) not found. Language ID = {languageId}");
return localeStringResource;
}
///
/// Inserts a locale string resource
///
/// Locale string resource
/// A task that represents the asynchronous operation
public virtual async Task InsertLocaleStringResourceAsync(LocaleStringResource localeStringResource)
{
if (!string.IsNullOrEmpty(localeStringResource?.ResourceName))
localeStringResource.ResourceName = localeStringResource.ResourceName.Trim().ToLowerInvariant();
await _lsrRepository.InsertAsync(localeStringResource);
}
///
/// Updates the locale string resource
///
/// Locale string resource
/// A task that represents the asynchronous operation
public virtual async Task UpdateLocaleStringResourceAsync(LocaleStringResource localeStringResource)
{
await _lsrRepository.UpdateAsync(localeStringResource);
}
///
/// Updates the locale string resource
///
/// Locale string resource
public virtual void UpdateLocaleStringResource(LocaleStringResource localeStringResource)
{
_lsrRepository.Update(localeStringResource);
}
///
/// Gets all locale string resources by language identifier
///
/// Language identifier
/// A value indicating whether to load data for the public store only (if "false", then for admin area only. If null, then load all locales. We use it for performance optimization of the site startup
///
/// A task that represents the asynchronous operation
/// The task result contains the locale string resources
///
public virtual async Task>> GetAllResourceValuesAsync(int languageId, bool? loadPublicLocales)
{
var key = _staticCacheManager.PrepareKeyForDefaultCache(NopLocalizationDefaults.LocaleStringResourcesAllCacheKey, languageId);
//get all locale string resources by language identifier
var allLocales =
await _staticCacheManager.GetAsync>>(key);
if (!loadPublicLocales.HasValue || allLocales != null)
{
var rez = allLocales ?? await _staticCacheManager.GetAsync(key, () =>
{
//we use no tracking here for performance optimization
//anyway records are loaded only for read-only operations
var query = from l in _lsrRepository.Table
orderby l.ResourceName
where l.LanguageId == languageId
select l;
return ResourceValuesToDictionary(query);
});
//remove separated resource
await _staticCacheManager.RemoveAsync(NopLocalizationDefaults.LocaleStringResourcesAllPublicCacheKey, languageId);
await _staticCacheManager.RemoveAsync(NopLocalizationDefaults.LocaleStringResourcesAllAdminCacheKey, languageId);
return rez;
}
//performance optimization of the site startup
key = _staticCacheManager.PrepareKeyForDefaultCache(loadPublicLocales.Value
? NopLocalizationDefaults.LocaleStringResourcesAllPublicCacheKey
: NopLocalizationDefaults.LocaleStringResourcesAllAdminCacheKey,
languageId);
return await _staticCacheManager.GetAsync(key, () =>
{
//we use no tracking here for performance optimization
//anyway records are loaded only for read-only operations
var query = from l in _lsrRepository.Table
orderby l.ResourceName
where l.LanguageId == languageId
select l;
query = loadPublicLocales.Value ? query.Where(r => !r.ResourceName.StartsWith(NopLocalizationDefaults.AdminLocaleStringResourcesPrefix)) : query.Where(r => r.ResourceName.StartsWith(NopLocalizationDefaults.AdminLocaleStringResourcesPrefix));
return ResourceValuesToDictionary(query);
});
}
///
/// Gets a resource string based on the specified ResourceKey property.
///
/// A string representing a ResourceKey.
///
/// A task that represents the asynchronous operation
/// The task result contains a string representing the requested resource string.
///
public virtual async Task GetResourceAsync(string resourceKey)
{
var workingLanguage = await _workContext.GetWorkingLanguageAsync();
if (workingLanguage != null)
return await GetResourceAsync(resourceKey, workingLanguage.Id);
return string.Empty;
}
///
/// Gets a resource string based on the specified ResourceKey property.
///
/// A string representing a ResourceKey.
/// Language identifier
/// A value indicating whether to log error if locale string resource is not found
/// Default value
/// A value indicating whether an empty string will be returned if a resource is not found and default value is set to empty string
///
/// A task that represents the asynchronous operation
/// The task result contains a string representing the requested resource string.
///
public virtual async Task GetResourceAsync(string resourceKey, int languageId,
bool logIfNotFound = true, string defaultValue = "", bool returnEmptyIfNotFound = false)
{
var result = string.Empty;
resourceKey ??= string.Empty;
resourceKey = resourceKey.Trim().ToLowerInvariant();
if (_localizationSettings.LoadAllLocaleRecordsOnStartup)
{
//load all records (we know they are cached)
var resources = await GetAllResourceValuesAsync(languageId, !resourceKey.StartsWith(NopLocalizationDefaults.AdminLocaleStringResourcesPrefix, StringComparison.InvariantCultureIgnoreCase));
if (resources.TryGetValue(resourceKey, out var keyValuePair))
{
result = keyValuePair.Value;
}
}
else
{
//gradual loading
var key = _staticCacheManager.PrepareKeyForDefaultCache(NopLocalizationDefaults.LocaleStringResourcesByNameCacheKey
, languageId, resourceKey);
var query = from l in _lsrRepository.Table
where l.ResourceName == resourceKey
&& l.LanguageId == languageId
select l.ResourceValue;
var lsr = await _staticCacheManager.GetAsync(key, async () => await query.FirstOrDefaultAsync());
if (lsr != null)
result = lsr;
}
if (!string.IsNullOrEmpty(result))
return result;
if (logIfNotFound)
await _logger.WarningAsync($"Resource string ({resourceKey}) is not found. Language ID = {languageId}");
if (!string.IsNullOrEmpty(defaultValue))
{
result = defaultValue;
}
else
{
if (!returnEmptyIfNotFound)
result = resourceKey;
}
return result;
}
///
/// Export language resources to XML
///
/// Language
///
/// A task that represents the asynchronous operation
/// The task result contains the result in XML format
///
public virtual async Task ExportResourcesToXmlAsync(Language language)
{
ArgumentNullException.ThrowIfNull(language);
var settings = new XmlWriterSettings
{
Async = true,
Encoding = Encoding.UTF8,
ConformanceLevel = ConformanceLevel.Auto
};
await using var stream = new MemoryStream();
await using var xmlWriter = XmlWriter.Create(stream, settings);
await xmlWriter.WriteStartDocumentAsync();
await xmlWriter.WriteStartElementAsync("Language");
await xmlWriter.WriteAttributeStringAsync("Name", language.Name);
await xmlWriter.WriteAttributeStringAsync("SupportedVersion", NopVersion.CURRENT_VERSION);
var resources = await GetAllResourcesAsync(language.Id);
foreach (var resource in resources)
{
await xmlWriter.WriteStartElementAsync("LocaleResource");
await xmlWriter.WriteAttributeStringAsync("Name", resource.ResourceName);
await xmlWriter.WriteElementStringAsync("Value", null, resource.ResourceValue);
await xmlWriter.WriteEndElementAsync();
}
await xmlWriter.WriteEndElementAsync();
await xmlWriter.WriteEndDocumentAsync();
await xmlWriter.FlushAsync();
return Encoding.UTF8.GetString(stream.ToArray());
}
///
/// Import language resources from XML file
///
/// Language
/// Stream reader of XML file
/// A value indicating whether to update existing resources
/// A task that represents the asynchronous operation
public virtual async Task ImportResourcesFromXmlAsync(Language language, StreamReader xmlStreamReader, bool updateExistingResources = true)
{
ArgumentNullException.ThrowIfNull(language);
if (xmlStreamReader.EndOfStream)
return;
var lsNamesList = new Dictionary();
foreach (var localeStringResource in _lsrRepository.Table.Where(lsr => lsr.LanguageId == language.Id)
.OrderBy(lsr => lsr.Id))
lsNamesList[localeStringResource.ResourceName.ToLowerInvariant()] = localeStringResource;
var lrsToUpdateList = new List();
var lrsToInsertList = new Dictionary();
foreach (var (name, value) in LoadLocaleResourcesFromStream(xmlStreamReader, language.Name))
{
if (lsNamesList.TryGetValue(name, out var localString))
{
if (!updateExistingResources)
continue;
var lsr = localString;
lsr.ResourceValue = value;
lrsToUpdateList.Add(lsr);
}
else
{
var lsr = new LocaleStringResource { LanguageId = language.Id, ResourceName = name, ResourceValue = value };
lrsToInsertList[name] = lsr;
}
}
await _lsrRepository.UpdateAsync(lrsToUpdateList, false);
await _lsrRepository.InsertAsync(lrsToInsertList.Values.ToList(), false);
//clear cache
await _staticCacheManager.RemoveByPrefixAsync(NopEntityCacheDefaults.Prefix);
}
///
/// Get localized property of an entity
///
/// Entity type
/// Property type
/// Entity
/// Key selector
/// Language identifier; pass null to use the current working language; pass 0 to get standard language value
/// A value indicating whether to return default value (if localized is not found)
/// A value indicating whether to ensure that we have at least two published languages; otherwise, load only default value
///
/// A task that represents the asynchronous operation
/// The task result contains the localized property
///
public virtual async Task GetLocalizedAsync(TEntity entity, Expression> keySelector,
int? languageId = null, bool returnDefaultValue = true, bool ensureTwoPublishedLanguages = true)
where TEntity : BaseEntity, ILocalizedEntity
{
ArgumentNullException.ThrowIfNull(entity);
if (keySelector.Body is not MemberExpression member)
throw new ArgumentException($"Expression '{keySelector}' refers to a method, not a property.");
if (member.Member is not PropertyInfo propInfo)
throw new ArgumentException($"Expression '{keySelector}' refers to a field, not a property.");
var result = default(TPropType);
var resultStr = string.Empty;
var localeKeyGroup = entity.GetType().Name;
var localeKey = propInfo.Name;
var workingLanguage = await _workContext.GetWorkingLanguageAsync();
if (!languageId.HasValue)
languageId = workingLanguage.Id;
if (languageId > 0)
{
//ensure that we have at least two published languages
var loadLocalizedValue = true;
if (ensureTwoPublishedLanguages)
{
var totalPublishedLanguages = (await _languageService.GetAllLanguagesAsync()).Count;
loadLocalizedValue = totalPublishedLanguages >= 2;
}
//localized value
if (loadLocalizedValue)
{
resultStr = await _localizedEntityService
.GetLocalizedValueAsync(languageId.Value, entity.Id, localeKeyGroup, localeKey);
if (!string.IsNullOrEmpty(resultStr))
result = CommonHelper.To(resultStr);
}
}
//set default value if required
if (!string.IsNullOrEmpty(resultStr) || !returnDefaultValue)
return result;
var localizer = keySelector.Compile();
result = localizer(entity);
return result;
}
///
/// Get localized property of setting
///
/// Settings type
/// Settings
/// Key selector
/// Language identifier
/// Store identifier
/// A value indicating whether to return default value (if localized is not found)
/// A value indicating whether to ensure that we have at least two published languages; otherwise, load only default value
///
/// A task that represents the asynchronous operation
/// The task result contains the localized property
///
public virtual async Task GetLocalizedSettingAsync(TSettings settings, Expression> keySelector,
int languageId, int storeId, bool returnDefaultValue = true, bool ensureTwoPublishedLanguages = true)
where TSettings : ISettings, new()
{
var key = _settingService.GetSettingKey(settings, keySelector);
//we do not support localized settings per store (overridden store settings)
var setting = await _settingService.GetSettingAsync(key, storeId: storeId, loadSharedValueIfNotFound: true);
if (setting == null)
return null;
return await GetLocalizedAsync(setting, x => x.Value, languageId, returnDefaultValue, ensureTwoPublishedLanguages);
}
///
/// Save localized property of setting
///
/// Settings type
/// Settings
/// Key selector
/// Language identifier
/// Localized value
///
/// A task that represents the asynchronous operation
/// The task result contains the localized property
///
public virtual async Task SaveLocalizedSettingAsync(TSettings settings, Expression> keySelector,
int languageId, string value) where TSettings : ISettings, new()
{
var key = _settingService.GetSettingKey(settings, keySelector);
//we do not support localized settings per store (overridden store settings)
var setting = await _settingService.GetSettingAsync(key);
if (setting == null)
return;
await _localizedEntityService.SaveLocalizedValueAsync(setting, x => x.Value, value, languageId);
}
///
/// Get localized value of enum
///
/// Enum type
/// Enum value
/// Language identifier; pass null to use the current working language
///
/// A task that represents the asynchronous operation
/// The task result contains the localized value
///
public virtual async Task GetLocalizedEnumAsync(TEnum enumValue, int? languageId = null) where TEnum : struct
{
if (!typeof(TEnum).IsEnum)
throw new ArgumentException("T must be an enumerated type");
//localized value
var workingLanguage = await _workContext.GetWorkingLanguageAsync();
var resourceName = $"{NopLocalizationDefaults.EnumLocaleStringResourcesPrefix}{typeof(TEnum)}.{enumValue}";
var result = await GetResourceAsync(resourceName, languageId ?? workingLanguage.Id, false, string.Empty, true);
//set default value if required
if (string.IsNullOrEmpty(result))
result = CommonHelper.ConvertEnum(enumValue.ToString());
return result;
}
///
/// Get localized value of enum
/// We don't have UI to manage permission localizable name. That's why we're using this method
///
/// Permission record
/// Language identifier; pass null to use the current working language
///
/// A task that represents the asynchronous operation
/// The task result contains the localized value
///
public virtual async Task GetLocalizedPermissionNameAsync(PermissionRecord permissionRecord, int? languageId = null)
{
ArgumentNullException.ThrowIfNull(permissionRecord);
//localized value
var workingLanguage = await _workContext.GetWorkingLanguageAsync();
var resourceName = $"{NopLocalizationDefaults.PermissionLocaleStringResourcesPrefix}{permissionRecord.SystemName}";
var result = await GetResourceAsync(resourceName, languageId ?? workingLanguage.Id, false, string.Empty, true);
//set default value if required
if (string.IsNullOrEmpty(result))
result = permissionRecord.Name;
return result;
}
///
/// Save localized name of a permission
///
/// Permission record
/// A task that represents the asynchronous operation
public virtual async Task SaveLocalizedPermissionNameAsync(PermissionRecord permissionRecord)
{
ArgumentNullException.ThrowIfNull(permissionRecord);
var resourceName = $"{NopLocalizationDefaults.PermissionLocaleStringResourcesPrefix}{permissionRecord.SystemName}";
var resourceValue = permissionRecord.Name;
foreach (var lang in await _languageService.GetAllLanguagesAsync(true))
{
var lsr = await GetLocaleStringResourceByNameAsync(resourceName, lang.Id, false);
if (lsr == null)
{
lsr = new LocaleStringResource
{
LanguageId = lang.Id,
ResourceName = resourceName,
ResourceValue = resourceValue
};
await InsertLocaleStringResourceAsync(lsr);
}
else
{
lsr.ResourceValue = resourceValue;
await UpdateLocaleStringResourceAsync(lsr);
}
}
}
///
/// Delete a localized name of a permission
///
/// Permission record
/// A task that represents the asynchronous operation
public virtual async Task DeleteLocalizedPermissionNameAsync(PermissionRecord permissionRecord)
{
ArgumentNullException.ThrowIfNull(permissionRecord);
var resourceName = $"{NopLocalizationDefaults.PermissionLocaleStringResourcesPrefix}{permissionRecord.SystemName}";
foreach (var lang in await _languageService.GetAllLanguagesAsync(true))
{
var lsr = await GetLocaleStringResourceByNameAsync(resourceName, lang.Id, false);
if (lsr != null)
await DeleteLocaleStringResourceAsync(lsr);
}
}
///
/// Add a locale resource (if new) or update an existing one
///
/// Resource name
/// Resource value
/// Language culture code. If null or empty, then a resource will be added for all languages
/// A task that represents the asynchronous operation
public virtual async Task AddOrUpdateLocaleResourceAsync(string resourceName, string resourceValue, string languageCulture = null)
{
foreach (var lang in await _languageService.GetAllLanguagesAsync(true))
{
if (!string.IsNullOrEmpty(languageCulture) && !languageCulture.Equals(lang.LanguageCulture))
continue;
var lsr = await GetLocaleStringResourceByNameAsync(resourceName, lang.Id, false);
if (lsr == null)
{
lsr = new LocaleStringResource
{
LanguageId = lang.Id,
ResourceName = resourceName,
ResourceValue = resourceValue
};
await InsertLocaleStringResourceAsync(lsr);
}
else
{
lsr.ResourceValue = resourceValue;
await UpdateLocaleStringResourceAsync(lsr);
}
}
}
///
/// Add locale resources
///
/// Resource name-value pairs
/// Language identifier; pass null to add the passed resources for all languages
/// A task that represents the asynchronous operation
public virtual async Task AddOrUpdateLocaleResourceAsync(IDictionary resources, int? languageId = null)
{
//first update all previous locales with the passed names if they exist
var resourcesToInsert = await UpdateLocaleResourceAsync(resources, languageId, false);
if (resourcesToInsert.Any())
{
//insert new locale resources
var locales = (await _languageService.GetAllLanguagesAsync(true))
.Where(language => !languageId.HasValue || language.Id == languageId.Value)
.SelectMany(language => resourcesToInsert.Select(resource => new LocaleStringResource
{
LanguageId = language.Id,
ResourceName = resource.Key.Trim().ToLowerInvariant(),
ResourceValue = resource.Value
}))
.ToList();
await _lsrRepository.InsertAsync(locales, false);
}
//clear cache
await _staticCacheManager.RemoveByPrefixAsync(NopEntityCacheDefaults.Prefix);
}
///
/// Add locale resources
///
/// Resource name-value pairs
/// Language identifier; pass null to add the passed resources for all languages
public virtual void AddOrUpdateLocaleResource(IDictionary resources, int? languageId = null)
{
//first update all previous locales with the passed names if they exist
var resourcesToInsert = UpdateLocaleResource(resources, languageId, false);
if (resourcesToInsert.Any())
{
//insert new locale resources
var locales = _languageService.GetAllLanguages(true)
.Where(language => !languageId.HasValue || language.Id == languageId.Value)
.SelectMany(language => resourcesToInsert.Select(resource => new LocaleStringResource
{
LanguageId = language.Id,
ResourceName = resource.Key.Trim().ToLowerInvariant(),
ResourceValue = resource.Value
}))
.ToList();
_lsrRepository.Insert(locales, false);
}
//clear cache
_staticCacheManager.RemoveByPrefix(NopEntityCacheDefaults.Prefix);
}
///
/// Delete a locale resource
///
/// Resource name
/// A task that represents the asynchronous operation
public virtual async Task DeleteLocaleResourceAsync(string resourceName)
{
foreach (var lang in await _languageService.GetAllLanguagesAsync(true))
{
var lsr = await GetLocaleStringResourceByNameAsync(resourceName, lang.Id, false);
if (lsr != null)
await DeleteLocaleStringResourceAsync(lsr);
}
}
///
/// Delete locale resources
///
/// Resource names
/// Language identifier; pass null to delete the passed resources from all languages
/// A task that represents the asynchronous operation
public virtual async Task DeleteLocaleResourcesAsync(IList resourceNames, int? languageId = null)
{
await _lsrRepository.DeleteAsync(locale => (!languageId.HasValue || locale.LanguageId == languageId.Value) &&
resourceNames.Contains(locale.ResourceName, StringComparer.InvariantCultureIgnoreCase));
//clear cache
await _staticCacheManager.RemoveByPrefixAsync(NopEntityCacheDefaults.Prefix);
}
///
/// Delete locale resources
///
/// Resource names
/// Language identifier; pass null to delete the passed resources from all languages
public virtual void DeleteLocaleResources(IList resourceNames, int? languageId = null)
{
_lsrRepository.Delete(locale =>
(!languageId.HasValue || locale.LanguageId == languageId.Value) &&
resourceNames.Contains(locale.ResourceName, StringComparer.InvariantCultureIgnoreCase));
//clear cache
_staticCacheManager.RemoveByPrefix(NopEntityCacheDefaults.Prefix);
}
///
/// Delete locale resources by the passed name prefix
///
/// Resource name prefix
/// Language identifier; pass null to delete resources by prefix from all languages
/// A task that represents the asynchronous operation
public virtual async Task DeleteLocaleResourcesAsync(string resourceNamePrefix, int? languageId = null)
{
await _lsrRepository.DeleteAsync(locale => (!languageId.HasValue || locale.LanguageId == languageId.Value) &&
!string.IsNullOrEmpty(locale.ResourceName) &&
locale.ResourceName.StartsWith(resourceNamePrefix, StringComparison.InvariantCultureIgnoreCase));
//clear cache
await _staticCacheManager.RemoveByPrefixAsync(NopEntityCacheDefaults.Prefix);
}
///
/// Get localized friendly name of a plugin
///
/// Plugin type
/// Plugin
/// Language identifier
/// A value indicating whether to return default value (if localized is not found)
///
/// A task that represents the asynchronous operation
/// The task result contains the localized value
///
public virtual async Task GetLocalizedFriendlyNameAsync(TPlugin plugin, int languageId, bool returnDefaultValue = true)
where TPlugin : IPlugin
{
ArgumentNullException.ThrowIfNull(plugin);
if (plugin.PluginDescriptor == null)
throw new ArgumentException("Plugin descriptor cannot be loaded");
var systemName = plugin.PluginDescriptor.SystemName;
//localized value
var resourceName = $"{NopLocalizationDefaults.PluginNameLocaleStringResourcesPrefix}{systemName}";
var result = await GetResourceAsync(resourceName, languageId, false, string.Empty, true);
//set default value if required
if (string.IsNullOrEmpty(result) && returnDefaultValue)
result = plugin.PluginDescriptor.FriendlyName;
return result;
}
///
/// Save localized friendly name of a plugin
///
/// Plugin
/// Plugin
/// Language identifier
/// Localized friendly name
/// A task that represents the asynchronous operation
public virtual async Task SaveLocalizedFriendlyNameAsync(TPlugin plugin, int languageId, string localizedFriendlyName)
where TPlugin : IPlugin
{
if (languageId == 0)
throw new ArgumentOutOfRangeException(nameof(languageId), "Language ID should not be 0");
ArgumentNullException.ThrowIfNull(plugin);
if (plugin.PluginDescriptor == null)
throw new ArgumentException("Plugin descriptor cannot be loaded");
var systemName = plugin.PluginDescriptor.SystemName;
//localized value
var resourceName = $"{NopLocalizationDefaults.PluginNameLocaleStringResourcesPrefix}{systemName}";
var resource = await GetLocaleStringResourceByNameAsync(resourceName, languageId, false);
if (resource != null)
{
if (string.IsNullOrWhiteSpace(localizedFriendlyName))
{
//delete
await DeleteLocaleStringResourceAsync(resource);
}
else
{
//update
resource.ResourceValue = localizedFriendlyName;
await UpdateLocaleStringResourceAsync(resource);
}
}
else
{
if (string.IsNullOrWhiteSpace(localizedFriendlyName))
return;
//insert
resource = new LocaleStringResource
{
LanguageId = languageId,
ResourceName = resourceName,
ResourceValue = localizedFriendlyName
};
await InsertLocaleStringResourceAsync(resource);
}
}
#endregion
}