Beispiel #1
0
        public void CompareInvariantCultures_UsingExcept_NoChanges()
        {
            var incomingResource = new LocalizationResource("key")
            {
                Translations = new List <LocalizationResourceTranslation>
                {
                    new LocalizationResourceTranslation
                    {
                        Language = "",
                        Value    = "incoming value"
                    }
                }
            };

            var existingResource = new LocalizationResource("key")
            {
                Translations = new List <LocalizationResourceTranslation>
                {
                    new LocalizationResourceTranslation
                    {
                        Language = "",
                        Value    = "existing value"
                    }
                }
            };

            var sut = new TranslationComparer(true);

            var differences = incomingResource.Translations.Except(existingResource.Translations, sut).ToList();

            Assert.Empty(differences);
        }
        public void CompareUsingInvariant_UsingExcept_NewLanguageDetected()
        {
            var incomingResource = new LocalizationResource("key", false);

            incomingResource.Translations.AddRange(
                new List <LocalizationResourceTranslation>
            {
                new LocalizationResourceTranslation {
                    Language = "", Value = "incoming value"
                },
                new LocalizationResourceTranslation {
                    Language = "en", Value = "incoming EN value"
                }
            });

            var existingResource = new LocalizationResource("key", false);

            existingResource.Translations.Add(new LocalizationResourceTranslation {
                Language = "", Value = "existing value"
            });
            var sut = new TranslationComparer(true);

            var differences = incomingResource.Translations.Except(existingResource.Translations, sut).ToList();

            Assert.NotEmpty(differences);
        }
        public ICollection <DetectedImportChange> DetectChanges(ICollection <LocalizationResource> importingResources, IEnumerable <LocalizationResource> existingResources)
        {
            var result = new List <DetectedImportChange>();

            // deleted deletes
            var resourceComparer = new ResourceComparer();
            var deletes          = existingResources.Except(importingResources, resourceComparer);

            result.AddRange(deletes.Select(d => new DetectedImportChange(ChangeType.Delete, LocalizationResource.CreateNonExisting(d.ResourceKey), d)));

            foreach (var incomingResource in importingResources.Except(deletes, resourceComparer))
            {
                // clean up nulls from translations
                incomingResource.Translations = incomingResource.Translations.Where(t => t != null).ToList();

                var existing = existingResources.FirstOrDefault(r => r.ResourceKey == incomingResource.ResourceKey);
                if (existing != null)
                {
                    var comparer             = new TranslationComparer(true);
                    var existingTranslations = existing.Translations.Where(_ => _ != null).ToList();
                    var differences          = incomingResource.Translations.Except(existingTranslations, comparer).Where(_ => _ != null).ToList();

                    // some of the translations are different - so marking this resource as potential update
                    if (differences.Any())
                    {
                        // here we need to check whether incoming resource is overriding existing translation (exists translation in given language)
                        // or we are maybe importing exported language that had no translations
                        // this could happen if you export language with no translations in xliff format
                        // then new exported target language will have translation as empty string
                        // these cases we need to filter out

                        var detectedChangedLanguages = differences.Select(_ => _.Language).Distinct().ToList();
                        var existingLanguages        = existingTranslations.Select(_ => _.Language).Distinct().ToList();

                        if (!differences.All(r => string.IsNullOrEmpty(r.Value)) || !detectedChangedLanguages.Except(existingLanguages).Any())
                        {
                            result.Add(new DetectedImportChange(ChangeType.Update, incomingResource, existing)
                            {
                                ChangedLanguages = detectedChangedLanguages
                            });
                        }
                    }
                }
                else
                {
                    result.Add(new DetectedImportChange(ChangeType.Insert, incomingResource, LocalizationResource.CreateNonExisting(incomingResource.ResourceKey))
                    {
                        ChangedLanguages = incomingResource.Translations.Select(t => t.Language).ToList()
                    });
                }
            }

            return(result);
        }
        public void TwoDifferentTranslations_InvariantCulture_NoChangesDetected()
        {
            var sut = new TranslationComparer(true);

            var result = sut.Equals(new LocalizationResourceTranslation {
                Language = "", Value = "Value 1"
            },
                                    new LocalizationResourceTranslation {
                Language = "", Value = "Value 2"
            });

            Assert.True(result);
        }
        public IEnumerable <DetectedImportChange> DetectChanges(IEnumerable <LocalizationResource> importingResources, IEnumerable <LocalizationResource> existingResources)
        {
            var result = new List <DetectedImportChange>();

            // deleted deletes
            var resourceComparer = new ResourceComparer();
            var deletes          = existingResources.Except(importingResources, resourceComparer);

            result.AddRange(deletes.Select(d => new DetectedImportChange(ChangeType.Delete, LocalizationResource.CreateNonExisting(d.ResourceKey), d)));

            foreach (var incomingResource in importingResources.Except(deletes, resourceComparer))
            {
                var existing = existingResources.FirstOrDefault(r => r.ResourceKey == incomingResource.ResourceKey);
                if (existing != null)
                {
                    var comparer    = new TranslationComparer();
                    var differences = incomingResource.Translations.Except(existing.Translations, comparer)
                                      .ToList();

                    // some of the translations are different - so marking this resource as potential update
                    if (differences.Any())
                    {
                        result.Add(new DetectedImportChange(ChangeType.Update, incomingResource, existing)
                        {
                            ChangedLanguages = differences.Select(t => t.Language).Distinct().ToList()
                        });
                    }
                }
                else
                {
                    result.Add(new DetectedImportChange(ChangeType.Insert, incomingResource, LocalizationResource.CreateNonExisting(incomingResource.ResourceKey)));
                }
            }

            return(result);
        }
        /// <summary>
        /// Converts translations to sql commands that'll insert and/or update translations to the database.
        /// 
        /// To determine whether an update or translation is needed, translations already in the database are queried and compared against
        /// the translations passed into this method.
        /// 
        /// A two finger algorithm is used against the sorted database stream to the sorted translation parameter for a time
        /// complexity of O(n+m).  All statements are wrapped into a transaction.
        /// </summary>
        public string syncSqlCmds(SortedSet<Translation> translations)
        {
            var categoriesClause = categoriesSqlClause(translations.ToList());  //todo: change algorithm to work with HashSet.Enumerator

            StringBuilder buff = new StringBuilder();

            using (var conn = new MySqlConnection(FlashCardAppDB.instance.connectionString)){
                var cmd = new MySqlCommand(
                    $"select italiano,category from translation where category in ({categoriesClause}) order by category,italiano", conn);
                conn.Open();
                MySqlDataReader rdr = cmd.ExecuteReader();

                var translateEnumerator = translations.GetEnumerator();
                var comparer = new TranslationComparer();
                var hasNext = translateEnumerator.MoveNext();

                Func <string,string> printNull = x => (x != null) ? $"'{x}'" : "null";

                Translation dbt;
                if (hasNext){
                    buff.AppendLine("start transaction;");
                    while (hasNext){ //read-only, forward-only stream
                        dbt = (rdr.Read()) ?
                            new Translation{ italiano = rdr.GetString("italiano"), category = rdr.GetString("category") } : null;

                        if (dbt == null || comparer.Compare(translateEnumerator.Current, dbt) < 0){ //Less than or remaining parsed translations
                            buff.AppendLine("insert into translation (italiano,category,espanol,priority) " +
                                $"values ('{translateEnumerator.Current.italiano}','{translateEnumerator.Current.category}',{printNull(translateEnumerator.Current.espanol)},{translateEnumerator.Current.priority});");
                            hasNext = translateEnumerator.MoveNext();
                        }else if (comparer.Compare(translateEnumerator.Current, dbt) == 0){ //Equal
                            buff.AppendLine($"update translation set espanol={printNull(translateEnumerator.Current.espanol)},priority={translateEnumerator.Current.priority} " +
                                $"where italiano='{translateEnumerator.Current.italiano}' and category='{translateEnumerator.Current.category}';");
                            hasNext = translateEnumerator.MoveNext();
                        } //Greater than... skip
                    }
                    buff.AppendLine("commit;");
                }
                return buff.ToString();
            }
        }