using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Persistence.Repositories;
using Umbraco.Cms.Core.Scoping;
using Umbraco.Cms.Core.Services.OperationStatus;
using Umbraco.Extensions;
namespace Umbraco.Cms.Core.Services;
///
/// Represents the Localization Service, which is an easy access to operations involving and
///
///
[Obsolete("Please use ILanguageService and IDictionaryItemService for localization. Will be removed in V15.")]
internal class LocalizationService : RepositoryService, ILocalizationService
{
private readonly IDictionaryRepository _dictionaryRepository;
private readonly ILanguageRepository _languageRepository;
private readonly ILanguageService _languageService;
private readonly IDictionaryItemService _dictionaryItemService;
private readonly IUserIdKeyResolver _userIdKeyResolver;
[Obsolete("Please use constructor with language, dictionary and user services. Will be removed in V15")]
public LocalizationService(
ICoreScopeProvider provider,
ILoggerFactory loggerFactory,
IEventMessagesFactory eventMessagesFactory,
IDictionaryRepository dictionaryRepository,
ILanguageRepository languageRepository)
: this(
provider,
loggerFactory,
eventMessagesFactory,
dictionaryRepository,
languageRepository,
StaticServiceProvider.Instance.GetRequiredService(),
StaticServiceProvider.Instance.GetRequiredService(),
StaticServiceProvider.Instance.GetRequiredService())
{
}
[Obsolete("Please use ILanguageService and IDictionaryItemService for localization. Will be removed in V15.")]
public LocalizationService(
ICoreScopeProvider provider,
ILoggerFactory loggerFactory,
IEventMessagesFactory eventMessagesFactory,
IDictionaryRepository dictionaryRepository,
ILanguageRepository languageRepository,
ILanguageService languageService,
IDictionaryItemService dictionaryItemService,
IUserIdKeyResolver userIdKeyResolver)
: base(provider, loggerFactory, eventMessagesFactory)
{
_dictionaryRepository = dictionaryRepository;
_languageRepository = languageRepository;
_languageService = languageService;
_dictionaryItemService = dictionaryItemService;
_userIdKeyResolver = userIdKeyResolver;
}
///
/// Adds or updates a translation for a dictionary item and language
///
///
///
///
///
///
/// This does not save the item, that needs to be done explicitly
///
[Obsolete("Please use IDictionaryItemService for dictionary item operations. Will be removed in V15.")]
public void AddOrUpdateDictionaryValue(IDictionaryItem item, ILanguage? language, string value)
{
if (item == null)
{
throw new ArgumentNullException(nameof(item));
}
if (language == null)
{
throw new ArgumentNullException(nameof(language));
}
item.AddOrUpdateDictionaryValue(language, value);
}
///
/// Creates and saves a new dictionary item and assigns a value to all languages if defaultValue is specified.
///
///
///
///
///
[Obsolete("Please use IDictionaryItemService for dictionary item operations. Will be removed in V15.")]
public IDictionaryItem CreateDictionaryItemWithIdentity(string key, Guid? parentId, string? defaultValue = null)
{
IEnumerable translations = defaultValue.IsNullOrWhiteSpace()
? Array.Empty()
: GetAllLanguages()
.Select(language => new DictionaryTranslation(language, defaultValue!))
.ToArray();
Attempt result = _dictionaryItemService
.CreateAsync(new DictionaryItem(parentId, key) { Translations = translations }, Constants.Security.SuperUserKey)
.GetAwaiter()
.GetResult();
// mimic old service behavior
return result.Success || result.Status == DictionaryItemOperationStatus.CancelledByNotification
? result.Result
: throw new ArgumentException($"Could not create a dictionary item with key: {key} under parent: {parentId}");
}
///
/// Gets a by its id
///
/// Id of the
///
///
///
[Obsolete("Please use IDictionaryItemService for dictionary item operations. Will be removed in V15.")]
public IDictionaryItem? GetDictionaryItemById(int id)
{
using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true))
{
return _dictionaryRepository.Get(id);
}
}
///
/// Gets a by its id
///
/// Id of the
///
///
///
[Obsolete("Please use IDictionaryItemService for dictionary item operations. Will be removed in V15.")]
public IDictionaryItem? GetDictionaryItemById(Guid id)
=> _dictionaryItemService.GetAsync(id).GetAwaiter().GetResult();
///
/// Gets a collection by their ids
///
/// Ids of the
///
/// A collection of
///
[Obsolete("Please use IDictionaryItemService for dictionary item operations. Will be removed in V15.")]
public IEnumerable GetDictionaryItemsByIds(params Guid[] ids)
=> _dictionaryItemService.GetManyAsync(ids).GetAwaiter().GetResult();
///
/// Gets a by its key
///
/// Key of the
///
///
///
[Obsolete("Please use IDictionaryItemService for dictionary item operations. Will be removed in V15.")]
public IDictionaryItem? GetDictionaryItemByKey(string key)
=> _dictionaryItemService.GetAsync(key).GetAwaiter().GetResult();
///
/// Gets a collection of by their keys
///
/// Keys of the
///
/// A collection of
///
[Obsolete("Please use IDictionaryItemService for dictionary item operations. Will be removed in V15.")]
public IEnumerable GetDictionaryItemsByKeys(params string[] keys)
=> _dictionaryItemService.GetManyAsync(keys).GetAwaiter().GetResult();
///
/// Gets a list of children for a
///
/// Id of the parent
/// An enumerable list of objects
[Obsolete("Please use IDictionaryItemService for dictionary item operations. Will be removed in V15.")]
public IEnumerable GetDictionaryItemChildren(Guid parentId)
=> _dictionaryItemService.GetChildrenAsync(parentId).GetAwaiter().GetResult();
///
/// Gets a list of descendants for a
///
/// Id of the parent, null will return all dictionary items
/// An enumerable list of objects
[Obsolete("Please use IDictionaryItemService for dictionary item operations. Will be removed in V15.")]
public IEnumerable GetDictionaryItemDescendants(Guid? parentId)
=> _dictionaryItemService.GetDescendantsAsync(parentId).GetAwaiter().GetResult();
///
/// Gets the root/top objects
///
/// An enumerable list of objects
[Obsolete("Please use IDictionaryItemService for dictionary item operations. Will be removed in V15.")]
public IEnumerable GetRootDictionaryItems()
=> _dictionaryItemService.GetAtRootAsync().GetAwaiter().GetResult();
///
/// Checks if a with given key exists
///
/// Key of the
/// True if a exists, otherwise false
[Obsolete("Please use IDictionaryItemService for dictionary item operations. Will be removed in V15.")]
public bool DictionaryItemExists(string key)
=> _dictionaryItemService.ExistsAsync(key).GetAwaiter().GetResult();
///
/// Saves a object
///
/// to save
/// Optional id of the user saving the dictionary item
[Obsolete("Please use IDictionaryItemService for dictionary item operations. Will be removed in V15.")]
public void Save(IDictionaryItem dictionaryItem, int userId = Constants.Security.SuperUserId)
{
Guid currentUserKey = _userIdKeyResolver.GetAsync(userId).GetAwaiter().GetResult();
if (dictionaryItem.Id > 0)
{
_dictionaryItemService.UpdateAsync(dictionaryItem, currentUserKey).GetAwaiter().GetResult();
}
else
{
_dictionaryItemService.CreateAsync(dictionaryItem, currentUserKey).GetAwaiter().GetResult();
}
}
///
/// Deletes a object and its related translations
/// as well as its children.
///
/// to delete
/// Optional id of the user deleting the dictionary item
[Obsolete("Please use IDictionaryItemService for dictionary item operations. Will be removed in V15.")]
public void Delete(IDictionaryItem dictionaryItem, int userId = Constants.Security.SuperUserId)
{
Guid currentUserKey = _userIdKeyResolver.GetAsync(userId).GetAwaiter().GetResult();
_dictionaryItemService.DeleteAsync(dictionaryItem.Key, currentUserKey).GetAwaiter().GetResult();
}
///
/// Gets a by its id
///
/// Id of the
///
///
///
[Obsolete("Please use ILanguageService for language operations. Will be removed in V15.")]
public ILanguage? GetLanguageById(int id)
{
using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true))
{
return _languageRepository.Get(id);
}
}
///
/// Gets a by its iso code
///
/// Iso Code of the language (ie. en-US)
///
///
///
[Obsolete("Please use ILanguageService for language operations. Will be removed in V15.")]
public ILanguage? GetLanguageByIsoCode(string? isoCode)
{
ArgumentException.ThrowIfNullOrEmpty(isoCode);
return _languageService.GetAsync(isoCode).GetAwaiter().GetResult();
}
///
[Obsolete("Please use ILanguageService for language operations. Will be removed in V15.")]
public int? GetLanguageIdByIsoCode(string isoCode)
=> _languageService.GetAsync(isoCode).GetAwaiter().GetResult()?.Id;
///
[Obsolete("Please use ILanguageService for language operations. Will be removed in V15.")]
public string? GetLanguageIsoCodeById(int id)
{
using (ScopeProvider.CreateCoreScope(autoComplete: true))
{
return _languageRepository.GetIsoCodeById(id);
}
}
///
[Obsolete("Please use ILanguageService for language operations. Will be removed in V15.")]
public string GetDefaultLanguageIsoCode()
=> _languageService.GetDefaultIsoCodeAsync().GetAwaiter().GetResult();
///
[Obsolete("Please use ILanguageService for language operations. Will be removed in V15.")]
public int? GetDefaultLanguageId()
{
using (ScopeProvider.CreateCoreScope(autoComplete: true))
{
return _languageRepository.GetDefaultId();
}
}
///
/// Gets all available languages
///
/// An enumerable list of objects
[Obsolete("Please use ILanguageService for language operations. Will be removed in V15.")]
public IEnumerable GetAllLanguages()
=> _languageService.GetAllAsync().GetAwaiter().GetResult();
///
/// Saves a object
///
/// to save
/// Optional id of the user saving the language
[Obsolete("Please use ILanguageService for language operations. Will be removed in V15.")]
public void Save(ILanguage language, int userId = Constants.Security.SuperUserId)
{
Guid currentUserKey = _userIdKeyResolver.GetAsync(userId).GetAwaiter().GetResult();
Attempt result = language.Id > 0
? _languageService.UpdateAsync(language, currentUserKey).GetAwaiter().GetResult()
: _languageService.CreateAsync(language, currentUserKey).GetAwaiter().GetResult();
// mimic old Save behavior
if (result.Status == LanguageOperationStatus.InvalidFallback)
{
throw new InvalidOperationException($"Cannot save language {language.IsoCode} with fallback {language.FallbackIsoCode}.");
}
}
///
/// Deletes a by removing it (but not its usages) from the db
///
/// to delete
/// Optional id of the user deleting the language
[Obsolete("Please use ILanguageService for language operations. Will be removed in V15.")]
public void Delete(ILanguage language, int userId = Constants.Security.SuperUserId)
{
Guid currentUserKey = _userIdKeyResolver.GetAsync(userId).GetAwaiter().GetResult();
_languageService.DeleteAsync(language.IsoCode, currentUserKey).GetAwaiter().GetResult();
}
[Obsolete("Please use IDictionaryItemService for dictionary item operations. Will be removed in V15.")]
public Dictionary GetDictionaryItemKeyMap()
{
using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true))
{
return _dictionaryRepository.GetDictionaryItemKeyMap();
}
}
}