using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Reflection; using Newtonsoft.Json; namespace gehGassi.Domain.Localization { /// /// Basis-Klasse für eine Entität die Übersetzungen für String-Felder ermöglicht /// public class LocalizableBase : ILocalizable { private string _language = string.Empty; /// /// In welcher Sprache sollen die übersetzbaren Felder abgerufen oder gesetzt werden? /// /// ISO2 codierte Sprache public void SetLanguage(string language) { if (GetAvailableLanguages().Contains(language.ToUpper())) _language = language.ToUpper(); } /// /// Gibt die gewählte Sprache intern zurück. /// Wenn diese nicht verfügbar ist, wird versucht die aktuelle Culture zu verwenden. /// Wenn diese auch nicht verfügbar ist, wird die Default-Sprache verwendet /// /// Sprache als ISO2 protected string GetLanguage() { if (string.IsNullOrWhiteSpace(_language)) { var lang = CultureInfo.CurrentCulture.TwoLetterISOLanguageName; _language = GetAvailableLanguages().Contains(lang.ToUpper()) ? lang.ToUpper() : DefaultLanguage; } return _language; } /// /// Setzt eine Übersetzung direkt für ein Feld mittels Reflection /// /// Name der Eigenschaft /// ISO2 codierte Sprache /// Zu setzender Wert public void Set(string property, string language, string value) { property = property + "Localized"; language = language.ToUpper(); var serialized = GetPropValue(GetType(), property, this); Dictionary dictionary; if (serialized != null) { try { dictionary = JsonConvert.DeserializeObject>(serialized.ToString()); } catch { dictionary = new Dictionary(); } } else dictionary = new Dictionary(); if (dictionary.ContainsKey(language)) dictionary[language] = value; else dictionary.Add(language, value); var serializedDict = JsonConvert.SerializeObject(dictionary); SetPropValue(GetType(), property, serializedDict, this); } /// /// Setzt alle übersetzungen für ein Feld mittels Reflection. /// Achtung: das gesamte Dictionary wird ersetzt /// /// Name der Eigenschaft /// Zu setzendes Dictionary public void Set(string property, Dictionary dictionary) { property = property + "Localized"; var serializedDict = JsonConvert.SerializeObject(dictionary); SetPropValue(GetType(), property, serializedDict, this); } /// /// Ruft eine Übersetzung direkt für ein Feld mittels Reflection /// /// Name der Eigenschaft /// ISO2 codierte Sprache /// Gibt an ob leer als Rückgabe gültig ist und nicht die Default-Werte genommen werden sollen wenn eine Übersetzung fehlt /// Wert public string Get(string property, string language, bool allowEmpty = false) { property = property + "Localized"; language = language.ToUpper(); var serialized = GetPropValue(GetType(), property, this); if (serialized != null) { try { var dictionary = JsonConvert.DeserializeObject>(serialized.ToString()); if (dictionary != null) { if (dictionary.ContainsKey(language) && !string.IsNullOrWhiteSpace(dictionary[language])) return dictionary[language]; if (allowEmpty) return string.Empty; if (dictionary.ContainsKey(DefaultLanguage)) return dictionary[DefaultLanguage]; return dictionary.First().Value; } } catch { // ignored } } return string.Empty; } /// /// Ruft alle Übersetzungen direkt für ein Feld mittels Reflection /// /// Name der Eigenschaft /// Dictionary mit allen Übersetzungen public Dictionary Get(string property) { property = property + "Localized"; var serialized = GetPropValue(GetType(), property, this); if (serialized != null) { try { var dictionary = JsonConvert.DeserializeObject>(serialized.ToString()); if (dictionary != null) { return dictionary; } } catch { // ignored } } return new Dictionary(); } /// /// Gibt eine Liste aller verfügbaren Sprachen für ein Feld zurück. /// Basiert auf den bereits gesetzten Sprachen /// /// Name der Eigenschaft /// Liste verfügbarer Sprachen public List GetLanguages(string property) { property = property + "Localized"; var serialized = GetPropValue(GetType(), property, this); if (serialized != null) { try { var dictionary = JsonConvert.DeserializeObject>(serialized.ToString()); if (dictionary != null) { return dictionary.Select(c => c.Key).ToList(); } } catch { // ignored } } return new List(); } #region private /// /// Ruft die Liste aller verfügbaren Sprachen mittels App-Settings ab. /// /// Liste verfügbare Sprachen ISO2 codiert protected static IEnumerable GetAvailableLanguages() { var languages = LocalizableHelper.Languages; if (string.IsNullOrWhiteSpace(languages)) { return new[] { LocalizableHelper.DefaultLanguage }; } return languages.ToUpper().Split(','); } /// /// Gibt die Standard-Sprache zurück /// protected static string DefaultLanguage => LocalizableHelper.DefaultLanguage; /// /// Hilfsfunktion die den Wert einer Eigenschaft aus einem Objekt sucht und zurückgibt /// /// Basis-Typ des Objekts /// Gesuchte Eigenschaft /// Objekt das die Eigenschaft beinhaltet /// Tiefe der Rekursion /// Wert der Eigenschaft oder null, wenn nicht gefunden protected static object GetPropValue(Type baseType, string propertyName, object targetObject, int depth = 0) { if (depth >= 100) throw new Exception("Recursion detected."); string[] parts = propertyName.Split('.'); if (parts.Length > 1) return GetPropValue(baseType.GetProperty(parts[0])?.PropertyType, parts.Skip(1).Aggregate((a, i) => a + "." + i), baseType.GetProperty(parts[0])?.GetValue(targetObject, null), depth + 1); var properties = baseType.GetProperties(BindingFlags.SetProperty | BindingFlags.GetProperty | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public).ToList(); if (properties.Count > 0) { var property = properties.FirstOrDefault(c => c.Name == propertyName); if (property != null) return property.GetValue(targetObject, null); } return null; } /// /// Hilfsfunktion die versucht den Wert einer Eigenschaft zu setzen /// /// Basis-Typ des Objektes /// Name der Eigenschaft /// Zu setzender Wert /// Ziel-Objekt /// Tiefe der Rekursion protected static void SetPropValue(Type baseType, string propertyName, object value, object targetObject, int depth = 0) { if (depth >= 100) throw new Exception("Recursion detected."); string[] parts = propertyName.Split('.'); if (parts.Length > 1) SetPropValue(baseType.GetProperty(parts[0])?.PropertyType, parts.Skip(1).Aggregate((a, i) => a + "." + i), value, baseType.GetProperty(parts[0])?.GetValue(targetObject, null), depth + 1); var properties = baseType.GetProperties(BindingFlags.SetProperty | BindingFlags.GetProperty | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public).ToList(); if (properties.Count > 0) { var property = properties.FirstOrDefault(c => c.Name == propertyName); if (property != null) property.SetValue(targetObject, value); } } #endregion } }