public void ToString_ICultureDictionaryThrowsException_ReturnNull()
        {
            // Arrange
            Mock <ILogger>            logger            = new Mock <ILogger>();
            Mock <ICultureDictionary> cultureDictionary = new Mock <ICultureDictionary>();

            cultureDictionary.SetupGet(x => x[It.IsAny <string>()]).Throws <Exception>();

            TestFactory.CultureDictionaryFactory
            .Setup(x => x.CreateDictionary())
            .Returns(cultureDictionary.Object);

            Log.Logger = logger.Object;

            DictionaryModel subject = new DictionaryModelWrapper(It.IsAny <Guid>(), It.IsAny <string>());

            // Act
            string result = subject.ToString(It.IsAny <CultureInfo>());

            // Assert
            Assert.That(result, Is.Null);
            logger.Verify(x => x.Write(
                              It.Is <LogEventLevel>(level => level == LogEventLevel.Error),
                              It.IsAny <Exception>(),
                              It.IsAny <string>()
                              ));
        }
        protected DictionaryModel Create(string itemKey, DictionaryModel parent, Func <CultureInfo, string> valueResolver)
        {
            DictionaryModelWrapper parentModel = parent as DictionaryModelWrapper;

            // Get the dictionary item from Umbraco. Otherwise crete a new.
            IDictionaryItem dictionaryItem = _localizationService.GetDictionaryItemByKey(itemKey) ??
                                             _localizationService.CreateDictionaryItemWithIdentity(itemKey,
                                                                                                   parentModel?.Key);

            // Create the model
            DictionaryModelWrapper model = new DictionaryModelWrapper(dictionaryItem, parentModel);

            // If no value resolver are provided, then return the model
            if (valueResolver == null)
            {
                return(model);
            }

            // A save indicator
            bool save = false;

            // Iterate through all languages
            foreach (ILanguage language in Languages)
            {
                IDictionaryTranslation translation =
                    dictionaryItem.Translations.SingleOrDefault(x => x.Language == language);
                // If the dictionary translation already has a value, then don't change it
                if (!string.IsNullOrEmpty(translation?.Value))
                {
                    continue;
                }

                // Get the culture specific default value from the value resolver
                string value = valueResolver(language.CultureInfo);
                // If there is no value, then do nothing
                if (value == null)
                {
                    continue;
                }

                // Add the value to the Umbraco dictionary item
                _localizationService.AddOrUpdateDictionaryValue(dictionaryItem, language, value);
                // Indicate that a value has been added to the dictionary, and ensure save
                save = true;

                // Log the addition
                Log.Information(
                    $"Adding '{language}' value:'{value}' for dictionary item: '{dictionaryItem.ItemKey}'");
            }

            // Save the dictionary item
            if (save)
            {
                _localizationService.Save(dictionaryItem);
            }

            // Return the model
            return(model);
        }
        /// <summary>
        /// Get dictionary models that are children to the parent model or if no parent model provided, then the root dictionary items
        /// </summary>
        /// <param name="dictionaryItems">The collection of all dictionary items</param>
        /// <param name="parentModel">The parent model</param>
        /// <returns>A collection of dictionary models</returns>
        private static IEnumerable <DictionaryModel> GetDictionaryModels(IDictionaryItem[] dictionaryItems, DictionaryModelWrapper parentModel = null)
        {
            if (dictionaryItems == null)
            {
                yield break;
            }

            // Iterate through dictionary items that are children to the parent model or if no parent model provided, then the root dictionary items
            foreach (IDictionaryItem dictionaryItem in dictionaryItems.Where(x => x.ParentId == parentModel?.Key))
            {
                // Create a model, return it and continue
                DictionaryModelWrapper model = new DictionaryModelWrapper(dictionaryItem, parentModel);
                yield return(model);

                // Generate child models and return them
                foreach (DictionaryModel childModel in GetDictionaryModels(dictionaryItems, model))
                {
                    yield return(childModel);
                }
            }
        }
        private void LocalizationServiceOnSavingDictionaryItem(ILocalizationService sender, SaveEventArgs<IDictionaryItem> e)
        {
            // If not enabled or if we do use nested structure or if e can't cancel, then return. Nothing to validate or cancel.
            if(!_configuration.Enable || !_configuration.UseNestedStructure || !e.CanCancel)
                return;

            // See if there are any newly created items
            bool containsNewItems = e.SavedEntities.Any(x => !x.HasIdentity);
            // An indicator of whether any item key has changed
            bool anyItemKeyChanged = false;
            
            foreach (IDictionaryItem dictionaryItem in e.SavedEntities)
            {
                IDictionaryItem parentDictionaryItem = dictionaryItem.ParentId.HasValue
                    ? sender.GetDictionaryItemById(dictionaryItem.ParentId.Value)
                    : null;
                // Create the parent model
                DictionaryModel parentModel = parentDictionaryItem != null ? new DictionaryModelWrapper(parentDictionaryItem) : null;
                // Create the model
                DictionaryModel model = new DictionaryModelWrapper(dictionaryItem, parentModel);

                if (dictionaryItem.HasIdentity && !anyItemKeyChanged)
                {
                    // Load the current dictionary item, to see if the ItemKey has changed.
                    IDictionaryItem currentDictionaryItem = sender.GetDictionaryItemById(dictionaryItem.Id);
                    anyItemKeyChanged = currentDictionaryItem.ItemKey != dictionaryItem.ItemKey;
                }

                if (model.IsValidForNestedStructure()) 
                    continue;

                e.CancelOperation(new EventMessage("DictionaryItem", "Invalid key. The key must start with the full key of the parent + .ItemKey", EventMessageType.Error));
            }
            
            // If the operation isn't cancelled and there are new items, or any existing dictionary has a new item key
            // then mark the models to be out-of-date.
            if(!e.Cancel && (containsNewItems || anyItemKeyChanged))
                SetOutOfDateMark();
        }
        private dynamic GenerateVueI18N(DictionaryModelWrapper[] allDictionaryItems, DictionaryModelWrapper parent, out bool hasChildItems)
        {
            Dictionary <dynamic, dynamic> items = new Dictionary <dynamic, dynamic>();

            DictionaryModelWrapper[] childDictionaryItems = allDictionaryItems.Where(x => x.GetParentModel() == parent).ToArray();
            hasChildItems = childDictionaryItems.Any();
            foreach (DictionaryModelWrapper dictionaryItem in childDictionaryItems)
            {
                string itemKey = dictionaryItem.GenerateCodeItemKey(_configuration.UseNestedStructure);

                itemKey = itemKey.ToCodeString(true).ToCamelCase();
                try
                {
                    items.Add($"${itemKey}", dictionaryItem.ToString());
                }
                catch (Exception e)
                {
                    Log.Error(e, $"Unable to add '${itemKey}' dictionaryItem");
                }

                dynamic childItems = GenerateVueI18N(allDictionaryItems, dictionaryItem, out bool addChildItems);
                if (!addChildItems)
                {
                    continue;
                }

                try
                {
                    items.Add($"{itemKey}", childItems);
                }
                catch (Exception e)
                {
                    Log.Error(e, $"Unable to add '${itemKey}' dictionaryItem");
                }
            }

            return(items);
        }
 private dynamic GenerateVueI18N(DictionaryModelWrapper[] allDictionaryItems, DictionaryModelWrapper parent)
 {
     return(GenerateVueI18N(allDictionaryItems, parent, out bool _));
 }