private void TranslateOneFolder(string fileFolder, string dictionaryFolder, bool log = true)
        {
            void LogInner(string contents = "", bool writeNewLine = true)
            {
                if (log)
                {
                    Log(contents, writeNewLine);
                }
            }

            LogInner("Opening dictionaries...");

            string[] paths = File.ReadAllLines(Path.Combine(dictionaryFolder, "Paths.dict"));

            List <DictionaryFile> dicts =
                Directory.EnumerateFiles(Path.Combine(dictionaryFolder, "Dictionaries"))
                .Select(file => new DictionaryFile(file))
                .ToList();

            ProgressValue.Value = 0;
            ProgressMax.Value   = paths.Length;

            LogInner("Translating files:");

            for (int i = 0; i < paths.Length; i++)
            {
                ProgressValue.Value++;
                string xmlFilePath = Path.Combine(fileFolder, paths[i]);

                LogInner("  -- " + xmlFilePath, false);

                if (!IOUtils.FileExists(xmlFilePath))
                {
                    LogInner(" - skipped");

                    continue;
                }

                DictionaryFile dict = dicts.Find(d => Path.GetFileNameWithoutExtension(d.FileName) == i.ToString());

                if (dict == null)
                {
                    LogInner(" - skipped");

                    continue;
                }

                try
                {
                    var xmlFile = new XmlFile(xmlFilePath);

                    xmlFile.TranslateWithDictionary(dict, true);

                    LogInner(" - translated");
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"Message: {ex.Message}\nStackTrace: {ex.StackTrace}");
                    LogInner(" - error");
                }
            }

            if (!IOUtils.FileExists(Path.Combine(dictionaryFolder, "Languages.dict")))
            {
                return;
            }

            LogInner("Adding languages:");

            string[] languages = File.ReadAllLines(Path.Combine(dictionaryFolder, "Languages.dict"));

            ProgressValue.Value = 0;
            ProgressMax.Value   = languages.Length;

            foreach (var language in languages)
            {
                ProgressValue.Value++;

                LogInner("  -- " + language);

                IOUtils.CopyFilesRecursively(
                    Path.Combine(dictionaryFolder, "Languages", language),
                    Path.Combine(fileFolder, "res", language)
                    );
            }
        }
        private void CreateOneFolderDictionary(string sourceFolder, string modifiedFolder, string resultFolder, bool log = true)
        {
            void LogInner(string contents = "", bool writeNewLine = true)
            {
                if (log)
                {
                    Log(contents, writeNewLine);
                }
            }

            if (IOUtils.FolderExists(resultFolder))
            {
                IOUtils.DeleteFolder(resultFolder);
            }

            IOUtils.CreateFolder(resultFolder);

            var dictFileWriter    = new StreamWriter(Path.Combine(resultFolder, "Paths.dict"), false, Encoding.UTF8);
            var foldersFileWriter = new StreamWriter(Path.Combine(resultFolder, "Languages.dict"), false, Encoding.UTF8);

            if (new[] { sourceFolder, modifiedFolder, resultFolder }.Any(str => str.IsNullOrEmpty() || !IOUtils.FolderExists(str)))
            {
                return;
            }

            string dictsFolder = Path.Combine(resultFolder, "Dictionaries");

            IOUtils.CreateFolder(dictsFolder);

            string languagesFolder = Path.Combine(resultFolder, "Languages");

            IOUtils.CreateFolder(languagesFolder);

            LogInner("Searching for xml files in the first folder...");

            List <XmlFile> firstXmlFiles =
                Directory.EnumerateFiles(sourceFolder, "*.xml", SearchOption.AllDirectories)
                .SelectSafe(file => new XmlFile(file))
                .ToList();


            LogInner("Searching for xml files in the second folder...");

            List <XmlFile> secondXmlFiles =
                Directory.EnumerateFiles(modifiedFolder, "*.xml", SearchOption.AllDirectories)
                .SelectSafe(file => new XmlFile(file))
                .ToList();

            secondXmlFiles.Sort((fFile, sFile) => string.Compare(fFile.FileName, sFile.FileName, StringComparison.Ordinal));

            ProgressValue.Value = 0;
            ProgressMax.Value   = firstXmlFiles.Count;

            int filenameIndex = 0;
            var errors        = new List <string>();

            LogInner("Comparing...");

            var comparison =
                new ComparisonWrapper <XmlFile>((fFile, sFile) =>
                                                string.Compare(
                                                    fFile.FileName.Substring(modifiedFolder.Length + 1),
                                                    sFile.FileName.Substring(sourceFolder.Length + 1),
                                                    StringComparison.Ordinal
                                                    )
                                                );

            foreach (XmlFile file in firstXmlFiles)
            {
                try
                {
                    ProgressValue.Value++;

                    if (file.Details.Count == 0)
                    {
                        continue;
                    }

                    int index = secondXmlFiles.BinarySearch(file, comparison);

                    if (index < 0)
                    {
                        continue;
                    }

                    XmlFile item = secondXmlFiles[index];

                    var dict = CreateDictionary(file, item, Path.Combine(dictsFolder, $"{filenameIndex}.xml"));

                    if (dict.Details.Count == 0)
                    {
                        continue;
                    }

                    dict.SaveChanges();
                    filenameIndex++;

                    dictFileWriter.WriteLine(file.FileName.Substring(sourceFolder.Length + 1));
                }
                catch (Exception ex)
                {
                    errors.Add(file.FileName + " - " + ex.Message);
                }
            }

            string resFolder = Path.Combine(sourceFolder, "res");

            var sourceFolders   = Directory.EnumerateDirectories(resFolder, "values-*", SearchOption.TopDirectoryOnly).Select(Path.GetFileName).ToList();
            var modifiedFolders = Directory.EnumerateDirectories(resFolder, "values-*", SearchOption.TopDirectoryOnly).ToList();

            LogInner("Comparing languages...");

            ProgressValue.Value = 0;
            ProgressMax.Value   = modifiedFolders.Count;

            foreach (string folder in modifiedFolders)
            {
                ProgressValue.Value++;

                string part = Path.GetFileName(folder) ?? string.Empty;

                if (sourceFolders.Contains(part))
                {
                    continue;
                }

                foldersFileWriter.WriteLine(part);

                IOUtils.CopyFilesRecursively(folder, Path.Combine(languagesFolder, part));
            }

            if (log)
            {
                Log();
                Log("Number of created dictionaries: " + filenameIndex);

                if (errors.Count > 0)
                {
                    Log("Number of errors: " + errors.Count);
                    foreach (var error in errors)
                    {
                        Log("  -- " + error);
                    }
                }
            }

            dictFileWriter.Close();
            foldersFileWriter.Close();
        }