/// <summary>
        ///     Creates the instance of the ExcelFileProvider, which reads and persists all translations as Excel-files.
        ///     A backup Excel-file will be created for all edits.
        /// </summary>
        /// <param name="translationFilePath">Path to the file containing the translations.</param>
        /// <param name="glossaryTag">
        ///     (Optional) Entries in the Excel table that start with this tag will be interpreted as part of the glossary.
        /// </param>
        /// <param name="oldTranslationFilePath">
        ///     (Optional) The path to where the original translation file will be copied as a backup.
        /// </param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown, if <paramref name="translationFilePath" /> is null.
        /// </exception>
        /// <exception cref="UnauthorizedAccessException">
        ///     Thrown, if the permissions are missing that are needed to create the directory for
        ///     <paramref name="translationFilePath" /> / <paramref name="oldTranslationFilePath" /> or one of them
        ///     is write-only, read-only, a directory, hidden, the needed permissions for opening or writing are
        ///     missing or the operation is not supported on the current platform.
        /// </exception>
        /// <exception cref="System.Security.SecurityException">
        ///     Thrown, if certain permissions are missing. (CLR level)
        /// </exception>
        /// <exception cref="FileNotFoundException">
        ///     Thrown, if <paramref name="translationFilePath" /> / <paramref name="oldTranslationFilePath" />
        ///     does not exist or cannot be found.
        /// </exception>
        /// <exception cref="IOException">
        ///     Thrown, if an unknown I/O-Error occurs.
        /// </exception>
        /// <exception cref="NotSupportedException">
        ///     Thrown, if <paramref name="translationFilePath" /> / <paramref name="oldTranslationFilePath" />
        ///     contains a colon anywhere other than as part of a volume identifier ("C:\").
        /// </exception>
        /// <exception cref="PathTooLongException">
        ///     Thrown, if <paramref name="translationFilePath" /> / <paramref name="oldTranslationFilePath" />
        ///     is too long.
        /// </exception>
        /// <exception cref="DirectoryNotFoundException">
        ///     Thrown, if the directory was not found.
        ///     For example because it is on an unmapped device.
        /// </exception>
        public ExcelFileProvider(string translationFilePath, string glossaryTag = null,
                                 string oldTranslationFilePath = null)
        {
            //set Status.
            Status = ProviderStatus.InitializationInProgress;

            //easy initializations.
            _logger = GlobalSettings.LibraryLoggerFactory.CreateLogger <ExcelFileProvider>();
            _logger.Log(LogLevel.Trace, "Initializing ExcelFileProvider.");
            _fileHandler = new ExcelFileHandler(typeof(ExcelFileProvider),
                                                //make sure all possible not-null values for glossaryTag can be recognized in sheet.
                                                glossaryTag == string.Empty ? null : glossaryTag);

            //null check.
            ExceptionLoggingUtils.ThrowIfNull(_logger, (object)translationFilePath, nameof(translationFilePath),
                                              "Unable to open null path.", "ExcelFileProvider received null parameter in constructor.");

            //start difficult initializations.
            if (oldTranslationFilePath != null)
            {
                _fileHandler.VerifyPath(oldTranslationFilePath);
                _backupPath = oldTranslationFilePath;
            }

            _fileHandler.VerifyPath(translationFilePath);
            _path             = translationFilePath;
            _fileHandler.Path = _path;

            Initialize();
        }
        /// <summary>
        ///     Goes through all elements nested inside <paramref name="rootElement" /> and writes the current
        ///     translation into each element.
        /// </summary>
        /// <param name="rootElement">
        ///     The element, based on which all nested elements will recursively be translated.
        ///     <paramref name="rootElement" /> itself will also be translated.
        /// </param>
        public static void TranslateGui(FrameworkElement rootElement)
        {
            //null check.
            ExceptionLoggingUtils.ThrowIfNull(Logger, rootElement, nameof(rootElement),
                                              "Unable to translate null UserControl / Window.",
                                              "TranslateGui received null as root element for translation.");

            //TranslateGuiElement will do nothing if visual is a non translatable like Grid.
            TranslateGuiElement(rootElement);

            foreach (var childVisual in LogicalTreeHelper.GetChildren(rootElement))
            {
                //if View or Window contain a TabControl - break foreach to prevent translating sub View.
                if (childVisual is TabControl)
                {
                    break;
                }

                if (childVisual is FrameworkElement element)
                {
                    //also iterate all childs of visual, if they are FrameworkElements.
                    //as DataGridColumns are not FrameworkElements, they require special treatment in TranslateGuiElement.
                    TranslateGui(element);
                }
            }
        }
Exemplo n.º 3
0
        /// <summary>
        ///     Handles Exception logging for the given <paramref name="path" />.
        ///     Returns the given <paramref name="path" /> with the appropriate ending, if it was not present.
        /// </summary>
        /// <param name="path">The path that should be verified.</param>
        /// <exception cref="ArgumentNullException">Thrown, if <paramref name="path" /> is null.</exception>
        /// <exception cref="ArgumentException">
        ///     Thrown, if <paramref name="path" /> contains only white space, includes
        ///     unsupported characters or if the system fails to get the fully qualified
        ///     location for the given path.
        /// </exception>
        /// <exception cref="System.Security.SecurityException">
        ///     Thrown, if the permissions for accessing the full path are missing.
        /// </exception>
        /// <exception cref="NotSupportedException">
        ///     Thrown, if <paramref name="path" /> contains a colon anywhere other than as part of a
        ///     volume identifier ("C:\").
        /// </exception>
        /// <exception cref="PathTooLongException">
        ///     Thrown, if <paramref name="path" /> is too long.
        /// </exception>
        /// <exception cref="UnauthorizedAccessException">
        ///     Thrown, if permissions to create the directory are missing.
        /// </exception>
        /// <exception cref="DirectoryNotFoundException">
        ///     Thrown, if the directory was not found.
        ///     For example because it is on an unmapped device.
        /// </exception>
        /// <exception cref="IOException">
        ///     Thrown, if a file with the name of the dictionary that should be created already exists.
        /// </exception>
        /// <exception cref="FileNotFoundException">
        ///     Thrown, if <paramref name="path" /> is a dictionary.
        /// </exception>
        public void VerifyPath(string path)
        {
            ExceptionLoggingUtils.ThrowIfNull(_logger, nameof(VerifyPath), (object)path, nameof(path),
                                              "Unable to open path, because it is null.");

            var fullPath = GetFullPathWrapper(path);

            if (File.Exists(fullPath))
            {
                return;
            }

            ExceptionLoggingUtils.ThrowIf(Directory.Exists(fullPath), _logger, new FileNotFoundException(
                                              "Unable to find file, because directory with same name exists.", path),
                                          "Given path is directory instead of file.");

            CreateDirectoryWrapper(fullPath);
        }
        /// <summary>
        ///     Updates the internal dictionary of translations at <paramref name="key" /> with the given dictionary.
        ///     Only languages contained in <paramref name="texts" /> will be updated.
        ///     Will automatically write to file, if this is the first Update call
        ///     and no file existed upon creation of this object.
        /// </summary>
        /// <exception cref="ArgumentNullException">Thrown, if <paramref name="key" /> is null.</exception>
        /// <param name="key">The entry for which translations should be updated.</param>
        /// <param name="texts">
        ///     The new translations. If list is null or empty, no changes will be made to the dictionary.
        /// </param>
        public void Update(string key, IEnumerable <TextLocalization> texts)
        {
            //null checks.
            ExceptionLoggingUtils.ThrowIfNull(_logger, nameof(Update), (object)key, nameof(key),
                                              "Unable to update dictionary for null key.");
            if (texts == null)
            {
                //no exception has to be thrown here, because null is treated like empty list and
                //no translations will be updated.
                _logger.Log(LogLevel.Debug, "Unable to update dictionary for null translations. " +
                            "No translations were updated.");
                return;
            }

            //logging.
            IList <TextLocalization> textsEnumerated = texts.ToList();
            var textsString = string.Join(", ", textsEnumerated.Select(l => l.ToString()));

            _logger.Log(LogLevel.Trace, $"Update was called with {{{textsString}}} as translations for key ({key}).");

            //dictionary updates.
            if (!UpdateDictionary(key, textsEnumerated))
            {
                _logger.Log(LogLevel.Debug, "Did not update dictionary.");
                return;
            }

            //create file based on first entry,
            //if dictionary was updated and the file was created by JsonFileProvider itself.
            if (Status == ProviderStatus.Empty)
            {
                _logger.Log(LogLevel.Debug, "First update after empty sheet was created.");
                _fileHandler.ExcelWriteActions(_dictOfDicts);

                Status = ProviderStatus.Initialized;
                _logger.Log(LogLevel.Information, "Finished updating dictionary. " +
                            "ExcelFileProvider is now in State Initialized.");
            }
            else
            {
                _logger.Log(LogLevel.Debug, "Finished updating dictionary.");
            }
        }
        /// <summary>
        ///     Creates the instance of the JsonFileProvider, which reads and persists all translations from Json-files.
        /// </summary>
        /// <param name="translationFilePath">The path under which the dictionary will be saved.</param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown, if <paramref name="translationFilePath" /> is null.
        /// </exception>
        /// <exception cref="UnauthorizedAccessException">
        ///     Thrown, if the permissions are missing that are needed to create the directory for
        ///     <paramref name="translationFilePath" /> or <paramref name="translationFilePath" /> is write-only,
        ///     read-only, a directory, hidden, the needed permissions for opening or writing are missing or
        ///     the operation is not supported on the current platform.
        /// </exception>
        /// <exception cref="System.Security.SecurityException">
        ///     Thrown, if certain permissions are missing. (CLR level)
        /// </exception>
        /// <exception cref="FileNotFoundException">
        ///     Thrown, if <paramref name="translationFilePath" /> does not exist or cannot be found.
        ///     For example because it is a direcory.
        /// </exception>
        /// <exception cref="IOException">
        ///     Thrown, if an unknown I/O-Error occurs.
        /// </exception>
        /// <exception cref="NotSupportedException">
        ///     Thrown, if <paramref name="translationFilePath" /> contains a colon anywhere other than as part of a
        ///     volume identifier ("C:\").
        /// </exception>
        /// <exception cref="PathTooLongException">
        ///     Thrown, if <paramref name="translationFilePath" /> is too long.
        /// </exception>
        /// <exception cref="DirectoryNotFoundException">
        ///     Thrown, if the directory was not found.
        ///     For example because it is on an unmapped device.
        /// </exception>
        public JsonFileProvider(string translationFilePath)
        {
            //set Status.
            Status = ProviderStatus.InitializationInProgress;

            //easy initializations.
            _logger = GlobalSettings.LibraryLoggerFactory.CreateLogger <JsonFileProvider>();
            _logger.Log(LogLevel.Trace, "Initializing JsonFileProvider.");
            _fileHandler = new UniversalFileHandler(typeof(JsonFileProvider));

            //null check.
            ExceptionLoggingUtils.ThrowIfNull(_logger, (object)translationFilePath, nameof(translationFilePath),
                                              "Unable to open null path.", "JsonFileProvider received null parameter in constructor.");

            //start proper initialization.
            _fileHandler.VerifyPath(translationFilePath);
            _path = translationFilePath;
            Initialize();
        }