/// <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); } } }
/// <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(); }