diff options
108 files changed, 1322 insertions, 685 deletions
diff --git a/MediaBrowser.Api/AppThemeService.cs b/MediaBrowser.Api/AppThemeService.cs index 0c8a0aaa6..87084e415 100644 --- a/MediaBrowser.Api/AppThemeService.cs +++ b/MediaBrowser.Api/AppThemeService.cs @@ -94,7 +94,7 @@ namespace MediaBrowser.Api var contentType = MimeTypes.GetMimeType(info.Path); - return ToCachedResult(cacheGuid, info.DateModified, cacheDuration, () => _fileSystem.GetFileStream(info.Path, FileMode.Open, FileAccess.Read, FileShare.Read), contentType); + return ResultFactory.GetCachedResult(Request, cacheGuid, null, cacheDuration, () => _fileSystem.GetFileStream(info.Path, FileMode.Open, FileAccess.Read, FileShare.Read), contentType); } } } diff --git a/MediaBrowser.Api/BaseApiService.cs b/MediaBrowser.Api/BaseApiService.cs index 727ee6fbc..1af7054d9 100644 --- a/MediaBrowser.Api/BaseApiService.cs +++ b/MediaBrowser.Api/BaseApiService.cs @@ -98,24 +98,6 @@ namespace MediaBrowser.Api } /// <summary> - /// To the cached result. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="cacheKey">The cache key.</param> - /// <param name="lastDateModified">The last date modified.</param> - /// <param name="cacheDuration">Duration of the cache.</param> - /// <param name="factoryFn">The factory fn.</param> - /// <param name="contentType">Type of the content.</param> - /// <param name="responseHeaders">The response headers.</param> - /// <returns>System.Object.</returns> - /// <exception cref="System.ArgumentNullException">cacheKey</exception> - protected object ToCachedResult<T>(Guid cacheKey, DateTime? lastDateModified, TimeSpan? cacheDuration, Func<T> factoryFn, string contentType, IDictionary<string,string> responseHeaders = null) - where T : class - { - return ResultFactory.GetCachedResult(Request, cacheKey, lastDateModified, cacheDuration, factoryFn, contentType, responseHeaders); - } - - /// <summary> /// To the static file result. /// </summary> /// <param name="path">The path.</param> diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs index 43e9ad3ef..2213a5af1 100644 --- a/MediaBrowser.Api/Images/ImageService.cs +++ b/MediaBrowser.Api/Images/ImageService.cs @@ -361,7 +361,7 @@ namespace MediaBrowser.Api.Images /// <returns>System.Object.</returns> public object Get(GetItemImage request) { - var item = string.IsNullOrEmpty(request.Id) ? + var item = string.IsNullOrEmpty(request.Id) ? _libraryManager.RootFolder : _libraryManager.GetItemById(request.Id); @@ -542,24 +542,24 @@ namespace MediaBrowser.Api.Images {"realTimeInfo.dlna.org", "DLNA.ORG_TLAG=*"} }; - return GetImageResult(item, - request, - imageInfo, - supportedImageEnhancers, - contentType, + return GetImageResult(item, + request, + imageInfo, + supportedImageEnhancers, + contentType, cacheDuration, responseHeaders, isHeadRequest) .Result; } - private async Task<object> GetImageResult(IHasImages item, + private async Task<object> GetImageResult(IHasImages item, ImageRequest request, ItemImageInfo image, List<IImageEnhancer> enhancers, string contentType, TimeSpan? cacheDuration, - IDictionary<string,string> headers, + IDictionary<string, string> headers, bool isHeadRequest) { var cropwhitespace = request.Type == ImageType.Logo || request.Type == ImageType.Art; @@ -590,7 +590,14 @@ namespace MediaBrowser.Api.Images var file = await _imageProcessor.ProcessImage(options).ConfigureAwait(false); - return ResultFactory.GetStaticFileResult(Request, file, contentType, cacheDuration, FileShare.Read, headers, isHeadRequest); + return ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions + { + CacheDuration = cacheDuration, + ResponseHeaders = headers, + ContentType = contentType, + IsHeadRequest = isHeadRequest, + Path = file + }); } private string GetMimeType(ImageOutputFormat format, string path) diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index a0a8ee61e..31a81de73 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -348,14 +348,16 @@ namespace MediaBrowser.Api.Playback var profileScore = 0; string crf; + var qmin = "0"; + var qmax = "50"; switch (qualitySetting) { case EncodingQuality.HighSpeed: - crf = "12"; + crf = "10"; break; case EncodingQuality.HighQuality: - crf = "8"; + crf = "6"; break; case EncodingQuality.MaxQuality: crf = "4"; @@ -371,11 +373,13 @@ namespace MediaBrowser.Api.Playback // Max of 2 profileScore = Math.Min(profileScore, 2); - + // http://www.webmproject.org/docs/encoder-parameters/ - param = string.Format("-speed 16 -quality good -profile:v {0} -slices 8 -crf {1}", + param = string.Format("-speed 16 -quality good -profile:v {0} -slices 8 -crf {1} -qmin {2} -qmax {3}", profileScore.ToString(UsCulture), - crf); + crf, + qmin, + qmax); } else if (string.Equals(videoCodec, "mpeg4", StringComparison.OrdinalIgnoreCase)) @@ -789,7 +793,7 @@ namespace MediaBrowser.Api.Playback { if (state.RunTimeTicks.Value >= TimeSpan.FromMinutes(5).Ticks && state.IsInputVideo) { - var url = "http://localhost:8096/mediabrowser/videos/" + state.Request.Id + "/stream?static=true&Throttle=true&mediaSourceId=" + state.Request.MediaSourceId; + var url = "http://localhost:" + ServerConfigurationManager.Configuration.HttpServerPortNumber.ToString(UsCulture) + "/mediabrowser/videos/" + state.Request.Id + "/stream?static=true&Throttle=true&mediaSourceId=" + state.Request.MediaSourceId; return string.Format("\"{0}\"", url); } diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs index 0d90e3739..346af016e 100644 --- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs @@ -10,7 +10,6 @@ using ServiceStack; using System; using System.IO; using System.Linq; -using System.Threading; using System.Threading.Tasks; namespace MediaBrowser.Api.Playback.Hls @@ -63,6 +62,14 @@ namespace MediaBrowser.Api.Playback.Hls { } + protected override bool SupportsThrottling + { + get + { + return false; + } + } + /// <summary> /// Gets the specified request. /// </summary> @@ -79,14 +86,6 @@ namespace MediaBrowser.Api.Playback.Hls return ResultFactory.GetStaticFileResult(Request, file); } - protected override bool SupportsThrottling - { - get - { - return false; - } - } - /// <summary> /// Called when [begin request]. /// </summary> diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs index d8255bd29..997cc7ca4 100644 --- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs +++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs @@ -7,6 +7,7 @@ using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.MediaEncoding; +using MediaBrowser.Controller.Net; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; using ServiceStack.Web; @@ -26,7 +27,8 @@ namespace MediaBrowser.Api.Playback.Progressive protected readonly IImageProcessor ImageProcessor; protected readonly IHttpClient HttpClient; - protected BaseProgressiveStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder) + protected BaseProgressiveStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IImageProcessor imageProcessor, IHttpClient httpClient) + : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder) { ImageProcessor = imageProcessor; HttpClient = httpClient; @@ -52,23 +54,23 @@ namespace MediaBrowser.Api.Playback.Progressive if (isVideoRequest) { var videoCodec = state.VideoRequest.VideoCodec; - - if (string.Equals(videoCodec, "h264", StringComparison.OrdinalIgnoreCase)) - { - return ".ts"; - } - if (string.Equals(videoCodec, "theora", StringComparison.OrdinalIgnoreCase)) - { - return ".ogv"; - } - if (string.Equals(videoCodec, "vpx", StringComparison.OrdinalIgnoreCase)) - { - return ".webm"; - } - if (string.Equals(videoCodec, "wmv", StringComparison.OrdinalIgnoreCase)) - { - return ".asf"; - } + + if (string.Equals(videoCodec, "h264", StringComparison.OrdinalIgnoreCase)) + { + return ".ts"; + } + if (string.Equals(videoCodec, "theora", StringComparison.OrdinalIgnoreCase)) + { + return ".ogv"; + } + if (string.Equals(videoCodec, "vpx", StringComparison.OrdinalIgnoreCase)) + { + return ".webm"; + } + if (string.Equals(videoCodec, "wmv", StringComparison.OrdinalIgnoreCase)) + { + return ".asf"; + } } // Try to infer based on the desired audio codec @@ -153,7 +155,20 @@ namespace MediaBrowser.Api.Playback.Progressive { var throttleLimit = state.InputBitrate.HasValue ? (state.InputBitrate.Value / 8) : 0; - return ResultFactory.GetStaticFileResult(Request, state.MediaPath, contentType, null, FileShare.Read, responseHeaders, isHeadRequest, request.Throttle, throttleLimit); + return ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions + { + ResponseHeaders = responseHeaders, + ContentType = contentType, + IsHeadRequest = isHeadRequest, + Path = state.MediaPath, + Throttle = request.Throttle, + + // Pad by 20% to play it safe + ThrottleLimit = Convert.ToInt64(1.2 * throttleLimit), + + // Three minutes + MinThrottlePosition = throttleLimit * 180 + }); } } @@ -164,7 +179,13 @@ namespace MediaBrowser.Api.Playback.Progressive try { - return ResultFactory.GetStaticFileResult(Request, outputPath, contentType, null, FileShare.Read, responseHeaders, isHeadRequest); + return ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions + { + ResponseHeaders = responseHeaders, + ContentType = contentType, + IsHeadRequest = isHeadRequest, + Path = outputPath + }); } finally { diff --git a/MediaBrowser.Api/PluginService.cs b/MediaBrowser.Api/PluginService.cs index 29cc7baf8..d6c854734 100644 --- a/MediaBrowser.Api/PluginService.cs +++ b/MediaBrowser.Api/PluginService.cs @@ -7,12 +7,12 @@ using MediaBrowser.Model.Entities; using MediaBrowser.Model.Plugins; using MediaBrowser.Model.Serialization; using ServiceStack; +using ServiceStack.Text.Controller; +using ServiceStack.Web; using System; using System.Collections.Generic; using System.IO; using System.Linq; -using ServiceStack.Text.Controller; -using ServiceStack.Web; namespace MediaBrowser.Api { @@ -190,8 +190,7 @@ namespace MediaBrowser.Api var result = new PluginSecurityInfo { IsMBSupporter = _securityManager.IsMBSupporter, - SupporterKey = _securityManager.SupporterKey, - LegacyKey = _securityManager.LegacyKey + SupporterKey = _securityManager.SupporterKey }; return ToOptimizedSerializedResultUsingCache(result); @@ -206,7 +205,6 @@ namespace MediaBrowser.Api var info = request; _securityManager.SupporterKey = info.SupporterKey; - _securityManager.LegacyKey = info.LegacyKey; } /// <summary> diff --git a/MediaBrowser.Api/System/SystemService.cs b/MediaBrowser.Api/System/SystemService.cs index cae648ae0..bac99c848 100644 --- a/MediaBrowser.Api/System/SystemService.cs +++ b/MediaBrowser.Api/System/SystemService.cs @@ -1,8 +1,10 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Common.IO; using MediaBrowser.Common.Net; +using MediaBrowser.Common.Security; using MediaBrowser.Controller; using MediaBrowser.Controller.Net; +using MediaBrowser.Model.Entities; using MediaBrowser.Model.System; using ServiceStack; using System; @@ -42,6 +44,7 @@ namespace MediaBrowser.Api.System /// This is currently not authenticated because the uninstaller needs to be able to shutdown the server. /// </summary> [Route("/System/Shutdown", "POST", Summary = "Shuts down the application")] + [Authenticated(AllowLocal = true)] public class ShutdownApplication { } @@ -66,6 +69,12 @@ namespace MediaBrowser.Api.System public string Name { get; set; } } + [Route("/System/SupporterInfo", "GET")] + [Authenticated] + public class GetSupporterInfo : IReturn<SupporterInfo> + { + } + /// <summary> /// Class SystemInfoService /// </summary> @@ -80,6 +89,8 @@ namespace MediaBrowser.Api.System private readonly INetworkManager _network; + private readonly ISecurityManager _security; + /// <summary> /// Initializes a new instance of the <see cref="SystemService" /> class. /// </summary> @@ -87,12 +98,20 @@ namespace MediaBrowser.Api.System /// <param name="appPaths">The application paths.</param> /// <param name="fileSystem">The file system.</param> /// <exception cref="ArgumentNullException">jsonSerializer</exception> - public SystemService(IServerApplicationHost appHost, IApplicationPaths appPaths, IFileSystem fileSystem, INetworkManager network) + public SystemService(IServerApplicationHost appHost, IApplicationPaths appPaths, IFileSystem fileSystem, INetworkManager network, ISecurityManager security) { _appHost = appHost; _appPaths = appPaths; _fileSystem = fileSystem; _network = network; + _security = security; + } + + public async Task<object> Get(GetSupporterInfo request) + { + var result = await _security.GetSupporterInfo().ConfigureAwait(false); + + return ToOptimizedResult(result); } public object Get(GetServerLogs request) diff --git a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj index abb2f2089..4b0c95616 100644 --- a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj +++ b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj @@ -99,9 +99,9 @@ <Compile Include="ScheduledTasks\Tasks\ReloadLoggerFileTask.cs" /> <Compile Include="ScheduledTasks\Tasks\SystemUpdateTask.cs" /> <Compile Include="Security\MBLicenseFile.cs" /> - <Compile Include="Security\MBRegistration.cs" /> <Compile Include="Security\PluginSecurityManager.cs" /> <Compile Include="Security\RegRecord.cs" /> + <Compile Include="Security\SuppporterInfoResponse.cs" /> <Compile Include="Serialization\JsonSerializer.cs" /> <Compile Include="Serialization\XmlSerializer.cs" /> <Compile Include="Updates\InstallationManager.cs" /> @@ -135,4 +135,4 @@ xcopy "$(TargetPath)" "$(SolutionDir)\Nuget\dlls\" /y /d /r /i <Target Name="AfterBuild"> </Target> --> -</Project> +</Project>
\ No newline at end of file diff --git a/MediaBrowser.Common.Implementations/Security/MBLicenseFile.cs b/MediaBrowser.Common.Implementations/Security/MBLicenseFile.cs index 77a7bf0f6..8f3225f4e 100644 --- a/MediaBrowser.Common.Implementations/Security/MBLicenseFile.cs +++ b/MediaBrowser.Common.Implementations/Security/MBLicenseFile.cs @@ -1,7 +1,10 @@ using MediaBrowser.Common.Configuration; using System; +using System.Collections.Concurrent; using System.Collections.Generic; +using System.Globalization; using System.IO; +using System.Linq; using System.Security.Cryptography; using System.Text; @@ -19,7 +22,7 @@ namespace MediaBrowser.Common.Implementations.Security if (value != _regKey) { //if key is changed - clear out our saved validations - UpdateRecords.Clear(); + _updateRecords.Clear(); _regKey = value; } } @@ -33,24 +36,30 @@ namespace MediaBrowser.Common.Implementations.Security } } - public string LegacyKey { get; set; } - private Dictionary<Guid, DateTime> UpdateRecords { get; set; } - private readonly object _lck = new object(); + private readonly ConcurrentDictionary<Guid, DateTime> _updateRecords = new ConcurrentDictionary<Guid, DateTime>(); + private readonly object _fileLock = new object(); private string _regKey; public MBLicenseFile(IApplicationPaths appPaths) { _appPaths = appPaths; - UpdateRecords = new Dictionary<Guid, DateTime>(); Load(); } + private void SetUpdateRecord(Guid key, DateTime value) + { + _updateRecords.AddOrUpdate(key, value, (k, v) => value); + } + public void AddRegCheck(string featureId) { using (var provider = new MD5CryptoServiceProvider()) { - UpdateRecords[new Guid(provider.ComputeHash(Encoding.Unicode.GetBytes(featureId)))] = DateTime.UtcNow; + var key = new Guid(provider.ComputeHash(Encoding.Unicode.GetBytes(featureId))); + var value = DateTime.UtcNow; + + SetUpdateRecord(key, value); Save(); } @@ -60,7 +69,11 @@ namespace MediaBrowser.Common.Implementations.Security { using (var provider = new MD5CryptoServiceProvider()) { - UpdateRecords.Remove(new Guid(provider.ComputeHash(Encoding.Unicode.GetBytes(featureId)))); + var key = new Guid(provider.ComputeHash(Encoding.Unicode.GetBytes(featureId))); + DateTime val; + + _updateRecords.TryRemove(key, out val); + Save(); } @@ -71,8 +84,10 @@ namespace MediaBrowser.Common.Implementations.Security using (var provider = new MD5CryptoServiceProvider()) { DateTime last; - lock(_lck) UpdateRecords.TryGetValue(new Guid(provider.ComputeHash(Encoding.Unicode.GetBytes(featureId))), out last); - return last < DateTime.UtcNow ? last : DateTime.MinValue; // guard agains people just putting a large number in the file + _updateRecords.TryGetValue(new Guid(provider.ComputeHash(Encoding.Unicode.GetBytes(featureId))), out last); + + // guard agains people just putting a large number in the file + return last < DateTime.UtcNow ? last : DateTime.MinValue; } } @@ -80,7 +95,7 @@ namespace MediaBrowser.Common.Implementations.Security { string[] contents = null; var licenseFile = Filename; - lock (_lck) + lock (_fileLock) { try { @@ -95,13 +110,19 @@ namespace MediaBrowser.Common.Implementations.Security { //first line is reg key RegKey = contents[0]; + //next is legacy key - if (contents.Length > 1) LegacyKey = contents[1]; + if (contents.Length > 1) + { + // Don't need this anymore + } + //the rest of the lines should be pairs of features and timestamps for (var i = 2; i < contents.Length; i = i + 2) { var feat = Guid.Parse(contents[i]); - UpdateRecords[feat] = new DateTime(Convert.ToInt64(contents[i + 1])); + + SetUpdateRecord(feat, new DateTime(Convert.ToInt64(contents[i + 1]))); } } } @@ -109,16 +130,24 @@ namespace MediaBrowser.Common.Implementations.Security public void Save() { //build our array - var lines = new List<string> {RegKey, LegacyKey}; - foreach (var pair in UpdateRecords) + var lines = new List<string> + { + RegKey, + + // Legacy key + string.Empty + }; + + foreach (var pair in _updateRecords + .ToList()) { lines.Add(pair.Key.ToString()); - lines.Add(pair.Value.Ticks.ToString()); + lines.Add(pair.Value.Ticks.ToString(CultureInfo.InvariantCulture)); } var licenseFile = Filename; Directory.CreateDirectory(Path.GetDirectoryName(licenseFile)); - lock (_lck) File.WriteAllLines(licenseFile, lines); + lock (_fileLock) File.WriteAllLines(licenseFile, lines); } } } diff --git a/MediaBrowser.Common.Implementations/Security/MBRegistration.cs b/MediaBrowser.Common.Implementations/Security/MBRegistration.cs deleted file mode 100644 index dbb1b13e1..000000000 --- a/MediaBrowser.Common.Implementations/Security/MBRegistration.cs +++ /dev/null @@ -1,99 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Net; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Serialization; -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Common.Implementations.Security -{ - public static class MBRegistration - { - - private static MBLicenseFile _licenseFile; - private const string MBValidateUrl = Constants.Constants.MbAdminUrl + "service/registration/validate"; - - private static IApplicationPaths _appPaths; - private static INetworkManager _networkManager; - private static ILogger _logger; - private static IApplicationHost _applicationHost; - - private static MBLicenseFile LicenseFile - { - get { return _licenseFile ?? (_licenseFile = new MBLicenseFile(_appPaths)); } - } - - public static string SupporterKey - { - get { return LicenseFile.RegKey; } - set { LicenseFile.RegKey = value; LicenseFile.Save(); } - } - - public static string LegacyKey - { - get { return LicenseFile.LegacyKey; } - set { LicenseFile.LegacyKey = value; LicenseFile.Save(); } - } - - public static void Init(IApplicationPaths appPaths, INetworkManager networkManager, ILogManager logManager, IApplicationHost appHost) - { - // Ugly alert (static init) - - _appPaths = appPaths; - _networkManager = networkManager; - _logger = logManager.GetLogger("SecurityManager"); - _applicationHost = appHost; - } - - public static async Task<MBRegistrationRecord> GetRegistrationStatus(IHttpClient httpClient, IJsonSerializer jsonSerializer, string feature, string mb2Equivalent = null, string version = null) - { - //check the reg file first to alleviate strain on the MB admin server - must actually check in every 30 days tho - var reg = new RegRecord { registered = LicenseFile.LastChecked(feature) > DateTime.UtcNow.AddDays(-30) }; - var success = reg.registered; - - if (!reg.registered) - { - var mac = _networkManager.GetMacAddress(); - var data = new Dictionary<string, string> - { - { "feature", feature }, - { "key", SupporterKey }, - { "mac", mac }, - { "mb2equiv", mb2Equivalent }, - { "legacykey", LegacyKey }, - { "ver", version }, - { "platform", Environment.OSVersion.VersionString }, - { "isservice", _applicationHost.IsRunningAsService.ToString().ToLower() } - }; - - try - { - using (var json = await httpClient.Post(MBValidateUrl, data, CancellationToken.None).ConfigureAwait(false)) - { - reg = jsonSerializer.DeserializeFromStream<RegRecord>(json); - success = true; - } - - if (reg.registered) - { - LicenseFile.AddRegCheck(feature); - } - else - { - LicenseFile.RemoveRegCheck(feature); - } - - } - catch (Exception e) - { - _logger.ErrorException("Error checking registration status of {0}", e, feature); - } - } - - return new MBRegistrationRecord { IsRegistered = reg.registered, ExpirationDate = reg.expDate, RegChecked = true, RegError = !success}; - } - } -} diff --git a/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs b/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs index d0b108c7d..22fce1ce1 100644 --- a/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs +++ b/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs @@ -17,6 +17,8 @@ namespace MediaBrowser.Common.Implementations.Security /// </summary> public class PluginSecurityManager : ISecurityManager { + private const string MBValidateUrl = Constants.Constants.MbAdminUrl + "service/registration/validate"; + /// <summary> /// The _is MB supporter /// </summary> @@ -38,16 +40,23 @@ namespace MediaBrowser.Common.Implementations.Security { get { - LazyInitializer.EnsureInitialized(ref _isMbSupporter, ref _isMbSupporterInitialized, ref _isMbSupporterSyncLock, () => GetRegistrationStatus("MBSupporter", null, _appHost.ApplicationVersion.ToString()).Result.IsRegistered); + LazyInitializer.EnsureInitialized(ref _isMbSupporter, ref _isMbSupporterInitialized, ref _isMbSupporterSyncLock, () => GetSupporterRegistrationStatus().Result.IsRegistered); return _isMbSupporter.Value; } } + private MBLicenseFile _licenseFile; + private MBLicenseFile LicenseFile + { + get { return _licenseFile ?? (_licenseFile = new MBLicenseFile(_appPaths)); } + } + private readonly IHttpClient _httpClient; private readonly IJsonSerializer _jsonSerializer; private readonly IApplicationHost _appHost; - private readonly IApplicationPaths _applciationPaths; + private readonly ILogger _logger; private readonly INetworkManager _networkManager; + private readonly IApplicationPaths _appPaths; private IEnumerable<IRequiresRegistration> _registeredEntities; protected IEnumerable<IRequiresRegistration> RegisteredEntities @@ -69,12 +78,12 @@ namespace MediaBrowser.Common.Implementations.Security throw new ArgumentNullException("httpClient"); } - _applciationPaths = appPaths; - _networkManager = networkManager; _appHost = appHost; _httpClient = httpClient; _jsonSerializer = jsonSerializer; - MBRegistration.Init(_applciationPaths, _networkManager, logManager, _appHost); + _networkManager = networkManager; + _appPaths = appPaths; + _logger = logManager.GetLogger("SecurityManager"); } /// <summary> @@ -97,9 +106,9 @@ namespace MediaBrowser.Common.Implementations.Security /// <param name="feature">The feature.</param> /// <param name="mb2Equivalent">The MB2 equivalent.</param> /// <returns>Task{MBRegistrationRecord}.</returns> - public async Task<MBRegistrationRecord> GetRegistrationStatus(string feature, string mb2Equivalent = null) + public Task<MBRegistrationRecord> GetRegistrationStatus(string feature, string mb2Equivalent = null) { - return await MBRegistration.GetRegistrationStatus(_httpClient, _jsonSerializer, feature, mb2Equivalent).ConfigureAwait(false); + return GetRegistrationStatusInternal(feature, mb2Equivalent); } /// <summary> @@ -109,9 +118,14 @@ namespace MediaBrowser.Common.Implementations.Security /// <param name="mb2Equivalent">The MB2 equivalent.</param> /// <param name="version">The version of this feature</param> /// <returns>Task{MBRegistrationRecord}.</returns> - public async Task<MBRegistrationRecord> GetRegistrationStatus(string feature, string mb2Equivalent, string version) + public Task<MBRegistrationRecord> GetRegistrationStatus(string feature, string mb2Equivalent, string version) { - return await MBRegistration.GetRegistrationStatus(_httpClient, _jsonSerializer, feature, mb2Equivalent, version).ConfigureAwait(false); + return GetRegistrationStatusInternal(feature, mb2Equivalent, version); + } + + private Task<MBRegistrationRecord> GetSupporterRegistrationStatus() + { + return GetRegistrationStatusInternal("MBSupporter", null, _appHost.ApplicationVersion.ToString()); } /// <summary> @@ -122,38 +136,130 @@ namespace MediaBrowser.Common.Implementations.Security { get { - return MBRegistration.SupporterKey; + return LicenseFile.RegKey; } set { - if (value != MBRegistration.SupporterKey) + if (value != LicenseFile.RegKey) { - MBRegistration.SupporterKey = value; + LicenseFile.RegKey = value; + LicenseFile.Save(); + // re-load registration info Task.Run(() => LoadAllRegistrationInfo()); } } } - /// <summary> - /// Gets or sets the legacy key. - /// </summary> - /// <value>The legacy key.</value> - public string LegacyKey + public async Task<SupporterInfo> GetSupporterInfo() { - get + var key = SupporterKey; + + if (string.IsNullOrWhiteSpace(key)) { - return MBRegistration.LegacyKey; + return new SupporterInfo(); } - set + + var url = Constants.Constants.MbAdminUrl + "/service/supporter/retrieve?key=" + key; + + using (var stream = await _httpClient.Get(url, CancellationToken.None).ConfigureAwait(false)) { - if (value != MBRegistration.LegacyKey) + var response = _jsonSerializer.DeserializeFromStream<SuppporterInfoResponse>(stream); + + + var info = new SupporterInfo { - MBRegistration.LegacyKey = value; - // re-load registration info - Task.Run(() => LoadAllRegistrationInfo()); + Email = response.email, + PlanType = response.planType, + SupporterKey = response.supporterKey, + ExpirationDate = string.IsNullOrWhiteSpace(response.expDate) ? (DateTime?)null : DateTime.Parse(response.expDate), + RegistrationDate = DateTime.Parse(response.regDate), + IsActiveSupporter = IsMBSupporter + }; + + info.IsExpiredSupporter = info.ExpirationDate.HasValue && info.ExpirationDate < DateTime.UtcNow && !string.IsNullOrWhiteSpace(info.SupporterKey); + + // TODO: Now that we've pulled this down, might as well update the cached suppoter registrationinfo? + + return info; + } + } + + private async Task<MBRegistrationRecord> GetRegistrationStatusInternal(string feature, + string mb2Equivalent = null, + string version = null) + { + //check the reg file first to alleviate strain on the MB admin server - must actually check in every 30 days tho + var reg = new RegRecord + { + registered = LicenseFile.LastChecked(feature) > DateTime.UtcNow.AddDays(-7) + }; + + var success = reg.registered; + + if (!reg.registered) + { + var mac = _networkManager.GetMacAddress(); + var data = new Dictionary<string, string> + { + { "feature", feature }, + { "key", SupporterKey }, + { "mac", mac }, + { "mb2equiv", mb2Equivalent }, + { "ver", version }, + { "platform", Environment.OSVersion.VersionString }, + { "isservice", _appHost.IsRunningAsService.ToString().ToLower() } + }; + + try + { + using (var json = await _httpClient.Post(MBValidateUrl, data, CancellationToken.None).ConfigureAwait(false)) + { + reg = _jsonSerializer.DeserializeFromStream<RegRecord>(json); + success = true; + } + + if (reg.registered) + { + LicenseFile.AddRegCheck(feature); + } + else + { + LicenseFile.RemoveRegCheck(feature); + } + } + catch (Exception e) + { + _logger.ErrorException("Error checking registration status of {0}", e, feature); + } + } + + var record = new MBRegistrationRecord + { + IsRegistered = reg.registered, + ExpirationDate = reg.expDate, + RegChecked = true, + RegError = !success + }; + + record.TrialVersion = IsInTrial(reg.expDate, record.RegChecked, record.IsRegistered); + record.IsValid = !record.RegChecked || (record.IsRegistered || record.TrialVersion); + + return record; + } + + private bool IsInTrial(DateTime expirationDate, bool regChecked, bool isRegistered) + { + //don't set this until we've successfully obtained exp date + if (!regChecked) + { + return false; } + + var isInTrial = expirationDate > DateTime.UtcNow; + + return (isInTrial && !isRegistered); } /// <summary> diff --git a/MediaBrowser.Common.Implementations/Security/SuppporterInfoResponse.cs b/MediaBrowser.Common.Implementations/Security/SuppporterInfoResponse.cs new file mode 100644 index 000000000..49c5af8d8 --- /dev/null +++ b/MediaBrowser.Common.Implementations/Security/SuppporterInfoResponse.cs @@ -0,0 +1,14 @@ + +namespace MediaBrowser.Common.Implementations.Security +{ + internal class SuppporterInfoResponse + { + public string email { get; set; } + public string supporterKey { get; set; } + public int totalRegs { get; set; } + public int totalMachines { get; set; } + public string expDate { get; set; } + public string regDate { get; set; } + public string planType { get; set; } + } +} diff --git a/MediaBrowser.Common/Security/ISecurityManager.cs b/MediaBrowser.Common/Security/ISecurityManager.cs index 1555f1d86..935454353 100644 --- a/MediaBrowser.Common/Security/ISecurityManager.cs +++ b/MediaBrowser.Common/Security/ISecurityManager.cs @@ -1,5 +1,5 @@ -using System.Threading.Tasks; using MediaBrowser.Model.Entities; +using System.Threading.Tasks; namespace MediaBrowser.Common.Security { @@ -18,17 +18,10 @@ namespace MediaBrowser.Common.Security string SupporterKey { get; set; } /// <summary> - /// Gets or sets the legacy key. - /// </summary> - /// <value>The legacy key.</value> - string LegacyKey { get; set; } - - /// <summary> /// Gets the registration status. Overload to support existing plug-ins. /// </summary> /// <param name="feature">The feature.</param> /// <param name="mb2Equivalent">The MB2 equivalent.</param> - /// <param name="version">The version of the feature</param> /// <returns>Task{MBRegistrationRecord}.</returns> Task<MBRegistrationRecord> GetRegistrationStatus(string feature, string mb2Equivalent = null); @@ -40,10 +33,17 @@ namespace MediaBrowser.Common.Security /// <param name="version">The version of the feature</param> /// <returns>Task{MBRegistrationRecord}.</returns> Task<MBRegistrationRecord> GetRegistrationStatus(string feature, string mb2Equivalent, string version); + /// <summary> /// Load all registration info for all entities that require registration /// </summary> /// <returns></returns> Task LoadAllRegistrationInfo(); + + /// <summary> + /// Gets the supporter information. + /// </summary> + /// <returns>Task<SupporterInfo>.</returns> + Task<SupporterInfo> GetSupporterInfo(); } }
\ No newline at end of file diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs index b13403bbf..25d41565a 100644 --- a/MediaBrowser.Controller/Entities/Audio/Audio.cs +++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs @@ -38,6 +38,7 @@ namespace MediaBrowser.Controller.Entities.Audio Tags = new List<string>(); } + [IgnoreDataMember] public override bool SupportsAddingToPlaylist { get { return LocationType == LocationType.FileSystem && RunTimeTicks.HasValue; } @@ -118,6 +119,7 @@ namespace MediaBrowser.Controller.Entities.Audio /// Gets the type of the media. /// </summary> /// <value>The type of the media.</value> + [IgnoreDataMember] public override string MediaType { get diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs index 2eeec9715..dc9f83b3c 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs @@ -22,6 +22,7 @@ namespace MediaBrowser.Controller.Entities.Audio AlbumArtists = new List<string>(); } + [IgnoreDataMember] public override bool SupportsAddingToPlaylist { get { return true; } diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs index de527b68b..070572b9b 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Common.Progress; +using System.Runtime.Serialization; +using MediaBrowser.Common.Progress; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; @@ -26,6 +27,7 @@ namespace MediaBrowser.Controller.Entities.Audio } } + [IgnoreDataMember] public override bool SupportsAddingToPlaylist { get { return true; } diff --git a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs index f1dc56ac6..928eb6463 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.Serialization; namespace MediaBrowser.Controller.Entities.Audio { @@ -18,6 +19,7 @@ namespace MediaBrowser.Controller.Entities.Audio return "MusicGenre-" + Name; } + [IgnoreDataMember] public override bool SupportsAddingToPlaylist { get { return true; } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index fd7a33ddf..26b28ec72 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -53,6 +53,7 @@ namespace MediaBrowser.Controller.Entities public List<ItemImageInfo> ImageInfos { get; set; } + [IgnoreDataMember] public virtual bool SupportsAddingToPlaylist { get @@ -192,6 +193,7 @@ namespace MediaBrowser.Controller.Entities } } + [IgnoreDataMember] public virtual bool SupportsLocalMetadata { get diff --git a/MediaBrowser.Controller/Entities/Photo.cs b/MediaBrowser.Controller/Entities/Photo.cs index 1f38de9a3..367db5dcb 100644 --- a/MediaBrowser.Controller/Entities/Photo.cs +++ b/MediaBrowser.Controller/Entities/Photo.cs @@ -17,6 +17,7 @@ namespace MediaBrowser.Controller.Entities Taglines = new List<string>(); } + [IgnoreDataMember] public override bool SupportsLocalMetadata { get @@ -25,6 +26,7 @@ namespace MediaBrowser.Controller.Entities } } + [IgnoreDataMember] public override string MediaType { get @@ -38,6 +40,16 @@ namespace MediaBrowser.Controller.Entities { get { + return Album; + } + } + + + [IgnoreDataMember] + public PhotoAlbum Album + { + get + { return Parents.OfType<PhotoAlbum>().FirstOrDefault(); } } @@ -53,6 +65,11 @@ namespace MediaBrowser.Controller.Entities public double? Aperture { get; set; } public double? ShutterSpeed { get; set; } + public double? Latitude { get; set; } + public double? Longitude { get; set; } + public double? Altitude { get; set; } + public int? IsoSpeedRating { get; set; } + protected override bool GetBlockUnratedValue(UserConfiguration config) { return config.BlockUnratedItems.Contains(UnratedItem.Other); diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs index b82a400fe..6804b29b7 100644 --- a/MediaBrowser.Controller/Entities/TV/Season.cs +++ b/MediaBrowser.Controller/Entities/TV/Season.cs @@ -29,6 +29,7 @@ namespace MediaBrowser.Controller.Entities.TV } } + [IgnoreDataMember] public override bool SupportsAddingToPlaylist { get { return true; } diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index 856ed4fdf..d3b95eb0c 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -39,6 +39,7 @@ namespace MediaBrowser.Controller.Entities.TV DisplaySpecialsWithSeasons = true; } + [IgnoreDataMember] public override bool SupportsAddingToPlaylist { get { return true; } diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index ea530272d..492a4a02f 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -58,6 +58,7 @@ namespace MediaBrowser.Controller.Entities LinkedAlternateVersions = new List<LinkedChild>(); } + [IgnoreDataMember] public override bool SupportsAddingToPlaylist { get { return LocationType == LocationType.FileSystem && RunTimeTicks.HasValue; } @@ -238,6 +239,7 @@ namespace MediaBrowser.Controller.Entities /// Gets the type of the media. /// </summary> /// <value>The type of the media.</value> + [IgnoreDataMember] public override string MediaType { get diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index aeeaae073..6a78fa5d9 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -214,6 +214,7 @@ <Compile Include="Net\IRestfulService.cs" /> <Compile Include="Net\ISessionContext.cs" /> <Compile Include="Net\LoggedAttribute.cs" /> + <Compile Include="Net\StaticResultOptions.cs" /> <Compile Include="News\INewsService.cs" /> <Compile Include="Notifications\INotificationManager.cs" /> <Compile Include="Notifications\INotificationService.cs" /> diff --git a/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs b/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs index 567d20f39..329dbaa46 100644 --- a/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs +++ b/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs @@ -8,6 +8,12 @@ namespace MediaBrowser.Controller.Net public IAuthService AuthService { get; set; } /// <summary> + /// Gets or sets a value indicating whether or not to allow local unauthenticated access. + /// </summary> + /// <value><c>true</c> if [allow local]; otherwise, <c>false</c>.</value> + public bool AllowLocal { get; set; } + + /// <summary> /// The request filter is executed before the service. /// </summary> /// <param name="request">The http request wrapper</param> @@ -15,7 +21,7 @@ namespace MediaBrowser.Controller.Net /// <param name="requestDto">The request DTO</param> public void RequestFilter(IRequest request, IResponse response, object requestDto) { - AuthService.Authenticate(request, response, requestDto); + AuthService.Authenticate(request, response, requestDto, AllowLocal); } /// <summary> diff --git a/MediaBrowser.Controller/Net/IAuthService.cs b/MediaBrowser.Controller/Net/IAuthService.cs index 41859395b..dca70f58f 100644 --- a/MediaBrowser.Controller/Net/IAuthService.cs +++ b/MediaBrowser.Controller/Net/IAuthService.cs @@ -4,6 +4,6 @@ namespace MediaBrowser.Controller.Net { public interface IAuthService { - void Authenticate(IRequest request, IResponse response, object requestDto); + void Authenticate(IRequest request, IResponse response, object requestDto, bool allowLocal); } } diff --git a/MediaBrowser.Controller/Net/IHttpResultFactory.cs b/MediaBrowser.Controller/Net/IHttpResultFactory.cs index f0cfbbcfa..526bf4be2 100644 --- a/MediaBrowser.Controller/Net/IHttpResultFactory.cs +++ b/MediaBrowser.Controller/Net/IHttpResultFactory.cs @@ -1,8 +1,8 @@ -using System; +using ServiceStack.Web; +using System; using System.Collections.Generic; using System.IO; using System.Threading.Tasks; -using ServiceStack.Web; namespace MediaBrowser.Controller.Net { @@ -89,47 +89,29 @@ namespace MediaBrowser.Controller.Net bool isHeadRequest = false); /// <summary> - /// Gets the static file result. + /// Gets the static result. /// </summary> /// <param name="requestContext">The request context.</param> - /// <param name="path">The path.</param> - /// <param name="fileShare">The file share.</param> - /// <param name="responseHeaders">The response headers.</param> - /// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param> + /// <param name="options">The options.</param> /// <returns>System.Object.</returns> - object GetStaticFileResult(IRequest requestContext, string path, FileShare fileShare = FileShare.Read, IDictionary<string, string> responseHeaders = null, bool isHeadRequest = false); + object GetStaticResult(IRequest requestContext, StaticResultOptions options); /// <summary> /// Gets the static file result. /// </summary> /// <param name="requestContext">The request context.</param> /// <param name="path">The path.</param> - /// <param name="contentType">Type of the content.</param> - /// <param name="cacheCuration">The cache curation.</param> /// <param name="fileShare">The file share.</param> - /// <param name="responseHeaders">The response headers.</param> - /// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param> - /// <param name="throttle">if set to <c>true</c> [throttle].</param> - /// <param name="throttleLimit">The throttle limit.</param> /// <returns>System.Object.</returns> - object GetStaticFileResult(IRequest requestContext, - string path, - string contentType, - TimeSpan? cacheCuration = null, - FileShare fileShare = FileShare.Read, - IDictionary<string, string> responseHeaders = null, - bool isHeadRequest = false, - bool throttle = false, - long throttleLimit = 0); - + object GetStaticFileResult(IRequest requestContext, string path, FileShare fileShare = FileShare.Read); + /// <summary> - /// Gets the optimized serialized result using cache. + /// Gets the static file result. /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="request">The request.</param> - /// <param name="result">The result.</param> + /// <param name="requestContext">The request context.</param> + /// <param name="options">The options.</param> /// <returns>System.Object.</returns> - object GetOptimizedSerializedResultUsingCache<T>(IRequest request, T result) - where T : class; + object GetStaticFileResult(IRequest requestContext, + StaticFileResultOptions options); } } diff --git a/MediaBrowser.Controller/Net/StaticResultOptions.cs b/MediaBrowser.Controller/Net/StaticResultOptions.cs new file mode 100644 index 000000000..fde08c269 --- /dev/null +++ b/MediaBrowser.Controller/Net/StaticResultOptions.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; + +namespace MediaBrowser.Controller.Net +{ + public class StaticResultOptions + { + public string ContentType { get; set; } + public TimeSpan? CacheDuration { get; set; } + public DateTime? DateLastModified { get; set; } + public Guid CacheKey { get; set; } + + public Func<Task<Stream>> ContentFactory { get; set; } + + public bool IsHeadRequest { get; set; } + + public IDictionary<string, string> ResponseHeaders { get; set; } + + public bool Throttle { get; set; } + public long ThrottleLimit { get; set; } + public long MinThrottlePosition { get; set; } + + public StaticResultOptions() + { + ResponseHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); + } + } + + public class StaticFileResultOptions : StaticResultOptions + { + public string Path { get; set; } + + public FileShare FileShare { get; set; } + + public StaticFileResultOptions() + { + FileShare = FileShare.Read; + } + } +} diff --git a/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs b/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs index 6d5ed9eb8..3d08159d6 100644 --- a/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs +++ b/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs @@ -190,6 +190,8 @@ namespace MediaBrowser.Dlna.ContentDirectory if (string.Equals(flag, "BrowseMetadata")) { + + var folder = item as Folder; if (folder == null) @@ -198,10 +200,12 @@ namespace MediaBrowser.Dlna.ContentDirectory } else { + + var childrenResult = (await GetChildrenSorted(folder, user, sortCriteria, start, requested).ConfigureAwait(false)); totalCount = childrenResult.TotalRecordCount; - result.DocumentElement.AppendChild(_didlBuilder.GetFolderElement(result, folder, totalCount, filter)); + result.DocumentElement.AppendChild(_didlBuilder.GetFolderElement(result, folder, totalCount, filter, id)); } provided++; } @@ -531,10 +535,7 @@ namespace MediaBrowser.Dlna.ContentDirectory private BaseItem GetItemFromObjectId(string id, User user) { - return string.IsNullOrWhiteSpace(id) || string.Equals(id, "0", StringComparison.OrdinalIgnoreCase) - - // Samsung sometimes uses 1 as root - || string.Equals(id, "1", StringComparison.OrdinalIgnoreCase) + return DidlBuilder.IsIdRoot(id) ? user.RootFolder : ParseItemId(id, user); diff --git a/MediaBrowser.Dlna/Didl/DidlBuilder.cs b/MediaBrowser.Dlna/Didl/DidlBuilder.cs index 69fec1e44..53fac9a93 100644 --- a/MediaBrowser.Dlna/Didl/DidlBuilder.cs +++ b/MediaBrowser.Dlna/Didl/DidlBuilder.cs @@ -362,22 +362,46 @@ namespace MediaBrowser.Dlna.Didl container.AppendChild(res); } - public XmlElement GetFolderElement(XmlDocument doc, Folder folder, int childCount, Filter filter) + public static bool IsIdRoot(string id) + { + if (string.IsNullOrWhiteSpace(id) || + + string.Equals(id, "0", StringComparison.OrdinalIgnoreCase) + + // Samsung sometimes uses 1 as root + || string.Equals(id, "1", StringComparison.OrdinalIgnoreCase)) + { + return true; + } + + return false; + } + + public XmlElement GetFolderElement(XmlDocument doc, Folder folder, int childCount, Filter filter, string requestedId = null) { var container = doc.CreateElement(string.Empty, "container", NS_DIDL); container.SetAttribute("restricted", "0"); container.SetAttribute("searchable", "1"); container.SetAttribute("childCount", childCount.ToString(_usCulture)); - container.SetAttribute("id", folder.Id.ToString("N")); - var parent = folder.Parent; - if (parent == null) + if (string.Equals(requestedId, "0")) { - container.SetAttribute("parentID", "0"); + container.SetAttribute("id", "0"); + container.SetAttribute("parentID", "-1"); } else { - container.SetAttribute("parentID", parent.Id.ToString("N")); + container.SetAttribute("id", folder.Id.ToString("N")); + + var parent = folder.Parent; + if (parent == null) + { + container.SetAttribute("parentID", "0"); + } + else + { + container.SetAttribute("parentID", parent.Id.ToString("N")); + } } AddCommonFields(folder, container, filter); diff --git a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs index b8c64a787..a237a0d67 100644 --- a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs +++ b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs @@ -170,7 +170,10 @@ namespace MediaBrowser.Dlna.Ssdp values["ST"] = d.Type; values["USN"] = d.USN; - SendDatagram(header, values, endpoint, new IPEndPoint(d.Address, 0)); + // Commenting this out because binding to the local ipendpoint often throws an error + //SendDatagram(header, values, endpoint, new IPEndPoint(d.Address, 0)); + + SendDatagram(header, values, endpoint, null); if (_config.GetDlnaConfiguration().EnableDebugLogging) { diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 9263a3187..22873d910 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -62,6 +62,7 @@ <Compile Include="Subtitles\ISubtitleParser.cs" /> <Compile Include="Subtitles\ISubtitleWriter.cs" /> <Compile Include="Subtitles\JsonWriter.cs" /> + <Compile Include="Subtitles\ParserValues.cs" /> <Compile Include="Subtitles\SrtParser.cs" /> <Compile Include="Subtitles\SrtWriter.cs" /> <Compile Include="Subtitles\AssParser.cs" /> diff --git a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs index e5a727428..aaaafc226 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs @@ -1,4 +1,5 @@ -using System; +using MediaBrowser.Common.Extensions; +using System; using System.Collections.Generic; using System.Globalization; using System.IO; @@ -42,6 +43,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles subEvent.StartPositionTicks = GetTicks(sections[headers["Start"]]); subEvent.EndPositionTicks = GetTicks(sections[headers["End"]]); subEvent.Text = string.Join(",", sections.Skip(headers["Text"])); + subEvent.Text = subEvent.Text.Replace(@"\N", ParserValues.NewLine, StringComparison.OrdinalIgnoreCase); subEvent.Text = Regex.Replace(subEvent.Text, @"\{(\\[\w]+\(?([\w\d]+,?)+\)?)+\}", string.Empty, RegexOptions.IgnoreCase); trackInfo.TrackEvents.Add(subEvent); diff --git a/MediaBrowser.MediaEncoding/Subtitles/ParserValues.cs b/MediaBrowser.MediaEncoding/Subtitles/ParserValues.cs new file mode 100644 index 000000000..d79aeee76 --- /dev/null +++ b/MediaBrowser.MediaEncoding/Subtitles/ParserValues.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MediaBrowser.MediaEncoding.Subtitles +{ + public class ParserValues + { + public const string NewLine = "\r\n"; + } +} diff --git a/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs index 84cd1eb2d..ea565f70a 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs @@ -4,6 +4,7 @@ using System.Globalization; using System.IO; using System.Text.RegularExpressions; using System.Threading; +using MediaBrowser.Common.Extensions; namespace MediaBrowser.MediaEncoding.Subtitles { @@ -48,7 +49,8 @@ namespace MediaBrowser.MediaEncoding.Subtitles } multiline.Add(line); } - subEvent.Text = string.Join(@"\n", multiline); + subEvent.Text = string.Join(ParserValues.NewLine, multiline); + subEvent.Text = subEvent.Text.Replace(@"\N", ParserValues.NewLine, StringComparison.OrdinalIgnoreCase); subEvent.Text = Regex.Replace(subEvent.Text, @"\{(\\[\w]+\(?([\w\d]+,?)+\)?)+\}", string.Empty, RegexOptions.IgnoreCase); subEvent.Text = Regex.Replace(subEvent.Text, "<", "<", RegexOptions.IgnoreCase); subEvent.Text = Regex.Replace(subEvent.Text, ">", ">", RegexOptions.IgnoreCase); diff --git a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs index 559a05bc8..d82ef4e24 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs @@ -1,4 +1,5 @@ -using System; +using MediaBrowser.Common.Extensions; +using System; using System.IO; using System.Text; using System.Threading; @@ -147,7 +148,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles public static string GetFormattedText(string text) { - text = text.Replace("\\n", Environment.NewLine).Replace("\\n", Environment.NewLine); + text = text.Replace("\\n", ParserValues.NewLine, StringComparison.OrdinalIgnoreCase) + .Replace("\\n", ParserValues.NewLine, StringComparison.OrdinalIgnoreCase); + bool italic = false; for (int i = 0; i < 10; i++) // just look ten times... diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index df22b5e1f..7a3a7d2d0 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -194,17 +194,38 @@ namespace MediaBrowser.MediaEncoding.Subtitles MediaStream subtitleStream, CancellationToken cancellationToken) { - const string extractedFormat = "srt"; - if (!subtitleStream.IsExternal) { + string outputFormat; + string outputCodec; + + if (string.Equals(subtitleStream.Codec, "ass", StringComparison.OrdinalIgnoreCase)) + { + // Extract + outputCodec = "copy"; + outputFormat = "ass"; + } + else if (string.Equals(subtitleStream.Codec, "subrip", StringComparison.OrdinalIgnoreCase) || + string.Equals(subtitleStream.Codec, "srt", StringComparison.OrdinalIgnoreCase)) + { + // Extract + outputCodec = "copy"; + outputFormat = "srt"; + } + else + { + // Extract + outputCodec = "srt"; + outputFormat = "srt"; + } + // Extract - var outputPath = GetSubtitleCachePath(mediaPath, subtitleStream.Index, "." + extractedFormat); + var outputPath = GetSubtitleCachePath(mediaPath, subtitleStream.Index, "." + outputFormat); - await ExtractTextSubtitle(inputFiles, protocol, subtitleStream.Index, false, outputPath, cancellationToken) + await ExtractTextSubtitle(inputFiles, protocol, subtitleStream.Index, outputCodec, outputPath, cancellationToken) .ConfigureAwait(false); - return new Tuple<string, string>(outputPath, extractedFormat); + return new Tuple<string, string>(outputPath, outputFormat); } var currentFormat = (Path.GetExtension(subtitleStream.Path) ?? subtitleStream.Codec) @@ -213,12 +234,12 @@ namespace MediaBrowser.MediaEncoding.Subtitles if (GetReader(currentFormat, false) == null) { // Convert - var outputPath = GetSubtitleCachePath(mediaPath, subtitleStream.Index, "." + extractedFormat); + var outputPath = GetSubtitleCachePath(mediaPath, subtitleStream.Index, ".srt"); await ConvertTextSubtitleToSrt(subtitleStream.Path, outputPath, subtitleStream.Language, cancellationToken) .ConfigureAwait(false); - return new Tuple<string, string>(outputPath, extractedFormat); + return new Tuple<string, string>(outputPath, "srt"); } return new Tuple<string, string>(subtitleStream.Path, currentFormat); @@ -477,13 +498,13 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// <param name="inputFiles">The input files.</param> /// <param name="protocol">The protocol.</param> /// <param name="subtitleStreamIndex">Index of the subtitle stream.</param> - /// <param name="copySubtitleStream">if set to true, copy stream instead of converting.</param> + /// <param name="outputCodec">The output codec.</param> /// <param name="outputPath">The output path.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> /// <exception cref="System.ArgumentException">Must use inputPath list overload</exception> private async Task ExtractTextSubtitle(string[] inputFiles, MediaProtocol protocol, int subtitleStreamIndex, - bool copySubtitleStream, string outputPath, CancellationToken cancellationToken) + string outputCodec, string outputPath, CancellationToken cancellationToken) { var semaphore = GetLock(outputPath); @@ -494,7 +515,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles if (!File.Exists(outputPath)) { await ExtractTextSubtitleInternal(_mediaEncoder.GetInputArgument(inputFiles, protocol), subtitleStreamIndex, - copySubtitleStream, outputPath, cancellationToken).ConfigureAwait(false); + outputCodec, outputPath, cancellationToken).ConfigureAwait(false); } } finally @@ -503,23 +524,8 @@ namespace MediaBrowser.MediaEncoding.Subtitles } } - /// <summary> - /// Extracts the text subtitle. - /// </summary> - /// <param name="inputPath">The input path.</param> - /// <param name="subtitleStreamIndex">Index of the subtitle stream.</param> - /// <param name="copySubtitleStream">if set to true, copy stream instead of converting.</param> - /// <param name="outputPath">The output path.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException">inputPath - /// or - /// outputPath - /// or - /// cancellationToken</exception> - /// <exception cref="System.ApplicationException"></exception> private async Task ExtractTextSubtitleInternal(string inputPath, int subtitleStreamIndex, - bool copySubtitleStream, string outputPath, CancellationToken cancellationToken) + string outputCodec, string outputPath, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(inputPath)) { @@ -533,14 +539,8 @@ namespace MediaBrowser.MediaEncoding.Subtitles Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); - var processArgs = string.Format("-i {0} -map 0:{1} -an -vn -c:s srt \"{2}\"", inputPath, - subtitleStreamIndex, outputPath); - - if (copySubtitleStream) - { - processArgs = string.Format("-i {0} -map 0:{1} -an -vn -c:s copy \"{2}\"", inputPath, - subtitleStreamIndex, outputPath); - } + var processArgs = string.Format("-i {0} -map 0:{1} -an -vn -c:s {2} \"{3}\"", inputPath, + subtitleStreamIndex, outputCodec, outputPath); var process = new Process { diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index 360d2d862..ec5a26eee 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -732,7 +732,11 @@ namespace MediaBrowser.Model.Dto public ImageOrientation? ImageOrientation { get; set; } public double? Aperture { get; set; } public double? ShutterSpeed { get; set; } - + public double? Latitude { get; set; } + public double? Longitude { get; set; } + public double? Altitude { get; set; } + public int? IsoSpeedRating { get; set; } + /// <summary> /// Gets a value indicating whether this instance can resume. /// </summary> diff --git a/MediaBrowser.Model/Entities/MBRegistrationRecord.cs b/MediaBrowser.Model/Entities/MBRegistrationRecord.cs index e72a5011c..3a4af19d8 100644 --- a/MediaBrowser.Model/Entities/MBRegistrationRecord.cs +++ b/MediaBrowser.Model/Entities/MBRegistrationRecord.cs @@ -5,25 +5,21 @@ namespace MediaBrowser.Model.Entities public class MBRegistrationRecord { public DateTime ExpirationDate { get; set; } - public bool IsRegistered { get; set;} + public bool IsRegistered { get; set; } public bool RegChecked { get; set; } public bool RegError { get; set; } - private bool? _isInTrial; - public bool TrialVersion - { - get - { - if (_isInTrial == null) - { - if (!RegChecked) return false; //don't set this until we've successfully obtained exp date - _isInTrial = ExpirationDate > DateTime.Now; - } - return (_isInTrial.Value && !IsRegistered); - } - } - public bool IsValid - { - get { return !RegChecked || (IsRegistered || TrialVersion); } - } + public bool TrialVersion { get; set; } + public bool IsValid { get; set; } + } + + public class SupporterInfo + { + public string Email { get; set; } + public string SupporterKey { get; set; } + public DateTime? ExpirationDate { get; set; } + public DateTime RegistrationDate { get; set; } + public string PlanType { get; set; } + public bool IsActiveSupporter { get; set; } + public bool IsExpiredSupporter { get; set; } } }
\ No newline at end of file diff --git a/MediaBrowser.Model/Entities/PluginSecurityInfo.cs b/MediaBrowser.Model/Entities/PluginSecurityInfo.cs index e338e43f8..5cab55013 100644 --- a/MediaBrowser.Model/Entities/PluginSecurityInfo.cs +++ b/MediaBrowser.Model/Entities/PluginSecurityInfo.cs @@ -13,12 +13,6 @@ namespace MediaBrowser.Model.Entities public string SupporterKey { get; set; } /// <summary> - /// Gets or sets the legacy supporter key. - /// </summary> - /// <value><c>The legacy supporter key</value> - public string LegacyKey { get; set; } - - /// <summary> /// Gets or sets a value indicating whether this instance is MB supporter. /// </summary> /// <value><c>true</c> if this instance is MB supporter; otherwise, <c>false</c>.</value> diff --git a/MediaBrowser.Providers/Photos/PhotoProvider.cs b/MediaBrowser.Providers/Photos/PhotoProvider.cs index 123c91d07..b298c62e7 100644 --- a/MediaBrowser.Providers/Photos/PhotoProvider.cs +++ b/MediaBrowser.Providers/Photos/PhotoProvider.cs @@ -123,6 +123,19 @@ namespace MediaBrowser.Providers.Photos item.ExposureTime = image.ImageTag.ExposureTime; item.FocalLength = image.ImageTag.FocalLength; + + item.Latitude = image.ImageTag.Latitude; + item.Longitude = image.ImageTag.Longitude; + item.Altitude = image.ImageTag.Altitude; + + if (image.ImageTag.ISOSpeedRatings.HasValue) + { + item.IsoSpeedRating = Convert.ToInt32(image.ImageTag.ISOSpeedRatings.Value); + } + else + { + item.IsoSpeedRating = null; + } } catch (Exception e) { @@ -145,7 +158,7 @@ namespace MediaBrowser.Providers.Photos public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) { // Moved to plural AlbumArtists - if (date < new DateTime(2014, 8, 28)) + if (date < new DateTime(2014, 8, 29)) { // Revamped vaptured metadata return true; diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index 61517ce6e..922287f6e 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -1,5 +1,4 @@ -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.IO; +using MediaBrowser.Common.IO; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Drawing; @@ -369,6 +368,19 @@ namespace MediaBrowser.Server.Implementations.Dto dto.ImageOrientation = item.Orientation; dto.Aperture = item.Aperture; dto.ShutterSpeed = item.ShutterSpeed; + + dto.Latitude = item.Latitude; + dto.Longitude = item.Longitude; + dto.Altitude = item.Altitude; + dto.IsoSpeedRating = item.IsoSpeedRating; + + var album = item.Album; + + if (album != null) + { + dto.Album = item.Name; + dto.AlbumId = item.Id.ToString("N"); + } } private void SetMusicVideoProperties(BaseItemDto dto, MusicVideo item) diff --git a/MediaBrowser.Server.Implementations/EntryPoints/LoadRegistrations.cs b/MediaBrowser.Server.Implementations/EntryPoints/LoadRegistrations.cs index c2c4056f5..27170ced9 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/LoadRegistrations.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/LoadRegistrations.cs @@ -2,6 +2,8 @@ using MediaBrowser.Controller.Plugins; using MediaBrowser.Model.Logging; using System; +using System.Threading; +using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.EntryPoints { @@ -20,6 +22,8 @@ namespace MediaBrowser.Server.Implementations.EntryPoints /// </summary> private readonly ILogger _logger; + private Timer _timer; + /// <summary> /// Initializes a new instance of the <see cref="LoadRegistrations" /> class. /// </summary> @@ -35,7 +39,12 @@ namespace MediaBrowser.Server.Implementations.EntryPoints /// <summary> /// Runs this instance. /// </summary> - public async void Run() + public void Run() + { + _timer = new Timer(s => LoadAllRegistrations(), null, TimeSpan.FromMilliseconds(100), TimeSpan.FromHours(24)); + } + + private async Task LoadAllRegistrations() { try { @@ -52,6 +61,11 @@ namespace MediaBrowser.Server.Implementations.EntryPoints /// </summary> public void Dispose() { + if (_timer != null) + { + _timer.Dispose(); + _timer = null; + } } } } diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index 1cec4461b..16ca8b099 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -14,6 +14,7 @@ using ServiceStack.Host.HttpListener; using ServiceStack.Logging; using ServiceStack.Web; using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; @@ -39,13 +40,15 @@ namespace MediaBrowser.Server.Implementations.HttpServer public event EventHandler<WebSocketConnectEventArgs> WebSocketConnected; + private readonly ConcurrentDictionary<string, string> _localEndPoints = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase); + /// <summary> /// Gets the local end points. /// </summary> /// <value>The local end points.</value> public IEnumerable<string> LocalEndPoints { - get { return _listener == null ? new List<string>() : _listener.LocalEndPoints; } + get { return _listener == null ? new List<string>() : _localEndPoints.Keys.ToList(); } } public HttpListenerHost(IApplicationHost applicationHost, ILogManager logManager, string serviceName, string handlerPath, string defaultRedirectPath, params Assembly[] assembliesWithServices) @@ -151,6 +154,11 @@ namespace MediaBrowser.Server.Implementations.HttpServer return this; } + private void OnRequestReceived(string localEndPoint) + { + _localEndPoints.GetOrAdd(localEndPoint, localEndPoint); + } + /// <summary> /// Starts the Web Service /// </summary> @@ -159,9 +167,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer HostContext.Config.HandlerFactoryPath = ListenerRequest.GetHandlerPathIfAny(UrlPrefixes.First()); _listener = NativeWebSocket.IsSupported - ? _listener = new HttpListenerServer(_logger) + ? _listener = new HttpListenerServer(_logger, OnRequestReceived) //? _listener = new WebSocketSharpListener(_logger) - : _listener = new WebSocketSharpListener(_logger); + : _listener = new WebSocketSharpListener(_logger, OnRequestReceived); _listener.WebSocketHandler = WebSocketHandler; _listener.ErrorHandler = ErrorHandler; diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs index be3e5f005..9997cfbdb 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs @@ -289,41 +289,28 @@ namespace MediaBrowser.Server.Implementations.HttpServer return null; } - /// <summary> - /// Gets the static file result. - /// </summary> - /// <param name="requestContext">The request context.</param> - /// <param name="path">The path.</param> - /// <param name="fileShare">The file share.</param> - /// <param name="responseHeaders">The response headers.</param> - /// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param> - /// <returns>System.Object.</returns> - /// <exception cref="ArgumentNullException">path</exception> - /// <exception cref="System.ArgumentNullException">path</exception> public object GetStaticFileResult(IRequest requestContext, string path, - FileShare fileShare = FileShare.Read, - IDictionary<string, string> responseHeaders = null, - bool isHeadRequest = false) + FileShare fileShare = FileShare.Read) { if (string.IsNullOrEmpty(path)) { throw new ArgumentNullException("path"); } - return GetStaticFileResult(requestContext, path, MimeTypes.GetMimeType(path), null, fileShare, responseHeaders, isHeadRequest); + return GetStaticFileResult(requestContext, new StaticFileResultOptions + { + Path = path, + FileShare = fileShare + }); } public object GetStaticFileResult(IRequest requestContext, - string path, - string contentType, - TimeSpan? cacheCuration = null, - FileShare fileShare = FileShare.Read, - IDictionary<string, string> responseHeaders = null, - bool isHeadRequest = false, - bool throttle = false, - long throttleLimit = 0) + StaticFileResultOptions options) { + var path = options.Path; + var fileShare = options.FileShare; + if (string.IsNullOrEmpty(path)) { throw new ArgumentNullException("path"); @@ -334,11 +321,18 @@ namespace MediaBrowser.Server.Implementations.HttpServer throw new ArgumentException("FileShare must be either Read or ReadWrite"); } - var dateModified = _fileSystem.GetLastWriteTimeUtc(path); + if (string.IsNullOrWhiteSpace(options.ContentType)) + { + options.ContentType = MimeTypes.GetMimeType(path); + } - var cacheKey = path + dateModified.Ticks; + options.DateLastModified = _fileSystem.GetLastWriteTimeUtc(path); + var cacheKey = path + options.DateLastModified.Value.Ticks; - return GetStaticResult(requestContext, cacheKey.GetMD5(), dateModified, cacheCuration, contentType, () => Task.FromResult(GetFileStream(path, fileShare)), responseHeaders, isHeadRequest, throttle, throttleLimit); + options.CacheKey = cacheKey.GetMD5(); + options.ContentFactory = () => Task.FromResult(GetFileStream(path, fileShare)); + + return GetStaticResult(requestContext, options); } /// <summary> @@ -352,21 +346,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer return _fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, fileShare, true); } - /// <summary> - /// Gets the static result. - /// </summary> - /// <param name="requestContext">The request context.</param> - /// <param name="cacheKey">The cache key.</param> - /// <param name="lastDateModified">The last date modified.</param> - /// <param name="cacheDuration">Duration of the cache.</param> - /// <param name="contentType">Type of the content.</param> - /// <param name="factoryFn">The factory fn.</param> - /// <param name="responseHeaders">The response headers.</param> - /// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param> - /// <returns>System.Object.</returns> - /// <exception cref="System.ArgumentNullException">cacheKey - /// or - /// factoryFn</exception> public object GetStaticResult(IRequest requestContext, Guid cacheKey, DateTime? lastDateModified, @@ -376,39 +355,37 @@ namespace MediaBrowser.Server.Implementations.HttpServer IDictionary<string, string> responseHeaders = null, bool isHeadRequest = false) { - return GetStaticResult(requestContext, cacheKey, lastDateModified, cacheDuration, contentType, factoryFn, - responseHeaders, isHeadRequest, false, 0); + return GetStaticResult(requestContext, new StaticResultOptions + { + CacheDuration = cacheDuration, + CacheKey = cacheKey, + ContentFactory = factoryFn, + ContentType = contentType, + DateLastModified = lastDateModified, + IsHeadRequest = isHeadRequest, + ResponseHeaders = responseHeaders + }); } - public object GetStaticResult(IRequest requestContext, - Guid cacheKey, - DateTime? lastDateModified, - TimeSpan? cacheDuration, - string contentType, - Func<Task<Stream>> factoryFn, - IDictionary<string, string> responseHeaders = null, - bool isHeadRequest = false, - bool throttle = false, - long throttleLimit = 0) + public object GetStaticResult(IRequest requestContext, StaticResultOptions options) { + var cacheKey = options.CacheKey; + options.ResponseHeaders = options.ResponseHeaders ?? new Dictionary<string, string>(); + var contentType = options.ContentType; + if (cacheKey == Guid.Empty) { throw new ArgumentNullException("cacheKey"); } - if (factoryFn == null) + if (options.ContentFactory == null) { throw new ArgumentNullException("factoryFn"); } var key = cacheKey.ToString("N"); - if (responseHeaders == null) - { - responseHeaders = new Dictionary<string, string>(); - } - // See if the result is already cached in the browser - var result = GetCachedResult(requestContext, responseHeaders, cacheKey, key, lastDateModified, cacheDuration, contentType); + var result = GetCachedResult(requestContext, options.ResponseHeaders, cacheKey, key, options.DateLastModified, options.CacheDuration, contentType); if (result != null) { @@ -416,8 +393,8 @@ namespace MediaBrowser.Server.Implementations.HttpServer } var compress = ShouldCompressResponse(requestContext, contentType); - var hasOptions = GetStaticResult(requestContext, responseHeaders, contentType, factoryFn, compress, isHeadRequest, throttle, throttleLimit).Result; - AddResponseHeaders(hasOptions, responseHeaders); + var hasOptions = GetStaticResult(requestContext, options, compress).Result; + AddResponseHeaders(hasOptions, options.ResponseHeaders); return hasOptions; } @@ -473,20 +450,13 @@ namespace MediaBrowser.Server.Implementations.HttpServer /// </summary> private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); - /// <summary> - /// Gets the static result. - /// </summary> - /// <param name="requestContext">The request context.</param> - /// <param name="responseHeaders">The response headers.</param> - /// <param name="contentType">Type of the content.</param> - /// <param name="factoryFn">The factory fn.</param> - /// <param name="compress">if set to <c>true</c> [compress].</param> - /// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param> - /// <param name="throttle">if set to <c>true</c> [throttle].</param> - /// <param name="throttleLimit">The throttle limit.</param> - /// <returns>Task{IHasOptions}.</returns> - private async Task<IHasOptions> GetStaticResult(IRequest requestContext, IDictionary<string, string> responseHeaders, string contentType, Func<Task<Stream>> factoryFn, bool compress, bool isHeadRequest, bool throttle, long throttleLimit = 0) + private async Task<IHasOptions> GetStaticResult(IRequest requestContext, StaticResultOptions options, bool compress) { + var isHeadRequest = options.IsHeadRequest; + var factoryFn = options.ContentFactory; + var contentType = options.ContentType; + var responseHeaders = options.ResponseHeaders; + var requestedCompressionType = requestContext.GetCompressionType(); if (!compress || string.IsNullOrEmpty(requestedCompressionType)) @@ -499,8 +469,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer { return new RangeRequestWriter(rangeHeader, stream, contentType, isHeadRequest) { - Throttle = throttle, - ThrottleLimit = throttleLimit + Throttle = options.Throttle, + ThrottleLimit = options.ThrottleLimit, + MinThrottlePosition = options.MinThrottlePosition }; } @@ -515,8 +486,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer return new StreamWriter(stream, contentType, _logger) { - Throttle = throttle, - ThrottleLimit = throttleLimit + Throttle = options.Throttle, + ThrottleLimit = options.ThrottleLimit, + MinThrottlePosition = options.MinThrottlePosition }; } @@ -746,14 +718,5 @@ namespace MediaBrowser.Server.Implementations.HttpServer throw error; } - - public object GetOptimizedSerializedResultUsingCache<T>(IRequest request, T result) - where T : class - { - var json = _jsonSerializer.SerializeToString(result); - var cacheKey = json.GetMD5(); - - return GetOptimizedResultUsingCache(request, cacheKey, null, null, () => result); - } } }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/HttpServer/IHttpListener.cs b/MediaBrowser.Server.Implementations/HttpServer/IHttpListener.cs index 1d80a263c..86e8856cf 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/IHttpListener.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/IHttpListener.cs @@ -8,8 +8,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer { public interface IHttpListener : IDisposable { - IEnumerable<string> LocalEndPoints { get; } - /// <summary> /// Gets or sets the error handler. /// </summary> diff --git a/MediaBrowser.Server.Implementations/HttpServer/NetListener/HttpListenerServer.cs b/MediaBrowser.Server.Implementations/HttpServer/NetListener/HttpListenerServer.cs index bdc2750fb..118bec60e 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/NetListener/HttpListenerServer.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/NetListener/HttpListenerServer.cs @@ -4,7 +4,6 @@ using ServiceStack; using ServiceStack.Host.HttpListener; using ServiceStack.Web; using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Net; @@ -20,26 +19,18 @@ namespace MediaBrowser.Server.Implementations.HttpServer.NetListener private HttpListener _listener; private readonly AutoResetEvent _listenForNextRequest = new AutoResetEvent(false); - public System.Action<Exception, IRequest> ErrorHandler { get; set; } + public Action<Exception, IRequest> ErrorHandler { get; set; } public Action<WebSocketConnectEventArgs> WebSocketHandler { get; set; } - public System.Func<IHttpRequest, Uri, Task> RequestHandler { get; set; } + public Func<IHttpRequest, Uri, Task> RequestHandler { get; set; } - private readonly ConcurrentDictionary<string, string> _localEndPoints = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase); + private readonly Action<string> _endpointListener; - public HttpListenerServer(ILogger logger) + public HttpListenerServer(ILogger logger, Action<string> endpointListener) { _logger = logger; + _endpointListener = endpointListener; } - /// <summary> - /// Gets the local end points. - /// </summary> - /// <value>The local end points.</value> - public IEnumerable<string> LocalEndPoints - { - get { return _localEndPoints.Keys.ToList(); } - } - private List<string> UrlPrefixes { get; set; } public void Start(IEnumerable<string> urlPrefixes) @@ -47,7 +38,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.NetListener UrlPrefixes = urlPrefixes.ToList(); if (_listener == null) - _listener = new System.Net.HttpListener(); + _listener = new HttpListener(); //HostContext.Config.HandlerFactoryPath = ListenerRequest.GetHandlerPathIfAny(UrlPrefixes.First()); @@ -229,7 +220,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.NetListener { var address = endpoint.ToString(); - _localEndPoints.GetOrAdd(address, address); + _endpointListener(address); } LogRequest(_logger, request); diff --git a/MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs b/MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs index 5fd43aa76..657545069 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs @@ -26,6 +26,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer public bool Throttle { get; set; } public long ThrottleLimit { get; set; } + public long MinThrottlePosition; /// <summary> /// The _options @@ -166,7 +167,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer { responseStream = new ThrottledStream(responseStream, ThrottleLimit) { - MinThrottlePosition = ThrottleLimit * 180 + MinThrottlePosition = MinThrottlePosition }; } var task = WriteToAsync(responseStream); diff --git a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs index 19870c435..2b9ae7d09 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs @@ -42,7 +42,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security /// </summary> public string HtmlRedirect { get; set; } - public void Authenticate(IRequest req, IResponse res, object requestDto) + public void Authenticate(IRequest req, IResponse res, object requestDto, bool allowLocal) { if (HostContext.HasValidAuthSecret(req)) return; @@ -50,13 +50,13 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security //ExecuteBasic(req, res, requestDto); //first check if session is authenticated //if (res.IsClosed) return; //AuthenticateAttribute already closed the request (ie auth failed) - ValidateUser(req); + ValidateUser(req, allowLocal); } // TODO: Remove this when all clients have supported the new sescurity - private readonly List<string> _updatedClients = new List<string>(){"Dashboard"}; + private readonly List<string> _updatedClients = new List<string>() { "Dashboard", "Chromecast" }; - private void ValidateUser(IRequest req) + private void ValidateUser(IRequest req, bool allowLocal) { //This code is executed before the service var auth = AuthorizationContext.GetAuthorizationInfo(req); @@ -65,7 +65,10 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security || _config.Configuration.EnableTokenAuthentication || _updatedClients.Contains(auth.Client ?? string.Empty, StringComparer.OrdinalIgnoreCase)) { - SessionManager.ValidateSecurityToken(auth.Token); + if (!allowLocal || !req.IsLocal) + { + SessionManager.ValidateSecurityToken(auth.Token); + } } var user = string.IsNullOrWhiteSpace(auth.UserId) @@ -96,35 +99,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security } } - private void ExecuteBasic(IRequest req, IResponse res, object requestDto) - { - if (AuthenticateService.AuthProviders == null) - throw new InvalidOperationException( - "The AuthService must be initialized by calling AuthService.Init to use an authenticate attribute"); - - var matchingOAuthConfigs = AuthenticateService.AuthProviders.Where(x => - this.Provider.IsNullOrEmpty() - || x.Provider == this.Provider).ToList(); - - if (matchingOAuthConfigs.Count == 0) - { - res.WriteError(req, requestDto, "No OAuth Configs found matching {0} provider" - .Fmt(this.Provider ?? "any")); - res.EndRequest(); - } - - matchingOAuthConfigs.OfType<IAuthWithRequest>() - .Each(x => x.PreAuthenticate(req, res)); - - var session = req.GetSession(); - if (session == null || !matchingOAuthConfigs.Any(x => session.IsAuthorized(x.Provider))) - { - if (this.DoHtmlRedirectIfConfigured(req, res, true)) return; - - AuthProvider.HandleFailedAuth(matchingOAuthConfigs[0], session, req, res); - } - } - protected bool DoHtmlRedirectIfConfigured(IRequest req, IResponse res, bool includeRedirectParam = false) { var htmlRedirect = this.HtmlRedirect ?? AuthenticateService.HtmlRedirect; diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs index 477aa3878..f2fae9e90 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs @@ -3,7 +3,6 @@ using MediaBrowser.Model.Logging; using ServiceStack; using ServiceStack.Web; using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; @@ -15,20 +14,16 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp { public class WebSocketSharpListener : IHttpListener { - private readonly ConcurrentDictionary<string, string> _localEndPoints = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase); private WebSocketSharp.Net.HttpListener _listener; private readonly AutoResetEvent _listenForNextRequest = new AutoResetEvent(false); private readonly ILogger _logger; + private readonly Action<string> _endpointListener; - public WebSocketSharpListener(ILogger logger) + public WebSocketSharpListener(ILogger logger, Action<string> endpointListener) { _logger = logger; - } - - public IEnumerable<string> LocalEndPoints - { - get { return _localEndPoints.Keys.ToList(); } + _endpointListener = endpointListener; } public Action<Exception, IRequest> ErrorHandler { get; set; } @@ -170,7 +165,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp { var address = endpoint.ToString(); - _localEndPoints.GetOrAdd(address, address); + _endpointListener(address); } LogRequest(_logger, request); diff --git a/MediaBrowser.Server.Implementations/HttpServer/StreamWriter.cs b/MediaBrowser.Server.Implementations/HttpServer/StreamWriter.cs index f1112ae0b..28fc094f7 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/StreamWriter.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/StreamWriter.cs @@ -38,7 +38,8 @@ namespace MediaBrowser.Server.Implementations.HttpServer public bool Throttle { get; set; } public long ThrottleLimit { get; set; } - + public long MinThrottlePosition; + /// <summary> /// Initializes a new instance of the <see cref="StreamWriter" /> class. /// </summary> @@ -84,7 +85,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer { responseStream = new ThrottledStream(responseStream, ThrottleLimit) { - MinThrottlePosition = ThrottleLimit * 180 + MinThrottlePosition = MinThrottlePosition }; } var task = WriteToAsync(responseStream); diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/ar.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/ar.json index 91796d5dc..84f1d5aaa 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/ar.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/ar.json @@ -429,5 +429,14 @@ "TabMusicVideos": "\u0645\u0648\u0633\u064a\u0642\u0649 \u0627\u0644\u0641\u064a\u062f\u064a\u0648", "BirthPlaceValue": "Birth place: {0}", "DeathDateValue": "Died: {0}", - "BirthDateValue": "Born: {0}" + "BirthDateValue": "Born: {0}", + "HeaderLatestReviews": "Latest Reviews", + "HeaderPluginInstallation": "Plugin Installation", + "MessageAlreadyInstalled": "This version is already installed.", + "ValueReviewCount": "{0} Reviews", + "MessageYouHaveVersionInstalled": "You currently have version {0} installed.", + "MessageTrialExpired": "The trial period for this feature has expired", + "MessageTrialWillExpireIn": "The trial period for this feature will expire in {0} day(s)", + "MessageInstallPluginFromApp": "This plugin must be installed from with in the app you intend to use it in.", + "ValuePriceUSD": "Price: {0} (USD)" }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/ca.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/ca.json index 1440a079c..8bec53c5f 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/ca.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/ca.json @@ -429,5 +429,14 @@ "TabMusicVideos": "Music Videos", "BirthPlaceValue": "Birth place: {0}", "DeathDateValue": "Died: {0}", - "BirthDateValue": "Born: {0}" + "BirthDateValue": "Born: {0}", + "HeaderLatestReviews": "Latest Reviews", + "HeaderPluginInstallation": "Plugin Installation", + "MessageAlreadyInstalled": "This version is already installed.", + "ValueReviewCount": "{0} Reviews", + "MessageYouHaveVersionInstalled": "You currently have version {0} installed.", + "MessageTrialExpired": "The trial period for this feature has expired", + "MessageTrialWillExpireIn": "The trial period for this feature will expire in {0} day(s)", + "MessageInstallPluginFromApp": "This plugin must be installed from with in the app you intend to use it in.", + "ValuePriceUSD": "Price: {0} (USD)" }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json index e9e733300..f2219933f 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json @@ -429,5 +429,14 @@ "TabMusicVideos": "Hudebn\u00ed videa", "BirthPlaceValue": "Birth place: {0}", "DeathDateValue": "Died: {0}", - "BirthDateValue": "Born: {0}" + "BirthDateValue": "Born: {0}", + "HeaderLatestReviews": "Latest Reviews", + "HeaderPluginInstallation": "Plugin Installation", + "MessageAlreadyInstalled": "This version is already installed.", + "ValueReviewCount": "{0} Reviews", + "MessageYouHaveVersionInstalled": "You currently have version {0} installed.", + "MessageTrialExpired": "The trial period for this feature has expired", + "MessageTrialWillExpireIn": "The trial period for this feature will expire in {0} day(s)", + "MessageInstallPluginFromApp": "This plugin must be installed from with in the app you intend to use it in.", + "ValuePriceUSD": "Price: {0} (USD)" }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/da.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/da.json index 4703d6b9f..7d7492e64 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/da.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/da.json @@ -429,5 +429,14 @@ "TabMusicVideos": "Musik Videoer", "BirthPlaceValue": "Birth place: {0}", "DeathDateValue": "Died: {0}", - "BirthDateValue": "Born: {0}" + "BirthDateValue": "Born: {0}", + "HeaderLatestReviews": "Latest Reviews", + "HeaderPluginInstallation": "Plugin Installation", + "MessageAlreadyInstalled": "This version is already installed.", + "ValueReviewCount": "{0} Reviews", + "MessageYouHaveVersionInstalled": "You currently have version {0} installed.", + "MessageTrialExpired": "The trial period for this feature has expired", + "MessageTrialWillExpireIn": "The trial period for this feature will expire in {0} day(s)", + "MessageInstallPluginFromApp": "This plugin must be installed from with in the app you intend to use it in.", + "ValuePriceUSD": "Price: {0} (USD)" }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json index e671c7da0..dfa4fd59e 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json @@ -429,5 +429,14 @@ "TabMusicVideos": "Musikvideos", "BirthPlaceValue": "Geburtsort: {0}", "DeathDateValue": "Gestorben: {0}", - "BirthDateValue": "Geboren: {0}" + "BirthDateValue": "Geboren: {0}", + "HeaderLatestReviews": "Latest Reviews", + "HeaderPluginInstallation": "Plugin Installation", + "MessageAlreadyInstalled": "This version is already installed.", + "ValueReviewCount": "{0} Reviews", + "MessageYouHaveVersionInstalled": "You currently have version {0} installed.", + "MessageTrialExpired": "The trial period for this feature has expired", + "MessageTrialWillExpireIn": "The trial period for this feature will expire in {0} day(s)", + "MessageInstallPluginFromApp": "This plugin must be installed from with in the app you intend to use it in.", + "ValuePriceUSD": "Price: {0} (USD)" }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/el.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/el.json index f961db055..3d57ae21f 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/el.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/el.json @@ -429,5 +429,14 @@ "TabMusicVideos": "\u039c\u03bf\u03c5\u03c3\u03b9\u03ba\u03ac \u03b2\u03af\u03bd\u03c4\u03b5\u03bf", "BirthPlaceValue": "Birth place: {0}", "DeathDateValue": "Died: {0}", - "BirthDateValue": "Born: {0}" + "BirthDateValue": "Born: {0}", + "HeaderLatestReviews": "Latest Reviews", + "HeaderPluginInstallation": "Plugin Installation", + "MessageAlreadyInstalled": "This version is already installed.", + "ValueReviewCount": "{0} Reviews", + "MessageYouHaveVersionInstalled": "You currently have version {0} installed.", + "MessageTrialExpired": "The trial period for this feature has expired", + "MessageTrialWillExpireIn": "The trial period for this feature will expire in {0} day(s)", + "MessageInstallPluginFromApp": "This plugin must be installed from with in the app you intend to use it in.", + "ValuePriceUSD": "Price: {0} (USD)" }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/en_GB.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/en_GB.json index e8525157d..9db725ec7 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/en_GB.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/en_GB.json @@ -429,5 +429,14 @@ "TabMusicVideos": "Music Videos", "BirthPlaceValue": "Birth place: {0}", "DeathDateValue": "Died: {0}", - "BirthDateValue": "Born: {0}" + "BirthDateValue": "Born: {0}", + "HeaderLatestReviews": "Latest Reviews", + "HeaderPluginInstallation": "Plugin Installation", + "MessageAlreadyInstalled": "This version is already installed.", + "ValueReviewCount": "{0} Reviews", + "MessageYouHaveVersionInstalled": "You currently have version {0} installed.", + "MessageTrialExpired": "The trial period for this feature has expired", + "MessageTrialWillExpireIn": "The trial period for this feature will expire in {0} day(s)", + "MessageInstallPluginFromApp": "This plugin must be installed from with in the app you intend to use it in.", + "ValuePriceUSD": "Price: {0} (USD)" }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json index dd6e416e1..b740506ae 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json @@ -429,5 +429,14 @@ "TabMusicVideos": "Music Videos", "BirthPlaceValue": "Birth place: {0}", "DeathDateValue": "Died: {0}", - "BirthDateValue": "Born: {0}" + "BirthDateValue": "Born: {0}", + "HeaderLatestReviews": "Latest Reviews", + "HeaderPluginInstallation": "Plugin Installation", + "MessageAlreadyInstalled": "This version is already installed.", + "ValueReviewCount": "{0} Reviews", + "MessageYouHaveVersionInstalled": "You currently have version {0} installed.", + "MessageTrialExpired": "The trial period for this feature has expired", + "MessageTrialWillExpireIn": "The trial period for this feature will expire in {0} day(s)", + "MessageInstallPluginFromApp": "This plugin must be installed from with in the app you intend to use it in.", + "ValuePriceUSD": "Price: {0} (USD)" }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/es.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/es.json index c05f42914..3d736ba36 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/es.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/es.json @@ -429,5 +429,14 @@ "TabMusicVideos": "Videos Musicales", "BirthPlaceValue": "Birth place: {0}", "DeathDateValue": "Died: {0}", - "BirthDateValue": "Born: {0}" + "BirthDateValue": "Born: {0}", + "HeaderLatestReviews": "Latest Reviews", + "HeaderPluginInstallation": "Plugin Installation", + "MessageAlreadyInstalled": "This version is already installed.", + "ValueReviewCount": "{0} Reviews", + "MessageYouHaveVersionInstalled": "You currently have version {0} installed.", + "MessageTrialExpired": "The trial period for this feature has expired", + "MessageTrialWillExpireIn": "The trial period for this feature will expire in {0} day(s)", + "MessageInstallPluginFromApp": "This plugin must be installed from with in the app you intend to use it in.", + "ValuePriceUSD": "Price: {0} (USD)" }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json index 9db75b4bc..27930a13a 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json @@ -429,5 +429,14 @@ "TabMusicVideos": "Videos Musicales", "BirthPlaceValue": "Lugar de nacimiento: {0}", "DeathDateValue": "Fallcimiento: {0}", - "BirthDateValue": "Nacimiento: {0}" + "BirthDateValue": "Nacimiento: {0}", + "HeaderLatestReviews": "Latest Reviews", + "HeaderPluginInstallation": "Plugin Installation", + "MessageAlreadyInstalled": "This version is already installed.", + "ValueReviewCount": "{0} Reviews", + "MessageYouHaveVersionInstalled": "You currently have version {0} installed.", + "MessageTrialExpired": "The trial period for this feature has expired", + "MessageTrialWillExpireIn": "The trial period for this feature will expire in {0} day(s)", + "MessageInstallPluginFromApp": "This plugin must be installed from with in the app you intend to use it in.", + "ValuePriceUSD": "Price: {0} (USD)" }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json index 7b1feb6b3..ca08980ab 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json @@ -429,5 +429,14 @@ "TabMusicVideos": "Videos musicales", "BirthPlaceValue": "Birth place: {0}", "DeathDateValue": "Died: {0}", - "BirthDateValue": "Born: {0}" + "BirthDateValue": "Born: {0}", + "HeaderLatestReviews": "Latest Reviews", + "HeaderPluginInstallation": "Plugin Installation", + "MessageAlreadyInstalled": "This version is already installed.", + "ValueReviewCount": "{0} Reviews", + "MessageYouHaveVersionInstalled": "You currently have version {0} installed.", + "MessageTrialExpired": "The trial period for this feature has expired", + "MessageTrialWillExpireIn": "The trial period for this feature will expire in {0} day(s)", + "MessageInstallPluginFromApp": "This plugin must be installed from with in the app you intend to use it in.", + "ValuePriceUSD": "Price: {0} (USD)" }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/he.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/he.json index e81dc5775..aaff70b69 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/he.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/he.json @@ -429,5 +429,14 @@ "TabMusicVideos": "\u05e7\u05dc\u05d9\u05e4\u05d9\u05dd", "BirthPlaceValue": "Birth place: {0}", "DeathDateValue": "Died: {0}", - "BirthDateValue": "Born: {0}" + "BirthDateValue": "Born: {0}", + "HeaderLatestReviews": "Latest Reviews", + "HeaderPluginInstallation": "Plugin Installation", + "MessageAlreadyInstalled": "This version is already installed.", + "ValueReviewCount": "{0} Reviews", + "MessageYouHaveVersionInstalled": "You currently have version {0} installed.", + "MessageTrialExpired": "The trial period for this feature has expired", + "MessageTrialWillExpireIn": "The trial period for this feature will expire in {0} day(s)", + "MessageInstallPluginFromApp": "This plugin must be installed from with in the app you intend to use it in.", + "ValuePriceUSD": "Price: {0} (USD)" }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/it.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/it.json index 50cc701cf..5ded6e80b 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/it.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/it.json @@ -429,5 +429,14 @@ "TabMusicVideos": "Video Musicali", "BirthPlaceValue": "Birth place: {0}", "DeathDateValue": "Died: {0}", - "BirthDateValue": "Born: {0}" + "BirthDateValue": "Born: {0}", + "HeaderLatestReviews": "Latest Reviews", + "HeaderPluginInstallation": "Plugin Installation", + "MessageAlreadyInstalled": "This version is already installed.", + "ValueReviewCount": "{0} Reviews", + "MessageYouHaveVersionInstalled": "You currently have version {0} installed.", + "MessageTrialExpired": "The trial period for this feature has expired", + "MessageTrialWillExpireIn": "The trial period for this feature will expire in {0} day(s)", + "MessageInstallPluginFromApp": "This plugin must be installed from with in the app you intend to use it in.", + "ValuePriceUSD": "Price: {0} (USD)" }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json index c8ce64b83..bdc184a37 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json @@ -383,58 +383,67 @@ "LabelImageFetchersHelp": "Enable and rank your preferred image fetchers in order of priority.", "ButtonQueueAllFromHere": "Queue all from here", "ButtonPlayAllFromHere": "Play all from here", - "LabelDynamicExternalId": "{0} Id:", - "HeaderIdentify": "Identify Item", - "PersonTypePerson": "Person", - "LabelTitleDisplayOrder": "Title display order:", - "OptionSortName": "Sort name", - "OptionReleaseDate": "Release date", - "LabelSeasonNumber": "Season number:", - "LabelDiscNumber": "Disc number", - "LabelParentNumber": "Parent number", - "LabelEpisodeNumber": "Episode number:", - "LabelTrackNumber": "Track number:", - "LabelNumber": "Number:", - "LabelReleaseDate": "Release date:", - "LabelEndDate": "End date:", - "LabelYear": "Year:", - "LabelDateOfBirth": "Date of birth:", - "LabelBirthYear": "Birth year:", - "LabelDeathDate": "Death date:", - "HeaderRemoveMediaLocation": "Remove Media Location", - "MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?", - "HeaderRenameMediaFolder": "Rename Media Folder", - "LabelNewName": "New name:", - "HeaderAddMediaFolder": "Add Media Folder", - "HeaderAddMediaFolderHelp": "Name (Movies, Music, TV, etc):", - "HeaderRemoveMediaFolder": "Remove Media Folder", - "MessageTheFollowingLocationWillBeRemovedFromLibrary": "The following media locations will be removed from your library:", - "MessageAreYouSureYouWishToRemoveMediaFolder": "Are you sure you wish to remove this media folder?", - "ButtonRename": "Rename", - "ButtonChangeType": "Change type", - "ButtonRemove": "Remove", - "HeaderMediaLocations": "Media Locations", - "LabelFolderTypeValue": "Folder type: {0}", - "LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.", - "FolderTypeMixed": "Mixed movies & tv", - "FolderTypeMovies": "Movies", - "FolderTypeMusic": "Music", - "FolderTypeAdultVideos": "Adult videos", - "FolderTypePhotos": "Photos", - "FolderTypeMusicVideos": "Music videos", - "FolderTypeHomeVideos": "Home videos", - "FolderTypeGames": "Games", - "FolderTypeBooks": "Books", - "FolderTypeTvShows": "TV shows", - "TabMovies": "Movies", - "TabSeries": "Series", - "TabEpisodes": "Episodes", - "TabTrailers": "Trailers", - "TabGames": "Games", - "TabAlbums": "Albums", - "TabSongs": "Songs", - "TabMusicVideos": "Music Videos", - "BirthPlaceValue": "Birth place: {0}", - "DeathDateValue": "Died: {0}", - "BirthDateValue": "Born: {0}" + "LabelDynamicExternalId": "{0} Id:", + "HeaderIdentify": "Identify Item", + "PersonTypePerson": "Person", + "LabelTitleDisplayOrder": "Title display order:", + "OptionSortName": "Sort name", + "OptionReleaseDate": "Release date", + "LabelSeasonNumber": "Season number:", + "LabelDiscNumber": "Disc number", + "LabelParentNumber": "Parent number", + "LabelEpisodeNumber": "Episode number:", + "LabelTrackNumber": "Track number:", + "LabelNumber": "Number:", + "LabelReleaseDate": "Release date:", + "LabelEndDate": "End date:", + "LabelYear": "Year:", + "LabelDateOfBirth": "Date of birth:", + "LabelBirthYear": "Birth year:", + "LabelDeathDate": "Death date:", + "HeaderRemoveMediaLocation": "Remove Media Location", + "MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?", + "HeaderRenameMediaFolder": "Rename Media Folder", + "LabelNewName": "New name:", + "HeaderAddMediaFolder": "Add Media Folder", + "HeaderAddMediaFolderHelp": "Name (Movies, Music, TV, etc):", + "HeaderRemoveMediaFolder": "Remove Media Folder", + "MessageTheFollowingLocationWillBeRemovedFromLibrary": "The following media locations will be removed from your library:", + "MessageAreYouSureYouWishToRemoveMediaFolder": "Are you sure you wish to remove this media folder?", + "ButtonRename": "Rename", + "ButtonChangeType": "Change type", + "ButtonRemove": "Remove", + "HeaderMediaLocations": "Media Locations", + "LabelFolderTypeValue": "Folder type: {0}", + "LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.", + "FolderTypeMixed": "Mixed movies & tv", + "FolderTypeMovies": "Movies", + "FolderTypeMusic": "Music", + "FolderTypeAdultVideos": "Adult videos", + "FolderTypePhotos": "Photos", + "FolderTypeMusicVideos": "Music videos", + "FolderTypeHomeVideos": "Home videos", + "FolderTypeGames": "Games", + "FolderTypeBooks": "Books", + "FolderTypeTvShows": "TV shows", + "TabMovies": "Movies", + "TabSeries": "Series", + "TabEpisodes": "Episodes", + "TabTrailers": "Trailers", + "TabGames": "Games", + "TabAlbums": "Albums", + "TabSongs": "Songs", + "TabMusicVideos": "Music Videos", + "BirthPlaceValue": "Birth place: {0}", + "DeathDateValue": "Died: {0}", + "BirthDateValue": "Born: {0}", + "HeaderLatestReviews": "Latest Reviews", + "HeaderPluginInstallation": "Plugin Installation", + "MessageAlreadyInstalled": "This version is already installed.", + "ValueReviewCount": "{0} Reviews", + "MessageYouHaveVersionInstalled": "You currently have version {0} installed.", + "MessageTrialExpired": "The trial period for this feature has expired", + "MessageTrialWillExpireIn": "The trial period for this feature will expire in {0} day(s)", + "MessageInstallPluginFromApp": "This plugin must be installed from with in the app you intend to use it in.", + "ValuePriceUSD": "Price: {0} (USD)" } diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json index 0e07e2f02..8572c0b6b 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json @@ -132,14 +132,14 @@ "HeaderRatingsDownloads": "\u0411\u0430\u0493\u0430\u043b\u0430\u0443 \/ \u0416\u04af\u043a\u0442\u0435\u0443\u043b\u0435\u0440", "HeaderConfirmProfileDeletion": "\u041f\u0440\u043e\u0444\u0430\u0439\u043b \u0436\u043e\u044e\u0434\u044b \u0440\u0430\u0441\u0442\u0430\u0443", "MessageConfirmProfileDeletion": "\u0428\u044b\u043d\u044b\u043c\u0435\u043d \u043e\u0441\u044b \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u0434\u044b \u0436\u043e\u044e \u049b\u0430\u0436\u0435\u0442 \u043f\u0435?", - "HeaderSelectServerCachePath": "Server Cache \u049b\u0430\u043b\u0442\u0430\u0441\u044b \u0436\u043e\u043b\u044b\u043d \u0442\u0430\u04a3\u0434\u0430\u0443", - "HeaderSelectTranscodingPath": "Transcoding Temporary \u049b\u0430\u043b\u0442\u0430\u0441\u044b \u0436\u043e\u043b\u044b\u043d \u0442\u0430\u04a3\u0434\u0430\u0443", - "HeaderSelectImagesByNamePath": "Images By Name \u049b\u0430\u043b\u0442\u0430\u0441\u044b \u0436\u043e\u043b\u044b\u043d \u0442\u0430\u04a3\u0434\u0430\u0443", - "HeaderSelectMetadataPath": "Metadata \u049b\u0430\u043b\u0442\u0430\u0441\u044b \u0436\u043e\u043b\u044b\u043d \u0442\u0430\u04a3\u0434\u0430\u0443", - "HeaderSelectServerCachePathHelp": "Server cache \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443 \u04af\u0448\u0456\u043d \u0436\u043e\u043b\u0434\u044b \u0448\u043e\u043b\u044b\u04a3\u044b\u0437 \u043d\u0435\u043c\u0435\u0441\u0435 \u0435\u043d\u0433\u0456\u0437\u0456\u04a3\u0456\u0437. \u041e\u0441\u044b \u049b\u0430\u043b\u0442\u0430 \u0436\u0430\u0437\u0443 \u04af\u0448\u0456\u043d \u049b\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456 \u0431\u043e\u043b\u0443\u044b \u049b\u0430\u0436\u0435\u0442.", - "HeaderSelectTranscodingPathHelp": "Transcoding temporary \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443 \u04af\u0448\u0456\u043d \u0436\u043e\u043b\u0434\u044b \u0448\u043e\u043b\u044b\u04a3\u044b\u0437 \u043d\u0435\u043c\u0435\u0441\u0435 \u0435\u043d\u0433\u0456\u0437\u0456\u04a3\u0456\u0437. \u041e\u0441\u044b \u049b\u0430\u043b\u0442\u0430 \u0436\u0430\u0437\u0443 \u04af\u0448\u0456\u043d \u049b\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456 \u0431\u043e\u043b\u0443\u044b \u049b\u0430\u0436\u0435\u0442.", - "HeaderSelectImagesByNamePathHelp": "Items by name \u049b\u0430\u043b\u0442\u0430\u0441\u044b \u04af\u0448\u0456\u043d \u0436\u043e\u043b\u0434\u044b \u0448\u043e\u043b\u044b\u04a3\u044b\u0437 \u043d\u0435\u043c\u0435\u0441\u0435 \u0435\u043d\u0433\u0456\u0437\u0456\u04a3\u0456\u0437. \u041e\u0441\u044b \u049b\u0430\u043b\u0442\u0430 \u0436\u0430\u0437\u0443 \u04af\u0448\u0456\u043d \u049b\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456 \u0431\u043e\u043b\u0443\u044b \u049b\u0430\u0436\u0435\u0442.", - "HeaderSelectMetadataPathHelp": "Metadata \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b\u043d \u0441\u0430\u049b\u0442\u0430\u0443 \u04af\u0448\u0456\u043d \u0436\u043e\u043b\u0434\u044b \u0448\u043e\u043b\u044b\u04a3\u044b\u0437 \u043d\u0435\u043c\u0435\u0441\u0435 \u0435\u043d\u0433\u0456\u0437\u0456\u04a3\u0456\u0437. \u041e\u0441\u044b \u049b\u0430\u043b\u0442\u0430 \u0436\u0430\u0437\u0443 \u04af\u0448\u0456\u043d \u049b\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456 \u0431\u043e\u043b\u0443\u044b \u049b\u0430\u0436\u0435\u0442.", + "HeaderSelectServerCachePath": "\u0421\u0435\u0440\u0432\u0435\u0440 \u043a\u0435\u0448\u0456\u043d\u0456\u04a3 \u0436\u043e\u043b\u044b\u043d \u0442\u0430\u04a3\u0434\u0430\u0443", + "HeaderSelectTranscodingPath": "\u049a\u0430\u0439\u0442\u0430 \u043a\u043e\u0434\u0442\u0430\u0443\u0434\u044b\u04a3 \u0443\u0430\u049b\u044b\u0442\u0448\u0430 \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b\u0435\u044b\u04a3 \u0436\u043e\u043b\u044b\u043d \u0442\u0430\u04a3\u0434\u0430\u0443", + "HeaderSelectImagesByNamePath": "\u0410\u0442\u044b \u0431\u043e\u0439\u044b\u043d\u0448\u0430 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440 \u0436\u043e\u043b\u044b\u043d \u0442\u0430\u04a3\u0434\u0430\u0443", + "HeaderSelectMetadataPath": "\u041c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440 \u0436\u043e\u043b\u044b\u043d \u0442\u0430\u04a3\u0434\u0430\u0443", + "HeaderSelectServerCachePathHelp": "\u0421\u0435\u0440\u0432\u0435\u0440\u0434\u0456\u04a3 \u043a\u0435\u0448 \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443 \u04af\u0448\u0456\u043d \u0436\u043e\u043b\u0434\u044b \u0448\u043e\u043b\u044b\u04a3\u044b\u0437 \u043d\u0435\u043c\u0435\u0441\u0435 \u0435\u043d\u0433\u0456\u0437\u0456\u04a3\u0456\u0437. \u041e\u0441\u044b \u049b\u0430\u043b\u0442\u0430 \u0436\u0430\u0437\u0443 \u04af\u0448\u0456\u043d \u049b\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456 \u0431\u043e\u043b\u0443\u044b \u049b\u0430\u0436\u0435\u0442.", + "HeaderSelectTranscodingPathHelp": "\u049a\u0430\u0439\u0442\u0430 \u043a\u043e\u0434\u0442\u0430\u0443\u0434\u044b\u04a3 \u0443\u0430\u049b\u044b\u0442\u0448\u0430 \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443 \u04af\u0448\u0456\u043d \u0436\u043e\u043b\u0434\u044b \u0448\u043e\u043b\u044b\u04a3\u044b\u0437 \u043d\u0435\u043c\u0435\u0441\u0435 \u0435\u043d\u0433\u0456\u0437\u0456\u04a3\u0456\u0437. \u041e\u0441\u044b \u049b\u0430\u043b\u0442\u0430 \u0436\u0430\u0437\u0443 \u04af\u0448\u0456\u043d \u049b\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456 \u0431\u043e\u043b\u0443\u044b \u049b\u0430\u0436\u0435\u0442.", + "HeaderSelectImagesByNamePathHelp": "\u0410\u0442\u044b \u0431\u043e\u0439\u044b\u043d\u0448\u0430 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440 \u04af\u0448\u0456\u043d \u0436\u043e\u043b\u0434\u044b \u0448\u043e\u043b\u044b\u04a3\u044b\u0437 \u043d\u0435\u043c\u0435\u0441\u0435 \u0435\u043d\u0433\u0456\u0437\u0456\u04a3\u0456\u0437. \u041e\u0441\u044b \u049b\u0430\u043b\u0442\u0430 \u0436\u0430\u0437\u0443 \u04af\u0448\u0456\u043d \u049b\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456 \u0431\u043e\u043b\u0443\u044b \u049b\u0430\u0436\u0435\u0442.", + "HeaderSelectMetadataPathHelp": "\u041c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440 \u0441\u0430\u049b\u0442\u0430\u0443 \u04af\u0448\u0456\u043d \u0436\u043e\u043b\u0434\u044b \u0448\u043e\u043b\u044b\u04a3\u044b\u0437 \u043d\u0435\u043c\u0435\u0441\u0435 \u0435\u043d\u0433\u0456\u0437\u0456\u04a3\u0456\u0437. \u041e\u0441\u044b \u049b\u0430\u043b\u0442\u0430 \u0436\u0430\u0437\u0443 \u04af\u0448\u0456\u043d \u049b\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456 \u0431\u043e\u043b\u0443\u044b \u049b\u0430\u0436\u0435\u0442.", "HeaderSelectChannelDownloadPath": "\u0410\u0440\u043d\u0430 \u0436\u04af\u043a\u0442\u0435\u0443 \u0436\u043e\u043b\u044b\u043d \u0442\u0430\u04a3\u0434\u0430\u04a3\u044b\u0437", "HeaderSelectChannelDownloadPathHelp": "\u0410\u0440\u043d\u0430 \u043a\u0435\u0448\u0456 \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b\u043d \u0441\u0430\u049b\u0442\u0430\u043f \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443 \u04af\u0448\u0456\u043d \u0436\u043e\u043b\u0434\u044b \u0448\u043e\u043b\u044b\u04a3\u044b\u0437 \u043d\u0435\u043c\u0435\u0441\u0435 \u0435\u043d\u0433\u0456\u0437\u0456\u04a3\u0456\u0437. \u041e\u0441\u044b \u049b\u0430\u043b\u0442\u0430 \u0436\u0430\u0437\u0443 \u04af\u0448\u0456\u043d \u049b\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456 \u0431\u043e\u043b\u0443\u044b \u049b\u0430\u0436\u0435\u0442.", "OptionNewCollection": "\u0416\u0430\u04a3\u0430...", @@ -275,7 +275,7 @@ "OptionGenres": "\u0416\u0430\u043d\u0440\u043b\u0430\u0440", "OptionParentalRating": "\u0416\u0430\u0441\u0442\u0430\u0441 \u0441\u0430\u043d\u0430\u0442", "OptionPeople": "\u0410\u0434\u0430\u043c\u0434\u0430\u0440", - "OptionRuntime": "\u041e\u0440\u044b\u043d\u0434\u0430\u0443 \u0443\u0430\u049b\u044b\u0442\u044b", + "OptionRuntime": "\u04b0\u0437\u0430\u049b\u0442\u044b\u0493\u044b", "OptionProductionLocations": "\u04e8\u043d\u0434\u0456\u0440\u0443 \u043e\u0440\u044b\u043d\u0434\u0430\u0440\u044b", "OptionBirthLocation": "\u0422\u0443\u0493\u0430\u043d \u043e\u0440\u043d\u044b", "LabelAllChannels": "\u0411\u0430\u0440\u043b\u044b\u049b \u0430\u0440\u043d\u0430\u043b\u0430\u0440", @@ -429,5 +429,14 @@ "TabMusicVideos": "\u0411\u0435\u0439\u043d\u0435\u043a\u043b\u0438\u043f\u0442\u0435\u0440", "BirthPlaceValue": "\u0422\u0443\u0493\u0430\u043d \u043e\u0440\u043d\u044b: {0}", "DeathDateValue": "\u04e8\u043b\u0433\u0435\u043d\u0456: {0}", - "BirthDateValue": "\u0422\u0443\u0493\u0430\u043d\u044b: {0}" + "BirthDateValue": "\u0422\u0443\u0493\u0430\u043d\u044b: {0}", + "HeaderLatestReviews": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456 \u043f\u0456\u043a\u0456\u0440\u043b\u0435\u0440", + "HeaderPluginInstallation": "\u041f\u043b\u0430\u0433\u0438\u043d \u043e\u0440\u043d\u0430\u0442\u044b\u043c\u044b", + "MessageAlreadyInstalled": "\u041e\u0441\u044b \u043d\u04b1\u0441\u049b\u0430 \u0431\u04b1\u0440\u044b\u043d\u043d\u0430\u043d \u043e\u0440\u043d\u0430\u0442\u044b\u043b\u0493\u0430\u043d.", + "ValueReviewCount": "{0} \u043f\u0456\u043a\u0456\u0440", + "MessageYouHaveVersionInstalled": "\u049a\u0430\u0437\u0456\u0440 {0} \u043e\u0440\u043d\u0430\u0442\u044b\u043b\u0493\u0430\u043d", + "MessageTrialExpired": "\u041e\u0441\u044b \u043c\u04af\u043c\u043a\u0456\u043d\u0434\u0456\u043a \u04af\u0448\u0456\u043d \u0442\u0430\u043d\u044b\u0441\u0442\u044b\u0440\u0443 \u043a\u0435\u0437\u0435\u04a3\u0456\u043d\u0456\u04a3 \u043c\u0435\u0440\u0437\u0456\u043c\u0456 \u04e9\u0442\u0442\u0456", + "MessageTrialWillExpireIn": "\u041e\u0441\u044b \u043c\u04af\u043c\u043a\u0456\u043d\u0434\u0456\u043a \u04af\u0448\u0456\u043d \u0442\u0430\u043d\u044b\u0441\u0442\u044b\u0440\u0443 \u043a\u0435\u0437\u0435\u04a3\u0456\u043d\u0456\u04a3 \u043c\u0435\u0440\u0437\u0456\u043c\u0456 {0} \u043a\u04af\u043d\u0434\u0435 \u04e9\u0442\u0435\u0434\u0456", + "MessageInstallPluginFromApp": "This plugin must be installed from with in the app you intend to use it in.", + "ValuePriceUSD": "\u0411\u0430\u0493\u0430\u0441\u044b: {0} USD" }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/ms.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/ms.json index b6d5e50e5..6aff55b44 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/ms.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/ms.json @@ -429,5 +429,14 @@ "TabMusicVideos": "Music Videos", "BirthPlaceValue": "Birth place: {0}", "DeathDateValue": "Died: {0}", - "BirthDateValue": "Born: {0}" + "BirthDateValue": "Born: {0}", + "HeaderLatestReviews": "Latest Reviews", + "HeaderPluginInstallation": "Plugin Installation", + "MessageAlreadyInstalled": "This version is already installed.", + "ValueReviewCount": "{0} Reviews", + "MessageYouHaveVersionInstalled": "You currently have version {0} installed.", + "MessageTrialExpired": "The trial period for this feature has expired", + "MessageTrialWillExpireIn": "The trial period for this feature will expire in {0} day(s)", + "MessageInstallPluginFromApp": "This plugin must be installed from with in the app you intend to use it in.", + "ValuePriceUSD": "Price: {0} (USD)" }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/nb.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/nb.json index 024009e03..13a031937 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/nb.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/nb.json @@ -429,5 +429,14 @@ "TabMusicVideos": "Musikk-videoer", "BirthPlaceValue": "Birth place: {0}", "DeathDateValue": "Died: {0}", - "BirthDateValue": "Born: {0}" + "BirthDateValue": "Born: {0}", + "HeaderLatestReviews": "Latest Reviews", + "HeaderPluginInstallation": "Plugin Installation", + "MessageAlreadyInstalled": "This version is already installed.", + "ValueReviewCount": "{0} Reviews", + "MessageYouHaveVersionInstalled": "You currently have version {0} installed.", + "MessageTrialExpired": "The trial period for this feature has expired", + "MessageTrialWillExpireIn": "The trial period for this feature will expire in {0} day(s)", + "MessageInstallPluginFromApp": "This plugin must be installed from with in the app you intend to use it in.", + "ValuePriceUSD": "Price: {0} (USD)" }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json index 6b722885a..912aabe85 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json @@ -429,5 +429,14 @@ "TabMusicVideos": "Music Videos", "BirthPlaceValue": "Geboorte plaats: {0})", "DeathDateValue": "Overleden: {0}", - "BirthDateValue": "Geboren: {0}" + "BirthDateValue": "Geboren: {0}", + "HeaderLatestReviews": "Latest Reviews", + "HeaderPluginInstallation": "Plugin Installation", + "MessageAlreadyInstalled": "This version is already installed.", + "ValueReviewCount": "{0} Reviews", + "MessageYouHaveVersionInstalled": "You currently have version {0} installed.", + "MessageTrialExpired": "The trial period for this feature has expired", + "MessageTrialWillExpireIn": "The trial period for this feature will expire in {0} day(s)", + "MessageInstallPluginFromApp": "This plugin must be installed from with in the app you intend to use it in.", + "ValuePriceUSD": "Price: {0} (USD)" }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json index b9238b554..be23009ba 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json @@ -429,5 +429,14 @@ "TabMusicVideos": "Teledyski", "BirthPlaceValue": "Birth place: {0}", "DeathDateValue": "Died: {0}", - "BirthDateValue": "Born: {0}" + "BirthDateValue": "Born: {0}", + "HeaderLatestReviews": "Latest Reviews", + "HeaderPluginInstallation": "Plugin Installation", + "MessageAlreadyInstalled": "This version is already installed.", + "ValueReviewCount": "{0} Reviews", + "MessageYouHaveVersionInstalled": "You currently have version {0} installed.", + "MessageTrialExpired": "The trial period for this feature has expired", + "MessageTrialWillExpireIn": "The trial period for this feature will expire in {0} day(s)", + "MessageInstallPluginFromApp": "This plugin must be installed from with in the app you intend to use it in.", + "ValuePriceUSD": "Price: {0} (USD)" }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json index db6012513..e4b0dee4c 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json @@ -58,14 +58,14 @@ "ButtonMute": "Mudo", "ButtonUnmute": "Remover Mudo", "ButtonStop": "Parar", - "ButtonNextTrack": "Faixa seguinte", + "ButtonNextTrack": "Pr\u00f3xima Faixa", "ButtonPause": "Pausar", "ButtonPlay": "Reproduzir", "ButtonEdit": "Editar", "ButtonQueue": "Adicionar \u00e0 fila", "ButtonPlayTrailer": "Reproduzir trailer", "ButtonPlaylist": "Lista de reprodu\u00e7\u00e3o", - "ButtonPreviousTrack": "Faixa anterior", + "ButtonPreviousTrack": "Faixa Anterior", "LabelEnabled": "Ativada", "LabelDisabled": "Desativada", "ButtonMoreInformation": "Mais informa\u00e7\u00f5es", @@ -429,5 +429,14 @@ "TabMusicVideos": "V\u00eddeos Musicais", "BirthPlaceValue": "Local de nascimento: {0}", "DeathDateValue": "Morte: {0}", - "BirthDateValue": "Nascimento: {0}" + "BirthDateValue": "Nascimento: {0}", + "HeaderLatestReviews": "Latest Reviews", + "HeaderPluginInstallation": "Plugin Installation", + "MessageAlreadyInstalled": "This version is already installed.", + "ValueReviewCount": "{0} Reviews", + "MessageYouHaveVersionInstalled": "You currently have version {0} installed.", + "MessageTrialExpired": "The trial period for this feature has expired", + "MessageTrialWillExpireIn": "The trial period for this feature will expire in {0} day(s)", + "MessageInstallPluginFromApp": "This plugin must be installed from with in the app you intend to use it in.", + "ValuePriceUSD": "Price: {0} (USD)" }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json index 6f3146bfd..00ed7f622 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json @@ -429,5 +429,14 @@ "TabMusicVideos": "Videos Musicais", "BirthPlaceValue": "Birth place: {0}", "DeathDateValue": "Died: {0}", - "BirthDateValue": "Born: {0}" + "BirthDateValue": "Born: {0}", + "HeaderLatestReviews": "Latest Reviews", + "HeaderPluginInstallation": "Plugin Installation", + "MessageAlreadyInstalled": "This version is already installed.", + "ValueReviewCount": "{0} Reviews", + "MessageYouHaveVersionInstalled": "You currently have version {0} installed.", + "MessageTrialExpired": "The trial period for this feature has expired", + "MessageTrialWillExpireIn": "The trial period for this feature will expire in {0} day(s)", + "MessageInstallPluginFromApp": "This plugin must be installed from with in the app you intend to use it in.", + "ValuePriceUSD": "Price: {0} (USD)" }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json index b00872075..76e572669 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json @@ -137,7 +137,7 @@ "HeaderSelectImagesByNamePath": "\u0412\u044b\u0431\u043e\u0440 \u043f\u0443\u0442\u0438 \u0434\u043b\u044f \u043f\u0430\u043f\u043a\u0438 Images By Name", "HeaderSelectMetadataPath": "\u0412\u044b\u0431\u043e\u0440 \u043f\u0443\u0442\u0438 \u0434\u043b\u044f \u043f\u0430\u043f\u043a\u0438 Metadata", "HeaderSelectServerCachePathHelp": "\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u043a \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0443 \u0438\u043b\u0438 \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u0443\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u043e\u0432 server cache. \u041f\u0430\u043f\u043a\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438.", - "HeaderSelectTranscodingPathHelp": "\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u043a \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0443 \u0438\u043b\u0438 \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u0443\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u043e\u0432 transcoding temporary. \u041f\u0430\u043f\u043a\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438.", + "HeaderSelectTranscodingPathHelp": "\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u043a \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0443 \u0438\u043b\u0438 \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u0443\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0438. \u041f\u0430\u043f\u043a\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438.", "HeaderSelectImagesByNamePathHelp": "\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u043a \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0443 \u0438\u043b\u0438 \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u0443\u0442\u044c \u043a \u043f\u0430\u043f\u043a\u0435 items by name. \u041f\u0430\u043f\u043a\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438.", "HeaderSelectMetadataPathHelp": "\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u043a \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0443 \u0438\u043b\u0438 \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0432\u043d\u0443\u0442\u0440\u0438 \u0444\u0430\u0439\u043b\u043e\u0432 metadata. \u041f\u0430\u043f\u043a\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438.", "HeaderSelectChannelDownloadPath": "\u0412\u044b\u0431\u043e\u0440 \u043f\u0443\u0442\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043a\u0430\u043d\u0430\u043b\u043e\u0432", @@ -288,7 +288,7 @@ "HeaderAlert": "\u041e\u043f\u043e\u0432\u0435\u0449\u0435\u043d\u0438\u0435", "MessagePleaseRestart": "\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0435, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435.", "ButtonRestart": "\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c", - "MessagePleaseRefreshPage": "\u041f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u0435 \u0434\u0430\u043d\u043d\u0443\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430.", + "MessagePleaseRefreshPage": "\u0410\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0439\u0442\u0435 \u0434\u0430\u043d\u043d\u0443\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430.", "ButtonHide": "\u0421\u043a\u0440\u044b\u0442\u044c", "MessageSettingsSaved": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u044b.", "ButtonSignOut": "\u0412\u044b\u0439\u0442\u0438", @@ -429,5 +429,14 @@ "TabMusicVideos": "\u041a\u043b\u0438\u043f\u044b", "BirthPlaceValue": "\u041c\u0435\u0441\u0442\u043e \u0440\u043e\u0436\u0434\u0435\u043d\u0438\u044f: {0}", "DeathDateValue": "\u041a\u043e\u043d\u0447\u0438\u043d\u0430: {0}", - "BirthDateValue": "\u0420\u043e\u0436\u0434\u0435\u043d\u0438\u0435: {0}" + "BirthDateValue": "\u0420\u043e\u0436\u0434\u0435\u043d\u0438\u0435: {0}", + "HeaderLatestReviews": "\u041d\u043e\u0432\u0438\u043d\u043a\u0438 \u043e\u0442\u0437\u044b\u0432\u043e\u0432", + "HeaderPluginInstallation": "\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043f\u043b\u0430\u0433\u0438\u043d\u0430", + "MessageAlreadyInstalled": "\u0414\u0430\u043d\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u0443\u0436\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0430.", + "ValueReviewCount": "\u041e\u0442\u0437\u044b\u0432\u043e\u0432: {0}", + "MessageYouHaveVersionInstalled": "\u0412 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0430 \u0432\u0435\u0440\u0441\u0438\u044f {0}.", + "MessageTrialExpired": "\u041f\u0440\u043e\u0431\u043d\u044b\u0439 \u043f\u0435\u0440\u0438\u043e\u0434 \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438\u0441\u0442\u0451\u043a", + "MessageTrialWillExpireIn": "\u041f\u0440\u043e\u0431\u043d\u044b\u0439 \u043f\u0435\u0440\u0438\u043e\u0434 \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438\u0441\u0442\u0435\u0447\u0451\u0442 \u0447\u0435\u0440\u0435\u0437 {0} \u0434\u043d\u0435\u0439", + "MessageInstallPluginFromApp": "\u0414\u0430\u043d\u043d\u044b\u0439 \u043f\u043b\u0430\u0433\u0438\u043d \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u043d\u043e \u0441 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043e \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f.", + "ValuePriceUSD": "\u0426\u0435\u043d\u0430: {0} USD" }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json index 50d24dae5..f6c2313e5 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json @@ -429,5 +429,14 @@ "TabMusicVideos": "Musikvideor", "BirthPlaceValue": "Birth place: {0}", "DeathDateValue": "Died: {0}", - "BirthDateValue": "Born: {0}" + "BirthDateValue": "Born: {0}", + "HeaderLatestReviews": "Latest Reviews", + "HeaderPluginInstallation": "Plugin Installation", + "MessageAlreadyInstalled": "This version is already installed.", + "ValueReviewCount": "{0} Reviews", + "MessageYouHaveVersionInstalled": "You currently have version {0} installed.", + "MessageTrialExpired": "The trial period for this feature has expired", + "MessageTrialWillExpireIn": "The trial period for this feature will expire in {0} day(s)", + "MessageInstallPluginFromApp": "This plugin must be installed from with in the app you intend to use it in.", + "ValuePriceUSD": "Price: {0} (USD)" }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/tr.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/tr.json index 9232c2fdd..c6c2b4491 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/tr.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/tr.json @@ -429,5 +429,14 @@ "TabMusicVideos": "Klipler", "BirthPlaceValue": "Birth place: {0}", "DeathDateValue": "Died: {0}", - "BirthDateValue": "Born: {0}" + "BirthDateValue": "Born: {0}", + "HeaderLatestReviews": "Latest Reviews", + "HeaderPluginInstallation": "Plugin Installation", + "MessageAlreadyInstalled": "This version is already installed.", + "ValueReviewCount": "{0} Reviews", + "MessageYouHaveVersionInstalled": "You currently have version {0} installed.", + "MessageTrialExpired": "The trial period for this feature has expired", + "MessageTrialWillExpireIn": "The trial period for this feature will expire in {0} day(s)", + "MessageInstallPluginFromApp": "This plugin must be installed from with in the app you intend to use it in.", + "ValuePriceUSD": "Price: {0} (USD)" }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/vi.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/vi.json index b62b24367..b63fb262f 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/vi.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/vi.json @@ -429,5 +429,14 @@ "TabMusicVideos": "C\u00e1c video \u00e2m nh\u1ea1c", "BirthPlaceValue": "Birth place: {0}", "DeathDateValue": "Died: {0}", - "BirthDateValue": "Born: {0}" + "BirthDateValue": "Born: {0}", + "HeaderLatestReviews": "Latest Reviews", + "HeaderPluginInstallation": "Plugin Installation", + "MessageAlreadyInstalled": "This version is already installed.", + "ValueReviewCount": "{0} Reviews", + "MessageYouHaveVersionInstalled": "You currently have version {0} installed.", + "MessageTrialExpired": "The trial period for this feature has expired", + "MessageTrialWillExpireIn": "The trial period for this feature will expire in {0} day(s)", + "MessageInstallPluginFromApp": "This plugin must be installed from with in the app you intend to use it in.", + "ValuePriceUSD": "Price: {0} (USD)" }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json index dc4e7eb84..1b7217efb 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json @@ -429,5 +429,14 @@ "TabMusicVideos": "Music Videos", "BirthPlaceValue": "Birth place: {0}", "DeathDateValue": "Died: {0}", - "BirthDateValue": "Born: {0}" + "BirthDateValue": "Born: {0}", + "HeaderLatestReviews": "Latest Reviews", + "HeaderPluginInstallation": "Plugin Installation", + "MessageAlreadyInstalled": "This version is already installed.", + "ValueReviewCount": "{0} Reviews", + "MessageYouHaveVersionInstalled": "You currently have version {0} installed.", + "MessageTrialExpired": "The trial period for this feature has expired", + "MessageTrialWillExpireIn": "The trial period for this feature will expire in {0} day(s)", + "MessageInstallPluginFromApp": "This plugin must be installed from with in the app you intend to use it in.", + "ValuePriceUSD": "Price: {0} (USD)" }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/ar.json b/MediaBrowser.Server.Implementations/Localization/Server/ar.json index bb05037f9..5d7ebaffb 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/ar.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/ar.json @@ -192,15 +192,25 @@ "TabUpcoming": "\u0627\u0644\u0642\u0627\u062f\u0645", "HeaderPhotoInfo": "Photo Info", "TabShows": "\u0627\u0644\u0645\u0633\u0644\u0633\u0644\u0627\u062a", + "HeaderInstall": "Install", "TabEpisodes": "\u0627\u0644\u062d\u0644\u0642\u0627\u062a", + "LabelSelectVersionToInstall": "Select version to install:", "TabGenres": "\u0627\u0646\u0648\u0627\u0639", + "LinkSupporterMembership": "Learn about the Supporter Membership", "TabPeople": "\u0627\u0644\u0646\u0627\u0633", + "MessageSupporterPluginRequiresMembership": "This plugin will require an active supporter membership after the 14 day free trial.", "TabNetworks": "\u0627\u0644\u0634\u0628\u0643\u0627\u062a", + "MessagePremiumPluginRequiresMembership": "This plugin will require an active supporter membership in order to purchase after the 14 day free trial.", "HeaderUsers": "\u0627\u0644\u0645\u0633\u062a\u062e\u062f\u0645\u064a\u0646", + "HeaderReviews": "Reviews", "HeaderFilters": "\u0641\u0644\u062a\u0631\u0627\u062a:", + "HeaderDeveloperInfo": "Developer Info", "ButtonFilter": "\u0641\u0644\u062a\u0631", + "HeaderRevisionHistory": "Revision History", "OptionFavorite": "\u0627\u0644\u0645\u0641\u0636\u0644\u0627\u062a", + "ButtonViewWebsite": "View website", "OptionLikes": "\u0645\u062d\u0628\u0628", + "LabelRecurringDonationCanBeCancelledHelp": "Recurring donations can be cancelled at any time from within your PayPal account.", "OptionDislikes": "\u0645\u0643\u0631\u0648\u0647", "OptionActors": "\u0627\u0644\u0645\u0645\u062b\u0644\u0648\u0646", "OptionGuestStars": "\u0636\u064a\u0648\u0641", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/ca.json b/MediaBrowser.Server.Implementations/Localization/Server/ca.json index 36d831887..8b72f1dc2 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/ca.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/ca.json @@ -192,15 +192,25 @@ "TabUpcoming": "Upcoming", "HeaderPhotoInfo": "Photo Info", "TabShows": "Shows", + "HeaderInstall": "Install", "TabEpisodes": "Episodes", + "LabelSelectVersionToInstall": "Select version to install:", "TabGenres": "Genres", + "LinkSupporterMembership": "Learn about the Supporter Membership", "TabPeople": "People", + "MessageSupporterPluginRequiresMembership": "This plugin will require an active supporter membership after the 14 day free trial.", "TabNetworks": "Networks", + "MessagePremiumPluginRequiresMembership": "This plugin will require an active supporter membership in order to purchase after the 14 day free trial.", "HeaderUsers": "Users", + "HeaderReviews": "Reviews", "HeaderFilters": "Filters:", + "HeaderDeveloperInfo": "Developer Info", "ButtonFilter": "Filter", + "HeaderRevisionHistory": "Revision History", "OptionFavorite": "Favorites", + "ButtonViewWebsite": "View website", "OptionLikes": "Likes", + "LabelRecurringDonationCanBeCancelledHelp": "Recurring donations can be cancelled at any time from within your PayPal account.", "OptionDislikes": "Dislikes", "OptionActors": "Actors", "OptionGuestStars": "Guest Stars", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/da.json b/MediaBrowser.Server.Implementations/Localization/Server/da.json index 6d3e9bc04..87fc9288f 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/da.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/da.json @@ -192,15 +192,25 @@ "TabUpcoming": "Kommende", "HeaderPhotoInfo": "Photo Info", "TabShows": "Shows", + "HeaderInstall": "Install", "TabEpisodes": "Episoder", + "LabelSelectVersionToInstall": "Select version to install:", "TabGenres": "Genre", + "LinkSupporterMembership": "Learn about the Supporter Membership", "TabPeople": "Personer", + "MessageSupporterPluginRequiresMembership": "This plugin will require an active supporter membership after the 14 day free trial.", "TabNetworks": "Netv\u00e6rk", + "MessagePremiumPluginRequiresMembership": "This plugin will require an active supporter membership in order to purchase after the 14 day free trial.", "HeaderUsers": "Brugere", + "HeaderReviews": "Reviews", "HeaderFilters": "Filtre:", + "HeaderDeveloperInfo": "Developer Info", "ButtonFilter": "Filter", + "HeaderRevisionHistory": "Revision History", "OptionFavorite": "Favoritter", + "ButtonViewWebsite": "View website", "OptionLikes": "Likes", + "LabelRecurringDonationCanBeCancelledHelp": "Recurring donations can be cancelled at any time from within your PayPal account.", "OptionDislikes": "Dislikes", "OptionActors": "Skuespillere", "OptionGuestStars": "G\u00e6ste Stjerner", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/de.json b/MediaBrowser.Server.Implementations/Localization/Server/de.json index 907c466d0..361bd42c8 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/de.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/de.json @@ -158,7 +158,7 @@ "LabelNewPasswordConfirm": "Neues Passwort wiederhohlen:", "OptionMakeOneTimeDonation": "Mache eine einmalige Spende", "HeaderCreatePassword": "Erstelle Passwort", - "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.", + "OptionOneTimeDescription": "Das ist eine zus\u00e4tzliche Spende an das Team, um deine Unterst\u00fctzung zu zeigen. Dies bringt keine zus\u00e4tzlichen Vorteile.", "LabelCurrentPassword": "Aktuelles Passwort:", "OptionLifeTimeSupporterClubMembership": "Lebensl\u00e4ngliche Unterst\u00fctzer Club Mitgliedschaft", "LabelMaxParentalRating": "H\u00f6chste erlaubte elterlich Bewertung:", @@ -184,23 +184,33 @@ "MessageNothingHere": "Nichts hier.", "OptionWriter": "Drehbuchautor", "MessagePleaseEnsureInternetMetadata": "Bitte sicherstellen, dass das Herunterladen von Internet Metadaten aktiviert ist.", - "LabelAirDays": "Air days:", + "LabelAirDays": "Ausstrahlungstage:", "TabSuggested": "Vorgeschlagen", - "LabelAirTime": "Air time:", + "LabelAirTime": "Ausstrahlungszeit:", "TabLatest": "Neueste", - "HeaderMediaInfo": "Media Info", + "HeaderMediaInfo": "Medieninformation", "TabUpcoming": "Bevorstehend", - "HeaderPhotoInfo": "Photo Info", + "HeaderPhotoInfo": "Fotoinformation", "TabShows": "Shows", + "HeaderInstall": "Install", "TabEpisodes": "Episoden", + "LabelSelectVersionToInstall": "Select version to install:", "TabGenres": "Genres", + "LinkSupporterMembership": "Learn about the Supporter Membership", "TabPeople": "Personen", + "MessageSupporterPluginRequiresMembership": "This plugin will require an active supporter membership after the 14 day free trial.", "TabNetworks": "Sendergruppen", + "MessagePremiumPluginRequiresMembership": "This plugin will require an active supporter membership in order to purchase after the 14 day free trial.", "HeaderUsers": "Benutzer", + "HeaderReviews": "Reviews", "HeaderFilters": "Filter:", + "HeaderDeveloperInfo": "Developer Info", "ButtonFilter": "Filter", + "HeaderRevisionHistory": "Revision History", "OptionFavorite": "Favoriten", + "ButtonViewWebsite": "View website", "OptionLikes": "Likes", + "LabelRecurringDonationCanBeCancelledHelp": "Recurring donations can be cancelled at any time from within your PayPal account.", "OptionDislikes": "Dislikes", "OptionActors": "Darsteller", "OptionGuestStars": "Gaststar", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/el.json b/MediaBrowser.Server.Implementations/Localization/Server/el.json index 2923d3a9f..a7ab23633 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/el.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/el.json @@ -192,15 +192,25 @@ "TabUpcoming": "\u0395\u03c0\u03b5\u03c1\u03c7\u03cc\u03bc\u03b5\u03bd\u03b7", "HeaderPhotoInfo": "Photo Info", "TabShows": "\u0395\u03c0\u03b5\u03b9\u03c3\u03cc\u03b4\u03b9\u03b1", + "HeaderInstall": "Install", "TabEpisodes": "\u0395\u03c0\u03b5\u03b9\u03c3\u03cc\u03b4\u03b9\u03b1", + "LabelSelectVersionToInstall": "Select version to install:", "TabGenres": "\u0395\u03af\u03b4\u03b7", + "LinkSupporterMembership": "Learn about the Supporter Membership", "TabPeople": "\u0386\u03bd\u03b8\u03c1\u03c9\u03c0\u03bf\u03b9 ", + "MessageSupporterPluginRequiresMembership": "This plugin will require an active supporter membership after the 14 day free trial.", "TabNetworks": "\u0394\u03af\u03ba\u03c4\u03c5\u03b1", + "MessagePremiumPluginRequiresMembership": "This plugin will require an active supporter membership in order to purchase after the 14 day free trial.", "HeaderUsers": "\u03a7\u03c1\u03ae\u03c3\u03c4\u03b5\u03c2 ", + "HeaderReviews": "Reviews", "HeaderFilters": "\u03a6\u03af\u03bb\u03c4\u03c1\u03b1", + "HeaderDeveloperInfo": "Developer Info", "ButtonFilter": "\u03c6\u03af\u03bb\u03c4\u03c1\u03bf", + "HeaderRevisionHistory": "Revision History", "OptionFavorite": "\u0391\u03b3\u03b1\u03c0\u03b7\u03bc\u03ad\u03bd\u03b1", + "ButtonViewWebsite": "View website", "OptionLikes": "\u03a3\u03c5\u03bc\u03c0\u03b1\u03b8\u03b5\u03af", + "LabelRecurringDonationCanBeCancelledHelp": "Recurring donations can be cancelled at any time from within your PayPal account.", "OptionDislikes": "\u0391\u03bd\u03c4\u03b9\u03c0\u03b1\u03b8\u03b5\u03af", "OptionActors": "\u0397\u03b8\u03bf\u03c0\u03bf\u03b9\u03bf\u03af", "OptionGuestStars": "\u0393\u03ba\u03b5\u03c3\u03c4 \u03c3\u03c4\u03b1\u03c1", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/en_GB.json b/MediaBrowser.Server.Implementations/Localization/Server/en_GB.json index 7d328c042..7209c0e62 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/en_GB.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/en_GB.json @@ -192,15 +192,25 @@ "TabUpcoming": "Upcoming", "HeaderPhotoInfo": "Photo Info", "TabShows": "Shows", + "HeaderInstall": "Install", "TabEpisodes": "Episodes", + "LabelSelectVersionToInstall": "Select version to install:", "TabGenres": "Genres", + "LinkSupporterMembership": "Learn about the Supporter Membership", "TabPeople": "People", + "MessageSupporterPluginRequiresMembership": "This plugin will require an active supporter membership after the 14 day free trial.", "TabNetworks": "Networks", + "MessagePremiumPluginRequiresMembership": "This plugin will require an active supporter membership in order to purchase after the 14 day free trial.", "HeaderUsers": "Users", + "HeaderReviews": "Reviews", "HeaderFilters": "Filters:", + "HeaderDeveloperInfo": "Developer Info", "ButtonFilter": "Filter", + "HeaderRevisionHistory": "Revision History", "OptionFavorite": "Favourites", + "ButtonViewWebsite": "View website", "OptionLikes": "Likes", + "LabelRecurringDonationCanBeCancelledHelp": "Recurring donations can be cancelled at any time from within your PayPal account.", "OptionDislikes": "Dislikes", "OptionActors": "Actors", "OptionGuestStars": "Guest Stars", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/en_US.json b/MediaBrowser.Server.Implementations/Localization/Server/en_US.json index 79f5001b8..29c870d39 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/en_US.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/en_US.json @@ -192,15 +192,25 @@ "TabUpcoming": "Upcoming", "HeaderPhotoInfo": "Photo Info", "TabShows": "Shows", + "HeaderInstall": "Install", "TabEpisodes": "Episodes", + "LabelSelectVersionToInstall": "Select version to install:", "TabGenres": "Genres", + "LinkSupporterMembership": "Learn about the Supporter Membership", "TabPeople": "People", + "MessageSupporterPluginRequiresMembership": "This plugin will require an active supporter membership after the 14 day free trial.", "TabNetworks": "Networks", + "MessagePremiumPluginRequiresMembership": "This plugin will require an active supporter membership in order to purchase after the 14 day free trial.", "HeaderUsers": "Users", + "HeaderReviews": "Reviews", "HeaderFilters": "Filters:", + "HeaderDeveloperInfo": "Developer Info", "ButtonFilter": "Filter", + "HeaderRevisionHistory": "Revision History", "OptionFavorite": "Favorites", + "ButtonViewWebsite": "View website", "OptionLikes": "Likes", + "LabelRecurringDonationCanBeCancelledHelp": "Recurring donations can be cancelled at any time from within your PayPal account.", "OptionDislikes": "Dislikes", "OptionActors": "Actors", "OptionGuestStars": "Guest Stars", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/es.json b/MediaBrowser.Server.Implementations/Localization/Server/es.json index 4b8bb6cc6..a376fbbf1 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/es.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/es.json @@ -192,15 +192,25 @@ "TabUpcoming": "Pr\u00f3ximos", "HeaderPhotoInfo": "Photo Info", "TabShows": "Programas", + "HeaderInstall": "Install", "TabEpisodes": "Episodios", + "LabelSelectVersionToInstall": "Select version to install:", "TabGenres": "G\u00e9neros", + "LinkSupporterMembership": "Learn about the Supporter Membership", "TabPeople": "Gente", + "MessageSupporterPluginRequiresMembership": "This plugin will require an active supporter membership after the 14 day free trial.", "TabNetworks": "redes", + "MessagePremiumPluginRequiresMembership": "This plugin will require an active supporter membership in order to purchase after the 14 day free trial.", "HeaderUsers": "Usuarios", + "HeaderReviews": "Reviews", "HeaderFilters": "Filtros:", + "HeaderDeveloperInfo": "Developer Info", "ButtonFilter": "Filtro", + "HeaderRevisionHistory": "Revision History", "OptionFavorite": "Favoritos", + "ButtonViewWebsite": "View website", "OptionLikes": "Me gusta", + "LabelRecurringDonationCanBeCancelledHelp": "Recurring donations can be cancelled at any time from within your PayPal account.", "OptionDislikes": "No me gusta", "OptionActors": "Actores", "OptionGuestStars": "Estrellas invitadas", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/es_MX.json b/MediaBrowser.Server.Implementations/Localization/Server/es_MX.json index d040bdc23..f6981335d 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/es_MX.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/es_MX.json @@ -156,9 +156,9 @@ "LabelNewPassword": "Nueva contrase\u00f1a:", "HeaderDonationType": "Tipo de Donaci\u00f3n:", "LabelNewPasswordConfirm": "Confirmaci\u00f3n de contrase\u00f1a nueva:", - "OptionMakeOneTimeDonation": "Hacer una donaci\u00f3n \u00fanica", + "OptionMakeOneTimeDonation": "Hacer una donaci\u00f3n independiente", "HeaderCreatePassword": "Crear Contrase\u00f1a", - "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.", + "OptionOneTimeDescription": "Esta es una donaci\u00f3n adicional para mostrar tu apoyo al equipo. No tiene ning\u00fan beneficio adicional.", "LabelCurrentPassword": "Contrase\u00f1a actual:", "OptionLifeTimeSupporterClubMembership": "Membres\u00eda vitalicia del club de aficionados", "LabelMaxParentalRating": "M\u00e1xima clasificaci\u00f3n parental permitida:", @@ -184,23 +184,33 @@ "MessageNothingHere": "Nada aqu\u00ed.", "OptionWriter": "Escritor", "MessagePleaseEnsureInternetMetadata": "Por favor aseg\u00farese que la descarga de metadatos de internet esta habilitada.", - "LabelAirDays": "Air days:", + "LabelAirDays": "Se emite los d\u00edas:", "TabSuggested": "Sugerencias", - "LabelAirTime": "Air time:", + "LabelAirTime": "Duraci\u00f3n:", "TabLatest": "Recientes", - "HeaderMediaInfo": "Media Info", + "HeaderMediaInfo": "Info del Medio:", "TabUpcoming": "Por Estrenar", - "HeaderPhotoInfo": "Photo Info", + "HeaderPhotoInfo": "Info de Fotograf\u00eda:", "TabShows": "Programas", + "HeaderInstall": "Install", "TabEpisodes": "Episodios", + "LabelSelectVersionToInstall": "Select version to install:", "TabGenres": "G\u00e9neros", + "LinkSupporterMembership": "Learn about the Supporter Membership", "TabPeople": "Personas", + "MessageSupporterPluginRequiresMembership": "This plugin will require an active supporter membership after the 14 day free trial.", "TabNetworks": "Cadenas", + "MessagePremiumPluginRequiresMembership": "This plugin will require an active supporter membership in order to purchase after the 14 day free trial.", "HeaderUsers": "Usuarios", + "HeaderReviews": "Reviews", "HeaderFilters": "Filtros:", + "HeaderDeveloperInfo": "Developer Info", "ButtonFilter": "Filtro", + "HeaderRevisionHistory": "Revision History", "OptionFavorite": "Favoritos", + "ButtonViewWebsite": "View website", "OptionLikes": "Me gusta", + "LabelRecurringDonationCanBeCancelledHelp": "Recurring donations can be cancelled at any time from within your PayPal account.", "OptionDislikes": "No me gusta", "OptionActors": "Actores", "OptionGuestStars": "Estrellas Invitadas", @@ -225,7 +235,7 @@ "OptionAscending": "Ascendente", "OptionDescending": "Descendente", "OptionRuntime": "Duraci\u00f3n", - "OptionReleaseDate": "Release Date", + "OptionReleaseDate": "Fecha de Liberaci\u00f3n", "OptionPlayCount": "N\u00famero de Reproducc.", "OptionDatePlayed": "Fecha de Reproducci\u00f3n", "OptionDateAdded": "Fecha de Adici\u00f3n", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/fr.json b/MediaBrowser.Server.Implementations/Localization/Server/fr.json index f0d030f4d..a8ca45785 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/fr.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/fr.json @@ -192,15 +192,25 @@ "TabUpcoming": "\u00c0 venir", "HeaderPhotoInfo": "Photo Info", "TabShows": "S\u00e9ries", + "HeaderInstall": "Install", "TabEpisodes": "\u00c9pisodes", + "LabelSelectVersionToInstall": "Select version to install:", "TabGenres": "Genres", + "LinkSupporterMembership": "Learn about the Supporter Membership", "TabPeople": "Personnes", + "MessageSupporterPluginRequiresMembership": "This plugin will require an active supporter membership after the 14 day free trial.", "TabNetworks": "R\u00e9seaux", + "MessagePremiumPluginRequiresMembership": "This plugin will require an active supporter membership in order to purchase after the 14 day free trial.", "HeaderUsers": "Utilisateurs", + "HeaderReviews": "Reviews", "HeaderFilters": "Filtres:", + "HeaderDeveloperInfo": "Developer Info", "ButtonFilter": "Filtre", + "HeaderRevisionHistory": "Revision History", "OptionFavorite": "Favoris", + "ButtonViewWebsite": "View website", "OptionLikes": "Aim\u00e9s", + "LabelRecurringDonationCanBeCancelledHelp": "Recurring donations can be cancelled at any time from within your PayPal account.", "OptionDislikes": "Non aim\u00e9s", "OptionActors": "Acteurs", "OptionGuestStars": "Guest Stars", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/he.json b/MediaBrowser.Server.Implementations/Localization/Server/he.json index 70b2bfe84..8f828e6ce 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/he.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/he.json @@ -192,15 +192,25 @@ "TabUpcoming": "\u05d1\u05e7\u05e8\u05d5\u05d1", "HeaderPhotoInfo": "Photo Info", "TabShows": "\u05ea\u05d5\u05db\u05e0\u05d9\u05d5\u05ea", + "HeaderInstall": "Install", "TabEpisodes": "\u05e4\u05e8\u05e7\u05d9\u05dd", + "LabelSelectVersionToInstall": "Select version to install:", "TabGenres": "\u05d6\u05d0\u05e0\u05e8\u05d9\u05dd", + "LinkSupporterMembership": "Learn about the Supporter Membership", "TabPeople": "\u05d0\u05e0\u05e9\u05d9\u05dd", + "MessageSupporterPluginRequiresMembership": "This plugin will require an active supporter membership after the 14 day free trial.", "TabNetworks": "\u05e8\u05e9\u05ea\u05d5\u05ea", + "MessagePremiumPluginRequiresMembership": "This plugin will require an active supporter membership in order to purchase after the 14 day free trial.", "HeaderUsers": "\u05de\u05e9\u05ea\u05de\u05e9\u05d9\u05dd", + "HeaderReviews": "Reviews", "HeaderFilters": "\u05de\u05e1\u05e0\u05e0\u05d9\u05dd:", + "HeaderDeveloperInfo": "Developer Info", "ButtonFilter": "\u05de\u05e1\u05e0\u05df", + "HeaderRevisionHistory": "Revision History", "OptionFavorite": "\u05de\u05d5\u05e2\u05d3\u05e4\u05d9\u05dd", + "ButtonViewWebsite": "View website", "OptionLikes": "\u05e0\u05d1\u05d7\u05e8\u05d9\u05dd", + "LabelRecurringDonationCanBeCancelledHelp": "Recurring donations can be cancelled at any time from within your PayPal account.", "OptionDislikes": "\u05dc\u05d0 \u05d0\u05d5\u05d4\u05d1", "OptionActors": "\u05e9\u05d7\u05e7\u05e0\u05d9\u05dd", "OptionGuestStars": "\u05e9\u05d7\u05e7\u05df \u05d0\u05d5\u05e8\u05d7", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/it.json b/MediaBrowser.Server.Implementations/Localization/Server/it.json index a8ffcc2eb..88820c2c1 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/it.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/it.json @@ -192,15 +192,25 @@ "TabUpcoming": "IN ONDA A BREVE", "HeaderPhotoInfo": "Photo Info", "TabShows": "Serie", + "HeaderInstall": "Install", "TabEpisodes": "Episodi", + "LabelSelectVersionToInstall": "Select version to install:", "TabGenres": "Generi", + "LinkSupporterMembership": "Learn about the Supporter Membership", "TabPeople": "Attori", + "MessageSupporterPluginRequiresMembership": "This plugin will require an active supporter membership after the 14 day free trial.", "TabNetworks": "Internet", + "MessagePremiumPluginRequiresMembership": "This plugin will require an active supporter membership in order to purchase after the 14 day free trial.", "HeaderUsers": "Utenti", + "HeaderReviews": "Reviews", "HeaderFilters": "Filtri", + "HeaderDeveloperInfo": "Developer Info", "ButtonFilter": "Filtro", + "HeaderRevisionHistory": "Revision History", "OptionFavorite": "Preferiti", + "ButtonViewWebsite": "View website", "OptionLikes": "Belli", + "LabelRecurringDonationCanBeCancelledHelp": "Recurring donations can be cancelled at any time from within your PayPal account.", "OptionDislikes": "Brutti", "OptionActors": "Attori", "OptionGuestStars": "Guest Stars", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/kk.json b/MediaBrowser.Server.Implementations/Localization/Server/kk.json index bf0fd1212..eb30d69fd 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/kk.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/kk.json @@ -66,7 +66,7 @@ "LabelEnableAutomaticPortMapping": "\u041f\u043e\u0440\u0442 \u0430\u0432\u0442\u043e\u0441\u0430\u043b\u0493\u0430\u0441\u0442\u044b\u0440\u0443\u044b\u043d \u049b\u043e\u0441\u0443", "LabelCommunityRating": "\u049a\u0430\u0443\u044b\u043c \u0431\u0430\u0493\u0430\u043b\u0430\u0443\u044b:", "LabelEnableAutomaticPortMappingHelp": "UPnP \u049b\u0430\u0448\u044b\u049b\u0442\u0430\u043d \u049b\u0430\u0442\u044b\u043d\u0430\u0441\u0443\u0434\u044b \u0436\u0435\u04a3\u0456\u043b\u0434\u0435\u0442\u0443 \u04af\u0448\u0456\u043d \u0440\u043e\u0443\u0442\u0435\u0440\u0434\u0456 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0442\u044b \u0442\u04af\u0440\u0434\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f\u043b\u0430\u0443\u0493\u0430 \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0435\u0434\u0456. \u0411\u04b1\u043b \u043a\u0435\u0439\u0431\u0456\u0440 \u0440\u043e\u0443\u0442\u0435\u0440 \u04b1\u043b\u0433\u0456\u043b\u0435\u0440\u0456\u043c\u0435\u043d \u0436\u04b1\u043c\u044b\u0441 \u0456\u0441\u0442\u0435\u043c\u0435\u0439\u0442\u0456\u043d\u0456 \u043c\u04af\u043c\u043a\u0456\u043d.", - "LabelVoteCount": "\u0414\u0430\u0443\u044b\u0441 \u0441\u0430\u043d\u044b:", + "LabelVoteCount": "\u0414\u0430\u0443\u044b\u0441 \u0435\u0441\u0435\u0431\u0456:", "ButtonOk": "\u0416\u0430\u0440\u0430\u0439\u0434\u044b", "LabelMetascore": "Metascore \u0431\u0430\u0493\u0430\u043b\u0430\u0443\u044b:", "ButtonCancel": "\u0411\u043e\u043b\u0434\u044b\u0440\u043c\u0430\u0443", @@ -96,7 +96,7 @@ "LabelDownloadInternetMetadata": "\u0421\u0443\u0440\u0435\u0442\u0442\u0435\u043c\u0435 \u043c\u0435\u043d \u043c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0456 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0442\u0435\u043d \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443", "LabelAirTime:": "\u042d\u0444\u0438\u0440 \u0443\u0430\u049b\u044b\u0442\u044b", "LabelDownloadInternetMetadataHelp": "\u0422\u043e\u043b\u044b \u043a\u04e9\u0440\u0441\u0435\u0442\u0456\u043b\u0456\u043c\u0434\u0435\u0440\u0434\u0456 \u049b\u043e\u0441\u0443 \u04af\u0448\u0456\u043d Media Browser \u0442\u0430\u0441\u0443\u0448\u044b\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440 \u0442\u0443\u0440\u0430\u043b\u044b \u043c\u04d9\u043b\u0456\u043c\u0435\u0442\u0442\u0435\u0440\u0434\u0456 \u0436\u04af\u043a\u0442\u0435\u0443\u0456 \u043c\u04af\u043c\u043a\u0456\u043d.", - "LabelRuntimeMinutes": "\u041e\u0440\u044b\u043d\u0434\u0430\u043b\u0443 \u0443\u0430\u049b\u044b\u0442\u044b, \u043c\u0438\u043d:", + "LabelRuntimeMinutes": "\u04b0\u0437\u0430\u049b\u0442\u044b\u0493\u044b, \u043c\u0438\u043d:", "TabPreferences": "\u0422\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0434\u0435\u0440", "LabelParentalRating": "\u0416\u0430\u0441\u0442\u0430\u0441 \u0441\u0430\u043d\u0430\u0442\u044b:", "TabPassword": "\u049a\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437", @@ -156,9 +156,9 @@ "LabelNewPassword": "\u0416\u0430\u04a3\u0430 \u049b\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437", "HeaderDonationType": "\u049a\u0430\u0439\u044b\u0440\u043c\u0430\u043b\u0434\u044b\u049b \u0442\u04af\u0440\u0456:", "LabelNewPasswordConfirm": "\u0416\u0430\u04a3\u0430 \u049b\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437\u0434\u0456 \u0440\u0430\u0441\u0442\u0430\u0443:", - "OptionMakeOneTimeDonation": "\u0411\u0456\u0440 \u0440\u0435\u0442 \u049b\u0430\u0439\u044b\u0440\u043c\u0430\u043b\u0434\u044b\u049b \u0436\u0430\u0441\u0430\u0443", + "OptionMakeOneTimeDonation": "\u0411\u04e9\u043b\u0435\u043a \u049b\u0430\u0439\u044b\u0440\u043c\u0430\u043b\u0434\u044b\u049b \u0436\u0430\u0441\u0430\u0443", "HeaderCreatePassword": "\u049a\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437\u0434\u0456 \u0436\u0430\u0441\u0430\u0443", - "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.", + "OptionOneTimeDescription": "\u0411\u04b1\u043b \u049b\u043e\u043b\u0434\u0430\u0443\u044b\u04a3\u044b\u0437\u0434\u044b \u043a\u04e9\u0440\u0441\u0435\u0442\u0443 \u04af\u0448\u0456\u043d \u0442\u043e\u043f\u049b\u0430 \u049b\u043e\u0441\u044b\u043c\u0448\u0430 \u049b\u0430\u0439\u044b\u0440\u043c\u0430\u043b\u0434\u044b\u049b. \u0415\u0448\u049b\u0430\u043d\u0434\u0430\u0439 \u049b\u043e\u0441\u044b\u043c\u0448\u0430 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u0440 \u0431\u043e\u043b\u043c\u0430\u0439\u0434\u044b.", "LabelCurrentPassword": "\u0410\u0493\u044b\u043c\u0434\u0430\u0493\u044b \u049b\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437:", "OptionLifeTimeSupporterClubMembership": "\u049a\u043e\u043b\u0434\u0430\u0443\u0448\u044b \u043a\u043b\u0443\u0431\u044b\u043d\u044b\u04a3 \u0493\u04b1\u043c\u044b\u0440\u043b\u044b\u049b \u043c\u04af\u0448\u0435\u043b\u0456\u0433\u0456", "LabelMaxParentalRating": "\u0420\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0456\u043b\u0433\u0435\u043d \u0435\u04a3 \u0436\u043e\u0493\u0430\u0440\u044b \u0436\u0430\u0441\u0442\u0430\u0441 \u0441\u0430\u043d\u0430\u0442\u044b:", @@ -184,23 +184,33 @@ "MessageNothingHere": "\u041e\u0441\u044b\u043d\u0434\u0430 \u0435\u0448\u0442\u0435\u043c\u0435 \u0436\u043e\u049b.", "OptionWriter": "\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439\u0448\u0456", "MessagePleaseEnsureInternetMetadata": "\u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0442\u0435\u043d \u043c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0456 \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443\u044b \u049b\u043e\u0441\u044b\u043b\u0493\u0430\u043d\u044b\u043d \u0442\u0435\u043a\u0441\u0435\u0440\u0456\u04a3\u0456\u0437.", - "LabelAirDays": "Air days:", + "LabelAirDays": "\u042d\u0444\u0438\u0440 \u043a\u04af\u043d\u0434\u0435\u0440\u0456:", "TabSuggested": "\u04b0\u0441\u044b\u043d\u044b\u043b\u0493\u0430\u043d", - "LabelAirTime": "Air time:", + "LabelAirTime": "\u042d\u0444\u0438\u0440 \u0443\u0430\u049b\u044b\u0442\u044b:", "TabLatest": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456", - "HeaderMediaInfo": "Media Info", + "HeaderMediaInfo": "\u0422\u0430\u0441\u0443\u0448\u044b\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440 \u043c\u04d9\u043b\u0456\u043c\u0435\u0442\u0456", "TabUpcoming": "\u041a\u04af\u0442\u0456\u043b\u0433\u0435\u043d", - "HeaderPhotoInfo": "Photo Info", + "HeaderPhotoInfo": "\u0424\u043e\u0442\u043e\u0441\u0443\u0440\u0435\u0442 \u043c\u04d9\u043b\u0456\u043c\u0435\u0442\u0456", "TabShows": "\u041a\u04e9\u0440\u0441\u0435\u0442\u0456\u043c\u0434\u0435\u0440", + "HeaderInstall": "\u041e\u0440\u043d\u0430\u0442\u0443", "TabEpisodes": "\u042d\u043f\u0438\u0437\u043e\u0434\u0442\u0430\u0440", + "LabelSelectVersionToInstall": "\u041e\u0440\u043d\u0430\u0442\u044b\u043c \u043d\u04b1\u0441\u049b\u0430\u0441\u044b\u043d \u0442\u0430\u04a3\u0434\u0430\u0443:", "TabGenres": "\u0416\u0430\u043d\u0440\u043b\u0430\u0440", + "LinkSupporterMembership": "Learn about the Supporter Membership", "TabPeople": "\u0410\u0434\u0430\u043c\u0434\u0430\u0440", + "MessageSupporterPluginRequiresMembership": "This plugin will require an active supporter membership after the 14 day free trial.", "TabNetworks": "\u0422\u0414 \u0436\u0435\u043b\u0456\u043b\u0435\u0440\u0456", + "MessagePremiumPluginRequiresMembership": "This plugin will require an active supporter membership in order to purchase after the 14 day free trial.", "HeaderUsers": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043b\u0430\u0440", + "HeaderReviews": "\u041f\u0456\u043a\u0456\u0440\u043b\u0435\u0440", "HeaderFilters": "\u0421\u04af\u0437\u0433\u0456\u043b\u0435\u0440:", + "HeaderDeveloperInfo": "\u0416\u0430\u0441\u0430\u049b\u0442\u0430\u0443\u0448\u044b \u0442\u0443\u0440\u0430\u043b\u044b", "ButtonFilter": "\u0421\u04af\u0437\u0443", + "HeaderRevisionHistory": "\u04e8\u0437\u0433\u0435\u0440\u0456\u0441\u0442\u0435\u0440 \u0442\u0430\u0440\u0438\u0445\u044b", "OptionFavorite": "\u0422\u0430\u04a3\u0434\u0430\u0443\u043b\u044b\u043b\u0430\u0440", + "ButtonViewWebsite": "\u0492\u0430\u043b\u0430\u043c\u0442\u043e\u0440 \u0441\u0430\u0439\u0442\u044b\u043d \u049b\u0430\u0440\u0430\u0443", "OptionLikes": "\u04b0\u043d\u0430\u0442\u0443\u043b\u0430\u0440", + "LabelRecurringDonationCanBeCancelledHelp": "Recurring donations can be cancelled at any time from within your PayPal account.", "OptionDislikes": "\u04b0\u043d\u0430\u0442\u043f\u0430\u0443\u043b\u0430\u0440", "OptionActors": "\u0410\u043a\u0442\u0435\u0440\u043b\u0435\u0440", "OptionGuestStars": "\u0428\u0430\u049b\u044b\u0440\u044b\u043b\u0493\u0430\u043d \u0430\u043a\u0442\u0435\u0440\u043b\u0435\u0440", @@ -224,9 +234,9 @@ "OptionUnplayed": "\u041e\u0439\u043d\u0430\u0442\u044b\u043b\u043c\u0430\u0493\u0430\u043d", "OptionAscending": "\u0410\u0440\u0442\u0443\u044b \u0431\u043e\u0439\u044b\u043d\u0448\u0430", "OptionDescending": "\u041a\u0435\u043c\u0443\u0456 \u0431\u043e\u0439\u044b\u043d\u0448\u0430", - "OptionRuntime": "\u041e\u0440\u044b\u043d\u0434\u0430\u0443 \u0443\u0430\u049b\u044b\u0442\u044b", + "OptionRuntime": "\u04b0\u0437\u0430\u049b\u0442\u044b\u0493\u044b", "OptionReleaseDate": "\u0428\u044b\u0493\u0430\u0440\u0443 \u043a\u04af\u043d-\u0430\u0439\u044b", - "OptionPlayCount": "\u041e\u0439\u043d\u0430\u0442\u0443 \u0441\u0430\u043d\u044b", + "OptionPlayCount": "\u041e\u0439\u043d\u0430\u0442\u0443 \u0435\u0441\u0435\u0431\u0456", "OptionDatePlayed": "\u041e\u0439\u043d\u0430\u0442\u044b\u043b\u0493\u0430\u043d \u043a\u04af\u043d-\u0430\u0439\u044b", "OptionDateAdded": "\u04ae\u0441\u0442\u0435\u043b\u0433\u0435\u043d \u043a\u04af\u043d-\u0430\u0439\u044b", "OptionAlbumArtist": "\u0410\u043b\u044c\u0431\u043e\u043c \u043e\u0440\u044b\u043d\u0434\u0430\u0443\u0448\u044b\u0441\u044b", @@ -353,11 +363,11 @@ "LabelRunServerAtStartupHelp": "\u0411\u04b1\u043b Windows \u0436\u04b1\u043c\u044b\u0441\u044b\u043d \u0431\u0430\u0441\u0442\u0430\u0493\u0430\u043d\u0434\u0430 \u0436\u04af\u0439\u0435\u043b\u0456\u043a \u0442\u0430\u049b\u0442\u0430\u0434\u0430\u0493\u044b \u0431\u0435\u043b\u0433\u0456\u0448\u0435 \u0456\u0441\u043a\u0435 \u049b\u043e\u0441\u044b\u043b\u0430\u0434\u044b. Windows \u049b\u044b\u0437\u043c\u0435\u0442\u0456\u043d \u0456\u0441\u043a\u0435 \u049b\u043e\u0441\u0443 \u04af\u0448\u0456\u043d, \u049b\u04b1\u0441\u0431\u0435\u043b\u0433\u0456\u043d\u0456 \u0430\u043b\u044b\u04a3\u044b\u0437 \u0436\u04d9\u043d\u0435 \u049b\u044b\u0437\u043c\u0435\u0442\u0442\u0456 Windows \u049a\u044b\u0437\u043c\u0435\u0442\u0442\u0435\u0440 \u0434\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440\u0456 \u0430\u0440\u049b\u044b\u043b\u044b \u043e\u0440\u044b\u043d\u0434\u0430\u04a3\u044b\u0437. \u041d\u0430\u0437\u0430\u0440 \u0430\u0443\u0434\u0430\u0440\u044b\u04a3\u044b\u0437! \u0411\u04b1\u043b \u0435\u043a\u0435\u0443\u0456\u043d \u0441\u043e\u043b \u043c\u0435\u0437\u0433\u0456\u043b\u0434\u0435 \u0431\u0456\u0440\u0433\u0435 \u043e\u0440\u044b\u043d\u0434\u0430\u0443 \u043c\u04af\u043c\u043a\u0456\u043d \u0435\u043c\u0435\u0441, \u0441\u043e\u043d\u044b\u043c\u0435\u043d \u049b\u044b\u0437\u043c\u0435\u0442\u0442\u0456 \u0456\u0441\u043a\u0435 \u049b\u043e\u0441\u0443 \u0430\u043b\u0434\u044b\u043d\u0430\u043d \u0436\u04af\u0439\u0435\u043b\u0456\u043a \u0442\u0430\u049b\u0442\u0430\u0434\u0430\u0493\u044b \u0431\u0435\u043b\u0433\u0456\u0448\u0435\u0434\u0435\u043d \u0448\u044b\u0493\u044b\u04a3\u044b\u0437.", "ButtonSelectDirectory": "\u049a\u0430\u0442\u0430\u043b\u043e\u0433\u0442\u044b \u0431\u04e9\u043b\u0435\u043a\u0442\u0435\u0443", "LabelCustomPaths": "\u049a\u0430\u043b\u0430\u0443\u044b\u04a3\u044b\u0437 \u0431\u043e\u0439\u044b\u043d\u0448\u0430 \u0442\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u0436\u043e\u043b\u0434\u0430\u0440\u0434\u044b \u0430\u043d\u044b\u049b\u0442\u0430\u04a3\u044b\u0437. \u04d8\u0434\u0435\u043f\u043a\u0456\u043b\u0435\u0440\u0434\u0456 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443 \u04af\u0448\u0456\u043d \u04e9\u0440\u0456\u0441\u0442\u0435\u0440\u0434\u0456 \u0431\u043e\u0441 \u049b\u0430\u043b\u0434\u044b\u0440\u044b\u04a3\u044b\u0437.", - "LabelCachePath": "Cache \u049b\u0430\u043b\u0442\u0430\u0441\u044b\u043d\u044b\u04a3 \u0436\u043e\u043b\u044b:", + "LabelCachePath": "\u041a\u0435\u0448\u043a\u0435 \u049b\u0430\u0440\u0430\u0439 \u0436\u043e\u043b:", "LabelCachePathHelp": "\u0421\u0443\u0440\u0435\u0442 \u0441\u0438\u044f\u049b\u0442\u044b \u0441\u0435\u0440\u0432\u0435\u0440\u0434\u0456\u04a3 \u043a\u044d\u0448 \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b \u04af\u0448\u0456\u043d \u0442\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u0436\u0430\u0439\u0493\u0430\u0441\u044b\u043c\u0434\u044b \u0430\u043d\u044b\u049b\u0442\u0430\u04a3\u044b\u0437.", - "LabelImagesByNamePath": "Images by name \u049b\u0430\u043b\u0442\u0430\u0441\u044b\u043d\u044b\u04a3 \u0436\u043e\u043b\u044b:", + "LabelImagesByNamePath": "\u0410\u0442\u044b \u0431\u043e\u0439\u044b\u043d\u0448\u0430 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0433\u0435 \u049b\u0430\u0440\u0430\u0439 \u0436\u043e\u043b:", "LabelImagesByNamePathHelp": "\u0416\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u044b\u043d\u0493\u0430\u043d \u0430\u043a\u0442\u0435\u0440, \u043e\u0440\u044b\u043d\u0434\u0430\u0443\u0448\u044b, \u0436\u0430\u043d\u0440, \u0436\u04d9\u043d\u0435 \u0441\u0442\u0443\u0434\u0438\u044f \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0456 \u04af\u0448\u0456\u043d \u0442\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u0436\u0430\u0439\u0493\u0430\u0441\u044b\u043c\u0434\u044b \u0430\u043d\u044b\u049b\u0442\u0430\u04a3\u044b\u0437.", - "LabelMetadataPath": "Metadata \u049b\u0430\u043b\u0442\u0430\u0441\u044b\u043d\u044b\u04a3 \u0436\u043e\u043b\u044b:", + "LabelMetadataPath": "\u041c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0433\u0435 \u049b\u0430\u0440\u0430\u0439 \u0436\u043e\u043b:", "LabelMetadataPathHelp": "\u0416\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u044b\u043d\u0493\u0430\u043d \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u043c\u0435\u043b\u0435\u0440 \u0431\u0435\u043d \u043c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440 \u04af\u0448\u0456\u043d \u0442\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u0436\u0430\u0439\u0493\u0430\u0441\u044b\u043c\u0434\u044b \u0430\u043d\u044b\u049b\u0442\u0430\u04a3\u044b\u0437.", "LabelTranscodingTempPath": "Transcoding temporary \u049b\u0430\u043b\u0442\u0430\u0441\u044b\u043d\u044b\u04a3 \u0436\u043e\u043b\u044b:", "LabelTranscodingTempPathHelp": "\u0411\u04b1\u043b \u049b\u0430\u043b\u0442\u0430 \u049b\u04b1\u0440\u0430\u043c\u044b\u043d\u0434\u0430 \u049b\u0430\u0439\u0442\u0430 \u043a\u043e\u0434\u0442\u0430\u0443 \u049b\u04b1\u0440\u0430\u043b\u044b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0430\u0442\u044b\u043d \u0436\u04b1\u043c\u044b\u0441 \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b \u0431\u0430\u0440. \u0422\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u0436\u043e\u043b\u0434\u044b \u0430\u043d\u044b\u049b\u0442\u0430\u04a3\u044b\u0437, \u043d\u0435\u043c\u0435\u0441\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0434\u0456\u04a3 \u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440 \u049b\u0430\u043b\u0442\u0430\u0441\u044b \u0456\u0448\u0456\u043d\u0434\u0435\u0433\u0456 \u04d9\u0434\u0435\u043f\u043a\u0456\u0441\u0456\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443 \u04af\u0448\u0456\u043d \u0431\u043e\u0441 \u049b\u0430\u043b\u0434\u044b\u0440\u044b\u04a3\u044b\u0437.", @@ -937,7 +947,7 @@ "OptionLatestTvRecordings": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456 \u0436\u0430\u0437\u0431\u0430\u043b\u0430\u0440", "LabelProtocolInfo": "\u041f\u0440\u043e\u0442\u043e\u049b\u043e\u043b \u0430\u049b\u043f\u0430\u0440\u0430\u0442\u044b:", "LabelProtocolInfoHelp": "\u0411\u04b1\u043b \u043c\u04d9\u043d \u0436\u0430\u0431\u0434\u044b\u049b\u0442\u044b\u04a3 GetProtocolInfo \u0441\u04b1\u0440\u0430\u043d\u044b\u0441\u0442\u0430\u0440\u044b\u043d\u0430 \u0436\u0430\u0443\u0430\u043f \u0431\u0435\u0440\u0433\u0435\u043d\u0434\u0435 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u043b\u0430\u0434\u044b.", - "TabXbmcMetadata": "Xbmc", + "TabXbmcMetadata": "XBMC", "HeaderXbmcMetadataHelp": "Media Browser \u0431\u0430\u0493\u0434\u0430\u0440\u043b\u0430\u043c\u0430\u0441\u044b Xbmc Nfo \u043c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0442\u0435\u0440\u0456\u043d\u0456\u04a3 \u0436\u04d9\u043d\u0435 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0456\u043d\u0456\u04a3 \u043a\u0456\u0440\u0456\u043a\u0442\u0456\u0440\u043c\u0435 \u049b\u043e\u043b\u0434\u0430\u0443\u044b\u043d \u049b\u0430\u043c\u0442\u0438\u0434\u044b. Xbmc \u043c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0456\u043d \u049b\u043e\u0441\u0443 \u043d\u0435\u043c\u0435\u0441\u0435 \u04e9\u0448\u0456\u0440\u0443 \u04af\u0448\u0456\u043d \u049a\u044b\u0437\u043c\u0435\u0442\u0442\u0435\u0440 \u049b\u043e\u0439\u044b\u043d\u0434\u044b\u0441\u044b\u043d\u0434\u0430\u0493\u044b \u0442\u0430\u0441\u0443\u0448\u044b \u0442\u04af\u0440\u043b\u0435\u0440\u0456\u043d\u0435 \u0430\u0440\u043d\u0430\u043b\u0493\u0430\u043d \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440\u0434\u0456 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u04a3\u044b\u0437.", "LabelXbmcMetadataUser": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043d\u044b\u04a3 \u049b\u0430\u0440\u0430\u0443 \u043a\u04af\u0439\u0456\u043d nfo \u04af\u0448\u0456\u043d \u043c\u044b\u043d\u0430\u0493\u0430\u043d \u049b\u043e\u0441\u0443:", "LabelXbmcMetadataUserHelp": "\u041a\u04e9\u0440\u0456\u043b\u0433\u0435\u043d \u043a\u04af\u0439\u0434\u0456 Media Browser \u0436\u04d9\u043d\u0435 Xbmc \u0430\u0440\u0430\u0441\u044b\u043d\u0434\u0430 \u04af\u0439\u043b\u0435\u0441\u0442\u0456\u0440\u0456\u043f \u0442\u04b1\u0440\u0443 \u04af\u0448\u0456\u043d \u0431\u04b1\u043d\u044b \u049b\u043e\u0441\u044b\u04a3\u044b\u0437.", @@ -965,11 +975,11 @@ "OptionList": "\u0422\u0456\u0437\u0456\u043c", "TabDashboard": "\u0411\u0430\u049b\u044b\u043b\u0430\u0443 \u0442\u0430\u049b\u0442\u0430\u0441\u044b", "TitleServer": "\u0421\u0435\u0440\u0432\u0435\u0440", - "LabelCache": "Cache:", - "LabelLogs": "Logs:", - "LabelMetadata": "Metadata:", - "LabelImagesByName": "Images by name:", - "LabelTranscodingTemporaryFiles": "Transcoding temporary files:", + "LabelCache": "\u041a\u0435\u0448:", + "LabelLogs": "\u0416\u04b1\u0440\u043d\u0430\u043b\u0434\u0430\u0440:", + "LabelMetadata": "\u041c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440:", + "LabelImagesByName": "\u0410\u0442\u044b \u0431\u043e\u0439\u044b\u043d\u0448\u0430 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440:", + "LabelTranscodingTemporaryFiles": "\u049a\u0430\u0439\u0442\u0430 \u043a\u043e\u0434\u0442\u0430\u0443\u044b\u043d\u044b\u04a3 \u0443\u0430\u049b\u044b\u0442\u0448\u0430 \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b:", "HeaderLatestMusic": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456 \u043c\u0443\u0437\u044b\u043a\u0430", "HeaderBranding": "\u0411\u0440\u0435\u043d\u0434\u0438\u04a3\u0433", "HeaderApiKeys": "API \u043a\u0456\u043b\u0442\u0442\u0435\u0440\u0456", @@ -1010,7 +1020,7 @@ "TabSync": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443", "TitleUsers": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043b\u0430\u0440", "LabelProtocol": "\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b:", - "OptionProtocolHttp": "Http", + "OptionProtocolHttp": "HTTP", "OptionProtocolHls": "Http \u0422\u0456\u043a\u0435\u043b\u0435\u0439 \u0410\u0493\u044b\u043d (HLS)", "LabelContext": "\u041c\u04d9\u0442\u0456\u043d\u043c\u04d9\u043d:", "OptionContextStreaming": "\u0410\u0493\u044b\u043d\u043c\u0435\u043d \u0442\u0430\u0441\u044b\u043c\u0430\u043b\u0434\u0430\u0443", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/ko.json b/MediaBrowser.Server.Implementations/Localization/Server/ko.json index 3a322eba7..956e4909a 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/ko.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/ko.json @@ -192,15 +192,25 @@ "TabUpcoming": "Upcoming", "HeaderPhotoInfo": "Photo Info", "TabShows": "Shows", + "HeaderInstall": "Install", "TabEpisodes": "Episodes", + "LabelSelectVersionToInstall": "Select version to install:", "TabGenres": "Genres", + "LinkSupporterMembership": "Learn about the Supporter Membership", "TabPeople": "People", + "MessageSupporterPluginRequiresMembership": "This plugin will require an active supporter membership after the 14 day free trial.", "TabNetworks": "Networks", + "MessagePremiumPluginRequiresMembership": "This plugin will require an active supporter membership in order to purchase after the 14 day free trial.", "HeaderUsers": "Users", + "HeaderReviews": "Reviews", "HeaderFilters": "Filters:", + "HeaderDeveloperInfo": "Developer Info", "ButtonFilter": "Filter", + "HeaderRevisionHistory": "Revision History", "OptionFavorite": "Favorites", + "ButtonViewWebsite": "View website", "OptionLikes": "Likes", + "LabelRecurringDonationCanBeCancelledHelp": "Recurring donations can be cancelled at any time from within your PayPal account.", "OptionDislikes": "Dislikes", "OptionActors": "Actors", "OptionGuestStars": "Guest Stars", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/ms.json b/MediaBrowser.Server.Implementations/Localization/Server/ms.json index 0180f0060..5311a3875 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/ms.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/ms.json @@ -192,15 +192,25 @@ "TabUpcoming": "Upcoming", "HeaderPhotoInfo": "Photo Info", "TabShows": "Shows", + "HeaderInstall": "Install", "TabEpisodes": "Episodes", + "LabelSelectVersionToInstall": "Select version to install:", "TabGenres": "Genres", + "LinkSupporterMembership": "Learn about the Supporter Membership", "TabPeople": "People", + "MessageSupporterPluginRequiresMembership": "This plugin will require an active supporter membership after the 14 day free trial.", "TabNetworks": "Networks", + "MessagePremiumPluginRequiresMembership": "This plugin will require an active supporter membership in order to purchase after the 14 day free trial.", "HeaderUsers": "Users", + "HeaderReviews": "Reviews", "HeaderFilters": "Filters:", + "HeaderDeveloperInfo": "Developer Info", "ButtonFilter": "Filter", + "HeaderRevisionHistory": "Revision History", "OptionFavorite": "Favorites", + "ButtonViewWebsite": "View website", "OptionLikes": "Likes", + "LabelRecurringDonationCanBeCancelledHelp": "Recurring donations can be cancelled at any time from within your PayPal account.", "OptionDislikes": "Dislikes", "OptionActors": "Actors", "OptionGuestStars": "Guest Stars", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/nb.json b/MediaBrowser.Server.Implementations/Localization/Server/nb.json index 21236b292..5186d9799 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/nb.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/nb.json @@ -192,15 +192,25 @@ "TabUpcoming": "Kommer", "HeaderPhotoInfo": "Photo Info", "TabShows": "Show", + "HeaderInstall": "Install", "TabEpisodes": "Episoder", + "LabelSelectVersionToInstall": "Select version to install:", "TabGenres": "Sjanger", + "LinkSupporterMembership": "Learn about the Supporter Membership", "TabPeople": "Folk", + "MessageSupporterPluginRequiresMembership": "This plugin will require an active supporter membership after the 14 day free trial.", "TabNetworks": "Nettverk", + "MessagePremiumPluginRequiresMembership": "This plugin will require an active supporter membership in order to purchase after the 14 day free trial.", "HeaderUsers": "Bruker", + "HeaderReviews": "Reviews", "HeaderFilters": "Filtre", + "HeaderDeveloperInfo": "Developer Info", "ButtonFilter": "Filter", + "HeaderRevisionHistory": "Revision History", "OptionFavorite": "Favoritter", + "ButtonViewWebsite": "View website", "OptionLikes": "Liker", + "LabelRecurringDonationCanBeCancelledHelp": "Recurring donations can be cancelled at any time from within your PayPal account.", "OptionDislikes": "Misliker", "OptionActors": "Skuespiller", "OptionGuestStars": "Gjeste-opptredelser", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/nl.json b/MediaBrowser.Server.Implementations/Localization/Server/nl.json index 8eda36b99..210531a01 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/nl.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/nl.json @@ -158,7 +158,7 @@ "LabelNewPasswordConfirm": "Bevestig nieuw wachtwoord:", "OptionMakeOneTimeDonation": "Doe een eenmalige donatie", "HeaderCreatePassword": "Maak wachtwoord", - "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.", + "OptionOneTimeDescription": "Dit is een extra donatie voor het team om te laten zien dat je ze steunt. Het geeft geen extra voordelen.", "LabelCurrentPassword": "Huidig wachtwoord", "OptionLifeTimeSupporterClubMembership": "Levenslang supporters club lidmaatschap", "LabelMaxParentalRating": "Maximaal toegestane kijkwijzer classificatie:", @@ -172,35 +172,45 @@ "ButtonDeleteImage": "Verwijder afbeelding", "LabelOneTimeDonationAmount": "Donatie bedrag:", "LabelSelectUsers": "Selecteer gebruikers:", - "OptionActor": "Actor", + "OptionActor": "Acteur", "ButtonUpload": "Uploaden", - "OptionComposer": "Composer", + "OptionComposer": "Componist", "HeaderUploadNewImage": "Nieuwe afbeelding uploaden", - "OptionDirector": "Director", + "OptionDirector": "Regiseur", "LabelDropImageHere": "Afbeelding hier neerzetten", - "OptionGuestStar": "Guest star", + "OptionGuestStar": "Gast ster", "ImageUploadAspectRatioHelp": "1:1 beeldverhouding geadviseerd. Alleen JPG\/PNG.", - "OptionProducer": "Producer", + "OptionProducer": "Producent", "MessageNothingHere": "Lijst is leeg.", - "OptionWriter": "Writer", + "OptionWriter": "Schrijver", "MessagePleaseEnsureInternetMetadata": "Zorg ervoor dat het downloaden van metadata van het internet is ingeschakeld.", - "LabelAirDays": "Air days:", + "LabelAirDays": "Uitzend dagen:", "TabSuggested": "Aanbevolen", - "LabelAirTime": "Air time:", + "LabelAirTime": "Uitzend tijd:", "TabLatest": "Nieuw", - "HeaderMediaInfo": "Media Info", + "HeaderMediaInfo": "Media informatie", "TabUpcoming": "Binnenkort", - "HeaderPhotoInfo": "Photo Info", + "HeaderPhotoInfo": "Foto informatie", "TabShows": "Series", + "HeaderInstall": "Install", "TabEpisodes": "Afleveringen", + "LabelSelectVersionToInstall": "Select version to install:", "TabGenres": "Genres", + "LinkSupporterMembership": "Learn about the Supporter Membership", "TabPeople": "Personen", + "MessageSupporterPluginRequiresMembership": "This plugin will require an active supporter membership after the 14 day free trial.", "TabNetworks": "TV-Studio's", + "MessagePremiumPluginRequiresMembership": "This plugin will require an active supporter membership in order to purchase after the 14 day free trial.", "HeaderUsers": "Gebruikers", + "HeaderReviews": "Reviews", "HeaderFilters": "Filters:", + "HeaderDeveloperInfo": "Developer Info", "ButtonFilter": "Filter", + "HeaderRevisionHistory": "Revision History", "OptionFavorite": "Favorieten", + "ButtonViewWebsite": "View website", "OptionLikes": "Leuk", + "LabelRecurringDonationCanBeCancelledHelp": "Recurring donations can be cancelled at any time from within your PayPal account.", "OptionDislikes": "Niet leuk", "OptionActors": "Acteurs", "OptionGuestStars": "Gast Sterren", @@ -854,15 +864,15 @@ "LabelDisplayPluginsFor": "Toon Plug-ins voor:", "PluginTabMediaBrowserClassic": "MB Classic", "PluginTabMediaBrowserTheater": "MB Theater", - "LabelEpisodeNamePlain": "Episode name", - "LabelSeriesNamePlain": "Series name", + "LabelEpisodeNamePlain": "Naam aflevering", + "LabelSeriesNamePlain": "Naam serie", "ValueSeriesNamePeriod": "Serie.Naam", "ValueSeriesNameUnderscore": "Serie_naam", "ValueEpisodeNamePeriod": "Aflevering.naam", "ValueEpisodeNameUnderscore": "Aflevering_naam", - "LabelSeasonNumberPlain": "Season number", - "LabelEpisodeNumberPlain": "Episode number", - "LabelEndingEpisodeNumberPlain": "Ending episode number", + "LabelSeasonNumberPlain": "nummer seizoen", + "LabelEpisodeNumberPlain": "Nummer aflevering", + "LabelEndingEpisodeNumberPlain": "Laatste nummer aflevering", "HeaderTypeText": "Voer tekst in", "LabelTypeText": "Tekst", "HeaderSearchForSubtitles": "Zoeken naar Ondertitels", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/pl.json b/MediaBrowser.Server.Implementations/Localization/Server/pl.json index fcd29a463..161f4578c 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/pl.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/pl.json @@ -192,15 +192,25 @@ "TabUpcoming": "Upcoming", "HeaderPhotoInfo": "Photo Info", "TabShows": "Seriale", + "HeaderInstall": "Install", "TabEpisodes": "Odcinki", + "LabelSelectVersionToInstall": "Select version to install:", "TabGenres": "Rodzaje", + "LinkSupporterMembership": "Learn about the Supporter Membership", "TabPeople": "Osoby", + "MessageSupporterPluginRequiresMembership": "This plugin will require an active supporter membership after the 14 day free trial.", "TabNetworks": "Sieci", + "MessagePremiumPluginRequiresMembership": "This plugin will require an active supporter membership in order to purchase after the 14 day free trial.", "HeaderUsers": "U\u017cytkownicy", + "HeaderReviews": "Reviews", "HeaderFilters": "Filtry:", + "HeaderDeveloperInfo": "Developer Info", "ButtonFilter": "Filtr", + "HeaderRevisionHistory": "Revision History", "OptionFavorite": "Ulubione", + "ButtonViewWebsite": "View website", "OptionLikes": "Likes", + "LabelRecurringDonationCanBeCancelledHelp": "Recurring donations can be cancelled at any time from within your PayPal account.", "OptionDislikes": "Dislikes", "OptionActors": "Aktorzy", "OptionGuestStars": "Guest Stars", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json b/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json index fa01486a8..4a8b6d59d 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json @@ -92,9 +92,9 @@ "LabelSaveLocalMetadata": "Salvar artwork e metadados dentro das pastas da m\u00eddia", "LabelEndDate": "Data final:", "LabelSaveLocalMetadataHelp": "Salvar artwork e metadados diretamente nas pastas da m\u00eddia as deixar\u00e1 em um local f\u00e1cil para edit\u00e1-las.", - "LabelAirDate": "Dias de exibi\u00e7\u00e3o:", + "LabelAirDate": "Dias da exibi\u00e7\u00e3o:", "LabelDownloadInternetMetadata": "Fazer download das imagens e metadados da internet", - "LabelAirTime:": "Hora da exibi\u00e7\u00e3o:", + "LabelAirTime:": "Hor\u00e1rio:", "LabelDownloadInternetMetadataHelp": "O Media Browser pode fazer download das informa\u00e7\u00f5es de sua m\u00eddia para melhorar a apresenta\u00e7\u00e3o.", "LabelRuntimeMinutes": "Dura\u00e7\u00e3o (minutos):", "TabPreferences": "Prefer\u00eancias", @@ -156,9 +156,9 @@ "LabelNewPassword": "Nova senha:", "HeaderDonationType": "Tipo de doa\u00e7\u00e3o:", "LabelNewPasswordConfirm": "Confirmar nova senha:", - "OptionMakeOneTimeDonation": "Fazer doa\u00e7\u00e3o uma \u00fanica vez", + "OptionMakeOneTimeDonation": "Fazer uma doa\u00e7\u00e3o \u00fanica", "HeaderCreatePassword": "Criar Senha", - "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.", + "OptionOneTimeDescription": "Esta \u00e9 uma doa\u00e7\u00e3o adicional \u00e0 equipe para demonstrar seu apoio. N\u00e3o garante nenhum benef\u00edcio adicional.", "LabelCurrentPassword": "Senha atual:", "OptionLifeTimeSupporterClubMembership": "Filia\u00e7\u00e3o vital\u00edcia do clube do colaborador", "LabelMaxParentalRating": "Classifica\u00e7\u00e3o parental m\u00e1xima permitida:", @@ -184,23 +184,33 @@ "MessageNothingHere": "Nada aqui.", "OptionWriter": "Escritor", "MessagePleaseEnsureInternetMetadata": "Por favor, certifique-se que o download de metadados da internet est\u00e1 habilitado.", - "LabelAirDays": "Air days:", + "LabelAirDays": "Dias da exibi\u00e7\u00e3o:", "TabSuggested": "Sugeridos", - "LabelAirTime": "Air time:", + "LabelAirTime": "Hor\u00e1rio:", "TabLatest": "Recentes", - "HeaderMediaInfo": "Media Info", + "HeaderMediaInfo": "Informa\u00e7\u00f5es da M\u00eddia", "TabUpcoming": "Por Estrear", - "HeaderPhotoInfo": "Photo Info", + "HeaderPhotoInfo": "Informa\u00e7\u00f5es da Foto", "TabShows": "S\u00e9ries", + "HeaderInstall": "Install", "TabEpisodes": "Epis\u00f3dios", + "LabelSelectVersionToInstall": "Select version to install:", "TabGenres": "G\u00eaneros", + "LinkSupporterMembership": "Learn about the Supporter Membership", "TabPeople": "Pessoas", + "MessageSupporterPluginRequiresMembership": "This plugin will require an active supporter membership after the 14 day free trial.", "TabNetworks": "Redes", + "MessagePremiumPluginRequiresMembership": "This plugin will require an active supporter membership in order to purchase after the 14 day free trial.", "HeaderUsers": "Usu\u00e1rios", + "HeaderReviews": "Reviews", "HeaderFilters": "Filtros:", + "HeaderDeveloperInfo": "Developer Info", "ButtonFilter": "Filtro", + "HeaderRevisionHistory": "Revision History", "OptionFavorite": "Favoritos", + "ButtonViewWebsite": "View website", "OptionLikes": "Gostei", + "LabelRecurringDonationCanBeCancelledHelp": "Recurring donations can be cancelled at any time from within your PayPal account.", "OptionDislikes": "N\u00e3o Gostei", "OptionActors": "Atores", "OptionGuestStars": "Convidados Especiais", @@ -288,7 +298,7 @@ "HeaderStatus": "Status", "OptionContinuing": "Em Exibi\u00e7\u00e3o", "OptionEnded": "Finalizada", - "HeaderAirDays": "Dias de Exibi\u00e7\u00e3o", + "HeaderAirDays": "Dias da Exibi\u00e7\u00e3o", "OptionSunday": "Domingo", "OptionMonday": "Segunda-feira", "OptionTuesday": "Ter\u00e7a-feira", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json b/MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json index 359d838d9..2826927cb 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json @@ -192,15 +192,25 @@ "TabUpcoming": "Pr\u00f3ximos", "HeaderPhotoInfo": "Photo Info", "TabShows": "S\u00e9ries", + "HeaderInstall": "Install", "TabEpisodes": "Epis\u00f3dios", + "LabelSelectVersionToInstall": "Select version to install:", "TabGenres": "G\u00e9neros Art\u00edsticos", + "LinkSupporterMembership": "Learn about the Supporter Membership", "TabPeople": "Pessoas", + "MessageSupporterPluginRequiresMembership": "This plugin will require an active supporter membership after the 14 day free trial.", "TabNetworks": "Redes", + "MessagePremiumPluginRequiresMembership": "This plugin will require an active supporter membership in order to purchase after the 14 day free trial.", "HeaderUsers": "Utilizadores", + "HeaderReviews": "Reviews", "HeaderFilters": "Filtros:", + "HeaderDeveloperInfo": "Developer Info", "ButtonFilter": "Filtro", + "HeaderRevisionHistory": "Revision History", "OptionFavorite": "Favoritos", + "ButtonViewWebsite": "View website", "OptionLikes": "Gostos", + "LabelRecurringDonationCanBeCancelledHelp": "Recurring donations can be cancelled at any time from within your PayPal account.", "OptionDislikes": "N\u00e3o gostos", "OptionActors": "Actores", "OptionGuestStars": "Actores convidados", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/ru.json b/MediaBrowser.Server.Implementations/Localization/Server/ru.json index 2902f716d..7b437805f 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/ru.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/ru.json @@ -66,7 +66,7 @@ "LabelEnableAutomaticPortMapping": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0430\u0432\u0442\u043e\u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u0440\u0442\u043e\u0432", "LabelCommunityRating": "\u041e\u0431\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u0430\u044f \u043e\u0446\u0435\u043d\u043a\u0430:", "LabelEnableAutomaticPortMappingHelp": "UPnP \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0442\u043e\u0440 \u0434\u043b\u044f \u043e\u0431\u043b\u0435\u0433\u0447\u0435\u043d\u0438\u044f \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u044d\u0442\u043e \u043d\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u043c\u043e\u0434\u0435\u043b\u044f\u043c\u0438 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0442\u043e\u0440\u043e\u0432.", - "LabelVoteCount": "\u0427\u0438\u0441\u043b\u043e \u0433\u043e\u043b\u043e\u0441\u043e\u0432:", + "LabelVoteCount": "\u041f\u043e\u0434\u0441\u0447\u0451\u0442 \u0433\u043e\u043b\u043e\u0441\u043e\u0432:", "ButtonOk": "\u041e\u041a", "LabelMetascore": "\u041e\u0446\u0435\u043d\u043a\u0430 Metascore:", "ButtonCancel": "\u041e\u0442\u043c\u0435\u043d\u0430", @@ -96,7 +96,7 @@ "LabelDownloadInternetMetadata": "\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0438 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430", "LabelAirTime:": "\u0412\u0440\u0435\u043c\u044f \u044d\u0444\u0438\u0440\u0430:", "LabelDownloadInternetMetadataHelp": "\u0414\u043b\u044f \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0445 \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0432 Media Browser.", - "LabelRuntimeMinutes": "\u0412\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u0435\u043d\u0438\u044f, \u043c\u0438\u043d:", + "LabelRuntimeMinutes": "\u0414\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c, \u043c\u0438\u043d:", "TabPreferences": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438", "LabelParentalRating": "\u0412\u043e\u0437\u0440\u0430\u0441\u0442\u043d\u0430\u044f \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f:", "TabPassword": "\u041f\u0430\u0440\u043e\u043b\u044c", @@ -156,9 +156,9 @@ "LabelNewPassword": "\u041d\u043e\u0432\u044b\u0439 \u043f\u0430\u0440\u043e\u043b\u044c", "HeaderDonationType": "\u0422\u0438\u043f \u043f\u043e\u0436\u0435\u0440\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u044f:", "LabelNewPasswordConfirm": "\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f", - "OptionMakeOneTimeDonation": "\u041e\u0434\u043d\u043e\u043a\u0440\u0430\u0442\u043d\u043e\u0435 \u043f\u043e\u0436\u0435\u0440\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0435", + "OptionMakeOneTimeDonation": "\u041f\u043e\u0436\u0435\u0440\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e", "HeaderCreatePassword": "\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c", - "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.", + "OptionOneTimeDescription": "\u042d\u0442\u043e \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u043f\u043e\u0436\u0435\u0440\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u0435, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0430\u0448\u0443 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443. \u041d\u0435 \u0434\u0430\u0451\u0442 \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432.", "LabelCurrentPassword": "\u0422\u0435\u043a\u0443\u0449\u0438\u0439 \u043f\u0430\u0440\u043e\u043b\u044c", "OptionLifeTimeSupporterClubMembership": "\u041f\u043e\u0436\u0438\u0437\u043d\u0435\u043d\u043d\u043e\u0435 \u0447\u043b\u0435\u043d\u0441\u0442\u0432\u043e \u0432 \u043a\u043b\u0443\u0431\u0435 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u043e\u0432", "LabelMaxParentalRating": "\u041c\u0430\u043a\u0441. \u0440\u0430\u0437\u0440\u0435\u0448\u0451\u043d\u043d\u0430\u044f \u0432\u043e\u0437\u0440\u0430\u0441\u0442\u043d\u0430\u044f \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f:", @@ -184,23 +184,33 @@ "MessageNothingHere": "\u0417\u0434\u0435\u0441\u044c \u043d\u0435\u0442 \u043d\u0438\u0447\u0435\u0433\u043e.", "OptionWriter": "\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0441\u0442", "MessagePleaseEnsureInternetMetadata": "\u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0430.", - "LabelAirDays": "Air days:", + "LabelAirDays": "\u0414\u043d\u0438 \u044d\u0444\u0438\u0440\u0430:", "TabSuggested": "\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u043c\u044b\u0435", - "LabelAirTime": "Air time:", + "LabelAirTime": "\u0412\u0440\u0435\u043c\u044f \u044d\u0444\u0438\u0440\u0430:", "TabLatest": "\u041d\u043e\u0432\u0438\u043d\u043a\u0438", - "HeaderMediaInfo": "Media Info", + "HeaderMediaInfo": "\u0421\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445", "TabUpcoming": "\u041e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0435", - "HeaderPhotoInfo": "Photo Info", + "HeaderPhotoInfo": "\u0421\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e \u0444\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0438", "TabShows": "\u0426\u0438\u043a\u043b\u044b", + "HeaderInstall": "\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430", "TabEpisodes": "\u042d\u043f\u0438\u0437\u043e\u0434\u044b", + "LabelSelectVersionToInstall": "\u0412\u044b\u0431\u043e\u0440 \u0432\u0435\u0440\u0441\u0438\u0438 \u0434\u043b\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438:", "TabGenres": "\u0416\u0430\u043d\u0440\u044b", + "LinkSupporterMembership": "\u041e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0447\u043b\u0435\u043d\u0441\u0442\u0432\u043e\u043c \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u043e\u0432", "TabPeople": "\u041b\u044e\u0434\u0438", + "MessageSupporterPluginRequiresMembership": "\u0414\u0430\u043d\u043d\u043e\u043c\u0443 \u043f\u043b\u0430\u0433\u0438\u043d\u0443 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0447\u043b\u0435\u043d\u0441\u0442\u0432\u043e \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430 \u0447\u0435\u0440\u0435\u0437 14 \u0434\u043d\u0435\u0439 \u043f\u0440\u043e\u0431\u043d\u043e\u0433\u043e \u043f\u0435\u0440\u0438\u043e\u0434\u0430.", "TabNetworks": "\u0422\u0435\u043b\u0435\u0441\u0435\u0442\u0438", + "MessagePremiumPluginRequiresMembership": "\u0414\u0430\u043d\u043d\u043e\u043c\u0443 \u043f\u043b\u0430\u0433\u0438\u043d\u0443 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0447\u043b\u0435\u043d\u0441\u0442\u0432\u043e \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430 \u0434\u043b\u044f \u043f\u0440\u0438\u043e\u0431\u0440\u0435\u0442\u0435\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437 14 \u0434\u043d\u0435\u0439 \u043f\u0440\u043e\u0431\u043d\u043e\u0433\u043e \u043f\u0435\u0440\u0438\u043e\u0434\u0430.", "HeaderUsers": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438", + "HeaderReviews": "\u041e\u0442\u0437\u044b\u0432\u044b", "HeaderFilters": "\u0424\u0438\u043b\u044c\u0442\u0440\u044b:", + "HeaderDeveloperInfo": "\u0421\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0435", "ButtonFilter": "\u0424\u0438\u043b\u044c\u0442\u0440\u043e\u0432\u0430\u0442\u044c", + "HeaderRevisionHistory": "\u0418\u0441\u0442\u043e\u0440\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439", "OptionFavorite": "\u0418\u0437\u0431\u0440\u0430\u043d\u043d\u044b\u0435", + "ButtonViewWebsite": "\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432\u0435\u0431\u0441\u0430\u0439\u0442", "OptionLikes": "\u041d\u0440\u0430\u0432\u0438\u0442\u0441\u044f", + "LabelRecurringDonationCanBeCancelledHelp": "\u0420\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u044b\u0435 \u043f\u043e\u0436\u0435\u0440\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043c\u0435\u043d\u0438\u0442\u044c \u0432 \u043b\u044e\u0431\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0447\u0435\u0440\u0435\u0437 \u0432\u0430\u0448\u0443 \u0443\u0447\u0451\u0442\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c PayPal.", "OptionDislikes": "\u041d\u0435 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f", "OptionActors": "\u0410\u043a\u0442\u0451\u0440\u044b", "OptionGuestStars": "\u041f\u0440\u0438\u0433\u043b\u0430\u0448\u0451\u043d\u043d\u044b\u0435 \u0430\u043a\u0442\u0451\u0440\u044b", @@ -226,7 +236,7 @@ "OptionDescending": "\u0423\u0431\u044b\u0432\u0430\u043d\u0438\u0435", "OptionRuntime": "\u0414\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c", "OptionReleaseDate": "\u0414\u0430\u0442\u0430 \u0432\u044b\u043f\u0443\u0441\u043a\u0430", - "OptionPlayCount": "\u0427\u0438\u0441\u043b\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0439", + "OptionPlayCount": "\u041f\u043e\u0434\u0441\u0447\u0451\u0442 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0439", "OptionDatePlayed": "\u0414\u0430\u0442\u0430 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f", "OptionDateAdded": "\u0414\u0430\u0442\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f", "OptionAlbumArtist": "\u0410\u043b\u044c\u0431\u043e\u043c. \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c", @@ -353,13 +363,13 @@ "LabelRunServerAtStartupHelp": "\u0417\u043d\u0430\u0447\u043e\u043a \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u043c \u043b\u043e\u0442\u043a\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0441\u0442\u0430\u0440\u0442\u0430 Windows. \u0427\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0441\u043b\u0443\u0436\u0431\u0443 Windows, \u0443\u0431\u0435\u0440\u0438\u0442\u0435 \u0433\u0430\u043b\u043e\u0447\u043a\u0443 \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0435 \u0441\u043b\u0443\u0436\u0431\u0443 \u0438\u0437 \u043a\u043e\u043d\u0441\u043e\u043b\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f Windows. \u041f\u0440\u0438\u043c\u0438\u0442\u0435 \u043a \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044e, \u0447\u0442\u043e \u043e\u043d\u0438 \u043e\u0431\u0430 \u043d\u0435 \u043c\u043e\u0433\u0443\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u043e\u043a \u0432 \u043b\u043e\u0442\u043a\u0435 \u0434\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0441\u043b\u0443\u0436\u0431\u044b.", "ButtonSelectDirectory": "\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u043a\u0430\u0442\u0430\u043b\u043e\u0433", "LabelCustomPaths": "\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0435 \u043f\u0443\u0442\u0438 \u043f\u043e \u0436\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f\u043c. \u041e\u0441\u0442\u0430\u0432\u043b\u044f\u0439\u0442\u0435 \u043f\u043e\u043b\u044f \u043f\u0443\u0441\u0442\u044b\u043c\u0438 \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0445.", - "LabelCachePath": "\u041f\u0443\u0442\u044c \u043a \u043f\u0430\u043f\u043a\u0435 Cache:", + "LabelCachePath": "\u041f\u0443\u0442\u044c \u043a\u043e \u043a\u0435\u0448\u0443:", "LabelCachePathHelp": "\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e\u0435 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u043e\u0432 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0433\u043e \u043a\u044d\u0448\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432.", - "LabelImagesByNamePath": "\u041f\u0443\u0442\u044c \u043a \u043f\u0430\u043f\u043a\u0435 Images by name:", + "LabelImagesByNamePath": "\u041f\u0443\u0442\u044c \u043a\u043e \u0440\u0438\u0441\u0443\u043d\u043a\u0430\u043c \u0447\u0435\u0440\u0435\u0437 \u0438\u043c\u044f:", "LabelImagesByNamePathHelp": "\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e\u0435 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u044b\u0445 \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432 \u0430\u043a\u0442\u0451\u0440\u043e\u0432, \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u0435\u0439, \u0436\u0430\u043d\u0440\u043e\u0432 \u0438 \u0441\u0442\u0443\u0434\u0438\u0439.", - "LabelMetadataPath": "\u041f\u0443\u0442\u044c \u043a \u043f\u0430\u043f\u043a\u0435 Metadata:", + "LabelMetadataPath": "\u041f\u0443\u0442\u044c \u043a\u043e \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u043c:", "LabelMetadataPathHelp": "\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e\u0435 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u044b\u0445 \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0439 \u0438 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445, \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u043d\u0435 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0438 \u043c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043e\u043a.", - "LabelTranscodingTempPath": "\u041f\u0443\u0442\u044c \u043a \u043f\u0430\u043f\u043a\u0435 Transcoding temporary:", + "LabelTranscodingTempPath": "\u041f\u0443\u0442\u044c \u043a\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c \u0444\u0430\u0439\u043b\u0430\u043c \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0438:", "LabelTranscodingTempPathHelp": "\u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u043f\u0430\u043f\u043a\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u0441\u044f \u0440\u0430\u0431\u043e\u0447\u0438\u0435 \u0444\u0430\u0439\u043b\u044b, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0435. \u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439 \u043f\u0443\u0442\u044c, \u0438\u043b\u0438 \u043e\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u043f\u0443\u0441\u0442\u044b\u043c, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u0432\u043d\u0443\u0442\u0440\u0438 \u043f\u0430\u043f\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u0435\u0440\u0432\u0435\u0440\u0430.", "TabBasics": "\u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435", "TabTV": "\u0422\u0412", @@ -965,11 +975,11 @@ "OptionList": "\u0421\u043f\u0438\u0441\u043e\u043a", "TabDashboard": "\u0418\u043d\u0444\u043e\u043f\u0430\u043d\u0435\u043b\u044c", "TitleServer": "\u0421\u0435\u0440\u0432\u0435\u0440", - "LabelCache": "Cache:", - "LabelLogs": "Logs:", - "LabelMetadata": "Metadata:", - "LabelImagesByName": "Images by name:", - "LabelTranscodingTemporaryFiles": "Transcoding temporary files:", + "LabelCache": "\u041a\u0435\u0448:", + "LabelLogs": "\u0416\u0443\u0440\u043d\u0430\u043b\u044b:", + "LabelMetadata": "\u041c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435:", + "LabelImagesByName": "\u0420\u0438\u0441\u0443\u043d\u043a\u0438 \u0447\u0435\u0440\u0435\u0437 \u0438\u043c\u044f:", + "LabelTranscodingTemporaryFiles": "\u0412\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0438:", "HeaderLatestMusic": "\u041d\u043e\u0432\u0438\u043d\u043a\u0438 \u043c\u0443\u0437\u044b\u043a\u0438", "HeaderBranding": "\u0411\u0440\u0435\u043d\u0434\u0438\u043d\u0433", "HeaderApiKeys": "\u041a\u043b\u044e\u0447\u0438 API", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json index 21eb0c1c9..2ed67ccf0 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/server.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json @@ -1110,5 +1110,15 @@ "LabelAirDays": "Air days:", "LabelAirTime": "Air time:", "HeaderMediaInfo": "Media Info", - "HeaderPhotoInfo": "Photo Info" + "HeaderPhotoInfo": "Photo Info", + "HeaderInstall": "Install", + "LabelSelectVersionToInstall": "Select version to install:", + "LinkSupporterMembership": "Learn about the Supporter Membership", + "MessageSupporterPluginRequiresMembership": "This plugin will require an active supporter membership after the 14 day free trial.", + "MessagePremiumPluginRequiresMembership": "This plugin will require an active supporter membership in order to purchase after the 14 day free trial.", + "HeaderReviews": "Reviews", + "HeaderDeveloperInfo": "Developer Info", + "HeaderRevisionHistory": "Revision History", + "ButtonViewWebsite": "View website", + "LabelRecurringDonationCanBeCancelledHelp": "Recurring donations can be cancelled at any time from within your PayPal account." } diff --git a/MediaBrowser.Server.Implementations/Localization/Server/sv.json b/MediaBrowser.Server.Implementations/Localization/Server/sv.json index 445071cdd..ced6fe1f8 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/sv.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/sv.json @@ -192,15 +192,25 @@ "TabUpcoming": "Kommande", "HeaderPhotoInfo": "Photo Info", "TabShows": "Serier", + "HeaderInstall": "Install", "TabEpisodes": "Avsnitt", + "LabelSelectVersionToInstall": "Select version to install:", "TabGenres": "Genrer", + "LinkSupporterMembership": "Learn about the Supporter Membership", "TabPeople": "Personer", + "MessageSupporterPluginRequiresMembership": "This plugin will require an active supporter membership after the 14 day free trial.", "TabNetworks": "TV-bolag", + "MessagePremiumPluginRequiresMembership": "This plugin will require an active supporter membership in order to purchase after the 14 day free trial.", "HeaderUsers": "Anv\u00e4ndare", + "HeaderReviews": "Reviews", "HeaderFilters": "Filter:", + "HeaderDeveloperInfo": "Developer Info", "ButtonFilter": "Filtrera", + "HeaderRevisionHistory": "Revision History", "OptionFavorite": "Favoriter", + "ButtonViewWebsite": "View website", "OptionLikes": "Gillar", + "LabelRecurringDonationCanBeCancelledHelp": "Recurring donations can be cancelled at any time from within your PayPal account.", "OptionDislikes": "Ogillar", "OptionActors": "Sk\u00e5despelare", "OptionGuestStars": "G\u00e4startister", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/tr.json b/MediaBrowser.Server.Implementations/Localization/Server/tr.json index ea2a7e95d..d991debe6 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/tr.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/tr.json @@ -192,15 +192,25 @@ "TabUpcoming": "Gelecek", "HeaderPhotoInfo": "Photo Info", "TabShows": "G\u00f6steriler", + "HeaderInstall": "Install", "TabEpisodes": "B\u00f6l\u00fcmler", + "LabelSelectVersionToInstall": "Select version to install:", "TabGenres": "T\u00fcrler", + "LinkSupporterMembership": "Learn about the Supporter Membership", "TabPeople": "Oyuncular", + "MessageSupporterPluginRequiresMembership": "This plugin will require an active supporter membership after the 14 day free trial.", "TabNetworks": "A\u011flar", + "MessagePremiumPluginRequiresMembership": "This plugin will require an active supporter membership in order to purchase after the 14 day free trial.", "HeaderUsers": "Kullan\u0131c\u0131lar", + "HeaderReviews": "Reviews", "HeaderFilters": "Filtrelemeler", + "HeaderDeveloperInfo": "Developer Info", "ButtonFilter": "Filtre", + "HeaderRevisionHistory": "Revision History", "OptionFavorite": "Favoriler", + "ButtonViewWebsite": "View website", "OptionLikes": "Be\u011feniler", + "LabelRecurringDonationCanBeCancelledHelp": "Recurring donations can be cancelled at any time from within your PayPal account.", "OptionDislikes": "Be\u011fenmeyenler", "OptionActors": "Akt\u00f6rler", "OptionGuestStars": "Konuk oylar\u0131", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/vi.json b/MediaBrowser.Server.Implementations/Localization/Server/vi.json index 3590a5fea..01f7f85c9 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/vi.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/vi.json @@ -192,15 +192,25 @@ "TabUpcoming": "S\u1eafp di\u1ec5n ra", "HeaderPhotoInfo": "Photo Info", "TabShows": "Shows", + "HeaderInstall": "Install", "TabEpisodes": "C\u00e1c t\u1eadp phim", + "LabelSelectVersionToInstall": "Select version to install:", "TabGenres": "C\u00e1c th\u1ec3 lo\u1ea1i", + "LinkSupporterMembership": "Learn about the Supporter Membership", "TabPeople": "M\u1ecdi ng\u01b0\u1eddi", + "MessageSupporterPluginRequiresMembership": "This plugin will require an active supporter membership after the 14 day free trial.", "TabNetworks": "C\u00e1c m\u1ea1ng", + "MessagePremiumPluginRequiresMembership": "This plugin will require an active supporter membership in order to purchase after the 14 day free trial.", "HeaderUsers": "d\u00f9ng", + "HeaderReviews": "Reviews", "HeaderFilters": "Filters:", + "HeaderDeveloperInfo": "Developer Info", "ButtonFilter": "Filter", + "HeaderRevisionHistory": "Revision History", "OptionFavorite": "Y\u00eau th\u00edch", + "ButtonViewWebsite": "View website", "OptionLikes": "Th\u00edch", + "LabelRecurringDonationCanBeCancelledHelp": "Recurring donations can be cancelled at any time from within your PayPal account.", "OptionDislikes": "Kh\u00f4ng th\u00edch", "OptionActors": "Di\u1ec5n vi\u00ean", "OptionGuestStars": "Guest Stars", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json b/MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json index 50a794ec8..0c3ba3c4a 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json @@ -192,15 +192,25 @@ "TabUpcoming": "\u5373\u5c07\u767c\u5e03", "HeaderPhotoInfo": "Photo Info", "TabShows": "\u7bc0\u76ee", + "HeaderInstall": "Install", "TabEpisodes": "\u55ae\u5143", + "LabelSelectVersionToInstall": "Select version to install:", "TabGenres": "\u985e\u578b", + "LinkSupporterMembership": "Learn about the Supporter Membership", "TabPeople": "\u4eba\u7269", + "MessageSupporterPluginRequiresMembership": "This plugin will require an active supporter membership after the 14 day free trial.", "TabNetworks": "\u7db2\u7d61", + "MessagePremiumPluginRequiresMembership": "This plugin will require an active supporter membership in order to purchase after the 14 day free trial.", "HeaderUsers": "\u7528\u6236", + "HeaderReviews": "Reviews", "HeaderFilters": "\u904e\u6ffe\uff1a", + "HeaderDeveloperInfo": "Developer Info", "ButtonFilter": "\u904e\u6ffe", + "HeaderRevisionHistory": "Revision History", "OptionFavorite": "\u6211\u7684\u6700\u611b", + "ButtonViewWebsite": "View website", "OptionLikes": "\u559c\u6b61", + "LabelRecurringDonationCanBeCancelledHelp": "Recurring donations can be cancelled at any time from within your PayPal account.", "OptionDislikes": "\u4e0d\u559c\u6b61", "OptionActors": "\u6f14\u54e1", "OptionGuestStars": "\u7279\u9080\u660e\u661f", diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index 1b5bd8440..51dccddff 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -305,20 +305,6 @@ namespace MediaBrowser.ServerApplication { var saveConfig = false; - if (ServerConfigurationManager.Configuration.DlnaOptions != null) - { - ServerConfigurationManager.SaveConfiguration("dlna", ServerConfigurationManager.Configuration.DlnaOptions); - ServerConfigurationManager.Configuration.DlnaOptions = null; - saveConfig = true; - } - - if (ServerConfigurationManager.Configuration.LiveTvOptions != null) - { - ServerConfigurationManager.SaveConfiguration("livetv", ServerConfigurationManager.Configuration.LiveTvOptions); - ServerConfigurationManager.Configuration.LiveTvOptions = null; - saveConfig = true; - } - if (ServerConfigurationManager.Configuration.TvFileOrganizationOptions != null) { ServerConfigurationManager.SaveConfiguration("autoorganize", new AutoOrganizeOptions { TvOptions = ServerConfigurationManager.Configuration.TvFileOrganizationOptions }); diff --git a/MediaBrowser.Tests/MediaBrowser.Tests.csproj b/MediaBrowser.Tests/MediaBrowser.Tests.csproj index dc7393b01..315ec583e 100644 --- a/MediaBrowser.Tests/MediaBrowser.Tests.csproj +++ b/MediaBrowser.Tests/MediaBrowser.Tests.csproj @@ -50,7 +50,7 @@ </Otherwise> </Choose> <ItemGroup> - <Compile Include="MediaEncoding\Subtitles\SsaParserTests.cs" /> + <Compile Include="MediaEncoding\Subtitles\AssParserTests.cs" /> <Compile Include="MediaEncoding\Subtitles\SrtParserTests.cs" /> <Compile Include="MediaEncoding\Subtitles\VttWriterTest.cs" /> <Compile Include="Providers\MovieDbProviderTests.cs" /> @@ -93,7 +93,7 @@ <None Include="MediaEncoding\Subtitles\TestSubtitles\expected.vtt"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> - <None Include="MediaEncoding\Subtitles\TestSubtitles\data.ssa"> + <None Include="MediaEncoding\Subtitles\TestSubtitles\data.ass"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> <None Include="MediaEncoding\Subtitles\TestSubtitles\unit.srt"> diff --git a/MediaBrowser.Tests/MediaEncoding/Subtitles/SsaParserTests.cs b/MediaBrowser.Tests/MediaEncoding/Subtitles/AssParserTests.cs index d869146fd..17687bc3a 100644 --- a/MediaBrowser.Tests/MediaEncoding/Subtitles/SsaParserTests.cs +++ b/MediaBrowser.Tests/MediaEncoding/Subtitles/AssParserTests.cs @@ -1,14 +1,13 @@ -using System; +using MediaBrowser.MediaEncoding.Subtitles; +using Microsoft.VisualStudio.TestTools.UnitTesting; using System.Collections.Generic; using System.IO; using System.Threading; -using MediaBrowser.MediaEncoding.Subtitles; -using Microsoft.VisualStudio.TestTools.UnitTesting; namespace MediaBrowser.Tests.MediaEncoding.Subtitles { [TestClass] - public class SsaParserTests { + public class AssParserTests { [TestMethod] public void TestParse() { @@ -21,7 +20,7 @@ namespace MediaBrowser.Tests.MediaEncoding.Subtitles { StartPositionTicks = 24000000, EndPositionTicks = 72000000, Text = - "Senator, we're <br />making our final <br />approach into Coruscant." + "Senator, we're "+ParserValues.NewLine+"making our final "+ParserValues.NewLine+"approach into Coruscant." }, new SubtitleTrackEvent { Id = "2", @@ -34,14 +33,14 @@ namespace MediaBrowser.Tests.MediaEncoding.Subtitles { Id = "3", StartPositionTicks = 150400000, EndPositionTicks = 180400000, - Text = "It's <br />a <br />trap!" + Text = "It's "+ParserValues.NewLine+"a "+ParserValues.NewLine+"trap!" } } }; var sut = new AssParser(); - var stream = File.OpenRead(@"MediaEncoding\Subtitles\TestSubtitles\data.ssa"); + var stream = File.OpenRead(@"MediaEncoding\Subtitles\TestSubtitles\data.ass"); var result = sut.Parse(stream, CancellationToken.None); diff --git a/MediaBrowser.Tests/MediaEncoding/Subtitles/SrtParserTests.cs b/MediaBrowser.Tests/MediaEncoding/Subtitles/SrtParserTests.cs index 2c2c944b1..6724ca597 100644 --- a/MediaBrowser.Tests/MediaEncoding/Subtitles/SrtParserTests.cs +++ b/MediaBrowser.Tests/MediaEncoding/Subtitles/SrtParserTests.cs @@ -5,17 +5,21 @@ using System.Threading; using MediaBrowser.MediaEncoding.Subtitles; using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace MediaBrowser.Tests.MediaEncoding.Subtitles { +namespace MediaBrowser.Tests.MediaEncoding.Subtitles +{ [TestClass] - public class SrtParserTests { + public class SrtParserTests + { [TestMethod] - public void TestParse() { + public void TestParse() + { var expectedSubs = - new SubtitleTrackInfo { - TrackEvents = new List<SubtitleTrackEvent> { + new SubtitleTrackInfo + { + TrackEvents = new List<SubtitleTrackEvent> { new SubtitleTrackEvent { Id = "1", StartPositionTicks = 24000000, @@ -28,7 +32,7 @@ namespace MediaBrowser.Tests.MediaEncoding.Subtitles { StartPositionTicks = 157120000, EndPositionTicks = 173990000, Text = - "Oh my god, Watch out!<br />It's coming!!" + "Oh my god, Watch out!"+ParserValues.NewLine+"It's coming!!" }, new SubtitleTrackEvent { Id = "3", @@ -48,7 +52,7 @@ namespace MediaBrowser.Tests.MediaEncoding.Subtitles { StartPositionTicks = 320000000, EndPositionTicks = 329990000, Text = - "This is a<br />new line, as is<br />this" + "This is a"+ParserValues.NewLine+"new line, as is"+ParserValues.NewLine+"this" }, new SubtitleTrackEvent { Id = "6", @@ -86,7 +90,7 @@ namespace MediaBrowser.Tests.MediaEncoding.Subtitles { "Greater than (<) and less than (>) are shown" } } - }; + }; var sut = new SrtParser(); @@ -95,7 +99,7 @@ namespace MediaBrowser.Tests.MediaEncoding.Subtitles { var result = sut.Parse(stream, CancellationToken.None); Assert.IsNotNull(result); - Assert.AreEqual(expectedSubs.TrackEvents.Count,result.TrackEvents.Count); + Assert.AreEqual(expectedSubs.TrackEvents.Count, result.TrackEvents.Count); for (int i = 0; i < expectedSubs.TrackEvents.Count; i++) { Assert.AreEqual(expectedSubs.TrackEvents[i].Id, result.TrackEvents[i].Id); diff --git a/MediaBrowser.Tests/MediaEncoding/Subtitles/TestSubtitles/data.ssa b/MediaBrowser.Tests/MediaEncoding/Subtitles/TestSubtitles/data.ass index 3114a844a..3114a844a 100644 --- a/MediaBrowser.Tests/MediaEncoding/Subtitles/TestSubtitles/data.ssa +++ b/MediaBrowser.Tests/MediaEncoding/Subtitles/TestSubtitles/data.ass |
