diff options
| author | Luke Pulverenti <luke.pulverenti@gmail.com> | 2016-11-04 22:17:18 -0400 |
|---|---|---|
| committer | Luke Pulverenti <luke.pulverenti@gmail.com> | 2016-11-04 22:17:18 -0400 |
| commit | 3c1447804b5de9a7d840c7158c3cb4e0a27f76e1 (patch) | |
| tree | b7ea2715a1a9feb5e6f36c26bca09b2a32996847 /Emby.Server.Implementations/Localization/LocalizationManager.cs | |
| parent | 25312d7d03af665818cfd2cee2edb549e0e940f2 (diff) | |
move localization classes
Diffstat (limited to 'Emby.Server.Implementations/Localization/LocalizationManager.cs')
| -rw-r--r-- | Emby.Server.Implementations/Localization/LocalizationManager.cs | 433 |
1 files changed, 433 insertions, 0 deletions
diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs new file mode 100644 index 000000000..120f445c2 --- /dev/null +++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs @@ -0,0 +1,433 @@ +using MediaBrowser.Model.Extensions; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Globalization; +using MediaBrowser.Model.Serialization; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Reflection; + +namespace Emby.Server.Implementations.Localization +{ + /// <summary> + /// Class LocalizationManager + /// </summary> + public class LocalizationManager : ILocalizationManager + { + /// <summary> + /// The _configuration manager + /// </summary> + private readonly IServerConfigurationManager _configurationManager; + + /// <summary> + /// The us culture + /// </summary> + private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); + + private readonly ConcurrentDictionary<string, Dictionary<string, ParentalRating>> _allParentalRatings = + new ConcurrentDictionary<string, Dictionary<string, ParentalRating>>(StringComparer.OrdinalIgnoreCase); + + private readonly IFileSystem _fileSystem; + private readonly IJsonSerializer _jsonSerializer; + private readonly ILogger _logger; + private readonly IAssemblyInfo _assemblyInfo; + private readonly ITextLocalizer _textLocalizer; + + /// <summary> + /// Initializes a new instance of the <see cref="LocalizationManager" /> class. + /// </summary> + /// <param name="configurationManager">The configuration manager.</param> + /// <param name="fileSystem">The file system.</param> + /// <param name="jsonSerializer">The json serializer.</param> + public LocalizationManager(IServerConfigurationManager configurationManager, IFileSystem fileSystem, IJsonSerializer jsonSerializer, ILogger logger, IAssemblyInfo assemblyInfo, ITextLocalizer textLocalizer) + { + _configurationManager = configurationManager; + _fileSystem = fileSystem; + _jsonSerializer = jsonSerializer; + _logger = logger; + _assemblyInfo = assemblyInfo; + _textLocalizer = textLocalizer; + + ExtractAll(); + } + + private void ExtractAll() + { + var type = GetType(); + var resourcePath = type.Namespace + ".Ratings."; + + var localizationPath = LocalizationPath; + + _fileSystem.CreateDirectory(localizationPath); + + var existingFiles = GetRatingsFiles(localizationPath) + .Select(Path.GetFileName) + .ToList(); + + // Extract from the assembly + foreach (var resource in _assemblyInfo + .GetManifestResourceNames(type) + .Where(i => i.StartsWith(resourcePath))) + { + var filename = "ratings-" + resource.Substring(resourcePath.Length); + + if (!existingFiles.Contains(filename)) + { + using (var stream = _assemblyInfo.GetManifestResourceStream(type, resource)) + { + var target = Path.Combine(localizationPath, filename); + _logger.Info("Extracting ratings to {0}", target); + + using (var fs = _fileSystem.GetFileStream(target, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read)) + { + stream.CopyTo(fs); + } + } + } + } + + foreach (var file in GetRatingsFiles(localizationPath)) + { + LoadRatings(file); + } + } + + private List<string> GetRatingsFiles(string directory) + { + return _fileSystem.GetFilePaths(directory, false) + .Where(i => string.Equals(Path.GetExtension(i), ".txt", StringComparison.OrdinalIgnoreCase)) + .Where(i => Path.GetFileName(i).StartsWith("ratings-", StringComparison.OrdinalIgnoreCase)) + .ToList(); + } + + /// <summary> + /// Gets the localization path. + /// </summary> + /// <value>The localization path.</value> + public string LocalizationPath + { + get + { + return Path.Combine(_configurationManager.ApplicationPaths.ProgramDataPath, "localization"); + } + } + + public string RemoveDiacritics(string text) + { + return _textLocalizer.RemoveDiacritics(text); + } + + public string NormalizeFormKD(string text) + { + return _textLocalizer.NormalizeFormKD(text); + } + + /// <summary> + /// Gets the cultures. + /// </summary> + /// <returns>IEnumerable{CultureDto}.</returns> + public IEnumerable<CultureDto> GetCultures() + { + var type = GetType(); + var path = type.Namespace + ".iso6392.txt"; + + var list = new List<CultureDto>(); + + using (var stream = _assemblyInfo.GetManifestResourceStream(type, path)) + { + using (var reader = new StreamReader(stream)) + { + while (!reader.EndOfStream) + { + var line = reader.ReadLine(); + + if (!string.IsNullOrWhiteSpace(line)) + { + var parts = line.Split('|'); + + if (parts.Length == 5) + { + list.Add(new CultureDto + { + DisplayName = parts[3], + Name = parts[3], + ThreeLetterISOLanguageName = parts[0], + TwoLetterISOLanguageName = parts[2] + }); + } + } + } + } + } + + return list.Where(i => !string.IsNullOrWhiteSpace(i.Name) && + !string.IsNullOrWhiteSpace(i.DisplayName) && + !string.IsNullOrWhiteSpace(i.ThreeLetterISOLanguageName) && + !string.IsNullOrWhiteSpace(i.TwoLetterISOLanguageName)); + } + + /// <summary> + /// Gets the countries. + /// </summary> + /// <returns>IEnumerable{CountryInfo}.</returns> + public IEnumerable<CountryInfo> GetCountries() + { + var type = GetType(); + var path = type.Namespace + ".countries.json"; + + using (var stream = _assemblyInfo.GetManifestResourceStream(type, path)) + { + return _jsonSerializer.DeserializeFromStream<List<CountryInfo>>(stream); + } + } + + /// <summary> + /// Gets the parental ratings. + /// </summary> + /// <returns>IEnumerable{ParentalRating}.</returns> + public IEnumerable<ParentalRating> GetParentalRatings() + { + return GetParentalRatingsDictionary().Values.ToList(); + } + + /// <summary> + /// Gets the parental ratings dictionary. + /// </summary> + /// <returns>Dictionary{System.StringParentalRating}.</returns> + private Dictionary<string, ParentalRating> GetParentalRatingsDictionary() + { + var countryCode = _configurationManager.Configuration.MetadataCountryCode; + + if (string.IsNullOrEmpty(countryCode)) + { + countryCode = "us"; + } + + var ratings = GetRatings(countryCode); + + if (ratings == null) + { + ratings = GetRatings("us"); + } + + return ratings; + } + + /// <summary> + /// Gets the ratings. + /// </summary> + /// <param name="countryCode">The country code.</param> + private Dictionary<string, ParentalRating> GetRatings(string countryCode) + { + Dictionary<string, ParentalRating> value; + + _allParentalRatings.TryGetValue(countryCode, out value); + + return value; + } + + /// <summary> + /// Loads the ratings. + /// </summary> + /// <param name="file">The file.</param> + /// <returns>Dictionary{System.StringParentalRating}.</returns> + private void LoadRatings(string file) + { + var dict = _fileSystem.ReadAllLines(file).Select(i => + { + if (!string.IsNullOrWhiteSpace(i)) + { + var parts = i.Split(','); + + if (parts.Length == 2) + { + int value; + + if (int.TryParse(parts[1], NumberStyles.Integer, UsCulture, out value)) + { + return new ParentalRating { Name = parts[0], Value = value }; + } + } + } + + return null; + + }) + .Where(i => i != null) + .ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase); + + var countryCode = _fileSystem.GetFileNameWithoutExtension(file) + .Split('-') + .Last(); + + _allParentalRatings.TryAdd(countryCode, dict); + } + + private readonly string[] _unratedValues = {"n/a", "unrated", "not rated"}; + + /// <summary> + /// Gets the rating level. + /// </summary> + public int? GetRatingLevel(string rating) + { + if (string.IsNullOrEmpty(rating)) + { + throw new ArgumentNullException("rating"); + } + + if (_unratedValues.Contains(rating, StringComparer.OrdinalIgnoreCase)) + { + return null; + } + + // Fairly common for some users to have "Rated R" in their rating field + rating = rating.Replace("Rated ", string.Empty, StringComparison.OrdinalIgnoreCase); + + var ratingsDictionary = GetParentalRatingsDictionary(); + + ParentalRating value; + + if (!ratingsDictionary.TryGetValue(rating, out value)) + { + // If we don't find anything check all ratings systems + foreach (var dictionary in _allParentalRatings.Values) + { + if (dictionary.TryGetValue(rating, out value)) + { + return value.Value; + } + } + } + + return value == null ? (int?)null : value.Value; + } + + public string GetLocalizedString(string phrase) + { + return GetLocalizedString(phrase, _configurationManager.Configuration.UICulture); + } + + public string GetLocalizedString(string phrase, string culture) + { + var dictionary = GetLocalizationDictionary(culture); + + string value; + + if (dictionary.TryGetValue(phrase, out value)) + { + return value; + } + + return phrase; + } + + private readonly ConcurrentDictionary<string, Dictionary<string, string>> _dictionaries = + new ConcurrentDictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase); + + public Dictionary<string, string> GetLocalizationDictionary(string culture) + { + const string prefix = "Core"; + var key = prefix + culture; + + return _dictionaries.GetOrAdd(key, k => GetDictionary(prefix, culture, "core.json")); + } + + private Dictionary<string, string> GetDictionary(string prefix, string culture, string baseFilename) + { + var dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); + + var namespaceName = GetType().Namespace + "." + prefix; + + CopyInto(dictionary, namespaceName + "." + baseFilename); + CopyInto(dictionary, namespaceName + "." + GetResourceFilename(culture)); + + return dictionary; + } + + private void CopyInto(IDictionary<string, string> dictionary, string resourcePath) + { + using (var stream = _assemblyInfo.GetManifestResourceStream(GetType(), resourcePath)) + { + if (stream != null) + { + var dict = _jsonSerializer.DeserializeFromStream<Dictionary<string, string>>(stream); + + foreach (var key in dict.Keys) + { + dictionary[key] = dict[key]; + } + } + } + } + + private string GetResourceFilename(string culture) + { + var parts = culture.Split('-'); + + if (parts.Length == 2) + { + culture = parts[0].ToLower() + "-" + parts[1].ToUpper(); + } + else + { + culture = culture.ToLower(); + } + + return culture + ".json"; + } + + public IEnumerable<LocalizatonOption> GetLocalizationOptions() + { + return new List<LocalizatonOption> + { + new LocalizatonOption{ Name="Arabic", Value="ar"}, + new LocalizatonOption{ Name="Bulgarian (Bulgaria)", Value="bg-BG"}, + new LocalizatonOption{ Name="Catalan", Value="ca"}, + new LocalizatonOption{ Name="Chinese Simplified", Value="zh-CN"}, + new LocalizatonOption{ Name="Chinese Traditional", Value="zh-TW"}, + new LocalizatonOption{ Name="Croatian", Value="hr"}, + new LocalizatonOption{ Name="Czech", Value="cs"}, + new LocalizatonOption{ Name="Danish", Value="da"}, + new LocalizatonOption{ Name="Dutch", Value="nl"}, + new LocalizatonOption{ Name="English (United Kingdom)", Value="en-GB"}, + new LocalizatonOption{ Name="English (United States)", Value="en-us"}, + new LocalizatonOption{ Name="Finnish", Value="fi"}, + new LocalizatonOption{ Name="French", Value="fr"}, + new LocalizatonOption{ Name="French (Canada)", Value="fr-CA"}, + new LocalizatonOption{ Name="German", Value="de"}, + new LocalizatonOption{ Name="Greek", Value="el"}, + new LocalizatonOption{ Name="Hebrew", Value="he"}, + new LocalizatonOption{ Name="Hungarian", Value="hu"}, + new LocalizatonOption{ Name="Indonesian", Value="id"}, + new LocalizatonOption{ Name="Italian", Value="it"}, + new LocalizatonOption{ Name="Kazakh", Value="kk"}, + new LocalizatonOption{ Name="Norwegian Bokmål", Value="nb"}, + new LocalizatonOption{ Name="Polish", Value="pl"}, + new LocalizatonOption{ Name="Portuguese (Brazil)", Value="pt-BR"}, + new LocalizatonOption{ Name="Portuguese (Portugal)", Value="pt-PT"}, + new LocalizatonOption{ Name="Russian", Value="ru"}, + new LocalizatonOption{ Name="Slovenian (Slovenia)", Value="sl-SI"}, + new LocalizatonOption{ Name="Spanish", Value="es-ES"}, + new LocalizatonOption{ Name="Spanish (Mexico)", Value="es-MX"}, + new LocalizatonOption{ Name="Swedish", Value="sv"}, + new LocalizatonOption{ Name="Turkish", Value="tr"}, + new LocalizatonOption{ Name="Ukrainian", Value="uk"}, + new LocalizatonOption{ Name="Vietnamese", Value="vi"} + + }.OrderBy(i => i.Name); + } + } + + public interface ITextLocalizer + { + string RemoveDiacritics(string text); + + string NormalizeFormKD(string text); + } +} |
