/// <summary> /// Finds the translation entry out of <paramref name="baseDictionary" /> for <paramref name="targetLanguage" /> /// and <paramref name="key" />, if no entry is found in <paramref name="targetLanguage" />, dictionaries of /// compatible languages are searched. Returns default value (null) if no entry for /// <paramref name="key" /> can be found in dictionaries campatible with <paramref name="targetLanguage" />. /// </summary> /// <param name="baseDictionary">Dictionary collection to be searched.</param> /// <param name="targetLanguage">CultureInfo with which the used dictionary has to be compatible.</param> /// <param name="key">Key to search for in available dictionarys.</param> /// <param name="inputLanguage"> /// The language the application was originally designed in. Used as a fallback. /// </param> /// <param name="useOnlyExactLanguage">If true, compatible languages and fallbacks are ignored.</param> /// <returns> /// Value for <paramref name="key" /> out of dictionary for <paramref name="targetLanguage" />, its /// parent (usually same as two letter name), its two letter name (e.g. en for en-US), its patents two /// letter name, <see cref="CultureInfo.InvariantCulture" />, the <paramref name="inputLanguage" /> or /// null if no compatible dictionary can be found in <paramref name="baseDictionary" /> /// (Dictionaries will be searched in this order). /// </returns> /// <exception cref="ArgumentNullException"> /// Thrown if either <paramref name="baseDictionary" />, <paramref name="targetLanguage" /> or /// <paramref name="key" /> is null. /// </exception> public static string GetLanguageDictValueOrDefault( Dictionary <CultureInfo, Dictionary <string, string> > baseDictionary, CultureInfo targetLanguage, string key, CultureInfo inputLanguage, bool useOnlyExactLanguage) { //null checks. ExceptionLoggingUtils.VerifyMultiple(baseDictionary, nameof(baseDictionary)) .AlsoVerify(targetLanguage, nameof(targetLanguage)) .AlsoVerify(key, nameof(key)) .AlsoVerify(inputLanguage, nameof(inputLanguage)) .ThrowIfNull(Logger, nameof(GetLanguageDictValueOrDefault), "Unable to pick dictionary with null parameter."); //searching baseDictionary. if (baseDictionary.ContainsKey(targetLanguage) && baseDictionary[targetLanguage].ContainsKey(key)) { return(baseDictionary[targetLanguage][key]); } if (useOnlyExactLanguage) { return(null); } var parentCultureInfo = targetLanguage.Parent; if (baseDictionary.ContainsKey(parentCultureInfo) && baseDictionary[parentCultureInfo].ContainsKey(key)) { return(baseDictionary[parentCultureInfo][key]); } var twoLetterTarget = new CultureInfo(targetLanguage.TwoLetterISOLanguageName); if (baseDictionary.ContainsKey(twoLetterTarget) && baseDictionary[twoLetterTarget].ContainsKey(key)) { return(baseDictionary[twoLetterTarget][key]); } var twoLetterParent = new CultureInfo(parentCultureInfo.TwoLetterISOLanguageName); if (baseDictionary.ContainsKey(twoLetterParent) && baseDictionary[twoLetterParent].ContainsKey(key)) { return(baseDictionary[twoLetterParent][key]); } if (baseDictionary.ContainsKey(CultureInfo.InvariantCulture) && baseDictionary[CultureInfo.InvariantCulture].ContainsKey(key)) { return(baseDictionary[CultureInfo.InvariantCulture][key]); } if (baseDictionary.ContainsKey(inputLanguage) && baseDictionary[inputLanguage].ContainsKey(key)) { return(baseDictionary[inputLanguage][key]); } //default. return(null); }
/// <summary> /// Returns the DataGrid of the given DataGridColumn. /// </summary> /// <exception cref="InvalidOperationException"> /// Thrown, if DataGrid of given DataGridColumn cannot be accessed. /// </exception> /// <exception cref="ArgumentNullException"> /// Thrown, if given DataGridColumn is null. /// </exception> public static DataGrid GetDataGridParent(DataGridColumn column) { ExceptionLoggingUtils.ThrowIfNull(Logger, nameof(GetDataGridParent), column, nameof(column), "Unable find parent DataGrid of null."); var propertyInfo = column.GetType() .GetProperty("DataGridOwner", BindingFlags.Instance | BindingFlags.NonPublic); return(propertyInfo?.GetValue(column, null) as DataGrid); }
/// <summary>Returns the CultureInfo object corresponding to language code given</summary> /// <param name="cultureName">String representation of CultureInfo as language tag.</param> /// <param name="onlyBracketsAtEndOfString"> /// Will default back to false if no matching brackets are found. /// </param> /// <exception cref="CultureNotFoundException"> /// Thrown if language tag cannot be found within list of languages supported by .NET. /// </exception> /// <exception cref="ArgumentNullException">Thrown if culture string given is null.</exception> public static CultureInfo GetCultureInfo(string cultureName, bool onlyBracketsAtEndOfString) { ExceptionLoggingUtils.ThrowIfNull(Logger, nameof(GetCultureInfo), (object)cultureName, nameof(cultureName), "Unable to generate CultureInfo object from null sting."); var culture = GetCultureInfoOrDefaultInternal(cultureName, onlyBracketsAtEndOfString, out var searched); ExceptionLoggingUtils.ThrowIf(culture == null, Logger, new CultureNotFoundException(cultureName, searched, "Unable to generate CultureInfo object from string."), "GetCultureInfo received invalid culture name."); return(culture); }
/// <summary> /// Returns ResourcesManager of <see cref="GlobalSettings.ResourcesAssembly" /> or the current entry assembly, /// if not set. /// </summary> /// <exception cref="ResourcesNotFoundException"> /// Thrown, if both <see cref="GlobalSettings.ResourcesAssembly" /> is not set and the entry assembly /// cannot be accesed. /// </exception> public static ResourceManager GetResourcesManager() { if (GlobalSettings.ResourcesAssembly == null) { GlobalSettings.ResourcesAssembly = Assembly.GetEntryAssembly(); ExceptionLoggingUtils.ThrowIf <ResourcesNotFoundException>( GlobalSettings.ResourcesAssembly == null, Logger, "GlobalSettings.ResourcesAssembly was not set and entry assembly cannot be accessed."); } var nameOfAppToBeTranslated = GlobalSettings.ResourcesAssembly.FullName.Split(',')[0]; return(new ResourceManager(nameOfAppToBeTranslated + ".Properties.Resources", GlobalSettings.ResourcesAssembly)); }
/// <summary> /// Collectes translations of <paramref name="text" /> for <paramref name="targetLanguage" /> /// that share the same translation in <paramref name="inputLanguage" />. /// </summary> /// <param name="text">The text in <paramref name="inputLanguage" />.</param> /// <param name="targetLanguage">The language for which translations should be collected.</param> /// <param name="inputLanguage">The language of <paramref name="text" />.</param> /// <param name="allTranslations"> /// The collection of all translation to pull the needed translations from. /// </param> /// <returns> /// All possible translations of <paramref name="text" /> into <paramref name="targetLanguage" /> /// based on which keys inside the inner Dictionary of <paramref name="allTranslations" /> share /// the same translations in <paramref name="inputLanguage" />. /// </returns> /// <exception cref="ArgumentNullException"> /// Thrown, if <paramref name="targetLanguage" />, <paramref name="inputLanguage" /> or /// <paramref name="allTranslations" /> is null. /// </exception> /// <exception cref="InputLanguageNotFoundException"> /// Thrown, if <paramref name="allTranslations" /> does not contain <paramref name="inputLanguage" />. /// </exception> public static IEnumerable <string> ExtractKnownTranslations(string text, CultureInfo targetLanguage, CultureInfo inputLanguage, Dictionary <CultureInfo, Dictionary <string, string> > allTranslations) { //null and argument checks. ExceptionLoggingUtils.VerifyMultiple(targetLanguage, nameof(targetLanguage)) .AlsoVerify(inputLanguage, nameof(inputLanguage)) .AlsoVerify(allTranslations, nameof(allTranslations)) .ThrowIfNull(Logger, nameof(ExtractKnownTranslations), "Unable to extract known translation for null parameter."); ExceptionLoggingUtils.ThrowIfInputLanguageMissing(Logger, allTranslations.Keys.ToList(), inputLanguage, "InputLanguage is not part of languages collection.", "Unable to generate translation recommendations for Localizaions without InputLanguage."); allTranslations.TryGetValue(inputLanguage, out var sourceDictionary); ICollection <string> knownTranslations = new Collection <string>(); if (string.IsNullOrWhiteSpace(text) || Equals(targetLanguage, inputLanguage)) { //no Exceptions should be thrown here. return(knownTranslations); } //get all entries out of sourceDictionary, where value matches given text var fittingDictionaryEntries = sourceDictionary.Where(x => text.Equals(x.Value)); //collect possible translations foreach (var entry in fittingDictionaryEntries) { var value = ""; allTranslations.TryGetValue(targetLanguage, out var langDict); langDict?.TryGetValue(entry.Key, out value); //do not recommend the same translation twice if (!string.IsNullOrWhiteSpace(value) && !knownTranslations.Contains(value)) { knownTranslations.Add(value); } } return(knownTranslations); }
/// <summary> /// Returns a placeholder text (e.g. "fr--Total amount") and evaluates, what translation /// should be used as basis for the text (part after "fr--"). /// </summary> /// <param name="targetLanguage">The language for which the placeholder needs to be generated.</param> /// <param name="localizedTexts"> /// The collection of all known translations. /// </param> /// <param name="preferPreferredOverInputLangauge"> /// Determines which out of <paramref name="inputLanguage" /> and <paramref name="preferredLanguage" /> /// should be used by default. /// This value will be ignored, if there are conflicts with the preference (e.g. /// <paramref name="targetLanguage" /> being identical to <paramref name="preferedLanguage" /> or /// <paramref name="inputLanguage" />). /// </param> /// <param name="inputLanguage">The language in which the application was originally created in.</param> /// <param name="preferredLanguage"> /// The language to fall back to, if <paramref name="inputLanguage" /> is the <paramref name="targetLanguage" /> /// or to aid as basis for further translation (e.g application was originally french, is then translated /// to english and from english to multiple others). /// </param> /// <returns> /// The full placeholder string consisting of language code, "--" and the translation of /// <paramref name="inputLanguage" /> or <paramref name="preferredLanguage" />. /// </returns> /// <exception cref="InputLanguageNotFoundException"> /// Thrown, if <paramref name="localizedTexts" /> does not contain <paramref name="inputLanguage" />. /// </exception> public static string GetRecommendedText(CultureInfo targetLanguage, ICollection <TextLocalization> localizedTexts, bool preferPreferredOverInputLangauge, CultureInfo inputLanguage, CultureInfo preferredLanguage) { ExceptionLoggingUtils.ThrowIfInputLanguageMissing(Logger, localizedTexts.Select(loc => loc.Language), inputLanguage, "InputLanguage is not part of languages collection.", "Unable to generate translation recommendations for Localizaions without InputLanguage."); var usePreferredInsted = EvaluateLanguagePreference(preferPreferredOverInputLangauge, localizedTexts, targetLanguage, preferredLanguage, inputLanguage); //Will find a fitting entry, because EvaluateLanguagePreference returns false //to usePreferredInsted if list does not contain the preferredLanguage and this function //throws InputLanguageNotFoundException is inputLanguage is not in the list. var recommendedTranslation = localizedTexts.First(loc => Equals(loc.Language, usePreferredInsted ? preferredLanguage : inputLanguage)).Text; return(targetLanguage.Name + "--" + recommendedTranslation); }
/// <summary> /// Tries to find the closest parent of given parameter <paramref name="child" /> /// in the VisualTree that satisfies the typeparameter <paramref name="T" />. /// Returns null if no fitting parent is found. /// </summary> /// <exception cref="ArgumentNullException">Thrown, if <paramref name="child" /> is null.</exception> public static T FindVisualParent <T>(DependencyObject child) where T : DependencyObject { ExceptionLoggingUtils.ThrowIfNull(Logger, nameof(FindVisualParent), child, nameof(child), "Unable to find visual parent of null."); var parentObject = VisualTreeHelper.GetParent(child); //end of the tree, nothing found. if (parentObject == null) { return(null); } if (parentObject is T parent) { return(parent); } return(FindVisualParent <T>(parentObject)); }
/// <summary> /// Reads the properties <paramref name="controlId" />, <paramref name="currentText" />, /// <paramref name="controlType" /> and <paramref name="parentDialogName" /> of the given /// <paramref name="element" />. /// Returns true, if <paramref name="element" /> is eligible for translation. /// </summary> /// <param name="element">The element that should be inspected.</param> /// <param name="controlId"> /// The Name Property of <paramref name="element" />. This value is not null, if true is returned. /// </param> /// <param name="currentText"> /// The Content / Text / Header Property of <paramref name="element" /> that is currently displayed in the /// GUI. This value can be null, if true is returned. /// </param> /// <param name="controlType"> /// The Type of <paramref name="element" />. This value is not null, if true is returned. /// </param> /// <param name="parentDialogName"> /// The Name Property of the UserControl or Window, <paramref name="element" /> is contained inside. /// This value is not null, if true is returned. /// </param> /// <returns>True, if <paramref name="element" /> is eligible for translation.</returns> /// <exception cref="ArgumentNullException">Thrown, if <paramref name="element" /> is null.</exception> public static bool GetControlProperties(DependencyObject element, out string controlId, out string currentText, out string controlType, out string parentDialogName) { ExceptionLoggingUtils.ThrowIfNull(Logger, nameof(GetControlProperties), element, nameof(element), "Unable to get control properties of null element"); //determine Name, Type and current Text. if (!GetElementSpecificControlProperties(element, out controlId, out currentText, out controlType, out parentDialogName)) { return(false); } //determine Name of View or Window, if element isn't DataGridColumn. if (parentDialogName == null) { parentDialogName = GetParentDialogName(element); } //determine again, if element can be translated. //if properties like Name are not set in XAML, they can still be string.Empty instead of null. if (string.IsNullOrEmpty(controlId) || string.IsNullOrEmpty(controlType) || string.IsNullOrEmpty(parentDialogName)) { return(false); } //to avoid misalignment while using ExcelFileProvider. controlId = controlId.Replace(Settings.Default.Seperator_for_partial_Literalkeys.ToString(), ""); controlType = controlType.Replace(Settings.Default.Seperator_for_partial_Literalkeys.ToString(), ""); parentDialogName = parentDialogName.Replace(Settings.Default.Seperator_for_partial_Literalkeys.ToString(), ""); return(true); }
/// <summary> /// Sets the <paramref name="element" /> specific Property to <paramref name="guiString" />. /// </summary> /// <param name="element">The element whose Property should be set.</param> /// <param name="guiString">The text that should be displayed in the GUI.</param> /// <exception cref="ArgumentNullException">Thrown, if <paramref name="element" /> is null.</exception> public static void WriteToControlElement(FrameworkElement element, string guiString) { ExceptionLoggingUtils.ThrowIfNull(Logger, nameof(WriteToControlElement), element, nameof(element), "Unable to write new gui text to null element."); switch (element) { case RibbonTab tab: tab.Header = guiString; break; case RibbonGroup ribbonGroup: ribbonGroup.Header = guiString; break; case RibbonButton button: button.Label = guiString; break; case RibbonRadioButton button: button.Content = guiString; break; case RibbonApplicationMenuItem menuItem: menuItem.Header = guiString; break; case Label label: label.Content = guiString; break; case Button button: if (button.Content is string || button.Content == null) { button.Content = guiString; } break; case TabItem tabItem: tabItem.Header = guiString; break; case RadioButton radioButton: radioButton.Content = guiString; break; case TextBlock textBlock: textBlock.Text = guiString; break; case CheckBox checkBox: checkBox.Content = guiString; break; default: Logger.Log(LogLevel.Debug, $"Unable to translate unkown type ({element.GetType()}) " + $"with not translation ({guiString})."); break; } }