2013-02-23 07:57:11 +00:00
|
|
|
|
using MediaBrowser.Model.Logging;
|
2013-02-21 01:33:05 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Concurrent;
|
|
|
|
|
using System.Globalization;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
using System.Xml.Serialization;
|
|
|
|
|
|
|
|
|
|
namespace MediaBrowser.Controller.Localization
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Class LocalizedStrings
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class LocalizedStrings
|
|
|
|
|
{
|
2013-02-21 20:26:35 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// The logger
|
|
|
|
|
/// </summary>
|
2013-02-22 01:26:35 +00:00
|
|
|
|
static internal ILogger Logger { get; set; }
|
2013-02-21 01:33:05 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// The base prefix
|
|
|
|
|
/// </summary>
|
|
|
|
|
public const string BasePrefix = "base-";
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// The local strings
|
|
|
|
|
/// </summary>
|
|
|
|
|
protected ConcurrentDictionary<string, string> LocalStrings = new ConcurrentDictionary<string, string>();
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// The _instance
|
|
|
|
|
/// </summary>
|
|
|
|
|
private static LocalizedStrings _instance;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the instance.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <value>The instance.</value>
|
|
|
|
|
public static LocalizedStrings Instance { get { return _instance ?? (_instance = new LocalizedStrings()); } }
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Initializes a new instance of the <see cref="LocalizedStrings" /> class.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public LocalizedStrings()
|
|
|
|
|
{
|
|
|
|
|
foreach (var stringObject in Kernel.Instance.StringFiles)
|
|
|
|
|
{
|
|
|
|
|
AddStringData(LoadFromFile(GetFileName(stringObject),stringObject.GetType()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the name of the file.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="stringObject">The string object.</param>
|
|
|
|
|
/// <returns>System.String.</returns>
|
|
|
|
|
protected string GetFileName(LocalizedStringData stringObject)
|
|
|
|
|
{
|
|
|
|
|
var path = Kernel.Instance.ApplicationPaths.LocalizationPath;
|
|
|
|
|
var name = Path.Combine(path, stringObject.Prefix + "strings-" + CultureInfo.CurrentCulture + ".xml");
|
|
|
|
|
if (File.Exists(name))
|
|
|
|
|
{
|
|
|
|
|
return name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
name = Path.Combine(path, stringObject.Prefix + "strings-" + CultureInfo.CurrentCulture.Parent + ".xml");
|
|
|
|
|
if (File.Exists(name))
|
|
|
|
|
{
|
|
|
|
|
return name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//just return default
|
|
|
|
|
return Path.Combine(path, stringObject.Prefix + "strings-en.xml");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Loads from file.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="file">The file.</param>
|
|
|
|
|
/// <param name="t">The t.</param>
|
|
|
|
|
/// <returns>LocalizedStringData.</returns>
|
|
|
|
|
protected LocalizedStringData LoadFromFile(string file, Type t)
|
|
|
|
|
{
|
|
|
|
|
var xs = new XmlSerializer(t);
|
|
|
|
|
var strings = (LocalizedStringData)Activator.CreateInstance(t);
|
|
|
|
|
strings.FileName = file;
|
2013-02-21 20:26:35 +00:00
|
|
|
|
Logger.Info("Using String Data from {0}", file);
|
2013-02-21 01:33:05 +00:00
|
|
|
|
if (File.Exists(file))
|
|
|
|
|
{
|
|
|
|
|
using (var fs = new FileStream(file, FileMode.Open, FileAccess.Read))
|
|
|
|
|
{
|
|
|
|
|
strings = (LocalizedStringData)xs.Deserialize(fs);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
strings.Save(); //brand new - save it
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (strings.ThisVersion != strings.Version && file.ToLower().Contains("-en.xml"))
|
|
|
|
|
{
|
|
|
|
|
//only re-save the english version as that is the one defined internally
|
|
|
|
|
strings = new BaseStrings {FileName = file};
|
|
|
|
|
strings.Save();
|
|
|
|
|
}
|
|
|
|
|
return strings;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Adds the string data.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="stringData">The string data.</param>
|
|
|
|
|
public void AddStringData(object stringData )
|
|
|
|
|
{
|
|
|
|
|
//translate our object definition into a dictionary for lookups
|
|
|
|
|
// and a reverse dictionary so we can lookup keys by value
|
|
|
|
|
foreach (var field in stringData.GetType().GetFields().Where(f => f != null && f.FieldType == typeof(string)))
|
|
|
|
|
{
|
|
|
|
|
string value;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
value = field.GetValue(stringData) as string;
|
|
|
|
|
}
|
|
|
|
|
catch (TargetException ex)
|
|
|
|
|
{
|
2013-02-21 20:26:35 +00:00
|
|
|
|
Logger.ErrorException("Error getting value for field: {0}", ex, field.Name);
|
2013-02-21 01:33:05 +00:00
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
catch (FieldAccessException ex)
|
|
|
|
|
{
|
2013-02-21 20:26:35 +00:00
|
|
|
|
Logger.ErrorException("Error getting value for field: {0}", ex, field.Name);
|
2013-02-21 01:33:05 +00:00
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
catch (NotSupportedException ex)
|
|
|
|
|
{
|
2013-02-21 20:26:35 +00:00
|
|
|
|
Logger.ErrorException("Error getting value for field: {0}", ex, field.Name);
|
2013-02-21 01:33:05 +00:00
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LocalStrings.TryAdd(field.Name, value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the string.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="key">The key.</param>
|
|
|
|
|
/// <returns>System.String.</returns>
|
|
|
|
|
public string GetString(string key)
|
|
|
|
|
{
|
|
|
|
|
string value;
|
|
|
|
|
|
|
|
|
|
LocalStrings.TryGetValue(key, out value);
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|