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
}
}