diff options
431 files changed, 12827 insertions, 5269 deletions
diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs index 0eb92d5a7..ef415ec57 100644 --- a/MediaBrowser.Api/ApiEntryPoint.cs +++ b/MediaBrowser.Api/ApiEntryPoint.cs @@ -1,10 +1,10 @@ using MediaBrowser.Api.Playback; using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.IO; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Session; using System; @@ -39,6 +39,7 @@ namespace MediaBrowser.Api private readonly IServerConfigurationManager _config; private readonly ISessionManager _sessionManager; + private readonly IFileSystem _fileSystem; public readonly SemaphoreSlim TranscodingStartLock = new SemaphoreSlim(1, 1); @@ -48,11 +49,12 @@ namespace MediaBrowser.Api /// <param name="logger">The logger.</param> /// <param name="sessionManager">The session manager.</param> /// <param name="config">The configuration.</param> - public ApiEntryPoint(ILogger logger, ISessionManager sessionManager, IServerConfigurationManager config) + public ApiEntryPoint(ILogger logger, ISessionManager sessionManager, IServerConfigurationManager config, IFileSystem fileSystem) { Logger = logger; _sessionManager = sessionManager; _config = config; + _fileSystem = fileSystem; Instance = this; } @@ -86,12 +88,12 @@ namespace MediaBrowser.Api /// </summary> private void DeleteEncodedMediaCache() { - var path = Path.Combine(_config.ApplicationPaths.TranscodingTempPath, EncodingContext.Streaming.ToString().ToLower()); + var path = _config.ApplicationPaths.TranscodingTempPath; foreach (var file in Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories) .ToList()) { - File.Delete(file); + _fileSystem.DeleteFile(file); } } @@ -462,7 +464,7 @@ namespace MediaBrowser.Api /// <param name="outputFilePath">The output file path.</param> private void DeleteProgressivePartialStreamFiles(string outputFilePath) { - File.Delete(outputFilePath); + _fileSystem.DeleteFile(outputFilePath); } /// <summary> @@ -479,13 +481,13 @@ namespace MediaBrowser.Api .ToList(); Exception e = null; - + foreach (var file in filesToDelete) { try { Logger.Info("Deleting HLS file {0}", file); - File.Delete(file); + _fileSystem.DeleteFile(file); } catch (DirectoryNotFoundException) { diff --git a/MediaBrowser.Api/BaseApiService.cs b/MediaBrowser.Api/BaseApiService.cs index 297a13155..dff433c9d 100644 --- a/MediaBrowser.Api/BaseApiService.cs +++ b/MediaBrowser.Api/BaseApiService.cs @@ -1,9 +1,12 @@ -using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Session; +using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; +using ServiceStack.Text.Controller; using ServiceStack.Web; using System; using System.Collections.Generic; @@ -21,7 +24,7 @@ namespace MediaBrowser.Api /// </summary> /// <value>The logger.</value> public ILogger Logger { get; set; } - + /// <summary> /// Gets or sets the HTTP result factory. /// </summary> @@ -35,6 +38,7 @@ namespace MediaBrowser.Api public IRequest Request { get; set; } public ISessionContext SessionContext { get; set; } + public IAuthorizationContext AuthorizationContext { get; set; } public string GetHeader(string name) { @@ -109,6 +113,37 @@ namespace MediaBrowser.Api private readonly char[] _dashReplaceChars = { '?', '/', '&' }; private const char SlugChar = '-'; + protected DtoOptions GetDtoOptions(object request) + { + var options = new DtoOptions(); + + options.DeviceId = AuthorizationContext.GetAuthorizationInfo(Request).DeviceId; + + var hasFields = request as IHasItemFields; + if (hasFields != null) + { + options.Fields = hasFields.GetItemFields().ToList(); + } + + var hasDtoOptions = request as IHasDtoOptions; + if (hasDtoOptions != null) + { + options.EnableImages = hasDtoOptions.EnableImages ?? true; + + if (hasDtoOptions.ImageTypeLimit.HasValue) + { + options.ImageTypeLimit = hasDtoOptions.ImageTypeLimit.Value; + } + + if (!string.IsNullOrWhiteSpace(hasDtoOptions.EnableImageTypes)) + { + options.ImageTypes = (hasDtoOptions.EnableImageTypes ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).Select(v => (ImageType)Enum.Parse(typeof(ImageType), v, true)).ToList(); + } + } + + return options; + } + protected MusicArtist GetArtist(string name, ILibraryManager libraryManager) { return libraryManager.GetArtist(DeSlugArtistName(name, libraryManager)); @@ -139,11 +174,11 @@ namespace MediaBrowser.Api return libraryManager.GetPerson(DeSlugPersonName(name, libraryManager)); } - protected IEnumerable<BaseItem> GetAllLibraryItems(Guid? userId, IUserManager userManager, ILibraryManager libraryManager, string parentId = null) + protected IList<BaseItem> GetAllLibraryItems(Guid? userId, IUserManager userManager, ILibraryManager libraryManager, string parentId, Func<BaseItem,bool> filter) { if (!string.IsNullOrEmpty(parentId)) { - var folder = (Folder) libraryManager.GetItemById(new Guid(parentId)); + var folder = (Folder)libraryManager.GetItemById(new Guid(parentId)); if (userId.HasValue) { @@ -154,10 +189,13 @@ namespace MediaBrowser.Api throw new ArgumentException("User not found"); } - return folder.GetRecursiveChildren(user); + return folder + .GetRecursiveChildren(user, filter) + .ToList(); } - return folder.GetRecursiveChildren(); + return folder + .GetRecursiveChildren(filter); } if (userId.HasValue) { @@ -168,10 +206,16 @@ namespace MediaBrowser.Api throw new ArgumentException("User not found"); } - return userManager.GetUserById(userId.Value).RootFolder.GetRecursiveChildren(user); + return userManager + .GetUserById(userId.Value) + .RootFolder + .GetRecursiveChildren(user, filter) + .ToList(); } - return libraryManager.RootFolder.GetRecursiveChildren(); + return libraryManager + .RootFolder + .GetRecursiveChildren(filter); } /// <summary> @@ -187,8 +231,9 @@ namespace MediaBrowser.Api return name; } - return libraryManager.RootFolder.RecursiveChildren - .OfType<Audio>() + return libraryManager.RootFolder + .GetRecursiveChildren(i => i is IHasArtist) + .Cast<IHasArtist>() .SelectMany(i => i.AllArtists) .Distinct(StringComparer.OrdinalIgnoreCase) .FirstOrDefault(i => @@ -229,8 +274,8 @@ namespace MediaBrowser.Api return name; } - return libraryManager.RootFolder.GetRecursiveChildren() - .OfType<Game>() + return libraryManager.RootFolder + .GetRecursiveChildren(i => i is Game) .SelectMany(i => i.Genres) .Distinct(StringComparer.OrdinalIgnoreCase) .FirstOrDefault(i => @@ -252,7 +297,8 @@ namespace MediaBrowser.Api return name; } - return libraryManager.RootFolder.GetRecursiveChildren() + return libraryManager.RootFolder + .GetRecursiveChildren() .SelectMany(i => i.Studios) .Distinct(StringComparer.OrdinalIgnoreCase) .FirstOrDefault(i => @@ -274,7 +320,8 @@ namespace MediaBrowser.Api return name; } - return libraryManager.RootFolder.GetRecursiveChildren() + return libraryManager.RootFolder + .GetRecursiveChildren() .SelectMany(i => i.People) .Select(i => i.Name) .Distinct(StringComparer.OrdinalIgnoreCase) @@ -287,6 +334,20 @@ namespace MediaBrowser.Api }) ?? name; } + protected string GetPathValue(int index) + { + var pathInfo = PathInfo.Parse(Request.PathInfo); + var first = pathInfo.GetArgumentValue<string>(0); + + // backwards compatibility + if (string.Equals(first, "mediabrowser", StringComparison.OrdinalIgnoreCase)) + { + index++; + } + + return pathInfo.GetArgumentValue<string>(index); + } + /// <summary> /// Gets the name of the item by. /// </summary> @@ -294,7 +355,6 @@ namespace MediaBrowser.Api /// <param name="type">The type.</param> /// <param name="libraryManager">The library manager.</param> /// <returns>Task{BaseItem}.</returns> - /// <exception cref="System.ArgumentException"></exception> protected BaseItem GetItemByName(string name, string type, ILibraryManager libraryManager) { BaseItem item; diff --git a/MediaBrowser.Api/BrandingService.cs b/MediaBrowser.Api/BrandingService.cs index 4b49b411a..ac491a997 100644 --- a/MediaBrowser.Api/BrandingService.cs +++ b/MediaBrowser.Api/BrandingService.cs @@ -8,7 +8,12 @@ namespace MediaBrowser.Api public class GetBrandingOptions : IReturn<BrandingOptions> { } - + + [Route("/Branding/Css", "GET", Summary = "Gets custom css")] + public class GetBrandingCss + { + } + public class BrandingService : BaseApiService { private readonly IConfigurationManager _config; @@ -24,5 +29,12 @@ namespace MediaBrowser.Api return ToOptimizedResult(result); } + + public object Get(GetBrandingCss request) + { + var result = _config.GetConfiguration<BrandingOptions>("branding"); + + return ResultFactory.GetResult(result.CustomCss, "text/css"); + } } } diff --git a/MediaBrowser.Api/ConfigurationService.cs b/MediaBrowser.Api/ConfigurationService.cs index 3eb0296fc..d0abd18c2 100644 --- a/MediaBrowser.Api/ConfigurationService.cs +++ b/MediaBrowser.Api/ConfigurationService.cs @@ -143,8 +143,7 @@ namespace MediaBrowser.Api public void Post(UpdateNamedConfiguration request) { - var pathInfo = PathInfo.Parse(Request.PathInfo); - var key = pathInfo.GetArgumentValue<string>(2); + var key = GetPathValue(2); var configurationType = _configurationManager.GetConfigurationType(key); var configuration = _jsonSerializer.DeserializeFromStream(request.RequestStream, configurationType); diff --git a/MediaBrowser.Api/ConnectService.cs b/MediaBrowser.Api/ConnectService.cs index 102e2d45e..4bcd33d9e 100644 --- a/MediaBrowser.Api/ConnectService.cs +++ b/MediaBrowser.Api/ConnectService.cs @@ -39,11 +39,11 @@ namespace MediaBrowser.Api [ApiMember(Name = "SendingUserId", Description = "Sending User Id", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")] public string SendingUserId { get; set; } - [ApiMember(Name = "ExcludeLibraries", Description = "ExcludeLibraries", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")] - public string ExcludedLibraries { get; set; } + [ApiMember(Name = "EnabledLibraries", Description = "EnabledLibraries", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")] + public string EnabledLibraries { get; set; } - [ApiMember(Name = "ExcludedChannels", Description = "ExcludedChannels", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")] - public string ExcludedChannels { get; set; } + [ApiMember(Name = "EnabledChannels", Description = "EnabledChannels", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")] + public string EnabledChannels { get; set; } [ApiMember(Name = "EnableLiveTv", Description = "EnableLiveTv", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")] public bool EnableLiveTv { get; set; } @@ -91,12 +91,12 @@ namespace MediaBrowser.Api public object Post(CreateConnectInvite request) { - var excludeLibraries = (request.ExcludedLibraries ?? string.Empty) + var enabledLibraries = (request.EnabledLibraries ?? string.Empty) .Split(',') .Where(i => !string.IsNullOrWhiteSpace(i)) .ToArray(); - var excludedChannels = (request.ExcludedChannels ?? string.Empty) + var enabledChannels = (request.EnabledChannels ?? string.Empty) .Split(',') .Where(i => !string.IsNullOrWhiteSpace(i)) .ToArray(); @@ -105,8 +105,8 @@ namespace MediaBrowser.Api { ConnectUserName = request.ConnectUsername, SendingUserId = request.SendingUserId, - ExcludedLibraries = excludeLibraries, - ExcludedChannels = excludedChannels, + EnabledLibraries = enabledLibraries, + EnabledChannels = enabledChannels, EnableLiveTv = request.EnableLiveTv }); } diff --git a/MediaBrowser.Api/Dlna/DlnaServerService.cs b/MediaBrowser.Api/Dlna/DlnaServerService.cs index 94d6e25b0..24a6c52d0 100644 --- a/MediaBrowser.Api/Dlna/DlnaServerService.cs +++ b/MediaBrowser.Api/Dlna/DlnaServerService.cs @@ -1,6 +1,5 @@ using MediaBrowser.Controller.Dlna; using ServiceStack; -using ServiceStack.Text.Controller; using ServiceStack.Web; using System; using System.Collections.Generic; @@ -19,19 +18,31 @@ namespace MediaBrowser.Api.Dlna public string UuId { get; set; } } - [Route("/Dlna/contentdirectory/contentdirectory.xml", "GET", Summary = "Gets dlna content directory xml")] - [Route("/Dlna/contentdirectory/contentdirectory", "GET", Summary = "Gets dlna content directory xml")] + [Route("/Dlna/{UuId}/contentdirectory/contentdirectory.xml", "GET", Summary = "Gets dlna content directory xml")] + [Route("/Dlna/{UuId}/contentdirectory/contentdirectory", "GET", Summary = "Gets dlna content directory xml")] public class GetContentDirectory { + [ApiMember(Name = "UuId", Description = "Server UuId", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "GET")] + public string UuId { get; set; } } - [Route("/Dlna/connectionmanager/connectionmanager.xml", "GET", Summary = "Gets dlna connection manager xml")] - [Route("/Dlna/connectionmanager/connectionmanager", "GET", Summary = "Gets dlna connection manager xml")] + [Route("/Dlna/{UuId}/connectionmanager/connectionmanager.xml", "GET", Summary = "Gets dlna connection manager xml")] + [Route("/Dlna/{UuId}/connectionmanager/connectionmanager", "GET", Summary = "Gets dlna connection manager xml")] public class GetConnnectionManager { + [ApiMember(Name = "UuId", Description = "Server UuId", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "GET")] + public string UuId { get; set; } + } + + [Route("/Dlna/{UuId}/mediareceiverregistrar/mediareceiverregistrar.xml", "GET", Summary = "Gets dlna mediareceiverregistrar xml")] + [Route("/Dlna/{UuId}/mediareceiverregistrar/mediareceiverregistrar", "GET", Summary = "Gets dlna mediareceiverregistrar xml")] + public class GetMediaReceiverRegistrar + { + [ApiMember(Name = "UuId", Description = "Server UuId", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "GET")] + public string UuId { get; set; } } - [Route("/Dlna/contentdirectory/{UuId}/control", "POST", Summary = "Processes a control request")] + [Route("/Dlna/{UuId}/contentdirectory/control", "POST", Summary = "Processes a control request")] public class ProcessContentDirectoryControlRequest : IRequiresRequestStream { [ApiMember(Name = "UuId", Description = "Server UuId", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "GET")] @@ -40,7 +51,7 @@ namespace MediaBrowser.Api.Dlna public Stream RequestStream { get; set; } } - [Route("/Dlna/connectionmanager/{UuId}/control", "POST", Summary = "Processes a control request")] + [Route("/Dlna/{UuId}/connectionmanager/control", "POST", Summary = "Processes a control request")] public class ProcessConnectionManagerControlRequest : IRequiresRequestStream { [ApiMember(Name = "UuId", Description = "Server UuId", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "GET")] @@ -49,23 +60,43 @@ namespace MediaBrowser.Api.Dlna public Stream RequestStream { get; set; } } - [Route("/Dlna/contentdirectory/{UuId}/events", Summary = "Processes an event subscription request")] + [Route("/Dlna/{UuId}/mediareceiverregistrar/control", "POST", Summary = "Processes a control request")] + public class ProcessMediaReceiverRegistrarControlRequest : IRequiresRequestStream + { + [ApiMember(Name = "UuId", Description = "Server UuId", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "GET")] + public string UuId { get; set; } + + public Stream RequestStream { get; set; } + } + + [Route("/Dlna/{UuId}/mediareceiverregistrar/events", Summary = "Processes an event subscription request")] + public class ProcessMediaReceiverRegistrarEventRequest + { + [ApiMember(Name = "UuId", Description = "Server UuId", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "GET")] + public string UuId { get; set; } + } + + [Route("/Dlna/{UuId}/contentdirectory/events", Summary = "Processes an event subscription request")] public class ProcessContentDirectoryEventRequest { [ApiMember(Name = "UuId", Description = "Server UuId", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "GET")] public string UuId { get; set; } } - [Route("/Dlna/connectionmanager/{UuId}/events", Summary = "Processes an event subscription request")] + [Route("/Dlna/{UuId}/connectionmanager/events", Summary = "Processes an event subscription request")] public class ProcessConnectionManagerEventRequest { [ApiMember(Name = "UuId", Description = "Server UuId", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "GET")] public string UuId { get; set; } } + [Route("/Dlna/{UuId}/icons/{Filename}", "GET", Summary = "Gets a server icon")] [Route("/Dlna/icons/{Filename}", "GET", Summary = "Gets a server icon")] public class GetIcon { + [ApiMember(Name = "UuId", Description = "Server UuId", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "GET")] + public string UuId { get; set; } + [ApiMember(Name = "Filename", Description = "The icon filename", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] public string Filename { get; set; } } @@ -75,17 +106,21 @@ namespace MediaBrowser.Api.Dlna private readonly IDlnaManager _dlnaManager; private readonly IContentDirectory _contentDirectory; private readonly IConnectionManager _connectionManager; + private readonly IMediaReceiverRegistrar _mediaReceiverRegistrar; - public DlnaServerService(IDlnaManager dlnaManager, IContentDirectory contentDirectory, IConnectionManager connectionManager) + public DlnaServerService(IDlnaManager dlnaManager, IContentDirectory contentDirectory, IConnectionManager connectionManager, IMediaReceiverRegistrar mediaReceiverRegistrar) { _dlnaManager = dlnaManager; _contentDirectory = contentDirectory; _connectionManager = connectionManager; + _mediaReceiverRegistrar = mediaReceiverRegistrar; } public object Get(GetDescriptionXml request) { - var xml = _dlnaManager.GetServerDescriptionXml(GetRequestHeaders(), request.UuId); + var url = Request.AbsoluteUri; + var serverAddress = url.Substring(0, url.IndexOf("/dlna/", StringComparison.OrdinalIgnoreCase)); + var xml = _dlnaManager.GetServerDescriptionXml(GetRequestHeaders(), request.UuId, serverAddress); return ResultFactory.GetResult(xml, "text/xml"); } @@ -97,6 +132,13 @@ namespace MediaBrowser.Api.Dlna return ResultFactory.GetResult(xml, "text/xml"); } + public object Get(GetMediaReceiverRegistrar request) + { + var xml = _mediaReceiverRegistrar.GetServiceXml(GetRequestHeaders()); + + return ResultFactory.GetResult(xml, "text/xml"); + } + public object Get(GetConnnectionManager request) { var xml = _connectionManager.GetServiceXml(GetRequestHeaders()); @@ -104,6 +146,13 @@ namespace MediaBrowser.Api.Dlna return ResultFactory.GetResult(xml, "text/xml"); } + public async Task<object> Post(ProcessMediaReceiverRegistrarControlRequest request) + { + var response = await PostAsync(request.RequestStream, _mediaReceiverRegistrar).ConfigureAwait(false); + + return ResultFactory.GetResult(response.Xml, "text/xml"); + } + public async Task<object> Post(ProcessContentDirectoryControlRequest request) { var response = await PostAsync(request.RequestStream, _contentDirectory).ConfigureAwait(false); @@ -120,8 +169,7 @@ namespace MediaBrowser.Api.Dlna private async Task<ControlResponse> PostAsync(Stream requestStream, IUpnpService service) { - var pathInfo = PathInfo.Parse(Request.PathInfo); - var id = pathInfo.GetArgumentValue<string>(2); + var id = GetPathValue(2); using (var reader = new StreamReader(requestStream)) { @@ -172,6 +220,11 @@ namespace MediaBrowser.Api.Dlna return ProcessEventRequest(_connectionManager); } + public object Any(ProcessMediaReceiverRegistrarEventRequest request) + { + return ProcessEventRequest(_mediaReceiverRegistrar); + } + private object ProcessEventRequest(IEventManager eventManager) { var subscriptionId = GetHeader("SID"); diff --git a/MediaBrowser.Api/GamesService.cs b/MediaBrowser.Api/GamesService.cs index 9aba2b065..c18c32920 100644 --- a/MediaBrowser.Api/GamesService.cs +++ b/MediaBrowser.Api/GamesService.cs @@ -102,8 +102,8 @@ namespace MediaBrowser.Api /// <returns>System.Object.</returns> public object Get(GetGameSystemSummaries request) { - var gameSystems = GetAllLibraryItems(request.UserId, _userManager, _libraryManager) - .OfType<GameSystem>() + var gameSystems = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, null, i => i is GameSystem) + .Cast<GameSystem>() .ToList(); var user = request.UserId == null ? null : _userManager.GetUserById(request.UserId.Value); @@ -119,9 +119,8 @@ namespace MediaBrowser.Api public object Get(GetPlayerIndex request) { - var games = GetAllLibraryItems(request.UserId, _userManager, _libraryManager) - .OfType<Game>() - .ToList(); + var games = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, null, i => i is Game) + .Cast<Game>(); var lookup = games .ToLookup(i => i.PlayersSupported ?? -1) @@ -150,9 +149,11 @@ namespace MediaBrowser.Api DisplayName = system.Name }; - var items = user == null ? system.RecursiveChildren : system.GetRecursiveChildren(user); + var items = user == null ? + system.GetRecursiveChildren(i => i is Game) : + system.GetRecursiveChildren(user, i => i is Game); - var games = items.OfType<Game>().ToList(); + var games = items.Cast<Game>().ToList(); summary.ClientInstalledGameCount = games.Count(i => i.IsPlaceHolder); @@ -172,7 +173,9 @@ namespace MediaBrowser.Api /// <returns>System.Object.</returns> public object Get(GetSimilarGames request) { - var result = SimilarItemsHelper.GetSimilarItemsResult(_userManager, + var dtoOptions = GetDtoOptions(request); + + var result = SimilarItemsHelper.GetSimilarItemsResult(dtoOptions, _userManager, _itemRepo, _libraryManager, _userDataRepository, diff --git a/MediaBrowser.Api/IHasDtoOptions.cs b/MediaBrowser.Api/IHasDtoOptions.cs index 7fe47c4a1..dac366113 100644 --- a/MediaBrowser.Api/IHasDtoOptions.cs +++ b/MediaBrowser.Api/IHasDtoOptions.cs @@ -1,8 +1,4 @@ -using MediaBrowser.Controller.Dto; -using MediaBrowser.Model.Entities; -using System; -using System.Linq; - + namespace MediaBrowser.Api { public interface IHasDtoOptions : IHasItemFields @@ -13,27 +9,4 @@ namespace MediaBrowser.Api string EnableImageTypes { get; set; } } - - public static class HasDtoOptionsExtensions - { - public static DtoOptions GetDtoOptions(this IHasDtoOptions request) - { - var options = new DtoOptions(); - - options.Fields = request.GetItemFields().ToList(); - options.EnableImages = request.EnableImages ?? true; - - if (request.ImageTypeLimit.HasValue) - { - options.ImageTypeLimit = request.ImageTypeLimit.Value; - } - - if (!string.IsNullOrWhiteSpace(request.EnableImageTypes)) - { - options.ImageTypes = (request.EnableImageTypes ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).Select(v => (ImageType)Enum.Parse(typeof(ImageType), v, true)).ToList(); - } - - return options; - } - } } diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs index f2586b043..f141d9df9 100644 --- a/MediaBrowser.Api/Images/ImageService.cs +++ b/MediaBrowser.Api/Images/ImageService.cs @@ -396,8 +396,7 @@ namespace MediaBrowser.Api.Images public object Get(GetItemByNameImage request) { - var pathInfo = PathInfo.Parse(Request.PathInfo); - var type = pathInfo.GetArgumentValue<string>(0); + var type = GetPathValue(0); var item = GetItemByName(request.Name, type, _libraryManager); @@ -406,8 +405,7 @@ namespace MediaBrowser.Api.Images public object Head(GetItemByNameImage request) { - var pathInfo = PathInfo.Parse(Request.PathInfo); - var type = pathInfo.GetArgumentValue<string>(0); + var type = GetPathValue(0); var item = GetItemByName(request.Name, type, _libraryManager); @@ -420,10 +418,9 @@ namespace MediaBrowser.Api.Images /// <param name="request">The request.</param> public void Post(PostUserImage request) { - var pathInfo = PathInfo.Parse(Request.PathInfo); - var id = new Guid(pathInfo.GetArgumentValue<string>(1)); + var id = new Guid(GetPathValue(1)); - request.Type = (ImageType)Enum.Parse(typeof(ImageType), pathInfo.GetArgumentValue<string>(3), true); + request.Type = (ImageType)Enum.Parse(typeof(ImageType), GetPathValue(3), true); var item = _userManager.GetUserById(id); @@ -438,10 +435,9 @@ namespace MediaBrowser.Api.Images /// <param name="request">The request.</param> public void Post(PostItemImage request) { - var pathInfo = PathInfo.Parse(Request.PathInfo); - var id = new Guid(pathInfo.GetArgumentValue<string>(1)); + var id = new Guid(GetPathValue(1)); - request.Type = (ImageType)Enum.Parse(typeof(ImageType), pathInfo.GetArgumentValue<string>(3), true); + request.Type = (ImageType)Enum.Parse(typeof(ImageType), GetPathValue(3), true); var item = _libraryManager.GetItemById(id); diff --git a/MediaBrowser.Api/ItemLookupService.cs b/MediaBrowser.Api/ItemLookupService.cs index 9a97022b6..d6b4da8be 100644 --- a/MediaBrowser.Api/ItemLookupService.cs +++ b/MediaBrowser.Api/ItemLookupService.cs @@ -205,7 +205,8 @@ namespace MediaBrowser.Api Logger = Logger, Request = Request, ResultFactory = ResultFactory, - SessionContext = SessionContext + SessionContext = SessionContext, + AuthorizationContext = AuthorizationContext }; service.Post(new RefreshItem diff --git a/MediaBrowser.Api/ItemRefreshService.cs b/MediaBrowser.Api/ItemRefreshService.cs index 152a64c24..78bc14ab0 100644 --- a/MediaBrowser.Api/ItemRefreshService.cs +++ b/MediaBrowser.Api/ItemRefreshService.cs @@ -51,7 +51,7 @@ namespace MediaBrowser.Api var cancellationToken = CancellationToken.None; var albums = _libraryManager.RootFolder - .RecursiveChildren + .GetRecursiveChildren() .OfType<MusicAlbum>() .Where(i => i.HasArtist(item.Name)) .ToList(); diff --git a/MediaBrowser.Api/ItemUpdateService.cs b/MediaBrowser.Api/ItemUpdateService.cs index 98c259825..ea90afc3b 100644 --- a/MediaBrowser.Api/ItemUpdateService.cs +++ b/MediaBrowser.Api/ItemUpdateService.cs @@ -215,7 +215,7 @@ namespace MediaBrowser.Api { var folder = (Folder)item; - foreach (var child in folder.RecursiveChildren.ToList()) + foreach (var child in folder.GetRecursiveChildren()) { child.IsLocked = newLockData; await child.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); diff --git a/MediaBrowser.Api/Library/LibraryHelpers.cs b/MediaBrowser.Api/Library/LibraryHelpers.cs index e21dc4a73..0ee28d6fe 100644 --- a/MediaBrowser.Api/Library/LibraryHelpers.cs +++ b/MediaBrowser.Api/Library/LibraryHelpers.cs @@ -42,7 +42,7 @@ namespace MediaBrowser.Api.Library if (!string.IsNullOrEmpty(shortcut)) { - File.Delete(shortcut); + fileSystem.DeleteFile(shortcut); } } diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs index 5e1619672..f147234fe 100644 --- a/MediaBrowser.Api/Library/LibraryService.cs +++ b/MediaBrowser.Api/Library/LibraryService.cs @@ -272,7 +272,7 @@ namespace MediaBrowser.Api.Library items = items.Where(i => i.IsHidden == val).ToList(); } - var dtoOptions = new DtoOptions(); + var dtoOptions = GetDtoOptions(request); var result = new ItemsResult { @@ -344,7 +344,7 @@ namespace MediaBrowser.Api.Library var user = request.UserId.HasValue ? _userManager.GetUserById(request.UserId.Value) : null; - var dtoOptions = new DtoOptions(); + var dtoOptions = GetDtoOptions(request); BaseItem parent = item.Parent; @@ -392,52 +392,43 @@ namespace MediaBrowser.Api.Library /// <returns>System.Object.</returns> public object Get(GetItemCounts request) { - var items = GetAllLibraryItems(request.UserId, _userManager, _libraryManager) - .Where(i => i.LocationType != LocationType.Virtual) - .ToList(); - - var filteredItems = request.UserId.HasValue ? FilterItems(items, request, request.UserId.Value).ToList() : items; - - var albums = filteredItems.OfType<MusicAlbum>().ToList(); - var episodes = filteredItems.OfType<Episode>().ToList(); - var games = filteredItems.OfType<Game>().ToList(); - var movies = filteredItems.OfType<Movie>().ToList(); - var musicVideos = filteredItems.OfType<MusicVideo>().ToList(); - var boxsets = filteredItems.OfType<BoxSet>().ToList(); - var books = filteredItems.OfType<Book>().ToList(); - var songs = filteredItems.OfType<Audio>().ToList(); - var series = filteredItems.OfType<Series>().ToList(); + var filteredItems = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, null, i => i.LocationType != LocationType.Virtual && FilterItem(i, request, request.UserId)); var counts = new ItemCounts { - AlbumCount = albums.Count, - EpisodeCount = episodes.Count, - GameCount = games.Count, - GameSystemCount = filteredItems.OfType<GameSystem>().Count(), - MovieCount = movies.Count, - SeriesCount = series.Count, - SongCount = songs.Count, - MusicVideoCount = musicVideos.Count, - BoxSetCount = boxsets.Count, - BookCount = books.Count, - - UniqueTypes = items.Select(i => i.GetClientTypeName()).Distinct().ToList() + AlbumCount = filteredItems.Count(i => i is MusicAlbum), + EpisodeCount = filteredItems.Count(i => i is Episode), + GameCount = filteredItems.Count(i => i is Game), + GameSystemCount = filteredItems.Count(i => i is GameSystem), + MovieCount = filteredItems.Count(i => i is Movie), + SeriesCount = filteredItems.Count(i => i is Series), + SongCount = filteredItems.Count(i => i is Audio), + MusicVideoCount = filteredItems.Count(i => i is MusicVideo), + BoxSetCount = filteredItems.Count(i => i is BoxSet), + BookCount = filteredItems.Count(i => i is Book), + + UniqueTypes = filteredItems.Select(i => i.GetClientTypeName()).Distinct().ToList() }; return ToOptimizedSerializedResultUsingCache(counts); } - private IEnumerable<T> FilterItems<T>(IEnumerable<T> items, GetItemCounts request, Guid userId) - where T : BaseItem + private bool FilterItem(BaseItem item, GetItemCounts request, Guid? userId) { - if (request.IsFavorite.HasValue) + if (userId.HasValue) { - var val = request.IsFavorite.Value; + if (request.IsFavorite.HasValue) + { + var val = request.IsFavorite.Value; - items = items.Where(i => _userDataManager.GetUserData(userId, i.GetUserDataKey()).IsFavorite == val); + if (_userDataManager.GetUserData(userId.Value, item.GetUserDataKey()).IsFavorite != val) + { + return false; + } + } } - return items; + return true; } /// <summary> @@ -544,7 +535,7 @@ namespace MediaBrowser.Api.Library ThemeSongsResult = themeSongs, ThemeVideosResult = themeVideos, - SoundtrackSongsResult = GetSoundtrackSongs(request.Id, request.UserId, request.InheritFromParent) + SoundtrackSongsResult = GetSoundtrackSongs(request, request.Id, request.UserId, request.InheritFromParent) }); } @@ -597,7 +588,7 @@ namespace MediaBrowser.Api.Library } } - var dtoOptions = new DtoOptions(); + var dtoOptions = GetDtoOptions(request); var dtos = themeSongIds.Select(_libraryManager.GetItemById) .OrderBy(i => i.SortName) @@ -667,7 +658,7 @@ namespace MediaBrowser.Api.Library } } - var dtoOptions = new DtoOptions(); + var dtoOptions = GetDtoOptions(request); var dtos = themeVideoIds.Select(_libraryManager.GetItemById) .OrderBy(i => i.SortName) @@ -711,13 +702,24 @@ namespace MediaBrowser.Api.Library public object Get(GetYearIndex request) { - IEnumerable<BaseItem> items = GetAllLibraryItems(request.UserId, _userManager, _libraryManager); + var includeTypes = string.IsNullOrWhiteSpace(request.IncludeItemTypes) + ? new string[] { } + : request.IncludeItemTypes.Split(','); - if (!string.IsNullOrEmpty(request.IncludeItemTypes)) + Func<BaseItem, bool> filter = i => { - var vals = request.IncludeItemTypes.Split(','); - items = items.Where(f => vals.Contains(f.GetType().Name, StringComparer.OrdinalIgnoreCase)); - } + if (includeTypes.Length > 0) + { + if (!includeTypes.Contains(i.GetType().Name, StringComparer.OrdinalIgnoreCase)) + { + return false; + } + } + + return true; + }; + + IEnumerable<BaseItem> items = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, null, filter); var lookup = items .ToLookup(i => i.ProductionYear ?? -1) @@ -732,23 +734,22 @@ namespace MediaBrowser.Api.Library return ToOptimizedSerializedResultUsingCache(lookup); } - public ThemeMediaResult GetSoundtrackSongs(string id, Guid? userId, bool inheritFromParent) + public ThemeMediaResult GetSoundtrackSongs(GetThemeMedia request, string id, Guid? userId, bool inheritFromParent) { var user = userId.HasValue ? _userManager.GetUserById(userId.Value) : null; var item = string.IsNullOrEmpty(id) ? (userId.HasValue ? user.RootFolder - : (Folder)_libraryManager.RootFolder) + : _libraryManager.RootFolder) : _libraryManager.GetItemById(id); - var dtoOptions = new DtoOptions(); + var dtoOptions = GetDtoOptions(request); var dtos = GetSoundtrackSongIds(item, inheritFromParent) .Select(_libraryManager.GetItemById) .OfType<MusicAlbum>() - .SelectMany(i => i.RecursiveChildren) - .OfType<Audio>() + .SelectMany(i => i.GetRecursiveChildren(a => a is Audio)) .OrderBy(i => i.SortName) .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item)); diff --git a/MediaBrowser.Api/Library/LibraryStructureService.cs b/MediaBrowser.Api/Library/LibraryStructureService.cs index ee80d4b73..27944a4ea 100644 --- a/MediaBrowser.Api/Library/LibraryStructureService.cs +++ b/MediaBrowser.Api/Library/LibraryStructureService.cs @@ -3,7 +3,6 @@ using MediaBrowser.Controller; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; using ServiceStack; using System; using System.Collections.Generic; @@ -18,7 +17,6 @@ namespace MediaBrowser.Api.Library /// Class GetDefaultVirtualFolders /// </summary> [Route("/Library/VirtualFolders", "GET")] - [Route("/Users/{UserId}/VirtualFolders", "GET")] public class GetVirtualFolders : IReturn<List<VirtualFolderInfo>> { /// <summary> @@ -144,11 +142,6 @@ namespace MediaBrowser.Api.Library private readonly IServerApplicationPaths _appPaths; /// <summary> - /// The _user manager - /// </summary> - private readonly IUserManager _userManager; - - /// <summary> /// The _library manager /// </summary> private readonly ILibraryManager _libraryManager; @@ -156,27 +149,21 @@ namespace MediaBrowser.Api.Library private readonly ILibraryMonitor _libraryMonitor; private readonly IFileSystem _fileSystem; - private readonly ILogger _logger; /// <summary> - /// Initializes a new instance of the <see cref="LibraryStructureService"/> class. + /// Initializes a new instance of the <see cref="LibraryStructureService" /> class. /// </summary> - /// <param name="appPaths">The app paths.</param> - /// <param name="userManager">The user manager.</param> - /// <param name="libraryManager">The library manager.</param> - public LibraryStructureService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, ILibraryMonitor libraryMonitor, IFileSystem fileSystem, ILogger logger) + public LibraryStructureService(IServerApplicationPaths appPaths, ILibraryManager libraryManager, ILibraryMonitor libraryMonitor, IFileSystem fileSystem) { if (appPaths == null) { throw new ArgumentNullException("appPaths"); } - _userManager = userManager; _appPaths = appPaths; _libraryManager = libraryManager; _libraryMonitor = libraryMonitor; _fileSystem = fileSystem; - _logger = logger; } /// <summary> @@ -186,20 +173,9 @@ namespace MediaBrowser.Api.Library /// <returns>System.Object.</returns> public object Get(GetVirtualFolders request) { - if (string.IsNullOrEmpty(request.UserId)) - { - var result = _libraryManager.GetDefaultVirtualFolders().OrderBy(i => i.Name).ToList(); + var result = _libraryManager.GetVirtualFolders().OrderBy(i => i.Name).ToList(); - return ToOptimizedSerializedResultUsingCache(result); - } - else - { - var user = _userManager.GetUserById(request.UserId); - - var result = _libraryManager.GetVirtualFolders(user).OrderBy(i => i.Name).ToList(); - - return ToOptimizedSerializedResultUsingCache(result); - } + return ToOptimizedSerializedResultUsingCache(result); } /// <summary> @@ -348,7 +324,7 @@ namespace MediaBrowser.Api.Library try { - Directory.Delete(path, true); + _fileSystem.DeleteDirectory(path, true); // Need to add a delay here or directory watchers may still pick up the changes var delayTask = Task.Delay(1000); diff --git a/MediaBrowser.Api/Movies/CollectionService.cs b/MediaBrowser.Api/Movies/CollectionService.cs index 97c6cd87d..e6277e39a 100644 --- a/MediaBrowser.Api/Movies/CollectionService.cs +++ b/MediaBrowser.Api/Movies/CollectionService.cs @@ -71,7 +71,7 @@ namespace MediaBrowser.Api.Movies }).ConfigureAwait(false); - var dtoOptions = new DtoOptions(); + var dtoOptions = GetDtoOptions(request); var dto = _dtoService.GetBaseItemDto(item, dtoOptions); diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs index ba3c15a90..07f5942c6 100644 --- a/MediaBrowser.Api/Movies/MoviesService.cs +++ b/MediaBrowser.Api/Movies/MoviesService.cs @@ -121,8 +121,7 @@ namespace MediaBrowser.Api.Movies { var user = _userManager.GetUserById(request.UserId.Value); - var movies = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, request.ParentId) - .Where(i => i is Movie); + IEnumerable<BaseItem> movies = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, request.ParentId, i => i is Movie); movies = _libraryManager.ReplaceVideosWithPrimaryVersions(movies); @@ -157,7 +156,7 @@ namespace MediaBrowser.Api.Movies .DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString(), StringComparer.OrdinalIgnoreCase) .ToList(); - var dtoOptions = new DtoOptions(); + var dtoOptions = GetDtoOptions(request); dtoOptions.Fields = request.GetItemFields().ToList(); @@ -174,13 +173,11 @@ namespace MediaBrowser.Api.Movies (request.UserId.HasValue ? user.RootFolder : _libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id); - var fields = request.GetItemFields().ToList(); - + Func<BaseItem, bool> filter = i => i.Id != item.Id && includeInSearch(i); + var inputItems = user == null - ? _libraryManager.RootFolder.GetRecursiveChildren().Where(i => i.Id != item.Id) - : user.RootFolder.GetRecursiveChildren(user).Where(i => i.Id != item.Id); - - inputItems = inputItems.Where(includeInSearch); + ? _libraryManager.RootFolder.GetRecursiveChildren(filter) + : user.RootFolder.GetRecursiveChildren(user, filter); var list = inputItems.ToList(); @@ -225,10 +222,12 @@ namespace MediaBrowser.Api.Movies { returnItems = returnItems.Take(request.Limit.Value); } + + var dtoOptions = GetDtoOptions(request); var result = new ItemsResult { - Items = returnItems.Select(i => _dtoService.GetBaseItemDto(i, fields, user)).ToArray(), + Items = _dtoService.GetBaseItemDtos(returnItems, dtoOptions, user).ToArray(), TotalRecordCount = items.Count }; @@ -351,7 +350,7 @@ namespace MediaBrowser.Api.Movies BaselineItemName = director, CategoryId = director.GetMD5().ToString("N"), RecommendationType = type, - Items = items.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user)).ToArray() + Items = _dtoService.GetBaseItemDtos(items, dtoOptions, user).ToArray() }; } } @@ -375,7 +374,7 @@ namespace MediaBrowser.Api.Movies BaselineItemName = name, CategoryId = name.GetMD5().ToString("N"), RecommendationType = type, - Items = items.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user)).ToArray() + Items = _dtoService.GetBaseItemDtos(items, dtoOptions, user).ToArray() }; } } @@ -399,7 +398,7 @@ namespace MediaBrowser.Api.Movies BaselineItemName = item.Name, CategoryId = item.Id.ToString("N"), RecommendationType = type, - Items = similar.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user)).ToArray() + Items = _dtoService.GetBaseItemDtos(similar, dtoOptions, user).ToArray() }; } } diff --git a/MediaBrowser.Api/Movies/TrailersService.cs b/MediaBrowser.Api/Movies/TrailersService.cs index 8e1704af7..3bee59a86 100644 --- a/MediaBrowser.Api/Movies/TrailersService.cs +++ b/MediaBrowser.Api/Movies/TrailersService.cs @@ -84,7 +84,9 @@ namespace MediaBrowser.Api.Movies /// <returns>System.Object.</returns> public object Get(GetSimilarTrailers request) { - var result = SimilarItemsHelper.GetSimilarItemsResult(_userManager, + var dtoOptions = GetDtoOptions(request); + + var result = SimilarItemsHelper.GetSimilarItemsResult(dtoOptions, _userManager, _itemRepo, _libraryManager, _userDataRepository, @@ -119,9 +121,9 @@ namespace MediaBrowser.Api.Movies var pagedItems = ApplyPaging(request, itemsArray); - var fields = request.GetItemFields().ToList(); + var dtoOptions = GetDtoOptions(request); - var returnItems = pagedItems.Select(i => _dtoService.GetBaseItemDto(i, fields, user)).ToArray(); + var returnItems = _dtoService.GetBaseItemDtos(pagedItems, dtoOptions, user).ToArray(); return new ItemsResult { diff --git a/MediaBrowser.Api/Music/AlbumsService.cs b/MediaBrowser.Api/Music/AlbumsService.cs index 34a933dee..76c6c5776 100644 --- a/MediaBrowser.Api/Music/AlbumsService.cs +++ b/MediaBrowser.Api/Music/AlbumsService.cs @@ -50,7 +50,9 @@ namespace MediaBrowser.Api.Music /// <returns>System.Object.</returns> public object Get(GetSimilarAlbums request) { - var result = SimilarItemsHelper.GetSimilarItemsResult(_userManager, + var dtoOptions = GetDtoOptions(request); + + var result = SimilarItemsHelper.GetSimilarItemsResult(dtoOptions, _userManager, _itemRepo, _libraryManager, _userDataRepository, @@ -75,14 +77,14 @@ namespace MediaBrowser.Api.Music var album1 = (MusicAlbum)item1; var album2 = (MusicAlbum)item2; - var artists1 = album1.GetRecursiveChildren() - .OfType<Audio>() + var artists1 = album1.GetRecursiveChildren(i => i is IHasArtist) + .Cast<IHasArtist>() .SelectMany(i => i.AllArtists) .Distinct(StringComparer.OrdinalIgnoreCase) .ToList(); - var artists2 = album2.GetRecursiveChildren() - .OfType<Audio>() + var artists2 = album2.GetRecursiveChildren(i => i is IHasArtist) + .Cast<IHasArtist>() .SelectMany(i => i.AllArtists) .Distinct(StringComparer.OrdinalIgnoreCase) .ToDictionary(i => i, StringComparer.OrdinalIgnoreCase); diff --git a/MediaBrowser.Api/Music/InstantMixService.cs b/MediaBrowser.Api/Music/InstantMixService.cs index 43fd0894b..78c6a8bf4 100644 --- a/MediaBrowser.Api/Music/InstantMixService.cs +++ b/MediaBrowser.Api/Music/InstantMixService.cs @@ -73,44 +73,44 @@ namespace MediaBrowser.Api.Music public object Get(GetInstantMixFromArtistId request) { - var item = (MusicArtist)_libraryManager.GetItemById(request.Id); + var item = _libraryManager.GetItemById(request.Id); var user = _userManager.GetUserById(request.UserId.Value); - var items = _musicManager.GetInstantMixFromArtist(item.Name, user); + var items = _musicManager.GetInstantMixFromItem(item, user); return GetResult(items, user, request); } public object Get(GetInstantMixFromMusicGenreId request) { - var item = (MusicGenre)_libraryManager.GetItemById(request.Id); + var item = _libraryManager.GetItemById(request.Id); var user = _userManager.GetUserById(request.UserId.Value); - var items = _musicManager.GetInstantMixFromGenres(new[] { item.Name }, user); + var items = _musicManager.GetInstantMixFromItem(item, user); return GetResult(items, user, request); } public object Get(GetInstantMixFromSong request) { - var item = (Audio)_libraryManager.GetItemById(request.Id); + var item = _libraryManager.GetItemById(request.Id); var user = _userManager.GetUserById(request.UserId.Value); - var items = _musicManager.GetInstantMixFromSong(item, user); + var items = _musicManager.GetInstantMixFromItem(item, user); return GetResult(items, user, request); } public object Get(GetInstantMixFromAlbum request) { - var album = (MusicAlbum)_libraryManager.GetItemById(request.Id); + var album = _libraryManager.GetItemById(request.Id); var user = _userManager.GetUserById(request.UserId.Value); - var items = _musicManager.GetInstantMixFromAlbum(album, user); + var items = _musicManager.GetInstantMixFromItem(album, user); return GetResult(items, user, request); } @@ -121,7 +121,7 @@ namespace MediaBrowser.Api.Music var user = _userManager.GetUserById(request.UserId.Value); - var items = _musicManager.GetInstantMixFromPlaylist(playlist, user); + var items = _musicManager.GetInstantMixFromItem(playlist, user); return GetResult(items, user, request); } @@ -146,8 +146,6 @@ namespace MediaBrowser.Api.Music private object GetResult(IEnumerable<Audio> items, User user, BaseGetSimilarItems request) { - var fields = request.GetItemFields().ToList(); - var list = items.ToList(); var result = new ItemsResult @@ -155,10 +153,9 @@ namespace MediaBrowser.Api.Music TotalRecordCount = list.Count }; - var dtos = list.Take(request.Limit ?? list.Count) - .Select(i => _dtoService.GetBaseItemDto(i, fields, user)); + var dtoOptions = GetDtoOptions(request); - result.Items = dtos.ToArray(); + result.Items = _dtoService.GetBaseItemDtos(list.Take(request.Limit ?? list.Count), dtoOptions, user).ToArray(); return ToOptimizedResult(result); } diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 034f5c56b..b3610bc38 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller.Devices; +using MediaBrowser.Model.Extensions; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.IO; using MediaBrowser.Controller.Channels; @@ -66,14 +67,16 @@ namespace MediaBrowser.Api.Playback protected ILiveTvManager LiveTvManager { get; private set; } protected IDlnaManager DlnaManager { get; private set; } + protected IDeviceManager DeviceManager { get; private set; } protected IChannelManager ChannelManager { get; private set; } protected ISubtitleEncoder SubtitleEncoder { get; private set; } /// <summary> /// Initializes a new instance of the <see cref="BaseStreamingService" /> class. /// </summary> - protected BaseStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder) + protected BaseStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager) { + DeviceManager = deviceManager; SubtitleEncoder = subtitleEncoder; ChannelManager = channelManager; DlnaManager = dlnaManager; @@ -119,7 +122,7 @@ namespace MediaBrowser.Api.Playback /// <returns>System.String.</returns> private string GetOutputFilePath(StreamState state) { - var folder = Path.Combine(ServerConfigurationManager.ApplicationPaths.TranscodingTempPath, EncodingContext.Streaming.ToString().ToLower()); + var folder = ServerConfigurationManager.ApplicationPaths.TranscodingTempPath; var outputFileExtension = GetOutputFileExtension(state); @@ -349,6 +352,24 @@ namespace MediaBrowser.Api.Playback } } + // h264 (h264_qsv) + else if (string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase)) + { + switch (qualitySetting) + { + case EncodingQuality.HighSpeed: + param = "-preset 7"; + break; + case EncodingQuality.HighQuality: + param = "-preset 4"; + break; + case EncodingQuality.MaxQuality: + param = "-preset 1"; + break; + } + + } + // webm else if (string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase)) { @@ -567,6 +588,11 @@ namespace MediaBrowser.Api.Playback } } + if (string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase)) + { + filters[filters.Count - 1] += ":flags=fast_bilinear"; + } + var output = string.Empty; if (state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream) @@ -606,7 +632,7 @@ namespace MediaBrowser.Api.Playback if (!string.IsNullOrEmpty(state.SubtitleStream.Language)) { - var charenc = SubtitleEncoder.GetSubtitleFileCharacterSet(subtitlePath, state.SubtitleStream.Language); + var charenc = SubtitleEncoder.GetSubtitleFileCharacterSet(subtitlePath); if (!string.IsNullOrEmpty(charenc)) { @@ -834,8 +860,8 @@ namespace MediaBrowser.Api.Playback { if (SupportsThrottleWithStream) { - var url = "http://localhost:" + ServerConfigurationManager.Configuration.HttpServerPortNumber.ToString(UsCulture) + "/mediabrowser/videos/" + state.Request.Id + "/stream?static=true&Throttle=true&mediaSourceId=" + state.Request.MediaSourceId; - + var url = "http://localhost:" + ServerConfigurationManager.Configuration.HttpServerPortNumber.ToString(UsCulture) + "/videos/" + state.Request.Id + "/stream?static=true&Throttle=true&mediaSourceId=" + state.Request.MediaSourceId; + url += "&transcodingJobId=" + transcodingJobId; return string.Format("\"{0}\"", url); @@ -1183,6 +1209,22 @@ namespace MediaBrowser.Api.Playback return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture)); } + // h264_qsv + if (string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase)) + { + if (hasFixedResolution) + { + if (isHls) + { + return string.Format(" -b:v {0} -maxrate ({0}*.80) -bufsize {0}", bitrate.Value.ToString(UsCulture)); + } + + return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture)); + } + + return string.Format(" -b:v {0} -maxrate ({0}*1.2) -bufsize ({0}*2)", bitrate.Value.ToString(UsCulture)); + } + // H264 if (hasFixedResolution) { @@ -1991,9 +2033,26 @@ namespace MediaBrowser.Api.Playback headers[key] = Request.Headers[key]; } - state.DeviceProfile = string.IsNullOrWhiteSpace(state.Request.DeviceProfileId) ? - DlnaManager.GetProfile(headers) : - DlnaManager.GetProfile(state.Request.DeviceProfileId); + if (!string.IsNullOrWhiteSpace(state.Request.DeviceProfileId)) + { + state.DeviceProfile = DlnaManager.GetProfile(state.Request.DeviceProfileId); + } + else + { + if (!string.IsNullOrWhiteSpace(state.Request.DeviceId)) + { + var caps = DeviceManager.GetCapabilities(state.Request.DeviceId); + + if (caps != null) + { + state.DeviceProfile = caps.DeviceProfile; + } + else + { + state.DeviceProfile = DlnaManager.GetProfile(headers); + } + } + } var profile = state.DeviceProfile; diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index 8a33a88f2..2da5c33ce 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -1,20 +1,20 @@ -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.IO; -using MediaBrowser.Common.Net; +using MediaBrowser.Common.IO; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.MediaEncoding; +using MediaBrowser.Model.Extensions; using MediaBrowser.Model.IO; +using MediaBrowser.Model.Net; using System; using System.Collections.Generic; using System.IO; using System.Text; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Model.Net; namespace MediaBrowser.Api.Playback.Hls { @@ -23,8 +23,7 @@ namespace MediaBrowser.Api.Playback.Hls /// </summary> public abstract class BaseHlsService : BaseStreamingService { - protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder) - : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder) + protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder, deviceManager) { } diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index 86866bdf5..e639dbdfe 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Common.Extensions; +using MediaBrowser.Controller.Devices; +using MediaBrowser.Model.Extensions; using MediaBrowser.Common.IO; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Channels; @@ -62,38 +63,31 @@ namespace MediaBrowser.Api.Playback.Hls public class DynamicHlsService : BaseHlsService { - protected INetworkManager NetworkManager { get; private set; } - - public DynamicHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, INetworkManager networkManager) - : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder) + public DynamicHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, INetworkManager networkManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder, deviceManager) { NetworkManager = networkManager; } - public object Get(GetMasterHlsVideoStream request) - { - var result = GetAsync(request, "GET").Result; + protected INetworkManager NetworkManager { get; private set; } - return result; + public Task<object> Get(GetMasterHlsVideoStream request) + { + return GetAsync(request, "GET"); } - public object Head(GetMasterHlsVideoStream request) + public Task<object> Head(GetMasterHlsVideoStream request) { - var result = GetAsync(request, "HEAD").Result; - - return result; + return GetAsync(request, "HEAD"); } - public object Get(GetMainHlsVideoStream request) + public Task<object> Get(GetMainHlsVideoStream request) { - var result = GetPlaylistAsync(request, "main").Result; - - return result; + return GetPlaylistAsync(request, "main"); } - public object Get(GetDynamicHlsVideoSegment request) + public Task<object> Get(GetDynamicHlsVideoSegment request) { - return GetDynamicSegment(request, request.SegmentId).Result; + return GetDynamicSegment(request, request.SegmentId); } private async Task<object> GetDynamicSegment(VideoStreamRequest request, string segmentId) @@ -210,10 +204,10 @@ namespace MediaBrowser.Api.Playback.Hls { return; } - + try { - File.Delete(file.FullName); + FileSystem.DeleteFile(file.FullName); } catch (IOException ex) { diff --git a/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs b/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs index 14045b3a5..9f80fcd0a 100644 --- a/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs +++ b/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs @@ -1,10 +1,6 @@ using MediaBrowser.Controller; -using MediaBrowser.Model.Dlna; using ServiceStack; -using System; using System.IO; -using System.Linq; -using System.Threading.Tasks; namespace MediaBrowser.Api.Playback.Hls { @@ -66,7 +62,7 @@ namespace MediaBrowser.Api.Playback.Hls { var file = request.PlaylistId + Path.GetExtension(Request.PathInfo); - file = Path.Combine(_appPaths.TranscodingTempPath, EncodingContext.Streaming.ToString().ToLower(), file); + file = Path.Combine(_appPaths.TranscodingTempPath, file); return ResultFactory.GetStaticFileResult(Request, file, FileShare.ReadWrite); } @@ -85,7 +81,7 @@ namespace MediaBrowser.Api.Playback.Hls { var file = request.SegmentId + Path.GetExtension(Request.PathInfo); - file = Path.Combine(_appPaths.TranscodingTempPath, EncodingContext.Streaming.ToString().ToLower(), file); + file = Path.Combine(_appPaths.TranscodingTempPath, file); return ResultFactory.GetStaticFileResult(Request, file, FileShare.ReadWrite); } diff --git a/MediaBrowser.Api/Playback/Hls/MpegDashService.cs b/MediaBrowser.Api/Playback/Hls/MpegDashService.cs index 87e2eedcf..80451c0cc 100644 --- a/MediaBrowser.Api/Playback/Hls/MpegDashService.cs +++ b/MediaBrowser.Api/Playback/Hls/MpegDashService.cs @@ -2,6 +2,7 @@ using MediaBrowser.Common.Net; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; @@ -50,14 +51,13 @@ namespace MediaBrowser.Api.Playback.Hls public class MpegDashService : BaseHlsService { - protected INetworkManager NetworkManager { get; private set; } - - public MpegDashService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, INetworkManager networkManager) - : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder) + public MpegDashService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, INetworkManager networkManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder, deviceManager) { NetworkManager = networkManager; } + protected INetworkManager NetworkManager { get; private set; } + public object Get(GetMasterManifest request) { var result = GetAsync(request, "GET").Result; @@ -489,7 +489,7 @@ namespace MediaBrowser.Api.Playback.Hls { try { - File.Delete(file.FullName); + FileSystem.DeleteFile(file.FullName); } catch (IOException ex) { @@ -625,7 +625,7 @@ namespace MediaBrowser.Api.Playback.Hls protected override string GetCommandLineArguments(string outputPath, string transcodingJobId, StreamState state, bool isEncoding) { - // test url http://192.168.1.2:8096/mediabrowser/videos/233e8905d559a8f230db9bffd2ac9d6d/master.mpd?mediasourceid=233e8905d559a8f230db9bffd2ac9d6d&videocodec=h264&audiocodec=aac&maxwidth=1280&videobitrate=500000&audiobitrate=128000&profile=baseline&level=3 + // test url http://192.168.1.2:8096/videos/233e8905d559a8f230db9bffd2ac9d6d/master.mpd?mediasourceid=233e8905d559a8f230db9bffd2ac9d6d&videocodec=h264&audiocodec=aac&maxwidth=1280&videobitrate=500000&audiobitrate=128000&profile=baseline&level=3 // Good info on i-frames http://blog.streamroot.io/encode-multi-bitrate-videos-mpeg-dash-mse-based-media-players/ var threads = GetNumberOfThreads(state, false); diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs index d786b51b3..8de52ea02 100644 --- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs @@ -1,11 +1,11 @@ using MediaBrowser.Common.IO; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Model.Dlna; using MediaBrowser.Model.IO; using ServiceStack; using System; @@ -57,8 +57,7 @@ namespace MediaBrowser.Api.Playback.Hls /// </summary> public class VideoHlsService : BaseHlsService { - public VideoHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder) - : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder) + public VideoHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder, deviceManager) { } @@ -71,7 +70,7 @@ namespace MediaBrowser.Api.Playback.Hls { var file = request.SegmentId + Path.GetExtension(Request.PathInfo); - file = Path.Combine(ServerConfigurationManager.ApplicationPaths.TranscodingTempPath, EncodingContext.Streaming.ToString().ToLower(), file); + file = Path.Combine(ServerConfigurationManager.ApplicationPaths.TranscodingTempPath, file); return ResultFactory.GetStaticFileResult(Request, file); } diff --git a/MediaBrowser.Api/Playback/Progressive/AudioService.cs b/MediaBrowser.Api/Playback/Progressive/AudioService.cs index 725526ecd..37155b8f9 100644 --- a/MediaBrowser.Api/Playback/Progressive/AudioService.cs +++ b/MediaBrowser.Api/Playback/Progressive/AudioService.cs @@ -2,6 +2,7 @@ using MediaBrowser.Common.Net; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Library; @@ -31,7 +32,7 @@ namespace MediaBrowser.Api.Playback.Progressive /// </summary> public class AudioService : BaseProgressiveStreamingService { - public AudioService(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, httpClient) + public AudioService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder, deviceManager, imageProcessor, httpClient) { } diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs index 6bec387d4..9dbe3389e 100644 --- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs +++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs @@ -1,8 +1,8 @@ -using System.Linq; -using MediaBrowser.Common.IO; +using MediaBrowser.Common.IO; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Library; @@ -15,6 +15,7 @@ using ServiceStack.Web; using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -28,8 +29,7 @@ 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, IDeviceManager deviceManager, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder, deviceManager) { ImageProcessor = imageProcessor; HttpClient = httpClient; diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs index 5ef72a495..8924bb38f 100644 --- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs +++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs @@ -2,6 +2,7 @@ using MediaBrowser.Common.IO; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Library; @@ -62,7 +63,7 @@ namespace MediaBrowser.Api.Playback.Progressive /// </summary> public class VideoService : BaseProgressiveStreamingService { - public VideoService(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, httpClient) + public VideoService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder, deviceManager, imageProcessor, httpClient) { } diff --git a/MediaBrowser.Api/Playback/StaticRemoteStreamWriter.cs b/MediaBrowser.Api/Playback/StaticRemoteStreamWriter.cs index ada2a98a1..fc94d070a 100644 --- a/MediaBrowser.Api/Playback/StaticRemoteStreamWriter.cs +++ b/MediaBrowser.Api/Playback/StaticRemoteStreamWriter.cs @@ -40,7 +40,10 @@ namespace MediaBrowser.Api.Playback /// <param name="responseStream">The response stream.</param> public void WriteTo(Stream responseStream) { - _response.Content.CopyTo(responseStream, 819200); + using (_response) + { + _response.Content.CopyTo(responseStream, 819200); + } } } } diff --git a/MediaBrowser.Api/PlaylistService.cs b/MediaBrowser.Api/PlaylistService.cs index 7f7717f71..e16ca1ee8 100644 --- a/MediaBrowser.Api/PlaylistService.cs +++ b/MediaBrowser.Api/PlaylistService.cs @@ -151,9 +151,10 @@ namespace MediaBrowser.Api { items = items.Take(request.Limit.Value).ToArray(); } - - var dtos = items - .Select(i => _dtoService.GetBaseItemDto(i.Item2, request.GetItemFields().ToList(), user)) + + var dtoOptions = GetDtoOptions(request); + + var dtos = _dtoService.GetBaseItemDtos(items.Select(i => i.Item2), dtoOptions, user) .ToArray(); var index = 0; diff --git a/MediaBrowser.Api/PluginService.cs b/MediaBrowser.Api/PluginService.cs index 62aa1e755..f9098f5bf 100644 --- a/MediaBrowser.Api/PluginService.cs +++ b/MediaBrowser.Api/PluginService.cs @@ -236,8 +236,7 @@ namespace MediaBrowser.Api { // We need to parse this manually because we told service stack not to with IRequiresRequestStream // https://code.google.com/p/servicestack/source/browse/trunk/Common/ServiceStack.Text/ServiceStack.Text/Controller/PathInfo.cs - var pathInfo = PathInfo.Parse(Request.PathInfo); - var id = new Guid(pathInfo.GetArgumentValue<string>(1)); + var id = new Guid(GetPathValue(1)); var plugin = _appHost.Plugins.First(p => p.Id == id); diff --git a/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs b/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs index a05be024e..e3722b4a7 100644 --- a/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs +++ b/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs @@ -32,6 +32,9 @@ namespace MediaBrowser.Api.ScheduledTasks { [ApiMember(Name = "IsHidden", Description = "Optional filter tasks that are hidden, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] public bool? IsHidden { get; set; } + + [ApiMember(Name = "IsEnabled", Description = "Optional filter tasks that are enabled, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] + public bool? IsEnabled { get; set; } } /// <summary> @@ -132,6 +135,25 @@ namespace MediaBrowser.Api.ScheduledTasks }); } + if (request.IsEnabled.HasValue) + { + var val = request.IsEnabled.Value; + + result = result.Where(i => + { + var isEnabled = true; + + var configurableTask = i.ScheduledTask as IConfigurableScheduledTask; + + if (configurableTask != null) + { + isEnabled = configurableTask.IsEnabled; + } + + return isEnabled == val; + }); + } + var infos = result .Select(ScheduledTaskHelpers.GetTaskInfo) .ToList(); @@ -202,8 +224,7 @@ namespace MediaBrowser.Api.ScheduledTasks { // We need to parse this manually because we told service stack not to with IRequiresRequestStream // https://code.google.com/p/servicestack/source/browse/trunk/Common/ServiceStack.Text/ServiceStack.Text/Controller/PathInfo.cs - var pathInfo = PathInfo.Parse(Request.PathInfo); - var id = pathInfo.GetArgumentValue<string>(1); + var id = GetPathValue(1); var task = TaskManager.ScheduledTasks.FirstOrDefault(i => string.Equals(i.Id, id)); diff --git a/MediaBrowser.Api/SearchService.cs b/MediaBrowser.Api/SearchService.cs index 61c7305b5..ee48946d5 100644 --- a/MediaBrowser.Api/SearchService.cs +++ b/MediaBrowser.Api/SearchService.cs @@ -194,29 +194,24 @@ namespace MediaBrowser.Api { result.Series = season.Series.Name; - result.EpisodeCount = season.GetRecursiveChildren().Count(i => i is Episode); + result.EpisodeCount = season.GetRecursiveChildren(i => i is Episode).Count; } var series = item as Series; if (series != null) { - result.EpisodeCount = series.GetRecursiveChildren().Count(i => i is Episode); + result.EpisodeCount = series.GetRecursiveChildren(i => i is Episode).Count; } var album = item as MusicAlbum; if (album != null) { - var songs = album.GetRecursiveChildren().OfType<Audio>().ToList(); + result.SongCount = album.Tracks.Count(); - result.SongCount = songs.Count; - - result.Artists = songs.SelectMany(i => i.AllArtists) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToArray(); - - result.AlbumArtist = songs.SelectMany(i => i.AlbumArtists).FirstOrDefault(i => !string.IsNullOrEmpty(i)); + result.Artists = album.Artists.ToArray(); + result.AlbumArtist = album.AlbumArtists.FirstOrDefault(); } var song = item as Audio; diff --git a/MediaBrowser.Api/Session/SessionsService.cs b/MediaBrowser.Api/Session/SessionsService.cs index 59b8e85c2..319b3d28c 100644 --- a/MediaBrowser.Api/Session/SessionsService.cs +++ b/MediaBrowser.Api/Session/SessionsService.cs @@ -243,8 +243,13 @@ namespace MediaBrowser.Api.Session [ApiMember(Name = "SupportsSync", Description = "Determines whether sync is supported.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")] public bool SupportsSync { get; set; } - [ApiMember(Name = "SupportsUniqueIdentifier", Description = "Determines whether the device supports a unique identifier.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")] - public bool SupportsUniqueIdentifier { get; set; } + [ApiMember(Name = "SupportsPersistentIdentifier", Description = "Determines whether the device supports a unique identifier.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")] + public bool SupportsPersistentIdentifier { get; set; } + + public PostCapabilities() + { + SupportsPersistentIdentifier = true; + } } [Route("/Sessions/Capabilities/Full", "POST", Summary = "Updates capabilities for a device")] @@ -556,7 +561,7 @@ namespace MediaBrowser.Api.Session SupportsSync = request.SupportsSync, - SupportsUniqueIdentifier = request.SupportsUniqueIdentifier + SupportsPersistentIdentifier = request.SupportsPersistentIdentifier }); } diff --git a/MediaBrowser.Api/SimilarItemsHelper.cs b/MediaBrowser.Api/SimilarItemsHelper.cs index 2da29928b..e061c391a 100644 --- a/MediaBrowser.Api/SimilarItemsHelper.cs +++ b/MediaBrowser.Api/SimilarItemsHelper.cs @@ -57,6 +57,7 @@ namespace MediaBrowser.Api /// <summary> /// Gets the similar items. /// </summary> + /// <param name="dtoOptions">The dto options.</param> /// <param name="userManager">The user manager.</param> /// <param name="itemRepository">The item repository.</param> /// <param name="libraryManager">The library manager.</param> @@ -67,7 +68,7 @@ namespace MediaBrowser.Api /// <param name="includeInSearch">The include in search.</param> /// <param name="getSimilarityScore">The get similarity score.</param> /// <returns>ItemsResult.</returns> - internal static ItemsResult GetSimilarItemsResult(IUserManager userManager, IItemRepository itemRepository, ILibraryManager libraryManager, IUserDataManager userDataRepository, IDtoService dtoService, ILogger logger, BaseGetSimilarItemsFromItem request, Func<BaseItem, bool> includeInSearch, Func<BaseItem, BaseItem, int> getSimilarityScore) + internal static ItemsResult GetSimilarItemsResult(DtoOptions dtoOptions, IUserManager userManager, IItemRepository itemRepository, ILibraryManager libraryManager, IUserDataManager userDataRepository, IDtoService dtoService, ILogger logger, BaseGetSimilarItemsFromItem request, Func<BaseItem, bool> includeInSearch, Func<BaseItem, BaseItem, int> getSimilarityScore) { var user = request.UserId.HasValue ? userManager.GetUserById(request.UserId.Value) : null; @@ -75,13 +76,13 @@ namespace MediaBrowser.Api (request.UserId.HasValue ? user.RootFolder : libraryManager.RootFolder) : libraryManager.GetItemById(request.Id); - var fields = request.GetItemFields().ToList(); + Func<BaseItem, bool> filter = i => i.Id != item.Id && includeInSearch(i); var inputItems = user == null - ? libraryManager.RootFolder.GetRecursiveChildren().Where(i => i.Id != item.Id) - : user.RootFolder.GetRecursiveChildren(user).Where(i => i.Id != item.Id); + ? libraryManager.RootFolder.GetRecursiveChildren(filter) + : user.RootFolder.GetRecursiveChildren(user, filter); - var items = GetSimilaritems(item, inputItems.Where(includeInSearch), getSimilarityScore) + var items = GetSimilaritems(item, inputItems, getSimilarityScore) .ToList(); IEnumerable<BaseItem> returnItems = items; @@ -93,7 +94,7 @@ namespace MediaBrowser.Api var result = new ItemsResult { - Items = returnItems.Select(i => dtoService.GetBaseItemDto(i, fields, user)).ToArray(), + Items = dtoService.GetBaseItemDtos(returnItems, dtoOptions, user).ToArray(), TotalRecordCount = items.Count }; @@ -164,7 +165,7 @@ namespace MediaBrowser.Api // Find common keywords points += GetKeywords(item1).Where(i => GetKeywords(item2).Contains(i, StringComparer.OrdinalIgnoreCase)).Sum(i => 10); - + // Find common studios points += item1.Studios.Where(i => item2.Studios.Contains(i, StringComparer.OrdinalIgnoreCase)).Sum(i => 3); diff --git a/MediaBrowser.Api/StartupWizardService.cs b/MediaBrowser.Api/StartupWizardService.cs index 4443b2a2b..bf5c04540 100644 --- a/MediaBrowser.Api/StartupWizardService.cs +++ b/MediaBrowser.Api/StartupWizardService.cs @@ -62,6 +62,9 @@ namespace MediaBrowser.Api { _config.Configuration.IsStartupWizardCompleted = true; _config.Configuration.EnableLocalizedGuids = true; + _config.Configuration.MergeMetadataAndImagesByName = true; + _config.Configuration.EnableStandaloneMetadata = true; + _config.Configuration.EnableLibraryMetadataSubFolder = true; _config.SaveConfiguration(); } diff --git a/MediaBrowser.Api/Sync/SyncService.cs b/MediaBrowser.Api/Sync/SyncService.cs index a7467c12f..93d8a8d0a 100644 --- a/MediaBrowser.Api/Sync/SyncService.cs +++ b/MediaBrowser.Api/Sync/SyncService.cs @@ -2,7 +2,6 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Sync; -using MediaBrowser.Model.Dto; using MediaBrowser.Model.Querying; using MediaBrowser.Model.Sync; using MediaBrowser.Model.Users; @@ -38,6 +37,34 @@ namespace MediaBrowser.Api.Sync { } + [Route("/Sync/JobItems/{Id}/Enable", "POST", Summary = "Enables a cancelled or queued sync job item")] + public class EnableSyncJobItem : IReturnVoid + { + [ApiMember(Name = "Id", Description = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public string Id { get; set; } + } + + [Route("/Sync/JobItems/{Id}/MarkForRemoval", "POST", Summary = "Marks a job item for removal")] + public class MarkJobItemForRemoval : IReturnVoid + { + [ApiMember(Name = "Id", Description = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public string Id { get; set; } + } + + [Route("/Sync/JobItems/{Id}/UnmarkForRemoval", "POST", Summary = "Unmarks a job item for removal")] + public class UnmarkJobItemForRemoval : IReturnVoid + { + [ApiMember(Name = "Id", Description = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public string Id { get; set; } + } + + [Route("/Sync/JobItems/{Id}", "DELETE", Summary = "Cancels a sync job item")] + public class CancelSyncJobItem : IReturnVoid + { + [ApiMember(Name = "Id", Description = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")] + public string Id { get; set; } + } + [Route("/Sync/Jobs", "GET", Summary = "Gets sync jobs.")] public class GetSyncJobs : SyncJobQuery, IReturn<QueryResult<SyncJob>> { @@ -85,6 +112,16 @@ namespace MediaBrowser.Api.Sync public string Id { get; set; } } + [Route("/Sync/JobItems/{Id}/AdditionalFiles", "GET", Summary = "Gets a sync job item file")] + public class GetSyncJobItemAdditionalFile + { + [ApiMember(Name = "Id", Description = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] + public string Id { get; set; } + + [ApiMember(Name = "Name", Description = "Name", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] + public string Name { get; set; } + } + [Route("/Sync/OfflineActions", "POST", Summary = "Reports an action that occurred while offline.")] public class ReportOfflineActions : List<UserAction>, IReturnVoid { @@ -198,10 +235,11 @@ namespace MediaBrowser.Api.Sync } }; - var dtos = request.ItemIds.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) + var items = request.ItemIds.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries) .Select(_libraryManager.GetItemById) - .Where(i => i != null) - .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions)) + .Where(i => i != null); + + var dtos = _dtoService.GetBaseItemDtos(items, dtoOptions) .ToList(); result.Options = SyncHelper.GetSyncOptions(dtos); @@ -243,5 +281,52 @@ namespace MediaBrowser.Api.Sync Task.WaitAll(task); } + + public object Get(GetSyncJobItemAdditionalFile request) + { + var jobItem = _syncManager.GetJobItem(request.Id); + + if (jobItem.Status != SyncJobItemStatus.Transferring) + { + throw new ArgumentException("The job item is not yet ready for transfer."); + } + + var file = jobItem.AdditionalFiles.FirstOrDefault(i => string.Equals(i.Name, request.Name, StringComparison.OrdinalIgnoreCase)); + + if (file == null) + { + throw new ArgumentException("Sync job additional file not found."); + } + + return ToStaticFileResult(file.Path); + } + + public void Post(EnableSyncJobItem request) + { + var task = _syncManager.ReEnableJobItem(request.Id); + + Task.WaitAll(task); + } + + public void Delete(CancelSyncJobItem request) + { + var task = _syncManager.CancelJobItem(request.Id); + + Task.WaitAll(task); + } + + public void Post(MarkJobItemForRemoval request) + { + var task = _syncManager.MarkJobItemForRemoval(request.Id); + + Task.WaitAll(task); + } + + public void Post(UnmarkJobItemForRemoval request) + { + var task = _syncManager.UnmarkJobItemForRemoval(request.Id); + + Task.WaitAll(task); + } } } diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs index d1464cd26..13ec1db3c 100644 --- a/MediaBrowser.Api/TvShowsService.cs +++ b/MediaBrowser.Api/TvShowsService.cs @@ -156,6 +156,20 @@ namespace MediaBrowser.Api [ApiMember(Name = "AdjacentTo", Description = "Optional. Return items that are siblings of a supplied item.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] public string AdjacentTo { get; set; } + + /// <summary> + /// Skips over a given number of items within the results. Use for paging. + /// </summary> + /// <value>The start index.</value> + [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] + public int? StartIndex { get; set; } + + /// <summary> + /// The maximum number of items to return + /// </summary> + /// <value>The limit.</value> + [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] + public int? Limit { get; set; } } [Route("/Shows/{Id}/Seasons", "GET", Summary = "Gets seasons for a tv series")] @@ -238,7 +252,9 @@ namespace MediaBrowser.Api /// <returns>System.Object.</returns> public object Get(GetSimilarShows request) { - var result = SimilarItemsHelper.GetSimilarItemsResult(_userManager, + var dtoOptions = GetDtoOptions(request); + + var result = SimilarItemsHelper.GetSimilarItemsResult(dtoOptions, _userManager, _itemRepo, _libraryManager, _userDataManager, @@ -254,10 +270,10 @@ namespace MediaBrowser.Api { var user = _userManager.GetUserById(request.UserId); - var items = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, request.ParentId) - .OfType<Episode>(); + var items = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, request.ParentId, i => i is Episode); - var itemsList = _libraryManager.Sort(items, user, new[] { "PremiereDate", "AirTime", "SortName" }, SortOrder.Ascending) + var itemsList = _libraryManager + .Sort(items, user, new[] { "PremiereDate", "AirTime", "SortName" }, SortOrder.Ascending) .Cast<Episode>() .ToList(); @@ -270,9 +286,9 @@ namespace MediaBrowser.Api var pagedItems = ApplyPaging(previousEpisodes, request.StartIndex, request.Limit); - var options = request.GetDtoOptions(); + var options = GetDtoOptions(request); - var returnItems = pagedItems.Select(i => _dtoService.GetBaseItemDto(i, options, user)).ToArray(); + var returnItems = _dtoService.GetBaseItemDtos(pagedItems, options, user).ToArray(); var result = new ItemsResult { @@ -301,9 +317,9 @@ namespace MediaBrowser.Api var user = _userManager.GetUserById(request.UserId); - var options = request.GetDtoOptions(); + var options = GetDtoOptions(request); - var returnItems = result.Items.Select(i => _dtoService.GetBaseItemDto(i, options, user)).ToArray(); + var returnItems = _dtoService.GetBaseItemDtos(result.Items, options, user).ToArray(); return ToOptimizedSerializedResultUsingCache(new ItemsResult { @@ -365,9 +381,9 @@ namespace MediaBrowser.Api .Cast<Season>(); } - var fields = request.GetItemFields().ToList(); + var dtoOptions = GetDtoOptions(request); - var returnItems = seasons.Select(i => _dtoService.GetBaseItemDto(i, fields, user)) + var returnItems = _dtoService.GetBaseItemDtos(seasons, dtoOptions, user) .ToArray(); return new ItemsResult @@ -411,7 +427,18 @@ namespace MediaBrowser.Api IEnumerable<Episode> episodes; - if (string.IsNullOrEmpty(request.SeasonId)) + if (!string.IsNullOrWhiteSpace(request.SeasonId)) + { + var season = _libraryManager.GetItemById(new Guid(request.SeasonId)) as Season; + + if (season == null) + { + throw new ResourceNotFoundException("No season exists with Id " + request.SeasonId); + } + + episodes = season.GetEpisodes(user); + } + else if (request.Season.HasValue) { var series = _libraryManager.GetItemById(request.Id) as Series; @@ -424,14 +451,14 @@ namespace MediaBrowser.Api } else { - var season = _libraryManager.GetItemById(new Guid(request.SeasonId)) as Season; + var series = _libraryManager.GetItemById(request.Id) as Series; - if (season == null) + if (series == null) { - throw new ResourceNotFoundException("No season exists with Id " + request.SeasonId); + throw new ResourceNotFoundException("No series exists with Id " + request.Id); } - episodes = season.GetEpisodes(user); + episodes = series.GetEpisodes(user); } // Filter after the fact in case the ui doesn't want them @@ -448,24 +475,27 @@ namespace MediaBrowser.Api episodes = episodes.Where(i => i.IsVirtualUnaired == val); } + IEnumerable<BaseItem> returnItems = episodes; + // This must be the last filter if (!string.IsNullOrEmpty(request.AdjacentTo)) { - episodes = UserViewBuilder.FilterForAdjacency(episodes, request.AdjacentTo) - .Cast<Episode>(); + returnItems = UserViewBuilder.FilterForAdjacency(returnItems, request.AdjacentTo); } - var fields = request.GetItemFields().ToList(); + returnItems = _libraryManager.ReplaceVideosWithPrimaryVersions(returnItems); - episodes = _libraryManager.ReplaceVideosWithPrimaryVersions(episodes).Cast<Episode>(); + var pagedItems = ApplyPaging(returnItems, request.StartIndex, request.Limit); + + var dtoOptions = GetDtoOptions(request); - var returnItems = episodes.Select(i => _dtoService.GetBaseItemDto(i, fields, user)) + var dtos = _dtoService.GetBaseItemDtos(pagedItems, dtoOptions, user) .ToArray(); return new ItemsResult { - TotalRecordCount = returnItems.Length, - Items = returnItems + TotalRecordCount = dtos.Length, + Items = dtos }; } } diff --git a/MediaBrowser.Api/UserLibrary/ArtistsService.cs b/MediaBrowser.Api/UserLibrary/ArtistsService.cs index 128423238..2ab08fd8d 100644 --- a/MediaBrowser.Api/UserLibrary/ArtistsService.cs +++ b/MediaBrowser.Api/UserLibrary/ArtistsService.cs @@ -83,7 +83,7 @@ namespace MediaBrowser.Api.UserLibrary { var item = GetArtist(request.Name, LibraryManager); - var dtoOptions = new DtoOptions(); + var dtoOptions = GetDtoOptions(request); if (request.UserId.HasValue) { diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs index 9d211a419..880d57b9a 100644 --- a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs +++ b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs @@ -56,46 +56,52 @@ namespace MediaBrowser.Api.UserLibrary protected ItemsResult GetResult(GetItemsByName request) { User user = null; - BaseItem item; + BaseItem parentItem; List<BaseItem> libraryItems; if (request.UserId.HasValue) { user = UserManager.GetUserById(request.UserId.Value); - item = string.IsNullOrEmpty(request.ParentId) ? user.RootFolder : LibraryManager.GetItemById(request.ParentId); - + parentItem = string.IsNullOrEmpty(request.ParentId) ? user.RootFolder : LibraryManager.GetItemById(request.ParentId); libraryItems = user.RootFolder.GetRecursiveChildren(user).ToList(); } else { - item = string.IsNullOrEmpty(request.ParentId) ? LibraryManager.RootFolder : LibraryManager.GetItemById(request.ParentId); - - libraryItems = LibraryManager.RootFolder.RecursiveChildren.ToList(); + parentItem = string.IsNullOrEmpty(request.ParentId) ? LibraryManager.RootFolder : LibraryManager.GetItemById(request.ParentId); + libraryItems = LibraryManager.RootFolder.GetRecursiveChildren().ToList(); } IEnumerable<BaseItem> items; - if (item.IsFolder) + var excludeItemTypes = request.GetExcludeItemTypes(); + var includeItemTypes = request.GetIncludeItemTypes(); + var mediaTypes = request.GetMediaTypes(); + + Func<BaseItem, bool> filter = i => FilterItem(request, i, excludeItemTypes, includeItemTypes, mediaTypes); + + if (parentItem.IsFolder) { - var folder = (Folder)item; + var folder = (Folder)parentItem; if (request.UserId.HasValue) { - items = request.Recursive ? folder.GetRecursiveChildren(user) : folder.GetChildren(user, true); + items = request.Recursive ? + folder.GetRecursiveChildren(user, filter) : + folder.GetChildren(user, true).Where(filter); } else { - items = request.Recursive ? folder.GetRecursiveChildren() : folder.Children; + items = request.Recursive ? + folder.GetRecursiveChildren(filter) : + folder.Children.Where(filter); } } else { - items = new[] { item }; + items = new[] { parentItem }.Where(filter); } - items = FilterItems(request, items); - var extractedItems = GetAllItems(request, items); var filteredItems = FilterItems(request, extractedItems, user); @@ -129,7 +135,7 @@ namespace MediaBrowser.Api.UserLibrary var tuples = ibnItems.Select(i => new Tuple<TItemType, List<BaseItem>>(i, i.GetTaggedItems(libraryItems).ToList())); - var dtoOptions = request.GetDtoOptions(); + var dtoOptions = GetDtoOptions(request); var dtos = tuples.Select(i => GetDto(i.Item1, user, dtoOptions, i.Item2)); @@ -290,33 +296,41 @@ namespace MediaBrowser.Api.UserLibrary /// Filters the items. /// </summary> /// <param name="request">The request.</param> - /// <param name="items">The items.</param> + /// <param name="f">The f.</param> + /// <param name="excludeItemTypes">The exclude item types.</param> + /// <param name="includeItemTypes">The include item types.</param> + /// <param name="mediaTypes">The media types.</param> /// <returns>IEnumerable{BaseItem}.</returns> - protected virtual IEnumerable<BaseItem> FilterItems(GetItemsByName request, IEnumerable<BaseItem> items) + protected bool FilterItem(GetItemsByName request, BaseItem f, string[] excludeItemTypes, string[] includeItemTypes, string[] mediaTypes) { // Exclude item types - if (!string.IsNullOrEmpty(request.ExcludeItemTypes)) + if (excludeItemTypes.Length > 0) { - var vals = request.ExcludeItemTypes.Split(','); - items = items.Where(f => !vals.Contains(f.GetType().Name, StringComparer.OrdinalIgnoreCase)); + if (excludeItemTypes.Contains(f.GetType().Name, StringComparer.OrdinalIgnoreCase)) + { + return false; + } } // Include item types - if (!string.IsNullOrEmpty(request.IncludeItemTypes)) + if (includeItemTypes.Length > 0) { - var vals = request.IncludeItemTypes.Split(','); - items = items.Where(f => vals.Contains(f.GetType().Name, StringComparer.OrdinalIgnoreCase)); + if (!includeItemTypes.Contains(f.GetType().Name, StringComparer.OrdinalIgnoreCase)) + { + return false; + } } // Include MediaTypes - if (!string.IsNullOrEmpty(request.MediaTypes)) + if (mediaTypes.Length > 0) { - var vals = request.MediaTypes.Split(','); - - items = items.Where(f => vals.Contains(f.MediaType ?? string.Empty, StringComparer.OrdinalIgnoreCase)); + if (!mediaTypes.Contains(f.MediaType ?? string.Empty, StringComparer.OrdinalIgnoreCase)) + { + return false; + } } - return items; + return true; } /// <summary> diff --git a/MediaBrowser.Api/UserLibrary/GameGenresService.cs b/MediaBrowser.Api/UserLibrary/GameGenresService.cs index 2f1c73ace..3063e19c7 100644 --- a/MediaBrowser.Api/UserLibrary/GameGenresService.cs +++ b/MediaBrowser.Api/UserLibrary/GameGenresService.cs @@ -69,7 +69,7 @@ namespace MediaBrowser.Api.UserLibrary { var item = GetGameGenre(request.Name, LibraryManager); - var dtoOptions = new DtoOptions(); + var dtoOptions = GetDtoOptions(request); if (request.UserId.HasValue) { diff --git a/MediaBrowser.Api/UserLibrary/GenresService.cs b/MediaBrowser.Api/UserLibrary/GenresService.cs index db0b0fe61..c659852de 100644 --- a/MediaBrowser.Api/UserLibrary/GenresService.cs +++ b/MediaBrowser.Api/UserLibrary/GenresService.cs @@ -74,7 +74,7 @@ namespace MediaBrowser.Api.UserLibrary { var item = GetGenre(request.Name, LibraryManager); - var dtoOptions = new DtoOptions(); + var dtoOptions = GetDtoOptions(request); if (request.UserId.HasValue) { diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index cf9b0b438..15b1f6dba 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -321,14 +321,14 @@ namespace MediaBrowser.Api.UserLibrary var result = await GetItemsToSerialize(request, user, parentItem).ConfigureAwait(false); var isFiltered = result.Item2; - var dtoOptions = request.GetDtoOptions(); + var dtoOptions = GetDtoOptions(request); if (isFiltered) { return new ItemsResult { TotalRecordCount = result.Item1.TotalRecordCount, - Items = result.Item1.Items.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user)).ToArray() + Items = _dtoService.GetBaseItemDtos(result.Item1.Items, dtoOptions, user).ToArray() }; } @@ -362,7 +362,7 @@ namespace MediaBrowser.Api.UserLibrary var pagedItems = ApplyPaging(request, itemsArray); - var returnItems = pagedItems.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user)).ToArray(); + var returnItems = _dtoService.GetBaseItemDtos(pagedItems, dtoOptions, user).ToArray(); return new ItemsResult { @@ -398,7 +398,7 @@ namespace MediaBrowser.Api.UserLibrary { if (user == null) { - items = ((Folder)item).RecursiveChildren; + items = ((Folder)item).GetRecursiveChildren(); items = _libraryManager.ReplaceVideosWithPrimaryVersions(items); } @@ -464,7 +464,7 @@ namespace MediaBrowser.Api.UserLibrary SortBy = request.GetOrderBy(), SortOrder = request.SortOrder ?? SortOrder.Ascending, - Filter = (i, u) => ApplyAdditionalFilters(request, i, u, true, _libraryManager), + Filter = i => ApplyAdditionalFilters(request, i, user, true, _libraryManager), Limit = request.Limit, StartIndex = request.StartIndex, diff --git a/MediaBrowser.Api/UserLibrary/MusicGenresService.cs b/MediaBrowser.Api/UserLibrary/MusicGenresService.cs index f8575aa7c..3733128f0 100644 --- a/MediaBrowser.Api/UserLibrary/MusicGenresService.cs +++ b/MediaBrowser.Api/UserLibrary/MusicGenresService.cs @@ -69,7 +69,7 @@ namespace MediaBrowser.Api.UserLibrary { var item = GetMusicGenre(request.Name, LibraryManager); - var dtoOptions = new DtoOptions(); + var dtoOptions = GetDtoOptions(request); if (request.UserId.HasValue) { diff --git a/MediaBrowser.Api/UserLibrary/PersonsService.cs b/MediaBrowser.Api/UserLibrary/PersonsService.cs index 33ce6cd80..b424c9313 100644 --- a/MediaBrowser.Api/UserLibrary/PersonsService.cs +++ b/MediaBrowser.Api/UserLibrary/PersonsService.cs @@ -86,7 +86,7 @@ namespace MediaBrowser.Api.UserLibrary { var item = GetPerson(request.Name, LibraryManager); - var dtoOptions = new DtoOptions(); + var dtoOptions = GetDtoOptions(request); if (request.UserId.HasValue) { diff --git a/MediaBrowser.Api/UserLibrary/StudiosService.cs b/MediaBrowser.Api/UserLibrary/StudiosService.cs index 272134b70..a4ebef684 100644 --- a/MediaBrowser.Api/UserLibrary/StudiosService.cs +++ b/MediaBrowser.Api/UserLibrary/StudiosService.cs @@ -73,7 +73,7 @@ namespace MediaBrowser.Api.UserLibrary { var item = GetStudio(request.Name, LibraryManager); - var dtoOptions = new DtoOptions(); + var dtoOptions = GetDtoOptions(request); if (request.UserId.HasValue) { diff --git a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs index 45a330a50..cdfd00ce9 100644 --- a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs +++ b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs @@ -228,7 +228,7 @@ namespace MediaBrowser.Api.UserLibrary /// </summary> /// <value>The user id.</value> [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public Guid UserId { get; set; } + public string UserId { get; set; } [ApiMember(Name = "Limit", Description = "Limit", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] public int Limit { get; set; } @@ -259,7 +259,7 @@ namespace MediaBrowser.Api.UserLibrary [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] public string EnableImageTypes { get; set; } - + public GetLatestMedia() { Limit = 20; @@ -304,74 +304,17 @@ namespace MediaBrowser.Api.UserLibrary { var user = _userManager.GetUserById(request.UserId); - // Avoid implicitly captured closure - var libraryItems = string.IsNullOrEmpty(request.ParentId) && user != null ? - GetItemsConfiguredForLatest(user) : - GetAllLibraryItems(request.UserId, _userManager, _libraryManager, request.ParentId); - - libraryItems = libraryItems.OrderByDescending(i => i.DateCreated) - .Where(i => i.LocationType != LocationType.Virtual); - - - //if (request.IsFolder.HasValue) - //{ - //var val = request.IsFolder.Value; - libraryItems = libraryItems.Where(f => f.IsFolder == false); - //} - - if (!string.IsNullOrEmpty(request.IncludeItemTypes)) - { - var vals = request.IncludeItemTypes.Split(','); - libraryItems = libraryItems.Where(f => vals.Contains(f.GetType().Name, StringComparer.OrdinalIgnoreCase)); - } - - var currentUser = user; - - if (request.IsPlayed.HasValue) - { - var takeLimit = request.Limit * 20; - - var val = request.IsPlayed.Value; - libraryItems = libraryItems.Where(f => f.IsPlayed(currentUser) == val) - .Take(takeLimit); - } - - // Avoid implicitly captured closure - var items = libraryItems - .ToList(); - - var list = new List<Tuple<BaseItem, List<BaseItem>>>(); - - foreach (var item in items) + var list = _userViewManager.GetLatestItems(new LatestItemsQuery { - // Only grab the index container for media - var container = item.IsFolder || !request.GroupItems ? null : item.LatestItemsIndexContainer; - - if (container == null) - { - list.Add(new Tuple<BaseItem, List<BaseItem>>(null, new List<BaseItem> { item })); - } - else - { - var current = list.FirstOrDefault(i => i.Item1 != null && i.Item1.Id == container.Id); - - if (current != null) - { - current.Item2.Add(item); - } - else - { - list.Add(new Tuple<BaseItem, List<BaseItem>>(container, new List<BaseItem> { item })); - } - } - - if (list.Count >= request.Limit) - { - break; - } - } + GroupItems = request.GroupItems, + IncludeItemTypes = (request.IncludeItemTypes ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToArray(), + IsPlayed = request.IsPlayed, + Limit = request.Limit, + ParentId = request.ParentId, + UserId = request.UserId + }); - var options = request.GetDtoOptions(); + var options = GetDtoOptions(request); var dtos = list.Select(i => { @@ -394,15 +337,6 @@ namespace MediaBrowser.Api.UserLibrary return ToOptimizedResult(dtos.ToList()); } - private IEnumerable<BaseItem> GetItemsConfiguredForLatest(User user) - { - return user.RootFolder.GetChildren(user, true) - .OfType<Folder>() - .Where(i => !user.Configuration.LatestItemsExcludes.Contains(i.Id.ToString("N"))) - .SelectMany(i => i.GetRecursiveChildren(user)) - .DistinctBy(i => i.Id); - } - public async Task<object> Get(GetUserViews request) { var user = _userManager.GetUserById(request.UserId); @@ -420,7 +354,7 @@ namespace MediaBrowser.Api.UserLibrary var folders = await _userViewManager.GetUserViews(query, CancellationToken.None).ConfigureAwait(false); - var dtoOptions = new DtoOptions(); + var dtoOptions = GetDtoOptions(request); var dtos = folders.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user)) .ToArray(); @@ -447,14 +381,13 @@ namespace MediaBrowser.Api.UserLibrary // Get them from the child tree if (series != null) { - var dtoOptions = new DtoOptions(); + var dtoOptions = GetDtoOptions(request); // Avoid implicitly captured closure var currentUser = user; var dtos = series - .GetRecursiveChildren() - .Where(i => i is Episode && i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == 0) + .GetRecursiveChildren(i => i is Episode && i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == 0) .OrderBy(i => { if (i.PremiereDate.HasValue) @@ -479,7 +412,7 @@ namespace MediaBrowser.Api.UserLibrary // Get them from the db if (movie != null) { - var dtoOptions = new DtoOptions(); + var dtoOptions = GetDtoOptions(request); var dtos = movie.SpecialFeatureIds .Select(_libraryManager.GetItemById) @@ -518,11 +451,10 @@ namespace MediaBrowser.Api.UserLibrary trailerIds = hasTrailers.GetTrailerIds(); } - var dtoOptions = new DtoOptions(); + var dtoOptions = GetDtoOptions(request); var dtos = trailerIds .Select(_libraryManager.GetItemById) - .OrderBy(i => i.SortName) .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item)); return dtos.ToList(); @@ -539,7 +471,7 @@ namespace MediaBrowser.Api.UserLibrary var item = string.IsNullOrEmpty(request.Id) ? user.RootFolder : _libraryManager.GetItemById(request.Id); - var dtoOptions = new DtoOptions(); + var dtoOptions = GetDtoOptions(request); var result = _dtoService.GetBaseItemDto(item, dtoOptions, user); @@ -557,7 +489,7 @@ namespace MediaBrowser.Api.UserLibrary var item = user.RootFolder; - var dtoOptions = new DtoOptions(); + var dtoOptions = GetDtoOptions(request); var result = _dtoService.GetBaseItemDto(item, dtoOptions, user); @@ -577,7 +509,7 @@ namespace MediaBrowser.Api.UserLibrary var items = await _libraryManager.GetIntros(item, user).ConfigureAwait(false); - var dtoOptions = new DtoOptions(); + var dtoOptions = GetDtoOptions(request); var dtos = items.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user)) .ToArray(); diff --git a/MediaBrowser.Api/UserLibrary/YearsService.cs b/MediaBrowser.Api/UserLibrary/YearsService.cs index b1b0aeb63..d95496333 100644 --- a/MediaBrowser.Api/UserLibrary/YearsService.cs +++ b/MediaBrowser.Api/UserLibrary/YearsService.cs @@ -73,7 +73,7 @@ namespace MediaBrowser.Api.UserLibrary { var item = LibraryManager.GetYear(request.Year); - var dtoOptions = new DtoOptions(); + var dtoOptions = GetDtoOptions(request); if (request.UserId.HasValue) { diff --git a/MediaBrowser.Api/UserService.cs b/MediaBrowser.Api/UserService.cs index 51a7584b8..c34924f3c 100644 --- a/MediaBrowser.Api/UserService.cs +++ b/MediaBrowser.Api/UserService.cs @@ -11,7 +11,6 @@ using MediaBrowser.Model.Connect; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Users; using ServiceStack; -using ServiceStack.Text.Controller; using System; using System.Collections.Generic; using System.Linq; @@ -57,6 +56,21 @@ namespace MediaBrowser.Api } /// <summary> + /// Class GetUser + /// </summary> + [Route("/Users/{Id}/Offline", "GET", Summary = "Gets an offline user record by Id")] + [Authenticated] + public class GetOfflineUser : IReturn<UserDto> + { + /// <summary> + /// Gets or sets the id. + /// </summary> + /// <value>The id.</value> + [ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] + public string Id { get; set; } + } + + /// <summary> /// Class DeleteUser /// </summary> [Route("/Users/{Id}", "DELETE", Summary = "Deletes a user")] @@ -149,6 +163,32 @@ namespace MediaBrowser.Api } /// <summary> + /// Class UpdateUserEasyPassword + /// </summary> + [Route("/Users/{Id}/EasyPassword", "POST", Summary = "Updates a user's easy password")] + [Authenticated] + public class UpdateUserEasyPassword : IReturnVoid + { + /// <summary> + /// Gets or sets the id. + /// </summary> + /// <value>The id.</value> + public string Id { get; set; } + + /// <summary> + /// Gets or sets the new password. + /// </summary> + /// <value>The new password.</value> + public string NewPassword { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether [reset password]. + /// </summary> + /// <value><c>true</c> if [reset password]; otherwise, <c>false</c>.</value> + public bool ResetPassword { get; set; } + } + + /// <summary> /// Class UpdateUser /// </summary> [Route("/Users/{Id}", "POST", Summary = "Updates a user")] @@ -294,7 +334,7 @@ namespace MediaBrowser.Api .Select(i => _userManager.GetUserDto(i, Request.RemoteIp)) .ToList(); - return ToOptimizedSerializedResultUsingCache(result); + return ToOptimizedResult(result); } /// <summary> @@ -313,7 +353,23 @@ namespace MediaBrowser.Api var result = _userManager.GetUserDto(user, Request.RemoteIp); - return ToOptimizedSerializedResultUsingCache(result); + return ToOptimizedResult(result); + } + + public object Get(GetOfflineUser request) + { + var user = _userManager.GetUserById(request.Id); + + if (user == null) + { + throw new ResourceNotFoundException("User not found"); + } + + var auth = AuthorizationContext.GetAuthorizationInfo(Request); + + var result = _userManager.GetOfflineUserDto(user, auth.DeviceId); + + return ToOptimizedResult(result); } /// <summary> @@ -410,6 +466,8 @@ namespace MediaBrowser.Api public async Task PostAsync(UpdateUserPassword request) { + AssertCanUpdateUser(request.Id); + var user = _userManager.GetUserById(request.Id); if (user == null) @@ -434,6 +492,33 @@ namespace MediaBrowser.Api } } + public void Post(UpdateUserEasyPassword request) + { + var task = PostAsync(request); + Task.WaitAll(task); + } + + public async Task PostAsync(UpdateUserEasyPassword request) + { + AssertCanUpdateUser(request.Id); + + var user = _userManager.GetUserById(request.Id); + + if (user == null) + { + throw new ResourceNotFoundException("User not found"); + } + + if (request.ResetPassword) + { + await _userManager.ResetEasyPassword(user).ConfigureAwait(false); + } + else + { + await _userManager.ChangeEasyPassword(user, request.NewPassword).ConfigureAwait(false); + } + } + /// <summary> /// Posts the specified request. /// </summary> @@ -449,14 +534,15 @@ namespace MediaBrowser.Api { // We need to parse this manually because we told service stack not to with IRequiresRequestStream // https://code.google.com/p/servicestack/source/browse/trunk/Common/ServiceStack.Text/ServiceStack.Text/Controller/PathInfo.cs - var pathInfo = PathInfo.Parse(Request.PathInfo); - var id = new Guid(pathInfo.GetArgumentValue<string>(1)); + var id = GetPathValue(1); + + AssertCanUpdateUser(id); var dtoUser = request; var user = _userManager.GetUserById(id); - var task = user.Name.Equals(dtoUser.Name, StringComparison.Ordinal) ? + var task = string.Equals(user.Name, dtoUser.Name, StringComparison.Ordinal) ? _userManager.UpdateUser(user) : _userManager.RenameUser(user, dtoUser.Name); @@ -500,11 +586,29 @@ namespace MediaBrowser.Api public void Post(UpdateUserConfiguration request) { + AssertCanUpdateUser(request.Id); + var task = _userManager.UpdateConfiguration(request.Id, request); Task.WaitAll(task); } + private void AssertCanUpdateUser(string userId) + { + var auth = AuthorizationContext.GetAuthorizationInfo(Request); + + // If they're going to update the record of another user, they must be an administrator + if (!string.Equals(userId, auth.UserId, StringComparison.OrdinalIgnoreCase)) + { + var authenticatedUser = _userManager.GetUserById(auth.UserId); + + if (!authenticatedUser.Policy.IsAdministrator) + { + throw new SecurityException("Unauthorized access."); + } + } + } + public void Post(UpdateUserPolicy request) { var task = UpdateUserPolicy(request); diff --git a/MediaBrowser.Api/VideosService.cs b/MediaBrowser.Api/VideosService.cs index 28db46b98..d1b0eb05f 100644 --- a/MediaBrowser.Api/VideosService.cs +++ b/MediaBrowser.Api/VideosService.cs @@ -5,7 +5,6 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Persistence; -using MediaBrowser.Model.Dto; using MediaBrowser.Model.Querying; using ServiceStack; using System; @@ -80,7 +79,7 @@ namespace MediaBrowser.Api : _libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id); - var dtoOptions = new DtoOptions(); + var dtoOptions = GetDtoOptions(request); var video = (Video)item; diff --git a/MediaBrowser.Common.Implementations/BaseApplicationHost.cs b/MediaBrowser.Common.Implementations/BaseApplicationHost.cs index c98a6bd6c..0f89bd1a6 100644 --- a/MediaBrowser.Common.Implementations/BaseApplicationHost.cs +++ b/MediaBrowser.Common.Implementations/BaseApplicationHost.cs @@ -475,7 +475,7 @@ namespace MediaBrowser.Common.Implementations SecurityManager = new PluginSecurityManager(this, HttpClient, JsonSerializer, ApplicationPaths, LogManager); RegisterSingleInstance(SecurityManager); - InstallationManager = new InstallationManager(Logger, this, ApplicationPaths, HttpClient, JsonSerializer, SecurityManager, ConfigurationManager); + InstallationManager = new InstallationManager(Logger, this, ApplicationPaths, HttpClient, JsonSerializer, SecurityManager, ConfigurationManager, FileSystemManager); RegisterSingleInstance(InstallationManager); ZipClient = new ZipClient(); diff --git a/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs b/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs index 1f82c5eb0..b925649fc 100644 --- a/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs +++ b/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs @@ -690,7 +690,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager { try { - File.Delete(file); + _fileSystem.DeleteFile(file); } catch (IOException) { diff --git a/MediaBrowser.Common.Implementations/IO/CommonFileSystem.cs b/MediaBrowser.Common.Implementations/IO/CommonFileSystem.cs index 68df0e52a..ea4a61e25 100644 --- a/MediaBrowser.Common.Implementations/IO/CommonFileSystem.cs +++ b/MediaBrowser.Common.Implementations/IO/CommonFileSystem.cs @@ -1,4 +1,4 @@ -using MediaBrowser.Common.Extensions; +using MediaBrowser.Model.Extensions; using MediaBrowser.Common.IO; using MediaBrowser.Model.Logging; using System; @@ -270,8 +270,8 @@ namespace MediaBrowser.Common.Implementations.IO File.Copy(temp1, file2, true); File.Copy(temp2, file1, true); - File.Delete(temp1); - File.Delete(temp2); + DeleteFile(temp1); + DeleteFile(temp2); } /// <summary> @@ -409,5 +409,25 @@ namespace MediaBrowser.Common.Implementations.IO //return Path.IsPathRooted(path); } + + public void DeleteFile(string path, bool sendToRecycleBin) + { + File.Delete(path); + } + + public void DeleteDirectory(string path, bool recursive, bool sendToRecycleBin) + { + Directory.Delete(path, recursive); + } + + public void DeleteFile(string path) + { + DeleteFile(path, false); + } + + public void DeleteDirectory(string path, bool recursive) + { + DeleteDirectory(path, recursive, false); + } } } diff --git a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj index ff08c31bc..d7e5886d5 100644 --- a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj +++ b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj @@ -48,21 +48,21 @@ <RunPostBuildEvent>Always</RunPostBuildEvent> </PropertyGroup> <ItemGroup> - <Reference Include="NLog, Version=3.1.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL"> + <Reference Include="NLog, Version=3.2.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> - <HintPath>..\packages\NLog.3.1.0.0\lib\net45\NLog.dll</HintPath> + <HintPath>..\packages\NLog.3.2.0.0\lib\net45\NLog.dll</HintPath> </Reference> <Reference Include="SharpCompress, Version=0.10.2.0, Culture=neutral, PublicKeyToken=beaf6f427e128133, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> <HintPath>..\ThirdParty\SharpCompress\SharpCompress.dll</HintPath> </Reference> - <Reference Include="SimpleInjector, Version=2.6.1.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL"> + <Reference Include="SimpleInjector, Version=2.7.0.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> - <HintPath>..\packages\SimpleInjector.2.6.1\lib\net45\SimpleInjector.dll</HintPath> + <HintPath>..\packages\SimpleInjector.2.7.0\lib\net45\SimpleInjector.dll</HintPath> </Reference> - <Reference Include="SimpleInjector.Diagnostics, Version=2.6.1.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL"> + <Reference Include="SimpleInjector.Diagnostics, Version=2.7.0.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> - <HintPath>..\packages\SimpleInjector.2.6.1\lib\net45\SimpleInjector.Diagnostics.dll</HintPath> + <HintPath>..\packages\SimpleInjector.2.7.0\lib\net45\SimpleInjector.Diagnostics.dll</HintPath> </Reference> <Reference Include="System" /> <Reference Include="System.Core" /> diff --git a/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs b/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs index bf6ebf7ef..6deda1293 100644 --- a/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs +++ b/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs @@ -18,12 +18,65 @@ namespace MediaBrowser.Common.Implementations.Networking Logger = logger; } + private volatile List<string> _localIpAddresses; + private readonly object _localIpAddressSyncLock = new object(); + /// <summary> /// Gets the machine's local ip address /// </summary> /// <returns>IPAddress.</returns> public IEnumerable<string> GetLocalIpAddresses() { + if (_localIpAddresses == null) + { + lock (_localIpAddressSyncLock) + { + if (_localIpAddresses == null) + { + var addresses = GetLocalIpAddressesInternal().ToList(); + + _localIpAddresses = addresses; + BindEvents(); + + return addresses; + } + } + } + + return _localIpAddresses; + } + + private void BindEvents() + { + NetworkChange.NetworkAddressChanged -= NetworkChange_NetworkAddressChanged; + NetworkChange.NetworkAvailabilityChanged -= NetworkChange_NetworkAvailabilityChanged; + + NetworkChange.NetworkAddressChanged += NetworkChange_NetworkAddressChanged; + NetworkChange.NetworkAvailabilityChanged += NetworkChange_NetworkAvailabilityChanged; + } + + void NetworkChange_NetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e) + { + Logger.Debug("NetworkAvailabilityChanged fired. Resetting cached network info."); + + lock (_localIpAddressSyncLock) + { + _localIpAddresses = null; + } + } + + void NetworkChange_NetworkAddressChanged(object sender, EventArgs e) + { + Logger.Debug("NetworkAddressChanged fired. Resetting cached network info."); + + lock (_localIpAddressSyncLock) + { + _localIpAddresses = null; + } + } + + private IEnumerable<string> GetLocalIpAddressesInternal() + { var list = GetIPsDefault() .Where(i => !IPAddress.IsLoopback(i)) .Select(i => i.ToString()) @@ -53,6 +106,11 @@ namespace MediaBrowser.Common.Implementations.Networking // Private address space: // http://en.wikipedia.org/wiki/Private_network + if (endpoint.StartsWith("172.", StringComparison.OrdinalIgnoreCase)) + { + return Is172AddressPrivate(endpoint); + } + return // If url was requested with computer name, we may see this @@ -61,11 +119,23 @@ namespace MediaBrowser.Common.Implementations.Networking endpoint.StartsWith("localhost", StringComparison.OrdinalIgnoreCase) || endpoint.StartsWith("127.", StringComparison.OrdinalIgnoreCase) || endpoint.StartsWith("10.", StringComparison.OrdinalIgnoreCase) || - endpoint.StartsWith("192.", StringComparison.OrdinalIgnoreCase) || - endpoint.StartsWith("172.", StringComparison.OrdinalIgnoreCase) || + endpoint.StartsWith("192.168", StringComparison.OrdinalIgnoreCase) || endpoint.StartsWith("169.", StringComparison.OrdinalIgnoreCase); } + private bool Is172AddressPrivate(string endpoint) + { + for (var i = 16; i <= 31; i++) + { + if (endpoint.StartsWith("172." + i.ToString(CultureInfo.InvariantCulture) + ".", StringComparison.OrdinalIgnoreCase)) + { + return true; + } + } + + return false; + } + public bool IsInLocalNetwork(string endpoint) { return IsInLocalNetworkInternal(endpoint, true); @@ -122,7 +192,7 @@ namespace MediaBrowser.Common.Implementations.Networking return false; } - + public IEnumerable<IPAddress> GetIpAddresses(string hostName) { return Dns.GetHostAddresses(hostName); diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index 0dc67f8c0..b09cb7105 100644 --- a/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -108,13 +108,9 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks /// </summary> private TaskResult _lastExecutionResult; /// <summary> - /// The _last execution resultinitialized - /// </summary> - private bool _lastExecutionResultinitialized; - /// <summary> /// The _last execution result sync lock /// </summary> - private object _lastExecutionResultSyncLock = new object(); + private readonly object _lastExecutionResultSyncLock = new object(); /// <summary> /// Gets the last execution result. /// </summary> @@ -123,38 +119,39 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks { get { - LazyInitializer.EnsureInitialized(ref _lastExecutionResult, ref _lastExecutionResultinitialized, ref _lastExecutionResultSyncLock, () => + if (_lastExecutionResult == null) { - var path = GetHistoryFilePath(); - - try + lock (_lastExecutionResultSyncLock) { - return JsonSerializer.DeserializeFromFile<TaskResult>(path); + if (_lastExecutionResult == null) + { + var path = GetHistoryFilePath(); + + try + { + return JsonSerializer.DeserializeFromFile<TaskResult>(path); + } + catch (DirectoryNotFoundException) + { + // File doesn't exist. No biggie + } + catch (FileNotFoundException) + { + // File doesn't exist. No biggie + } + catch (Exception ex) + { + Logger.ErrorException("Error deserializing {0}", ex, path); + } + } } - catch (DirectoryNotFoundException) - { - // File doesn't exist. No biggie - return null; - } - catch (FileNotFoundException) - { - // File doesn't exist. No biggie - return null; - } - catch (Exception ex) - { - Logger.ErrorException("Error deserializing {0}", ex, path); - return null; - } - }); + } return _lastExecutionResult; } private set { _lastExecutionResult = value; - - _lastExecutionResultinitialized = value != null; } } @@ -227,13 +224,9 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks /// </summary> private IEnumerable<ITaskTrigger> _triggers; /// <summary> - /// The _triggers initialized - /// </summary> - private bool _triggersInitialized; - /// <summary> /// The _triggers sync lock /// </summary> - private object _triggersSyncLock = new object(); + private readonly object _triggersSyncLock = new object(); /// <summary> /// Gets the triggers that define when the task will run /// </summary> @@ -243,7 +236,16 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks { get { - LazyInitializer.EnsureInitialized(ref _triggers, ref _triggersInitialized, ref _triggersSyncLock, LoadTriggers); + if (_triggers == null) + { + lock (_triggersSyncLock) + { + if (_triggers == null) + { + _triggers = LoadTriggers(); + } + } + } return _triggers; } @@ -262,8 +264,6 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks _triggers = value.ToList(); - _triggersInitialized = true; - ReloadTriggerEvents(false); SaveTriggers(_triggers); @@ -544,6 +544,12 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks Id = Id }; + var hasKey = ScheduledTask as IHasKey; + if (hasKey != null) + { + result.Key = hasKey.Key; + } + if (ex != null) { result.ErrorMessage = ex.Message; diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs index fcb7b159b..779f992d3 100644 --- a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs +++ b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs @@ -125,7 +125,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks { try { - File.Delete(path); + _fileSystem.DeleteFile(path); } catch (IOException ex) { diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs index 3b0c02dc6..6b9bcbfc1 100644 --- a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs +++ b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs @@ -76,7 +76,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks cancellationToken.ThrowIfCancellationRequested(); - File.Delete(file.FullName); + _fileSystem.DeleteFile(file.FullName); index++; } diff --git a/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs b/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs index 47215aacf..264e63b47 100644 --- a/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs +++ b/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs @@ -1,6 +1,7 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Events; using MediaBrowser.Common.Implementations.Security; +using MediaBrowser.Common.IO; using MediaBrowser.Common.Net; using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Progress; @@ -106,6 +107,7 @@ namespace MediaBrowser.Common.Implementations.Updates private readonly IJsonSerializer _jsonSerializer; private readonly ISecurityManager _securityManager; private readonly IConfigurationManager _config; + private readonly IFileSystem _fileSystem; /// <summary> /// Gets the application host. @@ -113,7 +115,7 @@ namespace MediaBrowser.Common.Implementations.Updates /// <value>The application host.</value> private readonly IApplicationHost _applicationHost; - public InstallationManager(ILogger logger, IApplicationHost appHost, IApplicationPaths appPaths, IHttpClient httpClient, IJsonSerializer jsonSerializer, ISecurityManager securityManager, IConfigurationManager config) + public InstallationManager(ILogger logger, IApplicationHost appHost, IApplicationPaths appPaths, IHttpClient httpClient, IJsonSerializer jsonSerializer, ISecurityManager securityManager, IConfigurationManager config, IFileSystem fileSystem) { if (logger == null) { @@ -129,6 +131,7 @@ namespace MediaBrowser.Common.Implementations.Updates _jsonSerializer = jsonSerializer; _securityManager = securityManager; _config = config; + _fileSystem = fileSystem; _logger = logger; } @@ -570,7 +573,7 @@ namespace MediaBrowser.Common.Implementations.Updates try { - File.Delete(tempFile); + _fileSystem.DeleteFile(tempFile); } catch (IOException e) { @@ -591,7 +594,7 @@ namespace MediaBrowser.Common.Implementations.Updates // Remove it the quick way for now _applicationHost.RemovePlugin(plugin); - File.Delete(plugin.AssemblyFilePath); + _fileSystem.DeleteFile(plugin.AssemblyFilePath); OnPluginUninstalled(plugin); diff --git a/MediaBrowser.Common.Implementations/packages.config b/MediaBrowser.Common.Implementations/packages.config index 63d288bbb..825b6662b 100644 --- a/MediaBrowser.Common.Implementations/packages.config +++ b/MediaBrowser.Common.Implementations/packages.config @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <packages> - <package id="NLog" version="3.1.0.0" targetFramework="net45" /> - <package id="SimpleInjector" version="2.6.1" targetFramework="net45" /> + <package id="NLog" version="3.2.0.0" targetFramework="net45" /> + <package id="SimpleInjector" version="2.7.0" targetFramework="net45" /> </packages> diff --git a/MediaBrowser.Common/Extensions/BaseExtensions.cs b/MediaBrowser.Common/Extensions/BaseExtensions.cs index 4c94f3aa2..22dfa378f 100644 --- a/MediaBrowser.Common/Extensions/BaseExtensions.cs +++ b/MediaBrowser.Common/Extensions/BaseExtensions.cs @@ -26,36 +26,6 @@ namespace MediaBrowser.Common.Extensions return Regex.Replace(htmlString, pattern, string.Empty).Trim(); } - /// <summary> - /// Replaces the specified STR. - /// </summary> - /// <param name="str">The STR.</param> - /// <param name="oldValue">The old value.</param> - /// <param name="newValue">The new value.</param> - /// <param name="comparison">The comparison.</param> - /// <returns>System.String.</returns> - public static string Replace(this string str, string oldValue, string newValue, StringComparison comparison) - { - var sb = new StringBuilder(); - - var previousIndex = 0; - var index = str.IndexOf(oldValue, comparison); - - while (index != -1) - { - sb.Append(str.Substring(previousIndex, index - previousIndex)); - sb.Append(newValue); - index += oldValue.Length; - - previousIndex = index; - index = str.IndexOf(oldValue, index, comparison); - } - - sb.Append(str.Substring(previousIndex)); - - return sb.ToString(); - } - public static string RemoveDiacritics(this string text) { return String.Concat( diff --git a/MediaBrowser.Common/IO/IFileSystem.cs b/MediaBrowser.Common/IO/IFileSystem.cs index 3bcec98ce..5ce84f436 100644 --- a/MediaBrowser.Common/IO/IFileSystem.cs +++ b/MediaBrowser.Common/IO/IFileSystem.cs @@ -133,5 +133,33 @@ namespace MediaBrowser.Common.IO /// <param name="path">The path.</param> /// <returns><c>true</c> if [is path file] [the specified path]; otherwise, <c>false</c>.</returns> bool IsPathFile(string path); + + /// <summary> + /// Deletes the file. + /// </summary> + /// <param name="path">The path.</param> + /// <param name="sendToRecycleBin">if set to <c>true</c> [send to recycle bin].</param> + void DeleteFile(string path, bool sendToRecycleBin); + + /// <summary> + /// Deletes the directory. + /// </summary> + /// <param name="path">The path.</param> + /// <param name="recursive">if set to <c>true</c> [recursive].</param> + /// <param name="sendToRecycleBin">if set to <c>true</c> [send to recycle bin].</param> + void DeleteDirectory(string path, bool recursive, bool sendToRecycleBin); + + /// <summary> + /// Deletes the file. + /// </summary> + /// <param name="path">The path.</param> + void DeleteFile(string path); + + /// <summary> + /// Deletes the directory. + /// </summary> + /// <param name="path">The path.</param> + /// <param name="recursive">if set to <c>true</c> [recursive].</param> + void DeleteDirectory(string path, bool recursive); } } diff --git a/MediaBrowser.Common/Net/INetworkManager.cs b/MediaBrowser.Common/Net/INetworkManager.cs index 979dae49c..8fc947e8f 100644 --- a/MediaBrowser.Common/Net/INetworkManager.cs +++ b/MediaBrowser.Common/Net/INetworkManager.cs @@ -51,5 +51,12 @@ namespace MediaBrowser.Common.Net /// <param name="endpoint">The endpoint.</param> /// <returns><c>true</c> if [is in local network] [the specified endpoint]; otherwise, <c>false</c>.</returns> bool IsInLocalNetwork(string endpoint); + + /// <summary> + /// Generates a self signed certificate at the locatation specified by <paramref name="certificatePath"/>. + /// </summary> + /// <param name="certificatePath">The path to generate the certificate.</param> + /// <param name="hostname">The common name for the certificate.</param> + void GenerateSelfSignedSslCertificate(string certificatePath, string hostname); } }
\ No newline at end of file diff --git a/MediaBrowser.Controller/Channels/Channel.cs b/MediaBrowser.Controller/Channels/Channel.cs index 5a9fc3322..87d257f12 100644 --- a/MediaBrowser.Controller/Channels/Channel.cs +++ b/MediaBrowser.Controller/Channels/Channel.cs @@ -14,9 +14,19 @@ namespace MediaBrowser.Controller.Channels public override bool IsVisible(User user) { - if (user.Policy.BlockedChannels.Contains(Id.ToString("N"), StringComparer.OrdinalIgnoreCase)) + if (user.Policy.BlockedChannels != null) { - return false; + if (user.Policy.BlockedChannels.Contains(Id.ToString("N"), StringComparer.OrdinalIgnoreCase)) + { + return false; + } + } + else + { + if (!user.Policy.EnableAllChannels && !user.Policy.EnabledChannels.Contains(Id.ToString("N"), StringComparer.OrdinalIgnoreCase)) + { + return false; + } } return base.IsVisible(user); @@ -50,7 +60,12 @@ namespace MediaBrowser.Controller.Channels protected override string GetInternalMetadataPath(string basePath) { - return System.IO.Path.Combine(basePath, "channels", Id.ToString("N"), "metadata"); + return GetInternalMetadataPath(basePath, Id); + } + + public static string GetInternalMetadataPath(string basePath, Guid id) + { + return System.IO.Path.Combine(basePath, "channels", id.ToString("N"), "metadata"); } } } diff --git a/MediaBrowser.Controller/Channels/ChannelAudioItem.cs b/MediaBrowser.Controller/Channels/ChannelAudioItem.cs index 896d598bb..d9330f8a3 100644 --- a/MediaBrowser.Controller/Channels/ChannelAudioItem.cs +++ b/MediaBrowser.Controller/Channels/ChannelAudioItem.cs @@ -32,7 +32,7 @@ namespace MediaBrowser.Controller.Channels return config.BlockUnratedItems.Contains(UnratedItem.ChannelContent); } - public override string GetUserDataKey() + protected override string CreateUserDataKey() { return ExternalId; } diff --git a/MediaBrowser.Controller/Channels/ChannelFolderItem.cs b/MediaBrowser.Controller/Channels/ChannelFolderItem.cs index 8482e38df..dce9840ed 100644 --- a/MediaBrowser.Controller/Channels/ChannelFolderItem.cs +++ b/MediaBrowser.Controller/Channels/ChannelFolderItem.cs @@ -40,7 +40,7 @@ namespace MediaBrowser.Controller.Channels return false; } - public override string GetUserDataKey() + protected override string CreateUserDataKey() { return ExternalId; } diff --git a/MediaBrowser.Controller/Channels/ChannelVideoItem.cs b/MediaBrowser.Controller/Channels/ChannelVideoItem.cs index f0eafcbdf..e3fad56e9 100644 --- a/MediaBrowser.Controller/Channels/ChannelVideoItem.cs +++ b/MediaBrowser.Controller/Channels/ChannelVideoItem.cs @@ -28,8 +28,8 @@ namespace MediaBrowser.Controller.Channels public string OriginalImageUrl { get; set; } public List<ChannelMediaInfo> ChannelMediaSources { get; set; } - - public override string GetUserDataKey() + + protected override string CreateUserDataKey() { if (ContentType == ChannelMediaContentType.MovieExtra) { diff --git a/MediaBrowser.Controller/Collections/ICollectionManager.cs b/MediaBrowser.Controller/Collections/ICollectionManager.cs index 9130f68d4..89e505579 100644 --- a/MediaBrowser.Controller/Collections/ICollectionManager.cs +++ b/MediaBrowser.Controller/Collections/ICollectionManager.cs @@ -60,5 +60,12 @@ namespace MediaBrowser.Controller.Collections /// <param name="userId">The user identifier.</param> /// <returns>Folder.</returns> Folder GetCollectionsFolder(string userId); + + /// <summary> + /// Gets the collections. + /// </summary> + /// <param name="user">The user.</param> + /// <returns>IEnumerable<BoxSet>.</returns> + IEnumerable<BoxSet> GetCollections(User user); } } diff --git a/MediaBrowser.Controller/Devices/CameraImageUploadInfo.cs b/MediaBrowser.Controller/Devices/CameraImageUploadInfo.cs new file mode 100644 index 000000000..b3f3bb902 --- /dev/null +++ b/MediaBrowser.Controller/Devices/CameraImageUploadInfo.cs @@ -0,0 +1,10 @@ +using MediaBrowser.Model.Devices; + +namespace MediaBrowser.Controller.Devices +{ + public class CameraImageUploadInfo + { + public LocalFileInfo FileInfo { get; set; } + public DeviceInfo Device { get; set; } + } +} diff --git a/MediaBrowser.Controller/Devices/IDeviceManager.cs b/MediaBrowser.Controller/Devices/IDeviceManager.cs index f5010bb45..78eebd994 100644 --- a/MediaBrowser.Controller/Devices/IDeviceManager.cs +++ b/MediaBrowser.Controller/Devices/IDeviceManager.cs @@ -3,7 +3,6 @@ using MediaBrowser.Model.Events; using MediaBrowser.Model.Querying; using MediaBrowser.Model.Session; using System; -using System.Collections.Generic; using System.IO; using System.Threading.Tasks; @@ -15,6 +14,10 @@ namespace MediaBrowser.Controller.Devices /// Occurs when [device options updated]. /// </summary> event EventHandler<GenericEventArgs<DeviceInfo>> DeviceOptionsUpdated; + /// <summary> + /// Occurs when [camera image uploaded]. + /// </summary> + event EventHandler<GenericEventArgs<CameraImageUploadInfo>> CameraImageUploaded; /// <summary> /// Registers the device. diff --git a/MediaBrowser.Controller/Dlna/IDlnaManager.cs b/MediaBrowser.Controller/Dlna/IDlnaManager.cs index 34464f6a2..2f64cd194 100644 --- a/MediaBrowser.Controller/Dlna/IDlnaManager.cs +++ b/MediaBrowser.Controller/Dlna/IDlnaManager.cs @@ -62,8 +62,9 @@ namespace MediaBrowser.Controller.Dlna /// </summary> /// <param name="headers">The headers.</param> /// <param name="serverUuId">The server uu identifier.</param> + /// <param name="serverAddress">The server address.</param> /// <returns>System.String.</returns> - string GetServerDescriptionXml(IDictionary<string, string> headers, string serverUuId); + string GetServerDescriptionXml(IDictionary<string, string> headers, string serverUuId, string serverAddress); /// <summary> /// Gets the icon. diff --git a/MediaBrowser.Controller/Dlna/IMediaReceiverRegistrar.cs b/MediaBrowser.Controller/Dlna/IMediaReceiverRegistrar.cs new file mode 100644 index 000000000..6b76783a5 --- /dev/null +++ b/MediaBrowser.Controller/Dlna/IMediaReceiverRegistrar.cs @@ -0,0 +1,7 @@ + +namespace MediaBrowser.Controller.Dlna +{ + public interface IMediaReceiverRegistrar : IEventManager, IUpnpService + { + } +} diff --git a/MediaBrowser.Controller/Dto/DtoOptions.cs b/MediaBrowser.Controller/Dto/DtoOptions.cs index eeb4fc114..a8d1b1862 100644 --- a/MediaBrowser.Controller/Dto/DtoOptions.cs +++ b/MediaBrowser.Controller/Dto/DtoOptions.cs @@ -17,6 +17,7 @@ namespace MediaBrowser.Controller.Dto public List<ImageType> ImageTypes { get; set; } public int ImageTypeLimit { get; set; } public bool EnableImages { get; set; } + public string DeviceId { get; set; } public DtoOptions() { diff --git a/MediaBrowser.Controller/Dto/IDtoService.cs b/MediaBrowser.Controller/Dto/IDtoService.cs index 7c7ec56d5..ea311d993 100644 --- a/MediaBrowser.Controller/Dto/IDtoService.cs +++ b/MediaBrowser.Controller/Dto/IDtoService.cs @@ -44,6 +44,17 @@ namespace MediaBrowser.Controller.Dto /// <param name="owner">The owner.</param> /// <returns>BaseItemDto.</returns> BaseItemDto GetBaseItemDto(BaseItem item, DtoOptions options, User user = null, BaseItem owner = null); + + /// <summary> + /// Gets the base item dtos. + /// </summary> + /// <param name="items">The items.</param> + /// <param name="options">The options.</param> + /// <param name="user">The user.</param> + /// <param name="owner">The owner.</param> + /// <returns>IEnumerable<BaseItemDto>.</returns> + IEnumerable<BaseItemDto> GetBaseItemDtos(IEnumerable<BaseItem> items, DtoOptions options, User user = null, + BaseItem owner = null); /// <summary> /// Gets the chapter information dto. diff --git a/MediaBrowser.Controller/Entities/AdultVideo.cs b/MediaBrowser.Controller/Entities/AdultVideo.cs deleted file mode 100644 index 6c3f7851e..000000000 --- a/MediaBrowser.Controller/Entities/AdultVideo.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace MediaBrowser.Controller.Entities -{ - [Obsolete] - public class AdultVideo : Video, IHasProductionLocations, IHasTaglines - { - public List<string> ProductionLocations { get; set; } - - public List<string> Taglines { get; set; } - - public AdultVideo() - { - Taglines = new List<string>(); - ProductionLocations = new List<string>(); - } - } -} diff --git a/MediaBrowser.Controller/Entities/AggregateFolder.cs b/MediaBrowser.Controller/Entities/AggregateFolder.cs index 362096b5e..af2cca5e6 100644 --- a/MediaBrowser.Controller/Entities/AggregateFolder.cs +++ b/MediaBrowser.Controller/Entities/AggregateFolder.cs @@ -66,7 +66,7 @@ namespace MediaBrowser.Controller.Entities { var path = ContainingFolderPath; - var args = new ItemResolveArgs(ConfigurationManager.ApplicationPaths, LibraryManager, directoryService) + var args = new ItemResolveArgs(ConfigurationManager.ApplicationPaths , directoryService) { FileInfo = new DirectoryInfo(path), Path = path, diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs index c5ed09016..2dcea37bd 100644 --- a/MediaBrowser.Controller/Entities/Audio/Audio.cs +++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs @@ -4,11 +4,11 @@ using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.MediaInfo; +using MediaBrowser.Model.Users; using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; -using MediaBrowser.Model.Users; namespace MediaBrowser.Controller.Entities.Audio { @@ -81,6 +81,15 @@ namespace MediaBrowser.Controller.Entities.Audio } [IgnoreDataMember] + protected override bool SupportsOwnedItems + { + get + { + return false; + } + } + + [IgnoreDataMember] public override Folder LatestItemsIndexContainer { get @@ -169,7 +178,7 @@ namespace MediaBrowser.Controller.Entities.Audio /// Gets the user data key. /// </summary> /// <returns>System.String.</returns> - public override string GetUserDataKey() + protected override string CreateUserDataKey() { var parent = FindParent<MusicAlbum>(); @@ -186,7 +195,7 @@ namespace MediaBrowser.Controller.Entities.Audio } } - return base.GetUserDataKey(); + return base.CreateUserDataKey(); } protected override bool GetBlockUnratedValue(UserPolicy config) diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs index 90edfcce7..e3f523b5a 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs @@ -1,11 +1,11 @@ using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Users; using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; -using MediaBrowser.Model.Users; namespace MediaBrowser.Controller.Entities.Audio { @@ -52,14 +52,14 @@ namespace MediaBrowser.Controller.Entities.Audio } } - public List<string> AlbumArtists { get; set; } - [IgnoreDataMember] public string AlbumArtist { get { return AlbumArtists.FirstOrDefault(); } } + public List<string> AlbumArtists { get; set; } + /// <summary> /// Gets the tracks. /// </summary> @@ -68,7 +68,7 @@ namespace MediaBrowser.Controller.Entities.Audio { get { - return RecursiveChildren.OfType<Audio>(); + return GetRecursiveChildren(i => i is Audio).Cast<Audio>(); } } @@ -136,7 +136,7 @@ namespace MediaBrowser.Controller.Entities.Audio /// Gets the user data key. /// </summary> /// <returns>System.String.</returns> - public override string GetUserDataKey() + protected override string CreateUserDataKey() { var id = this.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup); @@ -152,7 +152,7 @@ namespace MediaBrowser.Controller.Entities.Audio return "MusicAlbum-Musicbrainz-" + id; } - return base.GetUserDataKey(); + return base.CreateUserDataKey(); } protected override bool GetBlockUnratedValue(UserPolicy config) @@ -173,17 +173,12 @@ namespace MediaBrowser.Controller.Entities.Audio id.ArtistProviderIds = artist.ProviderIds; } - id.SongInfos = RecursiveChildren.OfType<Audio>() + id.SongInfos = GetRecursiveChildren(i => i is Audio) + .Cast<Audio>() .Select(i => i.GetLookupInfo()) .ToList(); return id; } } - - [Obsolete] - public class MusicAlbumDisc : Folder - { - - } } diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs index a60258d1a..038aa98aa 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs @@ -19,7 +19,8 @@ namespace MediaBrowser.Controller.Entities.Audio { public bool IsAccessedByName { get; set; } public List<string> ProductionLocations { get; set; } - + + [IgnoreDataMember] public override bool IsFolder { get @@ -68,7 +69,7 @@ namespace MediaBrowser.Controller.Entities.Audio /// Gets the user data key. /// </summary> /// <returns>System.String.</returns> - public override string GetUserDataKey() + protected override string CreateUserDataKey() { return GetUserDataKey(this); } @@ -78,6 +79,7 @@ namespace MediaBrowser.Controller.Entities.Audio /// If the item is a folder, it returns the folder itself /// </summary> /// <value>The containing folder path.</value> + [IgnoreDataMember] public override string ContainingFolderPath { get @@ -90,6 +92,7 @@ namespace MediaBrowser.Controller.Entities.Audio /// Gets a value indicating whether this instance is owned item. /// </summary> /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value> + [IgnoreDataMember] public override bool IsOwnedItem { get @@ -122,89 +125,53 @@ namespace MediaBrowser.Controller.Entities.Audio public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken) { - var items = RecursiveChildren.ToList(); + var items = GetRecursiveChildren().ToList(); var songs = items.OfType<Audio>().ToList(); var others = items.Except(songs).ToList(); var totalItems = songs.Count + others.Count; - var percentages = new Dictionary<Guid, double>(totalItems); - - var tasks = new List<Task>(); + var numComplete = 0; // Refresh songs foreach (var item in songs) { - if (tasks.Count >= 2) - { - await Task.WhenAll(tasks).ConfigureAwait(false); - tasks.Clear(); - } - cancellationToken.ThrowIfCancellationRequested(); - var innerProgress = new ActionableProgress<double>(); - // Avoid implicitly captured closure - var currentChild = item; - innerProgress.RegisterAction(p => - { - lock (percentages) - { - percentages[currentChild.Id] = p / 100; - - var percent = percentages.Values.Sum(); - percent /= totalItems; - percent *= 100; - progress.Report(percent); - } - }); - - var taskChild = item; - tasks.Add(Task.Run(async () => await RefreshItem(taskChild, refreshOptions, innerProgress, cancellationToken).ConfigureAwait(false), cancellationToken)); - } + await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); - await Task.WhenAll(tasks).ConfigureAwait(false); - tasks.Clear(); + numComplete++; + double percent = numComplete; + percent /= totalItems; + progress.Report(percent * 100); + } // Refresh current item await RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); - + // Refresh all non-songs foreach (var item in others) { cancellationToken.ThrowIfCancellationRequested(); - // Avoid implicitly captured closure - var currentChild = item; - await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); - lock (percentages) - { - percentages[currentChild.Id] = 1; - var percent = percentages.Values.Sum(); - percent /= totalItems; - percent *= 100; - progress.Report(percent); - } + numComplete++; + double percent = numComplete; + percent /= totalItems; + progress.Report(percent * 100); } progress.Report(100); } - private async Task RefreshItem(BaseItem item, MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken) - { - await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); - - progress.Report(100); - } - public ArtistInfo GetLookupInfo() { var info = GetItemLookupInfo<ArtistInfo>(); - info.SongInfos = RecursiveChildren.OfType<Audio>() + info.SongInfos = GetRecursiveChildren(i => i is Audio) + .Cast<Audio>() .Select(i => i.GetLookupInfo()) .ToList(); @@ -213,9 +180,16 @@ namespace MediaBrowser.Controller.Entities.Audio public IEnumerable<BaseItem> GetTaggedItems(IEnumerable<BaseItem> inputItems) { - return inputItems.OfType<IHasArtist>() - .Where(i => i.HasArtist(Name)) - .Cast<BaseItem>(); + return inputItems.Where(GetItemFilter()); + } + + public Func<BaseItem, bool> GetItemFilter() + { + return i => + { + var hasArtist = i as IHasArtist; + return hasArtist != null && hasArtist.HasArtist(Name); + }; } } } diff --git a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs index 928eb6463..9689d7cce 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs @@ -14,7 +14,7 @@ namespace MediaBrowser.Controller.Entities.Audio /// Gets the user data key. /// </summary> /// <returns>System.String.</returns> - public override string GetUserDataKey() + protected override string CreateUserDataKey() { return "MusicGenre-" + Name; } @@ -30,6 +30,7 @@ namespace MediaBrowser.Controller.Entities.Audio /// If the item is a folder, it returns the folder itself /// </summary> /// <value>The containing folder path.</value> + [IgnoreDataMember] public override string ContainingFolderPath { get @@ -42,6 +43,7 @@ namespace MediaBrowser.Controller.Entities.Audio /// Gets a value indicating whether this instance is owned item. /// </summary> /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value> + [IgnoreDataMember] public override bool IsOwnedItem { get @@ -52,7 +54,12 @@ namespace MediaBrowser.Controller.Entities.Audio public IEnumerable<BaseItem> GetTaggedItems(IEnumerable<BaseItem> inputItems) { - return inputItems.Where(i => (i is IHasMusicGenres) && i.Genres.Contains(Name, StringComparer.OrdinalIgnoreCase)); + return inputItems.Where(GetItemFilter()); + } + + public Func<BaseItem, bool> GetItemFilter() + { + return i => (i is IHasMusicGenres) && i.Genres.Contains(Name, StringComparer.OrdinalIgnoreCase); } } } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index ee562d8b4..1e46aa9e5 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -359,7 +359,7 @@ namespace MediaBrowser.Controller.Entities { get { - if (!string.IsNullOrEmpty(ForcedSortName)) + if (!string.IsNullOrWhiteSpace(ForcedSortName)) { return ForcedSortName; } @@ -379,21 +379,19 @@ namespace MediaBrowser.Controller.Entities public string GetInternalMetadataPath() { - return GetInternalMetadataPath(ConfigurationManager.ApplicationPaths.InternalMetadataPath); + var basePath = ConfigurationManager.ApplicationPaths.InternalMetadataPath; + + return GetInternalMetadataPath(basePath); } protected virtual string GetInternalMetadataPath(string basePath) { var idString = Id.ToString("N"); - return System.IO.Path.Combine(basePath, idString.Substring(0, 2), idString); - } - - public static string GetInternalMetadataPathForId(Guid id) - { - var idString = id.ToString("N"); - - var basePath = ConfigurationManager.ApplicationPaths.InternalMetadataPath; + if (ConfigurationManager.Configuration.EnableLibraryMetadataSubFolder) + { + basePath = System.IO.Path.Combine(basePath, "library"); + } return System.IO.Path.Combine(basePath, idString.Substring(0, 2), idString); } @@ -692,7 +690,7 @@ namespace MediaBrowser.Controller.Entities var requiresSave = false; - if (IsFolder || Parent != null) + if (SupportsOwnedItems) { try { @@ -724,6 +722,12 @@ namespace MediaBrowser.Controller.Entities } } + [IgnoreDataMember] + protected virtual bool SupportsOwnedItems + { + get { return IsFolder || Parent != null; } + } + /// <summary> /// Refreshes owned items such as trailers, theme videos, special features, etc. /// Returns true or false indicating if changes were found. @@ -889,11 +893,24 @@ namespace MediaBrowser.Controller.Entities get { return null; } } + private string _userDataKey; /// <summary> /// Gets the user data key. /// </summary> /// <returns>System.String.</returns> - public virtual string GetUserDataKey() + public string GetUserDataKey() + { + if (string.IsNullOrWhiteSpace(_userDataKey)) + { + var key = CreateUserDataKey(); + _userDataKey = key; + return key; + } + + return _userDataKey; + } + + protected virtual string CreateUserDataKey() { return Id.ToString(); } @@ -905,6 +922,12 @@ namespace MediaBrowser.Controller.Entities return current.IsInMixedFolder == newItem.IsInMixedFolder; } + public void AfterMetadataRefresh() + { + _sortName = null; + _userDataKey = null; + } + /// <summary> /// Gets the preferred metadata language. /// </summary> @@ -1146,7 +1169,7 @@ namespace MediaBrowser.Controller.Entities if (!string.IsNullOrWhiteSpace(info.ItemName) && !string.IsNullOrWhiteSpace(info.ItemType)) { - return LibraryManager.RootFolder.RecursiveChildren.FirstOrDefault(i => + return LibraryManager.RootFolder.GetRecursiveChildren(i => { if (string.Equals(i.Name, info.ItemName, StringComparison.OrdinalIgnoreCase)) { @@ -1164,7 +1187,8 @@ namespace MediaBrowser.Controller.Entities } return false; - }); + + }).FirstOrDefault(); } return null; @@ -1458,7 +1482,7 @@ namespace MediaBrowser.Controller.Entities currentFile.Attributes &= ~FileAttributes.Hidden; } - currentFile.Delete(); + FileSystem.DeleteFile(currentFile.FullName); } return UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None); @@ -1703,6 +1727,9 @@ namespace MediaBrowser.Controller.Entities /// </summary> public virtual bool BeforeMetadataRefresh() { + _userDataKey = null; + _sortName = null; + var hasChanges = false; if (string.IsNullOrEmpty(Name) && !string.IsNullOrEmpty(Path)) diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs index f47a439a7..f82934a51 100644 --- a/MediaBrowser.Controller/Entities/CollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs @@ -86,7 +86,7 @@ namespace MediaBrowser.Controller.Entities { var path = ContainingFolderPath; - var args = new ItemResolveArgs(ConfigurationManager.ApplicationPaths, LibraryManager, directoryService) + var args = new ItemResolveArgs(ConfigurationManager.ApplicationPaths, directoryService) { FileInfo = new DirectoryInfo(path), Path = path, @@ -121,12 +121,6 @@ namespace MediaBrowser.Controller.Entities return args; } - // Cache this since it will be used a lot - /// <summary> - /// The null task result - /// </summary> - private static readonly Task NullTaskResult = Task.FromResult<object>(null); - /// <summary> /// Compare our current children (presumably just read from the repo) with the current state of the file system and adjust for any changes /// ***Currently does not contain logic to maintain items that are unavailable in the file system*** @@ -138,7 +132,7 @@ namespace MediaBrowser.Controller.Entities /// <param name="refreshOptions">The refresh options.</param> /// <param name="directoryService">The directory service.</param> /// <returns>Task.</returns> - protected override async Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService) + protected override Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService) { var list = PhysicalLocationsList.ToList(); @@ -146,8 +140,10 @@ namespace MediaBrowser.Controller.Entities if (!list.SequenceEqual(PhysicalLocationsList)) { - await UpdateToRepository(ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false); + return UpdateToRepository(ItemUpdateType.MetadataImport, cancellationToken); } + + return Task.FromResult(true); } /// <summary> diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 2761aa5d7..a4f8955d0 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -6,7 +6,6 @@ using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; -using MoreLinq; using System; using System.Collections; using System.Collections.Generic; @@ -21,7 +20,7 @@ namespace MediaBrowser.Controller.Entities /// <summary> /// Class Folder /// </summary> - public class Folder : BaseItem, IHasThemeMedia, IHasTags + public class Folder : BaseItem, IHasThemeMedia, IHasTags, IHasPreferredMetadataLanguage { public static IUserManager UserManager { get; set; } public static IUserViewManager UserViewManager { get; set; } @@ -30,6 +29,14 @@ namespace MediaBrowser.Controller.Entities public List<Guid> ThemeVideoIds { get; set; } public List<string> Tags { get; set; } + public string PreferredMetadataLanguage { get; set; } + + /// <summary> + /// Gets or sets the preferred metadata country code. + /// </summary> + /// <value>The preferred metadata country code.</value> + public string PreferredMetadataCountryCode { get; set; } + public Folder() { LinkedChildren = new List<LinkedChild>(); @@ -98,6 +105,7 @@ namespace MediaBrowser.Controller.Entities public virtual List<LinkedChild> LinkedChildren { get; set; } + [IgnoreDataMember] protected virtual bool SupportsShortcutChildren { get { return true; } @@ -275,7 +283,17 @@ namespace MediaBrowser.Controller.Entities { get { - return _children ?? (_children = LoadChildrenInternal()); + if (_children == null) + { + lock (_childrenSyncLock) + { + if (_children == null) + { + _children = LoadChildrenInternal(); + } + } + } + return _children; } } @@ -301,14 +319,24 @@ namespace MediaBrowser.Controller.Entities public override bool IsVisible(User user) { - if (this is ICollectionFolder) + if (this is ICollectionFolder && !(this is BasePluginFolder)) { - if (user.Policy.BlockedMediaFolders.Contains(Id.ToString("N"), StringComparer.OrdinalIgnoreCase) || + if (user.Policy.BlockedMediaFolders != null) + { + if (user.Policy.BlockedMediaFolders.Contains(Id.ToString("N"), StringComparer.OrdinalIgnoreCase) || - // Backwards compatibility - user.Policy.BlockedMediaFolders.Contains(Name, StringComparer.OrdinalIgnoreCase)) + // Backwards compatibility + user.Policy.BlockedMediaFolders.Contains(Name, StringComparer.OrdinalIgnoreCase)) + { + return false; + } + } + else { - return false; + if (!user.Policy.EnableAllFolders && !user.Policy.EnabledFolders.Contains(Id.ToString("N"), StringComparer.OrdinalIgnoreCase)) + { + return false; + } } } @@ -345,12 +373,7 @@ namespace MediaBrowser.Controller.Entities /// <returns>Task.</returns> public Task ValidateChildren(IProgress<double> progress, CancellationToken cancellationToken, MetadataRefreshOptions metadataRefreshOptions, bool recursive = true) { - return ValidateChildrenWithCancellationSupport(progress, cancellationToken, recursive, true, metadataRefreshOptions, metadataRefreshOptions.DirectoryService); - } - - private Task ValidateChildrenWithCancellationSupport(IProgress<double> progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService) - { - return ValidateChildrenInternal(progress, cancellationToken, recursive, refreshChildMetadata, refreshOptions, directoryService); + return ValidateChildrenInternal(progress, cancellationToken, recursive, true, metadataRefreshOptions, metadataRefreshOptions.DirectoryService); } private Dictionary<Guid, BaseItem> GetActualChildrenDictionary() @@ -540,50 +563,49 @@ namespace MediaBrowser.Controller.Entities var children = ActualChildren.ToList(); var percentages = new Dictionary<Guid, double>(children.Count); - - var tasks = new List<Task>(); + var numComplete = 0; + var count = children.Count; foreach (var child in children) { - if (tasks.Count >= 2) - { - await Task.WhenAll(tasks).ConfigureAwait(false); - tasks.Clear(); - } - cancellationToken.ThrowIfCancellationRequested(); - var innerProgress = new ActionableProgress<double>(); - // Avoid implicitly captured closure - var currentChild = child; - innerProgress.RegisterAction(p => + if (child.IsFolder) { - lock (percentages) + var innerProgress = new ActionableProgress<double>(); + + // Avoid implicitly captured closure + var currentChild = child; + innerProgress.RegisterAction(p => { - percentages[currentChild.Id] = p / 100; + lock (percentages) + { + percentages[currentChild.Id] = p / 100; - var percent = percentages.Values.Sum(); - percent /= children.Count; - percent *= 100; - progress.Report(percent); - } - }); + var innerPercent = percentages.Values.Sum(); + innerPercent /= count; + innerPercent *= 100; + progress.Report(innerPercent); + } + }); - if (child.IsFolder) - { await RefreshChildMetadata(child, refreshOptions, recursive, innerProgress, cancellationToken) .ConfigureAwait(false); } else { - // Avoid implicitly captured closure - var taskChild = child; - - tasks.Add(Task.Run(async () => await RefreshChildMetadata(taskChild, refreshOptions, false, innerProgress, cancellationToken).ConfigureAwait(false), cancellationToken)); + await RefreshChildMetadata(child, refreshOptions, false, new Progress<double>(), cancellationToken) + .ConfigureAwait(false); } + + numComplete++; + double percent = numComplete; + percent /= count; + percent *= 100; + + progress.Report(percent); } - await Task.WhenAll(tasks).ConfigureAwait(false); progress.Report(100); } @@ -648,7 +670,7 @@ namespace MediaBrowser.Controller.Entities } }); - await child.ValidateChildrenWithCancellationSupport(innerProgress, cancellationToken, true, false, null, directoryService) + await child.ValidateChildrenInternal(innerProgress, cancellationToken, true, false, null, directoryService) .ConfigureAwait(false); } } @@ -678,12 +700,12 @@ namespace MediaBrowser.Controller.Entities path = System.IO.Path.GetDirectoryName(path); } - if (ContainsPath(LibraryManager.GetDefaultVirtualFolders(), originalPath)) + if (ContainsPath(LibraryManager.GetVirtualFolders(), originalPath)) { return true; } - return UserManager.Users.Any(user => ContainsPath(LibraryManager.GetVirtualFolders(user), originalPath)); + return ContainsPath(LibraryManager.GetVirtualFolders(), originalPath); } /// <summary> @@ -731,28 +753,6 @@ namespace MediaBrowser.Controller.Entities return childrenItems; } - /// <summary> - /// Retrieves the child. - /// </summary> - /// <param name="child">The child.</param> - /// <returns>BaseItem.</returns> - private BaseItem RetrieveChild(Guid child) - { - var item = LibraryManager.GetItemById(child); - - if (item != null) - { - if (item is IByReferenceItem) - { - return LibraryManager.GetOrAddByReferenceItem(item); - } - - item.Parent = this; - } - - return item; - } - private BaseItem RetrieveChild(BaseItem child) { if (child.Id == Guid.Empty) @@ -786,18 +786,20 @@ namespace MediaBrowser.Controller.Entities { var user = query.User; + Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager); + var items = query.Recursive - ? GetRecursiveChildren(user) - : GetChildren(user, true); + ? GetRecursiveChildren(user, filter) + : GetChildren(user, true).Where(filter); - var result = SortAndFilter(items, query); + var result = PostFilterAndSort(items, query); return Task.FromResult(result); } - protected QueryResult<BaseItem> SortAndFilter(IEnumerable<BaseItem> items, InternalItemsQuery query) + protected QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items, InternalItemsQuery query) { - return UserViewBuilder.SortAndFilter(items, this, null, query, LibraryManager, UserDataManager); + return UserViewBuilder.PostFilterAndSort(items, this, null, query, LibraryManager); } /// <summary> @@ -822,11 +824,11 @@ namespace MediaBrowser.Controller.Entities //the true root should return our users root folder children if (IsPhysicalRoot) return user.RootFolder.GetChildren(user, includeLinkedChildren); - var list = new List<BaseItem>(); + var result = new Dictionary<Guid, BaseItem>(); - var hasLinkedChildren = AddChildrenToList(user, includeLinkedChildren, list, includeHidden, false); + AddChildren(user, includeLinkedChildren, result, includeHidden, false, null); - return hasLinkedChildren ? list.DistinctBy(i => i.Id).ToList() : list; + return result.Values; } protected virtual IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user) @@ -839,31 +841,30 @@ namespace MediaBrowser.Controller.Entities /// </summary> /// <param name="user">The user.</param> /// <param name="includeLinkedChildren">if set to <c>true</c> [include linked children].</param> - /// <param name="list">The list.</param> + /// <param name="result">The result.</param> /// <param name="includeHidden">if set to <c>true</c> [include hidden].</param> /// <param name="recursive">if set to <c>true</c> [recursive].</param> + /// <param name="filter">The filter.</param> /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> - private bool AddChildrenToList(User user, bool includeLinkedChildren, List<BaseItem> list, bool includeHidden, bool recursive) + private void AddChildren(User user, bool includeLinkedChildren, Dictionary<Guid, BaseItem> result, bool includeHidden, bool recursive, Func<BaseItem, bool> filter) { - var hasLinkedChildren = false; - foreach (var child in GetEligibleChildrenForRecursiveChildren(user)) { if (child.IsVisible(user)) { if (includeHidden || !child.IsHiddenFromUser(user)) { - list.Add(child); + if (filter == null || filter(child)) + { + result[child.Id] = child; + } } if (recursive && child.IsFolder) { var folder = (Folder)child; - if (folder.AddChildrenToList(user, includeLinkedChildren, list, includeHidden, true)) - { - hasLinkedChildren = true; - } + folder.AddChildren(user, includeLinkedChildren, result, includeHidden, true, filter); } } } @@ -874,14 +875,13 @@ namespace MediaBrowser.Controller.Entities { if (child.IsVisible(user)) { - hasLinkedChildren = true; - - list.Add(child); + if (filter == null || filter(child)) + { + result[child.Id] = child; + } } } } - - return hasLinkedChildren; } /// <summary> @@ -891,18 +891,23 @@ namespace MediaBrowser.Controller.Entities /// <param name="includeLinkedChildren">if set to <c>true</c> [include linked children].</param> /// <returns>IEnumerable{BaseItem}.</returns> /// <exception cref="System.ArgumentNullException"></exception> - public virtual IEnumerable<BaseItem> GetRecursiveChildren(User user, bool includeLinkedChildren = true) + public IEnumerable<BaseItem> GetRecursiveChildren(User user, bool includeLinkedChildren = true) + { + return GetRecursiveChildren(user, i => true); + } + + public virtual IEnumerable<BaseItem> GetRecursiveChildren(User user, Func<BaseItem, bool> filter) { if (user == null) { throw new ArgumentNullException("user"); } - var list = new List<BaseItem>(); + var result = new Dictionary<Guid, BaseItem>(); - var hasLinkedChildren = AddChildrenToList(user, includeLinkedChildren, list, false, true); + AddChildren(user, true, result, false, true, filter); - return hasLinkedChildren ? list.DistinctBy(i => i.Id).ToList() : list; + return result.Values; } /// <summary> @@ -911,9 +916,14 @@ namespace MediaBrowser.Controller.Entities /// <returns>IList{BaseItem}.</returns> public IList<BaseItem> GetRecursiveChildren() { + return GetRecursiveChildren(i => true); + } + + public IList<BaseItem> GetRecursiveChildren(Func<BaseItem, bool> filter) + { var list = new List<BaseItem>(); - AddChildrenToList(list, true, null); + AddChildrenToList(list, true, filter); return list; } @@ -1022,6 +1032,15 @@ namespace MediaBrowser.Controller.Entities .Where(i => i.Item2 != null); } + [IgnoreDataMember] + protected override bool SupportsOwnedItems + { + get + { + return base.SupportsOwnedItems || SupportsShortcutChildren; + } + } + protected override async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemInfo> fileSystemChildren, CancellationToken cancellationToken) { var changesFound = false; @@ -1126,8 +1145,7 @@ namespace MediaBrowser.Controller.Entities bool resetPosition) { // Sweep through recursively and update status - var tasks = GetRecursiveChildren(user, true) - .Where(i => !i.IsFolder && i.LocationType != LocationType.Virtual) + var tasks = GetRecursiveChildren(user, i => !i.IsFolder && i.LocationType != LocationType.Virtual) .Select(c => c.MarkPlayed(user, datePlayed, resetPosition)); await Task.WhenAll(tasks).ConfigureAwait(false); @@ -1141,8 +1159,7 @@ namespace MediaBrowser.Controller.Entities public override async Task MarkUnplayed(User user) { // Sweep through recursively and update status - var tasks = GetRecursiveChildren(user, true) - .Where(i => !i.IsFolder && i.LocationType != LocationType.Virtual) + var tasks = GetRecursiveChildren(user, i => !i.IsFolder && i.LocationType != LocationType.Virtual) .Select(c => c.MarkUnplayed(user)); await Task.WhenAll(tasks).ConfigureAwait(false); @@ -1171,15 +1188,15 @@ namespace MediaBrowser.Controller.Entities return this; } - return RecursiveChildren.FirstOrDefault(i => string.Equals(i.Path, path, StringComparison.OrdinalIgnoreCase) || + return GetRecursiveChildren(i => string.Equals(i.Path, path, StringComparison.OrdinalIgnoreCase) || (!i.IsFolder && !i.IsInMixedFolder && string.Equals(i.ContainingFolderPath, path, StringComparison.OrdinalIgnoreCase)) || - i.PhysicalLocations.Contains(path, StringComparer.OrdinalIgnoreCase)); + i.PhysicalLocations.Contains(path, StringComparer.OrdinalIgnoreCase)) + .FirstOrDefault(); } public override bool IsPlayed(User user) { - return GetRecursiveChildren(user) - .Where(i => !i.IsFolder && i.LocationType != LocationType.Virtual) + return GetRecursiveChildren(user, i => !i.IsFolder && i.LocationType != LocationType.Virtual) .All(i => i.IsPlayed(user)); } @@ -1206,8 +1223,7 @@ namespace MediaBrowser.Controller.Entities } else { - children = folder.GetRecursiveChildren(user) - .Where(i => !i.IsFolder && i.LocationType != LocationType.Virtual); + children = folder.GetRecursiveChildren(user, i => !i.IsFolder && i.LocationType != LocationType.Virtual); } // Loop through each recursive child diff --git a/MediaBrowser.Controller/Entities/Game.cs b/MediaBrowser.Controller/Entities/Game.cs index bf32d3e63..71642ea90 100644 --- a/MediaBrowser.Controller/Entities/Game.cs +++ b/MediaBrowser.Controller/Entities/Game.cs @@ -88,7 +88,7 @@ namespace MediaBrowser.Controller.Entities /// </summary> public List<string> MultiPartGameFiles { get; set; } - public override string GetUserDataKey() + protected override string CreateUserDataKey() { var id = this.GetProviderId(MetadataProviders.Gamesdb); @@ -96,7 +96,7 @@ namespace MediaBrowser.Controller.Entities { return "Game-Gamesdb-" + id; } - return base.GetUserDataKey(); + return base.CreateUserDataKey(); } public override IEnumerable<string> GetDeletePaths() diff --git a/MediaBrowser.Controller/Entities/GameGenre.cs b/MediaBrowser.Controller/Entities/GameGenre.cs index 825468954..41ce0c12a 100644 --- a/MediaBrowser.Controller/Entities/GameGenre.cs +++ b/MediaBrowser.Controller/Entities/GameGenre.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.Serialization; namespace MediaBrowser.Controller.Entities { @@ -10,7 +11,7 @@ namespace MediaBrowser.Controller.Entities /// Gets the user data key. /// </summary> /// <returns>System.String.</returns> - public override string GetUserDataKey() + protected override string CreateUserDataKey() { return "GameGenre-" + Name; } @@ -20,6 +21,7 @@ namespace MediaBrowser.Controller.Entities /// If the item is a folder, it returns the folder itself /// </summary> /// <value>The containing folder path.</value> + [IgnoreDataMember] public override string ContainingFolderPath { get @@ -32,6 +34,7 @@ namespace MediaBrowser.Controller.Entities /// Gets a value indicating whether this instance is owned item. /// </summary> /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value> + [IgnoreDataMember] public override bool IsOwnedItem { get @@ -42,7 +45,12 @@ namespace MediaBrowser.Controller.Entities public IEnumerable<BaseItem> GetTaggedItems(IEnumerable<BaseItem> inputItems) { - return inputItems.Where(i => (i is Game) && i.Genres.Contains(Name, StringComparer.OrdinalIgnoreCase)); + return inputItems.Where(GetItemFilter()); + } + + public Func<BaseItem, bool> GetItemFilter() + { + return i => (i is Game) && i.Genres.Contains(Name, StringComparer.OrdinalIgnoreCase); } } } diff --git a/MediaBrowser.Controller/Entities/GameSystem.cs b/MediaBrowser.Controller/Entities/GameSystem.cs index 758498977..cf6916763 100644 --- a/MediaBrowser.Controller/Entities/GameSystem.cs +++ b/MediaBrowser.Controller/Entities/GameSystem.cs @@ -35,13 +35,13 @@ namespace MediaBrowser.Controller.Entities /// Gets the user data key. /// </summary> /// <returns>System.String.</returns> - public override string GetUserDataKey() + protected override string CreateUserDataKey() { if (!string.IsNullOrEmpty(GameSystemName)) { return "GameSystem-" + GameSystemName; } - return base.GetUserDataKey(); + return base.CreateUserDataKey(); } protected override bool GetBlockUnratedValue(UserPolicy config) diff --git a/MediaBrowser.Controller/Entities/Genre.cs b/MediaBrowser.Controller/Entities/Genre.cs index 05442f2b7..f581c55e8 100644 --- a/MediaBrowser.Controller/Entities/Genre.cs +++ b/MediaBrowser.Controller/Entities/Genre.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Controller.Entities.Audio; +using System.Runtime.Serialization; +using MediaBrowser.Controller.Entities.Audio; using System; using System.Collections.Generic; using System.Linq; @@ -14,7 +15,7 @@ namespace MediaBrowser.Controller.Entities /// Gets the user data key. /// </summary> /// <returns>System.String.</returns> - public override string GetUserDataKey() + protected override string CreateUserDataKey() { return "Genre-" + Name; } @@ -24,6 +25,7 @@ namespace MediaBrowser.Controller.Entities /// If the item is a folder, it returns the folder itself /// </summary> /// <value>The containing folder path.</value> + [IgnoreDataMember] public override string ContainingFolderPath { get @@ -36,6 +38,7 @@ namespace MediaBrowser.Controller.Entities /// Gets a value indicating whether this instance is owned item. /// </summary> /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value> + [IgnoreDataMember] public override bool IsOwnedItem { get @@ -46,7 +49,12 @@ namespace MediaBrowser.Controller.Entities public IEnumerable<BaseItem> GetTaggedItems(IEnumerable<BaseItem> inputItems) { - return inputItems.Where(i => !(i is Game) && !(i is IHasMusicGenres) && i.Genres.Contains(Name, StringComparer.OrdinalIgnoreCase)); + return inputItems.Where(GetItemFilter()); + } + + public Func<BaseItem, bool> GetItemFilter() + { + return i => !(i is Game) && !(i is IHasMusicGenres) && i.Genres.Contains(Name, StringComparer.OrdinalIgnoreCase); } } } diff --git a/MediaBrowser.Controller/Entities/IHasMetadata.cs b/MediaBrowser.Controller/Entities/IHasMetadata.cs index 10ddaa474..3643c58b3 100644 --- a/MediaBrowser.Controller/Entities/IHasMetadata.cs +++ b/MediaBrowser.Controller/Entities/IHasMetadata.cs @@ -54,5 +54,10 @@ namespace MediaBrowser.Controller.Entities /// Gets the item identities. /// </summary> List<IItemIdentity> Identities { get; set; } + + /// <summary> + /// Afters the metadata refresh. + /// </summary> + void AfterMetadataRefresh(); } } diff --git a/MediaBrowser.Controller/Entities/IItemByName.cs b/MediaBrowser.Controller/Entities/IItemByName.cs index 70d5b840f..b48ad788f 100644 --- a/MediaBrowser.Controller/Entities/IItemByName.cs +++ b/MediaBrowser.Controller/Entities/IItemByName.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; namespace MediaBrowser.Controller.Entities { @@ -13,6 +14,8 @@ namespace MediaBrowser.Controller.Entities /// <param name="inputItems">The input items.</param> /// <returns>IEnumerable{BaseItem}.</returns> IEnumerable<BaseItem> GetTaggedItems(IEnumerable<BaseItem> inputItems); + + Func<BaseItem, bool> GetItemFilter(); } public interface IHasDualAccess : IItemByName diff --git a/MediaBrowser.Controller/Entities/ISupportsBoxSetGrouping.cs b/MediaBrowser.Controller/Entities/ISupportsBoxSetGrouping.cs index 0fd463155..fbe5a06d0 100644 --- a/MediaBrowser.Controller/Entities/ISupportsBoxSetGrouping.cs +++ b/MediaBrowser.Controller/Entities/ISupportsBoxSetGrouping.cs @@ -1,6 +1,4 @@ -using System; -using System.Collections.Generic; - + namespace MediaBrowser.Controller.Entities { /// <summary> @@ -10,10 +8,5 @@ namespace MediaBrowser.Controller.Entities /// </summary> public interface ISupportsBoxSetGrouping { - /// <summary> - /// Gets or sets the box set identifier list. - /// </summary> - /// <value>The box set identifier list.</value> - List<Guid> BoxSetIdList { get; set; } } } diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index 30043682d..e99c11e87 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -17,7 +17,7 @@ namespace MediaBrowser.Controller.Entities public User User { get; set; } - public Func<BaseItem, User, bool> Filter { get; set; } + public Func<BaseItem, bool> Filter { get; set; } public bool? IsFolder { get; set; } public bool? IsFavorite { get; set; } diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs index 4483c7b0f..7f74e3379 100644 --- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs +++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs @@ -1,22 +1,22 @@ -using MediaBrowser.Common.Progress; +using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; +using MediaBrowser.Model.Users; using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Model.Users; namespace MediaBrowser.Controller.Entities.Movies { /// <summary> /// Class BoxSet /// </summary> - public class BoxSet : Folder, IHasTrailers, IHasKeywords, IHasPreferredMetadataLanguage, IHasDisplayOrder, IHasLookupInfo<BoxSetInfo>, IMetadataContainer, IHasShares + public class BoxSet : Folder, IHasTrailers, IHasKeywords, IHasDisplayOrder, IHasLookupInfo<BoxSetInfo>, IMetadataContainer, IHasShares { public List<Share> Shares { get; set; } @@ -54,14 +54,6 @@ namespace MediaBrowser.Controller.Entities.Movies /// <value>The tags.</value> public List<string> Keywords { get; set; } - public string PreferredMetadataLanguage { get; set; } - - /// <summary> - /// Gets or sets the preferred metadata country code. - /// </summary> - /// <value>The preferred metadata country code.</value> - public string PreferredMetadataCountryCode { get; set; } - /// <summary> /// Gets or sets the display order. /// </summary> @@ -93,6 +85,31 @@ namespace MediaBrowser.Controller.Entities.Movies return list; } + /// <summary> + /// Updates the official rating based on content and returns true or false indicating if it changed. + /// </summary> + /// <returns></returns> + public bool UpdateRatingToContent() + { + var currentOfficialRating = OfficialRating; + + // Gather all possible ratings + var ratings = GetRecursiveChildren() + .Concat(GetLinkedChildren()) + .Where(i => i is Movie || i is Series) + .Select(i => i.OfficialRating) + .Where(i => !string.IsNullOrEmpty(i)) + .Distinct(StringComparer.OrdinalIgnoreCase) + .Select(i => new Tuple<string, int?>(i, LocalizationManager.GetRatingLevel(i))) + .OrderBy(i => i.Item2 ?? 1000) + .Select(i => i.Item1); + + OfficialRating = ratings.FirstOrDefault() ?? currentOfficialRating; + + return !string.Equals(currentOfficialRating ?? string.Empty, OfficialRating ?? string.Empty, + StringComparison.OrdinalIgnoreCase); + } + public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren) { var children = base.GetChildren(user, includeLinkedChildren); @@ -122,34 +139,22 @@ namespace MediaBrowser.Controller.Entities.Movies { // Refresh bottom up, children first, then the boxset // By then hopefully the movies within will have Tmdb collection values - var items = RecursiveChildren.ToList(); + var items = GetRecursiveChildren().ToList(); var totalItems = items.Count; - var percentages = new Dictionary<Guid, double>(totalItems); + var numComplete = 0; // Refresh songs foreach (var item in items) { cancellationToken.ThrowIfCancellationRequested(); - var innerProgress = new ActionableProgress<double>(); - // Avoid implicitly captured closure - var currentChild = item; - innerProgress.RegisterAction(p => - { - lock (percentages) - { - percentages[currentChild.Id] = p / 100; - - var percent = percentages.Values.Sum(); - percent /= totalItems; - percent *= 100; - progress.Report(percent); - } - }); - - // Avoid implicitly captured closure - await RefreshItem(item, refreshOptions, innerProgress, cancellationToken).ConfigureAwait(false); + await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); + + numComplete++; + double percent = numComplete; + percent /= totalItems; + progress.Report(percent * 100); } // Refresh current item @@ -158,13 +163,6 @@ namespace MediaBrowser.Controller.Entities.Movies progress.Report(100); } - private async Task RefreshItem(BaseItem item, MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken) - { - await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); - - progress.Report(100); - } - public override bool IsVisible(User user) { if (base.IsVisible(user)) diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs index b3774cfe0..cfe008bd7 100644 --- a/MediaBrowser.Controller/Entities/Movies/Movie.cs +++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs @@ -25,12 +25,6 @@ namespace MediaBrowser.Controller.Entities.Movies public List<Guid> ThemeVideoIds { get; set; } public List<string> ProductionLocations { get; set; } - /// <summary> - /// This is just a cache to enable quick access by Id - /// </summary> - [IgnoreDataMember] - public List<Guid> BoxSetIdList { get; set; } - public Movie() { SpecialFeatureIds = new List<Guid>(); @@ -40,7 +34,6 @@ namespace MediaBrowser.Controller.Entities.Movies RemoteTrailerIds = new List<Guid>(); ThemeSongIds = new List<Guid>(); ThemeVideoIds = new List<Guid>(); - BoxSetIdList = new List<Guid>(); Taglines = new List<string>(); Keywords = new List<string>(); ProductionLocations = new List<string>(); @@ -107,9 +100,9 @@ namespace MediaBrowser.Controller.Entities.Movies /// Gets the user data key. /// </summary> /// <returns>System.String.</returns> - public override string GetUserDataKey() + protected override string CreateUserDataKey() { - return this.GetProviderId(MetadataProviders.Tmdb) ?? this.GetProviderId(MetadataProviders.Imdb) ?? base.GetUserDataKey(); + return this.GetProviderId(MetadataProviders.Tmdb) ?? this.GetProviderId(MetadataProviders.Imdb) ?? base.CreateUserDataKey(); } protected override async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemInfo> fileSystemChildren, CancellationToken cancellationToken) diff --git a/MediaBrowser.Controller/Entities/MusicVideo.cs b/MediaBrowser.Controller/Entities/MusicVideo.cs index 4ca8cf1c5..771c62fd6 100644 --- a/MediaBrowser.Controller/Entities/MusicVideo.cs +++ b/MediaBrowser.Controller/Entities/MusicVideo.cs @@ -48,21 +48,6 @@ namespace MediaBrowser.Controller.Entities } /// <summary> - /// TODO: Remove - /// </summary> - public string Artist - { - get { return Artists.FirstOrDefault(); } - set - { - if (!string.IsNullOrEmpty(value) && !Artists.Contains(value, StringComparer.OrdinalIgnoreCase)) - { - Artists.Add(value); - } - } - } - - /// <summary> /// Determines whether the specified name has artist. /// </summary> /// <param name="name">The name.</param> @@ -76,9 +61,9 @@ namespace MediaBrowser.Controller.Entities /// Gets the user data key. /// </summary> /// <returns>System.String.</returns> - public override string GetUserDataKey() + protected override string CreateUserDataKey() { - return this.GetProviderId(MetadataProviders.Tmdb) ?? this.GetProviderId(MetadataProviders.Imdb) ?? base.GetUserDataKey(); + return this.GetProviderId(MetadataProviders.Tmdb) ?? this.GetProviderId(MetadataProviders.Imdb) ?? base.CreateUserDataKey(); } protected override bool GetBlockUnratedValue(UserPolicy config) diff --git a/MediaBrowser.Controller/Entities/Person.cs b/MediaBrowser.Controller/Entities/Person.cs index fe8d61836..25509b153 100644 --- a/MediaBrowser.Controller/Entities/Person.cs +++ b/MediaBrowser.Controller/Entities/Person.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Controller.Providers; +using System.Runtime.Serialization; +using MediaBrowser.Controller.Providers; using System; using System.Collections.Generic; using System.Linq; @@ -15,12 +16,12 @@ namespace MediaBrowser.Controller.Entities /// </summary> /// <value>The place of birth.</value> public string PlaceOfBirth { get; set; } - + /// <summary> /// Gets the user data key. /// </summary> /// <returns>System.String.</returns> - public override string GetUserDataKey() + protected override string CreateUserDataKey() { return "Person-" + Name; } @@ -35,6 +36,7 @@ namespace MediaBrowser.Controller.Entities /// If the item is a folder, it returns the folder itself /// </summary> /// <value>The containing folder path.</value> + [IgnoreDataMember] public override string ContainingFolderPath { get @@ -47,6 +49,7 @@ namespace MediaBrowser.Controller.Entities /// Gets a value indicating whether this instance is owned item. /// </summary> /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value> + [IgnoreDataMember] public override bool IsOwnedItem { get @@ -57,7 +60,13 @@ namespace MediaBrowser.Controller.Entities public IEnumerable<BaseItem> GetTaggedItems(IEnumerable<BaseItem> inputItems) { - return inputItems.Where(i => i.People.Any(p => string.Equals(p.Name, Name, StringComparison.OrdinalIgnoreCase))); + return inputItems.Where(GetItemFilter()); + } + + + public Func<BaseItem, bool> GetItemFilter() + { + return i => i.People.Any(p => string.Equals(p.Name, Name, StringComparison.OrdinalIgnoreCase)); } } diff --git a/MediaBrowser.Controller/Entities/Studio.cs b/MediaBrowser.Controller/Entities/Studio.cs index 0d934ad0a..76193d6c4 100644 --- a/MediaBrowser.Controller/Entities/Studio.cs +++ b/MediaBrowser.Controller/Entities/Studio.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.Serialization; namespace MediaBrowser.Controller.Entities { @@ -15,12 +16,12 @@ namespace MediaBrowser.Controller.Entities { Tags = new List<string>(); } - + /// <summary> /// Gets the user data key. /// </summary> /// <returns>System.String.</returns> - public override string GetUserDataKey() + protected override string CreateUserDataKey() { return "Studio-" + Name; } @@ -30,6 +31,7 @@ namespace MediaBrowser.Controller.Entities /// If the item is a folder, it returns the folder itself /// </summary> /// <value>The containing folder path.</value> + [IgnoreDataMember] public override string ContainingFolderPath { get @@ -42,6 +44,7 @@ namespace MediaBrowser.Controller.Entities /// Gets a value indicating whether this instance is owned item. /// </summary> /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value> + [IgnoreDataMember] public override bool IsOwnedItem { get @@ -52,7 +55,13 @@ namespace MediaBrowser.Controller.Entities public IEnumerable<BaseItem> GetTaggedItems(IEnumerable<BaseItem> inputItems) { - return inputItems.Where(i => i.Studios.Contains(Name, StringComparer.OrdinalIgnoreCase)); + return inputItems.Where(GetItemFilter()); + } + + + public Func<BaseItem, bool> GetItemFilter() + { + return i => i.Studios.Contains(Name, StringComparer.OrdinalIgnoreCase); } } } diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs index 6b67cebc8..c8408365d 100644 --- a/MediaBrowser.Controller/Entities/TV/Episode.cs +++ b/MediaBrowser.Controller/Entities/TV/Episode.cs @@ -56,6 +56,15 @@ namespace MediaBrowser.Controller.Entities.TV } [IgnoreDataMember] + protected override bool SupportsOwnedItems + { + get + { + return IsStacked || MediaSourceCount > 1; + } + } + + [IgnoreDataMember] public int? AiredSeasonNumber { get @@ -117,7 +126,7 @@ namespace MediaBrowser.Controller.Entities.TV /// Gets the user data key. /// </summary> /// <returns>System.String.</returns> - public override string GetUserDataKey() + protected override string CreateUserDataKey() { var series = Series; @@ -126,7 +135,7 @@ namespace MediaBrowser.Controller.Entities.TV return series.GetUserDataKey() + ParentIndexNumber.Value.ToString("000") + IndexNumber.Value.ToString("000"); } - return base.GetUserDataKey(); + return base.CreateUserDataKey(); } /// <summary> diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs index 54db12b6f..f28306661 100644 --- a/MediaBrowser.Controller/Entities/TV/Season.cs +++ b/MediaBrowser.Controller/Entities/TV/Season.cs @@ -92,7 +92,7 @@ namespace MediaBrowser.Controller.Entities.TV /// Gets the user data key. /// </summary> /// <returns>System.String.</returns> - public override string GetUserDataKey() + protected override string CreateUserDataKey() { if (Series != null) { @@ -100,7 +100,7 @@ namespace MediaBrowser.Controller.Entities.TV return Series.GetUserDataKey() + seasonNo.ToString("000"); } - return base.GetUserDataKey(); + return base.CreateUserDataKey(); } /// <summary> @@ -244,7 +244,7 @@ namespace MediaBrowser.Controller.Entities.TV private IEnumerable<Episode> GetEpisodes() { - var episodes = RecursiveChildren.OfType<Episode>(); + var episodes = GetRecursiveChildren().OfType<Episode>(); var series = Series; if (series != null && series.ContainsEpisodesWithoutSeasonFolders) @@ -254,12 +254,12 @@ namespace MediaBrowser.Controller.Entities.TV if (seasonNumber.HasValue) { - list.AddRange(series.RecursiveChildren.OfType<Episode>() + list.AddRange(series.GetRecursiveChildren().OfType<Episode>() .Where(i => i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == seasonNumber.Value)); } else { - list.AddRange(series.RecursiveChildren.OfType<Episode>() + list.AddRange(series.GetRecursiveChildren().OfType<Episode>() .Where(i => !i.ParentIndexNumber.HasValue)); } diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index 55cfffeb2..8e96786d5 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -1,4 +1,6 @@ -using MediaBrowser.Controller.Localization; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Controller.Localization; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; @@ -14,7 +16,7 @@ namespace MediaBrowser.Controller.Entities.TV /// <summary> /// Class Series /// </summary> - public class Series : Folder, IHasSoundtracks, IHasTrailers, IHasPreferredMetadataLanguage, IHasDisplayOrder, IHasLookupInfo<SeriesInfo>, IHasSpecialFeatures + public class Series : Folder, IHasSoundtracks, IHasTrailers, IHasDisplayOrder, IHasLookupInfo<SeriesInfo>, IHasSpecialFeatures, IMetadataContainer { public List<Guid> SpecialFeatureIds { get; set; } public List<Guid> SoundtrackIds { get; set; } @@ -23,12 +25,6 @@ namespace MediaBrowser.Controller.Entities.TV public int? AnimeSeriesIndex { get; set; } - /// <summary> - /// Gets or sets the preferred metadata country code. - /// </summary> - /// <value>The preferred metadata country code.</value> - public string PreferredMetadataCountryCode { get; set; } - public Series() { AirDays = new List<DayOfWeek>(); @@ -93,7 +89,7 @@ namespace MediaBrowser.Controller.Entities.TV { get { - return RecursiveChildren.OfType<Episode>() + return GetRecursiveChildren(i => i is Episode) .Select(i => i.DateCreated) .OrderByDescending(i => i) .FirstOrDefault(); @@ -117,9 +113,9 @@ namespace MediaBrowser.Controller.Entities.TV /// Gets the user data key. /// </summary> /// <returns>System.String.</returns> - public override string GetUserDataKey() + protected override string CreateUserDataKey() { - return this.GetProviderId(MetadataProviders.Tvdb) ?? this.GetProviderId(MetadataProviders.Tvcom) ?? base.GetUserDataKey(); + return this.GetProviderId(MetadataProviders.Tvdb) ?? this.GetProviderId(MetadataProviders.Tvcom) ?? base.CreateUserDataKey(); } /// <summary> @@ -191,6 +187,80 @@ namespace MediaBrowser.Controller.Entities.TV .Cast<Season>(); } + public IEnumerable<Episode> GetEpisodes(User user) + { + var config = user.Configuration; + + var allEpisodes = GetSeasons(user, true, true) + .SelectMany(i => i.GetEpisodes(user, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes)) + .Reverse() + .ToList(); + + // Specials could appear twice based on above - once in season 0, once in the aired season + // This depends on settings for that series + // When this happens, remove the duplicate from season 0 + var returnList = new List<Episode>(); + + foreach (var episode in allEpisodes) + { + if (!returnList.Contains(episode)) + { + returnList.Insert(0, episode); + } + } + + return returnList; + } + + public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken) + { + // Refresh bottom up, children first, then the boxset + // By then hopefully the movies within will have Tmdb collection values + var items = GetRecursiveChildren().ToList(); + + var seasons = items.OfType<Season>().ToList(); + var otherItems = items.Except(seasons).ToList(); + + var totalItems = seasons.Count + otherItems.Count; + var numComplete = 0; + + refreshOptions = new MetadataRefreshOptions(refreshOptions); + refreshOptions.IsPostRecursiveRefresh = true; + + // Refresh songs + foreach (var item in seasons) + { + cancellationToken.ThrowIfCancellationRequested(); + + await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); + + numComplete++; + double percent = numComplete; + percent /= totalItems; + progress.Report(percent * 100); + } + + // Refresh current item + await RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); + + // Refresh all non-songs + foreach (var item in otherItems) + { + cancellationToken.ThrowIfCancellationRequested(); + + await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); + + numComplete++; + double percent = numComplete; + percent /= totalItems; + progress.Report(percent * 100); + } + + await ProviderManager.RefreshMetadata(this, refreshOptions, cancellationToken).ConfigureAwait(false); + + progress.Report(100); + } + public IEnumerable<Episode> GetEpisodes(User user, int seasonNumber) { var config = user.Configuration; @@ -206,8 +276,8 @@ namespace MediaBrowser.Controller.Entities.TV internal IEnumerable<Episode> GetEpisodes(User user, int seasonNumber, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes, IEnumerable<Episode> additionalEpisodes) { - var episodes = GetRecursiveChildren(user) - .OfType<Episode>(); + var episodes = GetRecursiveChildren(user, i => i is Episode) + .Cast<Episode>(); episodes = FilterEpisodesBySeason(episodes, seasonNumber, DisplaySpecialsWithSeasons); @@ -262,8 +332,6 @@ namespace MediaBrowser.Controller.Entities.TV return config.BlockUnratedItems.Contains(UnratedItem.Series); } - public string PreferredMetadataLanguage { get; set; } - public SeriesInfo GetLookupInfo() { var info = GetItemLookupInfo<SeriesInfo>(); diff --git a/MediaBrowser.Controller/Entities/Trailer.cs b/MediaBrowser.Controller/Entities/Trailer.cs index 7a1eef8db..522e6edf6 100644 --- a/MediaBrowser.Controller/Entities/Trailer.cs +++ b/MediaBrowser.Controller/Entities/Trailer.cs @@ -1,12 +1,12 @@ using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Users; using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Runtime.Serialization; -using MediaBrowser.Model.Users; namespace MediaBrowser.Controller.Entities { @@ -79,7 +79,7 @@ namespace MediaBrowser.Controller.Entities } } - public override string GetUserDataKey() + protected override string CreateUserDataKey() { var key = this.GetProviderId(MetadataProviders.Imdb) ?? this.GetProviderId(MetadataProviders.Tmdb); @@ -96,7 +96,7 @@ namespace MediaBrowser.Controller.Entities return key; } - return base.GetUserDataKey(); + return base.CreateUserDataKey(); } protected override bool GetBlockUnratedValue(UserPolicy config) diff --git a/MediaBrowser.Controller/Entities/User.cs b/MediaBrowser.Controller/Entities/User.cs index 626afcfdf..01a7486b3 100644 --- a/MediaBrowser.Controller/Entities/User.cs +++ b/MediaBrowser.Controller/Entities/User.cs @@ -32,7 +32,7 @@ namespace MediaBrowser.Controller.Entities /// </summary> /// <value>The password.</value> public string Password { get; set; } - public string LocalPassword { get; set; } + public string EasyPassword { get; set; } public string ConnectUserName { get; set; } public string ConnectUserId { get; set; } @@ -62,6 +62,7 @@ namespace MediaBrowser.Controller.Entities /// If the item is a folder, it returns the folder itself /// </summary> /// <value>The containing folder path.</value> + [IgnoreDataMember] public override string ContainingFolderPath { get @@ -74,6 +75,7 @@ namespace MediaBrowser.Controller.Entities /// Gets a value indicating whether this instance is owned item. /// </summary> /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value> + [IgnoreDataMember] public override bool IsOwnedItem { get @@ -166,7 +168,7 @@ namespace MediaBrowser.Controller.Entities } // If only the casing is changing, leave the file system alone - if (!UsesIdForConfigurationPath && !newName.Equals(Name, StringComparison.OrdinalIgnoreCase)) + if (!UsesIdForConfigurationPath && !string.Equals(newName, Name, StringComparison.OrdinalIgnoreCase)) { UsesIdForConfigurationPath = true; @@ -177,7 +179,7 @@ namespace MediaBrowser.Controller.Entities // Exceptions will be thrown if these paths already exist if (Directory.Exists(newConfigDirectory)) { - Directory.Delete(newConfigDirectory, true); + FileSystem.DeleteDirectory(newConfigDirectory, true); } if (Directory.Exists(oldConfigurationDirectory)) @@ -227,16 +229,16 @@ namespace MediaBrowser.Controller.Entities /// <returns>System.String.</returns> private string GetConfigurationDirectoryPath(string username) { - if (string.IsNullOrEmpty(username)) - { - throw new ArgumentNullException("username"); - } - var parentPath = ConfigurationManager.ApplicationPaths.UserConfigurationDirectoryPath; // Legacy if (!UsesIdForConfigurationPath) { + if (string.IsNullOrEmpty(username)) + { + throw new ArgumentNullException("username"); + } + var safeFolderName = FileSystem.GetValidFilename(username); return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.UserConfigurationDirectoryPath, safeFolderName); diff --git a/MediaBrowser.Controller/Entities/UserRootFolder.cs b/MediaBrowser.Controller/Entities/UserRootFolder.cs index a7276e262..b065ae171 100644 --- a/MediaBrowser.Controller/Entities/UserRootFolder.cs +++ b/MediaBrowser.Controller/Entities/UserRootFolder.cs @@ -18,10 +18,13 @@ namespace MediaBrowser.Controller.Entities { public override async Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query) { + var user = query.User; + Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager); + if (query.Recursive) { - var items = query.User.RootFolder.GetRecursiveChildren(query.User); - return SortAndFilter(items, query); + var items = query.User.RootFolder.GetRecursiveChildren(query.User, filter); + return PostFilterAndSort(items, query); } var result = await UserViewManager.GetUserViews(new UserViewQuery @@ -30,7 +33,7 @@ namespace MediaBrowser.Controller.Entities }, CancellationToken.None).ConfigureAwait(false); - return SortAndFilter(result, query); + return PostFilterAndSort(result.Where(filter), query); } public override bool IsPreSorted diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs index 0364ff678..cd179eb42 100644 --- a/MediaBrowser.Controller/Entities/UserView.cs +++ b/MediaBrowser.Controller/Entities/UserView.cs @@ -40,12 +40,13 @@ namespace MediaBrowser.Controller.Entities return result.Items; } - public override IEnumerable<BaseItem> GetRecursiveChildren(User user, bool includeLinkedChildren = true) + public override IEnumerable<BaseItem> GetRecursiveChildren(User user, Func<BaseItem, bool> filter) { var result = GetItems(new InternalItemsQuery { User = user, - Recursive = true + Recursive = true, + Filter = filter }).Result; @@ -63,8 +64,7 @@ namespace MediaBrowser.Controller.Entities { CollectionType.Books, CollectionType.HomeVideos, - CollectionType.Photos, - string.Empty + CollectionType.Photos }; var collectionFolder = folder as ICollectionFolder; diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index 166d56c51..a24a42535 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -18,6 +18,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using MoreLinq; namespace MediaBrowser.Controller.Entities { @@ -117,7 +118,7 @@ namespace MediaBrowser.Controller.Entities return await GetGameView(user, queryParent, query).ConfigureAwait(false); case CollectionType.BoxSets: - return GetResult(GetMediaFolders(user).SelectMany(i => i.GetRecursiveChildren(user)).OfType<BoxSet>(), queryParent, query); + return await GetBoxsetView(queryParent, user, query).ConfigureAwait(false); case CollectionType.TvShows: return await GetTvView(queryParent, user, query).ConfigureAwait(false); @@ -238,7 +239,9 @@ namespace MediaBrowser.Controller.Entities { if (query.Recursive) { - return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }), parent, query); + var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }, i => FilterItem(i, query)); + + return PostFilterAndSort(items, parent, null, query); } var list = new List<BaseItem>(); @@ -392,27 +395,54 @@ namespace MediaBrowser.Controller.Entities private QueryResult<BaseItem> GetMusicAlbums(Folder parent, User user, InternalItemsQuery query) { - return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }).Where(i => i is MusicAlbum), parent, query); + var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }, i => (i is MusicAlbum) && FilterItem(i, query)); + + return PostFilterAndSort(items, parent, null, query); } private QueryResult<BaseItem> GetMusicSongs(Folder parent, User user, InternalItemsQuery query) { - return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }).Where(i => i is Audio.Audio), parent, query); + var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }, i => (i is Audio.Audio) && FilterItem(i, query)); + + return PostFilterAndSort(items, parent, null, query); } private QueryResult<BaseItem> GetMusicLatest(Folder parent, User user, InternalItemsQuery query) { - query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName }; - query.SortOrder = SortOrder.Descending; + var items = _userViewManager.GetLatestItems(new LatestItemsQuery + { + UserId = user.Id.ToString("N"), + Limit = GetSpecialItemsLimit(), + IncludeItemTypes = new[] { typeof(Audio.Audio).Name }, + ParentId = (parent == null ? null : parent.Id.ToString("N")), + GroupItems = true + + }).Select(i => i.Item1); - return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }).Where(i => i is MusicVideo || i is Audio.Audio), parent, GetSpecialItemsLimit(), query); + query.SortBy = new string[] { }; + + //var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }, i => i is MusicVideo || i is Audio.Audio && FilterItem(i, query)); + + return PostFilterAndSort(items, parent, null, query); } private async Task<QueryResult<BaseItem>> GetMovieFolders(Folder parent, User user, InternalItemsQuery query) { if (query.Recursive) { - return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is Movie || i is BoxSet), parent, query); + var recursiveItems = GetRecursiveChildren(parent, user, + new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }) + .Where(i => i is Movie || i is BoxSet); + + //var collections = _collectionManager.CollapseItemsWithinBoxSets(recursiveItems, user).ToList(); + + //if (collections.Count > 0) + //{ + // recursiveItems.AddRange(_collectionManager.CollapseItemsWithinBoxSets(recursiveItems, user)); + // recursiveItems = recursiveItems.DistinctBy(i => i.Id).ToList(); + //} + + return GetResult(recursiveItems, parent, query); } var list = new List<BaseItem>(); @@ -431,45 +461,59 @@ namespace MediaBrowser.Controller.Entities { query.IsFavorite = true; - return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is Movie), parent, query); + var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }, i => (i is Movie) && FilterItem(i, query)); + + return PostFilterAndSort(items, parent, null, query); } private QueryResult<BaseItem> GetFavoriteSeries(Folder parent, User user, InternalItemsQuery query) { query.IsFavorite = true; - return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }).Where(i => i is Series), parent, query); + var items = GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }, i => (i is Series) && FilterItem(i, query)); + + return PostFilterAndSort(items, parent, null, query); } private QueryResult<BaseItem> GetFavoriteEpisodes(Folder parent, User user, InternalItemsQuery query) { query.IsFavorite = true; - return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }).Where(i => i is Episode), parent, query); + var items = GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }, i => (i is Episode) && FilterItem(i, query)); + + return PostFilterAndSort(items, parent, null, query); } private QueryResult<BaseItem> GetFavoriteSongs(Folder parent, User user, InternalItemsQuery query) { query.IsFavorite = true; - return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Music }).Where(i => i is Audio.Audio), parent, query); + var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music }, i => (i is Audio.Audio) && FilterItem(i, query)); + + return PostFilterAndSort(items, parent, null, query); } private QueryResult<BaseItem> GetFavoriteAlbums(Folder parent, User user, InternalItemsQuery query) { query.IsFavorite = true; - return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Music }).Where(i => i is MusicAlbum), parent, query); + var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music }, i => (i is MusicAlbum) && FilterItem(i, query)); + + return PostFilterAndSort(items, parent, null, query); } private QueryResult<BaseItem> GetMovieMovies(Folder parent, User user, InternalItemsQuery query) { - return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is Movie), parent, query); + var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }, i => (i is Movie) && FilterItem(i, query)); + + return PostFilterAndSort(items, parent, null, query); } private QueryResult<BaseItem> GetMovieCollections(Folder parent, User user, InternalItemsQuery query) { - return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is BoxSet), parent, query); + var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }, i => (i is BoxSet) && FilterItem(i, query)); + + return PostFilterAndSort(items, parent, null, query); } private QueryResult<BaseItem> GetMovieLatest(Folder parent, User user, InternalItemsQuery query) @@ -477,7 +521,9 @@ namespace MediaBrowser.Controller.Entities query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName }; query.SortOrder = SortOrder.Descending; - return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is Movie), parent, GetSpecialItemsLimit(), query); + var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }, i => i is Movie && FilterItem(i, query)); + + return PostFilterAndSort(items, parent, GetSpecialItemsLimit(), query); } private QueryResult<BaseItem> GetMovieResume(Folder parent, User user, InternalItemsQuery query) @@ -486,7 +532,9 @@ namespace MediaBrowser.Controller.Entities query.SortOrder = SortOrder.Descending; query.IsResumable = true; - return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }).Where(i => i is Movie), parent, GetSpecialItemsLimit(), query); + var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }, i => i is Movie && FilterItem(i, query)); + + return PostFilterAndSort(items, parent, GetSpecialItemsLimit(), query); } private async Task<QueryResult<BaseItem>> GetMovieGenres(Folder parent, User user, InternalItemsQuery query) @@ -526,11 +574,30 @@ namespace MediaBrowser.Controller.Entities return GetResult(items, queryParent, query); } + private async Task<QueryResult<BaseItem>> GetBoxsetView(Folder parent, User user, InternalItemsQuery query) + { + return GetResult(GetMediaFolders(user).SelectMany(i => + { + var hasCollectionType = i as ICollectionFolder; + Func<BaseItem, bool> filter = b => b is BoxSet; + + if (hasCollectionType != null && string.Equals(hasCollectionType.CollectionType, CollectionType.BoxSets, StringComparison.OrdinalIgnoreCase)) + { + return i.GetChildren(user, true).Where(filter); + } + + return i.GetRecursiveChildren(user, filter); + + }), parent, query); + } + private async Task<QueryResult<BaseItem>> GetTvView(Folder parent, User user, InternalItemsQuery query) { if (query.Recursive) { - return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }).Where(i => i is Series || i is Season || i is Episode), parent, query); + var items = GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }, i => (i is Series || i is Season || i is Episode) && FilterItem(i, query)); + + return PostFilterAndSort(items, parent, null, query); } var list = new List<BaseItem>(); @@ -550,7 +617,8 @@ namespace MediaBrowser.Controller.Entities { if (query.Recursive) { - return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Games }), parent, query); + var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }, i => FilterItem(i, query)); + return PostFilterAndSort(items, parent, null, query); } var list = new List<BaseItem>(); @@ -569,7 +637,9 @@ namespace MediaBrowser.Controller.Entities query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName }; query.SortOrder = SortOrder.Descending; - return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Games }).OfType<Game>(), parent, GetSpecialItemsLimit(), query); + var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }, i => i is Game && FilterItem(i, query)); + + return PostFilterAndSort(items, parent, GetSpecialItemsLimit(), query); } private QueryResult<BaseItem> GetRecentlyPlayedGames(Folder parent, User user, InternalItemsQuery query) @@ -578,14 +648,17 @@ namespace MediaBrowser.Controller.Entities query.SortBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.SortName }; query.SortOrder = SortOrder.Descending; - return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Games }).OfType<Game>(), parent, GetSpecialItemsLimit(), query); + var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }, i => i is Game && FilterItem(i, query)); + + return PostFilterAndSort(items, parent, GetSpecialItemsLimit(), query); } private QueryResult<BaseItem> GetFavoriteGames(Folder parent, User user, InternalItemsQuery query) { query.IsFavorite = true; - return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Games }).OfType<Game>(), parent, query); + var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }, i => i is Game && FilterItem(i, query)); + return PostFilterAndSort(items, parent, null, query); } private QueryResult<BaseItem> GetTvLatest(Folder parent, User user, InternalItemsQuery query) @@ -593,7 +666,9 @@ namespace MediaBrowser.Controller.Entities query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName }; query.SortOrder = SortOrder.Descending; - return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }).OfType<Episode>(), parent, GetSpecialItemsLimit(), query); + var items = GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }, i => i is Episode && FilterItem(i, query)); + + return PostFilterAndSort(items, parent, GetSpecialItemsLimit(), query); } private QueryResult<BaseItem> GetTvNextUp(Folder parent, InternalItemsQuery query) @@ -617,12 +692,16 @@ namespace MediaBrowser.Controller.Entities query.SortOrder = SortOrder.Descending; query.IsResumable = true; - return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }).OfType<Episode>(), parent, GetSpecialItemsLimit(), query); + var items = GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }, i => i is Episode && FilterItem(i, query)); + + return PostFilterAndSort(items, parent, GetSpecialItemsLimit(), query); } private QueryResult<BaseItem> GetTvSeries(Folder parent, User user, InternalItemsQuery query) { - return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }).OfType<Series>(), parent, query); + var items = GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }, i => i is Series && FilterItem(i, query)); + + return PostFilterAndSort(items, parent, null, query); } private async Task<QueryResult<BaseItem>> GetTvGenres(Folder parent, User user, InternalItemsQuery query) @@ -664,14 +743,15 @@ namespace MediaBrowser.Controller.Entities private QueryResult<BaseItem> GetGameSystems(Folder parent, User user, InternalItemsQuery query) { - return GetResult(GetRecursiveChildren(parent, user, new[] { CollectionType.Games }).OfType<GameSystem>(), parent, query); + var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }, i => i is GameSystem && FilterItem(i, query)); + + return PostFilterAndSort(items, parent, null, query); } private async Task<QueryResult<BaseItem>> GetGameGenreItems(Folder queryParent, Folder displayParent, User user, InternalItemsQuery query) { - var items = GetRecursiveChildren(queryParent, user, new[] { CollectionType.Games }) - .OfType<Game>() - .Where(i => i.Genres.Contains(displayParent.Name, StringComparer.OrdinalIgnoreCase)); + var items = GetRecursiveChildren(queryParent, user, new[] { CollectionType.Games }, + i => i is Game && i.Genres.Contains(displayParent.Name, StringComparer.OrdinalIgnoreCase)); return GetResult(items, queryParent, query); } @@ -719,29 +799,32 @@ namespace MediaBrowser.Controller.Entities InternalItemsQuery query) where T : BaseItem { - return GetResult(items, queryParent, null, query); + items = items.Where(i => Filter(i, query.User, query, _userDataManager, _libraryManager)); + + return PostFilterAndSort(items, queryParent, null, query, _libraryManager); } - private QueryResult<BaseItem> GetResult<T>(IEnumerable<T> items, + public bool FilterItem(BaseItem item, InternalItemsQuery query) + { + return Filter(item, query.User, query, _userDataManager, _libraryManager); + } + + private QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items, BaseItem queryParent, int? totalRecordLimit, InternalItemsQuery query) - where T : BaseItem { - return SortAndFilter(items, queryParent, totalRecordLimit, query, _libraryManager, _userDataManager); + return PostFilterAndSort(items, queryParent, totalRecordLimit, query, _libraryManager); } - public static QueryResult<BaseItem> SortAndFilter(IEnumerable<BaseItem> items, + public static QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items, BaseItem queryParent, int? totalRecordLimit, InternalItemsQuery query, - ILibraryManager libraryManager, - IUserDataManager userDataManager) + ILibraryManager libraryManager) { var user = query.User; - items = items.Where(i => Filter(i, user, query, userDataManager, libraryManager)); - items = FilterVirtualEpisodes(items, query.IsMissing, query.IsVirtualUnaired, @@ -1140,7 +1223,7 @@ namespace MediaBrowser.Controller.Entities }; } - private static bool Filter(BaseItem item, User user, InternalItemsQuery query, IUserDataManager userDataManager, ILibraryManager libraryManager) + public static bool Filter(BaseItem item, User user, InternalItemsQuery query, IUserDataManager userDataManager, ILibraryManager libraryManager) { if (query.MediaTypes.Length > 0 && !query.MediaTypes.Contains(item.MediaType ?? string.Empty, StringComparer.OrdinalIgnoreCase)) { @@ -1162,7 +1245,7 @@ namespace MediaBrowser.Controller.Entities return false; } - if (query.Filter != null && !query.Filter(item, user)) + if (query.Filter != null && !query.Filter(item)) { return false; } @@ -1612,6 +1695,16 @@ namespace MediaBrowser.Controller.Entities return parent.GetRecursiveChildren(user); } + private IEnumerable<BaseItem> GetRecursiveChildren(Folder parent, User user, IEnumerable<string> viewTypes, Func<BaseItem, bool> filter) + { + if (parent == null || parent is UserView) + { + return GetMediaFolders(user, viewTypes).SelectMany(i => i.GetRecursiveChildren(user, filter)); + } + + return parent.GetRecursiveChildren(user, filter); + } + private async Task<IEnumerable<BaseItem>> GetLiveTvFolders(User user) { var list = new List<BaseItem>(); diff --git a/MediaBrowser.Controller/Entities/Year.cs b/MediaBrowser.Controller/Entities/Year.cs index 8deb930e8..59a4bf16d 100644 --- a/MediaBrowser.Controller/Entities/Year.cs +++ b/MediaBrowser.Controller/Entities/Year.cs @@ -1,6 +1,8 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Runtime.Serialization; namespace MediaBrowser.Controller.Entities { @@ -13,7 +15,7 @@ namespace MediaBrowser.Controller.Entities /// Gets the user data key. /// </summary> /// <returns>System.String.</returns> - public override string GetUserDataKey() + protected override string CreateUserDataKey() { return "Year-" + Name; } @@ -23,6 +25,7 @@ namespace MediaBrowser.Controller.Entities /// If the item is a folder, it returns the folder itself /// </summary> /// <value>The containing folder path.</value> + [IgnoreDataMember] public override string ContainingFolderPath { get @@ -35,6 +38,7 @@ namespace MediaBrowser.Controller.Entities /// Gets a value indicating whether this instance is owned item. /// </summary> /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value> + [IgnoreDataMember] public override bool IsOwnedItem { get @@ -47,8 +51,8 @@ namespace MediaBrowser.Controller.Entities { int year; - var usCulture = new CultureInfo("en-US"); - + var usCulture = new CultureInfo("en-US"); + if (!int.TryParse(Name, NumberStyles.Integer, usCulture, out year)) { return inputItems; @@ -56,5 +60,23 @@ namespace MediaBrowser.Controller.Entities return inputItems.Where(i => i.ProductionYear.HasValue && i.ProductionYear.Value == year); } + + public int? GetYearValue() + { + int i; + + if (int.TryParse(Name, NumberStyles.Integer, CultureInfo.InvariantCulture, out i)) + { + return i; + } + + return null; + } + + public Func<BaseItem, bool> GetItemFilter() + { + var val = GetYearValue(); + return i => i.ProductionYear.HasValue && val.HasValue && i.ProductionYear.Value == val.Value; + } } } diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs index d1a9b386c..105e4e2f0 100644 --- a/MediaBrowser.Controller/IServerApplicationHost.cs +++ b/MediaBrowser.Controller/IServerApplicationHost.cs @@ -1,7 +1,7 @@ -using System.Collections.Generic; -using MediaBrowser.Common; +using MediaBrowser.Common; using MediaBrowser.Model.System; using System; +using System.Collections.Generic; namespace MediaBrowser.Controller { @@ -19,12 +19,6 @@ namespace MediaBrowser.Controller SystemInfo GetSystemInfo(); /// <summary> - /// Gets the name of the web application. - /// </summary> - /// <value>The name of the web application.</value> - string WebApplicationName { get; } - - /// <summary> /// Gets a value indicating whether [supports automatic run at startup]. /// </summary> /// <value><c>true</c> if [supports automatic run at startup]; otherwise, <c>false</c>.</value> @@ -34,7 +28,19 @@ namespace MediaBrowser.Controller /// Gets the HTTP server port. /// </summary> /// <value>The HTTP server port.</value> - int HttpServerPort { get; } + int HttpPort { get; } + + /// <summary> + /// Gets the HTTPS port. + /// </summary> + /// <value>The HTTPS port.</value> + int HttpsPort { get; } + + /// <summary> + /// Gets a value indicating whether [supports HTTPS]. + /// </summary> + /// <value><c>true</c> if [supports HTTPS]; otherwise, <c>false</c>.</value> + bool EnableHttps { get; } /// <summary> /// Gets a value indicating whether this instance has update available. @@ -49,9 +55,15 @@ namespace MediaBrowser.Controller string FriendlyName { get; } /// <summary> - /// Gets the HTTP server ip addresses. + /// Gets the local ip address. + /// </summary> + /// <value>The local ip address.</value> + string LocalIpAddress { get; } + + /// <summary> + /// Gets the local API URL. /// </summary> - /// <value>The HTTP server ip addresses.</value> - IEnumerable<string> HttpServerIpAddresses { get; } + /// <value>The local API URL.</value> + string LocalApiUrl { get; } } } diff --git a/MediaBrowser.Controller/IServerApplicationPaths.cs b/MediaBrowser.Controller/IServerApplicationPaths.cs index e3438c3d2..c07934d0b 100644 --- a/MediaBrowser.Controller/IServerApplicationPaths.cs +++ b/MediaBrowser.Controller/IServerApplicationPaths.cs @@ -60,12 +60,6 @@ namespace MediaBrowser.Controller string GameGenrePath { get; } /// <summary> - /// Gets the artists path. - /// </summary> - /// <value>The artists path.</value> - string ArtistsPath { get; } - - /// <summary> /// Gets the path to the Studio directory /// </summary> /// <value>The studio path.</value> diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 2ebd1cab9..9871ef3c5 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -123,14 +123,7 @@ namespace MediaBrowser.Controller.Library /// Gets the default view. /// </summary> /// <returns>IEnumerable{VirtualFolderInfo}.</returns> - IEnumerable<VirtualFolderInfo> GetDefaultVirtualFolders(); - - /// <summary> - /// Gets the view. - /// </summary> - /// <param name="user">The user.</param> - /// <returns>IEnumerable{VirtualFolderInfo}.</returns> - IEnumerable<VirtualFolderInfo> GetVirtualFolders(User user); + IEnumerable<VirtualFolderInfo> GetVirtualFolders(); /// <summary> /// Gets the item by id. diff --git a/MediaBrowser.Controller/Library/IMusicManager.cs b/MediaBrowser.Controller/Library/IMusicManager.cs index f66f18401..0ce0687cc 100644 --- a/MediaBrowser.Controller/Library/IMusicManager.cs +++ b/MediaBrowser.Controller/Library/IMusicManager.cs @@ -1,6 +1,5 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Playlists; using System.Collections.Generic; namespace MediaBrowser.Controller.Library @@ -13,7 +12,7 @@ namespace MediaBrowser.Controller.Library /// <param name="item">The item.</param> /// <param name="user">The user.</param> /// <returns>IEnumerable{Audio}.</returns> - IEnumerable<Audio> GetInstantMixFromSong(Audio item, User user); + IEnumerable<Audio> GetInstantMixFromItem(BaseItem item, User user); /// <summary> /// Gets the instant mix from artist. /// </summary> @@ -22,20 +21,6 @@ namespace MediaBrowser.Controller.Library /// <returns>IEnumerable{Audio}.</returns> IEnumerable<Audio> GetInstantMixFromArtist(string name, User user); /// <summary> - /// Gets the instant mix from album. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="user">The user.</param> - /// <returns>IEnumerable{Audio}.</returns> - IEnumerable<Audio> GetInstantMixFromAlbum(MusicAlbum item, User user); - /// <summary> - /// Gets the instant mix from playlist. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="user">The user.</param> - /// <returns>IEnumerable<Audio>.</returns> - IEnumerable<Audio> GetInstantMixFromPlaylist(Playlist item, User user); - /// <summary> /// Gets the instant mix from genre. /// </summary> /// <param name="genres">The genres.</param> diff --git a/MediaBrowser.Controller/Library/IUserManager.cs b/MediaBrowser.Controller/Library/IUserManager.cs index f5846973e..97a3cced9 100644 --- a/MediaBrowser.Controller/Library/IUserManager.cs +++ b/MediaBrowser.Controller/Library/IUserManager.cs @@ -118,6 +118,21 @@ namespace MediaBrowser.Controller.Library Task ResetPassword(User user); /// <summary> + /// Gets the offline user dto. + /// </summary> + /// <param name="user">The user.</param> + /// <param name="deviceId">The device identifier.</param> + /// <returns>UserDto.</returns> + UserDto GetOfflineUserDto(User user, string deviceId); + + /// <summary> + /// Resets the easy password. + /// </summary> + /// <param name="user">The user.</param> + /// <returns>Task.</returns> + Task ResetEasyPassword(User user); + + /// <summary> /// Changes the password. /// </summary> /// <param name="user">The user.</param> @@ -126,6 +141,14 @@ namespace MediaBrowser.Controller.Library Task ChangePassword(User user, string newPasswordSha1); /// <summary> + /// Changes the easy password. + /// </summary> + /// <param name="user">The user.</param> + /// <param name="newPasswordSha1">The new password sha1.</param> + /// <returns>Task.</returns> + Task ChangeEasyPassword(User user, string newPasswordSha1); + + /// <summary> /// Gets the user dto. /// </summary> /// <param name="user">The user.</param> diff --git a/MediaBrowser.Controller/Library/IUserViewManager.cs b/MediaBrowser.Controller/Library/IUserViewManager.cs index 727ccd00a..f55c17924 100644 --- a/MediaBrowser.Controller/Library/IUserViewManager.cs +++ b/MediaBrowser.Controller/Library/IUserViewManager.cs @@ -1,5 +1,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Library; +using MediaBrowser.Model.Querying; +using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; @@ -16,5 +18,7 @@ namespace MediaBrowser.Controller.Library Task<UserView> GetUserView(string type, string sortName, CancellationToken cancellationToken); Task<UserView> GetUserView(string category, string type, User user, string sortName, CancellationToken cancellationToken); + + List<Tuple<BaseItem, List<BaseItem>>> GetLatestItems(LatestItemsQuery request); } } diff --git a/MediaBrowser.Controller/Library/ItemResolveArgs.cs b/MediaBrowser.Controller/Library/ItemResolveArgs.cs index 4fa07421c..db441d285 100644 --- a/MediaBrowser.Controller/Library/ItemResolveArgs.cs +++ b/MediaBrowser.Controller/Library/ItemResolveArgs.cs @@ -17,7 +17,6 @@ namespace MediaBrowser.Controller.Library /// The _app paths /// </summary> private readonly IServerApplicationPaths _appPaths; - private readonly ILibraryManager _libraryManager; public IDirectoryService DirectoryService { get; private set; } @@ -25,11 +24,10 @@ namespace MediaBrowser.Controller.Library /// Initializes a new instance of the <see cref="ItemResolveArgs" /> class. /// </summary> /// <param name="appPaths">The app paths.</param> - /// <param name="libraryManager">The library manager.</param> - public ItemResolveArgs(IServerApplicationPaths appPaths, ILibraryManager libraryManager, IDirectoryService directoryService) + /// <param name="directoryService">The directory service.</param> + public ItemResolveArgs(IServerApplicationPaths appPaths, IDirectoryService directoryService) { _appPaths = appPaths; - _libraryManager = libraryManager; DirectoryService = directoryService; } @@ -137,18 +135,6 @@ namespace MediaBrowser.Controller.Library } /// <summary> - /// Gets a value indicating whether this instance is root. - /// </summary> - /// <value><c>true</c> if this instance is root; otherwise, <c>false</c>.</value> - public bool IsRoot - { - get - { - return Parent == null; - } - } - - /// <summary> /// Gets or sets the additional locations. /// </summary> /// <value>The additional locations.</value> diff --git a/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs index b95d67ad8..8faaa895c 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs @@ -1,8 +1,9 @@ -using MediaBrowser.Controller.Entities.Audio; +using System.Runtime.Serialization; +using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; -using System.Linq; using MediaBrowser.Model.Users; +using System.Linq; namespace MediaBrowser.Controller.LiveTv { @@ -12,7 +13,7 @@ namespace MediaBrowser.Controller.LiveTv /// Gets the user data key. /// </summary> /// <returns>System.String.</returns> - public override string GetUserDataKey() + protected override string CreateUserDataKey() { var name = GetClientTypeName(); @@ -32,6 +33,7 @@ namespace MediaBrowser.Controller.LiveTv /// Gets a value indicating whether this instance is owned item. /// </summary> /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value> + [IgnoreDataMember] public override bool IsOwnedItem { get @@ -40,6 +42,7 @@ namespace MediaBrowser.Controller.LiveTv } } + [IgnoreDataMember] public override string MediaType { get @@ -48,6 +51,7 @@ namespace MediaBrowser.Controller.LiveTv } } + [IgnoreDataMember] public override LocationType LocationType { get @@ -71,6 +75,7 @@ namespace MediaBrowser.Controller.LiveTv return false; } + [IgnoreDataMember] public override bool SupportsLocalMetadata { get @@ -83,5 +88,10 @@ namespace MediaBrowser.Controller.LiveTv { return config.BlockUnratedItems.Contains(UnratedItem.LiveTvProgram); } + + protected override string GetInternalMetadataPath(string basePath) + { + return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N")); + } } } diff --git a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs index de72accff..1948ce0d5 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs @@ -1,12 +1,13 @@ -using MediaBrowser.Controller.Entities; +using System.Runtime.Serialization; +using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.MediaInfo; +using MediaBrowser.Model.Users; using System.Collections.Generic; using System.Linq; -using MediaBrowser.Model.Users; namespace MediaBrowser.Controller.LiveTv { @@ -16,24 +17,11 @@ namespace MediaBrowser.Controller.LiveTv /// Gets the user data key. /// </summary> /// <returns>System.String.</returns> - public override string GetUserDataKey() + protected override string CreateUserDataKey() { return GetClientTypeName() + "-" + Name; } - /// <summary> - /// Returns the folder containing the item. - /// If the item is a folder, it returns the folder itself - /// </summary> - /// <value>The containing folder path.</value> - public override string ContainingFolderPath - { - get - { - return Path; - } - } - protected override bool GetBlockUnratedValue(UserPolicy config) { return config.BlockUnratedItems.Contains(UnratedItem.LiveTvChannel); @@ -43,6 +31,7 @@ namespace MediaBrowser.Controller.LiveTv /// Gets a value indicating whether this instance is owned item. /// </summary> /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value> + [IgnoreDataMember] public override bool IsOwnedItem { get @@ -51,11 +40,6 @@ namespace MediaBrowser.Controller.LiveTv } } - public override bool IsSaveLocalMetadataEnabled() - { - return true; - } - /// <summary> /// Gets or sets the number. /// </summary> @@ -106,6 +90,7 @@ namespace MediaBrowser.Controller.LiveTv return number.ToString("000-") + (Name ?? string.Empty); } + [IgnoreDataMember] public override string MediaType { get @@ -145,5 +130,10 @@ namespace MediaBrowser.Controller.LiveTv return list; } + + protected override string GetInternalMetadataPath(string basePath) + { + return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N"), "metadata"); + } } } diff --git a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs index 29b23a551..a66aaad6f 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Controller.Entities; +using System.Runtime.Serialization; +using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.LiveTv; @@ -16,7 +17,7 @@ namespace MediaBrowser.Controller.LiveTv /// Gets the user data key. /// </summary> /// <returns>System.String.</returns> - public override string GetUserDataKey() + protected override string CreateUserDataKey() { return GetClientTypeName() + "-" + Name; } @@ -138,6 +139,7 @@ namespace MediaBrowser.Controller.LiveTv /// If the item is a folder, it returns the folder itself /// </summary> /// <value>The containing folder path.</value> + [IgnoreDataMember] public override string ContainingFolderPath { get @@ -150,6 +152,7 @@ namespace MediaBrowser.Controller.LiveTv /// Gets a value indicating whether this instance is owned item. /// </summary> /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value> + [IgnoreDataMember] public override bool IsOwnedItem { get @@ -158,6 +161,7 @@ namespace MediaBrowser.Controller.LiveTv } } + [IgnoreDataMember] public override string MediaType { get @@ -166,6 +170,7 @@ namespace MediaBrowser.Controller.LiveTv } } + [IgnoreDataMember] public bool IsAiring { get @@ -176,6 +181,7 @@ namespace MediaBrowser.Controller.LiveTv } } + [IgnoreDataMember] public bool HasAired { get @@ -204,5 +210,10 @@ namespace MediaBrowser.Controller.LiveTv { return config.BlockUnratedItems.Contains(UnratedItem.LiveTvProgram); } + + protected override string GetInternalMetadataPath(string basePath) + { + return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N")); + } } } diff --git a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs index 6fc985643..34fe757a7 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Controller.Entities; +using System.Runtime.Serialization; +using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using System.Linq; @@ -12,7 +13,7 @@ namespace MediaBrowser.Controller.LiveTv /// Gets the user data key. /// </summary> /// <returns>System.String.</returns> - public override string GetUserDataKey() + protected override string CreateUserDataKey() { var name = GetClientTypeName(); @@ -28,6 +29,7 @@ namespace MediaBrowser.Controller.LiveTv public string ServiceName { get; set; } + [IgnoreDataMember] public override string MediaType { get @@ -36,6 +38,7 @@ namespace MediaBrowser.Controller.LiveTv } } + [IgnoreDataMember] public override LocationType LocationType { get @@ -53,6 +56,7 @@ namespace MediaBrowser.Controller.LiveTv /// Gets a value indicating whether this instance is owned item. /// </summary> /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value> + [IgnoreDataMember] public override bool IsOwnedItem { get @@ -83,5 +87,10 @@ namespace MediaBrowser.Controller.LiveTv { return config.BlockUnratedItems.Contains(UnratedItem.LiveTvProgram); } + + protected override string GetInternalMetadataPath(string basePath) + { + return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N")); + } } } diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 0667730fd..238cdbc9e 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -101,6 +101,7 @@ <Compile Include="Collections\ICollectionManager.cs" /> <Compile Include="Connect\IConnectManager.cs" /> <Compile Include="Connect\UserLinkResult.cs" /> + <Compile Include="Devices\CameraImageUploadInfo.cs" /> <Compile Include="Devices\IDeviceManager.cs" /> <Compile Include="Devices\IDeviceRepository.cs" /> <Compile Include="Dlna\ControlRequest.cs" /> @@ -110,6 +111,7 @@ <Compile Include="Dlna\IContentDirectory.cs" /> <Compile Include="Dlna\IDlnaManager.cs" /> <Compile Include="Dlna\IEventManager.cs" /> + <Compile Include="Dlna\IMediaReceiverRegistrar.cs" /> <Compile Include="Dlna\IUpnpService.cs" /> <Compile Include="Drawing\IImageProcessor.cs" /> <Compile Include="Drawing\ImageProcessingOptions.cs" /> @@ -117,7 +119,6 @@ <Compile Include="Drawing\ImageStream.cs" /> <Compile Include="Dto\DtoOptions.cs" /> <Compile Include="Dto\IDtoService.cs" /> - <Compile Include="Entities\AdultVideo.cs" /> <Compile Include="Entities\Audio\IHasAlbumArtist.cs" /> <Compile Include="Entities\Audio\IHasMusicGenres.cs" /> <Compile Include="Entities\Book.cs" /> diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs index a988c2f97..ad9ab90a0 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs @@ -5,6 +5,7 @@ namespace MediaBrowser.Controller.MediaEncoding public class EncodingJobOptions { public string OutputContainer { get; set; } + public string OutputDirectory { get; set; } public long? StartTimeTicks { get; set; } public int? Width { get; set; } diff --git a/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs b/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs index 9e32fc32b..37c2bf4d2 100644 --- a/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs @@ -47,9 +47,8 @@ namespace MediaBrowser.Controller.MediaEncoding /// Gets the subtitle language encoding parameter. /// </summary> /// <param name="path">The path.</param> - /// <param name="language">The language.</param> /// <returns>System.String.</returns> - string GetSubtitleFileCharacterSet(string path, string language); + string GetSubtitleFileCharacterSet(string path); } } diff --git a/MediaBrowser.Controller/MediaEncoding/MediaStreamSelector.cs b/MediaBrowser.Controller/MediaEncoding/MediaStreamSelector.cs index 4a807df7a..b18651a68 100644 --- a/MediaBrowser.Controller/MediaEncoding/MediaStreamSelector.cs +++ b/MediaBrowser.Controller/MediaEncoding/MediaStreamSelector.cs @@ -38,7 +38,8 @@ namespace MediaBrowser.Controller.MediaEncoding SubtitlePlaybackMode mode, string audioTrackLanguage) { - streams = GetSortedStreams(streams, MediaStreamType.Subtitle, preferredLanguages).ToList(); + streams = GetSortedStreams(streams, MediaStreamType.Subtitle, preferredLanguages) + .ToList(); var full = streams.Where(s => !s.IsForced); @@ -81,11 +82,9 @@ namespace MediaBrowser.Controller.MediaEncoding private static IEnumerable<MediaStream> GetSortedStreams(IEnumerable<MediaStream> streams, MediaStreamType type, List<string> languagePreferences) { - var orderStreams = streams - .Where(i => i.Type == type); - // Give some preferance to external text subs for better performance - return orderStreams.OrderBy(i => + return streams.Where(i => i.Type == type) + .OrderBy(i => { var index = languagePreferences.FindIndex(l => string.Equals(i.Language, l, StringComparison.OrdinalIgnoreCase)); @@ -94,8 +93,7 @@ namespace MediaBrowser.Controller.MediaEncoding .ThenBy(i => i.IsDefault) .ThenBy(i => i.IsTextSubtitleStream) .ThenBy(i => i.IsExternal) - .ThenBy(i => i.Index) - .ToList(); + .ThenBy(i => i.Index); } } } diff --git a/MediaBrowser.Controller/Net/IHttpServer.cs b/MediaBrowser.Controller/Net/IHttpServer.cs index 5b179d479..315b48b83 100644 --- a/MediaBrowser.Controller/Net/IHttpServer.cs +++ b/MediaBrowser.Controller/Net/IHttpServer.cs @@ -1,4 +1,3 @@ -using MediaBrowser.Common.Net; using System; using System.Collections.Generic; @@ -16,10 +15,18 @@ namespace MediaBrowser.Controller.Net IEnumerable<string> UrlPrefixes { get; } /// <summary> + /// Gets the certificate path. + /// </summary> + /// <value>The certificate path.</value> + string CertificatePath { get; } + + /// <summary> /// Starts the specified server name. /// </summary> /// <param name="urlPrefixes">The URL prefixes.</param> - void StartServer(IEnumerable<string> urlPrefixes); + /// <param name="certificatePath">If an https prefix is specified, + /// the ssl certificate localtion on the file system.</param> + void StartServer(IEnumerable<string> urlPrefixes, string certificatePath); /// <summary> /// Gets the local end points. diff --git a/MediaBrowser.Controller/Net/IServerManager.cs b/MediaBrowser.Controller/Net/IServerManager.cs index dff086347..d90a0f8ed 100644 --- a/MediaBrowser.Controller/Net/IServerManager.cs +++ b/MediaBrowser.Controller/Net/IServerManager.cs @@ -15,7 +15,9 @@ namespace MediaBrowser.Controller.Net /// Starts this instance. /// </summary> /// <param name="urlPrefixes">The URL prefixes.</param> - void Start(IEnumerable<string> urlPrefixes); + /// <param name="certificatePath">If an https prefix is specified, + /// the ssl certificate localtion on the file system.</param> + void Start(IEnumerable<string> urlPrefixes, string certificatePath); /// <summary> /// Sends a message to all clients currently connected via a web socket diff --git a/MediaBrowser.Controller/Playlists/Playlist.cs b/MediaBrowser.Controller/Playlists/Playlist.cs index e48cddaaa..0f0c6a97e 100644 --- a/MediaBrowser.Controller/Playlists/Playlist.cs +++ b/MediaBrowser.Controller/Playlists/Playlist.cs @@ -50,9 +50,16 @@ namespace MediaBrowser.Controller.Playlists return GetPlayableItems(user); } - public override IEnumerable<BaseItem> GetRecursiveChildren(User user, bool includeLinkedChildren = true) + public override IEnumerable<BaseItem> GetRecursiveChildren(User user, Func<BaseItem, bool> filter) { - return GetPlayableItems(user); + var items = GetPlayableItems(user); + + if (filter != null) + { + items = items.Where(filter); + } + + return items; } public IEnumerable<Tuple<LinkedChild, BaseItem>> GetManageableItems() @@ -76,75 +83,51 @@ namespace MediaBrowser.Controller.Playlists .Where(m => string.Equals(m.MediaType, playlistMediaType, StringComparison.OrdinalIgnoreCase)); } - private static IEnumerable<BaseItem> GetPlaylistItems(BaseItem i, User user) + private static IEnumerable<BaseItem> GetPlaylistItems(BaseItem item, User user) { - var musicGenre = i as MusicGenre; + var musicGenre = item as MusicGenre; if (musicGenre != null) { - var items = user == null - ? LibraryManager.RootFolder.GetRecursiveChildren() - : user.RootFolder.GetRecursiveChildren(user, true); - - var songs = items - .OfType<Audio>() - .Where(a => a.Genres.Contains(musicGenre.Name, StringComparer.OrdinalIgnoreCase)); + Func<BaseItem, bool> filter = i => i is Audio && i.Genres.Contains(musicGenre.Name, StringComparer.OrdinalIgnoreCase); - return LibraryManager.Sort(songs, user, new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName }, SortOrder.Ascending); - } - - var musicArtist = i as MusicArtist; - if (musicArtist != null) - { var items = user == null - ? LibraryManager.RootFolder.GetRecursiveChildren() - : user.RootFolder.GetRecursiveChildren(user, true); - - var songs = items - .OfType<Audio>() - .Where(a => a.HasArtist(musicArtist.Name)); + ? LibraryManager.RootFolder.GetRecursiveChildren(filter) + : user.RootFolder.GetRecursiveChildren(user, filter); - return LibraryManager.Sort(songs, user, new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName }, SortOrder.Ascending); + return LibraryManager.Sort(items, user, new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName }, SortOrder.Ascending); } - // Grab these explicitly to avoid the sorting that will happen below - var collection = i as BoxSet; - if (collection != null) + var musicArtist = item as MusicArtist; + if (musicArtist != null) { - var items = user == null - ? collection.Children - : collection.GetChildren(user, true); + Func<BaseItem, bool> filter = i => + { + var audio = i as Audio; + return audio != null && audio.HasArtist(musicArtist.Name); + }; - return items - .Where(m => !m.IsFolder); - } - - // Grab these explicitly to avoid the sorting that will happen below - var season = i as Season; - if (season != null) - { var items = user == null - ? season.Children - : season.GetChildren(user, true); + ? LibraryManager.RootFolder.GetRecursiveChildren(filter) + : user.RootFolder.GetRecursiveChildren(user, filter); - return items - .Where(m => !m.IsFolder); + return LibraryManager.Sort(items, user, new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName }, SortOrder.Ascending); } - var folder = i as Folder; - + var folder = item as Folder; if (folder != null) { var items = user == null - ? folder.GetRecursiveChildren() - : folder.GetRecursiveChildren(user, true); - - items = items - .Where(m => !m.IsFolder); + ? folder.GetRecursiveChildren(m => !m.IsFolder) + : folder.GetRecursiveChildren(user, m => !m.IsFolder); + if (folder.IsPreSorted) + { + return items; + } return LibraryManager.Sort(items, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending); } - return new[] { i }; + return new[] { item }; } [IgnoreDataMember] diff --git a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs index a9e155509..2cd119cf5 100644 --- a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs +++ b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs @@ -11,6 +11,8 @@ namespace MediaBrowser.Controller.Providers /// </summary> public bool ReplaceAllMetadata { get; set; } + public bool IsPostRecursiveRefresh { get; set; } + public MetadataRefreshMode MetadataRefreshMode { get; set; } public bool ForceSave { get; set; } diff --git a/MediaBrowser.Controller/Session/ISessionController.cs b/MediaBrowser.Controller/Session/ISessionController.cs index d6dd7698e..a4badee47 100644 --- a/MediaBrowser.Controller/Session/ISessionController.cs +++ b/MediaBrowser.Controller/Session/ISessionController.cs @@ -105,5 +105,15 @@ namespace MediaBrowser.Controller.Session /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> Task SendServerRestartNotification(CancellationToken cancellationToken); + + /// <summary> + /// Sends the message. + /// </summary> + /// <typeparam name="T"></typeparam> + /// <param name="name">The name.</param> + /// <param name="data">The data.</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns>Task.</returns> + Task SendMessage<T>(string name, T data, CancellationToken cancellationToken); } } diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs index f0272b335..4082f5600 100644 --- a/MediaBrowser.Controller/Session/ISessionManager.cs +++ b/MediaBrowser.Controller/Session/ISessionManager.cs @@ -171,6 +171,29 @@ namespace MediaBrowser.Controller.Session Task SendPlaystateCommand(string controllingSessionId, string sessionId, PlaystateRequest command, CancellationToken cancellationToken); /// <summary> + /// Sends the message to user sessions. + /// </summary> + /// <typeparam name="T"></typeparam> + /// <param name="userId">The user identifier.</param> + /// <param name="name">The name.</param> + /// <param name="data">The data.</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns>Task.</returns> + Task SendMessageToUserSessions<T>(string userId, string name, T data, CancellationToken cancellationToken); + + /// <summary> + /// Sends the message to user device sessions. + /// </summary> + /// <typeparam name="T"></typeparam> + /// <param name="deviceId">The device identifier.</param> + /// <param name="name">The name.</param> + /// <param name="data">The data.</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns>Task.</returns> + Task SendMessageToUserDeviceSessions<T>(string deviceId, string name, T data, + CancellationToken cancellationToken); + + /// <summary> /// Sends the restart required message. /// </summary> /// <param name="cancellationToken">The cancellation token.</param> diff --git a/MediaBrowser.Controller/Session/SessionInfo.cs b/MediaBrowser.Controller/Session/SessionInfo.cs index d8a2464d6..078d4d70f 100644 --- a/MediaBrowser.Controller/Session/SessionInfo.cs +++ b/MediaBrowser.Controller/Session/SessionInfo.cs @@ -160,6 +160,11 @@ namespace MediaBrowser.Controller.Session } } + public bool ContainsUser(string userId) + { + return ContainsUser(new Guid(userId)); + } + public bool ContainsUser(Guid userId) { return (UserId ?? Guid.Empty) == userId || AdditionalUsers.Any(i => userId == new Guid(i.UserId)); diff --git a/MediaBrowser.Controller/Sync/ISyncManager.cs b/MediaBrowser.Controller/Sync/ISyncManager.cs index 59136c0e6..dedde2d9e 100644 --- a/MediaBrowser.Controller/Sync/ISyncManager.cs +++ b/MediaBrowser.Controller/Sync/ISyncManager.cs @@ -1,8 +1,10 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Dlna; +using MediaBrowser.Model.Events; using MediaBrowser.Model.Querying; using MediaBrowser.Model.Sync; using MediaBrowser.Model.Users; +using System; using System.Collections.Generic; using System.Threading.Tasks; @@ -10,6 +12,9 @@ namespace MediaBrowser.Controller.Sync { public interface ISyncManager { + event EventHandler<GenericEventArgs<SyncJobCreationResult>> SyncJobCreated; + event EventHandler<GenericEventArgs<SyncJob>> SyncJobCancelled; + /// <summary> /// Creates the job. /// </summary> @@ -45,6 +50,20 @@ namespace MediaBrowser.Controller.Sync Task UpdateJob(SyncJob job); /// <summary> + /// Res the enable job item. + /// </summary> + /// <param name="id">The identifier.</param> + /// <returns>Task.</returns> + Task ReEnableJobItem(string id); + + /// <summary> + /// Cnacels the job item. + /// </summary> + /// <param name="id">The identifier.</param> + /// <returns>Task.</returns> + Task CancelJobItem(string id); + + /// <summary> /// Cancels the job. /// </summary> /// <param name="id">The identifier.</param> @@ -109,5 +128,26 @@ namespace MediaBrowser.Controller.Sync /// <param name="request">The request.</param> /// <returns>Task<SyncDataResponse>.</returns> Task<SyncDataResponse> SyncData(SyncDataRequest request); + + /// <summary> + /// Marks the job item for removal. + /// </summary> + /// <param name="id">The identifier.</param> + /// <returns>Task.</returns> + Task MarkJobItemForRemoval(string id); + + /// <summary> + /// Unmarks the job item for removal. + /// </summary> + /// <param name="id">The identifier.</param> + /// <returns>Task.</returns> + Task UnmarkJobItemForRemoval(string id); + + /// <summary> + /// Gets the library item ids. + /// </summary> + /// <param name="query">The query.</param> + /// <returns>QueryResult<System.String>.</returns> + QueryResult<string> GetLibraryItemIds(SyncJobItemQuery query); } } diff --git a/MediaBrowser.Controller/Sync/ISyncRepository.cs b/MediaBrowser.Controller/Sync/ISyncRepository.cs index f1bcd7f07..315f5f541 100644 --- a/MediaBrowser.Controller/Sync/ISyncRepository.cs +++ b/MediaBrowser.Controller/Sync/ISyncRepository.cs @@ -68,5 +68,12 @@ namespace MediaBrowser.Controller.Sync /// <param name="query">The query.</param> /// <returns>IEnumerable<SyncJobItem>.</returns> QueryResult<SyncJobItem> GetJobItems(SyncJobItemQuery query); + + /// <summary> + /// Gets the library item ids. + /// </summary> + /// <param name="query">The query.</param> + /// <returns>QueryResult<System.String>.</returns> + QueryResult<string> GetLibraryItemIds(SyncJobItemQuery query); } } diff --git a/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs b/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs index 1faf690c9..e480326e9 100644 --- a/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs +++ b/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs @@ -185,13 +185,15 @@ namespace MediaBrowser.Dlna.ContentDirectory var provided = 0; - int? requested = 0; + // Default to null instead of 0 + // Upnp inspector sends 0 as requestedCount when it wants everything + int? requestedCount = null; int? start = 0; int requestedVal; if (sparams.ContainsKey("RequestedCount") && int.TryParse(sparams["RequestedCount"], out requestedVal) && requestedVal > 0) { - requested = requestedVal; + requestedCount = requestedVal; } int startVal; @@ -221,7 +223,7 @@ namespace MediaBrowser.Dlna.ContentDirectory if (item.IsFolder || serverItem.StubType.HasValue) { - var childrenResult = (await GetUserItems(item, serverItem.StubType, user, sortCriteria, start, requested).ConfigureAwait(false)); + var childrenResult = (await GetUserItems(item, serverItem.StubType, user, sortCriteria, start, requestedCount).ConfigureAwait(false)); result.DocumentElement.AppendChild(_didlBuilder.GetFolderElement(result, item, serverItem.StubType, null, childrenResult.TotalRecordCount, filter, id)); } @@ -234,7 +236,7 @@ namespace MediaBrowser.Dlna.ContentDirectory } else { - var childrenResult = (await GetUserItems(item, serverItem.StubType, user, sortCriteria, start, requested).ConfigureAwait(false)); + var childrenResult = (await GetUserItems(item, serverItem.StubType, user, sortCriteria, start, requestedCount).ConfigureAwait(false)); totalCount = childrenResult.TotalRecordCount; provided = childrenResult.Items.Length; @@ -277,13 +279,15 @@ namespace MediaBrowser.Dlna.ContentDirectory // sort example: dc:title, dc:date - int? requested = 0; + // Default to null instead of 0 + // Upnp inspector sends 0 as requestedCount when it wants everything + int? requestedCount = null; int? start = 0; int requestedVal; if (sparams.ContainsKey("RequestedCount") && int.TryParse(sparams["RequestedCount"], out requestedVal) && requestedVal > 0) { - requested = requestedVal; + requestedCount = requestedVal; } int startVal; @@ -311,7 +315,7 @@ namespace MediaBrowser.Dlna.ContentDirectory var item = serverItem.Item; - var childrenResult = (await GetChildrenSorted(item, user, searchCriteria, sortCriteria, start, requested).ConfigureAwait(false)); + var childrenResult = (await GetChildrenSorted(item, user, searchCriteria, sortCriteria, start, requestedCount).ConfigureAwait(false)); var totalCount = childrenResult.TotalRecordCount; @@ -479,9 +483,7 @@ namespace MediaBrowser.Dlna.ContentDirectory private async Task<QueryResult<ServerItem>> GetItemsFromPerson(Person person, User user, int? startIndex, int? limit) { - var items = user.RootFolder.GetRecursiveChildren(user) - .Where(i => i is Movie || i is Series) - .Where(i => i.ContainsPerson(person.Name)) + var items = user.RootFolder.GetRecursiveChildren(user, i => i is Movie || i is Series && i.ContainsPerson(person.Name)) .ToList(); var trailerResult = await _channelManager.GetAllMediaInternal(new AllChannelMediaQuery @@ -595,7 +597,7 @@ namespace MediaBrowser.Dlna.ContentDirectory }); } - private bool FilterUnsupportedContent(BaseItem i, User user) + private bool FilterUnsupportedContent(BaseItem i) { // Unplayable if (i.LocationType == LocationType.Virtual && !i.IsFolder) diff --git a/MediaBrowser.Dlna/Didl/DidlBuilder.cs b/MediaBrowser.Dlna/Didl/DidlBuilder.cs index d1941c856..59dcbdecb 100644 --- a/MediaBrowser.Dlna/Didl/DidlBuilder.cs +++ b/MediaBrowser.Dlna/Didl/DidlBuilder.cs @@ -1,5 +1,4 @@ -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Net; +using MediaBrowser.Model.Extensions; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Entities; @@ -13,12 +12,12 @@ using MediaBrowser.Dlna.ContentDirectory; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Net; using System; using System.Globalization; using System.IO; using System.Linq; using System.Xml; -using MediaBrowser.Model.Net; namespace MediaBrowser.Dlna.Didl { @@ -801,7 +800,10 @@ namespace MediaBrowser.Dlna.Didl if (string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase) || string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase)) { - return; + if (!stubType.HasValue) + { + return; + } } } diff --git a/MediaBrowser.Dlna/DlnaManager.cs b/MediaBrowser.Dlna/DlnaManager.cs index 7517cea50..872c07939 100644 --- a/MediaBrowser.Dlna/DlnaManager.cs +++ b/MediaBrowser.Dlna/DlnaManager.cs @@ -132,61 +132,74 @@ namespace MediaBrowser.Dlna { if (!string.IsNullOrWhiteSpace(profileInfo.DeviceDescription)) { - if (deviceInfo.DeviceDescription == null || !Regex.IsMatch(deviceInfo.DeviceDescription, profileInfo.DeviceDescription)) + if (deviceInfo.DeviceDescription == null || !IsRegexMatch(deviceInfo.DeviceDescription, profileInfo.DeviceDescription)) return false; } if (!string.IsNullOrWhiteSpace(profileInfo.FriendlyName)) { - if (deviceInfo.FriendlyName == null || !Regex.IsMatch(deviceInfo.FriendlyName, profileInfo.FriendlyName)) + if (deviceInfo.FriendlyName == null || !IsRegexMatch(deviceInfo.FriendlyName, profileInfo.FriendlyName)) return false; } if (!string.IsNullOrWhiteSpace(profileInfo.Manufacturer)) { - if (deviceInfo.Manufacturer == null || !Regex.IsMatch(deviceInfo.Manufacturer, profileInfo.Manufacturer)) + if (deviceInfo.Manufacturer == null || !IsRegexMatch(deviceInfo.Manufacturer, profileInfo.Manufacturer)) return false; } if (!string.IsNullOrWhiteSpace(profileInfo.ManufacturerUrl)) { - if (deviceInfo.ManufacturerUrl == null || !Regex.IsMatch(deviceInfo.ManufacturerUrl, profileInfo.ManufacturerUrl)) + if (deviceInfo.ManufacturerUrl == null || !IsRegexMatch(deviceInfo.ManufacturerUrl, profileInfo.ManufacturerUrl)) return false; } if (!string.IsNullOrWhiteSpace(profileInfo.ModelDescription)) { - if (deviceInfo.ModelDescription == null || !Regex.IsMatch(deviceInfo.ModelDescription, profileInfo.ModelDescription)) + if (deviceInfo.ModelDescription == null || !IsRegexMatch(deviceInfo.ModelDescription, profileInfo.ModelDescription)) return false; } if (!string.IsNullOrWhiteSpace(profileInfo.ModelName)) { - if (deviceInfo.ModelName == null || !Regex.IsMatch(deviceInfo.ModelName, profileInfo.ModelName)) + if (deviceInfo.ModelName == null || !IsRegexMatch(deviceInfo.ModelName, profileInfo.ModelName)) return false; } if (!string.IsNullOrWhiteSpace(profileInfo.ModelNumber)) { - if (deviceInfo.ModelNumber == null || !Regex.IsMatch(deviceInfo.ModelNumber, profileInfo.ModelNumber)) + if (deviceInfo.ModelNumber == null || !IsRegexMatch(deviceInfo.ModelNumber, profileInfo.ModelNumber)) return false; } if (!string.IsNullOrWhiteSpace(profileInfo.ModelUrl)) { - if (deviceInfo.ModelUrl == null || !Regex.IsMatch(deviceInfo.ModelUrl, profileInfo.ModelUrl)) + if (deviceInfo.ModelUrl == null || !IsRegexMatch(deviceInfo.ModelUrl, profileInfo.ModelUrl)) return false; } if (!string.IsNullOrWhiteSpace(profileInfo.SerialNumber)) { - if (deviceInfo.SerialNumber == null || !Regex.IsMatch(deviceInfo.SerialNumber, profileInfo.SerialNumber)) + if (deviceInfo.SerialNumber == null || !IsRegexMatch(deviceInfo.SerialNumber, profileInfo.SerialNumber)) return false; } return true; } + private bool IsRegexMatch(string input, string pattern) + { + try + { + return Regex.IsMatch(input, pattern); + } + catch (ArgumentException ex) + { + _logger.ErrorException("Error evaluating regex pattern {0}", ex, pattern); + return false; + } + } + public DeviceProfile GetProfile(IDictionary<string, string> headers) { if (headers == null) @@ -393,7 +406,7 @@ namespace MediaBrowser.Dlna throw new ArgumentException("System profiles cannot be deleted."); } - File.Delete(info.Path); + _fileSystem.DeleteFile(info.Path); } public void CreateProfile(DeviceProfile profile) @@ -432,9 +445,9 @@ namespace MediaBrowser.Dlna if (!string.Equals(path, current.Path, StringComparison.Ordinal) && current.Info.Type != DeviceProfileType.System) { - File.Delete(current.Path); + _fileSystem.DeleteFile(current.Path); } - + _xmlSerializer.SerializeToFile(profile, path); } @@ -462,12 +475,12 @@ namespace MediaBrowser.Dlna internal string Path { get; set; } } - public string GetServerDescriptionXml(IDictionary<string, string> headers, string serverUuId) + public string GetServerDescriptionXml(IDictionary<string, string> headers, string serverUuId, string serverAddress) { var profile = GetProfile(headers) ?? GetDefaultProfile(); - return new DescriptionXmlBuilder(profile, serverUuId, "").GetXml(); + return new DescriptionXmlBuilder(profile, serverUuId, serverAddress).GetXml(); } public ImageStream GetIcon(string filename) diff --git a/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs b/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs index 810b1e568..f6c04cdbe 100644 --- a/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs +++ b/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs @@ -165,15 +165,17 @@ namespace MediaBrowser.Dlna.Main { var guid = address.GetMD5(); - var descriptorURI = "/mediabrowser/dlna/" + guid.ToString("N") + "/description.xml"; + var descriptorURI = "/dlna/" + guid.ToString("N") + "/description.xml"; - var uri = new Uri(string.Format("http://{0}:{1}{2}", address, _config.Configuration.HttpServerPortNumber, descriptorURI)); + var uri = new Uri(string.Format("http://{0}:{1}{2}", address, _appHost.HttpPort, descriptorURI)); var services = new List<string> { "upnp:rootdevice", "urn:schemas-upnp-org:device:MediaServer:1", "urn:schemas-upnp-org:service:ContentDirectory:1", + "urn:schemas-upnp-org:service:ConnectionManager:1", + "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1", "uuid:" + guid.ToString("N") }; diff --git a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj index 7871946cb..aed4ef421 100644 --- a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj +++ b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj @@ -64,6 +64,10 @@ <Compile Include="Eventing\EventManager.cs" /> <Compile Include="Eventing\EventSubscription.cs" /> <Compile Include="Main\DlnaEntryPoint.cs" /> + <Compile Include="MediaReceiverRegistrar\ControlHandler.cs" /> + <Compile Include="MediaReceiverRegistrar\MediaReceiverRegistrar.cs" /> + <Compile Include="MediaReceiverRegistrar\MediaReceiverRegistrarXmlBuilder.cs" /> + <Compile Include="MediaReceiverRegistrar\ServiceActionListBuilder.cs" /> <Compile Include="PlayTo\CurrentIdEventArgs.cs" /> <Compile Include="PlayTo\Device.cs"> <SubType>Code</SubType> diff --git a/MediaBrowser.Dlna/MediaReceiverRegistrar/ControlHandler.cs b/MediaBrowser.Dlna/MediaReceiverRegistrar/ControlHandler.cs new file mode 100644 index 000000000..d1f701711 --- /dev/null +++ b/MediaBrowser.Dlna/MediaReceiverRegistrar/ControlHandler.cs @@ -0,0 +1,43 @@ +using MediaBrowser.Common.Extensions; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Dlna.Server; +using MediaBrowser.Dlna.Service; +using MediaBrowser.Model.Logging; +using System; +using System.Collections.Generic; + +namespace MediaBrowser.Dlna.MediaReceiverRegistrar +{ + public class ControlHandler : BaseControlHandler + { + public ControlHandler(IServerConfigurationManager config, ILogger logger) : base(config, logger) + { + } + + protected override IEnumerable<KeyValuePair<string, string>> GetResult(string methodName, Headers methodParams) + { + if (string.Equals(methodName, "IsAuthorized", StringComparison.OrdinalIgnoreCase)) + return HandleIsAuthorized(); + if (string.Equals(methodName, "IsValidated", StringComparison.OrdinalIgnoreCase)) + return HandleIsValidated(); + + throw new ResourceNotFoundException("Unexpected control request name: " + methodName); + } + + private IEnumerable<KeyValuePair<string, string>> HandleIsAuthorized() + { + return new Headers(true) + { + { "Result", "1" } + }; + } + + private IEnumerable<KeyValuePair<string, string>> HandleIsValidated() + { + return new Headers(true) + { + { "Result", "1" } + }; + } + } +} diff --git a/MediaBrowser.Dlna/MediaReceiverRegistrar/MediaReceiverRegistrar.cs b/MediaBrowser.Dlna/MediaReceiverRegistrar/MediaReceiverRegistrar.cs new file mode 100644 index 000000000..a3b2bcee0 --- /dev/null +++ b/MediaBrowser.Dlna/MediaReceiverRegistrar/MediaReceiverRegistrar.cs @@ -0,0 +1,39 @@ +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Dlna; +using MediaBrowser.Dlna.Service; +using MediaBrowser.Model.Logging; +using System; +using System.Collections.Generic; + +namespace MediaBrowser.Dlna.MediaReceiverRegistrar +{ + public class MediaReceiverRegistrar : BaseService, IMediaReceiverRegistrar, IDisposable + { + private readonly IServerConfigurationManager _config; + + public MediaReceiverRegistrar(ILogger logger, IHttpClient httpClient, IServerConfigurationManager config) + : base(logger, httpClient) + { + _config = config; + } + + public string GetServiceXml(IDictionary<string, string> headers) + { + return new MediaReceiverRegistrarXmlBuilder().GetXml(); + } + + public ControlResponse ProcessControlRequest(ControlRequest request) + { + return new ControlHandler( + _config, + Logger) + .ProcessControlRequest(request); + } + + public void Dispose() + { + + } + } +} diff --git a/MediaBrowser.Dlna/MediaReceiverRegistrar/MediaReceiverRegistrarXmlBuilder.cs b/MediaBrowser.Dlna/MediaReceiverRegistrar/MediaReceiverRegistrarXmlBuilder.cs new file mode 100644 index 000000000..cb1fdcecb --- /dev/null +++ b/MediaBrowser.Dlna/MediaReceiverRegistrar/MediaReceiverRegistrarXmlBuilder.cs @@ -0,0 +1,78 @@ +using MediaBrowser.Dlna.Common; +using MediaBrowser.Dlna.Service; +using System.Collections.Generic; + +namespace MediaBrowser.Dlna.MediaReceiverRegistrar +{ + public class MediaReceiverRegistrarXmlBuilder + { + public string GetXml() + { + return new ServiceXmlBuilder().GetXml(new ServiceActionListBuilder().GetActions(), + GetStateVariables()); + } + + private IEnumerable<StateVariable> GetStateVariables() + { + var list = new List<StateVariable>(); + + list.Add(new StateVariable + { + Name = "AuthorizationGrantedUpdateID", + DataType = "ui4", + SendsEvents = true + }); + + list.Add(new StateVariable + { + Name = "A_ARG_TYPE_DeviceID", + DataType = "string", + SendsEvents = false + }); + + list.Add(new StateVariable + { + Name = "AuthorizationDeniedUpdateID", + DataType = "ui4", + SendsEvents = true + }); + + list.Add(new StateVariable + { + Name = "ValidationSucceededUpdateID", + DataType = "ui4", + SendsEvents = true + }); + + list.Add(new StateVariable + { + Name = "A_ARG_TYPE_RegistrationRespMsg", + DataType = "bin.base64", + SendsEvents = false + }); + + list.Add(new StateVariable + { + Name = "A_ARG_TYPE_RegistrationReqMsg", + DataType = "bin.base64", + SendsEvents = false + }); + + list.Add(new StateVariable + { + Name = "ValidationRevokedUpdateID", + DataType = "ui4", + SendsEvents = true + }); + + list.Add(new StateVariable + { + Name = "A_ARG_TYPE_Result", + DataType = "int", + SendsEvents = false + }); + + return list; + } + } +} diff --git a/MediaBrowser.Dlna/MediaReceiverRegistrar/ServiceActionListBuilder.cs b/MediaBrowser.Dlna/MediaReceiverRegistrar/ServiceActionListBuilder.cs new file mode 100644 index 000000000..7e19805db --- /dev/null +++ b/MediaBrowser.Dlna/MediaReceiverRegistrar/ServiceActionListBuilder.cs @@ -0,0 +1,154 @@ +using MediaBrowser.Dlna.Common; +using System.Collections.Generic; + +namespace MediaBrowser.Dlna.MediaReceiverRegistrar +{ + public class ServiceActionListBuilder + { + public IEnumerable<ServiceAction> GetActions() + { + var list = new List<ServiceAction> + { + GetIsValidated(), + GetIsAuthorized(), + GetRegisterDevice(), + GetGetAuthorizationDeniedUpdateID(), + GetGetAuthorizationGrantedUpdateID(), + GetGetValidationRevokedUpdateID(), + GetGetValidationSucceededUpdateID() + }; + + return list; + } + + private ServiceAction GetIsValidated() + { + var action = new ServiceAction + { + Name = "IsValidated" + }; + + action.ArgumentList.Add(new Argument + { + Name = "DeviceID", + Direction = "in" + }); + + action.ArgumentList.Add(new Argument + { + Name = "Result", + Direction = "out" + }); + + return action; + } + + private ServiceAction GetIsAuthorized() + { + var action = new ServiceAction + { + Name = "IsAuthorized" + }; + + action.ArgumentList.Add(new Argument + { + Name = "DeviceID", + Direction = "in" + }); + + action.ArgumentList.Add(new Argument + { + Name = "Result", + Direction = "out" + }); + + return action; + } + + private ServiceAction GetRegisterDevice() + { + var action = new ServiceAction + { + Name = "RegisterDevice" + }; + + action.ArgumentList.Add(new Argument + { + Name = "RegistrationReqMsg", + Direction = "in" + }); + + action.ArgumentList.Add(new Argument + { + Name = "RegistrationRespMsg", + Direction = "out" + }); + + return action; + } + + private ServiceAction GetGetValidationSucceededUpdateID() + { + var action = new ServiceAction + { + Name = "GetValidationSucceededUpdateID" + }; + + action.ArgumentList.Add(new Argument + { + Name = "ValidationSucceededUpdateID", + Direction = "out" + }); + + return action; + } + + private ServiceAction GetGetAuthorizationDeniedUpdateID() + { + var action = new ServiceAction + { + Name = "GetAuthorizationDeniedUpdateID" + }; + + action.ArgumentList.Add(new Argument + { + Name = "AuthorizationDeniedUpdateID", + Direction = "out" + }); + + return action; + } + + private ServiceAction GetGetValidationRevokedUpdateID() + { + var action = new ServiceAction + { + Name = "GetValidationRevokedUpdateID" + }; + + action.ArgumentList.Add(new Argument + { + Name = "ValidationRevokedUpdateID", + Direction = "out" + }); + + return action; + } + + private ServiceAction GetGetAuthorizationGrantedUpdateID() + { + var action = new ServiceAction + { + Name = "GetAuthorizationGrantedUpdateID" + }; + + action.ArgumentList.Add(new Argument + { + Name = "AuthorizationGrantedUpdateID", + Direction = "out" + }); + + return action; + } + } +} diff --git a/MediaBrowser.Dlna/PlayTo/Device.cs b/MediaBrowser.Dlna/PlayTo/Device.cs index c43efcd1d..00cb34be3 100644 --- a/MediaBrowser.Dlna/PlayTo/Device.cs +++ b/MediaBrowser.Dlna/PlayTo/Device.cs @@ -712,14 +712,10 @@ namespace MediaBrowser.Dlna.PlayTo if (avService == null) return; - var url = avService.ScpdUrl; - if (!url.Contains("/")) - url = "/dmr/" + url; - if (!url.StartsWith("/")) - url = "/" + url; + string url = NormalizeUrl(Properties.BaseUrl, avService.ScpdUrl); var httpClient = new SsdpHttpClient(_httpClient, _config); - var document = await httpClient.GetDataAsync(Properties.BaseUrl + url); + var document = await httpClient.GetDataAsync(url); AvCommands = TransportCommands.Create(document); } @@ -730,16 +726,28 @@ namespace MediaBrowser.Dlna.PlayTo if (avService == null) return; - string url = avService.ScpdUrl; + string url = NormalizeUrl(Properties.BaseUrl, avService.ScpdUrl); + + var httpClient = new SsdpHttpClient(_httpClient, _config); + var document = await httpClient.GetDataAsync(url); + + RendererCommands = TransportCommands.Create(document); + } + + private string NormalizeUrl(string baseUrl, string url) + { + // If it's already a complete url, don't stick anything onto the front of it + if (url.StartsWith("http", StringComparison.OrdinalIgnoreCase)) + { + return url; + } + if (!url.Contains("/")) url = "/dmr/" + url; if (!url.StartsWith("/")) url = "/" + url; - var httpClient = new SsdpHttpClient(_httpClient, _config); - var document = await httpClient.GetDataAsync(Properties.BaseUrl + url); - - RendererCommands = TransportCommands.Create(document); + return baseUrl + url; } private TransportCommands AvCommands diff --git a/MediaBrowser.Dlna/PlayTo/PlayToController.cs b/MediaBrowser.Dlna/PlayTo/PlayToController.cs index 1989c437a..bd2b169ad 100644 --- a/MediaBrowser.Dlna/PlayTo/PlayToController.cs +++ b/MediaBrowser.Dlna/PlayTo/PlayToController.cs @@ -272,7 +272,7 @@ namespace MediaBrowser.Dlna.PlayTo return new PlaybackStartInfo { - ItemId = mediaInfo.Id, + ItemId = info.ItemId, SessionId = _session.Id, PositionTicks = ticks, IsMuted = _device.IsMuted, @@ -899,5 +899,11 @@ namespace MediaBrowser.Dlna.PlayTo return request; } } + + public Task SendMessage<T>(string name, T data, CancellationToken cancellationToken) + { + // Not supported or needed right now + return Task.FromResult(true); + } } } diff --git a/MediaBrowser.Dlna/PlayTo/PlayToManager.cs b/MediaBrowser.Dlna/PlayTo/PlayToManager.cs index a60b5efa4..5e37417c6 100644 --- a/MediaBrowser.Dlna/PlayTo/PlayToManager.cs +++ b/MediaBrowser.Dlna/PlayTo/PlayToManager.cs @@ -152,7 +152,7 @@ namespace MediaBrowser.Dlna.PlayTo "http", localIp, - _appHost.HttpServerPort + _appHost.HttpPort ); } diff --git a/MediaBrowser.Dlna/PlayTo/SsdpHttpClient.cs b/MediaBrowser.Dlna/PlayTo/SsdpHttpClient.cs index ccc7d46e6..f0689751c 100644 --- a/MediaBrowser.Dlna/PlayTo/SsdpHttpClient.cs +++ b/MediaBrowser.Dlna/PlayTo/SsdpHttpClient.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Common.Net; +using System; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Dlna.Common; using System.Globalization; @@ -29,11 +30,7 @@ namespace MediaBrowser.Dlna.PlayTo string postData, string header = null) { - var serviceUrl = service.ControlUrl; - if (!serviceUrl.StartsWith("/")) - serviceUrl = "/" + serviceUrl; - - var response = await PostSoapDataAsync(baseUrl + serviceUrl, "\"" + service.ServiceType + "#" + command + "\"", postData, header) + var response = await PostSoapDataAsync(NormalizeServiceUrl(baseUrl, service.ControlUrl), "\"" + service.ServiceType + "#" + command + "\"", postData, header) .ConfigureAwait(false); using (var stream = response.Content) @@ -45,6 +42,20 @@ namespace MediaBrowser.Dlna.PlayTo } } + private string NormalizeServiceUrl(string baseUrl, string serviceUrl) + { + // If it's already a complete url, don't stick anything onto the front of it + if (serviceUrl.StartsWith("http", StringComparison.OrdinalIgnoreCase)) + { + return serviceUrl; + } + + if (!serviceUrl.StartsWith("/")) + serviceUrl = "/" + serviceUrl; + + return baseUrl + serviceUrl; + } + private readonly CultureInfo _usCulture = new CultureInfo("en-US"); public async Task SubscribeAsync(string url, diff --git a/MediaBrowser.Dlna/Profiles/SamsungSmartTvProfile.cs b/MediaBrowser.Dlna/Profiles/SamsungSmartTvProfile.cs index 1499d0e74..970995b7d 100644 --- a/MediaBrowser.Dlna/Profiles/SamsungSmartTvProfile.cs +++ b/MediaBrowser.Dlna/Profiles/SamsungSmartTvProfile.cs @@ -336,6 +336,13 @@ namespace MediaBrowser.Dlna.Profiles Container = "mkv", MimeType = "video/x-mkv", Type = DlnaProfileType.Video + }, + + new ResponseProfile + { + Container = "flac", + MimeType = "audio/x-flac", + Type = DlnaProfileType.Audio } }; diff --git a/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml b/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml index 27d8e00ec..d2b814de3 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml @@ -110,6 +110,9 @@ <ResponseProfile container="mkv" type="Video" mimeType="video/x-mkv"> <Conditions /> </ResponseProfile> + <ResponseProfile container="flac" type="Audio" mimeType="audio/x-flac"> + <Conditions /> + </ResponseProfile> </ResponseProfiles> <SubtitleProfiles> <SubtitleProfile format="srt" method="External" didlMode="CaptionInfoEx" /> diff --git a/MediaBrowser.Dlna/Server/DescriptionXmlBuilder.cs b/MediaBrowser.Dlna/Server/DescriptionXmlBuilder.cs index f4f724d07..ae544cb6c 100644 --- a/MediaBrowser.Dlna/Server/DescriptionXmlBuilder.cs +++ b/MediaBrowser.Dlna/Server/DescriptionXmlBuilder.cs @@ -23,11 +23,21 @@ namespace MediaBrowser.Dlna.Server throw new ArgumentNullException("serverUdn"); } + if (string.IsNullOrWhiteSpace(serverAddress)) + { + throw new ArgumentNullException("serverAddress"); + } + _profile = profile; _serverUdn = serverUdn; _serverAddress = serverAddress; } + private bool EnableAbsoluteUrls + { + get { return false; } + } + public string GetXml() { var builder = new StringBuilder(); @@ -81,8 +91,13 @@ namespace MediaBrowser.Dlna.Server builder.Append("<modelURL>" + SecurityElement.Escape(_profile.ModelUrl ?? string.Empty) + "</modelURL>"); builder.Append("<serialNumber>" + SecurityElement.Escape(_profile.SerialNumber ?? string.Empty) + "</serialNumber>"); - //builder.Append("<URLBase>" + SecurityElement.Escape(_serverAddress) + "</URLBase>"); - + builder.Append("<presentationURL>" + SecurityElement.Escape(_serverAddress) + "</presentationURL>"); + + if (!EnableAbsoluteUrls) + { + builder.Append("<URLBase>" + SecurityElement.Escape(_serverAddress) + "</URLBase>"); + } + if (!string.IsNullOrWhiteSpace(_profile.SonyAggregationFlags)) { builder.Append("<av:aggregationFlags xmlns:av=\"urn:schemas-sony-com:av\">" + SecurityElement.Escape(_profile.SonyAggregationFlags) + "</av:aggregationFlags>"); @@ -101,7 +116,7 @@ namespace MediaBrowser.Dlna.Server builder.Append("<width>" + SecurityElement.Escape(icon.Width.ToString(_usCulture)) + "</width>"); builder.Append("<height>" + SecurityElement.Escape(icon.Height.ToString(_usCulture)) + "</height>"); builder.Append("<depth>" + SecurityElement.Escape(icon.Depth ?? string.Empty) + "</depth>"); - builder.Append("<url>" + SecurityElement.Escape(icon.Url ?? string.Empty) + "</url>"); + builder.Append("<url>" + BuildUrl(icon.Url) + "</url>"); builder.Append("</icon>"); } @@ -119,9 +134,9 @@ namespace MediaBrowser.Dlna.Server builder.Append("<serviceType>" + SecurityElement.Escape(service.ServiceType ?? string.Empty) + "</serviceType>"); builder.Append("<serviceId>" + SecurityElement.Escape(service.ServiceId ?? string.Empty) + "</serviceId>"); - builder.Append("<SCPDURL>" + SecurityElement.Escape(service.ScpdUrl ?? string.Empty) + "</SCPDURL>"); - builder.Append("<controlURL>" + SecurityElement.Escape(service.ControlUrl ?? string.Empty) + "</controlURL>"); - builder.Append("<eventSubURL>" + SecurityElement.Escape(service.EventSubUrl ?? string.Empty) + "</eventSubURL>"); + builder.Append("<SCPDURL>" + BuildUrl(service.ScpdUrl) + "</SCPDURL>"); + builder.Append("<controlURL>" + BuildUrl(service.ControlUrl) + "</controlURL>"); + builder.Append("<eventSubURL>" + BuildUrl(service.EventSubUrl) + "</eventSubURL>"); builder.Append("</service>"); } @@ -129,6 +144,25 @@ namespace MediaBrowser.Dlna.Server builder.Append("</serviceList>"); } + private string BuildUrl(string url) + { + if (string.IsNullOrWhiteSpace(url)) + { + return string.Empty; + } + + url = url.TrimStart('/'); + + url = "/dlna/" + _serverUdn + "/" + url; + + if (EnableAbsoluteUrls) + { + url = _serverAddress.TrimEnd('/') + url; + } + + return SecurityElement.Escape(url); + } + private IEnumerable<DeviceIcon> GetIcons() { var list = new List<DeviceIcon>(); @@ -139,7 +173,7 @@ namespace MediaBrowser.Dlna.Server Depth = "24", Width = 240, Height = 240, - Url = "/mediabrowser/dlna/icons/logo240.png" + Url = "icons/logo240.png" }); list.Add(new DeviceIcon @@ -148,7 +182,7 @@ namespace MediaBrowser.Dlna.Server Depth = "24", Width = 240, Height = 240, - Url = "/mediabrowser/dlna/icons/logo240.jpg" + Url = "icons/logo240.jpg" }); list.Add(new DeviceIcon @@ -157,7 +191,7 @@ namespace MediaBrowser.Dlna.Server Depth = "24", Width = 120, Height = 120, - Url = "/mediabrowser/dlna/icons/logo120.png" + Url = "icons/logo120.png" }); list.Add(new DeviceIcon @@ -166,7 +200,7 @@ namespace MediaBrowser.Dlna.Server Depth = "24", Width = 120, Height = 120, - Url = "/mediabrowser/dlna/icons/logo120.jpg" + Url = "icons/logo120.jpg" }); list.Add(new DeviceIcon @@ -175,7 +209,7 @@ namespace MediaBrowser.Dlna.Server Depth = "24", Width = 48, Height = 48, - Url = "/mediabrowser/dlna/icons/logo48.png" + Url = "icons/logo48.png" }); list.Add(new DeviceIcon @@ -184,7 +218,7 @@ namespace MediaBrowser.Dlna.Server Depth = "24", Width = 48, Height = 48, - Url = "/mediabrowser/dlna/icons/logo48.jpg" + Url = "icons/logo48.jpg" }); return list; @@ -198,18 +232,27 @@ namespace MediaBrowser.Dlna.Server { ServiceType = "urn:schemas-upnp-org:service:ContentDirectory:1", ServiceId = "urn:upnp-org:serviceId:ContentDirectory", - ScpdUrl = "/mediabrowser/dlna/contentdirectory/contentdirectory.xml", - ControlUrl = "/mediabrowser/dlna/contentdirectory/" + _serverUdn + "/control", - EventSubUrl = "/mediabrowser/dlna/contentdirectory/" + _serverUdn + "/events" + ScpdUrl = "contentdirectory/contentdirectory.xml", + ControlUrl = "contentdirectory/control", + EventSubUrl = "contentdirectory/events" }); list.Add(new DeviceService { ServiceType = "urn:schemas-upnp-org:service:ConnectionManager:1", ServiceId = "urn:upnp-org:serviceId:ConnectionManager", - ScpdUrl = "/mediabrowser/dlna/connectionmanager/connectionmanager.xml", - ControlUrl = "/mediabrowser/dlna/connectionmanager/" + _serverUdn + "/control", - EventSubUrl = "/mediabrowser/dlna/connectionmanager/" + _serverUdn + "/events" + ScpdUrl = "connectionmanager/connectionmanager.xml", + ControlUrl = "connectionmanager/control", + EventSubUrl = "connectionmanager/events" + }); + + list.Add(new DeviceService + { + ServiceType = "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1", + ServiceId = "urn:microsoft.com:serviceId:X_MS_MediaReceiverRegistrar", + ScpdUrl = "mediareceiverregistrar/mediareceiverregistrar.xml", + ControlUrl = "mediareceiverregistrar/control", + EventSubUrl = "mediareceiverregistrar/events" }); return list; diff --git a/MediaBrowser.Dlna/Ssdp/Datagram.cs b/MediaBrowser.Dlna/Ssdp/Datagram.cs index f16464209..ae79ab44f 100644 --- a/MediaBrowser.Dlna/Ssdp/Datagram.cs +++ b/MediaBrowser.Dlna/Ssdp/Datagram.cs @@ -11,26 +11,15 @@ namespace MediaBrowser.Dlna.Ssdp public EndPoint ToEndPoint { get; private set; } public EndPoint FromEndPoint { get; private set; } public string Message { get; private set; } - - /// <summary> - /// The number of times to send the message - /// </summary> - public int TotalSendCount { get; private set; } public bool IgnoreBindFailure { get; private set; } - /// <summary> - /// The number of times the message has been sent - /// </summary> - public int SendCount { get; private set; } - private readonly ILogger _logger; - public Datagram(EndPoint toEndPoint, EndPoint fromEndPoint, ILogger logger, string message, int totalSendCount, bool ignoreBindFailure) + public Datagram(EndPoint toEndPoint, EndPoint fromEndPoint, ILogger logger, string message, bool ignoreBindFailure) { Message = message; _logger = logger; IgnoreBindFailure = ignoreBindFailure; - TotalSendCount = totalSendCount; FromEndPoint = fromEndPoint; ToEndPoint = toEndPoint; } @@ -83,7 +72,6 @@ namespace MediaBrowser.Dlna.Ssdp { _logger.ErrorException("Error sending Datagram to {0} from {1}: " + Message, ex, ToEndPoint, FromEndPoint == null ? "" : FromEndPoint.ToString()); } - ++SendCount; } private Socket CreateSocket() diff --git a/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs b/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs index adc2d731a..a90c6dc01 100644 --- a/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs +++ b/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs @@ -86,7 +86,7 @@ namespace MediaBrowser.Dlna.Ssdp try { - var ip = _appHost.HttpServerIpAddresses.FirstOrDefault(); + var ip = _appHost.LocalIpAddress; if (!string.IsNullOrWhiteSpace(ip)) { diff --git a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs index bd3098ecd..8ca16832d 100644 --- a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs +++ b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs @@ -62,20 +62,14 @@ namespace MediaBrowser.Dlna.Ssdp { if (string.Equals(args.Method, "M-SEARCH", StringComparison.OrdinalIgnoreCase)) { - string mx = null; - args.Headers.TryGetValue("mx", out mx); - int delaySeconds; - if (!string.IsNullOrWhiteSpace(mx) && - int.TryParse(mx, NumberStyles.Any, CultureInfo.InvariantCulture, out delaySeconds) - && delaySeconds > 0) + TimeSpan delay = GetSearchDelay(args.Headers); + + if (_config.GetDlnaConfiguration().EnableDebugLogging) { - if (_config.GetDlnaConfiguration().EnableDebugLogging) - { - _logger.Debug("Delaying search response by {0} seconds", delaySeconds); - } - - await Task.Delay(delaySeconds * 1000).ConfigureAwait(false); + _logger.Debug("Delaying search response by {0} seconds", delay.TotalSeconds); } + + await Task.Delay(delay).ConfigureAwait(false); RespondToSearch(args.EndPoint, args.Headers["st"]); } @@ -135,17 +129,50 @@ namespace MediaBrowser.Dlna.Ssdp int sendCount = 1) { var msg = new SsdpMessageBuilder().BuildMessage(header, values); + var queued = false; - var dgram = new Datagram(endpoint, localAddress, _logger, msg, sendCount, ignoreBindFailure); + for (var i = 0; i < sendCount; i++) + { + var dgram = new Datagram(endpoint, localAddress, _logger, msg, ignoreBindFailure); - if (_messageQueue.Count == 0) + if (_messageQueue.Count == 0) + { + dgram.Send(); + } + else + { + _messageQueue.Enqueue(dgram); + queued = true; + } + } + + if (queued) { - dgram.Send(); - return; + StartQueueTimer(); } + } - _messageQueue.Enqueue(dgram); - StartQueueTimer(); + /// <summary> + /// According to the spec: http://www.upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.0-20080424.pdf + /// Device responses should be delayed a random duration between 0 and this many seconds to balance + /// load for the control point when it processes responses. In my testing kodi times out after mx + /// so we will generate from mx - 1 + /// </summary> + /// <param name="headers">The mx headers</param> + /// <returns>A timepsan for the amount to delay before returning search result.</returns> + private TimeSpan GetSearchDelay(Dictionary<string, string> headers) + { + string mx; + headers.TryGetValue("mx", out mx); + int delaySeconds = 0; + if (!string.IsNullOrWhiteSpace(mx) + && int.TryParse(mx, NumberStyles.Any, CultureInfo.InvariantCulture, out delaySeconds) + && delaySeconds > 1) + { + delaySeconds = new Random().Next(delaySeconds - 1); + } + + return TimeSpan.FromSeconds(delaySeconds); } private void RespondToSearch(EndPoint endpoint, string deviceType) @@ -172,8 +199,8 @@ namespace MediaBrowser.Dlna.Ssdp values["ST"] = d.Type; values["USN"] = d.USN; - SendDatagram(header, values, endpoint, null, true); - SendDatagram(header, values, endpoint, new IPEndPoint(d.Address, 0), true); + SendDatagram(header, values, endpoint, null, true, 1); + SendDatagram(header, values, endpoint, new IPEndPoint(d.Address, 0), true, 1); //SendDatagram(header, values, endpoint, null, true); if (_config.GetDlnaConfiguration().EnableDebugLogging) @@ -191,36 +218,21 @@ namespace MediaBrowser.Dlna.Ssdp { if (_queueTimer == null) { - _queueTimer = new Timer(QueueTimerCallback, null, 1000, Timeout.Infinite); + _queueTimer = new Timer(QueueTimerCallback, null, 500, Timeout.Infinite); } else { - _queueTimer.Change(1000, Timeout.Infinite); + _queueTimer.Change(500, Timeout.Infinite); } } } private void QueueTimerCallback(object state) { - while (_messageQueue.Count != 0) + Datagram msg; + while (_messageQueue.TryDequeue(out msg)) { - Datagram msg; - if (!_messageQueue.TryPeek(out msg)) - { - continue; - } - - if (msg != null && (!_isDisposed || msg.TotalSendCount > 1)) - { - msg.Send(); - if (msg.SendCount > msg.TotalSendCount) - { - _messageQueue.TryDequeue(out msg); - } - break; - } - - _messageQueue.TryDequeue(out msg); + msg.Send(); } _datagramPosted.Set(); diff --git a/MediaBrowser.LocalMetadata/BaseXmlProvider.cs b/MediaBrowser.LocalMetadata/BaseXmlProvider.cs index 7c60df4cb..afe4b5799 100644 --- a/MediaBrowser.LocalMetadata/BaseXmlProvider.cs +++ b/MediaBrowser.LocalMetadata/BaseXmlProvider.cs @@ -8,7 +8,7 @@ using System.Threading.Tasks; namespace MediaBrowser.LocalMetadata { - public abstract class BaseXmlProvider<T> : ILocalMetadataProvider<T>, IHasChangeMonitor + public abstract class BaseXmlProvider<T> : ILocalMetadataProvider<T>, IHasChangeMonitor, IHasOrder where T : IHasMetadata, new() { protected IFileSystem FileSystem; diff --git a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj index cb9c23494..894be8799 100644 --- a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj +++ b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj @@ -61,7 +61,6 @@ <Compile Include="Providers\AlbumXmlProvider.cs" /> <Compile Include="Providers\ArtistXmlProvider.cs" /> <Compile Include="Providers\BoxSetXmlProvider.cs" /> - <Compile Include="Providers\ChannelXmlProvider.cs" /> <Compile Include="Providers\EpisodeXmlProvider.cs" /> <Compile Include="Providers\FolderXmlProvider.cs" /> <Compile Include="Providers\GameSystemXmlProvider.cs" /> @@ -74,7 +73,6 @@ <Compile Include="Providers\SeriesXmlProvider.cs" /> <Compile Include="Providers\VideoXmlProvider.cs" /> <Compile Include="Savers\BoxSetXmlSaver.cs" /> - <Compile Include="Savers\ChannelXmlSaver.cs" /> <Compile Include="Savers\EpisodeXmlSaver.cs" /> <Compile Include="Savers\FolderXmlSaver.cs" /> <Compile Include="Savers\GameSystemXmlSaver.cs" /> diff --git a/MediaBrowser.LocalMetadata/Providers/ChannelXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/ChannelXmlProvider.cs deleted file mode 100644 index 78845487a..000000000 --- a/MediaBrowser.LocalMetadata/Providers/ChannelXmlProvider.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.IO; -using System.Threading; -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Logging; - -namespace MediaBrowser.LocalMetadata.Providers -{ - public class ChannelXmlProvider : BaseXmlProvider<LiveTvChannel> - { - private readonly ILogger _logger; - - public ChannelXmlProvider(IFileSystem fileSystem, ILogger logger) - : base(fileSystem) - { - _logger = logger; - } - - protected override void Fetch(LocalMetadataResult<LiveTvChannel> result, string path, CancellationToken cancellationToken) - { - new BaseItemXmlParser<LiveTvChannel>(_logger).Fetch(result.Item, path, cancellationToken); - } - - protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService) - { - return directoryService.GetFile(Path.Combine(info.Path, "channel.xml")); - } - } -} diff --git a/MediaBrowser.LocalMetadata/Providers/EpisodeXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/EpisodeXmlProvider.cs index dff3c1c07..d80009330 100644 --- a/MediaBrowser.LocalMetadata/Providers/EpisodeXmlProvider.cs +++ b/MediaBrowser.LocalMetadata/Providers/EpisodeXmlProvider.cs @@ -1,16 +1,16 @@ -using System.Collections.Generic; -using System.IO; -using System.Threading; -using MediaBrowser.Common.IO; +using MediaBrowser.Common.IO; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Providers; using MediaBrowser.LocalMetadata.Parsers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; +using System.Collections.Generic; +using System.IO; +using System.Threading; namespace MediaBrowser.LocalMetadata.Providers { - public class EpisodeXmlProvider : BaseXmlProvider<Episode>, IHasOrder + public class EpisodeXmlProvider : BaseXmlProvider<Episode> { private readonly ILogger _logger; @@ -40,14 +40,5 @@ namespace MediaBrowser.LocalMetadata.Providers return directoryService.GetFile(metadataFile); } - - public int Order - { - get - { - // After Xbmc - return 1; - } - } } } diff --git a/MediaBrowser.LocalMetadata/Savers/ChannelXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/ChannelXmlSaver.cs deleted file mode 100644 index 03fdf2bc8..000000000 --- a/MediaBrowser.LocalMetadata/Savers/ChannelXmlSaver.cs +++ /dev/null @@ -1,81 +0,0 @@ -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.LiveTv; -using System.Collections.Generic; -using System.IO; -using System.Text; -using System.Threading; - -namespace MediaBrowser.LocalMetadata.Savers -{ - /// <summary> - /// Class PersonXmlSaver - /// </summary> - public class ChannelXmlSaver : IMetadataFileSaver - { - private readonly IServerConfigurationManager _config; - - public ChannelXmlSaver(IServerConfigurationManager config) - { - _config = config; - } - - /// <summary> - /// Determines whether [is enabled for] [the specified item]. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="updateType">Type of the update.</param> - /// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns> - public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) - { - if (!item.SupportsLocalMetadata) - { - return false; - } - - return item is LiveTvChannel && updateType >= ItemUpdateType.MetadataDownload; - } - - public string Name - { - get - { - return XmlProviderUtils.Name; - } - } - - /// <summary> - /// Saves the specified item. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public void Save(IHasMetadata item, CancellationToken cancellationToken) - { - var builder = new StringBuilder(); - - builder.Append("<Item>"); - - XmlSaverHelpers.AddCommonNodes((LiveTvChannel)item, builder); - - builder.Append("</Item>"); - - var xmlFilePath = GetSavePath(item); - - XmlSaverHelpers.Save(builder, xmlFilePath, new List<string> - { - }, _config); - } - - /// <summary> - /// Gets the save path. - /// </summary> - /// <param name="item">The item.</param> - /// <returns>System.String.</returns> - public string GetSavePath(IHasMetadata item) - { - return Path.Combine(item.Path, "channel.xml"); - } - } -} diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs index ecf5d72d5..344eb9fbd 100644 --- a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs @@ -248,7 +248,7 @@ namespace MediaBrowser.MediaEncoding.Encoder protected virtual void DeleteFiles(EncodingJob job) { - File.Delete(job.OutputFilePath); + FileSystem.DeleteFile(job.OutputFilePath); } private void OnTranscodeBeginning(EncodingJob job) @@ -280,13 +280,14 @@ namespace MediaBrowser.MediaEncoding.Encoder private string GetOutputFilePath(EncodingJob state) { - var folder = ConfigurationManager.ApplicationPaths.TranscodingTempPath; + var folder = string.IsNullOrWhiteSpace(state.Options.OutputDirectory) ? + ConfigurationManager.ApplicationPaths.TranscodingTempPath : + state.Options.OutputDirectory; var outputFileExtension = GetOutputFileExtension(state); - var context = state.Options.Context; var filename = state.Id + (outputFileExtension ?? string.Empty).ToLower(); - return Path.Combine(folder, context.ToString().ToLower(), filename); + return Path.Combine(folder, filename); } protected virtual string GetOutputFileExtension(EncodingJob state) @@ -460,7 +461,7 @@ namespace MediaBrowser.MediaEncoding.Encoder // { // if (SupportsThrottleWithStream) // { - // var url = "http://localhost:" + ServerConfigurationManager.Configuration.HttpServerPortNumber.ToString(UsCulture) + "/mediabrowser/videos/" + job.Request.Id + "/stream?static=true&Throttle=true&mediaSourceId=" + job.Request.MediaSourceId; + // var url = "http://localhost:" + ServerConfigurationManager.Configuration.HttpServerPortNumber.ToString(UsCulture) + "/videos/" + job.Request.Id + "/stream?static=true&Throttle=true&mediaSourceId=" + job.Request.MediaSourceId; // url += "&transcodingJobId=" + transcodingJobId; @@ -1014,7 +1015,7 @@ namespace MediaBrowser.MediaEncoding.Encoder if (!string.IsNullOrEmpty(state.SubtitleStream.Language)) { - var charenc = SubtitleEncoder.GetSubtitleFileCharacterSet(subtitlePath, state.SubtitleStream.Language); + var charenc = SubtitleEncoder.GetSubtitleFileCharacterSet(subtitlePath); if (!string.IsNullOrEmpty(charenc)) { diff --git a/MediaBrowser.MediaEncoding/Encoder/JobLogger.cs b/MediaBrowser.MediaEncoding/Encoder/JobLogger.cs index 6be870519..cb6e58f17 100644 --- a/MediaBrowser.MediaEncoding/Encoder/JobLogger.cs +++ b/MediaBrowser.MediaEncoding/Encoder/JobLogger.cs @@ -1,4 +1,4 @@ -using MediaBrowser.Common.Extensions; +using MediaBrowser.Model.Extensions; using MediaBrowser.Model.Logging; using System; using System.Globalization; diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index a4ab1c551..d631cab98 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -357,6 +357,8 @@ namespace MediaBrowser.MediaEncoding.Encoder } }; + _logger.Debug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); + await resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); process.Start(); diff --git a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs index aaaafc226..f28944945 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs @@ -1,4 +1,4 @@ -using MediaBrowser.Common.Extensions; +using MediaBrowser.Model.Extensions; using System; using System.Collections.Generic; using System.Globalization; diff --git a/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs index ea565f70a..9751176cb 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs @@ -1,16 +1,25 @@ -using System; +using MediaBrowser.Model.Extensions; +using MediaBrowser.Model.Logging; +using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Text.RegularExpressions; using System.Threading; -using MediaBrowser.Common.Extensions; namespace MediaBrowser.MediaEncoding.Subtitles { public class SrtParser : ISubtitleParser { + private readonly ILogger _logger; + private readonly CultureInfo _usCulture = new CultureInfo("en-US"); + + public SrtParser(ILogger logger) + { + _logger = logger; + } + public SubtitleTrackInfo Parse(Stream stream, CancellationToken cancellationToken) { var trackInfo = new SubtitleTrackInfo(); @@ -34,6 +43,14 @@ namespace MediaBrowser.MediaEncoding.Subtitles } var time = Regex.Split(line, @"[\t ]*-->[\t ]*"); + + if (time.Length < 2) + { + // This occurs when subtitle text has an empty line as part of the text. + // Need to adjust the break statement below to resolve this. + _logger.Warn("Unrecognized line in srt: {0}", line); + continue; + } subEvent.StartPositionTicks = GetTicks(time[0]); var endTime = time[1]; var idx = endTime.IndexOf(" ", StringComparison.Ordinal); diff --git a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs index d82ef4e24..358251625 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs @@ -1,4 +1,4 @@ -using MediaBrowser.Common.Extensions; +using MediaBrowser.Model.Extensions; using System; using System.IO; using System.Text; diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 4f8b6c6ac..b9cad27e0 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -149,22 +149,22 @@ namespace MediaBrowser.MediaEncoding.Subtitles var fileInfo = await GetReadableFile(mediaSource.Path, inputFiles, mediaSource.Protocol, subtitleStream, cancellationToken).ConfigureAwait(false); - var stream = await GetSubtitleStream(fileInfo.Item1, subtitleStream.Language, fileInfo.Item3).ConfigureAwait(false); + var stream = await GetSubtitleStream(fileInfo.Item1, fileInfo.Item3).ConfigureAwait(false); return new Tuple<Stream, string>(stream, fileInfo.Item2); } - private async Task<Stream> GetSubtitleStream(string path, string language, bool requiresCharset) + private async Task<Stream> GetSubtitleStream(string path, bool requiresCharset) { - if (requiresCharset && !string.IsNullOrEmpty(language)) + if (requiresCharset) { - var charset = GetSubtitleFileCharacterSet(path, language); + var charset = GetSubtitleFileCharacterSet(path); if (!string.IsNullOrEmpty(charset)) { using (var fs = _fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true)) { - using (var reader = new StreamReader(fs, Encoding.GetEncoding(charset))) + using (var reader = new StreamReader(fs, GetEncoding(charset))) { var text = await reader.ReadToEndAsync().ConfigureAwait(false); @@ -179,6 +179,23 @@ namespace MediaBrowser.MediaEncoding.Subtitles return File.OpenRead(path); } + private Encoding GetEncoding(string charset) + { + if (string.IsNullOrWhiteSpace(charset)) + { + throw new ArgumentNullException("charset"); + } + + try + { + return Encoding.GetEncoding(charset); + } + catch (ArgumentException) + { + return Encoding.GetEncoding(charset.Replace("-", string.Empty)); + } + } + private async Task<Tuple<string, string, bool>> GetReadableFile(string mediaPath, string[] inputFiles, MediaProtocol protocol, @@ -227,8 +244,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles // Convert var outputPath = GetSubtitleCachePath(mediaPath, subtitleStream.Index, ".srt"); - await ConvertTextSubtitleToSrt(subtitleStream.Path, outputPath, subtitleStream.Language, cancellationToken) - .ConfigureAwait(false); + await ConvertTextSubtitleToSrt(subtitleStream.Path, outputPath, cancellationToken).ConfigureAwait(false); return new Tuple<string, string, bool>(outputPath, "srt", true); } @@ -254,7 +270,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles if (string.Equals(format, SubtitleFormat.SRT, StringComparison.OrdinalIgnoreCase)) { - return new SrtParser(); + return new SrtParser(_logger); } if (string.Equals(format, SubtitleFormat.SSA, StringComparison.OrdinalIgnoreCase)) { @@ -321,11 +337,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// </summary> /// <param name="inputPath">The input path.</param> /// <param name="outputPath">The output path.</param> - /// <param name="language">The language.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - public async Task ConvertTextSubtitleToSrt(string inputPath, string outputPath, string language, - CancellationToken cancellationToken) + public async Task ConvertTextSubtitleToSrt(string inputPath, string outputPath, CancellationToken cancellationToken) { var semaphore = GetLock(outputPath); @@ -335,7 +349,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles { if (!File.Exists(outputPath)) { - await ConvertTextSubtitleToSrtInternal(inputPath, outputPath, language).ConfigureAwait(false); + await ConvertTextSubtitleToSrtInternal(inputPath, outputPath).ConfigureAwait(false); } } finally @@ -349,15 +363,12 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// </summary> /// <param name="inputPath">The input path.</param> /// <param name="outputPath">The output path.</param> - /// <param name="language">The language.</param> /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException"> - /// inputPath + /// <exception cref="System.ArgumentNullException">inputPath /// or - /// outputPath - /// </exception> + /// outputPath</exception> /// <exception cref="System.ApplicationException"></exception> - private async Task ConvertTextSubtitleToSrtInternal(string inputPath, string outputPath, string language) + private async Task ConvertTextSubtitleToSrtInternal(string inputPath, string outputPath) { if (string.IsNullOrEmpty(inputPath)) { @@ -371,9 +382,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); - var encodingParam = string.IsNullOrEmpty(language) - ? string.Empty - : GetSubtitleFileCharacterSet(inputPath, language); + var encodingParam = GetSubtitleFileCharacterSet(inputPath); if (!string.IsNullOrEmpty(encodingParam)) { @@ -459,7 +468,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles try { _logger.Info("Deleting converted subtitle due to failure: ", outputPath); - File.Delete(outputPath); + _fileSystem.DeleteFile(outputPath); } catch (IOException ex) { @@ -608,7 +617,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles try { _logger.Info("Deleting extracted subtitle due to failure: {0}", outputPath); - File.Delete(outputPath); + _fileSystem.DeleteFile(outputPath); } catch (FileNotFoundException) { @@ -696,27 +705,31 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// Gets the subtitle language encoding param. /// </summary> /// <param name="path">The path.</param> - /// <param name="language">The language.</param> /// <returns>System.String.</returns> - public string GetSubtitleFileCharacterSet(string path, string language) + public string GetSubtitleFileCharacterSet(string path) { - //var charset = DetectCharset(path); - - //if (!string.IsNullOrWhiteSpace(charset)) - //{ - // if (string.Equals(charset, "utf-8", StringComparison.OrdinalIgnoreCase)) - // { - // return null; - // } - - // return charset; - //} - if (GetFileEncoding(path).Equals(Encoding.UTF8)) { return string.Empty; } + var charset = DetectCharset(path); + + if (!string.IsNullOrWhiteSpace(charset)) + { + if (string.Equals(charset, "utf-8", StringComparison.OrdinalIgnoreCase)) + { + return null; + } + + return charset; + } + + return null; + } + + public string GetSubtitleFileCharacterSetFromLanguage(string language) + { switch (language.ToLower()) { case "pol": diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index c49e3e303..310170b5f 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -122,6 +122,9 @@ <Compile Include="..\MediaBrowser.Model\ApiClient\ServerInfo.cs"> <Link>ApiClient\ServerInfo.cs</Link> </Compile> + <Compile Include="..\MediaBrowser.Model\ApiClient\ServerUserInfo.cs"> + <Link>ApiClient\ServerUserInfo.cs</Link> + </Compile> <Compile Include="..\MediaBrowser.Model\ApiClient\SessionUpdatesEventArgs.cs"> <Link>ApiClient\SessionUpdatesEventArgs.cs</Link> </Compile> @@ -194,6 +197,9 @@ <Compile Include="..\MediaBrowser.Model\Configuration\EncodingQuality.cs"> <Link>Configuration\EncodingQuality.cs</Link> </Compile> + <Compile Include="..\MediaBrowser.Model\Configuration\FanartOptions.cs"> + <Link>Configuration\FanartOptions.cs</Link> + </Compile> <Compile Include="..\MediaBrowser.Model\Configuration\ImageOption.cs"> <Link>Configuration\ImageOption.cs</Link> </Compile> @@ -227,6 +233,12 @@ <Compile Include="..\MediaBrowser.Model\Configuration\SubtitlePlaybackMode.cs"> <Link>Configuration\SubtitlePlaybackMode.cs</Link> </Compile> + <Compile Include="..\MediaBrowser.Model\Configuration\TheMovieDbOptions.cs"> + <Link>Configuration\TheMovieDbOptions.cs</Link> + </Compile> + <Compile Include="..\MediaBrowser.Model\Configuration\TvdbOptions.cs"> + <Link>Configuration\TvdbOptions.cs</Link> + </Compile> <Compile Include="..\MediaBrowser.Model\Configuration\UnratedItem.cs"> <Link>Configuration\UnratedItem.cs</Link> </Compile> @@ -488,9 +500,6 @@ <Compile Include="..\MediaBrowser.Model\Dto\UserItemDataDto.cs"> <Link>Dto\UserItemDataDto.cs</Link> </Compile> - <Compile Include="..\MediaBrowser.Model\Dto\VideoStreamOptions.cs"> - <Link>Dto\VideoStreamOptions.cs</Link> - </Compile> <Compile Include="..\MediaBrowser.Model\Entities\BaseItemInfo.cs"> <Link>Entities\BaseItemInfo.cs</Link> </Compile> @@ -812,9 +821,6 @@ <Compile Include="..\MediaBrowser.Model\Net\WebSocketState.cs"> <Link>Net\WebSocketState.cs</Link> </Compile> - <Compile Include="..\MediaBrowser.Model\News\NewsChannel.cs"> - <Link>News\NewsChannel.cs</Link> - </Compile> <Compile Include="..\MediaBrowser.Model\News\NewsItem.cs"> <Link>News\NewsItem.cs</Link> </Compile> @@ -1094,6 +1100,9 @@ <Compile Include="..\MediaBrowser.Model\Sync\SyncOptions.cs"> <Link>Sync\SyncOptions.cs</Link> </Compile> + <Compile Include="..\MediaBrowser.Model\Sync\SyncParameter.cs"> + <Link>Sync\SyncParameter.cs</Link> + </Compile> <Compile Include="..\MediaBrowser.Model\Sync\SyncQuality.cs"> <Link>Sync\SyncQuality.cs</Link> </Compile> diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index d8a29e8da..31d2e6470 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -87,6 +87,9 @@ <Compile Include="..\MediaBrowser.Model\ApiClient\ServerInfo.cs"> <Link>ApiClient\ServerInfo.cs</Link> </Compile> + <Compile Include="..\MediaBrowser.Model\ApiClient\ServerUserInfo.cs"> + <Link>ApiClient\ServerUserInfo.cs</Link> + </Compile> <Compile Include="..\MediaBrowser.Model\ApiClient\SessionUpdatesEventArgs.cs"> <Link>ApiClient\SessionUpdatesEventArgs.cs</Link> </Compile> @@ -159,6 +162,9 @@ <Compile Include="..\MediaBrowser.Model\Configuration\EncodingQuality.cs"> <Link>Configuration\EncodingQuality.cs</Link> </Compile> + <Compile Include="..\MediaBrowser.Model\Configuration\FanartOptions.cs"> + <Link>Configuration\FanartOptions.cs</Link> + </Compile> <Compile Include="..\MediaBrowser.Model\Configuration\ImageOption.cs"> <Link>Configuration\ImageOption.cs</Link> </Compile> @@ -192,6 +198,12 @@ <Compile Include="..\MediaBrowser.Model\Configuration\SubtitlePlaybackMode.cs"> <Link>Configuration\SubtitlePlaybackMode.cs</Link> </Compile> + <Compile Include="..\MediaBrowser.Model\Configuration\TheMovieDbOptions.cs"> + <Link>Configuration\TheMovieDbOptions.cs</Link> + </Compile> + <Compile Include="..\MediaBrowser.Model\Configuration\TvdbOptions.cs"> + <Link>Configuration\TvdbOptions.cs</Link> + </Compile> <Compile Include="..\MediaBrowser.Model\Configuration\UnratedItem.cs"> <Link>Configuration\UnratedItem.cs</Link> </Compile> @@ -453,9 +465,6 @@ <Compile Include="..\MediaBrowser.Model\Dto\UserItemDataDto.cs"> <Link>Dto\UserItemDataDto.cs</Link> </Compile> - <Compile Include="..\MediaBrowser.Model\Dto\VideoStreamOptions.cs"> - <Link>Dto\VideoStreamOptions.cs</Link> - </Compile> <Compile Include="..\MediaBrowser.Model\Entities\BaseItemInfo.cs"> <Link>Entities\BaseItemInfo.cs</Link> </Compile> @@ -771,9 +780,6 @@ <Compile Include="..\MediaBrowser.Model\Net\WebSocketState.cs"> <Link>Net\WebSocketState.cs</Link> </Compile> - <Compile Include="..\MediaBrowser.Model\News\NewsChannel.cs"> - <Link>News\NewsChannel.cs</Link> - </Compile> <Compile Include="..\MediaBrowser.Model\News\NewsItem.cs"> <Link>News\NewsItem.cs</Link> </Compile> @@ -1053,6 +1059,9 @@ <Compile Include="..\MediaBrowser.Model\Sync\SyncOptions.cs"> <Link>Sync\SyncOptions.cs</Link> </Compile> + <Compile Include="..\MediaBrowser.Model\Sync\SyncParameter.cs"> + <Link>Sync\SyncParameter.cs</Link> + </Compile> <Compile Include="..\MediaBrowser.Model\Sync\SyncQuality.cs"> <Link>Sync\SyncQuality.cs</Link> </Compile> diff --git a/MediaBrowser.Model/ApiClient/ConnectionResult.cs b/MediaBrowser.Model/ApiClient/ConnectionResult.cs index 12a80ee15..32a80d1a3 100644 --- a/MediaBrowser.Model/ApiClient/ConnectionResult.cs +++ b/MediaBrowser.Model/ApiClient/ConnectionResult.cs @@ -1,4 +1,5 @@ using MediaBrowser.Model.Connect; +using MediaBrowser.Model.Dto; using System.Collections.Generic; namespace MediaBrowser.Model.ApiClient @@ -9,6 +10,7 @@ namespace MediaBrowser.Model.ApiClient public List<ServerInfo> Servers { get; set; } public IApiClient ApiClient { get; set; } public ConnectUser ConnectUser { get; set; } + public UserDto OfflineUser { get; set; } public ConnectionResult() { diff --git a/MediaBrowser.Model/ApiClient/ConnectionState.cs b/MediaBrowser.Model/ApiClient/ConnectionState.cs index 5e47d688e..9b753c7bb 100644 --- a/MediaBrowser.Model/ApiClient/ConnectionState.cs +++ b/MediaBrowser.Model/ApiClient/ConnectionState.cs @@ -6,6 +6,8 @@ namespace MediaBrowser.Model.ApiClient ServerSignIn = 2, SignedIn = 3, ServerSelection = 4, - ConnectSignIn = 5 + ConnectSignIn = 5, + OfflineSignIn = 6, + OfflineSignedIn = 7 } }
\ No newline at end of file diff --git a/MediaBrowser.Model/ApiClient/IApiClient.cs b/MediaBrowser.Model/ApiClient/IApiClient.cs index 9faa8fced..bcd1dfe12 100644 --- a/MediaBrowser.Model/ApiClient/IApiClient.cs +++ b/MediaBrowser.Model/ApiClient/IApiClient.cs @@ -558,6 +558,13 @@ namespace MediaBrowser.Model.ApiClient Task<UserDto> GetUserAsync(string id); /// <summary> + /// Gets the offline user asynchronous. + /// </summary> + /// <param name="id">The identifier.</param> + /// <returns>Task<UserDto>.</returns> + Task<UserDto> GetOfflineUserAsync(string id); + + /// <summary> /// Gets the parental ratings async. /// </summary> /// <returns>Task{List{ParentalRating}}.</returns> @@ -1317,24 +1324,6 @@ namespace MediaBrowser.Model.ApiClient Task<QueryResult<BaseItemDto>> GetPlaylistItems(PlaylistItemQuery query); /// <summary> - /// Gets the url needed to stream a video file - /// </summary> - /// <param name="options">The options.</param> - /// <returns>System.String.</returns> - /// <exception cref="ArgumentNullException">options</exception> - [Obsolete] - string GetVideoStreamUrl(VideoStreamOptions options); - - /// <summary> - /// Formulates a url for streaming video using the HLS protocol - /// </summary> - /// <param name="options">The options.</param> - /// <returns>System.String.</returns> - /// <exception cref="ArgumentNullException">options</exception> - [Obsolete] - string GetHlsVideoStreamUrl(VideoStreamOptions options); - - /// <summary> /// Sends the context message asynchronous. /// </summary> /// <param name="itemType">Type of the item.</param> @@ -1414,6 +1403,15 @@ namespace MediaBrowser.Model.ApiClient Task<Stream> GetSyncJobItemFile(string id, CancellationToken cancellationToken); /// <summary> + /// Gets the synchronize job item additional file. + /// </summary> + /// <param name="id">The identifier.</param> + /// <param name="name">The name.</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns>Task<Stream>.</returns> + Task<Stream> GetSyncJobItemAdditionalFile(string id, string name, CancellationToken cancellationToken); + + /// <summary> /// Opens the web socket. /// </summary> /// <param name="webSocketFactory">The web socket factory.</param> @@ -1440,5 +1438,41 @@ namespace MediaBrowser.Model.ApiClient /// <param name="request">The request.</param> /// <returns>Task<SyncDataResponse>.</returns> Task<SyncDataResponse> SyncData(SyncDataRequest request); + /// <summary> + /// Gets the synchronize job item file URL. + /// </summary> + /// <param name="id">The identifier.</param> + /// <returns>System.String.</returns> + string GetSyncJobItemFileUrl(string id); + /// <summary> + /// Marks the synchronize job item for removal. + /// </summary> + /// <param name="id">The identifier.</param> + /// <returns>Task.</returns> + Task MarkSyncJobItemForRemoval(string id); + /// <summary> + /// Unmarks the synchronize job item for removal. + /// </summary> + /// <param name="id">The identifier.</param> + /// <returns>Task.</returns> + Task UnmarkSyncJobItemForRemoval(string id); + /// <summary> + /// Queues the failed synchronize job item for retry. + /// </summary> + /// <param name="id">The identifier.</param> + /// <returns>Task.</returns> + Task QueueFailedSyncJobItemForRetry(string id); + /// <summary> + /// Cancels the synchronize job item. + /// </summary> + /// <param name="id">The identifier.</param> + /// <returns>Task.</returns> + Task CancelSyncJobItem(string id); + /// <summary> + /// Enables the cancelled synchronize job item. + /// </summary> + /// <param name="id">The identifier.</param> + /// <returns>Task.</returns> + Task EnableCancelledSyncJobItem(string id); } }
\ No newline at end of file diff --git a/MediaBrowser.Model/ApiClient/IConnectionManager.cs b/MediaBrowser.Model/ApiClient/IConnectionManager.cs index a54c330ac..658c71ac5 100644 --- a/MediaBrowser.Model/ApiClient/IConnectionManager.cs +++ b/MediaBrowser.Model/ApiClient/IConnectionManager.cs @@ -136,5 +136,14 @@ namespace MediaBrowser.Model.ApiClient /// </summary> /// <param name="cancellationToken">The cancellation token.</param> Task<List<ServerInfo>> GetAvailableServers(CancellationToken cancellationToken); + + /// <summary> + /// Authenticates an offline user with their password + /// </summary> + /// <param name="user">The user.</param> + /// <param name="password">The password.</param> + /// <param name="rememberCredentials">if set to <c>true</c> [remember credentials].</param> + /// <returns>Task.</returns> + Task AuthenticateOffline(UserDto user, string password, bool rememberCredentials); } } diff --git a/MediaBrowser.Model/ApiClient/IServerEvents.cs b/MediaBrowser.Model/ApiClient/IServerEvents.cs index 88faad388..b74d43ee0 100644 --- a/MediaBrowser.Model/ApiClient/IServerEvents.cs +++ b/MediaBrowser.Model/ApiClient/IServerEvents.cs @@ -3,6 +3,7 @@ using MediaBrowser.Model.Entities; using MediaBrowser.Model.Events; using MediaBrowser.Model.Plugins; using MediaBrowser.Model.Session; +using MediaBrowser.Model.Sync; using MediaBrowser.Model.Tasks; using MediaBrowser.Model.Updates; using System; @@ -130,5 +131,9 @@ namespace MediaBrowser.Model.ApiClient /// Occurs when [session ended]. /// </summary> event EventHandler<GenericEventArgs<SessionInfoDto>> SessionEnded; + /// <summary> + /// Occurs when [synchronize job created]. + /// </summary> + event EventHandler<GenericEventArgs<SyncJobCreationResult>> SyncJobCreated; } } diff --git a/MediaBrowser.Model/ApiClient/ServerCredentials.cs b/MediaBrowser.Model/ApiClient/ServerCredentials.cs index fbbc6c05d..b5f38f4db 100644 --- a/MediaBrowser.Model/ApiClient/ServerCredentials.cs +++ b/MediaBrowser.Model/ApiClient/ServerCredentials.cs @@ -70,6 +70,10 @@ namespace MediaBrowser.Model.ApiClient { existing.LastConnectionMode = server.LastConnectionMode; } + foreach (ServerUserInfo user in server.Users) + { + existing.AddOrUpdate(user); + } } else { diff --git a/MediaBrowser.Model/ApiClient/ServerInfo.cs b/MediaBrowser.Model/ApiClient/ServerInfo.cs index 46cc560af..dcd5e75b1 100644 --- a/MediaBrowser.Model/ApiClient/ServerInfo.cs +++ b/MediaBrowser.Model/ApiClient/ServerInfo.cs @@ -1,12 +1,16 @@ using MediaBrowser.Model.Connect; +using MediaBrowser.Model.Extensions; using MediaBrowser.Model.System; using System; using System.Collections.Generic; +using System.Linq; namespace MediaBrowser.Model.ApiClient { public class ServerInfo { + public List<ServerUserInfo> Users { get; set; } + public String Name { get; set; } public String Id { get; set; } public String LocalAddress { get; set; } @@ -23,6 +27,7 @@ namespace MediaBrowser.Model.ApiClient public ServerInfo() { WakeOnLanInfos = new List<WakeOnLanInfo>(); + Users = new List<ServerUserInfo>(); } public void ImportInfo(PublicSystemInfo systemInfo) @@ -70,5 +75,48 @@ namespace MediaBrowser.Model.ApiClient throw new ArgumentException("Unexpected ConnectionMode"); } } + + public void AddOrUpdate(ServerUserInfo user) + { + if (user == null) + { + throw new ArgumentNullException("user"); + } + + var list = Users.ToList(); + + var index = FindIndex(list, user.Id); + + if (index != -1) + { + var existing = list[index]; + + // Merge the data + existing.IsSignedInOffline = user.IsSignedInOffline; + } + else + { + list.Add(user); + } + + Users = list; + } + + private int FindIndex(List<ServerUserInfo> users, string id) + { + var index = 0; + + foreach (var user in users) + { + if (StringHelper.Equals(id, user.Id)) + { + return index; + } + + index++; + } + + return -1; + } } } diff --git a/MediaBrowser.Model/ApiClient/ServerUserInfo.cs b/MediaBrowser.Model/ApiClient/ServerUserInfo.cs new file mode 100644 index 000000000..812da7402 --- /dev/null +++ b/MediaBrowser.Model/ApiClient/ServerUserInfo.cs @@ -0,0 +1,9 @@ + +namespace MediaBrowser.Model.ApiClient +{ + public class ServerUserInfo + { + public string Id { get; set; } + public bool IsSignedInOffline { get; set; } + } +} diff --git a/MediaBrowser.Model/Branding/BrandingOptions.cs b/MediaBrowser.Model/Branding/BrandingOptions.cs index 737cb5c48..3b207d345 100644 --- a/MediaBrowser.Model/Branding/BrandingOptions.cs +++ b/MediaBrowser.Model/Branding/BrandingOptions.cs @@ -8,5 +8,10 @@ namespace MediaBrowser.Model.Branding /// </summary> /// <value>The login disclaimer.</value> public string LoginDisclaimer { get; set; } + /// <summary> + /// Gets or sets the custom CSS. + /// </summary> + /// <value>The custom CSS.</value> + public string CustomCss { get; set; } } } diff --git a/MediaBrowser.Model/Configuration/FanartOptions.cs b/MediaBrowser.Model/Configuration/FanartOptions.cs new file mode 100644 index 000000000..e992abe5d --- /dev/null +++ b/MediaBrowser.Model/Configuration/FanartOptions.cs @@ -0,0 +1,17 @@ + +namespace MediaBrowser.Model.Configuration +{ + public class FanartOptions + { + /// <summary> + /// Gets or sets a value indicating whether [enable automatic updates]. + /// </summary> + /// <value><c>true</c> if [enable automatic updates]; otherwise, <c>false</c>.</value> + public bool EnableAutomaticUpdates { get; set; } + /// <summary> + /// Gets or sets the user API key. + /// </summary> + /// <value>The user API key.</value> + public string UserApiKey { get; set; } + } +} diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index f9c5c6567..c15c76004 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -21,6 +21,12 @@ namespace MediaBrowser.Model.Configuration public int PublicPort { get; set; } /// <summary> + /// Gets or sets the public HTTPS port. + /// </summary> + /// <value>The public HTTPS port.</value> + public int PublicHttpsPort { get; set; } + + /// <summary> /// Gets or sets the HTTP server port number. /// </summary> /// <value>The HTTP server port number.</value> @@ -31,7 +37,19 @@ namespace MediaBrowser.Model.Configuration /// </summary> /// <value>The HTTPS server port number.</value> public int HttpsPortNumber { get; set; } - + + /// <summary> + /// Gets or sets a value indicating whether [use HTTPS]. + /// </summary> + /// <value><c>true</c> if [use HTTPS]; otherwise, <c>false</c>.</value> + public bool EnableHttps { get; set; } + + /// <summary> + /// Gets or sets the value pointing to the file system where the ssl certiifcate is located.. + /// </summary> + /// <value>The value pointing to the file system where the ssl certiifcate is located..</value> + public string CertificatePath { get; set; } + /// <summary> /// Gets or sets a value indicating whether [enable internet providers]. /// </summary> @@ -73,6 +91,12 @@ namespace MediaBrowser.Model.Configuration /// </summary> /// <value><c>true</c> if [enable localized guids]; otherwise, <c>false</c>.</value> public bool EnableLocalizedGuids { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether [enable library metadata sub folder]. + /// </summary> + /// <value><c>true</c> if [enable library metadata sub folder]; otherwise, <c>false</c>.</value> + public bool EnableLibraryMetadataSubFolder { get; set; } /// <summary> /// Gets or sets the preferred metadata language. @@ -136,6 +160,7 @@ namespace MediaBrowser.Model.Configuration /// </summary> /// <value><c>true</c> if [enable dashboard response caching]; otherwise, <c>false</c>.</value> public bool EnableDashboardResponseCaching { get; set; } + public bool EnableDashboardResourceMinification { get; set; } /// <summary> /// Allows the dashboard to be served from a custom path. @@ -143,13 +168,8 @@ namespace MediaBrowser.Model.Configuration /// <value>The dashboard source path.</value> public string DashboardSourcePath { get; set; } - /// <summary> - /// Gets or sets a value indicating whether [enable tv db updates]. - /// </summary> - /// <value><c>true</c> if [enable tv db updates]; otherwise, <c>false</c>.</value> - public bool EnableTvDbUpdates { get; set; } - public bool EnableTmdbUpdates { get; set; } - public bool EnableFanArtUpdates { get; set; } + public bool MergeMetadataAndImagesByName { get; set; } + public bool EnableStandaloneMetadata { get; set; } /// <summary> /// Gets or sets the image saving convention. @@ -177,13 +197,14 @@ namespace MediaBrowser.Model.Configuration public string[] InsecureApps8 { get; set; } public bool SaveMetadataHidden { get; set; } - public bool EnableWin8HttpListener { get; set; } public NameValuePair[] ContentTypes { get; set; } public bool EnableAudioArchiveFiles { get; set; } public bool EnableVideoArchiveFiles { get; set; } + public bool EnableLegacyCollections { get; set; } + /// <summary> /// Initializes a new instance of the <see cref="ServerConfiguration" /> class. /// </summary> @@ -192,12 +213,14 @@ namespace MediaBrowser.Model.Configuration { ImageSavingConvention = ImageSavingConvention.Compatible; PublicPort = 8096; + PublicHttpsPort = 8920; HttpServerPortNumber = 8096; HttpsPortNumber = 8920; + EnableHttps = false; EnableDashboardResponseCaching = true; + EnableDashboardResourceMinification = true; EnableAutomaticRestart = true; - EnableWin8HttpListener = true; EnableUPnP = true; diff --git a/MediaBrowser.Model/Configuration/TheMovieDbOptions.cs b/MediaBrowser.Model/Configuration/TheMovieDbOptions.cs new file mode 100644 index 000000000..9a73e3476 --- /dev/null +++ b/MediaBrowser.Model/Configuration/TheMovieDbOptions.cs @@ -0,0 +1,12 @@ + +namespace MediaBrowser.Model.Configuration +{ + public class TheMovieDbOptions + { + /// <summary> + /// Gets or sets a value indicating whether [enable automatic updates]. + /// </summary> + /// <value><c>true</c> if [enable automatic updates]; otherwise, <c>false</c>.</value> + public bool EnableAutomaticUpdates { get; set; } + } +} diff --git a/MediaBrowser.Model/Configuration/TvdbOptions.cs b/MediaBrowser.Model/Configuration/TvdbOptions.cs new file mode 100644 index 000000000..034af609c --- /dev/null +++ b/MediaBrowser.Model/Configuration/TvdbOptions.cs @@ -0,0 +1,12 @@ + +namespace MediaBrowser.Model.Configuration +{ + public class TvdbOptions + { + /// <summary> + /// Gets or sets a value indicating whether [enable automatic updates]. + /// </summary> + /// <value><c>true</c> if [enable automatic updates]; otherwise, <c>false</c>.</value> + public bool EnableAutomaticUpdates { get; set; } + } +} diff --git a/MediaBrowser.Model/Configuration/UserConfiguration.cs b/MediaBrowser.Model/Configuration/UserConfiguration.cs index 9e33c1c36..aa49ee50d 100644 --- a/MediaBrowser.Model/Configuration/UserConfiguration.cs +++ b/MediaBrowser.Model/Configuration/UserConfiguration.cs @@ -7,12 +7,6 @@ namespace MediaBrowser.Model.Configuration public class UserConfiguration { /// <summary> - /// Gets or sets the max parental rating. - /// </summary> - /// <value>The max parental rating.</value> - public int? MaxParentalRating { get; set; } - - /// <summary> /// Gets or sets a value indicating whether this instance is administrator. /// </summary> /// <value><c>true</c> if this instance is administrator; otherwise, <c>false</c>.</value> @@ -36,22 +30,8 @@ namespace MediaBrowser.Model.Configuration /// <value>The subtitle language preference.</value> public string SubtitleLanguagePreference { get; set; } - /// <summary> - /// Gets or sets a value indicating whether this instance is hidden. - /// </summary> - /// <value><c>true</c> if this instance is hidden; otherwise, <c>false</c>.</value> - public bool IsHidden { get; set; } - - /// <summary> - /// Gets or sets a value indicating whether this instance is disabled. - /// </summary> - /// <value><c>true</c> if this instance is disabled; otherwise, <c>false</c>.</value> - public bool IsDisabled { get; set; } - public bool DisplayMissingEpisodes { get; set; } public bool DisplayUnairedEpisodes { get; set; } - public bool EnableRemoteControlOfOtherUsers { get; set; } - public bool EnableSharedDeviceControl { get; set; } public bool EnableLiveTvManagement { get; set; } public bool EnableLiveTvAccess { get; set; } @@ -61,9 +41,6 @@ namespace MediaBrowser.Model.Configuration public bool GroupMoviesIntoBoxSets { get; set; } - public string[] BlockedMediaFolders { get; set; } - public string[] BlockedChannels { get; set; } - public string[] DisplayChannelsWithinViews { get; set; } public string[] ExcludeFoldersFromGrouping { get; set; } @@ -82,12 +59,7 @@ namespace MediaBrowser.Model.Configuration public bool EnableCinemaMode { get; set; } - public AccessSchedule[] AccessSchedules { get; set; } - - public bool EnableUserPreferenceAccess { get; set; } - public string[] LatestItemsExcludes { get; set; } - public string[] BlockedTags { get; set; } public bool HasMigratedToPolicy { get; set; } @@ -100,14 +72,10 @@ namespace MediaBrowser.Model.Configuration EnableLiveTvManagement = true; EnableMediaPlayback = true; EnableLiveTvAccess = true; - EnableSharedDeviceControl = true; LatestItemsExcludes = new string[] { }; OrderedViews = new string[] { }; - BlockedMediaFolders = new string[] { }; DisplayChannelsWithinViews = new string[] { }; - BlockedTags = new string[] { }; - BlockedChannels = new string[] { }; BlockUnratedItems = new UnratedItem[] { }; ExcludeFoldersFromGrouping = new string[] { }; @@ -115,9 +83,6 @@ namespace MediaBrowser.Model.Configuration IncludeTrailersInSuggestions = true; EnableCinemaMode = true; - EnableUserPreferenceAccess = true; - - AccessSchedules = new AccessSchedule[] { }; } } } diff --git a/MediaBrowser.Model/Connect/ConnectAuthorization.cs b/MediaBrowser.Model/Connect/ConnectAuthorization.cs index 0c545f4ba..e8baf7269 100644 --- a/MediaBrowser.Model/Connect/ConnectAuthorization.cs +++ b/MediaBrowser.Model/Connect/ConnectAuthorization.cs @@ -7,14 +7,14 @@ namespace MediaBrowser.Model.Connect public string UserName { get; set; } public string ImageUrl { get; set; } public string Id { get; set; } - public string[] ExcludedLibraries { get; set; } + public string[] EnabledLibraries { get; set; } public bool EnableLiveTv { get; set; } - public string[] ExcludedChannels { get; set; } + public string[] EnabledChannels { get; set; } public ConnectAuthorization() { - ExcludedLibraries = new string[] { }; - ExcludedChannels = new string[] { }; + EnabledLibraries = new string[] { }; + EnabledChannels = new string[] { }; } } } diff --git a/MediaBrowser.Model/Connect/ConnectAuthorizationRequest.cs b/MediaBrowser.Model/Connect/ConnectAuthorizationRequest.cs index d40d353f0..6baea15a9 100644 --- a/MediaBrowser.Model/Connect/ConnectAuthorizationRequest.cs +++ b/MediaBrowser.Model/Connect/ConnectAuthorizationRequest.cs @@ -5,14 +5,14 @@ namespace MediaBrowser.Model.Connect { public string SendingUserId { get; set; } public string ConnectUserName { get; set; } - public string[] ExcludedLibraries { get; set; } + public string[] EnabledLibraries { get; set; } public bool EnableLiveTv { get; set; } - public string[] ExcludedChannels { get; set; } + public string[] EnabledChannels { get; set; } public ConnectAuthorizationRequest() { - ExcludedLibraries = new string[] { }; - ExcludedChannels = new string[] { }; + EnabledLibraries = new string[] { }; + EnabledChannels = new string[] { }; } } } diff --git a/MediaBrowser.Model/Devices/DeviceQuery.cs b/MediaBrowser.Model/Devices/DeviceQuery.cs index 2cd2389d8..9ae498606 100644 --- a/MediaBrowser.Model/Devices/DeviceQuery.cs +++ b/MediaBrowser.Model/Devices/DeviceQuery.cs @@ -12,7 +12,7 @@ namespace MediaBrowser.Model.Devices /// Gets or sets a value indicating whether [supports unique identifier]. /// </summary> /// <value><c>null</c> if [supports unique identifier] contains no value, <c>true</c> if [supports unique identifier]; otherwise, <c>false</c>.</value> - public bool? SupportsUniqueIdentifier { get; set; } + public bool? SupportsPersistentIdentifier { get; set; } /// <summary> /// Gets or sets a value indicating whether [supports synchronize]. /// </summary> diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 7c47b0d44..721da54a8 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -267,7 +267,10 @@ namespace MediaBrowser.Model.Dlna if (subtitleStream != null) { - playlistItem.SubtitleDeliveryMethod = GetSubtitleDeliveryMethod(subtitleStream, options); + SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options); + + playlistItem.SubtitleDeliveryMethod = subtitleProfile.Method; + playlistItem.SubtitleFormat = subtitleProfile.Format; } return playlistItem; @@ -289,7 +292,10 @@ namespace MediaBrowser.Model.Dlna { if (subtitleStream != null) { - playlistItem.SubtitleDeliveryMethod = GetSubtitleDeliveryMethod(subtitleStream, options); + SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options); + + playlistItem.SubtitleDeliveryMethod = subtitleProfile.Method; + playlistItem.SubtitleFormat = subtitleProfile.Format; } playlistItem.PlayMethod = PlayMethod.Transcode; @@ -525,9 +531,9 @@ namespace MediaBrowser.Model.Dlna return false; } - SubtitleDeliveryMethod subtitleMethod = GetSubtitleDeliveryMethod(subtitleStream, options); + SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options); - if (subtitleMethod != SubtitleDeliveryMethod.External && subtitleMethod != SubtitleDeliveryMethod.Embed) + if (subtitleProfile.Method != SubtitleDeliveryMethod.External && subtitleProfile.Method != SubtitleDeliveryMethod.Embed) { return false; } @@ -536,43 +542,43 @@ namespace MediaBrowser.Model.Dlna return IsAudioEligibleForDirectPlay(item, maxBitrate); } - private SubtitleDeliveryMethod GetSubtitleDeliveryMethod(MediaStream subtitleStream, - VideoOptions options) + private SubtitleProfile GetSubtitleProfile(MediaStream subtitleStream, VideoOptions options) { if (subtitleStream.IsTextSubtitleStream) { - // See if the device can retrieve the subtitles externally - bool supportsSubsExternally = options.Context == EncodingContext.Streaming && - ContainsSubtitleFormat(options.Profile.SubtitleProfiles, SubtitleDeliveryMethod.External, _serverTextSubtitleOutputs); + SubtitleProfile externalProfile = GetSubtitleProfile(options.Profile.SubtitleProfiles, SubtitleDeliveryMethod.External, _serverTextSubtitleOutputs); - if (supportsSubsExternally) + if (externalProfile != null) { - return SubtitleDeliveryMethod.External; + return externalProfile; } - // See if the device can retrieve the subtitles externally - bool supportsEmbedded = ContainsSubtitleFormat(options.Profile.SubtitleProfiles, SubtitleDeliveryMethod.Embed, _serverTextSubtitleOutputs); + SubtitleProfile embedProfile = GetSubtitleProfile(options.Profile.SubtitleProfiles, SubtitleDeliveryMethod.Embed, _serverTextSubtitleOutputs); - if (supportsEmbedded) + if (embedProfile != null) { - return SubtitleDeliveryMethod.Embed; + return embedProfile; } } - return SubtitleDeliveryMethod.Encode; + return new SubtitleProfile + { + Method = SubtitleDeliveryMethod.Encode, + Format = subtitleStream.Codec + }; } - private bool ContainsSubtitleFormat(SubtitleProfile[] profiles, SubtitleDeliveryMethod method, string[] formats) + private SubtitleProfile GetSubtitleProfile(SubtitleProfile[] profiles, SubtitleDeliveryMethod method, string[] formats) { foreach (SubtitleProfile profile in profiles) { if (method == profile.Method && ListHelper.ContainsIgnoreCase(formats, profile.Format)) { - return true; + return profile; } } - return false; + return null; } private bool IsAudioEligibleForDirectPlay(MediaSourceInfo item, int? maxBitrate) diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index 22eb0cf6c..acd2658a8 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -212,7 +212,8 @@ namespace MediaBrowser.Model.Dlna IsForced = stream.IsForced, Language = stream.Language, Name = stream.Language ?? "Unknown", - Format = SubtitleFormat + Format = SubtitleFormat, + Index = stream.Index }); } diff --git a/MediaBrowser.Model/Dlna/SubtitleStreamInfo.cs b/MediaBrowser.Model/Dlna/SubtitleStreamInfo.cs index 1600408d6..a7a8da3ba 100644 --- a/MediaBrowser.Model/Dlna/SubtitleStreamInfo.cs +++ b/MediaBrowser.Model/Dlna/SubtitleStreamInfo.cs @@ -7,5 +7,6 @@ namespace MediaBrowser.Model.Dlna public string Name { get; set; } public bool IsForced { get; set; } public string Format { get; set; } + public int Index { get; set; } } }
\ No newline at end of file diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index 2383d4809..c1a34a7f6 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -69,7 +69,8 @@ namespace MediaBrowser.Model.Dto public int? AnimeSeriesIndex { get; set; } public bool? SupportsSync { get; set; } - + public bool? HasSyncJob { get; set; } + /// <summary> /// Gets or sets the DVD season number. /// </summary> @@ -224,12 +225,6 @@ namespace MediaBrowser.Model.Dto public long? RunTimeTicks { get; set; } /// <summary> - /// Gets or sets the recursive unplayed item count. - /// </summary> - /// <value>The recursive unplayed item count.</value> - public int? RecursiveUnplayedItemCount { get; set; } - - /// <summary> /// Gets or sets the play access. /// </summary> /// <value>The play access.</value> diff --git a/MediaBrowser.Model/Dto/UserDto.cs b/MediaBrowser.Model/Dto/UserDto.cs index 9b6d92030..c66b34150 100644 --- a/MediaBrowser.Model/Dto/UserDto.cs +++ b/MediaBrowser.Model/Dto/UserDto.cs @@ -26,7 +26,14 @@ namespace MediaBrowser.Model.Dto /// </summary> /// <value>The server identifier.</value> public string ServerId { get; set; } - + + /// <summary> + /// Gets or sets the name of the server. + /// This is not used by the server and is for client-side usage only. + /// </summary> + /// <value>The name of the server.</value> + public string ServerName { get; set; } + /// <summary> /// Gets or sets the name of the connect user. /// </summary> @@ -48,7 +55,13 @@ namespace MediaBrowser.Model.Dto /// </summary> /// <value>The id.</value> public string Id { get; set; } - + + /// <summary> + /// Gets or sets the offline password. + /// </summary> + /// <value>The offline password.</value> + public string OfflinePassword { get; set; } + /// <summary> /// Gets or sets the primary image tag. /// </summary> @@ -66,6 +79,12 @@ namespace MediaBrowser.Model.Dto /// </summary> /// <value><c>true</c> if this instance has configured password; otherwise, <c>false</c>.</value> public bool HasConfiguredPassword { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether this instance has configured easy password. + /// </summary> + /// <value><c>true</c> if this instance has configured easy password; otherwise, <c>false</c>.</value> + public bool HasConfiguredEasyPassword { get; set; } /// <summary> /// Gets or sets the last login date. @@ -102,7 +121,7 @@ namespace MediaBrowser.Model.Dto /// </summary> /// <value>The original primary image aspect ratio.</value> public double? OriginalPrimaryImageAspectRatio { get; set; } - + /// <summary> /// Gets a value indicating whether this instance has primary image. /// </summary> diff --git a/MediaBrowser.Model/Dto/VideoStreamOptions.cs b/MediaBrowser.Model/Dto/VideoStreamOptions.cs deleted file mode 100644 index e9a83bd12..000000000 --- a/MediaBrowser.Model/Dto/VideoStreamOptions.cs +++ /dev/null @@ -1,158 +0,0 @@ -using System; - -namespace MediaBrowser.Model.Dto -{ - /// <summary> - /// Class VideoStreamOptions - /// </summary> - [Obsolete] - public class VideoStreamOptions - { - /// <summary> - /// Gets or sets the audio bit rate. - /// </summary> - /// <value>The audio bit rate.</value> - public int? AudioBitRate { get; set; } - - /// <summary> - /// Gets or sets the audio codec. - /// Omit to copy the original stream - /// </summary> - /// <value>The audio encoding format.</value> - public string AudioCodec { get; set; } - - /// <summary> - /// Gets or sets the item id. - /// </summary> - /// <value>The item id.</value> - public string ItemId { get; set; } - - /// <summary> - /// Gets or sets the max audio channels. - /// </summary> - /// <value>The max audio channels.</value> - public int? MaxAudioChannels { get; set; } - - /// <summary> - /// Gets or sets the max audio sample rate. - /// </summary> - /// <value>The max audio sample rate.</value> - public int? MaxAudioSampleRate { get; set; } - - /// <summary> - /// Gets or sets the start time ticks. - /// </summary> - /// <value>The start time ticks.</value> - public long? StartTimeTicks { get; set; } - - /// <summary> - /// Gets or sets a value indicating whether the original media should be served statically - /// Only used with progressive streaming - /// </summary> - /// <value><c>true</c> if static; otherwise, <c>false</c>.</value> - public bool? Static { get; set; } - - /// <summary> - /// Gets or sets the output file extension. - /// </summary> - /// <value>The output file extension.</value> - public string OutputFileExtension { get; set; } - - /// <summary> - /// Gets or sets the device id. - /// </summary> - /// <value>The device id.</value> - public string DeviceId { get; set; } - - /// <summary> - /// Gets or sets the video codec. - /// Omit to copy - /// </summary> - /// <value>The video codec.</value> - public string VideoCodec { get; set; } - - /// <summary> - /// Gets or sets the video bit rate. - /// </summary> - /// <value>The video bit rate.</value> - public int? VideoBitRate { get; set; } - - /// <summary> - /// Gets or sets the width. - /// </summary> - /// <value>The width.</value> - public int? Width { get; set; } - - /// <summary> - /// Gets or sets the height. - /// </summary> - /// <value>The height.</value> - public int? Height { get; set; } - - /// <summary> - /// Gets or sets the width of the max. - /// </summary> - /// <value>The width of the max.</value> - public int? MaxWidth { get; set; } - - /// <summary> - /// Gets or sets the height of the max. - /// </summary> - /// <value>The height of the max.</value> - public int? MaxHeight { get; set; } - - /// <summary> - /// Gets or sets the frame rate. - /// </summary> - /// <value>The frame rate.</value> - public double? FrameRate { get; set; } - - /// <summary> - /// Gets or sets the index of the audio stream. - /// </summary> - /// <value>The index of the audio stream.</value> - public int? AudioStreamIndex { get; set; } - - /// <summary> - /// Gets or sets the index of the video stream. - /// </summary> - /// <value>The index of the video stream.</value> - public int? VideoStreamIndex { get; set; } - - /// <summary> - /// Gets or sets the index of the subtitle stream. - /// </summary> - /// <value>The index of the subtitle stream.</value> - public int? SubtitleStreamIndex { get; set; } - - /// <summary> - /// Gets or sets the profile. - /// </summary> - /// <value>The profile.</value> - public string Profile { get; set; } - - /// <summary> - /// Gets or sets the level. - /// </summary> - /// <value>The level.</value> - public string Level { get; set; } - - /// <summary> - /// Gets or sets the baseline stream audio bit rate. - /// </summary> - /// <value>The baseline stream audio bit rate.</value> - public int? BaselineStreamAudioBitRate { get; set; } - - /// <summary> - /// Gets or sets a value indicating whether [append baseline stream]. - /// </summary> - /// <value><c>true</c> if [append baseline stream]; otherwise, <c>false</c>.</value> - public bool AppendBaselineStream { get; set; } - - /// <summary> - /// Gets or sets the time stamp offset ms. Only used with HLS. - /// </summary> - /// <value>The time stamp offset ms.</value> - public int? TimeStampOffsetMs { get; set; } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Model/Entities/MetadataProviders.cs b/MediaBrowser.Model/Entities/MetadataProviders.cs index e86773789..7644b150a 100644 --- a/MediaBrowser.Model/Entities/MetadataProviders.cs +++ b/MediaBrowser.Model/Entities/MetadataProviders.cs @@ -40,6 +40,7 @@ namespace MediaBrowser.Model.Entities NesBoxRom = 14, TvRage = 15, AudioDbArtist = 16, - AudioDbAlbum = 17 + AudioDbAlbum = 17, + MusicBrainzTrack = 18 } } diff --git a/MediaBrowser.Model/Extensions/StringHelper.cs b/MediaBrowser.Model/Extensions/StringHelper.cs index 206723467..99bec68a7 100644 --- a/MediaBrowser.Model/Extensions/StringHelper.cs +++ b/MediaBrowser.Model/Extensions/StringHelper.cs @@ -1,5 +1,6 @@ using System; using System.Globalization; +using System.Text; using System.Text.RegularExpressions; namespace MediaBrowser.Model.Extensions @@ -94,5 +95,35 @@ namespace MediaBrowser.Model.Extensions { return new Regex(term).Split(str, limit); } + + /// <summary> + /// Replaces the specified STR. + /// </summary> + /// <param name="str">The STR.</param> + /// <param name="oldValue">The old value.</param> + /// <param name="newValue">The new value.</param> + /// <param name="comparison">The comparison.</param> + /// <returns>System.String.</returns> + public static string Replace(this string str, string oldValue, string newValue, StringComparison comparison) + { + var sb = new StringBuilder(); + + var previousIndex = 0; + var index = str.IndexOf(oldValue, comparison); + + while (index != -1) + { + sb.Append(str.Substring(previousIndex, index - previousIndex)); + sb.Append(newValue); + index += oldValue.Length; + + previousIndex = index; + index = str.IndexOf(oldValue, index, comparison); + } + + sb.Append(str.Substring(previousIndex)); + + return sb.ToString(); + } } } diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 2a1b0b659..0962cbe7a 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -76,6 +76,7 @@ <Compile Include="ApiClient\ServerCredentials.cs" /> <Compile Include="ApiClient\ServerDiscoveryInfo.cs" /> <Compile Include="ApiClient\ServerInfo.cs" /> + <Compile Include="ApiClient\ServerUserInfo.cs" /> <Compile Include="ApiClient\SessionUpdatesEventArgs.cs" /> <Compile Include="ApiClient\WakeOnLanInfo.cs" /> <Compile Include="Branding\BrandingOptions.cs" /> @@ -97,8 +98,11 @@ <Compile Include="Configuration\ChapterOptions.cs" /> <Compile Include="Configuration\CinemaModeConfiguration.cs" /> <Compile Include="Configuration\EncodingOptions.cs" /> + <Compile Include="Configuration\FanartOptions.cs" /> <Compile Include="Configuration\MetadataConfiguration.cs" /> <Compile Include="Configuration\PeopleMetadataOptions.cs" /> + <Compile Include="Configuration\TheMovieDbOptions.cs" /> + <Compile Include="Configuration\TvdbOptions.cs" /> <Compile Include="Configuration\XbmcMetadataOptions.cs" /> <Compile Include="Configuration\SubtitlePlaybackMode.cs" /> <Compile Include="Connect\ConnectAuthenticationExchangeResult.cs" /> @@ -132,7 +136,6 @@ <Compile Include="Dto\NameValuePair.cs" /> <Compile Include="MediaInfo\LiveMediaInfoResult.cs" /> <Compile Include="Dto\MediaSourceType.cs" /> - <Compile Include="Dto\VideoStreamOptions.cs" /> <Compile Include="Configuration\DynamicDayOfWeek.cs" /> <Compile Include="Entities\ExtraType.cs" /> <Compile Include="Entities\SupporterInfo.cs" /> @@ -262,7 +265,6 @@ <Compile Include="MediaInfo\SubtitleFormat.cs" /> <Compile Include="MediaInfo\TransportStreamTimestamp.cs" /> <Compile Include="MediaInfo\VideoCodec.cs" /> - <Compile Include="News\NewsChannel.cs" /> <Compile Include="News\NewsItem.cs" /> <Compile Include="News\NewsQuery.cs" /> <Compile Include="Notifications\NotificationRequest.cs" /> @@ -385,6 +387,7 @@ <Compile Include="Sync\SyncJobRequest.cs" /> <Compile Include="Sync\SyncJobStatus.cs" /> <Compile Include="Sync\SyncOptions.cs" /> + <Compile Include="Sync\SyncParameter.cs" /> <Compile Include="Sync\SyncQuality.cs" /> <Compile Include="Sync\SyncTarget.cs" /> <Compile Include="System\LogFile.cs" /> diff --git a/MediaBrowser.Model/News/NewsChannel.cs b/MediaBrowser.Model/News/NewsChannel.cs deleted file mode 100644 index c3955b0a0..000000000 --- a/MediaBrowser.Model/News/NewsChannel.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Collections.Generic; - -namespace MediaBrowser.Model.News -{ - public class NewsChannel - { - public string Title { get; set; } - public string Link { get; set; } - public string Description { get; set; } - public List<NewsItem> Items { get; set; } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Model/Notifications/NotificationType.cs b/MediaBrowser.Model/Notifications/NotificationType.cs index 34e4d32b5..269e27a4f 100644 --- a/MediaBrowser.Model/Notifications/NotificationType.cs +++ b/MediaBrowser.Model/Notifications/NotificationType.cs @@ -18,6 +18,7 @@ namespace MediaBrowser.Model.Notifications NewLibraryContent, NewLibraryContentMultiple, ServerRestartRequired, - TaskFailed + TaskFailed, + CameraImageUploaded } }
\ No newline at end of file diff --git a/MediaBrowser.Model/Session/ClientCapabilities.cs b/MediaBrowser.Model/Session/ClientCapabilities.cs index 5a806a867..6ca4507c0 100644 --- a/MediaBrowser.Model/Session/ClientCapabilities.cs +++ b/MediaBrowser.Model/Session/ClientCapabilities.cs @@ -14,16 +14,22 @@ namespace MediaBrowser.Model.Session public string MessageCallbackUrl { get; set; } public bool SupportsContentUploading { get; set; } - public bool SupportsUniqueIdentifier { get; set; } + public bool SupportsPersistentIdentifier { get; set; } public bool SupportsSync { get; set; } + public bool SupportsOfflineAccess { get; set; } public DeviceProfile DeviceProfile { get; set; } + /// <summary> + /// Usage should be migrated to SupportsPersistentIdentifier. Keeping this to preserve data. + /// </summary> + public bool? SupportsUniqueIdentifier { get; set; } + public ClientCapabilities() { PlayableMediaTypes = new List<string>(); SupportedCommands = new List<string>(); - SupportsUniqueIdentifier = true; + SupportsPersistentIdentifier = true; } } }
\ No newline at end of file diff --git a/MediaBrowser.Model/Sync/ItemFIleInfo.cs b/MediaBrowser.Model/Sync/ItemFIleInfo.cs index b110af6b5..e023572fd 100644 --- a/MediaBrowser.Model/Sync/ItemFIleInfo.cs +++ b/MediaBrowser.Model/Sync/ItemFIleInfo.cs @@ -23,6 +23,11 @@ namespace MediaBrowser.Model.Sync /// Gets or sets the type of the image. /// </summary> /// <value>The type of the image.</value> - public ImageType ImageType { get; set; } + public ImageType? ImageType { get; set; } + /// <summary> + /// Gets or sets the index. + /// </summary> + /// <value>The index.</value> + public int Index { get; set; } } } diff --git a/MediaBrowser.Model/Sync/SyncDialogOptions.cs b/MediaBrowser.Model/Sync/SyncDialogOptions.cs index 0154b16ec..304e10ccc 100644 --- a/MediaBrowser.Model/Sync/SyncDialogOptions.cs +++ b/MediaBrowser.Model/Sync/SyncDialogOptions.cs @@ -13,12 +13,12 @@ namespace MediaBrowser.Model.Sync /// Gets or sets the options. /// </summary> /// <value>The options.</value> - public List<SyncOptions> Options { get; set; } + public List<SyncJobOption> Options { get; set; } public SyncDialogOptions() { Targets = new List<SyncTarget>(); - Options = new List<SyncOptions>(); + Options = new List<SyncJobOption>(); } } } diff --git a/MediaBrowser.Model/Sync/SyncHelper.cs b/MediaBrowser.Model/Sync/SyncHelper.cs index c2a446fbe..34a5ba995 100644 --- a/MediaBrowser.Model/Sync/SyncHelper.cs +++ b/MediaBrowser.Model/Sync/SyncHelper.cs @@ -5,13 +5,13 @@ namespace MediaBrowser.Model.Sync { public static class SyncHelper { - public static List<SyncOptions> GetSyncOptions(List<BaseItemDto> items) + public static List<SyncJobOption> GetSyncOptions(List<BaseItemDto> items) { - List<SyncOptions> options = new List<SyncOptions>(); + List<SyncJobOption> options = new List<SyncJobOption>(); if (items.Count > 1) { - options.Add(SyncOptions.Name); + options.Add(SyncJobOption.Name); } foreach (BaseItemDto item in items) @@ -20,23 +20,23 @@ namespace MediaBrowser.Model.Sync { if (item.IsVideo) { - options.Add(SyncOptions.Quality); + options.Add(SyncJobOption.Quality); if (items.Count > 1) { - options.Add(SyncOptions.UnwatchedOnly); + options.Add(SyncJobOption.UnwatchedOnly); } break; } if (item.IsFolder && !item.IsMusicGenre && !item.IsArtist && !item.IsType("musicalbum") && !item.IsGameGenre) { - options.Add(SyncOptions.Quality); - options.Add(SyncOptions.UnwatchedOnly); + options.Add(SyncJobOption.Quality); + options.Add(SyncJobOption.UnwatchedOnly); break; } if (item.IsGenre) { - options.Add(SyncOptions.SyncNewContent); - options.Add(SyncOptions.ItemLimit); + options.Add(SyncJobOption.SyncNewContent); + options.Add(SyncJobOption.ItemLimit); break; } } @@ -48,8 +48,8 @@ namespace MediaBrowser.Model.Sync { if (item.IsFolder || item.IsGameGenre || item.IsMusicGenre || item.IsGenre || item.IsArtist || item.IsStudio || item.IsPerson) { - options.Add(SyncOptions.SyncNewContent); - options.Add(SyncOptions.ItemLimit); + options.Add(SyncJobOption.SyncNewContent); + options.Add(SyncJobOption.ItemLimit); break; } } @@ -58,15 +58,15 @@ namespace MediaBrowser.Model.Sync return options; } - public static List<SyncOptions> GetSyncOptions(SyncCategory category) + public static List<SyncJobOption> GetSyncOptions(SyncCategory category) { - List<SyncOptions> options = new List<SyncOptions>(); + List<SyncJobOption> options = new List<SyncJobOption>(); - options.Add(SyncOptions.Name); - options.Add(SyncOptions.Quality); - options.Add(SyncOptions.UnwatchedOnly); - options.Add(SyncOptions.SyncNewContent); - options.Add(SyncOptions.ItemLimit); + options.Add(SyncJobOption.Name); + options.Add(SyncJobOption.Quality); + options.Add(SyncJobOption.UnwatchedOnly); + options.Add(SyncJobOption.SyncNewContent); + options.Add(SyncJobOption.ItemLimit); return options; } diff --git a/MediaBrowser.Model/Sync/SyncJobCreationResult.cs b/MediaBrowser.Model/Sync/SyncJobCreationResult.cs index 797318b2a..6723aa2cf 100644 --- a/MediaBrowser.Model/Sync/SyncJobCreationResult.cs +++ b/MediaBrowser.Model/Sync/SyncJobCreationResult.cs @@ -1,8 +1,15 @@ - +using System.Collections.Generic; + namespace MediaBrowser.Model.Sync { public class SyncJobCreationResult { public SyncJob Job { get; set; } + public List<SyncJobItem> JobItems { get; set; } + + public SyncJobCreationResult() + { + JobItems = new List<SyncJobItem>(); + } } } diff --git a/MediaBrowser.Model/Sync/SyncJobItem.cs b/MediaBrowser.Model/Sync/SyncJobItem.cs index 3d06943aa..77464be58 100644 --- a/MediaBrowser.Model/Sync/SyncJobItem.cs +++ b/MediaBrowser.Model/Sync/SyncJobItem.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using MediaBrowser.Model.Dto; namespace MediaBrowser.Model.Sync { @@ -27,12 +29,18 @@ namespace MediaBrowser.Model.Sync /// </summary> /// <value>The name of the item.</value> public string ItemName { get; set; } - + /// <summary> /// Gets or sets the media source identifier. /// </summary> /// <value>The media source identifier.</value> public string MediaSourceId { get; set; } + + /// <summary> + /// Gets or sets the media source. + /// </summary> + /// <value>The media source.</value> + public MediaSourceInfo MediaSource { get; set; } /// <summary> /// Gets or sets the target identifier. @@ -74,9 +82,29 @@ namespace MediaBrowser.Model.Sync /// <value>The primary image tag.</value> public string PrimaryImageTag { get; set; } /// <summary> - /// Gets or sets a value indicating whether [requires conversion]. + /// Gets or sets the temporary path. + /// </summary> + /// <value>The temporary path.</value> + public string TemporaryPath { get; set; } + /// <summary> + /// Gets or sets the additional files. + /// </summary> + /// <value>The additional files.</value> + public List<ItemFileInfo> AdditionalFiles { get; set; } + /// <summary> + /// Gets or sets a value indicating whether this instance is marked for removal. /// </summary> - /// <value><c>true</c> if [requires conversion]; otherwise, <c>false</c>.</value> - public bool RequiresConversion { get; set; } + /// <value><c>true</c> if this instance is marked for removal; otherwise, <c>false</c>.</value> + public bool IsMarkedForRemoval { get; set; } + /// <summary> + /// Gets or sets the index of the job item. + /// </summary> + /// <value>The index of the job item.</value> + public int JobItemIndex { get; set; } + + public SyncJobItem() + { + AdditionalFiles = new List<ItemFileInfo>(); + } } } diff --git a/MediaBrowser.Model/Sync/SyncOptions.cs b/MediaBrowser.Model/Sync/SyncOptions.cs index d4a7461f3..294f7bcef 100644 --- a/MediaBrowser.Model/Sync/SyncOptions.cs +++ b/MediaBrowser.Model/Sync/SyncOptions.cs @@ -1,12 +1,8 @@ namespace MediaBrowser.Model.Sync { - public enum SyncOptions + public class SyncOptions { - Name = 0, - Quality = 1, - UnwatchedOnly = 2, - SyncNewContent = 3, - ItemLimit = 4 + public string TemporaryPath { get; set; } } } diff --git a/MediaBrowser.Model/Sync/SyncParameter.cs b/MediaBrowser.Model/Sync/SyncParameter.cs new file mode 100644 index 000000000..def4ab3e3 --- /dev/null +++ b/MediaBrowser.Model/Sync/SyncParameter.cs @@ -0,0 +1,12 @@ + +namespace MediaBrowser.Model.Sync +{ + public enum SyncJobOption + { + Name = 0, + Quality = 1, + UnwatchedOnly = 2, + SyncNewContent = 3, + ItemLimit = 4 + } +} diff --git a/MediaBrowser.Model/Sync/SyncedItem.cs b/MediaBrowser.Model/Sync/SyncedItem.cs index 784a12bc9..2063506b1 100644 --- a/MediaBrowser.Model/Sync/SyncedItem.cs +++ b/MediaBrowser.Model/Sync/SyncedItem.cs @@ -1,4 +1,5 @@ using MediaBrowser.Model.Dto; +using System.Collections.Generic; namespace MediaBrowser.Model.Sync { @@ -34,5 +35,15 @@ namespace MediaBrowser.Model.Sync /// </summary> /// <value>The user identifier.</value> public string UserId { get; set; } + /// <summary> + /// Gets or sets the additional files. + /// </summary> + /// <value>The additional files.</value> + public List<ItemFileInfo> AdditionalFiles { get; set; } + + public SyncedItem() + { + AdditionalFiles = new List<ItemFileInfo>(); + } } } diff --git a/MediaBrowser.Model/System/SystemInfo.cs b/MediaBrowser.Model/System/SystemInfo.cs index 415c619ea..ce081d5f2 100644 --- a/MediaBrowser.Model/System/SystemInfo.cs +++ b/MediaBrowser.Model/System/SystemInfo.cs @@ -63,12 +63,6 @@ namespace MediaBrowser.Model.System public List<InstallationInfo> CompletedInstallations { get; set; } /// <summary> - /// Gets or sets a value indicating whether [supports native web socket]. - /// </summary> - /// <value><c>true</c> if [supports native web socket]; otherwise, <c>false</c>.</value> - public bool SupportsNativeWebSocket { get; set; } - - /// <summary> /// Gets or sets a value indicating whether this instance can self restart. /// </summary> /// <value><c>true</c> if this instance can self restart; otherwise, <c>false</c>.</value> @@ -129,6 +123,18 @@ namespace MediaBrowser.Model.System public int HttpServerPortNumber { get; set; } /// <summary> + /// Gets or sets a value indicating whether [enable HTTPS]. + /// </summary> + /// <value><c>true</c> if [enable HTTPS]; otherwise, <c>false</c>.</value> + public bool SupportsHttps { get; set; } + + /// <summary> + /// Gets or sets the HTTPS server port number. + /// </summary> + /// <value>The HTTPS server port number.</value> + public int HttpsPortNumber { get; set; } + + /// <summary> /// Gets or sets a value indicating whether this instance has update available. /// </summary> /// <value><c>true</c> if this instance has update available; otherwise, <c>false</c>.</value> diff --git a/MediaBrowser.Model/Tasks/TaskResult.cs b/MediaBrowser.Model/Tasks/TaskResult.cs index 956d68ae4..39eacdf66 100644 --- a/MediaBrowser.Model/Tasks/TaskResult.cs +++ b/MediaBrowser.Model/Tasks/TaskResult.cs @@ -32,6 +32,12 @@ namespace MediaBrowser.Model.Tasks public string Name { get; set; } /// <summary> + /// Gets or sets the key. + /// </summary> + /// <value>The key.</value> + public string Key { get; set; } + + /// <summary> /// Gets or sets the id. /// </summary> /// <value>The id.</value> diff --git a/MediaBrowser.Model/Users/UserPolicy.cs b/MediaBrowser.Model/Users/UserPolicy.cs index 0a6a37696..cdc5077b0 100644 --- a/MediaBrowser.Model/Users/UserPolicy.cs +++ b/MediaBrowser.Model/Users/UserPolicy.cs @@ -52,6 +52,12 @@ namespace MediaBrowser.Model.Users public string[] EnabledDevices { get; set; } public bool EnableAllDevices { get; set; } + public string[] EnabledChannels { get; set; } + public bool EnableAllChannels { get; set; } + + public string[] EnabledFolders { get; set; } + public bool EnableAllFolders { get; set; } + public UserPolicy() { EnableLiveTvManagement = true; @@ -59,15 +65,19 @@ namespace MediaBrowser.Model.Users EnableLiveTvAccess = true; EnableSharedDeviceControl = true; - BlockedMediaFolders = new string[] { }; BlockedTags = new string[] { }; - BlockedChannels = new string[] { }; BlockUnratedItems = new UnratedItem[] { }; EnableUserPreferenceAccess = true; AccessSchedules = new AccessSchedule[] { }; + EnableAllChannels = true; + EnabledChannels = new string[] { }; + + EnableAllFolders = true; + EnabledFolders = new string[] { }; + EnabledDevices = new string[] { }; EnableAllDevices = true; } diff --git a/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs b/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs index 5afaaa875..3ac3cccb3 100644 --- a/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs +++ b/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs @@ -2,16 +2,15 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Localization; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Providers.Manager; -using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; namespace MediaBrowser.Providers.BoxSets { @@ -51,31 +50,18 @@ namespace MediaBrowser.Providers.BoxSets } } - protected override ItemUpdateType BeforeSave(BoxSet item) + protected override async Task<ItemUpdateType> BeforeSave(BoxSet item, bool isFullRefresh, ItemUpdateType currentUpdateType) { - var updateType = base.BeforeSave(item); + var updateType = await base.BeforeSave(item, isFullRefresh, currentUpdateType).ConfigureAwait(false); - if (!item.LockedFields.Contains(MetadataFields.OfficialRating)) + if (isFullRefresh || currentUpdateType > ItemUpdateType.None) { - var currentOfficialRating = item.OfficialRating; - - // Gather all possible ratings - var ratings = item.RecursiveChildren - .Concat(item.GetLinkedChildren()) - .Where(i => i is Movie || i is Series) - .Select(i => i.OfficialRating) - .Where(i => !string.IsNullOrEmpty(i)) - .Distinct(StringComparer.OrdinalIgnoreCase) - .Select(i => new Tuple<string, int?>(i, _iLocalizationManager.GetRatingLevel(i))) - .OrderBy(i => i.Item2 ?? 1000) - .Select(i => i.Item1); - - item.OfficialRating = ratings.FirstOrDefault() ?? item.OfficialRating; - - if (!string.Equals(currentOfficialRating ?? string.Empty, item.OfficialRating ?? string.Empty, - StringComparison.OrdinalIgnoreCase)) + if (!item.LockedFields.Contains(MetadataFields.OfficialRating)) { - updateType = updateType | ItemUpdateType.MetadataEdit; + if (item.UpdateRatingToContent()) + { + updateType = updateType | ItemUpdateType.MetadataEdit; + } } } diff --git a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs index 0611e415d..0e7050741 100644 --- a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs +++ b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs @@ -170,7 +170,7 @@ namespace MediaBrowser.Providers.BoxSets url += string.Format("&language={0}", language); } - var includeImageLanguageParam = MovieDbProvider.GetImageLanguagesParam(_localization, language); + var includeImageLanguageParam = MovieDbProvider.GetImageLanguagesParam(language); // Get images in english and with no language url += "&include_image_language=" + includeImageLanguageParam; diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index 700bca0fa..a8e16e4ae 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -1,6 +1,5 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Common.IO; -using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; @@ -9,6 +8,7 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Net; using System; using System.Collections.Generic; using System.Globalization; @@ -16,7 +16,6 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Model.Net; namespace MediaBrowser.Providers.Manager { @@ -183,7 +182,7 @@ namespace MediaBrowser.Providers.Manager currentFile.Attributes &= ~FileAttributes.Hidden; } - currentFile.Delete(); + _fileSystem.DeleteFile(currentFile.FullName); } } finally @@ -233,7 +232,8 @@ namespace MediaBrowser.Providers.Manager using (var fs = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true)) { - await source.CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, cancellationToken).ConfigureAwait(false); + await source.CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, cancellationToken) + .ConfigureAwait(false); } if (_config.Configuration.SaveMetadataHidden) @@ -244,6 +244,11 @@ namespace MediaBrowser.Providers.Manager file.Attributes |= FileAttributes.Hidden; } } + catch (UnauthorizedAccessException ex) + { + _logger.Error("Error saving image to {0}", ex, path); + throw new Exception(string.Format("Error saving image to {0}", path), ex); + } finally { _libraryMonitor.ReportFileSystemChangeComplete(path, false); diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index 0d318c377..66b0f9259 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -349,7 +349,7 @@ namespace MediaBrowser.Providers.Manager currentFile.Attributes &= ~FileAttributes.Hidden; } - currentFile.Delete(); + _fileSystem.DeleteFile(currentFile.FullName); deleted = true; } } diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index e27c39df1..ab6cb89a6 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -114,7 +114,7 @@ namespace MediaBrowser.Providers.Manager catch (Exception ex) { localImagesFailed = true; - Logger.ErrorException("Error validating images for {0}", ex, item.Path ?? item.Name); + Logger.ErrorException("Error validating images for {0}", ex, item.Path ?? item.Name ?? "Unknown name"); refreshResult.AddStatus(ProviderRefreshStatus.Failure, ex.Message); } @@ -163,14 +163,13 @@ namespace MediaBrowser.Providers.Manager } } - updateType = updateType | BeforeSave(itemOfType); - - var providersHadChanges = updateType > ItemUpdateType.None; + updateType = updateType | (await BeforeSave(itemOfType, item.DateLastSaved == default(DateTime) || refreshOptions.ReplaceAllMetadata, updateType).ConfigureAwait(false)); // Save if changes were made, or it's never been saved before - if (refreshOptions.ForceSave || providersHadChanges || item.DateLastSaved == default(DateTime) || refreshOptions.ReplaceAllMetadata) + if (refreshOptions.ForceSave || updateType > ItemUpdateType.None || item.DateLastSaved == default(DateTime) || refreshOptions.ReplaceAllMetadata) { - if (refreshOptions.ForceSave || providersHadChanges || refreshOptions.ReplaceAllMetadata) + // If any of these properties are set then make sure the updateType is not None, just to force everything to save + if (refreshOptions.ForceSave || refreshOptions.ReplaceAllMetadata) { updateType = updateType | ItemUpdateType.MetadataDownload; } @@ -179,10 +178,19 @@ namespace MediaBrowser.Providers.Manager await SaveItem(itemOfType, updateType, cancellationToken); } - if (providersHadChanges || refreshResult.IsDirty) + if (updateType > ItemUpdateType.None || refreshResult.IsDirty) { await SaveProviderResult(itemOfType, refreshResult, refreshOptions.DirectoryService).ConfigureAwait(false); } + + await AfterMetadataRefresh(itemOfType, refreshOptions, cancellationToken).ConfigureAwait(false); + } + + private readonly Task _cachedTask = Task.FromResult(true); + protected virtual Task AfterMetadataRefresh(TItemType item, MetadataRefreshOptions refreshOptions, CancellationToken cancellationToken) + { + item.AfterMetadataRefresh(); + return _cachedTask; } private void MergeIdentities(TItemType item, TIdType id) @@ -194,14 +202,17 @@ namespace MediaBrowser.Providers.Manager } } + private readonly Task<ItemUpdateType> _cachedResult = Task.FromResult(ItemUpdateType.None); /// <summary> /// Befores the save. /// </summary> /// <param name="item">The item.</param> + /// <param name="isFullRefresh">if set to <c>true</c> [is full refresh].</param> + /// <param name="currentUpdateType">Type of the current update.</param> /// <returns>ItemUpdateType.</returns> - protected virtual ItemUpdateType BeforeSave(TItemType item) + protected virtual Task<ItemUpdateType> BeforeSave(TItemType item, bool isFullRefresh, ItemUpdateType currentUpdateType) { - return ItemUpdateType.None; + return _cachedResult; } /// <summary> @@ -319,11 +330,11 @@ namespace MediaBrowser.Providers.Manager return item is TItemType; } - protected virtual async Task<RefreshResult> RefreshWithProviders(TItemType item, - TIdType id, - MetadataRefreshOptions options, - List<IMetadataProvider> providers, - ItemImageProvider imageService, + protected virtual async Task<RefreshResult> RefreshWithProviders(TItemType item, + TIdType id, + MetadataRefreshOptions options, + List<IMetadataProvider> providers, + ItemImageProvider imageService, CancellationToken cancellationToken) { var refreshResult = new RefreshResult @@ -435,8 +446,7 @@ namespace MediaBrowser.Providers.Manager localProviders.Count == 0 && refreshResult.UpdateType > ItemUpdateType.None) { - // TODO: If the new metadata from above has some blank data, this - // can cause old data to get filled into those empty fields + // TODO: If the new metadata from above has some blank data, this can cause old data to get filled into those empty fields MergeData(item, temp, new List<MetadataFields>(), false, true); } @@ -549,11 +559,6 @@ namespace MediaBrowser.Providers.Manager } } - if (refreshResult.Successes > 0) - { - AfterRemoteRefresh(temp); - } - return refreshResult; } @@ -570,11 +575,6 @@ namespace MediaBrowser.Providers.Manager } } - protected virtual void AfterRemoteRefresh(TItemType item) - { - - } - private async Task<TIdType> CreateInitialLookupInfo(TItemType item, CancellationToken cancellationToken) { var info = item.GetLookupInfo(); @@ -610,10 +610,10 @@ namespace MediaBrowser.Providers.Manager } } - protected abstract void MergeData(TItemType source, - TItemType target, - List<MetadataFields> lockedFields, - bool replaceData, + protected abstract void MergeData(TItemType source, + TItemType target, + List<MetadataFields> lockedFields, + bool replaceData, bool mergeMetadataSettings); public virtual int Order diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index d9982e786..823c34a75 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -1,5 +1,6 @@ using MediaBrowser.Common.IO; using MediaBrowser.Common.Net; +using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; @@ -58,6 +59,7 @@ namespace MediaBrowser.Providers.Manager private IMetadataProvider[] _metadataProviders = { }; private IEnumerable<IMetadataSaver> _savers; private IImageSaver[] _imageSavers; + private readonly IServerApplicationPaths _appPaths; private IExternalId[] _externalIds; @@ -69,13 +71,14 @@ namespace MediaBrowser.Providers.Manager /// <param name="libraryMonitor">The directory watchers.</param> /// <param name="logManager">The log manager.</param> /// <param name="fileSystem">The file system.</param> - public ProviderManager(IHttpClient httpClient, IServerConfigurationManager configurationManager, ILibraryMonitor libraryMonitor, ILogManager logManager, IFileSystem fileSystem) + public ProviderManager(IHttpClient httpClient, IServerConfigurationManager configurationManager, ILibraryMonitor libraryMonitor, ILogManager logManager, IFileSystem fileSystem, IServerApplicationPaths appPaths) { _logger = logManager.GetLogger("ProviderManager"); _httpClient = httpClient; ConfigurationManager = configurationManager; _libraryMonitor = libraryMonitor; _fileSystem = fileSystem; + _appPaths = appPaths; } /// <summary> @@ -467,7 +470,7 @@ namespace MediaBrowser.Providers.Manager // Give it a dummy path just so that it looks like a file system item var dummy = new T() { - Path = BaseItem.GetInternalMetadataPathForId(Guid.NewGuid()), + Path = Path.Combine(_appPaths.InternalMetadataPath, "dummy"), // Dummy this up to fool the local trailer check Parent = new Folder() @@ -709,7 +712,7 @@ namespace MediaBrowser.Providers.Manager // Give it a dummy path just so that it looks like a file system item var dummy = new TItemType { - Path = BaseItem.GetInternalMetadataPathForId(Guid.NewGuid()), + Path = Path.Combine(_appPaths.InternalMetadataPath, "dummy"), // Dummy this up to fool the local trailer check Parent = new Folder() diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 6ac1ab84e..2df8f8e3c 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -162,6 +162,7 @@ <Compile Include="Subtitles\ConfigurationExtension.cs" /> <Compile Include="Subtitles\OpenSubtitleDownloader.cs" /> <Compile Include="Subtitles\SubtitleManager.cs" /> + <Compile Include="TV\DummySeasonProvider.cs" /> <Compile Include="TV\EpisodeMetadataService.cs" /> <Compile Include="TV\FanArtTvUpdatesPostScanTask.cs" /> <Compile Include="TV\FanArtSeasonProvider.cs" /> diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs index 2634bd9bc..ad2b6ed0f 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs @@ -1,5 +1,5 @@ using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Extensions; +using MediaBrowser.Model.Extensions; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; @@ -187,18 +187,27 @@ namespace MediaBrowser.Providers.MediaInfo audio.Album = FFProbeHelpers.GetDictionaryValue(tags, "album"); - var artist = FFProbeHelpers.GetDictionaryValue(tags, "artist"); + var artists = FFProbeHelpers.GetDictionaryValue(tags, "artists"); - if (string.IsNullOrWhiteSpace(artist)) + if (!string.IsNullOrWhiteSpace(artists)) { - audio.Artists.Clear(); + audio.Artists = artists.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries) + .Distinct(StringComparer.OrdinalIgnoreCase) + .ToList(); } else { - audio.Artists = SplitArtists(artist) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToList(); - + var artist = FFProbeHelpers.GetDictionaryValue(tags, "artist"); + if (string.IsNullOrWhiteSpace(artist)) + { + audio.Artists.Clear(); + } + else + { + audio.Artists = SplitArtists(artist) + .Distinct(StringComparer.OrdinalIgnoreCase) + .ToList(); + } } var albumArtist = FFProbeHelpers.GetDictionaryValue(tags, "albumartist") ?? FFProbeHelpers.GetDictionaryValue(tags, "album artist") ?? FFProbeHelpers.GetDictionaryValue(tags, "album_artist"); @@ -250,10 +259,23 @@ namespace MediaBrowser.Providers.MediaInfo FetchStudios(audio, tags, "publisher"); } - audio.SetProviderId(MetadataProviders.MusicBrainzAlbumArtist, FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Artist Id")); - audio.SetProviderId(MetadataProviders.MusicBrainzArtist, FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Artist Id")); + // These support mulitple values, but for now we only store the first. + audio.SetProviderId(MetadataProviders.MusicBrainzAlbumArtist, GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Artist Id"))); + audio.SetProviderId(MetadataProviders.MusicBrainzArtist, GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Artist Id"))); + audio.SetProviderId(MetadataProviders.MusicBrainzAlbum, FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Id")); audio.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Group Id")); + audio.SetProviderId(MetadataProviders.MusicBrainzTrack, FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Track Id")); + } + + private string GetMultipleMusicBrainzId(string value) + { + if (string.IsNullOrWhiteSpace(value)) + { + return null; + } + + return value.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries).FirstOrDefault(); } private readonly char[] _nameDelimiters = { '/', '|', ';', '\\' }; diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs index 7f025dea1..5ec773532 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs @@ -1,6 +1,6 @@ using DvdLib.Ifo; using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Extensions; +using MediaBrowser.Model.Extensions; using MediaBrowser.Common.IO; using MediaBrowser.Controller.Chapters; using MediaBrowser.Controller.Configuration; diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs b/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs index 78d1fac47..ae5f93a2e 100644 --- a/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs +++ b/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs @@ -1,4 +1,4 @@ -using MediaBrowser.Common.Extensions; +using MediaBrowser.Model.Extensions; using MediaBrowser.Common.IO; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Localization; diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs b/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs index d913bd076..2852f5719 100644 --- a/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs +++ b/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs @@ -58,10 +58,13 @@ namespace MediaBrowser.Providers.MediaInfo var options = GetOptions(); var videos = _libraryManager.RootFolder - .RecursiveChildren - .OfType<Video>() - .Where(i => + .GetRecursiveChildren(i => { + if (!(i is Video)) + { + return false; + } + if (i.LocationType == LocationType.Remote || i.LocationType == LocationType.Virtual) { return false; @@ -72,6 +75,7 @@ namespace MediaBrowser.Providers.MediaInfo (options.DownloadMovieSubtitles && i is Movie); }) + .Cast<Video>() .ToList(); var numComplete = 0; diff --git a/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPostScanTask.cs b/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPostScanTask.cs index 2936fec0e..6e57ddb01 100644 --- a/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPostScanTask.cs +++ b/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPostScanTask.cs @@ -2,6 +2,7 @@ using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; using MediaBrowser.Providers.Music; @@ -13,6 +14,7 @@ using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Providers.TV; namespace MediaBrowser.Providers.Movies { @@ -54,7 +56,9 @@ namespace MediaBrowser.Providers.Movies /// <returns>Task.</returns> public async Task Run(IProgress<double> progress, CancellationToken cancellationToken) { - if (!_config.Configuration.EnableFanArtUpdates) + var options = FanartSeriesProvider.Current.GetFanartOptions(); + + if (!options.EnableAutomaticUpdates) { progress.Report(100); return; @@ -82,7 +86,7 @@ namespace MediaBrowser.Providers.Movies // If this is our first time, don't do any updates and just record the timestamp if (!string.IsNullOrEmpty(lastUpdateTime)) { - var moviesToUpdate = await GetMovieIdsToUpdate(existingDirectories, lastUpdateTime, cancellationToken).ConfigureAwait(false); + var moviesToUpdate = await GetMovieIdsToUpdate(existingDirectories, lastUpdateTime, options, cancellationToken).ConfigureAwait(false); progress.Report(5); @@ -96,12 +100,20 @@ namespace MediaBrowser.Providers.Movies progress.Report(100); } - private async Task<IEnumerable<string>> GetMovieIdsToUpdate(IEnumerable<string> existingIds, string lastUpdateTime, CancellationToken cancellationToken) + private async Task<IEnumerable<string>> GetMovieIdsToUpdate(IEnumerable<string> existingIds, string lastUpdateTime, FanartOptions options, CancellationToken cancellationToken) { + var url = string.Format(UpdatesUrl, FanartArtistProvider.ApiKey, lastUpdateTime); + + var clientKey = options.UserApiKey; + if (!string.IsNullOrWhiteSpace(clientKey)) + { + url += "&client_key=" + clientKey; + } + // First get last time using (var stream = await _httpClient.Get(new HttpRequestOptions { - Url = string.Format(UpdatesUrl, FanartArtistProvider.ApiKey, lastUpdateTime), + Url = url, CancellationToken = cancellationToken, EnableHttpCompression = true, ResourcePool = FanartArtistProvider.Current.FanArtResourcePool diff --git a/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs b/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs index 6813f2ff5..8d0c5cd54 100644 --- a/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs +++ b/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs @@ -19,6 +19,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Providers.TV; namespace MediaBrowser.Providers.Movies { @@ -216,7 +217,8 @@ namespace MediaBrowser.Providers.Movies public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) { - if (!_config.Configuration.EnableFanArtUpdates) + var options = FanartSeriesProvider.Current.GetFanartOptions(); + if (!options.EnableAutomaticUpdates) { return false; } @@ -283,6 +285,12 @@ namespace MediaBrowser.Providers.Movies var url = string.Format(FanArtBaseUrl, FanartArtistProvider.ApiKey, id); + var clientKey = FanartSeriesProvider.Current.GetFanartOptions().UserApiKey; + if (!string.IsNullOrWhiteSpace(clientKey)) + { + url += "&client_key=" + clientKey; + } + var path = GetFanartJsonPath(id); Directory.CreateDirectory(Path.GetDirectoryName(path)); diff --git a/MediaBrowser.Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Providers/Movies/MovieDbProvider.cs index 05747e49f..ed15a2eef 100644 --- a/MediaBrowser.Providers/Movies/MovieDbProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbProvider.cs @@ -7,6 +7,7 @@ using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Localization; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Providers; @@ -15,7 +16,6 @@ using System; using System.Collections.Generic; using System.Globalization; using System.IO; -using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -262,7 +262,7 @@ namespace MediaBrowser.Providers.Movies return Path.Combine(path, filename); } - public static string GetImageLanguagesParam(ILocalizationManager localization, string preferredLanguage) + public static string GetImageLanguagesParam(string preferredLanguage) { var languages = new List<string>(); @@ -276,18 +276,6 @@ namespace MediaBrowser.Providers.Movies languages.Add("en"); } - var firstLetter = string.IsNullOrWhiteSpace(preferredLanguage) - ? string.Empty - : preferredLanguage.Substring(0, 1); - - var allLanguages = localization.GetCultures() - .Select(i => i.TwoLetterISOLanguageName) - .Distinct(StringComparer.OrdinalIgnoreCase) - .Where(i => !languages.Contains(i, StringComparer.OrdinalIgnoreCase) && i.StartsWith(firstLetter, StringComparison.OrdinalIgnoreCase)) - .ToList(); - - //languages.AddRange(allLanguages); - return string.Join(",", languages.ToArray()); } @@ -308,7 +296,7 @@ namespace MediaBrowser.Providers.Movies url += string.Format("&language={0}", language); } - var includeImageLanguageParam = GetImageLanguagesParam(_localization, language); + var includeImageLanguageParam = GetImageLanguagesParam(language); // Get images in english and with no language url += "&include_image_language=" + includeImageLanguageParam; @@ -335,26 +323,29 @@ namespace MediaBrowser.Providers.Movies cancellationToken.ThrowIfCancellationRequested(); - if (mainResult != null && string.IsNullOrEmpty(mainResult.overview)) + // If the language preference isn't english, then have the overview fallback to english if it's blank + if (mainResult != null && + string.IsNullOrEmpty(mainResult.overview) && + !string.IsNullOrEmpty(language) && + !string.Equals(language, "en", StringComparison.OrdinalIgnoreCase)) { - if (!string.IsNullOrEmpty(language) && !string.Equals(language, "en", StringComparison.OrdinalIgnoreCase)) - { - _logger.Info("MovieDbProvider couldn't find meta for language " + language + ". Trying English..."); + _logger.Info("MovieDbProvider couldn't find meta for language " + language + ". Trying English..."); - url = string.Format(GetMovieInfo3, id, ApiKey) + "&include_image_language=" + includeImageLanguageParam + "&language=en"; + url = string.Format(GetMovieInfo3, id, ApiKey) + "&include_image_language=" + includeImageLanguageParam + "&language=en"; - using (var json = await GetMovieDbResponse(new HttpRequestOptions - { - Url = url, - CancellationToken = cancellationToken, - AcceptHeader = AcceptHeader, - CacheMode = cacheMode, - CacheLength = cacheLength + using (var json = await GetMovieDbResponse(new HttpRequestOptions + { + Url = url, + CancellationToken = cancellationToken, + AcceptHeader = AcceptHeader, + CacheMode = cacheMode, + CacheLength = cacheLength - }).ConfigureAwait(false)) - { - mainResult = _jsonSerializer.DeserializeFromStream<CompleteMovieData>(json); - } + }).ConfigureAwait(false)) + { + var englishResult = _jsonSerializer.DeserializeFromStream<CompleteMovieData>(json); + + mainResult.overview = englishResult.overview; } } @@ -371,9 +362,14 @@ namespace MediaBrowser.Providers.Movies return _httpClient.Get(options); } + public TheMovieDbOptions GetTheMovieDbOptions() + { + return _configurationManager.GetConfiguration<TheMovieDbOptions>("themoviedb"); + } + public bool HasChanged(IHasMetadata item, DateTime date) { - if (!_configurationManager.Configuration.EnableTmdbUpdates) + if (!GetTheMovieDbOptions().EnableAutomaticUpdates) { return false; } @@ -605,4 +601,19 @@ namespace MediaBrowser.Providers.Movies }); } } + + public class TmdbConfigStore : IConfigurationFactory + { + public IEnumerable<ConfigurationStore> GetConfigurations() + { + return new List<ConfigurationStore> + { + new ConfigurationStore + { + Key = "themoviedb", + ConfigurationType = typeof(TheMovieDbOptions) + } + }; + } + } } diff --git a/MediaBrowser.Providers/Movies/MovieDbSearch.cs b/MediaBrowser.Providers/Movies/MovieDbSearch.cs index ae176e489..f1a4d7bba 100644 --- a/MediaBrowser.Providers/Movies/MovieDbSearch.cs +++ b/MediaBrowser.Providers/Movies/MovieDbSearch.cs @@ -61,7 +61,6 @@ namespace MediaBrowser.Providers.Movies var parsedName = _libraryManager.ParseName(name); var yearInName = parsedName.Year; name = parsedName.Name; - year = year ?? yearInName; _logger.Info("MovieDbProvider: Finding id for item: " + name); @@ -183,14 +182,7 @@ namespace MediaBrowser.Providers.Movies if (DateTime.TryParseExact(result.release_date, "yyyy-MM-dd", EnUs, DateTimeStyles.None, out r)) { // Allow one year tolernace, preserve order from Tmdb - var variance = Math.Abs(r.Year - year.Value); - - if (variance <= 1) - { - return 0; - } - - return variance; + return Math.Abs(r.Year - year.Value); } } diff --git a/MediaBrowser.Providers/Movies/MovieUpdatesPrescanTask.cs b/MediaBrowser.Providers/Movies/MovieUpdatesPrescanTask.cs index d03573a96..cc2142292 100644 --- a/MediaBrowser.Providers/Movies/MovieUpdatesPrescanTask.cs +++ b/MediaBrowser.Providers/Movies/MovieUpdatesPrescanTask.cs @@ -68,7 +68,7 @@ namespace MediaBrowser.Providers.Movies /// <returns>Task.</returns> public async Task Run(IProgress<double> progress, CancellationToken cancellationToken) { - if (!_config.Configuration.EnableTmdbUpdates) + if (!MovieDbProvider.Current.GetTheMovieDbOptions().EnableAutomaticUpdates) { progress.Report(100); return; @@ -177,9 +177,8 @@ namespace MediaBrowser.Providers.Movies var numComplete = 0; // Gather all movies into a lookup by tmdb id - var allMovies = _libraryManager.RootFolder.RecursiveChildren - .Where(i => i is Movie) - .Where(i => !string.IsNullOrEmpty(i.GetProviderId(MetadataProviders.Tmdb))) + var allMovies = _libraryManager.RootFolder + .GetRecursiveChildren(i => i is Movie && !string.IsNullOrEmpty(i.GetProviderId(MetadataProviders.Tmdb))) .ToLookup(i => i.GetProviderId(MetadataProviders.Tmdb)); foreach (var id in list) diff --git a/MediaBrowser.Providers/Music/AlbumImageFromSongProvider.cs b/MediaBrowser.Providers/Music/AlbumImageFromSongProvider.cs index dac3c4836..2ba700b09 100644 --- a/MediaBrowser.Providers/Music/AlbumImageFromSongProvider.cs +++ b/MediaBrowser.Providers/Music/AlbumImageFromSongProvider.cs @@ -20,7 +20,8 @@ namespace MediaBrowser.Providers.Music { var album = (MusicAlbum)item; - var image = album.RecursiveChildren.OfType<Audio>() + var image = album.GetRecursiveChildren() + .OfType<Audio>() .Select(i => i.GetImagePath(type)) .FirstOrDefault(i => !string.IsNullOrEmpty(i)); diff --git a/MediaBrowser.Providers/Music/AlbumMetadataService.cs b/MediaBrowser.Providers/Music/AlbumMetadataService.cs index 6e3a5bf06..11348361a 100644 --- a/MediaBrowser.Providers/Music/AlbumMetadataService.cs +++ b/MediaBrowser.Providers/Music/AlbumMetadataService.cs @@ -9,6 +9,7 @@ using MediaBrowser.Providers.Manager; using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; namespace MediaBrowser.Providers.Music { @@ -36,59 +37,64 @@ namespace MediaBrowser.Providers.Music } } - protected override ItemUpdateType BeforeSave(MusicAlbum item) + protected override async Task<ItemUpdateType> BeforeSave(MusicAlbum item, bool isFullRefresh, ItemUpdateType currentUpdateType) { - var updateType = base.BeforeSave(item); + var updateType = await base.BeforeSave(item, isFullRefresh, currentUpdateType).ConfigureAwait(false); - var songs = item.RecursiveChildren.OfType<Audio>().ToList(); - - if (!item.IsLocked) + if (isFullRefresh || currentUpdateType > ItemUpdateType.None) { - if (!item.LockedFields.Contains(MetadataFields.Genres)) + if (!item.IsLocked) { - var currentList = item.Genres.ToList(); - - item.Genres = songs.SelectMany(i => i.Genres) - .Distinct(StringComparer.OrdinalIgnoreCase) + var songs = item.GetRecursiveChildren(i => i is Audio) + .Cast<Audio>() .ToList(); - if (currentList.Count != item.Genres.Count || !currentList.OrderBy(i => i).SequenceEqual(item.Genres.OrderBy(i => i), StringComparer.OrdinalIgnoreCase)) + if (!item.LockedFields.Contains(MetadataFields.Genres)) { - updateType = updateType | ItemUpdateType.MetadataEdit; - } - } + var currentList = item.Genres.ToList(); - if (!item.LockedFields.Contains(MetadataFields.Studios)) - { - var currentList = item.Studios.ToList(); + item.Genres = songs.SelectMany(i => i.Genres) + .Distinct(StringComparer.OrdinalIgnoreCase) + .ToList(); - item.Studios = songs.SelectMany(i => i.Studios) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToList(); + if (currentList.Count != item.Genres.Count || !currentList.OrderBy(i => i).SequenceEqual(item.Genres.OrderBy(i => i), StringComparer.OrdinalIgnoreCase)) + { + updateType = updateType | ItemUpdateType.MetadataEdit; + } + } - if (currentList.Count != item.Studios.Count || !currentList.OrderBy(i => i).SequenceEqual(item.Studios.OrderBy(i => i), StringComparer.OrdinalIgnoreCase)) + if (!item.LockedFields.Contains(MetadataFields.Studios)) { - updateType = updateType | ItemUpdateType.MetadataEdit; - } - } + var currentList = item.Studios.ToList(); - if (!item.LockedFields.Contains(MetadataFields.Name)) - { - var name = songs.Select(i => i.Album).FirstOrDefault(i => !string.IsNullOrEmpty(i)); + item.Studios = songs.SelectMany(i => i.Studios) + .Distinct(StringComparer.OrdinalIgnoreCase) + .ToList(); - if (!string.IsNullOrEmpty(name)) - { - if (!string.Equals(item.Name, name, StringComparison.Ordinal)) + if (currentList.Count != item.Studios.Count || !currentList.OrderBy(i => i).SequenceEqual(item.Studios.OrderBy(i => i), StringComparer.OrdinalIgnoreCase)) { - item.Name = name; updateType = updateType | ItemUpdateType.MetadataEdit; } } - } - updateType = updateType | SetAlbumArtistFromSongs(item, songs); - updateType = updateType | SetArtistsFromSongs(item, songs); - updateType = updateType | SetDateFromSongs(item, songs); + if (!item.LockedFields.Contains(MetadataFields.Name)) + { + var name = songs.Select(i => i.Album).FirstOrDefault(i => !string.IsNullOrEmpty(i)); + + if (!string.IsNullOrEmpty(name)) + { + if (!string.Equals(item.Name, name, StringComparison.Ordinal)) + { + item.Name = name; + updateType = updateType | ItemUpdateType.MetadataEdit; + } + } + } + + updateType = updateType | SetAlbumArtistFromSongs(item, songs); + updateType = updateType | SetArtistsFromSongs(item, songs); + updateType = updateType | SetDateFromSongs(item, songs); + } } return updateType; diff --git a/MediaBrowser.Providers/Music/ArtistMetadataService.cs b/MediaBrowser.Providers/Music/ArtistMetadataService.cs index a73d82992..2497cc1ec 100644 --- a/MediaBrowser.Providers/Music/ArtistMetadataService.cs +++ b/MediaBrowser.Providers/Music/ArtistMetadataService.cs @@ -9,13 +9,17 @@ using MediaBrowser.Providers.Manager; using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; namespace MediaBrowser.Providers.Music { public class ArtistMetadataService : MetadataService<MusicArtist, ArtistInfo> { - public ArtistMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, IUserDataManager userDataManager) : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem, userDataManager) + private readonly ILibraryManager _libraryManager; + + public ArtistMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, IUserDataManager userDataManager, ILibraryManager libraryManager) : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem, userDataManager) { + _libraryManager = libraryManager; } /// <summary> @@ -31,28 +35,35 @@ namespace MediaBrowser.Providers.Music ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings); } - protected override ItemUpdateType BeforeSave(MusicArtist item) + protected override async Task<ItemUpdateType> BeforeSave(MusicArtist item, bool isFullRefresh, ItemUpdateType currentUpdateType) { - var updateType = base.BeforeSave(item); + var updateType = await base.BeforeSave(item, isFullRefresh, currentUpdateType).ConfigureAwait(false); - if (!item.IsAccessedByName && !item.IsLocked) + if (isFullRefresh || currentUpdateType > ItemUpdateType.None) { - if (!item.LockedFields.Contains(MetadataFields.Genres)) + if (!item.IsLocked) { - var songs = item.RecursiveChildren.OfType<Audio>().ToList(); - - var currentList = item.Genres.ToList(); + var itemFilter = item.GetItemFilter(); - item.Genres = songs.SelectMany(i => i.Genres) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToList(); + var taggedItems = item.IsAccessedByName ? + _libraryManager.RootFolder.GetRecursiveChildren(i => !i.IsFolder && itemFilter(i)).ToList() : + item.GetRecursiveChildren(i => i is IHasArtist && !i.IsFolder).ToList(); - if (currentList.Count != item.Genres.Count || !currentList.OrderBy(i => i).SequenceEqual(item.Genres.OrderBy(i => i), StringComparer.OrdinalIgnoreCase)) + if (!item.LockedFields.Contains(MetadataFields.Genres)) { - updateType = updateType | ItemUpdateType.MetadataEdit; + var currentList = item.Genres.ToList(); + + item.Genres = taggedItems.SelectMany(i => i.Genres) + .Distinct(StringComparer.OrdinalIgnoreCase) + .ToList(); + + if (currentList.Count != item.Genres.Count || !currentList.OrderBy(i => i).SequenceEqual(item.Genres.OrderBy(i => i), StringComparer.OrdinalIgnoreCase)) + { + updateType = updateType | ItemUpdateType.MetadataEdit; + } } } - } + } return updateType; } diff --git a/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs b/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs index 123ff9e29..734ee74b6 100644 --- a/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs +++ b/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs @@ -16,6 +16,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using System.Xml; +using MediaBrowser.Providers.TV; namespace MediaBrowser.Providers.Music { @@ -356,7 +357,8 @@ namespace MediaBrowser.Providers.Music public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) { - if (!_config.Configuration.EnableFanArtUpdates) + var options = FanartSeriesProvider.Current.GetFanartOptions(); + if (!options.EnableAutomaticUpdates) { return false; } diff --git a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs index 6f633cfc8..0ed654962 100644 --- a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs +++ b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs @@ -17,6 +17,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using System.Xml; +using MediaBrowser.Providers.TV; namespace MediaBrowser.Providers.Music { @@ -373,7 +374,8 @@ namespace MediaBrowser.Providers.Music public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) { - if (!_config.Configuration.EnableFanArtUpdates) + var options = FanartSeriesProvider.Current.GetFanartOptions(); + if (!options.EnableAutomaticUpdates) { return false; } @@ -423,6 +425,12 @@ namespace MediaBrowser.Providers.Music var url = string.Format(FanArtBaseUrl, ApiKey, musicBrainzId); + var clientKey = FanartSeriesProvider.Current.GetFanartOptions().UserApiKey; + if (!string.IsNullOrWhiteSpace(clientKey)) + { + url += "&client_key=" + clientKey; + } + var xmlPath = GetArtistXmlPath(_config.ApplicationPaths, musicBrainzId); Directory.CreateDirectory(Path.GetDirectoryName(xmlPath)); diff --git a/MediaBrowser.Providers/Music/FanArtUpdatesPostScanTask.cs b/MediaBrowser.Providers/Music/FanArtUpdatesPostScanTask.cs index 4c6706287..a9b05c99f 100644 --- a/MediaBrowser.Providers/Music/FanArtUpdatesPostScanTask.cs +++ b/MediaBrowser.Providers/Music/FanArtUpdatesPostScanTask.cs @@ -2,6 +2,7 @@ using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; using System; @@ -12,6 +13,7 @@ using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Providers.TV; namespace MediaBrowser.Providers.Music { @@ -53,7 +55,9 @@ namespace MediaBrowser.Providers.Music /// <returns>Task.</returns> public async Task Run(IProgress<double> progress, CancellationToken cancellationToken) { - if (!_config.Configuration.EnableFanArtUpdates) + var options = FanartSeriesProvider.Current.GetFanartOptions(); + + if (!options.EnableAutomaticUpdates) { progress.Report(100); return; @@ -81,7 +85,7 @@ namespace MediaBrowser.Providers.Music // If this is our first time, don't do any updates and just record the timestamp if (!string.IsNullOrEmpty(lastUpdateTime)) { - var artistsToUpdate = await GetArtistIdsToUpdate(existingDirectories, lastUpdateTime, cancellationToken).ConfigureAwait(false); + var artistsToUpdate = await GetArtistIdsToUpdate(existingDirectories, lastUpdateTime, options, cancellationToken).ConfigureAwait(false); progress.Report(5); @@ -102,12 +106,19 @@ namespace MediaBrowser.Providers.Music /// <param name="lastUpdateTime">The last update time.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task{IEnumerable{System.String}}.</returns> - private async Task<IEnumerable<string>> GetArtistIdsToUpdate(IEnumerable<string> existingArtistIds, string lastUpdateTime, CancellationToken cancellationToken) + private async Task<IEnumerable<string>> GetArtistIdsToUpdate(IEnumerable<string> existingArtistIds, string lastUpdateTime, FanartOptions options, CancellationToken cancellationToken) { + var url = string.Format(UpdatesUrl, FanartArtistProvider.ApiKey, lastUpdateTime); + + if (!string.IsNullOrWhiteSpace(options.UserApiKey)) + { + url += "&client_key=" + options.UserApiKey; + } + // First get last time using (var stream = await _httpClient.Get(new HttpRequestOptions { - Url = string.Format(UpdatesUrl, FanartArtistProvider.ApiKey, lastUpdateTime), + Url = url, CancellationToken = cancellationToken, EnableHttpCompression = true, ResourcePool = FanartArtistProvider.Current.FanArtResourcePool diff --git a/MediaBrowser.Providers/Music/MusicExternalIds.cs b/MediaBrowser.Providers/Music/MusicExternalIds.cs index a4eab1eee..bcafdc6f6 100644 --- a/MediaBrowser.Providers/Music/MusicExternalIds.cs +++ b/MediaBrowser.Providers/Music/MusicExternalIds.cs @@ -118,4 +118,27 @@ namespace MediaBrowser.Providers.Music return item is Audio || item is MusicAlbum; } } + + public class MusicBrainzTrackId : IExternalId + { + public string Name + { + get { return "MusicBrainz Track"; } + } + + public string Key + { + get { return MetadataProviders.MusicBrainzTrack.ToString(); } + } + + public string UrlFormatString + { + get { return "http://musicbrainz.org/track/{0}"; } + } + + public bool Supports(IHasProviderIds item) + { + return item is Audio; + } + } } diff --git a/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs b/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs index 1494eaee8..859a8e8e2 100644 --- a/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs +++ b/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs @@ -14,6 +14,8 @@ using MediaBrowser.Providers.Movies; using MediaBrowser.Providers.TV; using System; using System.Collections.Generic; +using System.Globalization; +using System.Net; using System.Threading; using System.Threading.Tasks; @@ -35,19 +37,80 @@ namespace MediaBrowser.Providers.Omdb _libraryManager = libraryManager; } - public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(SeriesInfo searchInfo, CancellationToken cancellationToken) + public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(SeriesInfo searchInfo, CancellationToken cancellationToken) { - return new List<RemoteSearchResult>(); + return GetSearchResults(searchInfo, "series", cancellationToken); } - public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(TrailerInfo searchInfo, CancellationToken cancellationToken) + public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(MovieInfo searchInfo, CancellationToken cancellationToken) { - return new List<RemoteSearchResult>(); + return GetSearchResults(searchInfo, "movie", cancellationToken); } - public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(MovieInfo searchInfo, CancellationToken cancellationToken) + public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(ItemLookupInfo searchInfo, string type, CancellationToken cancellationToken) { - return new List<RemoteSearchResult>(); + var list = new List<RemoteSearchResult>(); + + var imdbId = searchInfo.GetProviderId(MetadataProviders.Imdb); + if (!string.IsNullOrWhiteSpace(imdbId)) + { + return list; + } + + var url = "http://www.omdbapi.com/?plot=short&r=json"; + + var name = searchInfo.Name; + var year = searchInfo.Year; + + var parsedName = _libraryManager.ParseName(name); + var yearInName = parsedName.Year; + name = parsedName.Name; + year = year ?? yearInName; + + if (year.HasValue) + { + url += "&y=" + year.Value.ToString(CultureInfo.InvariantCulture); + } + + url += "&t=" + WebUtility.UrlEncode(name); + url += "&type=" + type; + + using (var stream = await _httpClient.Get(new HttpRequestOptions + { + Url = url, + ResourcePool = OmdbProvider.ResourcePool, + CancellationToken = cancellationToken, + CacheMode = CacheMode.Unconditional, + CacheLength = TimeSpan.FromDays(7) + + }).ConfigureAwait(false)) + { + var result = _jsonSerializer.DeserializeFromStream<SearchResult>(stream); + + if (string.Equals(result.Response, "true", StringComparison.OrdinalIgnoreCase)) + { + var item = new RemoteSearchResult(); + + item.SearchProviderName = Name; + item.Name = result.Title; + item.SetProviderId(MetadataProviders.Imdb, result.imdbID); + + int parsedYear; + if (int.TryParse(result.Year, NumberStyles.Any, CultureInfo.InvariantCulture, out parsedYear)) + { + item.ProductionYear = parsedYear; + } + + if (!string.IsNullOrWhiteSpace(result.Poster) && !string.Equals(result.Poster, "N/A", StringComparison.OrdinalIgnoreCase)) + { + item.ImageUrl = result.Poster; + } + + list.Add(item); + } + } + + return list; } public Task<MetadataResult<ChannelVideoItem>> GetMetadata(ChannelItemLookupInfo info, CancellationToken cancellationToken) @@ -60,9 +123,14 @@ namespace MediaBrowser.Providers.Omdb return GetMovieResult<ChannelVideoItem>(info, cancellationToken); } - public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(ChannelItemLookupInfo searchInfo, CancellationToken cancellationToken) + public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(ChannelItemLookupInfo searchInfo, CancellationToken cancellationToken) { - return new List<RemoteSearchResult>(); + if (searchInfo.ContentType != ChannelMediaContentType.MovieExtra || searchInfo.ExtraType != ExtraType.Trailer) + { + return Task.FromResult<IEnumerable<RemoteSearchResult>>(new List<RemoteSearchResult>()); + } + + return GetSearchResults(searchInfo, "movie", cancellationToken); } public string Name @@ -185,7 +253,36 @@ namespace MediaBrowser.Providers.Omdb public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) { - throw new NotImplementedException(); + return _httpClient.GetResponse(new HttpRequestOptions + { + CancellationToken = cancellationToken, + Url = url, + ResourcePool = OmdbProvider.ResourcePool + }); + } + + class SearchResult + { + public string Title { get; set; } + public string Year { get; set; } + public string Rated { get; set; } + public string Released { get; set; } + public string Runtime { get; set; } + public string Genre { get; set; } + public string Director { get; set; } + public string Writer { get; set; } + public string Actors { get; set; } + public string Plot { get; set; } + public string Language { get; set; } + public string Country { get; set; } + public string Awards { get; set; } + public string Poster { get; set; } + public string Metascore { get; set; } + public string imdbRating { get; set; } + public string imdbVotes { get; set; } + public string imdbID { get; set; } + public string Type { get; set; } + public string Response { get; set; } } } } diff --git a/MediaBrowser.Providers/People/TvdbPersonImageProvider.cs b/MediaBrowser.Providers/People/TvdbPersonImageProvider.cs index 253acc13f..0258fd539 100644 --- a/MediaBrowser.Providers/People/TvdbPersonImageProvider.cs +++ b/MediaBrowser.Providers/People/TvdbPersonImageProvider.cs @@ -56,10 +56,12 @@ namespace MediaBrowser.Providers.People public Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, CancellationToken cancellationToken) { + // Avoid implicitly captured closure + var itemName = item.Name; + var seriesWithPerson = _library.RootFolder - .RecursiveChildren - .OfType<Series>() - .Where(i => !string.IsNullOrEmpty(i.GetProviderId(MetadataProviders.Tvdb)) && i.People.Any(p => string.Equals(p.Name, item.Name, StringComparison.OrdinalIgnoreCase))) + .GetRecursiveChildren(i => i is Series && !string.IsNullOrEmpty(i.GetProviderId(MetadataProviders.Tvdb)) && i.People.Any(p => string.Equals(p.Name, itemName, StringComparison.OrdinalIgnoreCase))) + .Cast<Series>() .ToList(); var infos = seriesWithPerson.Select(i => GetImageFromSeriesData(i, item.Name, cancellationToken)) diff --git a/MediaBrowser.Providers/Photos/PhotoProvider.cs b/MediaBrowser.Providers/Photos/PhotoProvider.cs index 29b75d830..3eaef59fb 100644 --- a/MediaBrowser.Providers/Photos/PhotoProvider.cs +++ b/MediaBrowser.Providers/Photos/PhotoProvider.cs @@ -15,7 +15,7 @@ using TagLib.IFD.Tags; namespace MediaBrowser.Providers.Photos { - public class PhotoProvider : ICustomMetadataProvider<Photo>, IHasItemChangeMonitor + public class PhotoProvider : ICustomMetadataProvider<Photo>, IHasItemChangeMonitor, IForcedProvider { private readonly ILogger _logger; private readonly IImageProcessor _imageProcessor; diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs index 9a16ae24d..187f8814b 100644 --- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs +++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs @@ -245,7 +245,7 @@ namespace MediaBrowser.Providers.Subtitles try { - File.Delete(path); + _fileSystem.DeleteFile(path); } finally { diff --git a/MediaBrowser.Providers/TV/DummySeasonProvider.cs b/MediaBrowser.Providers/TV/DummySeasonProvider.cs new file mode 100644 index 000000000..fb5282551 --- /dev/null +++ b/MediaBrowser.Providers/TV/DummySeasonProvider.cs @@ -0,0 +1,181 @@ +using MediaBrowser.Common.Extensions; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Localization; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; +using System.Globalization; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Providers.TV +{ + public class DummySeasonProvider + { + private readonly IServerConfigurationManager _config; + private readonly ILogger _logger; + private readonly ILocalizationManager _localization; + private readonly ILibraryManager _libraryManager; + + private readonly CultureInfo _usCulture = new CultureInfo("en-US"); + + public DummySeasonProvider(IServerConfigurationManager config, ILogger logger, ILocalizationManager localization, ILibraryManager libraryManager) + { + _config = config; + _logger = logger; + _localization = localization; + _libraryManager = libraryManager; + } + + public async Task Run(Series series, CancellationToken cancellationToken) + { + await RemoveObsoleteSeasons(series).ConfigureAwait(false); + + var hasNewSeasons = await AddDummySeasonFolders(series, cancellationToken).ConfigureAwait(false); + + if (hasNewSeasons) + { + var directoryService = new DirectoryService(); + + //await series.RefreshMetadata(new MetadataRefreshOptions(directoryService), cancellationToken).ConfigureAwait(false); + + //await series.ValidateChildren(new Progress<double>(), cancellationToken, new MetadataRefreshOptions(directoryService)) + // .ConfigureAwait(false); + } + } + + private async Task<bool> AddDummySeasonFolders(Series series, CancellationToken cancellationToken) + { + var episodesInSeriesFolder = series.GetRecursiveChildren() + .OfType<Episode>() + .Where(i => !i.IsInSeasonFolder) + .ToList(); + + var hasChanges = false; + + // Loop through the unique season numbers + foreach (var seasonNumber in episodesInSeriesFolder.Select(i => i.ParentIndexNumber ?? -1) + .Where(i => i >= 0) + .Distinct() + .ToList()) + { + var hasSeason = series.Children.OfType<Season>() + .Any(i => i.IndexNumber.HasValue && i.IndexNumber.Value == seasonNumber); + + if (!hasSeason) + { + await AddSeason(series, seasonNumber, cancellationToken).ConfigureAwait(false); + + hasChanges = true; + } + } + + // Unknown season - create a dummy season to put these under + if (episodesInSeriesFolder.Any(i => !i.ParentIndexNumber.HasValue)) + { + var hasSeason = series.Children.OfType<Season>() + .Any(i => !i.IndexNumber.HasValue); + + if (!hasSeason) + { + await AddSeason(series, null, cancellationToken).ConfigureAwait(false); + + hasChanges = true; + } + } + + return hasChanges; + } + + /// <summary> + /// Adds the season. + /// </summary> + /// <param name="series">The series.</param> + /// <param name="seasonNumber">The season number.</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns>Task{Season}.</returns> + public async Task<Season> AddSeason(Series series, + int? seasonNumber, + CancellationToken cancellationToken) + { + var seasonName = seasonNumber == 0 ? + _config.Configuration.SeasonZeroDisplayName : + (seasonNumber.HasValue ? string.Format(_localization.GetLocalizedString("NameSeasonNumber"), seasonNumber.Value.ToString(_usCulture)) : _localization.GetLocalizedString("NameSeasonUnknown")); + + _logger.Info("Creating Season {0} entry for {1}", seasonName, series.Name); + + var season = new Season + { + Name = seasonName, + IndexNumber = seasonNumber, + Parent = series, + Id = (series.Id + (seasonNumber ?? -1).ToString(_usCulture) + seasonName).GetMBId(typeof(Season)) + }; + + await series.AddChild(season, cancellationToken).ConfigureAwait(false); + + await season.RefreshMetadata(new MetadataRefreshOptions(), cancellationToken).ConfigureAwait(false); + + return season; + } + + private async Task<bool> RemoveObsoleteSeasons(Series series) + { + var existingSeasons = series.Children.OfType<Season>().ToList(); + + var physicalSeasons = existingSeasons + .Where(i => i.LocationType != LocationType.Virtual) + .ToList(); + + var virtualSeasons = existingSeasons + .Where(i => i.LocationType == LocationType.Virtual) + .ToList(); + + var episodes = series.GetRecursiveChildren().OfType<Episode>().ToList(); + + var seasonsToRemove = virtualSeasons + .Where(i => + { + if (i.IndexNumber.HasValue) + { + var seasonNumber = i.IndexNumber.Value; + + // If there's a physical season with the same number, delete it + if (physicalSeasons.Any(p => p.IndexNumber.HasValue && (p.IndexNumber.Value == seasonNumber))) + { + return true; + } + + // If there are no episodes with this season number, delete it + if (episodes.All(e => !e.ParentIndexNumber.HasValue || e.ParentIndexNumber.Value != seasonNumber)) + { + return true; + } + + return false; + } + + // Season does not have a number + // Remove if there are no episodes directly in series without a season number + return episodes.All(s => s.ParentIndexNumber.HasValue || !s.IsInSeasonFolder); + }) + .ToList(); + + var hasChanges = false; + + foreach (var seasonToRemove in seasonsToRemove) + { + _logger.Info("Removing virtual season {0} {1}", seasonToRemove.Series.Name, seasonToRemove.IndexNumber); + + await _libraryManager.DeleteItem(seasonToRemove).ConfigureAwait(false); + + hasChanges = true; + } + + return hasChanges; + } + } +} diff --git a/MediaBrowser.Providers/TV/FanArtSeasonProvider.cs b/MediaBrowser.Providers/TV/FanArtSeasonProvider.cs index 9f0cd4ff1..bbffd91b7 100644 --- a/MediaBrowser.Providers/TV/FanArtSeasonProvider.cs +++ b/MediaBrowser.Providers/TV/FanArtSeasonProvider.cs @@ -223,7 +223,8 @@ namespace MediaBrowser.Providers.TV public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) { - if (!_config.Configuration.EnableFanArtUpdates) + var options = FanartSeriesProvider.Current.GetFanartOptions(); + if (!options.EnableAutomaticUpdates) { return false; } diff --git a/MediaBrowser.Providers/TV/FanArtTvUpdatesPostScanTask.cs b/MediaBrowser.Providers/TV/FanArtTvUpdatesPostScanTask.cs index 13920d942..115b80434 100644 --- a/MediaBrowser.Providers/TV/FanArtTvUpdatesPostScanTask.cs +++ b/MediaBrowser.Providers/TV/FanArtTvUpdatesPostScanTask.cs @@ -2,6 +2,7 @@ using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; using MediaBrowser.Providers.Music; @@ -54,7 +55,9 @@ namespace MediaBrowser.Providers.TV /// <returns>Task.</returns> public async Task Run(IProgress<double> progress, CancellationToken cancellationToken) { - if (!_config.Configuration.EnableFanArtUpdates) + var options = FanartSeriesProvider.Current.GetFanartOptions(); + + if (!options.EnableAutomaticUpdates) { progress.Report(100); return; @@ -82,7 +85,7 @@ namespace MediaBrowser.Providers.TV // If this is our first time, don't do any updates and just record the timestamp if (!string.IsNullOrEmpty(lastUpdateTime)) { - var seriesToUpdate = await GetSeriesIdsToUpdate(existingDirectories, lastUpdateTime, cancellationToken).ConfigureAwait(false); + var seriesToUpdate = await GetSeriesIdsToUpdate(existingDirectories, lastUpdateTime, options, cancellationToken).ConfigureAwait(false); progress.Report(5); @@ -103,12 +106,19 @@ namespace MediaBrowser.Providers.TV /// <param name="lastUpdateTime">The last update time.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task{IEnumerable{System.String}}.</returns> - private async Task<IEnumerable<string>> GetSeriesIdsToUpdate(IEnumerable<string> existingSeriesIds, string lastUpdateTime, CancellationToken cancellationToken) + private async Task<IEnumerable<string>> GetSeriesIdsToUpdate(IEnumerable<string> existingSeriesIds, string lastUpdateTime, FanartOptions options, CancellationToken cancellationToken) { + var url = string.Format(UpdatesUrl, FanartArtistProvider.ApiKey, lastUpdateTime); + + if (!string.IsNullOrWhiteSpace(options.UserApiKey)) + { + url += "&client_key=" + options.UserApiKey; + } + // First get last time using (var stream = await _httpClient.Get(new HttpRequestOptions { - Url = string.Format(UpdatesUrl, FanartArtistProvider.ApiKey, lastUpdateTime), + Url = url, CancellationToken = cancellationToken, EnableHttpCompression = true, ResourcePool = FanartArtistProvider.Current.FanArtResourcePool diff --git a/MediaBrowser.Providers/TV/FanartSeriesProvider.cs b/MediaBrowser.Providers/TV/FanartSeriesProvider.cs index 8ba25e9f1..e512e6af8 100644 --- a/MediaBrowser.Providers/TV/FanartSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/FanartSeriesProvider.cs @@ -6,6 +6,7 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Net; @@ -161,10 +162,10 @@ namespace MediaBrowser.Providers.TV PopulateImages(list, obj.tvposter, ImageType.Primary, 1000, 1426); } - private void PopulateImages(List<RemoteImageInfo> list, - List<Image> images, - ImageType type, - int width, + private void PopulateImages(List<RemoteImageInfo> list, + List<Image> images, + ImageType type, + int width, int height, bool allowSeasonAll = false) { @@ -283,6 +284,11 @@ namespace MediaBrowser.Providers.TV } } + public FanartOptions GetFanartOptions() + { + return _config.GetConfiguration<FanartOptions>("fanart"); + } + /// <summary> /// Downloads the series json. /// </summary> @@ -295,6 +301,12 @@ namespace MediaBrowser.Providers.TV var url = string.Format(FanArtBaseUrl, FanartArtistProvider.ApiKey, tvdbId); + var clientKey = GetFanartOptions().UserApiKey; + if (!string.IsNullOrWhiteSpace(clientKey)) + { + url += "&client_key=" + clientKey; + } + var path = GetFanartJsonPath(tvdbId); Directory.CreateDirectory(Path.GetDirectoryName(path)); @@ -331,7 +343,8 @@ namespace MediaBrowser.Providers.TV public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) { - if (!_config.Configuration.EnableFanArtUpdates) + var options = GetFanartOptions(); + if (!options.EnableAutomaticUpdates) { return false; } @@ -378,4 +391,19 @@ namespace MediaBrowser.Providers.TV public List<Image> seasonbanner { get; set; } } } + + public class FanartConfigStore : IConfigurationFactory + { + public IEnumerable<ConfigurationStore> GetConfigurations() + { + return new List<ConfigurationStore> + { + new ConfigurationStore + { + Key = "fanart", + ConfigurationType = typeof(FanartOptions) + } + }; + } + } } diff --git a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs index 0b52956de..d45128288 100644 --- a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs @@ -25,7 +25,7 @@ namespace MediaBrowser.Providers.TV private readonly ILibraryManager _libraryManager; private readonly ILocalizationManager _localization; - private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); + private readonly CultureInfo _usCulture = new CultureInfo("en-US"); public MissingEpisodeProvider(ILogger logger, IServerConfigurationManager config, ILibraryManager libraryManager, ILocalizationManager localization) { @@ -78,11 +78,11 @@ namespace MediaBrowser.Providers.TV { int seasonNumber; - if (int.TryParse(parts[1], NumberStyles.Integer, UsCulture, out seasonNumber)) + if (int.TryParse(parts[1], NumberStyles.Integer, _usCulture, out seasonNumber)) { int episodeNumber; - if (int.TryParse(parts[2], NumberStyles.Integer, UsCulture, out episodeNumber)) + if (int.TryParse(parts[2], NumberStyles.Integer, _usCulture, out episodeNumber)) { return new Tuple<int, int>(seasonNumber, episodeNumber); } @@ -103,12 +103,6 @@ namespace MediaBrowser.Providers.TV .ConfigureAwait(false); var hasNewEpisodes = false; - var hasNewSeasons = false; - - foreach (var series in group) - { - hasNewSeasons = await AddDummySeasonFolders(series, cancellationToken).ConfigureAwait(false); - } if (_config.Configuration.EnableInternetProviders) { @@ -121,7 +115,7 @@ namespace MediaBrowser.Providers.TV } } - if (hasNewSeasons || hasNewEpisodes || anySeasonsRemoved || anyEpisodesRemoved) + if (hasNewEpisodes || anySeasonsRemoved || anyEpisodesRemoved) { foreach (var series in group) { @@ -145,7 +139,7 @@ namespace MediaBrowser.Providers.TV /// <returns></returns> private bool HasInvalidContent(IEnumerable<Series> group) { - var allItems = group.ToList().SelectMany(i => i.RecursiveChildren).ToList(); + var allItems = group.ToList().SelectMany(i => i.GetRecursiveChildren()).ToList(); return allItems.OfType<Season>().Any(i => !i.IndexNumber.HasValue) || allItems.OfType<Episode>().Any(i => @@ -161,55 +155,6 @@ namespace MediaBrowser.Providers.TV } /// <summary> - /// For series with episodes directly under the series folder, this adds dummy seasons to enable regular browsing and metadata - /// </summary> - /// <param name="series"></param> - /// <param name="cancellationToken"></param> - /// <returns></returns> - private async Task<bool> AddDummySeasonFolders(Series series, CancellationToken cancellationToken) - { - var episodesInSeriesFolder = series.RecursiveChildren - .OfType<Episode>() - .Where(i => !i.IsInSeasonFolder) - .ToList(); - - var hasChanges = false; - - // Loop through the unique season numbers - foreach (var seasonNumber in episodesInSeriesFolder.Select(i => i.ParentIndexNumber ?? -1) - .Where(i => i >= 0) - .Distinct() - .ToList()) - { - var hasSeason = series.Children.OfType<Season>() - .Any(i => i.IndexNumber.HasValue && i.IndexNumber.Value == seasonNumber); - - if (!hasSeason) - { - await AddSeason(series, seasonNumber, cancellationToken).ConfigureAwait(false); - - hasChanges = true; - } - } - - // Unknown season - create a dummy season to put these under - if (episodesInSeriesFolder.Any(i => !i.ParentIndexNumber.HasValue)) - { - var hasSeason = series.Children.OfType<Season>() - .Any(i => !i.IndexNumber.HasValue); - - if (!hasSeason) - { - await AddSeason(series, null, cancellationToken).ConfigureAwait(false); - - hasChanges = true; - } - } - - return hasChanges; - } - - /// <summary> /// Adds the missing episodes. /// </summary> /// <param name="series">The series.</param> @@ -218,22 +163,23 @@ namespace MediaBrowser.Providers.TV /// <param name="episodeLookup">The episode lookup.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - private async Task<bool> AddMissingEpisodes(List<Series> series, + private async Task<bool> AddMissingEpisodes(List<Series> series, bool seriesHasBadData, - string seriesDataPath, - IEnumerable<Tuple<int, int>> episodeLookup, + string seriesDataPath, + IEnumerable<Tuple<int, int>> episodeLookup, CancellationToken cancellationToken) { var existingEpisodes = (from s in series let seasonOffset = TvdbSeriesProvider.GetSeriesOffset(s.ProviderIds) ?? ((s.AnimeSeriesIndex ?? 1) - 1) - from c in s.RecursiveChildren.OfType<Episode>() + from c in s.GetRecursiveChildren().OfType<Episode>() select new Tuple<int, Episode>((c.ParentIndexNumber ?? 0) + seasonOffset, c)) .ToList(); var lookup = episodeLookup as IList<Tuple<int, int>> ?? episodeLookup.ToList(); var seasonCounts = (from e in lookup - group e by e.Item1 into g select g) + group e by e.Item1 into g + select g) .ToDictionary(g => g.Key, g => g.Count()); var hasChanges = false; @@ -299,23 +245,23 @@ namespace MediaBrowser.Providers.TV { var seriesAndOffsets = series.Select(s => new { Series = s, SeasonOffset = TvdbSeriesProvider.GetSeriesOffset(s.ProviderIds) ?? ((s.AnimeSeriesIndex ?? 1) - 1) }).ToList(); - var bestMatch = seriesAndOffsets.FirstOrDefault(s => s.Series.RecursiveChildren.OfType<Season>().Any(season => (season.IndexNumber + s.SeasonOffset) == seasonNumber)) ?? - seriesAndOffsets.FirstOrDefault(s => s.Series.RecursiveChildren.OfType<Season>().Any(season => (season.IndexNumber + s.SeasonOffset) == 1)) ?? - seriesAndOffsets.OrderBy(s => s.Series.RecursiveChildren.OfType<Season>().Select(season => season.IndexNumber + s.SeasonOffset).Min()).First(); + var bestMatch = seriesAndOffsets.FirstOrDefault(s => s.Series.GetRecursiveChildren().OfType<Season>().Any(season => (season.IndexNumber + s.SeasonOffset) == seasonNumber)) ?? + seriesAndOffsets.FirstOrDefault(s => s.Series.GetRecursiveChildren().OfType<Season>().Any(season => (season.IndexNumber + s.SeasonOffset) == 1)) ?? + seriesAndOffsets.OrderBy(s => s.Series.GetRecursiveChildren().OfType<Season>().Select(season => season.IndexNumber + s.SeasonOffset).Min()).First(); return bestMatch.Series; } - + /// <summary> /// Removes the virtual entry after a corresponding physical version has been added /// </summary> - private async Task<bool> RemoveObsoleteOrMissingEpisodes(IEnumerable<Series> series, + private async Task<bool> RemoveObsoleteOrMissingEpisodes(IEnumerable<Series> series, IEnumerable<Tuple<int, int>> episodeLookup) { var existingEpisodes = (from s in series let seasonOffset = TvdbSeriesProvider.GetSeriesOffset(s.ProviderIds) ?? ((s.AnimeSeriesIndex ?? 1) - 1) - from c in s.RecursiveChildren.OfType<Episode>() - select new { SeasonOffset = seasonOffset, Episode = c }) + from c in s.GetRecursiveChildren().OfType<Episode>() + select new { SeasonOffset = seasonOffset, Episode = c }) .ToList(); var physicalEpisodes = existingEpisodes @@ -375,7 +321,7 @@ namespace MediaBrowser.Providers.TV /// <param name="series">The series.</param> /// <param name="episodeLookup">The episode lookup.</param> /// <returns>Task{System.Boolean}.</returns> - private async Task<bool> RemoveObsoleteOrMissingSeasons(IEnumerable<Series> series, + private async Task<bool> RemoveObsoleteOrMissingSeasons(IEnumerable<Series> series, IEnumerable<Tuple<int, int>> episodeLookup) { var existingSeasons = (from s in series @@ -416,7 +362,7 @@ namespace MediaBrowser.Providers.TV // Season does not have a number // Remove if there are no episodes directly in series without a season number - return i.Season.Series.RecursiveChildren.OfType<Episode>().All(s => s.ParentIndexNumber.HasValue || s.IsInSeasonFolder); + return i.Season.Series.GetRecursiveChildren().OfType<Episode>().All(s => s.ParentIndexNumber.HasValue || !s.IsInSeasonFolder); }) .ToList(); @@ -449,10 +395,11 @@ namespace MediaBrowser.Providers.TV if (season == null) { - season = await AddSeason(series, seasonNumber, cancellationToken).ConfigureAwait(false); + var provider = new DummySeasonProvider(_config, _logger, _localization, _libraryManager); + season = await provider.AddSeason(series, seasonNumber, cancellationToken).ConfigureAwait(false); } - var name = string.Format("Episode {0}", episodeNumber.ToString(UsCulture)); + var name = string.Format("Episode {0}", episodeNumber.ToString(_usCulture)); var episode = new Episode { @@ -460,8 +407,7 @@ namespace MediaBrowser.Providers.TV IndexNumber = episodeNumber, ParentIndexNumber = seasonNumber, Parent = season, - DisplayMediaType = typeof(Episode).Name, - Id = (series.Id + seasonNumber.ToString(UsCulture) + name).GetMBId(typeof(Episode)) + Id = (series.Id + seasonNumber.ToString(_usCulture) + name).GetMBId(typeof(Episode)) }; await season.AddChild(episode, cancellationToken).ConfigureAwait(false); @@ -472,39 +418,6 @@ namespace MediaBrowser.Providers.TV } /// <summary> - /// Adds the season. - /// </summary> - /// <param name="series">The series.</param> - /// <param name="seasonNumber">The season number.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task{Season}.</returns> - private async Task<Season> AddSeason(Series series, - int? seasonNumber, - CancellationToken cancellationToken) - { - var seasonName = seasonNumber == 0 ? - _config.Configuration.SeasonZeroDisplayName : - (seasonNumber.HasValue ? string.Format(_localization.GetLocalizedString("NameSeasonNumber"), seasonNumber.Value.ToString(UsCulture)) : _localization.GetLocalizedString("NameSeasonUnknown")); - - _logger.Info("Creating Season {0} entry for {1}", seasonName, series.Name); - - var season = new Season - { - Name = seasonName, - IndexNumber = seasonNumber, - Parent = series, - DisplayMediaType = typeof(Season).Name, - Id = (series.Id + (seasonNumber ?? -1).ToString(UsCulture) + seasonName).GetMBId(typeof(Season)) - }; - - await series.AddChild(season, cancellationToken).ConfigureAwait(false); - - await season.RefreshMetadata(new MetadataRefreshOptions(), cancellationToken).ConfigureAwait(false); - - return season; - } - - /// <summary> /// Gets the existing episode. /// </summary> /// <param name="existingEpisodes">The existing episodes.</param> @@ -551,7 +464,7 @@ namespace MediaBrowser.Providers.TV private DateTime? GetAirDate(string seriesDataPath, int seasonNumber, int episodeNumber) { // First open up the tvdb xml file and make sure it has valid data - var filename = string.Format("episode-{0}-{1}.xml", seasonNumber.ToString(UsCulture), episodeNumber.ToString(UsCulture)); + var filename = string.Format("episode-{0}-{1}.xml", seasonNumber.ToString(_usCulture), episodeNumber.ToString(_usCulture)); var xmlPath = Path.Combine(seriesDataPath, filename); diff --git a/MediaBrowser.Providers/TV/MovieDbEpisodeImageProvider.cs b/MediaBrowser.Providers/TV/MovieDbEpisodeImageProvider.cs index 6aa27f496..ff5e6025d 100644 --- a/MediaBrowser.Providers/TV/MovieDbEpisodeImageProvider.cs +++ b/MediaBrowser.Providers/TV/MovieDbEpisodeImageProvider.cs @@ -219,7 +219,7 @@ namespace MediaBrowser.Providers.TV url += string.Format("&language={0}", language); } - var includeImageLanguageParam = MovieDbProvider.GetImageLanguagesParam(_localization, language); + var includeImageLanguageParam = MovieDbProvider.GetImageLanguagesParam(language); // Get images in english and with no language url += "&include_image_language=" + includeImageLanguageParam; diff --git a/MediaBrowser.Providers/TV/MovieDbSeasonProvider.cs b/MediaBrowser.Providers/TV/MovieDbSeasonProvider.cs index 80f4c9485..44c36af8f 100644 --- a/MediaBrowser.Providers/TV/MovieDbSeasonProvider.cs +++ b/MediaBrowser.Providers/TV/MovieDbSeasonProvider.cs @@ -203,7 +203,7 @@ namespace MediaBrowser.Providers.TV url += string.Format("&language={0}", language); } - var includeImageLanguageParam = MovieDbProvider.GetImageLanguagesParam(_localization, language); + var includeImageLanguageParam = MovieDbProvider.GetImageLanguagesParam(language); // Get images in english and with no language url += "&include_image_language=" + includeImageLanguageParam; diff --git a/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs b/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs index b4588741e..28fee246b 100644 --- a/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs @@ -62,7 +62,7 @@ namespace MediaBrowser.Providers.TV cancellationToken.ThrowIfCancellationRequested(); await EnsureSeriesInfo(tmdbId, searchInfo.MetadataLanguage, cancellationToken).ConfigureAwait(false); - + var dataFilePath = GetDataFilePath(tmdbId, searchInfo.MetadataLanguage); var obj = _jsonSerializer.DeserializeFromFile<RootObject>(dataFilePath); @@ -84,7 +84,7 @@ namespace MediaBrowser.Providers.TV { remoteResult.SetProviderId(MetadataProviders.Tvdb, obj.external_ids.tvdb_id.ToString(_usCulture)); } - + return new[] { remoteResult }; } @@ -233,7 +233,7 @@ namespace MediaBrowser.Providers.TV } series.HomePageUrl = seriesInfo.homepage; - + series.RunTimeTicks = seriesInfo.episode_run_time.Select(i => TimeSpan.FromMinutes(i).Ticks).FirstOrDefault(); if (string.Equals(seriesInfo.status, "Ended", StringComparison.OrdinalIgnoreCase)) @@ -302,12 +302,14 @@ namespace MediaBrowser.Providers.TV url += string.Format("&language={0}", language); } - var includeImageLanguageParam = MovieDbProvider.GetImageLanguagesParam(_localization, language); + var includeImageLanguageParam = MovieDbProvider.GetImageLanguagesParam(language); // Get images in english and with no language url += "&include_image_language=" + includeImageLanguageParam; cancellationToken.ThrowIfCancellationRequested(); + RootObject mainResult; + using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions { Url = url, @@ -316,8 +318,36 @@ namespace MediaBrowser.Providers.TV }).ConfigureAwait(false)) { - return _jsonSerializer.DeserializeFromStream<RootObject>(json); + mainResult = _jsonSerializer.DeserializeFromStream<RootObject>(json); } + + cancellationToken.ThrowIfCancellationRequested(); + + // If the language preference isn't english, then have the overview fallback to english if it's blank + if (mainResult != null && + string.IsNullOrEmpty(mainResult.overview) && + !string.IsNullOrEmpty(language) && + !string.Equals(language, "en", StringComparison.OrdinalIgnoreCase)) + { + _logger.Info("MovieDbSeriesProvider couldn't find meta for language " + language + ". Trying English..."); + + url = string.Format(GetTvInfo3, id, MovieDbProvider.ApiKey) + "&include_image_language=" + includeImageLanguageParam + "&language=en"; + + using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions + { + Url = url, + CancellationToken = cancellationToken, + AcceptHeader = MovieDbProvider.AcceptHeader + + }).ConfigureAwait(false)) + { + var englishResult = _jsonSerializer.DeserializeFromStream<RootObject>(json); + + mainResult.overview = englishResult.overview; + } + } + + return mainResult; } private readonly Task _cachedTask = Task.FromResult(true); @@ -369,7 +399,7 @@ namespace MediaBrowser.Providers.TV public bool HasChanged(IHasMetadata item, DateTime date) { - if (!_configurationManager.Configuration.EnableTmdbUpdates) + if (!MovieDbProvider.Current.GetTheMovieDbOptions().EnableAutomaticUpdates) { return false; } diff --git a/MediaBrowser.Providers/TV/SeasonMetadataService.cs b/MediaBrowser.Providers/TV/SeasonMetadataService.cs index 2510d4785..8955b224e 100644 --- a/MediaBrowser.Providers/TV/SeasonMetadataService.cs +++ b/MediaBrowser.Providers/TV/SeasonMetadataService.cs @@ -6,7 +6,9 @@ using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Providers.Manager; +using System; using System.Collections.Generic; +using System.Threading.Tasks; namespace MediaBrowser.Providers.TV { @@ -29,14 +31,20 @@ namespace MediaBrowser.Providers.TV ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings); } - protected override void AfterRemoteRefresh(Season item) + protected override async Task<ItemUpdateType> BeforeSave(Season item, bool isFullRefresh, ItemUpdateType currentUpdateType) { - base.AfterRemoteRefresh(item); + var updateType = await base.BeforeSave(item, isFullRefresh, currentUpdateType).ConfigureAwait(false); if (item.IndexNumber.HasValue && item.IndexNumber.Value == 0) { - item.Name = ServerConfigurationManager.Configuration.SeasonZeroDisplayName; + if (!string.Equals(item.Name, ServerConfigurationManager.Configuration.SeasonZeroDisplayName, StringComparison.OrdinalIgnoreCase)) + { + item.Name = ServerConfigurationManager.Configuration.SeasonZeroDisplayName; + updateType = updateType | ItemUpdateType.MetadataEdit; + } } + + return updateType; } } } diff --git a/MediaBrowser.Providers/TV/SeriesMetadataService.cs b/MediaBrowser.Providers/TV/SeriesMetadataService.cs index 713d46347..df06525c1 100644 --- a/MediaBrowser.Providers/TV/SeriesMetadataService.cs +++ b/MediaBrowser.Providers/TV/SeriesMetadataService.cs @@ -2,18 +2,27 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Localization; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Providers.Manager; using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; namespace MediaBrowser.Providers.TV { public class SeriesMetadataService : MetadataService<Series, SeriesInfo> { - public SeriesMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, IUserDataManager userDataManager) : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem, userDataManager) + private readonly ILocalizationManager _localization; + private readonly ILibraryManager _libraryManager; + + public SeriesMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, IUserDataManager userDataManager, ILocalizationManager localization, ILibraryManager libraryManager) + : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem, userDataManager) { + _localization = localization; + _libraryManager = libraryManager; } /// <summary> @@ -46,12 +55,24 @@ namespace MediaBrowser.Providers.TV if (replaceData || target.AirDays.Count == 0) { target.AirDays = source.AirDays; - } - + } + if (mergeMetadataSettings) { target.DisplaySpecialsWithSeasons = source.DisplaySpecialsWithSeasons; } } + + protected override async Task AfterMetadataRefresh(Series item, MetadataRefreshOptions refreshOptions, CancellationToken cancellationToken) + { + await base.AfterMetadataRefresh(item, refreshOptions, cancellationToken).ConfigureAwait(false); + + if (refreshOptions.IsPostRecursiveRefresh) + { + var provider = new DummySeasonProvider(ServerConfigurationManager, Logger, _localization, _libraryManager); + + await provider.Run(item, CancellationToken.None).ConfigureAwait(false); + } + } } } diff --git a/MediaBrowser.Providers/TV/SeriesPostScanTask.cs b/MediaBrowser.Providers/TV/SeriesPostScanTask.cs index 17a219f52..874b5c92d 100644 --- a/MediaBrowser.Providers/TV/SeriesPostScanTask.cs +++ b/MediaBrowser.Providers/TV/SeriesPostScanTask.cs @@ -44,8 +44,8 @@ namespace MediaBrowser.Providers.TV private async Task RunInternal(IProgress<double> progress, CancellationToken cancellationToken) { var seriesList = _libraryManager.RootFolder - .RecursiveChildren - .OfType<Series>() + .GetRecursiveChildren(i => i is Series) + .Cast<Series>() .ToList(); var seriesGroups = FindSeriesGroups(seriesList).Where(g => !string.IsNullOrEmpty(g.Key)).ToList(); @@ -58,8 +58,8 @@ namespace MediaBrowser.Providers.TV { cancellationToken.ThrowIfCancellationRequested(); - var episodes = series.RecursiveChildren - .OfType<Episode>() + var episodes = series.GetRecursiveChildren(i => i is Episode) + .Cast<Episode>() .ToList(); var physicalEpisodes = episodes.Where(i => i.LocationType != LocationType.Virtual) diff --git a/MediaBrowser.Providers/TV/TvdbEpisodeImageProvider.cs b/MediaBrowser.Providers/TV/TvdbEpisodeImageProvider.cs index d10517470..969a76e38 100644 --- a/MediaBrowser.Providers/TV/TvdbEpisodeImageProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbEpisodeImageProvider.cs @@ -193,7 +193,7 @@ namespace MediaBrowser.Providers.TV if (!episode.IsVirtualUnaired) { // For non-unaired items, only enable if configured - if (!_config.Configuration.EnableTvDbUpdates) + if (!TvdbSeriesProvider.Current.GetTvDbOptions().EnableAutomaticUpdates) { return false; } diff --git a/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs b/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs index 52c1ab7dd..cbd3f0af0 100644 --- a/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs @@ -28,11 +28,13 @@ namespace MediaBrowser.Providers.TV internal static TvdbEpisodeProvider Current; private readonly IFileSystem _fileSystem; private readonly IServerConfigurationManager _config; + private readonly IHttpClient _httpClient; - public TvdbEpisodeProvider(IFileSystem fileSystem, IServerConfigurationManager config) + public TvdbEpisodeProvider(IFileSystem fileSystem, IServerConfigurationManager config, IHttpClient httpClient) { _fileSystem = fileSystem; _config = config; + _httpClient = httpClient; Current = this; } @@ -731,7 +733,12 @@ namespace MediaBrowser.Providers.TV public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) { - throw new NotImplementedException(); + return _httpClient.GetResponse(new HttpRequestOptions + { + CancellationToken = cancellationToken, + Url = url, + ResourcePool = TvdbSeriesProvider.Current.TvDbResourcePool + }); } public Task<EpisodeIdentity> FindIdentity(EpisodeInfo info) @@ -743,7 +750,7 @@ namespace MediaBrowser.Providers.TV { return Task.FromResult<EpisodeIdentity>(null); } - + var id = new EpisodeIdentity { Type = MetadataProviders.Tvdb.ToString(), diff --git a/MediaBrowser.Providers/TV/TvdbPrescanTask.cs b/MediaBrowser.Providers/TV/TvdbPrescanTask.cs index 32ed5d7f6..4bc4a2c8d 100644 --- a/MediaBrowser.Providers/TV/TvdbPrescanTask.cs +++ b/MediaBrowser.Providers/TV/TvdbPrescanTask.cs @@ -110,10 +110,10 @@ namespace MediaBrowser.Providers.TV .Select(Path.GetFileName) .ToList(); - var seriesIdsInLibrary = _libraryManager.RootFolder.RecursiveChildren - .OfType<Series>() + var seriesIdsInLibrary = _libraryManager.RootFolder + .GetRecursiveChildren(i => i is Series && !string.IsNullOrEmpty(i.GetProviderId(MetadataProviders.Tvdb))) + .Cast<Series>() .Select(i => i.GetProviderId(MetadataProviders.Tvdb)) - .Where(i => !string.IsNullOrEmpty(i)) .ToList(); var missingSeries = seriesIdsInLibrary.Except(existingDirectories, StringComparer.OrdinalIgnoreCase) @@ -301,9 +301,9 @@ namespace MediaBrowser.Providers.TV var numComplete = 0; // Gather all series into a lookup by tvdb id - var allSeries = _libraryManager.RootFolder.RecursiveChildren - .OfType<Series>() - .Where(i => !string.IsNullOrEmpty(i.GetProviderId(MetadataProviders.Tvdb))) + var allSeries = _libraryManager.RootFolder + .GetRecursiveChildren(i => i is Series && !string.IsNullOrEmpty(i.GetProviderId(MetadataProviders.Tvdb))) + .Cast<Series>() .ToLookup(i => i.GetProviderId(MetadataProviders.Tvdb)); foreach (var seriesId in list) diff --git a/MediaBrowser.Providers/TV/TvdbSeasonImageProvider.cs b/MediaBrowser.Providers/TV/TvdbSeasonImageProvider.cs index 1ebd7bed5..4dbf05d53 100644 --- a/MediaBrowser.Providers/TV/TvdbSeasonImageProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbSeasonImageProvider.cs @@ -362,7 +362,7 @@ namespace MediaBrowser.Providers.TV if (item.LocationType != LocationType.Virtual) { // For non-virtual items, only enable if configured - if (!_config.Configuration.EnableTvDbUpdates) + if (!TvdbSeriesProvider.Current.GetTvDbOptions().EnableAutomaticUpdates) { return false; } diff --git a/MediaBrowser.Providers/TV/TvdbSeriesImageProvider.cs b/MediaBrowser.Providers/TV/TvdbSeriesImageProvider.cs index 08913d3b4..6c8a06e38 100644 --- a/MediaBrowser.Providers/TV/TvdbSeriesImageProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbSeriesImageProvider.cs @@ -340,7 +340,7 @@ namespace MediaBrowser.Providers.TV public bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService) { - if (!_config.Configuration.EnableTvDbUpdates) + if (!TvdbSeriesProvider.Current.GetTvDbOptions().EnableAutomaticUpdates) { return false; } diff --git a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs index 20dc6c485..0f7a9f7d8 100644 --- a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs @@ -6,6 +6,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.Logging; @@ -224,6 +225,11 @@ namespace MediaBrowser.Providers.TV await ExtractEpisodes(seriesDataPath, Path.Combine(seriesDataPath, preferredMetadataLanguage + ".xml"), lastTvDbUpdateTime).ConfigureAwait(false); } + public TvdbOptions GetTvDbOptions() + { + return _config.GetConfiguration<TvdbOptions>("tvdb"); + } + private readonly Task _cachedTask = Task.FromResult(true); internal Task EnsureSeriesInfo(string seriesId, string preferredMetadataLanguage, CancellationToken cancellationToken) { @@ -237,7 +243,7 @@ namespace MediaBrowser.Providers.TV var seriesXmlFilename = preferredMetadataLanguage + ".xml"; var download = false; - var automaticUpdatesEnabled = _config.Configuration.EnableTvDbUpdates; + var automaticUpdatesEnabled = GetTvDbOptions().EnableAutomaticUpdates; const int cacheDays = 2; @@ -298,8 +304,6 @@ namespace MediaBrowser.Providers.TV private async Task<IEnumerable<RemoteSearchResult>> FindSeriesInternal(string name, CancellationToken cancellationToken) { - // TODO: Support returning more data, including image url's for the identify function - var url = string.Format(RootUrl + SeriesQuery, WebUtility.UrlEncode(name)); var doc = new XmlDocument(); @@ -324,6 +328,11 @@ namespace MediaBrowser.Providers.TV { foreach (XmlNode node in nodes) { + var searchResult = new RemoteSearchResult + { + SearchProviderName = Name + }; + var titles = new List<string>(); var nameNode = node.SelectSingleNode("./SeriesName"); @@ -339,19 +348,35 @@ namespace MediaBrowser.Providers.TV titles.AddRange(alias); } + var imdbIdNode = node.SelectSingleNode("./IMDB_ID"); + if (imdbIdNode != null) + { + var val = imdbIdNode.InnerText; + if (!string.IsNullOrWhiteSpace(val)) + { + searchResult.SetProviderId(MetadataProviders.Imdb, val); + } + } + + var bannerNode = node.SelectSingleNode("./banner"); + if (bannerNode != null) + { + var val = bannerNode.InnerText; + if (!string.IsNullOrWhiteSpace(val)) + { + searchResult.ImageUrl = TVUtils.BannerUrl + val; + } + } + if (titles.Any(t => string.Equals(t, comparableName, StringComparison.OrdinalIgnoreCase))) { - var id = node.SelectSingleNode("./seriesid"); + var id = node.SelectSingleNode("./seriesid") ?? + node.SelectSingleNode("./id"); + if (id != null) { - var searchResult = new RemoteSearchResult - { - Name = titles.FirstOrDefault(), - SearchProviderName = Name - }; - + searchResult.Name = titles.FirstOrDefault(); searchResult.SetProviderId(MetadataProviders.Tvdb, id.InnerText); - searchResults.Add(searchResult); } } @@ -1108,7 +1133,7 @@ namespace MediaBrowser.Providers.TV .EnumerateFiles("*.xml", SearchOption.AllDirectories) .ToList()) { - file.Delete(); + _fileSystem.DeleteFile(file.FullName); } } catch (DirectoryNotFoundException) @@ -1219,4 +1244,19 @@ namespace MediaBrowser.Providers.TV }); } } + + public class TvdbConfigStore : IConfigurationFactory + { + public IEnumerable<ConfigurationStore> GetConfigurations() + { + return new List<ConfigurationStore> + { + new ConfigurationStore + { + Key = "tvdb", + ConfigurationType = typeof(TvdbOptions) + } + }; + } + } } diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs b/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs index ce939aeb4..0e0e4fbcb 100644 --- a/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs +++ b/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs @@ -7,6 +7,7 @@ using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Channels; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Dto; @@ -95,7 +96,7 @@ namespace MediaBrowser.Server.Implementations.Channels public static string GetUserDistinctValue(User user) { - var channels = user.Policy.BlockedChannels + var channels = user.Policy.EnabledChannels .OrderBy(i => i) .ToList(); @@ -208,16 +209,6 @@ namespace MediaBrowser.Server.Implementations.Channels CancellationToken cancellationToken, string path) { - var limit = GetDownloadLimit(channelOptions); - - if (limit.HasValue) - { - if (IsSizeLimitReached(path, limit.Value)) - { - return; - } - } - var itemId = item.Id.ToString("N"); var sources = await _manager.GetChannelItemMediaSources(itemId, false, cancellationToken) .ConfigureAwait(false); @@ -230,6 +221,16 @@ namespace MediaBrowser.Server.Implementations.Channels return; } + var limit = GetDownloadLimit(channelOptions); + + if (limit.HasValue) + { + if (IsSizeLimitReached(path, limit.Value)) + { + return; + } + } + var channelItem = (IChannelMediaItem)item; var destination = Path.Combine(path, channelItem.ChannelId, itemId); @@ -254,10 +255,25 @@ namespace MediaBrowser.Server.Implementations.Channels if (item != null) { + var forceSave = false; + // Get the version from the database - item = _libraryManager.GetItemById(item.Id) ?? item; + var dbItem = _libraryManager.GetItemById(item.Id); + + if (dbItem == null) + { + forceSave = true; + } + else + { + item = dbItem; + } + + await item.RefreshMetadata(new MetadataRefreshOptions + { + ForceSave = forceSave - await item.RefreshMetadata(cancellationToken).ConfigureAwait(false); + }, cancellationToken).ConfigureAwait(false); } } @@ -358,7 +374,7 @@ namespace MediaBrowser.Server.Implementations.Channels { try { - File.Delete(path); + _fileSystem.DeleteFile(path); } catch (IOException ex) { diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs index c12a1161b..37536a4ee 100644 --- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs +++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs @@ -11,6 +11,7 @@ using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Channels; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Extensions; using MediaBrowser.Model.Logging; using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.Net; @@ -179,7 +180,7 @@ namespace MediaBrowser.Server.Implementations.Channels var dtoOptions = new DtoOptions(); - var returnItems = internalResult.Items.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user)) + var returnItems = _dtoService.GetBaseItemDtos(internalResult.Items, dtoOptions, user) .ToArray(); var result = new QueryResult<BaseItemDto> @@ -392,7 +393,9 @@ namespace MediaBrowser.Server.Implementations.Channels private async Task<Channel> GetChannel(IChannel channelInfo, CancellationToken cancellationToken) { - var path = Path.Combine(_config.ApplicationPaths.ItemsByNamePath, "channels", _fileSystem.GetValidFilename(channelInfo.Name)); + var id = GetInternalChannelId(channelInfo.Name); + + var path = Channel.GetInternalMetadataPath(_config.ApplicationPaths.InternalMetadataPath, id); var fileInfo = new DirectoryInfo(path); @@ -413,8 +416,6 @@ namespace MediaBrowser.Server.Implementations.Channels isNew = true; } - var id = GetInternalChannelId(channelInfo.Name); - var item = _libraryManager.GetItemById(id) as Channel; if (item == null) @@ -555,7 +556,7 @@ namespace MediaBrowser.Server.Implementations.Channels var dtoOptions = new DtoOptions(); - var returnItems = items.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user)) + var returnItems = _dtoService.GetBaseItemDtos(items, dtoOptions, user) .ToArray(); var result = new QueryResult<BaseItemDto> @@ -822,7 +823,7 @@ namespace MediaBrowser.Server.Implementations.Channels var dtoOptions = new DtoOptions(); - var returnItems = internalResult.Items.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user)) + var returnItems = _dtoService.GetBaseItemDtos(internalResult.Items, dtoOptions, user) .ToArray(); var result = new QueryResult<BaseItemDto> @@ -971,7 +972,7 @@ namespace MediaBrowser.Server.Implementations.Channels var dtoOptions = new DtoOptions(); - var returnItems = internalResult.Items.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user)) + var returnItems = _dtoService.GetBaseItemDtos(internalResult.Items, dtoOptions, user) .ToArray(); var result = new QueryResult<BaseItemDto> @@ -1262,8 +1263,6 @@ namespace MediaBrowser.Server.Implementations.Channels var mediaSource = info.MediaSources.FirstOrDefault(); item.Path = mediaSource == null ? null : mediaSource.Path; - - item.DisplayMediaType = channelMediaItem.ContentType.ToString(); } if (isNew) @@ -1492,7 +1491,7 @@ namespace MediaBrowser.Server.Implementations.Channels } else { - File.Delete(response.TempFilePath); + _fileSystem.DeleteFile(response.TempFilePath); throw new ApplicationException("Unexpected response type encountered: " + response.ContentType); } @@ -1501,7 +1500,7 @@ namespace MediaBrowser.Server.Implementations.Channels try { - File.Delete(response.TempFilePath); + _fileSystem.DeleteFile(response.TempFilePath); } catch { diff --git a/MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs b/MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs new file mode 100644 index 000000000..27ec6cc3b --- /dev/null +++ b/MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs @@ -0,0 +1,67 @@ +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using MediaBrowser.Server.Implementations.Photos; +using MoreLinq; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace MediaBrowser.Server.Implementations.Collections +{ + public class CollectionImageProvider : BaseDynamicImageProvider<BoxSet>, ICustomMetadataProvider<BoxSet> + { + public CollectionImageProvider(IFileSystem fileSystem, IProviderManager providerManager) + : base(fileSystem, providerManager) + { + } + + protected override Task<List<BaseItem>> GetItemsWithImages(IHasImages item) + { + var playlist = (BoxSet)item; + + var items = playlist.Children.Concat(playlist.GetLinkedChildren()) + .Select(i => + { + var subItem = i; + + var episode = subItem as Episode; + + if (episode != null) + { + var series = episode.Series; + if (series != null && series.HasImage(ImageType.Primary)) + { + return series; + } + } + + if (subItem.HasImage(ImageType.Primary)) + { + return subItem; + } + + var parent = subItem.Parent; + + if (parent != null && parent.HasImage(ImageType.Primary)) + { + if (parent is MusicAlbum) + { + return parent; + } + } + + return null; + }) + .Where(i => i != null) + .DistinctBy(i => i.Id) + .ToList(); + + return Task.FromResult(GetFinalItems(items)); + } + } +} diff --git a/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs b/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs index 9fee27db9..faf73c059 100644 --- a/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs +++ b/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs @@ -6,7 +6,6 @@ using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Logging; -using MoreLinq; using System; using System.Collections.Generic; using System.IO; @@ -41,6 +40,14 @@ namespace MediaBrowser.Server.Implementations.Collections .FirstOrDefault(); } + public IEnumerable<BoxSet> GetCollections(User user) + { + var folder = GetCollectionsFolder(user.Id.ToString("N")); + return folder == null ? + new List<BoxSet>() : + folder.GetChildren(user, true).OfType<BoxSet>(); + } + public async Task<BoxSet> CreateCollection(CollectionCreationOptions options) { var name = options.Name; @@ -69,7 +76,6 @@ namespace MediaBrowser.Server.Implementations.Collections { Name = name, Parent = parentFolder, - DisplayMediaType = "Collection", Path = path, IsLocked = options.IsLocked, ProviderIds = options.ProviderIds, @@ -168,24 +174,13 @@ namespace MediaBrowser.Server.Implementations.Collections } list.Add(LinkedChild.Create(item)); - - var supportsGrouping = item as ISupportsBoxSetGrouping; - - if (supportsGrouping != null) - { - var boxsetIdList = supportsGrouping.BoxSetIdList.ToList(); - if (!boxsetIdList.Contains(collectionId)) - { - boxsetIdList.Add(collectionId); - } - supportsGrouping.BoxSetIdList = boxsetIdList; - } } collection.LinkedChildren.AddRange(list); - await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); + collection.UpdateRatingToContent(); + await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); await collection.RefreshMetadata(CancellationToken.None).ConfigureAwait(false); if (fireEvent) @@ -228,15 +223,6 @@ namespace MediaBrowser.Server.Implementations.Collections { itemList.Add(childItem); } - - var supportsGrouping = childItem as ISupportsBoxSetGrouping; - - if (supportsGrouping != null) - { - var boxsetIdList = supportsGrouping.BoxSetIdList.ToList(); - boxsetIdList.Remove(collectionId); - supportsGrouping.BoxSetIdList = boxsetIdList; - } } var shortcutFiles = Directory @@ -258,7 +244,7 @@ namespace MediaBrowser.Server.Implementations.Collections { foreach (var file in shortcutFilesToDelete) { - File.Delete(file); + _fileSystem.DeleteFile(file); } foreach (var child in list) @@ -274,8 +260,9 @@ namespace MediaBrowser.Server.Implementations.Collections } } - await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); + collection.UpdateRatingToContent(); + await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); await collection.RefreshMetadata(CancellationToken.None).ConfigureAwait(false); EventHelper.FireEventIfNotNull(ItemsRemovedFromCollection, this, new CollectionModifiedEventArgs @@ -288,29 +275,41 @@ namespace MediaBrowser.Server.Implementations.Collections public IEnumerable<BaseItem> CollapseItemsWithinBoxSets(IEnumerable<BaseItem> items, User user) { - var itemsToCollapse = new List<ISupportsBoxSetGrouping>(); - var boxsets = new List<BaseItem>(); + var results = new Dictionary<Guid, BaseItem>(); - var list = items.ToList(); + var allBoxsets = GetCollections(user).ToList(); - foreach (var item in list.OfType<ISupportsBoxSetGrouping>()) + foreach (var item in items) { - var currentBoxSets = item.BoxSetIdList - .Select(i => _libraryManager.GetItemById(i)) - .Where(i => i != null && i.IsVisible(user)) - .ToList(); + var grouping = item as ISupportsBoxSetGrouping; - if (currentBoxSets.Count > 0) + if (grouping == null) + { + results[item.Id] = item; + } + else { - itemsToCollapse.Add(item); - boxsets.AddRange(currentBoxSets); + var itemId = item.Id; + + var currentBoxSets = allBoxsets + .Where(i => i.GetLinkedChildren().Any(j => j.Id == itemId)) + .ToList(); + + if (currentBoxSets.Count > 0) + { + foreach (var boxset in currentBoxSets) + { + results[boxset.Id] = boxset; + } + } + else + { + results[item.Id] = item; + } } } - return list - .Except(itemsToCollapse.Cast<BaseItem>()) - .Concat(boxsets) - .DistinctBy(i => i.Id); + return results.Values; } } } diff --git a/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs b/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs index b02c52874..bbe37cb50 100644 --- a/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs +++ b/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs @@ -1,4 +1,5 @@ using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Movies; using System.Linq; namespace MediaBrowser.Server.Implementations.Collections @@ -13,8 +14,9 @@ namespace MediaBrowser.Server.Implementations.Collections public override bool IsVisible(User user) { - return GetChildren(user, true).Any() && - base.IsVisible(user); + return base.IsVisible(user) && GetChildren(user, false) + .OfType<BoxSet>() + .Any(i => i.IsVisible(user)); } public override bool IsHidden diff --git a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs index b3b8ccbd8..bb9e9057a 100644 --- a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs +++ b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs @@ -88,9 +88,12 @@ namespace MediaBrowser.Server.Implementations.Configuration /// </summary> private void UpdateItemsByNamePath() { - ((ServerApplicationPaths)ApplicationPaths).ItemsByNamePath = string.IsNullOrEmpty(Configuration.ItemsByNamePath) ? - null : - Configuration.ItemsByNamePath; + if (!Configuration.MergeMetadataAndImagesByName) + { + ((ServerApplicationPaths)ApplicationPaths).ItemsByNamePath = string.IsNullOrEmpty(Configuration.ItemsByNamePath) ? + null : + Configuration.ItemsByNamePath; + } } /// <summary> @@ -99,8 +102,23 @@ namespace MediaBrowser.Server.Implementations.Configuration private void UpdateMetadataPath() { ((ServerApplicationPaths)ApplicationPaths).InternalMetadataPath = string.IsNullOrEmpty(Configuration.MetadataPath) ? - null : + GetInternalMetadataPath() : Configuration.MetadataPath; + + if (Configuration.MergeMetadataAndImagesByName) + { + ((ServerApplicationPaths)ApplicationPaths).ItemsByNamePath = ((ServerApplicationPaths)ApplicationPaths).InternalMetadataPath; + } + } + + private string GetInternalMetadataPath() + { + if (Configuration.EnableStandaloneMetadata) + { + return Path.Combine(ApplicationPaths.ProgramDataPath, "metadata"); + } + + return null; } /// <summary> diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs index 67d844543..e079aaf61 100644 --- a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs +++ b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs @@ -1,5 +1,4 @@ using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; @@ -79,10 +78,13 @@ namespace MediaBrowser.Server.Implementations.Connect if (!ip.StartsWith("http://", StringComparison.OrdinalIgnoreCase) && !ip.StartsWith("https://", StringComparison.OrdinalIgnoreCase)) { - ip = "http://" + ip; + ip = (_appHost.EnableHttps ? "https://" : "http://") + ip; } - return ip + ":" + _config.Configuration.PublicPort.ToString(CultureInfo.InvariantCulture); + ip += ":"; + ip += _appHost.EnableHttps ? _config.Configuration.PublicHttpsPort.ToString(CultureInfo.InvariantCulture) : _config.Configuration.PublicPort.ToString(CultureInfo.InvariantCulture); + + return ip; } return null; @@ -91,7 +93,7 @@ namespace MediaBrowser.Server.Implementations.Connect private string XApplicationValue { - get { return "Media Browser Server/" + _appHost.ApplicationVersion; } + get { return _appHost.Name + "/" + _appHost.ApplicationVersion; } } public ConnectManager(ILogger logger, @@ -113,6 +115,7 @@ namespace MediaBrowser.Server.Implementations.Connect _providerManager = providerManager; _userManager.UserConfigurationUpdated += _userManager_UserConfigurationUpdated; + _config.ConfigurationUpdated += _config_ConfigurationUpdated; LoadCachedData(); } @@ -150,7 +153,7 @@ namespace MediaBrowser.Server.Implementations.Connect try { - var localAddress = _appHost.GetSystemInfo().LocalAddress; + var localAddress = _appHost.LocalApiUrl; var hasExistingRecord = !string.IsNullOrWhiteSpace(ConnectServerId) && !string.IsNullOrWhiteSpace(ConnectAccessKey); @@ -165,8 +168,7 @@ namespace MediaBrowser.Server.Implementations.Connect } catch (HttpException ex) { - if (!ex.StatusCode.HasValue || - !new[] { HttpStatusCode.NotFound, HttpStatusCode.Unauthorized }.Contains(ex.StatusCode.Value)) + if (!ex.StatusCode.HasValue || !new[] { HttpStatusCode.NotFound, HttpStatusCode.Unauthorized }.Contains(ex.StatusCode.Value)) { throw; } @@ -180,6 +182,8 @@ namespace MediaBrowser.Server.Implementations.Connect await CreateServerRegistration(wanApiAddress, localAddress).ConfigureAwait(false); } + _lastReportedIdentifier = GetConnectReportingIdentifier(localAddress, wanApiAddress); + await RefreshAuthorizationsInternal(true, CancellationToken.None).ConfigureAwait(false); } catch (Exception ex) @@ -188,6 +192,27 @@ namespace MediaBrowser.Server.Implementations.Connect } } + private string _lastReportedIdentifier; + private string GetConnectReportingIdentifier() + { + return GetConnectReportingIdentifier(_appHost.LocalApiUrl, WanApiAddress); + } + private string GetConnectReportingIdentifier(string localAddress, string remoteAddress) + { + return (remoteAddress ?? string.Empty) + (localAddress ?? string.Empty); + } + + void _config_ConfigurationUpdated(object sender, EventArgs e) + { + // If info hasn't changed, don't report anything + if (string.Equals(_lastReportedIdentifier, GetConnectReportingIdentifier(), StringComparison.OrdinalIgnoreCase)) + { + return; + } + + UpdateConnectInfo(); + } + private async Task CreateServerRegistration(string wanApiAddress, string localAddress) { if (string.IsNullOrWhiteSpace(wanApiAddress)) @@ -547,8 +572,8 @@ namespace MediaBrowser.Server.Implementations.Connect Id = response.Id, ImageUrl = response.UserImageUrl, UserName = response.UserName, - ExcludedLibraries = request.ExcludedLibraries, - ExcludedChannels = request.ExcludedChannels, + EnabledLibraries = request.EnabledLibraries, + EnabledChannels = request.EnabledChannels, EnableLiveTv = request.EnableLiveTv, AccessToken = accessToken }); @@ -808,9 +833,13 @@ namespace MediaBrowser.Server.Implementations.Connect if (currentPendingEntry != null) { + user.Policy.EnabledFolders = currentPendingEntry.EnabledLibraries; + user.Policy.EnableAllFolders = false; + + user.Policy.EnabledChannels = currentPendingEntry.EnabledChannels; + user.Policy.EnableAllChannels = false; + user.Policy.EnableLiveTvAccess = currentPendingEntry.EnableLiveTv; - user.Policy.BlockedMediaFolders = currentPendingEntry.ExcludedLibraries; - user.Policy.BlockedChannels = currentPendingEntry.ExcludedChannels; } await _userManager.UpdateConfiguration(user.Id.ToString("N"), user.Configuration); @@ -937,8 +966,8 @@ namespace MediaBrowser.Server.Implementations.Connect { ConnectUserId = i.ConnectUserId, EnableLiveTv = i.EnableLiveTv, - ExcludedChannels = i.ExcludedChannels, - ExcludedLibraries = i.ExcludedLibraries, + EnabledChannels = i.EnabledChannels, + EnabledLibraries = i.EnabledLibraries, Id = i.Id, ImageUrl = i.ImageUrl, UserName = i.UserName diff --git a/MediaBrowser.Server.Implementations/Devices/CameraUploadsFolder.cs b/MediaBrowser.Server.Implementations/Devices/CameraUploadsFolder.cs index 10fc2ad91..2fe5d8f74 100644 --- a/MediaBrowser.Server.Implementations/Devices/CameraUploadsFolder.cs +++ b/MediaBrowser.Server.Implementations/Devices/CameraUploadsFolder.cs @@ -10,7 +10,6 @@ namespace MediaBrowser.Server.Implementations.Devices public CameraUploadsFolder() { Name = "Camera Uploads"; - DisplayMediaType = "CollectionFolder"; } public override bool IsVisible(User user) diff --git a/MediaBrowser.Server.Implementations/Devices/DeviceManager.cs b/MediaBrowser.Server.Implementations/Devices/DeviceManager.cs index ddd5ef58d..3211f88d5 100644 --- a/MediaBrowser.Server.Implementations/Devices/DeviceManager.cs +++ b/MediaBrowser.Server.Implementations/Devices/DeviceManager.cs @@ -27,6 +27,8 @@ namespace MediaBrowser.Server.Implementations.Devices private readonly IConfigurationManager _config; private readonly ILogger _logger; + public event EventHandler<GenericEventArgs<CameraImageUploadInfo>> CameraImageUploaded; + /// <summary> /// Occurs when [device options updated]. /// </summary> @@ -100,18 +102,23 @@ namespace MediaBrowser.Server.Implementations.Devices devices = devices.Where(i => GetCapabilities(i.Id).SupportsSync == val); } - if (query.SupportsUniqueIdentifier.HasValue) + if (query.SupportsPersistentIdentifier.HasValue) { - var val = query.SupportsUniqueIdentifier.Value; + var val = query.SupportsPersistentIdentifier.Value; - devices = devices.Where(i => GetCapabilities(i.Id).SupportsUniqueIdentifier == val); + devices = devices.Where(i => + { + var caps = GetCapabilities(i.Id); + var deviceVal = caps.SupportsUniqueIdentifier ?? caps.SupportsPersistentIdentifier; + return deviceVal == val; + }); } if (!string.IsNullOrWhiteSpace(query.UserId)) { devices = devices.Where(i => CanAccessDevice(query.UserId, i.Id)); } - + var array = devices.ToArray(); return new QueryResult<DeviceInfo> { @@ -132,7 +139,8 @@ namespace MediaBrowser.Server.Implementations.Devices public async Task AcceptCameraUpload(string deviceId, Stream stream, LocalFileInfo file) { - var path = GetUploadPath(deviceId); + var device = GetDevice(deviceId); + var path = GetUploadPath(device); if (!string.IsNullOrWhiteSpace(file.Album)) { @@ -158,11 +166,27 @@ namespace MediaBrowser.Server.Implementations.Devices { _libraryMonitor.ReportFileSystemChangeComplete(path, true); } + + if (CameraImageUploaded != null) + { + EventHelper.FireEventIfNotNull(CameraImageUploaded, this, new GenericEventArgs<CameraImageUploadInfo> + { + Argument = new CameraImageUploadInfo + { + Device = device, + FileInfo = file + } + }, _logger); + } } private string GetUploadPath(string deviceId) { - var device = GetDevice(deviceId); + return GetUploadPath(GetDevice(deviceId)); + } + + private string GetUploadPath(DeviceInfo device) + { if (!string.IsNullOrWhiteSpace(device.CameraUploadPath)) { return device.CameraUploadPath; @@ -212,7 +236,7 @@ namespace MediaBrowser.Server.Implementations.Devices { var capabilities = GetCapabilities(deviceId); - if (capabilities.SupportsUniqueIdentifier) + if (capabilities != null && capabilities.SupportsPersistentIdentifier) { return false; } diff --git a/MediaBrowser.Server.Implementations/Devices/DeviceRepository.cs b/MediaBrowser.Server.Implementations/Devices/DeviceRepository.cs index d587e5af7..6d324b1ab 100644 --- a/MediaBrowser.Server.Implementations/Devices/DeviceRepository.cs +++ b/MediaBrowser.Server.Implementations/Devices/DeviceRepository.cs @@ -1,5 +1,6 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.IO; using MediaBrowser.Controller.Devices; using MediaBrowser.Model.Devices; using MediaBrowser.Model.Logging; @@ -21,14 +22,16 @@ namespace MediaBrowser.Server.Implementations.Devices private readonly IApplicationPaths _appPaths; private readonly IJsonSerializer _json; private readonly ILogger _logger; + private readonly IFileSystem _fileSystem; private ConcurrentBag<DeviceInfo> _devices; - public DeviceRepository(IApplicationPaths appPaths, IJsonSerializer json, ILogger logger) + public DeviceRepository(IApplicationPaths appPaths, IJsonSerializer json, ILogger logger, IFileSystem fileSystem) { _appPaths = appPaths; _json = json; _logger = logger; + _fileSystem = fileSystem; } private string GetDevicesPath() @@ -57,6 +60,12 @@ namespace MediaBrowser.Server.Implementations.Devices public Task SaveCapabilities(string reportedId, ClientCapabilities capabilities) { var device = GetDevice(reportedId); + + if (device == null) + { + throw new ArgumentException("No device has been registed with id " + reportedId); + } + device.Capabilities = capabilities; SaveDevice(device); @@ -72,6 +81,11 @@ namespace MediaBrowser.Server.Implementations.Devices public DeviceInfo GetDevice(string id) { + if (string.IsNullOrWhiteSpace(id)) + { + throw new ArgumentNullException("id"); + } + return GetDevices() .FirstOrDefault(i => string.Equals(i.Id, id, StringComparison.OrdinalIgnoreCase)); } @@ -129,12 +143,12 @@ namespace MediaBrowser.Server.Implementations.Devices { try { - Directory.Delete(path, true); + _fileSystem.DeleteDirectory(path, true); } catch (DirectoryNotFoundException) { } - + _devices = null; } diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index 362ee80b0..61c24cf54 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -2,6 +2,7 @@ using MediaBrowser.Common.IO; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; @@ -19,6 +20,7 @@ using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Querying; +using MediaBrowser.Model.Sync; using MoreLinq; using System; using System.Collections.Generic; @@ -42,8 +44,9 @@ namespace MediaBrowser.Server.Implementations.Dto private readonly Func<IChannelManager> _channelManagerFactory; private readonly ISyncManager _syncManager; private readonly IApplicationHost _appHost; + private readonly Func<IDeviceManager> _deviceManager; - public DtoService(ILogger logger, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepo, IImageProcessor imageProcessor, IServerConfigurationManager config, IFileSystem fileSystem, IProviderManager providerManager, Func<IChannelManager> channelManagerFactory, ISyncManager syncManager, IApplicationHost appHost) + public DtoService(ILogger logger, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepo, IImageProcessor imageProcessor, IServerConfigurationManager config, IFileSystem fileSystem, IProviderManager providerManager, Func<IChannelManager> channelManagerFactory, ISyncManager syncManager, IApplicationHost appHost, Func<IDeviceManager> deviceManager) { _logger = logger; _libraryManager = libraryManager; @@ -56,6 +59,7 @@ namespace MediaBrowser.Server.Implementations.Dto _channelManagerFactory = channelManagerFactory; _syncManager = syncManager; _appHost = appHost; + _deviceManager = deviceManager; } /// <summary> @@ -73,10 +77,41 @@ namespace MediaBrowser.Server.Implementations.Dto { Fields = fields }; - + return GetBaseItemDto(item, options, user, owner); } + public IEnumerable<BaseItemDto> GetBaseItemDtos(IEnumerable<BaseItem> items, DtoOptions options, User user = null, BaseItem owner = null) + { + var itemIdsWithSyncJobs = GetItemIdsWithSyncJobs(options).ToList(); + + var list = new List<BaseItemDto>(); + + foreach (var item in items) + { + var dto = GetBaseItemDtoInternal(item, options, user, owner); + + var byName = item as IItemByName; + + if (byName != null && !(item is LiveTvChannel)) + { + var itemFilter = byName.GetItemFilter(); + + var libraryItems = user != null ? + user.RootFolder.GetRecursiveChildren(user, itemFilter) : + _libraryManager.RootFolder.GetRecursiveChildren(itemFilter); + + SetItemByNameInfo(item, dto, libraryItems.ToList(), user); + } + + FillSyncInfo(dto, item, itemIdsWithSyncJobs, options); + + list.Add(dto); + } + + return list; + } + public BaseItemDto GetBaseItemDto(BaseItem item, DtoOptions options, User user = null, BaseItem owner = null) { var dto = GetBaseItemDtoInternal(item, options, user, owner); @@ -85,18 +120,81 @@ namespace MediaBrowser.Server.Implementations.Dto if (byName != null && !(item is LiveTvChannel)) { + var itemFilter = byName.GetItemFilter(); + var libraryItems = user != null ? - user.RootFolder.GetRecursiveChildren(user) : - _libraryManager.RootFolder.RecursiveChildren; + user.RootFolder.GetRecursiveChildren(user, itemFilter) : + _libraryManager.RootFolder.GetRecursiveChildren(itemFilter); - SetItemByNameInfo(item, dto, byName.GetTaggedItems(libraryItems).ToList(), user); + SetItemByNameInfo(item, dto, libraryItems.ToList(), user); return dto; } + FillSyncInfo(dto, item, options); + return dto; } + private IEnumerable<string> GetItemIdsWithSyncJobs(DtoOptions options) + { + if (!options.Fields.Contains(ItemFields.SyncInfo)) + { + return new List<string>(); + } + + var deviceId = options.DeviceId; + if (string.IsNullOrWhiteSpace(deviceId)) + { + return new List<string>(); + } + + var caps = _deviceManager().GetCapabilities(deviceId); + if (caps == null || !caps.SupportsSync) + { + return new List<string>(); + } + + var result = _syncManager.GetLibraryItemIds(new SyncJobItemQuery + { + TargetId = deviceId, + Statuses = new List<SyncJobItemStatus> + { + SyncJobItemStatus.Converting, + SyncJobItemStatus.Queued, + SyncJobItemStatus.Transferring + } + }); + + return result.Items; + } + + private void FillSyncInfo(BaseItemDto dto, BaseItem item, DtoOptions options) + { + if (options.Fields.Contains(ItemFields.SyncInfo)) + { + dto.SupportsSync = _syncManager.SupportsSync(item); + } + + if (dto.SupportsSync ?? false) + { + dto.HasSyncJob = GetItemIdsWithSyncJobs(options).Contains(dto.Id, StringComparer.OrdinalIgnoreCase); + } + } + + private void FillSyncInfo(BaseItemDto dto, BaseItem item, IEnumerable<string> itemIdsWithSyncJobs, DtoOptions options) + { + if (options.Fields.Contains(ItemFields.SyncInfo)) + { + dto.SupportsSync = _syncManager.SupportsSync(item); + } + + if (dto.SupportsSync ?? false) + { + dto.HasSyncJob = itemIdsWithSyncJobs.Contains(dto.Id, StringComparer.OrdinalIgnoreCase); + } + } + private BaseItemDto GetBaseItemDtoInternal(BaseItem item, DtoOptions options, User user = null, BaseItem owner = null) { var fields = options.Fields; @@ -167,11 +265,6 @@ namespace MediaBrowser.Server.Implementations.Dto AttachBasicFields(dto, item, owner, options); - if (fields.Contains(ItemFields.SyncInfo)) - { - dto.SupportsSync = _syncManager.SupportsSync(item); - } - if (fields.Contains(ItemFields.SoundtrackIds)) { var hasSoundtracks = item as IHasSoundtracks; @@ -368,9 +461,8 @@ namespace MediaBrowser.Server.Implementations.Dto if (!string.IsNullOrEmpty(item.Album)) { var parentAlbum = _libraryManager.RootFolder - .GetRecursiveChildren() - .Where(i => i is MusicAlbum) - .FirstOrDefault(i => string.Equals(i.Name, item.Album, StringComparison.OrdinalIgnoreCase)); + .GetRecursiveChildren(i => i is MusicAlbum && string.Equals(i.Name, item.Album, StringComparison.OrdinalIgnoreCase)) + .FirstOrDefault(); if (parentAlbum != null) { @@ -1029,7 +1121,7 @@ namespace MediaBrowser.Server.Implementations.Dto //if (fields.Contains(ItemFields.MediaSourceCount)) //{ - // Songs always have one + // Songs always have one //} } @@ -1140,7 +1232,7 @@ namespace MediaBrowser.Server.Implementations.Dto dto.AbsoluteEpisodeNumber = episode.AbsoluteEpisodeNumber; } - //if (fields.Contains(ItemFields.SpecialEpisodeNumbers)) + if (fields.Contains(ItemFields.SpecialEpisodeNumbers)) { dto.AirsAfterSeasonNumber = episode.AirsAfterSeasonNumber; dto.AirsBeforeEpisodeNumber = episode.AirsBeforeEpisodeNumber; @@ -1302,7 +1394,7 @@ namespace MediaBrowser.Server.Implementations.Dto { linkedChildren = user == null ? folder.GetRecursiveChildren().ToList() - : folder.GetRecursiveChildren(user, true).ToList(); + : folder.GetRecursiveChildren(user).ToList(); var parentWithBackdrop = linkedChildren.FirstOrDefault(i => i.GetImages(ImageType.Backdrop).Any()); @@ -1319,7 +1411,7 @@ namespace MediaBrowser.Server.Implementations.Dto { linkedChildren = user == null ? folder.GetRecursiveChildren().ToList() - : folder.GetRecursiveChildren(user, true).ToList(); + : folder.GetRecursiveChildren(user).ToList(); } var parentWithImage = linkedChildren.FirstOrDefault(i => i.GetImages(ImageType.Primary).Any()); @@ -1396,12 +1488,14 @@ namespace MediaBrowser.Server.Implementations.Dto if (season != null) { - children = season.GetEpisodes(user).Where(i => i.LocationType != LocationType.Virtual); + children = season + .GetEpisodes(user) + .Where(i => i.LocationType != LocationType.Virtual); } else { - children = folder.GetRecursiveChildren(user) - .Where(i => !i.IsFolder && i.LocationType != LocationType.Virtual); + children = folder + .GetRecursiveChildren(user, i => !i.IsFolder && i.LocationType != LocationType.Virtual); } // Loop through each recursive child @@ -1449,7 +1543,6 @@ namespace MediaBrowser.Server.Implementations.Dto dto.RecursiveItemCount = recursiveItemCount; dto.UserData.UnplayedItemCount = unplayed; - dto.RecursiveUnplayedItemCount = unplayed; if (recursiveItemCount > 0) { @@ -1507,7 +1600,10 @@ namespace MediaBrowser.Server.Implementations.Dto if (fields.Contains(ItemFields.OriginalPrimaryImageAspectRatio)) { - dto.OriginalPrimaryImageAspectRatio = size.Width / size.Height; + if (size.Width > 0 && size.Height > 0) + { + dto.OriginalPrimaryImageAspectRatio = size.Width / size.Height; + } } var supportedEnhancers = _imageProcessor.GetSupportedEnhancers(item, ImageType.Primary).ToList(); @@ -1524,7 +1620,10 @@ namespace MediaBrowser.Server.Implementations.Dto } } - dto.PrimaryImageAspectRatio = size.Width / size.Height; + if (size.Width > 0 && size.Height > 0) + { + dto.PrimaryImageAspectRatio = size.Width / size.Height; + } } } } diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index e32068905..5c69db3e1 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -5,6 +5,7 @@ using MediaBrowser.Model.Logging; using Mono.Nat; using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Text; using System.Threading; @@ -17,30 +18,44 @@ namespace MediaBrowser.Server.Implementations.EntryPoints private readonly ILogger _logger; private readonly IServerConfigurationManager _config; - private bool _isStarted; - private Timer _timer; + private bool _isStarted; public ExternalPortForwarding(ILogManager logmanager, IServerApplicationHost appHost, IServerConfigurationManager config) { _logger = logmanager.GetLogger("PortMapper"); _appHost = appHost; _config = config; + } - _config.ConfigurationUpdated += _config_ConfigurationUpdated; + private string _lastConfigIdentifier; + private string GetConfigIdentifier() + { + var values = new List<string>(); + var config = _config.Configuration; + + values.Add(config.EnableUPnP.ToString()); + values.Add(config.PublicPort.ToString(CultureInfo.InvariantCulture)); + values.Add(_appHost.HttpPort.ToString(CultureInfo.InvariantCulture)); + values.Add(_appHost.HttpsPort.ToString(CultureInfo.InvariantCulture)); + values.Add(config.EnableHttps.ToString()); + values.Add(_appHost.EnableHttps.ToString()); + + return string.Join("|", values.ToArray()); } void _config_ConfigurationUpdated(object sender, EventArgs e) { - var enable = _config.Configuration.EnableUPnP; - - if (enable && !_isStarted) - { - Reload(); - } - else if (!enable && _isStarted) + _config.ConfigurationUpdated -= _config_ConfigurationUpdated; + + if (!string.Equals(_lastConfigIdentifier, GetConfigIdentifier(), StringComparison.OrdinalIgnoreCase)) { - DisposeNat(); + if (_isStarted) + { + DisposeNat(); + } + + Run(); } } @@ -48,31 +63,36 @@ namespace MediaBrowser.Server.Implementations.EntryPoints { //NatUtility.Logger = new LogWriter(_logger); - Reload(); + if (_config.Configuration.EnableUPnP) + { + Start(); + } + + _config.ConfigurationUpdated -= _config_ConfigurationUpdated; + _config.ConfigurationUpdated += _config_ConfigurationUpdated; } - private void Reload() + private void Start() { - if (_config.Configuration.EnableUPnP) - { - _logger.Debug("Starting NAT discovery"); + _logger.Debug("Starting NAT discovery"); - NatUtility.DeviceFound += NatUtility_DeviceFound; + NatUtility.DeviceFound += NatUtility_DeviceFound; - // Mono.Nat does never rise this event. The event is there however it is useless. - // You could remove it with no risk. - NatUtility.DeviceLost += NatUtility_DeviceLost; + // Mono.Nat does never rise this event. The event is there however it is useless. + // You could remove it with no risk. + NatUtility.DeviceLost += NatUtility_DeviceLost; - // it is hard to say what one should do when an unhandled exception is raised - // because there isn't anything one can do about it. Probably save a log or ignored it. - NatUtility.UnhandledException += NatUtility_UnhandledException; - NatUtility.StartDiscovery(); + // it is hard to say what one should do when an unhandled exception is raised + // because there isn't anything one can do about it. Probably save a log or ignored it. + NatUtility.UnhandledException += NatUtility_UnhandledException; + NatUtility.StartDiscovery(); - _isStarted = true; + _timer = new Timer(s => _createdRules = new List<string>(), null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5)); - _timer = new Timer(s => _createdRules = new List<string>(), null, TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10)); - } + _lastConfigIdentifier = GetConfigIdentifier(); + + _isStarted = true; } void NatUtility_UnhandledException(object sender, UnhandledExceptionEventArgs e) @@ -124,9 +144,8 @@ namespace MediaBrowser.Server.Implementations.EntryPoints { _createdRules.Add(address); - var info = _appHost.GetSystemInfo(); - - CreatePortMap(device, info.HttpServerPortNumber, _config.Configuration.PublicPort); + CreatePortMap(device, _appHost.HttpPort, _config.Configuration.PublicPort); + CreatePortMap(device, _appHost.HttpsPort, _config.Configuration.PublicHttpsPort); } } @@ -136,7 +155,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints device.CreatePortMap(new Mapping(Protocol.Tcp, privatePort, publicPort) { - Description = "Media Browser Server" + Description = _appHost.Name }); } diff --git a/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs b/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs index e6976c54b..dd5dc82e8 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs @@ -245,7 +245,8 @@ namespace MediaBrowser.Server.Implementations.EntryPoints var collections = user.RootFolder.GetChildren(user, true).ToList(); - var allRecursiveChildren = user.RootFolder.GetRecursiveChildren(user) + var allRecursiveChildren = user.RootFolder + .GetRecursiveChildren(user) .Select(i => i.Id) .Distinct() .ToDictionary(i => i); diff --git a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs index 2d824f36c..37bca4ddb 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs @@ -3,6 +3,7 @@ using MediaBrowser.Common.Plugins; using MediaBrowser.Common.ScheduledTasks; using MediaBrowser.Common.Updates; using MediaBrowser.Controller; +using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; @@ -44,8 +45,9 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications private readonly object _libraryChangedSyncLock = new object(); private readonly IConfigurationManager _config; + private readonly IDeviceManager _deviceManager; - public Notifications(IInstallationManager installationManager, IUserManager userManager, ILogger logger, ITaskManager taskManager, INotificationManager notificationManager, ILibraryManager libraryManager, ISessionManager sessionManager, IServerApplicationHost appHost, IConfigurationManager config) + public Notifications(IInstallationManager installationManager, IUserManager userManager, ILogger logger, ITaskManager taskManager, INotificationManager notificationManager, ILibraryManager libraryManager, ISessionManager sessionManager, IServerApplicationHost appHost, IConfigurationManager config, IDeviceManager deviceManager) { _installationManager = installationManager; _userManager = userManager; @@ -56,6 +58,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications _sessionManager = sessionManager; _appHost = appHost; _config = config; + _deviceManager = deviceManager; } public void Run() @@ -74,6 +77,21 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications _appHost.HasPendingRestartChanged += _appHost_HasPendingRestartChanged; _appHost.HasUpdateAvailableChanged += _appHost_HasUpdateAvailableChanged; _appHost.ApplicationUpdated += _appHost_ApplicationUpdated; + _deviceManager.CameraImageUploaded +=_deviceManager_CameraImageUploaded; + } + + async void _deviceManager_CameraImageUploaded(object sender, GenericEventArgs<CameraImageUploadInfo> e) + { + var type = NotificationType.CameraImageUploaded.ToString(); + + var notification = new NotificationRequest + { + NotificationType = type + }; + + notification.Variables["DeviceName"] = e.Argument.Device.Name; + + await SendNotification(notification).ConfigureAwait(false); } async void _appHost_ApplicationUpdated(object sender, GenericEventArgs<PackageVersionInfo> e) @@ -451,6 +469,8 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications _appHost.HasPendingRestartChanged -= _appHost_HasPendingRestartChanged; _appHost.HasUpdateAvailableChanged -= _appHost_HasUpdateAvailableChanged; _appHost.ApplicationUpdated -= _appHost_ApplicationUpdated; + + _deviceManager.CameraImageUploaded -= _deviceManager_CameraImageUploaded; } private void DisposeLibraryUpdateTimer() diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ServerEventNotifier.cs b/MediaBrowser.Server.Implementations/EntryPoints/ServerEventNotifier.cs index 1eb4a6655..51e6ddc0e 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/ServerEventNotifier.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/ServerEventNotifier.cs @@ -2,13 +2,14 @@ using MediaBrowser.Common.ScheduledTasks; using MediaBrowser.Common.Updates; using MediaBrowser.Controller; -using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Session; +using MediaBrowser.Controller.Sync; using MediaBrowser.Model.Events; +using MediaBrowser.Model.Sync; using System; using System.Threading; @@ -44,29 +45,18 @@ namespace MediaBrowser.Server.Implementations.EntryPoints /// </summary> private readonly ITaskManager _taskManager; - private readonly IDtoService _dtoService; - private readonly ISessionManager _sessionManager; + private readonly ISyncManager _syncManager; - /// <summary> - /// Initializes a new instance of the <see cref="ServerEventNotifier" /> class. - /// </summary> - /// <param name="serverManager">The server manager.</param> - /// <param name="appHost">The application host.</param> - /// <param name="userManager">The user manager.</param> - /// <param name="installationManager">The installation manager.</param> - /// <param name="taskManager">The task manager.</param> - /// <param name="dtoService">The dto service.</param> - /// <param name="sessionManager">The session manager.</param> - public ServerEventNotifier(IServerManager serverManager, IServerApplicationHost appHost, IUserManager userManager, IInstallationManager installationManager, ITaskManager taskManager, IDtoService dtoService, ISessionManager sessionManager) + public ServerEventNotifier(IServerManager serverManager, IServerApplicationHost appHost, IUserManager userManager, IInstallationManager installationManager, ITaskManager taskManager, ISessionManager sessionManager, ISyncManager syncManager) { _serverManager = serverManager; _userManager = userManager; _installationManager = installationManager; _appHost = appHost; _taskManager = taskManager; - _dtoService = dtoService; _sessionManager = sessionManager; + _syncManager = syncManager; } public void Run() @@ -84,13 +74,12 @@ namespace MediaBrowser.Server.Implementations.EntryPoints _installationManager.PackageInstallationFailed += _installationManager_PackageInstallationFailed; _taskManager.TaskCompleted += _taskManager_TaskCompleted; + _syncManager.SyncJobCreated += _syncManager_SyncJobCreated; } - void _userManager_UserConfigurationUpdated(object sender, GenericEventArgs<User> e) + void _syncManager_SyncJobCreated(object sender, GenericEventArgs<SyncJobCreationResult> e) { - var dto = _userManager.GetUserDto(e.Argument); - - _serverManager.SendWebSocketMessage("UserConfigurationUpdated", dto); + _sessionManager.SendMessageToUserDeviceSessions(e.Argument.Job.TargetId, "SyncJobCreated", e.Argument, CancellationToken.None); } void _installationManager_PackageInstalling(object sender, InstallationEventArgs e) @@ -146,8 +135,8 @@ namespace MediaBrowser.Server.Implementations.EntryPoints void userManager_UserUpdated(object sender, GenericEventArgs<User> e) { var dto = _userManager.GetUserDto(e.Argument); - - _serverManager.SendWebSocketMessage("UserUpdated", dto); + + SendMessageToUserSession(e.Argument, "UserUpdated", dto); } /// <summary> @@ -157,7 +146,19 @@ namespace MediaBrowser.Server.Implementations.EntryPoints /// <param name="e">The e.</param> void userManager_UserDeleted(object sender, GenericEventArgs<User> e) { - _serverManager.SendWebSocketMessage("UserDeleted", e.Argument.Id.ToString("N")); + SendMessageToUserSession(e.Argument, "UserDeleted", e.Argument.Id.ToString("N")); + } + + void _userManager_UserConfigurationUpdated(object sender, GenericEventArgs<User> e) + { + var dto = _userManager.GetUserDto(e.Argument); + + SendMessageToUserSession(e.Argument, "UserConfigurationUpdated", dto); + } + + private async void SendMessageToUserSession<T>(User user, string name, T data) + { + await _sessionManager.SendMessageToUserSessions(user.Id.ToString("N"), name, data, CancellationToken.None); } /// <summary> @@ -187,6 +188,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints _installationManager.PackageInstallationFailed -= _installationManager_PackageInstallationFailed; _appHost.HasPendingRestartChanged -= kernel_HasPendingRestartChanged; + _syncManager.SyncJobCreated -= _syncManager_SyncJobCreated; } } } diff --git a/MediaBrowser.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs b/MediaBrowser.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs index c31f46215..ccd427a47 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs @@ -108,7 +108,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints { var userId = pair.Key; var userSessions = _sessionManager.Sessions - .Where(u => u.UserId.HasValue && u.UserId.Value == userId && u.SessionController != null && u.IsActive) + .Where(u => u.ContainsUser(userId) && u.SessionController != null && u.IsActive) .ToList(); if (userSessions.Count > 0) diff --git a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs index 611f887ee..10e50e497 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs @@ -17,6 +17,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Server.Implementations.Library; +using MediaBrowser.Server.Implementations.Logging; namespace MediaBrowser.Server.Implementations.FileOrganization { @@ -57,7 +58,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization }; var namingOptions = ((LibraryManager) _libraryManager).GetNamingOptions(); - var resolver = new Naming.TV.EpisodeResolver(namingOptions, new Naming.Logging.NullLogger()); + var resolver = new Naming.TV.EpisodeResolver(namingOptions, new PatternsLogger()); var episodeInfo = resolver.Resolve(path, FileInfoType.File) ?? new Naming.TV.EpisodeInfo(); @@ -209,7 +210,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization try { - File.Delete(path); + _fileSystem.DeleteFile(path); } catch (IOException ex) { @@ -225,7 +226,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization private List<string> GetOtherDuplicatePaths(string targetPath, Series series, int seasonNumber, int episodeNumber, int? endingEpisodeNumber) { - var episodePaths = series.RecursiveChildren + var episodePaths = series.GetRecursiveChildren() .OfType<Episode>() .Where(i => { @@ -315,7 +316,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization { try { - File.Delete(result.OriginalPath); + _fileSystem.DeleteFile(result.OriginalPath); } catch (Exception ex) { @@ -334,8 +335,8 @@ namespace MediaBrowser.Server.Implementations.FileOrganization result.ExtractedName = nameWithoutYear; result.ExtractedYear = yearInName; - return _libraryManager.RootFolder.RecursiveChildren - .OfType<Series>() + return _libraryManager.RootFolder.GetRecursiveChildren(i => i is Series) + .Cast<Series>() .Select(i => NameUtils.GetMatchScore(nameWithoutYear, yearInName, i)) .Where(i => i.Item2 > 0) .OrderByDescending(i => i.Item2) @@ -399,9 +400,8 @@ namespace MediaBrowser.Server.Implementations.FileOrganization { // If there's already a season folder, use that var season = series - .RecursiveChildren - .OfType<Season>() - .FirstOrDefault(i => i.LocationType == LocationType.FileSystem && i.IndexNumber.HasValue && i.IndexNumber.Value == seasonNumber); + .GetRecursiveChildren(i => i is Season && i.LocationType == LocationType.FileSystem && i.IndexNumber.HasValue && i.IndexNumber.Value == seasonNumber) + .FirstOrDefault(); if (season != null) { diff --git a/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs b/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs index 7c5269678..a6116ab09 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs @@ -85,7 +85,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization _logger.Info("Requested to delete {0}", result.OriginalPath); try { - File.Delete(result.OriginalPath); + _fileSystem.DeleteFile(result.OriginalPath); } catch (Exception ex) { diff --git a/MediaBrowser.Server.Implementations/FileOrganization/NameUtils.cs b/MediaBrowser.Server.Implementations/FileOrganization/NameUtils.cs index d50696d81..624133d4f 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/NameUtils.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/NameUtils.cs @@ -1,4 +1,4 @@ -using MediaBrowser.Common.Extensions; +using MediaBrowser.Model.Extensions; using MediaBrowser.Controller.Entities; using System; using System.Globalization; @@ -54,9 +54,6 @@ namespace MediaBrowser.Server.Implementations.FileOrganization private static string GetComparableName(string name) { - // TODO: Improve this - should ignore spaces, periods, underscores, most likely all symbols and - // possibly remove sorting words like "the", "and", etc. - name = RemoveDiacritics(name); name = " " + name + " "; diff --git a/MediaBrowser.Server.Implementations/FileOrganization/OrganizerScheduledTask.cs b/MediaBrowser.Server.Implementations/FileOrganization/OrganizerScheduledTask.cs index 8dfdfdaec..f993e1fc3 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/OrganizerScheduledTask.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/OrganizerScheduledTask.cs @@ -13,7 +13,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.FileOrganization { - public class OrganizerScheduledTask : IScheduledTask, IConfigurableScheduledTask, IScheduledTaskActivityLog + public class OrganizerScheduledTask : IScheduledTask, IConfigurableScheduledTask, IScheduledTaskActivityLog, IHasKey { private readonly ILibraryMonitor _libraryMonitor; private readonly ILibraryManager _libraryManager; @@ -54,10 +54,13 @@ namespace MediaBrowser.Server.Implementations.FileOrganization return _config.GetAutoOrganizeOptions().TvOptions; } - public Task Execute(CancellationToken cancellationToken, IProgress<double> progress) + public async Task Execute(CancellationToken cancellationToken, IProgress<double> progress) { - return new TvFolderOrganizer(_libraryManager, _logger, _fileSystem, _libraryMonitor, _organizationService, _config, _providerManager) - .Organize(GetTvOptions(), cancellationToken, progress); + if (GetTvOptions().IsEnabled) + { + await new TvFolderOrganizer(_libraryManager, _logger, _fileSystem, _libraryMonitor, _organizationService, _config, _providerManager) + .Organize(GetTvOptions(), cancellationToken, progress).ConfigureAwait(false); + } } public IEnumerable<ITaskTrigger> GetDefaultTriggers() @@ -82,5 +85,10 @@ namespace MediaBrowser.Server.Implementations.FileOrganization { get { return false; } } + + public string Key + { + get { return "AutoOrganize"; } + } } } diff --git a/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs index cf120f147..e3c8e6d25 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs @@ -166,7 +166,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization { try { - File.Delete(file.FullName); + _fileSystem.DeleteFile(file.FullName); } catch (Exception ex) { diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index c3228db92..f64e29e4d 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -3,7 +3,6 @@ using MediaBrowser.Common; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Net; using MediaBrowser.Model.Logging; -using MediaBrowser.Server.Implementations.HttpServer.NetListener; using MediaBrowser.Server.Implementations.HttpServer.SocketSharp; using ServiceStack; using ServiceStack.Api.Swagger; @@ -24,7 +23,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer { public class HttpListenerHost : ServiceStackHost, IHttpServer { - private string HandlerPath { get; set; } private string DefaultRedirectPath { get; set; } private readonly ILogger _logger; @@ -42,7 +40,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer private readonly ReaderWriterLockSlim _localEndpointLock = new ReaderWriterLockSlim(); - private readonly bool _supportsNativeWebSocket; + public string CertificatePath { get; private set; } /// <summary> /// Gets the local end points. @@ -62,18 +60,14 @@ namespace MediaBrowser.Server.Implementations.HttpServer } } - public HttpListenerHost(IApplicationHost applicationHost, - ILogManager logManager, - string serviceName, - string handlerPath, - string defaultRedirectPath, - bool supportsNativeWebSocket, + public HttpListenerHost(IApplicationHost applicationHost, + ILogManager logManager, + string serviceName, + string defaultRedirectPath, params Assembly[] assembliesWithServices) : base(serviceName, assembliesWithServices) { DefaultRedirectPath = defaultRedirectPath; - _supportsNativeWebSocket = supportsNativeWebSocket; - HandlerPath = handlerPath; _logger = logManager.GetLogger("HttpServer"); @@ -134,13 +128,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer { base.OnConfigLoad(); - Config.HandlerFactoryPath = string.IsNullOrEmpty(HandlerPath) - ? null - : HandlerPath; + Config.HandlerFactoryPath = null; - Config.MetadataRedirectPath = string.IsNullOrEmpty(HandlerPath) - ? "metadata" - : PathUtils.CombinePaths(HandlerPath, "metadata"); + Config.MetadataRedirectPath = "metadata"; } protected override ServiceController CreateServiceController(params Assembly[] assembliesWithServices) @@ -215,12 +205,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer private IHttpListener GetListener() { - if (_supportsNativeWebSocket && NativeWebSocket.IsSupported) - { - return new HttpListenerServer(_logger, OnRequestReceived); - } - - return new WebSocketSharpListener(_logger, OnRequestReceived); + return new WebSocketSharpListener(_logger, OnRequestReceived, CertificatePath); } private void WebSocketHandler(WebSocketConnectEventArgs args) @@ -241,7 +226,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer { return; } - + var errorResponse = new ErrorResponse { ResponseStatus = new ResponseStatus @@ -310,24 +295,24 @@ namespace MediaBrowser.Server.Implementations.HttpServer var operationName = httpReq.OperationName; var localPath = url.LocalPath; - if (string.Equals(localPath, "/" + HandlerPath + "/", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(localPath, "/mediabrowser/", StringComparison.OrdinalIgnoreCase)) { - httpRes.RedirectToUrl(DefaultRedirectPath); + httpRes.RedirectToUrl("/../" + DefaultRedirectPath); return Task.FromResult(true); } - if (string.Equals(localPath, "/" + HandlerPath, StringComparison.OrdinalIgnoreCase)) + if (string.Equals(localPath, "/mediabrowser", StringComparison.OrdinalIgnoreCase)) { - httpRes.RedirectToUrl(HandlerPath + "/" + DefaultRedirectPath); + httpRes.RedirectToUrl("../" + DefaultRedirectPath); return Task.FromResult(true); } if (string.Equals(localPath, "/", StringComparison.OrdinalIgnoreCase)) { - httpRes.RedirectToUrl(HandlerPath + "/" + DefaultRedirectPath); + httpRes.RedirectToUrl(DefaultRedirectPath); return Task.FromResult(true); } if (string.IsNullOrEmpty(localPath)) { - httpRes.RedirectToUrl("/" + HandlerPath + "/" + DefaultRedirectPath); + httpRes.RedirectToUrl("/" + DefaultRedirectPath); return Task.FromResult(true); } @@ -382,12 +367,33 @@ namespace MediaBrowser.Server.Implementations.HttpServer base.Init(); } - //public override RouteAttribute[] GetRouteAttributes(System.Type requestType) - //{ - // var routes = base.GetRouteAttributes(requestType); - // routes.Each(x => x.Path = "/api" + x.Path); - // return routes; - //} + public override RouteAttribute[] GetRouteAttributes(Type requestType) + { + var routes = base.GetRouteAttributes(requestType).ToList(); + var clone = routes.ToList(); + + foreach (var route in clone) + { + routes.Add(new RouteAttribute(NormalizeRoutePath(route.Path), route.Verbs) + { + Notes = route.Notes, + Priority = route.Priority, + Summary = route.Summary + }); + } + + return routes.ToArray(); + } + + private string NormalizeRoutePath(string path) + { + if (path.StartsWith("/", StringComparison.OrdinalIgnoreCase)) + { + return "/mediabrowser" + path; + } + + return "mediabrowser/" + path; + } /// <summary> /// Releases the specified instance. @@ -425,8 +431,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer GC.SuppressFinalize(this); } - public void StartServer(IEnumerable<string> urlPrefixes) + public void StartServer(IEnumerable<string> urlPrefixes, string certificatePath) { + CertificatePath = certificatePath; UrlPrefixes = urlPrefixes.ToList(); Start(UrlPrefixes.First()); } diff --git a/MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs b/MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs index b48703a15..d1222ab74 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs @@ -16,20 +16,16 @@ namespace MediaBrowser.Server.Implementations.HttpServer /// <param name="applicationHost">The application host.</param> /// <param name="logManager">The log manager.</param> /// <param name="serverName">Name of the server.</param> - /// <param name="handlerPath">The handler path.</param> /// <param name="defaultRedirectpath">The default redirectpath.</param> - /// <param name="supportsNativeWebSocket">if set to <c>true</c> [supports native web socket].</param> /// <returns>IHttpServer.</returns> public static IHttpServer CreateServer(IApplicationHost applicationHost, ILogManager logManager, string serverName, - string handlerPath, - string defaultRedirectpath, - bool supportsNativeWebSocket) + string defaultRedirectpath) { LogManager.LogFactory = new ServerLogFactory(logManager); - return new HttpListenerHost(applicationHost, logManager, serverName, handlerPath, defaultRedirectpath, supportsNativeWebSocket); + return new HttpListenerHost(applicationHost, logManager, serverName, defaultRedirectpath); } } } diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/RequestMono.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/RequestMono.cs index 226d97b3c..2c8413f5e 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/RequestMono.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/RequestMono.cs @@ -556,31 +556,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp return (stream); } } - - public void SaveAs(string filename) - { - byte[] buffer = new byte[16 * 1024]; - long old_post = stream.Position; - - try - { - File.Delete(filename); - using (FileStream fs = File.Create(filename)) - { - stream.Position = 0; - int n; - - while ((n = stream.Read(buffer, 0, 16 * 1024)) != 0) - { - fs.Write(buffer, 0, n); - } - } - } - finally - { - stream.Position = old_post; - } - } } class Helpers diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs index 419d145bb..0c5c9e9bf 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs @@ -1,13 +1,14 @@ using MediaBrowser.Controller.Net; using MediaBrowser.Model.Logging; +using MediaBrowser.Server.Implementations.Logging; using ServiceStack; using ServiceStack.Web; +using SocketHttpListener.Net; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; -using SocketHttpListener.Net; namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp { @@ -17,11 +18,14 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp private readonly ILogger _logger; private readonly Action<string> _endpointListener; + private readonly string _certificatePath ; - public WebSocketSharpListener(ILogger logger, Action<string> endpointListener) + public WebSocketSharpListener(ILogger logger, Action<string> endpointListener, + string certificatePath) { _logger = logger; _endpointListener = endpointListener; + _certificatePath = certificatePath; } public Action<Exception, IRequest> ErrorHandler { get; set; } @@ -33,7 +37,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp public void Start(IEnumerable<string> urlPrefixes) { if (_listener == null) - _listener = new HttpListener(new SocketSharpLogger(_logger)); + _listener = new HttpListener(new PatternsLogger(_logger), _certificatePath); foreach (var prefix in urlPrefixes) { diff --git a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs index ce6224295..d501d1210 100644 --- a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs +++ b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs @@ -566,7 +566,10 @@ namespace MediaBrowser.Server.Implementations.IO .Distinct() .ToList(); - foreach (var p in paths) Logger.Info(p + " reports change."); + foreach (var p in paths) + { + Logger.Info(p + " reports change."); + } // If the root folder changed, run the library task so the user can see it if (itemsToRefresh.Any(i => i is AggregateFolder)) diff --git a/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs b/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs index a113e8d5e..2af6e5588 100644 --- a/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs +++ b/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs @@ -67,29 +67,26 @@ namespace MediaBrowser.Server.Implementations.Intros ? null : _localization.GetRatingLevel(item.OfficialRating); - var libaryItems = user.RootFolder.GetRecursiveChildren(user, false) - .ToList(); - var random = new Random(Environment.TickCount + Guid.NewGuid().GetHashCode()); var candidates = new List<ItemWithTrailer>(); if (config.EnableIntrosFromMoviesInLibrary) { - var itemsWithTrailers = libaryItems - .Where(i => - { - var hasTrailers = i as IHasTrailers; - - if (hasTrailers != null && hasTrailers.LocalTrailerIds.Count > 0) - { - if (i is Movie) - { - return !IsDuplicate(item, i); - } - } - return false; - }); + var itemsWithTrailers = user.RootFolder + .GetRecursiveChildren(user, i => + { + var hasTrailers = i as IHasTrailers; + + if (hasTrailers != null && hasTrailers.LocalTrailerIds.Count > 0) + { + if (i is Movie) + { + return !IsDuplicate(item, i); + } + } + return false; + }); candidates.AddRange(itemsWithTrailers.Select(i => new ItemWithTrailer { @@ -141,15 +138,16 @@ namespace MediaBrowser.Server.Implementations.Intros })); } + return GetResult(item, candidates, config, ratingLevel); + } + + private IEnumerable<IntroInfo> GetResult(BaseItem item, IEnumerable<ItemWithTrailer> candidates, CinemaModeConfiguration config, int? ratingLevel) + { var customIntros = !string.IsNullOrWhiteSpace(config.CustomIntroPath) ? GetCustomIntros(item) : new List<IntroInfo>(); var trailerLimit = config.TrailerLimit; - if (customIntros.Count > 0) - { - trailerLimit--; - } // Avoid implicitly captured closure return candidates.Where(i => diff --git a/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs b/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs index 1771bbdb2..db4910c52 100644 --- a/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs +++ b/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs @@ -1,4 +1,4 @@ -using MediaBrowser.Common.Extensions; +using MediaBrowser.Model.Extensions; using MediaBrowser.Common.IO; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index ab72d89fd..d7ea444a3 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -13,7 +13,6 @@ using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Resolvers; using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Naming.Audio; @@ -22,6 +21,7 @@ using MediaBrowser.Naming.IO; using MediaBrowser.Naming.TV; using MediaBrowser.Naming.Video; using MediaBrowser.Server.Implementations.Library.Validators; +using MediaBrowser.Server.Implementations.Logging; using MediaBrowser.Server.Implementations.ScheduledTasks; using System; using System.Collections.Concurrent; @@ -218,11 +218,7 @@ namespace MediaBrowser.Server.Implementations.Library /// <summary> /// The _root folder sync lock /// </summary> - private object _rootFolderSyncLock = new object(); - /// <summary> - /// The _root folder initialized - /// </summary> - private bool _rootFolderInitialized; + private readonly object _rootFolderSyncLock = new object(); /// <summary> /// Gets the root folder. /// </summary> @@ -231,17 +227,17 @@ namespace MediaBrowser.Server.Implementations.Library { get { - LazyInitializer.EnsureInitialized(ref _rootFolder, ref _rootFolderInitialized, ref _rootFolderSyncLock, CreateRootFolder); - return _rootFolder; - } - private set - { - _rootFolder = value; - - if (value == null) + if (_rootFolder == null) { - _rootFolderInitialized = false; + lock (_rootFolderSyncLock) + { + if (_rootFolder == null) + { + _rootFolder = CreateRootFolder(); + } + } } + return _rootFolder; } } @@ -336,8 +332,8 @@ namespace MediaBrowser.Server.Implementations.Library /// <returns>Task.</returns> private async Task UpdateSeasonZeroNames(string newName, CancellationToken cancellationToken) { - var seasons = RootFolder.RecursiveChildren - .OfType<Season>() + var seasons = RootFolder.GetRecursiveChildren(i => i is Season) + .Cast<Season>() .Where(i => i.IndexNumber.HasValue && i.IndexNumber.Value == 0 && !string.Equals(i.Name, newName, StringComparison.Ordinal)) .ToList(); @@ -392,7 +388,7 @@ namespace MediaBrowser.Server.Implementations.Library var locationType = item.LocationType; var children = item.IsFolder - ? ((Folder)item).RecursiveChildren.ToList() + ? ((Folder)item).GetRecursiveChildren().ToList() : new List<BaseItem>(); foreach (var metadataPath in GetMetadataPaths(item, children)) @@ -401,11 +397,11 @@ namespace MediaBrowser.Server.Implementations.Library try { - Directory.Delete(metadataPath, true); + _fileSystem.DeleteDirectory(metadataPath, true); } catch (DirectoryNotFoundException) { - + } catch (Exception ex) { @@ -420,12 +416,12 @@ namespace MediaBrowser.Server.Implementations.Library if (Directory.Exists(path)) { _logger.Debug("Deleting path {0}", path); - Directory.Delete(path, true); + _fileSystem.DeleteDirectory(path, true); } else if (File.Exists(path)) { _logger.Debug("Deleting path {0}", path); - File.Delete(path); + _fileSystem.DeleteFile(path); } } @@ -577,12 +573,12 @@ namespace MediaBrowser.Server.Implementations.Library var fullPath = fileInfo.FullName; - if (string.IsNullOrWhiteSpace(collectionType)) + if (string.IsNullOrWhiteSpace(collectionType) && parent != null) { collectionType = GetContentTypeOverride(fullPath, true); } - var args = new ItemResolveArgs(ConfigurationManager.ApplicationPaths, this, directoryService) + var args = new ItemResolveArgs(ConfigurationManager.ApplicationPaths, directoryService) { Parent = parent, Path = fullPath, @@ -756,12 +752,14 @@ namespace MediaBrowser.Server.Implementations.Library Directory.CreateDirectory(userRootPath); - _userRootFolder = GetItemById(GetNewItemId(userRootPath, typeof(UserRootFolder))) as UserRootFolder; + var tmpItem = GetItemById(GetNewItemId(userRootPath, typeof(UserRootFolder))) as UserRootFolder; - if (_userRootFolder == null) + if (tmpItem == null) { - _userRootFolder = (UserRootFolder)ResolvePath(new DirectoryInfo(userRootPath)); + tmpItem = (UserRootFolder)ResolvePath(new DirectoryInfo(userRootPath)); } + + _userRootFolder = tmpItem; } } } @@ -841,13 +839,25 @@ namespace MediaBrowser.Server.Implementations.Library } /// <summary> + /// Gets the artists path. + /// </summary> + /// <value>The artists path.</value> + public string ArtistsPath + { + get + { + return Path.Combine(ConfigurationManager.ApplicationPaths.ItemsByNamePath, "artists"); + } + } + + /// <summary> /// Gets a Genre /// </summary> /// <param name="name">The name.</param> /// <returns>Task{Genre}.</returns> public MusicArtist GetArtist(string name) { - return GetItemByName<MusicArtist>(ConfigurationManager.ApplicationPaths.ArtistsPath, name); + return GetItemByName<MusicArtist>(ArtistsPath, name); } private T GetItemByName<T>(string path, string name) @@ -892,14 +902,6 @@ namespace MediaBrowser.Server.Implementations.Library return obj as T; } - /// <summary> - /// Creates an IBN item based on a given path - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="path">The path.</param> - /// <param name="name">The name.</param> - /// <returns>Task{``0}.</returns> - /// <exception cref="System.IO.IOException">Path not created: + path</exception> private T CreateItemByName<T>(string path, string name, Guid id) where T : BaseItem, new() { @@ -909,9 +911,10 @@ namespace MediaBrowser.Server.Implementations.Library { var validFilename = _fileSystem.GetValidFilename(name).Trim(); - var existing = RootFolder.RecursiveChildren - .OfType<T>() - .FirstOrDefault(i => string.Equals(_fileSystem.GetValidFilename(i.Name).Trim(), validFilename, StringComparison.OrdinalIgnoreCase)); + var existing = RootFolder + .GetRecursiveChildren(i => i is T && string.Equals(_fileSystem.GetValidFilename(i.Name).Trim(), validFilename, StringComparison.OrdinalIgnoreCase)) + .Cast<T>() + .FirstOrDefault(); if (existing != null) { @@ -925,7 +928,15 @@ namespace MediaBrowser.Server.Implementations.Library if (!fileInfo.Exists) { - fileInfo = Directory.CreateDirectory(path); + try + { + fileInfo = Directory.CreateDirectory(path); + } + catch (UnauthorizedAccessException ex) + { + _logger.Error("Error creating directory {0}", ex, path); + throw new Exception(string.Format("Error creating directory {0}", path), ex); + } isNew = true; } @@ -968,76 +979,6 @@ namespace MediaBrowser.Server.Implementations.Library } /// <summary> - /// Validates the artists. - /// </summary> - /// <param name="cancellationToken">The cancellation token.</param> - /// <param name="progress">The progress.</param> - /// <returns>Task.</returns> - public Task ValidateArtists(CancellationToken cancellationToken, IProgress<double> progress) - { - // Ensure the location is unavailable. - Directory.CreateDirectory(ConfigurationManager.ApplicationPaths.ArtistsPath); - - return new ArtistsValidator(this, _userManager, _logger).Run(progress, cancellationToken); - } - - /// <summary> - /// Validates the music genres. - /// </summary> - /// <param name="cancellationToken">The cancellation token.</param> - /// <param name="progress">The progress.</param> - /// <returns>Task.</returns> - public Task ValidateMusicGenres(CancellationToken cancellationToken, IProgress<double> progress) - { - // Ensure the location is unavailable. - Directory.CreateDirectory(ConfigurationManager.ApplicationPaths.MusicGenrePath); - - return new MusicGenresValidator(this, _logger).Run(progress, cancellationToken); - } - - /// <summary> - /// Validates the game genres. - /// </summary> - /// <param name="cancellationToken">The cancellation token.</param> - /// <param name="progress">The progress.</param> - /// <returns>Task.</returns> - public Task ValidateGameGenres(CancellationToken cancellationToken, IProgress<double> progress) - { - // Ensure the location is unavailable. - Directory.CreateDirectory(ConfigurationManager.ApplicationPaths.GameGenrePath); - - return new GameGenresValidator(this, _userManager, _logger).Run(progress, cancellationToken); - } - - /// <summary> - /// Validates the studios. - /// </summary> - /// <param name="cancellationToken">The cancellation token.</param> - /// <param name="progress">The progress.</param> - /// <returns>Task.</returns> - public Task ValidateStudios(CancellationToken cancellationToken, IProgress<double> progress) - { - // Ensure the location is unavailable. - Directory.CreateDirectory(ConfigurationManager.ApplicationPaths.StudioPath); - - return new StudiosValidator(this, _userManager, _logger).Run(progress, cancellationToken); - } - - /// <summary> - /// Validates the genres. - /// </summary> - /// <param name="cancellationToken">The cancellation token.</param> - /// <param name="progress">The progress.</param> - /// <returns>Task.</returns> - public Task ValidateGenres(CancellationToken cancellationToken, IProgress<double> progress) - { - // Ensure the location is unavailable. - Directory.CreateDirectory(ConfigurationManager.ApplicationPaths.GenrePath); - - return new GenresValidator(this, _userManager, _logger).Run(progress, cancellationToken); - } - - /// <summary> /// Reloads the root media folder /// </summary> /// <param name="progress">The progress.</param> @@ -1176,7 +1117,7 @@ namespace MediaBrowser.Server.Implementations.Library /// Gets the default view. /// </summary> /// <returns>IEnumerable{VirtualFolderInfo}.</returns> - public IEnumerable<VirtualFolderInfo> GetDefaultVirtualFolders() + public IEnumerable<VirtualFolderInfo> GetVirtualFolders() { return GetView(ConfigurationManager.ApplicationPaths.DefaultUserViewsPath); } @@ -1184,16 +1125,6 @@ namespace MediaBrowser.Server.Implementations.Library /// <summary> /// Gets the view. /// </summary> - /// <param name="user">The user.</param> - /// <returns>IEnumerable{VirtualFolderInfo}.</returns> - public IEnumerable<VirtualFolderInfo> GetVirtualFolders(User user) - { - return GetDefaultVirtualFolders(); - } - - /// <summary> - /// Gets the view. - /// </summary> /// <param name="path">The path.</param> /// <returns>IEnumerable{VirtualFolderInfo}.</returns> private IEnumerable<VirtualFolderInfo> GetView(string path) @@ -1637,7 +1568,7 @@ namespace MediaBrowser.Server.Implementations.Library CancellationToken cancellationToken) { var path = Path.Combine(ConfigurationManager.ApplicationPaths.ItemsByNamePath, - "views"); + "views"); path = Path.Combine(path, _fileSystem.GetValidFilename(type)); @@ -1708,7 +1639,7 @@ namespace MediaBrowser.Server.Implementations.Library var id = GetNewItemId("7_namedview_" + name + user.Id.ToString("N") + parentId, typeof(UserView)); - var path = BaseItem.GetInternalMetadataPathForId(id); + var path = Path.Combine(ConfigurationManager.ApplicationPaths.InternalMetadataPath, "views", "specialviews", id.ToString("N")); var item = GetItemById(id) as UserView; @@ -1754,7 +1685,7 @@ namespace MediaBrowser.Server.Implementations.Library public bool IsVideoFile(string path) { - var resolver = new VideoResolver(GetNamingOptions(), new Naming.Logging.NullLogger()); + var resolver = new VideoResolver(GetNamingOptions(), new PatternsLogger()); return resolver.IsVideoFile(path); } @@ -1772,7 +1703,7 @@ namespace MediaBrowser.Server.Implementations.Library public bool FillMissingEpisodeNumbersFromPath(Episode episode) { var resolver = new EpisodeResolver(GetNamingOptions(), - new Naming.Logging.NullLogger()); + new PatternsLogger()); var fileType = episode.VideoType == VideoType.BluRay || episode.VideoType == VideoType.Dvd || episode.VideoType == VideoType.HdDvd ? FileInfoType.Directory : @@ -1910,7 +1841,7 @@ namespace MediaBrowser.Server.Implementations.Library public ItemLookupInfo ParseName(string name) { - var resolver = new VideoResolver(GetNamingOptions(), new Naming.Logging.NullLogger()); + var resolver = new VideoResolver(GetNamingOptions(), new PatternsLogger()); var result = resolver.CleanDateTime(name); var cleanName = resolver.CleanString(result.Name); @@ -1929,7 +1860,7 @@ namespace MediaBrowser.Server.Implementations.Library .SelectMany(i => i.EnumerateFiles("*", SearchOption.TopDirectoryOnly)) .ToList(); - var videoListResolver = new VideoListResolver(GetNamingOptions(), new Naming.Logging.NullLogger()); + var videoListResolver = new VideoListResolver(GetNamingOptions(), new PatternsLogger()); var videos = videoListResolver.Resolve(fileSystemChildren.Select(i => new PortableFileInfo { @@ -1982,7 +1913,7 @@ namespace MediaBrowser.Server.Implementations.Library .SelectMany(i => i.EnumerateFiles("*", SearchOption.TopDirectoryOnly)) .ToList(); - var videoListResolver = new VideoListResolver(GetNamingOptions(), new Naming.Logging.NullLogger()); + var videoListResolver = new VideoListResolver(GetNamingOptions(), new PatternsLogger()); var videos = videoListResolver.Resolve(fileSystemChildren.Select(i => new PortableFileInfo { @@ -2020,7 +1951,7 @@ namespace MediaBrowser.Server.Implementations.Library private void SetExtraTypeFromFilename(Video item) { - var resolver = new ExtraResolver(GetNamingOptions(), new Naming.Logging.NullLogger(), new RegexProvider()); + var resolver = new ExtraResolver(GetNamingOptions(), new PatternsLogger(), new RegexProvider()); var result = resolver.GetExtraInfo(item.Path); diff --git a/MediaBrowser.Server.Implementations/Library/LocalTrailerPostScanTask.cs b/MediaBrowser.Server.Implementations/Library/LocalTrailerPostScanTask.cs index 9196bf734..b72406730 100644 --- a/MediaBrowser.Server.Implementations/Library/LocalTrailerPostScanTask.cs +++ b/MediaBrowser.Server.Implementations/Library/LocalTrailerPostScanTask.cs @@ -1,5 +1,4 @@ -using System.Collections.Generic; -using MediaBrowser.Controller.Channels; +using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Channels; @@ -25,8 +24,8 @@ namespace MediaBrowser.Server.Implementations.Library public async Task Run(IProgress<double> progress, CancellationToken cancellationToken) { var items = _libraryManager.RootFolder - .RecursiveChildren - .OfType<IHasTrailers>() + .GetRecursiveChildren(i => i is IHasTrailers) + .Cast<IHasTrailers>() .ToList(); var channelTrailerResult = await _channelManager.GetAllMediaInternal(new AllChannelMediaQuery diff --git a/MediaBrowser.Server.Implementations/Library/MusicManager.cs b/MediaBrowser.Server.Implementations/Library/MusicManager.cs index b8c29c19b..7733e7d37 100644 --- a/MediaBrowser.Server.Implementations/Library/MusicManager.cs +++ b/MediaBrowser.Server.Implementations/Library/MusicManager.cs @@ -32,8 +32,8 @@ namespace MediaBrowser.Server.Implementations.Library var artist = _libraryManager.GetArtist(name); var genres = user.RootFolder - .GetRecursiveChildren(user) - .OfType<Audio>() + .GetRecursiveChildren(user, i => i is Audio) + .Cast<Audio>() .Where(i => i.HasArtist(name)) .SelectMany(i => i.Genres) .Concat(artist.Genres) @@ -45,8 +45,8 @@ namespace MediaBrowser.Server.Implementations.Library public IEnumerable<Audio> GetInstantMixFromAlbum(MusicAlbum item, User user) { var genres = item - .GetRecursiveChildren(user, true) - .OfType<Audio>() + .GetRecursiveChildren(user, i => i is Audio) + .Cast<Audio>() .SelectMany(i => i.Genres) .Concat(item.Genres) .Distinct(StringComparer.OrdinalIgnoreCase); @@ -57,8 +57,8 @@ namespace MediaBrowser.Server.Implementations.Library public IEnumerable<Audio> GetInstantMixFromPlaylist(Playlist item, User user) { var genres = item - .GetRecursiveChildren(user, true) - .OfType<Audio>() + .GetRecursiveChildren(user, i => i is Audio) + .Cast<Audio>() .SelectMany(i => i.Genres) .Concat(item.Genres) .Distinct(StringComparer.OrdinalIgnoreCase); @@ -68,12 +68,13 @@ namespace MediaBrowser.Server.Implementations.Library public IEnumerable<Audio> GetInstantMixFromGenres(IEnumerable<string> genres, User user) { - var inputItems = user.RootFolder.GetRecursiveChildren(user); + var inputItems = user.RootFolder + .GetRecursiveChildren(user, i => i is Audio); var genresDictionary = genres.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase); return inputItems - .OfType<Audio>() + .Cast<Audio>() .Select(i => new Tuple<Audio, int>(i, i.Genres.Count(genresDictionary.ContainsKey))) .Where(i => i.Item2 > 0) .OrderByDescending(i => i.Item2) @@ -82,5 +83,40 @@ namespace MediaBrowser.Server.Implementations.Library .Take(100) .OrderBy(i => Guid.NewGuid()); } + + public IEnumerable<Audio> GetInstantMixFromItem(BaseItem item, User user) + { + var genre = item as MusicGenre; + if (genre != null) + { + return GetInstantMixFromGenres(new[] { item.Name }, user); + } + + var playlist = item as Playlist; + if (playlist != null) + { + return GetInstantMixFromPlaylist(playlist, user); + } + + var album = item as MusicAlbum; + if (album != null) + { + return GetInstantMixFromAlbum(album, user); + } + + var artist = item as MusicArtist; + if (artist != null) + { + return GetInstantMixFromArtist(artist.Name, user); + } + + var song = item as Audio; + if (song != null) + { + return GetInstantMixFromSong(song, user); + } + + return new Audio[] { }; + } } } diff --git a/MediaBrowser.Server.Implementations/Library/ResolverHelper.cs b/MediaBrowser.Server.Implementations/Library/ResolverHelper.cs index 03e28d7ba..b6a93408a 100644 --- a/MediaBrowser.Server.Implementations/Library/ResolverHelper.cs +++ b/MediaBrowser.Server.Implementations/Library/ResolverHelper.cs @@ -39,12 +39,6 @@ namespace MediaBrowser.Server.Implementations.Library item.Id = libraryManager.GetNewItemId(item.Path, item.GetType()); - // If the resolver didn't specify this - if (string.IsNullOrEmpty(item.DisplayMediaType)) - { - item.DisplayMediaType = item.GetType().Name; - } - item.IsLocked = item.Path.IndexOf("[dontfetchmeta]", StringComparison.OrdinalIgnoreCase) != -1 || item.Parents.Any(i => i.IsLocked); @@ -79,12 +73,6 @@ namespace MediaBrowser.Server.Implementations.Library item.Id = libraryManager.GetNewItemId(item.Path, item.GetType()); - // If the resolver didn't specify this - if (string.IsNullOrEmpty(item.DisplayMediaType)) - { - item.DisplayMediaType = item.GetType().Name; - } - // Make sure the item has a name EnsureName(item, args.FileInfo); diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs index 7c8ddabeb..0abdc4296 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs @@ -6,7 +6,7 @@ using MediaBrowser.Controller.Resolvers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Naming.Audio; -using MediaBrowser.Naming.Common; +using MediaBrowser.Server.Implementations.Logging; using System; using System.Collections.Generic; using System.IO; @@ -169,7 +169,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio { var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions(); - var parser = new AlbumParser(namingOptions, new Naming.Logging.NullLogger()); + var parser = new AlbumParser(namingOptions, new PatternsLogger()); var result = parser.ParseMultiPart(path); return result.IsMultiPart; diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs index 1a4d35af5..3333719b7 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs @@ -7,6 +7,7 @@ using MediaBrowser.Naming.Video; using System; using System.IO; using System.Linq; +using MediaBrowser.Server.Implementations.Logging; namespace MediaBrowser.Server.Implementations.Library.Resolvers { @@ -47,7 +48,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers var namingOptions = ((LibraryManager)LibraryManager).GetNamingOptions(); // If the path is a file check for a matching extensions - var parser = new Naming.Video.VideoResolver(namingOptions, new Naming.Logging.NullLogger()); + var parser = new Naming.Video.VideoResolver(namingOptions, new PatternsLogger()); if (args.IsDirectory) { @@ -233,7 +234,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers { var namingOptions = ((LibraryManager)LibraryManager).GetNamingOptions(); - var resolver = new Format3DParser(namingOptions, new Naming.Logging.NullLogger()); + var resolver = new Format3DParser(namingOptions, new PatternsLogger()); var result = resolver.Parse(video.Path); Set3DFormat(video, result.Is3D, result.Format3D); diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs index 67b9d546f..e3447afc9 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs @@ -4,7 +4,6 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Model.Entities; using System; using System.IO; -using System.Linq; namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies { @@ -46,17 +45,6 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies return null; } - private bool IsInvalid(string collectionType) - { - var validCollectionTypes = new[] - { - CollectionType.Movies, - CollectionType.BoxSets - }; - - return !validCollectionTypes.Contains(collectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase); - } - /// <summary> /// Sets the initial item values. /// </summary> diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs index 4c0767b08..95dcee98a 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs @@ -1,13 +1,14 @@ -using MediaBrowser.Common.Extensions; -using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Resolvers; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Extensions; using MediaBrowser.Naming.IO; using MediaBrowser.Naming.Video; +using MediaBrowser.Server.Implementations.Logging; using System; using System.Collections.Generic; using System.IO; @@ -111,7 +112,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies var namingOptions = ((LibraryManager)LibraryManager).GetNamingOptions(); - var resolver = new VideoListResolver(namingOptions, new Naming.Logging.NullLogger()); + var resolver = new VideoListResolver(namingOptions, new PatternsLogger()); var resolverResult = resolver.Resolve(files.Select(i => new PortableFileInfo { FullName = i.FullName, @@ -125,7 +126,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies Items = videos }; - var isInMixedFolder = resolverResult.Count > 0; + var isInMixedFolder = resolverResult.Count > 1; foreach (var video in resolverResult) { @@ -436,7 +437,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies } var namingOptions = ((LibraryManager)LibraryManager).GetNamingOptions(); - var resolver = new StackResolver(namingOptions, new Naming.Logging.NullLogger()); + var resolver = new StackResolver(namingOptions, new PatternsLogger()); var result = resolver.ResolveDirectories(folderPaths); diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs index 0a41a6c04..31b2d8b0f 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs @@ -1,4 +1,5 @@ using MediaBrowser.Common.IO; +using MediaBrowser.Controller; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Resolvers; @@ -11,10 +12,12 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers class SpecialFolderResolver : FolderResolver<Folder> { private readonly IFileSystem _fileSystem; + private readonly IServerApplicationPaths _appPaths; - public SpecialFolderResolver(IFileSystem fileSystem) + public SpecialFolderResolver(IFileSystem fileSystem, IServerApplicationPaths appPaths) { _fileSystem = fileSystem; + _appPaths = appPaths; } /// <summary> @@ -39,7 +42,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers { return new AggregateFolder(); } - if (args.IsRoot) + if (string.Equals(args.Path, _appPaths.DefaultUserViewsPath, StringComparison.OrdinalIgnoreCase)) { return new UserRootFolder(); //if we got here and still a root - must be user root } diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs index ff05c29ee..7371ca5a9 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs @@ -12,6 +12,7 @@ using MediaBrowser.Model.Logging; using MediaBrowser.Naming.Common; using MediaBrowser.Naming.IO; using MediaBrowser.Naming.TV; +using MediaBrowser.Server.Implementations.Logging; using EpisodeInfo = MediaBrowser.Controller.Providers.EpisodeInfo; namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV @@ -152,7 +153,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV .ToList(); } - var episodeResolver = new Naming.TV.EpisodeResolver(namingOptions, new Naming.Logging.NullLogger()); + var episodeResolver = new Naming.TV.EpisodeResolver(namingOptions, new PatternsLogger()); var episodeInfo = episodeResolver.Resolve(fullName, FileInfoType.File, false); if (episodeInfo != null && episodeInfo.EpisodeNumber.HasValue) { diff --git a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs index 1c92f6c4a..51cad7a35 100644 --- a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs +++ b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs @@ -35,20 +35,19 @@ namespace MediaBrowser.Server.Implementations.Library { IEnumerable<BaseItem> inputItems; + Func<BaseItem, bool> filter = i => !(i is ICollectionFolder); + if (string.IsNullOrWhiteSpace(query.UserId)) { - inputItems = _libraryManager.RootFolder.RecursiveChildren; + inputItems = _libraryManager.RootFolder.GetRecursiveChildren(filter); } else { var user = _userManager.GetUserById(query.UserId); - inputItems = user.RootFolder.GetRecursiveChildren(user, true); + inputItems = user.RootFolder.GetRecursiveChildren(user, filter); } - - inputItems = inputItems.Where(i => !(i is ICollectionFolder)); - inputItems = _libraryManager.ReplaceVideosWithPrimaryVersions(inputItems); var results = await GetSearchHints(inputItems, query).ConfigureAwait(false); diff --git a/MediaBrowser.Server.Implementations/Library/UserManager.cs b/MediaBrowser.Server.Implementations/Library/UserManager.cs index 3b6de5998..37f7e31fa 100644 --- a/MediaBrowser.Server.Implementations/Library/UserManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserManager.cs @@ -1,5 +1,6 @@ using MediaBrowser.Common.Events; using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.IO; using MediaBrowser.Common.Net; using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; @@ -70,8 +71,9 @@ namespace MediaBrowser.Server.Implementations.Library private readonly Func<IDtoService> _dtoServiceFactory; private readonly Func<IConnectManager> _connectFactory; private readonly IServerApplicationHost _appHost; + private readonly IFileSystem _fileSystem; - public UserManager(ILogger logger, IServerConfigurationManager configurationManager, IUserRepository userRepository, IXmlSerializer xmlSerializer, INetworkManager networkManager, Func<IImageProcessor> imageProcessorFactory, Func<IDtoService> dtoServiceFactory, Func<IConnectManager> connectFactory, IServerApplicationHost appHost, IJsonSerializer jsonSerializer) + public UserManager(ILogger logger, IServerConfigurationManager configurationManager, IUserRepository userRepository, IXmlSerializer xmlSerializer, INetworkManager networkManager, Func<IImageProcessor> imageProcessorFactory, Func<IDtoService> dtoServiceFactory, Func<IConnectManager> connectFactory, IServerApplicationHost appHost, IJsonSerializer jsonSerializer, IFileSystem fileSystem) { _logger = logger; UserRepository = userRepository; @@ -82,6 +84,7 @@ namespace MediaBrowser.Server.Implementations.Library _connectFactory = connectFactory; _appHost = appHost; _jsonSerializer = jsonSerializer; + _fileSystem = fileSystem; ConfigurationManager = configurationManager; Users = new List<User>(); @@ -204,7 +207,7 @@ namespace MediaBrowser.Server.Implementations.Library { return username; } - + // Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.) var builder = new StringBuilder(); @@ -272,9 +275,9 @@ namespace MediaBrowser.Server.Implementations.Library private string GetLocalPasswordHash(User user) { - return string.IsNullOrEmpty(user.LocalPassword) + return string.IsNullOrEmpty(user.EasyPassword) ? GetSha1String(string.Empty) - : user.LocalPassword; + : user.EasyPassword; } private bool IsPasswordEmpty(string passwordHash) @@ -329,22 +332,12 @@ namespace MediaBrowser.Server.Implementations.Library { if (!user.Configuration.HasMigratedToPolicy) { - user.Policy.AccessSchedules = user.Configuration.AccessSchedules; - user.Policy.BlockedChannels = user.Configuration.BlockedChannels; - user.Policy.BlockedMediaFolders = user.Configuration.BlockedMediaFolders; - user.Policy.BlockedTags = user.Configuration.BlockedTags; user.Policy.BlockUnratedItems = user.Configuration.BlockUnratedItems; user.Policy.EnableContentDeletion = user.Configuration.EnableContentDeletion; user.Policy.EnableLiveTvAccess = user.Configuration.EnableLiveTvAccess; user.Policy.EnableLiveTvManagement = user.Configuration.EnableLiveTvManagement; user.Policy.EnableMediaPlayback = user.Configuration.EnableMediaPlayback; - user.Policy.EnableRemoteControlOfOtherUsers = user.Configuration.EnableRemoteControlOfOtherUsers; - user.Policy.EnableSharedDeviceControl = user.Configuration.EnableSharedDeviceControl; - user.Policy.EnableUserPreferenceAccess = user.Configuration.EnableUserPreferenceAccess; user.Policy.IsAdministrator = user.Configuration.IsAdministrator; - user.Policy.IsDisabled = user.Configuration.IsDisabled; - user.Policy.IsHidden = user.Configuration.IsHidden; - user.Policy.MaxParentalRating = user.Configuration.MaxParentalRating; await UpdateUserPolicy(user, user.Policy, false); @@ -362,18 +355,20 @@ namespace MediaBrowser.Server.Implementations.Library var passwordHash = GetPasswordHash(user); - var hasConfiguredDefaultPassword = !IsPasswordEmpty(passwordHash); + var hasConfiguredPassword = !IsPasswordEmpty(passwordHash); + var hasConfiguredEasyPassword = !IsPasswordEmpty(GetLocalPasswordHash(user)); var hasPassword = user.Configuration.EnableLocalPassword && !string.IsNullOrEmpty(remoteEndPoint) && _networkManager.IsInLocalNetwork(remoteEndPoint) ? - !IsPasswordEmpty(GetLocalPasswordHash(user)) : - hasConfiguredDefaultPassword; + hasConfiguredEasyPassword : + hasConfiguredPassword; var dto = new UserDto { Id = user.Id.ToString("N"), Name = user.Name, HasPassword = hasPassword, - HasConfiguredPassword = hasConfiguredDefaultPassword, + HasConfiguredPassword = hasConfiguredPassword, + HasConfiguredEasyPassword = hasConfiguredEasyPassword, LastActivityDate = user.LastActivityDate, LastLoginDate = user.LastLoginDate, Configuration = user.Configuration, @@ -407,6 +402,21 @@ namespace MediaBrowser.Server.Implementations.Library return dto; } + public UserDto GetOfflineUserDto(User user, string deviceId) + { + var dto = GetUserDto(user); + + var offlinePasswordHash = GetLocalPasswordHash(user); + dto.HasPassword = !IsPasswordEmpty(offlinePasswordHash); + + // Hash the pin with the device Id to create a unique result for this device + dto.OfflinePassword = GetSha1String(offlinePasswordHash + deviceId); + + dto.ServerName = _appHost.FriendlyName; + + return dto; + } + private string GetImageCacheTag(BaseItem item, ItemImageInfo image) { try @@ -591,7 +601,7 @@ namespace MediaBrowser.Server.Implementations.Library try { - File.Delete(configPath); + _fileSystem.DeleteFile(configPath); } catch (IOException ex) { @@ -620,18 +630,11 @@ namespace MediaBrowser.Server.Implementations.Library return ChangePassword(user, GetSha1String(string.Empty)); } - /// <summary> - /// Changes the password. - /// </summary> - /// <param name="user">The user.</param> - /// <param name="newPasswordSha1">The new password sha1.</param> - /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException"> - /// user - /// or - /// newPassword - /// </exception> - /// <exception cref="System.ArgumentException">Passwords for guests cannot be changed.</exception> + public Task ResetEasyPassword(User user) + { + return ChangeEasyPassword(user, GetSha1String(string.Empty)); + } + public async Task ChangePassword(User user, string newPasswordSha1) { if (user == null) @@ -655,6 +658,29 @@ namespace MediaBrowser.Server.Implementations.Library EventHelper.FireEventIfNotNull(UserPasswordChanged, this, new GenericEventArgs<User>(user), _logger); } + public async Task ChangeEasyPassword(User user, string newPasswordSha1) + { + if (user == null) + { + throw new ArgumentNullException("user"); + } + if (string.IsNullOrWhiteSpace(newPasswordSha1)) + { + throw new ArgumentNullException("newPasswordSha1"); + } + + if (user.ConnectLinkType.HasValue && user.ConnectLinkType.Value == UserLinkType.Guest) + { + throw new ArgumentException("Passwords for guests cannot be changed."); + } + + user.EasyPassword = newPasswordSha1; + + await UpdateUser(user).ConfigureAwait(false); + + EventHelper.FireEventIfNotNull(UserPasswordChanged, this, new GenericEventArgs<User>(user), _logger); + } + /// <summary> /// Instantiates the new user. /// </summary> @@ -703,12 +729,11 @@ namespace MediaBrowser.Server.Implementations.Library var text = new StringBuilder(); - var info = _appHost.GetSystemInfo(); - var localAddress = info.LocalAddress ?? string.Empty; + var localAddress = _appHost.LocalApiUrl ?? string.Empty; text.AppendLine("Use your web browser to visit:"); text.AppendLine(string.Empty); - text.AppendLine(localAddress + "/mediabrowser/web/forgotpasswordpin.html"); + text.AppendLine(localAddress + "/web/forgotpasswordpin.html"); text.AppendLine(string.Empty); text.AppendLine("Enter the following pin code:"); text.AppendLine(string.Empty); @@ -817,7 +842,7 @@ namespace MediaBrowser.Server.Implementations.Library { try { - File.Delete(PasswordResetFile); + _fileSystem.DeleteFile(PasswordResetFile); } catch { @@ -881,7 +906,7 @@ namespace MediaBrowser.Server.Implementations.Library var json = _jsonSerializer.SerializeToString(userPolicy); userPolicy = _jsonSerializer.DeserializeFromString<UserPolicy>(json); } - + var path = GetPolifyFilePath(user); Directory.CreateDirectory(Path.GetDirectoryName(path)); @@ -909,7 +934,7 @@ namespace MediaBrowser.Server.Implementations.Library { lock (_policySyncLock) { - File.Delete(path); + _fileSystem.DeleteFile(path); } } catch (IOException) @@ -971,14 +996,14 @@ namespace MediaBrowser.Server.Implementations.Library var path = GetConfigurationFilePath(user); // The xml serializer will output differently if the type is not exact - if (config.GetType() != typeof (UserConfiguration)) + if (config.GetType() != typeof(UserConfiguration)) { var json = _jsonSerializer.SerializeToString(config); config = _jsonSerializer.DeserializeFromString<UserConfiguration>(json); } Directory.CreateDirectory(Path.GetDirectoryName(path)); - + lock (_configSyncLock) { _xmlSerializer.SerializeToFile(config, path); diff --git a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs index 46c32cc56..2ec9e8a4f 100644 --- a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs @@ -1,6 +1,6 @@ -using MediaBrowser.Common.IO; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Channels; +using MediaBrowser.Controller.Channels; +using MediaBrowser.Controller.Collections; +using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Library; @@ -16,6 +16,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using MoreLinq; namespace MediaBrowser.Server.Implementations.Library { @@ -23,24 +24,24 @@ namespace MediaBrowser.Server.Implementations.Library { private readonly ILibraryManager _libraryManager; private readonly ILocalizationManager _localizationManager; - private readonly IFileSystem _fileSystem; private readonly IUserManager _userManager; private readonly IChannelManager _channelManager; private readonly ILiveTvManager _liveTvManager; - private readonly IServerApplicationPaths _appPaths; private readonly IPlaylistManager _playlists; + private readonly ICollectionManager _collectionManager; + private readonly IServerConfigurationManager _config; - public UserViewManager(ILibraryManager libraryManager, ILocalizationManager localizationManager, IFileSystem fileSystem, IUserManager userManager, IChannelManager channelManager, ILiveTvManager liveTvManager, IServerApplicationPaths appPaths, IPlaylistManager playlists) + public UserViewManager(ILibraryManager libraryManager, ILocalizationManager localizationManager, IUserManager userManager, IChannelManager channelManager, ILiveTvManager liveTvManager, IPlaylistManager playlists, ICollectionManager collectionManager, IServerConfigurationManager config) { _libraryManager = libraryManager; _localizationManager = localizationManager; - _fileSystem = fileSystem; _userManager = userManager; _channelManager = channelManager; _liveTvManager = liveTvManager; - _appPaths = appPaths; _playlists = playlists; + _collectionManager = collectionManager; + _config = config; } public async Task<IEnumerable<Folder>> GetUserViews(UserViewQuery query, CancellationToken cancellationToken) @@ -56,7 +57,9 @@ namespace MediaBrowser.Server.Implementations.Library var excludeFolderIds = user.Configuration.ExcludeFoldersFromGrouping.Select(i => new Guid(i)).ToList(); - var standaloneFolders = folders.Where(i => UserView.IsExcludedFromGrouping(i) || excludeFolderIds.Contains(i.Id)).ToList(); + var standaloneFolders = folders + .Where(i => UserView.IsExcludedFromGrouping(i) || excludeFolderIds.Contains(i.Id)) + .ToList(); var foldersWithViewTypes = folders .Except(standaloneFolders) @@ -88,11 +91,9 @@ namespace MediaBrowser.Server.Implementations.Library list.Add(await GetUserView(CollectionType.Games, string.Empty, cancellationToken).ConfigureAwait(false)); } - if (user.Configuration.DisplayCollectionsView && - folders - .Except(standaloneFolders) - .SelectMany(i => i.GetRecursiveChildren(user, false)).OfType<BoxSet>().Any()) + if (foldersWithViewTypes.Any(i => string.Equals(i.CollectionType, CollectionType.BoxSets, StringComparison.OrdinalIgnoreCase))) { + //list.Add(_collectionManager.GetCollectionsFolder(user.Id.ToString("N"))); list.Add(await GetUserView(CollectionType.BoxSets, string.Empty, cancellationToken).ConfigureAwait(false)); } @@ -166,5 +167,141 @@ namespace MediaBrowser.Server.Implementations.Library return _libraryManager.GetNamedView(name, type, sortName, cancellationToken); } + + public List<Tuple<BaseItem, List<BaseItem>>> GetLatestItems(LatestItemsQuery request) + { + var user = _userManager.GetUserById(request.UserId); + + var includeTypes = request.IncludeItemTypes; + + var currentUser = user; + + Func<BaseItem, bool> filter = i => + { + if (includeTypes.Length > 0) + { + if (!includeTypes.Contains(i.GetType().Name, StringComparer.OrdinalIgnoreCase)) + { + return false; + } + } + + if (request.IsPlayed.HasValue) + { + var val = request.IsPlayed.Value; + if (i.IsPlayed(currentUser) != val) + { + return false; + } + } + + return i.LocationType != LocationType.Virtual && !i.IsFolder; + }; + + // Avoid implicitly captured closure + var libraryItems = string.IsNullOrEmpty(request.ParentId) && user != null ? + GetItemsConfiguredForLatest(user, filter) : + GetAllLibraryItems(request.UserId, _userManager, _libraryManager, request.ParentId, filter); + + libraryItems = libraryItems.OrderByDescending(i => i.DateCreated); + + if (request.IsPlayed.HasValue) + { + var takeLimit = (request.Limit ?? 20) * 20; + libraryItems = libraryItems.Take(takeLimit); + } + + // Avoid implicitly captured closure + var items = libraryItems + .ToList(); + + var list = new List<Tuple<BaseItem, List<BaseItem>>>(); + + foreach (var item in items) + { + // Only grab the index container for media + var container = item.IsFolder || !request.GroupItems ? null : item.LatestItemsIndexContainer; + + if (container == null) + { + list.Add(new Tuple<BaseItem, List<BaseItem>>(null, new List<BaseItem> { item })); + } + else + { + var current = list.FirstOrDefault(i => i.Item1 != null && i.Item1.Id == container.Id); + + if (current != null) + { + current.Item2.Add(item); + } + else + { + list.Add(new Tuple<BaseItem, List<BaseItem>>(container, new List<BaseItem> { item })); + } + } + + if (list.Count >= request.Limit) + { + break; + } + } + + return list; + } + + protected IList<BaseItem> GetAllLibraryItems(string userId, IUserManager userManager, ILibraryManager libraryManager, string parentId, Func<BaseItem, bool> filter) + { + if (!string.IsNullOrEmpty(parentId)) + { + var folder = (Folder)libraryManager.GetItemById(new Guid(parentId)); + + if (!string.IsNullOrWhiteSpace(userId)) + { + var user = userManager.GetUserById(userId); + + if (user == null) + { + throw new ArgumentException("User not found"); + } + + return folder + .GetRecursiveChildren(user, filter) + .ToList(); + } + + return folder + .GetRecursiveChildren(filter); + } + if (!string.IsNullOrWhiteSpace(userId)) + { + var user = userManager.GetUserById(userId); + + if (user == null) + { + throw new ArgumentException("User not found"); + } + + return user + .RootFolder + .GetRecursiveChildren(user, filter) + .ToList(); + } + + return libraryManager + .RootFolder + .GetRecursiveChildren(filter); + } + + private IEnumerable<BaseItem> GetItemsConfiguredForLatest(User user, Func<BaseItem, bool> filter) + { + // Avoid implicitly captured closure + var currentUser = user; + + return user.RootFolder.GetChildren(user, true) + .OfType<Folder>() + .Where(i => !user.Configuration.LatestItemsExcludes.Contains(i.Id.ToString("N"))) + .SelectMany(i => i.GetRecursiveChildren(currentUser, filter)) + .DistinctBy(i => i.Id); + } } } diff --git a/MediaBrowser.Server.Implementations/Library/Validators/ArtistsPostScanTask.cs b/MediaBrowser.Server.Implementations/Library/Validators/ArtistsPostScanTask.cs index 60116ac61..079867ddd 100644 --- a/MediaBrowser.Server.Implementations/Library/Validators/ArtistsPostScanTask.cs +++ b/MediaBrowser.Server.Implementations/Library/Validators/ArtistsPostScanTask.cs @@ -1,4 +1,5 @@ using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Logging; using System; using System.Threading; using System.Threading.Tasks; @@ -14,14 +15,16 @@ namespace MediaBrowser.Server.Implementations.Library.Validators /// The _library manager /// </summary> private readonly ILibraryManager _libraryManager; + private readonly ILogger _logger; /// <summary> /// Initializes a new instance of the <see cref="ArtistsPostScanTask" /> class. /// </summary> /// <param name="libraryManager">The library manager.</param> - public ArtistsPostScanTask(ILibraryManager libraryManager) + public ArtistsPostScanTask(ILibraryManager libraryManager, ILogger logger) { _libraryManager = libraryManager; + _logger = logger; } /// <summary> @@ -32,7 +35,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators /// <returns>Task.</returns> public Task Run(IProgress<double> progress, CancellationToken cancellationToken) { - return ((LibraryManager)_libraryManager).ValidateArtists(cancellationToken, progress); + return new ArtistsValidator(_libraryManager, _logger).Run(progress, cancellationToken); } } } diff --git a/MediaBrowser.Server.Implementations/Library/Validators/ArtistsValidator.cs b/MediaBrowser.Server.Implementations/Library/Validators/ArtistsValidator.cs index 5968d847e..7636833e4 100644 --- a/MediaBrowser.Server.Implementations/Library/Validators/ArtistsValidator.cs +++ b/MediaBrowser.Server.Implementations/Library/Validators/ArtistsValidator.cs @@ -1,7 +1,5 @@ -using MediaBrowser.Common.Progress; -using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using System; using System.Collections.Generic; @@ -23,11 +21,6 @@ namespace MediaBrowser.Server.Implementations.Library.Validators private readonly ILibraryManager _libraryManager; /// <summary> - /// The _user manager - /// </summary> - private readonly IUserManager _userManager; - - /// <summary> /// The _logger /// </summary> private readonly ILogger _logger; @@ -36,12 +29,10 @@ namespace MediaBrowser.Server.Implementations.Library.Validators /// Initializes a new instance of the <see cref="ArtistsPostScanTask" /> class. /// </summary> /// <param name="libraryManager">The library manager.</param> - /// <param name="userManager">The user manager.</param> /// <param name="logger">The logger.</param> - public ArtistsValidator(ILibraryManager libraryManager, IUserManager userManager, ILogger logger) + public ArtistsValidator(ILibraryManager libraryManager, ILogger logger) { _libraryManager = libraryManager; - _userManager = userManager; _logger = logger; } @@ -53,58 +44,11 @@ namespace MediaBrowser.Server.Implementations.Library.Validators /// <returns>Task.</returns> public async Task Run(IProgress<double> progress, CancellationToken cancellationToken) { - var allItems = _libraryManager.RootFolder.GetRecursiveChildren(); - - var allSongs = allItems.OfType<Audio>().ToList(); - - var innerProgress = new ActionableProgress<double>(); - - innerProgress.RegisterAction(pct => progress.Report(pct * .8)); - - var allArtists = await GetAllArtists(allSongs, cancellationToken, innerProgress).ConfigureAwait(false); - - progress.Report(80); - - var numComplete = 0; - - var numArtists = allArtists.Count; - - foreach (var artist in allArtists) - { - cancellationToken.ThrowIfCancellationRequested(); - - // Only do this for artists accessed by name. Folder-based artists get it from the normal refresh - if (artist.IsAccessedByName && !artist.LockedFields.Contains(MetadataFields.Genres)) - { - // Avoid implicitly captured closure - var artist1 = artist; - - artist.Genres = allSongs.Where(i => i.HasArtist(artist1.Name)) - .SelectMany(i => i.Genres) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToList(); - } - - numComplete++; - double percent = numComplete; - percent /= numArtists; - percent *= 20; - - progress.Report(80 + percent); - } - - progress.Report(100); - } + var allSongs = _libraryManager.RootFolder + .GetRecursiveChildren(i => !i.IsFolder && (i is IHasArtist)) + .Cast<IHasArtist>() + .ToList(); - /// <summary> - /// Gets all artists. - /// </summary> - /// <param name="allSongs">All songs.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <param name="progress">The progress.</param> - /// <returns>Task{Artist[]}.</returns> - private async Task<List<MusicArtist>> GetAllArtists(IEnumerable<Audio> allSongs, CancellationToken cancellationToken, IProgress<double> progress) - { var allArtists = allSongs.SelectMany(i => i.AllArtists) .Distinct(StringComparer.OrdinalIgnoreCase) .ToList(); @@ -138,8 +82,6 @@ namespace MediaBrowser.Server.Implementations.Library.Validators progress.Report(100 * percent); } - - return returnArtists; } } } diff --git a/MediaBrowser.Server.Implementations/Library/Validators/BoxSetPostScanTask.cs b/MediaBrowser.Server.Implementations/Library/Validators/BoxSetPostScanTask.cs deleted file mode 100644 index 86d88f7e0..000000000 --- a/MediaBrowser.Server.Implementations/Library/Validators/BoxSetPostScanTask.cs +++ /dev/null @@ -1,50 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.Library; -using System; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.Library.Validators -{ - public class BoxSetPostScanTask : ILibraryPostScanTask - { - private readonly ILibraryManager _libraryManager; - - public BoxSetPostScanTask(ILibraryManager libraryManager) - { - _libraryManager = libraryManager; - } - - public Task Run(IProgress<double> progress, CancellationToken cancellationToken) - { - var items = _libraryManager.RootFolder.RecursiveChildren.ToList(); - - var boxsets = items.OfType<BoxSet>().ToList(); - - var numComplete = 0; - - foreach (var boxset in boxsets) - { - foreach (var child in boxset.Children.Concat(boxset.GetLinkedChildren()).OfType<ISupportsBoxSetGrouping>()) - { - var boxsetIdList = child.BoxSetIdList.ToList(); - if (!boxsetIdList.Contains(boxset.Id)) - { - boxsetIdList.Add(boxset.Id); - } - child.BoxSetIdList = boxsetIdList; - } - - numComplete++; - double percent = numComplete; - percent /= boxsets.Count; - progress.Report(percent * 100); - } - - progress.Report(100); - return Task.FromResult(true); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/Validators/GameGenresPostScanTask.cs b/MediaBrowser.Server.Implementations/Library/Validators/GameGenresPostScanTask.cs index ae6c863a7..8be2e436f 100644 --- a/MediaBrowser.Server.Implementations/Library/Validators/GameGenresPostScanTask.cs +++ b/MediaBrowser.Server.Implementations/Library/Validators/GameGenresPostScanTask.cs @@ -1,4 +1,5 @@ using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Logging; using System; using System.Threading; using System.Threading.Tasks; @@ -14,14 +15,17 @@ namespace MediaBrowser.Server.Implementations.Library.Validators /// The _library manager /// </summary> private readonly ILibraryManager _libraryManager; + private readonly ILogger _logger; /// <summary> /// Initializes a new instance of the <see cref="GameGenresPostScanTask" /> class. /// </summary> /// <param name="libraryManager">The library manager.</param> - public GameGenresPostScanTask(ILibraryManager libraryManager) + /// <param name="logger">The logger.</param> + public GameGenresPostScanTask(ILibraryManager libraryManager, ILogger logger) { _libraryManager = libraryManager; + _logger = logger; } /// <summary> @@ -32,7 +36,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators /// <returns>Task.</returns> public Task Run(IProgress<double> progress, CancellationToken cancellationToken) { - return ((LibraryManager)_libraryManager).ValidateGameGenres(cancellationToken, progress); + return new GameGenresValidator(_libraryManager, _logger).Run(progress, cancellationToken); } } } diff --git a/MediaBrowser.Server.Implementations/Library/Validators/GameGenresValidator.cs b/MediaBrowser.Server.Implementations/Library/Validators/GameGenresValidator.cs index 6b658e175..757936aa7 100644 --- a/MediaBrowser.Server.Implementations/Library/Validators/GameGenresValidator.cs +++ b/MediaBrowser.Server.Implementations/Library/Validators/GameGenresValidator.cs @@ -16,19 +16,13 @@ namespace MediaBrowser.Server.Implementations.Library.Validators private readonly ILibraryManager _libraryManager; /// <summary> - /// The _user manager - /// </summary> - private readonly IUserManager _userManager; - - /// <summary> /// The _logger /// </summary> private readonly ILogger _logger; - public GameGenresValidator(ILibraryManager libraryManager, IUserManager userManager, ILogger logger) + public GameGenresValidator(ILibraryManager libraryManager, ILogger logger) { _libraryManager = libraryManager; - _userManager = userManager; _logger = logger; } @@ -40,19 +34,16 @@ namespace MediaBrowser.Server.Implementations.Library.Validators /// <returns>Task.</returns> public async Task Run(IProgress<double> progress, CancellationToken cancellationToken) { - var items = _libraryManager.RootFolder.RecursiveChildren.Where(i => (i is Game)) + var items = _libraryManager.RootFolder.GetRecursiveChildren(i => (i is Game)) .SelectMany(i => i.Genres) .Distinct(StringComparer.OrdinalIgnoreCase) .ToList(); - progress.Report(2); var numComplete = 0; var count = items.Count; foreach (var name in items) { - cancellationToken.ThrowIfCancellationRequested(); - try { var itemByName = _libraryManager.GetGameGenre(name); @@ -72,9 +63,9 @@ namespace MediaBrowser.Server.Implementations.Library.Validators numComplete++; double percent = numComplete; percent /= count; - percent *= 90; + percent *= 100; - progress.Report(percent + 10); + progress.Report(percent); } progress.Report(100); diff --git a/MediaBrowser.Server.Implementations/Library/Validators/GenresPostScanTask.cs b/MediaBrowser.Server.Implementations/Library/Validators/GenresPostScanTask.cs index f1d0ef370..a1c34676c 100644 --- a/MediaBrowser.Server.Implementations/Library/Validators/GenresPostScanTask.cs +++ b/MediaBrowser.Server.Implementations/Library/Validators/GenresPostScanTask.cs @@ -2,6 +2,7 @@ using System; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Model.Logging; namespace MediaBrowser.Server.Implementations.Library.Validators { @@ -11,14 +12,17 @@ namespace MediaBrowser.Server.Implementations.Library.Validators /// The _library manager /// </summary> private readonly ILibraryManager _libraryManager; + private readonly ILogger _logger; /// <summary> /// Initializes a new instance of the <see cref="ArtistsPostScanTask" /> class. /// </summary> /// <param name="libraryManager">The library manager.</param> - public GenresPostScanTask(ILibraryManager libraryManager) + /// <param name="logger">The logger.</param> + public GenresPostScanTask(ILibraryManager libraryManager, ILogger logger) { _libraryManager = libraryManager; + _logger = logger; } /// <summary> @@ -29,7 +33,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators /// <returns>Task.</returns> public Task Run(IProgress<double> progress, CancellationToken cancellationToken) { - return ((LibraryManager)_libraryManager).ValidateGenres(cancellationToken, progress); + return new GenresValidator(_libraryManager, _logger).Run(progress, cancellationToken); } } } diff --git a/MediaBrowser.Server.Implementations/Library/Validators/GenresValidator.cs b/MediaBrowser.Server.Implementations/Library/Validators/GenresValidator.cs index b0dee9aaf..3a06fac1b 100644 --- a/MediaBrowser.Server.Implementations/Library/Validators/GenresValidator.cs +++ b/MediaBrowser.Server.Implementations/Library/Validators/GenresValidator.cs @@ -17,19 +17,13 @@ namespace MediaBrowser.Server.Implementations.Library.Validators private readonly ILibraryManager _libraryManager; /// <summary> - /// The _user manager - /// </summary> - private readonly IUserManager _userManager; - - /// <summary> /// The _logger /// </summary> private readonly ILogger _logger; - public GenresValidator(ILibraryManager libraryManager, IUserManager userManager, ILogger logger) + public GenresValidator(ILibraryManager libraryManager, ILogger logger) { _libraryManager = libraryManager; - _userManager = userManager; _logger = logger; } @@ -41,19 +35,16 @@ namespace MediaBrowser.Server.Implementations.Library.Validators /// <returns>Task.</returns> public async Task Run(IProgress<double> progress, CancellationToken cancellationToken) { - var items = _libraryManager.RootFolder.RecursiveChildren.Where(i => !(i is IHasMusicGenres) && !(i is Game)) + var items = _libraryManager.RootFolder.GetRecursiveChildren(i => !(i is IHasMusicGenres) && !(i is Game)) .SelectMany(i => i.Genres) .Distinct(StringComparer.OrdinalIgnoreCase) .ToList(); - progress.Report(2); var numComplete = 0; var count = items.Count; foreach (var name in items) { - cancellationToken.ThrowIfCancellationRequested(); - try { var itemByName = _libraryManager.GetGenre(name); @@ -73,9 +64,9 @@ namespace MediaBrowser.Server.Implementations.Library.Validators numComplete++; double percent = numComplete; percent /= count; - percent *= 90; + percent *= 100; - progress.Report(percent + 10); + progress.Report(percent); } progress.Report(100); diff --git a/MediaBrowser.Server.Implementations/Library/Validators/MusicGenresPostScanTask.cs b/MediaBrowser.Server.Implementations/Library/Validators/MusicGenresPostScanTask.cs index 280dd90f4..dbcab0832 100644 --- a/MediaBrowser.Server.Implementations/Library/Validators/MusicGenresPostScanTask.cs +++ b/MediaBrowser.Server.Implementations/Library/Validators/MusicGenresPostScanTask.cs @@ -1,4 +1,5 @@ using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Logging; using System; using System.Threading; using System.Threading.Tasks; @@ -14,14 +15,17 @@ namespace MediaBrowser.Server.Implementations.Library.Validators /// The _library manager /// </summary> private readonly ILibraryManager _libraryManager; + private readonly ILogger _logger; /// <summary> /// Initializes a new instance of the <see cref="ArtistsPostScanTask" /> class. /// </summary> /// <param name="libraryManager">The library manager.</param> - public MusicGenresPostScanTask(ILibraryManager libraryManager) + /// <param name="logger">The logger.</param> + public MusicGenresPostScanTask(ILibraryManager libraryManager, ILogger logger) { _libraryManager = libraryManager; + _logger = logger; } /// <summary> @@ -32,7 +36,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators /// <returns>Task.</returns> public Task Run(IProgress<double> progress, CancellationToken cancellationToken) { - return ((LibraryManager)_libraryManager).ValidateMusicGenres(cancellationToken, progress); + return new MusicGenresValidator(_libraryManager, _logger).Run(progress, cancellationToken); } } } diff --git a/MediaBrowser.Server.Implementations/Library/Validators/MusicGenresValidator.cs b/MediaBrowser.Server.Implementations/Library/Validators/MusicGenresValidator.cs index aa6c6281e..25eddb48a 100644 --- a/MediaBrowser.Server.Implementations/Library/Validators/MusicGenresValidator.cs +++ b/MediaBrowser.Server.Implementations/Library/Validators/MusicGenresValidator.cs @@ -34,19 +34,16 @@ namespace MediaBrowser.Server.Implementations.Library.Validators /// <returns>Task.</returns> public async Task Run(IProgress<double> progress, CancellationToken cancellationToken) { - var items = _libraryManager.RootFolder.RecursiveChildren.Where(i => (i is IHasMusicGenres)) + var items = _libraryManager.RootFolder.GetRecursiveChildren(i => (i is IHasMusicGenres)) .SelectMany(i => i.Genres) .Distinct(StringComparer.OrdinalIgnoreCase) .ToList(); - progress.Report(2); var numComplete = 0; var count = items.Count; foreach (var name in items) { - cancellationToken.ThrowIfCancellationRequested(); - try { var itemByName = _libraryManager.GetMusicGenre(name); @@ -66,9 +63,9 @@ namespace MediaBrowser.Server.Implementations.Library.Validators numComplete++; double percent = numComplete; percent /= count; - percent *= 90; + percent *= 100; - progress.Report(percent + 10); + progress.Report(percent); } progress.Report(100); diff --git a/MediaBrowser.Server.Implementations/Library/Validators/StudiosPostScanTask.cs b/MediaBrowser.Server.Implementations/Library/Validators/StudiosPostScanTask.cs index 0f998b070..0ff609da1 100644 --- a/MediaBrowser.Server.Implementations/Library/Validators/StudiosPostScanTask.cs +++ b/MediaBrowser.Server.Implementations/Library/Validators/StudiosPostScanTask.cs @@ -1,4 +1,5 @@ using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Logging; using System; using System.Threading; using System.Threading.Tasks; @@ -15,13 +16,16 @@ namespace MediaBrowser.Server.Implementations.Library.Validators /// </summary> private readonly ILibraryManager _libraryManager; + private readonly ILogger _logger; + /// <summary> /// Initializes a new instance of the <see cref="ArtistsPostScanTask" /> class. /// </summary> /// <param name="libraryManager">The library manager.</param> - public StudiosPostScanTask(ILibraryManager libraryManager) + public StudiosPostScanTask(ILibraryManager libraryManager, ILogger logger) { _libraryManager = libraryManager; + _logger = logger; } /// <summary> @@ -32,7 +36,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators /// <returns>Task.</returns> public Task Run(IProgress<double> progress, CancellationToken cancellationToken) { - return ((LibraryManager)_libraryManager).ValidateStudios(cancellationToken, progress); + return new StudiosValidator(_libraryManager, _logger).Run(progress, cancellationToken); } } } diff --git a/MediaBrowser.Server.Implementations/Library/Validators/StudiosValidator.cs b/MediaBrowser.Server.Implementations/Library/Validators/StudiosValidator.cs index a2ec9788c..5feebab9c 100644 --- a/MediaBrowser.Server.Implementations/Library/Validators/StudiosValidator.cs +++ b/MediaBrowser.Server.Implementations/Library/Validators/StudiosValidator.cs @@ -15,19 +15,13 @@ namespace MediaBrowser.Server.Implementations.Library.Validators private readonly ILibraryManager _libraryManager; /// <summary> - /// The _user manager - /// </summary> - private readonly IUserManager _userManager; - - /// <summary> /// The _logger /// </summary> private readonly ILogger _logger; - public StudiosValidator(ILibraryManager libraryManager, IUserManager userManager, ILogger logger) + public StudiosValidator(ILibraryManager libraryManager, ILogger logger) { _libraryManager = libraryManager; - _userManager = userManager; _logger = logger; } @@ -39,19 +33,16 @@ namespace MediaBrowser.Server.Implementations.Library.Validators /// <returns>Task.</returns> public async Task Run(IProgress<double> progress, CancellationToken cancellationToken) { - var items = _libraryManager.RootFolder.RecursiveChildren + var items = _libraryManager.RootFolder.GetRecursiveChildren() .SelectMany(i => i.Studios) .Distinct(StringComparer.OrdinalIgnoreCase) .ToList(); - progress.Report(2); var numComplete = 0; var count = items.Count; foreach (var name in items) { - cancellationToken.ThrowIfCancellationRequested(); - try { var itemByName = _libraryManager.GetStudio(name); @@ -71,9 +62,9 @@ namespace MediaBrowser.Server.Implementations.Library.Validators numComplete++; double percent = numComplete; percent /= count; - percent *= 90; + percent *= 100; - progress.Report(percent + 10); + progress.Report(percent); } progress.Report(100); diff --git a/MediaBrowser.Server.Implementations/Library/Validators/YearsPostScanTask.cs b/MediaBrowser.Server.Implementations/Library/Validators/YearsPostScanTask.cs index 78783db90..5ea5fb254 100644 --- a/MediaBrowser.Server.Implementations/Library/Validators/YearsPostScanTask.cs +++ b/MediaBrowser.Server.Implementations/Library/Validators/YearsPostScanTask.cs @@ -20,23 +20,21 @@ namespace MediaBrowser.Server.Implementations.Library.Validators public async Task Run(IProgress<double> progress, CancellationToken cancellationToken) { - var allYears = _libraryManager.RootFolder.RecursiveChildren + var allYears = _libraryManager.RootFolder.GetRecursiveChildren(i => i.ProductionYear.HasValue) .Select(i => i.ProductionYear ?? -1) .Where(i => i > 0) .Distinct() .ToList(); - progress.Report(10); - var count = allYears.Count; var numComplete = 0; foreach (var yearNumber in allYears) { - var year = _libraryManager.GetYear(yearNumber); - try { + var year = _libraryManager.GetYear(yearNumber); + await year.RefreshMetadata(cancellationToken).ConfigureAwait(false); } catch (OperationCanceledException) @@ -46,15 +44,15 @@ namespace MediaBrowser.Server.Implementations.Library.Validators } catch (Exception ex) { - _logger.ErrorException("Error refreshing year {0}", ex, year); + _logger.ErrorException("Error refreshing year {0}", ex, yearNumber); } numComplete++; double percent = numComplete; percent /= count; - percent *= 90; + percent *= 100; - progress.Report(percent + 10); + progress.Report(percent); } } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index 96498563e..74069e580 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -436,40 +436,19 @@ namespace MediaBrowser.Server.Implementations.LiveTv private async Task<LiveTvChannel> GetChannel(ChannelInfo channelInfo, string serviceName, CancellationToken cancellationToken) { - var path = Path.Combine(_config.ApplicationPaths.ItemsByNamePath, "tvchannels", _fileSystem.GetValidFilename(channelInfo.Name)); - - var fileInfo = new DirectoryInfo(path); - var isNew = false; - if (!fileInfo.Exists) - { - _logger.Debug("Creating directory {0}", path); - - Directory.CreateDirectory(path); - fileInfo = new DirectoryInfo(path); - - if (!fileInfo.Exists) - { - throw new IOException("Path not created: " + path); - } - - isNew = true; - } - var id = _tvDtoService.GetInternalChannelId(serviceName, channelInfo.Id); var item = _itemRepo.RetrieveItem(id) as LiveTvChannel; - if (item == null || !string.Equals(item.Path, path, StringComparison.OrdinalIgnoreCase)) + if (item == null) { item = new LiveTvChannel { Name = channelInfo.Name, Id = id, - DateCreated = _fileSystem.GetCreationTimeUtc(fileInfo), - DateModified = _fileSystem.GetLastWriteTimeUtc(fileInfo), - Path = path + DateCreated = DateTime.UtcNow, }; isNew = true; diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/ar.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/ar.json index b810ff630..2fd96dd0d 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/ar.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/ar.json @@ -6,6 +6,8 @@ "Administrator": "\u0627\u0644\u0645\u0633\u0624\u0648\u0644", "Password": "\u0643\u0644\u0645\u0629 \u0627\u0644\u0633\u0631", "DeleteImage": "\u062d\u0630\u0641 \u0635\u0648\u0631\u0629", + "MessageThankYouForSupporting": "Thank you for supporting Media Browser.", + "MessagePleaseSupportMediaBrowser": "Please support Media Browser.", "DeleteImageConfirmation": "\u0647\u0644 \u0627\u0646\u062a \u0645\u062a\u0627\u0643\u062f \u0645\u0646 \u062d\u0630\u0641 \u0647\u0630\u0647 \u0627\u0644\u0635\u0648\u0631\u0629\u061f", "FileReadCancelled": "\u062a\u0645 \u0627\u0644\u063a\u0627\u0621 \u0642\u0631\u0627\u0621\u0629 \u0627\u0644\u0645\u0644\u0641.", "FileNotFound": "\u0627\u0644\u0645\u0644\u0641 \u063a\u064a\u0631 \u0645\u0648\u062c\u0648\u062f.", @@ -14,7 +16,10 @@ "DeleteUserConfirmation": "\u0647\u0644 \u0627\u0646\u062a \u0645\u062a\u0627\u0643\u062f \u0645\u0646 \u0627\u0646\u0643 \u062a\u0631\u064a\u062f \u062d\u0630\u0641 \u0647\u0630\u0627 \u0627\u0644\u0645\u0633\u062a\u062e\u062f\u0645 \u061f", "PasswordResetHeader": "\u0627\u0639\u0627\u062f\u0629 \u062a\u0639\u064a\u064a\u0646 \u0643\u0644\u0645\u0629 \u0627\u0644\u0633\u0631", "PasswordResetComplete": "\u0644\u0642\u062f \u062a\u0645 \u0627\u0639\u0627\u062f\u0629 \u062a\u0639\u064a\u064a\u0646 \u0643\u0644\u0645\u0629 \u0627\u0644\u0633\u0631.", + "PinCodeResetComplete": "The pin code has been reset.", "PasswordResetConfirmation": "\u0647\u0644 \u0627\u0646\u062a \u0645\u062a\u0627\u0643\u062f \u0645\u0646 \u0627\u0646\u0643 \u062a\u0631\u064a\u062f \u0627\u0639\u0627\u062f\u0629 \u062a\u0639\u064a\u064a\u0646 \u0643\u0644\u0645\u0629 \u0627\u0644\u0633\u0631\u061f", + "PinCodeResetConfirmation": "Are you sure you wish to reset the pin code?", + "HeaderPinCodeReset": "Reset Pin Code", "PasswordSaved": "\u062a\u0645 \u062d\u0641\u0638 \u0643\u0644\u0645\u0629 \u0627\u0644\u0633\u0631.", "PasswordMatchError": "\u0643\u0644\u0645\u0629 \u0627\u0644\u0633\u0631 \u0648\u062a\u0627\u0643\u064a\u062f\u0647\u0627 \u064a\u062c\u0628 \u0627\u0646 \u064a\u062a\u0637\u0627\u0628\u0642\u0627\u0646.", "OptionRelease": "\u0627\u0644\u0627\u0635\u062f\u0627\u0631 \u0627\u0644\u0631\u0633\u0645\u0649", @@ -32,6 +37,7 @@ "MessageKeyRemoved": "Thank you. Your supporter key has been removed.", "ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.", "HeaderSearch": "Search", + "ValueDateCreated": "Date created: {0}", "LabelArtist": "Artist", "LabelMovie": "Movie", "LabelMusicVideo": "Music Video", @@ -42,6 +48,17 @@ "LabelFailed": "(failed)", "ButtonHelp": "Help", "ButtonSave": "\u062a\u062e\u0632\u064a\u0646", + "LabelCollection": "Collection", + "HeaderAddToCollection": "Add to Collection", + "NewCollectionNameExample": "Example: Star Wars Collection", + "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata", + "LabelSelectCollection": "Select collection:", + "HeaderDevices": "Devices", + "ButtonScheduledTasks": "Scheduled tasks", + "MessageItemsAdded": "Items added", + "ButtonAddToCollection": "Add to collection", + "HeaderSelectCertificatePath": "Select Certificate Path", + "ConfirmMessageScheduledTaskButton": "This operation normally runs automatically as a scheduled task. It can also be run manually here. To configure the scheduled task, see:", "HeaderSupporterBenefit": "A supporter membership provides additional benefits such as access to premium plugins, internet channel content, and more. {0}Learn more{1}.", "HeaderWelcomeToMediaBrowserServerDashboard": "Welcome to the Media Browser Dashboard", "HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client", @@ -53,6 +70,10 @@ "HeaderChannelAccess": "Channel Access", "HeaderDeviceAccess": "Device Access", "HeaderSelectDevices": "Select Devices", + "ButtonCancelItem": "Cancel item", + "ButtonQueueForRetry": "Queue for retry", + "ButtonReenable": "Re-enable", + "SyncJobItemStatusSyncedMarkForRemoval": "Marked for removal", "LabelAbortedByServerShutdown": "(Aborted by server shutdown)", "LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.", "HeaderDeleteTaskTrigger": "Delete Task Trigger", @@ -64,10 +85,13 @@ "LabelFree": "Free", "HeaderSelectAudio": "Select Audio", "HeaderSelectSubtitles": "Select Subtitles", + "ButtonMarkForRemoval": "Mark for removal from device", + "ButtonUnmarkForRemoval": "Unmark for removal from device", "LabelDefaultStream": "(Default)", "LabelForcedStream": "(Forced)", "LabelDefaultForcedStream": "(Default\/Forced)", "LabelUnknownLanguage": "Unknown language", + "MessageConfirmSyncJobItemCancellation": "Are you sure you wish to cancel this item?", "ButtonMute": "Mute", "ButtonUnmute": "Unmute", "ButtonStop": "Stop", @@ -191,8 +215,10 @@ "LabelPlayMethodDirectPlay": "Direct Playing", "LabelAudioCodec": "Audio: {0}", "LabelVideoCodec": "Video: {0}", + "LabelLocalAccessUrl": "Local access: {0}", "LabelRemoteAccessUrl": "Remote access: {0}", - "LabelRunningOnPort": "Running on port {0}.", + "LabelRunningOnPort": "Running on http port {0}.", + "LabelRunningOnPorts": "Running on http port {0}, and https port {1}.", "HeaderLatestFromChannel": "Latest from {0}", "ButtonDownload": "Download", "LabelUnknownLanaguage": "Unknown language", @@ -206,6 +232,7 @@ "ButtonRefresh": "Refresh", "LabelCurrentPath": "Current path:", "HeaderSelectMediaPath": "Select Media Path", + "HeaderSelectPath": "Select Path", "ButtonNetwork": "Network", "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.", "HeaderMenu": "Menu", @@ -216,6 +243,7 @@ "ButtonResume": "Resume", "HeaderScenes": "Scenes", "HeaderAudioTracks": "Audio Tracks", + "HeaderLibraries": "Libraries", "HeaderSubtitles": "Subtitles", "HeaderVideoQuality": "Video Quality", "MessageErrorPlayingVideo": "There was an error playing the video.", @@ -581,6 +609,8 @@ "MediaInfoStreamTypeEmbeddedImage": "Embedded Image", "MediaInfoRefFrames": "Ref frames", "TabPlayback": "Playback", + "TabNotifications": "Notifications", + "TabExpert": "Expert", "HeaderSelectCustomIntrosPath": "Select Custom Intros Path", "HeaderRateAndReview": "Rate and Review", "HeaderThankYou": "Thank You", @@ -615,6 +645,7 @@ "DashboardTourMobile": "The Media Browser dashboard works great on smartphones and tablets. Manage your server from the palm of your hand anytime, anywhere.", "MessageRefreshQueued": "Refresh queued", "TabDevices": "Devices", + "TabExtras": "Extras", "DeviceLastUsedByUserName": "Last used by {0}", "HeaderDeleteDevice": "Delete Device", "DeleteDeviceConfirmation": "Are you sure you wish to delete this device? It will reappear the next time a user signs in with it.", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/bg_BG.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/bg_BG.json new file mode 100644 index 000000000..e373d1716 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/bg_BG.json @@ -0,0 +1,710 @@ +{ + "SettingsSaved": "Settings saved.", + "AddUser": "Add User", + "Users": "Users", + "Delete": "Delete", + "Administrator": "Administrator", + "Password": "Password", + "DeleteImage": "Delete Image", + "MessageThankYouForSupporting": "Thank you for supporting Media Browser.", + "MessagePleaseSupportMediaBrowser": "Please support Media Browser.", + "DeleteImageConfirmation": "Are you sure you wish to delete this image?", + "FileReadCancelled": "The file read has been canceled.", + "FileNotFound": "File not found.", + "FileReadError": "An error occurred while reading the file.", + "DeleteUser": "Delete User", + "DeleteUserConfirmation": "Are you sure you wish to delete this user?", + "PasswordResetHeader": "Reset Password", + "PasswordResetComplete": "The password has been reset.", + "PinCodeResetComplete": "The pin code has been reset.", + "PasswordResetConfirmation": "Are you sure you wish to reset the password?", + "PinCodeResetConfirmation": "Are you sure you wish to reset the pin code?", + "HeaderPinCodeReset": "Reset Pin Code", + "PasswordSaved": "Password saved.", + "PasswordMatchError": "Password and password confirmation must match.", + "OptionRelease": "\u041e\u0444\u0438\u0446\u0438\u0430\u043b\u043d\u043e \u0438\u0437\u0434\u0430\u043d\u0438\u0435", + "OptionBeta": "\u0411\u0435\u0442\u0430", + "OptionDev": "\u0417\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u0446\u0438 (\u041d\u0435\u0441\u0442\u0430\u0431\u0438\u043b\u0435\u043d)", + "UninstallPluginHeader": "Uninstall Plugin", + "UninstallPluginConfirmation": "Are you sure you wish to uninstall {0}?", + "NoPluginConfigurationMessage": "This plugin has nothing to configure.", + "NoPluginsInstalledMessage": "You have no plugins installed.", + "BrowsePluginCatalogMessage": "Browse our plugin catalog to view available plugins.", + "MessageKeyEmailedTo": "Key emailed to {0}.", + "MessageKeysLinked": "Keys linked.", + "HeaderConfirmation": "Confirmation", + "MessageKeyUpdated": "Thank you. Your supporter key has been updated.", + "MessageKeyRemoved": "Thank you. Your supporter key has been removed.", + "ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.", + "HeaderSearch": "Search", + "ValueDateCreated": "Date created: {0}", + "LabelArtist": "Artist", + "LabelMovie": "Movie", + "LabelMusicVideo": "Music Video", + "LabelEpisode": "Episode", + "LabelSeries": "\u041f\u043e\u0440\u0435\u0434\u0438\u0446\u0430", + "LabelStopping": "Stopping", + "LabelCancelled": "(cancelled)", + "LabelFailed": "(\u043d\u0435\u0443\u0441\u043f\u0435\u0448\u043d\u043e)", + "ButtonHelp": "\u041f\u043e\u043c\u043e\u0449", + "ButtonSave": "\u0417\u0430\u043f\u043e\u043c\u043d\u0438", + "LabelCollection": "Collection", + "HeaderAddToCollection": "Add to Collection", + "NewCollectionNameExample": "Example: Star Wars Collection", + "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata", + "LabelSelectCollection": "Select collection:", + "HeaderDevices": "Devices", + "ButtonScheduledTasks": "Scheduled tasks", + "MessageItemsAdded": "Items added", + "ButtonAddToCollection": "Add to collection", + "HeaderSelectCertificatePath": "Select Certificate Path", + "ConfirmMessageScheduledTaskButton": "This operation normally runs automatically as a scheduled task. It can also be run manually here. To configure the scheduled task, see:", + "HeaderSupporterBenefit": "\u041f\u0440\u0438\u0432\u044a\u0440\u0436\u0435\u043d\u0441\u043a\u043e\u0442\u043e \u0447\u043b\u0435\u043d\u0441\u0442\u0432\u043e \u043e\u0441\u0438\u0433\u0443\u0440\u044f\u0432\u0430 \u0434\u043e\u043f\u044a\u043b\u043d\u0438\u0442\u0435\u043b\u043d\u0438 \u043e\u0431\u043b\u0430\u0433\u0438, \u043a\u0430\u0442\u043e \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0434\u043e\u0441\u0442\u044a\u043f \u0434\u043e \u043f\u044a\u0440\u0432\u043e\u043a\u043b\u0430\u0441\u043d\u0438 \u043f\u043b\u044a\u0433\u0438\u043d\u0438, \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435 \u043d\u0430 \u043a\u0430\u043d\u0430\u043b\u0438\u0442\u0435, \u0438 \u0434\u0440\u0443\u0433\u0438. {0} \u041d\u0430\u0443\u0447\u0435\u0442\u0435 \u043f\u043e\u0432\u0435\u0447\u0435 {1}.", + "HeaderWelcomeToMediaBrowserServerDashboard": "\u0414\u043e\u0431\u0440\u0435 \u0434\u043e\u0448\u043b\u0438 \u0432 \u0433\u043b\u0430\u0432\u043d\u0438\u044f \u043f\u0430\u043d\u0435\u043b \u043d\u0430 Media Browser", + "HeaderWelcomeToMediaBrowserWebClient": "\u0414\u043e\u0431\u0440\u0435 \u0434\u043e\u0448\u043b\u0438 \u0432 \u0443\u0435\u0431 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u043d\u0430 Media Browser", + "ButtonTakeTheTour": "\u0420\u0430\u0437\u0433\u043b\u0435\u0434\u0430\u0439 \u043d\u0430\u043e\u043a\u043e\u043b\u043e", + "HeaderWelcomeBack": "Welcome back!", + "ButtonTakeTheTourToSeeWhatsNew": "Take the tour to see what's new", + "MessageNoSyncJobsFound": "No sync jobs found. Create sync jobs using the Sync buttons found throughout the web interface.", + "HeaderLibraryAccess": "Library Access", + "HeaderChannelAccess": "Channel Access", + "HeaderDeviceAccess": "\u0414\u043e\u0441\u0442\u044a\u043f \u043d\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u0442\u0430", + "HeaderSelectDevices": "Select Devices", + "ButtonCancelItem": "Cancel item", + "ButtonQueueForRetry": "Queue for retry", + "ButtonReenable": "Re-enable", + "SyncJobItemStatusSyncedMarkForRemoval": "Marked for removal", + "LabelAbortedByServerShutdown": "(Aborted by server shutdown)", + "LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.", + "HeaderDeleteTaskTrigger": "Delete Task Trigger", + "HeaderTaskTriggers": "Task Triggers", + "MessageDeleteTaskTrigger": "Are you sure you wish to delete this task trigger?", + "MessageNoPluginsInstalled": "You have no plugins installed.", + "LabelVersionInstalled": "{0} installed", + "LabelNumberReviews": "{0} Reviews", + "LabelFree": "Free", + "HeaderSelectAudio": "Select Audio", + "HeaderSelectSubtitles": "Select Subtitles", + "ButtonMarkForRemoval": "Mark for removal from device", + "ButtonUnmarkForRemoval": "Unmark for removal from device", + "LabelDefaultStream": "(Default)", + "LabelForcedStream": "(Forced)", + "LabelDefaultForcedStream": "(Default\/Forced)", + "LabelUnknownLanguage": "Unknown language", + "MessageConfirmSyncJobItemCancellation": "Are you sure you wish to cancel this item?", + "ButtonMute": "Mute", + "ButtonUnmute": "Unmute", + "ButtonStop": "Stop", + "ButtonNextTrack": "\u0421\u043b\u0435\u0434\u0432\u0430\u0449\u0430 \u043f\u044a\u0442\u0435\u043a\u0430", + "ButtonPause": "Pause", + "ButtonPlay": "\u041f\u0443\u0441\u043d\u0438", + "ButtonEdit": "\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0430\u0439", + "ButtonQueue": "Queue", + "ButtonPlayTrailer": "\u041f\u0443\u0441\u043d\u0438 \u0442\u0440\u0435\u0439\u043b\u044a\u0440\u0430", + "ButtonPlaylist": "Playlist", + "ButtonPreviousTrack": "\u041f\u0440\u0435\u0434\u0438\u0448\u043d\u0430 \u043f\u044a\u0442\u0435\u043a\u0430", + "LabelEnabled": "Enabled", + "LabelDisabled": "Disabled", + "ButtonMoreInformation": "More Information", + "LabelNoUnreadNotifications": "No unread notifications.", + "ButtonViewNotifications": "View notifications", + "ButtonMarkTheseRead": "Mark these read", + "ButtonClose": "Close", + "LabelAllPlaysSentToPlayer": "All plays will be sent to the selected player.", + "MessageInvalidUser": "Invalid username or password. Please try again.", + "HeaderLoginFailure": "Login Failure", + "HeaderAllRecordings": "\u0412\u0441\u0438\u0447\u043a\u0438 \u0417\u0430\u043f\u0438\u0441\u0438", + "RecommendationBecauseYouLike": "Because you like {0}", + "RecommendationBecauseYouWatched": "Because you watched {0}", + "RecommendationDirectedBy": "Directed by {0}", + "RecommendationStarring": "Starring {0}", + "HeaderConfirmRecordingCancellation": "Confirm Recording Cancellation", + "MessageConfirmRecordingCancellation": "Are you sure you wish to cancel this recording?", + "MessageRecordingCancelled": "Recording cancelled.", + "HeaderConfirmSeriesCancellation": "Confirm Series Cancellation", + "MessageConfirmSeriesCancellation": "Are you sure you wish to cancel this series?", + "MessageSeriesCancelled": "Series cancelled.", + "HeaderConfirmRecordingDeletion": "Confirm Recording Deletion", + "MessageConfirmRecordingDeletion": "Are you sure you wish to delete this recording?", + "MessageRecordingDeleted": "Recording deleted.", + "ButonCancelRecording": "Cancel Recording", + "MessageRecordingSaved": "Recording saved.", + "OptionSunday": "\u041d\u0435\u0434\u0435\u043b\u044f", + "OptionMonday": "\u041f\u043e\u043d\u0435\u0434\u0435\u043b\u043d\u0438\u043a", + "OptionTuesday": "\u0412\u0442\u043e\u0440\u043d\u0438\u043a", + "OptionWednesday": "\u0421\u0440\u044f\u0434\u0430", + "OptionThursday": "\u0427\u0435\u0442\u0432\u044a\u0440\u0442\u044a\u043a", + "OptionFriday": "\u041f\u0435\u0442\u044a\u043a", + "OptionSaturday": "\u0421\u044a\u0431\u043e\u0442\u0430", + "HeaderConfirmDeletion": "Confirm Deletion", + "MessageConfirmPathSubstitutionDeletion": "Are you sure you wish to delete this path substitution?", + "LiveTvUpdateAvailable": "(Update available)", + "LabelVersionUpToDate": "Up to date!", + "ButtonResetTuner": "Reset tuner", + "HeaderResetTuner": "Reset Tuner", + "MessageConfirmResetTuner": "Are you sure you wish to reset this tuner? Any active players or recordings will be abruptly stopped.", + "ButtonCancelSeries": "Cancel Series", + "HeaderSeriesRecordings": "Series Recordings", + "LabelAnytime": "Any time", + "StatusRecording": "Recording", + "StatusWatching": "Watching", + "StatusRecordingProgram": "Recording {0}", + "StatusWatchingProgram": "Watching {0}", + "HeaderSplitMedia": "Split Media Apart", + "MessageConfirmSplitMedia": "Are you sure you wish to split the media sources into separate items?", + "HeaderError": "Error", + "MessagePleaseSelectOneItem": "Please select at least one item.", + "MessagePleaseSelectTwoItems": "Please select at least two items.", + "MessageTheFollowingItemsWillBeGrouped": "The following titles will be grouped into one item:", + "MessageConfirmItemGrouping": "Media Browser clients will automatically choose the optimal version to play based on device and network performance. Are you sure you wish to continue?", + "HeaderResume": "\u041f\u0440\u043e\u0436\u044a\u043b\u0436\u0438", + "HeaderMyViews": "My Views", + "HeaderLibraryFolders": "Media Folders", + "HeaderLatestMedia": "Latest Media", + "ButtonMoreItems": "More...", + "ButtonMore": "More", + "HeaderFavoriteMovies": "Favorite Movies", + "HeaderFavoriteShows": "Favorite Shows", + "HeaderFavoriteEpisodes": "Favorite Episodes", + "HeaderFavoriteGames": "Favorite Games", + "HeaderRatingsDownloads": "Rating \/ Downloads", + "HeaderConfirmProfileDeletion": "Confirm Profile Deletion", + "MessageConfirmProfileDeletion": "Are you sure you wish to delete this profile?", + "HeaderSelectServerCachePath": "Select Server Cache Path", + "HeaderSelectTranscodingPath": "Select Transcoding Temporary Path", + "HeaderSelectImagesByNamePath": "Select Images By Name Path", + "HeaderSelectMetadataPath": "Select Metadata Path", + "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable.", + "HeaderSelectTranscodingPathHelp": "Browse or enter the path to use for transcoding temporary files. The folder must be writeable.", + "HeaderSelectImagesByNamePathHelp": "Browse or enter the path to your items by name folder. The folder must be writeable.", + "HeaderSelectMetadataPathHelp": "Browse or enter the path you'd like to store metadata within. The folder must be writeable.", + "HeaderSelectChannelDownloadPath": "Select Channel Download Path", + "HeaderSelectChannelDownloadPathHelp": "Browse or enter the path to use for storing channel cache files. The folder must be writeable.", + "OptionNewCollection": "New...", + "ButtonAdd": "\u0414\u043e\u0431\u0430\u0432\u0438", + "ButtonRemove": "\u041f\u0440\u0435\u043c\u0430\u0445\u043d\u0438", + "LabelChapterDownloaders": "Chapter downloaders:", + "LabelChapterDownloadersHelp": "Enable and rank your preferred chapter downloaders in order of priority. Lower priority downloaders will only be used to fill in missing information.", + "HeaderFavoriteAlbums": "Favorite Albums", + "HeaderLatestChannelMedia": "Latest Channel Items", + "ButtonOrganizeFile": "Organize File", + "ButtonDeleteFile": "Delete File", + "HeaderOrganizeFile": "Organize File", + "HeaderDeleteFile": "Delete File", + "StatusSkipped": "Skipped", + "StatusFailed": "Failed", + "StatusSuccess": "Success", + "MessageFileWillBeDeleted": "The following file will be deleted:", + "MessageSureYouWishToProceed": "Are you sure you wish to proceed?", + "MessageDuplicatesWillBeDeleted": "In addition the following dupliates will be deleted:", + "MessageFollowingFileWillBeMovedFrom": "The following file will be moved from:", + "MessageDestinationTo": "to:", + "HeaderSelectWatchFolder": "Select Watch Folder", + "HeaderSelectWatchFolderHelp": "Browse or enter the path to your watch folder. The folder must be writeable.", + "OrganizePatternResult": "Result: {0}", + "HeaderRestart": "Restart", + "HeaderShutdown": "Shutdown", + "MessageConfirmRestart": "Are you sure you wish to restart Media Browser Server?", + "MessageConfirmShutdown": "Are you sure you wish to shutdown Media Browser Server?", + "ButtonUpdateNow": "Update Now", + "NewVersionOfSomethingAvailable": "A new version of {0} is available!", + "VersionXIsAvailableForDownload": "Version {0} is now available for download.", + "LabelVersionNumber": "Version {0}", + "LabelPlayMethodTranscoding": "Transcoding", + "LabelPlayMethodDirectStream": "Direct Streaming", + "LabelPlayMethodDirectPlay": "Direct Playing", + "LabelAudioCodec": "Audio: {0}", + "LabelVideoCodec": "Video: {0}", + "LabelLocalAccessUrl": "Local access: {0}", + "LabelRemoteAccessUrl": "Remote access: {0}", + "LabelRunningOnPort": "Running on http port {0}.", + "LabelRunningOnPorts": "Running on http port {0}, and https port {1}.", + "HeaderLatestFromChannel": "Latest from {0}", + "ButtonDownload": "Download", + "LabelUnknownLanaguage": "Unknown language", + "HeaderCurrentSubtitles": "Current Subtitles", + "MessageDownloadQueued": "The download has been queued.", + "MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?", + "ButtonRemoteControl": "Remote Control", + "HeaderLatestTvRecordings": "Latest Recordings", + "ButtonOk": "\u041e\u043a", + "ButtonCancel": "\u041e\u0442\u043c\u0435\u043d\u0438", + "ButtonRefresh": "\u041e\u0431\u043d\u043e\u0432\u0438", + "LabelCurrentPath": "Current path:", + "HeaderSelectMediaPath": "Select Media Path", + "HeaderSelectPath": "Select Path", + "ButtonNetwork": "Network", + "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.", + "HeaderMenu": "Menu", + "ButtonOpen": "Open", + "ButtonOpenInNewTab": "Open in new tab", + "ButtonShuffle": "Shuffle", + "ButtonInstantMix": "Instant mix", + "ButtonResume": "Resume", + "HeaderScenes": "\u0421\u0446\u0435\u043d\u0438", + "HeaderAudioTracks": "Audio Tracks", + "HeaderLibraries": "Libraries", + "HeaderSubtitles": "Subtitles", + "HeaderVideoQuality": "Video Quality", + "MessageErrorPlayingVideo": "There was an error playing the video.", + "MessageEnsureOpenTuner": "Please ensure there is an open tuner availalble.", + "ButtonHome": "Home", + "ButtonDashboard": "Dashboard", + "ButtonReports": "Reports", + "ButtonMetadataManager": "Metadata Manager", + "HeaderTime": "Time", + "HeaderName": "Name", + "HeaderAlbum": "Album", + "HeaderAlbumArtist": "Album Artist", + "HeaderArtist": "Artist", + "LabelAddedOnDate": "Added {0}", + "ButtonStart": "Start", + "HeaderChannels": "\u041a\u0430\u043d\u0430\u043b\u0438", + "HeaderMediaFolders": "\u041c\u0435\u0434\u0438\u0439\u043d\u0438 \u041f\u0430\u043f\u043a\u0438", + "HeaderBlockItemsWithNoRating": "Block items with no rating information:", + "OptionBlockOthers": "Others", + "OptionBlockTvShows": "TV Shows", + "OptionBlockTrailers": "Trailers", + "OptionBlockMusic": "Music", + "OptionBlockMovies": "Movies", + "OptionBlockBooks": "Books", + "OptionBlockGames": "Games", + "OptionBlockLiveTvPrograms": "Live TV Programs", + "OptionBlockLiveTvChannels": "Live TV Channels", + "OptionBlockChannelContent": "Internet Channel Content", + "ButtonRevoke": "Revoke", + "MessageConfirmRevokeApiKey": "Are you sure you wish to revoke this api key? The application's connection to Media Browser will be abruptly terminated.", + "HeaderConfirmRevokeApiKey": "Revoke Api Key", + "ValueContainer": "Container: {0}", + "ValueAudioCodec": "Audio Codec: {0}", + "ValueVideoCodec": "Video Codec: {0}", + "ValueCodec": "Codec: {0}", + "ValueConditions": "Conditions: {0}", + "LabelAll": "All", + "HeaderDeleteImage": "Delete Image", + "MessageFileNotFound": "File not found.", + "MessageFileReadError": "An error occurred reading this file.", + "ButtonNextPage": "Next Page", + "ButtonPreviousPage": "Previous Page", + "ButtonMoveLeft": "Move left", + "ButtonMoveRight": "Move right", + "ButtonBrowseOnlineImages": "Browse online images", + "HeaderDeleteItem": "Delete Item", + "ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?", + "MessagePleaseEnterNameOrId": "Please enter a name or an external Id.", + "MessageValueNotCorrect": "The value entered is not correct. Please try again.", + "MessageItemSaved": "Item saved.", + "MessagePleaseAcceptTermsOfServiceBeforeContinuing": "Please accept the terms of service before continuing.", + "OptionEnded": "\u041f\u0440\u0438\u043a\u043b\u044e\u0447\u0438\u043b\u043e", + "OptionContinuing": "\u041f\u0440\u043e\u0434\u044a\u043b\u0436\u0430\u0432\u0430\u0449\u043e", + "OptionOff": "Off", + "OptionOn": "On", + "ButtonSettings": "Settings", + "ButtonUninstall": "Uninstall", + "HeaderFields": "Fields", + "HeaderFieldsHelp": "Slide a field to 'off' to lock it and prevent it's data from being changed.", + "HeaderLiveTV": "Live TV", + "MissingLocalTrailer": "Missing local trailer.", + "MissingPrimaryImage": "Missing primary image.", + "MissingBackdropImage": "Missing backdrop image.", + "MissingLogoImage": "Missing logo image.", + "MissingEpisode": "Missing episode.", + "OptionScreenshots": "Screenshots", + "OptionBackdrops": "Backdrops", + "OptionImages": "Images", + "OptionKeywords": "Keywords", + "OptionTags": "Tags", + "OptionStudios": "Studios", + "OptionName": "Name", + "OptionOverview": "Overview", + "OptionGenres": "Genres", + "OptionParentalRating": "\u0420\u043e\u0434\u0438\u0442\u0435\u043b\u0441\u043a\u0438 \u0420\u0435\u0439\u0442\u0438\u043d\u0433", + "OptionPeople": "People", + "OptionRuntime": "\u0412\u0440\u0435\u043c\u0435\u0442\u0440\u0430\u0435\u043d\u0435", + "OptionProductionLocations": "Production Locations", + "OptionBirthLocation": "Birth Location", + "LabelAllChannels": "All channels", + "LabelLiveProgram": "LIVE", + "LabelNewProgram": "NEW", + "LabelPremiereProgram": "PREMIERE", + "LabelHDProgram": "HD", + "HeaderChangeFolderType": "Change Content Type", + "HeaderChangeFolderTypeHelp": "To change the type, please remove and rebuild the folder with the new type.", + "HeaderAlert": "Alert", + "MessagePleaseRestart": "Please restart to finish updating.", + "ButtonRestart": "Restart", + "MessagePleaseRefreshPage": "Please refresh this page to receive new updates from the server.", + "ButtonHide": "Hide", + "MessageSettingsSaved": "Settings saved.", + "ButtonSignOut": "Sign Out", + "ButtonMyProfile": "My Profile", + "ButtonMyPreferences": "My Preferences", + "MessageBrowserDoesNotSupportWebSockets": "This browser does not support web sockets. For a better experience, try a newer browser such as Chrome, Firefox, IE10+, Safari (iOS) or Opera.", + "LabelInstallingPackage": "Installing {0}", + "LabelPackageInstallCompleted": "{0} installation completed.", + "LabelPackageInstallFailed": "{0} installation failed.", + "LabelPackageInstallCancelled": "{0} installation cancelled.", + "TabServer": "\u0421\u044a\u0440\u0432\u044a\u0440", + "TabUsers": "Users", + "TabLibrary": "Library", + "TabMetadata": "\u041c\u0435\u0442\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f", + "TabDLNA": "DLNA", + "TabLiveTV": "Live TV", + "TabAutoOrganize": "Auto-Organize", + "TabPlugins": "Plugins", + "TabAdvanced": "\u0414\u043e\u043f\u044a\u043b\u043d\u0438\u0442\u0435\u043b\u043d\u0438", + "TabHelp": "Help", + "TabScheduledTasks": "Scheduled Tasks", + "ButtonFullscreen": "\u0426\u044f\u043b \u0435\u043a\u0440\u0430\u043d", + "ButtonAudioTracks": "\u0410\u0443\u0434\u0438\u043e \u043f\u044a\u0442\u0435\u043a\u0430", + "ButtonSubtitles": "Subtitles", + "ButtonScenes": "Scenes", + "ButtonQuality": "Quality", + "HeaderNotifications": "Notifications", + "HeaderSelectPlayer": "Select Player:", + "ButtonSelect": "\u0418\u0437\u0431\u0435\u0440\u0438", + "ButtonNew": "\u041d\u043e\u0432", + "MessageInternetExplorerWebm": "For best results with Internet Explorer please install the WebM playback plugin.", + "HeaderVideoError": "Video Error", + "ButtonAddToPlaylist": "Add to playlist", + "HeaderAddToPlaylist": "Add to Playlist", + "LabelName": "\u0418\u043c\u0435:", + "ButtonSubmit": "Submit", + "LabelSelectPlaylist": "Playlist:", + "OptionNewPlaylist": "New playlist...", + "MessageAddedToPlaylistSuccess": "Ok", + "ButtonView": "View", + "ButtonViewSeriesRecording": "View series recording", + "ValueOriginalAirDate": "Original air date: {0}", + "ButtonRemoveFromPlaylist": "Remove from playlist", + "HeaderSpecials": "Specials", + "HeaderTrailers": "Trailers", + "HeaderAudio": "\u0410\u0443\u0434\u0438\u043e", + "HeaderResolution": "Resolution", + "HeaderVideo": "\u0412\u0438\u0434\u0435\u043e", + "HeaderRuntime": "Runtime", + "HeaderCommunityRating": "Community rating", + "HeaderParentalRating": "Parental rating", + "HeaderReleaseDate": "Release date", + "HeaderDateAdded": "Date added", + "HeaderSeries": "Series", + "HeaderSeason": "Season", + "HeaderSeasonNumber": "Season number", + "HeaderNetwork": "Network", + "HeaderYear": "Year", + "HeaderGameSystem": "Game system", + "HeaderPlayers": "Players", + "HeaderEmbeddedImage": "Embedded image", + "HeaderTrack": "Track", + "HeaderDisc": "Disc", + "OptionMovies": "\u0424\u0438\u043b\u043c\u0438", + "OptionCollections": "Collections", + "OptionSeries": "Series", + "OptionSeasons": "Seasons", + "OptionEpisodes": "\u0415\u043f\u0438\u0437\u043e\u0434\u0438", + "OptionGames": "Games", + "OptionGameSystems": "Game systems", + "OptionMusicArtists": "Music artists", + "OptionMusicAlbums": "Music albums", + "OptionMusicVideos": "Music videos", + "OptionSongs": "Songs", + "OptionHomeVideos": "Home videos", + "OptionBooks": "Books", + "OptionAdultVideos": "Adult videos", + "ButtonUp": "Up", + "ButtonDown": "Down", + "LabelMetadataReaders": "Metadata readers:", + "LabelMetadataReadersHelp": "Rank your preferred local metadata sources in order of priority. The first file found will be read.", + "LabelMetadataDownloaders": "Metadata downloaders:", + "LabelMetadataDownloadersHelp": "Enable and rank your preferred metadata downloaders in order of priority. Lower priority downloaders will only be used to fill in missing information.", + "LabelMetadataSavers": "Metadata savers:", + "LabelMetadataSaversHelp": "Choose the file formats to save your metadata to.", + "LabelImageFetchers": "Image fetchers:", + "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": "\u0414\u0430\u0442\u0430 \u043d\u0430 \u0438\u0437\u0434\u0430\u0432\u0430\u043d\u0435", + "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:", + "LabelBirthDate": "Birth date:", + "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", + "HeaderMediaLocations": "Media Locations", + "LabelContentTypeValue": "Content type: {0}", + "LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.", + "FolderTypeUnset": "Unset (mixed content)", + "FolderTypeMovies": "\u0424\u0438\u043b\u043c\u0438", + "FolderTypeMusic": "\u041c\u0443\u0437\u0438\u043a\u0430", + "FolderTypeAdultVideos": "\u041a\u043b\u0438\u043f\u043e\u0432\u0435 \u0437\u0430 \u0432\u044a\u0437\u0440\u0430\u0441\u0442\u043d\u0438", + "FolderTypePhotos": "\u0421\u043d\u0438\u043c\u043a\u0438", + "FolderTypeMusicVideos": "\u041c\u0443\u0437\u0438\u043a\u0430\u043b\u043d\u0438 \u043a\u043b\u0438\u043f\u043e\u0432\u0435", + "FolderTypeHomeVideos": "\u0414\u043e\u043c\u0430\u0448\u043d\u0438 \u043a\u043b\u0438\u043f\u043e\u0432\u0435", + "FolderTypeGames": "\u0418\u0433\u0440\u0438", + "FolderTypeBooks": "\u041a\u043d\u0438\u0433\u0438", + "FolderTypeTvShows": "TV", + "TabMovies": "\u0424\u0438\u043b\u043c\u0438", + "TabSeries": "\u041f\u0440\u0435\u0434\u0430\u0432\u0430\u043d\u0438\u044f", + "TabEpisodes": "\u0415\u043f\u0438\u0437\u043e\u0434\u0438", + "TabTrailers": "\u0422\u0440\u0435\u0439\u043b\u044a\u0440\u0438", + "TabGames": "\u0418\u0433\u0440\u0438", + "TabAlbums": "\u0410\u043b\u0431\u0443\u043c\u0438", + "TabSongs": "\u041f\u0435\u0441\u043d\u0438", + "TabMusicVideos": "\u041c\u0443\u0437\u0438\u043a\u0430\u043b\u043d\u0438 \u043a\u043b\u0438\u043f\u043e\u0432\u0435", + "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)", + "MessageFeatureIncludedWithSupporter": "You are registered for this feature, and will be able to continue using it with an active supporter membership.", + "MessageChangeRecurringPlanConfirm": "After completing this transaction you will need to cancel your previous recurring donation from within your PayPal account. Thank you for supporting Media Browser.", + "MessageSupporterMembershipExpiredOn": "Your supporter membership expired on {0}.", + "MessageYouHaveALifetimeMembership": "You have a lifetime supporter membership. You can provide additional donations on a one-time or recurring basis using the options below. Thank you for supporting Media Browser.", + "MessageYouHaveAnActiveRecurringMembership": "You have an active {0} membership. You can upgrade your plan using the options below.", + "ButtonDelete": "\u0418\u0437\u0442\u0440\u0438\u0439", + "HeaderMediaBrowserAccountAdded": "Media Browser Account Added", + "MessageMediaBrowserAccountAdded": "The Media Browser account has been added to this user.", + "MessagePendingMediaBrowserAccountAdded": "The Media Browser account has been added to this user. An email will be sent to the owner of the account. The invitation will need to be confirmed by clicking a link within the email.", + "HeaderMediaBrowserAccountRemoved": "Media Browser Account Removed", + "MessageMediaBrowserAccontRemoved": "The Media Browser account has been removed from this user.", + "TooltipLinkedToMediaBrowserConnect": "Linked to Media Browser Connect", + "HeaderUnrated": "Unrated", + "ValueDiscNumber": "Disc {0}", + "HeaderUnknownDate": "Unknown Date", + "HeaderUnknownYear": "Unknown Year", + "ValueMinutes": "{0} min", + "ButtonPlayExternalPlayer": "Play with external player", + "HeaderSelectExternalPlayer": "Select External Player", + "HeaderExternalPlayerPlayback": "External Player Playback", + "ButtonImDone": "I'm Done", + "OptionWatched": "Watched", + "OptionUnwatched": "Unwatched", + "ExternalPlayerPlaystateOptionsHelp": "Specify how you would like to resume playing this video next time.", + "LabelMarkAs": "Mark as:", + "OptionInProgress": "In-Progress", + "LabelResumePoint": "Resume point:", + "ValueOneMovie": "1 movie", + "ValueMovieCount": "{0} movies", + "ValueOneTrailer": "1 trailer", + "ValueTrailerCount": "{0} trailers", + "ValueOneSeries": "1 series", + "ValueSeriesCount": "{0} series", + "ValueOneEpisode": "1 episode", + "ValueEpisodeCount": "{0} episodes", + "ValueOneGame": "1 game", + "ValueGameCount": "{0} games", + "ValueOneAlbum": "1 album", + "ValueAlbumCount": "{0} albums", + "ValueOneSong": "1 song", + "ValueSongCount": "{0} songs", + "ValueOneMusicVideo": "1 music video", + "ValueMusicVideoCount": "{0} music videos", + "HeaderOffline": "Offline", + "HeaderUnaired": "Unaired", + "HeaderMissing": "Missing", + "ButtonWebsite": "Website", + "TooltipFavorite": "Favorite", + "TooltipLike": "Like", + "TooltipDislike": "Dislike", + "TooltipPlayed": "Played", + "ValueSeriesYearToPresent": "{0}-Present", + "ValueAwards": "Awards: {0}", + "ValueBudget": "Budget: {0}", + "ValueRevenue": "Revenue: {0}", + "ValuePremiered": "Premiered {0}", + "ValuePremieres": "Premieres {0}", + "ValueStudio": "Studio: {0}", + "ValueStudios": "Studios: {0}", + "ValueSpecialEpisodeName": "Special - {0}", + "LabelLimit": "Limit:", + "ValueLinks": "Links: {0}", + "HeaderPeople": "People", + "HeaderCastAndCrew": "Cast & Crew", + "ValueArtist": "Artist: {0}", + "ValueArtists": "Artists: {0}", + "HeaderTags": "Tags", + "MediaInfoCameraMake": "Camera make", + "MediaInfoCameraModel": "Camera model", + "MediaInfoAltitude": "Altitude", + "MediaInfoAperture": "Aperture", + "MediaInfoExposureTime": "Exposure time", + "MediaInfoFocalLength": "Focal length", + "MediaInfoOrientation": "Orientation", + "MediaInfoIsoSpeedRating": "Iso speed rating", + "MediaInfoLatitude": "Latitude", + "MediaInfoLongitude": "Longitude", + "MediaInfoShutterSpeed": "Shutter speed", + "MediaInfoSoftware": "Software", + "HeaderIfYouLikeCheckTheseOut": "If you like {0}, check these out...", + "HeaderPlotKeywords": "Plot Keywords", + "HeaderMovies": "Movies", + "HeaderAlbums": "Albums", + "HeaderGames": "Games", + "HeaderBooks": "Books", + "HeaderEpisodes": "\u0415\u043f\u0438\u0437\u043e\u0434\u0438", + "HeaderSeasons": "Seasons", + "HeaderTracks": "Tracks", + "HeaderItems": "Items", + "HeaderOtherItems": "Other Items", + "ButtonFullReview": "Full review", + "ValueAsRole": "as {0}", + "ValueGuestStar": "Guest star", + "MediaInfoSize": "Size", + "MediaInfoPath": "Path", + "MediaInfoFormat": "Format", + "MediaInfoContainer": "Container", + "MediaInfoDefault": "Default", + "MediaInfoForced": "Forced", + "MediaInfoExternal": "External", + "MediaInfoTimestamp": "Timestamp", + "MediaInfoPixelFormat": "Pixel format", + "MediaInfoBitDepth": "Bit depth", + "MediaInfoSampleRate": "Sample rate", + "MediaInfoBitrate": "Bitrate", + "MediaInfoChannels": "Channels", + "MediaInfoLayout": "Layout", + "MediaInfoLanguage": "Language", + "MediaInfoCodec": "Codec", + "MediaInfoProfile": "Profile", + "MediaInfoLevel": "Level", + "MediaInfoAspectRatio": "Aspect ratio", + "MediaInfoResolution": "Resolution", + "MediaInfoAnamorphic": "Anamorphic", + "MediaInfoInterlaced": "Interlaced", + "MediaInfoFramerate": "Framerate", + "MediaInfoStreamTypeAudio": "Audio", + "MediaInfoStreamTypeData": "Data", + "MediaInfoStreamTypeVideo": "Video", + "MediaInfoStreamTypeSubtitle": "Subtitle", + "MediaInfoStreamTypeEmbeddedImage": "Embedded Image", + "MediaInfoRefFrames": "Ref frames", + "TabPlayback": "Playback", + "TabNotifications": "\u0418\u0437\u0432\u0435\u0441\u0442\u0438\u044f", + "TabExpert": "Expert", + "HeaderSelectCustomIntrosPath": "Select Custom Intros Path", + "HeaderRateAndReview": "Rate and Review", + "HeaderThankYou": "Thank You", + "MessageThankYouForYourReview": "Thank you for your review.", + "LabelYourRating": "Your rating:", + "LabelFullReview": "Full review:", + "LabelShortRatingDescription": "Short rating summary:", + "OptionIRecommendThisItem": "I recommend this item", + "WebClientTourContent": "View your recently added media, next episodes, and more. The green circles indicate how many unplayed items you have.", + "WebClientTourMovies": "Play movies, trailers and more from any device with a web browser", + "WebClientTourMouseOver": "Hold the mouse over any poster for quick access to important information", + "WebClientTourTapHold": "Tap and hold or right click any poster for a context menu", + "WebClientTourMetadataManager": "Click edit to open the metadata manager", + "WebClientTourPlaylists": "Easily create playlists and instant mixes, and play them on any device", + "WebClientTourCollections": "Create movie collections to group box sets together", + "WebClientTourUserPreferences1": "User preferences allow you to customize the way your library is presented in all of your Media Browser apps", + "WebClientTourUserPreferences2": "Configure your audio and subtitle language settings once, for every Media Browser app", + "WebClientTourUserPreferences3": "Design the web client home page to your liking", + "WebClientTourUserPreferences4": "Configure backdrops, theme songs and external players", + "WebClientTourMobile1": "The web client works great on smartphones and tablets...", + "WebClientTourMobile2": "and easily controls other devices and Media Browser apps", + "MessageEnjoyYourStay": "Enjoy your stay", + "DashboardTourDashboard": "The server dashboard allows you to monitor your server and your users. You'll always know who is doing what and where they are.", + "DashboardTourHelp": "In-app help provides easy buttons to open wiki pages relating to the on-screen content.", + "DashboardTourUsers": "Easily create user accounts for your friends and family, each with their own permissions, library access, parental controls and more.", + "DashboardTourCinemaMode": "Cinema mode brings the theater experience straight to your living room with the ability to play trailers and custom intros before the main feature.", + "DashboardTourChapters": "Enable chapter image generation for your videos for a more pleasing presentation while viewing.", + "DashboardTourSubtitles": "Automatically download subtitles for your videos in any language.", + "DashboardTourPlugins": "Install plugins such as internet video channels, live tv, metadata scanners, and more.", + "DashboardTourNotifications": "Automatically send notifications of server events to your mobile device, email and more.", + "DashboardTourScheduledTasks": "Easily manage long running operations with scheduled tasks. Decide when they run, and how often.", + "DashboardTourMobile": "The Media Browser dashboard works great on smartphones and tablets. Manage your server from the palm of your hand anytime, anywhere.", + "MessageRefreshQueued": "Refresh queued", + "TabDevices": "Devices", + "TabExtras": "Extras", + "DeviceLastUsedByUserName": "Last used by {0}", + "HeaderDeleteDevice": "Delete Device", + "DeleteDeviceConfirmation": "Are you sure you wish to delete this device? It will reappear the next time a user signs in with it.", + "LabelEnableCameraUploadFor": "Enable camera upload for:", + "HeaderSelectUploadPath": "Select Upload Path", + "LabelEnableCameraUploadForHelp": "Uploads will occur automatically in the background when signed into Media Browser.", + "ErrorMessageStartHourGreaterThanEnd": "End time must be greater than the start time.", + "ButtonLibraryAccess": "Library access", + "ButtonParentalControl": "Parental control", + "HeaderInvitationSent": "Invitation Sent", + "MessageInvitationSentToUser": "An email has been sent to {0}, inviting them to accept your sharing invitation.", + "MessageInvitationSentToNewUser": "An email has been sent to {0} inviting them to sign up with Media Browser.", + "HeaderConnectionFailure": "Connection Failure", + "MessageUnableToConnectToServer": "We're unable to connect to the selected server right now. Please ensure it is running and try again.", + "ButtonSelectServer": "Select server", + "MessagePluginConfigurationRequiresLocalAccess": "To configure this plugin please sign in to your local server directly.", + "MessageLoggedOutParentalControl": "Access is currently restricted. Please try again later.", + "DefaultErrorMessage": "There was an error processing the request. Please try again later.", + "ButtonAccept": "Accept", + "ButtonReject": "Reject", + "HeaderForgotPassword": "Forgot Password", + "MessageContactAdminToResetPassword": "Please contact your system administrator to reset your password.", + "MessageForgotPasswordInNetworkRequired": "Please try again within your home network to initiate the password reset process.", + "MessageForgotPasswordFileCreated": "The following file has been created on your server and contains instructions on how to proceed:", + "MessageForgotPasswordFileExpiration": "The reset pin will expire at {0}.", + "MessageInvalidForgotPasswordPin": "An invalid or expired pin was entered. Please try again.", + "MessagePasswordResetForUsers": "Passwords have been reset for the following users:", + "HeaderInviteGuest": "Invite Guest", + "ButtonLinkMyMediaBrowserAccount": "Link my account now", + "MessageConnectAccountRequiredToInviteGuest": "In order to invite guests you need to first link your Media Browser account to this server.", + "ButtonSync": "Sync", + "SyncMedia": "Sync Media", + "HeaderCancelSyncJob": "Cancel Sync", + "CancelSyncJobConfirmation": "Are you sure you wish to cancel this sync job?", + "TabSync": "Sync", + "MessagePleaseSelectDeviceToSyncTo": "Please select a device to sync to.", + "MessageSyncJobCreated": "Sync job created.", + "LabelSyncTo": "Sync to:", + "LabelSyncJobName": "Sync job name:", + "LabelQuality": "Quality:", + "OptionHigh": "High", + "OptionMedium": "Medium", + "OptionLow": "Low", + "HeaderSettings": "Settings", + "OptionAutomaticallySyncNewContent": "Automatically sync new content", + "OptionAutomaticallySyncNewContentHelp": "New content added to this category will be automatically synced to the device.", + "OptionSyncUnwatchedVideosOnly": "Sync unwatched videos only", + "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched.", + "LabelItemLimit": "Item limit:", + "LabelItemLimitHelp": "Optional. Set a limit to the number of items that will be synced.", + "MessageBookPluginRequired": "Requires installation of the Bookshelf plugin", + "MessageGamePluginRequired": "Requires installation of the GameBrowser plugin", + "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders.", + "SyncJobItemStatusQueued": "Queued", + "SyncJobItemStatusConverting": "Converting", + "SyncJobItemStatusTransferring": "Transferring", + "SyncJobItemStatusSynced": "Synced", + "SyncJobItemStatusFailed": "Failed", + "SyncJobItemStatusRemovedFromDevice": "Removed from device", + "SyncJobItemStatusCancelled": "Cancelled", + "MessageJobItemHasNoActions": "d" +}
\ 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 fb95139e6..16b73f46c 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/ca.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/ca.json @@ -6,6 +6,8 @@ "Administrator": "Administrador", "Password": "Contrasenya", "DeleteImage": "Esborrar Imatge", + "MessageThankYouForSupporting": "Thank you for supporting Media Browser.", + "MessagePleaseSupportMediaBrowser": "Please support Media Browser.", "DeleteImageConfirmation": "Esteu segur que voleu suprimir aquesta imatge?", "FileReadCancelled": "La lectura de l'arxiu ha estat cancel\u00b7lada.", "FileNotFound": "Arxiu no trobat.", @@ -14,7 +16,10 @@ "DeleteUserConfirmation": "Are you sure you wish to delete this user?", "PasswordResetHeader": "Restablir contrasenya", "PasswordResetComplete": "La contrasenya s'ha restablert.", + "PinCodeResetComplete": "The pin code has been reset.", "PasswordResetConfirmation": "Esteu segur que voleu restablir la contrasenya?", + "PinCodeResetConfirmation": "Are you sure you wish to reset the pin code?", + "HeaderPinCodeReset": "Reset Pin Code", "PasswordSaved": "S'ha guardat la contrasenya.", "PasswordMatchError": "Confirmaci\u00f3 de la contrasenya i la contrasenya han de coincidir.", "OptionRelease": "Versi\u00f3 Oficial", @@ -32,6 +37,7 @@ "MessageKeyRemoved": "Thank you. Your supporter key has been removed.", "ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.", "HeaderSearch": "Search", + "ValueDateCreated": "Date created: {0}", "LabelArtist": "Artist", "LabelMovie": "Movie", "LabelMusicVideo": "Music Video", @@ -42,6 +48,17 @@ "LabelFailed": "(failed)", "ButtonHelp": "Help", "ButtonSave": "Save", + "LabelCollection": "Collection", + "HeaderAddToCollection": "Add to Collection", + "NewCollectionNameExample": "Example: Star Wars Collection", + "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata", + "LabelSelectCollection": "Select collection:", + "HeaderDevices": "Devices", + "ButtonScheduledTasks": "Scheduled tasks", + "MessageItemsAdded": "Items added", + "ButtonAddToCollection": "Add to collection", + "HeaderSelectCertificatePath": "Select Certificate Path", + "ConfirmMessageScheduledTaskButton": "This operation normally runs automatically as a scheduled task. It can also be run manually here. To configure the scheduled task, see:", "HeaderSupporterBenefit": "A supporter membership provides additional benefits such as access to premium plugins, internet channel content, and more. {0}Learn more{1}.", "HeaderWelcomeToMediaBrowserServerDashboard": "Welcome to the Media Browser Dashboard", "HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client", @@ -53,6 +70,10 @@ "HeaderChannelAccess": "Channel Access", "HeaderDeviceAccess": "Device Access", "HeaderSelectDevices": "Select Devices", + "ButtonCancelItem": "Cancel item", + "ButtonQueueForRetry": "Queue for retry", + "ButtonReenable": "Re-enable", + "SyncJobItemStatusSyncedMarkForRemoval": "Marked for removal", "LabelAbortedByServerShutdown": "(Aborted by server shutdown)", "LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.", "HeaderDeleteTaskTrigger": "Delete Task Trigger", @@ -64,10 +85,13 @@ "LabelFree": "Free", "HeaderSelectAudio": "Select Audio", "HeaderSelectSubtitles": "Select Subtitles", + "ButtonMarkForRemoval": "Mark for removal from device", + "ButtonUnmarkForRemoval": "Unmark for removal from device", "LabelDefaultStream": "(Default)", "LabelForcedStream": "(Forced)", "LabelDefaultForcedStream": "(Default\/Forced)", "LabelUnknownLanguage": "Unknown language", + "MessageConfirmSyncJobItemCancellation": "Are you sure you wish to cancel this item?", "ButtonMute": "Mute", "ButtonUnmute": "Unmute", "ButtonStop": "Stop", @@ -191,8 +215,10 @@ "LabelPlayMethodDirectPlay": "Direct Playing", "LabelAudioCodec": "Audio: {0}", "LabelVideoCodec": "Video: {0}", + "LabelLocalAccessUrl": "Local access: {0}", "LabelRemoteAccessUrl": "Remote access: {0}", - "LabelRunningOnPort": "Running on port {0}.", + "LabelRunningOnPort": "Running on http port {0}.", + "LabelRunningOnPorts": "Running on http port {0}, and https port {1}.", "HeaderLatestFromChannel": "Latest from {0}", "ButtonDownload": "Download", "LabelUnknownLanaguage": "Unknown language", @@ -206,6 +232,7 @@ "ButtonRefresh": "Refresh", "LabelCurrentPath": "Current path:", "HeaderSelectMediaPath": "Select Media Path", + "HeaderSelectPath": "Select Path", "ButtonNetwork": "Network", "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.", "HeaderMenu": "Menu", @@ -216,6 +243,7 @@ "ButtonResume": "Resume", "HeaderScenes": "Scenes", "HeaderAudioTracks": "Audio Tracks", + "HeaderLibraries": "Libraries", "HeaderSubtitles": "Subtitles", "HeaderVideoQuality": "Video Quality", "MessageErrorPlayingVideo": "There was an error playing the video.", @@ -581,6 +609,8 @@ "MediaInfoStreamTypeEmbeddedImage": "Embedded Image", "MediaInfoRefFrames": "Ref frames", "TabPlayback": "Playback", + "TabNotifications": "Notifications", + "TabExpert": "Expert", "HeaderSelectCustomIntrosPath": "Select Custom Intros Path", "HeaderRateAndReview": "Rate and Review", "HeaderThankYou": "Thank You", @@ -615,6 +645,7 @@ "DashboardTourMobile": "The Media Browser dashboard works great on smartphones and tablets. Manage your server from the palm of your hand anytime, anywhere.", "MessageRefreshQueued": "Refresh queued", "TabDevices": "Devices", + "TabExtras": "Extras", "DeviceLastUsedByUserName": "Last used by {0}", "HeaderDeleteDevice": "Delete Device", "DeleteDeviceConfirmation": "Are you sure you wish to delete this device? It will reappear the next time a user signs in with it.", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json index 9cf8d84c0..8473145e6 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json @@ -6,6 +6,8 @@ "Administrator": "Administr\u00e1tor", "Password": "Heslo", "DeleteImage": "Odstranit obr\u00e1zek", + "MessageThankYouForSupporting": "Thank you for supporting Media Browser.", + "MessagePleaseSupportMediaBrowser": "Please support Media Browser.", "DeleteImageConfirmation": "Jste si jisti, \u017ee chcete odstranit tento obr\u00e1zek?", "FileReadCancelled": "\u010cten\u00ed souboru bylo zru\u0161eno.", "FileNotFound": "Soubor nebyl nalezen.", @@ -14,7 +16,10 @@ "DeleteUserConfirmation": "Are you sure you wish to delete this user?", "PasswordResetHeader": "Obnovit heslo", "PasswordResetComplete": "Heslo bylo obnoveno.", + "PinCodeResetComplete": "The pin code has been reset.", "PasswordResetConfirmation": "Jste si jisti, \u017ee chcete obnovit heslo?", + "PinCodeResetConfirmation": "Are you sure you wish to reset the pin code?", + "HeaderPinCodeReset": "Reset Pin Code", "PasswordSaved": "Heslo ulo\u017eeno.", "PasswordMatchError": "Heslo a potvrzen\u00ed hesla mus\u00ed souhlasit.", "OptionRelease": "Ofici\u00e1ln\u00ed vyd\u00e1n\u00ed", @@ -32,6 +37,7 @@ "MessageKeyRemoved": "Thank you. Your supporter key has been removed.", "ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.", "HeaderSearch": "Vyhled\u00e1v\u00e1n\u00ed", + "ValueDateCreated": "Date created: {0}", "LabelArtist": "Um\u011blec", "LabelMovie": "Film", "LabelMusicVideo": "Hudebn\u00ed video", @@ -42,6 +48,17 @@ "LabelFailed": "(failed)", "ButtonHelp": "Help", "ButtonSave": "Ulo\u017eit", + "LabelCollection": "Collection", + "HeaderAddToCollection": "Add to Collection", + "NewCollectionNameExample": "P\u0159\u00edklad: Kolekce Star Wars", + "OptionSearchForInternetMetadata": "Prohledat internet pro nalezen\u00ed metadat a obalu.", + "LabelSelectCollection": "Select collection:", + "HeaderDevices": "Devices", + "ButtonScheduledTasks": "Scheduled tasks", + "MessageItemsAdded": "Items added", + "ButtonAddToCollection": "Add to collection", + "HeaderSelectCertificatePath": "Select Certificate Path", + "ConfirmMessageScheduledTaskButton": "This operation normally runs automatically as a scheduled task. It can also be run manually here. To configure the scheduled task, see:", "HeaderSupporterBenefit": "A supporter membership provides additional benefits such as access to premium plugins, internet channel content, and more. {0}Learn more{1}.", "HeaderWelcomeToMediaBrowserServerDashboard": "Welcome to the Media Browser Dashboard", "HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client", @@ -53,6 +70,10 @@ "HeaderChannelAccess": "Channel Access", "HeaderDeviceAccess": "Device Access", "HeaderSelectDevices": "Select Devices", + "ButtonCancelItem": "Cancel item", + "ButtonQueueForRetry": "Queue for retry", + "ButtonReenable": "Re-enable", + "SyncJobItemStatusSyncedMarkForRemoval": "Marked for removal", "LabelAbortedByServerShutdown": "(Aborted by server shutdown)", "LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.", "HeaderDeleteTaskTrigger": "Delete Task Trigger", @@ -64,10 +85,13 @@ "LabelFree": "Free", "HeaderSelectAudio": "Select Audio", "HeaderSelectSubtitles": "Select Subtitles", + "ButtonMarkForRemoval": "Mark for removal from device", + "ButtonUnmarkForRemoval": "Unmark for removal from device", "LabelDefaultStream": "(Default)", "LabelForcedStream": "(Forced)", "LabelDefaultForcedStream": "(Default\/Forced)", "LabelUnknownLanguage": "Unknown language", + "MessageConfirmSyncJobItemCancellation": "Are you sure you wish to cancel this item?", "ButtonMute": "Mute", "ButtonUnmute": "Unmute", "ButtonStop": "Stop", @@ -191,8 +215,10 @@ "LabelPlayMethodDirectPlay": "Direct Playing", "LabelAudioCodec": "Audio: {0}", "LabelVideoCodec": "Video: {0}", + "LabelLocalAccessUrl": "Local access: {0}", "LabelRemoteAccessUrl": "Remote access: {0}", - "LabelRunningOnPort": "Running on port {0}.", + "LabelRunningOnPort": "Running on http port {0}.", + "LabelRunningOnPorts": "Running on http port {0}, and https port {1}.", "HeaderLatestFromChannel": "Latest from {0}", "ButtonDownload": "St\u00e1hnout", "LabelUnknownLanaguage": "Unknown language", @@ -206,6 +232,7 @@ "ButtonRefresh": "Refresh", "LabelCurrentPath": "Current path:", "HeaderSelectMediaPath": "Select Media Path", + "HeaderSelectPath": "Select Path", "ButtonNetwork": "Network", "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.", "HeaderMenu": "Menu", @@ -216,6 +243,7 @@ "ButtonResume": "Pokra\u010dovat", "HeaderScenes": "Sc\u00e9ny", "HeaderAudioTracks": "Audio Tracks", + "HeaderLibraries": "Libraries", "HeaderSubtitles": "Titulky", "HeaderVideoQuality": "Video Quality", "MessageErrorPlayingVideo": "There was an error playing the video.", @@ -581,6 +609,8 @@ "MediaInfoStreamTypeEmbeddedImage": "Embedded Image", "MediaInfoRefFrames": "Ref frames", "TabPlayback": "Playback", + "TabNotifications": "Notifications", + "TabExpert": "Expert", "HeaderSelectCustomIntrosPath": "Select Custom Intros Path", "HeaderRateAndReview": "Rate and Review", "HeaderThankYou": "Thank You", @@ -615,6 +645,7 @@ "DashboardTourMobile": "The Media Browser dashboard works great on smartphones and tablets. Manage your server from the palm of your hand anytime, anywhere.", "MessageRefreshQueued": "Refresh queued", "TabDevices": "Devices", + "TabExtras": "Extras", "DeviceLastUsedByUserName": "Last used by {0}", "HeaderDeleteDevice": "Delete Device", "DeleteDeviceConfirmation": "Are you sure you wish to delete this device? It will reappear the next time a user signs in with it.", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/da.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/da.json index 7bd1ee293..5acae8560 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/da.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/da.json @@ -6,6 +6,8 @@ "Administrator": "Administrator", "Password": "Kode", "DeleteImage": "Slet Image", + "MessageThankYouForSupporting": "Thank you for supporting Media Browser.", + "MessagePleaseSupportMediaBrowser": "Please support Media Browser.", "DeleteImageConfirmation": "Er du sikker p\u00e5 du vil slette dette image?", "FileReadCancelled": "L\u00e6sning af filen er annulleret", "FileNotFound": "Filen blev ikke fundet", @@ -14,7 +16,10 @@ "DeleteUserConfirmation": "Er du sikker p\u00e5 du \u00f8nsker at slette denne bruger?", "PasswordResetHeader": "Nulstil kode", "PasswordResetComplete": "Koden er blevet nulstillet", + "PinCodeResetComplete": "The pin code has been reset.", "PasswordResetConfirmation": "Er du sikker p\u00e5 at koden skal nulstilles", + "PinCodeResetConfirmation": "Are you sure you wish to reset the pin code?", + "HeaderPinCodeReset": "Reset Pin Code", "PasswordSaved": "Koden er gemt", "PasswordMatchError": "Kode og kode bekr\u00e6ftelse skal v\u00e6re ens.", "OptionRelease": "Officiel Udgivelse", @@ -32,6 +37,7 @@ "MessageKeyRemoved": "Thank you. Your supporter key has been removed.", "ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.", "HeaderSearch": "Search", + "ValueDateCreated": "Date created: {0}", "LabelArtist": "Artist", "LabelMovie": "Movie", "LabelMusicVideo": "Music Video", @@ -42,6 +48,17 @@ "LabelFailed": "(failed)", "ButtonHelp": "Help", "ButtonSave": "Gem", + "LabelCollection": "Collection", + "HeaderAddToCollection": "Add to Collection", + "NewCollectionNameExample": "Example: Star Wars Collection", + "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata", + "LabelSelectCollection": "Select collection:", + "HeaderDevices": "Devices", + "ButtonScheduledTasks": "Scheduled tasks", + "MessageItemsAdded": "Items added", + "ButtonAddToCollection": "Add to collection", + "HeaderSelectCertificatePath": "Select Certificate Path", + "ConfirmMessageScheduledTaskButton": "This operation normally runs automatically as a scheduled task. It can also be run manually here. To configure the scheduled task, see:", "HeaderSupporterBenefit": "A supporter membership provides additional benefits such as access to premium plugins, internet channel content, and more. {0}Learn more{1}.", "HeaderWelcomeToMediaBrowserServerDashboard": "Welcome to the Media Browser Dashboard", "HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client", @@ -53,6 +70,10 @@ "HeaderChannelAccess": "Channel Access", "HeaderDeviceAccess": "Device Access", "HeaderSelectDevices": "Select Devices", + "ButtonCancelItem": "Cancel item", + "ButtonQueueForRetry": "Queue for retry", + "ButtonReenable": "Re-enable", + "SyncJobItemStatusSyncedMarkForRemoval": "Marked for removal", "LabelAbortedByServerShutdown": "(Aborted by server shutdown)", "LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.", "HeaderDeleteTaskTrigger": "Delete Task Trigger", @@ -64,10 +85,13 @@ "LabelFree": "Free", "HeaderSelectAudio": "Select Audio", "HeaderSelectSubtitles": "Select Subtitles", + "ButtonMarkForRemoval": "Mark for removal from device", + "ButtonUnmarkForRemoval": "Unmark for removal from device", "LabelDefaultStream": "(Default)", "LabelForcedStream": "(Forced)", "LabelDefaultForcedStream": "(Default\/Forced)", "LabelUnknownLanguage": "Unknown language", + "MessageConfirmSyncJobItemCancellation": "Are you sure you wish to cancel this item?", "ButtonMute": "Mute", "ButtonUnmute": "Unmute", "ButtonStop": "Stop", @@ -191,8 +215,10 @@ "LabelPlayMethodDirectPlay": "Direct Playing", "LabelAudioCodec": "Audio: {0}", "LabelVideoCodec": "Video: {0}", + "LabelLocalAccessUrl": "Local access: {0}", "LabelRemoteAccessUrl": "Remote access: {0}", - "LabelRunningOnPort": "Running on port {0}.", + "LabelRunningOnPort": "Running on http port {0}.", + "LabelRunningOnPorts": "Running on http port {0}, and https port {1}.", "HeaderLatestFromChannel": "Latest from {0}", "ButtonDownload": "Download", "LabelUnknownLanaguage": "Unknown language", @@ -206,6 +232,7 @@ "ButtonRefresh": "Refresh", "LabelCurrentPath": "Current path:", "HeaderSelectMediaPath": "Select Media Path", + "HeaderSelectPath": "Select Path", "ButtonNetwork": "Network", "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.", "HeaderMenu": "Menu", @@ -216,6 +243,7 @@ "ButtonResume": "Resume", "HeaderScenes": "Scenes", "HeaderAudioTracks": "Audio Tracks", + "HeaderLibraries": "Libraries", "HeaderSubtitles": "Subtitles", "HeaderVideoQuality": "Video Quality", "MessageErrorPlayingVideo": "There was an error playing the video.", @@ -581,6 +609,8 @@ "MediaInfoStreamTypeEmbeddedImage": "Embedded Image", "MediaInfoRefFrames": "Ref frames", "TabPlayback": "Playback", + "TabNotifications": "Notifications", + "TabExpert": "Expert", "HeaderSelectCustomIntrosPath": "Select Custom Intros Path", "HeaderRateAndReview": "Rate and Review", "HeaderThankYou": "Thank You", @@ -615,6 +645,7 @@ "DashboardTourMobile": "The Media Browser dashboard works great on smartphones and tablets. Manage your server from the palm of your hand anytime, anywhere.", "MessageRefreshQueued": "Refresh queued", "TabDevices": "Devices", + "TabExtras": "Extras", "DeviceLastUsedByUserName": "Last used by {0}", "HeaderDeleteDevice": "Delete Device", "DeleteDeviceConfirmation": "Are you sure you wish to delete this device? It will reappear the next time a user signs in with it.", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json index 02637a283..f06e6fe7b 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json @@ -6,6 +6,8 @@ "Administrator": "Administrator", "Password": "Passwort", "DeleteImage": "Bild l\u00f6schen", + "MessageThankYouForSupporting": "Danke, f\u00fcr die Unterst\u00fctzung von Media Browser.", + "MessagePleaseSupportMediaBrowser": "Bitte unterst\u00fctze Media Browser.", "DeleteImageConfirmation": "M\u00f6chtest du dieses Bild wirklich l\u00f6schen?", "FileReadCancelled": "Dateiimport wurde abgebrochen.", "FileNotFound": "Datei nicht gefunden", @@ -14,7 +16,10 @@ "DeleteUserConfirmation": "M\u00f6chtest du {0} wirklich l\u00f6schen?", "PasswordResetHeader": "Passwort zur\u00fccksetzen", "PasswordResetComplete": "Das Passwort wurde zur\u00fcckgesetzt.", + "PinCodeResetComplete": "The pin code has been reset.", "PasswordResetConfirmation": "M\u00f6chtest du das Passwort wirklich zur\u00fccksetzen?", + "PinCodeResetConfirmation": "Are you sure you wish to reset the pin code?", + "HeaderPinCodeReset": "Reset Pin Code", "PasswordSaved": "Passwort gespeichert", "PasswordMatchError": "Die Passw\u00f6rter m\u00fcssen \u00fcbereinstimmen.", "OptionRelease": "Offizielles Release", @@ -32,6 +37,7 @@ "MessageKeyRemoved": "Danke. Ihr Unterst\u00fctzerschl\u00fcssel wurde entfernt.", "ErrorLaunchingChromecast": "W\u00e4hrend des startens von Chromecast ist ein Fehler aufgetreten. Bitte stelle sicher, dass dein Ger\u00e4te mit dem WLAN verbunden ist.", "HeaderSearch": "Suche", + "ValueDateCreated": "Erstellungsdatum: {0}", "LabelArtist": "Interpret", "LabelMovie": "Film", "LabelMusicVideo": "Musikvideo", @@ -42,17 +48,32 @@ "LabelFailed": "(fehlgeschlagen)", "ButtonHelp": "Hilfe", "ButtonSave": "Speichern", - "HeaderSupporterBenefit": "A supporter membership provides additional benefits such as access to premium plugins, internet channel content, and more. {0}Learn more{1}.", + "LabelCollection": "Sammlung", + "HeaderAddToCollection": "Zur Sammlung hinzuf\u00fcgen", + "NewCollectionNameExample": "Beispiel: Star Wars Collection", + "OptionSearchForInternetMetadata": "Suche im Internet nach Bildmaterial und Metadaten", + "LabelSelectCollection": "W\u00e4hle Zusammenstellung:", + "HeaderDevices": "Ger\u00e4te", + "ButtonScheduledTasks": "Geplante Aufgaben", + "MessageItemsAdded": "Eintr\u00e4ge hinzugef\u00fcgt", + "ButtonAddToCollection": "Zu Sammlung hinzuf\u00fcgen", + "HeaderSelectCertificatePath": "W\u00e4hlen Sie einen Zertifikat Ordner", + "ConfirmMessageScheduledTaskButton": "Diese Aufgabe l\u00e4uft normalerweise automatisch als geplante Aufgabe. Sie kann jedoch auch manuell von hier gestartet werden. F\u00fcr Einstellungen der geplanten Aufgaben schauen Sie hier:", + "HeaderSupporterBenefit": "Eine Unterst\u00fctzer-Mitgliedschaft bietet weitere Vorteile, wie z.B. den Zugriff auf premium Plugins, weitere Internet-Channels und mehr. {0}Erfahren Sie mehr{1}.", "HeaderWelcomeToMediaBrowserServerDashboard": "Willkommen zur Media Browser \u00dcbersicht", "HeaderWelcomeToMediaBrowserWebClient": "Willkommen zum Media Browser Web Client", "ButtonTakeTheTour": "Mache die Tour", - "HeaderWelcomeBack": "Welcome back!", - "ButtonTakeTheTourToSeeWhatsNew": "Take the tour to see what's new", + "HeaderWelcomeBack": "Willkommen zur\u00fcck!", + "ButtonTakeTheTourToSeeWhatsNew": "Gehen Sie auf Erkundung und erfahren Sie was neu ist", "MessageNoSyncJobsFound": "Keine Synchronisierungs-Aufgaben gefunden. Um Synchronisierungs-Aufgaben zu erstellen verwenden Sie die dazugeh\u00f6rige Funktion im Web-Interface.", "HeaderLibraryAccess": "Bibliothekszugriff", "HeaderChannelAccess": "Channelzugriff", "HeaderDeviceAccess": "Ger\u00e4te Zugang", "HeaderSelectDevices": "Ger\u00e4t w\u00e4hlen", + "ButtonCancelItem": "Datei abw\u00e4hlen", + "ButtonQueueForRetry": "F\u00fcr Wiederholung in die Warteschlange setzen", + "ButtonReenable": "Reaktivierung", + "SyncJobItemStatusSyncedMarkForRemoval": "F\u00fcr L\u00f6schung markiert", "LabelAbortedByServerShutdown": "(Durch herunterfahrenden Server abgebrochen)", "LabelScheduledTaskLastRan": "Zuletzt ausgef\u00fchrt vor: {0}. Ben\u00f6tigte Zeit: {1}.", "HeaderDeleteTaskTrigger": "Entferne Aufgabenausl\u00f6ser", @@ -64,10 +85,13 @@ "LabelFree": "Frei", "HeaderSelectAudio": "W\u00e4hle Audio", "HeaderSelectSubtitles": "W\u00f6hle Untertitel", + "ButtonMarkForRemoval": "Zur L\u00f6schung vom Ger\u00e4t markieren", + "ButtonUnmarkForRemoval": "Markierung zur L\u00f6schung vom Ger\u00e4t aufheben", "LabelDefaultStream": "(Default)", "LabelForcedStream": "(Erzwungen)", "LabelDefaultForcedStream": "(Standard\/Erzwungen)", "LabelUnknownLanguage": "Unbekannte Sprache", + "MessageConfirmSyncJobItemCancellation": "Bist du dir sicher, dass du diese Datei abw\u00e4hlen m\u00f6chtest?", "ButtonMute": "Stumm", "ButtonUnmute": "Ton ein", "ButtonStop": "Stop", @@ -191,8 +215,10 @@ "LabelPlayMethodDirectPlay": "Direktes Abspielen", "LabelAudioCodec": "Audio: {0}", "LabelVideoCodec": "Video: {0}", + "LabelLocalAccessUrl": "Lokale Adresse: {0}", "LabelRemoteAccessUrl": "Fernzugriff: {0}", - "LabelRunningOnPort": "L\u00e4uft \u00fcber Port {0}.", + "LabelRunningOnPort": "L\u00e4uft \u00fcber HTTP Port: {0}", + "LabelRunningOnPorts": "L\u00e4uft \u00fcber HTTP Port {0} und HTTPS Port {1}.", "HeaderLatestFromChannel": "Neuestes von {0}", "ButtonDownload": "Download", "LabelUnknownLanaguage": "Unbekannte Sprache", @@ -206,6 +232,7 @@ "ButtonRefresh": "Aktualisieren", "LabelCurrentPath": "Aktueller Pfad:", "HeaderSelectMediaPath": "W\u00e4hle einen Medienpfad:", + "HeaderSelectPath": "Verzeichnis W\u00e4hlen", "ButtonNetwork": "Netzwerk", "MessageDirectoryPickerInstruction": "Falls der Netzwerk Button deine Endger\u00e4te nicht automatisch findet, kannst du deren Netzwerkpfade auch manuell eintragen. Zum Beispiel {0} oder {1}.", "HeaderMenu": "Men\u00fc", @@ -216,6 +243,7 @@ "ButtonResume": "Wiederholen", "HeaderScenes": "Szenen", "HeaderAudioTracks": "Audiospuren", + "HeaderLibraries": "Bibliotheken", "HeaderSubtitles": "Untertitel", "HeaderVideoQuality": "Videoqualit\u00e4t", "MessageErrorPlayingVideo": "Es gab einen Fehler bei der Videowiedergabe.", @@ -266,13 +294,13 @@ "MessagePleaseEnterNameOrId": "Bitte gib einen Namen oder eine externe Id an.", "MessageValueNotCorrect": "Der eingegeben Wert ist nicht korrekt. Bitte versuche es noch einmal.", "MessageItemSaved": "Element gespeichert", - "MessagePleaseAcceptTermsOfServiceBeforeContinuing": "Please accept the terms of service before continuing.", + "MessagePleaseAcceptTermsOfServiceBeforeContinuing": "Bitte akzeptieren Sie die Nutzungsbedingungen bevor sie fortfahren.", "OptionEnded": "Beendent", "OptionContinuing": "Fortdauernd", "OptionOff": "Aus", "OptionOn": "Ein", "ButtonSettings": "Einstellungen", - "ButtonUninstall": "Uninstall", + "ButtonUninstall": "Deinstallieren", "HeaderFields": "Felder", "HeaderFieldsHelp": "Verschiebe ein Feld zu \"Aus\" um es zu sperren und \u00c4nderungen an dessen Daten zu verhindern.", "HeaderLiveTV": "Live-TV", @@ -300,7 +328,7 @@ "LabelNewProgram": "NEU", "LabelPremiereProgram": "PREMIERE", "LabelHDProgram": "HD", - "HeaderChangeFolderType": "Change Content Type", + "HeaderChangeFolderType": "\u00c4ndere Inhalte Typ", "HeaderChangeFolderTypeHelp": "Um den Typ zu \u00e4ndern, entferne diesen bitte und erstelle die Bibliothek mit dem neuen Ordnertyp erneut.", "HeaderAlert": "Alarm", "MessagePleaseRestart": "Dr\u00fccke auf Neustart um das Update abzuschlie\u00dfen", @@ -581,6 +609,8 @@ "MediaInfoStreamTypeEmbeddedImage": "Eingebettetes Bild", "MediaInfoRefFrames": "Ref Frames", "TabPlayback": "Wiedergabe", + "TabNotifications": "Benachrichtigungen", + "TabExpert": "Experte", "HeaderSelectCustomIntrosPath": "W\u00e4hle einen benutzerdefinierten Pfad f\u00fcr Intros", "HeaderRateAndReview": "Bewerten und Kommentieren", "HeaderThankYou": "Danke", @@ -615,6 +645,7 @@ "DashboardTourMobile": "Die Media Browser \u00dcbersicht funktioniert auch hervorragend auf Smartphones und Tablets. Verwalte deinen Server jederzeit und \u00fcberall direkt von deiner Handfl\u00e4che aus.", "MessageRefreshQueued": "Warteschlange aktualisieren", "TabDevices": "Ger\u00e4te", + "TabExtras": "Extras", "DeviceLastUsedByUserName": "Zuletzt genutzt von {0}", "HeaderDeleteDevice": "Ger\u00e4t l\u00f6schen", "DeleteDeviceConfirmation": "Bist du dir sicher dieses Ger\u00e4t l\u00f6schen zu wollen? Es wird wieder angezeigt werden, sobald sich ein Uder dar\u00fcber einloggt.", @@ -628,7 +659,7 @@ "MessageInvitationSentToUser": "Eine E-Mail mit der Einladung zum Sharing ist an {0} geschickt worden.", "MessageInvitationSentToNewUser": "Eine E-Mail mit der Einladung zur Anmeldung am Media Browser ist an {0} geschickt worden.", "HeaderConnectionFailure": "Verbindungsfehler", - "MessageUnableToConnectToServer": "We're unable to connect to the selected server right now. Please ensure it is running and try again.", + "MessageUnableToConnectToServer": "Wir k\u00f6nnen gerade keine Verbindung zum gew\u00e4hlten Server herstellen. Bitte stellen Sie sicher das dieser l\u00e4uft und versuchen Sie es erneut.", "ButtonSelectServer": "W\u00e4hle Server", "MessagePluginConfigurationRequiresLocalAccess": "Melde dich bitte direkt an deinem lokalen Server an, um dieses Plugin konfigurieren zu k\u00f6nnen.", "MessageLoggedOutParentalControl": "Der Zugriff ist derzeit eingeschr\u00e4nkt. Bitte versuche es sp\u00e4ter erneut.", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/el.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/el.json index 515e079d4..e8426614b 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/el.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/el.json @@ -6,6 +6,8 @@ "Administrator": "\u03c4\u03bf \u03b4\u03b9\u03b1\u03c7\u03b5\u03b9\u03c1\u03b9\u03c3\u03c4\u03ae\u03c2", "Password": "\u03c4\u03bf\u03bd \u03ba\u03ce\u03b4\u03b9\u03ba\u03b1\u03c2 \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7\u03c2", "DeleteImage": "\u03b4\u03b9\u03b1\u03b3\u03c1\u03ac\u03c8\u03c4\u03b5 \u03c4\u03b7\u03bd \u03b5\u03b9\u03ba\u03cc\u03bd\u03b1", + "MessageThankYouForSupporting": "Thank you for supporting Media Browser.", + "MessagePleaseSupportMediaBrowser": "Please support Media Browser.", "DeleteImageConfirmation": "\u0395\u03af\u03c3\u03c4\u03b5 \u03c3\u03af\u03b3\u03bf\u03c5\u03c1\u03bf\u03b9 \u03cc\u03c4\u03b9 \u03b8\u03ad\u03bb\u03b5\u03c4\u03b5 \u03bd\u03b1 \u03b4\u03b9\u03b1\u03b3\u03c1\u03ac\u03c8\u03b5\u03c4\u03b5 \u03b1\u03c5\u03c4\u03ae \u03c4\u03b7\u03bd \u03b5\u03b9\u03ba\u03cc\u03bd\u03b1;", "FileReadCancelled": "The file read has been canceled.", "FileNotFound": "\u03a4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03b4\u03b5\u03bd \u03b2\u03c1\u03ad\u03b8\u03b7\u03ba\u03b5", @@ -14,7 +16,10 @@ "DeleteUserConfirmation": "Are you sure you wish to delete this user?", "PasswordResetHeader": "\u0395\u03c0\u03b1\u03bd\u03b1\u03c6\u03bf\u03c1\u03ac \u03ba\u03c9\u03b4\u03b9\u03ba\u03bf\u03cd \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7\u03c2", "PasswordResetComplete": "\u039f \u03ba\u03c9\u03b4\u03b9\u03ba\u03cc\u03c2 \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7\u03c2 \u03ad\u03c7\u03b5\u03b9 \u03b3\u03af\u03bd\u03b5\u03b9 \u03b5\u03c0\u03b1\u03bd\u03b1\u03c6\u03bf\u03c1\u03ac", + "PinCodeResetComplete": "The pin code has been reset.", "PasswordResetConfirmation": "\u0395\u03af\u03c3\u03c4\u03b5 \u03c3\u03af\u03b3\u03bf\u03c5\u03c1\u03bf\u03b9 \u03cc\u03c4\u03b9 \u03b8\u03ad\u03bb\u03b5\u03c4\u03b5 \u03bd\u03b1 \u03b5\u03c0\u03b1\u03bd\u03b1\u03c6\u03ad\u03c1\u03b5\u03c4\u03b5 \u03c4\u03bf\u03bd \u03ba\u03c9\u03b4\u03b9\u03ba\u03cc \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7\u03c2;", + "PinCodeResetConfirmation": "Are you sure you wish to reset the pin code?", + "HeaderPinCodeReset": "Reset Pin Code", "PasswordSaved": "\u039f \u03ba\u03c9\u03b4\u03b9\u03ba\u03cc\u03c2 \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7\u03c2 \u03b1\u03c0\u03bf\u03b8\u03b7\u03ba\u03b5\u03cd\u03c4\u03b7\u03ba\u03b5", "PasswordMatchError": "\u039f \u03ba\u03c9\u03b4\u03b9\u03ba\u03cc\u03c2 \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7\u03c2 \u03ba\u03b1\u03b9 \u03c4\u03bf\u03bd \u03ba\u03c9\u03b4\u03b9\u03ba\u03cc \u03b5\u03c0\u03b9\u03b2\u03b5\u03b2\u03b1\u03af\u03c9\u03c3\u03b7\u03c2 \u03c0\u03c1\u03ad\u03c0\u03b5\u03b9 \u03bd\u03b1 \u03c4\u03b1\u03b9\u03c1\u03b9\u03ac\u03b6\u03bf\u03c5\u03bd", "OptionRelease": "\u0397 \u03b5\u03c0\u03af\u03c3\u03b7\u03bc\u03b7 \u03ad\u03ba\u03b4\u03bf\u03c3\u03b7", @@ -32,6 +37,7 @@ "MessageKeyRemoved": "Thank you. Your supporter key has been removed.", "ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.", "HeaderSearch": "Search", + "ValueDateCreated": "Date created: {0}", "LabelArtist": "Artist", "LabelMovie": "Movie", "LabelMusicVideo": "Music Video", @@ -42,6 +48,17 @@ "LabelFailed": "(failed)", "ButtonHelp": "Help", "ButtonSave": "\u0391\u03c0\u03bf\u03b8\u03b7\u03ba\u03b5\u03cd\u03c3\u03c4\u03b5", + "LabelCollection": "Collection", + "HeaderAddToCollection": "Add to Collection", + "NewCollectionNameExample": "Example: Star Wars Collection", + "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata", + "LabelSelectCollection": "Select collection:", + "HeaderDevices": "Devices", + "ButtonScheduledTasks": "Scheduled tasks", + "MessageItemsAdded": "Items added", + "ButtonAddToCollection": "Add to collection", + "HeaderSelectCertificatePath": "Select Certificate Path", + "ConfirmMessageScheduledTaskButton": "This operation normally runs automatically as a scheduled task. It can also be run manually here. To configure the scheduled task, see:", "HeaderSupporterBenefit": "A supporter membership provides additional benefits such as access to premium plugins, internet channel content, and more. {0}Learn more{1}.", "HeaderWelcomeToMediaBrowserServerDashboard": "Welcome to the Media Browser Dashboard", "HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client", @@ -53,6 +70,10 @@ "HeaderChannelAccess": "Channel Access", "HeaderDeviceAccess": "Device Access", "HeaderSelectDevices": "Select Devices", + "ButtonCancelItem": "Cancel item", + "ButtonQueueForRetry": "Queue for retry", + "ButtonReenable": "Re-enable", + "SyncJobItemStatusSyncedMarkForRemoval": "Marked for removal", "LabelAbortedByServerShutdown": "(Aborted by server shutdown)", "LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.", "HeaderDeleteTaskTrigger": "Delete Task Trigger", @@ -64,10 +85,13 @@ "LabelFree": "Free", "HeaderSelectAudio": "Select Audio", "HeaderSelectSubtitles": "Select Subtitles", + "ButtonMarkForRemoval": "Mark for removal from device", + "ButtonUnmarkForRemoval": "Unmark for removal from device", "LabelDefaultStream": "(Default)", "LabelForcedStream": "(Forced)", "LabelDefaultForcedStream": "(Default\/Forced)", "LabelUnknownLanguage": "Unknown language", + "MessageConfirmSyncJobItemCancellation": "Are you sure you wish to cancel this item?", "ButtonMute": "Mute", "ButtonUnmute": "Unmute", "ButtonStop": "Stop", @@ -191,8 +215,10 @@ "LabelPlayMethodDirectPlay": "Direct Playing", "LabelAudioCodec": "Audio: {0}", "LabelVideoCodec": "Video: {0}", + "LabelLocalAccessUrl": "Local access: {0}", "LabelRemoteAccessUrl": "Remote access: {0}", - "LabelRunningOnPort": "Running on port {0}.", + "LabelRunningOnPort": "Running on http port {0}.", + "LabelRunningOnPorts": "Running on http port {0}, and https port {1}.", "HeaderLatestFromChannel": "Latest from {0}", "ButtonDownload": "Download", "LabelUnknownLanaguage": "Unknown language", @@ -206,6 +232,7 @@ "ButtonRefresh": "Refresh", "LabelCurrentPath": "Current path:", "HeaderSelectMediaPath": "Select Media Path", + "HeaderSelectPath": "Select Path", "ButtonNetwork": "Network", "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.", "HeaderMenu": "Menu", @@ -216,6 +243,7 @@ "ButtonResume": "Resume", "HeaderScenes": "Scenes", "HeaderAudioTracks": "Audio Tracks", + "HeaderLibraries": "Libraries", "HeaderSubtitles": "Subtitles", "HeaderVideoQuality": "Video Quality", "MessageErrorPlayingVideo": "There was an error playing the video.", @@ -581,6 +609,8 @@ "MediaInfoStreamTypeEmbeddedImage": "Embedded Image", "MediaInfoRefFrames": "Ref frames", "TabPlayback": "Playback", + "TabNotifications": "Notifications", + "TabExpert": "Expert", "HeaderSelectCustomIntrosPath": "Select Custom Intros Path", "HeaderRateAndReview": "Rate and Review", "HeaderThankYou": "Thank You", @@ -615,6 +645,7 @@ "DashboardTourMobile": "The Media Browser dashboard works great on smartphones and tablets. Manage your server from the palm of your hand anytime, anywhere.", "MessageRefreshQueued": "Refresh queued", "TabDevices": "Devices", + "TabExtras": "Extras", "DeviceLastUsedByUserName": "Last used by {0}", "HeaderDeleteDevice": "Delete Device", "DeleteDeviceConfirmation": "Are you sure you wish to delete this device? It will reappear the next time a user signs in with it.", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/en_GB.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/en_GB.json index 426c44f2a..8f5b55554 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/en_GB.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/en_GB.json @@ -6,15 +6,20 @@ "Administrator": "Administrator", "Password": "Password", "DeleteImage": "Delete Image", + "MessageThankYouForSupporting": "Thank you for supporting Media Browser.", + "MessagePleaseSupportMediaBrowser": "Please support Media Browser.", "DeleteImageConfirmation": "Are you sure you wish to delete this image?", "FileReadCancelled": "The file read has been cancelled.", "FileNotFound": "File not found.", "FileReadError": "An error occurred while reading the file.", "DeleteUser": "Delete User", "DeleteUserConfirmation": "Are you sure you wish to delete this user?", - "PasswordResetHeader": "Password Reset", + "PasswordResetHeader": "Reset Password", "PasswordResetComplete": "The password has been reset.", + "PinCodeResetComplete": "The pin code has been reset.", "PasswordResetConfirmation": "Are you sure you wish to reset the password?", + "PinCodeResetConfirmation": "Are you sure you wish to reset the pin code?", + "HeaderPinCodeReset": "Reset Pin Code", "PasswordSaved": "Password saved.", "PasswordMatchError": "Password and password confirmation must match.", "OptionRelease": "Official Release", @@ -32,6 +37,7 @@ "MessageKeyRemoved": "Thank you. Your supporter key has been removed.", "ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.", "HeaderSearch": "Search", + "ValueDateCreated": "Date created: {0}", "LabelArtist": "Artist", "LabelMovie": "Movie", "LabelMusicVideo": "Music Video", @@ -42,6 +48,17 @@ "LabelFailed": "(failed)", "ButtonHelp": "Help", "ButtonSave": "Save", + "LabelCollection": "Collection", + "HeaderAddToCollection": "Add to Collection", + "NewCollectionNameExample": "Example: Star Wars Collection", + "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata", + "LabelSelectCollection": "Select collection:", + "HeaderDevices": "Devices", + "ButtonScheduledTasks": "Scheduled tasks", + "MessageItemsAdded": "Items added", + "ButtonAddToCollection": "Add to collection", + "HeaderSelectCertificatePath": "Select Certificate Path", + "ConfirmMessageScheduledTaskButton": "This operation normally runs automatically as a scheduled task. It can also be run manually here. To configure the scheduled task, see:", "HeaderSupporterBenefit": "A supporter membership provides additional benefits such as access to premium plugins, internet channel content, and more. {0}Learn more{1}.", "HeaderWelcomeToMediaBrowserServerDashboard": "Welcome to the Media Browser Dashboard", "HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client", @@ -53,6 +70,10 @@ "HeaderChannelAccess": "Channel Access", "HeaderDeviceAccess": "Device Access", "HeaderSelectDevices": "Select Devices", + "ButtonCancelItem": "Cancel item", + "ButtonQueueForRetry": "Queue for retry", + "ButtonReenable": "Re-enable", + "SyncJobItemStatusSyncedMarkForRemoval": "Marked for removal", "LabelAbortedByServerShutdown": "(Aborted by server shutdown)", "LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.", "HeaderDeleteTaskTrigger": "Delete Task Trigger", @@ -64,10 +85,13 @@ "LabelFree": "Free", "HeaderSelectAudio": "Select Audio", "HeaderSelectSubtitles": "Select Subtitles", + "ButtonMarkForRemoval": "Mark for removal from device", + "ButtonUnmarkForRemoval": "Unmark for removal from device", "LabelDefaultStream": "(Default)", "LabelForcedStream": "(Forced)", "LabelDefaultForcedStream": "(Default\/Forced)", "LabelUnknownLanguage": "Unknown language", + "MessageConfirmSyncJobItemCancellation": "Are you sure you wish to cancel this item?", "ButtonMute": "Mute", "ButtonUnmute": "Unmute", "ButtonStop": "Stop", @@ -191,8 +215,10 @@ "LabelPlayMethodDirectPlay": "Direct Playing", "LabelAudioCodec": "Audio: {0}", "LabelVideoCodec": "Video: {0}", + "LabelLocalAccessUrl": "Local access: {0}", "LabelRemoteAccessUrl": "Remote access: {0}", - "LabelRunningOnPort": "Running on port {0}.", + "LabelRunningOnPort": "Running on http port {0}.", + "LabelRunningOnPorts": "Running on http port {0}, and https port {1}.", "HeaderLatestFromChannel": "Latest from {0}", "ButtonDownload": "Download", "LabelUnknownLanaguage": "Unknown language", @@ -206,6 +232,7 @@ "ButtonRefresh": "Refresh", "LabelCurrentPath": "Current path:", "HeaderSelectMediaPath": "Select Media Path", + "HeaderSelectPath": "Select Path", "ButtonNetwork": "Network", "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.", "HeaderMenu": "Menu", @@ -216,6 +243,7 @@ "ButtonResume": "Resume", "HeaderScenes": "Scenes", "HeaderAudioTracks": "Audio Tracks", + "HeaderLibraries": "Libraries", "HeaderSubtitles": "Subtitles", "HeaderVideoQuality": "Video Quality", "MessageErrorPlayingVideo": "There was an error playing the video.", @@ -581,6 +609,8 @@ "MediaInfoStreamTypeEmbeddedImage": "Embedded Image", "MediaInfoRefFrames": "Ref frames", "TabPlayback": "Playback", + "TabNotifications": "Notifications", + "TabExpert": "Expert", "HeaderSelectCustomIntrosPath": "Select Custom Intros Path", "HeaderRateAndReview": "Rate and Review", "HeaderThankYou": "Thank You", @@ -615,6 +645,7 @@ "DashboardTourMobile": "The Media Browser dashboard works great on smartphones and tablets. Manage your server from the palm of your hand anytime, anywhere.", "MessageRefreshQueued": "Refresh queued", "TabDevices": "Devices", + "TabExtras": "Extras", "DeviceLastUsedByUserName": "Last used by {0}", "HeaderDeleteDevice": "Delete Device", "DeleteDeviceConfirmation": "Are you sure you wish to delete this device? It will reappear the next time a user signs in with it.", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json index 7fc29b85b..6e884ec40 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json @@ -6,15 +6,20 @@ "Administrator": "Administrator", "Password": "Password", "DeleteImage": "Delete Image", + "MessageThankYouForSupporting": "Thank you for supporting Media Browser.", + "MessagePleaseSupportMediaBrowser": "Please support Media Browser.", "DeleteImageConfirmation": "Are you sure you wish to delete this image?", "FileReadCancelled": "The file read has been canceled.", "FileNotFound": "File not found.", "FileReadError": "An error occurred while reading the file.", "DeleteUser": "Delete User", "DeleteUserConfirmation": "Are you sure you wish to delete this user?", - "PasswordResetHeader": "Password Reset", + "PasswordResetHeader": "Reset Password", "PasswordResetComplete": "The password has been reset.", + "PinCodeResetComplete": "The pin code has been reset.", "PasswordResetConfirmation": "Are you sure you wish to reset the password?", + "PinCodeResetConfirmation": "Are you sure you wish to reset the pin code?", + "HeaderPinCodeReset": "Reset Pin Code", "PasswordSaved": "Password saved.", "PasswordMatchError": "Password and password confirmation must match.", "OptionRelease": "Official Release", @@ -32,6 +37,7 @@ "MessageKeyRemoved": "Thank you. Your supporter key has been removed.", "ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.", "HeaderSearch": "Search", + "ValueDateCreated": "Date created: {0}", "LabelArtist": "Artist", "LabelMovie": "Movie", "LabelMusicVideo": "Music Video", @@ -42,6 +48,17 @@ "LabelFailed": "(failed)", "ButtonHelp": "Help", "ButtonSave": "Save", + "LabelCollection": "Collection", + "HeaderAddToCollection": "Add to Collection", + "NewCollectionNameExample": "Example: Star Wars Collection", + "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata", + "LabelSelectCollection": "Select collection:", + "HeaderDevices": "Devices", + "ButtonScheduledTasks": "Scheduled tasks", + "MessageItemsAdded": "Items added", + "ButtonAddToCollection": "Add to collection", + "HeaderSelectCertificatePath": "Select Certificate Path", + "ConfirmMessageScheduledTaskButton": "This operation normally runs automatically as a scheduled task. It can also be run manually here. To configure the scheduled task, see:", "HeaderSupporterBenefit": "A supporter membership provides additional benefits such as access to premium plugins, internet channel content, and more. {0}Learn more{1}.", "HeaderWelcomeToMediaBrowserServerDashboard": "Welcome to the Media Browser Dashboard", "HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client", @@ -53,6 +70,10 @@ "HeaderChannelAccess": "Channel Access", "HeaderDeviceAccess": "Device Access", "HeaderSelectDevices": "Select Devices", + "ButtonCancelItem": "Cancel item", + "ButtonQueueForRetry": "Queue for retry", + "ButtonReenable": "Re-enable", + "SyncJobItemStatusSyncedMarkForRemoval": "Marked for removal", "LabelAbortedByServerShutdown": "(Aborted by server shutdown)", "LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.", "HeaderDeleteTaskTrigger": "Delete Task Trigger", @@ -64,10 +85,13 @@ "LabelFree": "Free", "HeaderSelectAudio": "Select Audio", "HeaderSelectSubtitles": "Select Subtitles", + "ButtonMarkForRemoval": "Mark for removal from device", + "ButtonUnmarkForRemoval": "Unmark for removal from device", "LabelDefaultStream": "(Default)", "LabelForcedStream": "(Forced)", "LabelDefaultForcedStream": "(Default\/Forced)", "LabelUnknownLanguage": "Unknown language", + "MessageConfirmSyncJobItemCancellation": "Are you sure you wish to cancel this item?", "ButtonMute": "Mute", "ButtonUnmute": "Unmute", "ButtonStop": "Stop", @@ -191,8 +215,10 @@ "LabelPlayMethodDirectPlay": "Direct Playing", "LabelAudioCodec": "Audio: {0}", "LabelVideoCodec": "Video: {0}", + "LabelLocalAccessUrl": "Local access: {0}", "LabelRemoteAccessUrl": "Remote access: {0}", - "LabelRunningOnPort": "Running on port {0}.", + "LabelRunningOnPort": "Running on http port {0}.", + "LabelRunningOnPorts": "Running on http port {0}, and https port {1}.", "HeaderLatestFromChannel": "Latest from {0}", "ButtonDownload": "Download", "LabelUnknownLanaguage": "Unknown language", @@ -206,6 +232,7 @@ "ButtonRefresh": "Refresh", "LabelCurrentPath": "Current path:", "HeaderSelectMediaPath": "Select Media Path", + "HeaderSelectPath": "Select Path", "ButtonNetwork": "Network", "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.", "HeaderMenu": "Menu", @@ -216,6 +243,7 @@ "ButtonResume": "Resume", "HeaderScenes": "Scenes", "HeaderAudioTracks": "Audio Tracks", + "HeaderLibraries": "Libraries", "HeaderSubtitles": "Subtitles", "HeaderVideoQuality": "Video Quality", "MessageErrorPlayingVideo": "There was an error playing the video.", @@ -581,6 +609,8 @@ "MediaInfoStreamTypeEmbeddedImage": "Embedded Image", "MediaInfoRefFrames": "Ref frames", "TabPlayback": "Playback", + "TabNotifications": "Notifications", + "TabExpert": "Expert", "HeaderSelectCustomIntrosPath": "Select Custom Intros Path", "HeaderRateAndReview": "Rate and Review", "HeaderThankYou": "Thank You", @@ -615,6 +645,7 @@ "DashboardTourMobile": "The Media Browser dashboard works great on smartphones and tablets. Manage your server from the palm of your hand anytime, anywhere.", "MessageRefreshQueued": "Refresh queued", "TabDevices": "Devices", + "TabExtras": "Extras", "DeviceLastUsedByUserName": "Last used by {0}", "HeaderDeleteDevice": "Delete Device", "DeleteDeviceConfirmation": "Are you sure you wish to delete this device? It will reappear the next time a user signs in with it.", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/es.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/es.json index 6a7898885..501d66e5b 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/es.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/es.json @@ -6,6 +6,8 @@ "Administrator": "Administrador", "Password": "Contrase\u00f1a", "DeleteImage": "Borrar Imagen", + "MessageThankYouForSupporting": "Thank you for supporting Media Browser.", + "MessagePleaseSupportMediaBrowser": "Please support Media Browser.", "DeleteImageConfirmation": "Est\u00e1 seguro que desea borrar esta imagen?", "FileReadCancelled": "The file read has been canceled.", "FileNotFound": "Archivo no encontrado.", @@ -14,7 +16,10 @@ "DeleteUserConfirmation": "Are you sure you wish to delete this user?", "PasswordResetHeader": "Restablecer contrase\u00f1a", "PasswordResetComplete": "La contrase\u00f1a se ha restablecido.", + "PinCodeResetComplete": "The pin code has been reset.", "PasswordResetConfirmation": "Esta seguro que desea restablecer la contrase\u00f1a?", + "PinCodeResetConfirmation": "Are you sure you wish to reset the pin code?", + "HeaderPinCodeReset": "Reset Pin Code", "PasswordSaved": "Contrase\u00f1a guardada.", "PasswordMatchError": "La contrase\u00f1a y la confirmaci\u00f3n de la contrase\u00f1a deben de ser iguales.", "OptionRelease": "Release Oficial", @@ -32,6 +37,7 @@ "MessageKeyRemoved": "Gracias. Su clave de seguidor ha sido eliminada.", "ErrorLaunchingChromecast": "Ha habido un error al lanzar chromecast. Asegurese que su dispositivo est\u00e1 conectado a su red inal\u00e1mbrica.", "HeaderSearch": "Buscar", + "ValueDateCreated": "Date created: {0}", "LabelArtist": "Artista", "LabelMovie": "Pel\u00edcula", "LabelMusicVideo": "Video Musical", @@ -42,6 +48,17 @@ "LabelFailed": "(failed)", "ButtonHelp": "Help", "ButtonSave": "Grabar", + "LabelCollection": "Collection", + "HeaderAddToCollection": "A\u00f1adir a la colecci\u00f3n", + "NewCollectionNameExample": "Ejemplo: Star Wars Colecci\u00f3n", + "OptionSearchForInternetMetadata": "Buscar en internet ilustraciones y metadatos", + "LabelSelectCollection": "Seleccionar colecci\u00f3n:", + "HeaderDevices": "Devices", + "ButtonScheduledTasks": "Scheduled tasks", + "MessageItemsAdded": "Items added", + "ButtonAddToCollection": "Add to collection", + "HeaderSelectCertificatePath": "Select Certificate Path", + "ConfirmMessageScheduledTaskButton": "This operation normally runs automatically as a scheduled task. It can also be run manually here. To configure the scheduled task, see:", "HeaderSupporterBenefit": "A supporter membership provides additional benefits such as access to premium plugins, internet channel content, and more. {0}Learn more{1}.", "HeaderWelcomeToMediaBrowserServerDashboard": "Welcome to the Media Browser Dashboard", "HeaderWelcomeToMediaBrowserWebClient": "Vienvenido al Cliente Web de Media Browser", @@ -53,6 +70,10 @@ "HeaderChannelAccess": "Channel Access", "HeaderDeviceAccess": "Device Access", "HeaderSelectDevices": "Select Devices", + "ButtonCancelItem": "Cancel item", + "ButtonQueueForRetry": "Queue for retry", + "ButtonReenable": "Re-enable", + "SyncJobItemStatusSyncedMarkForRemoval": "Marked for removal", "LabelAbortedByServerShutdown": "(Abortado por cierre del servidor)", "LabelScheduledTaskLastRan": "\u00daltima ejecuci\u00f3n {0}, teniendo {1}.", "HeaderDeleteTaskTrigger": "Eliminar tarea de activaci\u00f3n", @@ -64,10 +85,13 @@ "LabelFree": "Libre", "HeaderSelectAudio": "Seleccionar Audio", "HeaderSelectSubtitles": "Seleccionar Subt\u00edtulos", + "ButtonMarkForRemoval": "Mark for removal from device", + "ButtonUnmarkForRemoval": "Unmark for removal from device", "LabelDefaultStream": "(Por defecto)", "LabelForcedStream": "(Forzado)", "LabelDefaultForcedStream": "(Por defecto\/Forzado)", "LabelUnknownLanguage": "Idioma desconocido", + "MessageConfirmSyncJobItemCancellation": "Are you sure you wish to cancel this item?", "ButtonMute": "Silencio", "ButtonUnmute": "Activar audio", "ButtonStop": "Detener", @@ -191,8 +215,10 @@ "LabelPlayMethodDirectPlay": "Reproducci\u00f3n directa", "LabelAudioCodec": "Audio: {0}", "LabelVideoCodec": "Video: {0}", + "LabelLocalAccessUrl": "Local access: {0}", "LabelRemoteAccessUrl": "Acceso remoto: {0}", - "LabelRunningOnPort": "Ejecut\u00e1ndose en el puerto {0}.", + "LabelRunningOnPort": "Running on http port {0}.", + "LabelRunningOnPorts": "Running on http port {0}, and https port {1}.", "HeaderLatestFromChannel": "Lo \u00faltimo de {0}", "ButtonDownload": "Descargar", "LabelUnknownLanaguage": "Idioma desconocido", @@ -206,6 +232,7 @@ "ButtonRefresh": "Refrescar", "LabelCurrentPath": "Ruta actual:", "HeaderSelectMediaPath": "Seleccionar la ruta para Medios", + "HeaderSelectPath": "Select Path", "ButtonNetwork": "Red", "MessageDirectoryPickerInstruction": "Rutas de red pueden ser introducidas manualmente en el caso de que el bot\u00f3n de la red no pueda localizar sus dispositivos. Por ejemplo, {0} o {1}.", "HeaderMenu": "Men\u00fa", @@ -216,6 +243,7 @@ "ButtonResume": "Continuar", "HeaderScenes": "Escenas", "HeaderAudioTracks": "Pistas de audio", + "HeaderLibraries": "Libraries", "HeaderSubtitles": "Subt\u00edtulos", "HeaderVideoQuality": "Calidad de video", "MessageErrorPlayingVideo": "Ha habido un error reproduciendo el video.", @@ -581,6 +609,8 @@ "MediaInfoStreamTypeEmbeddedImage": "Embedded Image", "MediaInfoRefFrames": "Ref frames", "TabPlayback": "Playback", + "TabNotifications": "Notificaciones", + "TabExpert": "Expert", "HeaderSelectCustomIntrosPath": "Select Custom Intros Path", "HeaderRateAndReview": "Rate and Review", "HeaderThankYou": "Thank You", @@ -615,6 +645,7 @@ "DashboardTourMobile": "The Media Browser dashboard works great on smartphones and tablets. Manage your server from the palm of your hand anytime, anywhere.", "MessageRefreshQueued": "Refresh queued", "TabDevices": "Devices", + "TabExtras": "Extras", "DeviceLastUsedByUserName": "Last used by {0}", "HeaderDeleteDevice": "Delete Device", "DeleteDeviceConfirmation": "Are you sure you wish to delete this device? It will reappear the next time a user signs in with it.", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/es_ES.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/es_ES.json deleted file mode 100644 index c6efa636a..000000000 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/es_ES.json +++ /dev/null @@ -1,237 +0,0 @@ -{ - "SettingsSaved": "Configuraci\u00f3n guardada", - "AddUser": "Agregar usuario", - "Users": "Usuarios", - "Delete": "Borrar", - "Administrator": "Administrador", - "Password": "Contrase\u00f1a", - "DeleteImage": "Borrar Imagen", - "DeleteImageConfirmation": "Est\u00e1 seguro que desea borrar esta imagen?", - "FileReadCancelled": "La lectura del archivo se ha cancelado.", - "FileNotFound": "Archivo no encontrado.", - "FileReadError": "Se encontr\u00f3 un error al leer el archivo.", - "DeleteUser": "Borrar Usuario", - "DeleteUserConfirmation": "Esta seguro que desea eliminar a {0}?", - "PasswordResetHeader": "Restablecer contrase\u00f1a", - "PasswordResetComplete": "La contrase\u00f1a se ha restablecido.", - "PasswordResetConfirmation": "Esta seguro que desea restablecer la contrase\u00f1a?", - "PasswordSaved": "Contrase\u00f1a guardada.", - "PasswordMatchError": "La contrase\u00f1a y la confirmaci\u00f3n de la contrase\u00f1a deben de ser iguales.", - "OptionRelease": "Release Oficial", - "OptionBeta": "Beta", - "OptionDev": "Desarrollo", - "UninstallPluginHeader": "Desinstalar Plugin", - "UninstallPluginConfirmation": "Esta seguro que desea desinstalar {0}?", - "NoPluginConfigurationMessage": "El plugin no requiere configuraci\u00f3n", - "NoPluginsInstalledMessage": "No tiene plugins instalados.", - "BrowsePluginCatalogMessage": "Navegar el catalogo de plugins para ver los plugins disponibles.", - "MessageKeyEmailedTo": "Clave enviada por email a {0}.", - "MessageKeysLinked": "Claves vinculadas.", - "HeaderConfirmation": "Confirmaci\u00f3n", - "MessageKeyUpdated": "Gracias. Su clave de seguidor ha sido actualizada.", - "MessageKeyRemoved": "Gracias. Su clave de seguidor ha sido eliminada.", - "ErrorLaunchingChromecast": "Ha habido un error al lanzar chromecast. Asegurese que su dispositivo est\u00e1 conectado a su red inal\u00e1mbrica.", - "HeaderSearch": "Buscar", - "LabelArtist": "Artista", - "LabelMovie": "Pel\u00edcula", - "LabelMusicVideo": "Video Musical", - "LabelEpisode": "Episodio", - "LabelSeries": "Series", - "LabelStopping": "Deteniendo", - "ButtonStop": "Detener", - "LabelCancelled": "(cancelado)", - "LabelFailed": "(fracasado)", - "LabelAbortedByServerShutdown": "(Abortado por cierre del servidor)", - "LabelScheduledTaskLastRan": "\u00daltima ejecuci\u00f3n {0}, teniendo {1}.", - "HeaderDeleteTaskTrigger": "Eliminar tarea de activaci\u00f3n", - "HeaderTaskTriggers": "Tareas de activaci\u00f3n", - "MessageDeleteTaskTrigger": "\u00bfEst\u00e1 seguro que desea eliminar esta tarea de activaci\u00f3n?", - "MessageNoPluginsInstalled": "No tiene plugins instalados.", - "LabelVersionInstalled": "{0} instalado", - "LabelNumberReviews": "{0} Revisiones", - "LabelFree": "Libre", - "HeaderSelectAudio": "Seleccionar Audio", - "HeaderSelectSubtitles": "Seleccionar Subt\u00edtulos", - "LabelDefaultStream": "(Por defecto)", - "LabelForcedStream": "(Forzado)", - "LabelDefaultForcedStream": "(Por defecto\/Forzado)", - "LabelUnknownLanguage": "Idioma desconocido", - "ButtonMute": "Silencio", - "ButtonUnmute": "Activar audio", - "ButtonNextTrack": "Pista siguiente", - "ButtonPause": "Pausa", - "ButtonPlay": "Reproducir", - "ButtonEdit": "Editar", - "ButtonQueue": "En cola", - "ButtonPlayTrailer": "Reproducir trailer", - "ButtonPlaylist": "Lista de reproducci\u00f3n", - "ButtonPreviousTrack": "Pista anterior", - "LabelEnabled": "Activado", - "LabelDisabled": "Desactivado", - "ButtonMoreInformation": "M\u00e1s informaci\u00f3n", - "LabelNoUnreadNotifications": "No hay notificaciones sin leer.", - "ButtonViewNotifications": "Ver notificaciones", - "ButtonMarkTheseRead": "Marcar como le\u00eddo", - "ButtonClose": "Cerrar", - "LabelAllPlaysSentToPlayer": "Todas las reproducciones se enviar\u00e1n al reproductor seleccionado.", - "MessageInvalidUser": "Usuario o contrase\u00f1a no v\u00e1lido.", - "HeaderAllRecordings": "Todas la grabaciones", - "RecommendationBecauseYouLike": "Como le gusta {0}", - "RecommendationBecauseYouWatched": "Ya que vi\u00f3 {0}", - "RecommendationDirectedBy": "Dirigida por {0}", - "RecommendationStarring": "Protagonizada por {0}", - "HeaderConfirmRecordingCancellation": "Confirmar la cancelaci\u00f3n de la grabaci\u00f3n", - "MessageConfirmRecordingCancellation": "\u00bfEst\u00e1 seguro que desea cancelar esta grabaci\u00f3n?", - "MessageRecordingCancelled": "Grabaci\u00f3n cancelada.", - "HeaderConfirmSeriesCancellation": "Confirmar cancelaci\u00f3n de serie", - "MessageConfirmSeriesCancellation": "\u00bfEst\u00e1 seguro que desea cancelar esta serie?", - "MessageSeriesCancelled": "Serie cancelada", - "HeaderConfirmRecordingDeletion": "Confirmar borrado de la grabaci\u00f3n", - "MessageConfirmRecordingDeletion": "\u00bfEst\u00e1 seguro que desea borrar esta grabaci\u00f3n?", - "MessageRecordingDeleted": "Grabaci\u00f3n eliminada.", - "ButonCancelRecording": "Cancelar Grabaci\u00f3n", - "MessageRecordingSaved": "Grabaci\u00f3n guardada.", - "OptionSunday": "Domingo", - "OptionMonday": "Lunes", - "OptionTuesday": "Martes", - "OptionWednesday": "Mi\u00e9rcoles", - "OptionThursday": "Jueves", - "OptionFriday": "Viernes", - "OptionSaturday": "S\u00e1bado", - "HeaderConfirmDeletion": "Confirmar borrado", - "MessageConfirmPathSubstitutionDeletion": "\u00bfEst\u00e1 seguro que desea borrar esta ruta de sustituci\u00f3n?", - "LiveTvUpdateAvailable": "(Actualizaci\u00f3n disponible)", - "LabelVersionUpToDate": "\u00a1Actualizado!", - "ButtonResetTuner": "Reiniciar sintonizador", - "HeaderResetTuner": "Reinicio del sintonizador", - "MessageConfirmResetTuner": "\u00bfEst\u00e1 seguro que desea reiniciar este sintonizador? Cualquier reproducci\u00f3n o grabaci\u00f3n activa se detendr\u00e1 inmediatamente.", - "ButtonCancelSeries": "Cancelar serie", - "LabelAllChannels": "Todos los canales", - "HeaderSeriesRecordings": "Grabaciones de series", - "LabelAnytime": "A cualquier hora", - "StatusRecording": "Grabando", - "StatusWatching": "Viendo", - "StatusRecordingProgram": "Grabando {0}", - "StatusWatchingProgram": "Viendo {0}", - "HeaderSplitMedia": "Divisi\u00f3n de medios", - "MessageConfirmSplitMedia": "\u00bfEst\u00e1 seguro que desea dividir los medios en partes separadas?", - "HeaderError": "Error", - "MessagePleaseSelectOneItem": "Seleccione al menos un elemento.", - "MessagePleaseSelectTwoItems": "Seleccione al menos dos elementos.", - "MessageTheFollowingItemsWillBeGrouped": "Los siguientes t\u00edtulos se agrupar\u00e1n en un elemento.", - "MessageConfirmItemGrouping": "Los clientes de Media Browser elegir\u00e1n autom\u00e1ticamente la mejor forma de reproduccion sobre la base de dispositivo y rendimiento de la red. \u00bfEst\u00e1 seguro que desea continuar?", - "HeaderResume": "Continuar", - "HeaderMyViews": "Mis vistas", - "HeaderLibraryFolders": "Vista de carpeta", - "HeaderLatestMedia": "\u00daltimos medios", - "ButtonMore": "M\u00e1s...", - "HeaderFavoriteMovies": "Pel\u00edculas favoritas", - "HeaderFavoriteShows": "Programas favoritos", - "HeaderFavoriteEpisodes": "Episodios favoritos", - "HeaderFavoriteGames": "Juegos favoritos", - "HeaderRatingsDownloads": "\nClasificaci\u00f3n \/ Descargas", - "HeaderConfirmProfileDeletion": "Confirmar borrado del perfil", - "MessageConfirmProfileDeletion": "\u00bfEst\u00e1 seguro que desea eliminar este perfil?", - "HeaderSelectServerCachePath": "Seleccione la ruta para el cach\u00e9 del servidor", - "HeaderSelectTranscodingPath": "Seleccione la ruta temporal del transcodificador", - "HeaderSelectImagesByNamePath": "Seleccione la ruta para im\u00e1genes", - "HeaderSelectMetadataPath": "Seleccione la ruta para Metadatos", - "HeaderSelectServerCachePathHelp": "Busque o escriba la ruta de acceso que se utilizar\u00e1 para los archivos de cach\u00e9 del servidor. La carpeta debe tener permiso de escritura. La ubicaci\u00f3n de esta carpeta afectar\u00e1 directamente al rendimiento del servidor e idealmente debe ser colocado en una unidad de estado s\u00f3lido.", - "HeaderSelectTranscodingPathHelp": "Busque o escriba la ruta de acceso que se utilizar\u00e1 para la transcodificaci\u00f3n de archivos temporales. La carpeta debe tener permiso de escritura.", - "HeaderSelectImagesByNamePathHelp": "Busque o escriba la ruta de sus elementos por nombre de carpeta. La carpeta debe tener permisos de escritura.", - "HeaderSelectMetadataPathHelp": "Busque o escriba la ruta donde desea almacenar los metadatos. La carpeta debe tener permiso de escritura.", - "HeaderSelectChannelDownloadPath": "Seleccione la ruta de descargas de canal", - "HeaderSelectChannelDownloadPathHelp": "Navege o escriba la ruta para guardar el los archivos de cach\u00e9 de canales. La carpeta debe tener permisos de escritura.", - "OptionNewCollection": "Nuevo...", - "ButtonAdd": "A\u00f1adir", - "ButtonRemove": "Quitar", - "LabelChapterDownloaders": "Downloaders de cap\u00edtulos:", - "LabelChapterDownloadersHelp": "Habilitar y clasificar sus descargadores de cap\u00edtulos preferidos en orden de prioridad. Descargadores de menor prioridad s\u00f3lo se utilizar\u00e1n para completar la informaci\u00f3n que falta.", - "HeaderFavoriteAlbums": "\u00c1lbumes favoritos", - "HeaderLatestChannelMedia": "\u00dcltimos elementos de canal", - "ButtonOrganizeFile": "Organizar archivos", - "ButtonDeleteFile": "Borrar archivos", - "HeaderOrganizeFile": "Organizar archivos", - "HeaderDeleteFile": "Borrar archivos", - "StatusSkipped": "Saltado", - "StatusFailed": "Err\u00f3neo", - "StatusSuccess": "\u00c9xito", - "MessageFileWillBeDeleted": "El siguiente archivo se eliminar\u00e1:", - "MessageSureYouWishToProceed": "\u00bfEst\u00e1 seguro que desea proceder?", - "MessageDuplicatesWillBeDeleted": "Adem\u00e1s se eliminar\u00e1n los siguientes duplicados:", - "MessageFollowingFileWillBeMovedFrom": "El siguiente archivo se mover\u00e1 desde:", - "MessageDestinationTo": "hasta:", - "HeaderSelectWatchFolder": "Seleccionar carpeta para el reloj", - "HeaderSelectWatchFolderHelp": "Navegue o introduzca la ruta para la carpeta para el reloj. La carpeta debe tener permisos de escritura.", - "OrganizePatternResult": "Resultado: {0}", - "HeaderRestart": "Reiniciar", - "HeaderShutdown": "Apagar", - "MessageConfirmRestart": "\u00bfEst\u00e1 seguro que desea reiniciar Media Browser Server?", - "MessageConfirmShutdown": "\u00bfEst\u00e1 seguro que desea apagar Media Browser Server?", - "ButtonUpdateNow": "Actualizar ahora", - "NewVersionOfSomethingAvailable": "\u00a1Hay disponible una nueva versi\u00f3n de {0}!", - "VersionXIsAvailableForDownload": "La versi\u00f3n {0} est\u00e1 disponible para su descarga.", - "LabelVersionNumber": "Versi\u00f3n {0}", - "LabelPlayMethodTranscoding": "Transcodificaci\u00f3n", - "LabelPlayMethodDirectStream": "Streaming directo", - "LabelPlayMethodDirectPlay": "Reproducci\u00f3n directa", - "LabelAudioCodec": "Audio: {0}", - "LabelVideoCodec": "Video: {0}", - "LabelRemoteAccessUrl": "Acceso remoto: {0}", - "LabelRunningOnPort": "Ejecut\u00e1ndose en el puerto {0}.", - "LabelRunningOnPorts": "Ejecut\u00e1ndose en los puertos {0} y {1}.", - "HeaderLatestFromChannel": "Lo \u00faltimo de {0}", - "ButtonDownload": "Descargar", - "LabelUnknownLanaguage": "Idioma desconocido", - "HeaderCurrentSubtitles": "Subt\u00edtulos actuales", - "MessageDownloadQueued": "La descarga se ha a\u00f1adido a la cola", - "MessageAreYouSureDeleteSubtitles": "\u00bfEst\u00e1 seguro que desea eliminar este archivo de subt\u00edtulos?", - "ButtonRemoteControl": "Control remoto", - "HeaderLatestTvRecordings": "\u00daltimas grabaciones", - "ButtonOk": "OK", - "ButtonCancel": "Cancelar", - "ButtonRefresh": "Refrescar", - "LabelCurrentPath": "Ruta actual:", - "HeaderSelectMediaPath": "Seleccionar la ruta para Medios", - "ButtonNetwork": "Red", - "MessageDirectoryPickerInstruction": "Rutas de red pueden ser introducidas manualmente en el caso de que el bot\u00f3n de la red no pueda localizar sus dispositivos. Por ejemplo, {0} o {1}.", - "HeaderMenu": "Men\u00fa", - "ButtonOpen": "Abrir", - "ButtonOpenInNewTab": "Abrir en nueva pesta\u00f1a", - "ButtonShuffle": "Mezclar", - "ButtonInstantMix": "Mix instant\u00e1neo", - "ButtonResume": "Continuar", - "HeaderScenes": "Escenas", - "HeaderAudioTracks": "Pistas de audio", - "HeaderSubtitles": "Subt\u00edtulos", - "HeaderVideoQuality": "Calidad de video", - "MessageErrorPlayingVideo": "Ha habido un error reproduciendo el video.", - "MessageEnsureOpenTuner": "Aseg\u00farese que hay un sintonizador disponible.", - "ButtonHome": "Inicio", - "ButtonDashboard": "Panel de control", - "ButtonReports": "Informes", - "ButtonMetadataManager": "Metadata Manager", - "HeaderTime": "Duraci\u00f3n", - "HeaderName": "Nombre", - "HeaderAlbum": "Album", - "HeaderAlbumArtist": "Artista del album", - "HeaderArtist": "Artista", - "LabelAddedOnDate": "A\u00f1adido {0}", - "ButtonStart": "Inicio", - "HeaderChannels": "Canales", - "HeaderMediaFolders": "Carpetas de medios", - "HeaderBlockItemsWithNoRating": "Bloquear elementos sin informaci\u00f3n de clasificaci\u00f3n:", - "OptionBlockOthers": "Otros", - "OptionBlockTvShows": "Tv Shows", - "OptionBlockTrailers": "Trailers", - "OptionBlockMusic": "M\u00fasica", - "OptionBlockMovies": "Pel\u00edculas", - "OptionBlockBooks": "Libros", - "OptionBlockGames": "Juegos", - "OptionBlockLiveTvPrograms": "Programas de TV en vivo", - "OptionBlockLiveTvChannels": "Canales de Tv en vivo", - "OptionBlockChannelContent": "Contenido de canales de Internet", - "ButtonRevoke": "Revocar", - "MessageConfirmRevokeApiKey": "Are you sure you wish to revoke this api key? The application's connection to Media Browser will be abruptly terminated.", - "HeaderConfirmRevokeApiKey": "Revoke Api Key" -}
\ 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 11cff24d9..d365a2c76 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json @@ -6,6 +6,8 @@ "Administrator": "Administrador", "Password": "Contrase\u00f1a", "DeleteImage": "Eliminar imagen", + "MessageThankYouForSupporting": "Gracias por apoyar Media Browser.", + "MessagePleaseSupportMediaBrowser": "Por favor apoya Media Browser.", "DeleteImageConfirmation": "\u00bfEst\u00e1 seguro de querer eliminar esta imagen?", "FileReadCancelled": "La lectura del archivo ha sido cancelada.", "FileNotFound": "Archivo no encontrado.", @@ -14,7 +16,10 @@ "DeleteUserConfirmation": "\u00bfEst\u00e1 seguro de querer eliminar este usuario?", "PasswordResetHeader": "Restablecer Contrase\u00f1a", "PasswordResetComplete": "La contrase\u00f1a ha sido restablecida.", + "PinCodeResetComplete": "The pin code has been reset.", "PasswordResetConfirmation": "\u00bfEst\u00e1 seguro de querer restablecer la contrase\u00f1a?", + "PinCodeResetConfirmation": "Are you sure you wish to reset the pin code?", + "HeaderPinCodeReset": "Reset Pin Code", "PasswordSaved": "Contrase\u00f1a guardada.", "PasswordMatchError": "La Contrase\u00f1a y la confirmaci\u00f3n de la contrase\u00f1a deben coincidir.", "OptionRelease": "Versi\u00f3n Oficial", @@ -32,6 +37,7 @@ "MessageKeyRemoved": "Gracias. Su clave de aficionado ha sido eliminada.", "ErrorLaunchingChromecast": "Hubo un error iniciando chromecast. Por favor aseg\u00farate de que tu dispositivo este conectado a tu red inalambrica", "HeaderSearch": "Buscar", + "ValueDateCreated": "Fecha de creaci\u00f3n: {0}", "LabelArtist": "Artista", "LabelMovie": "Pel\u00edcula", "LabelMusicVideo": "Video Musical", @@ -42,17 +48,32 @@ "LabelFailed": "(Fallido)", "ButtonHelp": "Ayuda", "ButtonSave": "Guardar", - "HeaderSupporterBenefit": "A supporter membership provides additional benefits such as access to premium plugins, internet channel content, and more. {0}Learn more{1}.", + "LabelCollection": "Colecci\u00f3n", + "HeaderAddToCollection": "Agregar a Colecci\u00f3n.", + "NewCollectionNameExample": "Ejemplo: Colecci\u00f3n Guerra de las Galaxias", + "OptionSearchForInternetMetadata": "Buscar en internet ilustraciones y metadatos", + "LabelSelectCollection": "Elegir colecci\u00f3n:", + "HeaderDevices": "Dispositivos", + "ButtonScheduledTasks": "Tareas programadas", + "MessageItemsAdded": "\u00cdtems agregados", + "ButtonAddToCollection": "Agregar a colecci\u00f3n", + "HeaderSelectCertificatePath": "Seleccione Trayectoria del Certificado", + "ConfirmMessageScheduledTaskButton": "Esta operaci\u00f3n normalmente es ejecutada autom\u00e1ticamente como una tarea programada. Tambi\u00e9n puede ser ejecutada manualmente desde aqu\u00ed. Para configurar la tarea programada, vea:", + "HeaderSupporterBenefit": "La membres\u00eda de aficionado proporciona beneficios adicionales tales como acceso a complementos premium, contenido de canales de Internet y m\u00e1s. {0}Conocer m\u00e1s{1}.", "HeaderWelcomeToMediaBrowserServerDashboard": "Bienvenido al Panel de Control de Media Browser", "HeaderWelcomeToMediaBrowserWebClient": "Bienvenido al Cliente Web de Media Browser", "ButtonTakeTheTour": "Haga el recorrido", - "HeaderWelcomeBack": "Welcome back!", - "ButtonTakeTheTourToSeeWhatsNew": "Take the tour to see what's new", + "HeaderWelcomeBack": "\u00a1Bienvenido nuevamente!", + "ButtonTakeTheTourToSeeWhatsNew": "Inice el tour para ver que hay de nuevo", "MessageNoSyncJobsFound": "No se han encontrado trabajos de sincronizaci\u00f3n. Cree trabajos de sincronizaci\u00f3n empleando los botones de Sinc que se encuentran en la intergface web.", "HeaderLibraryAccess": "Acceso a la Biblioteca", "HeaderChannelAccess": "Acceso a los Canales", "HeaderDeviceAccess": "Acceso a Dispositivos", "HeaderSelectDevices": "Seleccionar Dispositivos", + "ButtonCancelItem": "Cancelar \u00edtem.", + "ButtonQueueForRetry": "En cola para reintentar", + "ButtonReenable": "Re-habilitar", + "SyncJobItemStatusSyncedMarkForRemoval": "Marcado para remover", "LabelAbortedByServerShutdown": "(Abortada por apagado del servidor)", "LabelScheduledTaskLastRan": "Ejecutado hace {0}, tomando {1}.", "HeaderDeleteTaskTrigger": "Borrar Disparador de Tarea", @@ -64,10 +85,13 @@ "LabelFree": "Gratis", "HeaderSelectAudio": "Seleccionar Audio", "HeaderSelectSubtitles": "Seleccionar Subtitulos", + "ButtonMarkForRemoval": "Marcado para remover del dispositivo", + "ButtonUnmarkForRemoval": "Desmarcar para remover del dispositivo", "LabelDefaultStream": "(Por defecto)", "LabelForcedStream": "(Forzado)", "LabelDefaultForcedStream": "(Por Defecto\/Forzado)", "LabelUnknownLanguage": "Idioma Desconocido", + "MessageConfirmSyncJobItemCancellation": "\u00bfEsta seguro que desea cancelar este \u00edtem?", "ButtonMute": "Mudo", "ButtonUnmute": "Quitar mudo", "ButtonStop": "Detener", @@ -191,8 +215,10 @@ "LabelPlayMethodDirectPlay": "Reproducci\u00f3n Directa", "LabelAudioCodec": "Audio: {0}", "LabelVideoCodec": "Video: {0}", + "LabelLocalAccessUrl": "Direcci\u00f3n local: {0}", "LabelRemoteAccessUrl": "Acceso remoto: {0}", - "LabelRunningOnPort": "Ejecutando en el puerto: {0}.", + "LabelRunningOnPort": "Ejecut\u00e1ndose en el puerto http {0}.", + "LabelRunningOnPorts": "Ejecut\u00e1ndose en el puerto http {0} y el puerto https {1}.", "HeaderLatestFromChannel": "M\u00e1s recientes desde {0}", "ButtonDownload": "Descargar", "LabelUnknownLanaguage": "Idioma desconocido", @@ -206,6 +232,7 @@ "ButtonRefresh": "Actualizar", "LabelCurrentPath": "Ruta actual:", "HeaderSelectMediaPath": "Seleccionar ruta a medios", + "HeaderSelectPath": "Seleccionar Trayectoria", "ButtonNetwork": "Red", "MessageDirectoryPickerInstruction": "Las rutas de red pueden ser ingresadas manualmente en caso de que el bot\u00f3n de Red no pueda localizar sus dispositivos. Por ejemplo, {0} or {1}.", "HeaderMenu": "Men\u00fa", @@ -216,6 +243,7 @@ "ButtonResume": "Continuar", "HeaderScenes": "Escenas", "HeaderAudioTracks": "Pistas de Audio", + "HeaderLibraries": "Bibliotecas", "HeaderSubtitles": "Subt\u00edtulos", "HeaderVideoQuality": "Calidad de Video", "MessageErrorPlayingVideo": "Ha ocurrido un error al reproducir el video.", @@ -266,13 +294,13 @@ "MessagePleaseEnterNameOrId": "Por favor ingrese un nombre o id externo.", "MessageValueNotCorrect": "El valor ingresado no es correcto. Intente nuevamente por favor.", "MessageItemSaved": "\u00cdtem guardado.", - "MessagePleaseAcceptTermsOfServiceBeforeContinuing": "Please accept the terms of service before continuing.", + "MessagePleaseAcceptTermsOfServiceBeforeContinuing": "Por favor acepte los t\u00e9rminos del servicio antes de continuar.", "OptionEnded": "Finalizado", "OptionContinuing": "Continuando", "OptionOff": "No", "OptionOn": "Si", "ButtonSettings": "Configuraci\u00f3n", - "ButtonUninstall": "Uninstall", + "ButtonUninstall": "Desinstalar", "HeaderFields": "Campos", "HeaderFieldsHelp": "Deslice un campo hacia \"apagado\" para bloquearlo y evitar que sus datos sean modificados.", "HeaderLiveTV": "TV en Vivo", @@ -338,8 +366,8 @@ "ButtonNew": "Nuevo", "MessageInternetExplorerWebm": "Para mejores resultados con Internet Explorer por favor instale el complemento de reproducci\u00f3n WebM.", "HeaderVideoError": "Error de Video", - "ButtonAddToPlaylist": "A\u00f1adir a lista de reproducci\u00f3n", - "HeaderAddToPlaylist": "A\u00f1adir a Lista de Reproducci\u00f3n", + "ButtonAddToPlaylist": "Agregar a lista de reproducci\u00f3n", + "HeaderAddToPlaylist": "Agregar a Lista de Reproducci\u00f3n", "LabelName": "Nombre:", "ButtonSubmit": "Enviar", "LabelSelectPlaylist": "Lista de Reproducci\u00f3n:", @@ -406,7 +434,7 @@ "LabelParentNumber": "N\u00famero antecesor", "LabelEpisodeNumber": "N\u00famero de episodio:", "LabelTrackNumber": "N\u00famero de Pista:", - "LabelNumber": "N\u00famero", + "LabelNumber": "N\u00famero:", "LabelReleaseDate": "Fecha de estreno:", "LabelEndDate": "Fecha de Fin:", "LabelYear": "A\u00f1o:", @@ -581,6 +609,8 @@ "MediaInfoStreamTypeEmbeddedImage": "Im\u00e1gen Embebida", "MediaInfoRefFrames": "Tramas de referencia", "TabPlayback": "Reproducci\u00f3n", + "TabNotifications": "Notificaciones", + "TabExpert": "Experto", "HeaderSelectCustomIntrosPath": "Seleccionar Trayectorias Personalizadas de Intros", "HeaderRateAndReview": "Clasificar y Rese\u00f1ar", "HeaderThankYou": "Gracias", @@ -591,8 +621,8 @@ "OptionIRecommendThisItem": "Yo recomiendo este \u00edtem", "WebClientTourContent": "Vea sus medios recientemente a\u00f1adidos, siguientes ep\u00ecsodios y m\u00e1s. Los c\u00edrculos verdes indican cuantos medios sin reproducir tiene.", "WebClientTourMovies": "Reproduzca pel\u00edculas, avances y m\u00e1s desde cualquier dispositivo con un navegador web.", - "WebClientTourMouseOver": "Mantgenga el rat\u00f3n sobre cualquier cartel para un acceso r\u00e1pido a informaci\u00f3n importante.", - "WebClientTourTapHold": "Mantenga presionado o haga clic derecho en cualquier cartel para mostrar un men\u00fa contextual", + "WebClientTourMouseOver": "Mantenga el rat\u00f3n sobre cualquier p\u00f3ster para un acceso r\u00e1pido a informaci\u00f3n importante.", + "WebClientTourTapHold": "Mantenga presionado o haga clic derecho en cualquier p\u00f3ster para mostrar un men\u00fa contextual", "WebClientTourMetadataManager": "Haga clic en editar para abrir el administrador de metadatos", "WebClientTourPlaylists": "Cree f\u00e1cilmente listas de reproducci\u00f3n y mezclas instant\u00e1neas, y reprod\u00fazcalas en cualquier dispositivo", "WebClientTourCollections": "Cree colecciones de pel\u00edculas para agruparlas en sets de pel\u00edculas", @@ -615,6 +645,7 @@ "DashboardTourMobile": "El Panel de Control de Media Browser funciona excelentemente en tel\u00e9fonos inteligentes y tabletas. Administre su servidor desde la palma de su mano en todo momento y lugar.", "MessageRefreshQueued": "Actualizaci\u00f3n programada", "TabDevices": "Dispositivos", + "TabExtras": "Extras", "DeviceLastUsedByUserName": "\u00daltimo usado por {0}", "HeaderDeleteDevice": "Eliminar Dispositivo", "DeleteDeviceConfirmation": "\u00bfEst\u00e1 seguro de querer eliminar este dispositivo? Volver\u00e1 a aparecer la siguiente vez que un usuario inicie sesi\u00f3n en \u00e9l.", @@ -647,11 +678,11 @@ "MessageConnectAccountRequiredToInviteGuest": "Para poder agregar invitados primero necesitas vincular tu cuenta de Media Browser a este servidor.", "ButtonSync": "SInc", "SyncMedia": "Sincronizar Medios", - "HeaderCancelSyncJob": "Cancelar Sinc", + "HeaderCancelSyncJob": "Cancelar Sinc.", "CancelSyncJobConfirmation": "\u00bfEsta seguro de querer cancelar este trabajo de sincronizaci\u00f3n?", "TabSync": "Sinc", "MessagePleaseSelectDeviceToSyncTo": "Por favor seleccione un dispositivo con el que desea sincronizar.", - "MessageSyncJobCreated": "Trabajo de sinc creado.", + "MessageSyncJobCreated": "Trabajo de sinc. creado.", "LabelSyncTo": "Sincronizar con:", "LabelSyncJobName": "Nombre del trabajo de sinc:", "LabelQuality": "Calidad:", @@ -668,7 +699,7 @@ "MessageBookPluginRequired": "Requiere instalaci\u00f3n del complemento Bookshelf", "MessageGamePluginRequired": "Requiere instalaci\u00f3n del complemento de GameBrowser", "MessageUnsetContentHelp": "El contenido ser\u00e1 desplegado como carpetas simples. Para mejores resultados utilice el administrador de metadatos para establecer los tipos de contenido para las sub-carpetas.", - "SyncJobItemStatusQueued": "Encolado", + "SyncJobItemStatusQueued": "En cola", "SyncJobItemStatusConverting": "Convirti\u00e9ndo", "SyncJobItemStatusTransferring": "Transfiri\u00e9ndo", "SyncJobItemStatusSynced": "Sincronizado", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/fi.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/fi.json index b6cc3ec14..83069c29e 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/fi.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/fi.json @@ -6,6 +6,8 @@ "Administrator": "Administrator", "Password": "Salasana", "DeleteImage": "Poista Kuva", + "MessageThankYouForSupporting": "Thank you for supporting Media Browser.", + "MessagePleaseSupportMediaBrowser": "Please support Media Browser.", "DeleteImageConfirmation": "Oletko varma ett\u00e4 haluat poistaa t\u00e4m\u00e4n kuvan?", "FileReadCancelled": "Tiedoston luku on peruutettu.", "FileNotFound": "Tiedostoa ei l\u00f6ydy.", @@ -14,7 +16,10 @@ "DeleteUserConfirmation": "Oletko varma ett\u00e4 haluat poistaa t\u00e4m\u00e4n k\u00e4ytt\u00e4j\u00e4n?", "PasswordResetHeader": "Salasanan Palautus", "PasswordResetComplete": "Salasana on palauttettu.", + "PinCodeResetComplete": "The pin code has been reset.", "PasswordResetConfirmation": "Oletko varma, ett\u00e4 haluat palauttaa salasanan?", + "PinCodeResetConfirmation": "Are you sure you wish to reset the pin code?", + "HeaderPinCodeReset": "Reset Pin Code", "PasswordSaved": "Salasana tallennettu.", "PasswordMatchError": "Salasana ja salasanan vahvistuksen pit\u00e4\u00e4 olla samat.", "OptionRelease": "Virallinen Julkaisu", @@ -32,6 +37,7 @@ "MessageKeyRemoved": "Thank you. Your supporter key has been removed.", "ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.", "HeaderSearch": "Search", + "ValueDateCreated": "Date created: {0}", "LabelArtist": "Artist", "LabelMovie": "Movie", "LabelMusicVideo": "Music Video", @@ -42,6 +48,17 @@ "LabelFailed": "(failed)", "ButtonHelp": "Help", "ButtonSave": "Tallenna", + "LabelCollection": "Collection", + "HeaderAddToCollection": "Add to Collection", + "NewCollectionNameExample": "Example: Star Wars Collection", + "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata", + "LabelSelectCollection": "Select collection:", + "HeaderDevices": "Devices", + "ButtonScheduledTasks": "Scheduled tasks", + "MessageItemsAdded": "Items added", + "ButtonAddToCollection": "Add to collection", + "HeaderSelectCertificatePath": "Select Certificate Path", + "ConfirmMessageScheduledTaskButton": "This operation normally runs automatically as a scheduled task. It can also be run manually here. To configure the scheduled task, see:", "HeaderSupporterBenefit": "A supporter membership provides additional benefits such as access to premium plugins, internet channel content, and more. {0}Learn more{1}.", "HeaderWelcomeToMediaBrowserServerDashboard": "Welcome to the Media Browser Dashboard", "HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client", @@ -53,6 +70,10 @@ "HeaderChannelAccess": "Channel Access", "HeaderDeviceAccess": "Device Access", "HeaderSelectDevices": "Select Devices", + "ButtonCancelItem": "Cancel item", + "ButtonQueueForRetry": "Queue for retry", + "ButtonReenable": "Re-enable", + "SyncJobItemStatusSyncedMarkForRemoval": "Marked for removal", "LabelAbortedByServerShutdown": "(Aborted by server shutdown)", "LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.", "HeaderDeleteTaskTrigger": "Delete Task Trigger", @@ -64,10 +85,13 @@ "LabelFree": "Free", "HeaderSelectAudio": "Select Audio", "HeaderSelectSubtitles": "Select Subtitles", + "ButtonMarkForRemoval": "Mark for removal from device", + "ButtonUnmarkForRemoval": "Unmark for removal from device", "LabelDefaultStream": "(Default)", "LabelForcedStream": "(Forced)", "LabelDefaultForcedStream": "(Default\/Forced)", "LabelUnknownLanguage": "Unknown language", + "MessageConfirmSyncJobItemCancellation": "Are you sure you wish to cancel this item?", "ButtonMute": "Mute", "ButtonUnmute": "Unmute", "ButtonStop": "Stop", @@ -191,8 +215,10 @@ "LabelPlayMethodDirectPlay": "Direct Playing", "LabelAudioCodec": "Audio: {0}", "LabelVideoCodec": "Video: {0}", + "LabelLocalAccessUrl": "Local access: {0}", "LabelRemoteAccessUrl": "Remote access: {0}", - "LabelRunningOnPort": "Running on port {0}.", + "LabelRunningOnPort": "Running on http port {0}.", + "LabelRunningOnPorts": "Running on http port {0}, and https port {1}.", "HeaderLatestFromChannel": "Latest from {0}", "ButtonDownload": "Download", "LabelUnknownLanaguage": "Unknown language", @@ -206,6 +232,7 @@ "ButtonRefresh": "Refresh", "LabelCurrentPath": "Current path:", "HeaderSelectMediaPath": "Select Media Path", + "HeaderSelectPath": "Select Path", "ButtonNetwork": "Network", "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.", "HeaderMenu": "Menu", @@ -216,6 +243,7 @@ "ButtonResume": "Resume", "HeaderScenes": "Scenes", "HeaderAudioTracks": "Audio Tracks", + "HeaderLibraries": "Libraries", "HeaderSubtitles": "Subtitles", "HeaderVideoQuality": "Video Quality", "MessageErrorPlayingVideo": "There was an error playing the video.", @@ -581,6 +609,8 @@ "MediaInfoStreamTypeEmbeddedImage": "Embedded Image", "MediaInfoRefFrames": "Ref frames", "TabPlayback": "Playback", + "TabNotifications": "Notifications", + "TabExpert": "Expert", "HeaderSelectCustomIntrosPath": "Select Custom Intros Path", "HeaderRateAndReview": "Rate and Review", "HeaderThankYou": "Thank You", @@ -615,6 +645,7 @@ "DashboardTourMobile": "The Media Browser dashboard works great on smartphones and tablets. Manage your server from the palm of your hand anytime, anywhere.", "MessageRefreshQueued": "Refresh queued", "TabDevices": "Devices", + "TabExtras": "Extras", "DeviceLastUsedByUserName": "Last used by {0}", "HeaderDeleteDevice": "Delete Device", "DeleteDeviceConfirmation": "Are you sure you wish to delete this device? It will reappear the next time a user signs in with it.", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json index f504475e8..074cd146d 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json @@ -6,6 +6,8 @@ "Administrator": "Administrateur", "Password": "Mot de passe", "DeleteImage": "Supprimer l'image", + "MessageThankYouForSupporting": "Merci pour votre soutien \u00e0 Media Browser.", + "MessagePleaseSupportMediaBrowser": "Supporter Media Browser s'il vous plait.", "DeleteImageConfirmation": "\u00cates-vous s\u00fbr de vouloir supprimer l'image?", "FileReadCancelled": "La lecture du fichier a \u00e9t\u00e9 annul\u00e9e.", "FileNotFound": "Fichier introuvable.", @@ -14,7 +16,10 @@ "DeleteUserConfirmation": "\u00cates-vous s\u00fbr de vouloir supprimer cet utilisateur?", "PasswordResetHeader": "R\u00e9initialisation du mot de passe", "PasswordResetComplete": "Le mot de passe a \u00e9t\u00e9 r\u00e9initialis\u00e9.", + "PinCodeResetComplete": "Le code Easy Pin a \u00e9t\u00e9 r\u00e9initialis\u00e9.", "PasswordResetConfirmation": "\u00cates-vous s\u00fbr de vouloir r\u00e9initialiser le mot de passe?", + "PinCodeResetConfirmation": "Etes-vous s\u00fbr de vouloir r\u00e9initialiser le code pin ?", + "HeaderPinCodeReset": "R\u00e9initialiser le code Pin", "PasswordSaved": "Mot de passe sauvegard\u00e9.", "PasswordMatchError": "Le mot de passe et sa confirmation doivent correspondre.", "OptionRelease": "Version officielle", @@ -32,6 +37,7 @@ "MessageKeyRemoved": "Merci. Votre cl\u00e9 de supporteur a \u00e9t\u00e9 supprim\u00e9e.", "ErrorLaunchingChromecast": "Une erreur a \u00e9t\u00e9 rencontr\u00e9e lors du lancement de Chromecast. Veuillez vous assurer que votre appareil est bien connect\u00e9 \u00e0 votre r\u00e9seau sans-fil.", "HeaderSearch": "Recherche", + "ValueDateCreated": "Date de cr\u00e9ation : {0}", "LabelArtist": "Artiste", "LabelMovie": "Film", "LabelMusicVideo": "Clip vid\u00e9o", @@ -42,7 +48,18 @@ "LabelFailed": "(\u00e9chou\u00e9)", "ButtonHelp": "Aide", "ButtonSave": "Sauvegarder", - "HeaderSupporterBenefit": "A supporter membership provides additional benefits such as access to premium plugins, internet channel content, and more. {0}Learn more{1}.", + "LabelCollection": "Collection", + "HeaderAddToCollection": "Ajouter \u00e0 la collection", + "NewCollectionNameExample": "Exemple: Collection Star Wars", + "OptionSearchForInternetMetadata": "Rechercher sur Internet les images et m\u00e9tadonn\u00e9es", + "LabelSelectCollection": "S\u00e9lectionner la collection :", + "HeaderDevices": "Appareils", + "ButtonScheduledTasks": "T\u00e2ches planifi\u00e9es", + "MessageItemsAdded": "Items ajout\u00e9s", + "ButtonAddToCollection": "Ajouter \u00e0 une collection", + "HeaderSelectCertificatePath": "S\u00e9lectionnez le chemin du certificat", + "ConfirmMessageScheduledTaskButton": "Cette op\u00e9ration s'ex\u00e9cute normalement automatiquement en tant que t\u00e2che planifi\u00e9e. Elle peut aussi \u00eatre ex\u00e9cut\u00e9e manuellement ici. Pour configurer la t\u00e2che planifi\u00e9e, voir:", + "HeaderSupporterBenefit": "Un partenariat de membre supporteur apporte des avantages suppl\u00e9mentaires, comme l'acc\u00e8s aux plugins premiums, aux contenus des cha\u00eenes Internet, et plus encore. {0}En savoir plus{1}.", "HeaderWelcomeToMediaBrowserServerDashboard": "Bienvenue dans le centre de contr\u00f4le de Media browser", "HeaderWelcomeToMediaBrowserWebClient": "Bienvenue sur le client web de Media Browser", "ButtonTakeTheTour": "Visite guid\u00e9e", @@ -53,6 +70,10 @@ "HeaderChannelAccess": "Acc\u00e8s Cha\u00eene", "HeaderDeviceAccess": "Acc\u00e8s \u00e0 l'appareil", "HeaderSelectDevices": "S\u00e9lectionnez un appareil", + "ButtonCancelItem": "Annuler l'\u00e9l\u00e9ment", + "ButtonQueueForRetry": "File d'attente pour une nouvelle tentative", + "ButtonReenable": "R\u00e9activer", + "SyncJobItemStatusSyncedMarkForRemoval": "Marquer pour suppression", "LabelAbortedByServerShutdown": "(Annul\u00e9 par fermeture du serveur)", "LabelScheduledTaskLastRan": "Derni\u00e8re ex\u00e9cution {0}, dur\u00e9e {1}.", "HeaderDeleteTaskTrigger": "Supprimer le d\u00e9clencheur de t\u00e2che", @@ -64,10 +85,13 @@ "LabelFree": "Gratuit", "HeaderSelectAudio": "S\u00e9lectionner audio", "HeaderSelectSubtitles": "S\u00e9lectionner sous-titres", + "ButtonMarkForRemoval": "Marquer pour suppression dans le disque", + "ButtonUnmarkForRemoval": "Lib\u00e9rer la suppression dans le disque", "LabelDefaultStream": "(Par d\u00e9faut)", "LabelForcedStream": "(Forc\u00e9)", "LabelDefaultForcedStream": "(Par d\u00e9faut\/Forc\u00e9)", "LabelUnknownLanguage": "Langue inconnue", + "MessageConfirmSyncJobItemCancellation": "Vouslez vous vraiment annuler cet action?", "ButtonMute": "Sourdine", "ButtonUnmute": "D\u00e9sactiver sourdine", "ButtonStop": "Arr\u00eat", @@ -191,8 +215,10 @@ "LabelPlayMethodDirectPlay": "Direct Play", "LabelAudioCodec": "Audio : {0}", "LabelVideoCodec": "Vid\u00e9o : {0}", + "LabelLocalAccessUrl": "Acc\u00e8s local : {0}", "LabelRemoteAccessUrl": "URL d'acc\u00e8s \u00e0 distance: {0}", - "LabelRunningOnPort": "En ex\u00e9cution sur le port: {0}.", + "LabelRunningOnPort": "En cours d'ex\u00e9cution sur le port http {0}.", + "LabelRunningOnPorts": "En cours d'ex\u00e9cution sur le port http {0} et https {1}.", "HeaderLatestFromChannel": "Les plus r\u00e9cents de {0}", "ButtonDownload": "T\u00e9l\u00e9chargement", "LabelUnknownLanaguage": "Langue inconnue", @@ -206,6 +232,7 @@ "ButtonRefresh": "Actualiser", "LabelCurrentPath": "Chemin d'acc\u00e8s actuel :", "HeaderSelectMediaPath": "S\u00e9lectionnez le chemin du m\u00e9dia", + "HeaderSelectPath": "S\u00e9lectionnez un chemin", "ButtonNetwork": "R\u00e9seau", "MessageDirectoryPickerInstruction": "Les chemins r\u00e9seaux peuvent \u00eatre saisis manuellement dans le cas o\u00f9 l'utilisation du bouton \"R\u00e9seau\" ne parvient pas \u00e0 localiser les ressources. Par exemple, {0} ou {1}.", "HeaderMenu": "Menu", @@ -216,6 +243,7 @@ "ButtonResume": "Reprendre", "HeaderScenes": "Sc\u00e8nes", "HeaderAudioTracks": "Pistes audio", + "HeaderLibraries": "Bilblioth\u00e8ques", "HeaderSubtitles": "Sous-titres", "HeaderVideoQuality": "Qualit\u00e9 vid\u00e9o", "MessageErrorPlayingVideo": "La lecture de la vid\u00e9o a rencontr\u00e9 une erreur", @@ -340,7 +368,7 @@ "HeaderVideoError": "Erreur vid\u00e9o", "ButtonAddToPlaylist": "Ajouter \u00e0 la liste de lecture", "HeaderAddToPlaylist": "Ajouter \u00e0 la liste de lecture", - "LabelName": "Nom :", + "LabelName": "Nom", "ButtonSubmit": "Soumettre", "LabelSelectPlaylist": "Liste de lecture :", "OptionNewPlaylist": "Nouvelle liste de lecture...", @@ -407,9 +435,9 @@ "LabelEpisodeNumber": "Num\u00e9ro de l'\u00e9pisode:", "LabelTrackNumber": "Num\u00e9ro de piste:", "LabelNumber": "Num\u00e9ro:", - "LabelReleaseDate": "Date de sortie :", + "LabelReleaseDate": "Date de sortie", "LabelEndDate": "Date de fin:", - "LabelYear": "Ann\u00e9e :", + "LabelYear": "Ann\u00e9e", "LabelDateOfBirth": "Date de naissance :", "LabelBirthYear": "Ann\u00e9e de naissance :", "LabelBirthDate": "Date de naissance :", @@ -569,7 +597,7 @@ "MediaInfoCodec": "Codec", "MediaInfoProfile": "Profil", "MediaInfoLevel": "Niveau", - "MediaInfoAspectRatio": "Ratio d'aspect original:", + "MediaInfoAspectRatio": "Ratio d'aspect original", "MediaInfoResolution": "R\u00e9solution", "MediaInfoAnamorphic": "Anamorphique", "MediaInfoInterlaced": "Entrelac\u00e9", @@ -581,6 +609,8 @@ "MediaInfoStreamTypeEmbeddedImage": "Image am\u00e9lior\u00e9e", "MediaInfoRefFrames": "Image de r\u00e9f\u00e9rence", "TabPlayback": "Lecture", + "TabNotifications": "Notifications", + "TabExpert": "Expert", "HeaderSelectCustomIntrosPath": "Choisir le chemin des intros personnalis\u00e9es", "HeaderRateAndReview": "Noter et commenter", "HeaderThankYou": "Merci", @@ -602,19 +632,20 @@ "WebClientTourUserPreferences4": "Configurer les images de fonds, les th\u00e8mes musicaux et les lecteurs externes", "WebClientTourMobile1": "Le client web fonctionne parfaitement sur les smartphones et les tablettes...", "WebClientTourMobile2": "et contr\u00f4le facilement les autres appareils et applications Media Browser", - "MessageEnjoyYourStay": "Profitez en bien", + "MessageEnjoyYourStay": "Amusez-vous bien !", "DashboardTourDashboard": "Le tableau de bord du serveur vous permet de g\u00e9rer votre serveur et vos utilisateurs. Vous saurez toujours qui fait quoi et o\u00f9.", "DashboardTourHelp": "L'aide contextuelle de l'application permet d'ouvrir les pages du wiki relatives au contenu affich\u00e9.", "DashboardTourUsers": "Cr\u00e9ez facilement des comptes utilisateurs pour vos amis et votre famille, chacun avec ses propres droits, biblioth\u00e8ques accessibles, contr\u00f4le parental et plus encore.", "DashboardTourCinemaMode": "Le mode cin\u00e9ma apporte l'exp\u00e9rience du cin\u00e9ma directement dans votre salon gr\u00e2ce \u00e0 la possibilit\u00e9 de lire les bandes-annonces et les introductions personnalis\u00e9es avant le programme principal.", - "DashboardTourChapters": "Autoriser la g\u00e9n\u00e9ration des images de chapitres de vos vid\u00e9os pour une pr\u00e9sentation plus agr\u00e9able pendant la navigation.", - "DashboardTourSubtitles": "T\u00e9l\u00e9charger automatiquement les sous-titres pour vos vid\u00e9os dans n'importe quelle langue.", - "DashboardTourPlugins": "Installer les plugin comme les chaines vid\u00e9os internet, live TV, analyseur de m\u00e9tadonn\u00e9es, et plus encore.", - "DashboardTourNotifications": "Envoyer automatiquement les notifications des \u00e9v\u00e8nements du serveur \u00e0 vos appareils mobiles, email et plus encore.", - "DashboardTourScheduledTasks": "G\u00e9rer facilement les op\u00e9rations longues des taches planifi\u00e9es. Sp\u00e9cifier quand et combien de fois elles doivent se lancer.", + "DashboardTourChapters": "Autorisez la g\u00e9n\u00e9ration des images de chapitres de vos vid\u00e9os pour une pr\u00e9sentation plus agr\u00e9able pendant la navigation.", + "DashboardTourSubtitles": "T\u00e9l\u00e9chargez automatiquement les sous-titres de vos vid\u00e9os dans n'importe quelle langue.", + "DashboardTourPlugins": "Installez des plugins : cha\u00eenes vid\u00e9os internet, TV en direct, analyseur de m\u00e9tadonn\u00e9es, et plus encore.", + "DashboardTourNotifications": "Envoyez automatiquement les notifications d'\u00e9v\u00e9nements du serveur vers vos appareils mobiles, vos adresses email et plus encore.", + "DashboardTourScheduledTasks": "G\u00e9rez facilement les op\u00e9rations longues des taches planifi\u00e9es. Sp\u00e9cifiez quand et \u00e0 quelle fr\u00e9quence elles doivent se lancer.", "DashboardTourMobile": "Le tableau de bord de Media Browser fonctionne parfaitement sur les smartphones et les tablettes. G\u00e9rer votre serveur du bout des doigts, n'importe quand, n'importe o\u00f9.", "MessageRefreshQueued": "Demande d'actualisation en file d'attente", "TabDevices": "Appareils", + "TabExtras": "Extras", "DeviceLastUsedByUserName": "Derni\u00e8rement utilis\u00e9 par {0}", "HeaderDeleteDevice": "Supprimer l'appareil", "DeleteDeviceConfirmation": "\u00cates-vous s\u00fbr de vouloir supprimer cet appareil ? La prochaine fois qu'un utilisateur se connecte depuis cet appareil, il sera ajout\u00e9 \u00e0 nouveau.", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/he.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/he.json index 9fef8e0de..30272ddcf 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/he.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/he.json @@ -6,6 +6,8 @@ "Administrator": "\u05de\u05e0\u05d4\u05dc", "Password": "\u05e1\u05d9\u05e1\u05de\u05d0", "DeleteImage": "\u05de\u05d7\u05e7 \u05ea\u05de\u05d5\u05e0\u05d4", + "MessageThankYouForSupporting": "Thank you for supporting Media Browser.", + "MessagePleaseSupportMediaBrowser": "Please support Media Browser.", "DeleteImageConfirmation": "\u05d4\u05d0\u05dd \u05d0\u05ea\u05d4 \u05d1\u05d8\u05d5\u05d7 \u05e9\u05d1\u05e8\u05e6\u05d5\u05e0\u05da \u05dc\u05de\u05d7\u05d5\u05e7 \u05ea\u05de\u05d5\u05e0\u05d4 \u05d6\u05d5?", "FileReadCancelled": "\u05e7\u05e8\u05d9\u05d0\u05ea \u05d4\u05e7\u05d5\u05d1\u05e5 \u05d1\u05d5\u05d8\u05dc\u05d4.", "FileNotFound": "\u05e7\u05d5\u05d1\u05e5 \u05dc\u05d0 \u05e0\u05de\u05e6\u05d0.", @@ -14,7 +16,10 @@ "DeleteUserConfirmation": "Are you sure you wish to delete this user?", "PasswordResetHeader": "\u05d0\u05d9\u05e4\u05d5\u05e1 \u05e1\u05d9\u05e1\u05de\u05d0", "PasswordResetComplete": "\u05d4\u05e1\u05d9\u05e1\u05de\u05d0 \u05d0\u05d5\u05e4\u05e1\u05d4.", + "PinCodeResetComplete": "The pin code has been reset.", "PasswordResetConfirmation": "\u05d4\u05d0\u05dd \u05d0\u05ea\u05d4 \u05d1\u05d8\u05d5\u05d7 \u05e9\u05d1\u05e8\u05e6\u05d5\u05e0\u05da \u05dc\u05d0\u05e4\u05e1 \u05d0\u05ea \u05d4\u05e1\u05d9\u05e1\u05de\u05d0?", + "PinCodeResetConfirmation": "Are you sure you wish to reset the pin code?", + "HeaderPinCodeReset": "Reset Pin Code", "PasswordSaved": "\u05d4\u05e1\u05d9\u05e1\u05de\u05d0 \u05e0\u05e9\u05de\u05e8\u05d4.", "PasswordMatchError": "\u05d4\u05e1\u05d9\u05e1\u05de\u05d0 \u05d5\u05d0\u05d9\u05de\u05d5\u05ea \u05d4\u05e1\u05d9\u05e1\u05de\u05d0 \u05e6\u05e8\u05d9\u05db\u05d5\u05ea \u05dc\u05d4\u05d9\u05d5\u05ea \u05d6\u05d4\u05d5\u05ea.", "OptionRelease": "\u05e9\u05d9\u05d7\u05e8\u05d5\u05e8 \u05e8\u05e9\u05de\u05d9", @@ -32,6 +37,7 @@ "MessageKeyRemoved": "Thank you. Your supporter key has been removed.", "ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.", "HeaderSearch": "Search", + "ValueDateCreated": "Date created: {0}", "LabelArtist": "Artist", "LabelMovie": "Movie", "LabelMusicVideo": "Music Video", @@ -42,6 +48,17 @@ "LabelFailed": "(failed)", "ButtonHelp": "Help", "ButtonSave": "\u05e9\u05de\u05d5\u05e8", + "LabelCollection": "Collection", + "HeaderAddToCollection": "Add to Collection", + "NewCollectionNameExample": "\u05dc\u05d3\u05d5\u05d2\u05de\u05d0 :\u05d0\u05d5\u05e1\u05e3 \u05de\u05dc\u05d7\u05de\u05ea \u05d4\u05db\u05d5\u05db\u05d1\u05d9\u05dd", + "OptionSearchForInternetMetadata": "\u05d7\u05e4\u05e9 \u05d1\u05d0\u05d9\u05e0\u05e8\u05e0\u05d8 \u05d0\u05d7\u05e8\u05d9 \u05de\u05d9\u05d3\u05e2 \u05d5\u05ea\u05de\u05d5\u05e0\u05d5\u05ea", + "LabelSelectCollection": "Select collection:", + "HeaderDevices": "Devices", + "ButtonScheduledTasks": "Scheduled tasks", + "MessageItemsAdded": "Items added", + "ButtonAddToCollection": "Add to collection", + "HeaderSelectCertificatePath": "Select Certificate Path", + "ConfirmMessageScheduledTaskButton": "This operation normally runs automatically as a scheduled task. It can also be run manually here. To configure the scheduled task, see:", "HeaderSupporterBenefit": "A supporter membership provides additional benefits such as access to premium plugins, internet channel content, and more. {0}Learn more{1}.", "HeaderWelcomeToMediaBrowserServerDashboard": "Welcome to the Media Browser Dashboard", "HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client", @@ -53,6 +70,10 @@ "HeaderChannelAccess": "Channel Access", "HeaderDeviceAccess": "Device Access", "HeaderSelectDevices": "Select Devices", + "ButtonCancelItem": "Cancel item", + "ButtonQueueForRetry": "Queue for retry", + "ButtonReenable": "Re-enable", + "SyncJobItemStatusSyncedMarkForRemoval": "Marked for removal", "LabelAbortedByServerShutdown": "(Aborted by server shutdown)", "LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.", "HeaderDeleteTaskTrigger": "Delete Task Trigger", @@ -64,10 +85,13 @@ "LabelFree": "Free", "HeaderSelectAudio": "Select Audio", "HeaderSelectSubtitles": "Select Subtitles", + "ButtonMarkForRemoval": "Mark for removal from device", + "ButtonUnmarkForRemoval": "Unmark for removal from device", "LabelDefaultStream": "(Default)", "LabelForcedStream": "(Forced)", "LabelDefaultForcedStream": "(Default\/Forced)", "LabelUnknownLanguage": "Unknown language", + "MessageConfirmSyncJobItemCancellation": "Are you sure you wish to cancel this item?", "ButtonMute": "Mute", "ButtonUnmute": "Unmute", "ButtonStop": "Stop", @@ -191,8 +215,10 @@ "LabelPlayMethodDirectPlay": "Direct Playing", "LabelAudioCodec": "Audio: {0}", "LabelVideoCodec": "Video: {0}", + "LabelLocalAccessUrl": "Local access: {0}", "LabelRemoteAccessUrl": "Remote access: {0}", - "LabelRunningOnPort": "Running on port {0}.", + "LabelRunningOnPort": "Running on http port {0}.", + "LabelRunningOnPorts": "Running on http port {0}, and https port {1}.", "HeaderLatestFromChannel": "Latest from {0}", "ButtonDownload": "Download", "LabelUnknownLanaguage": "Unknown language", @@ -206,6 +232,7 @@ "ButtonRefresh": "Refresh", "LabelCurrentPath": "Current path:", "HeaderSelectMediaPath": "Select Media Path", + "HeaderSelectPath": "Select Path", "ButtonNetwork": "Network", "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.", "HeaderMenu": "Menu", @@ -216,6 +243,7 @@ "ButtonResume": "Resume", "HeaderScenes": "\u05e1\u05e6\u05e0\u05d5\u05ea", "HeaderAudioTracks": "Audio Tracks", + "HeaderLibraries": "Libraries", "HeaderSubtitles": "Subtitles", "HeaderVideoQuality": "Video Quality", "MessageErrorPlayingVideo": "There was an error playing the video.", @@ -581,6 +609,8 @@ "MediaInfoStreamTypeEmbeddedImage": "Embedded Image", "MediaInfoRefFrames": "Ref frames", "TabPlayback": "Playback", + "TabNotifications": "\u05d4\u05ea\u05e8\u05d0\u05d5\u05ea", + "TabExpert": "Expert", "HeaderSelectCustomIntrosPath": "Select Custom Intros Path", "HeaderRateAndReview": "Rate and Review", "HeaderThankYou": "Thank You", @@ -615,6 +645,7 @@ "DashboardTourMobile": "The Media Browser dashboard works great on smartphones and tablets. Manage your server from the palm of your hand anytime, anywhere.", "MessageRefreshQueued": "Refresh queued", "TabDevices": "Devices", + "TabExtras": "Extras", "DeviceLastUsedByUserName": "Last used by {0}", "HeaderDeleteDevice": "Delete Device", "DeleteDeviceConfirmation": "Are you sure you wish to delete this device? It will reappear the next time a user signs in with it.", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/hr.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/hr.json index 42e4f67c7..de3050845 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/hr.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/hr.json @@ -6,6 +6,8 @@ "Administrator": "Administrator", "Password": "Lozinka", "DeleteImage": "Izbri\u0161i sliku", + "MessageThankYouForSupporting": "Thank you for supporting Media Browser.", + "MessagePleaseSupportMediaBrowser": "Please support Media Browser.", "DeleteImageConfirmation": "Da li ste sigurni da \u017eelite izbrisati ovu sliku?", "FileReadCancelled": "U\u010ditavanje datoteke je prekinuto.", "FileNotFound": "Datoteka nije prona\u0111ena.", @@ -14,7 +16,10 @@ "DeleteUserConfirmation": "Da li ste sigurni da \u017eelite izbrisati odabranog korisnika?", "PasswordResetHeader": "Resetiraj lozinku", "PasswordResetComplete": "Lozinka je resetirana.", + "PinCodeResetComplete": "The pin code has been reset.", "PasswordResetConfirmation": "Da li ste sigurni da \u017eelite resetirati lozinku?", + "PinCodeResetConfirmation": "Are you sure you wish to reset the pin code?", + "HeaderPinCodeReset": "Reset Pin Code", "PasswordSaved": "Lozinka snimljena.", "PasswordMatchError": "Lozinka i lozinka potvrde moraju biti identi\u010dne.", "OptionRelease": "Slu\u017ebeno izdanje", @@ -32,6 +37,7 @@ "MessageKeyRemoved": "Thank you. Your supporter key has been removed.", "ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.", "HeaderSearch": "Search", + "ValueDateCreated": "Date created: {0}", "LabelArtist": "Artist", "LabelMovie": "Movie", "LabelMusicVideo": "Music Video", @@ -42,6 +48,17 @@ "LabelFailed": "(failed)", "ButtonHelp": "Help", "ButtonSave": "Snimi", + "LabelCollection": "Collection", + "HeaderAddToCollection": "Add to Collection", + "NewCollectionNameExample": "Naprimjer: Star Wars Kolekcija", + "OptionSearchForInternetMetadata": "Potra\u017ei na internetu grafike i metadata", + "LabelSelectCollection": "Select collection:", + "HeaderDevices": "Devices", + "ButtonScheduledTasks": "Scheduled tasks", + "MessageItemsAdded": "Items added", + "ButtonAddToCollection": "Add to collection", + "HeaderSelectCertificatePath": "Select Certificate Path", + "ConfirmMessageScheduledTaskButton": "This operation normally runs automatically as a scheduled task. It can also be run manually here. To configure the scheduled task, see:", "HeaderSupporterBenefit": "A supporter membership provides additional benefits such as access to premium plugins, internet channel content, and more. {0}Learn more{1}.", "HeaderWelcomeToMediaBrowserServerDashboard": "Welcome to the Media Browser Dashboard", "HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client", @@ -53,6 +70,10 @@ "HeaderChannelAccess": "Channel Access", "HeaderDeviceAccess": "Device Access", "HeaderSelectDevices": "Select Devices", + "ButtonCancelItem": "Cancel item", + "ButtonQueueForRetry": "Queue for retry", + "ButtonReenable": "Re-enable", + "SyncJobItemStatusSyncedMarkForRemoval": "Marked for removal", "LabelAbortedByServerShutdown": "(Aborted by server shutdown)", "LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.", "HeaderDeleteTaskTrigger": "Delete Task Trigger", @@ -64,10 +85,13 @@ "LabelFree": "Free", "HeaderSelectAudio": "Select Audio", "HeaderSelectSubtitles": "Select Subtitles", + "ButtonMarkForRemoval": "Mark for removal from device", + "ButtonUnmarkForRemoval": "Unmark for removal from device", "LabelDefaultStream": "(Default)", "LabelForcedStream": "(Forced)", "LabelDefaultForcedStream": "(Default\/Forced)", "LabelUnknownLanguage": "Unknown language", + "MessageConfirmSyncJobItemCancellation": "Are you sure you wish to cancel this item?", "ButtonMute": "Bez zvuka", "ButtonUnmute": "Unmute", "ButtonStop": "Stop", @@ -191,8 +215,10 @@ "LabelPlayMethodDirectPlay": "Direct Playing", "LabelAudioCodec": "Audio: {0}", "LabelVideoCodec": "Video: {0}", + "LabelLocalAccessUrl": "Local access: {0}", "LabelRemoteAccessUrl": "Remote access: {0}", - "LabelRunningOnPort": "Running on port {0}.", + "LabelRunningOnPort": "Running on http port {0}.", + "LabelRunningOnPorts": "Running on http port {0}, and https port {1}.", "HeaderLatestFromChannel": "Latest from {0}", "ButtonDownload": "Download", "LabelUnknownLanaguage": "Unknown language", @@ -206,6 +232,7 @@ "ButtonRefresh": "Refresh", "LabelCurrentPath": "Current path:", "HeaderSelectMediaPath": "Select Media Path", + "HeaderSelectPath": "Select Path", "ButtonNetwork": "Network", "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.", "HeaderMenu": "Menu", @@ -216,6 +243,7 @@ "ButtonResume": "Resume", "HeaderScenes": "Scene", "HeaderAudioTracks": "Audio Tracks", + "HeaderLibraries": "Libraries", "HeaderSubtitles": "Subtitles", "HeaderVideoQuality": "Video Quality", "MessageErrorPlayingVideo": "There was an error playing the video.", @@ -581,6 +609,8 @@ "MediaInfoStreamTypeEmbeddedImage": "Embedded Image", "MediaInfoRefFrames": "Ref frames", "TabPlayback": "Playback", + "TabNotifications": "Obavijesti", + "TabExpert": "Expert", "HeaderSelectCustomIntrosPath": "Select Custom Intros Path", "HeaderRateAndReview": "Rate and Review", "HeaderThankYou": "Thank You", @@ -615,6 +645,7 @@ "DashboardTourMobile": "The Media Browser dashboard works great on smartphones and tablets. Manage your server from the palm of your hand anytime, anywhere.", "MessageRefreshQueued": "Refresh queued", "TabDevices": "Devices", + "TabExtras": "Extras", "DeviceLastUsedByUserName": "Last used by {0}", "HeaderDeleteDevice": "Delete Device", "DeleteDeviceConfirmation": "Are you sure you wish to delete this device? It will reappear the next time a user signs in with it.", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/it.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/it.json index 893b2eaab..4d85f6e34 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/it.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/it.json @@ -6,6 +6,8 @@ "Administrator": "Amministratore", "Password": "Password", "DeleteImage": "Elimina immagine", + "MessageThankYouForSupporting": "Thank you for supporting Media Browser.", + "MessagePleaseSupportMediaBrowser": "Please support Media Browser.", "DeleteImageConfirmation": "Sei sicuro di voler eliminare questa immagine?", "FileReadCancelled": "Il file letto \u00e8 stato cancellato.", "FileNotFound": "File non trovato", @@ -14,7 +16,10 @@ "DeleteUserConfirmation": "Sei sicuro di voler eliminare questo utente", "PasswordResetHeader": "Ripristina Password", "PasswordResetComplete": "la password \u00e8 stata ripristinata.", + "PinCodeResetComplete": "The pin code has been reset.", "PasswordResetConfirmation": "Sei sicuro di voler ripristinare la password?", + "PinCodeResetConfirmation": "Are you sure you wish to reset the pin code?", + "HeaderPinCodeReset": "Reset Pin Code", "PasswordSaved": "Password salvata.", "PasswordMatchError": "Le password non coincidono.", "OptionRelease": "Versione Ufficiale", @@ -32,6 +37,7 @@ "MessageKeyRemoved": "Grazie. La vostra chiave supporter \u00e8 stata rimossa.", "ErrorLaunchingChromecast": "Si \u00e8 verificato un errore all'avvio di chromecast. Assicurati che il tuo dispositivo sia connesso alla rete wireless.", "HeaderSearch": "Ricerca", + "ValueDateCreated": "Date created: {0}", "LabelArtist": "Artista", "LabelMovie": "Film", "LabelMusicVideo": "Video Musicali", @@ -42,17 +48,32 @@ "LabelFailed": "(fallito)", "ButtonHelp": "Aiuto", "ButtonSave": "Salva", - "HeaderSupporterBenefit": "A supporter membership provides additional benefits such as access to premium plugins, internet channel content, and more. {0}Learn more{1}.", + "LabelCollection": "Collection", + "HeaderAddToCollection": "Aggiungi alla Collezione", + "NewCollectionNameExample": "Esempio: Collezione Star wars", + "OptionSearchForInternetMetadata": "Cerca su internet le immagini e i metadati", + "LabelSelectCollection": "Seleziona Collezione:", + "HeaderDevices": "Dispositivi", + "ButtonScheduledTasks": "Scheduled tasks", + "MessageItemsAdded": "Items added", + "ButtonAddToCollection": "Add to collection", + "HeaderSelectCertificatePath": "Select Certificate Path", + "ConfirmMessageScheduledTaskButton": "This operation normally runs automatically as a scheduled task. It can also be run manually here. To configure the scheduled task, see:", + "HeaderSupporterBenefit": "La sottoscrizione Supporter concede dei benefici come: l'accesso a plug-in premium, contenuti dei canali internet, e altro. {0}Scopri di pi\u00f9{1}", "HeaderWelcomeToMediaBrowserServerDashboard": "Benvenuti nel Dashboard di Media Browser", "HeaderWelcomeToMediaBrowserWebClient": "Benvenuti nel Media Browser Web client", "ButtonTakeTheTour": "Fai il tour", - "HeaderWelcomeBack": "Welcome back!", - "ButtonTakeTheTourToSeeWhatsNew": "Take the tour to see what's new", + "HeaderWelcomeBack": "Ben tornato!", + "ButtonTakeTheTourToSeeWhatsNew": "Fai un tour per vedere cosa \u00e8 cambiato", "MessageNoSyncJobsFound": "Nessuna sincronizzazione pianificata. Creane una utilizzando i pulsanti sull'interfaccia web", "HeaderLibraryAccess": "Accesso libreria", "HeaderChannelAccess": "Accesso canali", "HeaderDeviceAccess": "Accesso dispositivo", "HeaderSelectDevices": "Seleziona periferiche", + "ButtonCancelItem": "Cancel item", + "ButtonQueueForRetry": "Queue for retry", + "ButtonReenable": "Re-enable", + "SyncJobItemStatusSyncedMarkForRemoval": "Marked for removal", "LabelAbortedByServerShutdown": "(Interrotto dallo spegnimento del server)", "LabelScheduledTaskLastRan": "Ultima esecuzione {0}, taking {1}.", "HeaderDeleteTaskTrigger": "Elimina Operazione pianificata", @@ -64,10 +85,13 @@ "LabelFree": "Gratis", "HeaderSelectAudio": "Seleziona audio", "HeaderSelectSubtitles": "Seleziona sottotitoli", + "ButtonMarkForRemoval": "Mark for removal from device", + "ButtonUnmarkForRemoval": "Unmark for removal from device", "LabelDefaultStream": "(Predefinito)", "LabelForcedStream": "(forzato)", "LabelDefaultForcedStream": "(Predefinito\/Forzato)", "LabelUnknownLanguage": "Lingua Sconosciuta", + "MessageConfirmSyncJobItemCancellation": "Are you sure you wish to cancel this item?", "ButtonMute": "Muto", "ButtonUnmute": "Togli muto", "ButtonStop": "Stop", @@ -191,8 +215,10 @@ "LabelPlayMethodDirectPlay": "Riproduzione Diretta", "LabelAudioCodec": "Audio: {0}", "LabelVideoCodec": "Video: {0}", + "LabelLocalAccessUrl": "Local access: {0}", "LabelRemoteAccessUrl": "Accesso remoto: {0}", - "LabelRunningOnPort": "Avviato su porta {0}", + "LabelRunningOnPort": "Running on http port {0}.", + "LabelRunningOnPorts": "Running on http port {0}, and https port {1}.", "HeaderLatestFromChannel": "Ultime da {0}", "ButtonDownload": "Download", "LabelUnknownLanaguage": "lingua sconosciuta", @@ -206,6 +232,7 @@ "ButtonRefresh": "Aggiorna", "LabelCurrentPath": "Percorso Corrente:", "HeaderSelectMediaPath": "Seleziona il percorso", + "HeaderSelectPath": "Select Path", "ButtonNetwork": "Rete", "MessageDirectoryPickerInstruction": "Percorsi di rete possono essere inseriti manualmente nel caso in cui il pulsante Rete non riesce a individuare i vostri dispositivi. Ad esempio, {0} o {1}", "HeaderMenu": "Menu", @@ -216,6 +243,7 @@ "ButtonResume": "Riprendi", "HeaderScenes": "Scene", "HeaderAudioTracks": "Tracce audio", + "HeaderLibraries": "Libraries", "HeaderSubtitles": "Sottotitoli", "HeaderVideoQuality": "Qualit\u00e0 video", "MessageErrorPlayingVideo": "Si \u00e8 verificato un errore nella riproduzione del video.", @@ -266,13 +294,13 @@ "MessagePleaseEnterNameOrId": "Inserisci il nome o id esterno.", "MessageValueNotCorrect": "Il valore inserito non \u00e8 corretto.Riprova di nuovo.", "MessageItemSaved": "Elemento salvato.", - "MessagePleaseAcceptTermsOfServiceBeforeContinuing": "Please accept the terms of service before continuing.", + "MessagePleaseAcceptTermsOfServiceBeforeContinuing": "Per favore accetta i termini di servizio prima di continuare.", "OptionEnded": "Finito", "OptionContinuing": "In corso", "OptionOff": "Off", "OptionOn": "On", "ButtonSettings": "Impostazioni", - "ButtonUninstall": "Uninstall", + "ButtonUninstall": "Disinstalla", "HeaderFields": "Campi", "HeaderFieldsHelp": "Far scorrere un campo a 'off' per bloccarlo e impedire che sia i dati vengano modificati.", "HeaderLiveTV": "Tv in diretta", @@ -581,6 +609,8 @@ "MediaInfoStreamTypeEmbeddedImage": "Immagine incorporata", "MediaInfoRefFrames": "Ref frames", "TabPlayback": "Riproduzione", + "TabNotifications": "Notifiche", + "TabExpert": "Expert", "HeaderSelectCustomIntrosPath": "Selezionare Intro Path Personalizzata", "HeaderRateAndReview": "Punteggio e Commenti", "HeaderThankYou": "Grazie", @@ -615,6 +645,7 @@ "DashboardTourMobile": "Il cruscotto Media Browser funziona alla grande su smartphone e tablet. Gestisci il tuo server dal palmo della tua mano in qualsiasi momento, ovunque.", "MessageRefreshQueued": "Aggiornamento programmato", "TabDevices": "Dispositivi", + "TabExtras": "Extras", "DeviceLastUsedByUserName": "Ultimo utilizzata da {0}", "HeaderDeleteDevice": "Elimina dispositivo", "DeleteDeviceConfirmation": "Sei sicuro di voler cancellare questo dispositivo? Esso riapparir\u00e0 la prossima volta che un utente accede con esso.", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json index 943daff5e..27b46db52 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json @@ -6,15 +6,20 @@ "Administrator": "Administrator", "Password": "Password", "DeleteImage": "Delete Image", + "MessageThankYouForSupporting": "Thank you for supporting Media Browser.", + "MessagePleaseSupportMediaBrowser": "Please support Media Browser.", "DeleteImageConfirmation": "Are you sure you wish to delete this image?", "FileReadCancelled": "The file read has been canceled.", "FileNotFound": "File not found.", "FileReadError": "An error occurred while reading the file.", "DeleteUser": "Delete User", "DeleteUserConfirmation": "Are you sure you wish to delete this user?", - "PasswordResetHeader": "Password Reset", + "PasswordResetHeader": "Reset Password", "PasswordResetComplete": "The password has been reset.", + "PinCodeResetComplete": "The pin code has been reset.", "PasswordResetConfirmation": "Are you sure you wish to reset the password?", + "PinCodeResetConfirmation": "Are you sure you wish to reset the pin code?", + "HeaderPinCodeReset": "Reset Pin Code", "PasswordSaved": "Password saved.", "PasswordMatchError": "Password and password confirmation must match.", "OptionRelease": "Official Release", @@ -32,6 +37,7 @@ "MessageKeyRemoved": "Thank you. Your supporter key has been removed.", "ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.", "HeaderSearch": "Search", + "ValueDateCreated": "Date created: {0}", "LabelArtist": "Artist", "LabelMovie": "Movie", "LabelMusicVideo": "Music Video", @@ -42,6 +48,17 @@ "LabelFailed": "(failed)", "ButtonHelp": "Help", "ButtonSave": "Save", + "LabelCollection": "Collection", + "HeaderAddToCollection": "Add to Collection", + "NewCollectionNameExample": "Example: Star Wars Collection", + "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata", + "LabelSelectCollection": "Select collection:", + "HeaderDevices": "Devices", + "ButtonScheduledTasks": "Scheduled tasks", + "MessageItemsAdded": "Items added", + "ButtonAddToCollection": "Add to collection", + "HeaderSelectCertificatePath": "Select Certificate Path", + "ConfirmMessageScheduledTaskButton": "This operation normally runs automatically as a scheduled task. It can also be run manually here. To configure the scheduled task, see:", "HeaderSupporterBenefit": "A supporter membership provides additional benefits such as access to premium plugins, internet channel content, and more. {0}Learn more{1}.", "HeaderWelcomeToMediaBrowserServerDashboard": "Welcome to the Media Browser Dashboard", "HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client", @@ -53,6 +70,10 @@ "HeaderChannelAccess": "Channel Access", "HeaderDeviceAccess": "Device Access", "HeaderSelectDevices": "Select Devices", + "ButtonCancelItem": "Cancel item", + "ButtonQueueForRetry": "Queue for retry", + "ButtonReenable": "Re-enable", + "SyncJobItemStatusSyncedMarkForRemoval": "Marked for removal", "LabelAbortedByServerShutdown": "(Aborted by server shutdown)", "LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.", "HeaderDeleteTaskTrigger": "Delete Task Trigger", @@ -64,10 +85,14 @@ "LabelFree": "Free", "HeaderSelectAudio": "Select Audio", "HeaderSelectSubtitles": "Select Subtitles", + "ButtonMarkForRemoval": "Mark for removal from device", + "ButtonUnmarkForRemoval": "Unmark for removal from device", "LabelDefaultStream": "(Default)", "LabelForcedStream": "(Forced)", "LabelDefaultForcedStream": "(Default/Forced)", "LabelUnknownLanguage": "Unknown language", + "HeaderConfirmation": "Confirmation", + "MessageConfirmSyncJobItemCancellation": "Are you sure you wish to cancel this item?", "ButtonMute": "Mute", "ButtonUnmute": "Unmute", "ButtonStop": "Stop", @@ -191,8 +216,10 @@ "LabelPlayMethodDirectPlay": "Direct Playing", "LabelAudioCodec": "Audio: {0}", "LabelVideoCodec": "Video: {0}", + "LabelLocalAccessUrl": "Local access: {0}", "LabelRemoteAccessUrl": "Remote access: {0}", - "LabelRunningOnPort": "Running on port {0}.", + "LabelRunningOnPort": "Running on http port {0}.", + "LabelRunningOnPorts": "Running on http port {0}, and https port {1}.", "HeaderLatestFromChannel": "Latest from {0}", "ButtonDownload": "Download", "LabelUnknownLanaguage": "Unknown language", @@ -206,6 +233,7 @@ "ButtonRefresh": "Refresh", "LabelCurrentPath": "Current path:", "HeaderSelectMediaPath": "Select Media Path", + "HeaderSelectPath": "Select Path", "ButtonNetwork": "Network", "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.", "HeaderMenu": "Menu", @@ -216,6 +244,7 @@ "ButtonResume": "Resume", "HeaderScenes": "Scenes", "HeaderAudioTracks": "Audio Tracks", + "HeaderLibraries": "Libraries", "LabelUnknownLanguage": "Unknown language", "HeaderSubtitles": "Subtitles", "HeaderVideoQuality": "Video Quality", @@ -589,6 +618,8 @@ "MediaInfoStreamTypeEmbeddedImage": "Embedded Image", "MediaInfoRefFrames": "Ref frames", "TabPlayback": "Playback", + "TabNotifications": "Notifications", + "TabExpert": "Expert", "HeaderSelectCustomIntrosPath": "Select Custom Intros Path", "HeaderRateAndReview": "Rate and Review", "HeaderThankYou": "Thank You", @@ -623,6 +654,7 @@ "DashboardTourMobile": "The Media Browser dashboard works great on smartphones and tablets. Manage your server from the palm of your hand anytime, anywhere.", "MessageRefreshQueued": "Refresh queued", "TabDevices": "Devices", + "TabExtras": "Extras", "DeviceLastUsedByUserName": "Last used by {0}", "HeaderDeleteDevice": "Delete Device", "DeleteDeviceConfirmation": "Are you sure you wish to delete this device? It will reappear the next time a user signs in with it.", @@ -649,7 +681,7 @@ "MessageForgotPasswordFileCreated": "The following file has been created on your server and contains instructions on how to proceed:", "MessageForgotPasswordFileExpiration": "The reset pin will expire at {0}.", "MessageInvalidForgotPasswordPin": "An invalid or expired pin was entered. Please try again.", - "MessagePasswordResetForUsers": "Passwords have been reset for the following users:", + "MessagePasswordResetForUsers": "Passwords have been removed for the following users:", "HeaderInviteGuest": "Invite Guest", "ButtonLinkMyMediaBrowserAccount": "Link my account now", "MessageConnectAccountRequiredToInviteGuest": "In order to invite guests you need to first link your Media Browser account to this server.", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json index 5be3de261..fd71dfebf 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json @@ -6,6 +6,8 @@ "Administrator": "\u04d8\u043a\u0456\u043c\u0448\u0456", "Password": "\u049a\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437", "DeleteImage": "\u0421\u0443\u0440\u0435\u0442\u0442\u0456 \u0436\u043e\u044e", + "MessageThankYouForSupporting": "Media Browser \u0431\u0430\u0493\u0434\u0430\u0440\u043b\u0430\u043c\u0430\u0441\u044b\u043d \u0436\u0430\u049b\u0442\u0430\u0493\u0430\u04a3\u044b\u0437 \u04af\u0448\u0456\u043d \u0430\u043b\u0493\u044b\u0441.", + "MessagePleaseSupportMediaBrowser": "Media Browser \u0431\u0430\u0493\u0434\u0430\u0440\u043b\u0430\u043c\u0430\u0441\u044b\u043d \u0436\u0430\u049b\u0442\u0430\u04a3\u044b\u0437.", "DeleteImageConfirmation": "\u0428\u044b\u043d\u044b\u043c\u0435\u043d \u0431\u04b1\u043b \u0441\u0443\u0440\u0435\u0442\u0442\u0456 \u0436\u043e\u044e \u049b\u0430\u0436\u0435\u0442 \u043f\u0435?", "FileReadCancelled": "\u0424\u0430\u0439\u043b \u043e\u049b\u0443\u044b \u0431\u043e\u043b\u0434\u044b\u0440\u044b\u043b\u043c\u0430\u0434\u044b.", "FileNotFound": "\u0424\u0430\u0439\u043b \u0442\u0430\u0431\u044b\u043b\u043c\u0430\u0434\u044b.", @@ -14,7 +16,10 @@ "DeleteUserConfirmation": "\u0428\u044b\u043d\u044b\u043c\u0435\u043d \u043e\u0441\u044b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043d\u044b \u0436\u043e\u044e \u049b\u0430\u0436\u0435\u0442 \u043f\u0435?", "PasswordResetHeader": "\u049a\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437\u0434\u0456 \u044b\u0441\u044b\u0440\u0443", "PasswordResetComplete": "\u049a\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437 \u044b\u0441\u044b\u0440\u044b\u043b\u0434\u044b.", + "PinCodeResetComplete": "PIN-\u043a\u043e\u0434 \u044b\u0441\u044b\u0440\u044b\u043b\u0434\u044b", "PasswordResetConfirmation": "\u0428\u044b\u043d\u044b\u043c\u0435\u043d \u049b\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437\u0434\u0456 \u044b\u0441\u044b\u0440\u0443 \u049b\u0430\u0436\u0435\u0442 \u043f\u0435?", + "PinCodeResetConfirmation": "\u0428\u044b\u043d\u044b\u043c\u0435\u043d PIN-\u043a\u043e\u0434\u0442\u044b \u044b\u0441\u044b\u0440\u0443 \u049b\u0430\u0436\u0435\u0442 \u043f\u0435?", + "HeaderPinCodeReset": "PIN-\u043a\u043e\u0434\u0442\u044b \u044b\u0441\u044b\u0440\u0443", "PasswordSaved": "\u049a\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437 \u0441\u0430\u049b\u0442\u0430\u043b\u0434\u044b.", "PasswordMatchError": "\u049a\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437\u0456 \u043c\u0435\u043d \u049a\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437\u0434\u0456 \u0440\u0430\u0441\u0442\u0430\u0443 \u04e9\u0440\u0456\u0441\u0442\u0435\u0440\u0456 \u0441\u04d9\u0439\u043a\u0435\u0441 \u0431\u043e\u043b\u0443 \u043a\u0435\u0440\u0435\u043a.", "OptionRelease": "\u0420\u0435\u0441\u043c\u0438 \u0448\u044b\u0493\u0430\u0440\u044b\u043b\u044b\u043c", @@ -28,10 +33,11 @@ "MessageKeyEmailedTo": "\u041a\u0456\u043b\u0442 {0} \u04af\u0448\u0456\u043d \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u0434\u044b \u043f\u043e\u0448\u0442\u0430\u043c\u0435\u043d \u0436\u0456\u0431\u0435\u0440\u0456\u043b\u0434\u0456.", "MessageKeysLinked": "\u041a\u0456\u043b\u0442\u0442\u0435\u0440 \u0431\u0430\u0439\u043b\u0430\u043d\u044b\u0441\u0442\u044b\u0440\u044b\u043b\u0434\u044b.", "HeaderConfirmation": "\u0420\u0430\u0441\u0442\u0430\u0443", - "MessageKeyUpdated": "\u049a\u043e\u043b\u0434\u0430\u0443\u0448\u044b \u043a\u0456\u043b\u0442\u0456\u04a3\u0456\u0437 \u0436\u0430\u04a3\u0430\u0440\u0442\u044b\u043b\u0434\u044b.", - "MessageKeyRemoved": "\u049a\u043e\u043b\u0434\u0430\u0443\u0448\u044b \u043a\u0456\u043b\u0442\u0456\u04a3\u0456\u0437 \u0430\u043b\u0430\u0441\u0442\u0430\u043b\u0434\u044b.", + "MessageKeyUpdated": "\u0416\u0430\u049b\u0442\u0430\u0443\u0448\u044b \u043a\u0456\u043b\u0442\u0456\u04a3\u0456\u0437 \u0436\u0430\u04a3\u0430\u0440\u0442\u044b\u043b\u0434\u044b.", + "MessageKeyRemoved": "\u0416\u0430\u049b\u0442\u0430\u0443\u0448\u044b \u043a\u0456\u043b\u0442\u0456\u04a3\u0456\u0437 \u0430\u043b\u0430\u0441\u0442\u0430\u043b\u0434\u044b.", "ErrorLaunchingChromecast": "Chromecast \u0456\u0441\u043a\u0435 \u049b\u043e\u0441\u044b\u043b\u0443 \u043a\u0435\u0437\u0456\u043d\u0434\u0435 \u049b\u0430\u0442\u0435 \u043e\u0440\u044b\u043d \u0430\u043b\u0434\u044b. \u049a\u04b1\u0440\u044b\u043b\u0493\u044b\u04a3\u044b\u0437 \u0441\u044b\u043c\u0441\u044b\u0437 \u0436\u0435\u043b\u0456\u0433\u0435 \u049b\u043e\u0441\u044b\u043b\u0493\u0430\u043d\u044b\u043d\u0430 \u043a\u04e9\u0437 \u0436\u0435\u0442\u043a\u0456\u0437\u0456\u04a3\u0456\u0437.", "HeaderSearch": "\u0406\u0437\u0434\u0435\u0443", + "ValueDateCreated": "\u0416\u0430\u0441\u0430\u043b\u0493\u0430\u043d \u043a\u04af\u043d\u0456: {0}", "LabelArtist": "\u041e\u0440\u044b\u043d\u0434\u0430\u0443\u0448\u044b", "LabelMovie": "\u0424\u0438\u043b\u044c\u043c", "LabelMusicVideo": "\u041c\u0443\u0437\u044b\u043a\u0430\u043b\u044b\u049b \u0431\u0435\u0439\u043d\u0435", @@ -42,17 +48,32 @@ "LabelFailed": "(\u0441\u04d9\u0442\u0441\u0456\u0437)", "ButtonHelp": "\u0410\u043d\u044b\u049b\u0442\u0430\u043c\u0430", "ButtonSave": "\u0421\u0430\u049b\u0442\u0430\u0443", - "HeaderSupporterBenefit": "A supporter membership provides additional benefits such as access to premium plugins, internet channel content, and more. {0}Learn more{1}.", + "LabelCollection": "\u0416\u0438\u044b\u043d\u0442\u044b\u049b", + "HeaderAddToCollection": "\u0416\u0438\u044b\u043d\u0442\u044b\u049b\u049b\u0430 \u04af\u0441\u0442\u0435\u0443", + "NewCollectionNameExample": "\u041c\u044b\u0441\u0430\u043b: \u0416\u04b1\u043b\u0434\u044b\u0437 \u0441\u043e\u0493\u044b\u0441\u0442\u0430\u0440\u044b (\u0436\u0438\u044b\u043d\u0442\u044b\u049b)", + "OptionSearchForInternetMetadata": "\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 \u0456\u0437\u0434\u0435\u0443", + "LabelSelectCollection": "\u0416\u0438\u044b\u043d\u0442\u044b\u049b\u0442\u044b \u0442\u0430\u04a3\u0434\u0430\u0443:", + "HeaderDevices": "\u049a\u04b1\u0440\u044b\u043b\u0493\u044b\u043b\u0430\u0440", + "ButtonScheduledTasks": "\u0416\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0493\u0430\u043d \u0442\u0430\u043f\u0441\u044b\u0440\u043c\u0430\u043b\u0430\u0440\u0493\u0430 \u04e9\u0442\u0443", + "MessageItemsAdded": "\u042d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0435\u0440 \u04af\u0441\u0442\u0435\u043b\u0433\u0435\u043d", + "ButtonAddToCollection": "\u0416\u0438\u044b\u043d\u0442\u044b\u049b\u049b\u0430 \u04af\u0441\u0442\u0435\u0443", + "HeaderSelectCertificatePath": "\u041a\u0443\u04d9\u043b\u0456\u043a \u0436\u043e\u043b\u044b\u043d \u0442\u0430\u04a3\u0434\u0430\u0443", + "ConfirmMessageScheduledTaskButton": "\u0411\u04b1\u043b \u04d9\u0440\u0435\u043a\u0435\u0442 \u04d9\u0434\u0435\u0442\u0442\u0435 \u0436\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0493\u0430\u043d \u0442\u0430\u043f\u0441\u044b\u0440\u043c\u0430 \u0440\u0435\u0442\u0456\u043d\u0434\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0442\u044b \u0442\u04af\u0440\u0434\u0435 \u0436\u04b1\u043c\u044b\u0441 \u0456\u0441\u0442\u0435\u0439\u0434\u0456. \u041e\u0441\u044b\u043d\u044b \u0441\u043e\u043d\u0434\u0430\u0439-\u0430\u049b \u0431\u04b1\u043b \u0436\u0435\u0440\u0434\u0435 \u049b\u043e\u043b\u043c\u0435\u043d \u0456\u0441\u043a\u0435 \u049b\u043e\u0441\u0443\u0493\u0430 \u0431\u043e\u043b\u0430\u0434\u044b. \u0416\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0493\u0430\u043d \u0442\u0430\u043f\u0441\u044b\u0440\u043c\u0430\u043d\u044b \u0442\u0435\u04a3\u0448\u0435\u0443 \u04af\u0448\u0456\u043d, \u049b\u0430\u0440\u0430\u04a3\u044b\u0437:", + "HeaderSupporterBenefit": "\u0416\u0430\u049b\u0442\u0430\u0443\u0448\u044b \u043c\u04af\u0448\u0435\u043b\u0456\u043a \u0441\u044b\u0439\u0430\u049b\u044b\u043b\u044b \u043f\u043b\u0430\u0433\u0438\u043d, \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u0430\u0440\u043d\u0430 \u043c\u0430\u0437\u043c\u04b1\u043d\u044b \u0436\u04d9\u043d\u0435 \u0441\u043e\u043d\u0434\u0430\u0439 \u0441\u0438\u044f\u049b\u0442\u044b\u043b\u0430\u0440\u0493\u0430 \u049b\u043e\u043b \u0436\u0435\u0442\u043a\u0456\u0437\u0443\u043c\u0435\u043d \u049b\u043e\u0441\u044b\u043c\u0448\u0430 \u0430\u0440\u0442\u044b\u049b\u0448\u044b\u043b\u044b\u049b\u0442\u0430\u0440 \u0431\u0435\u0440\u0435\u0434\u0456. {0}\u041a\u04e9\u0431\u0456\u0440\u0435\u043a \u0431\u0456\u043b\u0443{1}.", "HeaderWelcomeToMediaBrowserServerDashboard": "Media Browser \u0431\u0430\u049b\u044b\u043b\u0430\u0443 \u0442\u0430\u049b\u0442\u0430\u0441\u044b\u043d\u0430 \u049b\u043e\u0448 \u043a\u0435\u043b\u0434\u0456\u04a3\u0456\u0437!", "HeaderWelcomeToMediaBrowserWebClient": "Media Browser \u0432\u0435\u0431-\u043a\u043b\u0438\u0435\u043d\u0442\u0456\u043d\u0435 \u049b\u043e\u0448 \u043a\u0435\u043b\u0434\u0456\u04a3\u0456\u0437!", "ButtonTakeTheTour": "\u0410\u0440\u0430\u043b\u0430\u043f \u0448\u044b\u0493\u044b\u04a3\u044b\u0437", - "HeaderWelcomeBack": "Welcome back!", - "ButtonTakeTheTourToSeeWhatsNew": "Take the tour to see what's new", - "MessageNoSyncJobsFound": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443 \u0436\u04b1\u043c\u044b\u0441\u044b \u0442\u0430\u0431\u044b\u043b\u043c\u0430\u0434\u044b. \u0412\u0435\u0431-\u0442\u0456\u043b\u0434\u0435\u0441\u0443\u0434\u0435 \u0442\u0430\u0431\u044b\u043b\u0430\u0442\u044b\u043d \u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443 \u0442\u04af\u0439\u043c\u0435\u0448\u0456\u043a\u0442\u0435\u0440\u0456\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u043f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443 \u0436\u04b1\u043c\u044b\u0441\u0442\u0430\u0440\u044b\u043d \u0436\u0430\u0441\u0430\u04a3\u044b\u0437.", + "HeaderWelcomeBack": "\u049a\u0430\u0439\u0442\u0430 \u043a\u0435\u043b\u0443\u0456\u04a3\u0456\u0437\u0431\u0435\u043d!", + "ButtonTakeTheTourToSeeWhatsNew": "\u041d\u0435 \u0436\u0430\u04a3\u0430\u043b\u044b\u049b \u0431\u0430\u0440 \u0435\u043a\u0435\u043d\u0431\u0435\u043d \u0442\u0430\u043d\u044b\u0441\u044b\u04a3\u044b\u0437", + "MessageNoSyncJobsFound": "\u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443 \u0436\u04b1\u043c\u044b\u0441\u044b \u0442\u0430\u0431\u044b\u043b\u043c\u0430\u0434\u044b. \u0412\u0435\u0431-\u0442\u0456\u043b\u0434\u0435\u0441\u0443\u0434\u0435 \u0442\u0430\u0431\u044b\u043b\u0430\u0442\u044b\u043d \u04af\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443 \u0442\u04af\u0439\u043c\u0435\u0448\u0456\u043a\u0442\u0435\u0440\u0456\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u043f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443 \u0436\u04b1\u043c\u044b\u0441\u0442\u0430\u0440\u044b\u043d \u0436\u0430\u0441\u0430\u04a3\u044b\u0437.", "HeaderLibraryAccess": "\u0422\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430\u0493\u0430 \u049b\u0430\u0442\u044b\u043d\u0430\u0441\u0443", "HeaderChannelAccess": "\u0410\u0440\u043d\u0430\u0493\u0430 \u049b\u0430\u0442\u044b\u043d\u0430\u0441\u0443", "HeaderDeviceAccess": "\u049a\u04b1\u0440\u044b\u043b\u0493\u044b\u0493\u0430 \u049b\u0430\u0442\u044b\u043d\u0430\u0441", "HeaderSelectDevices": "\u049a\u04b1\u0440\u044b\u043b\u0493\u044b\u043b\u0430\u0440\u0434\u044b \u0442\u0430\u04a3\u0434\u0430\u0443", + "ButtonCancelItem": "\u042d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0456 \u0431\u043e\u043b\u0434\u044b\u0440\u043c\u0430\u0443", + "ButtonQueueForRetry": "\u049a\u0430\u0439\u0442\u0430\u043b\u0430\u0443\u0493\u0430 \u043a\u0435\u0437\u0435\u043a", + "ButtonReenable": "\u049a\u0430\u0439\u0442\u0430 \u049b\u043e\u0441\u0443", + "SyncJobItemStatusSyncedMarkForRemoval": "\u0410\u043b\u0430\u0441\u0442\u0430\u0443\u0493\u0430 \u0431\u0435\u043b\u0433\u0456\u043b\u0435\u043d\u0433\u0435\u043d", "LabelAbortedByServerShutdown": "(\u0421\u0435\u0440\u0432\u0435\u0440 \u0436\u04b1\u043c\u044b\u0441\u044b \u0430\u044f\u049b\u0442\u0430\u043b\u0443\u044b\u043d\u0430 \u0431\u0430\u0439\u043b\u0430\u043d\u044b\u0441\u0442\u044b \u04af\u0437\u0456\u043b\u0434\u0456)", "LabelScheduledTaskLastRan": "\u0421\u043e\u04a3\u0493\u044b \u0456\u0441\u043a\u0435 \u049b\u043e\u0441\u044b\u043b\u0493\u0430\u043d\u044b {0}, {1} \u0443\u0430\u049b\u044b\u0442 \u0430\u043b\u0434\u044b.", "HeaderDeleteTaskTrigger": "\u0422\u0430\u043f\u0441\u044b\u0440\u043c\u0430 \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u0456\u043d \u0436\u043e\u044e", @@ -64,10 +85,13 @@ "LabelFree": "\u0422\u0435\u0433\u0456\u043d", "HeaderSelectAudio": "\u0414\u044b\u0431\u044b\u0441 \u0442\u0430\u04a3\u0434\u0430\u0443", "HeaderSelectSubtitles": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440 \u0442\u0430\u04a3\u0434\u0430\u0443", + "ButtonMarkForRemoval": "\u049a\u04b1\u0440\u044b\u043b\u0493\u044b\u0434\u0430\u043d \u0430\u043b\u0430\u0441\u0442\u0430\u0443\u0493\u0430 \u0431\u0435\u043b\u0433\u0456\u043b\u0435\u0443", + "ButtonUnmarkForRemoval": "\u049a\u04b1\u0440\u044b\u043b\u0493\u044b\u0434\u0430\u043d \u0430\u043b\u0430\u0441\u0442\u0430\u0443\u0493\u0430 \u0431\u0435\u043b\u0433\u0456\u043b\u0435\u043c\u0435\u0443", "LabelDefaultStream": "(\u04d8\u0434\u0435\u043f\u043a\u0456)", "LabelForcedStream": "(\u041c\u04d9\u0436\u0431\u04af\u0440\u043b\u0456)", "LabelDefaultForcedStream": "(\u04d8\u0434\u0435\u043f\u043a\u0456\/\u041c\u04d9\u0436\u0431\u04af\u0440\u043b\u0456)", "LabelUnknownLanguage": "\u0411\u0435\u043b\u0433\u0456\u0441\u0456\u0437 \u0442\u0456\u043b", + "MessageConfirmSyncJobItemCancellation": "\u0428\u044b\u043d\u044b\u043c\u0435\u043d \u043e\u0441\u044b \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0456 \u0431\u043e\u043b\u0434\u044b\u0440\u043c\u0430\u0443 \u049b\u0430\u0436\u0435\u0442 \u043f\u0435?", "ButtonMute": "\u0414\u044b\u0431\u044b\u0441\u0442\u044b \u04e9\u0448\u0456\u0440\u0443", "ButtonUnmute": "\u0414\u044b\u0431\u044b\u0441\u0442\u044b \u049b\u043e\u0441\u0443", "ButtonStop": "\u0422\u043e\u049b\u0442\u0430\u0442\u0443", @@ -146,11 +170,11 @@ "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": "\u0421\u0435\u0440\u0432\u0435\u0440 \u043a\u0435\u0448\u0456\u043d\u0456\u04a3 \u0436\u043e\u043b\u044b\u043d \u0442\u0430\u04a3\u0434\u0430\u0443", + "HeaderSelectServerCachePath": "\u0421\u0435\u0440\u0432\u0435\u0440 \u043a\u044d\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.", + "HeaderSelectServerCachePathHelp": "\u0421\u0435\u0440\u0432\u0435\u0440\u0434\u0456\u04a3 \u043a\u044d\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.", @@ -191,8 +215,10 @@ "LabelPlayMethodDirectPlay": "\u0422\u0456\u043a\u0435\u043b\u0435\u0439 \u043e\u0439\u043d\u0430\u0442\u0443\u0434\u0430", "LabelAudioCodec": "\u0414\u044b\u0431\u044b\u0441: {0}", "LabelVideoCodec": "\u0411\u0435\u0439\u043d\u0435: {0}", + "LabelLocalAccessUrl": "\u0416\u0435\u0440\u0433\u0456\u043b\u0456\u043a\u0442\u0456 \u049b\u0430\u0442\u044b\u043d\u0430\u0441\u0443: {0}", "LabelRemoteAccessUrl": "\u049a\u0430\u0448\u044b\u049b\u0442\u0430\u043d \u049b\u0430\u0442\u044b\u043d\u0430\u0441\u0443: {0}", - "LabelRunningOnPort": "{0} \u043f\u043e\u0440\u0442\u044b\u043d\u0434\u0430 \u0436\u04b1\u043c\u044b\u0441 \u0456\u0441\u0442\u0435\u0439\u0434\u0456.", + "LabelRunningOnPort": "{0} http-\u043f\u043e\u0440\u0442\u044b\u043d\u0434\u0430 \u0436\u04b1\u043c\u044b\u0441 \u0456\u0441\u0442\u0435\u0439\u0434\u0456.", + "LabelRunningOnPorts": "{0} http-\u043f\u043e\u0440\u0442\u044b\u043d\u0434\u0430 \u0436\u04d9\u043d\u0435 {1} https-\u043f\u043e\u0440\u0442\u044b\u043d\u0434\u0430 \u0436\u04b1\u043c\u044b\u0441 \u0456\u0441\u0442\u0435\u0439\u0434\u0456.", "HeaderLatestFromChannel": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456 {0}", "ButtonDownload": "\u0416\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443", "LabelUnknownLanaguage": "\u0411\u0435\u043b\u0433\u0456\u0441\u0456\u0437 \u0442\u0456\u043b", @@ -206,6 +232,7 @@ "ButtonRefresh": "\u041a\u04e9\u043a\u0435\u0439\u0442\u0435\u0441\u0442\u0456 \u0435\u0442\u0443", "LabelCurrentPath": "\u0410\u0493\u044b\u043c\u0434\u044b\u049b \u0436\u043e\u043b:", "HeaderSelectMediaPath": "\u0422\u0430\u0441\u0443\u0448\u044b \u0436\u043e\u043b\u044b\u043d \u0442\u0430\u04a3\u0434\u0430\u0443", + "HeaderSelectPath": "\u0416\u043e\u043b\u0434\u044b \u0442\u0430\u04a3\u0434\u0430\u0443", "ButtonNetwork": "\u0416\u0435\u043b\u0456", "MessageDirectoryPickerInstruction": "\u0416\u0435\u043b\u0456 \u0442\u04af\u0439\u043c\u0435\u0448\u0456\u0433\u0456 \u0431\u0430\u0441\u044b\u043b\u0493\u0430\u043d\u0434\u0430 \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u043b\u0430\u0440\u044b\u04a3\u044b\u0437 \u043e\u0440\u043d\u044b \u0442\u0430\u0431\u044b\u043b\u043c\u0430\u0441\u0430, \u0436\u0435\u043b\u0456\u043b\u0456\u043a \u0436\u043e\u043b\u0434\u0430\u0440 \u049b\u043e\u043b\u043c\u0435\u043d \u0435\u043d\u0433\u0456\u0437\u0456\u043b\u0443\u0456 \u043c\u04af\u043c\u043a\u0456\u043d. \u041c\u044b\u0441\u0430\u043b\u044b, {0} \u043d\u0435\u043c\u0435\u0441\u0435 {1}.", "HeaderMenu": "\u041c\u04d9\u0437\u0456\u0440", @@ -216,13 +243,14 @@ "ButtonResume": "\u0416\u0430\u043b\u0493\u0430\u0441\u0442\u044b\u0440\u0443", "HeaderScenes": "\u0421\u0430\u0445\u043d\u0430\u043b\u0430\u0440", "HeaderAudioTracks": "\u0414\u044b\u0431\u044b\u0441 \u0436\u043e\u043b\u0448\u044b\u049b\u0442\u0430\u0440\u044b", + "HeaderLibraries": "\u0422\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430\u043b\u0430\u0440", "HeaderSubtitles": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440", "HeaderVideoQuality": "\u0411\u0435\u0439\u043d\u0435 \u0441\u0430\u043f\u0430\u0441\u044b", "MessageErrorPlayingVideo": "\u0411\u0435\u0439\u043d\u0435 \u043e\u0439\u043d\u0430\u0442\u0443 \u043a\u0435\u0437\u0456\u043d\u0434\u0435 \u049b\u0430\u0442\u0435 \u043e\u0440\u044b\u043d \u0430\u043b\u0434\u044b.", "MessageEnsureOpenTuner": "\u0410\u0448\u044b\u043b\u0493\u0430\u043d \u0442\u044e\u043d\u0435\u0440 \u049b\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456 \u0435\u043a\u0435\u043d\u0456\u043d\u0435 \u043a\u04e9\u0437 \u0436\u0435\u0442\u043a\u0456\u0437\u0456\u04a3\u0456\u0437.", "ButtonHome": "\u0411\u0430\u0441\u0442\u044b", "ButtonDashboard": "\u0411\u0430\u049b\u044b\u043b\u0430\u0443 \u0442\u0430\u049b\u0442\u0430\u0441\u044b", - "ButtonReports": "\u0415\u0441\u0435\u043f\u0442\u0435\u0440", + "ButtonReports": "\u0411\u0430\u044f\u043d\u0434\u0430\u043c\u0430\u043b\u0430\u0440", "ButtonMetadataManager": "\u041c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a \u0440\u0435\u0442\u0442\u0435\u0443\u0448\u0456", "HeaderTime": "\u0423\u0430\u049b\u044b\u0442", "HeaderName": "\u0410\u0442\u044b", @@ -266,13 +294,13 @@ "MessagePleaseEnterNameOrId": "\u0410\u0442\u044b\u043d \u043d\u0435\u043c\u0435\u0441\u0435 \u0441\u044b\u0440\u0442\u049b\u044b ID \u0435\u043d\u0433\u0456\u0437\u0456\u04a3\u0456\u0437.", "MessageValueNotCorrect": "\u0415\u043d\u0433\u0456\u0437\u0456\u043b\u0433\u0435\u043d \u043c\u04d9\u043d \u0434\u04b1\u0440\u044b\u0441 \u0435\u043c\u0435\u0441. \u04d8\u0440\u0435\u043a\u0435\u0442\u0442\u0456 \u049b\u0430\u0439\u0442\u0430\u043b\u0430\u04a3\u044b\u0437.", "MessageItemSaved": "\u042d\u043b\u0435\u043c\u0435\u043d\u0442 \u0441\u0430\u049b\u0442\u0430\u043b\u0434\u044b.", - "MessagePleaseAcceptTermsOfServiceBeforeContinuing": "Please accept the terms of service before continuing.", + "MessagePleaseAcceptTermsOfServiceBeforeContinuing": "\u0416\u0430\u043b\u0493\u0430\u0441\u0442\u044b\u0440\u043c\u0430\u0441 \u0431\u04b1\u0440\u044b\u043d \u049a\u044b\u0437\u043c\u0435\u0442 \u0448\u0430\u0440\u0442\u0442\u0430\u0440\u044b\u043d \u049b\u0430\u0431\u044b\u043b\u0434\u0430\u04a3\u044b\u0437.", "OptionEnded": "\u0410\u044f\u049b\u0442\u0430\u043b\u0434\u044b", "OptionContinuing": "\u0416\u0430\u043b\u0493\u0430\u0441\u0443\u0434\u0430", "OptionOff": "\u04e8\u0448\u0456\u0440", "OptionOn": "\u049a\u043e\u0441", "ButtonSettings": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440", - "ButtonUninstall": "Uninstall", + "ButtonUninstall": "\u041e\u0440\u043d\u0430\u0442\u044b\u043c\u0434\u044b \u0436\u043e\u044e", "HeaderFields": "\u04e8\u0440\u0456\u0441\u0442\u0435\u0440", "HeaderFieldsHelp": "\u049a\u04b1\u0440\u0441\u0430\u0443\u043b\u0430\u0443 \u04af\u0448\u0456\u043d \u0436\u04d9\u043d\u0435 \u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440 \u04e9\u0437\u0433\u0435\u0440\u0442\u0443\u0456\u043d\u0435 \u0442\u044b\u0439\u044b\u043c \u0441\u0430\u043b\u0443 \u04af\u0448\u0456\u043d, \u04e9\u0440\u0456\u0441\u0442\u0456 \"\u04e8\u0428\u0406\u0420\" \u0442\u0430\u0440\u0430\u043f\u044b\u043d\u0430 \u0441\u044b\u0440\u0493\u0430\u0442\u044b\u04a3\u044b\u0437.", "HeaderLiveTV": "\u042d\u0444\u0438\u0440\u043b\u0456\u043a \u0422\u0414", @@ -324,7 +352,7 @@ "TabLiveTV": "\u042d\u0444\u0438\u0440\u043b\u0456\u043a \u0422\u0414", "TabAutoOrganize": "\u0410\u0432\u0442\u043e\u04b1\u0439\u044b\u043c\u0434\u0430\u0441\u0442\u044b\u0440\u0443", "TabPlugins": "\u041f\u043b\u0430\u0433\u0438\u043d\u0434\u0435\u0440", - "TabAdvanced": "\u049a\u043e\u0441\u044b\u043c\u0448\u0430", + "TabAdvanced": "\u041a\u0435\u04a3\u0435\u0439\u0442\u0456\u043b\u0433\u0435\u043d", "TabHelp": "\u0410\u043d\u044b\u049b\u0442\u0430\u043c\u0430", "TabScheduledTasks": "\u0416\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0443\u0448\u044b", "ButtonFullscreen": "\u0422\u043e\u043b\u044b\u049b \u044d\u043a\u0440\u0430\u043d", @@ -454,14 +482,14 @@ "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 \u0431\u0456\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 \u0431\u0456\u0442\u0435\u0434\u0456", + "MessageTrialExpired": "\u041e\u0441\u044b \u0435\u0440\u0435\u043a\u0448\u0435\u043b\u0456\u043a \u04af\u0448\u0456\u043d \u0441\u044b\u043d\u0430\u043c\u0430 \u043a\u0435\u0437\u0435\u04a3\u0456\u043d\u0456\u04a3 \u043c\u0435\u0440\u0437\u0456\u043c\u0456 \u0431\u0456\u0442\u0442\u0456", + "MessageTrialWillExpireIn": "\u041e\u0441\u044b \u0435\u0440\u0435\u043a\u0448\u0435\u043b\u0456\u043a \u04af\u0448\u0456\u043d \u0441\u044b\u043d\u0430\u043c\u0430 \u043a\u0435\u0437\u0435\u04a3\u0456\u043d\u0456\u04a3 \u043c\u0435\u0440\u0437\u0456\u043c\u0456 {0} \u043a\u04af\u043d\u0434\u0435 \u0431\u0456\u0442\u0435\u0434\u0456", "MessageInstallPluginFromApp": "\u0411\u04b1\u043b \u043f\u043b\u0430\u0433\u0438\u043d \u049b\u0430\u043d\u0434\u0430\u0439 \u049b\u043e\u043b\u0434\u0430\u043d\u0431\u0430\u0493\u0430 \u0442\u0430\u0493\u0430\u0439\u044b\u043d\u0434\u0430\u043b\u0441\u0430, \u0441\u043e\u043d\u044b\u04a3 \u0456\u0448\u0456\u043d\u0435\u043d \u043e\u0440\u043d\u0430\u0442\u044b\u043b\u0443\u044b \u0442\u0438\u0456\u0441\u0442\u0456.", "ValuePriceUSD": "\u0411\u0430\u0493\u0430\u0441\u044b: {0} USD", - "MessageFeatureIncludedWithSupporter": "\u041e\u0441\u044b \u043c\u04af\u043c\u043a\u0456\u043d\u0434\u0456\u043a \u04af\u0448\u0456\u043d \u0442\u0456\u0440\u043a\u0435\u043b\u0433\u0435\u043d\u0441\u0456\u0437, \u0436\u04d9\u043d\u0435 \u043e\u043d\u044b \u0431\u0435\u043b\u0441\u0435\u043d\u0434\u0456 \u049b\u043e\u043b\u0434\u0430\u0443\u0448\u044b \u043c\u04af\u0448\u0435\u043b\u0456\u0433\u0456 \u0430\u0440\u049b\u044b\u043b\u044b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0434\u044b \u0436\u0430\u043b\u0493\u0430\u0441\u0442\u044b\u0440\u0430 \u0430\u043b\u0430\u0441\u044b\u0437.", - "MessageChangeRecurringPlanConfirm": "\u041e\u0441\u044b \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044f\u043d\u044b \u0430\u044f\u049b\u0442\u0430\u0493\u0430\u043d\u043d\u0430\u043d \u043a\u0435\u0439\u0456\u043d PayPal \u0435\u0441\u0435\u043f \u0448\u043e\u0442\u044b\u04a3\u044b\u0437 \u0430\u0440\u049b\u044b\u043b\u044b \u0430\u043b\u0434\u044b\u04a3\u0493\u044b \u049b\u0430\u0439\u0442\u0430\u043b\u0430\u043c\u0430 \u049b\u0430\u0439\u044b\u0440\u043c\u0430\u043b\u0434\u044b\u049b\u0442\u044b \u0431\u043e\u043b\u0434\u044b\u0440\u043c\u0430\u0443\u044b\u04a3\u044b\u0437 \u049b\u0430\u0436\u0435\u0442. Media Browser \u0436\u043e\u0431\u0430\u0441\u044b\u043d \u049b\u043e\u043b\u0434\u0430\u0443\u044b\u04a3\u044b\u0437\u0493\u0430 \u0430\u043b\u0493\u044b\u0441 \u0430\u0439\u0442\u0430\u043c\u044b\u0437!", - "MessageSupporterMembershipExpiredOn": "\u049a\u043e\u043b\u0434\u0430\u0443\u0448\u044b \u043c\u04af\u0448\u0435\u043b\u0456\u0433\u0456\u04a3\u0456\u0437\u0434\u0456\u04a3 \u043c\u0435\u0440\u0437\u0456\u043c\u0456 {0} \u0431\u0456\u0442\u0442\u0456.", - "MessageYouHaveALifetimeMembership": "\u0492\u04b1\u043c\u044b\u0440\u043b\u044b\u049b \u049b\u043e\u043b\u0434\u0430\u0443\u0448\u044b \u043c\u04af\u0448\u0435\u043b\u0456\u0433\u0456\u043d\u0435 \u0442\u0438\u0435\u0441\u043b\u0456\u0441\u0456\u0437. \u0422\u04e9\u043c\u0435\u043d\u0434\u0435\u0433\u0456 \u043d\u04b1\u0441\u049b\u0430\u043b\u0430\u0440\u0434\u044b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u043f \u0431\u0456\u0440 \u0436\u043e\u043b\u0493\u044b \u043d\u0435\u043c\u0435\u0441\u0435 \u049b\u0430\u0439\u0442\u0430\u043b\u0430\u043c\u0430 \u043d\u0435\u0433\u0456\u0437\u0456\u043d\u0434\u0435 \u049b\u043e\u0441\u044b\u043c\u0448\u0430 \u049b\u0430\u0439\u044b\u0440\u043c\u0430\u043b\u0434\u044b\u049b\u0442\u0430\u0440\u0434\u044b \u049b\u0430\u043c\u0442\u0430\u043c\u0430\u0441\u044b\u0437 \u0435\u0442\u0443 \u043c\u04af\u043c\u043a\u0456\u043d\u0434\u0456\u0433\u0456\u04a3\u0456\u0437 \u0431\u0430\u0440. Media Browser \u0436\u043e\u0431\u0430\u0441\u044b\u043d \u049b\u043e\u043b\u0434\u0430\u0443\u044b\u04a3\u044b\u0437\u0493\u0430 \u0430\u043b\u0493\u044b\u0441 \u0430\u0439\u0442\u0430\u043c\u044b\u0437!", + "MessageFeatureIncludedWithSupporter": "\u041e\u0441\u044b \u0435\u0440\u0435\u043a\u0448\u0435\u043b\u0456\u043a \u04af\u0448\u0456\u043d \u0442\u0456\u0440\u043a\u0435\u043b\u0433\u0435\u043d\u0441\u0456\u0437, \u0436\u04d9\u043d\u0435 \u043e\u043d\u044b \u0431\u0435\u043b\u0441\u0435\u043d\u0434\u0456 \u0436\u0430\u049b\u0442\u0430\u0443\u0448\u044b \u043c\u04af\u0448\u0435\u043b\u0456\u0433\u0456 \u0430\u0440\u049b\u044b\u043b\u044b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0434\u044b \u0436\u0430\u043b\u0493\u0430\u0441\u0442\u044b\u0440\u0430 \u0430\u043b\u0430\u0441\u044b\u0437.", + "MessageChangeRecurringPlanConfirm": "\u041e\u0441\u044b \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044f\u043d\u044b \u0430\u044f\u049b\u0442\u0430\u0493\u0430\u043d\u043d\u0430\u043d \u043a\u0435\u0439\u0456\u043d PayPal \u0435\u0441\u0435\u043f \u0448\u043e\u0442\u044b\u04a3\u044b\u0437 \u0430\u0440\u049b\u044b\u043b\u044b \u0430\u043b\u0434\u044b\u04a3\u0493\u044b \u049b\u0430\u0439\u0442\u0430\u043b\u0430\u043c\u0430 \u049b\u0430\u0439\u044b\u0440\u043c\u0430\u043b\u0434\u044b\u049b\u0442\u044b \u0431\u043e\u043b\u0434\u044b\u0440\u043c\u0430\u0443\u044b\u04a3\u044b\u0437 \u049b\u0430\u0436\u0435\u0442. Media Browser \u0436\u043e\u0431\u0430\u0441\u044b\u043d \u0436\u0430\u049b\u0442\u0430\u0443\u044b\u04a3\u044b\u0437\u0493\u0430 \u0430\u043b\u0493\u044b\u0441 \u0430\u0439\u0442\u0430\u043c\u044b\u0437!", + "MessageSupporterMembershipExpiredOn": "\u0416\u0430\u049b\u0442\u0430\u0443\u0448\u044b \u043c\u04af\u0448\u0435\u043b\u0456\u0433\u0456\u04a3\u0456\u0437\u0434\u0456\u04a3 \u043c\u0435\u0440\u0437\u0456\u043c\u0456 {0} \u0431\u0456\u0442\u0442\u0456.", + "MessageYouHaveALifetimeMembership": "\u0492\u04b1\u043c\u044b\u0440\u043b\u044b\u049b \u0436\u0430\u049b\u0442\u0430\u0443\u0448\u044b \u043c\u04af\u0448\u0435\u043b\u0456\u0433\u0456\u043d\u0435 \u0442\u0438\u0435\u0441\u043b\u0456\u0441\u0456\u0437. \u0422\u04e9\u043c\u0435\u043d\u0434\u0435\u0433\u0456 \u043d\u04b1\u0441\u049b\u0430\u043b\u0430\u0440\u0434\u044b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u043f \u0431\u0456\u0440 \u0436\u043e\u043b\u0493\u044b \u043d\u0435\u043c\u0435\u0441\u0435 \u049b\u0430\u0439\u0442\u0430\u043b\u0430\u043c\u0430 \u043d\u0435\u0433\u0456\u0437\u0456\u043d\u0434\u0435 \u049b\u043e\u0441\u044b\u043c\u0448\u0430 \u049b\u0430\u0439\u044b\u0440\u043c\u0430\u043b\u0434\u044b\u049b\u0442\u0430\u0440\u0434\u044b \u049b\u0430\u043c\u0442\u0430\u043c\u0430\u0441\u044b\u0437 \u0435\u0442\u0443 \u043c\u04af\u043c\u043a\u0456\u043d\u0434\u0456\u0433\u0456\u04a3\u0456\u0437 \u0431\u0430\u0440. Media Browser \u0436\u043e\u0431\u0430\u0441\u044b\u043d \u0436\u0430\u049b\u0442\u0430\u0443\u044b\u04a3\u044b\u0437\u0493\u0430 \u0430\u043b\u0493\u044b\u0441 \u0430\u0439\u0442\u0430\u043c\u044b\u0437!", "MessageYouHaveAnActiveRecurringMembership": "\u0411\u0435\u043b\u0441\u0435\u043d\u0434\u0456 {0} \u043c\u04af\u0448\u0435\u043b\u0456\u0433\u0456\u043d\u0435 \u0442\u0438\u0435\u0441\u043b\u0456\u0441\u0456\u0437. \u0422\u04e9\u043c\u0435\u043d\u0434\u0435\u0433\u0456 \u043d\u04b1\u0441\u049b\u0430\u043b\u0430\u0440\u0434\u044b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u043f \u0436\u043e\u0441\u043f\u0430\u0440\u044b\u04a3\u044b\u0437\u0434\u044b \u043a\u04e9\u0442\u0435\u0440\u0443 \u043c\u04af\u043c\u043a\u0456\u043d\u0434\u0456\u0433\u0456\u04a3\u0456\u0437 \u0431\u0430\u0440", "ButtonDelete": "\u0416\u043e\u044e", "HeaderMediaBrowserAccountAdded": "Media Browser \u0442\u0456\u0440\u043a\u0435\u043b\u0433\u0456\u0441\u0456 \u04af\u0441\u0442\u0435\u043b\u0433\u0435\u043d", @@ -581,6 +609,8 @@ "MediaInfoStreamTypeEmbeddedImage": "\u0415\u043d\u0434\u0456\u0440\u0456\u043b\u0433\u0435\u043d \u0441\u0443\u0440\u0435\u0442", "MediaInfoRefFrames": "\u0422\u0456\u0440\u0435\u043a \u043a\u0430\u0434\u0440\u043b\u0430\u0440", "TabPlayback": "\u041e\u0439\u043d\u0430\u0442\u0443", + "TabNotifications": "\u0425\u0430\u0431\u0430\u0440\u043b\u0430\u043d\u0434\u044b\u0440\u0443\u043b\u0430\u0440", + "TabExpert": "\u0421\u0430\u0440\u0430\u043f\u0442\u0430\u043c\u0430\u043b\u044b\u049b", "HeaderSelectCustomIntrosPath": "\u0422\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u043a\u04e9\u0440\u043d\u0435\u0443\u043b\u0435\u0440\u0434\u0456 \u0442\u0430\u04a3\u0434\u0430\u0443", "HeaderRateAndReview": "\u0411\u0430\u0493\u0430\u043b\u0430\u0443 \u0436\u04d9\u043d\u0435 \u043f\u0456\u043a\u0456\u0440\u043b\u0435\u0441\u0443", "HeaderThankYou": "\u0420\u0430\u0445\u043c\u0435\u0442 \u0441\u0456\u0437\u0433\u0435", @@ -602,11 +632,11 @@ "WebClientTourUserPreferences4": "\u0410\u0440\u0442\u049b\u044b \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0434\u0456, \u0442\u0430\u049b\u044b\u0440\u044b\u043f\u0442\u044b\u049b \u04d9\u0443\u0435\u043d\u0434\u0435\u0440\u0434\u0456 \u0436\u04d9\u043d\u0435 \u0441\u044b\u0440\u0442\u049b\u044b \u043e\u0439\u043d\u0430\u0442\u049b\u044b\u0448\u0442\u0430\u0440\u0434\u044b \u0442\u0435\u04a3\u0448\u0435\u04a3\u0456\u0437", "WebClientTourMobile1": "\u0492\u0430\u043b\u0430\u043c\u0442\u043e\u0440 \u043a\u043b\u0438\u0435\u043d\u0442\u0456 \u0441\u043c\u0430\u0440\u0442\u0444\u043e\u043d\u0434\u0430\u0440\u0434\u0430 \u0436\u04d9\u043d\u0435 \u043f\u043b\u0430\u043d\u0448\u0435\u0442\u0442\u0435\u0440\u0434\u0435 \u0442\u0430\u043c\u0430\u0448\u0430 \u0436\u04b1\u043c\u044b\u0441 \u0456\u0441\u0442\u0435\u0439\u0434\u0456", "WebClientTourMobile2": "\u0441\u043e\u043d\u044b\u043c\u0435\u043d \u049b\u0430\u0442\u0430\u0440 \u0431\u0430\u0441\u049b\u0430 \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u043b\u0430\u0440\u0434\u044b \u0436\u04d9\u043d\u0435 Media Browser \u049b\u043e\u043b\u0434\u0430\u043d\u0431\u0430\u043b\u0430\u0440\u044b\u043d \u0431\u0430\u0441\u049b\u0430\u0440\u0430\u0434\u044b", - "MessageEnjoyYourStay": "\u0416\u0430\u0493\u044b\u043c\u0434\u044b \u0435\u0440\u043c\u0435\u043a \u0435\u0442\u0456\u04a3\u0456\u0437", + "MessageEnjoyYourStay": "\u0416\u0430\u0493\u044b\u043c\u0434\u044b \u0442\u0430\u043c\u0430\u0448\u0430\u043b\u0430\u04a3\u044b\u0437", "DashboardTourDashboard": "\u0421\u0435\u0440\u0432\u0435\u0440\u0434\u0456\u04a3 \u0431\u0430\u049b\u044b\u043b\u0430\u0443 \u0442\u0430\u049b\u0442\u0430\u0441\u044b \u0441\u0435\u0440\u0432\u0435\u0440\u0434\u0456 \u0436\u04d9\u043d\u0435 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043b\u0430\u0440\u0434\u044b \u0431\u0430\u049b\u044b\u043b\u0430\u0443\u044b \u043c\u04af\u043c\u043a\u0456\u043d\u0434\u0456\u0433\u0456\u043d\u0435 \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0435\u0434\u0456. \u041a\u0456\u043c \u043d\u0435 \u0456\u0441\u0442\u0435\u0433\u0435\u043d\u0456\u043d \u0436\u04d9\u043d\u0435 \u049b\u0430\u0439\u0434\u0430 \u0442\u04b1\u0440\u0493\u0430\u043d\u044b\u043d \u0431\u0456\u043b\u0456\u043f \u0436\u0430\u0442\u0430\u0441\u044b\u0437.", - "DashboardTourHelp": "\u042d\u043a\u0440\u0430\u043d\u0434\u0430\u0493\u044b \u043c\u0430\u0437\u043c\u04b1\u043d\u0493\u0430 \u049b\u0430\u0442\u044b\u0441\u0442\u044b \u0443\u0438\u043a\u0438 \u0431\u0435\u0442\u0442\u0435\u0440\u0456\u043d \u0430\u0448\u0443 \u04af\u0448\u0456\u043d \u0456\u0448\u043a\u0456 \u0430\u043d\u044b\u049b\u0442\u0430\u043c\u0430 \u043e\u04a3\u0430\u0439 \u0442\u04af\u0439\u043c\u0435\u0448\u0456\u043a\u0442\u0435\u0440\u0434\u0456 \u049b\u0430\u043c\u0442\u0430\u043c\u0430\u0441\u044b\u0437 \u0435\u0442\u0435\u0434\u0456.", + "DashboardTourHelp": "\u042d\u043a\u0440\u0430\u043d\u0434\u0430\u0493\u044b \u043c\u0430\u0437\u043c\u04b1\u043d\u0493\u0430 \u049b\u0430\u0442\u044b\u0441\u0442\u044b \u0443\u0438\u043a\u0438 \u0431\u0435\u0442\u0442\u0435\u0440\u0456\u043d \u043e\u04a3\u0430\u0439\u0442\u044b\u043b\u044b\u043f \u0430\u0448\u0443 \u04af\u0448\u0456\u043d \u0456\u0448\u043a\u0456 \u0430\u043d\u044b\u049b\u0442\u0430\u043c\u0430 \u0442\u04af\u0439\u043c\u0435\u0448\u0456\u043a\u0442\u0435\u0440\u0456\u043d \u049b\u0430\u043c\u0442\u0430\u043c\u0430\u0441\u044b\u0437 \u0435\u0442\u0435\u0434\u0456. ", "DashboardTourUsers": "\u0414\u043e\u0441\u0442\u0430\u0440\u044b\u04a3\u044b\u0437 \u0431\u0435\u043d \u043e\u0442\u0431\u0430\u0441\u044b\u04a3\u044b\u0437 \u04d9\u0440\u049b\u0430\u0439\u0441\u044b\u043d\u0430 \u04e9\u0437\u0456\u043d\u0456\u04a3 \u049b\u04b1\u049b\u044b\u049b\u0442\u0430\u0440\u044b, \u0442\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430 \u049b\u0430\u0442\u044b\u043d\u0430\u0441\u0443\u044b, \u043c\u0430\u0437\u043c\u04b1\u043d \u0431\u0430\u0441\u049b\u0430\u0440\u0443\u044b \u0436\u04d9\u043d\u0435 \u0442.\u0431. \u0431\u0430\u0440 \u0442\u0456\u0440\u043a\u0435\u043b\u0433\u0456\u043b\u0435\u0440\u0456\u043d \u0436\u0435\u04a3\u0456\u043b \u0436\u0430\u0441\u0430\u04a3\u044b\u0437.", - "DashboardTourCinemaMode": "\u041a\u0438\u043d\u043e\u0442\u0435\u0430\u0442\u0440 \u0440\u0435\u0436\u0456\u043c\u0456 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043b\u0435\u0440\u0434\u0456 \u0436\u04d9\u043d\u0435 \u0442\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u043a\u04e9\u0440\u043d\u0435\u0443\u0434\u0456 \u0431\u0430\u0441\u0442\u044b \u049b\u0430\u0441\u0438\u0435\u0442\u0442\u0456\u04a3 \u0430\u043b\u0434\u044b\u043d\u0434\u0430 \u043e\u0439\u043d\u0430\u0442\u0443 \u049b\u0430\u0431\u0456\u043b\u0435\u0442\u0456\u043c\u0435\u043d \u043a\u0438\u043d\u043e \u043a\u04e9\u0440\u0441\u0435\u0442\u0435\u0442\u0456\u043d \u0437\u0430\u043b \u04d9\u0441\u0435\u0440\u0456\u043d \u049b\u043e\u043d\u0430\u049b\u0436\u0430\u0439\u044b\u04a3\u044b\u0437\u0493\u0430 \u0442\u0456\u043a\u0435\u043b\u0435\u0439 \u0436\u0435\u0442\u043a\u0456\u0437\u0435\u0434\u0456.", + "DashboardTourCinemaMode": "\u041a\u0438\u043d\u043e\u0442\u0435\u0430\u0442\u0440 \u0440\u0435\u0436\u0456\u043c\u0456 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043b\u0435\u0440\u0434\u0456 \u0436\u04d9\u043d\u0435 \u0442\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u043a\u04e9\u0440\u043d\u0435\u0443\u0434\u0456 \u0431\u0430\u0441\u0442\u044b \u0435\u0440\u0435\u043a\u0448\u0435\u043b\u0456\u043a\u0442\u0456\u04a3 \u0430\u043b\u0434\u044b\u043d\u0434\u0430 \u043e\u0439\u043d\u0430\u0442\u0443 \u049b\u0430\u0431\u0456\u043b\u0435\u0442\u0456\u043c\u0435\u043d \u043a\u0438\u043d\u043e \u043a\u04e9\u0440\u0441\u0435\u0442\u0435\u0442\u0456\u043d \u0437\u0430\u043b \u04d9\u0441\u0435\u0440\u0456\u043d \u049b\u043e\u043d\u0430\u049b\u0436\u0430\u0439\u044b\u04a3\u044b\u0437\u0493\u0430 \u0442\u0456\u043a\u0435\u043b\u0435\u0439 \u0436\u0435\u0442\u043a\u0456\u0437\u0435\u0434\u0456.", "DashboardTourChapters": "\u0411\u0435\u0439\u043d\u0435\u043b\u0435\u0440\u0434\u0456 \u049b\u0430\u0440\u0430\u0493\u0430\u043d \u043a\u0435\u0437\u0434\u0435 \u04b1\u043d\u0430\u043c\u0434\u044b\u043b\u0430\u0443 \u043a\u04e9\u0440\u0441\u0435\u0442\u0456\u043c \u04af\u0448\u0456\u043d \u0441\u0430\u0445\u043d\u0430 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0456\u043d \u0442\u0443\u0434\u044b\u0440\u0443\u044b\u043d \u049b\u043e\u0441\u044b\u04a3\u044b\u0437.", "DashboardTourSubtitles": "\u0411\u0435\u0439\u043d\u0435\u043b\u0435\u0440\u0433\u0435 \u049b\u0430\u0439 \u0442\u0456\u043b\u0434\u0435 \u0431\u043e\u043b\u0441\u044b\u043d \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440\u0434\u0456 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0442\u044b \u0442\u04af\u0440\u0434\u0435 \u0436\u04af\u043a\u0442\u0435\u04a3\u0456\u0437.", "DashboardTourPlugins": "\u041f\u043b\u0430\u0433\u0438\u043d\u0434\u0435\u0440\u0434\u0456, \u043c\u044b\u0441\u0430\u043b\u044b, \u0431\u0435\u0439\u043d\u0435\u043b\u0456\u043a \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u0430\u0440\u043d\u0430\u043b\u0430\u0440\u044b\u043d, \u044d\u0444\u0438\u0440\u043b\u0456\u043a \u0442\u0434, \u043c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440 \u0441\u043a\u0430\u043d\u0435\u0440\u043b\u0435\u0440\u0456\u043d \u0436\u0456\u043d\u0435 \u0442.\u0431., \u043e\u0440\u043d\u0430\u0442\u044b\u04a3\u044b\u0437.", @@ -615,6 +645,7 @@ "DashboardTourMobile": "Media Browser \u0431\u0430\u049b\u044b\u043b\u0430\u0443 \u0442\u0430\u049b\u0442\u0430\u0441\u044b \u0441\u043c\u0430\u0440\u0442\u0444\u043e\u043d\u0434\u0430\u0440\u0434\u0430 \u0436\u04d9\u043d\u0435 \u043f\u043b\u0430\u043d\u0448\u0435\u0442\u0442\u0435\u0440\u0434\u0435 \u0442\u0430\u043c\u0430\u0448\u0430 \u0436\u04b1\u043c\u044b\u0441 \u0456\u0441\u0442\u0435\u0439\u0434\u0456. \u0421\u0435\u0440\u0432\u0435\u0440\u0456\u04a3\u0456\u0437\u0434\u0456 \u04d9\u0440 \u0443\u0430\u049b\u044b\u0442\u0442\u0430, \u04d9\u0440 \u0436\u0435\u0440\u0434\u0435 \u049b\u043e\u043b\u044b\u04a3\u044b\u0437\u0434\u044b\u04a3 \u0430\u043b\u0430\u049b\u0430\u043d\u044b\u043d\u0430\u043d \u0431\u0430\u0441\u049b\u0430\u0440\u044b\u04a3\u044b\u0437.", "MessageRefreshQueued": "\u041a\u04e9\u043a\u0435\u0439\u0442\u0435\u0441\u0442\u0456 \u0435\u0442\u0443\u0456 \u043a\u0435\u0437\u0435\u043a\u0442\u0435", "TabDevices": "\u049a\u04b1\u0440\u044b\u043b\u0493\u044b\u043b\u0430\u0440", + "TabExtras": "\u049a\u043e\u0441\u044b\u043c\u0448\u0430\u043b\u0430\u0440", "DeviceLastUsedByUserName": "{0} \u0430\u0440\u049b\u044b\u043b\u044b \u0435\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u043b\u0493\u0430\u043d", "HeaderDeleteDevice": "\u049a\u04b1\u0440\u044b\u043b\u0493\u044b\u043d\u044b \u0436\u043e\u044e", "DeleteDeviceConfirmation": "\u0428\u044b\u043d\u044b\u043c\u0435\u043d \u043e\u0441\u044b \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u043d\u044b \u0436\u043e\u044e \u049b\u0430\u0436\u0435\u0442 \u043f\u0435? \u0411\u04b1\u043b \u043a\u0435\u043b\u0435\u0441\u0456 \u0440\u0435\u0442\u0442\u0435 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b \u043e\u0441\u044b\u0434\u0430\u043d \u043a\u0456\u0440\u0433\u0435\u043d\u0434\u0435 \u049b\u0430\u0439\u0442\u0430 \u043f\u0430\u0439\u0434\u0430 \u0431\u043e\u043b\u0430\u0434\u044b.", @@ -645,33 +676,33 @@ "HeaderInviteGuest": "\u049a\u043e\u043d\u0430\u049b\u0442\u044b \u0448\u0430\u049b\u044b\u0440\u0443", "ButtonLinkMyMediaBrowserAccount": "\u0422\u0456\u0440\u043a\u0435\u043b\u0433\u0456\u043c\u0434\u0456 \u0431\u0430\u0439\u043b\u0430\u043d\u044b\u0441\u0442\u044b\u0440\u0443", "MessageConnectAccountRequiredToInviteGuest": "\u049a\u043e\u043d\u0430\u049b\u0442\u0430\u0440\u0434\u044b \u0448\u0430\u049b\u044b\u0440\u0443 \u04af\u0448\u0456\u043d \u0435\u04a3 \u0430\u043b\u0434\u044b\u043d\u0434\u0430 \u043e\u0441\u044b \u0441\u0435\u0440\u0432\u0435\u0440\u0433\u0435 Media Browser \u0442\u0456\u0440\u043a\u0435\u043b\u0433\u0456\u04a3\u0456\u0437\u0434\u0456 \u0431\u0430\u0439\u043b\u0430\u043d\u044b\u0441\u0442\u0440\u0443\u044b\u04a3\u044b\u0437 \u049b\u0430\u0436\u0435\u0442.", - "ButtonSync": "\u0421\u0438\u043d\u0445\u0440\u043e", - "SyncMedia": "\u0422\u0430\u0441\u0443\u0448\u044b \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443", - "HeaderCancelSyncJob": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443\u0434\u044b \u0431\u043e\u043b\u0434\u044b\u0440\u043c\u0430\u0443", - "CancelSyncJobConfirmation": "\u0428\u044b\u043d\u044b\u043c\u0435\u043d \u043e\u0441\u044b \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443 \u0436\u04b1\u043c\u044b\u0441\u0442\u044b \u0431\u043e\u043b\u0434\u044b\u0440\u043c\u0430\u0443 \u049b\u0430\u0436\u0435\u0442 \u043f\u0435?", - "TabSync": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443", - "MessagePleaseSelectDeviceToSyncTo": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0439\u0442\u044b\u043d \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u043d\u044b \u0442\u0430\u04a3\u0434\u0430\u04a3\u044b\u0437.", - "MessageSyncJobCreated": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443 \u0436\u04b1\u043c\u044b\u0441\u044b \u0436\u0430\u0441\u0430\u043b\u0434\u044b.", - "LabelSyncTo": "\u041c\u044b\u043d\u0430\u0493\u0430\u043d \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443:", + "ButtonSync": "\u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443", + "SyncMedia": "\u0422\u0430\u0441\u0443\u0448\u044b\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0434\u0456 \u04af\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443", + "HeaderCancelSyncJob": "\u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443\u0434\u0456 \u0431\u043e\u043b\u0434\u044b\u0440\u043c\u0430\u0443", + "CancelSyncJobConfirmation": "\u0428\u044b\u043d\u044b\u043c\u0435\u043d \u043e\u0441\u044b \u04af\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443 \u0436\u04b1\u043c\u044b\u0441\u0442\u044b \u0431\u043e\u043b\u0434\u044b\u0440\u043c\u0430\u0443 \u049b\u0430\u0436\u0435\u0442 \u043f\u0435?", + "TabSync": "\u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443", + "MessagePleaseSelectDeviceToSyncTo": "\u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0456\u043b\u0435\u0442\u0456\u043d \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u043d\u044b \u0442\u0430\u04a3\u0434\u0430\u04a3\u044b\u0437.", + "MessageSyncJobCreated": "\u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443 \u0436\u04b1\u043c\u044b\u0441\u044b \u0436\u0430\u0441\u0430\u043b\u0434\u044b.", + "LabelSyncTo": "\u041c\u044b\u043d\u0430\u0493\u0430\u043d \u04af\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443:", "LabelSyncJobName": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443 \u0436\u04b1\u043c\u044b\u0441\u044b\u043d\u044b\u04a3 \u0430\u0442\u044b:", "LabelQuality": "\u0421\u0430\u043f\u0430\u0441\u044b:", "OptionHigh": "\u0416\u043e\u0493\u0430\u0440\u044b", "OptionMedium": "\u041e\u0440\u0442\u0430\u0448\u0430", "OptionLow": "\u0422\u04e9\u043c\u0435\u043d", "HeaderSettings": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440", - "OptionAutomaticallySyncNewContent": "\u0416\u0430\u04a3\u0430 \u043c\u0430\u0437\u043c\u04b1\u043d\u0434\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0442\u044b \u0442\u04af\u0440\u0434\u0435 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443", - "OptionAutomaticallySyncNewContentHelp": "\u041e\u0441\u044b \u0441\u0430\u043d\u0430\u0442\u049b\u0430 \u049b\u043e\u0441\u044b\u043b\u0493\u0430\u043d \u0436\u0430\u04a3\u0430 \u043c\u0430\u0437\u043c\u04b1\u043d \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0442\u044b \u0442\u04af\u0440\u0434\u0435 \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u043c\u0435\u043d \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u043b\u044b\u043d\u0430\u0434\u044b.", - "OptionSyncUnwatchedVideosOnly": "\u0422\u0435\u043a \u049b\u0430\u043d\u0430 \u043a\u04e9\u0440\u0456\u043b\u043c\u0435\u0433\u0435\u043d \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440\u0434\u0456 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443", - "OptionSyncUnwatchedVideosOnlyHelp": "\u0422\u0435\u043a \u049b\u0430\u043d\u0430 \u049b\u0430\u0440\u0430\u0440\u043c\u0430\u0493\u0430\u043d \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u043b\u044b\u043d\u0430\u0434\u044b, \u0436\u04d9\u043d\u0435 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440 \u049b\u0430\u0440\u0430\u043b\u0493\u0430\u043d\u043d\u0430\u043d \u043a\u0435\u0439\u0456\u043d \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u0434\u0430\u043d \u0430\u043b\u0430\u0441\u0442\u0430\u043b\u0430\u0434\u044b.", + "OptionAutomaticallySyncNewContent": "\u0416\u0430\u04a3\u0430 \u043c\u0430\u0437\u043c\u04b1\u043d\u0434\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0442\u044b \u0442\u04af\u0440\u0434\u0435 \u04af\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443", + "OptionAutomaticallySyncNewContentHelp": "\u041e\u0441\u044b \u0441\u0430\u043d\u0430\u0442\u049b\u0430 \u049b\u043e\u0441\u044b\u043b\u0493\u0430\u043d \u0436\u0430\u04a3\u0430 \u043c\u0430\u0437\u043c\u04b1\u043d \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0442\u044b \u0442\u04af\u0440\u0434\u0435 \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u043c\u0435\u043d \u04af\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0456\u043b\u0435\u0434\u0456.", + "OptionSyncUnwatchedVideosOnly": "\u0422\u0435\u043a \u049b\u0430\u043d\u0430 \u043a\u04e9\u0440\u0456\u043b\u043c\u0435\u0433\u0435\u043d \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440\u0434\u0456 \u04af\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443", + "OptionSyncUnwatchedVideosOnlyHelp": "\u0422\u0435\u043a \u049b\u0430\u043d\u0430 \u049b\u0430\u0440\u0430\u0440\u043c\u0430\u0493\u0430\u043d \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440 \u04af\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0456\u043b\u0435\u0434\u0456, \u0436\u04d9\u043d\u0435 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440 \u049b\u0430\u0440\u0430\u043b\u0493\u0430\u043d\u043d\u0430\u043d \u043a\u0435\u0439\u0456\u043d \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u0434\u0430\u043d \u0430\u043b\u0430\u0441\u0442\u0430\u043b\u0430\u0434\u044b.", "LabelItemLimit": "\u042d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0435\u0440 \u0448\u0435\u0433\u0456:", - "LabelItemLimitHelp": "\u049a\u0430\u043b\u0430\u0443 \u0431\u043e\u0439\u044b\u043d\u0448\u0430: \u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u043b\u0430\u0442\u044b\u043d \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0435\u0440 \u0441\u0430\u043d\u044b \u04af\u0448\u0456\u043d \u0448\u0435\u043a\u0442\u0456 \u043e\u0440\u043d\u0430\u0442\u044b\u04a3\u044b\u0437.", + "LabelItemLimitHelp": "\u049a\u0430\u043b\u0430\u0443 \u0431\u043e\u0439\u044b\u043d\u0448\u0430: \u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0456\u043b\u0435\u0442\u0456\u043d \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0435\u0440 \u0441\u0430\u043d\u044b \u04af\u0448\u0456\u043d \u0448\u0435\u043a\u0442\u0456 \u043e\u0440\u043d\u0430\u0442\u044b\u04a3\u044b\u0437.", "MessageBookPluginRequired": "Bookshelf \u043f\u043b\u0430\u0433\u0438\u043d\u0456\u043d \u043e\u0440\u043d\u0430\u0442\u0443\u0434\u044b \u049b\u0430\u0436\u0435\u0442 \u0435\u0442\u0435\u0434\u0456", "MessageGamePluginRequired": "GameBrowser \u043f\u043b\u0430\u0433\u0438\u043d\u0456\u043d \u043e\u0440\u043d\u0430\u0442\u0443\u0434\u044b \u049b\u0430\u0436\u0435\u0442 \u0435\u0442\u0435\u0434\u0456", "MessageUnsetContentHelp": "\u041c\u0430\u0437\u043c\u04b1\u043d \u043a\u04d9\u0434\u0456\u043c\u0433\u0456 \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440 \u0440\u0435\u0442\u0456\u043d\u0434\u0435 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u043d\u0435\u0434\u0456. \u0415\u04a3 \u0436\u0430\u049b\u0441\u044b \u043d\u04d9\u0442\u0438\u0436\u0435\u043b\u0435\u0440 \u0430\u043b\u0443 \u04af\u0448\u0456\u043d, \u0456\u0448\u043a\u0456 \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440\u0434\u044b\u04a3 \u043c\u0430\u0437\u043c\u04af\u043d \u0442\u04af\u0440\u043b\u0435\u0440\u0456\u043d \u043e\u0440\u043d\u0430\u0442\u044b\u043f \u041c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a \u0440\u0435\u0442\u0442\u0435\u0443\u0448\u0456\u043d\u0456 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u04a3\u044b\u0437", "SyncJobItemStatusQueued": "\u041a\u0435\u0437\u0435\u043a\u0442\u0435", "SyncJobItemStatusConverting": "\u0422\u04af\u0440\u043b\u0435\u043d\u0434\u0456\u0440\u0443\u0434\u0435", "SyncJobItemStatusTransferring": "\u0422\u0430\u0441\u044b\u043c\u0430\u043b\u0434\u0430\u0443\u0434\u0430", - "SyncJobItemStatusSynced": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u043b\u0493\u0430\u043d", + "SyncJobItemStatusSynced": "\u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0456\u043b\u0433\u0435\u043d", "SyncJobItemStatusFailed": "\u0421\u04d9\u0442\u0441\u0456\u0437", "SyncJobItemStatusRemovedFromDevice": "\u049a\u04b1\u0440\u044b\u043b\u0493\u044b\u0434\u0430\u043d \u0430\u043b\u0430\u0441\u0442\u0430\u043b\u0493\u0430\u043d", "SyncJobItemStatusCancelled": "\u0411\u043e\u043b\u0434\u044b\u0440\u044b\u043b\u043c\u0430\u0434\u044b", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/ms.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/ms.json index 54690def8..e16b6c492 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/ms.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/ms.json @@ -6,15 +6,20 @@ "Administrator": "Administrator", "Password": "Password", "DeleteImage": "Delete Image", + "MessageThankYouForSupporting": "Thank you for supporting Media Browser.", + "MessagePleaseSupportMediaBrowser": "Please support Media Browser.", "DeleteImageConfirmation": "Are you sure you wish to delete this image?", "FileReadCancelled": "The file read has been canceled.", "FileNotFound": "File not found.", "FileReadError": "An error occurred while reading the file.", "DeleteUser": "Delete User", "DeleteUserConfirmation": "Are you sure you wish to delete this user?", - "PasswordResetHeader": "Password Reset", + "PasswordResetHeader": "Reset Password", "PasswordResetComplete": "The password has been reset.", + "PinCodeResetComplete": "The pin code has been reset.", "PasswordResetConfirmation": "Are you sure you wish to reset the password?", + "PinCodeResetConfirmation": "Are you sure you wish to reset the pin code?", + "HeaderPinCodeReset": "Reset Pin Code", "PasswordSaved": "Password saved.", "PasswordMatchError": "Password and password confirmation must match.", "OptionRelease": "Official Release", @@ -32,6 +37,7 @@ "MessageKeyRemoved": "Thank you. Your supporter key has been removed.", "ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.", "HeaderSearch": "Search", + "ValueDateCreated": "Date created: {0}", "LabelArtist": "Artist", "LabelMovie": "Movie", "LabelMusicVideo": "Music Video", @@ -42,6 +48,17 @@ "LabelFailed": "(failed)", "ButtonHelp": "Help", "ButtonSave": "Save", + "LabelCollection": "Collection", + "HeaderAddToCollection": "Add to Collection", + "NewCollectionNameExample": "Example: Star Wars Collection", + "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata", + "LabelSelectCollection": "Select collection:", + "HeaderDevices": "Devices", + "ButtonScheduledTasks": "Scheduled tasks", + "MessageItemsAdded": "Items added", + "ButtonAddToCollection": "Add to collection", + "HeaderSelectCertificatePath": "Select Certificate Path", + "ConfirmMessageScheduledTaskButton": "This operation normally runs automatically as a scheduled task. It can also be run manually here. To configure the scheduled task, see:", "HeaderSupporterBenefit": "A supporter membership provides additional benefits such as access to premium plugins, internet channel content, and more. {0}Learn more{1}.", "HeaderWelcomeToMediaBrowserServerDashboard": "Welcome to the Media Browser Dashboard", "HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client", @@ -53,6 +70,10 @@ "HeaderChannelAccess": "Channel Access", "HeaderDeviceAccess": "Device Access", "HeaderSelectDevices": "Select Devices", + "ButtonCancelItem": "Cancel item", + "ButtonQueueForRetry": "Queue for retry", + "ButtonReenable": "Re-enable", + "SyncJobItemStatusSyncedMarkForRemoval": "Marked for removal", "LabelAbortedByServerShutdown": "(Aborted by server shutdown)", "LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.", "HeaderDeleteTaskTrigger": "Delete Task Trigger", @@ -64,10 +85,13 @@ "LabelFree": "Free", "HeaderSelectAudio": "Select Audio", "HeaderSelectSubtitles": "Select Subtitles", + "ButtonMarkForRemoval": "Mark for removal from device", + "ButtonUnmarkForRemoval": "Unmark for removal from device", "LabelDefaultStream": "(Default)", "LabelForcedStream": "(Forced)", "LabelDefaultForcedStream": "(Default\/Forced)", "LabelUnknownLanguage": "Unknown language", + "MessageConfirmSyncJobItemCancellation": "Are you sure you wish to cancel this item?", "ButtonMute": "Mute", "ButtonUnmute": "Unmute", "ButtonStop": "Stop", @@ -191,8 +215,10 @@ "LabelPlayMethodDirectPlay": "Direct Playing", "LabelAudioCodec": "Audio: {0}", "LabelVideoCodec": "Video: {0}", + "LabelLocalAccessUrl": "Local access: {0}", "LabelRemoteAccessUrl": "Remote access: {0}", - "LabelRunningOnPort": "Running on port {0}.", + "LabelRunningOnPort": "Running on http port {0}.", + "LabelRunningOnPorts": "Running on http port {0}, and https port {1}.", "HeaderLatestFromChannel": "Latest from {0}", "ButtonDownload": "Download", "LabelUnknownLanaguage": "Unknown language", @@ -206,6 +232,7 @@ "ButtonRefresh": "Refresh", "LabelCurrentPath": "Current path:", "HeaderSelectMediaPath": "Select Media Path", + "HeaderSelectPath": "Select Path", "ButtonNetwork": "Network", "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.", "HeaderMenu": "Menu", @@ -216,6 +243,7 @@ "ButtonResume": "Resume", "HeaderScenes": "Scenes", "HeaderAudioTracks": "Audio Tracks", + "HeaderLibraries": "Libraries", "HeaderSubtitles": "Subtitles", "HeaderVideoQuality": "Video Quality", "MessageErrorPlayingVideo": "There was an error playing the video.", @@ -581,6 +609,8 @@ "MediaInfoStreamTypeEmbeddedImage": "Embedded Image", "MediaInfoRefFrames": "Ref frames", "TabPlayback": "Playback", + "TabNotifications": "Notifications", + "TabExpert": "Expert", "HeaderSelectCustomIntrosPath": "Select Custom Intros Path", "HeaderRateAndReview": "Rate and Review", "HeaderThankYou": "Thank You", @@ -615,6 +645,7 @@ "DashboardTourMobile": "The Media Browser dashboard works great on smartphones and tablets. Manage your server from the palm of your hand anytime, anywhere.", "MessageRefreshQueued": "Refresh queued", "TabDevices": "Devices", + "TabExtras": "Extras", "DeviceLastUsedByUserName": "Last used by {0}", "HeaderDeleteDevice": "Delete Device", "DeleteDeviceConfirmation": "Are you sure you wish to delete this device? It will reappear the next time a user signs in with it.", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/nb.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/nb.json index d6b05127c..4604f8d57 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/nb.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/nb.json @@ -6,6 +6,8 @@ "Administrator": "Administrator", "Password": "Passord", "DeleteImage": "Slett bilde", + "MessageThankYouForSupporting": "Thank you for supporting Media Browser.", + "MessagePleaseSupportMediaBrowser": "Please support Media Browser.", "DeleteImageConfirmation": "Er du sikker p\u00e5 at du vil slette bildet?", "FileReadCancelled": "Lesing av filen kansellert.", "FileNotFound": "Fil ikke funnet", @@ -14,7 +16,10 @@ "DeleteUserConfirmation": "Er du sikker p\u00e5 at du vil slette denne brukeren?", "PasswordResetHeader": "Resett passord", "PasswordResetComplete": "Passordet har blitt resatt", + "PinCodeResetComplete": "The pin code has been reset.", "PasswordResetConfirmation": "Er du sikker p\u00e5 at du vil resette passordet?", + "PinCodeResetConfirmation": "Are you sure you wish to reset the pin code?", + "HeaderPinCodeReset": "Reset Pin Code", "PasswordSaved": "Passord lagret", "PasswordMatchError": "Passord og passord-verifiseringen m\u00e5 matche", "OptionRelease": "Offisiell utgivelse", @@ -32,6 +37,7 @@ "MessageKeyRemoved": "Takk. Din supporter n\u00f8kkel har blitt fjernet.", "ErrorLaunchingChromecast": "Det var en error ved \u00e5 starte Chromecast. Vennligst forsikre deg om at enheten har korrekt forbindelse mot ditt tr\u00e5dl\u00f8se nettverk.", "HeaderSearch": "S\u00f8k", + "ValueDateCreated": "Date created: {0}", "LabelArtist": "Artist", "LabelMovie": "Film", "LabelMusicVideo": "Musikk Video", @@ -42,6 +48,17 @@ "LabelFailed": "(Feilet)", "ButtonHelp": "Help", "ButtonSave": "lagre", + "LabelCollection": "Collection", + "HeaderAddToCollection": "Legg Til I Samling", + "NewCollectionNameExample": "Eksempel: Star Wars Samling", + "OptionSearchForInternetMetadata": "S\u00f8k p\u00e5 internet for artwork og metadata", + "LabelSelectCollection": "Velg samling:", + "HeaderDevices": "Devices", + "ButtonScheduledTasks": "Scheduled tasks", + "MessageItemsAdded": "Items added", + "ButtonAddToCollection": "Add to collection", + "HeaderSelectCertificatePath": "Select Certificate Path", + "ConfirmMessageScheduledTaskButton": "This operation normally runs automatically as a scheduled task. It can also be run manually here. To configure the scheduled task, see:", "HeaderSupporterBenefit": "A supporter membership provides additional benefits such as access to premium plugins, internet channel content, and more. {0}Learn more{1}.", "HeaderWelcomeToMediaBrowserServerDashboard": "Velkommen til Media Browser Dashbord", "HeaderWelcomeToMediaBrowserWebClient": "Velkommen til Media Browser Web Klient", @@ -53,6 +70,10 @@ "HeaderChannelAccess": "Kanal tilgang", "HeaderDeviceAccess": "Device Access", "HeaderSelectDevices": "Select Devices", + "ButtonCancelItem": "Cancel item", + "ButtonQueueForRetry": "Queue for retry", + "ButtonReenable": "Re-enable", + "SyncJobItemStatusSyncedMarkForRemoval": "Marked for removal", "LabelAbortedByServerShutdown": "(Avbrutt av server shutdown)", "LabelScheduledTaskLastRan": "Sist kj\u00f8rt {0}, tar {1}.", "HeaderDeleteTaskTrigger": "Slett Oppgave Trigger", @@ -64,10 +85,13 @@ "LabelFree": "Gratis", "HeaderSelectAudio": "Velg Lyd", "HeaderSelectSubtitles": "Velg Undertekst", + "ButtonMarkForRemoval": "Mark for removal from device", + "ButtonUnmarkForRemoval": "Unmark for removal from device", "LabelDefaultStream": "(Standard)", "LabelForcedStream": "(Tvunget)", "LabelDefaultForcedStream": "(Standard\/Tvunget)", "LabelUnknownLanguage": "Ukjent spr\u00e5k", + "MessageConfirmSyncJobItemCancellation": "Are you sure you wish to cancel this item?", "ButtonMute": "Mute", "ButtonUnmute": "unmute", "ButtonStop": "Stopp", @@ -191,8 +215,10 @@ "LabelPlayMethodDirectPlay": "Direkte Avspilling", "LabelAudioCodec": "Lyd: {0}", "LabelVideoCodec": "Video: {0}", + "LabelLocalAccessUrl": "Local access: {0}", "LabelRemoteAccessUrl": "Ekstern tilgang: {0}", - "LabelRunningOnPort": "Kj\u00f8rer p\u00e5 port {0}.", + "LabelRunningOnPort": "Running on http port {0}.", + "LabelRunningOnPorts": "Running on http port {0}, and https port {1}.", "HeaderLatestFromChannel": "Siste fra {0}", "ButtonDownload": "Nedlasting", "LabelUnknownLanaguage": "Ukjent Spr\u00e5k", @@ -206,6 +232,7 @@ "ButtonRefresh": "Oppdater", "LabelCurrentPath": "N\u00e5v\u00e6rende sti:", "HeaderSelectMediaPath": "Velg Media Sti", + "HeaderSelectPath": "Select Path", "ButtonNetwork": "Nettverk", "MessageDirectoryPickerInstruction": "Nettverksti kan skrives inn manuelt i tilfelle Nettverk-knappen ikke klarer \u00e5 lokalisere enhetene dine. For eksempel {0} eller {1}.", "HeaderMenu": "Meny", @@ -216,6 +243,7 @@ "ButtonResume": "Fortsette", "HeaderScenes": "Scener", "HeaderAudioTracks": "Lydspor", + "HeaderLibraries": "Libraries", "HeaderSubtitles": "Undertekster", "HeaderVideoQuality": "Video Kvalitet", "MessageErrorPlayingVideo": "Det oppstod en error ved avspilling av vidoen.", @@ -581,6 +609,8 @@ "MediaInfoStreamTypeEmbeddedImage": "Innebygd bilde", "MediaInfoRefFrames": "Ref frames", "TabPlayback": "Spill av", + "TabNotifications": "Varslinger", + "TabExpert": "Expert", "HeaderSelectCustomIntrosPath": "Velg tilpasset intro sti", "HeaderRateAndReview": "Ranger og anmeld", "HeaderThankYou": "Takk", @@ -615,6 +645,7 @@ "DashboardTourMobile": "Media Browser dashboard fungerer fint p\u00e5 en smart telefon og nettbrett. Administrer din server fra din h\u00e5ndflate n\u00e5r som helst, hvor som helst.", "MessageRefreshQueued": "Oppfrisk k\u00f8en", "TabDevices": "Enheter", + "TabExtras": "Extras", "DeviceLastUsedByUserName": "Sist brukt av {0}", "HeaderDeleteDevice": "Slett Enhet", "DeleteDeviceConfirmation": "Er du sikker p\u00e5 at du vil slette denne enheten? Den vil gjenoppst\u00e5 neste gang en bruker logger inn med den.", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json index a00071001..1594dd761 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json @@ -6,15 +6,20 @@ "Administrator": "Beheerder", "Password": "Wachtwoord", "DeleteImage": "Verwijder afbeelding", + "MessageThankYouForSupporting": "Dank u voor de ondersteuning van Media Browser.", + "MessagePleaseSupportMediaBrowser": "Geef a.u.b. uw steun aan Media Browser.", "DeleteImageConfirmation": "Weet u zeker dat u deze afbeelding wilt verwijderen?", "FileReadCancelled": "Bestand lezen is geannuleerd.", "FileNotFound": "Bestand niet gevonden.", "FileReadError": "Er is een fout opgetreden bij het lezen van het bestand.", "DeleteUser": "Verwijder gebruiker", - "DeleteUserConfirmation": "Weet je zeker dat je deze gebruiker wilt verwijderen?", + "DeleteUserConfirmation": "Weet u zeker dat u deze gebruiker wilt verwijderen?", "PasswordResetHeader": "Wachtwoord opnieuw instellen", "PasswordResetComplete": "Het wachtwoord is opnieuw ingesteld.", + "PinCodeResetComplete": "The pin code has been reset.", "PasswordResetConfirmation": "Weet u zeker dat u het wachtwoord opnieuw in wilt stellen?", + "PinCodeResetConfirmation": "Are you sure you wish to reset the pin code?", + "HeaderPinCodeReset": "Reset Pin Code", "PasswordSaved": "Wachtwoord opgeslagen.", "PasswordMatchError": "Wachtwoord en wachtwoord bevestiging moeten hetzelfde zijn.", "OptionRelease": "Offici\u00eble Release", @@ -32,6 +37,7 @@ "MessageKeyRemoved": "Dank u. Uw supporter sleutel is verwijderd.", "ErrorLaunchingChromecast": "Er is een fout opgetreden bij het starten van chromecast. Zorg ervoor dat uw apparaat is aangesloten op uw draadloze netwerk.", "HeaderSearch": "Zoeken", + "ValueDateCreated": "Datum aangemaakt: {0}", "LabelArtist": "Artiest", "LabelMovie": "Film", "LabelMusicVideo": "Muziek Video", @@ -42,17 +48,32 @@ "LabelFailed": "(mislukt)", "ButtonHelp": "Hulp", "ButtonSave": "Opslaan", - "HeaderSupporterBenefit": "A supporter membership provides additional benefits such as access to premium plugins, internet channel content, and more. {0}Learn more{1}.", + "LabelCollection": "Verzameling", + "HeaderAddToCollection": "Toevoegen aan verzameling", + "NewCollectionNameExample": "Voorbeeld: Star Wars Collectie", + "OptionSearchForInternetMetadata": "Zoeken op het internet voor afbeeldingen en metadata", + "LabelSelectCollection": "Selecteer verzameling:", + "HeaderDevices": "Apparaten", + "ButtonScheduledTasks": "Geplande taken", + "MessageItemsAdded": "Items toegevoegd", + "ButtonAddToCollection": "Voeg toe aan collectie", + "HeaderSelectCertificatePath": "Selecteer Certificaat Pad", + "ConfirmMessageScheduledTaskButton": "Deze operatie loopt normaal gesproken automatisch als een geplande taak. Het kan hier ook handmatig worden uitgevoerd. Om de geplande taak te configureren, zie:", + "HeaderSupporterBenefit": "Een supporter lidmaatschap biedt voordelen zoals toegang tot premium plug-ins, internet kanalen en meer. {0}Meer weten{1}.", "HeaderWelcomeToMediaBrowserServerDashboard": "Welkom bij het Media Browser Dashboard", "HeaderWelcomeToMediaBrowserWebClient": "Welkom op de Media Browser Web Client", - "ButtonTakeTheTour": "Neem de tour", + "ButtonTakeTheTour": "Volg de tour", "HeaderWelcomeBack": "Welkom terug!", - "ButtonTakeTheTourToSeeWhatsNew": "Neem de tour om te zien wat nieuw is", + "ButtonTakeTheTourToSeeWhatsNew": "Volg de tour om te zien wat nieuw is", "MessageNoSyncJobsFound": "Geen sync opdrachten gevonden. Maak sync opdrachten via de Synchronisatie knoppen in de web interface.", "HeaderLibraryAccess": "Bibliotheek toegang", "HeaderChannelAccess": "Kanaal toegang", "HeaderDeviceAccess": "Apparaat Toegang", "HeaderSelectDevices": "Selecteer Apparaten", + "ButtonCancelItem": "Annuleren item", + "ButtonQueueForRetry": "Wachtrij voor opnieuw proberen", + "ButtonReenable": "Opnieuw inschakelen", + "SyncJobItemStatusSyncedMarkForRemoval": "Gemarkeerd voor verwijdering", "LabelAbortedByServerShutdown": "(Afgebroken door afsluiten van de server)", "LabelScheduledTaskLastRan": "Laatste keer {0}, duur {1}.", "HeaderDeleteTaskTrigger": "Verwijderen Taak Trigger", @@ -64,10 +85,13 @@ "LabelFree": "Gratis", "HeaderSelectAudio": "Selecteer Audio", "HeaderSelectSubtitles": "Selecteer Ondertitels", + "ButtonMarkForRemoval": "Markeren voor verwijdering uit het apparaat", + "ButtonUnmarkForRemoval": "Niet markeren voor verwijdering uit het apparaat", "LabelDefaultStream": "(Standaard)", "LabelForcedStream": "(Geforceerd)", "LabelDefaultForcedStream": "(Standaard \/ Georceerd)", "LabelUnknownLanguage": "Onbekende taal", + "MessageConfirmSyncJobItemCancellation": "Bent u zeker dat u dit item wilt annuleren?", "ButtonMute": "Dempen", "ButtonUnmute": "Dempen opheffen", "ButtonStop": "Stop", @@ -76,7 +100,7 @@ "ButtonPlay": "Afspelen", "ButtonEdit": "Bewerken", "ButtonQueue": "Wachtrij", - "ButtonPlayTrailer": "Speel trailer", + "ButtonPlayTrailer": "Trailer afspelen", "ButtonPlaylist": "Afspeellijst", "ButtonPreviousTrack": "Vorig Nummer", "LabelEnabled": "Ingeschakeld", @@ -191,8 +215,10 @@ "LabelPlayMethodDirectPlay": "Direct Afspelen", "LabelAudioCodec": "Audio: {0}", "LabelVideoCodec": "Video: {0}", + "LabelLocalAccessUrl": "Lokale toegang: {0}", "LabelRemoteAccessUrl": "Toegang op afstand: {0}", - "LabelRunningOnPort": "Draait op poort {0}.", + "LabelRunningOnPort": "Draait op http poort {0}.", + "LabelRunningOnPorts": "Draait op http poort {0} en https poort {1}.", "HeaderLatestFromChannel": "Laatste van {0}", "ButtonDownload": "Download", "LabelUnknownLanaguage": "Onbekende taal", @@ -206,6 +232,7 @@ "ButtonRefresh": "Vernieuwen", "LabelCurrentPath": "Huidige pad:", "HeaderSelectMediaPath": "Selecteer Media Pad", + "HeaderSelectPath": "Selecteer Pad", "ButtonNetwork": "Netwerk", "MessageDirectoryPickerInstruction": "Netwerk paden kunnen handmatig worden ingevoerd in het geval de Netwerk knop faalt om uw apparatuur te lokaliseren . Bijvoorbeeld: {0} of {1}.", "HeaderMenu": "Menu", @@ -216,6 +243,7 @@ "ButtonResume": "Hervatten", "HeaderScenes": "Scenes", "HeaderAudioTracks": "Audio sporen", + "HeaderLibraries": "Bibliotheken", "HeaderSubtitles": "Ondertitels", "HeaderVideoQuality": "Video Kwalitet", "MessageErrorPlayingVideo": "Er ging iets mis bij het afspelen van de video.", @@ -415,14 +443,14 @@ "LabelBirthDate": "Geboortedatum:", "LabelDeathDate": "Overlijdens datum:", "HeaderRemoveMediaLocation": "Verwijder media locatie", - "MessageConfirmRemoveMediaLocation": "Weet je zeker dat je deze locatie wilt verwijderen?", + "MessageConfirmRemoveMediaLocation": "Weet u zeker dat u deze locatie wilt verwijderen?", "HeaderRenameMediaFolder": "Hernoem media map", "LabelNewName": "Nieuwe naam:", "HeaderAddMediaFolder": "Voeg media map toe", "HeaderAddMediaFolderHelp": "Naam (Films, Muziek, TV etc):", "HeaderRemoveMediaFolder": "Verwijder media map", "MessageTheFollowingLocationWillBeRemovedFromLibrary": "De volgende media locaties worden uit de bibliotheek verwijderd:", - "MessageAreYouSureYouWishToRemoveMediaFolder": "Weet je zeker dat je deze media map wilt verwijderen?", + "MessageAreYouSureYouWishToRemoveMediaFolder": "Weet u zeker dat u deze media map wilt verwijderen?", "ButtonRename": "Hernoem", "ButtonChangeType": "Verander soort", "HeaderMediaLocations": "Media Locaties", @@ -456,13 +484,13 @@ "MessageYouHaveVersionInstalled": "Op dit moment is versie {0} ge\u00efnstalleerd.", "MessageTrialExpired": "De proef periode voor deze feature is verlopen", "MessageTrialWillExpireIn": "De proef periode voor deze feature zal in {0} dag(en) verlopen", - "MessageInstallPluginFromApp": "Deze plugin moet ge\u00efnstalleerd worden vanuit de app waarin je het wil gebruiken.", + "MessageInstallPluginFromApp": "Deze plugin moet ge\u00efnstalleerd worden vanuit de app waarin u het wilt gebruiken.", "ValuePriceUSD": "Prijs {0} (USD)", "MessageFeatureIncludedWithSupporter": "U bent geregistreerd voor deze functie, en zal deze kunnen blijven gebruiken met uw actieve supporter lidmaatschap.", - "MessageChangeRecurringPlanConfirm": "Na het afronden van deze transactie moet je de vorige terugkeerende donatie in je PayPal account stopzetten. Bedankt voor je support aan Media Browser.", - "MessageSupporterMembershipExpiredOn": "Je supporter membership is verlopen op {0}", - "MessageYouHaveALifetimeMembership": "Je hebt een levenslang supporter lidmaatschap. Je kan aanvullende eenmalige of terugkerende donaties doen met de opties hieronder. Bedankt voor je support aan Media Browser.", - "MessageYouHaveAnActiveRecurringMembership": "Je hebt een actief {0} lidmaatschap. Je kan met de opties hieronder je lidmaatschap upgraden.", + "MessageChangeRecurringPlanConfirm": "Na het afronden van deze transactie moet u de vorige terugkerende donatie in uw PayPal account stopzetten. Bedankt voor uw support aan Media Browser.", + "MessageSupporterMembershipExpiredOn": "Uw supporter lidmaatschap is verlopen op {0}", + "MessageYouHaveALifetimeMembership": "U hebt een levenslang supporter lidmaatschap. U kunt aanvullende eenmalige of terugkerende donaties doen met de opties hieronder. Bedankt voor uw support aan Media Browser.", + "MessageYouHaveAnActiveRecurringMembership": "U hebt een actief {0} lidmaatschap. U kunt met de opties hieronder uw lidmaatschap upgraden.", "ButtonDelete": "Verwijderen", "HeaderMediaBrowserAccountAdded": "Media Browser account toegevoegd", "MessageMediaBrowserAccountAdded": "Het Media Browser account is aan deze gebruiker toegevoegd.", @@ -481,7 +509,7 @@ "ButtonImDone": "Ik ben klaar", "OptionWatched": "Gezien", "OptionUnwatched": "Ongezien", - "ExternalPlayerPlaystateOptionsHelp": "Geef aan hoe je deze video de volgende keer wilt hervatten.", + "ExternalPlayerPlaystateOptionsHelp": "Geef aan hoe u deze video de volgende keer wilt hervatten.", "LabelMarkAs": "Markeer als:", "OptionInProgress": "In uitvoering", "LabelResumePoint": "Hervat punt:", @@ -506,8 +534,8 @@ "HeaderMissing": "Missend", "ButtonWebsite": "Website", "TooltipFavorite": "Favoriet", - "TooltipLike": "Like", - "TooltipDislike": "Dislike", + "TooltipLike": "Leuk", + "TooltipDislike": "Niet leuk", "TooltipPlayed": "Afgespeeld", "ValueSeriesYearToPresent": "{0}-Heden", "ValueAwards": "Prijzen: {0}", @@ -581,11 +609,13 @@ "MediaInfoStreamTypeEmbeddedImage": "Ingevoegde afbeelding", "MediaInfoRefFrames": "Ref frames", "TabPlayback": "Afspelen", + "TabNotifications": "Meldingen", + "TabExpert": "Expert", "HeaderSelectCustomIntrosPath": "Selecteer eigen pad naar intro's", "HeaderRateAndReview": "Beoordelen", "HeaderThankYou": "Bedankt", "MessageThankYouForYourReview": "Bedankt voor de beoordeling", - "LabelYourRating": "Jouw beoordeling:", + "LabelYourRating": "Uw beoordeling:", "LabelFullReview": "Volledige beoordeling:", "LabelShortRatingDescription": "Korte beoordeling overzicht:", "OptionIRecommendThisItem": "Ik beveel dit item aan", @@ -596,9 +626,9 @@ "WebClientTourMetadataManager": "Klik wijzigen om de metadata manager te openen", "WebClientTourPlaylists": "Maak eenvoudig een afspeellijst en mixlijst, en speel deze op elk apparaat", "WebClientTourCollections": "Maak film verzamelingen door films samen te voegen", - "WebClientTourUserPreferences1": "Gebruikersvoorkeuren stelt je in staat de manier waarop de bibliotheek aan gebruikers getoont wordt aan te passen", - "WebClientTourUserPreferences2": "Configureer je geluids- en ondertitelingsinstellingen eenmalig voor elke Media Browser app", - "WebClientTourUserPreferences3": "Ontwerp de startpagina van de web client zoals jij wilt", + "WebClientTourUserPreferences1": "Gebruikersvoorkeuren stellen u in staat de manier waarop de bibliotheek aan gebruikers getoond wordt aan te passen", + "WebClientTourUserPreferences2": "Configureer uw geluids- en ondertitelingsinstellingen eenmalig voor elke Media Browser app", + "WebClientTourUserPreferences3": "Ontwerp de startpagina van de web client volgens uw wensen", "WebClientTourUserPreferences4": "Configureer achtergronden, theme songs en externe spelers", "WebClientTourMobile1": "De web client werk perfect op smartphones en tablets...", "WebClientTourMobile2": "en kan elke andere Media Browser app bedienen", @@ -606,18 +636,19 @@ "DashboardTourDashboard": "Het server-dashboard steld u in staat uw server en uw gebruikers te monitoren . U zult altijd weten wie wat doet en waar ze zijn.", "DashboardTourHelp": "De in-app hulp bevat handige knoppen om wiki pagina's te openen die gaan over de informatie op het scherm.", "DashboardTourUsers": "Maak gemakkelijk gebruikersaccounts voor uw vrienden en familie, elk met hun eigen machtigingen, bibliotheek toegang, ouderlijk toezicht en meer.", - "DashboardTourCinemaMode": "Cinema mode brengt de theater ervaring naar je woonkamer met de mogelijkheid om trailers en eigen intro's voor de film af te spelen", + "DashboardTourCinemaMode": "Cinema mode brengt de theater ervaring naar uw woonkamer met de mogelijkheid om trailers en eigen intro's voor de film af te spelen.", "DashboardTourChapters": "Schakel hoofdstuk afbeeldingen genereren in voor uw video's voor een aantrekkelijker presentatie tijdens het kijken.", - "DashboardTourSubtitles": "Download automatisch ondertitels voor uw video's in een andere talen.", + "DashboardTourSubtitles": "Download automatisch ondertitels voor uw video's in een andere taal.", "DashboardTourPlugins": "Installeer plugins zoals Internet videokanalen, live tv, metadata, scanners en meer.", "DashboardTourNotifications": "Meldingen van de server gebeurtenissen automatisch verzenden naar uw mobiele apparaat, e-mail en meer.", "DashboardTourScheduledTasks": "Beheer eenvoudig langlopende transacties met geplande taken. Beslis zelf wanneer ze worden uitgevoerd en hoe vaak.", - "DashboardTourMobile": "Het dashboard van Media Browser werkt geweldig op smartphones en tablets. Uw server beheren vanuit de palm van uw hand, overal en altijd.", + "DashboardTourMobile": "Het dashboard van Media Browser werkt geweldig op smartphones en tablets. Beheer je server vanuit de palm van je hand, overal en altijd.", "MessageRefreshQueued": "Vernieuwen wachtrij", "TabDevices": "Apparaten", + "TabExtras": "Extra's", "DeviceLastUsedByUserName": "Het laatste gebruikt door {0}", "HeaderDeleteDevice": "Verwijder apparaat", - "DeleteDeviceConfirmation": "Weet je zeker dat je dit apparaat wilt verwijderen? Het zal opnieuw verschijnen als er een gebruiker mee aanmeldt.", + "DeleteDeviceConfirmation": "Weet u zeker dat u dit apparaat wilt verwijderen? Het zal opnieuw verschijnen als een gebruiker zich hiermee aanmeldt.", "LabelEnableCameraUploadFor": "Schakel camera upload in voor:", "HeaderSelectUploadPath": "Kies upload pad", "LabelEnableCameraUploadForHelp": "Uploads zullen automatisch in de achtergrond uitgevoerd worden als er aangemeld is bij Media Browser.", @@ -625,7 +656,7 @@ "ButtonLibraryAccess": "Bibliotheek toegang", "ButtonParentalControl": "Ouderlijk toezicht", "HeaderInvitationSent": "Uitnodiging verzonden", - "MessageInvitationSentToUser": "Een email is verzonden naar {0} om je uitnodiging om media te delen te accepteren.", + "MessageInvitationSentToUser": "Een email is verzonden naar {0} om uw uitnodiging om media te delen te accepteren.", "MessageInvitationSentToNewUser": "Een email is verzonden naar {0} om je uitnodiging aan te melden bij Media Browser", "HeaderConnectionFailure": "Verbindingsfout", "MessageUnableToConnectToServer": "Het is momenteel niet mogelijk met de geselecteerde server te verbinden. Controleer dat deze draait en probeer het opnieuw.", @@ -636,15 +667,15 @@ "ButtonAccept": "Accepteren", "ButtonReject": "Weigeren", "HeaderForgotPassword": "Wachtwoord vergeten", - "MessageContactAdminToResetPassword": "Neem contact op met de server beheerder om je wachtwoord te resetten.", - "MessageForgotPasswordInNetworkRequired": "Probeer de wachtwoord herstel procedure opnieuw vanuit je thuisnetwerk.", + "MessageContactAdminToResetPassword": "Neem contact op met de server beheerder om uw wachtwoord te resetten.", + "MessageForgotPasswordInNetworkRequired": "Probeer de wachtwoord herstel procedure opnieuw vanuit uw thuisnetwerk.", "MessageForgotPasswordFileCreated": "Het volgende bestand met instructies hoe nu verder te gaan is gemaakt:", "MessageForgotPasswordFileExpiration": "De hertsel pincode verloopt {0}.", "MessageInvalidForgotPasswordPin": "Er is een ongeldige of verlopen pincode ingegeven. Probeer opnieuw.", "MessagePasswordResetForUsers": "Wachtwoorden zijn gereset voor de volgende gebruikers:", "HeaderInviteGuest": "Nodig gast uit", "ButtonLinkMyMediaBrowserAccount": "Koppel mijn account nu", - "MessageConnectAccountRequiredToInviteGuest": "Om gasten uit te kunnen nodigen moet je Media Browser account aan deze server gekoppeld worden.", + "MessageConnectAccountRequiredToInviteGuest": "Om gasten uit te kunnen nodigen moet uw Media Browser account aan deze server gekoppeld worden.", "ButtonSync": "Synchronisatie", "SyncMedia": "Synchroniseer media", "HeaderCancelSyncJob": "Annuleer synchronisatie", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json index 0d3cdbde0..0b252a4fd 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json @@ -6,6 +6,8 @@ "Administrator": "Administrator", "Password": "Has\u0142o", "DeleteImage": "Usu\u0144 zdj\u0119cie", + "MessageThankYouForSupporting": "Thank you for supporting Media Browser.", + "MessagePleaseSupportMediaBrowser": "Please support Media Browser.", "DeleteImageConfirmation": "Jeste\u015b pewien \u017ce chcesz usun\u0105\u0107 to zdj\u0119cie?", "FileReadCancelled": "Odczytywanie pliku zosta\u0142o anulowane.", "FileNotFound": "Plik nie znaleziony.", @@ -14,7 +16,10 @@ "DeleteUserConfirmation": "Czy na pewno chcesz skasowa\u0107 tego u\u017cytkownika?", "PasswordResetHeader": "Zresetuj has\u0142o", "PasswordResetComplete": "Has\u0142o zosta\u0142o zresetowane.", + "PinCodeResetComplete": "The pin code has been reset.", "PasswordResetConfirmation": "Jeste\u015b pewien \u017ce chcesz zresetowa\u0107 has\u0142o?", + "PinCodeResetConfirmation": "Are you sure you wish to reset the pin code?", + "HeaderPinCodeReset": "Reset Pin Code", "PasswordSaved": "Has\u0142o zapisane.", "PasswordMatchError": "Has\u0142o i potwierdzenie has\u0142a musz\u0105 si\u0119 zgadza\u0107.", "OptionRelease": "Oficjalne wydanie", @@ -32,6 +37,7 @@ "MessageKeyRemoved": "Thank you. Your supporter key has been removed.", "ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.", "HeaderSearch": "Search", + "ValueDateCreated": "Date created: {0}", "LabelArtist": "Artist", "LabelMovie": "Movie", "LabelMusicVideo": "Music Video", @@ -42,6 +48,17 @@ "LabelFailed": "(failed)", "ButtonHelp": "Help", "ButtonSave": "Zapisz", + "LabelCollection": "Collection", + "HeaderAddToCollection": "Add to Collection", + "NewCollectionNameExample": "Example: Star Wars Collection", + "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata", + "LabelSelectCollection": "Select collection:", + "HeaderDevices": "Devices", + "ButtonScheduledTasks": "Scheduled tasks", + "MessageItemsAdded": "Items added", + "ButtonAddToCollection": "Add to collection", + "HeaderSelectCertificatePath": "Select Certificate Path", + "ConfirmMessageScheduledTaskButton": "This operation normally runs automatically as a scheduled task. It can also be run manually here. To configure the scheduled task, see:", "HeaderSupporterBenefit": "A supporter membership provides additional benefits such as access to premium plugins, internet channel content, and more. {0}Learn more{1}.", "HeaderWelcomeToMediaBrowserServerDashboard": "Welcome to the Media Browser Dashboard", "HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client", @@ -53,6 +70,10 @@ "HeaderChannelAccess": "Channel Access", "HeaderDeviceAccess": "Device Access", "HeaderSelectDevices": "Select Devices", + "ButtonCancelItem": "Cancel item", + "ButtonQueueForRetry": "Queue for retry", + "ButtonReenable": "Re-enable", + "SyncJobItemStatusSyncedMarkForRemoval": "Marked for removal", "LabelAbortedByServerShutdown": "(Aborted by server shutdown)", "LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.", "HeaderDeleteTaskTrigger": "Delete Task Trigger", @@ -64,10 +85,13 @@ "LabelFree": "Free", "HeaderSelectAudio": "Select Audio", "HeaderSelectSubtitles": "Select Subtitles", + "ButtonMarkForRemoval": "Mark for removal from device", + "ButtonUnmarkForRemoval": "Unmark for removal from device", "LabelDefaultStream": "(Default)", "LabelForcedStream": "(Forced)", "LabelDefaultForcedStream": "(Default\/Forced)", "LabelUnknownLanguage": "Unknown language", + "MessageConfirmSyncJobItemCancellation": "Are you sure you wish to cancel this item?", "ButtonMute": "Mute", "ButtonUnmute": "Unmute", "ButtonStop": "Stop", @@ -191,8 +215,10 @@ "LabelPlayMethodDirectPlay": "Direct Playing", "LabelAudioCodec": "Audio: {0}", "LabelVideoCodec": "Video: {0}", + "LabelLocalAccessUrl": "Local access: {0}", "LabelRemoteAccessUrl": "Remote access: {0}", - "LabelRunningOnPort": "Running on port {0}.", + "LabelRunningOnPort": "Running on http port {0}.", + "LabelRunningOnPorts": "Running on http port {0}, and https port {1}.", "HeaderLatestFromChannel": "Latest from {0}", "ButtonDownload": "Download", "LabelUnknownLanaguage": "Unknown language", @@ -206,6 +232,7 @@ "ButtonRefresh": "Refresh", "LabelCurrentPath": "Current path:", "HeaderSelectMediaPath": "Select Media Path", + "HeaderSelectPath": "Select Path", "ButtonNetwork": "Network", "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.", "HeaderMenu": "Menu", @@ -216,6 +243,7 @@ "ButtonResume": "Resume", "HeaderScenes": "Scenes", "HeaderAudioTracks": "Audio Tracks", + "HeaderLibraries": "Libraries", "HeaderSubtitles": "Subtitles", "HeaderVideoQuality": "Video Quality", "MessageErrorPlayingVideo": "There was an error playing the video.", @@ -581,6 +609,8 @@ "MediaInfoStreamTypeEmbeddedImage": "Embedded Image", "MediaInfoRefFrames": "Ref frames", "TabPlayback": "Playback", + "TabNotifications": "Notifications", + "TabExpert": "Expert", "HeaderSelectCustomIntrosPath": "Select Custom Intros Path", "HeaderRateAndReview": "Rate and Review", "HeaderThankYou": "Thank You", @@ -615,6 +645,7 @@ "DashboardTourMobile": "The Media Browser dashboard works great on smartphones and tablets. Manage your server from the palm of your hand anytime, anywhere.", "MessageRefreshQueued": "Refresh queued", "TabDevices": "Devices", + "TabExtras": "Extras", "DeviceLastUsedByUserName": "Last used by {0}", "HeaderDeleteDevice": "Delete Device", "DeleteDeviceConfirmation": "Are you sure you wish to delete this device? It will reappear the next time a user signs in with it.", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json index 278527e7e..5a3e564e4 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json @@ -6,6 +6,8 @@ "Administrator": "Administrador", "Password": "Senha", "DeleteImage": "Excluir Imagem", + "MessageThankYouForSupporting": "Obrigado por apoiar o Media Browser", + "MessagePleaseSupportMediaBrowser": "Por favor, ap\u00f3ie o Media Browser.", "DeleteImageConfirmation": "Deseja realmente excluir esta imagem?", "FileReadCancelled": "A leitura do arquivo foi cancelada.", "FileNotFound": "Arquivo n\u00e3o encontrado.", @@ -14,7 +16,10 @@ "DeleteUserConfirmation": "Deseja realmente excluir este usu\u00e1rio?", "PasswordResetHeader": "Redefinir Senha", "PasswordResetComplete": "A senha foi redefinida.", + "PinCodeResetComplete": "The pin code has been reset.", "PasswordResetConfirmation": "Deseja realmente redefinir a senha?", + "PinCodeResetConfirmation": "Are you sure you wish to reset the pin code?", + "HeaderPinCodeReset": "Reset Pin Code", "PasswordSaved": "Senha salva.", "PasswordMatchError": "A senha e a confirma\u00e7\u00e3o da senha devem ser iguais.", "OptionRelease": "Lan\u00e7amento Oficial", @@ -32,6 +37,7 @@ "MessageKeyRemoved": "Obrigado. Sua chave de colaborador foi removida.", "ErrorLaunchingChromecast": "Ocorreu um erro ao iniciar o chromecast. Por favor verifique se seu dispositivo est\u00e1 conectado \u00e0 sua rede sem fio.", "HeaderSearch": "Busca", + "ValueDateCreated": "Data da cria\u00e7\u00e3o: {0}", "LabelArtist": "Artista", "LabelMovie": "Filme", "LabelMusicVideo": "V\u00eddeo Musical", @@ -42,17 +48,32 @@ "LabelFailed": "(falhou)", "ButtonHelp": "Ajuda", "ButtonSave": "Salvar", - "HeaderSupporterBenefit": "A supporter membership provides additional benefits such as access to premium plugins, internet channel content, and more. {0}Learn more{1}.", + "LabelCollection": "Cole\u00e7\u00e3o", + "HeaderAddToCollection": "Adicionar \u00e0 Cole\u00e7\u00e3o", + "NewCollectionNameExample": "Exemplo: Cole\u00e7\u00e3o Star Wars", + "OptionSearchForInternetMetadata": "Buscar artwork e metadados na internet", + "LabelSelectCollection": "Selecione cole\u00e7\u00e3o:", + "HeaderDevices": "Dispositivos", + "ButtonScheduledTasks": "Tarefas Agendadas", + "MessageItemsAdded": "Itens adicionados", + "ButtonAddToCollection": "Adicionar \u00e0 Cole\u00e7\u00e3o", + "HeaderSelectCertificatePath": "Selecione o Caminho do Certificado", + "ConfirmMessageScheduledTaskButton": "Esta opera\u00e7\u00e3o normalmente \u00e9 executada automaticamente como uma tarefa agendada. Tamb\u00e9m pode ser executada manualmente. Para configurar a tarefa agendada, veja:", + "HeaderSupporterBenefit": "A ades\u00e3o de colaborador fornece benef\u00edcios adicionais como acesso a plugins premium, canais de conte\u00fado da internet e mais. {0}Saiba mais{1}.", "HeaderWelcomeToMediaBrowserServerDashboard": "Bem Vindo ao Painel do Media Browser", "HeaderWelcomeToMediaBrowserWebClient": "Bem-vindo ao Cliente Web do Media Browser", "ButtonTakeTheTour": "Fa\u00e7a o tour", - "HeaderWelcomeBack": "Welcome back!", - "ButtonTakeTheTourToSeeWhatsNew": "Take the tour to see what's new", + "HeaderWelcomeBack": "Bem-vindo novamente!", + "ButtonTakeTheTourToSeeWhatsNew": "Fa\u00e7a o tour para ver as novidades", "MessageNoSyncJobsFound": "Nenhuma tarefa de sincroniza\u00e7\u00e3o encontrada. Crie uma tarefa de sincroniza\u00e7\u00e3o usando os bot\u00f5es Sincroniza\u00e7\u00e3o encontrados na interface web.", "HeaderLibraryAccess": "Acesso \u00e0 Biblioteca", "HeaderChannelAccess": "Acesso ao Canal", "HeaderDeviceAccess": "Acesso ao Dispositivo", "HeaderSelectDevices": "Selecionar Dispositivos", + "ButtonCancelItem": "Cancelar item", + "ButtonQueueForRetry": "Enfileirar para tentar novamente", + "ButtonReenable": "Reativar", + "SyncJobItemStatusSyncedMarkForRemoval": "Marcado para remo\u00e7\u00e3o", "LabelAbortedByServerShutdown": "(Abortada pelo desligamento do servidor)", "LabelScheduledTaskLastRan": "\u00daltima execu\u00e7\u00e3o {0}, demorando {1}.", "HeaderDeleteTaskTrigger": "Excluir Disparador da Tarefa", @@ -64,10 +85,13 @@ "LabelFree": "Gr\u00e1tis", "HeaderSelectAudio": "Selecione \u00c1udio", "HeaderSelectSubtitles": "Selecione Legendas", + "ButtonMarkForRemoval": "Marcado para remo\u00e7\u00e3o do dispositivo", + "ButtonUnmarkForRemoval": "Desmarcado para remo\u00e7\u00e3o do dispositivo", "LabelDefaultStream": "(Padr\u00e3o)", "LabelForcedStream": "(For\u00e7ada)", "LabelDefaultForcedStream": "(Padr\u00e3o\/For\u00e7ada)", "LabelUnknownLanguage": "Idioma desconhecido", + "MessageConfirmSyncJobItemCancellation": "Deseja realmente cancelar este item?", "ButtonMute": "Mudo", "ButtonUnmute": "Remover Mudo", "ButtonStop": "Parar", @@ -191,8 +215,10 @@ "LabelPlayMethodDirectPlay": "Reprodu\u00e7\u00e3o Direta", "LabelAudioCodec": "\u00c1udio: {0}", "LabelVideoCodec": "V\u00eddeo: {0}", + "LabelLocalAccessUrl": "Acesso local: {0}", "LabelRemoteAccessUrl": "Acesso Remoto: {0}", - "LabelRunningOnPort": "Executando na porta {0}.", + "LabelRunningOnPort": "Executando na porta http {0}.", + "LabelRunningOnPorts": "Executando na porta http {0} e porta https {1}.", "HeaderLatestFromChannel": "Mais recentes de {0}", "ButtonDownload": "Download", "LabelUnknownLanaguage": "Idioma desconhecido", @@ -206,6 +232,7 @@ "ButtonRefresh": "Atualizar", "LabelCurrentPath": "Caminho atual:", "HeaderSelectMediaPath": "Selecionar o Caminho da M\u00eddia", + "HeaderSelectPath": "Selecione o Caminho", "ButtonNetwork": "Rede", "MessageDirectoryPickerInstruction": "Os caminhos da rede podem ser digitados manualmente caso o bot\u00e3o de Rede n\u00e3o consiga localizar seus dispositivos. Por exemplo, {0} ou {1}.", "HeaderMenu": "Menu", @@ -216,6 +243,7 @@ "ButtonResume": "Retomar", "HeaderScenes": "Cenas", "HeaderAudioTracks": "Faixas de Audio", + "HeaderLibraries": "Bibliotecas", "HeaderSubtitles": "Legendas", "HeaderVideoQuality": "Qualidade do V\u00eddeo", "MessageErrorPlayingVideo": "Houve um erro na reprodu\u00e7\u00e3o do v\u00eddeo.", @@ -266,13 +294,13 @@ "MessagePleaseEnterNameOrId": "Por favor, digite um nome ou Id externo.", "MessageValueNotCorrect": "O valor digitado n\u00e3o est\u00e1 correto. Por favor, tente novamente.", "MessageItemSaved": "Item salvo.", - "MessagePleaseAcceptTermsOfServiceBeforeContinuing": "Please accept the terms of service before continuing.", + "MessagePleaseAcceptTermsOfServiceBeforeContinuing": "Por favor, aceite os termos de servi\u00e7o antes de continuar.", "OptionEnded": "Finalizada", "OptionContinuing": "Em Exibi\u00e7\u00e3o", "OptionOff": "Off", "OptionOn": "On", "ButtonSettings": "Ajustes", - "ButtonUninstall": "Uninstall", + "ButtonUninstall": "Desinstalar", "HeaderFields": "Campos", "HeaderFieldsHelp": "Deslize um campo para 'off' para bloquear e evitar que seus dados sejam alterados.", "HeaderLiveTV": "TV ao Vivo", @@ -581,6 +609,8 @@ "MediaInfoStreamTypeEmbeddedImage": "Imagem Incorporada", "MediaInfoRefFrames": "Quadros de refer\u00eancia", "TabPlayback": "Reprodu\u00e7\u00e3o", + "TabNotifications": "Notifica\u00e7\u00f5es", + "TabExpert": "Avan\u00e7ado", "HeaderSelectCustomIntrosPath": "Selecionar o Caminho para Intros Personalizadas", "HeaderRateAndReview": "Avaliar e Comentar", "HeaderThankYou": "Obrigado", @@ -615,6 +645,7 @@ "DashboardTourMobile": "O painel do M\u00e9dia Browser funciona perfeitamente em smartphones e tablets. Gerencie seu servidor da palma de sua m\u00e3o, a qualquer hora e em qualquer lugar.", "MessageRefreshQueued": "Atualiza\u00e7\u00e3o iniciada", "TabDevices": "Dispositivos", + "TabExtras": "Extras", "DeviceLastUsedByUserName": "Utilizado por \u00faltimo por {0}", "HeaderDeleteDevice": "Excluir Dispositivo", "DeleteDeviceConfirmation": "Tem certeza de que deseja excluir este dispositivo? Ele reaparecer\u00e1 a pr\u00f3xima vez que um usu\u00e1rio utiliz\u00e1-lo.", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json index e274bccc4..600f1f902 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json @@ -6,6 +6,8 @@ "Administrator": "Administrador", "Password": "Senha", "DeleteImage": "Apagar Imagem", + "MessageThankYouForSupporting": "Thank you for supporting Media Browser.", + "MessagePleaseSupportMediaBrowser": "Please support Media Browser.", "DeleteImageConfirmation": "Tem a certeza que deseja apagar a imagem?", "FileReadCancelled": "A leitura do ficheiro foi cancelada.", "FileNotFound": "Ficheiro n\u00e3o encontrado.", @@ -14,7 +16,10 @@ "DeleteUserConfirmation": "Tem a certeza que deseja apagar este utilizador?", "PasswordResetHeader": "Redefinir Senha", "PasswordResetComplete": "A senha foi redefinida.", + "PinCodeResetComplete": "The pin code has been reset.", "PasswordResetConfirmation": "Tem a certeza que deseja redefinir a senha?", + "PinCodeResetConfirmation": "Are you sure you wish to reset the pin code?", + "HeaderPinCodeReset": "Reset Pin Code", "PasswordSaved": "Senha guardada.", "PasswordMatchError": "A senha e a confirma\u00e7\u00e3o da senha devem coincidir.", "OptionRelease": "Lan\u00e7amento Oficial", @@ -32,6 +37,7 @@ "MessageKeyRemoved": "Thank you. Your supporter key has been removed.", "ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.", "HeaderSearch": "Search", + "ValueDateCreated": "Date created: {0}", "LabelArtist": "Artist", "LabelMovie": "Movie", "LabelMusicVideo": "Music Video", @@ -42,6 +48,17 @@ "LabelFailed": "(falhou)", "ButtonHelp": "Help", "ButtonSave": "Guardar", + "LabelCollection": "Collection", + "HeaderAddToCollection": "Add to Collection", + "NewCollectionNameExample": "Exemplo: Cole\u00e7\u00e3o Guerra das Estrelas", + "OptionSearchForInternetMetadata": "Procurar na internet por imagens e metadados", + "LabelSelectCollection": "Select collection:", + "HeaderDevices": "Devices", + "ButtonScheduledTasks": "Scheduled tasks", + "MessageItemsAdded": "Items added", + "ButtonAddToCollection": "Add to collection", + "HeaderSelectCertificatePath": "Select Certificate Path", + "ConfirmMessageScheduledTaskButton": "This operation normally runs automatically as a scheduled task. It can also be run manually here. To configure the scheduled task, see:", "HeaderSupporterBenefit": "A supporter membership provides additional benefits such as access to premium plugins, internet channel content, and more. {0}Learn more{1}.", "HeaderWelcomeToMediaBrowserServerDashboard": "Welcome to the Media Browser Dashboard", "HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client", @@ -53,6 +70,10 @@ "HeaderChannelAccess": "Channel Access", "HeaderDeviceAccess": "Device Access", "HeaderSelectDevices": "Select Devices", + "ButtonCancelItem": "Cancel item", + "ButtonQueueForRetry": "Queue for retry", + "ButtonReenable": "Re-enable", + "SyncJobItemStatusSyncedMarkForRemoval": "Marked for removal", "LabelAbortedByServerShutdown": "(Aborted by server shutdown)", "LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.", "HeaderDeleteTaskTrigger": "Delete Task Trigger", @@ -64,10 +85,13 @@ "LabelFree": "Free", "HeaderSelectAudio": "Select Audio", "HeaderSelectSubtitles": "Select Subtitles", + "ButtonMarkForRemoval": "Mark for removal from device", + "ButtonUnmarkForRemoval": "Unmark for removal from device", "LabelDefaultStream": "(Default)", "LabelForcedStream": "(Forced)", "LabelDefaultForcedStream": "(Default\/Forced)", "LabelUnknownLanguage": "Unknown language", + "MessageConfirmSyncJobItemCancellation": "Are you sure you wish to cancel this item?", "ButtonMute": "Mute", "ButtonUnmute": "Unmute", "ButtonStop": "Parar", @@ -191,8 +215,10 @@ "LabelPlayMethodDirectPlay": "Direct Playing", "LabelAudioCodec": "Audio: {0}", "LabelVideoCodec": "Video: {0}", + "LabelLocalAccessUrl": "Local access: {0}", "LabelRemoteAccessUrl": "Remote access: {0}", - "LabelRunningOnPort": "Running on port {0}.", + "LabelRunningOnPort": "Running on http port {0}.", + "LabelRunningOnPorts": "Running on http port {0}, and https port {1}.", "HeaderLatestFromChannel": "Latest from {0}", "ButtonDownload": "Download", "LabelUnknownLanaguage": "Unknown language", @@ -206,6 +232,7 @@ "ButtonRefresh": "Refresh", "LabelCurrentPath": "Current path:", "HeaderSelectMediaPath": "Select Media Path", + "HeaderSelectPath": "Select Path", "ButtonNetwork": "Network", "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.", "HeaderMenu": "Menu", @@ -216,6 +243,7 @@ "ButtonResume": "Resume", "HeaderScenes": "Cenas", "HeaderAudioTracks": "Audio Tracks", + "HeaderLibraries": "Libraries", "HeaderSubtitles": "Subtitles", "HeaderVideoQuality": "Video Quality", "MessageErrorPlayingVideo": "There was an error playing the video.", @@ -581,6 +609,8 @@ "MediaInfoStreamTypeEmbeddedImage": "Embedded Image", "MediaInfoRefFrames": "Ref frames", "TabPlayback": "Playback", + "TabNotifications": "Notifica\u00e7\u00f5es", + "TabExpert": "Expert", "HeaderSelectCustomIntrosPath": "Select Custom Intros Path", "HeaderRateAndReview": "Rate and Review", "HeaderThankYou": "Thank You", @@ -615,6 +645,7 @@ "DashboardTourMobile": "The Media Browser dashboard works great on smartphones and tablets. Manage your server from the palm of your hand anytime, anywhere.", "MessageRefreshQueued": "Refresh queued", "TabDevices": "Devices", + "TabExtras": "Extras", "DeviceLastUsedByUserName": "Last used by {0}", "HeaderDeleteDevice": "Delete Device", "DeleteDeviceConfirmation": "Are you sure you wish to delete this device? It will reappear the next time a user signs in with it.", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json index ba8afb0ad..dd136ff8a 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json @@ -6,6 +6,8 @@ "Administrator": "\u0410\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440", "Password": "\u041f\u0430\u0440\u043e\u043b\u044c", "DeleteImage": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0440\u0438\u0441\u0443\u043d\u043e\u043a", + "MessageThankYouForSupporting": "\u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u0438\u043c \u0437\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 Media Browser.", + "MessagePleaseSupportMediaBrowser": "\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0442\u0435 Media Browser.", "DeleteImageConfirmation": "\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0439 \u0440\u0438\u0441\u0443\u043d\u043e\u043a?", "FileReadCancelled": "\u0427\u0442\u0435\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430 \u0431\u044b\u043b\u043e \u043e\u0442\u043c\u0435\u043d\u0435\u043d\u043e.", "FileNotFound": "\u0424\u0430\u0439\u043b \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d.", @@ -14,12 +16,15 @@ "DeleteUserConfirmation": "\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f?", "PasswordResetHeader": "\u0421\u0431\u0440\u043e\u0441 \u043f\u0430\u0440\u043e\u043b\u044f", "PasswordResetComplete": "\u041f\u0430\u0440\u043e\u043b\u044c \u0431\u044b\u043b \u0441\u0431\u0440\u043e\u0448\u0435\u043d.", + "PinCodeResetComplete": "PIN-\u043a\u043e\u0434 \u0431\u044b\u043b \u0441\u0431\u0440\u043e\u0448\u0435\u043d.", "PasswordResetConfirmation": "\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u0441\u0431\u0440\u043e\u0441\u0438\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c?", + "PinCodeResetConfirmation": "\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u0441\u0431\u0440\u043e\u0441\u0438\u0442\u044c PIN-\u043a\u043e\u0434?", + "HeaderPinCodeReset": "\u0421\u0431\u0440\u043e\u0441 PIN-\u043a\u043e\u0434\u0430", "PasswordSaved": "\u041f\u0430\u0440\u043e\u043b\u044c \u0431\u044b\u043b \u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d.", "PasswordMatchError": "\u041f\u0430\u0440\u043e\u043b\u044c \u0438 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f \u0434\u043e\u043b\u0436\u043d\u044b \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u0442\u044c", "OptionRelease": "\u041e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u0432\u044b\u043f\u0443\u0441\u043a", "OptionBeta": "\u0411\u0435\u0442\u0430-\u0432\u0435\u0440\u0441\u0438\u044f", - "OptionDev": "\u0420\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c\u0430\u044f (\u043d\u0435\u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e)", + "OptionDev": "\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043e\u0447\u043d\u0430\u044f (\u043d\u0435\u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u0430\u044f)", "UninstallPluginHeader": "\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u0430", "UninstallPluginConfirmation": "\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u0443\u0434\u0430\u043b\u0438\u0442\u044c {0}?", "NoPluginConfigurationMessage": "\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u043f\u043b\u0430\u0433\u0438\u043d\u0435 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0438\u043c\u0435\u0435\u0442\u0441\u044f, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c.", @@ -32,6 +37,7 @@ "MessageKeyRemoved": "\u041a\u043b\u044e\u0447 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430 \u0431\u044b\u043b \u0443\u0434\u0430\u043b\u0451\u043d.", "ErrorLaunchingChromecast": "\u041f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 Chromecast. \u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0432\u0430\u0448\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u043e \u043a \u0431\u0435\u0441\u043f\u0440\u043e\u0432\u043e\u0434\u043d\u043e\u0439 \u0441\u0435\u0442\u0438.", "HeaderSearch": "\u041f\u043e\u0438\u0441\u043a", + "ValueDateCreated": "\u0414\u0430\u0442\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f: {0}", "LabelArtist": "\u0418\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c", "LabelMovie": "\u0424\u0438\u043b\u044c\u043c", "LabelMusicVideo": "\u041c\u0443\u0437\u044b\u043a\u0430\u043b\u044c\u043d\u043e\u0435 \u0432\u0438\u0434\u0435\u043e", @@ -42,6 +48,17 @@ "LabelFailed": "(\u043d\u0435\u0443\u0434\u0430\u0447\u043d\u043e)", "ButtonHelp": "\u0421\u043f\u0440\u0430\u0432\u043a\u0430", "ButtonSave": "\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c", + "LabelCollection": "\u041a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f", + "HeaderAddToCollection": "\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438", + "NewCollectionNameExample": "\u041f\u0440\u0438\u043c\u0435\u0440: \u0417\u0432\u0451\u0437\u0434\u043d\u044b\u0435 \u0432\u043e\u0439\u043d\u044b (\u041a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f)", + "OptionSearchForInternetMetadata": "\u0418\u0441\u043a\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 \u0432 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435", + "LabelSelectCollection": "\u0412\u044b\u0431\u043e\u0440 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438:", + "HeaderDevices": "\u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430", + "ButtonScheduledTasks": "\u041f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u041f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u0443", + "MessageItemsAdded": "\u042d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u044b", + "ButtonAddToCollection": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438", + "HeaderSelectCertificatePath": "\u0412\u044b\u0431\u043e\u0440 \u043f\u0443\u0442\u0438 \u043a \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0443", + "ConfirmMessageScheduledTaskButton": "\u042d\u0442\u0430 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043e\u0431\u044b\u0447\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043a\u0430\u043a \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430. \u042d\u0442\u043e \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043e \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u043e\u0442\u0441\u044e\u0434\u0430. \u0427\u0442\u043e\u0431\u044b \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443, \u0441\u043c.:", "HeaderSupporterBenefit": "\u0427\u043b\u0435\u043d\u0441\u0442\u0432\u043e \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043e\u0441\u0442\u0443\u043f \u043a\u043e \u043f\u0440\u0435\u043c\u0438\u0430\u043b\u044c\u043d\u044b\u043c \u043f\u043b\u0430\u0433\u0438\u043d\u0430\u043c, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044e \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u043a\u0430\u043d\u0430\u043b\u043e\u0432 \u0438 \u043c\u043d\u043e\u0433\u043e\u043c\u0443 \u0434\u0440\u0443\u0433\u043e\u043c\u0443. {0}\u0423\u0437\u043d\u0430\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0435{1}.", "HeaderWelcomeToMediaBrowserServerDashboard": "\u041f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u043c \u0432 \u0418\u043d\u0444\u043e\u043f\u0430\u043d\u0435\u043b\u0438 Media Browser", "HeaderWelcomeToMediaBrowserWebClient": "\u0412\u0435\u0431-\u043a\u043b\u0438\u0435\u043d\u0442 Media Browser \u043f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0432\u0430\u0441!", @@ -53,6 +70,10 @@ "HeaderChannelAccess": "\u0414\u043e\u0441\u0442\u0443\u043f \u043a \u043a\u0430\u043d\u0430\u043b\u0430\u043c", "HeaderDeviceAccess": "\u0414\u043e\u0441\u0442\u0443\u043f \u0441 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430", "HeaderSelectDevices": "\u0412\u044b\u0431\u043e\u0440 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430", + "ButtonCancelItem": "\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442", + "ButtonQueueForRetry": "\u0412 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0434\u043b\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u0430", + "ButtonReenable": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e", + "SyncJobItemStatusSyncedMarkForRemoval": "\u041e\u0442\u043c\u0435\u0447\u0435\u043d\u043e \u0434\u043b\u044f \u0438\u0437\u044a\u044f\u0442\u0438\u044f", "LabelAbortedByServerShutdown": "(\u041f\u0440\u0435\u0440\u0432\u0430\u043d\u043e \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u0430)", "LabelScheduledTaskLastRan": "\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u043b\u0430\u0441\u044c {0}, \u0437\u0430\u043d\u044f\u043b\u0430 {1}.", "HeaderDeleteTaskTrigger": "\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u0430 \u0437\u0430\u0434\u0430\u0447\u0438", @@ -64,10 +85,13 @@ "LabelFree": "\u0411\u0435\u0441\u043f\u043b.", "HeaderSelectAudio": "\u0412\u044b\u0431\u043e\u0440 \u0430\u0443\u0434\u0438\u043e", "HeaderSelectSubtitles": "\u0412\u044b\u0431\u043e\u0440 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u043e\u0432", + "ButtonMarkForRemoval": "\u041e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u0434\u043b\u044f \u0438\u0437\u044a\u044f\u0442\u0438\u044f \u0441 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430", + "ButtonUnmarkForRemoval": "\u0420\u0430\u0437\u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u0434\u043b\u044f \u0438\u0437\u044a\u044f\u0442\u0438\u044f \u0441 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430", "LabelDefaultStream": "(\u0423\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u0435)", "LabelForcedStream": "(\u0424\u043e\u0440\u0441-\u044b\u0435)", "LabelDefaultForcedStream": "(\u0423\u043c\u043e\u043b\u0447.\/\u0424\u043e\u0440\u0441-\u044b\u0435)", "LabelUnknownLanguage": "\u041d\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0439 \u044f\u0437\u044b\u043a", + "MessageConfirmSyncJobItemCancellation": "\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u043e\u0442\u043c\u0435\u043d\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442?", "ButtonMute": "\u041e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0437\u0432\u0443\u043a", "ButtonUnmute": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0437\u0432\u0443\u043a", "ButtonStop": "\u041e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c", @@ -191,8 +215,10 @@ "LabelPlayMethodDirectPlay": "\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e", "LabelAudioCodec": "\u0410\u0443\u0434\u0438\u043e: {0}", "LabelVideoCodec": "\u0412\u0438\u0434\u0435\u043e: {0}", + "LabelLocalAccessUrl": "\u041b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0430\u0434\u0440\u0435\u0441: {0}", "LabelRemoteAccessUrl": "\u0412\u043d\u0435\u0448\u043d\u0438\u0439 \u0434\u043e\u0441\u0442\u0443\u043f: {0}", - "LabelRunningOnPort": "\u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 \u043f\u043e\u0440\u0442\u0443 {0}.", + "LabelRunningOnPort": "\u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 HTTP-\u043f\u043e\u0440\u0442\u0443 {0}.", + "LabelRunningOnPorts": "\u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 HTTP-\u043f\u043e\u0440\u0442\u0443 {0} \u0438 HTTPS-\u043f\u043e\u0440\u0442\u0443 {1}.", "HeaderLatestFromChannel": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u0438\u0437 {0}", "ButtonDownload": "\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c", "LabelUnknownLanaguage": "\u041d\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0439 \u044f\u0437\u044b\u043a", @@ -206,6 +232,7 @@ "ButtonRefresh": "\u041f\u043e\u0434\u043d\u043e\u0432\u0438\u0442\u044c", "LabelCurrentPath": "\u0422\u0435\u043a\u0443\u0449\u0438\u0439 \u043f\u0443\u0442\u044c:", "HeaderSelectMediaPath": "\u0412\u044b\u0431\u043e\u0440 \u043f\u0443\u0442\u0438 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445", + "HeaderSelectPath": "\u0412\u044b\u0431\u043e\u0440 \u043f\u0443\u0442\u0438", "ButtonNetwork": "\u0421\u0435\u0442\u044c", "MessageDirectoryPickerInstruction": "\u0421\u0435\u0442\u0435\u0432\u044b\u0435 \u043f\u0443\u0442\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0432\u0432\u0435\u0441\u0442\u0438 \u0432\u0440\u0443\u0447\u043d\u0443\u044e, \u0432 \u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u043f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043a\u043d\u043e\u043f\u043a\u0438 \u00ab\u0421\u0435\u0442\u044c\u00bb \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0441\u0431\u043e\u0439 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: {0} \u0438\u043b\u0438 {1}.", "HeaderMenu": "\u041c\u0435\u043d\u044e", @@ -216,6 +243,7 @@ "ButtonResume": "\u0412\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c", "HeaderScenes": "\u0421\u0446\u0435\u043d\u044b", "HeaderAudioTracks": "\u0410\u0443\u0434\u0438\u043e\u0434\u043e\u0440\u043e\u0436\u043a\u0438", + "HeaderLibraries": "\u041c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438", "HeaderSubtitles": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u044b", "HeaderVideoQuality": "\u041a\u0430\u0447\u0435\u0441\u0442\u0432\u043e \u0432\u0438\u0434\u0435\u043e", "MessageErrorPlayingVideo": "\u041f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0438 \u0432\u0438\u0434\u0435\u043e.", @@ -225,7 +253,7 @@ "ButtonReports": "\u041e\u0442\u0447\u0451\u0442\u044b", "ButtonMetadataManager": "\u0414\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445", "HeaderTime": "\u0412\u0440\u0435\u043c\u044f", - "HeaderName": "\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435", + "HeaderName": "\u0418\u043c\u044f (\u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435)", "HeaderAlbum": "\u0410\u043b\u044c\u0431\u043e\u043c", "HeaderAlbumArtist": "\u0410\u043b\u044c\u0431\u043e\u043c\u043d\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c", "HeaderArtist": "\u0418\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c", @@ -324,7 +352,7 @@ "TabLiveTV": "\u0422\u0412-\u044d\u0444\u0438\u0440", "TabAutoOrganize": "\u0410\u0432\u0442\u043e\u0440\u0435\u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044f", "TabPlugins": "\u041f\u043b\u0430\u0433\u0438\u043d\u044b", - "TabAdvanced": "\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e", + "TabAdvanced": "\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u043e\u0435", "TabHelp": "\u0421\u043f\u0440\u0430\u0432\u043a\u0430", "TabScheduledTasks": "\u041f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a", "ButtonFullscreen": "\u041f\u043e\u043b\u043d\u044b\u0439 \u044d\u043a\u0440\u0430\u043d", @@ -349,16 +377,16 @@ "ButtonViewSeriesRecording": "\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0437\u0430\u043f\u0438\u0441\u044c \u0441\u0435\u0440\u0438\u0430\u043b\u0430", "ValueOriginalAirDate": "\u0414\u0430\u0442\u0430 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u044d\u0444\u0438\u0440\u0430: {0}", "ButtonRemoveFromPlaylist": "\u0418\u0437\u044a\u044f\u0442\u044c \u0438\u0437 \u0441\u043f\u0438\u0441\u043a\u0430 \u0432\u043e\u0441\u043f\u0440-\u0438\u044f", - "HeaderSpecials": "\u0421\u043f\u0435\u0446\u044d\u043f\u0438\u0437\u043e\u0434\u044b", + "HeaderSpecials": "\u0421\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0435", "HeaderTrailers": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440\u044b", "HeaderAudio": "\u0410\u0443\u0434\u0438\u043e", - "HeaderResolution": "\u0420\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435", + "HeaderResolution": "\u0420\u0430\u0437\u0440-\u0438\u0435", "HeaderVideo": "\u0412\u0438\u0434\u0435\u043e", - "HeaderRuntime": "\u0414\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c", - "HeaderCommunityRating": "\u041e\u0431\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u0430\u044f \u043e\u0446\u0435\u043d\u043a\u0430", - "HeaderParentalRating": "\u0412\u043e\u0437\u0440\u0430\u0441\u0442\u043d\u0430\u044f \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f", + "HeaderRuntime": "\u0414\u043b\u0438\u0442-c\u0442\u044c", + "HeaderCommunityRating": "\u041e\u0431\u0449-\u0430\u044f \u043e\u0446\u0435\u043d\u043a\u0430", + "HeaderParentalRating": "\u0412\u043e\u0437\u0440-\u0430\u044f \u043a\u0430\u0442-\u0438\u044f", "HeaderReleaseDate": "\u0414\u0430\u0442\u0430 \u0432\u044b\u043f\u0443\u0441\u043a\u0430", - "HeaderDateAdded": "\u0414\u0430\u0442\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f", + "HeaderDateAdded": "\u0414\u0430\u0442\u0430 \u0434\u043e\u0431-\u0438\u044f", "HeaderSeries": "\u0421\u0435\u0440\u0438\u0430\u043b\u044b", "HeaderSeason": "\u0421\u0435\u0437\u043e\u043d", "HeaderSeasonNumber": "\u041d\u043e\u043c\u0435\u0440 \u0441\u0435\u0437\u043e\u043d\u0430", @@ -581,6 +609,8 @@ "MediaInfoStreamTypeEmbeddedImage": "\u0412\u043d\u0435\u0434\u0440\u0451\u043d\u043d\u044b\u0439 \u0440\u0438\u0441\u0443\u043d\u043e\u043a", "MediaInfoRefFrames": "\u041e\u043f\u043e\u0440\u043d\u044b\u0435 \u043a\u0430\u0434\u0440\u044b", "TabPlayback": "\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435", + "TabNotifications": "\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f", + "TabExpert": "\u0414\u043b\u044f \u043e\u043f\u044b\u0442\u043d\u044b\u0445", "HeaderSelectCustomIntrosPath": "\u0412\u044b\u0431\u043e\u0440 \u043f\u0443\u0442\u0438 \u043a \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c \u0437\u0430\u0441\u0442\u0430\u0432\u043a\u0430\u043c", "HeaderRateAndReview": "\u041e\u0446\u0435\u043d\u043a\u0430 \u0438 \u043e\u0442\u0437\u044b\u0432", "HeaderThankYou": "\u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u0438\u043c \u0432\u0430\u0441", @@ -615,6 +645,7 @@ "DashboardTourMobile": "\u0418\u043d\u0444\u043e\u043f\u0430\u043d\u0435\u043b\u044c Media Browser \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043e\u0442\u043b\u0438\u0447\u043d\u043e \u043d\u0430 \u0441\u043c\u0430\u0440\u0442\u0444\u043e\u043d\u0430\u0445 \u0438 \u043f\u043b\u0430\u043d\u0448\u0435\u0442\u0430\u0445. \u0423\u043f\u0440\u0430\u0432\u043b\u044f\u0439\u0442\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u0441 \u0432\u0430\u0448\u0435\u0439 \u043b\u0430\u0434\u043e\u043d\u0438 \u0432 \u043b\u044e\u0431\u043e\u0435 \u0432\u0440\u0435\u043c\u044f, \u0432 \u043b\u044e\u0431\u043e\u043c \u043c\u0435\u0441\u0442\u0435.", "MessageRefreshQueued": "\u041f\u043e\u0434\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u0438", "TabDevices": "\u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430", + "TabExtras": "\u0412 \u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435", "DeviceLastUsedByUserName": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435: {0}", "HeaderDeleteDevice": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e", "DeleteDeviceConfirmation": "\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u043e\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e? \u041e\u043d\u043e \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u0441\u043d\u043e\u0432\u0430 \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0440\u0430\u0437, \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u043e\u0439\u0434\u0451\u0442 \u0441 \u043d\u0435\u0433\u043e.", @@ -626,7 +657,7 @@ "ButtonParentalControl": "\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435\u043c", "HeaderInvitationSent": "\u041f\u0440\u0438\u0433\u043b\u0430\u0448\u0435\u043d\u0438\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043e", "MessageInvitationSentToUser": "\u042d-\u043f\u043e\u0447\u0442\u0430 \u0431\u044b\u043b\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0430 \u043a {0}, \u0441 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u043f\u0440\u0438\u043d\u044f\u0442\u044c \u0432\u0430\u0448\u0435 \u043f\u0440\u0438\u0433\u043b\u0430\u0448\u0435\u043d\u0438\u0435 \u043a \u043e\u0431\u0449\u0435\u043c\u0443 \u0434\u043e\u0441\u0442\u0443\u043f\u0443.", - "MessageInvitationSentToNewUser": "\u042d-\u043f\u043e\u0447\u0442\u0430 \u0431\u044b\u043b\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0430 \u043a {0}, \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044f \u0438\u043c \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 Media Browser.", + "MessageInvitationSentToNewUser": "\u042d-\u043f\u043e\u0447\u0442\u0430 \u0431\u044b\u043b\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0430 \u043a {0}, \u0441 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0438\u043c \u0432 Media Browser.", "HeaderConnectionFailure": "\u0421\u0431\u043e\u0439 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f", "MessageUnableToConnectToServer": "\u041c\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u0434\u0441\u043e\u0435\u0434\u0438\u043d\u0438\u0442\u044c\u0441\u044f \u043a \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u043c\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u0432 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442. \u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u043e\u043d \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0435 \u043f\u043e\u043f\u044b\u0442\u043a\u0443 \u043f\u043e\u0437\u0436\u0435.", "ButtonSelectServer": "\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json index 5ab860c6f..3d2f9d088 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json @@ -6,6 +6,8 @@ "Administrator": "Administrat\u00f6r", "Password": "L\u00f6senord", "DeleteImage": "Ta bort bild", + "MessageThankYouForSupporting": "Thank you for supporting Media Browser.", + "MessagePleaseSupportMediaBrowser": "Please support Media Browser.", "DeleteImageConfirmation": "\u00c4r du s\u00e4ker p\u00e5 att du vill ta bort den h\u00e4r bilden?", "FileReadCancelled": "Inl\u00e4sningen av filen har avbrutits.", "FileNotFound": "Kan inte hitta filen.", @@ -14,7 +16,10 @@ "DeleteUserConfirmation": "\u00c4r du s\u00e4ker p\u00e5 att du vill radera denna anv\u00e4ndare?", "PasswordResetHeader": "\u00c5terst\u00e4ll l\u00f6senordet", "PasswordResetComplete": "L\u00f6senordet har \u00e5terst\u00e4llts.", + "PinCodeResetComplete": "The pin code has been reset.", "PasswordResetConfirmation": "\u00c4r du s\u00e4ker p\u00e5 att du vill \u00e5terst\u00e4lla l\u00f6senordet?", + "PinCodeResetConfirmation": "Are you sure you wish to reset the pin code?", + "HeaderPinCodeReset": "Reset Pin Code", "PasswordSaved": "L\u00f6senordet har sparats.", "PasswordMatchError": "L\u00f6senordet och bekr\u00e4ftelsen m\u00e5ste \u00f6verensst\u00e4mma.", "OptionRelease": "Officiell version", @@ -32,6 +37,7 @@ "MessageKeyRemoved": "Tack. Din donationskod har raderats.", "ErrorLaunchingChromecast": "Det gick inte att starta Chromecast. Kontrollera att enheten \u00e4r ansluten till det tr\u00e5dl\u00f6sa n\u00e4tverket.", "HeaderSearch": "S\u00f6k", + "ValueDateCreated": "Date created: {0}", "LabelArtist": "Artist", "LabelMovie": "Film", "LabelMusicVideo": "Musikvideo", @@ -40,8 +46,19 @@ "LabelStopping": "Avbryter", "LabelCancelled": "(avbr\u00f6ts)", "LabelFailed": "(misslyckades)", - "ButtonHelp": "Help", + "ButtonHelp": "Hj\u00e4lp", "ButtonSave": "Spara", + "LabelCollection": "Collection", + "HeaderAddToCollection": "L\u00e4gg till samling", + "NewCollectionNameExample": "Exemple: Star Wars-samling", + "OptionSearchForInternetMetadata": "S\u00f6k p\u00e5 internet efter grafik och metadata", + "LabelSelectCollection": "V\u00e4lj samling:", + "HeaderDevices": "Devices", + "ButtonScheduledTasks": "Scheduled tasks", + "MessageItemsAdded": "Items added", + "ButtonAddToCollection": "Add to collection", + "HeaderSelectCertificatePath": "Select Certificate Path", + "ConfirmMessageScheduledTaskButton": "This operation normally runs automatically as a scheduled task. It can also be run manually here. To configure the scheduled task, see:", "HeaderSupporterBenefit": "A supporter membership provides additional benefits such as access to premium plugins, internet channel content, and more. {0}Learn more{1}.", "HeaderWelcomeToMediaBrowserServerDashboard": "V\u00e4lkommen till Media Browsers kontrollpanel", "HeaderWelcomeToMediaBrowserWebClient": "V\u00e4lkommen till Media Browsers webbklient", @@ -51,8 +68,12 @@ "MessageNoSyncJobsFound": "No sync jobs found. Create sync jobs using the Sync buttons found throughout the web interface.", "HeaderLibraryAccess": "Library Access", "HeaderChannelAccess": "Channel Access", - "HeaderDeviceAccess": "Device Access", - "HeaderSelectDevices": "Select Devices", + "HeaderDeviceAccess": "Enhets\u00e5tkomst", + "HeaderSelectDevices": "V\u00e4lj Enheter", + "ButtonCancelItem": "Cancel item", + "ButtonQueueForRetry": "Queue for retry", + "ButtonReenable": "Re-enable", + "SyncJobItemStatusSyncedMarkForRemoval": "Marked for removal", "LabelAbortedByServerShutdown": "(avbr\u00f6ts eftersom servern st\u00e4ngdes av)", "LabelScheduledTaskLastRan": "Senast k\u00f6rd {0}, tog {1}", "HeaderDeleteTaskTrigger": "Ta bort aktivitetsutl\u00f6sare", @@ -64,10 +85,13 @@ "LabelFree": "Gratis", "HeaderSelectAudio": "V\u00e4lj ljudsp\u00e5r", "HeaderSelectSubtitles": "V\u00e4lj undertexter", + "ButtonMarkForRemoval": "Mark for removal from device", + "ButtonUnmarkForRemoval": "Unmark for removal from device", "LabelDefaultStream": "(f\u00f6rvalda)", "LabelForcedStream": "(tvingade)", "LabelDefaultForcedStream": "(f\u00f6rvalda\/tvingade)", "LabelUnknownLanguage": "Ok\u00e4nt spr\u00e5k", + "MessageConfirmSyncJobItemCancellation": "Are you sure you wish to cancel this item?", "ButtonMute": "Tyst", "ButtonUnmute": "Muting av", "ButtonStop": "Stopp", @@ -191,8 +215,10 @@ "LabelPlayMethodDirectPlay": "Direktuppspelning", "LabelAudioCodec": "Ljud: {0}", "LabelVideoCodec": "Video: {0}", + "LabelLocalAccessUrl": "Local access: {0}", "LabelRemoteAccessUrl": "Fj\u00e4rranslutning: {0}", - "LabelRunningOnPort": "Anv\u00e4nder port {0}.", + "LabelRunningOnPort": "Running on http port {0}.", + "LabelRunningOnPorts": "Running on http port {0}, and https port {1}.", "HeaderLatestFromChannel": "Senaste fr\u00e5n {0}", "ButtonDownload": "Ladda ned", "LabelUnknownLanaguage": "Ok\u00e4nt spr\u00e5k", @@ -206,6 +232,7 @@ "ButtonRefresh": "Uppdatera", "LabelCurrentPath": "Aktuell s\u00f6kv\u00e4g:", "HeaderSelectMediaPath": "V\u00e4lj s\u00f6kv\u00e4g till media", + "HeaderSelectPath": "Select Path", "ButtonNetwork": "N\u00e4tverk", "MessageDirectoryPickerInstruction": "N\u00e4tverkss\u00f6kv\u00e4gar kan anges manuellt om \"N\u00e4tverk\" inte hittar dina enheter. T ex {0} eller {1}.", "HeaderMenu": "Meny", @@ -216,6 +243,7 @@ "ButtonResume": "\u00c5teruppta", "HeaderScenes": "Kapitel", "HeaderAudioTracks": "Ljudsp\u00e5r", + "HeaderLibraries": "Libraries", "HeaderSubtitles": "Undertexter", "HeaderVideoQuality": "Videokvalitet", "MessageErrorPlayingVideo": "Ett fel uppstod vid uppspelning av videon.", @@ -272,7 +300,7 @@ "OptionOff": "Av", "OptionOn": "P\u00e5", "ButtonSettings": "Inst\u00e4llningar", - "ButtonUninstall": "Uninstall", + "ButtonUninstall": "Avinstallera", "HeaderFields": "F\u00e4lt", "HeaderFieldsHelp": "Dra ett f\u00e4lt till \"av\" f\u00f6r att l\u00e5sa det och f\u00f6rhindra att dess data \u00e4ndras.", "HeaderLiveTV": "Live-TV", @@ -581,6 +609,8 @@ "MediaInfoStreamTypeEmbeddedImage": "Infogad bild", "MediaInfoRefFrames": "Referensbildrutor", "TabPlayback": "Uppspelning", + "TabNotifications": "Meddelanden", + "TabExpert": "Expert", "HeaderSelectCustomIntrosPath": "V\u00e4lj s\u00f6kv\u00e4g f\u00f6r egna vinjetter", "HeaderRateAndReview": "Betygs\u00e4tt och rescensera", "HeaderThankYou": "Tack", @@ -615,6 +645,7 @@ "DashboardTourMobile": "Media Browsers kontrollpanel fungerar utm\u00e4rkt p\u00e5 smarta telefoner och surfplattor. Administrera din server n\u00e4r som helst, varifr\u00e5n som helst.", "MessageRefreshQueued": "Uppdatering k\u00f6ad", "TabDevices": "Enheter", + "TabExtras": "Extras", "DeviceLastUsedByUserName": "Senast anv\u00e4nd av {0}", "HeaderDeleteDevice": "Ta bort enhet", "DeleteDeviceConfirmation": "\u00c4r du s\u00e4ker p\u00e5 att du vill ta bort den h\u00e4r enheten? Den kommer att dyka upp igen n\u00e4sta g\u00e5ng en anv\u00e4ndare kopplar upp sig med den.", @@ -635,7 +666,7 @@ "DefaultErrorMessage": "There was an error processing the request. Please try again later.", "ButtonAccept": "Accept", "ButtonReject": "Reject", - "HeaderForgotPassword": "Forgot Password", + "HeaderForgotPassword": "Gl\u00f6mt L\u00f6senord", "MessageContactAdminToResetPassword": "Please contact your system administrator to reset your password.", "MessageForgotPasswordInNetworkRequired": "Please try again within your home network to initiate the password reset process.", "MessageForgotPasswordFileCreated": "The following file has been created on your server and contains instructions on how to proceed:", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/tr.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/tr.json index 07720a75a..3b9a34fe3 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/tr.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/tr.json @@ -6,6 +6,8 @@ "Administrator": "Y\u00f6netici", "Password": "Sifre", "DeleteImage": "Resmi Sil", + "MessageThankYouForSupporting": "Thank you for supporting Media Browser.", + "MessagePleaseSupportMediaBrowser": "Please support Media Browser.", "DeleteImageConfirmation": "Bu G\u00f6r\u00fcnt\u00fcy\u00fc Silmek \u0130stedi\u011finizden Eminmisiniz?", "FileReadCancelled": "Dosya Okuma \u0130ptal Edildi", "FileNotFound": "Dosya Bulunamad\u0131", @@ -14,7 +16,10 @@ "DeleteUserConfirmation": "Are you sure you wish to delete this user?", "PasswordResetHeader": "Sifre S\u0131f\u0131rland\u0131", "PasswordResetComplete": "Parolan\u0131z S\u0131f\u0131rlanm\u0131st\u0131r.", + "PinCodeResetComplete": "The pin code has been reset.", "PasswordResetConfirmation": "Sifrenizi S\u0131f\u0131rlamak \u0130stediginizden Eminmisiniz?", + "PinCodeResetConfirmation": "Are you sure you wish to reset the pin code?", + "HeaderPinCodeReset": "Reset Pin Code", "PasswordSaved": "Sifre Kaydedildi", "PasswordMatchError": "Parola ve Sifre Eslesmelidir.", "OptionRelease": "Resmi Yay\u0131n", @@ -32,6 +37,7 @@ "MessageKeyRemoved": "Thank you. Your supporter key has been removed.", "ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.", "HeaderSearch": "Search", + "ValueDateCreated": "Date created: {0}", "LabelArtist": "Artist", "LabelMovie": "Movie", "LabelMusicVideo": "Music Video", @@ -42,6 +48,17 @@ "LabelFailed": "(failed)", "ButtonHelp": "Help", "ButtonSave": "Kay\u0131t", + "LabelCollection": "Collection", + "HeaderAddToCollection": "Add to Collection", + "NewCollectionNameExample": "Example: Star Wars Collection", + "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata", + "LabelSelectCollection": "Select collection:", + "HeaderDevices": "Devices", + "ButtonScheduledTasks": "Scheduled tasks", + "MessageItemsAdded": "Items added", + "ButtonAddToCollection": "Add to collection", + "HeaderSelectCertificatePath": "Select Certificate Path", + "ConfirmMessageScheduledTaskButton": "This operation normally runs automatically as a scheduled task. It can also be run manually here. To configure the scheduled task, see:", "HeaderSupporterBenefit": "A supporter membership provides additional benefits such as access to premium plugins, internet channel content, and more. {0}Learn more{1}.", "HeaderWelcomeToMediaBrowserServerDashboard": "Welcome to the Media Browser Dashboard", "HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client", @@ -53,6 +70,10 @@ "HeaderChannelAccess": "Channel Access", "HeaderDeviceAccess": "Device Access", "HeaderSelectDevices": "Select Devices", + "ButtonCancelItem": "Cancel item", + "ButtonQueueForRetry": "Queue for retry", + "ButtonReenable": "Re-enable", + "SyncJobItemStatusSyncedMarkForRemoval": "Marked for removal", "LabelAbortedByServerShutdown": "(Aborted by server shutdown)", "LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.", "HeaderDeleteTaskTrigger": "Delete Task Trigger", @@ -64,10 +85,13 @@ "LabelFree": "Free", "HeaderSelectAudio": "Select Audio", "HeaderSelectSubtitles": "Select Subtitles", + "ButtonMarkForRemoval": "Mark for removal from device", + "ButtonUnmarkForRemoval": "Unmark for removal from device", "LabelDefaultStream": "(Default)", "LabelForcedStream": "(Forced)", "LabelDefaultForcedStream": "(Default\/Forced)", "LabelUnknownLanguage": "Unknown language", + "MessageConfirmSyncJobItemCancellation": "Are you sure you wish to cancel this item?", "ButtonMute": "Sessiz", "ButtonUnmute": "Unmute", "ButtonStop": "Durdur", @@ -191,8 +215,10 @@ "LabelPlayMethodDirectPlay": "Direct Playing", "LabelAudioCodec": "Audio: {0}", "LabelVideoCodec": "Video: {0}", + "LabelLocalAccessUrl": "Local access: {0}", "LabelRemoteAccessUrl": "Remote access: {0}", - "LabelRunningOnPort": "Running on port {0}.", + "LabelRunningOnPort": "Running on http port {0}.", + "LabelRunningOnPorts": "Running on http port {0}, and https port {1}.", "HeaderLatestFromChannel": "Latest from {0}", "ButtonDownload": "Download", "LabelUnknownLanaguage": "Unknown language", @@ -206,6 +232,7 @@ "ButtonRefresh": "Refresh", "LabelCurrentPath": "Current path:", "HeaderSelectMediaPath": "Select Media Path", + "HeaderSelectPath": "Select Path", "ButtonNetwork": "Network", "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.", "HeaderMenu": "Menu", @@ -216,6 +243,7 @@ "ButtonResume": "Resume", "HeaderScenes": "Diziler", "HeaderAudioTracks": "Audio Tracks", + "HeaderLibraries": "Libraries", "HeaderSubtitles": "Subtitles", "HeaderVideoQuality": "Video Quality", "MessageErrorPlayingVideo": "There was an error playing the video.", @@ -581,6 +609,8 @@ "MediaInfoStreamTypeEmbeddedImage": "Embedded Image", "MediaInfoRefFrames": "Ref frames", "TabPlayback": "Playback", + "TabNotifications": "Notifications", + "TabExpert": "Expert", "HeaderSelectCustomIntrosPath": "Select Custom Intros Path", "HeaderRateAndReview": "Rate and Review", "HeaderThankYou": "Thank You", @@ -615,6 +645,7 @@ "DashboardTourMobile": "The Media Browser dashboard works great on smartphones and tablets. Manage your server from the palm of your hand anytime, anywhere.", "MessageRefreshQueued": "Refresh queued", "TabDevices": "Devices", + "TabExtras": "Extras", "DeviceLastUsedByUserName": "Last used by {0}", "HeaderDeleteDevice": "Delete Device", "DeleteDeviceConfirmation": "Are you sure you wish to delete this device? It will reappear the next time a user signs in with it.", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/uk.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/uk.json index 0e60ba4c0..74286666d 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/uk.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/uk.json @@ -6,15 +6,20 @@ "Administrator": "Administrator", "Password": "Password", "DeleteImage": "Delete Image", + "MessageThankYouForSupporting": "Thank you for supporting Media Browser.", + "MessagePleaseSupportMediaBrowser": "Please support Media Browser.", "DeleteImageConfirmation": "Are you sure you wish to delete this image?", "FileReadCancelled": "The file read has been canceled.", "FileNotFound": "File not found.", "FileReadError": "An error occurred while reading the file.", "DeleteUser": "Delete User", "DeleteUserConfirmation": "Are you sure you wish to delete this user?", - "PasswordResetHeader": "Password Reset", + "PasswordResetHeader": "Reset Password", "PasswordResetComplete": "The password has been reset.", + "PinCodeResetComplete": "The pin code has been reset.", "PasswordResetConfirmation": "Are you sure you wish to reset the password?", + "PinCodeResetConfirmation": "Are you sure you wish to reset the pin code?", + "HeaderPinCodeReset": "Reset Pin Code", "PasswordSaved": "Password saved.", "PasswordMatchError": "Password and password confirmation must match.", "OptionRelease": "Official Release", @@ -32,16 +37,28 @@ "MessageKeyRemoved": "Thank you. Your supporter key has been removed.", "ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.", "HeaderSearch": "Search", + "ValueDateCreated": "Date created: {0}", "LabelArtist": "Artist", "LabelMovie": "Movie", "LabelMusicVideo": "Music Video", "LabelEpisode": "Episode", - "LabelSeries": "Series", + "LabelSeries": "\u0421\u0435\u0440\u0456\u0457", "LabelStopping": "Stopping", "LabelCancelled": "(cancelled)", "LabelFailed": "(failed)", "ButtonHelp": "Help", - "ButtonSave": "Save", + "ButtonSave": "\u0417\u0431\u0435\u0440\u0456\u0433\u0442\u0438", + "LabelCollection": "Collection", + "HeaderAddToCollection": "\u0414\u043e\u0434\u0430\u0442\u0438 \u0434\u043e \u043a\u043e\u043b\u0435\u043a\u0446\u0456\u0457", + "NewCollectionNameExample": "Example: Star Wars Collection", + "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata", + "LabelSelectCollection": "Select collection:", + "HeaderDevices": "Devices", + "ButtonScheduledTasks": "Scheduled tasks", + "MessageItemsAdded": "Items added", + "ButtonAddToCollection": "Add to collection", + "HeaderSelectCertificatePath": "Select Certificate Path", + "ConfirmMessageScheduledTaskButton": "This operation normally runs automatically as a scheduled task. It can also be run manually here. To configure the scheduled task, see:", "HeaderSupporterBenefit": "A supporter membership provides additional benefits such as access to premium plugins, internet channel content, and more. {0}Learn more{1}.", "HeaderWelcomeToMediaBrowserServerDashboard": "Welcome to the Media Browser Dashboard", "HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client", @@ -53,6 +70,10 @@ "HeaderChannelAccess": "Channel Access", "HeaderDeviceAccess": "Device Access", "HeaderSelectDevices": "Select Devices", + "ButtonCancelItem": "Cancel item", + "ButtonQueueForRetry": "Queue for retry", + "ButtonReenable": "Re-enable", + "SyncJobItemStatusSyncedMarkForRemoval": "Marked for removal", "LabelAbortedByServerShutdown": "(Aborted by server shutdown)", "LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.", "HeaderDeleteTaskTrigger": "Delete Task Trigger", @@ -64,21 +85,24 @@ "LabelFree": "Free", "HeaderSelectAudio": "Select Audio", "HeaderSelectSubtitles": "Select Subtitles", + "ButtonMarkForRemoval": "Mark for removal from device", + "ButtonUnmarkForRemoval": "Unmark for removal from device", "LabelDefaultStream": "(Default)", "LabelForcedStream": "(Forced)", "LabelDefaultForcedStream": "(Default\/Forced)", "LabelUnknownLanguage": "Unknown language", + "MessageConfirmSyncJobItemCancellation": "Are you sure you wish to cancel this item?", "ButtonMute": "Mute", "ButtonUnmute": "Unmute", "ButtonStop": "Stop", - "ButtonNextTrack": "Next Track", + "ButtonNextTrack": "\u041d\u0430\u0441\u0442\u0443\u043f\u043d\u0438\u0439 \u0437\u0430\u043f\u0438\u0441", "ButtonPause": "Pause", "ButtonPlay": "Play", "ButtonEdit": "Edit", "ButtonQueue": "Queue", "ButtonPlayTrailer": "Play trailer", "ButtonPlaylist": "Playlist", - "ButtonPreviousTrack": "Previous Track", + "ButtonPreviousTrack": "\u041f\u043e\u043f\u0435\u0440\u0435\u0434\u043d\u0456\u0439 \u0437\u0430\u043f\u0438\u0441", "LabelEnabled": "Enabled", "LabelDisabled": "Disabled", "ButtonMoreInformation": "More Information", @@ -191,8 +215,10 @@ "LabelPlayMethodDirectPlay": "Direct Playing", "LabelAudioCodec": "Audio: {0}", "LabelVideoCodec": "Video: {0}", + "LabelLocalAccessUrl": "Local access: {0}", "LabelRemoteAccessUrl": "Remote access: {0}", - "LabelRunningOnPort": "Running on port {0}.", + "LabelRunningOnPort": "Running on http port {0}.", + "LabelRunningOnPorts": "Running on http port {0}, and https port {1}.", "HeaderLatestFromChannel": "Latest from {0}", "ButtonDownload": "Download", "LabelUnknownLanaguage": "Unknown language", @@ -202,10 +228,11 @@ "ButtonRemoteControl": "Remote Control", "HeaderLatestTvRecordings": "Latest Recordings", "ButtonOk": "Ok", - "ButtonCancel": "Cancel", + "ButtonCancel": "\u0421\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438", "ButtonRefresh": "Refresh", "LabelCurrentPath": "Current path:", "HeaderSelectMediaPath": "Select Media Path", + "HeaderSelectPath": "Select Path", "ButtonNetwork": "Network", "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.", "HeaderMenu": "Menu", @@ -216,6 +243,7 @@ "ButtonResume": "Resume", "HeaderScenes": "Scenes", "HeaderAudioTracks": "Audio Tracks", + "HeaderLibraries": "Libraries", "HeaderSubtitles": "Subtitles", "HeaderVideoQuality": "Video Quality", "MessageErrorPlayingVideo": "There was an error playing the video.", @@ -319,7 +347,7 @@ "TabServer": "Server", "TabUsers": "Users", "TabLibrary": "Library", - "TabMetadata": "Metadata", + "TabMetadata": "\u041c\u0435\u0442\u0430\u0434\u0430\u043d\u0456", "TabDLNA": "DLNA", "TabLiveTV": "Live TV", "TabAutoOrganize": "Auto-Organize", @@ -335,7 +363,7 @@ "HeaderNotifications": "Notifications", "HeaderSelectPlayer": "Select Player:", "ButtonSelect": "Select", - "ButtonNew": "New", + "ButtonNew": "\u041d\u043e\u0432\u0438\u0439", "MessageInternetExplorerWebm": "For best results with Internet Explorer please install the WebM playback plugin.", "HeaderVideoError": "Video Error", "ButtonAddToPlaylist": "Add to playlist", @@ -351,9 +379,9 @@ "ButtonRemoveFromPlaylist": "Remove from playlist", "HeaderSpecials": "Specials", "HeaderTrailers": "Trailers", - "HeaderAudio": "Audio", + "HeaderAudio": "\u0410\u0443\u0434\u0456\u043e", "HeaderResolution": "Resolution", - "HeaderVideo": "Video", + "HeaderVideo": "\u0412\u0456\u0434\u0435\u043e", "HeaderRuntime": "Runtime", "HeaderCommunityRating": "Community rating", "HeaderParentalRating": "Parental rating", @@ -430,17 +458,17 @@ "LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.", "FolderTypeUnset": "Unset (mixed content)", "FolderTypeMovies": "Movies", - "FolderTypeMusic": "Music", + "FolderTypeMusic": "\u041c\u0443\u0437\u0438\u043a\u0430", "FolderTypeAdultVideos": "Adult videos", - "FolderTypePhotos": "Photos", + "FolderTypePhotos": "\u0421\u0432\u0456\u0442\u043b\u0438\u043d\u0438", "FolderTypeMusicVideos": "Music videos", "FolderTypeHomeVideos": "Home videos", - "FolderTypeGames": "Games", - "FolderTypeBooks": "Books", - "FolderTypeTvShows": "TV", + "FolderTypeGames": "\u0406\u0433\u0440\u0438", + "FolderTypeBooks": "\u041a\u043d\u0438\u0433\u0438", + "FolderTypeTvShows": "\u0422\u0411", "TabMovies": "Movies", "TabSeries": "Series", - "TabEpisodes": "Episodes", + "TabEpisodes": "\u0415\u043f\u0456\u0437\u043e\u0434\u0438", "TabTrailers": "Trailers", "TabGames": "Games", "TabAlbums": "Albums", @@ -543,7 +571,7 @@ "HeaderAlbums": "Albums", "HeaderGames": "Games", "HeaderBooks": "Books", - "HeaderEpisodes": "Episodes", + "HeaderEpisodes": "\u0415\u043f\u0456\u0437\u043e\u0434\u0438", "HeaderSeasons": "Seasons", "HeaderTracks": "Tracks", "HeaderItems": "Items", @@ -581,6 +609,8 @@ "MediaInfoStreamTypeEmbeddedImage": "Embedded Image", "MediaInfoRefFrames": "Ref frames", "TabPlayback": "Playback", + "TabNotifications": "\u041f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f", + "TabExpert": "Expert", "HeaderSelectCustomIntrosPath": "Select Custom Intros Path", "HeaderRateAndReview": "Rate and Review", "HeaderThankYou": "Thank You", @@ -615,6 +645,7 @@ "DashboardTourMobile": "The Media Browser dashboard works great on smartphones and tablets. Manage your server from the palm of your hand anytime, anywhere.", "MessageRefreshQueued": "Refresh queued", "TabDevices": "Devices", + "TabExtras": "Extras", "DeviceLastUsedByUserName": "Last used by {0}", "HeaderDeleteDevice": "Delete Device", "DeleteDeviceConfirmation": "Are you sure you wish to delete this device? It will reappear the next time a user signs in with it.", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/vi.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/vi.json index 1c22b1963..532953082 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/vi.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/vi.json @@ -6,6 +6,8 @@ "Administrator": "Ng\u01b0\u1eddi qu\u1ea3n tr\u1ecb", "Password": "M\u1eadt kh\u1ea9u", "DeleteImage": "X\u00f3a h\u00ecnh \u1ea3nh", + "MessageThankYouForSupporting": "Thank you for supporting Media Browser.", + "MessagePleaseSupportMediaBrowser": "Please support Media Browser.", "DeleteImageConfirmation": "B\u1ea1n c\u00f3 ch\u1eafc mu\u1ed1n x\u00f3a h\u00ecnh \u1ea3nh n\u00e0y?", "FileReadCancelled": "T\u1ec7p tin \u0111\u1ecdc \u0111\u00e3 b\u1ecb h\u1ee7y.", "FileNotFound": "Kh\u00f4ng t\u00ecm th\u1ea5y t\u1ec7p tin.", @@ -14,7 +16,10 @@ "DeleteUserConfirmation": "Are you sure you wish to delete this user?", "PasswordResetHeader": "Reset M\u1eadt kh\u1ea9u", "PasswordResetComplete": "M\u1eadt kh\u1ea9u \u0111\u00e3 \u0111\u01b0\u1ee3c reset", + "PinCodeResetComplete": "The pin code has been reset.", "PasswordResetConfirmation": "B\u1ea1n c\u00f3 ch\u1eafc mu\u1ed1n reset m\u1eadt kh\u1ea9u?", + "PinCodeResetConfirmation": "Are you sure you wish to reset the pin code?", + "HeaderPinCodeReset": "Reset Pin Code", "PasswordSaved": "M\u1eadt kh\u1ea9u \u0111\u00e3 \u0111\u01b0\u1ee3c l\u01b0u.", "PasswordMatchError": "M\u1eadt kh\u1ea9u v\u00e0 m\u1eadt kh\u1ea9u x\u00e1c nh\u1eadn c\u1ea7n ph\u1ea3i kh\u1edbp nhau .", "OptionRelease": "Ph\u00e1t h\u00e0nh ch\u00ednh th\u1ee9c", @@ -32,6 +37,7 @@ "MessageKeyRemoved": "Thank you. Your supporter key has been removed.", "ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.", "HeaderSearch": "Search", + "ValueDateCreated": "Date created: {0}", "LabelArtist": "Artist", "LabelMovie": "Movie", "LabelMusicVideo": "Music Video", @@ -42,6 +48,17 @@ "LabelFailed": "(failed)", "ButtonHelp": "Help", "ButtonSave": "L\u01b0u", + "LabelCollection": "Collection", + "HeaderAddToCollection": "Add to Collection", + "NewCollectionNameExample": "Example: Star Wars Collection", + "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata", + "LabelSelectCollection": "Select collection:", + "HeaderDevices": "Devices", + "ButtonScheduledTasks": "Scheduled tasks", + "MessageItemsAdded": "Items added", + "ButtonAddToCollection": "Add to collection", + "HeaderSelectCertificatePath": "Select Certificate Path", + "ConfirmMessageScheduledTaskButton": "This operation normally runs automatically as a scheduled task. It can also be run manually here. To configure the scheduled task, see:", "HeaderSupporterBenefit": "A supporter membership provides additional benefits such as access to premium plugins, internet channel content, and more. {0}Learn more{1}.", "HeaderWelcomeToMediaBrowserServerDashboard": "Welcome to the Media Browser Dashboard", "HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client", @@ -53,6 +70,10 @@ "HeaderChannelAccess": "Channel Access", "HeaderDeviceAccess": "Device Access", "HeaderSelectDevices": "Select Devices", + "ButtonCancelItem": "Cancel item", + "ButtonQueueForRetry": "Queue for retry", + "ButtonReenable": "Re-enable", + "SyncJobItemStatusSyncedMarkForRemoval": "Marked for removal", "LabelAbortedByServerShutdown": "(Aborted by server shutdown)", "LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.", "HeaderDeleteTaskTrigger": "Delete Task Trigger", @@ -64,10 +85,13 @@ "LabelFree": "Free", "HeaderSelectAudio": "Select Audio", "HeaderSelectSubtitles": "Select Subtitles", + "ButtonMarkForRemoval": "Mark for removal from device", + "ButtonUnmarkForRemoval": "Unmark for removal from device", "LabelDefaultStream": "(Default)", "LabelForcedStream": "(Forced)", "LabelDefaultForcedStream": "(Default\/Forced)", "LabelUnknownLanguage": "Unknown language", + "MessageConfirmSyncJobItemCancellation": "Are you sure you wish to cancel this item?", "ButtonMute": "Mute", "ButtonUnmute": "Unmute", "ButtonStop": "Stop", @@ -191,8 +215,10 @@ "LabelPlayMethodDirectPlay": "Direct Playing", "LabelAudioCodec": "Audio: {0}", "LabelVideoCodec": "Video: {0}", + "LabelLocalAccessUrl": "Local access: {0}", "LabelRemoteAccessUrl": "Remote access: {0}", - "LabelRunningOnPort": "Running on port {0}.", + "LabelRunningOnPort": "Running on http port {0}.", + "LabelRunningOnPorts": "Running on http port {0}, and https port {1}.", "HeaderLatestFromChannel": "Latest from {0}", "ButtonDownload": "Download", "LabelUnknownLanaguage": "Unknown language", @@ -206,6 +232,7 @@ "ButtonRefresh": "Refresh", "LabelCurrentPath": "Current path:", "HeaderSelectMediaPath": "Select Media Path", + "HeaderSelectPath": "Select Path", "ButtonNetwork": "Network", "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.", "HeaderMenu": "Menu", @@ -216,6 +243,7 @@ "ButtonResume": "Resume", "HeaderScenes": "Scenes", "HeaderAudioTracks": "Audio Tracks", + "HeaderLibraries": "Libraries", "HeaderSubtitles": "Subtitles", "HeaderVideoQuality": "Video Quality", "MessageErrorPlayingVideo": "There was an error playing the video.", @@ -581,6 +609,8 @@ "MediaInfoStreamTypeEmbeddedImage": "Embedded Image", "MediaInfoRefFrames": "Ref frames", "TabPlayback": "Playback", + "TabNotifications": "Notifications", + "TabExpert": "Expert", "HeaderSelectCustomIntrosPath": "Select Custom Intros Path", "HeaderRateAndReview": "Rate and Review", "HeaderThankYou": "Thank You", @@ -615,6 +645,7 @@ "DashboardTourMobile": "The Media Browser dashboard works great on smartphones and tablets. Manage your server from the palm of your hand anytime, anywhere.", "MessageRefreshQueued": "Refresh queued", "TabDevices": "Devices", + "TabExtras": "Extras", "DeviceLastUsedByUserName": "Last used by {0}", "HeaderDeleteDevice": "Delete Device", "DeleteDeviceConfirmation": "Are you sure you wish to delete this device? It will reappear the next time a user signs in with it.", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_CN.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_CN.json index 50fd14bb6..4f5e4b3eb 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_CN.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_CN.json @@ -6,6 +6,8 @@ "Administrator": "\u7ba1\u7406\u5458", "Password": "\u5bc6\u7801", "DeleteImage": "\u5220\u9664\u56fe\u50cf", + "MessageThankYouForSupporting": "Thank you for supporting Media Browser.", + "MessagePleaseSupportMediaBrowser": "Please support Media Browser.", "DeleteImageConfirmation": "\u4f60\u786e\u5b9a\u8981\u5220\u9664\u6b64\u56fe\u50cf\uff1f", "FileReadCancelled": "\u6587\u4ef6\u8bfb\u53d6\u5df2\u88ab\u53d6\u6d88\u3002", "FileNotFound": "\u672a\u627e\u5230\u6587\u4ef6\u3002", @@ -14,7 +16,10 @@ "DeleteUserConfirmation": "\u4f60\u786e\u5b9a\u8981\u5220\u9664\u6b64\u7528\u6237\uff1f", "PasswordResetHeader": "\u5bc6\u7801\u91cd\u7f6e", "PasswordResetComplete": "\u5bc6\u7801\u5df2\u91cd\u7f6e", + "PinCodeResetComplete": "The pin code has been reset.", "PasswordResetConfirmation": "\u4f60\u786e\u5b9a\u8981\u91cd\u7f6e\u5bc6\u7801\uff1f", + "PinCodeResetConfirmation": "Are you sure you wish to reset the pin code?", + "HeaderPinCodeReset": "Reset Pin Code", "PasswordSaved": "\u5bc6\u7801\u5df2\u4fdd\u5b58\u3002", "PasswordMatchError": "\u5bc6\u7801\u548c\u786e\u8ba4\u5bc6\u7801\u5fc5\u987b\u5339\u914d\u3002", "OptionRelease": "\u5b98\u65b9\u6b63\u5f0f\u7248", @@ -32,6 +37,7 @@ "MessageKeyRemoved": "\u8c22\u8c22\u3002\u4f60\u7684\u652f\u6301\u8005\u5e8f\u53f7\u5df2\u79fb\u9664\u3002", "ErrorLaunchingChromecast": "\u542f\u52a8chromecast\u9047\u5230\u9519\u8bef\uff0c\u8bf7\u786e\u8ba4\u8bbe\u5907\u5df2\u7ecf\u8fde\u63a5\u5230\u4f60\u7684\u65e0\u7ebf\u7f51\u7edc\u3002", "HeaderSearch": "\u641c\u7d22", + "ValueDateCreated": "Date created: {0}", "LabelArtist": "\u827a\u672f\u5bb6", "LabelMovie": "\u7535\u5f71", "LabelMusicVideo": "\u97f3\u4e50\u89c6\u9891", @@ -42,6 +48,17 @@ "LabelFailed": "(\u5931\u8d25)", "ButtonHelp": "Help", "ButtonSave": "\u50a8\u5b58", + "LabelCollection": "Collection", + "HeaderAddToCollection": "\u52a0\u5165\u5408\u96c6", + "NewCollectionNameExample": "\u4f8b\u5982\uff1a\u661f\u7403\u5927\u6218\u5408\u96c6", + "OptionSearchForInternetMetadata": "\u5728\u4e92\u8054\u7f51\u4e0a\u641c\u7d22\u5a92\u4f53\u56fe\u50cf\u548c\u8d44\u6599", + "LabelSelectCollection": "\u9009\u62e9\u5408\u96c6\uff1a", + "HeaderDevices": "Devices", + "ButtonScheduledTasks": "Scheduled tasks", + "MessageItemsAdded": "Items added", + "ButtonAddToCollection": "Add to collection", + "HeaderSelectCertificatePath": "Select Certificate Path", + "ConfirmMessageScheduledTaskButton": "This operation normally runs automatically as a scheduled task. It can also be run manually here. To configure the scheduled task, see:", "HeaderSupporterBenefit": "A supporter membership provides additional benefits such as access to premium plugins, internet channel content, and more. {0}Learn more{1}.", "HeaderWelcomeToMediaBrowserServerDashboard": "Welcome to the Media Browser Dashboard", "HeaderWelcomeToMediaBrowserWebClient": "\u6b22\u8fce\u8fdb\u5165Media Browser Web\u5ba2\u6237\u7aef", @@ -53,6 +70,10 @@ "HeaderChannelAccess": "Channel Access", "HeaderDeviceAccess": "Device Access", "HeaderSelectDevices": "Select Devices", + "ButtonCancelItem": "Cancel item", + "ButtonQueueForRetry": "Queue for retry", + "ButtonReenable": "Re-enable", + "SyncJobItemStatusSyncedMarkForRemoval": "Marked for removal", "LabelAbortedByServerShutdown": "(\u56e0\u4e3a\u670d\u52a1\u5668\u5173\u95ed\u88ab\u4e2d\u6b62)", "LabelScheduledTaskLastRan": "\u6700\u540e\u8fd0\u884c {0}, \u82b1\u8d39\u65f6\u95f4 {1}.", "HeaderDeleteTaskTrigger": "\u5220\u9664\u4efb\u52a1\u89e6\u53d1\u6761\u4ef6", @@ -64,10 +85,13 @@ "LabelFree": "\u514d\u8d39", "HeaderSelectAudio": "\u9009\u62e9\u97f3\u9891", "HeaderSelectSubtitles": "\u9009\u62e9\u5b57\u5e55", + "ButtonMarkForRemoval": "Mark for removal from device", + "ButtonUnmarkForRemoval": "Unmark for removal from device", "LabelDefaultStream": "(\u9ed8\u8ba4)", "LabelForcedStream": "(\u5f3a\u5236)", "LabelDefaultForcedStream": "(\u9ed8\u8ba4\/\u5f3a\u5236)", "LabelUnknownLanguage": "\u672a\u77e5\u8bed\u8a00", + "MessageConfirmSyncJobItemCancellation": "Are you sure you wish to cancel this item?", "ButtonMute": "\u9759\u97f3", "ButtonUnmute": "\u53d6\u6d88\u9759\u97f3", "ButtonStop": "\u505c\u6b62", @@ -191,8 +215,10 @@ "LabelPlayMethodDirectPlay": "\u76f4\u63a5\u64ad\u653e", "LabelAudioCodec": "\u97f3\u9891\uff1a {0}", "LabelVideoCodec": "\u89c6\u9891\uff1a{0}", + "LabelLocalAccessUrl": "Local access: {0}", "LabelRemoteAccessUrl": "\u8fdc\u7a0b\u8bbf\u95ee\uff1a{0}", - "LabelRunningOnPort": "\u8fd0\u884c\u5728\u7aef\u53e3{0}.", + "LabelRunningOnPort": "Running on http port {0}.", + "LabelRunningOnPorts": "Running on http port {0}, and https port {1}.", "HeaderLatestFromChannel": "\u6700\u65b0\u7684 {0}", "ButtonDownload": "\u4e0b\u8f7d", "LabelUnknownLanaguage": "\u672a\u77e5\u8bed\u8a00", @@ -206,6 +232,7 @@ "ButtonRefresh": "\u5237\u65b0", "LabelCurrentPath": "\u5f53\u524d\u8def\u5f84\uff1a", "HeaderSelectMediaPath": "\u9009\u62e9\u5a92\u4f53\u8def\u5f84", + "HeaderSelectPath": "Select Path", "ButtonNetwork": "\u7f51\u7edc", "MessageDirectoryPickerInstruction": "\u7f51\u7edc\u6309\u94ae\u65e0\u6cd5\u627e\u5230\u60a8\u7684\u8bbe\u5907\u7684\u60c5\u51b5\u4e0b\uff0c\u7f51\u7edc\u8def\u5f84\u53ef\u4ee5\u624b\u52a8\u8f93\u5165\u3002 \u4f8b\u5982\uff0c {0} \u6216\u8005 {1}\u3002", "HeaderMenu": "\u83dc\u5355", @@ -216,6 +243,7 @@ "ButtonResume": "\u6062\u590d\u64ad\u653e", "HeaderScenes": "\u573a\u666f", "HeaderAudioTracks": "\u97f3\u8f68", + "HeaderLibraries": "Libraries", "HeaderSubtitles": "\u5b57\u5e55", "HeaderVideoQuality": "\u89c6\u9891\u8d28\u91cf", "MessageErrorPlayingVideo": "\u64ad\u653e\u89c6\u9891\u51fa\u73b0\u9519\u8bef\u3002", @@ -581,6 +609,8 @@ "MediaInfoStreamTypeEmbeddedImage": "Embedded Image", "MediaInfoRefFrames": "Ref frames", "TabPlayback": "\u64ad\u653e", + "TabNotifications": "\u901a\u77e5", + "TabExpert": "Expert", "HeaderSelectCustomIntrosPath": "\u9009\u62e9\u81ea\u5b9a\u4e49\u4ecb\u7ecd\u8def\u5f84", "HeaderRateAndReview": "Rate and Review", "HeaderThankYou": "Thank You", @@ -615,6 +645,7 @@ "DashboardTourMobile": "The Media Browser dashboard works great on smartphones and tablets. Manage your server from the palm of your hand anytime, anywhere.", "MessageRefreshQueued": "Refresh queued", "TabDevices": "Devices", + "TabExtras": "Extras", "DeviceLastUsedByUserName": "Last used by {0}", "HeaderDeleteDevice": "Delete Device", "DeleteDeviceConfirmation": "Are you sure you wish to delete this device? It will reappear the next time a user signs in with it.", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json index 57a4fbb82..912e833d5 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json @@ -6,6 +6,8 @@ "Administrator": "\u7ba1\u7406\u54e1", "Password": "\u5bc6\u78bc", "DeleteImage": "\u522a\u9664\u5716\u50cf", + "MessageThankYouForSupporting": "Thank you for supporting Media Browser.", + "MessagePleaseSupportMediaBrowser": "Please support Media Browser.", "DeleteImageConfirmation": "\u4f60\u78ba\u5b9a\u8981\u522a\u9664\u9019\u5f35\u5716\u50cf\uff1f", "FileReadCancelled": "The file read has been canceled.", "FileNotFound": "\u672a\u627e\u5230\u6a94\u6848\u3002", @@ -14,7 +16,10 @@ "DeleteUserConfirmation": "Are you sure you wish to delete this user?", "PasswordResetHeader": "\u91cd\u8a2d\u5bc6\u78bc", "PasswordResetComplete": "\u5bc6\u78bc\u5df2\u91cd\u8a2d", + "PinCodeResetComplete": "The pin code has been reset.", "PasswordResetConfirmation": "\u4f60\u78ba\u5b9a\u8981\u91cd\u8a2d\u5bc6\u78bc\uff1f", + "PinCodeResetConfirmation": "Are you sure you wish to reset the pin code?", + "HeaderPinCodeReset": "Reset Pin Code", "PasswordSaved": "\u5bc6\u78bc\u5df2\u4fdd\u5b58\u3002", "PasswordMatchError": "\u5bc6\u78bc\u548c\u5bc6\u78bc\u78ba\u8a8d\u5fc5\u9808\u4e00\u81f4\u3002", "OptionRelease": "Official Release", @@ -32,6 +37,7 @@ "MessageKeyRemoved": "Thank you. Your supporter key has been removed.", "ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.", "HeaderSearch": "Search", + "ValueDateCreated": "Date created: {0}", "LabelArtist": "Artist", "LabelMovie": "Movie", "LabelMusicVideo": "Music Video", @@ -42,6 +48,17 @@ "LabelFailed": "(failed)", "ButtonHelp": "Help", "ButtonSave": "\u4fdd\u5b58", + "LabelCollection": "Collection", + "HeaderAddToCollection": "Add to Collection", + "NewCollectionNameExample": "\u4f8b\u5b50\uff1a\u661f\u7403\u5927\u6230\u5408\u96c6", + "OptionSearchForInternetMetadata": "\u5728\u4e92\u806f\u7db2\u4e0a\u641c\u7d22\u5a92\u9ad4\u5716\u50cf\u548c\u8cc7\u6599", + "LabelSelectCollection": "Select collection:", + "HeaderDevices": "Devices", + "ButtonScheduledTasks": "Scheduled tasks", + "MessageItemsAdded": "Items added", + "ButtonAddToCollection": "Add to collection", + "HeaderSelectCertificatePath": "Select Certificate Path", + "ConfirmMessageScheduledTaskButton": "This operation normally runs automatically as a scheduled task. It can also be run manually here. To configure the scheduled task, see:", "HeaderSupporterBenefit": "A supporter membership provides additional benefits such as access to premium plugins, internet channel content, and more. {0}Learn more{1}.", "HeaderWelcomeToMediaBrowserServerDashboard": "Welcome to the Media Browser Dashboard", "HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client", @@ -53,6 +70,10 @@ "HeaderChannelAccess": "Channel Access", "HeaderDeviceAccess": "Device Access", "HeaderSelectDevices": "Select Devices", + "ButtonCancelItem": "Cancel item", + "ButtonQueueForRetry": "Queue for retry", + "ButtonReenable": "Re-enable", + "SyncJobItemStatusSyncedMarkForRemoval": "Marked for removal", "LabelAbortedByServerShutdown": "(Aborted by server shutdown)", "LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.", "HeaderDeleteTaskTrigger": "Delete Task Trigger", @@ -64,10 +85,13 @@ "LabelFree": "Free", "HeaderSelectAudio": "Select Audio", "HeaderSelectSubtitles": "Select Subtitles", + "ButtonMarkForRemoval": "Mark for removal from device", + "ButtonUnmarkForRemoval": "Unmark for removal from device", "LabelDefaultStream": "(Default)", "LabelForcedStream": "(Forced)", "LabelDefaultForcedStream": "(Default\/Forced)", "LabelUnknownLanguage": "Unknown language", + "MessageConfirmSyncJobItemCancellation": "Are you sure you wish to cancel this item?", "ButtonMute": "Mute", "ButtonUnmute": "Unmute", "ButtonStop": "Stop", @@ -191,8 +215,10 @@ "LabelPlayMethodDirectPlay": "Direct Playing", "LabelAudioCodec": "Audio: {0}", "LabelVideoCodec": "Video: {0}", + "LabelLocalAccessUrl": "Local access: {0}", "LabelRemoteAccessUrl": "Remote access: {0}", - "LabelRunningOnPort": "Running on port {0}.", + "LabelRunningOnPort": "Running on http port {0}.", + "LabelRunningOnPorts": "Running on http port {0}, and https port {1}.", "HeaderLatestFromChannel": "Latest from {0}", "ButtonDownload": "Download", "LabelUnknownLanaguage": "Unknown language", @@ -206,6 +232,7 @@ "ButtonRefresh": "Refresh", "LabelCurrentPath": "Current path:", "HeaderSelectMediaPath": "Select Media Path", + "HeaderSelectPath": "Select Path", "ButtonNetwork": "Network", "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.", "HeaderMenu": "Menu", @@ -216,6 +243,7 @@ "ButtonResume": "Resume", "HeaderScenes": "\u5834\u666f", "HeaderAudioTracks": "Audio Tracks", + "HeaderLibraries": "Libraries", "HeaderSubtitles": "Subtitles", "HeaderVideoQuality": "Video Quality", "MessageErrorPlayingVideo": "There was an error playing the video.", @@ -581,6 +609,8 @@ "MediaInfoStreamTypeEmbeddedImage": "Embedded Image", "MediaInfoRefFrames": "Ref frames", "TabPlayback": "Playback", + "TabNotifications": "Notifications", + "TabExpert": "Expert", "HeaderSelectCustomIntrosPath": "Select Custom Intros Path", "HeaderRateAndReview": "Rate and Review", "HeaderThankYou": "Thank You", @@ -615,6 +645,7 @@ "DashboardTourMobile": "The Media Browser dashboard works great on smartphones and tablets. Manage your server from the palm of your hand anytime, anywhere.", "MessageRefreshQueued": "Refresh queued", "TabDevices": "Devices", + "TabExtras": "Extras", "DeviceLastUsedByUserName": "Last used by {0}", "HeaderDeleteDevice": "Delete Device", "DeleteDeviceConfirmation": "Are you sure you wish to delete this device? It will reappear the next time a user signs in with it.", diff --git a/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs b/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs index 66c6c3632..173b0e5ce 100644 --- a/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs +++ b/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs @@ -1,4 +1,4 @@ -using MediaBrowser.Common.Extensions; +using MediaBrowser.Model.Extensions; using MediaBrowser.Common.IO; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Localization; @@ -359,8 +359,7 @@ namespace MediaBrowser.Server.Implementations.Localization return new List<LocalizatonOption> { new LocalizatonOption{ Name="Arabic", Value="ar"}, - new LocalizatonOption{ Name="English (United Kingdom)", Value="en-GB"}, - new LocalizatonOption{ Name="English (United States)", Value="en-us"}, + new LocalizatonOption{ Name="Bulgarian (Bulgaria)", Value="bg-BG"}, new LocalizatonOption{ Name="Catalan", Value="ca"}, new LocalizatonOption{ Name="Chinese Simplified", Value="zh-CN"}, new LocalizatonOption{ Name="Chinese Traditional", Value="zh-TW"}, @@ -368,6 +367,8 @@ namespace MediaBrowser.Server.Implementations.Localization new LocalizatonOption{ Name="Czech", Value="cs"}, new LocalizatonOption{ Name="Danish", Value="da"}, new LocalizatonOption{ Name="Dutch", Value="nl"}, + new LocalizatonOption{ Name="English (United Kingdom)", Value="en-GB"}, + new LocalizatonOption{ Name="English (United States)", Value="en-us"}, new LocalizatonOption{ Name="Finnish", Value="fi"}, new LocalizatonOption{ Name="French", Value="fr"}, new LocalizatonOption{ Name="German", Value="de"}, @@ -384,6 +385,7 @@ namespace MediaBrowser.Server.Implementations.Localization new LocalizatonOption{ Name="Spanish (Mexico)", Value="es-MX"}, new LocalizatonOption{ Name="Swedish", Value="sv"}, new LocalizatonOption{ Name="Turkish", Value="tr"}, + new LocalizatonOption{ Name="Ukrainian", Value="uk"}, new LocalizatonOption{ Name="Vietnamese", Value="vi"} }.OrderBy(i => i.Name); diff --git a/MediaBrowser.Server.Implementations/Localization/Server/ar.json b/MediaBrowser.Server.Implementations/Localization/Server/ar.json index 5cb87a1a5..45ee5df06 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/ar.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/ar.json @@ -40,12 +40,32 @@ "OptionIAcceptTermsOfService": "I accept the terms of service", "ButtonPrivacyPolicy": "Privacy policy", "ButtonTermsOfService": "Terms of Service", + "HeaderDeveloperOptions": "Developer Options", + "OptionEnableWebClientResponseCache": "Enable web client response caching", + "OptionDisableForDevelopmentHelp": "Configure these as needed for web client development purposes.", + "OptionEnableWebClientResourceMinification": "Enable web client resource minification", + "LabelDashboardSourcePath": "Web client source path:", + "LabelDashboardSourcePathHelp": "If running the server from source, specify the path to the dashboard-ui folder. All web client files will be served from this location.", + "ButtonConvertMedia": "Convert media", + "ButtonOrganize": "Organize", "ButtonOk": "\u0645\u0648\u0627\u0641\u0642", "ButtonCancel": "\u0627\u0644\u063a\u0627\u0621", "ButtonNew": "New", "HeaderTV": "TV", "HeaderAudio": "Audio", "HeaderVideo": "Video", + "HeaderPaths": "Paths", + "CategorySync": "Sync", + "HeaderEasyPinCode": "Easy Pin Code", + "RegisterWithPayPal": "Register with PayPal", + "HeaderSyncRequiresSupporterMembership": "Sync Requires a Supporter Membership", + "HeaderEnjoyDayTrial": "Enjoy a 14 Day Free Trial", + "LabelSyncTempPath": "Temporary file path:", + "LabelSyncTempPathHelp": "Specify a custom sync working folder. Converted media created during the sync process will be stored here.", + "LabelCustomCertificatePath": "Custom certificate path:", + "LabelCustomCertificatePathHelp": "Supply your own ssl certificate. If omitted, the server will create a self-signed certificate.", + "TitleNotifications": "Notifications", + "ButtonDonateWithPayPal": "Donate with PayPal", "OptionDetectArchiveFilesAsMedia": "Detect archive files as media", "OptionDetectArchiveFilesAsMediaHelp": "If enabled, files with .rar and .zip extensions will be detected as media files.", "LabelEnterConnectUserName": "User name or email:", @@ -63,12 +83,14 @@ "FolderTypeTvShows": "TV", "FolderTypeInherit": "Inherit", "LabelContentType": "Content type:", + "TitleScheduledTasks": "Scheduled Tasks", "HeaderSetupLibrary": "\u0627\u0639\u062f\u0627\u062f \u0645\u0643\u062a\u0628\u0629 \u0627\u0644\u0648\u0633\u0627\u0626\u0637", "ButtonAddMediaFolder": "\u0627\u0636\u0627\u0641\u0629 \u0645\u062c\u0644\u062f \u0644\u0644\u0648\u0633\u0627\u0626\u0637", "LabelFolderType": "\u0646\u0648\u0639 \u0627\u0644\u0645\u062c\u0644\u062f:", "ReferToMediaLibraryWiki": "\u0627\u0644\u0631\u062c\u0648\u0639 \u0627\u0644\u0649 wiki \u0644\u0645\u0643\u062a\u0628\u0629 \u0627\u0644\u0648\u0633\u0627\u0626\u0637", "LabelCountry": "\u0627\u0644\u0628\u0644\u062f:", "LabelLanguage": "\u0627\u0644\u0644\u063a\u0629:", + "ButtonJoinTheDevelopmentTeam": "Join the Development Team", "HeaderPreferredMetadataLanguage": "\u0627\u0644\u0644\u063a\u0629 \u0627\u0644\u0645\u0641\u0636\u0644\u0629 \u0644\u0648\u0627\u0635\u0641\u0627\u062a \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a:", "LabelSaveLocalMetadata": "\u062d\u0641\u0638 \u0627\u0644\u0627\u0639\u0645\u0627\u0644 \u0627\u0644\u0641\u0646\u064a\u0629 \u0648\u0648\u0627\u0635\u0641\u0627\u062a \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a \u0641\u0649 \u0645\u062c\u0644\u062f\u0627\u062a \u0627\u0644\u0648\u0633\u0627\u0626\u0637", "LabelSaveLocalMetadataHelp": "\u0628\u062d\u0642\u0638 \u0627\u0644\u0627\u0639\u0645\u0627\u0644 \u0627\u0644\u0641\u0646\u064a\u0629 \u0648\u0648\u0627\u0635\u0641\u0627\u062a \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a \u0645\u0628\u0627\u0634\u0631\u0629 \u0641\u0649 \u0645\u062c\u0644\u062f\u0627\u062a \u0627\u0644\u0648\u0633\u0627\u0626\u0637 \u0633\u064a\u0633\u0647\u0644 \u0639\u0644\u064a\u0643 \u0627\u0644\u0648\u0635\u0648\u0644 \u0648\u0639\u0645\u0644 \u0627\u0644\u062a\u0639\u062f\u064a\u0644\u0627\u0627\u062a \u0639\u0644\u064a\u0647\u0627.", @@ -86,6 +108,8 @@ "TabCollectionTitles": "Titles", "HeaderDeviceAccess": "Device Access", "OptionEnableAccessFromAllDevices": "Enable access from all devices", + "OptionEnableAccessToAllChannels": "Enable access to all channels", + "OptionEnableAccessToAllLibraries": "Enable access to all libraries", "DeviceAccessHelp": "This only applies to devices that can be uniquely identified and will not prevent browser access. Filtering user device access will prevent them from using new devices until they've been approved here.", "LabelDisplayMissingEpisodesWithinSeasons": "Display missing episodes within seasons", "LabelUnairedMissingEpisodesWithinSeasons": "Display unaired episodes within seasons", @@ -299,7 +323,7 @@ "LabelCachePath": "Cache path:", "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.", "LabelImagesByNamePath": "Images by name path:", - "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, genre and studio images.", "LabelMetadataPath": "Metadata path:", "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.", "LabelTranscodingTempPath": "Transcoding temporary path:", @@ -314,12 +338,14 @@ "OptionEpisodes": "Episodes", "OptionOtherVideos": "Other Videos", "TitleMetadata": "Metadata", - "LabelAutomaticUpdatesFanart": "Enable automatic updates from FanArt.tv", + "LabelAutomaticUpdates": "Enable automatic updates", "LabelAutomaticUpdatesTmdb": "Enable automatic updates from TheMovieDB.org", "LabelAutomaticUpdatesTvdb": "Enable automatic updates from TheTVDB.com", "LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.", "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.", "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.", + "LabelFanartApiKey": "Personal api key:", + "LabelFanartApiKeyHelp": "Requests to fanart without a personal API key return results that were approved over 7 days ago. With a personal API key that drops to 48 hours and if you are also a fanart VIP member that will further drop to around 10 minutes.", "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", "LabelMetadataDownloadLanguage": "Preferred download language:", "ButtonAutoScroll": "Auto-scroll", @@ -487,6 +513,7 @@ "HeaderSystemPaths": "System Paths", "LinkCommunity": "Community", "LinkGithub": "Github", + "LinkApi": "Api", "LinkApiDocumentation": "Api Documentation", "LabelFriendlyServerName": "Friendly server name:", "LabelFriendlyServerNameHelp": "This name will be used to identify this server. If left blank, the computer name will be used.", @@ -494,20 +521,25 @@ "LabelPreferredDisplayLanguageHelp": "Translating Media Browser is an ongoing project and is not yet complete.", "LabelReadHowYouCanContribute": "Read about how you can contribute.", "HeaderNewCollection": "New Collection", - "HeaderAddToCollection": "Add to Collection", "ButtonSubmit": "Submit", - "NewCollectionNameExample": "Example: Star Wars Collection", - "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata", "ButtonCreate": "Create", - "LabelLocalHttpServerPortNumber": "Local port number:", + "LabelCustomCss": "Custom css:", + "LabelCustomCssHelp": "Apply your own custom css to the web interface.", + "LabelLocalHttpServerPortNumber": "Local http port number:", "LabelLocalHttpServerPortNumberHelp": "The tcp port number that Media Browser's http server should bind to.", - "LabelPublicPort": "Public port number:", - "LabelPublicPortHelp": "The public port number that should be mapped to the local port.", + "LabelPublicHttpPort": "Public http port number:", + "LabelPublicHttpPortHelp": "The public port number that should be mapped to the local http port.", + "LabelPublicHttpsPort": "Public https port number:", + "LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.", + "LabelEnableHttps": "Report https as external address", + "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.", + "LabelHttpsPort": "Local https port number:", + "LabelHttpsPortHelp": "The tcp port number that Media Browser's https server should bind to.", "LabelWebSocketPortNumber": "Web socket port number:", "LabelEnableAutomaticPortMap": "Enable automatic port mapping", "LabelEnableAutomaticPortMapHelp": "Attempt to automatically map the public port to the local port via UPnP. This may not work with some router models.", - "LabelExternalDDNS": "External DDNS:", - "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely.", + "LabelExternalDDNS": "External WAN Address:", + "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely. Leave empty for automatic detection.", "TabResume": "Resume", "TabWeather": "Weather", "TitleAppSettings": "App Settings", @@ -575,6 +607,7 @@ "ButtonRestart": "Restart", "ButtonShutdown": "Shutdown", "ButtonUpdateNow": "Update Now", + "TabHosting": "Hosting", "PleaseUpdateManually": "Please shutdown the server and update manually.", "NewServerVersionAvailable": "A new version of Media Browser Server is available!", "ServerUpToDate": "Media Browser Server is up to date", @@ -636,6 +669,7 @@ "NotificationOptionInstallationFailed": "Installation failure", "NotificationOptionNewLibraryContent": "New content added", "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", + "NotificationOptionCameraImageUploaded": "Camera image uploaded", "SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.", "NotificationOptionServerRestartRequired": "Server restart required", "LabelNotificationEnabled": "Enable this notification", @@ -853,6 +887,8 @@ "OptionDefaultSort": "Default", "OptionCommunityMostWatchedSort": "Most Watched", "TabNextUp": "Next Up", + "HeaderBecomeMediaBrowserSupporter": "Become a Media Browser Supporter", + "TextEnjoyBonusFeatures": "Enjoy Bonus Features", "MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.", "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.", "MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.", @@ -869,7 +905,6 @@ "LabelChannelDownloadAge": "Delete content after: (days)", "LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.", "ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.", - "LabelSelectCollection": "Select collection:", "ButtonOptions": "Options", "ViewTypeMovies": "Movies", "ViewTypeTvShows": "TV", @@ -917,7 +952,7 @@ "OptionLatestTvRecordings": "Latest recordings", "LabelProtocolInfo": "Protocol info:", "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.", - "TabKodiMetadata": "Kodi", + "TabNfo": "Nfo", "HeaderKodiMetadataHelp": "Media Browser includes native support for Kodi Nfo metadata and images. To enable or disable Kodi metadata, use the Advanced tab to configure options for your media types.", "LabelKodiMetadataUser": "Sync user watch data to nfo's for:", "LabelKodiMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Kodi.", @@ -931,6 +966,7 @@ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:", "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.", "LabelDisplayCollectionsView": "Display a collections view to show movie collections", + "LabelDisplayCollectionsViewHelp": "This will create a separate view to display collections that you've created or have access to. To create a collection, right-click or tap-hold any movie and select 'Add to Collection'. ", "LabelKodiMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs", "LabelKodiMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Kodi skin compatibility.", "TabServices": "Services", @@ -1084,11 +1120,14 @@ "LabelDisplayFoldersView": "Display a folders view to show plain media folders", "ViewTypeLiveTvRecordingGroups": "Recordings", "ViewTypeLiveTvChannels": "Channels", - "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password", - "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.", + "LabelEasyPinCode": "Easy pin code:", + "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Media Browser apps, and can also be used for easy in-network sign in.", + "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", + "LabelInNetworkSignInWithEasyPasswordHelp": "If enabled, you'll be able to use your easy pin code to sign in to Media Browser apps from inside your home network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", "HeaderPassword": "Password", "HeaderLocalAccess": "Local Access", "HeaderViewOrder": "View Order", + "ButtonResetEasyPassword": "Reset easy pin code", "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps", "LabelMetadataRefreshMode": "Metadata refresh mode:", "LabelImageRefreshMode": "Image refresh mode:", @@ -1279,7 +1318,7 @@ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.", "HeaderNewUsers": "New Users", "ButtonSignUp": "Sign up", - "ButtonForgotPassword": "Forgot password?", + "ButtonForgotPassword": "Forgot password", "OptionDisableUserPreferences": "Disable access to user preferences", "OptionDisableUserPreferencesHelp": "If enabled, only administrators will be able to configure user profile images, passwords, and language preferences.", "HeaderSelectServer": "Select Server", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/bg_BG.json b/MediaBrowser.Server.Implementations/Localization/Server/bg_BG.json new file mode 100644 index 000000000..6367a6bdc --- /dev/null +++ b/MediaBrowser.Server.Implementations/Localization/Server/bg_BG.json @@ -0,0 +1,1358 @@ +{ + "LabelExit": "\u0418\u0437\u043b\u0435\u0437", + "LabelVisitCommunity": "\u041f\u043e\u0441\u0435\u0442\u0438 \u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e\u0442\u043e", + "LabelGithub": "Github", + "LabelSwagger": "Swagger", + "LabelStandard": "\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e", + "LabelApiDocumentation": "API \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f", + "LabelDeveloperResources": "\u0420\u0435\u0441\u0443\u0440\u0441\u0438 \u0437\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u0446\u0438", + "LabelBrowseLibrary": "\u0420\u0430\u0437\u0433\u043b\u0435\u0434\u0430\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u0442\u0430", + "LabelConfigureMediaBrowser": "\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u0439 Media Browser", + "LabelOpenLibraryViewer": "\u041e\u0442\u0432\u043e\u0440\u0438 \u043f\u0440\u0435\u0433\u043b\u0435\u0434 \u043d\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u0442\u0430", + "LabelRestartServer": "\u0420\u0435\u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u0439 \u0441\u044a\u0440\u0432\u044a\u0440\u0430", + "LabelShowLogWindow": "\u041f\u043e\u043a\u0430\u0436\u0438 \u043b\u043e\u0433\u043e\u0432\u0438\u044f \u043f\u0440\u043e\u0437\u043e\u0440\u0435\u0446", + "LabelPrevious": "\u041f\u0440\u0435\u0434\u0438\u0448\u0435\u043d", + "LabelFinish": "\u041a\u0440\u0430\u0439", + "LabelNext": "\u0421\u043b\u0435\u0434\u0432\u0430\u0449", + "LabelYoureDone": "\u0413\u043e\u0442\u043e\u0432\u0438 \u0441\u0442\u0435!", + "WelcomeToMediaBrowser": "\u0414\u043e\u0431\u0440\u0435 \u0434\u043e\u0448\u043b\u0438 \u0432 Media Browser!", + "TitleMediaBrowser": "Media Browser", + "ThisWizardWillGuideYou": "\u0422\u043e\u0437\u0438 \u043c\u0430\u0433\u044c\u043e\u0441\u043d\u0438\u043a \u0449\u0435 \u0432\u0438 \u043d\u0430\u043f\u044a\u0442\u0441\u0442\u0432\u0430 \u043f\u0440\u0435\u0437 \u043f\u0440\u043e\u0446\u0435\u0441\u0430 \u043d\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f. \u0417\u0430 \u0434\u0430 \u0437\u0430\u043f\u043e\u0447\u043d\u0435\u0442\u0435, \u043c\u043e\u043b\u044f \u0438\u0437\u0431\u0435\u0440\u0435\u0442\u0435 \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u043d\u0438\u044f \u043e\u0442 \u0432\u0430\u0441 \u0435\u0437\u0438\u043a.", + "TellUsAboutYourself": "\u0420\u0430\u0437\u043a\u0430\u0436\u0435\u0442\u0435 \u0437\u0430 \u0441\u0435\u0431\u0435 \u0441\u0438", + "ButtonQuickStartGuide": "\u0420\u044a\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u0437\u0430 \u0431\u044a\u0440\u0437\u043e \u0437\u0430\u043f\u043e\u0447\u0432\u0430\u043d\u0435", + "LabelYourFirstName": "\u041f\u044a\u0440\u0432\u043e\u0442\u043e \u0432\u0438 \u0438\u043c\u0435:", + "MoreUsersCanBeAddedLater": "\u041f\u043e\u0432\u0435\u0447\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0438 \u043c\u043e\u0433\u0430\u0442 \u0434\u0430 \u0431\u044a\u0434\u0430\u0442 \u0434\u043e\u0431\u0430\u0432\u0435\u043d\u0438 \u043f\u043e-\u043a\u044a\u0441\u043d\u043e \u043e\u0442 \u0433\u043b\u0430\u0432\u043d\u0438\u044f \u043f\u0430\u043d\u0435\u043b.", + "UserProfilesIntro": "Media Browser \u0432\u043a\u043b\u044e\u0447\u0432\u0430 \u0432\u0433\u0440\u0430\u0434\u0435\u043d\u0430 \u043f\u043e\u0434\u0434\u0440\u044a\u0436\u043a\u0430 \u043d\u0430 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0441\u043a\u0438 \u043f\u0440\u043e\u0444\u0438\u043b\u0438, \u043a\u043e\u0438\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0432\u0430\u0442 \u043d\u0430 \u0432\u0441\u0435\u043a\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b \u0434\u0430 \u0438\u043c\u0430\u0442 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043d\u0430 \u0434\u0438\u0441\u043f\u043b\u0435\u044f, \u0441\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043d\u0430 \u043f\u0443\u0441\u043a\u0430\u043d\u0435 \u0438 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u0441\u043a\u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b.", + "LabelWindowsService": "Windows Service", + "AWindowsServiceHasBeenInstalled": "Windows Service \u0431\u0435\u0448\u0435 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d.", + "WindowsServiceIntro1": "Media Browser Server \u043e\u0431\u0438\u043a\u043d\u043e\u0432\u0435\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0438 \u043a\u0430\u0442\u043e \u0434\u0435\u0441\u043a\u0442\u043e\u043f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441 tray \u0438\u043a\u043e\u043d\u0430, \u043d\u043e \u0430\u043a\u043e \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u0442\u0435 \u0434\u0430 \u0433\u043e \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u0442\u0435 \u043a\u0430\u0442\u043e \u0443\u0441\u043b\u0443\u0433\u0430 \u0432\u044a\u0432 \u0444\u043e\u043d\u043e\u0432 \u0440\u0435\u0436\u0438\u043c, \u0442\u043e\u0439 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430 \u043e\u0442 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043d\u0438\u044f \u043f\u0430\u043d\u0435\u043b \u043d\u0430 Windows Services.", + "WindowsServiceIntro2": "\u0410\u043a\u043e \u043f\u043e\u043b\u0437\u0432\u0430\u0442\u0435 Windows \u0443\u0441\u043b\u0443\u0433\u0430\u0442\u0430, \u043c\u043e\u043b\u044f, \u0438\u043c\u0430\u0439\u0442\u0435 \u043f\u0440\u0435\u0434\u0432\u0438\u0434, \u0447\u0435 \u0442\u043e\u0439 \u043d\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0431\u044a\u0434\u0435 \u043f\u0443\u0441\u043d\u0430\u0442 \u0434\u043e\u043a\u0430\u0442\u043e \u044f \u0438\u043c\u0430 \u0438\u043a\u043e\u043d\u0430\u0442\u0430 \u0432 \u043b\u0435\u043d\u0442\u0430\u0442\u0430 ,\u0442\u0430\u043a\u0430 \u0447\u0435 \u0449\u0435 \u0442\u0440\u044f\u0431\u0432\u0430 \u0434\u0430 \u0438\u0437\u043b\u0435\u0437\u0435\u0442\u0435 \u043e\u0442 \u043d\u0435\u044f, \u0437\u0430 \u0434\u0430 \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430 \u0443\u0441\u043b\u0443\u0433\u0430\u0442\u0430. \u0423\u0441\u043b\u0443\u0433\u0430\u0442\u0430 \u0441\u044a\u0449\u043e \u0442\u0430\u043a\u0430 \u0449\u0435 \u0442\u0440\u044f\u0431\u0432\u0430 \u0434\u0430 \u0431\u044a\u0434\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u043d\u0430 \u0441 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u0438\u0432\u043d\u0438 \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u0438 \u0447\u0440\u0435\u0437 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043d\u0438\u044f \u043f\u0430\u043d\u0435\u043b. \u041c\u043e\u043b\u044f, \u0438\u043c\u0430\u0439\u0442\u0435 \u043f\u0440\u0435\u0434\u0432\u0438\u0434, \u0447\u0435 \u0432 \u0442\u043e\u0437\u0438 \u043c\u043e\u043c\u0435\u043d\u0442 \u0443\u0441\u043b\u0443\u0433\u0430\u0442\u0430 \u043d\u0435 \u0435 \u0432 \u0441\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u0430 \u0441\u0435 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u0430 \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u043d\u043e, \u0442\u0430\u043a\u0430 \u0447\u0435 \u043d\u043e\u0432\u0438\u0442\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0449\u0435 \u0438\u0437\u0438\u0441\u043a\u0432\u0430\u0442 \u0440\u044a\u0447\u043d\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435.", + "WizardCompleted": "\u0422\u043e\u0432\u0430 \u0435 \u0432\u0441\u0438\u0447\u043a\u043e \u043e\u0442 \u043a\u043e\u0435\u0442\u043e \u0441\u0435 \u043d\u0443\u0436\u0434\u0430\u0435\u043c \u0437\u0430\u0441\u0435\u0433\u0430. Media Browser \u0435 \u0437\u0430\u043f\u043e\u0447\u043d\u0430\u043b \u0434\u0430 \u0441\u044a\u0431\u0438\u0440\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0437\u0430 \u0432\u0430\u0448\u0430\u0442\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430. \u0412\u0438\u0436\u0442\u0435 \u043d\u044f\u043a\u043e\u0438 \u043e\u0442 \u043d\u0430\u0448\u0438\u0442\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0430 \u043f\u043e\u0441\u043b\u0435 \u043d\u0430\u0442\u0438\u0441\u043d\u0435\u0442\u0435 <b>\u041a\u0440\u0430\u0439<\/b>. \u0437\u0430 \u0434\u0430 \u0432\u0438\u0434\u0438\u0442\u0435 <b>\u0413\u043b\u0430\u0432\u0435\u043d \u043f\u0430\u043d\u0435\u043b \u043d\u0430 \u0441\u044a\u0440\u0432\u044a\u0440\u0430<\/b>.", + "LabelConfigureSettings": "\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u0439 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438", + "LabelEnableVideoImageExtraction": "\u0410\u043a\u0442\u0438\u0432\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0438\u0437\u0432\u043b\u0438\u0447\u0430\u043d\u0435 \u043d\u0430 \u0432\u0438\u0434\u0435\u043e \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f.", + "VideoImageExtractionHelp": "\u0417\u0430 \u0432\u0438\u0434\u0435\u043e\u043a\u043b\u0438\u043f\u043e\u0432\u0435, \u043a\u043e\u0438\u0442\u043e \u0432\u0441\u0435 \u043e\u0449\u0435 \u043d\u0435 \u0440\u0430\u0437\u043f\u043e\u043b\u0430\u0433\u0430\u0442 \u0441 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u0438 \u0437\u0430 \u043a\u043e\u0438\u0442\u043e \u043d\u0435 \u0441\u043c\u0435 \u0432 \u0441\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u0430 \u043d\u0430\u043c\u0435\u0440\u0438\u043c \u0442\u0430\u043a\u0438\u0432\u0430. \u0422\u043e\u0432\u0430 \u0449\u0435 \u0434\u043e\u0431\u0430\u0432\u0438 \u0434\u043e\u043f\u044a\u043b\u043d\u0438\u0442\u0435\u043b\u043d\u043e \u0432\u0440\u0435\u043c\u0435 \u043a\u044a\u043c \u043f\u044a\u0440\u0432\u043e\u043d\u0430\u0447\u0430\u043b\u043d\u043e\u0442\u043e \u0441\u043a\u0430\u043d\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u0442\u0430, \u043d\u043e \u0449\u0435 \u0434\u043e\u0432\u0435\u0434\u0435 \u0434\u043e \u043f\u043e-\u043f\u0440\u0438\u044f\u0442\u0435\u043d \u0432\u0438\u0434.", + "LabelEnableChapterImageExtractionForMovies": "\u0410\u043a\u0442\u0438\u0432\u0438\u0440\u0430\u043d\u0435 \u0438\u0437\u0432\u043b\u0438\u0447\u0430\u043d\u0435 \u043d\u0430 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u0433\u043b\u0430\u0432\u0438\u0442\u0435 \u0437\u0430 \u0424\u0438\u043b\u043c\u0438.", + "LabelChapterImageExtractionForMoviesHelp": "\u0418\u0437\u0432\u043b\u0438\u0447\u0430\u043d\u0435 \u043d\u0430 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u0433\u043b\u0430\u0432\u0438\u0442\u0435 \u0449\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u0438 \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0438\u0442\u0435 \u0434\u0430 \u043f\u043e\u043a\u0430\u0437\u0432\u0430\u0442 \u0433\u0440\u0430\u0444\u0438\u0447\u043d\u0438 \u043c\u0435\u043d\u044e\u0442\u0430 \u0437\u0430 \u0438\u0437\u0431\u043e\u0440 \u043d\u0430 \u0441\u0446\u0435\u043d\u0430. \u041f\u0440\u043e\u0446\u0435\u0441\u044a\u0442 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0431\u044a\u0434\u0435 \u0431\u0430\u0432\u0435\u043d, CPU-\u0438\u043d\u0442\u0435\u043d\u0437\u0438\u0432\u0435\u043d \u0438 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0438\u0437\u0438\u0441\u043a\u0432\u0430 \u043d\u044f\u043a\u043e\u043b\u043a\u043e \u0433\u0438\u0433\u0430\u0431\u0430\u0439\u0442\u0430 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e. \u0422\u043e \u0440\u0430\u0431\u043e\u0442\u0438 \u043a\u0430\u0442\u043e \u043d\u043e\u0449\u043d\u0430 \u043f\u043b\u0430\u043d\u0438\u0440\u0430\u043d\u0430 \u0437\u0430\u0434\u0430\u0447\u0430 \u0432 4 \u0447\u0430\u0441\u0430 \u0441\u0443\u0442\u0440\u0438\u043d\u0442\u0430, \u0432\u044a\u043f\u0440\u0435\u043a\u0438 \u0447\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430 \u0432 \u041f\u043b\u0430\u043d\u0438\u0440\u0430\u043d\u0438 \u0437\u0430\u0434\u0430\u0447\u0438. \u041d\u0435 \u0441\u0435 \u043f\u0440\u0435\u043f\u043e\u0440\u044a\u0447\u0432\u0430 \u0442\u0430\u0437\u0438 \u0437\u0430\u0434\u0430\u0447\u0430 \u0434\u0430 \u0441\u0435 \u0438\u0437\u043f\u044a\u043b\u043d\u044f\u0432\u0430 \u043f\u043e \u0432\u0440\u0435\u043c\u0435 \u043d\u0430 \u043f\u0438\u043a\u043e\u0432\u0438\u0442\u0435 \u0447\u0430\u0441\u043e\u0432\u0435 \u043d\u0430 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u043d\u0435.", + "LabelEnableAutomaticPortMapping": "\u0410\u043a\u0442\u0438\u0432\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043d\u0430 \u043f\u043e\u0440\u0442\u043e\u0432\u0435\u0442\u0435", + "LabelEnableAutomaticPortMappingHelp": "UPnP \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0432\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u043d\u0430 \u0440\u0443\u0442\u0435\u0440\u0430 \u0437\u0430 \u043b\u0435\u0441\u0435\u043d \u043e\u0442\u0434\u0430\u043b\u0435\u0447\u0435\u043d \u0434\u043e\u0441\u0442\u044a\u043f. \u0422\u043e\u0432\u0430 \u043c\u043e\u0436\u0435 \u0434\u0430 \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0438 \u0441 \u043d\u044f\u043a\u043e\u0438 \u0440\u0443\u0442\u0435\u0440\u0438.", + "HeaderTermsOfService": "Media Browser \u0423\u0441\u043b\u043e\u0432\u0438\u044f \u0437\u0430 \u041f\u043e\u043b\u0437\u0432\u0430\u043d\u0435", + "MessagePleaseAcceptTermsOfService": "\u041c\u043e\u043b\u044f \u043f\u0440\u0438\u0435\u043c\u0435\u0442\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u0442\u0430 \u0437\u0430 \u043f\u043e\u043b\u0437\u0432\u0430\u043d\u0435 \u0438 \u0434\u0435\u043a\u043b\u0430\u0440\u0430\u0446\u0438\u044f\u0442\u0430 \u0437\u0430 \u043f\u043e\u0432\u0435\u0440\u0438\u0442\u0435\u043b\u043d\u043e\u0441\u0442, \u043f\u0440\u0435\u0434\u0438 \u0434\u0430 \u043f\u0440\u043e\u0434\u044a\u043b\u0436\u0438\u0442\u0435.", + "OptionIAcceptTermsOfService": "\u041f\u0440\u0438\u0435\u043c\u0430\u043c \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u0442\u0430 \u0437\u0430 \u043f\u043e\u043b\u0437\u0432\u0430\u043d\u0435", + "ButtonPrivacyPolicy": "\u0414\u0435\u043a\u043b\u0430\u0440\u0430\u0446\u0438\u044f \u0437\u0430 \u043f\u043e\u0432\u0435\u0440\u0438\u0442\u0435\u043b\u043d\u043e\u0441\u0442", + "ButtonTermsOfService": "\u0423\u0441\u043b\u043e\u0432\u0438\u044f \u0437\u0430 \u043f\u043e\u043b\u0437\u0432\u0430\u043d\u0435", + "HeaderDeveloperOptions": "\u041e\u043f\u0446\u0438\u0438 \u0437\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u0446\u0438", + "OptionEnableWebClientResponseCache": "\u0410\u043a\u0442\u0438\u0432\u0438\u0440\u0430\u043d\u0435 \u043a\u0435\u0448\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u043e\u0442\u0433\u043e\u0432\u043e\u0440\u0438\u0442\u0435 \u043d\u0430 \u0443\u0435\u0431 \u043a\u043b\u0438\u0435\u043d\u0442\u0438\u0442\u0435", + "OptionDisableForDevelopmentHelp": "\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u0439\u0442\u0435 \u0442\u0435\u0437\u0438 \u0441\u043f\u043e\u0440\u0435\u0434 \u043d\u0443\u0436\u0434\u0438\u0442\u0435 \u0437\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043d\u0430 \u0443\u0435\u0431 \u043a\u043b\u0438\u0435\u043d\u0442\u0438.", + "OptionEnableWebClientResourceMinification": "\u0410\u043a\u0442\u0438\u0432\u0438\u0440\u0430\u043d\u0435 \u0441\u043c\u0430\u043b\u044f\u0432\u0430\u043d\u0435(\u043c\u0438\u043d\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f) \u043d\u0430 \u0440\u0435\u0441\u0443\u0440\u0441\u0438\u0442\u0435 \u043d\u0430 \u0443\u0435\u0431 \u043a\u043b\u0438\u0435\u043d\u0442\u0430", + "LabelDashboardSourcePath": "\u0413\u043b\u0430\u0432\u0435\u043d \u043f\u044a\u0442 \u043a\u044a\u043c \u0443\u0435\u0431 \u043a\u043b\u0438\u0435\u043d\u0442\u0430", + "LabelDashboardSourcePathHelp": "\u0410\u043a\u043e \u043f\u0443\u0441\u043a\u0430\u0442\u0435 \u0441\u044a\u0440\u0432\u044a\u0440\u0430 \u043e\u0442 \u0438\u0437\u0445\u043e\u0434\u0435\u043d \u043a\u043e\u0434, \u043f\u043e\u0441\u043e\u0447\u0435\u0442\u0435 \u043f\u044a\u0442\u044f \u043a\u044a\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u043d\u0430 \u0433\u043b\u0430\u0432\u043d\u043e\u0442\u043e \u0442\u0430\u0431\u043b\u043e. \u0412\u0441\u0438\u0447\u043a\u0438 \u0443\u0435\u0431 \u043a\u043b\u0438\u0435\u043d\u0442\u0438 \u0449\u0435 \u0431\u044a\u0434\u0430\u0442 \u043e\u0431\u0441\u043b\u0443\u0436\u0432\u0430\u043d\u0438 \u043e\u0442 \u0442\u0430\u043c.", + "ButtonConvertMedia": "\u041a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u0430\u0439 \u043c\u0435\u0434\u0438\u044f\u0442\u0430", + "ButtonOrganize": "\u041e\u0440\u0433\u0430\u043d\u0438\u0437\u0438\u0440\u0430\u0439", + "ButtonOk": "\u041e\u043a", + "ButtonCancel": "\u041e\u0442\u043c\u0435\u043d\u0438", + "ButtonNew": "\u041d\u043e\u0432", + "HeaderTV": "TV", + "HeaderAudio": "\u0410\u0443\u0434\u0438\u043e", + "HeaderVideo": "\u0412\u0438\u0434\u0435\u043e", + "HeaderPaths": "\u041f\u044a\u0442\u0438\u0449\u0430", + "CategorySync": "Sync", + "HeaderEasyPinCode": "Easy Pin Code", + "RegisterWithPayPal": "Register with PayPal", + "HeaderSyncRequiresSupporterMembership": "Sync Requires a Supporter Membership", + "HeaderEnjoyDayTrial": "Enjoy a 14 Day Free Trial", + "LabelSyncTempPath": "Temporary file path:", + "LabelSyncTempPathHelp": "Specify a custom sync working folder. Converted media created during the sync process will be stored here.", + "LabelCustomCertificatePath": "Custom certificate path:", + "LabelCustomCertificatePathHelp": "Supply your own ssl certificate. If omitted, the server will create a self-signed certificate.", + "TitleNotifications": "\u0418\u0437\u0432\u0435\u0441\u0442\u0438\u044f", + "ButtonDonateWithPayPal": "\u041d\u0430\u043f\u0440\u0430\u0432\u0438 \u0434\u0430\u0440\u0435\u043d\u0438\u0435 \u0441 PayPal", + "OptionDetectArchiveFilesAsMedia": "\u0420\u0430\u0437\u043f\u043e\u0437\u043d\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u0430\u0440\u0445\u0438\u0432\u0438 \u043a\u0430\u0442\u043e \u043c\u0435\u0434\u0438\u0439\u043d\u0438 \u0444\u0430\u0439\u043b\u043e\u0432\u0435", + "OptionDetectArchiveFilesAsMediaHelp": "\u0410\u043a\u043e \u0435 \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u0430\u043d\u043e, \u0444\u0430\u0439\u043b\u043e\u0432\u0435 \u0441 \u0440\u0430\u0437\u0448\u0438\u0440\u0435\u043d\u0438\u044f .rar \u0438 .zip \u0449\u0435 \u0431\u044a\u0434\u0430\u0442 \u0440\u0430\u0437\u043f\u043e\u0437\u043d\u0430\u0432\u0430\u043d\u0438 \u043a\u0430\u0442\u043e \u043c\u0435\u0434\u0438\u0439\u043d\u0438 \u0444\u0430\u0439\u043b\u043e\u0432\u0435.", + "LabelEnterConnectUserName": "\u041f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0441\u043a\u043e \u0438\u043c\u0435 \u0438\u043b\u0438 email:", + "LabelEnterConnectUserNameHelp": "\u0422\u043e\u0432\u0430 \u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0441\u043a\u043e\u0442\u043e \u0438\u043c\u0435 \u0438\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u0430\u0442\u0430 \u043d\u0430 \u0432\u0430\u0448\u0438\u044f Media Brower \u043e\u043d\u043b\u0430\u0439\u043d \u0430\u043a\u0430\u0443\u043d\u0442.", + "HeaderSyncJobInfo": "\u0421\u0438\u043d\u0445\u0440. \u0417\u0430\u0434\u0430\u0447\u0430", + "FolderTypeMixed": "\u0421\u043c\u0435\u0441\u0435\u043d\u043e \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435", + "FolderTypeMovies": "\u0424\u0438\u043b\u043c\u0438", + "FolderTypeMusic": "\u041c\u0443\u0437\u0438\u043a\u0430", + "FolderTypeAdultVideos": "\u041a\u043b\u0438\u043f\u043e\u0432\u0435 \u0437\u0430 \u0432\u044a\u0437\u0440\u0430\u0441\u0442\u043d\u0438", + "FolderTypePhotos": "\u0421\u043d\u0438\u043c\u043a\u0438", + "FolderTypeMusicVideos": "\u041c\u0443\u0437\u0438\u043a\u0430\u043b\u043d\u0438 \u043a\u043b\u0438\u043f\u043e\u0432\u0435", + "FolderTypeHomeVideos": "\u0414\u043e\u043c\u0430\u0448\u043d\u0438 \u043a\u043b\u0438\u043f\u043e\u0432\u0435", + "FolderTypeGames": "\u0418\u0433\u0440\u0438", + "FolderTypeBooks": "\u041a\u043d\u0438\u0433\u0438", + "FolderTypeTvShows": "TV", + "FolderTypeInherit": "\u041d\u0430\u0441\u043b\u0435\u0434\u0438", + "LabelContentType": "\u0422\u0438\u043f \u043d\u0430 \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435\u0442\u043e:", + "TitleScheduledTasks": "\u041f\u043b\u0430\u043d\u0438\u0440\u0430\u043d\u0438 \u0437\u0430\u0434\u0430\u0447\u0438", + "HeaderSetupLibrary": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u0442\u0435 \u043c\u0435\u0434\u0438\u0439\u043d\u0430\u0442\u0430 \u0441\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430", + "ButtonAddMediaFolder": "\u0414\u043e\u0431\u0430\u0432\u0438 \u043c\u0435\u0434\u0438\u0439\u043d\u0430 \u043f\u0430\u043f\u043a\u0430", + "LabelFolderType": "\u0422\u0438\u043f \u043d\u0430 \u043f\u0430\u043f\u043a\u0430\u0442\u0430:", + "ReferToMediaLibraryWiki": "\u0414\u043e\u043f\u0438\u0442\u0430\u0439\u0442\u0435 \u0441\u0435 \u0434\u043e wiki \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u0442\u0430 \u043d\u0430 \u043c\u0435\u0434\u0438\u0439\u043d\u0430\u0442\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430", + "LabelCountry": "\u0421\u0442\u0440\u0430\u043d\u0430:", + "LabelLanguage": "\u0415\u0437\u0438\u043a:", + "ButtonJoinTheDevelopmentTeam": "\u041f\u0440\u0438\u0441\u044a\u0435\u0434\u0438\u043d\u0435\u0442\u0435 \u0441\u0435 \u043a\u044a\u043c \u043e\u0442\u0431\u043e\u0440\u0430 \u043d\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u0446\u0438\u0442\u0435", + "HeaderPreferredMetadataLanguage": "\u041f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u043d \u0435\u0437\u0438\u043a \u043d\u0430 \u043c\u0435\u0442\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f\u0442\u0430:", + "LabelSaveLocalMetadata": "\u0417\u0430\u043f\u043e\u043c\u043d\u0438 \u0438\u0437\u043a\u0443\u0441\u0442\u0432\u043e \u0438 \u043c\u0435\u0442\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0432 \u043f\u0430\u043f\u043a\u0430\u0442\u0430 \u043d\u0430 \u043c\u0435\u0434\u0438\u044f\u0442\u0430", + "LabelSaveLocalMetadataHelp": "\u0417\u0430\u043f\u043e\u043c\u043d\u044f\u043d\u0435\u0442\u043e \u043d\u0430 \u0438\u0437\u043a\u0443\u0441\u0442\u0432\u043e \u0438 \u043c\u0435\u0442\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0434\u0438\u0440\u0435\u043a\u0442\u043d\u043e \u0432 \u043c\u0435\u0434\u0438\u0439\u043d\u0438\u0442\u0435 \u043f\u0430\u043f\u043a\u0438 \u0449\u0435 \u0433\u0438 \u0441\u043b\u043e\u0436\u0438 \u043d\u0430 \u043c\u044f\u0441\u0442\u043e, \u043a\u044a\u0434\u0435\u0442\u043e \u043b\u0435\u0441\u043d\u043e \u043c\u043e\u0433\u0430\u0442 \u0434\u0430 \u0431\u044a\u0434\u0430\u0442 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0430\u043d\u0438.", + "LabelDownloadInternetMetadata": "\u0421\u0432\u0430\u043b\u044f\u0439 \u0438\u0437\u043a\u0443\u0441\u0442\u0432\u043e \u0438 \u043c\u0435\u0442\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e\u0442 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442", + "LabelDownloadInternetMetadataHelp": "Media Browser \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0432\u0430\u043b\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0437\u0430 \u0432\u0430\u0448\u0430\u0442\u0430 \u043c\u0435\u0434\u0438\u044f, \u043a\u043e\u0435\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0432\u0430 \u043a\u0440\u0430\u0441\u0438\u0432\u043e \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u0435.", + "TabPreferences": "\u041f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u043d\u0438\u044f", + "TabPassword": "\u041f\u0430\u0440\u043e\u043b\u0430", + "TabLibraryAccess": "\u0414\u043e\u0441\u044a\u043f \u0434\u043e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u0442\u0430", + "TabAccess": "\u0414\u043e\u0441\u0442\u044a\u043f", + "TabImage": "\u041a\u0430\u0440\u0442\u0438\u043d\u0430", + "TabProfile": "\u041f\u0440\u043e\u0444\u0438\u043b", + "TabMetadata": "\u041c\u0435\u0442\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f", + "TabImages": "\u0418\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f", + "TabNotifications": "\u0418\u0437\u0432\u0435\u0441\u0442\u0438\u044f", + "TabCollectionTitles": "\u0417\u0430\u0433\u043b\u0430\u0432\u0438\u044f", + "HeaderDeviceAccess": "\u0414\u043e\u0441\u0442\u044a\u043f \u043d\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u0442\u0430", + "OptionEnableAccessFromAllDevices": "\u0410\u043a\u0442\u0438\u0432\u0438\u0440\u0430\u0439 \u0434\u043e\u0441\u0442\u044a\u043f \u043e\u0442 \u0432\u0441\u0438\u0447\u043a\u0438 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430", + "OptionEnableAccessToAllChannels": "\u0410\u043a\u0442\u0438\u0432\u0438\u0440\u0430\u0439 \u0434\u043e\u0441\u0442\u044a\u043f \u0434\u043e \u0432\u0441\u0438\u0447\u043a\u0438 \u043a\u0430\u043d\u0430\u043b\u0438", + "OptionEnableAccessToAllLibraries": "\u0410\u043a\u0442\u0438\u0432\u0438\u0440\u0430\u0439 \u0434\u043e\u0441\u0442\u044a\u043f \u0434\u043e \u0432\u0441\u0438\u0447\u043a\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438", + "DeviceAccessHelp": "\u0422\u043e\u0432\u0430 \u0441\u0435 \u043e\u0442\u043d\u0430\u0441\u044f \u0441\u0430\u043c\u043e \u0437\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430, \u043a\u043e\u0438\u0442\u043e \u043c\u043e\u0433\u0430\u0442 \u0434\u0430 \u0431\u044a\u0434\u0430\u0442 \u0440\u0430\u0437\u043b\u0438\u0447\u0435\u043d\u0438 \u0438 \u043d\u044f\u043c\u0430 \u0434\u0430 \u043f\u043e\u043f\u0440\u0435\u0447\u0438 \u043d\u0430 \u0434\u043e\u0441\u0442\u044a\u043f \u043e\u0442 \u0431\u0440\u0430\u0443\u0437\u044a\u0440. \u0424\u0438\u043b\u0442\u0440\u0438\u0440\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0441\u043a\u0438 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u0449\u0435 \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0442\u0438 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u043d\u0435\u0442\u043e \u0438\u043c \u0434\u043e\u043a\u0430\u0442\u043e \u043d\u0435 \u0431\u044a\u0434\u0430\u0442 \u043e\u0434\u043e\u0431\u0440\u0435\u043d\u0438 \u0442\u0443\u043a.", + "LabelDisplayMissingEpisodesWithinSeasons": "\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u0439 \u043b\u0438\u043f\u0441\u0432\u0430\u0449\u0438 \u0435\u043f\u0438\u0437\u043e\u0434\u0438 \u0432 \u0441\u0435\u0437\u043e\u043d\u0438\u0442\u0435", + "LabelUnairedMissingEpisodesWithinSeasons": "\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u0439 \u043d\u0435\u0438\u0437\u043b\u044a\u0447\u0435\u043d\u0438 \u0435\u043f\u0438\u0437\u043e\u0434\u0438 \u0432 \u0441\u0435\u0437\u043e\u043d\u0438\u0442\u0435", + "HeaderVideoPlaybackSettings": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043d\u0430 \u0432\u044a\u0437\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0436\u0434\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0432\u0438\u0434\u0435\u043e", + "HeaderPlaybackSettings": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043d\u0430 \u0432\u044a\u0437\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0436\u0434\u0430\u043d\u0435\u0442\u043e", + "LabelAudioLanguagePreference": "\u041f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u043d \u0435\u0437\u0438\u043a \u043d\u0430 \u0430\u0443\u0434\u0438\u043e\u0442\u043e:", + "LabelSubtitleLanguagePreference": "\u041f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u043d \u0435\u0437\u0438\u043a \u043d\u0430 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u0438\u0442\u0435:", + "OptionDefaultSubtitles": "\u041f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435", + "OptionOnlyForcedSubtitles": "\u0421\u0430\u043c\u043e \u043f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u043d\u0438 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u0438", + "OptionAlwaysPlaySubtitles": "\u0412\u0438\u043d\u0430\u0433\u0438 \u043f\u043e\u043a\u0430\u0437\u0432\u0430\u0439 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u0438", + "OptionNoSubtitles": "\u0411\u0435\u0437 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u0438", + "OptionDefaultSubtitlesHelp": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u0438 \u043e\u0442\u0433\u043e\u0432\u0430\u0440\u044f\u0449\u0438 \u043d\u0430 \u0435\u0437\u0438\u043a\u043e\u0432\u0438\u0442\u0435 \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u043d\u0438\u044f \u0449\u0435 \u0431\u044a\u0434\u0430\u0442 \u043f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0438, \u043a\u043e\u0433\u0430\u0442\u043e \u0430\u0443\u0434\u0438\u043e\u0442\u043e \u0435 \u043d\u0430 \u0434\u0440\u0443\u0433 \u0435\u0437\u0438\u043a.", + "OptionOnlyForcedSubtitlesHelp": "\u0421\u0430\u043c\u043e \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u0438, \u043c\u0430\u0440\u043a\u0438\u0440\u0430\u043d\u0438 \u043a\u0430\u0442\u043e \u043f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u043d\u0438, \u0449\u0435 \u0431\u044a\u0434\u0430\u0442 \u0437\u0430\u0440\u0435\u0436\u0434\u0430\u043d\u0438", + "OptionAlwaysPlaySubtitlesHelp": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u0438, \u043e\u0442\u0433\u043e\u0432\u0430\u0440\u044f\u0449\u0438 \u043d\u0430 \u0435\u0437\u0438\u043a\u043e\u0432\u043e\u0442\u043e \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u043d\u0438\u0435, \u0449\u0435 \u0431\u044a\u0434\u0430\u0442 \u0437\u0430\u0440\u0435\u0436\u0434\u0430\u043d\u0438 \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u043e\u0442 \u0435\u0437\u0438\u043a\u0430 \u043d\u0430 \u0430\u0443\u0434\u0438\u043e\u0442\u043e.", + "OptionNoSubtitlesHelp": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u0438 \u043d\u044f\u043c\u0430 \u0434\u0430 \u0431\u044a\u0434\u0430\u0442 \u0437\u0430\u0440\u0435\u0436\u0434\u0430\u043d\u0438 \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435.", + "TabProfiles": "\u041f\u0440\u043e\u0444\u0438\u043b\u0438", + "TabSecurity": "\u0417\u0430\u0449\u0438\u0442\u0430", + "ButtonAddUser": "\u0414\u043e\u0431\u0430\u0432\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b", + "ButtonAddLocalUser": "\u0414\u043e\u0431\u0430\u0432\u0438 \u043b\u043e\u043a\u0430\u043b\u0435\u043d \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b", + "ButtonInviteUser": "\u041f\u043e\u043a\u0430\u043d\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b", + "ButtonSave": "\u0417\u0430\u043f\u043e\u043c\u043d\u0438", + "ButtonResetPassword": "\u041d\u0443\u043b\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u043f\u0430\u0440\u043e\u043b\u0430", + "LabelNewPassword": "\u041d\u043e\u0432\u0430 \u043f\u0430\u0440\u043e\u043b\u0430:", + "LabelNewPasswordConfirm": "\u041d\u043e\u0432\u0430 \u043f\u0430\u0440\u043e\u043b\u0430(\u043e\u0442\u043d\u043e\u0432\u043e):", + "HeaderCreatePassword": "\u041d\u0430\u043f\u0440\u0430\u0432\u0438 \u043f\u0430\u0440\u043e\u043b\u0430", + "LabelCurrentPassword": "\u0422\u0435\u043a\u0443\u0449\u0430 \u043f\u0430\u0440\u043e\u043b\u0430:", + "LabelMaxParentalRating": "\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u043d\u043e \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u0441\u043a\u0438 \u0440\u0435\u0439\u0442\u0438\u043d\u0433:", + "MaxParentalRatingHelp": "\u0421\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435 \u0441 \u043f\u043e-\u0432\u0438\u0441\u043e\u043a \u0440\u0435\u0439\u0442\u0438\u043d\u0433 \u0449\u0435 \u0431\u044a\u0434\u0435 \u0441\u043a\u0440\u0438\u0442\u043e \u043e\u0442 \u0442\u043e\u0437\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b.", + "LibraryAccessHelp": "\u0418\u0437\u0431\u0435\u0440\u0435\u0442\u0435 \u043c\u0435\u0434\u0438\u0439\u043d\u0438\u0442\u0435 \u043f\u0430\u043f\u043a\u0438, \u043a\u043e\u0438\u0442\u043e \u0434\u0430 \u0441\u043f\u043e\u0434\u0435\u043b\u0438\u0442\u0435 \u0441 \u0442\u043e\u0437\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b. \u0410\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0438\u0442\u0435 \u0449\u0435 \u043c\u043e\u0433\u0430\u0442 \u0434\u0430 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0430\u0442 \u0432\u0441\u0438\u0447\u043a\u0438 \u043f\u0430\u043f\u043a\u0438 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u0439\u043a\u0438 \u043c\u0435\u043d\u0438\u0434\u0436\u044a\u0440\u0430 \u043d\u0430 \u043c\u0435\u0442\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f.", + "ChannelAccessHelp": "\u0418\u0437\u0431\u0435\u0440\u0435\u0442\u0435 \u043a\u0430\u043d\u0430\u043b\u0438\u0442\u0435, \u043a\u043e\u0438\u0442\u043e \u0434\u0430 \u0441\u043f\u043e\u0434\u0435\u043b\u0438\u0442\u0435 \u0441 \u0442\u043e\u0437\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b. \u0410\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0438\u0442\u0435 \u0449\u0435 \u043c\u043e\u0433\u0430\u0442 \u0434\u0430 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0430\u0442 \u0432\u0441\u0438\u0447\u043a\u0438 \u043a\u0430\u043d\u0430\u043b\u0438 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u0439\u043a\u0438 \u043c\u0435\u043d\u0438\u0434\u0436\u044a\u0440\u0430 \u043d\u0430 \u043c\u0435\u0442\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f.", + "ButtonDeleteImage": "\u0418\u0437\u0442\u0440\u0438\u0439 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435", + "LabelSelectUsers": "\u0418\u0437\u0431\u0435\u0440\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0438:", + "ButtonUpload": "\u041a\u0430\u0447\u0438:", + "HeaderUploadNewImage": "\u041a\u0430\u0447\u0438 \u041d\u043e\u0432\u043e \u0418\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435:", + "LabelDropImageHere": "\u041f\u0443\u0441\u043d\u0438 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435\u0442\u043e \u0442\u0443\u043a", + "ImageUploadAspectRatioHelp": "1:1 \u043f\u0440\u0435\u043f\u043e\u0440\u044a\u0447\u0430\u043d\u0430 \u043f\u0440\u043e\u043f\u043e\u0440\u0446\u0438\u044f. \u0421\u0430\u043c\u043e JPG\/PNG", + "MessageNothingHere": "\u0422\u0443\u043a \u043d\u044f\u043c\u0430 \u043d\u0438\u0449\u043e.", + "MessagePleaseEnsureInternetMetadata": "\u041c\u043e\u043b\u044f, \u0443\u0432\u0435\u0440\u0435\u0442\u0435 \u0441\u0435 \u0447\u0435 \u0441\u0432\u0430\u043b\u044f\u043d\u0435\u0442\u043e \u043d\u0430 \u043c\u0435\u0442\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e\u0442 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u043e.", + "TabSuggested": "\u041f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u044f", + "TabLatest": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438", + "TabUpcoming": "\u041f\u0440\u0435\u0434\u0441\u0442\u043e\u044f\u0449\u0438", + "TabShows": "\u041f\u0440\u0435\u0434\u0430\u0432\u0430\u043d\u0438\u044f", + "TabEpisodes": "\u0415\u043f\u0438\u0437\u043e\u0434\u0438", + "TabGenres": "\u0416\u0430\u043d\u0440\u043e\u0432\u0435", + "TabPeople": "\u0425\u043e\u0440\u0430", + "TabNetworks": "\u041c\u0440\u0435\u0436\u0438", + "HeaderUsers": "\u041f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0438", + "HeaderFilters": "\u0424\u0438\u043b\u0442\u0440\u0438:", + "ButtonFilter": "\u0424\u0438\u043b\u0442\u044a\u0440", + "OptionFavorite": "\u041b\u044e\u0431\u0438\u043c\u0438:", + "OptionLikes": "\u0425\u0430\u0440\u0435\u0441\u0432\u0430\u043d\u0438\u044f", + "OptionDislikes": "\u041d\u0435\u0445\u0430\u0440\u0435\u0441\u0432\u0430\u043d\u0438\u044f", + "OptionActors": "\u0410\u043a\u0442\u044c\u043e\u0440\u0438", + "OptionGuestStars": "\u0413\u043e\u0441\u0442\u0443\u0432\u0430\u0449\u0438 \u0437\u0432\u0435\u0437\u0434\u0438", + "OptionDirectors": "\u0420\u0435\u0436\u0438\u0441\u044c\u043e\u0440\u0438", + "OptionWriters": "\u041f\u0438\u0441\u0430\u0442\u0435\u043b\u0438", + "OptionProducers": "\u041f\u0440\u043e\u0434\u0443\u0446\u0435\u043d\u0442\u0438", + "HeaderResume": "\u041f\u0440\u043e\u0436\u044a\u043b\u0436\u0438", + "HeaderNextUp": "\u0421\u043b\u0435\u0434\u0432\u0430", + "NoNextUpItemsMessage": "\u041d\u0438\u0449\u043e \u043d\u0435 \u0435 \u043d\u0430\u043c\u0435\u0440\u0435\u043d\u043e. \u0417\u0430\u043f\u043e\u0447\u043d\u0435\u0442\u0435 \u0434\u0430 \u0433\u043b\u0435\u0434\u0430\u0442\u0435 \u0432\u0430\u0448\u0438\u0442\u0435 \u043f\u0440\u0435\u0434\u0430\u0432\u0430\u043d\u0438\u044f!", + "HeaderLatestEpisodes": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438 \u0415\u043f\u0438\u0437\u043e\u0434\u0438", + "HeaderPersonTypes": "\u0422\u0438\u043f\u043e\u0432\u0435 \u0425\u043e\u0440\u0430:", + "TabSongs": "\u041f\u0435\u0441\u043d\u0438", + "TabAlbums": "\u0410\u043b\u0431\u0443\u043c\u0438", + "TabArtists": "\u0410\u0440\u0442\u0438\u0441\u0442\u0438", + "TabAlbumArtists": "\u0410\u043b\u0431\u0443\u043c\u043e\u0432\u0438 \u0410\u0440\u0442\u0438\u0441\u0442\u0438", + "TabMusicVideos": "\u041c\u0443\u0437\u0438\u043a\u0430\u043b\u043d\u0438 \u043a\u043b\u0438\u043f\u043e\u0432\u0435", + "ButtonSort": "\u041f\u043e\u0434\u0440\u0435\u0434\u0438", + "HeaderSortBy": "\u041f\u043e\u0434\u0440\u0435\u0434\u0438 \u043f\u043e:", + "HeaderSortOrder": "\u0420\u0435\u0434 \u043d\u0430 \u043f\u043e\u0434\u0440\u0435\u0434\u0431\u0430:", + "OptionPlayed": "\u041f\u0443\u0441\u043a\u0430\u043d\u0438", + "OptionUnplayed": "\u041d\u0435 \u043f\u0443\u0441\u043a\u0430\u043d\u0438", + "OptionAscending": "\u0412\u044a\u0437\u0445\u043e\u0434\u044f\u0449", + "OptionDescending": "\u041d\u0438\u0437\u0445\u043e\u0434\u044f\u0449", + "OptionRuntime": "\u0412\u0440\u0435\u043c\u0435\u0442\u0440\u0430\u0435\u043d\u0435", + "OptionReleaseDate": "\u0414\u0430\u0442\u0430 \u043d\u0430 \u0438\u0437\u0434\u0430\u0432\u0430\u043d\u0435", + "OptionPlayCount": "\u0411\u0440\u043e\u0439 \u043f\u0443\u0441\u043a\u0430\u043d\u0438\u044f", + "OptionDatePlayed": "\u0414\u0430\u0442\u0430 \u043d\u0430 \u043f\u0443\u0441\u043a\u0430\u043d\u0435", + "OptionDateAdded": "\u0414\u0430\u0442\u0430 \u043d\u0430 \u0434\u043e\u0431\u0430\u0432\u044f\u043d\u0435", + "OptionAlbumArtist": "\u0410\u043b\u0431\u0443\u043c\u043e\u0432 \u0410\u0440\u0442\u0438\u0441\u0442", + "OptionArtist": "\u0410\u0440\u0442\u0438\u0441\u0442", + "OptionAlbum": "\u0410\u043b\u0431\u0443\u043c", + "OptionTrackName": "\u0418\u043c\u0435 \u043d\u0430 \u043f\u0435\u0441\u0435\u043d\u0442\u0430:", + "OptionCommunityRating": "\u041e\u0431\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u0430 \u043e\u0449\u0435\u043d\u043a\u0430", + "OptionNameSort": "Name", + "OptionFolderSort": "\u041f\u0430\u043f\u043a\u0438", + "OptionBudget": "\u0411\u044e\u0434\u0436\u0435\u0442", + "OptionRevenue": "\u041f\u0440\u0438\u0445\u043e\u0434\u0438", + "OptionPoster": "\u041f\u043b\u0430\u043a\u0430\u0442", + "OptionPosterCard": "\u041a\u0430\u0440\u0442\u0430 \u043f\u043b\u0430\u043a\u0430\u0442", + "OptionBackdrop": "\u0424\u043e\u043d", + "OptionTimeline": "\u0413\u0440\u0430\u0444\u0438\u043a", + "OptionThumb": "\u041c\u0438\u043d\u0438\u0430\u0442\u044e\u0440\u0430", + "OptionThumbCard": "\u041a\u0430\u0440\u0442\u0430 \u043c\u0438\u043d\u0438\u0430\u0442\u044e\u0440\u0430", + "OptionBanner": "\u0411\u0430\u043d\u0435\u0440", + "OptionCriticRating": "\u041e\u0446\u0435\u043d\u043a\u0430 \u043d\u0430 \u043a\u0440\u0438\u0442\u0438\u0446\u0438\u0442\u0435", + "OptionVideoBitrate": "\u0412\u0438\u0434\u0435\u043e \u0431\u0438\u0442\u0440\u0435\u0439\u0442", + "OptionResumable": "\u0412\u044a\u0437\u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c\u043e\u0441\u0442", + "ScheduledTasksHelp": "\u0426\u044a\u043a\u043d\u0435\u0442\u0435 \u043d\u0430 \u0437\u0430\u0434\u0430\u0447\u0430, \u0437\u0430 \u0434\u0430 \u043d\u0430\u0433\u043b\u0430\u0441\u0438\u0442\u0435 \u043f\u043b\u0430\u043d\u0430 \u045d.", + "ScheduledTasksTitle": "\u041f\u043b\u0430\u043d\u0438\u0440\u0430\u043d\u0438 \u0417\u0430\u0434\u0430\u0447\u0438", + "TabMyPlugins": "\u041c\u043e\u0438\u0442\u0435 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438", + "TabCatalog": "\u041a\u0430\u0442\u0430\u043b\u043e\u0433", + "PluginsTitle": "\u041f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438", + "HeaderAutomaticUpdates": "\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0438 \u0412\u044a\u0437\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f", + "HeaderNowPlaying": "\u0421\u0435\u0433\u0430 \u0412\u044a\u0437\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0436\u0434\u0430\u043d\u043e:", + "HeaderLatestAlbums": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438 \u0410\u043b\u0431\u0443\u043c\u0438", + "HeaderLatestSongs": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438 \u041f\u0435\u0441\u043d\u0438", + "HeaderRecentlyPlayed": "\u0421\u043a\u043e\u0440\u043e \u041f\u0443\u0441\u043a\u0430\u043d\u0438", + "HeaderFrequentlyPlayed": "\u0427\u0435\u0441\u0442\u043e \u041f\u0443\u0441\u043a\u0430\u043d\u0438", + "DevBuildWarning": "\u0412\u0435\u0440\u0441\u0438\u0438\u0442\u0435 \u0437\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u0446\u0438 \u0441\u0430 \u043d\u0430\u0439-\u043d\u043e\u0432\u043e\u0442\u043e. \u0422\u0435 \u0441\u0435 \u0432\u044a\u0437\u043e\u0431\u043d\u043e\u0432\u044f\u0432\u0430\u0442 \u0447\u0435\u0441\u0442\u043e, \u043d\u043e \u043d\u0435 \u0441\u0435 \u0442\u0435\u0441\u0442\u0432\u0430\u0442. \u041c\u043e\u0436\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u0442\u043e \u0434\u0430 \u0441\u0435 \u0447\u0443\u043f\u0438 \u0438 \u0446\u0435\u043b\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438\u0437\u043e\u0431\u0449\u043e \u0434\u0430 \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u044f\u0442.", + "LabelVideoType": "\u0422\u0438\u043f \u043d\u0430 \u0432\u0438\u0434\u0435\u043e\u0442\u043e:", + "OptionBluray": "Bluray", + "OptionDvd": "Dvd", + "OptionIso": "Iso", + "Option3D": "3D", + "LabelFeatures": "\u0424\u0443\u043d\u043a\u0446\u0438\u0438:", + "LabelService": "\u0423\u0441\u043b\u0443\u0433\u0430:", + "LabelStatus": "\u0421\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435:", + "LabelVersion": "\u0412\u0435\u0440\u0441\u0438\u044f:", + "LabelLastResult": "\u041f\u043e\u0441\u043b\u0435\u0434\u0435\u043d \u0440\u0435\u0437\u0443\u043b\u0442\u0430\u0442:", + "OptionHasSubtitles": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u0438", + "OptionHasTrailer": "\u0422\u0440\u0435\u0439\u043b\u044a\u0440", + "OptionHasThemeSong": "\u0424\u043e\u043d\u043e\u0432\u0430 \u041f\u0435\u0441\u0435\u043d", + "OptionHasThemeVideo": "\u0424\u043e\u043d\u043e\u0432\u043e \u0412\u0438\u0434\u0435\u043e", + "TabMovies": "\u0424\u0438\u043b\u043c\u0438", + "TabStudios": "\u0421\u0442\u0443\u0434\u0438\u0430", + "TabTrailers": "\u0422\u0440\u0435\u0439\u043b\u044a\u0440\u0438", + "LabelArtists": "\u0410\u0440\u0442\u0438\u0441\u0442\u0438:", + "LabelArtistsHelp": "\u041e\u0442\u0434\u0435\u043b\u0435\u0442\u0435 \u043d\u044f\u043a\u043e\u043b\u043a\u043e \u0441 ;", + "HeaderLatestMovies": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438 \u0424\u0438\u043b\u043c\u0438", + "HeaderLatestTrailers": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438 \u0422\u0440\u0435\u0439\u043b\u044a\u0440\u0438", + "OptionHasSpecialFeatures": "\u0421\u043f\u0435\u0446\u0438\u0430\u043b\u043d\u0438 \u0414\u043e\u0431\u0430\u0432\u043a\u0438", + "OptionImdbRating": "IMDb \u0420\u0435\u0439\u0442\u0438\u043d\u0433", + "OptionParentalRating": "\u0420\u043e\u0434\u0438\u0442\u0435\u043b\u0441\u043a\u0438 \u0420\u0435\u0439\u0442\u0438\u043d\u0433", + "OptionPremiereDate": "\u0414\u0430\u0442\u0430 \u043d\u0430 \u043f\u0440\u0435\u043c\u0438\u0435\u0440\u0430", + "TabBasic": "\u041e\u0441\u043d\u043e\u0432\u043d\u0438", + "TabAdvanced": "\u0414\u043e\u043f\u044a\u043b\u043d\u0438\u0442\u0435\u043b\u043d\u0438", + "HeaderStatus": "\u0421\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435:", + "OptionContinuing": "\u041f\u0440\u043e\u0434\u044a\u043b\u0436\u0430\u0432\u0430\u0449\u043e", + "OptionEnded": "\u041f\u0440\u0438\u043a\u043b\u044e\u0447\u0438\u043b\u043e", + "HeaderAirDays": "\u0414\u043d\u0438 \u043d\u0430 \u0438\u0437\u043b\u044a\u0447\u0432\u0430\u043d\u0435", + "OptionSunday": "\u041d\u0435\u0434\u0435\u043b\u044f", + "OptionMonday": "\u041f\u043e\u043d\u0435\u0434\u0435\u043b\u043d\u0438\u043a", + "OptionTuesday": "\u0412\u0442\u043e\u0440\u043d\u0438\u043a", + "OptionWednesday": "\u0421\u0440\u044f\u0434\u0430", + "OptionThursday": "\u0427\u0435\u0442\u0432\u044a\u0440\u0442\u044a\u043a", + "OptionFriday": "\u041f\u0435\u0442\u044a\u043a", + "OptionSaturday": "\u0421\u044a\u0431\u043e\u0442\u0430", + "HeaderManagement": "\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435", + "LabelManagement": "\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435:", + "OptionMissingImdbId": "\u041b\u0438\u043f\u0441\u0432\u0430\u0449\u043e IMDb ID", + "OptionMissingTvdbId": "\u041b\u0438\u043f\u0441\u0432\u0430\u0449\u043e TheTVDB ID", + "OptionMissingOverview": "\u041b\u0438\u043f\u0441\u0432\u0430\u0449\u0430 \u043e\u0431\u0449\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f", + "OptionFileMetadataYearMismatch": "\u0420\u0430\u0437\u043b\u0438\u0447\u0438\u0435 \u043d\u0430 \u0433\u043e\u0434\u0438\u043d\u0430 \u0432\u044a\u0432 \u0424\u0430\u0439\u043b\/\u041c\u0435\u0442\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f", + "TabGeneral": "\u0413\u043b\u0430\u0432\u043d\u043e", + "TitleSupport": "\u041f\u043e\u0434\u0434\u0440\u044a\u0436\u043a\u0430", + "TabLog": "\u041b\u043e\u0433", + "TabAbout": "\u041e\u0442\u043d\u043e\u0441\u043d\u043e", + "TabSupporterKey": "\u041f\u043e\u0434\u0434\u0440\u044a\u0436\u043d\u0438\u043a\u043e\u0432 \u043a\u043b\u044e\u0447", + "TabBecomeSupporter": "\u0421\u0442\u0430\u043d\u0438 \u043f\u043e\u0434\u0434\u0440\u044a\u0436\u043d\u0438\u043a", + "MediaBrowserHasCommunity": "Media Browser \u0438\u043c\u0430 \u043f\u0440\u043e\u0446\u044a\u0444\u0442\u044f\u0432\u0430\u0449\u0430 \u043e\u0431\u0449\u043d\u043e\u0441\u0442 \u043e\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0438 \u0438 \u0441\u044a\u0442\u0440\u0443\u0434\u043d\u0438\u0446\u0438.", + "CheckoutKnowledgeBase": "\u041f\u0440\u043e\u0432\u0435\u0440\u0435\u0442\u0435 \u043d\u0430\u0448\u0430\u0442\u0430 \u0431\u0430\u0437\u0430 \u043e\u0442 \u0437\u043d\u0430\u043d\u0438\u044f, \u0437\u0430 \u0434\u0430 \u0432\u0438 \u043f\u043e\u043c\u043e\u0433\u043d\u0435 \u0434\u0430 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0435 \u043d\u0430\u0439-\u0434\u043e\u0431\u0440\u043e\u0442\u043e \u043e\u0442 Media Browser.", + "SearchKnowledgeBase": "\u0422\u044a\u0440\u0441\u0438 \u0432 \u0411\u0430\u0437\u0430\u0442\u0430 \u043e\u0442 \u0417\u043d\u0430\u043d\u0438\u044f", + "VisitTheCommunity": "\u041f\u043e\u0441\u0435\u0442\u0435\u0442\u0435 \u041e\u0431\u0449\u0435\u0441\u0442\u0432\u043e\u0442\u043e", + "VisitMediaBrowserWebsite": "\u041f\u043e\u0441\u0435\u0442\u0435\u0442\u0435 \u0443\u0435\u0431-\u0441\u0430\u0439\u0442\u0430 \u043d\u0430 Media Browser", + "VisitMediaBrowserWebsiteLong": "\u041f\u043e\u0441\u0435\u0442\u0435\u0442\u0435 \u0443\u0435\u0431-\u0441\u0430\u0439\u0442\u0430 \u043d\u0430 Media Browser, \u0437\u0430 \u0434\u0430 \u0443\u0437\u043d\u0430\u0435\u0442\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0442\u0435 \u043d\u043e\u0432\u0438\u043d\u0438 \u0438 \u0434\u0430 \u0441\u0442\u0435 \u0432 \u043a\u0440\u0430\u043a \u0441 \u0431\u043b\u043e\u0433\u0430 \u043d\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u0446\u0438\u0442\u0435.", + "OptionHideUser": "\u0421\u043a\u0440\u0438\u0439 \u0442\u043e\u0437\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b \u043e\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0438\u0442\u0435 \u0437\u0430 \u0432\u0445\u043e\u0434", + "OptionHideUserFromLoginHelp": "\u041f\u043e\u043b\u0435\u0437\u043d\u043e \u0437\u0430 \u0447\u0430\u0441\u0442\u043d\u0438 \u0438\u043b\u0438 \u0441\u043a\u0440\u0438\u0442\u0438 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0441\u043a\u0438 \u0430\u043a\u0430\u0443\u043d\u0442\u0438. \u041f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u044f\u0442 \u0449\u0435 \u0442\u0440\u044f\u0431\u0432\u0430 \u0434\u0430 \u0432\u043b\u0435\u0437\u0435 \u0440\u044a\u0447\u043d\u043e \u0447\u0440\u0435\u0437 \u0432\u044a\u0432\u0435\u0436\u0434\u0430\u043d\u0435 \u043d\u0430 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0441\u043a\u043e \u0438\u043c\u0435 \u0438 \u043f\u0430\u0440\u043e\u043b\u0430.", + "OptionDisableUser": "\u0414\u0435\u0437\u0430\u043a\u0442\u0438\u0432\u0438\u0440\u0430\u0439\u0442\u0435 \u0442\u043e\u0437\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b", + "OptionDisableUserHelp": "\u0410\u043a\u043e \u0435 \u0434\u0435\u0437\u0430\u043a\u0442\u0438\u0432\u0438\u0440\u0430\u043d, \u0441\u044a\u0440\u0432\u044a\u0440\u044a\u0442 \u043d\u044f\u043c\u0430 \u0434\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u0438 \u043a\u0430\u043a\u0432\u0438\u0442\u043e \u0438 \u0434\u0430 \u0431\u0438\u043b\u043e \u0432\u0440\u044a\u0437\u043a\u0438 \u043e\u0442 \u0442\u043e\u0437\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b. \u0421\u044a\u0449\u0435\u0441\u0442\u0432\u0443\u0432\u0430\u0449\u0438\u0442\u0435 \u0432\u0440\u044a\u0437\u043a\u0438 \u0449\u0435 \u0431\u044a\u0434\u0430\u0442 \u0432\u043d\u0435\u0437\u0430\u043f\u043d\u043e \u043f\u0440\u0435\u043a\u0440\u0430\u0442\u0435\u043d\u0438.", + "HeaderAdvancedControl": "\u0414\u043e\u043f\u044a\u043b\u043d\u0438\u0442\u0435\u043b\u0435\u043d \u041a\u043e\u043d\u0442\u0440\u043e\u043b", + "LabelName": "\u0418\u043c\u0435:", + "ButtonHelp": "\u041f\u043e\u043c\u043e\u0449", + "OptionAllowUserToManageServer": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438 \u043d\u0430 \u0442\u043e\u0437\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b \u0434\u0430 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0432\u0430 \u0441\u044a\u0440\u0432\u044a\u0440\u0430", + "HeaderFeatureAccess": "\u0414\u043e\u0441\u0442\u044a\u043f \u0434\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u0438", + "OptionAllowMediaPlayback": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438 \u043f\u0443\u0441\u043a\u0430\u043d\u0435 \u043d\u0430 \u043c\u0435\u0434\u0438\u044f", + "OptionAllowBrowsingLiveTv": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438 \u0440\u0430\u0437\u0433\u043b\u0435\u0436\u0434\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0442\u0435\u043b\u0435\u0432\u0438\u0437\u0438\u044f \u043d\u0430 \u0436\u0438\u0432\u043e", + "OptionAllowDeleteLibraryContent": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438 \u0438\u0437\u0442\u0440\u0438\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435 \u043e\u0442 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u0442\u0430", + "OptionAllowManageLiveTv": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u0430 \u0437\u0430\u043f\u0438\u0441 \u043d\u0430 \u0442\u0435\u043b\u0435\u0432\u0438\u0437\u0438\u044f \u043d\u0430 \u0436\u0438\u0432\u043e", + "OptionAllowRemoteControlOthers": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438 \u043e\u0442\u0434\u0430\u043b\u0435\u0447\u0435\u043d \u043a\u043e\u043d\u0442\u0440\u043e\u043b \u043d\u0430 \u0434\u0440\u0443\u0433\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0438", + "OptionAllowRemoteSharedDevices": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438 \u043e\u0442\u0434\u0430\u043b\u0435\u0447\u0435\u043d \u043a\u043e\u043d\u0442\u0440\u043e\u043b \u043d\u0430 \u0441\u043f\u043e\u0434\u0435\u043b\u0435\u043d\u0438 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430", + "OptionAllowRemoteSharedDevicesHelp": "DLNA \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u0441\u0435 \u0441\u0447\u0438\u0442\u0430\u0442 \u0437\u0430 \u0441\u043f\u043e\u0434\u0435\u043b\u0435\u043d\u0438 \u0434\u043e\u043a\u0430\u0442\u043e \u043d\u044f\u043a\u043e\u0439 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b \u043d\u0435 \u0437\u0430\u043f\u043e\u0447\u043d\u0435 \u0434\u0430 \u0433\u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u0430.", + "HeaderRemoteControl": "\u041e\u0442\u0434\u0430\u043b\u0435\u0447\u0435\u043d \u041a\u043e\u043d\u0442\u0440\u043e\u043b", + "OptionMissingTmdbId": "\u041b\u0438\u043f\u0441\u0432\u0430\u0449\u043e Tmdb ID", + "OptionIsHD": "HD", + "OptionIsSD": "SD", + "OptionMetascore": "\u041c\u0435\u0442\u0430 \u0442\u043e\u0447\u043a\u0438", + "ButtonSelect": "\u0418\u0437\u0431\u0435\u0440\u0438", + "ButtonGroupVersions": "\u0413\u0440\u0443\u043f\u0438\u0440\u0430\u0439 \u0432\u0435\u0440\u0441\u0438\u0438\u0442\u0435", + "ButtonAddToCollection": "Add to Collection", + "PismoMessage": "\u0418\u0437\u043f\u043e\u043b\u0437\u0430\u043d\u0435 \u043d\u0430 Pismo File Mount \u0447\u0440\u0435\u0437 \u0434\u0430\u0440\u0435\u043d \u043b\u0438\u0446\u0435\u043d\u0437.", + "TangibleSoftwareMessage": "\u0418\u0437\u043f\u043e\u043b\u0437\u0430\u043d\u0435 \u043d\u0430 Tangible Solutions Java\/C# converters \u0447\u0440\u0435\u0437 \u0434\u0430\u0440\u0435\u043d \u043b\u0438\u0446\u0435\u043d\u0437.", + "HeaderCredits": "\u041a\u0440\u0435\u0434\u0438\u0442\u0438", + "PleaseSupportOtherProduces": "Please support other free products we utilize:", + "VersionNumber": "\u0412\u0435\u0440\u0441\u0438\u044f {0}", + "TabPaths": "\u041f\u044a\u0442\u0438\u0449\u0430", + "TabServer": "\u0421\u044a\u0440\u0432\u044a\u0440", + "TabTranscoding": "\u041f\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u0430\u043d\u0435", + "TitleAdvanced": "\u0414\u043e\u043f\u044a\u043b\u043d\u0438\u0442\u0435\u043b\u043d\u0438", + "LabelAutomaticUpdateLevel": "\u041d\u0438\u0432\u043e \u043d\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043d\u0435", + "OptionRelease": "\u041e\u0444\u0438\u0446\u0438\u0430\u043b\u043d\u043e \u0438\u0437\u0434\u0430\u043d\u0438\u0435", + "OptionBeta": "\u0411\u0435\u0442\u0430", + "OptionDev": "\u0417\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u0446\u0438 (\u041d\u0435\u0441\u0442\u0430\u0431\u0438\u043b\u0435\u043d)", + "LabelAllowServerAutoRestart": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438 \u043d\u0430 \u0441\u044a\u0440\u0432\u044a\u0440\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u043d \u0440\u0435\u0441\u0442\u0430\u0440\u0442 \u0437\u0430 \u043f\u0440\u0438\u043b\u0430\u0433\u0430\u043d\u0435 \u043d\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438\u0442\u0435", + "LabelAllowServerAutoRestartHelp": "\u0421\u044a\u0440\u0432\u044a\u0440\u044a\u0442 \u0449\u0435 \u0441\u0435 \u0440\u0435\u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430 \u0441\u0430\u043c\u043e \u043f\u0440\u0435\u0437 \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0442\u043e \u0441\u0438 \u0432\u0440\u0435\u043c\u0435, \u043a\u043e\u0433\u0430\u0442\u043e \u043d\u044f\u043c\u0430 \u0430\u043a\u0442\u0438\u0432\u043d\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0438.", + "LabelEnableDebugLogging": "\u0410\u043a\u0442\u0438\u0432\u0438\u0440\u0430\u0439 \u043b\u043e\u0433\u0438\u043d\u0433 \u043d\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0437\u0430 \u0433\u0440\u0435\u0448\u043a\u0438", + "LabelRunServerAtStartup": "\u041f\u0443\u0441\u043a\u0430\u043d\u0435 \u043d\u0430 \u0441\u044a\u0440\u0432\u044a\u0440\u0430 \u043f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u043d\u0435", + "LabelRunServerAtStartupHelp": "\u0422\u043e\u0432\u0430 \u0449\u0435 \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430 \u0438\u043a\u043e\u043d\u043a\u0430\u0442\u0430 \u0432 \u0442\u0440\u0435\u0439 \u043b\u0435\u043d\u0442\u0430\u0442\u0430 \u043f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 Windows. \u0417\u0430 \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 Windows service, \u043c\u0430\u0445\u043d\u0435\u0442\u0435 \u043e\u0442\u043c\u0435\u0442\u043a\u0430\u0442\u0430 \u043e\u0442 \u0442\u043e\u0432\u0430 \u0438 \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u0439\u0442\u0435 \u0443\u0441\u043b\u0443\u0433\u0430\u0442\u0430 \u043e\u0442 Windows \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043d\u0438\u044f \u043f\u0430\u043d\u0435\u043b. \u041c\u043e\u043b\u044f, \u043e\u0442\u0431\u0435\u043b\u0435\u0436\u0435\u0442\u0435, \u0447\u0435 \u0434\u0432\u0435\u0442\u0435 \u043d\u0435 \u043c\u043e\u0433\u0430\u0442 \u0434\u0430 \u0431\u044a\u0434\u0430\u0442 \u043f\u0443\u0441\u043d\u0430\u0442\u0438 \u043f\u043e \u0435\u0434\u043d\u043e \u0438 \u0441\u044a\u0449\u043e \u0432\u0440\u0435\u043c\u0435, \u0442\u0430\u043a\u0430 \u0447\u0435 \u0449\u0435 \u0442\u0440\u044f\u0431\u0432\u0430 \u0434\u0430 \u0438\u0437\u043a\u043b\u044e\u0447\u0438\u0442\u0435 \u0438\u043a\u043e\u043d\u043a\u0430\u0442\u0430 \u0432 \u0442\u0440\u0435\u0439 \u043b\u0435\u043d\u0442\u0430\u0442\u0430 \u043f\u0440\u0435\u0434\u0438 \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0443\u0441\u043b\u0443\u0433\u0430\u0442\u0430.", + "ButtonSelectDirectory": "\u0418\u0437\u0431\u0435\u0440\u0438 \u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f", + "LabelCustomPaths": "\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u0442\u0435 \u043f\u044a\u0442\u0438\u0449\u0430 \u043f\u043e \u0438\u0437\u0431\u043e\u0440 \u043a\u044a\u0434\u0435\u0442\u043e \u0436\u0435\u043b\u0430\u0435\u0442\u0435. \u041e\u0441\u0442\u0430\u0432\u0435\u0442\u0435 \u043f\u043e\u043b\u0435\u0442\u0430\u0442\u0430 \u043f\u0440\u0430\u0437\u043d\u0438 \u0437\u0430 \u0434\u0430 \u0441\u0435 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u0442 \u043f\u044a\u0442\u0438\u0449\u0430\u0442\u0430 \u043f\u043e \u0438\u0437\u0431\u043e\u0440.", + "LabelCachePath": "\u041f\u044a\u0442 \u043a\u044a\u043c \u043a\u0435\u0448\u0430:", + "LabelCachePathHelp": "\u0417\u0430\u0434\u0430\u0439\u0442\u0435 \u043c\u044f\u0441\u0442\u043e \u043f\u043e \u0438\u0437\u0431\u043e\u0440 \u0437\u0430 \u0441\u044a\u0440\u0432\u044a\u0440\u043d\u0438 \u043a\u0435\u0448 \u0444\u0430\u0439\u043b\u043e\u0432\u0435, \u043a\u0430\u0442\u043e \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f.", + "LabelImagesByNamePath": "\u0418\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043f\u043e \u043f\u044a\u0442 \u043d\u0430 \u0438\u043c\u0435\u0442\u043e:", + "LabelImagesByNamePathHelp": "\u0417\u0430\u0434\u0430\u0439\u0442\u0435 \u043c\u044f\u0441\u0442\u043e \u043f\u043e \u0438\u0437\u0431\u043e\u0440 \u0437\u0430 \u0441\u0432\u0430\u043b\u0435\u043d\u0438 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u0430\u043a\u0442\u044c\u043e\u0440\u0438, \u0436\u0430\u043d\u0440\u043e\u0432\u0435 \u0438 \u0441\u0442\u0443\u0434\u0438\u0430.", + "LabelMetadataPath": "\u041f\u044a\u0442 \u043a\u044a\u043c \u043c\u0435\u0442\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f\u0442\u0430:", + "LabelMetadataPathHelp": "\u0417\u0430\u0434\u0430\u0439\u0442\u0435 \u043c\u044f\u0441\u0442\u043e \u043f\u043e \u0438\u0437\u0431\u043e\u0440 \u0437\u0430 \u0441\u0432\u0430\u043b\u0435\u043d\u043e \u0438\u0437\u043a\u0443\u0441\u0442\u0432\u043e \u0438 \u043c\u0435\u0442\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f, \u0430\u043a\u043e \u043d\u0435 \u0441\u0435 \u0437\u0430\u043f\u0438\u0441\u0432\u0430\u0442 \u0432 \u043f\u0430\u043f\u043a\u0438\u0442\u0435 \u043d\u0430 \u043c\u0435\u0434\u0438\u044f\u0442\u0430.", + "LabelTranscodingTempPath": "\u0412\u0440\u0435\u043c\u0435\u043d\u0435\u043d \u043f\u044a\u0442 \u043d\u0430 \u043f\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u0430\u043d\u0435:", + "LabelTranscodingTempPathHelp": "\u0422\u0430\u0437\u0438 \u043f\u0430\u043f\u043a\u0430 \u0441\u044a\u0434\u044a\u0440\u0436\u0430 \u0440\u0430\u0431\u043e\u0442\u043d\u0438 \u0444\u0430\u0439\u043b\u043e\u0432\u0435 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u043d\u0438 \u043e\u0442 \u0442\u0440\u0430\u043d\u0441\u043a\u043e\u0434\u0435\u0440\u0430. \u0417\u0430\u0434\u0430\u0439\u0442\u0435 \u043c\u044f\u0441\u0442\u043e \u043f\u043e \u0438\u0437\u0431\u043e\u0440 \u0438\u043b\u0438 \u043e\u0441\u0442\u0430\u0432\u0435\u0442\u0435 \u043f\u0440\u0430\u0437\u043d\u043e \u0437\u0430 \u043c\u044f\u0441\u0442\u043e\u0442\u043e \u043f\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043d\u0435.", + "TabBasics": "\u041e\u0441\u043d\u043e\u0432\u0438", + "TabTV": "TV", + "TabGames": "\u0418\u0433\u0440\u0438", + "TabMusic": "\u041c\u0443\u0437\u0438\u043a\u0430", + "TabOthers": "\u0414\u0440\u0443\u0433\u043e", + "HeaderExtractChapterImagesFor": "\u0418\u0437\u0432\u0430\u0434\u0435\u043d\u0438 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u0433\u043b\u0430\u0432\u0438\u0442\u0435 \u0437\u0430:", + "OptionMovies": "\u0424\u0438\u043b\u043c\u0438", + "OptionEpisodes": "\u0415\u043f\u0438\u0437\u043e\u0434\u0438", + "OptionOtherVideos": "\u0414\u0440\u0443\u0433\u0438 \u043a\u043b\u0438\u043f\u043e\u0432\u0435", + "TitleMetadata": "\u041c\u0435\u0442\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f", + "LabelAutomaticUpdates": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0438\u0442\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f", + "LabelAutomaticUpdatesTmdb": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043e\u0442 TheMovieDB.org", + "LabelAutomaticUpdatesTvdb": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043e\u0442 TheTVDB.com", + "LabelAutomaticUpdatesFanartHelp": "\u0410\u043a\u043e \u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u043e, \u043d\u043e\u0432\u0438 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0449\u0435 \u0431\u044a\u0434\u0430\u0442 \u0441\u0432\u0430\u043b\u044f\u043d\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043a\u0430\u0442\u043e \u0441\u0435 \u0434\u043e\u0431\u0430\u0432\u044f\u0442 \u0432\u044a\u0432 fanart.tv. \u0412\u0435\u0447\u0435 \u0441\u044a\u0449\u0435\u0441\u0442\u0432\u0443\u0432\u0430\u0449\u0438 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043d\u044f\u043c\u0430 \u0434\u0430 \u0431\u044a\u0434\u0430\u0442 \u0437\u0430\u043c\u0435\u043d\u044f\u043d\u0438.", + "LabelAutomaticUpdatesTmdbHelp": "\u0410\u043a\u043e \u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u043e, \u043d\u043e\u0432\u0438 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0449\u0435 \u0431\u044a\u0434\u0430\u0442 \u0441\u0432\u0430\u043b\u044f\u043d\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043a\u0430\u0442\u043e \u0441\u0435 \u0434\u043e\u0431\u0430\u0432\u044f\u0442 \u0432\u044a\u0432 TheMovieDB.org. \u0412\u0435\u0447\u0435 \u0441\u044a\u0449\u0435\u0441\u0442\u0432\u0443\u0432\u0430\u0449\u0438 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043d\u044f\u043c\u0430 \u0434\u0430 \u0431\u044a\u0434\u0430\u0442 \u0437\u0430\u043c\u0435\u043d\u044f\u043d\u0438.", + "LabelAutomaticUpdatesTvdbHelp": "\u0410\u043a\u043e \u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u043e, \u043d\u043e\u0432\u0438 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0449\u0435 \u0431\u044a\u0434\u0430\u0442 \u0441\u0432\u0430\u043b\u044f\u043d\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043a\u0430\u0442\u043e \u0441\u0435 \u0434\u043e\u0431\u0430\u0432\u044f\u0442 \u0432\u044a\u0432 TheTVDB.com. \u0412\u0435\u0447\u0435 \u0441\u044a\u0449\u0435\u0441\u0442\u0432\u0443\u0432\u0430\u0449\u0438 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043d\u044f\u043c\u0430 \u0434\u0430 \u0431\u044a\u0434\u0430\u0442 \u0437\u0430\u043c\u0435\u043d\u044f\u043d\u0438.", + "LabelFanartApiKey": "\u041b\u0438\u0447\u0435\u043d API \u043a\u043b\u044e\u0447:", + "LabelFanartApiKeyHelp": "\u0417\u0430\u044f\u0432\u043a\u0438 \u0434\u043e fanart \u0431\u0435\u0437 \u043b\u0438\u0447\u0435\u043d API \u043a\u043b\u044e\u0447 \u0432\u0440\u044a\u0449\u0430\u0442 \u0440\u0435\u0437\u0443\u043b\u0442\u0430\u0442\u0438, \u043a\u043e\u0438\u0442\u043e \u0441\u0430 \u0431\u0438\u043b\u0438 \u043e\u0434\u043e\u0431\u0440\u0435\u043d\u0438 \u043f\u0440\u0435\u0434\u0438 \u043f\u043e\u0432\u0435\u0447\u0435 \u043e\u0442 7 \u0434\u043d\u0438. \u0421 \u043b\u0438\u0447\u0435\u043d API \u043a\u043b\u044e\u0447, \u0442\u043e\u0432\u0430 \u0432\u0440\u0435\u043c\u0435 \u043f\u0430\u0434\u0430 \u043d\u0430 48 \u0447\u0430\u0441\u0430, \u0430 \u0430\u043a\u043e \u0441\u0442\u0435 \u0438 fanart VIP \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b, \u0442\u043e \u0434\u043e\u043f\u044a\u043b\u043d\u0438\u0442\u0435\u043b\u043d\u043e \u0449\u0435 \u043f\u0430\u0434\u043d\u0435 \u0434\u043e \u043e\u043a\u043e\u043b\u043e 10 \u043c\u0438\u043d\u0443\u0442\u0438.", + "ExtractChapterImagesHelp": "\u0418\u0437\u0432\u043b\u0438\u0447\u0430\u043d\u0435 \u043d\u0430 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u0433\u043b\u0430\u0432\u0438\u0442\u0435 \u0449\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u0438 \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0438\u0442\u0435 \u0434\u0430 \u043f\u043e\u043a\u0430\u0437\u0432\u0430\u0442 \u0433\u0440\u0430\u0444\u0438\u0447\u043d\u0438 \u043c\u0435\u043d\u044e\u0442\u0430 \u0437\u0430 \u0438\u0437\u0431\u043e\u0440 \u043d\u0430 \u0441\u0446\u0435\u043d\u0430. \u041f\u0440\u043e\u0446\u0435\u0441\u044a\u0442 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0431\u044a\u0434\u0435 \u0431\u0430\u0432\u0435\u043d, CPU-\u0438\u043d\u0442\u0435\u043d\u0437\u0438\u0432\u0435\u043d \u0438 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0438\u0437\u0438\u0441\u043a\u0432\u0430 \u043d\u044f\u043a\u043e\u043b\u043a\u043e \u0433\u0438\u0433\u0430\u0431\u0430\u0439\u0442\u0430 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e. \u0422\u043e \u0440\u0430\u0431\u043e\u0442\u0438 \u043a\u0430\u0442\u043e \u043d\u043e\u0449\u043d\u0430 \u043f\u043b\u0430\u043d\u0438\u0440\u0430\u043d\u0430 \u0437\u0430\u0434\u0430\u0447\u0430 \u0432 4 \u0447\u0430\u0441\u0430 \u0441\u0443\u0442\u0440\u0438\u043d\u0442\u0430, \u0432\u044a\u043f\u0440\u0435\u043a\u0438 \u0447\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430 \u0432 \u041f\u043b\u0430\u043d\u0438\u0440\u0430\u043d\u0438 \u0437\u0430\u0434\u0430\u0447\u0438. \u041d\u0435 \u0441\u0435 \u043f\u0440\u0435\u043f\u043e\u0440\u044a\u0447\u0432\u0430 \u0442\u0430\u0437\u0438 \u0437\u0430\u0434\u0430\u0447\u0430 \u0434\u0430 \u0441\u0435 \u0438\u0437\u043f\u044a\u043b\u043d\u044f\u0432\u0430 \u043f\u043e \u0432\u0440\u0435\u043c\u0435 \u043d\u0430 \u043f\u0438\u043a\u043e\u0432\u0438\u0442\u0435 \u0447\u0430\u0441\u043e\u0432\u0435 \u043d\u0430 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u043d\u0435.", + "LabelMetadataDownloadLanguage": "\u041f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u043d \u0435\u0437\u0438\u043a \u043d\u0430 \u0441\u0432\u0430\u043b\u044f\u043d\u0435:", + "ButtonAutoScroll": "\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u043d \u0441\u043a\u0440\u043e\u043b", + "LabelImageSavingConvention": "Image saving convention:", + "LabelImageSavingConventionHelp": "Media Browser \u0440\u0430\u0437\u043f\u043e\u0437\u043d\u0430\u0432\u0430 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043e\u0442 \u0433\u043e\u043b\u044f\u043c\u0430 \u0447\u0430\u0441\u0442 \u043c\u0435\u0434\u0438\u0439\u043d\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0418\u0437\u0431\u043e\u0440\u044a\u0442 \u0432\u0438 \u043d\u0430 \u043a\u043e\u043d\u0432\u0435\u043d\u0446\u0438\u044f \u043d\u0430 \u0438\u0437\u0442\u0435\u0433\u043b\u044f\u043d\u0435 \u0435 \u043f\u043e\u043b\u0435\u0437\u0435\u043d, \u0430\u043a\u043e \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u0442\u0435 \u0438 \u0434\u0440\u0443\u0433\u0438 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0438.", + "OptionImageSavingCompatible": "\u0421\u044a\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u0438 - Media Browser\/Kodi\/Plex", + "OptionImageSavingStandard": "\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0438 - MB2", + "ButtonSignIn": "\u0412\u043b\u0438\u0437\u0430\u043d\u0435", + "TitleSignIn": "\u0412\u043b\u0438\u0437\u0430\u043d\u0435", + "HeaderPleaseSignIn": "\u041c\u043e\u043b\u044f, \u0432\u043b\u0435\u0437\u0442\u0435", + "LabelUser": "\u041f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b:", + "LabelPassword": "\u041f\u0430\u0440\u043e\u043b\u0430:", + "ButtonManualLogin": "\u0412\u0445\u043e\u0434 \u0441 \u0438\u043c\u0435 \u0438 \u043f\u0430\u0440\u043e\u043b\u0430", + "PasswordLocalhostMessage": "\u041f\u0430\u0440\u043e\u043b\u0438\u0442\u0435 \u043d\u0435 \u0441\u0430 \u0437\u0430\u0434\u044a\u043b\u0436\u0438\u0442\u0435\u043b\u043d\u0438, \u043a\u043e\u0433\u0430\u0442\u043e \u0432\u043b\u0438\u0437\u0430\u0442\u0435 \u043e\u0442 localhost", + "TabGuide": "\u0420\u044a\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e", + "TabChannels": "\u041a\u0430\u043d\u0430\u043b\u0438", + "TabCollections": "\u041a\u043e\u043b\u0435\u043a\u0446\u0438\u0438", + "HeaderChannels": "\u041a\u0430\u043d\u0430\u043b\u0438", + "TabRecordings": "\u0417\u0430\u043f\u0438\u0441\u0438", + "TabScheduled": "\u041f\u043b\u0430\u043d\u0438\u0440\u0430\u043d\u0438", + "TabSeries": "\u041f\u0440\u0435\u0434\u0430\u0432\u0430\u043d\u0438\u044f", + "TabFavorites": "\u041b\u044e\u0431\u0438\u043c\u0438", + "TabMyLibrary": "\u041c\u043e\u044f\u0442\u0430 \u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430", + "ButtonCancelRecording": "\u041f\u0440\u0435\u043a\u044a\u0441\u043d\u0438 \u0417\u0430\u043f\u0438\u0441\u0432\u0430\u043d\u0435\u0442\u043e", + "HeaderPrePostPadding": "\u041f\u0440\u0435\u0434\u0435\u043d\/\u0417\u0430\u0434\u0435\u043d \u0431\u0430\u043b\u0430\u0441\u0442", + "LabelPrePaddingMinutes": "\u041f\u0440\u0435\u0434\u0435\u043d \u0431\u0430\u043b\u0430\u0441\u0442 \u0432 \u043c\u0438\u043d\u0443\u0442\u0438:", + "OptionPrePaddingRequired": "\u041f\u0440\u0435\u0434\u043d\u0438\u044f\u0442 \u0431\u0430\u043b\u0430\u0441\u0442 \u0435 \u0437\u0430\u0434\u044a\u043b\u0436\u0438\u0442\u0435\u043b\u0435\u043d, \u0437\u0430 \u0434\u0430 \u0437\u0430\u043f\u0438\u0441\u0432\u0430\u0442\u0435. (\u0414\u043e\u043f\u044a\u043b\u043d\u0438\u0442\u0435\u043b\u043d\u0438 \u043c\u0438\u043d\u0443\u0442\u0438 \u043f\u0440\u0435\u0434\u0438 \u043d\u0430\u0447\u0430\u043b\u043e\u0442\u043e)", + "LabelPostPaddingMinutes": "\u0417\u0430\u0434\u0435\u043d \u0431\u0430\u043b\u0430\u0441\u0442 \u0432 \u043c\u0438\u043d\u0443\u0442\u0438:", + "OptionPostPaddingRequired": "\u0417\u0430\u0434\u043d\u0438\u044f\u0442 \u0431\u0430\u043b\u0430\u0441\u0442 \u0435 \u0437\u0430\u0434\u044a\u043b\u0436\u0438\u0442\u0435\u043b\u0435\u043d, \u0437\u0430 \u0434\u0430 \u0437\u0430\u043f\u0438\u0441\u0432\u0430\u0442\u0435. (\u0414\u043e\u043f\u044a\u043b\u043d\u0438\u0442\u0435\u043b\u043d\u0438 \u043c\u0438\u043d\u0443\u0442\u0438 \u0441\u043b\u0435\u0434 \u043a\u0440\u0430\u044f)", + "HeaderWhatsOnTV": "\u0412 \u043c\u043e\u043c\u0435\u043d\u0442\u0430", + "HeaderUpcomingTV": "\u041f\u0440\u0435\u0434\u0441\u0442\u043e\u044f\u0449\u0430 TV", + "TabStatus": "\u0421\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435", + "TabSettings": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438", + "ButtonRefreshGuideData": "\u041e\u0431\u043d\u043e\u0432\u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f\u0442\u0430 \u0432 \u0433\u0438\u0434-\u0430", + "ButtonRefresh": "\u041e\u0431\u043d\u043e\u0432\u0438", + "ButtonAdvancedRefresh": "\u041e\u0431\u043d\u043e\u0432\u0438 \u0434\u043e\u043f\u044a\u043b\u043d\u0438\u0442\u0435\u043b\u043d\u043e", + "OptionPriority": "\u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442", + "OptionRecordOnAllChannels": "\u0417\u0430\u043f\u0438\u0441\u0432\u0430\u0439 \u043f\u0440\u0435\u0434\u0430\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0432\u0441\u0438\u0447\u043a\u0438 \u043a\u0430\u043d\u0430\u043b\u0438", + "OptionRecordAnytime": "\u0417\u0430\u043f\u0438\u0441\u0432\u0430\u0439 \u043f\u0440\u0435\u0434\u0430\u0432\u0430\u043d\u0435\u0442\u043e \u043f\u043e \u0432\u0441\u044f\u043a\u043e \u0432\u0440\u0435\u043c\u0435", + "OptionRecordOnlyNewEpisodes": "\u0417\u0430\u043f\u0438\u0441\u0432\u0430\u0439 \u0441\u0430\u043c\u043e \u043d\u043e\u0432\u0438 \u0435\u043f\u0438\u0437\u043e\u0434\u0438", + "HeaderDays": "\u0414\u043d\u0438", + "HeaderActiveRecordings": "\u0410\u043a\u0442\u0438\u0432\u043d\u0438 \u0417\u0430\u043f\u0438\u0441\u0438", + "HeaderLatestRecordings": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0417\u0430\u043f\u0438\u0441\u0438", + "HeaderAllRecordings": "\u0412\u0441\u0438\u0447\u043a\u0438 \u0417\u0430\u043f\u0438\u0441\u0438", + "ButtonPlay": "\u041f\u0443\u0441\u043d\u0438", + "ButtonEdit": "\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0430\u0439", + "ButtonRecord": "\u0417\u0430\u043f\u0438\u0448\u0438", + "ButtonDelete": "\u0418\u0437\u0442\u0440\u0438\u0439", + "ButtonRemove": "\u041f\u0440\u0435\u043c\u0430\u0445\u043d\u0438", + "OptionRecordSeries": "\u0417\u0430\u043f\u0438\u0448\u0438 \u041f\u0440\u0435\u0434\u0430\u0432\u0430\u043d\u0438\u044f", + "HeaderDetails": "\u0414\u0435\u0442\u0430\u0439\u043b\u0438", + "TitleLiveTV": "\u0422V \u043d\u0430 \u0436\u0438\u0432\u043e", + "LabelNumberOfGuideDays": "\u0411\u0440\u043e\u0439 \u0434\u043d\u0438 \u0437\u0430 \u043a\u043e\u0438\u0442\u043e \u0434\u0430 \u0441\u0435 \u0441\u0432\u0430\u043b\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0430:", + "LabelNumberOfGuideDaysHelp": "\u0418\u0437\u0442\u0435\u0433\u043b\u044f\u043d\u0435\u0442\u043e \u043d\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0430 \u0437\u0430\u043f\u043e\u0432\u0435\u0447\u0435 \u0434\u043d\u0438 \u0434\u0430\u0432\u0430 \u0432\u044a\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442 \u0434\u0430 \u043f\u043b\u0430\u043d\u0438\u0440\u0430\u0442\u0435 \u043f\u043e-\u043d\u0430\u0442\u0430\u0442\u044a\u0448\u043d\u0438\u0442\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u043d\u043e, \u043d\u043e \u0438 \u043e\u0442\u043d\u0435\u043c\u0430 \u043f\u043e\u0432\u0435\u0447\u0435 \u0432\u0440\u0435\u043c\u0435, \u0437\u0430 \u0434\u0430 \u0441\u0435 \u0438\u0437\u0442\u0435\u0433\u043b\u0438. \u0410\u0432\u0442\u043e\u043c\u0430\u0442 \u0449\u0435 \u0438\u0437\u0431\u0435\u0440\u0435 \u0432\u044a\u0437 \u043e\u0441\u043d\u043e\u0432\u0430 \u043d\u0430 \u0431\u0440\u043e\u044f \u043d\u0430 \u043a\u0430\u043d\u0430\u043b\u0438\u0442\u0435.", + "LabelActiveService": "\u0410\u043a\u0442\u0438\u0432\u043d\u0430 \u0423\u0441\u043b\u0443\u0433\u0430:", + "LabelActiveServiceHelp": "\u041d\u044f\u043a\u043e\u043b\u043a\u043e TV \u0434\u043e\u0431\u0430\u0432\u043a\u0438 \u043c\u043e\u0433\u0430\u0442 \u0434\u0430 \u0431\u044a\u0434\u0430\u0442 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u0438, \u043d\u043e \u0441\u0430\u043c\u043e \u0435\u0434\u043d\u0430 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0431\u044a\u0434\u0435 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u043d\u0430 \u043f\u043e \u0435\u0434\u043d\u043e \u0438 \u0441\u044a\u0449\u043e \u0432\u0440\u0435\u043c\u0435.", + "OptionAutomatic": "\u0410\u0432\u0442\u043e\u043c\u0430\u0442", + "LiveTvPluginRequired": "\u041d\u0435\u0431\u0445\u043e\u0434\u0438\u043c\u0430 \u0435 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430 \u0437\u0430 \u0433\u043b\u0435\u0434\u0430\u043d\u0435 \u043d\u0430 \u0442\u0435\u043b\u0435\u0432\u0438\u0437\u0438\u044f \u043d\u0430 \u0436\u0438\u0432\u043e, \u0437\u0430 \u0434\u0430 \u0441\u0435 \u043f\u0440\u043e\u0434\u044a\u043b\u0436\u0438.", + "LiveTvPluginRequiredHelp": "\u041c\u043e\u043b\u044f, \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u0439\u0442\u0435 \u043d\u044f\u043a\u043e\u044f \u043e\u0442 \u043d\u0430\u043b\u0438\u0447\u043d\u0438\u0442\u0435 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438, \u043a\u0430\u0442\u043e \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 Next Pvr \u0438\u043b\u0438 ServerWmc.", + "LabelCustomizeOptionsPerMediaType": "\u041f\u0435\u0440\u0441\u043e\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043d\u0435 \u0437\u0430 \u0442\u0438\u043f \u043c\u0435\u0434\u0438\u044f:", + "OptionDownloadThumbImage": "\u041c\u0438\u043d\u0438\u0430\u0442\u044e\u0440\u0430", + "OptionDownloadMenuImage": "\u041c\u0435\u043d\u044e", + "OptionDownloadLogoImage": "\u041b\u043e\u0433\u043e", + "OptionDownloadBoxImage": "\u041a\u0443\u0442\u0438\u044f", + "OptionDownloadDiscImage": "\u0414\u0438\u0441\u043a", + "OptionDownloadBannerImage": "\u0411\u0430\u043d\u0435\u0440", + "OptionDownloadBackImage": "\u0417\u0430\u0434\u043d\u0430 \u0447\u0430\u0441\u0442", + "OptionDownloadArtImage": "\u0418\u0437\u043a\u0443\u0441\u0442\u0432\u043e", + "OptionDownloadPrimaryImage": "\u041a\u043e\u0440\u0438\u0446\u0430", + "HeaderFetchImages": "\u0421\u0432\u0430\u043b\u0438 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f:", + "HeaderImageSettings": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043d\u0430 \u043a\u0430\u0440\u0442\u0438\u043d\u0430\u0442\u0430", + "TabOther": "\u0414\u0440\u0443\u0433\u0438", + "LabelMaxBackdropsPerItem": "\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u0435\u043d \u0431\u0440\u043e\u0439 \u0444\u043e\u043d\u043e\u0432\u0435 \u043d\u0430 \u043c\u0435\u0434\u0438\u044f:", + "LabelMaxScreenshotsPerItem": "\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u0435\u043d \u0431\u0440\u043e\u0439 \u0441\u043a\u0440\u0438\u0439\u043d\u0448\u043e\u0442\u0438 \u043d\u0430 \u043c\u0435\u0434\u0438\u044f:", + "LabelMinBackdropDownloadWidth": "\u041c\u0438\u043d\u0438\u043c\u0430\u043b\u043d\u0430 \u0448\u0438\u0440\u043e\u0447\u0438\u043d\u0430 \u043d\u0430 \u0441\u0432\u0430\u043b\u0435\u043d\u0438\u044f \u0444\u043e\u043d:", + "LabelMinScreenshotDownloadWidth": "\u041c\u0438\u043d\u0438\u043c\u0430\u043b\u043d\u0430 \u0448\u0438\u0440\u043e\u0447\u0438\u043d\u0430 \u043d\u0430 \u0441\u0432\u0430\u043b\u0435\u043d\u0438\u044f \u0441\u043a\u0440\u0438\u0439\u043d\u0448\u043e\u0442:", + "ButtonAddScheduledTaskTrigger": "\u0414\u043e\u0431\u0430\u0432\u0438 \u0441\u043f\u0443\u0441\u044a\u043a", + "HeaderAddScheduledTaskTrigger": "\u0414\u043e\u0431\u0430\u0432\u0438 \u0441\u043f\u0443\u0441\u044a\u043a", + "ButtonAdd": "\u0414\u043e\u0431\u0430\u0432\u0438", + "LabelTriggerType": "\u0422\u0438\u043f \u043d\u0430 \u0441\u043f\u0443\u0441\u044a\u043a\u0430:", + "OptionDaily": "\u0414\u043d\u0435\u0432\u043d\u043e", + "OptionWeekly": "\u0421\u0435\u0434\u043c\u0438\u0447\u043d\u043e", + "OptionOnInterval": "\u041f\u0440\u0435\u0437 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b", + "OptionOnAppStartup": "\u041a\u0430\u0442\u043e \u0441\u0435 \u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u0442\u043e", + "OptionAfterSystemEvent": "\u0421\u043b\u0435\u0434 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e \u0441\u044a\u0431\u0438\u0442\u0438\u0435", + "LabelDay": "\u0414\u0435\u043d:", + "LabelTime": "\u0412\u0440\u0435\u043c\u0435:", + "LabelEvent": "\u0421\u044a\u0431\u0438\u0442\u0438\u0435:", + "OptionWakeFromSleep": "\u0421\u044a\u0431\u0443\u0436\u0434\u0430\u043d\u0435 \u043e\u0442 \u0441\u044a\u043d", + "LabelEveryXMinutes": "\u041d\u0430 \u0432\u0441\u0435\u043a\u0438:", + "HeaderTvTuners": "\u0422\u0443\u043d\u0435\u0440\u0438", + "HeaderGallery": "\u0413\u0430\u043b\u0435\u0440\u0438\u044f", + "HeaderLatestGames": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438 \u0418\u0433\u0440\u0438", + "HeaderRecentlyPlayedGames": "\u0421\u043a\u043e\u0440\u043e \u0418\u0433\u0440\u0430\u043d\u0438 \u0418\u0433\u0440\u0438", + "TabGameSystems": "\u0418\u0433\u0440\u043e\u0432\u0438 \u0421\u0438\u0441\u0442\u0435\u043c\u0438", + "TitleMediaLibrary": "\u041c\u0435\u0434\u0438\u0439\u043d\u0430 \u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430", + "TabFolders": "\u041f\u0430\u043f\u043a\u0438", + "TabPathSubstitution": "\u0417\u0430\u043c\u0435\u0441\u0442\u0432\u0430\u043d\u0435 \u043d\u0430 \u043f\u044a\u0442", + "LabelSeasonZeroDisplayName": "\u0418\u043c\u0435 \u043d\u0430 \u0421\u0435\u0437\u043e\u043d 0:", + "LabelEnableRealtimeMonitor": "\u0410\u043a\u0442\u0438\u0432\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u043d\u0430\u0431\u043b\u044e\u0434\u0435\u043d\u0438\u0435 \u0432 \u0440\u0435\u0430\u043b\u043d\u043e \u0432\u0440\u0435\u043c\u0435", + "LabelEnableRealtimeMonitorHelp": "\u041f\u0440\u043e\u043c\u0435\u043d\u0438\u0442\u0435 \u0449\u0435 \u0431\u044a\u0434\u0430\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0435\u043d\u0438 \u0432\u0435\u0434\u043d\u0430\u0433\u0430, \u043d\u0430 \u043f\u043e\u0434\u0434\u044a\u0440\u0436\u0430\u043d\u0438 \u0444\u0430\u0439\u043b\u043e\u0432\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u0438.", + "ButtonScanLibrary": "\u0421\u043a\u0430\u043d\u0438\u0440\u0430\u0439 \u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u0442\u0430", + "HeaderNumberOfPlayers": "\u041f\u043b\u0435\u0439\u044a\u0440\u0438:", + "OptionAnyNumberOfPlayers": "\u0412\u0441\u0435\u043a\u0438", + "Option1Player": "1+", + "Option2Player": "2+", + "Option3Player": "3+", + "Option4Player": "4+", + "HeaderMediaFolders": "\u041c\u0435\u0434\u0438\u0439\u043d\u0438 \u041f\u0430\u043f\u043a\u0438", + "HeaderThemeVideos": "\u0422\u0435\u043c\u0430\u0442\u0438\u0447\u043d\u0438 \u043a\u043b\u0438\u043f\u043e\u0432\u0435", + "HeaderThemeSongs": "\u0422\u0435\u043c\u0430\u0442\u0438\u0447\u043d\u0438 \u043f\u0435\u0441\u043d\u0438", + "HeaderScenes": "\u0421\u0446\u0435\u043d\u0438", + "HeaderAwardsAndReviews": "\u041d\u0430\u0433\u0440\u0430\u0434\u0438 \u0438 \u0440\u0435\u0432\u044e\u0442\u0430", + "HeaderSoundtracks": "\u0424\u0438\u043b\u043c\u043e\u0432\u0430 \u043c\u0443\u0437\u0438\u043a\u0430", + "HeaderMusicVideos": "\u041c\u0443\u0437\u0438\u043a\u0430\u043b\u043d\u0438 \u043a\u043b\u0438\u043f\u043e\u0432\u0435", + "HeaderSpecialFeatures": "\u0421\u043f\u0435\u0446\u0438\u0430\u043b\u043d\u0438 \u0414\u043e\u0431\u0430\u0432\u043a\u0438", + "HeaderCastCrew": "\u0415\u043a\u0438\u043f", + "HeaderAdditionalParts": "\u0414\u043e\u043f\u044a\u043b\u043d\u0438\u0442\u0435\u043b\u043d\u0438 \u0427\u0430\u0441\u0442\u0438", + "ButtonSplitVersionsApart": "Split Versions Apart", + "ButtonPlayTrailer": "Trailer", + "LabelMissing": "Missing", + "LabelOffline": "Offline", + "PathSubstitutionHelp": "Path substitutions are used for mapping a path on the server to a path that clients are able to access. By allowing clients direct access to media on the server they may be able to play them directly over the network and avoid using server resources to stream and transcode them.", + "HeaderFrom": "From", + "HeaderTo": "To", + "LabelFrom": "From:", + "LabelFromHelp": "Example: D:\\Movies (on the server)", + "LabelTo": "To:", + "LabelToHelp": "Example: \\\\MyServer\\Movies (a path clients can access)", + "ButtonAddPathSubstitution": "Add Substitution", + "OptionSpecialEpisode": "Specials", + "OptionMissingEpisode": "Missing Episodes", + "OptionUnairedEpisode": "Unaired Episodes", + "OptionEpisodeSortName": "Episode Sort Name", + "OptionSeriesSortName": "Series Name", + "OptionTvdbRating": "Tvdb Rating", + "HeaderTranscodingQualityPreference": "Transcoding Quality Preference:", + "OptionAutomaticTranscodingHelp": "The server will decide quality and speed", + "OptionHighSpeedTranscodingHelp": "Lower quality, but faster encoding", + "OptionHighQualityTranscodingHelp": "Higher quality, but slower encoding", + "OptionMaxQualityTranscodingHelp": "Best quality with slower encoding and high CPU usage", + "OptionHighSpeedTranscoding": "Higher speed", + "OptionHighQualityTranscoding": "Higher quality", + "OptionMaxQualityTranscoding": "Max quality", + "OptionEnableDebugTranscodingLogging": "Enable debug transcoding logging", + "OptionEnableDebugTranscodingLoggingHelp": "This will create very large log files and is only recommended as needed for troubleshooting purposes.", + "OptionUpscaling": "Allow clients to request upscaled video", + "OptionUpscalingHelp": "In some cases this will result in improved video quality but will increase CPU usage.", + "EditCollectionItemsHelp": "Add or remove any movies, series, albums, books or games you wish to group within this collection.", + "HeaderAddTitles": "Add Titles", + "LabelEnableDlnaPlayTo": "Enable DLNA Play To", + "LabelEnableDlnaPlayToHelp": "Media Browser can detect devices within your network and offer the ability to remote control them.", + "LabelEnableDlnaDebugLogging": "Enable DLNA debug logging", + "LabelEnableDlnaDebugLoggingHelp": "This will create large log files and should only be used as needed for troubleshooting purposes.", + "LabelEnableDlnaClientDiscoveryInterval": "Client discovery interval (seconds)", + "LabelEnableDlnaClientDiscoveryIntervalHelp": "Determines the duration in seconds between SSDP searches performed by Media Browser.", + "HeaderCustomDlnaProfiles": "Custom Profiles", + "HeaderSystemDlnaProfiles": "System Profiles", + "CustomDlnaProfilesHelp": "Create a custom profile to target a new device or override a system profile.", + "SystemDlnaProfilesHelp": "System profiles are read-only. Changes to a system profile will be saved to a new custom profile.", + "TitleDashboard": "Dashboard", + "TabHome": "Home", + "TabInfo": "Info", + "HeaderLinks": "Links", + "HeaderSystemPaths": "System Paths", + "LinkCommunity": "Community", + "LinkGithub": "Github", + "LinkApi": "Api", + "LinkApiDocumentation": "Api Documentation", + "LabelFriendlyServerName": "Friendly server name:", + "LabelFriendlyServerNameHelp": "This name will be used to identify this server. If left blank, the computer name will be used.", + "LabelPreferredDisplayLanguage": "Preferred display language:", + "LabelPreferredDisplayLanguageHelp": "Translating Media Browser is an ongoing project and is not yet complete.", + "LabelReadHowYouCanContribute": "Read about how you can contribute.", + "HeaderNewCollection": "New Collection", + "ButtonSubmit": "Submit", + "ButtonCreate": "Create", + "LabelCustomCss": "Custom css:", + "LabelCustomCssHelp": "Apply your own custom css to the web interface.", + "LabelLocalHttpServerPortNumber": "Local http port number:", + "LabelLocalHttpServerPortNumberHelp": "The tcp port number that Media Browser's http server should bind to.", + "LabelPublicHttpPort": "Public http port number:", + "LabelPublicHttpPortHelp": "The public port number that should be mapped to the local http port.", + "LabelPublicHttpsPort": "Public https port number:", + "LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.", + "LabelEnableHttps": "Report https as external address", + "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.", + "LabelHttpsPort": "Local https port number:", + "LabelHttpsPortHelp": "The tcp port number that Media Browser's https server should bind to.", + "LabelWebSocketPortNumber": "Web socket port number:", + "LabelEnableAutomaticPortMap": "Enable automatic port mapping", + "LabelEnableAutomaticPortMapHelp": "Attempt to automatically map the public port to the local port via UPnP. This may not work with some router models.", + "LabelExternalDDNS": "External WAN Address:", + "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely. Leave empty for automatic detection.", + "TabResume": "Resume", + "TabWeather": "Weather", + "TitleAppSettings": "App Settings", + "LabelMinResumePercentage": "Min resume percentage:", + "LabelMaxResumePercentage": "Max resume percentage:", + "LabelMinResumeDuration": "Min resume duration (seconds):", + "LabelMinResumePercentageHelp": "Titles are assumed unplayed if stopped before this time", + "LabelMaxResumePercentageHelp": "Titles are assumed fully played if stopped after this time", + "LabelMinResumeDurationHelp": "Titles shorter than this will not be resumable", + "TitleAutoOrganize": "Auto-Organize", + "TabActivityLog": "Activity Log", + "HeaderName": "Name", + "HeaderDate": "Date", + "HeaderSource": "Source", + "HeaderDestination": "Destination", + "HeaderProgram": "Program", + "HeaderClients": "Clients", + "LabelCompleted": "Completed", + "LabelFailed": "Failed", + "LabelSkipped": "Skipped", + "HeaderEpisodeOrganization": "Episode Organization", + "LabelSeries": "Series:", + "LabelSeasonNumber": "Season number:", + "LabelEpisodeNumber": "Episode number:", + "LabelEndingEpisodeNumber": "Ending episode number:", + "LabelEndingEpisodeNumberHelp": "Only required for multi-episode files", + "HeaderSupportTheTeam": "Support the Media Browser Team", + "LabelSupportAmount": "Amount (USD)", + "HeaderSupportTheTeamHelp": "Help ensure the continued development of this project by donating. A portion of all donations will be contributed to other free tools we depend on.", + "ButtonEnterSupporterKey": "Enter supporter key", + "DonationNextStep": "Once complete, please return and enter your supporter key, which you will receive by email.", + "AutoOrganizeHelp": "Auto-organize monitors your download folders for new files and moves them to your media directories.", + "AutoOrganizeTvHelp": "TV file organizing will only add episodes to existing series. It will not create new series folders.", + "OptionEnableEpisodeOrganization": "Enable new episode organization", + "LabelWatchFolder": "Watch folder:", + "LabelWatchFolderHelp": "The server will poll this folder during the 'Organize new media files' scheduled task.", + "ButtonViewScheduledTasks": "View scheduled tasks", + "LabelMinFileSizeForOrganize": "Minimum file size (MB):", + "LabelMinFileSizeForOrganizeHelp": "Files under this size will be ignored.", + "LabelSeasonFolderPattern": "Season folder pattern:", + "LabelSeasonZeroFolderName": "Season zero folder name:", + "HeaderEpisodeFilePattern": "Episode file pattern", + "LabelEpisodePattern": "Episode pattern:", + "LabelMultiEpisodePattern": "Multi-Episode pattern:", + "HeaderSupportedPatterns": "Supported Patterns", + "HeaderTerm": "Term", + "HeaderPattern": "Pattern", + "HeaderResult": "Result", + "LabelDeleteEmptyFolders": "Delete empty folders after organizing", + "LabelDeleteEmptyFoldersHelp": "Enable this to keep the download directory clean.", + "LabelDeleteLeftOverFiles": "Delete left over files with the following extensions:", + "LabelDeleteLeftOverFilesHelp": "Separate with ;. For example: .nfo;.txt", + "OptionOverwriteExistingEpisodes": "Overwrite existing episodes", + "LabelTransferMethod": "Transfer method", + "OptionCopy": "Copy", + "OptionMove": "Move", + "LabelTransferMethodHelp": "Copy or move files from the watch folder", + "HeaderLatestNews": "Latest News", + "HeaderHelpImproveMediaBrowser": "Help Improve Media Browser", + "HeaderRunningTasks": "Running Tasks", + "HeaderActiveDevices": "Active Devices", + "HeaderPendingInstallations": "Pending Installations", + "HeaderServerInformation": "Server Information", + "ButtonRestartNow": "Restart Now", + "ButtonRestart": "Restart", + "ButtonShutdown": "Shutdown", + "ButtonUpdateNow": "Update Now", + "TabHosting": "Hosting", + "PleaseUpdateManually": "Please shutdown the server and update manually.", + "NewServerVersionAvailable": "A new version of Media Browser Server is available!", + "ServerUpToDate": "Media Browser Server is up to date", + "ErrorConnectingToMediaBrowserRepository": "There was an error connecting to the remote Media Browser repository.", + "LabelComponentsUpdated": "The following components have been installed or updated:", + "MessagePleaseRestartServerToFinishUpdating": "Please restart the server to finish applying updates.", + "LabelDownMixAudioScale": "Audio boost when downmixing:", + "LabelDownMixAudioScaleHelp": "Boost audio when downmixing. Set to 1 to preserve original volume value.", + "ButtonLinkKeys": "Transfer Key", + "LabelOldSupporterKey": "Old supporter key", + "LabelNewSupporterKey": "New supporter key", + "HeaderMultipleKeyLinking": "Transfer to New Key", + "MultipleKeyLinkingHelp": "If you received a new supporter key, use this form to transfer the old key's registrations to your new one.", + "LabelCurrentEmailAddress": "Current email address", + "LabelCurrentEmailAddressHelp": "The current email address to which your new key was sent.", + "HeaderForgotKey": "Forgot Key", + "LabelEmailAddress": "Email address", + "LabelSupporterEmailAddress": "The email address that was used to purchase the key.", + "ButtonRetrieveKey": "Retrieve Key", + "LabelSupporterKey": "Supporter Key (paste from email)", + "LabelSupporterKeyHelp": "Enter your supporter key to start enjoying additional benefits the community has developed for Media Browser.", + "MessageInvalidKey": "Supporter key is missing or invalid.", + "ErrorMessageInvalidKey": "In order for any premium content to be registered, you must also be a Media Browser Supporter. Please donate and support the continued development of the core product. Thank you.", + "HeaderDisplaySettings": "Display Settings", + "TabPlayTo": "Play To", + "LabelEnableDlnaServer": "Enable Dlna server", + "LabelEnableDlnaServerHelp": "Allows UPnP devices on your network to browse and play Media Browser content.", + "LabelEnableBlastAliveMessages": "Blast alive messages", + "LabelEnableBlastAliveMessagesHelp": "Enable this if the server is not detected reliably by other UPnP devices on your network.", + "LabelBlastMessageInterval": "Alive message interval (seconds)", + "LabelBlastMessageIntervalHelp": "Determines the duration in seconds between server alive messages.", + "LabelDefaultUser": "Default user:", + "LabelDefaultUserHelp": "Determines which user library should be displayed on connected devices. This can be overridden for each device using profiles.", + "TitleDlna": "DLNA", + "TitleChannels": "Channels", + "HeaderServerSettings": "Server Settings", + "LabelWeatherDisplayLocation": "Weather display location:", + "LabelWeatherDisplayLocationHelp": "US zip code \/ City, State, Country \/ City, Country", + "LabelWeatherDisplayUnit": "Weather display unit:", + "OptionCelsius": "Celsius", + "OptionFahrenheit": "Fahrenheit", + "HeaderRequireManualLogin": "Require manual username entry for:", + "HeaderRequireManualLoginHelp": "When disabled clients may present a login screen with a visual selection of users.", + "OptionOtherApps": "Other apps", + "OptionMobileApps": "Mobile apps", + "HeaderNotificationList": "Click on a notification to configure it's sending options.", + "NotificationOptionApplicationUpdateAvailable": "Application update available", + "NotificationOptionApplicationUpdateInstalled": "Application update installed", + "NotificationOptionPluginUpdateInstalled": "Plugin update installed", + "NotificationOptionPluginInstalled": "Plugin installed", + "NotificationOptionPluginUninstalled": "Plugin uninstalled", + "NotificationOptionVideoPlayback": "Video playback started", + "NotificationOptionAudioPlayback": "Audio playback started", + "NotificationOptionGamePlayback": "Game playback started", + "NotificationOptionVideoPlaybackStopped": "Video playback stopped", + "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", + "NotificationOptionGamePlaybackStopped": "Game playback stopped", + "NotificationOptionTaskFailed": "Scheduled task failure", + "NotificationOptionInstallationFailed": "Installation failure", + "NotificationOptionNewLibraryContent": "New content added", + "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", + "NotificationOptionCameraImageUploaded": "Camera image uploaded", + "SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.", + "NotificationOptionServerRestartRequired": "Server restart required", + "LabelNotificationEnabled": "Enable this notification", + "LabelMonitorUsers": "Monitor activity from:", + "LabelSendNotificationToUsers": "Send the notification to:", + "LabelUseNotificationServices": "Use the following services:", + "CategoryUser": "User", + "CategorySystem": "System", + "CategoryApplication": "Application", + "CategoryPlugin": "Plugin", + "LabelMessageTitle": "Message title:", + "LabelAvailableTokens": "Available tokens:", + "AdditionalNotificationServices": "Browse the plugin catalog to install additional notification services.", + "OptionAllUsers": "All users", + "OptionAdminUsers": "Administrators", + "OptionCustomUsers": "Custom", + "ButtonArrowUp": "Up", + "ButtonArrowDown": "Down", + "ButtonArrowLeft": "Left", + "ButtonArrowRight": "Right", + "ButtonBack": "Back", + "ButtonInfo": "Info", + "ButtonOsd": "On screen display", + "ButtonPageUp": "Page Up", + "ButtonPageDown": "Page Down", + "PageAbbreviation": "PG", + "ButtonHome": "Home", + "ButtonSearch": "Search", + "ButtonSettings": "Settings", + "ButtonTakeScreenshot": "Capture Screenshot", + "ButtonLetterUp": "Letter Up", + "ButtonLetterDown": "Letter Down", + "PageButtonAbbreviation": "PG", + "LetterButtonAbbreviation": "A", + "TabNowPlaying": "Now Playing", + "TabNavigation": "Navigation", + "TabControls": "Controls", + "ButtonFullscreen": "Toggle fullscreen", + "ButtonScenes": "Scenes", + "ButtonSubtitles": "Subtitles", + "ButtonAudioTracks": "Audio tracks", + "ButtonPreviousTrack": "Previous track", + "ButtonNextTrack": "Next track", + "ButtonStop": "Stop", + "ButtonPause": "Pause", + "ButtonNext": "Next", + "ButtonPrevious": "Previous", + "LabelGroupMoviesIntoCollections": "Group movies into collections", + "LabelGroupMoviesIntoCollectionsHelp": "When displaying movie lists, movies belonging to a collection will be displayed as one grouped item.", + "NotificationOptionPluginError": "Plugin failure", + "ButtonVolumeUp": "Volume up", + "ButtonVolumeDown": "Volume down", + "ButtonMute": "Mute", + "HeaderLatestMedia": "Latest Media", + "OptionSpecialFeatures": "Special Features", + "HeaderCollections": "Collections", + "LabelProfileCodecsHelp": "Separated by comma. This can be left empty to apply to all codecs.", + "LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.", + "HeaderResponseProfile": "Response Profile", + "LabelType": "Type:", + "LabelPersonRole": "Role:", + "LabelPersonRoleHelp": "Role is generally only applicable to actors.", + "LabelProfileContainer": "Container:", + "LabelProfileVideoCodecs": "Video codecs:", + "LabelProfileAudioCodecs": "Audio codecs:", + "LabelProfileCodecs": "Codecs:", + "HeaderDirectPlayProfile": "Direct Play Profile", + "HeaderTranscodingProfile": "Transcoding Profile", + "HeaderCodecProfile": "Codec Profile", + "HeaderCodecProfileHelp": "Codec profiles indicate the limitations of a device when playing specific codecs. If a limitation applies then the media will be transcoded, even if the codec is configured for direct play.", + "HeaderContainerProfile": "Container Profile", + "HeaderContainerProfileHelp": "Container profiles indicate the limitations of a device when playing specific formats. If a limitation applies then the media will be transcoded, even if the format is configured for direct play.", + "OptionProfileVideo": "Video", + "OptionProfileAudio": "Audio", + "OptionProfileVideoAudio": "Video Audio", + "OptionProfilePhoto": "Photo", + "LabelUserLibrary": "User library:", + "LabelUserLibraryHelp": "Select which user library to display to the device. Leave empty to inherit the default setting.", + "OptionPlainStorageFolders": "Display all folders as plain storage folders", + "OptionPlainStorageFoldersHelp": "If enabled, all folders are represented in DIDL as \"object.container.storageFolder\" instead of a more specific type, such as \"object.container.person.musicArtist\".", + "OptionPlainVideoItems": "Display all videos as plain video items", + "OptionPlainVideoItemsHelp": "If enabled, all videos are represented in DIDL as \"object.item.videoItem\" instead of a more specific type, such as \"object.item.videoItem.movie\".", + "LabelSupportedMediaTypes": "Supported Media Types:", + "TabIdentification": "Identification", + "HeaderIdentification": "Identification", + "TabDirectPlay": "Direct Play", + "TabContainers": "Containers", + "TabCodecs": "Codecs", + "TabResponses": "Responses", + "HeaderProfileInformation": "Profile Information", + "LabelEmbedAlbumArtDidl": "Embed album art in Didl", + "LabelEmbedAlbumArtDidlHelp": "Some devices prefer this method for obtaining album art. Others may fail to play with this option enabled.", + "LabelAlbumArtPN": "Album art PN:", + "LabelAlbumArtHelp": "PN used for album art, within the dlna:profileID attribute on upnp:albumArtURI. Some clients require a specific value, regardless of the size of the image.", + "LabelAlbumArtMaxWidth": "Album art max width:", + "LabelAlbumArtMaxWidthHelp": "Max resolution of album art exposed via upnp:albumArtURI.", + "LabelAlbumArtMaxHeight": "Album art max height:", + "LabelAlbumArtMaxHeightHelp": "Max resolution of album art exposed via upnp:albumArtURI.", + "LabelIconMaxWidth": "Icon max width:", + "LabelIconMaxWidthHelp": "Max resolution of icons exposed via upnp:icon.", + "LabelIconMaxHeight": "Icon max height:", + "LabelIconMaxHeightHelp": "Max resolution of icons exposed via upnp:icon.", + "LabelIdentificationFieldHelp": "A case-insensitive substring or regex expression.", + "HeaderProfileServerSettingsHelp": "These values control how Media Browser will present itself to the device.", + "LabelMaxBitrate": "Max bitrate:", + "LabelMaxBitrateHelp": "Specify a max bitrate in bandwidth constrained environments, or if the device imposes it's own limit.", + "LabelMaxStreamingBitrate": "Max streaming bitrate:", + "LabelMaxStreamingBitrateHelp": "Specify a max bitrate when streaming.", + "LabelMaxStaticBitrate": "Max sync bitrate:", + "LabelMaxStaticBitrateHelp": "Specify a max bitrate when syncing content at high quality.", + "LabelMusicStaticBitrate": "Music sync bitrate:", + "LabelMusicStaticBitrateHelp": "Specify a max bitrate when syncing music", + "LabelMusicStreamingTranscodingBitrate": "Music transcoding bitrate:", + "LabelMusicStreamingTranscodingBitrateHelp": "Specify a max bitrate when streaming music", + "OptionIgnoreTranscodeByteRangeRequests": "Ignore transcode byte range requests", + "OptionIgnoreTranscodeByteRangeRequestsHelp": "If enabled, these requests will be honored but will ignore the byte range header.", + "LabelFriendlyName": "Friendly name", + "LabelManufacturer": "Manufacturer", + "LabelManufacturerUrl": "Manufacturer url", + "LabelModelName": "Model name", + "LabelModelNumber": "Model number", + "LabelModelDescription": "Model description", + "LabelModelUrl": "Model url", + "LabelSerialNumber": "Serial number", + "LabelDeviceDescription": "Device description", + "HeaderIdentificationCriteriaHelp": "Enter at least one identification criteria.", + "HeaderDirectPlayProfileHelp": "Add direct play profiles to indicate which formats the device can handle natively.", + "HeaderTranscodingProfileHelp": "Add transcoding profiles to indicate which formats should be used when transcoding is required.", + "HeaderResponseProfileHelp": "Response profiles provide a way to customize information sent to the device when playing certain kinds of media.", + "LabelXDlnaCap": "X-Dlna cap:", + "LabelXDlnaCapHelp": "Determines the content of the X_DLNACAP element in the urn:schemas-dlna-org:device-1-0 namespace.", + "LabelXDlnaDoc": "X-Dlna doc:", + "LabelXDlnaDocHelp": "Determines the content of the X_DLNADOC element in the urn:schemas-dlna-org:device-1-0 namespace.", + "LabelSonyAggregationFlags": "Sony aggregation flags:", + "LabelSonyAggregationFlagsHelp": "Determines the content of the aggregationFlags element in the urn:schemas-sonycom:av namespace.", + "LabelTranscodingContainer": "Container:", + "LabelTranscodingVideoCodec": "Video codec:", + "LabelTranscodingVideoProfile": "Video profile:", + "LabelTranscodingAudioCodec": "Audio codec:", + "OptionEnableM2tsMode": "Enable M2ts mode", + "OptionEnableM2tsModeHelp": "Enable m2ts mode when encoding to mpegts.", + "OptionEstimateContentLength": "Estimate content length when transcoding", + "OptionReportByteRangeSeekingWhenTranscoding": "Report that the server supports byte seeking when transcoding", + "OptionReportByteRangeSeekingWhenTranscodingHelp": "This is required for some devices that don't time seek very well.", + "HeaderSubtitleDownloadingHelp": "When Media Browser scans your video files it can search for missing subtitles, and download them using a subtitle provider such as OpenSubtitles.org.", + "HeaderDownloadSubtitlesFor": "Download subtitles for:", + "MessageNoChapterProviders": "Install a chapter provider plugin such as ChapterDb to enable additional chapter options.", + "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains graphical subtitles", + "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.", + "TabSubtitles": "Subtitles", + "TabChapters": "Chapters", + "HeaderDownloadChaptersFor": "Download chapter names for:", + "LabelOpenSubtitlesUsername": "Open Subtitles username:", + "LabelOpenSubtitlesPassword": "Open Subtitles password:", + "HeaderChapterDownloadingHelp": "When Media Browser scans your video files it can download friendly chapter names from the internet using chapter plugins such as ChapterDb.", + "LabelPlayDefaultAudioTrack": "Play default audio track regardless of language", + "LabelSubtitlePlaybackMode": "Subtitle mode:", + "LabelDownloadLanguages": "Download languages:", + "ButtonRegister": "Register", + "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language", + "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.", + "HeaderSendMessage": "Send Message", + "ButtonSend": "Send", + "LabelMessageText": "Message text:", + "MessageNoAvailablePlugins": "No available plugins.", + "LabelDisplayPluginsFor": "Display plugins for:", + "PluginTabMediaBrowserClassic": "MB Classic", + "PluginTabMediaBrowserTheater": "MB Theater", + "LabelEpisodeNamePlain": "Episode name", + "LabelSeriesNamePlain": "Series name", + "ValueSeriesNamePeriod": "Series.name", + "ValueSeriesNameUnderscore": "Series_name", + "ValueEpisodeNamePeriod": "Episode.name", + "ValueEpisodeNameUnderscore": "Episode_name", + "LabelSeasonNumberPlain": "Season number", + "LabelEpisodeNumberPlain": "Episode number", + "LabelEndingEpisodeNumberPlain": "Ending episode number", + "HeaderTypeText": "Enter Text", + "LabelTypeText": "Text", + "HeaderSearchForSubtitles": "Search for Subtitles", + "MessageNoSubtitleSearchResultsFound": "No search results founds.", + "TabDisplay": "Display", + "TabLanguages": "Languages", + "TabWebClient": "Web Client", + "LabelEnableThemeSongs": "Enable theme songs", + "LabelEnableBackdrops": "Enable backdrops", + "LabelEnableThemeSongsHelp": "If enabled, theme songs will be played in the background while browsing the library.", + "LabelEnableBackdropsHelp": "If enabled, backdrops will be displayed in the background of some pages while browsing the library.", + "HeaderHomePage": "Home Page", + "HeaderSettingsForThisDevice": "Settings for This Device", + "OptionAuto": "Auto", + "OptionYes": "Yes", + "OptionNo": "No", + "HeaderOptions": "Options", + "HeaderIdentificationResult": "Identification Result", + "LabelHomePageSection1": "Home page section 1:", + "LabelHomePageSection2": "Home page section 2:", + "LabelHomePageSection3": "Home page section 3:", + "LabelHomePageSection4": "Home page section 4:", + "OptionMyViewsButtons": "My views (buttons)", + "OptionMyViews": "My views", + "OptionMyViewsSmall": "My views (small)", + "OptionResumablemedia": "Resume", + "OptionLatestMedia": "Latest media", + "OptionLatestChannelMedia": "Latest channel items", + "HeaderLatestChannelItems": "Latest Channel Items", + "OptionNone": "None", + "HeaderLiveTv": "Live TV", + "HeaderReports": "Reports", + "HeaderMetadataManager": "Metadata Manager", + "HeaderPreferences": "Preferences", + "MessageLoadingChannels": "Loading channel content...", + "MessageLoadingContent": "Loading content...", + "ButtonMarkRead": "Mark Read", + "OptionDefaultSort": "Default", + "OptionCommunityMostWatchedSort": "Most Watched", + "TabNextUp": "Next Up", + "HeaderBecomeMediaBrowserSupporter": "Become a Media Browser Supporter", + "TextEnjoyBonusFeatures": "Enjoy Bonus Features", + "MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.", + "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.", + "MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.", + "MessageNoPlaylistItemsAvailable": "This playlist is currently empty.", + "ButtonDismiss": "Dismiss", + "ButtonEditOtherUserPreferences": "Edit this user's profile, password and personal preferences.", + "LabelChannelStreamQuality": "Preferred internet stream quality:", + "LabelChannelStreamQualityHelp": "In a low bandwidth environment, limiting quality can help ensure a smooth streaming experience.", + "OptionBestAvailableStreamQuality": "Best available", + "LabelEnableChannelContentDownloadingFor": "Enable channel content downloading for:", + "LabelEnableChannelContentDownloadingForHelp": "Some channels support downloading content prior to viewing. Enable this in low bandwidth enviornments to download channel content during off hours. Content is downloaded as part of the channel download scheduled task.", + "LabelChannelDownloadPath": "Channel content download path:", + "LabelChannelDownloadPathHelp": "Specify a custom download path if desired. Leave empty to download to an internal program data folder.", + "LabelChannelDownloadAge": "Delete content after: (days)", + "LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.", + "ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.", + "ButtonOptions": "Options", + "ViewTypeMovies": "Movies", + "ViewTypeTvShows": "TV", + "ViewTypeGames": "Games", + "ViewTypeMusic": "Music", + "ViewTypeMusicGenres": "Genres", + "ViewTypeMusicArtists": "Artists", + "ViewTypeBoxSets": "Collections", + "ViewTypeChannels": "Channels", + "ViewTypeLiveTV": "Live TV", + "ViewTypeLiveTvNowPlaying": "Now Airing", + "ViewTypeLatestGames": "Latest Games", + "ViewTypeRecentlyPlayedGames": "Recently Played", + "ViewTypeGameFavorites": "Favorites", + "ViewTypeGameSystems": "Game Systems", + "ViewTypeGameGenres": "Genres", + "ViewTypeTvResume": "Resume", + "ViewTypeTvNextUp": "Next Up", + "ViewTypeTvLatest": "Latest", + "ViewTypeTvShowSeries": "Series", + "ViewTypeTvGenres": "Genres", + "ViewTypeTvFavoriteSeries": "Favorite Series", + "ViewTypeTvFavoriteEpisodes": "Favorite Episodes", + "ViewTypeMovieResume": "Resume", + "ViewTypeMovieLatest": "Latest", + "ViewTypeMovieMovies": "Movies", + "ViewTypeMovieCollections": "Collections", + "ViewTypeMovieFavorites": "Favorites", + "ViewTypeMovieGenres": "Genres", + "ViewTypeMusicLatest": "Latest", + "ViewTypeMusicAlbums": "Albums", + "ViewTypeMusicAlbumArtists": "Album Artists", + "HeaderOtherDisplaySettings": "Display Settings", + "ViewTypeMusicSongs": "Songs", + "ViewTypeMusicFavorites": "Favorites", + "ViewTypeMusicFavoriteAlbums": "Favorite Albums", + "ViewTypeMusicFavoriteArtists": "Favorite Artists", + "ViewTypeMusicFavoriteSongs": "Favorite Songs", + "HeaderMyViews": "My Views", + "LabelSelectFolderGroups": "Automatically group content from the following folders into views such as Movies, Music and TV:", + "LabelSelectFolderGroupsHelp": "Folders that are unchecked will be displayed by themselves in their own view.", + "OptionDisplayAdultContent": "Display adult content", + "OptionLibraryFolders": "Media folders", + "TitleRemoteControl": "Remote Control", + "OptionLatestTvRecordings": "Latest recordings", + "LabelProtocolInfo": "Protocol info:", + "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.", + "TabNfo": "Nfo", + "HeaderKodiMetadataHelp": "Media Browser includes native support for Kodi Nfo metadata and images. To enable or disable Kodi metadata, use the Advanced tab to configure options for your media types.", + "LabelKodiMetadataUser": "Sync user watch data to nfo's for:", + "LabelKodiMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Kodi.", + "LabelKodiMetadataDateFormat": "Release date format:", + "LabelKodiMetadataDateFormatHelp": "All dates within nfo's will be read and written to using this format.", + "LabelKodiMetadataSaveImagePaths": "Save image paths within nfo files", + "LabelKodiMetadataSaveImagePathsHelp": "This is recommended if you have image file names that don't conform to Kodi guidelines.", + "LabelKodiMetadataEnablePathSubstitution": "Enable path substitution", + "LabelKodiMetadataEnablePathSubstitutionHelp": "Enables path substitution of image paths using the server's path substitution settings.", + "LabelKodiMetadataEnablePathSubstitutionHelp2": "See path substitution.", + "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:", + "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.", + "LabelDisplayCollectionsView": "Display a collections view to show movie collections", + "LabelDisplayCollectionsViewHelp": "This will create a separate view to display collections that you've created or have access to. To create a collection, right-click or tap-hold any movie and select 'Add to Collection'. ", + "LabelKodiMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs", + "LabelKodiMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Kodi skin compatibility.", + "TabServices": "Services", + "TabLogs": "Logs", + "HeaderServerLogFiles": "Server log files:", + "TabBranding": "Branding", + "HeaderBrandingHelp": "Customize the appearance of Media Browser to fit the needs of your group or organization.", + "LabelLoginDisclaimer": "Login disclaimer:", + "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.", + "LabelAutomaticallyDonate": "Automatically donate this amount every month", + "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.", + "OptionList": "List", + "TabDashboard": "Dashboard", + "TitleServer": "Server", + "LabelCache": "Cache:", + "LabelLogs": "Logs:", + "LabelMetadata": "Metadata:", + "LabelImagesByName": "Images by name:", + "LabelTranscodingTemporaryFiles": "Transcoding temporary files:", + "HeaderLatestMusic": "Latest Music", + "HeaderBranding": "Branding", + "HeaderApiKeys": "Api Keys", + "HeaderApiKeysHelp": "External applications are required to have an Api key in order to communicate with Media Browser. Keys are issued by logging in with a Media Browser account, or by manually granting the application a key.", + "HeaderApiKey": "Api Key", + "HeaderApp": "App", + "HeaderDevice": "Device", + "HeaderUser": "User", + "HeaderDateIssued": "Date Issued", + "LabelChapterName": "Chapter {0}", + "HeaderNewApiKey": "New Api Key", + "LabelAppName": "App name", + "LabelAppNameExample": "Example: Sickbeard, NzbDrone", + "HeaderNewApiKeyHelp": "Grant an application permission to communicate with Media Browser.", + "HeaderHttpHeaders": "Http Headers", + "HeaderIdentificationHeader": "Identification Header", + "LabelValue": "Value:", + "LabelMatchType": "Match type:", + "OptionEquals": "Equals", + "OptionRegex": "Regex", + "OptionSubstring": "Substring", + "TabView": "View", + "TabSort": "Sort", + "TabFilter": "Filter", + "ButtonView": "View", + "LabelPageSize": "Item limit:", + "LabelPath": "Path:", + "LabelView": "View:", + "TabUsers": "Users", + "LabelSortName": "Sort name:", + "LabelDateAdded": "Date added:", + "HeaderFeatures": "Features", + "HeaderAdvanced": "Advanced", + "ButtonSync": "Sync", + "TabScheduledTasks": "Scheduled Tasks", + "HeaderChapters": "Chapters", + "HeaderResumeSettings": "Resume Settings", + "TabSync": "Sync", + "TitleUsers": "Users", + "LabelProtocol": "Protocol:", + "OptionProtocolHttp": "Http", + "OptionProtocolHls": "Http Live Streaming", + "LabelContext": "Context:", + "OptionContextStreaming": "Streaming", + "OptionContextStatic": "Sync", + "ButtonAddToPlaylist": "Add to playlist", + "TabPlaylists": "Playlists", + "ButtonClose": "Close", + "LabelAllLanguages": "All languages", + "HeaderBrowseOnlineImages": "Browse Online Images", + "LabelSource": "Source:", + "OptionAll": "All", + "LabelImage": "Image:", + "ButtonBrowseImages": "Browse Images", + "HeaderImages": "Images", + "HeaderBackdrops": "Backdrops", + "HeaderScreenshots": "Screenshots", + "HeaderAddUpdateImage": "Add\/Update Image", + "LabelJpgPngOnly": "JPG\/PNG only", + "LabelImageType": "Image type:", + "OptionPrimary": "Primary", + "OptionArt": "Art", + "OptionBox": "Box", + "OptionBoxRear": "Box rear", + "OptionDisc": "Disc", + "OptionLogo": "Logo", + "OptionMenu": "Menu", + "OptionScreenshot": "Screenshot", + "OptionLocked": "Locked", + "OptionUnidentified": "Unidentified", + "OptionMissingParentalRating": "Missing parental rating", + "OptionStub": "Stub", + "HeaderEpisodes": "Episodes:", + "OptionSeason0": "Season 0", + "LabelReport": "Report:", + "OptionReportSongs": "Songs", + "OptionReportSeries": "Series", + "OptionReportSeasons": "Seasons", + "OptionReportTrailers": "Trailers", + "OptionReportMusicVideos": "Music videos", + "OptionReportMovies": "Movies", + "OptionReportHomeVideos": "Home videos", + "OptionReportGames": "Games", + "OptionReportEpisodes": "Episodes", + "OptionReportCollections": "Collections", + "OptionReportBooks": "Books", + "OptionReportArtists": "Artists", + "OptionReportAlbums": "Albums", + "OptionReportAdultVideos": "Adult videos", + "ButtonMore": "More", + "HeaderActivity": "Activity", + "ScheduledTaskStartedWithName": "{0} started", + "ScheduledTaskCancelledWithName": "{0} was cancelled", + "ScheduledTaskCompletedWithName": "{0} completed", + "ScheduledTaskFailed": "Scheduled task completed", + "PluginInstalledWithName": "{0} was installed", + "PluginUpdatedWithName": "{0} was updated", + "PluginUninstalledWithName": "{0} was uninstalled", + "ScheduledTaskFailedWithName": "{0} failed", + "ItemAddedWithName": "{0} was added to the library", + "ItemRemovedWithName": "{0} was removed from the library", + "DeviceOnlineWithName": "{0} is connected", + "UserOnlineFromDevice": "{0} is online from {1}", + "DeviceOfflineWithName": "{0} has disconnected", + "UserOfflineFromDevice": "{0} has disconnected from {1}", + "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", + "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", + "LabelRunningTimeValue": "Running time: {0}", + "LabelIpAddressValue": "Ip address: {0}", + "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", + "UserCreatedWithName": "User {0} has been created", + "UserPasswordChangedWithName": "Password has been changed for user {0}", + "UserDeletedWithName": "User {0} has been deleted", + "MessageServerConfigurationUpdated": "Server configuration has been updated", + "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", + "MessageApplicationUpdated": "Media Browser Server has been updated", + "AuthenticationSucceededWithUserName": "{0} successfully authenticated", + "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", + "UserStartedPlayingItemWithValues": "{0} has started playing {1}", + "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", + "AppDeviceValues": "App: {0}, Device: {1}", + "ProviderValue": "Provider: {0}", + "LabelChannelDownloadSizeLimit": "Download size limit (GB):", + "LabelChannelDownloadSizeLimitHelpText": "Limit the size of the channel download folder.", + "HeaderRecentActivity": "Recent Activity", + "HeaderPeople": "People", + "HeaderDownloadPeopleMetadataFor": "Download biography and images for:", + "OptionComposers": "Composers", + "OptionOthers": "Others", + "HeaderDownloadPeopleMetadataForHelp": "Enabling additional options will provide more on-screen information but will result in slower library scans.", + "ViewTypeFolders": "Folders", + "LabelDisplayFoldersView": "Display a folders view to show plain media folders", + "ViewTypeLiveTvRecordingGroups": "Recordings", + "ViewTypeLiveTvChannels": "Channels", + "LabelEasyPinCode": "Easy pin code:", + "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Media Browser apps, and can also be used for easy in-network sign in.", + "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", + "LabelInNetworkSignInWithEasyPasswordHelp": "If enabled, you'll be able to use your easy pin code to sign in to Media Browser apps from inside your home network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", + "HeaderPassword": "Password", + "HeaderLocalAccess": "Local Access", + "HeaderViewOrder": "View Order", + "ButtonResetEasyPassword": "Reset easy pin code", + "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps", + "LabelMetadataRefreshMode": "Metadata refresh mode:", + "LabelImageRefreshMode": "Image refresh mode:", + "OptionDownloadMissingImages": "Download missing images", + "OptionReplaceExistingImages": "Replace existing images", + "OptionRefreshAllData": "Refresh all data", + "OptionAddMissingDataOnly": "Add missing data only", + "OptionLocalRefreshOnly": "Local refresh only", + "HeaderRefreshMetadata": "Refresh Metadata", + "HeaderPersonInfo": "Person Info", + "HeaderIdentifyItem": "Identify Item", + "HeaderIdentifyItemHelp": "Enter one or more search criteria. Remove criteria to increase search results.", + "HeaderConfirmDeletion": "Confirm Deletion", + "LabelFollowingFileWillBeDeleted": "The following file will be deleted:", + "LabelIfYouWishToContinueWithDeletion": "If you wish to continue, please confirm by entering the value of:", + "ButtonIdentify": "Identify", + "LabelAlbumArtist": "Album artist:", + "LabelAlbum": "Album:", + "LabelCommunityRating": "Community rating:", + "LabelVoteCount": "Vote count:", + "LabelMetascore": "Metascore:", + "LabelCriticRating": "Critic rating:", + "LabelCriticRatingSummary": "Critic rating summary:", + "LabelAwardSummary": "Award summary:", + "LabelWebsite": "Website:", + "LabelTagline": "Tagline:", + "LabelOverview": "Overview:", + "LabelShortOverview": "Short overview:", + "LabelReleaseDate": "Release date:", + "LabelYear": "Year:", + "LabelPlaceOfBirth": "Place of birth:", + "LabelEndDate": "End date:", + "LabelAirDate": "Air days:", + "LabelAirTime:": "Air time:", + "LabelRuntimeMinutes": "Run time (minutes):", + "LabelParentalRating": "Parental rating:", + "LabelCustomRating": "Custom rating:", + "LabelBudget": "Budget", + "LabelRevenue": "Revenue ($):", + "LabelOriginalAspectRatio": "Original aspect ratio:", + "LabelPlayers": "Players:", + "Label3DFormat": "3D format:", + "HeaderAlternateEpisodeNumbers": "Alternate Episode Numbers", + "HeaderSpecialEpisodeInfo": "Special Episode Info", + "HeaderExternalIds": "External Id's:", + "LabelDvdSeasonNumber": "Dvd season number:", + "LabelDvdEpisodeNumber": "Dvd episode number:", + "LabelAbsoluteEpisodeNumber": "Absolute episode number:", + "LabelAirsBeforeSeason": "Airs before season:", + "LabelAirsAfterSeason": "Airs after season:", + "LabelAirsBeforeEpisode": "Airs before episode:", + "LabelTreatImageAs": "Treat image as:", + "LabelDisplayOrder": "Display order:", + "LabelDisplaySpecialsWithinSeasons": "Display specials within seasons they aired in", + "HeaderCountries": "Countries", + "HeaderGenres": "Genres", + "HeaderPlotKeywords": "Plot Keywords", + "HeaderStudios": "Studios", + "HeaderTags": "Tags", + "HeaderMetadataSettings": "Metadata Settings", + "LabelLockItemToPreventChanges": "Lock this item to prevent future changes", + "MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item, or the global default value.", + "TabDonate": "Donate", + "HeaderDonationType": "Donation type:", + "OptionMakeOneTimeDonation": "Make a separate donation", + "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits and will not produce a supporter key.", + "OptionLifeTimeSupporterMembership": "Lifetime supporter membership", + "OptionYearlySupporterMembership": "Yearly supporter membership", + "OptionMonthlySupporterMembership": "Monthly supporter membership", + "OptionNoTrailer": "No Trailer", + "OptionNoThemeSong": "No Theme Song", + "OptionNoThemeVideo": "No Theme Video", + "LabelOneTimeDonationAmount": "Donation amount:", + "ButtonDonate": "Donate", + "OptionActor": "Actor", + "OptionComposer": "Composer", + "OptionDirector": "Director", + "OptionGuestStar": "Guest star", + "OptionProducer": "Producer", + "OptionWriter": "Writer", + "LabelAirDays": "Air days:", + "LabelAirTime": "Air time:", + "HeaderMediaInfo": "Media 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.", + "HeaderXmlSettings": "Xml Settings", + "HeaderXmlDocumentAttributes": "Xml Document Attributes", + "HeaderXmlDocumentAttribute": "Xml Document Attribute", + "XmlDocumentAttributeListHelp": "These attributes are applied to the root element of every xml response.", + "OptionSaveMetadataAsHidden": "Save metadata and images as hidden files", + "LabelExtractChaptersDuringLibraryScan": "Extract chapter images during the library scan", + "LabelExtractChaptersDuringLibraryScanHelp": "If enabled, chapter images will be extracted when videos are imported during the library scan. If disabled they will be extracted during the chapter images scheduled task, allowing the regular library scan to complete faster.", + "LabelConnectGuestUserName": "Their Media Browser username or email address:", + "LabelConnectUserName": "Media Browser username\/email:", + "LabelConnectUserNameHelp": "Connect this user to a Media Browser account to enable easy sign-in access from Media Browser any app without having to know the server ip address.", + "ButtonLearnMoreAboutMediaBrowserConnect": "Learn more about Media Browser Connect", + "LabelExternalPlayers": "External players:", + "LabelExternalPlayersHelp": "Display buttons to play content in external players. This is only available on devices that support url schemes, generally Android and iOS. With external players there is generally no support for remote control or resuming.", + "HeaderSubtitleProfile": "Subtitle Profile", + "HeaderSubtitleProfiles": "Subtitle Profiles", + "HeaderSubtitleProfilesHelp": "Subtitle profiles describe the subtitle formats supported by the device.", + "LabelFormat": "Format:", + "LabelMethod": "Method:", + "LabelDidlMode": "Didl mode:", + "OptionCaptionInfoExSamsung": "CaptionInfoEx (Samsung)", + "OptionResElement": "res element", + "OptionEmbedSubtitles": "Embed within container", + "OptionExternallyDownloaded": "External download", + "OptionHlsSegmentedSubtitles": "Hls segmented subtitles", + "LabelSubtitleFormatHelp": "Example: srt", + "ButtonLearnMore": "Learn more", + "TabPlayback": "Playback", + "HeaderTrailersAndExtras": "Trailers & Extras", + "OptionFindTrailers": "Find trailers from the internet automatically", + "HeaderLanguagePreferences": "Language Preferences", + "TabCinemaMode": "Cinema Mode", + "TitlePlayback": "Playback", + "LabelEnableCinemaModeFor": "Enable cinema mode for:", + "CinemaModeConfigurationHelp": "Cinema mode brings the theater experience straight to your living room with the ability to play trailers and custom intros before the main feature.", + "OptionTrailersFromMyMovies": "Include trailers from movies in my library", + "OptionUpcomingMoviesInTheaters": "Include trailers from new and upcoming movies", + "LabelLimitIntrosToUnwatchedContent": "Only use trailers from unwatched content", + "LabelEnableIntroParentalControl": "Enable smart parental control", + "LabelEnableIntroParentalControlHelp": "Trailers will only be selected with a parental rating equal to or less than the content being watched.", + "LabelTheseFeaturesRequireSupporterHelpAndTrailers": "These features require an active supporter membership and installation of the Trailer channel plugin.", + "OptionTrailersFromMyMoviesHelp": "Requires setup of local trailers.", + "LabelCustomIntrosPath": "Custom intros path:", + "LabelCustomIntrosPathHelp": "A folder containing video files. A video will be randomly selected and played after trailers.", + "ValueSpecialEpisodeName": "Special - {0}", + "LabelSelectInternetTrailersForCinemaMode": "Internet trailers:", + "OptionUpcomingDvdMovies": "Include trailers from new and upcoming movies on Dvd & Blu-ray", + "OptionUpcomingStreamingMovies": "Include trailers from new and upcoming movies on Netflix", + "LabelDisplayTrailersWithinMovieSuggestions": "Display trailers within movie suggestions", + "LabelDisplayTrailersWithinMovieSuggestionsHelp": "Requires installation of the Trailer channel.", + "CinemaModeConfigurationHelp2": "Individual users will have the ability to disable cinema mode within their own preferences.", + "LabelEnableCinemaMode": "Enable cinema mode", + "HeaderCinemaMode": "Cinema Mode", + "LabelDateAddedBehavior": "Date added behavior for new content:", + "OptionDateAddedImportTime": "Use date scanned into the library", + "OptionDateAddedFileTime": "Use file creation date", + "LabelDateAddedBehaviorHelp": "If a metadata value is present it will always be used before either of these options.", + "LabelNumberTrailerToPlay": "Number of trailers to play:", + "TitleDevices": "Devices", + "TabCameraUpload": "Camera Upload", + "TabDevices": "Devices", + "HeaderCameraUploadHelp": "Automatically upload photos and videos taken from your mobile devices into Media Browser.", + "MessageNoDevicesSupportCameraUpload": "You currently don't have any devices that support camera upload.", + "LabelCameraUploadPath": "Camera upload path:", + "LabelCameraUploadPathHelp": "Select a custom upload path, if desired. If unspecified a default folder will be used. If using a custom path it will also need to be added in the library setup area.", + "LabelCreateCameraUploadSubfolder": "Create a subfolder for each device", + "LabelCreateCameraUploadSubfolderHelp": "Specific folders can be assigned to a device by clicking on it from the Devices page.", + "LabelCustomDeviceDisplayName": "Display name:", + "LabelCustomDeviceDisplayNameHelp": "Supply a custom display name or leave empty to use the name reported by the device.", + "HeaderInviteUser": "Invite User", + "LabelConnectGuestUserNameHelp": "This is the username that your friend uses to sign in to the Media Browser website, or their email address.", + "HeaderInviteUserHelp": "Sharing your media with friends is easier than ever before with Media Browser Connect.", + "ButtonSendInvitation": "Send Invitation", + "HeaderSignInWithConnect": "Sign in with Media Browser Connect", + "HeaderGuests": "Guests", + "HeaderLocalUsers": "Local Users", + "HeaderPendingInvitations": "Pending Invitations", + "TabParentalControl": "Parental Control", + "HeaderAccessSchedule": "Access Schedule", + "HeaderAccessScheduleHelp": "Create an access schedule to limit access to certain hours.", + "ButtonAddSchedule": "Add Schedule", + "LabelAccessDay": "Day of week:", + "LabelAccessStart": "Start time:", + "LabelAccessEnd": "End time:", + "HeaderSchedule": "Schedule", + "OptionEveryday": "Every day", + "OptionWeekdays": "Weekdays", + "OptionWeekends": "Weekends", + "MessageProfileInfoSynced": "User profile information synced with Media Browser Connect.", + "HeaderOptionalLinkMediaBrowserAccount": "Optional: Link your Media Browser account", + "ButtonTrailerReel": "Trailer reel", + "HeaderTrailerReel": "Trailer Reel", + "OptionPlayUnwatchedTrailersOnly": "Play only unwatched trailers", + "HeaderTrailerReelHelp": "Start a trailer reel to play a long running playlist of trailers.", + "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.", + "HeaderNewUsers": "New Users", + "ButtonSignUp": "Sign up", + "ButtonForgotPassword": "Forgot password", + "OptionDisableUserPreferences": "Disable access to user preferences", + "OptionDisableUserPreferencesHelp": "If enabled, only administrators will be able to configure user profile images, passwords, and language preferences.", + "HeaderSelectServer": "Select Server", + "MessageNoServersAvailableToConnect": "No servers are available to connect to. If you've been invited to share a server, make sure to accept it below or by clicking the link in the email.", + "TitleNewUser": "New User", + "ButtonConfigurePassword": "Configure Password", + "HeaderDashboardUserPassword": "User passwords are managed within each user's personal profile settings.", + "HeaderLibraryAccess": "Library Access", + "HeaderChannelAccess": "Channel Access", + "HeaderLatestItems": "Latest Items", + "LabelSelectLastestItemsFolders": "Include media from the following sections in Latest Items", + "HeaderShareMediaFolders": "Share Media Folders", + "MessageGuestSharingPermissionsHelp": "Most features are initially unavailable to guests but can be enabled as needed.", + "HeaderInvitations": "Invitations", + "LabelForgotPasswordUsernameHelp": "Enter your username, if you remember it.", + "HeaderForgotPassword": "Forgot Password", + "TitleForgotPassword": "Forgot Password", + "TitlePasswordReset": "Password Reset", + "LabelPasswordRecoveryPinCode": "Pin code:", + "HeaderPasswordReset": "Password Reset", + "HeaderParentalRatings": "Parental Ratings", + "HeaderVideoTypes": "Video Types", + "HeaderYears": "Years", + "HeaderAddTag": "Add Tag", + "LabelBlockItemsWithTags": "Block items with tags:", + "LabelTag": "Tag:", + "LabelEnableSingleImageInDidlLimit": "Limit to single embedded image", + "LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.", + "TabActivity": "Activity", + "TitleSync": "Sync", + "OptionAllowSyncContent": "Allow syncing media to devices", + "NameSeasonUnknown": "Season Unknown", + "NameSeasonNumber": "Season {0}", + "LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)", + "TabJobs": "Jobs", + "TabSyncJobs": "Sync Jobs" +}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/ca.json b/MediaBrowser.Server.Implementations/Localization/Server/ca.json index 6ab1bec15..e1bb9b5cc 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/ca.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/ca.json @@ -40,12 +40,32 @@ "OptionIAcceptTermsOfService": "I accept the terms of service", "ButtonPrivacyPolicy": "Privacy policy", "ButtonTermsOfService": "Terms of Service", + "HeaderDeveloperOptions": "Developer Options", + "OptionEnableWebClientResponseCache": "Enable web client response caching", + "OptionDisableForDevelopmentHelp": "Configure these as needed for web client development purposes.", + "OptionEnableWebClientResourceMinification": "Enable web client resource minification", + "LabelDashboardSourcePath": "Web client source path:", + "LabelDashboardSourcePathHelp": "If running the server from source, specify the path to the dashboard-ui folder. All web client files will be served from this location.", + "ButtonConvertMedia": "Convert media", + "ButtonOrganize": "Organize", "ButtonOk": "Ok", "ButtonCancel": "Cancel", "ButtonNew": "New", "HeaderTV": "TV", "HeaderAudio": "Audio", "HeaderVideo": "Video", + "HeaderPaths": "Paths", + "CategorySync": "Sync", + "HeaderEasyPinCode": "Easy Pin Code", + "RegisterWithPayPal": "Register with PayPal", + "HeaderSyncRequiresSupporterMembership": "Sync Requires a Supporter Membership", + "HeaderEnjoyDayTrial": "Enjoy a 14 Day Free Trial", + "LabelSyncTempPath": "Temporary file path:", + "LabelSyncTempPathHelp": "Specify a custom sync working folder. Converted media created during the sync process will be stored here.", + "LabelCustomCertificatePath": "Custom certificate path:", + "LabelCustomCertificatePathHelp": "Supply your own ssl certificate. If omitted, the server will create a self-signed certificate.", + "TitleNotifications": "Notifications", + "ButtonDonateWithPayPal": "Donate with PayPal", "OptionDetectArchiveFilesAsMedia": "Detect archive files as media", "OptionDetectArchiveFilesAsMediaHelp": "If enabled, files with .rar and .zip extensions will be detected as media files.", "LabelEnterConnectUserName": "User name or email:", @@ -63,12 +83,14 @@ "FolderTypeTvShows": "TV", "FolderTypeInherit": "Inherit", "LabelContentType": "Content type:", + "TitleScheduledTasks": "Scheduled Tasks", "HeaderSetupLibrary": "Setup your media library", "ButtonAddMediaFolder": "Add media folder", "LabelFolderType": "Folder type:", "ReferToMediaLibraryWiki": "Refer to the media library wiki.", "LabelCountry": "Country:", "LabelLanguage": "Language:", + "ButtonJoinTheDevelopmentTeam": "Join the Development Team", "HeaderPreferredMetadataLanguage": "Preferred metadata language:", "LabelSaveLocalMetadata": "Save artwork and metadata into media folders", "LabelSaveLocalMetadataHelp": "Saving artwork and metadata directly into media folders will put them in a place where they can be easily edited.", @@ -86,6 +108,8 @@ "TabCollectionTitles": "Titles", "HeaderDeviceAccess": "Device Access", "OptionEnableAccessFromAllDevices": "Enable access from all devices", + "OptionEnableAccessToAllChannels": "Enable access to all channels", + "OptionEnableAccessToAllLibraries": "Enable access to all libraries", "DeviceAccessHelp": "This only applies to devices that can be uniquely identified and will not prevent browser access. Filtering user device access will prevent them from using new devices until they've been approved here.", "LabelDisplayMissingEpisodesWithinSeasons": "Display missing episodes within seasons", "LabelUnairedMissingEpisodesWithinSeasons": "Display unaired episodes within seasons", @@ -299,7 +323,7 @@ "LabelCachePath": "Cache path:", "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.", "LabelImagesByNamePath": "Images by name path:", - "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, genre and studio images.", "LabelMetadataPath": "Metadata path:", "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.", "LabelTranscodingTempPath": "Transcoding temporary path:", @@ -314,12 +338,14 @@ "OptionEpisodes": "Episodes", "OptionOtherVideos": "Other Videos", "TitleMetadata": "Metadata", - "LabelAutomaticUpdatesFanart": "Enable automatic updates from FanArt.tv", + "LabelAutomaticUpdates": "Enable automatic updates", "LabelAutomaticUpdatesTmdb": "Enable automatic updates from TheMovieDB.org", "LabelAutomaticUpdatesTvdb": "Enable automatic updates from TheTVDB.com", "LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.", "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.", "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.", + "LabelFanartApiKey": "Personal api key:", + "LabelFanartApiKeyHelp": "Requests to fanart without a personal API key return results that were approved over 7 days ago. With a personal API key that drops to 48 hours and if you are also a fanart VIP member that will further drop to around 10 minutes.", "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", "LabelMetadataDownloadLanguage": "Preferred download language:", "ButtonAutoScroll": "Auto-scroll", @@ -487,6 +513,7 @@ "HeaderSystemPaths": "System Paths", "LinkCommunity": "Community", "LinkGithub": "Github", + "LinkApi": "Api", "LinkApiDocumentation": "Api Documentation", "LabelFriendlyServerName": "Friendly server name:", "LabelFriendlyServerNameHelp": "This name will be used to identify this server. If left blank, the computer name will be used.", @@ -494,20 +521,25 @@ "LabelPreferredDisplayLanguageHelp": "Translating Media Browser is an ongoing project and is not yet complete.", "LabelReadHowYouCanContribute": "Read about how you can contribute.", "HeaderNewCollection": "New Collection", - "HeaderAddToCollection": "Add to Collection", "ButtonSubmit": "Submit", - "NewCollectionNameExample": "Example: Star Wars Collection", - "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata", "ButtonCreate": "Create", - "LabelLocalHttpServerPortNumber": "Local port number:", + "LabelCustomCss": "Custom css:", + "LabelCustomCssHelp": "Apply your own custom css to the web interface.", + "LabelLocalHttpServerPortNumber": "Local http port number:", "LabelLocalHttpServerPortNumberHelp": "The tcp port number that Media Browser's http server should bind to.", - "LabelPublicPort": "Public port number:", - "LabelPublicPortHelp": "The public port number that should be mapped to the local port.", + "LabelPublicHttpPort": "Public http port number:", + "LabelPublicHttpPortHelp": "The public port number that should be mapped to the local http port.", + "LabelPublicHttpsPort": "Public https port number:", + "LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.", + "LabelEnableHttps": "Report https as external address", + "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.", + "LabelHttpsPort": "Local https port number:", + "LabelHttpsPortHelp": "The tcp port number that Media Browser's https server should bind to.", "LabelWebSocketPortNumber": "Web socket port number:", "LabelEnableAutomaticPortMap": "Enable automatic port mapping", "LabelEnableAutomaticPortMapHelp": "Attempt to automatically map the public port to the local port via UPnP. This may not work with some router models.", - "LabelExternalDDNS": "External DDNS:", - "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely.", + "LabelExternalDDNS": "External WAN Address:", + "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely. Leave empty for automatic detection.", "TabResume": "Resume", "TabWeather": "Weather", "TitleAppSettings": "App Settings", @@ -575,6 +607,7 @@ "ButtonRestart": "Restart", "ButtonShutdown": "Shutdown", "ButtonUpdateNow": "Update Now", + "TabHosting": "Hosting", "PleaseUpdateManually": "Please shutdown the server and update manually.", "NewServerVersionAvailable": "A new version of Media Browser Server is available!", "ServerUpToDate": "Media Browser Server is up to date", @@ -636,6 +669,7 @@ "NotificationOptionInstallationFailed": "Installation failure", "NotificationOptionNewLibraryContent": "New content added", "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", + "NotificationOptionCameraImageUploaded": "Camera image uploaded", "SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.", "NotificationOptionServerRestartRequired": "Server restart required", "LabelNotificationEnabled": "Enable this notification", @@ -853,6 +887,8 @@ "OptionDefaultSort": "Default", "OptionCommunityMostWatchedSort": "Most Watched", "TabNextUp": "Next Up", + "HeaderBecomeMediaBrowserSupporter": "Become a Media Browser Supporter", + "TextEnjoyBonusFeatures": "Enjoy Bonus Features", "MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.", "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.", "MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.", @@ -869,7 +905,6 @@ "LabelChannelDownloadAge": "Delete content after: (days)", "LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.", "ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.", - "LabelSelectCollection": "Select collection:", "ButtonOptions": "Options", "ViewTypeMovies": "Movies", "ViewTypeTvShows": "TV", @@ -917,7 +952,7 @@ "OptionLatestTvRecordings": "Latest recordings", "LabelProtocolInfo": "Protocol info:", "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.", - "TabKodiMetadata": "Kodi", + "TabNfo": "Nfo", "HeaderKodiMetadataHelp": "Media Browser includes native support for Kodi Nfo metadata and images. To enable or disable Kodi metadata, use the Advanced tab to configure options for your media types.", "LabelKodiMetadataUser": "Sync user watch data to nfo's for:", "LabelKodiMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Kodi.", @@ -931,6 +966,7 @@ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:", "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.", "LabelDisplayCollectionsView": "Display a collections view to show movie collections", + "LabelDisplayCollectionsViewHelp": "This will create a separate view to display collections that you've created or have access to. To create a collection, right-click or tap-hold any movie and select 'Add to Collection'. ", "LabelKodiMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs", "LabelKodiMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Kodi skin compatibility.", "TabServices": "Services", @@ -1084,11 +1120,14 @@ "LabelDisplayFoldersView": "Display a folders view to show plain media folders", "ViewTypeLiveTvRecordingGroups": "Recordings", "ViewTypeLiveTvChannels": "Channels", - "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password", - "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.", + "LabelEasyPinCode": "Easy pin code:", + "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Media Browser apps, and can also be used for easy in-network sign in.", + "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", + "LabelInNetworkSignInWithEasyPasswordHelp": "If enabled, you'll be able to use your easy pin code to sign in to Media Browser apps from inside your home network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", "HeaderPassword": "Password", "HeaderLocalAccess": "Local Access", "HeaderViewOrder": "View Order", + "ButtonResetEasyPassword": "Reset easy pin code", "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps", "LabelMetadataRefreshMode": "Metadata refresh mode:", "LabelImageRefreshMode": "Image refresh mode:", @@ -1279,7 +1318,7 @@ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.", "HeaderNewUsers": "New Users", "ButtonSignUp": "Sign up", - "ButtonForgotPassword": "Forgot password?", + "ButtonForgotPassword": "Forgot password", "OptionDisableUserPreferences": "Disable access to user preferences", "OptionDisableUserPreferencesHelp": "If enabled, only administrators will be able to configure user profile images, passwords, and language preferences.", "HeaderSelectServer": "Select Server", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/cs.json b/MediaBrowser.Server.Implementations/Localization/Server/cs.json index 7f1e6a067..7dada50ac 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/cs.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/cs.json @@ -40,12 +40,32 @@ "OptionIAcceptTermsOfService": "I accept the terms of service", "ButtonPrivacyPolicy": "Privacy policy", "ButtonTermsOfService": "Terms of Service", + "HeaderDeveloperOptions": "Developer Options", + "OptionEnableWebClientResponseCache": "Enable web client response caching", + "OptionDisableForDevelopmentHelp": "Configure these as needed for web client development purposes.", + "OptionEnableWebClientResourceMinification": "Enable web client resource minification", + "LabelDashboardSourcePath": "Web client source path:", + "LabelDashboardSourcePathHelp": "If running the server from source, specify the path to the dashboard-ui folder. All web client files will be served from this location.", + "ButtonConvertMedia": "Convert media", + "ButtonOrganize": "Organize", "ButtonOk": "Ok", "ButtonCancel": "Zru\u0161it", "ButtonNew": "Nov\u00e9", "HeaderTV": "TV", "HeaderAudio": "Audio", "HeaderVideo": "Video", + "HeaderPaths": "Paths", + "CategorySync": "Sync", + "HeaderEasyPinCode": "Easy Pin Code", + "RegisterWithPayPal": "Register with PayPal", + "HeaderSyncRequiresSupporterMembership": "Sync Requires a Supporter Membership", + "HeaderEnjoyDayTrial": "Enjoy a 14 Day Free Trial", + "LabelSyncTempPath": "Temporary file path:", + "LabelSyncTempPathHelp": "Specify a custom sync working folder. Converted media created during the sync process will be stored here.", + "LabelCustomCertificatePath": "Custom certificate path:", + "LabelCustomCertificatePathHelp": "Supply your own ssl certificate. If omitted, the server will create a self-signed certificate.", + "TitleNotifications": "Notifications", + "ButtonDonateWithPayPal": "Donate with PayPal", "OptionDetectArchiveFilesAsMedia": "Detect archive files as media", "OptionDetectArchiveFilesAsMediaHelp": "If enabled, files with .rar and .zip extensions will be detected as media files.", "LabelEnterConnectUserName": "User name or email:", @@ -63,12 +83,14 @@ "FolderTypeTvShows": "TV", "FolderTypeInherit": "Inherit", "LabelContentType": "Content type:", + "TitleScheduledTasks": "Scheduled Tasks", "HeaderSetupLibrary": "Nastaven\u00ed Va\u0161i knihovny m\u00e9di\u00ed", "ButtonAddMediaFolder": "P\u0159idat slo\u017eku m\u00e9di\u00ed", "LabelFolderType": "Typ slo\u017eky:", "ReferToMediaLibraryWiki": "Pod\u00edvejte se na wiki knihovny m\u00e9di\u00ed.", "LabelCountry": "Zem\u011b:", "LabelLanguage": "Jazyk:", + "ButtonJoinTheDevelopmentTeam": "Join the Development Team", "HeaderPreferredMetadataLanguage": "Preferovan\u00fd jazyk metadat:", "LabelSaveLocalMetadata": "Ulo\u017eit p\u0159ebaly a metadata do slo\u017eky s m\u00e9dii", "LabelSaveLocalMetadataHelp": "Povol\u00edte-li ulo\u017een\u00ed p\u0159ebal\u016f a metadat do slo\u017eky s m\u00e9dii bude mo\u017en\u00e9 je jednodu\u0161e upravovat.", @@ -86,6 +108,8 @@ "TabCollectionTitles": "N\u00e1zvy", "HeaderDeviceAccess": "Device Access", "OptionEnableAccessFromAllDevices": "Enable access from all devices", + "OptionEnableAccessToAllChannels": "Enable access to all channels", + "OptionEnableAccessToAllLibraries": "Enable access to all libraries", "DeviceAccessHelp": "This only applies to devices that can be uniquely identified and will not prevent browser access. Filtering user device access will prevent them from using new devices until they've been approved here.", "LabelDisplayMissingEpisodesWithinSeasons": "Zobrazit chyb\u011bj\u00edc\u00ed epizody", "LabelUnairedMissingEpisodesWithinSeasons": "Zobrazit neprov\u011btran\u00e9 epizody v r\u00e1mci sez\u00f3n", @@ -299,7 +323,7 @@ "LabelCachePath": "Adres\u00e1\u0159 pro cache:", "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.", "LabelImagesByNamePath": "Obr\u00e1zky dle n\u00e1zvu cesty:", - "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, genre and studio images.", "LabelMetadataPath": "Adres\u00e1\u0159 pro metadata:", "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.", "LabelTranscodingTempPath": "Adres\u00e1\u0159 p\u0159ek\u00f3dov\u00e1n\u00ed:", @@ -314,12 +338,14 @@ "OptionEpisodes": "Episody", "OptionOtherVideos": "Ostatn\u00ed videa", "TitleMetadata": "Metadata", - "LabelAutomaticUpdatesFanart": "Povolit automatick\u00e9 aktualizace z FanArt.tv", + "LabelAutomaticUpdates": "Enable automatic updates", "LabelAutomaticUpdatesTmdb": "Povolit automatick\u00e9 aktualizace z TheMovieDB.org", "LabelAutomaticUpdatesTvdb": "Povolit automatick\u00e9 aktualizace z TheTVDB.org", "LabelAutomaticUpdatesFanartHelp": "Pokud je povoleno, budou nov\u00e9 sn\u00edmky budou sta\u017eeny automaticky tak, jak jsou p\u0159id\u00e1ny na fanart.tv. St\u00e1vaj\u00edc\u00ed sn\u00edmky nebudou nahrazeny.", "LabelAutomaticUpdatesTmdbHelp": "Pokud je povoleno, budou nov\u00e9 sn\u00edmky budou sta\u017eeny automaticky tak, jak jsou p\u0159id\u00e1ny na TheMovieDB.org. St\u00e1vaj\u00edc\u00ed sn\u00edmky nebudou nahrazeny.", "LabelAutomaticUpdatesTvdbHelp": "Pokud je povoleno, budou nov\u00e9 sn\u00edmky budou sta\u017eeny automaticky tak, jak jsou p\u0159id\u00e1ny na TheTVDB.org. St\u00e1vaj\u00edc\u00ed sn\u00edmky nebudou nahrazeny.", + "LabelFanartApiKey": "Personal api key:", + "LabelFanartApiKeyHelp": "Requests to fanart without a personal API key return results that were approved over 7 days ago. With a personal API key that drops to 48 hours and if you are also a fanart VIP member that will further drop to around 10 minutes.", "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", "LabelMetadataDownloadLanguage": "Preferovan\u00fd jazyk:", "ButtonAutoScroll": "Automatick\u00e9 posouv\u00e1n\u00ed", @@ -487,6 +513,7 @@ "HeaderSystemPaths": "Syst\u00e9mov\u00e9 cesty", "LinkCommunity": "Komunita", "LinkGithub": "GitHub", + "LinkApi": "Api", "LinkApiDocumentation": "Dokumentace API", "LabelFriendlyServerName": "N\u00e1zev serveru:", "LabelFriendlyServerNameHelp": "Toto jm\u00e9no bude pou\u017eito jako identifikace serveru, ponech\u00e1te-li pr\u00e1zdn\u00e9 bude pou\u017eit n\u00e1zev po\u010d\u00edta\u010de.", @@ -494,20 +521,25 @@ "LabelPreferredDisplayLanguageHelp": "P\u0159eklad programu Media Browser prob\u00edh\u00e1, a je\u0161t\u011b nen\u00ed dokon\u010den.", "LabelReadHowYouCanContribute": "P\u0159e\u010dt\u011bte si o tom, jak m\u016f\u017eete p\u0159isp\u011bt.", "HeaderNewCollection": "Nov\u00e1 kolekce", - "HeaderAddToCollection": "Add to Collection", "ButtonSubmit": "Submit", - "NewCollectionNameExample": "P\u0159\u00edklad: Kolekce Star Wars", - "OptionSearchForInternetMetadata": "Prohledat internet pro nalezen\u00ed metadat a obalu.", "ButtonCreate": "Vytvo\u0159it", - "LabelLocalHttpServerPortNumber": "Local port number:", + "LabelCustomCss": "Custom css:", + "LabelCustomCssHelp": "Apply your own custom css to the web interface.", + "LabelLocalHttpServerPortNumber": "Local http port number:", "LabelLocalHttpServerPortNumberHelp": "The tcp port number that Media Browser's http server should bind to.", - "LabelPublicPort": "Public port number:", - "LabelPublicPortHelp": "The public port number that should be mapped to the local port.", + "LabelPublicHttpPort": "Public http port number:", + "LabelPublicHttpPortHelp": "The public port number that should be mapped to the local http port.", + "LabelPublicHttpsPort": "Public https port number:", + "LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.", + "LabelEnableHttps": "Report https as external address", + "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.", + "LabelHttpsPort": "Local https port number:", + "LabelHttpsPortHelp": "The tcp port number that Media Browser's https server should bind to.", "LabelWebSocketPortNumber": "\u010c\u00edslo portu web socketu:", "LabelEnableAutomaticPortMap": "Enable automatic port mapping", "LabelEnableAutomaticPortMapHelp": "Attempt to automatically map the public port to the local port via UPnP. This may not work with some router models.", - "LabelExternalDDNS": "Extern\u00ed DDNS:", - "LabelExternalDDNSHelp": "Pokud m\u00e1te dynamickou DNS zadejte jej zde. Media Browser aplikace ho pou\u017eije pro vzd\u00e1len\u00fd p\u0159\u00edstup.", + "LabelExternalDDNS": "External WAN Address:", + "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely. Leave empty for automatic detection.", "TabResume": "P\u0159eru\u0161it", "TabWeather": "Po\u010das\u00ed", "TitleAppSettings": "Nastaven\u00ed aplikace", @@ -575,6 +607,7 @@ "ButtonRestart": "Restart", "ButtonShutdown": "Vypnout", "ButtonUpdateNow": "Aktualizujte te\u010f", + "TabHosting": "Hosting", "PleaseUpdateManually": "Pros\u00edm, vypn\u011bte server a aktualizujte ru\u010dne.", "NewServerVersionAvailable": "Je dostupn\u00e1 nov\u00e1 verze programu Media Browser!", "ServerUpToDate": "Media Browser server je aktu\u00e1ln\u00ed.", @@ -636,6 +669,7 @@ "NotificationOptionInstallationFailed": "Installation failure", "NotificationOptionNewLibraryContent": "New content added", "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", + "NotificationOptionCameraImageUploaded": "Camera image uploaded", "SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.", "NotificationOptionServerRestartRequired": "Je vy\u017eadov\u00e1n restart serveru", "LabelNotificationEnabled": "Enable this notification", @@ -853,6 +887,8 @@ "OptionDefaultSort": "Default", "OptionCommunityMostWatchedSort": "Nejsledovan\u011bj\u0161\u00ed", "TabNextUp": "Next Up", + "HeaderBecomeMediaBrowserSupporter": "Become a Media Browser Supporter", + "TextEnjoyBonusFeatures": "Enjoy Bonus Features", "MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.", "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.", "MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.", @@ -869,7 +905,6 @@ "LabelChannelDownloadAge": "Delete content after: (days)", "LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.", "ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.", - "LabelSelectCollection": "Select collection:", "ButtonOptions": "Options", "ViewTypeMovies": "Filmy", "ViewTypeTvShows": "Televize", @@ -917,7 +952,7 @@ "OptionLatestTvRecordings": "Latest recordings", "LabelProtocolInfo": "Protocol info:", "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.", - "TabKodiMetadata": "Kodi", + "TabNfo": "Nfo", "HeaderKodiMetadataHelp": "Media Browser includes native support for Kodi Nfo metadata and images. To enable or disable Kodi metadata, use the Advanced tab to configure options for your media types.", "LabelKodiMetadataUser": "Sync user watch data to nfo's for:", "LabelKodiMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Kodi.", @@ -931,6 +966,7 @@ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:", "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.", "LabelDisplayCollectionsView": "Display a collections view to show movie collections", + "LabelDisplayCollectionsViewHelp": "This will create a separate view to display collections that you've created or have access to. To create a collection, right-click or tap-hold any movie and select 'Add to Collection'. ", "LabelKodiMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs", "LabelKodiMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Kodi skin compatibility.", "TabServices": "Slu\u017eby", @@ -1084,11 +1120,14 @@ "LabelDisplayFoldersView": "Display a folders view to show plain media folders", "ViewTypeLiveTvRecordingGroups": "Recordings", "ViewTypeLiveTvChannels": "Channels", - "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password", - "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.", + "LabelEasyPinCode": "Easy pin code:", + "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Media Browser apps, and can also be used for easy in-network sign in.", + "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", + "LabelInNetworkSignInWithEasyPasswordHelp": "If enabled, you'll be able to use your easy pin code to sign in to Media Browser apps from inside your home network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", "HeaderPassword": "Password", "HeaderLocalAccess": "Local Access", "HeaderViewOrder": "View Order", + "ButtonResetEasyPassword": "Reset easy pin code", "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps", "LabelMetadataRefreshMode": "Metadata refresh mode:", "LabelImageRefreshMode": "Image refresh mode:", @@ -1279,7 +1318,7 @@ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.", "HeaderNewUsers": "New Users", "ButtonSignUp": "Sign up", - "ButtonForgotPassword": "Forgot password?", + "ButtonForgotPassword": "Forgot password", "OptionDisableUserPreferences": "Disable access to user preferences", "OptionDisableUserPreferencesHelp": "If enabled, only administrators will be able to configure user profile images, passwords, and language preferences.", "HeaderSelectServer": "Select Server", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/da.json b/MediaBrowser.Server.Implementations/Localization/Server/da.json index 652fd8808..b35932f8e 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/da.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/da.json @@ -40,12 +40,32 @@ "OptionIAcceptTermsOfService": "I accept the terms of service", "ButtonPrivacyPolicy": "Privacy policy", "ButtonTermsOfService": "Terms of Service", + "HeaderDeveloperOptions": "Developer Options", + "OptionEnableWebClientResponseCache": "Enable web client response caching", + "OptionDisableForDevelopmentHelp": "Configure these as needed for web client development purposes.", + "OptionEnableWebClientResourceMinification": "Enable web client resource minification", + "LabelDashboardSourcePath": "Web client source path:", + "LabelDashboardSourcePathHelp": "If running the server from source, specify the path to the dashboard-ui folder. All web client files will be served from this location.", + "ButtonConvertMedia": "Convert media", + "ButtonOrganize": "Organize", "ButtonOk": "Ok", "ButtonCancel": "Annuller", "ButtonNew": "Ny", "HeaderTV": "TV", "HeaderAudio": "Audio", "HeaderVideo": "Video", + "HeaderPaths": "Paths", + "CategorySync": "Sync", + "HeaderEasyPinCode": "Easy Pin Code", + "RegisterWithPayPal": "Register with PayPal", + "HeaderSyncRequiresSupporterMembership": "Sync Requires a Supporter Membership", + "HeaderEnjoyDayTrial": "Enjoy a 14 Day Free Trial", + "LabelSyncTempPath": "Temporary file path:", + "LabelSyncTempPathHelp": "Specify a custom sync working folder. Converted media created during the sync process will be stored here.", + "LabelCustomCertificatePath": "Custom certificate path:", + "LabelCustomCertificatePathHelp": "Supply your own ssl certificate. If omitted, the server will create a self-signed certificate.", + "TitleNotifications": "Notifications", + "ButtonDonateWithPayPal": "Donate with PayPal", "OptionDetectArchiveFilesAsMedia": "Detect archive files as media", "OptionDetectArchiveFilesAsMediaHelp": "If enabled, files with .rar and .zip extensions will be detected as media files.", "LabelEnterConnectUserName": "User name or email:", @@ -63,12 +83,14 @@ "FolderTypeTvShows": "TV", "FolderTypeInherit": "Inherit", "LabelContentType": "Content type:", + "TitleScheduledTasks": "Scheduled Tasks", "HeaderSetupLibrary": "Konfigurer dit medie bibliotek", "ButtonAddMediaFolder": "Tilf\u00f8j medie mappe", "LabelFolderType": "Mappe type:", "ReferToMediaLibraryWiki": "Der henvises til medie bibliotekets wiki.", "LabelCountry": "Land:", "LabelLanguage": "Sprog:", + "ButtonJoinTheDevelopmentTeam": "Join the Development Team", "HeaderPreferredMetadataLanguage": "Foretrukket metadata sprog:", "LabelSaveLocalMetadata": "Gem illustrationer og metadata i medie mapper", "LabelSaveLocalMetadataHelp": "Lagring af illustrationer og metadata i medie mapper, vil placerer dem et sted hvor de nemt kan redigeres.", @@ -86,6 +108,8 @@ "TabCollectionTitles": "Titler", "HeaderDeviceAccess": "Device Access", "OptionEnableAccessFromAllDevices": "Enable access from all devices", + "OptionEnableAccessToAllChannels": "Enable access to all channels", + "OptionEnableAccessToAllLibraries": "Enable access to all libraries", "DeviceAccessHelp": "This only applies to devices that can be uniquely identified and will not prevent browser access. Filtering user device access will prevent them from using new devices until they've been approved here.", "LabelDisplayMissingEpisodesWithinSeasons": "Vis manglende episoder i s\u00e6soner", "LabelUnairedMissingEpisodesWithinSeasons": "Vis endnu ikke sendte episoder i s\u00e6soner", @@ -299,7 +323,7 @@ "LabelCachePath": "Cache sti:", "LabelCachePathHelp": "Definer en alternativ mappe til serverens cache filer, s\u00e5som billeder.", "LabelImagesByNamePath": "Billeder efter navn sti:", - "LabelImagesByNamePathHelp": "Angiv en alternativ mappe til downloadede informationer om skuespillere, artister, genrer og studie billeder.", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, genre and studio images.", "LabelMetadataPath": "Metadata sti:", "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.", "LabelTranscodingTempPath": "Transcoding temporary path:", @@ -314,12 +338,14 @@ "OptionEpisodes": "Episoder", "OptionOtherVideos": "Andre Videoer", "TitleMetadata": "Metadata", - "LabelAutomaticUpdatesFanart": "Aktiver automatiske opdateringer fra FanArt.tv", + "LabelAutomaticUpdates": "Enable automatic updates", "LabelAutomaticUpdatesTmdb": "Aktiver automatiske opdateringer fra TheMovieDB.org", "LabelAutomaticUpdatesTvdb": "Aktiver automatiske opdateringer fra TheTVDB.com", "LabelAutomaticUpdatesFanartHelp": "Hvis aktiveret, vil nye billeder blive hentet automatisk n\u00e5r de bliver tilf\u00f8jet til fanart.tv. Eksisterende billeder vil ikke bliver over skrevet.", "LabelAutomaticUpdatesTmdbHelp": "Hvis aktiveret, vil nye billeder blive hentet automatisk n\u00e5r de bliver tilf\u00f8jet til TheMovieDB.org. Eksisterende billeder vil ikke bliver over skrevet.", "LabelAutomaticUpdatesTvdbHelp": "Hvis aktiveret, vil nye billeder blive hentet automatisk n\u00e5r de bliver tilf\u00f8jet til TheTVDB.com. Eksisterende billeder vil ikke bliver over skrevet.", + "LabelFanartApiKey": "Personal api key:", + "LabelFanartApiKeyHelp": "Requests to fanart without a personal API key return results that were approved over 7 days ago. With a personal API key that drops to 48 hours and if you are also a fanart VIP member that will further drop to around 10 minutes.", "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", "LabelMetadataDownloadLanguage": "Preferred download language:", "ButtonAutoScroll": "Auto-scroll", @@ -487,6 +513,7 @@ "HeaderSystemPaths": "System Paths", "LinkCommunity": "Community", "LinkGithub": "Github", + "LinkApi": "Api", "LinkApiDocumentation": "Api Documentation", "LabelFriendlyServerName": "Friendly server name:", "LabelFriendlyServerNameHelp": "This name will be used to identify this server. If left blank, the computer name will be used.", @@ -494,20 +521,25 @@ "LabelPreferredDisplayLanguageHelp": "Translating Media Browser is an ongoing project and is not yet complete.", "LabelReadHowYouCanContribute": "Read about how you can contribute.", "HeaderNewCollection": "New Collection", - "HeaderAddToCollection": "Add to Collection", "ButtonSubmit": "Submit", - "NewCollectionNameExample": "Example: Star Wars Collection", - "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata", "ButtonCreate": "Create", - "LabelLocalHttpServerPortNumber": "Local port number:", + "LabelCustomCss": "Custom css:", + "LabelCustomCssHelp": "Apply your own custom css to the web interface.", + "LabelLocalHttpServerPortNumber": "Local http port number:", "LabelLocalHttpServerPortNumberHelp": "The tcp port number that Media Browser's http server should bind to.", - "LabelPublicPort": "Public port number:", - "LabelPublicPortHelp": "The public port number that should be mapped to the local port.", + "LabelPublicHttpPort": "Public http port number:", + "LabelPublicHttpPortHelp": "The public port number that should be mapped to the local http port.", + "LabelPublicHttpsPort": "Public https port number:", + "LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.", + "LabelEnableHttps": "Report https as external address", + "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.", + "LabelHttpsPort": "Local https port number:", + "LabelHttpsPortHelp": "The tcp port number that Media Browser's https server should bind to.", "LabelWebSocketPortNumber": "Web socket port number:", "LabelEnableAutomaticPortMap": "Enable automatic port mapping", "LabelEnableAutomaticPortMapHelp": "Attempt to automatically map the public port to the local port via UPnP. This may not work with some router models.", - "LabelExternalDDNS": "External DDNS:", - "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely.", + "LabelExternalDDNS": "External WAN Address:", + "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely. Leave empty for automatic detection.", "TabResume": "Resume", "TabWeather": "Weather", "TitleAppSettings": "App Settings", @@ -575,6 +607,7 @@ "ButtonRestart": "Restart", "ButtonShutdown": "Shutdown", "ButtonUpdateNow": "Update Now", + "TabHosting": "Hosting", "PleaseUpdateManually": "Please shutdown the server and update manually.", "NewServerVersionAvailable": "A new version of Media Browser Server is available!", "ServerUpToDate": "Media Browser Server is up to date", @@ -636,6 +669,7 @@ "NotificationOptionInstallationFailed": "Installation failure", "NotificationOptionNewLibraryContent": "New content added", "NotificationOptionNewLibraryContentMultiple": "Nyt indhold tilf\u00f8jet (flere)", + "NotificationOptionCameraImageUploaded": "Camera image uploaded", "SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.", "NotificationOptionServerRestartRequired": "Server restart required", "LabelNotificationEnabled": "Enable this notification", @@ -853,6 +887,8 @@ "OptionDefaultSort": "Default", "OptionCommunityMostWatchedSort": "Most Watched", "TabNextUp": "Next Up", + "HeaderBecomeMediaBrowserSupporter": "Become a Media Browser Supporter", + "TextEnjoyBonusFeatures": "Enjoy Bonus Features", "MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.", "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.", "MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.", @@ -869,7 +905,6 @@ "LabelChannelDownloadAge": "Delete content after: (days)", "LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.", "ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.", - "LabelSelectCollection": "Select collection:", "ButtonOptions": "Options", "ViewTypeMovies": "Movies", "ViewTypeTvShows": "TV", @@ -917,7 +952,7 @@ "OptionLatestTvRecordings": "Latest recordings", "LabelProtocolInfo": "Protocol info:", "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.", - "TabKodiMetadata": "Kodi", + "TabNfo": "Nfo", "HeaderKodiMetadataHelp": "Media Browser includes native support for Kodi Nfo metadata and images. To enable or disable Kodi metadata, use the Advanced tab to configure options for your media types.", "LabelKodiMetadataUser": "Sync user watch data to nfo's for:", "LabelKodiMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Kodi.", @@ -931,6 +966,7 @@ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:", "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.", "LabelDisplayCollectionsView": "Display a collections view to show movie collections", + "LabelDisplayCollectionsViewHelp": "This will create a separate view to display collections that you've created or have access to. To create a collection, right-click or tap-hold any movie and select 'Add to Collection'. ", "LabelKodiMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs", "LabelKodiMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Kodi skin compatibility.", "TabServices": "Services", @@ -1084,11 +1120,14 @@ "LabelDisplayFoldersView": "Display a folders view to show plain media folders", "ViewTypeLiveTvRecordingGroups": "Recordings", "ViewTypeLiveTvChannels": "Channels", - "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password", - "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.", + "LabelEasyPinCode": "Easy pin code:", + "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Media Browser apps, and can also be used for easy in-network sign in.", + "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", + "LabelInNetworkSignInWithEasyPasswordHelp": "If enabled, you'll be able to use your easy pin code to sign in to Media Browser apps from inside your home network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", "HeaderPassword": "Password", "HeaderLocalAccess": "Local Access", "HeaderViewOrder": "View Order", + "ButtonResetEasyPassword": "Reset easy pin code", "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps", "LabelMetadataRefreshMode": "Metadata refresh mode:", "LabelImageRefreshMode": "Image refresh mode:", @@ -1279,7 +1318,7 @@ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.", "HeaderNewUsers": "New Users", "ButtonSignUp": "Sign up", - "ButtonForgotPassword": "Forgot password?", + "ButtonForgotPassword": "Forgot password", "OptionDisableUserPreferences": "Disable access to user preferences", "OptionDisableUserPreferencesHelp": "If enabled, only administrators will be able to configure user profile images, passwords, and language preferences.", "HeaderSelectServer": "Select Server", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/de.json b/MediaBrowser.Server.Implementations/Localization/Server/de.json index da40da2d2..dd05b519e 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/de.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/de.json @@ -27,7 +27,7 @@ "AWindowsServiceHasBeenInstalled": "Ein Windows Dienst wurde installiert.", "WindowsServiceIntro1": "Media Browser Server l\u00e4uft normalerweise als Desktop Anwendung mit einem Symbol in der Taskleiste. Du kannst den Server aber auch als Hintergrunddienst starten. Verwende dazu das Windows Service Control Panel (services.msc).", "WindowsServiceIntro2": "Der Dienst kann nicht zu gleichen Zeit wie die Desktop Anwendung laufen. Schlie\u00dfe daher die Desktop Anwendung bevor du den Dienst startest. Der Dienst ben\u00f6tigt administrative Rechte, die du \u00fcber die Systemsteuerung einstellen musst. Beachte bitte auch, dass der Dienst zur Zeit nicht automatisch aktualisiert wird. Neue Versionen m\u00fcssen daher manuell installiert werden.", - "WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click <b>Finish<\/b> to view the <b>Server Dashboard<\/b>.", + "WizardCompleted": "Mehr brauchen wir momentan nicht. Media Browser hat nun angefangen Informationen zu Ihren Medien zu suchen. Schauen Sie sich nun unsere Apps an und klicken Sie auf <b>Fertig<\/b> um auf die <b>Server Startseite<\/b> zu gelangen.", "LabelConfigureSettings": "Konfiguriere Einstellungen", "LabelEnableVideoImageExtraction": "Aktiviere Videobild-Extrahierung", "VideoImageExtractionHelp": "F\u00fcr Videos die noch keien Bilder haben, und f\u00fcr die wir keine Internetbilder finden k\u00f6nnen. Hierdurch wird der erste Bibliothekenscan etwas mehr Zeit beanspruchen, f\u00fchrt aber zu einer ansprechenderen Pr\u00e4sentation.", @@ -40,14 +40,34 @@ "OptionIAcceptTermsOfService": "Ich akzeptiere die Nutzungsbedingungen.", "ButtonPrivacyPolicy": "Datenschutzbestimmungen", "ButtonTermsOfService": "Nutzungsbedingungen", + "HeaderDeveloperOptions": "Entwickleroptionen", + "OptionEnableWebClientResponseCache": "Aktiviere die Antwortzwischenspeicherung des Web Clients", + "OptionDisableForDevelopmentHelp": "Konfiguriere diese Einstellungen f\u00fcr die ben\u00f6tigten Entwicklungszwecke des Web Clients.", + "OptionEnableWebClientResourceMinification": "Aktiviere die Ressourcenminimierung des Web Clients", + "LabelDashboardSourcePath": "Web Client Sourcepfad:", + "LabelDashboardSourcePathHelp": "Spezifiziere den Pfad zum Dashboard-UI-Verzeichniss, falls der Server von der Source ausgef\u00fchrt wird. Alle Web-Client-Dateien werden von diesem Pfad aus bedient werden.", + "ButtonConvertMedia": "Convert media", + "ButtonOrganize": "Organisieren", "ButtonOk": "Ok", "ButtonCancel": "Abbrechen", "ButtonNew": "Neu", "HeaderTV": "TV", "HeaderAudio": "Audio", "HeaderVideo": "Video", - "OptionDetectArchiveFilesAsMedia": "Detect archive files as media", - "OptionDetectArchiveFilesAsMediaHelp": "If enabled, files with .rar and .zip extensions will be detected as media files.", + "HeaderPaths": "Pfade", + "CategorySync": "Sync", + "HeaderEasyPinCode": "Easy Pin Code", + "RegisterWithPayPal": "Register with PayPal", + "HeaderSyncRequiresSupporterMembership": "Synchronisation ben\u00f6tigt eine Supporter-Mitgliedschaft", + "HeaderEnjoyDayTrial": "Genie\u00dfen Sie eine 14 Tage Testversion", + "LabelSyncTempPath": "Verzeichnis f\u00fcr tempor\u00e4re Dateien", + "LabelSyncTempPathHelp": "Legen Sie einen eigenen Synchronisations-Arbeits Verzeichnis fest. Konvertierte Medien werden w\u00e4hrend der Synchronisation hier gespeichert.", + "LabelCustomCertificatePath": "Eigener Zertifikats Ordner:", + "LabelCustomCertificatePathHelp": "Legen Sie ein eigenes SSL Zertifikat fest. Der Server wird ein selbst signiertes Zertifikat erstellen.", + "TitleNotifications": "Benachrichtigungen", + "ButtonDonateWithPayPal": "Spende mit PayPal", + "OptionDetectArchiveFilesAsMedia": "Behandle Archive wie Medien", + "OptionDetectArchiveFilesAsMediaHelp": "Wenn aktiviert werden .rar und .zip Datei-Erweiterungen wie Medien behandelt.", "LabelEnterConnectUserName": "Benutzername oder Email:", "LabelEnterConnectUserNameHelp": "Dies ist Ihr online Media Browser Benutzername oder Passwort.", "HeaderSyncJobInfo": "Synchronisations-Aufgabe", @@ -63,12 +83,14 @@ "FolderTypeTvShows": "TV", "FolderTypeInherit": "\u00dcbernehmen", "LabelContentType": "Inhalte-Typ:", + "TitleScheduledTasks": "Geplante Aufgaben", "HeaderSetupLibrary": "Medienbibliothek einrichten", "ButtonAddMediaFolder": "Medienverzeichnis hinzuf\u00fcgen", "LabelFolderType": "Verzeichnistyp:", "ReferToMediaLibraryWiki": "Siehe die Medienbibliothek Wiki", "LabelCountry": "Land:", "LabelLanguage": "Sprache:", + "ButtonJoinTheDevelopmentTeam": "Schlie\u00dfen Sie sich dem Entwickler-Team an", "HeaderPreferredMetadataLanguage": "Bevorzugte Metadata Sprache:", "LabelSaveLocalMetadata": "Speichere Bildmaterial und Metadaten in den Medienverzeichnissen", "LabelSaveLocalMetadataHelp": "Durch die Speicherung von Bildmaterial und Metadaten direkt in den Medienverzeichnissen, befinden sich diese an einem Ort wo sie sehr leicht bearbeitet werden k\u00f6nnen.", @@ -86,6 +108,8 @@ "TabCollectionTitles": "Titel", "HeaderDeviceAccess": "Ger\u00e4te Zugang", "OptionEnableAccessFromAllDevices": "Zugriff von allen Ger\u00e4ten erlauben", + "OptionEnableAccessToAllChannels": "Aktiviere Zugriff auf alle Kan\u00e4le", + "OptionEnableAccessToAllLibraries": "Erlaube Zugriff auf alle Bibliotheken", "DeviceAccessHelp": "Dies wird nur auf Ger\u00e4te angewandt die eindeutig identifiziert werden k\u00f6nnen und verhindert nicht den Web-Zugriff. Gefilterter Zugriff auf Ger\u00e4te verhindert die Nutzung neuer Ger\u00e4te solange, bis der Zugriff f\u00fcr diese freigegeben wird.", "LabelDisplayMissingEpisodesWithinSeasons": "Zeige fehlende Episoden innerhalb von Staffeln", "LabelUnairedMissingEpisodesWithinSeasons": "Zeige noch nicht ausgestahlte Episoden innerhalb von Staffeln", @@ -275,7 +299,7 @@ "OptionMetascore": "Metascore", "ButtonSelect": "Ausw\u00e4hlen", "ButtonGroupVersions": "Gruppiere Versionen", - "ButtonAddToCollection": "Zur Sammlung hinzuf\u00fcgen", + "ButtonAddToCollection": "Zu Sammlung hinzuf\u00fcgen", "PismoMessage": "Verwendet Pismo File Mount durch eine gespendete Lizenz.", "TangibleSoftwareMessage": "Verwendung konkreter L\u00f6sungen von Java\/C# Konvertern durch eine gespendete Lizenz.", "HeaderCredits": "Herausgeber", @@ -299,7 +323,7 @@ "LabelCachePath": "Cache Pfad:", "LabelCachePathHelp": "W\u00e4hle eine Verzeichnis f\u00fcr Server Cache Dateien, wie z.B. Bilddateien.", "LabelImagesByNamePath": "Images by name Pfad:", - "LabelImagesByNamePathHelp": "W\u00e4hle eine Verzeichnis f\u00fcr Schauspieler, Interpreten, Genre und Studio Bilder.", + "LabelImagesByNamePathHelp": "Spezifiziere eine individuelles Verzeichnis, f\u00fcr die heruntergeladenen Bilder der Darsteller, Genres und Studios.", "LabelMetadataPath": "Metadata Pfad:", "LabelMetadataPathHelp": "W\u00e4hle ein Verzeichnis f\u00fcr heruntergeladenes Bildmaterial und Metadaten, falls diese nicht innerhalb der Medienverzeichnisse gespeichert werden sollen.", "LabelTranscodingTempPath": "Tempor\u00e4rer Transcoding Pfad:", @@ -314,12 +338,14 @@ "OptionEpisodes": "Episoden", "OptionOtherVideos": "Andere Filme", "TitleMetadata": "Metadaten", - "LabelAutomaticUpdatesFanart": "Aktiviere automatische Updates von FanArt.tv", + "LabelAutomaticUpdates": "Aktiviere automatische Updates", "LabelAutomaticUpdatesTmdb": "Aktiviere automatische Updates von TheMovieDB.org", "LabelAutomaticUpdatesTvdb": "Aktiviere automatische Updates von TheTVDB.com", "LabelAutomaticUpdatesFanartHelp": "Falls aktviert, werden Bilder die unter fanart.tv neu hinzugef\u00fcgt wurden, automatisch geladen. Vorhandene Bilder werden nicht ersetzt.", "LabelAutomaticUpdatesTmdbHelp": "Falls aktviert, werden Bilder die unter TheMovieDB.org neu hinzugef\u00fcgt wurden, automatisch geladen. Vorhandene Bilder werden nicht ersetzt.", "LabelAutomaticUpdatesTvdbHelp": "Falls aktviert, werden Bilder die unter TheTVDB.com neu hinzugef\u00fcgt wurden, automatisch geladen. Vorhandene Bilder werden nicht ersetzt.", + "LabelFanartApiKey": "Pers\u00f6nlicher API Schl\u00fcssel:", + "LabelFanartApiKeyHelp": "Fanart Anfragen ohne einen pers\u00f6nlichen API Schl\u00fcssel liefert Ergebnisse der letzten 7 Tage. Bei Verwendung eines pers\u00f6nlichen API Schl\u00fcssels werden Ergebnisse der letzten 48 Stunden, und als VIP Member, der letzten 10 Minuten geliefert.", "ExtractChapterImagesHelp": "Das Auslesen von Kapitelbildern erlaubt es den Clients grafische Szenenauswahlmen\u00fcs anzuzeigen. Der Prozess kann langsam sowie prozessorintensiv sein und kann mehrere Gigabyte an Speicherplatz erfordern. Er wird nachts um 4:00 Uhr als geplante Aufgabe ausgef\u00fchrt, dies l\u00e4sst sich im \"Geplante Aufgaben\" Bereich konfigurieren. Es ist nicht ratsam, diese Aufgabe in der Hauptbelastungszeit auszuf\u00fchren.", "LabelMetadataDownloadLanguage": "Bevorzugte Sprache f\u00fcr Downloads:", "ButtonAutoScroll": "Auto-scroll", @@ -487,6 +513,7 @@ "HeaderSystemPaths": "Systempfade", "LinkCommunity": "Community", "LinkGithub": "Github", + "LinkApi": "API", "LinkApiDocumentation": "Api Dokumentation", "LabelFriendlyServerName": "Freundlicher Servername:", "LabelFriendlyServerNameHelp": "Dieser Name wird benutzt um diesen Server zu identifizieren. Wenn leer gelassen, wird der Computername benutzt.", @@ -494,20 +521,25 @@ "LabelPreferredDisplayLanguageHelp": "Die \u00dcbersetzung von Media Browser ist ein andauerndes Projekt und noch nicht abgeschlossen.", "LabelReadHowYouCanContribute": "Lese wie du dazu beitragen kannst.", "HeaderNewCollection": "Neue Collection", - "HeaderAddToCollection": "Zur Sammlung hinzuf\u00fcgen", "ButtonSubmit": "Best\u00e4tigen", - "NewCollectionNameExample": "Beispiel: Star Wars Collection", - "OptionSearchForInternetMetadata": "Suche im Internet nach Bildmaterial und Metadaten", "ButtonCreate": "Kreieren", - "LabelLocalHttpServerPortNumber": "Lokale Port-Nummer:", + "LabelCustomCss": "Benutzerdefinierte CSS:", + "LabelCustomCssHelp": "Wende deine eigene, benutzerdefinierte CSS f\u00fcr das Webinterface an.", + "LabelLocalHttpServerPortNumber": "Lokale HTTP Portnummer:", "LabelLocalHttpServerPortNumberHelp": "Die TCP-Port-Nummer, an die der http-Server von Media Browser gebunden werden soll.", - "LabelPublicPort": "\u00d6ffentliche Port-Nummer:", - "LabelPublicPortHelp": "Der \u00f6ffentliche Port-Nummer, die auf den lokalen Port zugeordnet werden soll.", + "LabelPublicHttpPort": "\u00d6ffentliche HTTP Portnummer:", + "LabelPublicHttpPortHelp": "Die \u00f6ffentliche Portnummer sollte einem lokalen HTTP Port zugewiesen werden.", + "LabelPublicHttpsPort": "\u00d6ffentliche HTTPS Portnummer:", + "LabelPublicHttpsPortHelp": "Die \u00f6ffentliche Portnummer sollte einem lokalen HTTPS Port zugewiesen werden.", + "LabelEnableHttps": "Gebe HTTPS als externe Adresse aus", + "LabelEnableHttpsHelp": "Falls aktiviert, gibt der Server eine HTTPS URL als seine externe Adresse an die Clients weiter. Dies kann Clients deaktivieren, die kein HTTPS unterst\u00fctzen.", + "LabelHttpsPort": "Lokale HTTPS Portnummer:", + "LabelHttpsPortHelp": "Die TCP Portnummer, an die der HTTPS Server von Media Browser gebunden werden soll.", "LabelWebSocketPortNumber": "Web Socket Port Nummer:", "LabelEnableAutomaticPortMap": "Aktiviere das automatische Port-Mapping", "LabelEnableAutomaticPortMapHelp": "Versuche automatisch den \u00f6ffentlichen Port dem lokalen Port mit Hilfe von UPnP zuzuordnen. Dies kann mit einigen Router-Modellen nicht funktionieren.", - "LabelExternalDDNS": "Externe DDNS:", - "LabelExternalDDNSHelp": "Wenn du eine dynamische DNS besitzen, trage Sie sie hier ein. Media Browser Apps werden sie verwenden, wenn sie sich verbinden.", + "LabelExternalDDNS": "Externe WAN Adresse:", + "LabelExternalDDNSHelp": "Falls du eine dynamische DNS nutzt, gib diese hier ein. Media Browser Apps werden diese nutzen, wenn von au\u00dfen auf sie zugegriffen wird. Lasse das Feld f\u00fcr eine automatische Erkennung frei.", "TabResume": "Fortsetzen", "TabWeather": "Wetter", "TitleAppSettings": "App Einstellungen", @@ -575,6 +607,7 @@ "ButtonRestart": "Neu starten", "ButtonShutdown": "Herunterfahren", "ButtonUpdateNow": "Jetzt aktualisieren", + "TabHosting": "Hosting", "PleaseUpdateManually": "Bitte herunterfahren und den Server manuell aktualisieren.", "NewServerVersionAvailable": "Eine neue Version des Media Browser Server ist verf\u00fcgbar!", "ServerUpToDate": "Media Browser Server ist aktuell", @@ -636,6 +669,7 @@ "NotificationOptionInstallationFailed": "Installationsfehler", "NotificationOptionNewLibraryContent": "Neuer Inhalt hinzugef\u00fcgt", "NotificationOptionNewLibraryContentMultiple": "Neuen Inhalte hinzugef\u00fcgt (mehrere)", + "NotificationOptionCameraImageUploaded": "Camera image uploaded", "SendNotificationHelp": "Standardm\u00e4\u00dfig werden Benachrichtigungen in der Optionsleiste angezeigt. Durchsuche den Plugin Katalog f\u00fcr die Installation von weiteren Benachrichtigungsm\u00f6glichkeiten.", "NotificationOptionServerRestartRequired": "Serverneustart notwendig", "LabelNotificationEnabled": "Aktiviere diese Benachrichtigung", @@ -829,8 +863,8 @@ "OptionAuto": "Auto", "OptionYes": "Ja", "OptionNo": "Nein", - "HeaderOptions": "Options", - "HeaderIdentificationResult": "Identification Result", + "HeaderOptions": "Optionen", + "HeaderIdentificationResult": "Identifikationsergebnis", "LabelHomePageSection1": "Startseite Bereich 1:", "LabelHomePageSection2": "Startseite Bereich 2:", "LabelHomePageSection3": "Startseite Bereich 3:", @@ -853,8 +887,10 @@ "OptionDefaultSort": "Default", "OptionCommunityMostWatchedSort": "Meistgesehen", "TabNextUp": "Als N\u00e4chstes", + "HeaderBecomeMediaBrowserSupporter": "Werden Sie ein Media Browser Unterst\u00fctzer", + "TextEnjoyBonusFeatures": "Enjoy Bonus Features", "MessageNoMovieSuggestionsAvailable": "Momentan sind keine Filmvorschl\u00e4ge verf\u00fcgbar. Schaue und bewerte zuerst deine Filme. Komme danach zur\u00fcck, um deine Filmvorschl\u00e4ge anzuschauen.", - "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.", + "MessageNoCollectionsAvailable": "Sammlungen erlauben Ihnen eine personalisierte Gruppierung von Filmen, Serien, Alben, B\u00fcchern und Spielen. Klicken Sie die + Schaltfl\u00e4che um Sammlungen zu erstellen.", "MessageNoPlaylistsAvailable": "Wiedergabeliste erlauben es dir eine Liste mit Inhalt zu erstellen der fortlaufend abgespielt wird. Um einer Wiedergabeliste Inhalte hinzuzuf\u00fcgen klicke rechts oder mache einen langen Tap und w\u00e4hle daraufhin \"Zur Wiedergabeliste hinzuf\u00fcgen\" aus.", "MessageNoPlaylistItemsAvailable": "Diese Wiedergabeliste ist momentan leer.", "ButtonDismiss": "Verwerfen", @@ -869,7 +905,6 @@ "LabelChannelDownloadAge": "L\u00f6sche Inhalt nach: (Tagen)", "LabelChannelDownloadAgeHelp": "Heruntergeladene Inhalte die \u00e4lter als dieser Wert sind werden gel\u00f6scht. Sie werden aber weiterhin \u00fcber das Internetstreaming verf\u00fcgbar sein.", "ChannelSettingsFormHelp": "Installiere Kan\u00e4le wie beispielsweise \"Trailers\" oder \"Vimeo\" aus dem Plugin Katalog.", - "LabelSelectCollection": "W\u00e4hle Zusammenstellung:", "ButtonOptions": "Optionen", "ViewTypeMovies": "Filme", "ViewTypeTvShows": "TV", @@ -917,7 +952,7 @@ "OptionLatestTvRecordings": "Neueste Aufnahmen", "LabelProtocolInfo": "Protokoll Information:", "LabelProtocolInfoHelp": "Der Wert, der f\u00fcr die Beantwortung von GetProtocolInfo Anfragen durch die Endger\u00e4te benutzt wird.", - "TabKodiMetadata": "Kodi", + "TabNfo": "Nfo", "HeaderKodiMetadataHelp": "Media Browser bietet eine native Unterst\u00fctzung f\u00fcr Kodi NFO Metadaten und Bilder. Um Kodi Metadaten zu aktivieren oder zu deaktivieren und um Optionen f\u00fcr deine Medientypen zu konfigurieren, verwende die Registerkarte Erweitert.", "LabelKodiMetadataUser": "Synchronisiere den \"Gesehen\" Status von Benutzern in NFO's f\u00fcr:", "LabelKodiMetadataUserHelp": "Aktiviere diese Option, um den \"Gesehen\" Status zwischen Media Browser und Kodi synchron zu halten.", @@ -931,6 +966,7 @@ "LabelGroupChannelsIntoViews": "Zeige die folgenden Kan\u00e4le direkt innerhalb meiner Ansichten:", "LabelGroupChannelsIntoViewsHelp": "Falls aktiviert, werden diese Kan\u00e4le direkt neben den anderen Ansichten angezeigt. Falls deaktiviert, werden sie innerhalb einer separaten Kanalansicht angezeigt.", "LabelDisplayCollectionsView": "Zeigt eine Ansicht f\u00fcr Sammlungen, um Filmsammlungen darzustellen", + "LabelDisplayCollectionsViewHelp": "Die erstellt eine eigene Ansicht f\u00fcr Sammlungen, auf denen Sie Zugriff haben. Um eine Sammlung zu erstellen benutzen Sie einen Rechtsklick oder halten Sie einen Film gedr\u00fcckt und w\u00e4hlen Sie 'Zu Sammlung hinzuf\u00fcgen'.", "LabelKodiMetadataEnableExtraThumbs": "Kopiere Extrafanart in Extrathumbs", "LabelKodiMetadataEnableExtraThumbsHelp": "Beim downloaden von Bildern k\u00f6nnen diese sowohl als Extrafanart als auch als Extrathumb gespeichert werden, um maximale Kodi Kompatibilit\u00e4t zu erzielen.", "TabServices": "Dienste", @@ -1084,11 +1120,14 @@ "LabelDisplayFoldersView": "Nutze die Verzeichnissansicht f\u00fcr die Darstellung der reinen Medienordner", "ViewTypeLiveTvRecordingGroups": "Aufnahmen", "ViewTypeLiveTvChannels": "Kan\u00e4le", - "LabelAllowLocalAccessWithoutPassword": "Erlaube lokalen Zugriff ohne Passwort", - "LabelAllowLocalAccessWithoutPasswordHelp": "Fall aktiviert, wird kein Passwort f\u00fcr einen Zugriff innerhalb deines Heimnetzwerks ben\u00f6tigt.", + "LabelEasyPinCode": "Easy pin code:", + "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Media Browser apps, and can also be used for easy in-network sign in.", + "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", + "LabelInNetworkSignInWithEasyPasswordHelp": "If enabled, you'll be able to use your easy pin code to sign in to Media Browser apps from inside your home network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", "HeaderPassword": "Passwort", "HeaderLocalAccess": "Lokaler Zugriff", "HeaderViewOrder": "Reihenfolge f\u00fcr Ansichten", + "ButtonResetEasyPassword": "Reset easy pin code", "LabelSelectUserViewOrder": "W\u00e4hle die Reihenfolge in der die Ansichten innerhalb von Media Browser Apps angezeigt werden.", "LabelMetadataRefreshMode": "Metadaten Aktualisierungsmethode:", "LabelImageRefreshMode": "Aktualisierungsmethode f\u00fcr Bilder:", @@ -1162,7 +1201,7 @@ "OptionNoThemeSong": "Kein Theme Song", "OptionNoThemeVideo": "Kein Theme Video", "LabelOneTimeDonationAmount": "Spendenbetrag:", - "ButtonDonate": "Donate", + "ButtonDonate": "Spenden", "OptionActor": "Schauspieler", "OptionComposer": "Komponist", "OptionDirector": "Regisseur", @@ -1279,7 +1318,7 @@ "MessageNoTrailersFound": "Keine Trailer gefunden. Installieren Sie den Trailer-Channel um Ihre Film-Bibliothek mit Trailer aus dem Internet zu erweitern.", "HeaderNewUsers": "Neue Benutzer", "ButtonSignUp": "Anmeldung", - "ButtonForgotPassword": "Passwort vergessen?", + "ButtonForgotPassword": "Passwort vergessen", "OptionDisableUserPreferences": "Deaktiviere den Zugriff auf Benutzereinstellungen", "OptionDisableUserPreferencesHelp": "Falls aktiviert, werden nur Administratoren die M\u00f6glichkeit haben, Benutzerbilder, Passw\u00f6rter und Spracheinstellungen zu bearbeiten.", "HeaderSelectServer": "W\u00e4hle Server", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/el.json b/MediaBrowser.Server.Implementations/Localization/Server/el.json index cf43b65b2..1d15d4bbf 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/el.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/el.json @@ -40,12 +40,32 @@ "OptionIAcceptTermsOfService": "I accept the terms of service", "ButtonPrivacyPolicy": "Privacy policy", "ButtonTermsOfService": "Terms of Service", + "HeaderDeveloperOptions": "Developer Options", + "OptionEnableWebClientResponseCache": "Enable web client response caching", + "OptionDisableForDevelopmentHelp": "Configure these as needed for web client development purposes.", + "OptionEnableWebClientResourceMinification": "Enable web client resource minification", + "LabelDashboardSourcePath": "Web client source path:", + "LabelDashboardSourcePathHelp": "If running the server from source, specify the path to the dashboard-ui folder. All web client files will be served from this location.", + "ButtonConvertMedia": "Convert media", + "ButtonOrganize": "Organize", "ButtonOk": "\u03b5\u03bd\u03c4\u03ac\u03be\u03b5\u03b9", "ButtonCancel": "\u0391\u03ba\u03cd\u03c1\u03c9\u03c3\u03b7 ", "ButtonNew": "New", "HeaderTV": "TV", "HeaderAudio": "Audio", "HeaderVideo": "Video", + "HeaderPaths": "Paths", + "CategorySync": "Sync", + "HeaderEasyPinCode": "Easy Pin Code", + "RegisterWithPayPal": "Register with PayPal", + "HeaderSyncRequiresSupporterMembership": "Sync Requires a Supporter Membership", + "HeaderEnjoyDayTrial": "Enjoy a 14 Day Free Trial", + "LabelSyncTempPath": "Temporary file path:", + "LabelSyncTempPathHelp": "Specify a custom sync working folder. Converted media created during the sync process will be stored here.", + "LabelCustomCertificatePath": "Custom certificate path:", + "LabelCustomCertificatePathHelp": "Supply your own ssl certificate. If omitted, the server will create a self-signed certificate.", + "TitleNotifications": "Notifications", + "ButtonDonateWithPayPal": "Donate with PayPal", "OptionDetectArchiveFilesAsMedia": "Detect archive files as media", "OptionDetectArchiveFilesAsMediaHelp": "If enabled, files with .rar and .zip extensions will be detected as media files.", "LabelEnterConnectUserName": "User name or email:", @@ -63,12 +83,14 @@ "FolderTypeTvShows": "TV", "FolderTypeInherit": "Inherit", "LabelContentType": "Content type:", + "TitleScheduledTasks": "Scheduled Tasks", "HeaderSetupLibrary": "Setup your media library", "ButtonAddMediaFolder": "\u03a0\u03c1\u03bf\u03c3\u03b8\u03ad\u03c3\u03c4\u03b5 \u03c4\u03bf \u03c6\u03ac\u03ba\u03b5\u03bb\u03bf \u03c4\u03bf\u03c5 Media", "LabelFolderType": "\u03a4\u03cd\u03c0\u03bf \u03c6\u03b1\u03ba\u03ad\u03bb\u03bf\u03c5 ", "ReferToMediaLibraryWiki": "\u0391\u03bd\u03b1\u03c4\u03c1\u03b5\u03be\u03c4\u03b5 \u03c3\u03c4\u03bf media \u03b2\u03b9\u03b2\u03bb\u03b9\u03bf\u03b8\u03ae\u03ba\u03b7 wiki", "LabelCountry": "T\u03b7 \u03c7\u03ce\u03c1\u03b1", "LabelLanguage": "\u03a4\u03b7 \u03b3\u03bb\u03ce\u03c3\u03c3\u03b1", + "ButtonJoinTheDevelopmentTeam": "Join the Development Team", "HeaderPreferredMetadataLanguage": "\u03a0\u03c1\u03bf\u03c4\u03b9\u03bc\u03ce\u03bc\u03b5\u03bd\u03b7 \u03b3\u03bb\u03ce\u03c3\u03c3\u03b1 \u03bc\u03b5\u03c4\u03b1", "LabelSaveLocalMetadata": "\u0391\u03c0\u03bf\u03b8\u03b7\u03ba\u03b5\u03cd\u03c3\u03b5\u03c4\u03b5 \u03c4\u03bf \u03ad\u03c1\u03b3\u03bf \u03c4\u03ad\u03c7\u03bd\u03b7\u03c2 \u03ba\u03b1\u03b9 \u03c4\u03b1 \u03bc\u03b5\u03c4\u03b1\u03b4\u03b5\u03b4\u03bf\u03bc\u03ad\u03bd\u03b1 \u03c3\u03b5 \u03c6\u03b1\u03ba\u03ad\u03bb\u03bf\u03c5\u03c2 \u03c0\u03bf\u03bb\u03c5\u03bc\u03ad\u03c3\u03c9\u03bd", "LabelSaveLocalMetadataHelp": "\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7 artwork \u03ba\u03b1\u03b9 \u03bc\u03b5\u03c4\u03b1-\u03b4\u03b5\u03b4\u03bf\u03bc\u03ad\u03bd\u03b1 \u03b1\u03c0\u03b5\u03c5\u03b8\u03b5\u03af\u03b1\u03c2 \u03c3\u03b5 \u03c6\u03b1\u03ba\u03ad\u03bb\u03bf\u03c5\u03c2 \u03bc\u03ad\u03c3\u03c9\u03bd \u03b8\u03b1 \u03c4\u03bf\u03c5\u03c2 \u03b8\u03ad\u03c3\u03b5\u03b9 \u03c3\u03b5 \u03ad\u03bd\u03b1 \u03c4\u03cc\u03c0\u03bf \u03cc\u03c0\u03bf\u03c5 \u03bc\u03c0\u03bf\u03c1\u03bf\u03cd\u03bd \u03b5\u03cd\u03ba\u03bf\u03bb\u03b1 \u03bd\u03b1 \u03b5\u03c0\u03b5\u03be\u03b5\u03c1\u03b3\u03b1\u03c3\u03c4\u03b5\u03af\u03c4\u03b5.", @@ -86,6 +108,8 @@ "TabCollectionTitles": "Titles", "HeaderDeviceAccess": "Device Access", "OptionEnableAccessFromAllDevices": "Enable access from all devices", + "OptionEnableAccessToAllChannels": "Enable access to all channels", + "OptionEnableAccessToAllLibraries": "Enable access to all libraries", "DeviceAccessHelp": "This only applies to devices that can be uniquely identified and will not prevent browser access. Filtering user device access will prevent them from using new devices until they've been approved here.", "LabelDisplayMissingEpisodesWithinSeasons": "\u03b4\u03b5\u03af\u03c7\u03bd\u03bf\u03c5\u03bd \u03bb\u03b5\u03af\u03c0\u03b5\u03b9 \u03b5\u03c0\u03b5\u03b9\u03c3\u03cc\u03b4\u03b9\u03b1 \u03b5\u03bd\u03c4\u03cc\u03c2 \u03b5\u03c0\u03bf\u03c7\u03ad\u03c2", "LabelUnairedMissingEpisodesWithinSeasons": "\u03b4\u03b5\u03af\u03c7\u03bd\u03bf\u03c5\u03bd unaired \u03b5\u03c0\u03b5\u03b9\u03c3\u03cc\u03b4\u03b9\u03b1 \u03b5\u03bd\u03c4\u03cc\u03c2 \u03b5\u03c0\u03bf\u03c7\u03ad\u03c2", @@ -299,7 +323,7 @@ "LabelCachePath": "Cache path:", "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.", "LabelImagesByNamePath": "Images by name path:", - "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, genre and studio images.", "LabelMetadataPath": "Metadata path:", "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.", "LabelTranscodingTempPath": "Transcoding temporary path:", @@ -314,12 +338,14 @@ "OptionEpisodes": "Episodes", "OptionOtherVideos": "Other Videos", "TitleMetadata": "Metadata", - "LabelAutomaticUpdatesFanart": "Enable automatic updates from FanArt.tv", + "LabelAutomaticUpdates": "Enable automatic updates", "LabelAutomaticUpdatesTmdb": "Enable automatic updates from TheMovieDB.org", "LabelAutomaticUpdatesTvdb": "Enable automatic updates from TheTVDB.com", "LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.", "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.", "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.", + "LabelFanartApiKey": "Personal api key:", + "LabelFanartApiKeyHelp": "Requests to fanart without a personal API key return results that were approved over 7 days ago. With a personal API key that drops to 48 hours and if you are also a fanart VIP member that will further drop to around 10 minutes.", "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", "LabelMetadataDownloadLanguage": "Preferred download language:", "ButtonAutoScroll": "Auto-scroll", @@ -487,6 +513,7 @@ "HeaderSystemPaths": "System Paths", "LinkCommunity": "Community", "LinkGithub": "Github", + "LinkApi": "Api", "LinkApiDocumentation": "Api Documentation", "LabelFriendlyServerName": "Friendly server name:", "LabelFriendlyServerNameHelp": "This name will be used to identify this server. If left blank, the computer name will be used.", @@ -494,20 +521,25 @@ "LabelPreferredDisplayLanguageHelp": "Translating Media Browser is an ongoing project and is not yet complete.", "LabelReadHowYouCanContribute": "Read about how you can contribute.", "HeaderNewCollection": "New Collection", - "HeaderAddToCollection": "Add to Collection", "ButtonSubmit": "Submit", - "NewCollectionNameExample": "Example: Star Wars Collection", - "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata", "ButtonCreate": "Create", - "LabelLocalHttpServerPortNumber": "Local port number:", + "LabelCustomCss": "Custom css:", + "LabelCustomCssHelp": "Apply your own custom css to the web interface.", + "LabelLocalHttpServerPortNumber": "Local http port number:", "LabelLocalHttpServerPortNumberHelp": "The tcp port number that Media Browser's http server should bind to.", - "LabelPublicPort": "Public port number:", - "LabelPublicPortHelp": "The public port number that should be mapped to the local port.", + "LabelPublicHttpPort": "Public http port number:", + "LabelPublicHttpPortHelp": "The public port number that should be mapped to the local http port.", + "LabelPublicHttpsPort": "Public https port number:", + "LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.", + "LabelEnableHttps": "Report https as external address", + "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.", + "LabelHttpsPort": "Local https port number:", + "LabelHttpsPortHelp": "The tcp port number that Media Browser's https server should bind to.", "LabelWebSocketPortNumber": "Web socket port number:", "LabelEnableAutomaticPortMap": "Enable automatic port mapping", "LabelEnableAutomaticPortMapHelp": "Attempt to automatically map the public port to the local port via UPnP. This may not work with some router models.", - "LabelExternalDDNS": "External DDNS:", - "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely.", + "LabelExternalDDNS": "External WAN Address:", + "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely. Leave empty for automatic detection.", "TabResume": "Resume", "TabWeather": "Weather", "TitleAppSettings": "App Settings", @@ -575,6 +607,7 @@ "ButtonRestart": "Restart", "ButtonShutdown": "Shutdown", "ButtonUpdateNow": "Update Now", + "TabHosting": "Hosting", "PleaseUpdateManually": "Please shutdown the server and update manually.", "NewServerVersionAvailable": "A new version of Media Browser Server is available!", "ServerUpToDate": "Media Browser Server is up to date", @@ -636,6 +669,7 @@ "NotificationOptionInstallationFailed": "Installation failure", "NotificationOptionNewLibraryContent": "New content added", "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", + "NotificationOptionCameraImageUploaded": "Camera image uploaded", "SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.", "NotificationOptionServerRestartRequired": "Server restart required", "LabelNotificationEnabled": "Enable this notification", @@ -853,6 +887,8 @@ "OptionDefaultSort": "Default", "OptionCommunityMostWatchedSort": "Most Watched", "TabNextUp": "Next Up", + "HeaderBecomeMediaBrowserSupporter": "Become a Media Browser Supporter", + "TextEnjoyBonusFeatures": "Enjoy Bonus Features", "MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.", "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.", "MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.", @@ -869,7 +905,6 @@ "LabelChannelDownloadAge": "Delete content after: (days)", "LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.", "ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.", - "LabelSelectCollection": "Select collection:", "ButtonOptions": "Options", "ViewTypeMovies": "Movies", "ViewTypeTvShows": "TV", @@ -917,7 +952,7 @@ "OptionLatestTvRecordings": "Latest recordings", "LabelProtocolInfo": "Protocol info:", "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.", - "TabKodiMetadata": "Kodi", + "TabNfo": "Nfo", "HeaderKodiMetadataHelp": "Media Browser includes native support for Kodi Nfo metadata and images. To enable or disable Kodi metadata, use the Advanced tab to configure options for your media types.", "LabelKodiMetadataUser": "Sync user watch data to nfo's for:", "LabelKodiMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Kodi.", @@ -931,6 +966,7 @@ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:", "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.", "LabelDisplayCollectionsView": "Display a collections view to show movie collections", + "LabelDisplayCollectionsViewHelp": "This will create a separate view to display collections that you've created or have access to. To create a collection, right-click or tap-hold any movie and select 'Add to Collection'. ", "LabelKodiMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs", "LabelKodiMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Kodi skin compatibility.", "TabServices": "Services", @@ -1084,11 +1120,14 @@ "LabelDisplayFoldersView": "Display a folders view to show plain media folders", "ViewTypeLiveTvRecordingGroups": "Recordings", "ViewTypeLiveTvChannels": "Channels", - "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password", - "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.", + "LabelEasyPinCode": "Easy pin code:", + "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Media Browser apps, and can also be used for easy in-network sign in.", + "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", + "LabelInNetworkSignInWithEasyPasswordHelp": "If enabled, you'll be able to use your easy pin code to sign in to Media Browser apps from inside your home network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", "HeaderPassword": "Password", "HeaderLocalAccess": "Local Access", "HeaderViewOrder": "View Order", + "ButtonResetEasyPassword": "Reset easy pin code", "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps", "LabelMetadataRefreshMode": "Metadata refresh mode:", "LabelImageRefreshMode": "Image refresh mode:", @@ -1279,7 +1318,7 @@ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.", "HeaderNewUsers": "New Users", "ButtonSignUp": "Sign up", - "ButtonForgotPassword": "Forgot password?", + "ButtonForgotPassword": "Forgot password", "OptionDisableUserPreferences": "Disable access to user preferences", "OptionDisableUserPreferencesHelp": "If enabled, only administrators will be able to configure user profile images, passwords, and language preferences.", "HeaderSelectServer": "Select Server", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/en_GB.json b/MediaBrowser.Server.Implementations/Localization/Server/en_GB.json index b9fc03eb9..6c1cb185a 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/en_GB.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/en_GB.json @@ -40,12 +40,32 @@ "OptionIAcceptTermsOfService": "I accept the terms of service", "ButtonPrivacyPolicy": "Privacy policy", "ButtonTermsOfService": "Terms of Service", + "HeaderDeveloperOptions": "Developer Options", + "OptionEnableWebClientResponseCache": "Enable web client response caching", + "OptionDisableForDevelopmentHelp": "Configure these as needed for web client development purposes.", + "OptionEnableWebClientResourceMinification": "Enable web client resource minification", + "LabelDashboardSourcePath": "Web client source path:", + "LabelDashboardSourcePathHelp": "If running the server from source, specify the path to the dashboard-ui folder. All web client files will be served from this location.", + "ButtonConvertMedia": "Convert media", + "ButtonOrganize": "Organize", "ButtonOk": "Ok", "ButtonCancel": "Cancel", "ButtonNew": "New", "HeaderTV": "TV", "HeaderAudio": "Audio", "HeaderVideo": "Video", + "HeaderPaths": "Paths", + "CategorySync": "Sync", + "HeaderEasyPinCode": "Easy Pin Code", + "RegisterWithPayPal": "Register with PayPal", + "HeaderSyncRequiresSupporterMembership": "Sync Requires a Supporter Membership", + "HeaderEnjoyDayTrial": "Enjoy a 14 Day Free Trial", + "LabelSyncTempPath": "Temporary file path:", + "LabelSyncTempPathHelp": "Specify a custom sync working folder. Converted media created during the sync process will be stored here.", + "LabelCustomCertificatePath": "Custom certificate path:", + "LabelCustomCertificatePathHelp": "Supply your own ssl certificate. If omitted, the server will create a self-signed certificate.", + "TitleNotifications": "Notifications", + "ButtonDonateWithPayPal": "Donate with PayPal", "OptionDetectArchiveFilesAsMedia": "Detect archive files as media", "OptionDetectArchiveFilesAsMediaHelp": "If enabled, files with .rar and .zip extensions will be detected as media files.", "LabelEnterConnectUserName": "User name or email:", @@ -63,12 +83,14 @@ "FolderTypeTvShows": "TV", "FolderTypeInherit": "Inherit", "LabelContentType": "Content type:", + "TitleScheduledTasks": "Scheduled Tasks", "HeaderSetupLibrary": "Setup your media library", "ButtonAddMediaFolder": "Add media folder", "LabelFolderType": "Folder type:", "ReferToMediaLibraryWiki": "Refer to the media library wiki.", "LabelCountry": "Country:", "LabelLanguage": "Language:", + "ButtonJoinTheDevelopmentTeam": "Join the Development Team", "HeaderPreferredMetadataLanguage": "Preferred metadata language:", "LabelSaveLocalMetadata": "Save artwork and metadata into media folders", "LabelSaveLocalMetadataHelp": "Saving artwork and metadata directly into media folders will put them in a place where they can be easily edited.", @@ -86,6 +108,8 @@ "TabCollectionTitles": "Titles", "HeaderDeviceAccess": "Device Access", "OptionEnableAccessFromAllDevices": "Enable access from all devices", + "OptionEnableAccessToAllChannels": "Enable access to all channels", + "OptionEnableAccessToAllLibraries": "Enable access to all libraries", "DeviceAccessHelp": "This only applies to devices that can be uniquely identified and will not prevent browser access. Filtering user device access will prevent them from using new devices until they've been approved here.", "LabelDisplayMissingEpisodesWithinSeasons": "Display missing episodes within seasons", "LabelUnairedMissingEpisodesWithinSeasons": "Display unaired episodes within seasons", @@ -299,7 +323,7 @@ "LabelCachePath": "Cache path:", "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.", "LabelImagesByNamePath": "Images by name path:", - "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, genre and studio images.", "LabelMetadataPath": "Metadata path:", "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.", "LabelTranscodingTempPath": "Transcoding temporary path:", @@ -314,12 +338,14 @@ "OptionEpisodes": "Episodes", "OptionOtherVideos": "Other Videos", "TitleMetadata": "Metadata", - "LabelAutomaticUpdatesFanart": "Enable automatic updates from FanArt.tv", + "LabelAutomaticUpdates": "Enable automatic updates", "LabelAutomaticUpdatesTmdb": "Enable automatic updates from TheMovieDB.org", "LabelAutomaticUpdatesTvdb": "Enable automatic updates from TheTVDB.com", "LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.", "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.", "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.", + "LabelFanartApiKey": "Personal api key:", + "LabelFanartApiKeyHelp": "Requests to fanart without a personal API key return results that were approved over 7 days ago. With a personal API key that drops to 48 hours and if you are also a fanart VIP member that will further drop to around 10 minutes.", "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", "LabelMetadataDownloadLanguage": "Preferred download language:", "ButtonAutoScroll": "Auto-scroll", @@ -487,6 +513,7 @@ "HeaderSystemPaths": "System Paths", "LinkCommunity": "Community", "LinkGithub": "Github", + "LinkApi": "Api", "LinkApiDocumentation": "Api Documentation", "LabelFriendlyServerName": "Friendly server name:", "LabelFriendlyServerNameHelp": "This name will be used to identify this server. If left blank, the computer name will be used.", @@ -494,20 +521,25 @@ "LabelPreferredDisplayLanguageHelp": "Translating Media Browser is an ongoing project and is not yet complete.", "LabelReadHowYouCanContribute": "Read about how you can contribute.", "HeaderNewCollection": "New Collection", - "HeaderAddToCollection": "Add to Collection", "ButtonSubmit": "Submit", - "NewCollectionNameExample": "Example: Star Wars Collection", - "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata", "ButtonCreate": "Create", - "LabelLocalHttpServerPortNumber": "Local port number:", + "LabelCustomCss": "Custom css:", + "LabelCustomCssHelp": "Apply your own custom css to the web interface.", + "LabelLocalHttpServerPortNumber": "Local http port number:", "LabelLocalHttpServerPortNumberHelp": "The tcp port number that Media Browser's http server should bind to.", - "LabelPublicPort": "Public port number:", - "LabelPublicPortHelp": "The public port number that should be mapped to the local port.", + "LabelPublicHttpPort": "Public http port number:", + "LabelPublicHttpPortHelp": "The public port number that should be mapped to the local http port.", + "LabelPublicHttpsPort": "Public https port number:", + "LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.", + "LabelEnableHttps": "Report https as external address", + "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.", + "LabelHttpsPort": "Local https port number:", + "LabelHttpsPortHelp": "The tcp port number that Media Browser's https server should bind to.", "LabelWebSocketPortNumber": "Web socket port number:", "LabelEnableAutomaticPortMap": "Enable automatic port mapping", "LabelEnableAutomaticPortMapHelp": "Attempt to automatically map the public port to the local port via UPnP. This may not work with some router models.", - "LabelExternalDDNS": "External DDNS:", - "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely.", + "LabelExternalDDNS": "External WAN Address:", + "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely. Leave empty for automatic detection.", "TabResume": "Resume", "TabWeather": "Weather", "TitleAppSettings": "App Settings", @@ -575,6 +607,7 @@ "ButtonRestart": "Restart", "ButtonShutdown": "Shutdown", "ButtonUpdateNow": "Update Now", + "TabHosting": "Hosting", "PleaseUpdateManually": "Please shutdown the server and update manually.", "NewServerVersionAvailable": "A new version of Media Browser Server is available!", "ServerUpToDate": "Media Browser Server is up to date", @@ -636,6 +669,7 @@ "NotificationOptionInstallationFailed": "Installation failure", "NotificationOptionNewLibraryContent": "New content added", "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", + "NotificationOptionCameraImageUploaded": "Camera image uploaded", "SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.", "NotificationOptionServerRestartRequired": "Server restart required", "LabelNotificationEnabled": "Enable this notification", @@ -853,6 +887,8 @@ "OptionDefaultSort": "Default", "OptionCommunityMostWatchedSort": "Most Watched", "TabNextUp": "Next Up", + "HeaderBecomeMediaBrowserSupporter": "Become a Media Browser Supporter", + "TextEnjoyBonusFeatures": "Enjoy Bonus Features", "MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.", "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.", "MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.", @@ -869,7 +905,6 @@ "LabelChannelDownloadAge": "Delete content after: (days)", "LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.", "ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.", - "LabelSelectCollection": "Select collection:", "ButtonOptions": "Options", "ViewTypeMovies": "Movies", "ViewTypeTvShows": "TV", @@ -917,7 +952,7 @@ "OptionLatestTvRecordings": "Latest recordings", "LabelProtocolInfo": "Protocol info:", "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.", - "TabKodiMetadata": "Kodi", + "TabNfo": "Nfo", "HeaderKodiMetadataHelp": "Media Browser includes native support for Kodi Nfo metadata and images. To enable or disable Kodi metadata, use the Advanced tab to configure options for your media types.", "LabelKodiMetadataUser": "Sync user watch data to nfo's for:", "LabelKodiMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Kodi.", @@ -931,6 +966,7 @@ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:", "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.", "LabelDisplayCollectionsView": "Display a collections view to show movie collections", + "LabelDisplayCollectionsViewHelp": "This will create a separate view to display collections that you've created or have access to. To create a collection, right-click or tap-hold any movie and select 'Add to Collection'. ", "LabelKodiMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs", "LabelKodiMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Kodi skin compatibility.", "TabServices": "Services", @@ -1084,11 +1120,14 @@ "LabelDisplayFoldersView": "Display a folders view to show plain media folders", "ViewTypeLiveTvRecordingGroups": "Recordings", "ViewTypeLiveTvChannels": "Channels", - "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password", - "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.", + "LabelEasyPinCode": "Easy pin code:", + "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Media Browser apps, and can also be used for easy in-network sign in.", + "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", + "LabelInNetworkSignInWithEasyPasswordHelp": "If enabled, you'll be able to use your easy pin code to sign in to Media Browser apps from inside your home network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", "HeaderPassword": "Password", "HeaderLocalAccess": "Local Access", "HeaderViewOrder": "View Order", + "ButtonResetEasyPassword": "Reset easy pin code", "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps", "LabelMetadataRefreshMode": "Metadata refresh mode:", "LabelImageRefreshMode": "Image refresh mode:", @@ -1279,7 +1318,7 @@ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.", "HeaderNewUsers": "New Users", "ButtonSignUp": "Sign up", - "ButtonForgotPassword": "Forgot password?", + "ButtonForgotPassword": "Forgot password", "OptionDisableUserPreferences": "Disable access to user preferences", "OptionDisableUserPreferencesHelp": "If enabled, only administrators will be able to configure user profile images, passwords, and language preferences.", "HeaderSelectServer": "Select Server", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/en_US.json b/MediaBrowser.Server.Implementations/Localization/Server/en_US.json index d0dd88f16..5dd939774 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/en_US.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/en_US.json @@ -40,12 +40,32 @@ "OptionIAcceptTermsOfService": "I accept the terms of service", "ButtonPrivacyPolicy": "Privacy policy", "ButtonTermsOfService": "Terms of Service", + "HeaderDeveloperOptions": "Developer Options", + "OptionEnableWebClientResponseCache": "Enable web client response caching", + "OptionDisableForDevelopmentHelp": "Configure these as needed for web client development purposes.", + "OptionEnableWebClientResourceMinification": "Enable web client resource minification", + "LabelDashboardSourcePath": "Web client source path:", + "LabelDashboardSourcePathHelp": "If running the server from source, specify the path to the dashboard-ui folder. All web client files will be served from this location.", + "ButtonConvertMedia": "Convert media", + "ButtonOrganize": "Organize", "ButtonOk": "Ok", "ButtonCancel": "Cancel", "ButtonNew": "New", "HeaderTV": "TV", "HeaderAudio": "Audio", "HeaderVideo": "Video", + "HeaderPaths": "Paths", + "CategorySync": "Sync", + "HeaderEasyPinCode": "Easy Pin Code", + "RegisterWithPayPal": "Register with PayPal", + "HeaderSyncRequiresSupporterMembership": "Sync Requires a Supporter Membership", + "HeaderEnjoyDayTrial": "Enjoy a 14 Day Free Trial", + "LabelSyncTempPath": "Temporary file path:", + "LabelSyncTempPathHelp": "Specify a custom sync working folder. Converted media created during the sync process will be stored here.", + "LabelCustomCertificatePath": "Custom certificate path:", + "LabelCustomCertificatePathHelp": "Supply your own ssl certificate. If omitted, the server will create a self-signed certificate.", + "TitleNotifications": "Notifications", + "ButtonDonateWithPayPal": "Donate with PayPal", "OptionDetectArchiveFilesAsMedia": "Detect archive files as media", "OptionDetectArchiveFilesAsMediaHelp": "If enabled, files with .rar and .zip extensions will be detected as media files.", "LabelEnterConnectUserName": "User name or email:", @@ -63,12 +83,14 @@ "FolderTypeTvShows": "TV", "FolderTypeInherit": "Inherit", "LabelContentType": "Content type:", + "TitleScheduledTasks": "Scheduled Tasks", "HeaderSetupLibrary": "Setup your media library", "ButtonAddMediaFolder": "Add media folder", "LabelFolderType": "Folder type:", "ReferToMediaLibraryWiki": "Refer to the media library wiki.", "LabelCountry": "Country:", "LabelLanguage": "Language:", + "ButtonJoinTheDevelopmentTeam": "Join the Development Team", "HeaderPreferredMetadataLanguage": "Preferred metadata language:", "LabelSaveLocalMetadata": "Save artwork and metadata into media folders", "LabelSaveLocalMetadataHelp": "Saving artwork and metadata directly into media folders will put them in a place where they can be easily edited.", @@ -86,6 +108,8 @@ "TabCollectionTitles": "Titles", "HeaderDeviceAccess": "Device Access", "OptionEnableAccessFromAllDevices": "Enable access from all devices", + "OptionEnableAccessToAllChannels": "Enable access to all channels", + "OptionEnableAccessToAllLibraries": "Enable access to all libraries", "DeviceAccessHelp": "This only applies to devices that can be uniquely identified and will not prevent browser access. Filtering user device access will prevent them from using new devices until they've been approved here.", "LabelDisplayMissingEpisodesWithinSeasons": "Display missing episodes within seasons", "LabelUnairedMissingEpisodesWithinSeasons": "Display unaired episodes within seasons", @@ -299,7 +323,7 @@ "LabelCachePath": "Cache path:", "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.", "LabelImagesByNamePath": "Images by name path:", - "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, genre and studio images.", "LabelMetadataPath": "Metadata path:", "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.", "LabelTranscodingTempPath": "Transcoding temporary path:", @@ -314,12 +338,14 @@ "OptionEpisodes": "Episodes", "OptionOtherVideos": "Other Videos", "TitleMetadata": "Metadata", - "LabelAutomaticUpdatesFanart": "Enable automatic updates from FanArt.tv", + "LabelAutomaticUpdates": "Enable automatic updates", "LabelAutomaticUpdatesTmdb": "Enable automatic updates from TheMovieDB.org", "LabelAutomaticUpdatesTvdb": "Enable automatic updates from TheTVDB.com", "LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.", "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.", "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.", + "LabelFanartApiKey": "Personal api key:", + "LabelFanartApiKeyHelp": "Requests to fanart without a personal API key return results that were approved over 7 days ago. With a personal API key that drops to 48 hours and if you are also a fanart VIP member that will further drop to around 10 minutes.", "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", "LabelMetadataDownloadLanguage": "Preferred download language:", "ButtonAutoScroll": "Auto-scroll", @@ -487,6 +513,7 @@ "HeaderSystemPaths": "System Paths", "LinkCommunity": "Community", "LinkGithub": "Github", + "LinkApi": "Api", "LinkApiDocumentation": "Api Documentation", "LabelFriendlyServerName": "Friendly server name:", "LabelFriendlyServerNameHelp": "This name will be used to identify this server. If left blank, the computer name will be used.", @@ -494,20 +521,25 @@ "LabelPreferredDisplayLanguageHelp": "Translating Media Browser is an ongoing project and is not yet complete.", "LabelReadHowYouCanContribute": "Read about how you can contribute.", "HeaderNewCollection": "New Collection", - "HeaderAddToCollection": "Add to Collection", "ButtonSubmit": "Submit", - "NewCollectionNameExample": "Example: Star Wars Collection", - "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata", "ButtonCreate": "Create", - "LabelLocalHttpServerPortNumber": "Local port number:", + "LabelCustomCss": "Custom css:", + "LabelCustomCssHelp": "Apply your own custom css to the web interface.", + "LabelLocalHttpServerPortNumber": "Local http port number:", "LabelLocalHttpServerPortNumberHelp": "The tcp port number that Media Browser's http server should bind to.", - "LabelPublicPort": "Public port number:", - "LabelPublicPortHelp": "The public port number that should be mapped to the local port.", + "LabelPublicHttpPort": "Public http port number:", + "LabelPublicHttpPortHelp": "The public port number that should be mapped to the local http port.", + "LabelPublicHttpsPort": "Public https port number:", + "LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.", + "LabelEnableHttps": "Report https as external address", + "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.", + "LabelHttpsPort": "Local https port number:", + "LabelHttpsPortHelp": "The tcp port number that Media Browser's https server should bind to.", "LabelWebSocketPortNumber": "Web socket port number:", "LabelEnableAutomaticPortMap": "Enable automatic port mapping", "LabelEnableAutomaticPortMapHelp": "Attempt to automatically map the public port to the local port via UPnP. This may not work with some router models.", - "LabelExternalDDNS": "External DDNS:", - "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely.", + "LabelExternalDDNS": "External WAN Address:", + "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely. Leave empty for automatic detection.", "TabResume": "Resume", "TabWeather": "Weather", "TitleAppSettings": "App Settings", @@ -575,6 +607,7 @@ "ButtonRestart": "Restart", "ButtonShutdown": "Shutdown", "ButtonUpdateNow": "Update Now", + "TabHosting": "Hosting", "PleaseUpdateManually": "Please shutdown the server and update manually.", "NewServerVersionAvailable": "A new version of Media Browser Server is available!", "ServerUpToDate": "Media Browser Server is up to date", @@ -636,6 +669,7 @@ "NotificationOptionInstallationFailed": "Installation failure", "NotificationOptionNewLibraryContent": "New content added", "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", + "NotificationOptionCameraImageUploaded": "Camera image uploaded", "SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.", "NotificationOptionServerRestartRequired": "Server restart required", "LabelNotificationEnabled": "Enable this notification", @@ -853,6 +887,8 @@ "OptionDefaultSort": "Default", "OptionCommunityMostWatchedSort": "Most Watched", "TabNextUp": "Next Up", + "HeaderBecomeMediaBrowserSupporter": "Become a Media Browser Supporter", + "TextEnjoyBonusFeatures": "Enjoy Bonus Features", "MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.", "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.", "MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.", @@ -869,7 +905,6 @@ "LabelChannelDownloadAge": "Delete content after: (days)", "LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.", "ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.", - "LabelSelectCollection": "Select collection:", "ButtonOptions": "Options", "ViewTypeMovies": "Movies", "ViewTypeTvShows": "TV", @@ -917,7 +952,7 @@ "OptionLatestTvRecordings": "Latest recordings", "LabelProtocolInfo": "Protocol info:", "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.", - "TabKodiMetadata": "Kodi", + "TabNfo": "Nfo", "HeaderKodiMetadataHelp": "Media Browser includes native support for Kodi Nfo metadata and images. To enable or disable Kodi metadata, use the Advanced tab to configure options for your media types.", "LabelKodiMetadataUser": "Sync user watch data to nfo's for:", "LabelKodiMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Kodi.", @@ -931,6 +966,7 @@ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:", "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.", "LabelDisplayCollectionsView": "Display a collections view to show movie collections", + "LabelDisplayCollectionsViewHelp": "This will create a separate view to display collections that you've created or have access to. To create a collection, right-click or tap-hold any movie and select 'Add to Collection'. ", "LabelKodiMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs", "LabelKodiMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Kodi skin compatibility.", "TabServices": "Services", @@ -1084,11 +1120,14 @@ "LabelDisplayFoldersView": "Display a folders view to show plain media folders", "ViewTypeLiveTvRecordingGroups": "Recordings", "ViewTypeLiveTvChannels": "Channels", - "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password", - "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.", + "LabelEasyPinCode": "Easy pin code:", + "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Media Browser apps, and can also be used for easy in-network sign in.", + "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", + "LabelInNetworkSignInWithEasyPasswordHelp": "If enabled, you'll be able to use your easy pin code to sign in to Media Browser apps from inside your home network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", "HeaderPassword": "Password", "HeaderLocalAccess": "Local Access", "HeaderViewOrder": "View Order", + "ButtonResetEasyPassword": "Reset easy pin code", "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps", "LabelMetadataRefreshMode": "Metadata refresh mode:", "LabelImageRefreshMode": "Image refresh mode:", @@ -1279,7 +1318,7 @@ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.", "HeaderNewUsers": "New Users", "ButtonSignUp": "Sign up", - "ButtonForgotPassword": "Forgot password?", + "ButtonForgotPassword": "Forgot password", "OptionDisableUserPreferences": "Disable access to user preferences", "OptionDisableUserPreferencesHelp": "If enabled, only administrators will be able to configure user profile images, passwords, and language preferences.", "HeaderSelectServer": "Select Server", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/es.json b/MediaBrowser.Server.Implementations/Localization/Server/es.json index c8d5d62bc..10fb8f326 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/es.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/es.json @@ -40,12 +40,32 @@ "OptionIAcceptTermsOfService": "I accept the terms of service", "ButtonPrivacyPolicy": "Privacy policy", "ButtonTermsOfService": "Terms of Service", + "HeaderDeveloperOptions": "Developer Options", + "OptionEnableWebClientResponseCache": "Enable web client response caching", + "OptionDisableForDevelopmentHelp": "Configure these as needed for web client development purposes.", + "OptionEnableWebClientResourceMinification": "Enable web client resource minification", + "LabelDashboardSourcePath": "Web client source path:", + "LabelDashboardSourcePathHelp": "If running the server from source, specify the path to the dashboard-ui folder. All web client files will be served from this location.", + "ButtonConvertMedia": "Convert media", + "ButtonOrganize": "Organize", "ButtonOk": "OK", "ButtonCancel": "Cancelar", "ButtonNew": "Nuevo", "HeaderTV": "TV", "HeaderAudio": "Audio", "HeaderVideo": "Video", + "HeaderPaths": "Paths", + "CategorySync": "Sync", + "HeaderEasyPinCode": "Easy Pin Code", + "RegisterWithPayPal": "Register with PayPal", + "HeaderSyncRequiresSupporterMembership": "Sync Requires a Supporter Membership", + "HeaderEnjoyDayTrial": "Enjoy a 14 Day Free Trial", + "LabelSyncTempPath": "Temporary file path:", + "LabelSyncTempPathHelp": "Specify a custom sync working folder. Converted media created during the sync process will be stored here.", + "LabelCustomCertificatePath": "Custom certificate path:", + "LabelCustomCertificatePathHelp": "Supply your own ssl certificate. If omitted, the server will create a self-signed certificate.", + "TitleNotifications": "Notifications", + "ButtonDonateWithPayPal": "Donate with PayPal", "OptionDetectArchiveFilesAsMedia": "Detect archive files as media", "OptionDetectArchiveFilesAsMediaHelp": "If enabled, files with .rar and .zip extensions will be detected as media files.", "LabelEnterConnectUserName": "User name or email:", @@ -63,12 +83,14 @@ "FolderTypeTvShows": "TV", "FolderTypeInherit": "Inherit", "LabelContentType": "Content type:", + "TitleScheduledTasks": "Scheduled Tasks", "HeaderSetupLibrary": "Configurar biblioteca de medios", "ButtonAddMediaFolder": "Agregar una carpeta de medios", "LabelFolderType": "Tipo de carpeta:", "ReferToMediaLibraryWiki": "Consultar el wiki de la biblioteca de medios", "LabelCountry": "Pa\u00eds:", "LabelLanguage": "Idioma:", + "ButtonJoinTheDevelopmentTeam": "Join the Development Team", "HeaderPreferredMetadataLanguage": "Idioma preferido para metadata", "LabelSaveLocalMetadata": "Guardar im\u00e1genes y metadata en las carpetas de medios", "LabelSaveLocalMetadataHelp": "Guardar im\u00e1genes y metadata directamente en las carpetas de medios, permitir\u00e1 colocarlas en un lugar donde se pueden editar f\u00e1cilmente.", @@ -86,6 +108,8 @@ "TabCollectionTitles": "T\u00edtulos", "HeaderDeviceAccess": "Device Access", "OptionEnableAccessFromAllDevices": "Enable access from all devices", + "OptionEnableAccessToAllChannels": "Enable access to all channels", + "OptionEnableAccessToAllLibraries": "Enable access to all libraries", "DeviceAccessHelp": "This only applies to devices that can be uniquely identified and will not prevent browser access. Filtering user device access will prevent them from using new devices until they've been approved here.", "LabelDisplayMissingEpisodesWithinSeasons": "Mostar episodios no disponibles en temporadas", "LabelUnairedMissingEpisodesWithinSeasons": "Mostrar episodios a\u00fan no emitidos en temporadas", @@ -275,7 +299,7 @@ "OptionMetascore": "Metavalor", "ButtonSelect": "Seleccionar", "ButtonGroupVersions": "Versiones de Grupo", - "ButtonAddToCollection": "A\u00f1adir a la colecci\u00f3n", + "ButtonAddToCollection": "Add to Collection", "PismoMessage": "Usando Pismo File Mount a trav\u00e9s de una licencia donada.", "TangibleSoftwareMessage": "Utilizamos convertidores Java\/C# de Tangible Solutions a trav\u00e9s de una licencia donada.", "HeaderCredits": "Cr\u00e9ditos", @@ -299,7 +323,7 @@ "LabelCachePath": "Ruta del cach\u00e9:", "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.", "LabelImagesByNamePath": "Ruta de im\u00e1genes:", - "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, genre and studio images.", "LabelMetadataPath": "Ruta de Metadata:", "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.", "LabelTranscodingTempPath": "Ruta temporal de transcodificaci\u00f3n:", @@ -314,12 +338,14 @@ "OptionEpisodes": "Episodios", "OptionOtherVideos": "Otros v\u00eddeos", "TitleMetadata": "Metadata", - "LabelAutomaticUpdatesFanart": "Activar actualizaciones autom\u00e1ticas desde FanArt.tv", + "LabelAutomaticUpdates": "Enable automatic updates", "LabelAutomaticUpdatesTmdb": "Activar actualizaciones autom\u00e1ticas desde TheMovieDB.org", "LabelAutomaticUpdatesTvdb": "Activar actualizaciones autom\u00e1ticas desde TheTVDB.com", "LabelAutomaticUpdatesFanartHelp": "Si est\u00e1 activado, las nuevas im\u00e1genes se descargan autom\u00e1ticamente a medida que se a\u00f1aden a fanart.tv. Im\u00e1genes existentes no ser\u00e1n reemplazadas.", "LabelAutomaticUpdatesTmdbHelp": "Si est\u00e1 activado, las nuevas im\u00e1genes se descargan autom\u00e1ticamente a medida que se a\u00f1aden a TheMovieDB.org. Im\u00e1genes existentes no ser\u00e1n reemplazados.", "LabelAutomaticUpdatesTvdbHelp": "Si est\u00e1 activado, las nuevas im\u00e1genes se descargan autom\u00e1ticamente a medida que se a\u00f1aden a TheTVDB.com. Im\u00e1genes existentes no ser\u00e1n reemplazados.", + "LabelFanartApiKey": "Personal api key:", + "LabelFanartApiKeyHelp": "Requests to fanart without a personal API key return results that were approved over 7 days ago. With a personal API key that drops to 48 hours and if you are also a fanart VIP member that will further drop to around 10 minutes.", "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", "LabelMetadataDownloadLanguage": "Preferred download language:", "ButtonAutoScroll": "Auto-desplazamiento", @@ -487,6 +513,7 @@ "HeaderSystemPaths": "Rutas del sistema", "LinkCommunity": "Comunidad", "LinkGithub": "Github", + "LinkApi": "Api", "LinkApiDocumentation": "Documentaci\u00f3n API", "LabelFriendlyServerName": "Nombre informal del servidor:", "LabelFriendlyServerNameHelp": "Este nombre se podr\u00e1 utilizar para identificar este servidor. Si se deja en blanco se usar\u00e1 el nombre del ordenador.", @@ -494,20 +521,25 @@ "LabelPreferredDisplayLanguageHelp": "La traducci\u00f3n de Media Browser es un proyecto en curso y a\u00fan no est\u00e1 completado.", "LabelReadHowYouCanContribute": "Lea acerca de c\u00f3mo usted puede contribuir.", "HeaderNewCollection": "Nueva colecci\u00f3n", - "HeaderAddToCollection": "A\u00f1adir a la colecci\u00f3n", "ButtonSubmit": "Enviar", - "NewCollectionNameExample": "Ejemplo: Star Wars Colecci\u00f3n", - "OptionSearchForInternetMetadata": "Buscar en internet ilustraciones y metadatos", "ButtonCreate": "Crear", - "LabelLocalHttpServerPortNumber": "Local port number:", + "LabelCustomCss": "Custom css:", + "LabelCustomCssHelp": "Apply your own custom css to the web interface.", + "LabelLocalHttpServerPortNumber": "Local http port number:", "LabelLocalHttpServerPortNumberHelp": "The tcp port number that Media Browser's http server should bind to.", - "LabelPublicPort": "Public port number:", - "LabelPublicPortHelp": "The public port number that should be mapped to the local port.", + "LabelPublicHttpPort": "Public http port number:", + "LabelPublicHttpPortHelp": "The public port number that should be mapped to the local http port.", + "LabelPublicHttpsPort": "Public https port number:", + "LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.", + "LabelEnableHttps": "Report https as external address", + "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.", + "LabelHttpsPort": "Local https port number:", + "LabelHttpsPortHelp": "The tcp port number that Media Browser's https server should bind to.", "LabelWebSocketPortNumber": "N\u00famero de puerto WebSocket:", "LabelEnableAutomaticPortMap": "Enable automatic port mapping", "LabelEnableAutomaticPortMapHelp": "Attempt to automatically map the public port to the local port via UPnP. This may not work with some router models.", - "LabelExternalDDNS": "DDNS externa:", - "LabelExternalDDNSHelp": "Si dispone de DNS din\u00e1mica, escr\u00edbala aqu\u00ed. Media Brower la utilizar\u00e1 para las conexiones remotas.", + "LabelExternalDDNS": "External WAN Address:", + "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely. Leave empty for automatic detection.", "TabResume": "Continuar", "TabWeather": "El tiempo", "TitleAppSettings": "Opciones de la App", @@ -575,6 +607,7 @@ "ButtonRestart": "Reiniciar", "ButtonShutdown": "Apagar", "ButtonUpdateNow": "Actualizar ahora", + "TabHosting": "Hosting", "PleaseUpdateManually": "Por favor cierre el servidor y actualice manualmente.", "NewServerVersionAvailable": "\u00a1Hay disponible una nueva versi\u00f3n de Media Browser Server!", "ServerUpToDate": "Media Browser Server est\u00e1 actualizado", @@ -636,6 +669,7 @@ "NotificationOptionInstallationFailed": "Fallo en la instalaci\u00f3n", "NotificationOptionNewLibraryContent": "Nuevo contenido a\u00f1adido", "NotificationOptionNewLibraryContentMultiple": "Nuevo contenido a\u00f1adido (multiple)", + "NotificationOptionCameraImageUploaded": "Camera image uploaded", "SendNotificationHelp": "Por defecto, las notificaciones aparecer\u00e1n en el panel de control. Compruebe el cat\u00e1logo de plugins para instalar opciones adicionales para las notificaciones.", "NotificationOptionServerRestartRequired": "Se requiere el reinicio del servidor", "LabelNotificationEnabled": "Activar esta notificaci\u00f3n", @@ -853,6 +887,8 @@ "OptionDefaultSort": "Por defecto", "OptionCommunityMostWatchedSort": "M\u00e1s visto", "TabNextUp": "Siguiendo", + "HeaderBecomeMediaBrowserSupporter": "Become a Media Browser Supporter", + "TextEnjoyBonusFeatures": "Enjoy Bonus Features", "MessageNoMovieSuggestionsAvailable": "No hay sugerencias de pel\u00edculas disponibles. Comience ver y calificar sus pel\u00edculas y vuelva para ver las recomendaciones.", "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.", "MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.", @@ -869,7 +905,6 @@ "LabelChannelDownloadAge": "Borrar contenido despues de: (d\u00edas)", "LabelChannelDownloadAgeHelp": "Todo contenido descargado anterior se borrar\u00e1. Continuar\u00e1 estando disponible v\u00eda streaming de internet.", "ChannelSettingsFormHelp": "Instale canales como Trailers y Vimeo desde el cat\u00e1logo de plugins.", - "LabelSelectCollection": "Seleccionar colecci\u00f3n:", "ButtonOptions": "Options", "ViewTypeMovies": "Pel\u00edculas", "ViewTypeTvShows": "TV", @@ -917,7 +952,7 @@ "OptionLatestTvRecordings": "\u00daltimas grabaciones", "LabelProtocolInfo": "Informaci\u00f3n de protocolo:", "LabelProtocolInfoHelp": "El valor que se utilizar\u00e1 cuando se responde a una solicitud GetProtocolInfo desde el dispositivo.", - "TabKodiMetadata": "Kodi", + "TabNfo": "Nfo", "HeaderKodiMetadataHelp": "Media Browser includes native support for Kodi Nfo metadata and images. To enable or disable Kodi metadata, use the Advanced tab to configure options for your media types.", "LabelKodiMetadataUser": "Sync user watch data to nfo's for:", "LabelKodiMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Kodi.", @@ -931,6 +966,7 @@ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:", "LabelGroupChannelsIntoViewsHelp": "Si est\u00e1 activado, estos canales se mostrar\u00e1n directamente junto a Mis Vistas. Si est\u00e1 desactivada, ser\u00e1n mostrados separadamente en la vista de Canales.", "LabelDisplayCollectionsView": "Display a collections view to show movie collections", + "LabelDisplayCollectionsViewHelp": "This will create a separate view to display collections that you've created or have access to. To create a collection, right-click or tap-hold any movie and select 'Add to Collection'. ", "LabelKodiMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs", "LabelKodiMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Kodi skin compatibility.", "TabServices": "Servicios", @@ -1084,11 +1120,14 @@ "LabelDisplayFoldersView": "Display a folders view to show plain media folders", "ViewTypeLiveTvRecordingGroups": "Recordings", "ViewTypeLiveTvChannels": "Channels", - "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password", - "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.", + "LabelEasyPinCode": "Easy pin code:", + "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Media Browser apps, and can also be used for easy in-network sign in.", + "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", + "LabelInNetworkSignInWithEasyPasswordHelp": "If enabled, you'll be able to use your easy pin code to sign in to Media Browser apps from inside your home network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", "HeaderPassword": "Password", "HeaderLocalAccess": "Local Access", "HeaderViewOrder": "View Order", + "ButtonResetEasyPassword": "Reset easy pin code", "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps", "LabelMetadataRefreshMode": "Metadata refresh mode:", "LabelImageRefreshMode": "Image refresh mode:", @@ -1279,7 +1318,7 @@ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.", "HeaderNewUsers": "New Users", "ButtonSignUp": "Sign up", - "ButtonForgotPassword": "Forgot password?", + "ButtonForgotPassword": "Forgot password", "OptionDisableUserPreferences": "Disable access to user preferences", "OptionDisableUserPreferencesHelp": "If enabled, only administrators will be able to configure user profile images, passwords, and language preferences.", "HeaderSelectServer": "Select Server", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/es_ES.json b/MediaBrowser.Server.Implementations/Localization/Server/es_ES.json deleted file mode 100644 index 02412b97f..000000000 --- a/MediaBrowser.Server.Implementations/Localization/Server/es_ES.json +++ /dev/null @@ -1,872 +0,0 @@ -{ - "LabelExit": "Salir", - "LabelVisitCommunity": "Visitar la comunidad", - "LabelGithubWiki": "Wiki de Github", - "LabelSwagger": "Swagger", - "LabelStandard": "Est\u00e1ndar", - "LabelViewApiDocumentation": "Ver documentacion de Api", - "LabelBrowseLibrary": "Navegar biblioteca", - "LabelConfigureMediaBrowser": "Configurar Media Browser", - "LabelOpenLibraryViewer": "Abrir el visor de la biblioteca", - "LabelRestartServer": "Reiniciar el servidor", - "LabelShowLogWindow": "Mostrar la ventana del log", - "LabelPrevious": "Anterior", - "LabelFinish": "Terminar", - "LabelNext": "Siguiente", - "LabelYoureDone": "Ha Terminado!", - "WelcomeToMediaBrowser": "\u00a1Bienvenido a Media Browser!", - "TitleMediaBrowser": "Media Browser", - "ThisWizardWillGuideYou": "Este asistente lo guiar\u00e1 por el proceso de instalaci\u00f3n. Para comenzar seleccione su idioma preferido.", - "TellUsAboutYourself": "D\u00edganos acerca de usted", - "LabelYourFirstName": "Su nombre:", - "MoreUsersCanBeAddedLater": "M\u00e1s usuarios pueden agregarse m\u00e1s tarde en el panel de control.", - "UserProfilesIntro": "Media Browser incluye soporte integrado para los perfiles de usuario, lo que permite que cada usuario tenga su propia configuraci\u00f3n de la pantalla, estado de reproducci\u00f3n y control parental.", - "LabelWindowsService": "Servicio de Windows", - "AWindowsServiceHasBeenInstalled": "Un servicio de Windows se ha instalado", - "WindowsServiceIntro1": "Media Browser Server se ejecuta normalmente como una aplicaci\u00f3n de escritorio con un icono de la bandeja, pero si prefiere ejecutarlo como un servicio en segundo plano, se puede iniciar desde el panel de control de servicios de Windows en su lugar.", - "WindowsServiceIntro2": "Si se utiliza el servicio de Windows, tenga en cuenta que no se puede ejecutar al mismo tiempo que el icono de la bandeja, por lo que tendr\u00e1 que salir de la bandeja con el fin de ejecutar el servicio. Tambi\u00e9n tendr\u00e1 que ser configurado con privilegios administrativos a trav\u00e9s del panel de control del servicio. Tenga en cuenta que en este momento el servicio no es capaz de auto-actualizaci\u00f3n, por lo que las nuevas versiones requieren la interacci\u00f3n manual.", - "WizardCompleted": "Eso es todo lo que necesitamos por ahora. Media Browser ha comenzado a reunir informaci\u00f3n sobre su biblioteca de medios. Echa un vistazo a algunas de nuestras aplicaciones, y luego haga clic en <b>Finalizar<\/b> para ver el <b>Panel de control<\/b>.", - "LabelConfigureSettings": "Configuraci\u00f3n de opciones", - "LabelEnableVideoImageExtraction": "Habilitar extracci\u00f3n de im\u00e1genes de video", - "VideoImageExtractionHelp": "Para los v\u00eddeos que no dispongan de im\u00e1genes y que no podemos encontrar en Internet. Esto agregar\u00e1 un tiempo adicional para la exploraci\u00f3n inicial de bibliotecas, pero resultar\u00e1 en una presentaci\u00f3n m\u00e1s agradable.", - "LabelEnableChapterImageExtractionForMovies": "Extraer im\u00e1genes de cap\u00edtulos para pel\u00edculas", - "LabelChapterImageExtractionForMoviesHelp": "Extraer im\u00e1genes de cap\u00edtulo permitir\u00e1 a los clientes mostrar men\u00fas gr\u00e1ficos de selecci\u00f3n de escenas. El proceso puede ser lento, intensivo en utilizaci\u00f3n del CPU y puede requerir varios gigabytes de espacio. Se ejecuta como una tarea nocturna, a las 4 de la ma\u00f1ana, aunque esto se puede configurar en el \u00e1rea de tareas programadas. No se recomienda ejecutar esta tarea durante las horas pico de uso.", - "LabelEnableAutomaticPortMapping": "Habilitar asignaci\u00f3n de puertos autom\u00e1tico", - "LabelEnableAutomaticPortMappingHelp": "UPnP permite la configuraci\u00f3n del router para acceso externo de forma f\u00e1cil y autom\u00e1tica. Esto puede no funcionar en algunos modelos de routers.", - "ButtonOk": "OK", - "ButtonCancel": "Cancelar", - "ButtonNew": "Nuevo", - "HeaderSetupLibrary": "Configurar biblioteca de medios", - "ButtonAddMediaFolder": "Agregar una carpeta de medios", - "LabelFolderType": "Tipo de carpeta:", - "MediaFolderHelpPluginRequired": "* Requiere el uso de un plugin, por ejemplo GameBrowser o MB Bookshelf", - "ReferToMediaLibraryWiki": "Consultar el wiki de la biblioteca de medios", - "LabelCountry": "Pa\u00eds:", - "LabelLanguage": "Idioma:", - "HeaderPreferredMetadataLanguage": "Idioma preferido para metadata", - "LabelSaveLocalMetadata": "Guardar im\u00e1genes y metadata en las carpetas de medios", - "LabelSaveLocalMetadataHelp": "Guardar im\u00e1genes y metadata directamente en las carpetas de medios, permitir\u00e1 colocarlas en un lugar donde se pueden editar f\u00e1cilmente.", - "LabelDownloadInternetMetadata": "Descargar imagenes y metadata de internet", - "LabelDownloadInternetMetadataHelp": "Media Browser permite descargar informaci\u00f3n acerca de su media para enriquecer la presentaci\u00f3n.", - "TabPreferences": "Preferencias", - "TabPassword": "Contrase\u00f1a", - "TabLibraryAccess": "Acceso a biblioteca", - "TabImage": "imagen", - "TabProfile": "Perfil", - "TabMetadata": "Metadata", - "TabImages": "Im\u00e1genes", - "TabNotifications": "Notificaciones", - "TabCollectionTitles": "T\u00edtulos", - "LabelDisplayMissingEpisodesWithinSeasons": "Mostar episodios no disponibles en temporadas", - "LabelUnairedMissingEpisodesWithinSeasons": "Mostrar episodios a\u00fan no emitidos en temporadas", - "HeaderVideoPlaybackSettings": "Ajustes de Reproducci\u00f3n de Video", - "HeaderPlaybackSettings": "Ajustes de reproducci\u00f3n", - "LabelAudioLanguagePreference": "Preferencia de idioma de audio", - "LabelSubtitleLanguagePreference": "Preferencia de idioma de subtitulos", - "OptionDefaultSubtitles": "Por defecto", - "OptionOnlyForcedSubtitles": "S\u00f3lo subt\u00edtulos forzados", - "OptionAlwaysPlaySubtitles": "Mostrar siempre subt\u00edtulos", - "OptionNoSubtitles": "Sin subt\u00edtulos", - "OptionDefaultSubtitlesHelp": "Los subt\u00edtulos que concuerden con la preferencia de idioma se cargar\u00e1n cuando el audio est\u00e9 en un idioma extranjero.", - "OptionOnlyForcedSubtitlesHelp": "S\u00f3lo se cargar\u00e1n los subt\u00edtulos marcados como forzados.", - "OptionAlwaysPlaySubtitlesHelp": "Los subt\u00edtulos que concuerden con la preferencia de idioma se cargar\u00e1n independientemente del idioma de audio.", - "OptionNoSubtitlesHelp": "Los subt\u00edtulos no se cargar\u00e1n de forma predeterminada.", - "TabProfiles": "Perfiles", - "TabSecurity": "Seguridad", - "ButtonAddUser": "Agregar Usuario", - "ButtonSave": "Grabar", - "ButtonResetPassword": "Reiniciar Contrase\u00f1a", - "LabelNewPassword": "Nueva Contrase\u00f1a:", - "LabelNewPasswordConfirm": "Confirmaci\u00f3n de contrase\u00f1a nueva:", - "HeaderCreatePassword": "Crear Contrase\u00f1a", - "LabelCurrentPassword": "Contrase\u00f1a actual", - "LabelMaxParentalRating": "M\u00e1xima clasificaci\u00f3n permitida", - "MaxParentalRatingHelp": "El contenido con clasificaci\u00f3n parental superior se ocultar\u00e1 para este usuario.", - "LibraryAccessHelp": "Seleccione las carpetas de medios para compartir con este usuario. Los administradores podr\u00e1n editar todas las carpetas usando el gestor de metadata.", - "ChannelAccessHelp": "Seleccione los canales para compartir con este usuario. Los administradores podr\u00e1n editar todos los canales mediante el gestor de metadatos.", - "ButtonDeleteImage": "Borrar imagen", - "LabelSelectUsers": "Seleccionar usuarios:", - "ButtonUpload": "Subir", - "HeaderUploadNewImage": "Subir nueva imagen", - "LabelDropImageHere": "Depositar Imagen Aqu\u00ed", - "ImageUploadAspectRatioHelp": "Se Recomienda una Proporci\u00f3n de Aspecto 1:1. Solo JPG\/PNG", - "MessageNothingHere": "Nada aqu\u00ed.", - "MessagePleaseEnsureInternetMetadata": "Por favor aseg\u00farese que la descarga de metadata de internet esta habilitada", - "TabSuggested": "Sugerencia", - "TabLatest": "Novedades", - "TabUpcoming": "Pr\u00f3ximos", - "TabShows": "Programas", - "TabEpisodes": "Episodios", - "TabGenres": "G\u00e9neros", - "TabPeople": "Gente", - "TabNetworks": "redes", - "HeaderUsers": "Usuarios", - "HeaderFilters": "Filtros:", - "ButtonFilter": "Filtro", - "OptionFavorite": "Favoritos", - "OptionLikes": "Me gusta", - "OptionDislikes": "No me gusta", - "OptionActors": "Actores", - "OptionGuestStars": "Estrellas invitadas", - "OptionDirectors": "Directores", - "OptionWriters": "Guionistas", - "OptionProducers": "Productores", - "HeaderResume": "Continuar", - "HeaderNextUp": "Siguiendo", - "NoNextUpItemsMessage": "Nada encontrado. \u00a1Comienza a ver tus programas!", - "HeaderLatestEpisodes": "Ultimos episodios", - "HeaderPersonTypes": "Tipos de personas:", - "TabSongs": "Canciones", - "TabAlbums": "Albums", - "TabArtists": "Artistas", - "TabAlbumArtists": "Album Artistas", - "TabMusicVideos": "Videos Musicales", - "ButtonSort": "Ordenar", - "HeaderSortBy": "Ordenar por:", - "HeaderSortOrder": "Ordenado por:", - "OptionPlayed": "Reproducido", - "OptionUnplayed": "No reproducido", - "OptionAscending": "Ascendente", - "OptionDescending": "Descendente", - "OptionRuntime": "Tiempo", - "OptionReleaseDate": "Fecha de estreno", - "OptionPlayCount": "N\u00famero de reproducc.", - "OptionDatePlayed": "Fecha de reproducci\u00f3n", - "OptionDateAdded": "A\u00f1adido el", - "OptionAlbumArtist": "Album Artista", - "OptionArtist": "Artista", - "OptionAlbum": "Album", - "OptionTrackName": "Nombre de pista", - "OptionCommunityRating": "Valoraci\u00f3n comunidad", - "OptionNameSort": "Nombre", - "OptionFolderSort": "Carpetas", - "OptionBudget": "Presupuesto", - "OptionRevenue": "Recaudaci\u00f3n", - "OptionPoster": "Poster", - "OptionBackdrop": "Imagen de fondo", - "OptionTimeline": "L\u00ednea de tiempo", - "OptionThumb": "Miniatura", - "OptionBanner": "Banner", - "OptionCriticRating": "Valoraci\u00f3n cr\u00edtica", - "OptionVideoBitrate": "Video Bitrate", - "OptionResumable": "Se puede continuar", - "ScheduledTasksHelp": "Click en una tarea para ajustar su programaci\u00f3n", - "ScheduledTasksTitle": "Tareas programadas", - "TabMyPlugins": "Mis Plugins", - "TabCatalog": "Cat\u00e1logo", - "PluginsTitle": "Plugins", - "HeaderAutomaticUpdates": "Actualizaciones autom\u00e1ticas", - "HeaderNowPlaying": "Reproduciendo ahora", - "HeaderLatestAlbums": "\u00dcltimos Albums", - "HeaderLatestSongs": "\u00daltimas canciones", - "HeaderRecentlyPlayed": "Reproducido recientemente", - "HeaderFrequentlyPlayed": "Reproducido frequentemente", - "DevBuildWarning": "Las actualizaciones en desarrollo no est\u00e1n convenientemente probadas. La aplicaci\u00f3n se puede bloquear y caracter\u00edsticas completas pueden no funcionar del todo.", - "LabelVideoType": "Tipo de video", - "OptionBluray": "Bluray", - "OptionDvd": "Dvd", - "OptionIso": "Iso", - "Option3D": "3D", - "LabelFeatures": "Caracter\u00edsticas", - "LabelService": "Servicio:", - "LabelStatus": "Estado:", - "LabelVersion": "Versi\u00f3n:", - "LabelLastResult": "\u00daltimo resultado:", - "OptionHasSubtitles": "Subt\u00edtulos", - "OptionHasTrailer": "Trailer", - "OptionHasThemeSong": "Banda sonora", - "OptionHasThemeVideo": "Viideotema", - "TabMovies": "Pel\u00edculas", - "TabStudios": "Estudios", - "TabTrailers": "Trailers", - "HeaderLatestMovies": "\u00daltimas pel\u00edculas", - "HeaderLatestTrailers": "\u00daltimos trailers", - "OptionHasSpecialFeatures": "Caracter\u00edsticas especiales", - "OptionImdbRating": "Valoraci\u00f3n IMDb", - "OptionParentalRating": "Clasificaci\u00f3n parental", - "OptionPremiereDate": "Fecha de estreno", - "TabBasic": "B\u00e1sico", - "TabAdvanced": "Avanzado", - "HeaderStatus": "Estado", - "OptionContinuing": "Continuando", - "OptionEnded": "Finalizado", - "HeaderAirDays": "D\u00eda emisi\u00f3n", - "OptionSunday": "Domingo", - "OptionMonday": "Lunes", - "OptionTuesday": "Martes", - "OptionWednesday": "Mi\u00e9rcoles", - "OptionThursday": "Jueves", - "OptionFriday": "Viernes", - "OptionSaturday": "S\u00e1bado", - "HeaderManagement": "Administraci\u00f3n", - "OptionMissingImdbId": "Falta IMDb Id", - "OptionMissingTvdbId": "Falta TheTVDB Id", - "OptionMissingOverview": "Falta argumento", - "OptionFileMetadataYearMismatch": "Archivo\/Metadata a\u00f1os no coinciden", - "TabGeneral": "General", - "TitleSupport": "Soporte", - "TabLog": "Log", - "TabAbout": "Acerca de", - "TabSupporterKey": "Clave de Seguidor", - "TabBecomeSupporter": "Hazte Seguidor", - "MediaBrowserHasCommunity": "Media Browser cuenta con una pr\u00f3spera comunidad de usuarios y colaboradores.", - "CheckoutKnowledgeBase": "Echa un vistazo a nuestra base de conocimiento para ayudarte a sacar el m\u00e1ximo provecho de Media Browser.", - "SearchKnowledgeBase": "Buscar en la base de conocimiento", - "VisitTheCommunity": "Visitar la comunidad", - "VisitMediaBrowserWebsite": "Visitar la web de Media Browser", - "VisitMediaBrowserWebsiteLong": "Visita la web de Media Browser para estar informado de las \u00faltimas not\u00edcias y mantenerte al d\u00eda con el blog de desarrolladores.", - "OptionHideUser": "Ocultar este usuario en las pantallas de inicio de sesi\u00f3n", - "OptionDisableUser": "Deshabilitar este usuario", - "OptionDisableUserHelp": "Si est\u00e1 deshabilitado, el servidor no aceptar\u00e1 conexiones de este usuario. Si existen conexiones de este usuario, finalizar\u00e1n inmediatamente.", - "HeaderAdvancedControl": "Control avanzado", - "LabelName": "Nombre:", - "OptionAllowUserToManageServer": "Permite a este usuario administrar el servidor", - "HeaderFeatureAccess": "Permisos de acceso", - "OptionAllowMediaPlayback": "Permitir reproducci\u00f3n de medios", - "OptionAllowBrowsingLiveTv": "Acceso a TV en vivo", - "OptionAllowDeleteLibraryContent": "Permitir a este usuario eliminar contenido de la biblioteca", - "OptionAllowManageLiveTv": "Permitir la gesti\u00f3n de las grabaciones de TV en vivo", - "OptionAllowRemoteControlOthers": "Permitir a este usuario controlar rem\u00f3tamente a otros usuarios", - "OptionMissingTmdbId": "Falta Tmdb Id", - "OptionIsHD": "HD", - "OptionIsSD": "SD", - "OptionMetascore": "Metavalor", - "ButtonSelect": "Seleccionar", - "ButtonSearch": "Buscar", - "ButtonGroupVersions": "Versiones de Grupo", - "ButtonAddToCollection": "A\u00f1adir a la colecci\u00f3n", - "PismoMessage": "Usando Pismo File Mount a trav\u00e9s de una licencia donada.", - "TangibleSoftwareMessage": "Utilizamos convertidores Java\/C# de Tangible Solutions a trav\u00e9s de una licencia donada.", - "HeaderCredits": "Cr\u00e9ditos", - "PleaseSupportOtherProduces": "Por favor apoye otros productos gratuitos que utilizamos:", - "VersionNumber": "Versi\u00f3n {0}", - "TabPaths": "Ruta", - "TabServer": "Servidor", - "TabTranscoding": "Transcodificaci\u00f3n", - "TitleAdvanced": "Avanzado", - "LabelAutomaticUpdateLevel": "Actualizaci\u00f3n de nivel autom\u00e1tica", - "OptionRelease": "Release Oficial", - "OptionBeta": "Beta", - "OptionDev": "Desarrollo", - "LabelAllowServerAutoRestart": "Permitir al servidor reiniciarse autom\u00e1ticamente para aplicar las actualizaciones", - "LabelAllowServerAutoRestartHelp": "El servidor s\u00f3lo se reiniciar\u00e1 durante periodos de reposo, cuando no hayan usuarios activos.", - "LabelEnableDebugLogging": "Habilitar entrada de debug", - "LabelRunServerAtStartup": "Arrancar servidor al iniciar", - "LabelRunServerAtStartupHelp": "Esto iniciar\u00e1 como aplicaci\u00f3n en el inicio. Para iniciar en modo servicio de windows, desmarque esto e inicie el servicio desde el panel de control de windows. Tenga en cuenta que no es posible inciar de las dos formas a la vez, usted debe salir de la aplicaci\u00f3n para iniciar el servicio.", - "ButtonSelectDirectory": "Seleccionar directorio", - "LabelCustomPaths": "Especificar las rutas personalizadas que desee. D\u00e9jelo en blanco para usar las rutas por defecto.", - "LabelCachePath": "Ruta del cach\u00e9:", - "LabelCachePathHelp": "Esta carpeta contienes archivos de cach\u00e9 del servidor, tales como im\u00e1genes.", - "LabelImagesByNamePath": "Ruta de im\u00e1genes:", - "LabelImagesByNamePathHelp": "Esta carpeta contiene im\u00e1genes de actores, artistas, g\u00e9neros y estudios.", - "LabelMetadataPath": "Ruta de Metadata:", - "LabelMetadataPathHelp": "Esta localizaci\u00f3n contiene im\u00e1genes y metadata descargados que no est\u00e1n configurados para ser guardados en carpetas de medios.", - "LabelTranscodingTempPath": "Ruta temporal de transcodificaci\u00f3n:", - "LabelTranscodingTempPathHelp": "Esta carpeta contiene archivos de trabajo usados por el transcodificador.", - "TabBasics": "Basicos", - "TabTV": "TV", - "TabGames": "Juegos", - "TabMusic": "M\u00fasica", - "TabOthers": "Otros", - "HeaderExtractChapterImagesFor": "Extraer im\u00e1genes de cap\u00edtulos para:", - "OptionMovies": "Pel\u00edculas", - "OptionEpisodes": "Episodios", - "OptionOtherVideos": "Otros v\u00eddeos", - "TitleMetadata": "Metadata", - "LabelAutomaticUpdatesFanart": "Activar actualizaciones autom\u00e1ticas desde FanArt.tv", - "LabelAutomaticUpdatesTmdb": "Activar actualizaciones autom\u00e1ticas desde TheMovieDB.org", - "LabelAutomaticUpdatesTvdb": "Activar actualizaciones autom\u00e1ticas desde TheTVDB.com", - "LabelAutomaticUpdatesFanartHelp": "Si est\u00e1 activado, las nuevas im\u00e1genes se descargan autom\u00e1ticamente a medida que se a\u00f1aden a fanart.tv. Im\u00e1genes existentes no ser\u00e1n reemplazadas.", - "LabelAutomaticUpdatesTmdbHelp": "Si est\u00e1 activado, las nuevas im\u00e1genes se descargan autom\u00e1ticamente a medida que se a\u00f1aden a TheMovieDB.org. Im\u00e1genes existentes no ser\u00e1n reemplazados.", - "LabelAutomaticUpdatesTvdbHelp": "Si est\u00e1 activado, las nuevas im\u00e1genes se descargan autom\u00e1ticamente a medida que se a\u00f1aden a TheTVDB.com. Im\u00e1genes existentes no ser\u00e1n reemplazados.", - "ExtractChapterImagesHelp": "Extraer im\u00e1genes de cap\u00edtulo permitir\u00e1 a los clientes mostrar men\u00fas gr\u00e1ficos de selecci\u00f3n de escenas. El proceso puede ser lento, uso de CPU intensivo y puede requerir varios gigabytes de espacio. Se ejecuta como una tarea nocturna, a las 4 de la ma\u00f1ana, aunque esto se puede configurar en el \u00e1rea de tareas programadas. No se recomienda ejecutar esta tarea durante las horas pico.", - "LabelMetadataDownloadLanguage": "Idioma preferido:", - "ButtonAutoScroll": "Auto-desplazamiento", - "LabelImageSavingConvention": "Sistema de guardado de im\u00e1genes:", - "LabelImageSavingConventionHelp": "Media Browser reconoce im\u00e1genes de la mayor\u00eda de aplicaciones de medios. La elecci\u00f3n de su sistema de descarga es \u00fatil si tambi\u00e9n usa otros productos.", - "OptionImageSavingCompatible": "Compatible - MB3\/Plex\/Xbmc", - "OptionImageSavingStandard": "Est\u00e1ndard - MB3\/MB2", - "ButtonSignIn": "Registrarse", - "TitleSignIn": "Registrarse", - "HeaderPleaseSignIn": "Por favor reg\u00edstrese", - "LabelUser": "Usuario:", - "LabelPassword": "Contrase\u00f1a:", - "ButtonManualLogin": "Registro manual:", - "PasswordLocalhostMessage": "No se necesitan contrase\u00f1as al iniciar sesi\u00f3n desde localhost.", - "TabGuide": "Gu\u00eda", - "TabChannels": "Canales", - "TabCollections": "Colecciones", - "HeaderChannels": "Canales", - "TabRecordings": "Grabaciones", - "TabScheduled": "Programado", - "TabSeries": "Series", - "TabFavorites": "Favoritos", - "TabMyLibrary": "Mi biblioteca", - "ButtonCancelRecording": "Cancelar grabaci\u00f3n", - "HeaderPrePostPadding": "Pre\/post grabaci\u00f3n extra", - "LabelPrePaddingMinutes": "Minutos previos extras:", - "OptionPrePaddingRequired": "Minutos previos extras requeridos para grabar.", - "LabelPostPaddingMinutes": "Minutos extras post grabaci\u00f3n:", - "OptionPostPaddingRequired": "Minutos post grabaci\u00f3n extras requeridos para grabar.", - "HeaderWhatsOnTV": "Que hacen ahora", - "HeaderUpcomingTV": "Pr\u00f3ximos programas", - "TabStatus": "Estado", - "TabSettings": "Opciones", - "ButtonRefreshGuideData": "Actualizar datos de la gu\u00eda", - "OptionPriority": "Prioridad", - "OptionRecordOnAllChannels": "Grabar programa en cualquier canal", - "OptionRecordAnytime": "Grabar programa a cualquier hora", - "OptionRecordOnlyNewEpisodes": "Grabar s\u00f3lo nuevos episodios", - "HeaderDays": "D\u00edas", - "HeaderActiveRecordings": "Grabaciones activas", - "HeaderLatestRecordings": "\u00daltimas grabaciones", - "HeaderAllRecordings": "Todas la grabaciones", - "ButtonPlay": "Reproducir", - "ButtonEdit": "Editar", - "ButtonRecord": "Grabar", - "ButtonDelete": "Borrar", - "ButtonRemove": "Quitar", - "OptionRecordSeries": "Grabar serie", - "HeaderDetails": "Detalles", - "TitleLiveTV": "Tv en vivo", - "LabelNumberOfGuideDays": "N\u00famero de d\u00edas de descarga de la gu\u00eda.", - "LabelNumberOfGuideDaysHelp": "Descargar m\u00e1s d\u00edas de la gu\u00eda ofrece la posibilidad de programar grabaciones con mayor antelaci\u00f3n y ver m\u00e1s listas, pero tambi\u00e9n tarda m\u00e1s en descargarse. Auto elegir\u00e1 en funci\u00f3n del n\u00famero de canales.", - "LabelActiveService": "Activar servicio", - "LabelActiveServiceHelp": "Es posible instalar m\u00faltiples plugins de tv, pero s\u00f3lo puede estar activo uno a la vez.", - "OptionAutomatic": "Auto", - "LiveTvPluginRequired": "El servicio de TV en vivo es necesario para poder continuar.", - "LiveTvPluginRequiredHelp": "Instale uno de los plugins disponibles, como Next Pvr o ServerVmc.", - "LabelCustomizeOptionsPerMediaType": "Personalizar por tipo de medio:", - "OptionDownloadThumbImage": "Miniatura", - "OptionDownloadMenuImage": "Men\u00fa", - "OptionDownloadLogoImage": "Logo", - "OptionDownloadBoxImage": "Caja", - "OptionDownloadDiscImage": "Disco", - "OptionDownloadBannerImage": "Pancarta", - "OptionDownloadBackImage": "Atr\u00e1s", - "OptionDownloadArtImage": "Arte", - "OptionDownloadPrimaryImage": "Principal", - "HeaderFetchImages": "Buscar im\u00e1genes", - "HeaderImageSettings": "Opciones de im\u00e1gen", - "TabOther": "Otros", - "LabelMaxBackdropsPerItem": "M\u00e1ximo n\u00famero de im\u00e1genes de fondo por \u00edtem:", - "LabelMaxScreenshotsPerItem": "M\u00e1ximo n\u00famero de capturas de pantalla por \u00edtem:", - "LabelMinBackdropDownloadWidth": "Anchura m\u00ednima de descarga de im\u00e1genes de fondo:", - "LabelMinScreenshotDownloadWidth": "Anchura m\u00ednima de descarga de capturas de pantalla:", - "ButtonAddScheduledTaskTrigger": "A\u00f1adir eventos", - "HeaderAddScheduledTaskTrigger": "A\u00f1adir eventos de ejecuci\u00f3n", - "ButtonAdd": "A\u00f1adir", - "LabelTriggerType": "Tipo de evento:", - "OptionDaily": "Diario", - "OptionWeekly": "Semanal", - "OptionOnInterval": "En un intervalo", - "OptionOnAppStartup": "Al iniciar la aplicaci\u00f3n", - "OptionAfterSystemEvent": "Despu\u00e9s de un evento de sistema", - "LabelDay": "D\u00eda:", - "LabelTime": "Hora:", - "LabelEvent": "Evento:", - "OptionWakeFromSleep": "Despertar", - "LabelEveryXMinutes": "Cada:", - "HeaderTvTuners": "Sintonizadores", - "HeaderGallery": "Galer\u00eda", - "HeaderLatestGames": "\u00daltimos Juegos", - "HeaderRecentlyPlayedGames": "Juegos utilizados recientemente", - "TabGameSystems": "Sistema de Juego", - "TitleMediaLibrary": "Librer\u00eda de medios", - "TabFolders": "Carpetas", - "TabPathSubstitution": "Ruta alternativa", - "LabelSeasonZeroDisplayName": "Nombre de la Temporada 0:", - "LabelEnableRealtimeMonitor": "Activar monitoreo en tiempo real", - "LabelEnableRealtimeMonitorHelp": "Los cambios se procesar\u00e1n inmediatamente, en sistemas de archivo que lo soporten.", - "ButtonScanLibrary": "Escanear Librer\u00eda", - "HeaderNumberOfPlayers": "Jugadores:", - "OptionAnyNumberOfPlayers": "Cualquiera", - "Option1Player": "1+", - "Option2Player": "2+", - "Option3Player": "3+", - "Option4Player": "4+", - "HeaderMediaFolders": "Carpetas de medios", - "HeaderThemeVideos": "V\u00eddeos de tema", - "HeaderThemeSongs": "Canciones de tema", - "HeaderScenes": "Escenas", - "HeaderAwardsAndReviews": "Premios y reconocimientos", - "HeaderSoundtracks": "Pistas de audio", - "HeaderMusicVideos": "V\u00eddeos musicales", - "HeaderSpecialFeatures": "Caracter\u00edsticas especiales", - "HeaderCastCrew": "Reparto y equipo t\u00e9cnico", - "HeaderAdditionalParts": "Partes adicionales", - "ButtonSplitVersionsApart": "Dividir versiones aparte", - "ButtonPlayTrailer": "Trailer", - "LabelMissing": "Falta", - "LabelOffline": "Apagado", - "PathSubstitutionHelp": "Las rutas alternativas se utilizan para mapear una ruta en el servidor a la que los clientes puedan acceder. El permitir que los clientes se conecten directamente a trav\u00e9s de la red y puedan reproducir los medios directamente, evita utilizar recursos del servidor para la transcodificaci\u00f3n y el stream,", - "HeaderFrom": "Desde", - "HeaderTo": "Hasta", - "LabelFrom": "Desde:", - "LabelFromHelp": "Ejemplo: D:\\Pel\u00edculas (en el servidor)", - "LabelTo": "Hasta:", - "LabelToHelp": "Ejemplo: \\\\MiServidor\\Pel\u00edculas (ruta a la que puedan acceder los clientes)", - "ButtonAddPathSubstitution": "A\u00f1adir ruta alternativa", - "OptionSpecialEpisode": "Especiales", - "OptionMissingEpisode": "Episodios que faltan", - "OptionUnairedEpisode": "Episodios no emitidos", - "OptionEpisodeSortName": "Nombre corto del episodio", - "OptionSeriesSortName": "Nombre de la serie", - "OptionTvdbRating": "Valoraci\u00f3n tvdb", - "HeaderTranscodingQualityPreference": "Preferencia de calidad de transcodificaci\u00f3n:", - "OptionAutomaticTranscodingHelp": "El servidor decidir\u00e1 la calidad y la velocidad", - "OptionHighSpeedTranscodingHelp": "Calidad menor, pero codificaci\u00f3n r\u00e1pida", - "OptionHighQualityTranscodingHelp": "C\u00e1lidad mayor, pero codificaci\u00f3n lenta", - "OptionMaxQualityTranscodingHelp": "La mayor calidad posible con codificaci\u00f3n lenta y alto uso de CPU", - "OptionHighSpeedTranscoding": "Mayor velocidad", - "OptionHighQualityTranscoding": "Mayor calidad", - "OptionMaxQualityTranscoding": "M\u00e1xima calidad", - "OptionEnableDebugTranscodingLogging": "Activar el registro de depuraci\u00f3n del transcodificador", - "OptionEnableDebugTranscodingLoggingHelp": "Esto crear\u00e1 archivos de registro muy grandes y s\u00f3lo se recomienda cuando sea necesario para solucionar problemas.", - "OptionUpscaling": "Permitir que los clientes soliciten v\u00eddeo upscaled", - "OptionUpscalingHelp": "En algunos casos esto se traducir\u00e1 en una mejora de la calidad del v\u00eddeo, pero aumentar\u00e1 el uso de CPU.", - "EditCollectionItemsHelp": "Agregar o quitar pel\u00edculas, series, discos, libros o juegos que desee agrupar dentro de esta colecci\u00f3n.", - "HeaderAddTitles": "A\u00f1adir T\u00edtulos", - "LabelEnableDlnaPlayTo": "Actvar la reproducci\u00f3n en DLNAi", - "LabelEnableDlnaPlayToHelp": "Media Browser puede detectar dispositivos en su red y ofrecer la posibilidad de controlarlos remotamente.", - "LabelEnableDlnaDebugLogging": "Activar el registro de depuraci\u00f3n de DLNA", - "LabelEnableDlnaDebugLoggingHelp": "Esto crear\u00e1 archivos de registro de gran tama\u00f1o y s\u00f3lo debe ser utilizado cuando sea necesario para solucionar problemas.", - "LabelEnableDlnaClientDiscoveryInterval": "Intervalo de detecci\u00f3n de cliente (segundos)", - "LabelEnableDlnaClientDiscoveryIntervalHelp": "Determina la duraci\u00f3n en segundos del intervalo entre las b\u00fasquedas SSDP realizadas por Media Browser.", - "HeaderCustomDlnaProfiles": "Perfiles personalizados", - "HeaderSystemDlnaProfiles": "Perfiles del sistema", - "CustomDlnaProfilesHelp": "Crear un perfil personalizado para un nuevo dispositivo o reemplazar un perfil del sistema.", - "SystemDlnaProfilesHelp": "Los perfiles del sistema son de s\u00f3lo lectura. Para anular un perfil del sistema, crear un perfil personalizado del mismo dispositivo.", - "TitleDashboard": "Panel de control", - "TabHome": "Inicio", - "TabInfo": "Info", - "HeaderLinks": "Enlaces", - "HeaderSystemPaths": "Rutas del sistema", - "LinkCommunity": "Comunidad", - "LinkGithub": "Github", - "LinkApiDocumentation": "Documentaci\u00f3n API", - "LabelFriendlyServerName": "Nombre informal del servidor:", - "LabelFriendlyServerNameHelp": "Este nombre se podr\u00e1 utilizar para identificar este servidor. Si se deja en blanco se usar\u00e1 el nombre del ordenador.", - "LabelPreferredDisplayLanguage": "Idioma de pantalla preferido", - "LabelPreferredDisplayLanguageHelp": "La traducci\u00f3n de Media Browser es un proyecto en curso y a\u00fan no est\u00e1 completado.", - "LabelReadHowYouCanContribute": "Lea acerca de c\u00f3mo usted puede contribuir.", - "HeaderNewCollection": "Nueva colecci\u00f3n", - "HeaderAddToCollection": "A\u00f1adir a la colecci\u00f3n", - "ButtonSubmit": "Enviar", - "NewCollectionNameExample": "Ejemplo: Star Wars Colecci\u00f3n", - "OptionSearchForInternetMetadata": "Buscar en internet ilustraciones y metadatos", - "ButtonCreate": "Crear", - "LabelHttpServerPortNumber": "Puerto Http del servidor:", - "LabelWebSocketPortNumber": "N\u00famero de puerto WebSocket:", - "LabelEnableAutomaticPortHelp": "UPnP permite automatizar la configuraci\u00f3n del router para el acceso remoto. Esto puede no funcionar en algunos modelos de router.", - "LabelExternalDDNS": "DDNS externa:", - "LabelExternalDDNSHelp": "Si dispone de DNS din\u00e1mica, escr\u00edbala aqu\u00ed. Media Brower la utilizar\u00e1 para las conexiones remotas.", - "TabResume": "Continuar", - "TabWeather": "El tiempo", - "TitleAppSettings": "Opciones de la App", - "LabelMinResumePercentage": "Porcentaje m\u00ednimo para reanudaci\u00f3n:", - "LabelMaxResumePercentage": "Porcentaje m\u00e1ximo para reanudaci\u00f3n::", - "LabelMinResumeDuration": "Duraci\u00f3n m\u00ednima de reanudaci\u00f3n (segundos):", - "LabelMinResumePercentageHelp": "Los t\u00edtulos se asumir\u00e1n como no reproducidos si se paran antes de este momento", - "LabelMaxResumePercentageHelp": "Los t\u00edtulos se asumir\u00e1n como reproducidos si se paran despu\u00e9s de este momento", - "LabelMinResumeDurationHelp": "Los t\u00edtulos m\u00e1s cortos de esto no ser\u00e1n reanudables", - "TitleAutoOrganize": "Organizaci\u00f3n autom\u00e1tica", - "TabActivityLog": "Log de actividad", - "HeaderName": "Nombre", - "HeaderDate": "Fecha", - "HeaderSource": "Origen", - "HeaderDestination": "Destino", - "HeaderProgram": "Programa", - "HeaderClients": "Clientes", - "LabelCompleted": "Completado", - "LabelFailed": "Error", - "LabelSkipped": "Omitido", - "HeaderEpisodeOrganization": "Organizaci\u00f3n de episodios", - "LabelSeries": "Series:", - "LabelSeasonNumber": "Temporada n\u00famero:", - "LabelEpisodeNumber": "Episodio n\u00famero:", - "LabelEndingEpisodeNumber": "N\u00famero episodio final:", - "LabelEndingEpisodeNumberHelp": "S\u00f3lo requerido para archivos multi-episodio", - "HeaderSupportTheTeam": "Apoye al Equipo de Media Browser", - "LabelSupportAmount": "Importe (USD)", - "HeaderSupportTheTeamHelp": "Ayude a garantizar el desarrollo continuo de este proyecto mediante una donaci\u00f3n. Una parte de todas las donaciones ir\u00e1n a parar a otras herramientas gratuitas de las que dependemos.", - "ButtonEnterSupporterKey": "Entre la Key de Seguidor", - "DonationNextStep": "Cuando haya terminado, vuelva y entre su key de seguidor que recibir\u00e1 por email.", - "AutoOrganizeHelp": "Organizaci\u00f3n autom\u00e1tica monitoriza sus carpetas de descarga en busca de nuevos archivos y los mueve a sus directorios de medios.", - "AutoOrganizeTvHelp": "La organizaci\u00f3n de archivos de TV s\u00f3lo a\u00f1adir\u00e1 episodios a series existentes. No crear\u00e1 carpetas para series nuevas.", - "OptionEnableEpisodeOrganization": "Activar la organizaci\u00f3n de nuevos episodios", - "LabelWatchFolder": "Ver carpeta:", - "LabelWatchFolderHelp": "El servidor sondear\u00e1 esta carpeta durante la tarea programada \"Organizar nuevos archivos de medios\".", - "ButtonViewScheduledTasks": "Ver tareas programadas", - "LabelMinFileSizeForOrganize": "Tama\u00f1o m\u00ednimo de archivo (MB):", - "LabelMinFileSizeForOrganizeHelp": "Los archivos menores de este tama\u00f1po se ignorar\u00e1n.", - "LabelSeasonFolderPattern": "Patr\u00f3n de la carpeta para temporadas:", - "LabelSeasonZeroFolderName": "Nombre de la carpeta para la temporada cero:", - "HeaderEpisodeFilePattern": "Patr\u00f3n para archivos de episodio", - "LabelEpisodePattern": "Patr\u00f3n de episodio:", - "LabelMultiEpisodePattern": "Patr\u00f3n para multi-episodio:", - "HeaderSupportedPatterns": "Patrones soportados", - "HeaderTerm": "Plazo", - "HeaderPattern": "Patr\u00f3n", - "HeaderResult": "Resultado", - "LabelDeleteEmptyFolders": "Borrar carpetas vacias despu\u00e9s de la organizaci\u00f3n", - "LabelDeleteEmptyFoldersHelp": "Activar para mantener el directorio de descargas limpio.", - "LabelDeleteLeftOverFiles": "Eliminar los archivos sobrantes con las siguientes extensiones:", - "LabelDeleteLeftOverFilesHelp": "Separar con ;. Por ejemplo: .nfo;.txt", - "OptionOverwriteExistingEpisodes": "Sobreescribir episodios ya existentes", - "LabelTransferMethod": "M\u00e9todo de transferencia", - "OptionCopy": "Copiar", - "OptionMove": "Mover", - "LabelTransferMethodHelp": "Copiar o mover archivos desde la carpeta de inspecci\u00f3n", - "HeaderLatestNews": "Ultimas noticias", - "HeaderHelpImproveMediaBrowser": "Ayuda a mejorar Media Browser", - "HeaderRunningTasks": "Tareas en ejecuci\u00f3n", - "HeaderActiveDevices": "Dispositivos activos", - "HeaderPendingInstallations": "Instalaciones pendientes", - "HeaerServerInformation": "Informaci\u00f3n del servidor", - "ButtonRestartNow": "Reiniciar ahora", - "ButtonRestart": "Reiniciar", - "ButtonShutdown": "Apagar", - "ButtonUpdateNow": "Actualizar ahora", - "PleaseUpdateManually": "Por favor cierre el servidor y actualice manualmente.", - "NewServerVersionAvailable": "\u00a1Hay disponible una nueva versi\u00f3n de Media Browser Server!", - "ServerUpToDate": "Media Browser Server est\u00e1 actualizado", - "ErrorConnectingToMediaBrowserRepository": "Hubo un error al conectarse remotamente al repositorio de Media Browser,", - "LabelComponentsUpdated": "Los componentes siguientes se han instalado o actualizado:", - "MessagePleaseRestartServerToFinishUpdating": "Reinicie el servidor para acabar de aplicar las actualizaciones.", - "LabelDownMixAudioScale": "Escala de reducci\u00f3n de potencia de audio:", - "LabelDownMixAudioScaleHelp": "Potenciador de audio. Establecer a 1 para preservar el volumen original.", - "ButtonLinkKeys": "Enlazar claves", - "LabelOldSupporterKey": "Antigua clave de seguidor", - "LabelNewSupporterKey": "Nueva clave de seguidor", - "HeaderMultipleKeyLinking": "Vinculaci\u00f3n de m\u00faltiples claves", - "MultipleKeyLinkingHelp": "Si usted tiene m\u00e1s de una clave de seguidor, utilice este formulario para vincular los registros de la antigua clave con la nueva.", - "LabelCurrentEmailAddress": "Cuenta de correo actual", - "LabelCurrentEmailAddressHelp": "La direcci\u00f3n de correo electr\u00f3nico actual a la que se envi\u00f3 la nueva clave.", - "HeaderForgotKey": "Perd\u00ed mi clave", - "LabelEmailAddress": "Direcci\u00f3n de correo", - "LabelSupporterEmailAddress": "La direcci\u00f3n de correo que utliz\u00f3 para comprar la clave.", - "ButtonRetrieveKey": "Recuperar clave", - "LabelSupporterKey": "Clave de seguidor (pegar desde el correo)", - "LabelSupporterKeyHelp": "Entre su clave de seguidor para empezar a disfrutar de los beneficios adicionales que la comunidad ha creado para Media Browser.", - "MessageInvalidKey": "La clave MB3 falta o es inv\u00e1lida", - "ErrorMessageInvalidKey": "Para acceder al contenido premium debe registrarse, tambi\u00e9n debe ser un MB3 Seguidor. Por favor, done y apoye el desarrollo continuado del producto principal. Gracias.", - "HeaderDisplaySettings": "Opciones de pantalla", - "TabPlayTo": "Reproducir en", - "LabelEnableDlnaServer": "Habilitar servidor Dlna", - "LabelEnableDlnaServerHelp": "Permite que los dispositivos UPnp de su red puedan navegar y repoducir contenidos de Media Browser.", - "LabelEnableBlastAliveMessages": "Explotar mensajes en vivo", - "LabelEnableBlastAliveMessagesHelp": "Active aqu\u00ed si el servidor no es detectado correctamente por otros dispositivos UPnP en su red.", - "LabelBlastMessageInterval": "Intervalo para mensajes en vivo (segundos)", - "LabelBlastMessageIntervalHelp": "Determina la duraci\u00f3n en segundos entre los mensajes en vivo del servidor .", - "LabelDefaultUser": "Usuario por defecto:", - "LabelDefaultUserHelp": "Determina de q\u00fae usuario se utilizar\u00e1 su biblioteca de medios para mostrarla por defecto en los dipositivos conectados. Esto puede cambiarse para cada dispositivo mediante el uso de perfiles.", - "TitleDlna": "DLNA", - "TitleChannels": "Canales", - "HeaderServerSettings": "Ajustes del Servidor", - "LabelWeatherDisplayLocation": "Lugar del que mostar el tiempo:", - "LabelWeatherDisplayLocationHelp": "C\u00f3digo postal USA \/ Ciudad, Estado, Pa\u00eds \/ Ciudad, Pa\u00eds", - "LabelWeatherDisplayUnit": "Unidad de media para la temperatura:", - "OptionCelsius": "Celsius", - "OptionFahrenheit": "Fahrenheit", - "HeaderRequireManualLogin": "Requerir entrada de usuario manual para:", - "HeaderRequireManualLoginHelp": "Cuando est\u00e1 desactivado los clientes saldr\u00e1n en la pantalla de inicio para seleccionarlos visualmente.", - "OptionOtherApps": "Otras aplicaciones", - "OptionMobileApps": "Aplicaciones m\u00f3viles", - "HeaderNotificationList": "Haga click en una notificaci\u00f3n para configurar sus opciones de env\u00edo.", - "NotificationOptionApplicationUpdateAvailable": "Disponible actualizaci\u00f3n de la aplicaci\u00f3n", - "NotificationOptionApplicationUpdateInstalled": "Se ha instalado la actualizaci\u00f3n de la aplicaci\u00f3n", - "NotificationOptionPluginUpdateInstalled": "Se ha instalado la actualizaci\u00f3n del plugin", - "NotificationOptionPluginInstalled": "Plugin instalado", - "NotificationOptionPluginUninstalled": "Plugin desinstalado", - "NotificationOptionVideoPlayback": "Reproducci\u00f3n de video", - "NotificationOptionAudioPlayback": "Reproducci\u00f3n de audio", - "NotificationOptionGamePlayback": "Iniciar juegos", - "NotificationOptionVideoPlaybackStopped": "Reproducci\u00f3n de video detenida", - "NotificationOptionAudioPlaybackStopped": "Reproducci\u00f3n de audio detenida", - "NotificationOptionGamePlaybackStopped": "Reproducci\u00f3n de juego detenida", - "NotificationOptionTaskFailed": "La tarea programada ha fallado", - "NotificationOptionInstallationFailed": "Fallo en la instalaci\u00f3n", - "NotificationOptionNewLibraryContent": "Nuevo contenido a\u00f1adido", - "NotificationOptionNewLibraryContentMultiple": "Nuevo contenido a\u00f1adido (multiple)", - "SendNotificationHelp": "Por defecto, las notificaciones aparecer\u00e1n en el panel de control. Compruebe el cat\u00e1logo de plugins para instalar opciones adicionales para las notificaciones.", - "NotificationOptionServerRestartRequired": "Se requiere el reinicio del servidor", - "LabelNotificationEnabled": "Activar esta notificaci\u00f3n", - "LabelMonitorUsers": "Supervisar la actividad de:", - "LabelSendNotificationToUsers": "Enviar la notificaci\u00f3n a:", - "UsersNotNotifiedAboutSelfActivity": "Los usuarios no ser\u00e1n notificados acerca de sus propias actividades.", - "LabelUseNotificationServices": "Usar los siguientes servicios:", - "CategoryUser": "Usuario", - "CategorySystem": "Sistema", - "CategoryApplication": "Aplicaci\u00f3n", - "CategoryPlugin": "Plugin", - "LabelMessageTitle": "T\u00edtulo del mensaje:", - "LabelAvailableTokens": "Tokens disponibles:", - "AdditionalNotificationServices": "Visite el cat\u00e1logo de plugins para instalar servicios de notificaci\u00f3n adicionales.", - "OptionAllUsers": "Todos los usuarios", - "OptionAdminUsers": "Administradores", - "OptionCustomUsers": "A medida", - "ButtonArrowUp": "Arriba", - "ButtonArrowDown": "Abajo", - "ButtonArrowLeft": "Izquierda", - "ButtonArrowRight": "Derecha", - "ButtonBack": "Atr\u00e1s", - "ButtonInfo": "Info", - "ButtonOsd": "Visualizaci\u00f3n en pantalla", - "ButtonPageUp": "P\u00e1gina arriba", - "ButtonPageDown": "P\u00e1gina abajo", - "PageAbbreviation": "PG", - "ButtonHome": "Inicio", - "ButtonSettings": "Opciones", - "ButtonTakeScreenshot": "Captura de pantalla", - "ButtonLetterUp": "Letter arriba", - "ButtonLetterDown": "Letter abajo", - "PageButtonAbbreviation": "PG", - "LetterButtonAbbreviation": "A", - "TabNowPlaying": "Reproduciendo ahora", - "TabNavigation": "Navegaci\u00f3n", - "TabControls": "Controles", - "ButtonFullscreen": "Pantalla completa", - "ButtonScenes": "Escenas", - "ButtonSubtitles": "Subt\u00edtulos", - "ButtonAudioTracks": "Pistas de audio", - "ButtonPreviousTrack": "Pista anterior", - "ButtonNextTrack": "Pista siguiente", - "ButtonStop": "Detener", - "ButtonPause": "Pausa", - "LabelGroupMoviesIntoCollections": "Agrupar pel\u00edculas en colecciones", - "LabelGroupMoviesIntoCollectionsHelp": "Cuando se muestran las listas de pel\u00edculas, las pel\u00edculas pertenecientes a una colecci\u00f3n se mostrar\u00e1n como un elemento agrupado.", - "NotificationOptionPluginError": "Error en plugin", - "ButtonVolumeUp": "Subir volumen", - "ButtonVolumeDown": "Bajar volumen", - "ButtonMute": "Silencio", - "HeaderLatestMedia": "\u00daltimos medios", - "OptionSpecialFeatures": "Caracter\u00edsticas especiales", - "HeaderCollections": "Colecciones", - "LabelProfileCodecsHelp": "Separados por comas. Esto se puede dejar vac\u00edo para aplicar a todos los codecs.", - "LabelProfileContainersHelp": "Separados por comas. Esto se puede dejar vac\u00edo para aplicar a todos los contenedores.", - "HeaderResponseProfile": "Perfil de respuesta", - "LabelType": "Tipo:", - "LabelProfileContainer": "Contenedor:", - "LabelProfileVideoCodecs": "Codecs de video:", - "LabelProfileAudioCodecs": "Codecs de audio:", - "LabelProfileCodecs": "Codecs:", - "HeaderDirectPlayProfile": "Perfil de reproducci\u00f3n directa", - "HeaderTranscodingProfile": "Perfil de transcodificaci\u00f3n", - "HeaderCodecProfile": "Perfil de codec", - "HeaderCodecProfileHelp": "Perfiles de codec indican las limitaciones de un dispositivo cuando se reproducen codecs espec\u00edficos. Si se aplica una limitaci\u00f3n entonces el medio se transcodificar\u00e1, incluso si el codec est\u00e1 configurado para reproducci\u00f3n directa.", - "HeaderContainerProfile": "Perfil de contenedor", - "HeaderContainerProfileHelp": "Perfiles de codec indican las limitaciones de un dispositivo mientras reproduce formatos espec\u00edficos. If se aplica una limitaci\u00f3n entonces el medio se transcodificar\u00e1, incluso si el formato est\u00e1 configurado para reproducci\u00f3n directa.", - "OptionProfileVideo": "Video", - "OptionProfileAudio": "Audio", - "OptionProfileVideoAudio": "Video audio", - "OptionProfilePhoto": "Foto", - "LabelUserLibrary": "Librer\u00eda de usuario:", - "LabelUserLibraryHelp": "Seleccione de qu\u00e9 usuario se utilizar\u00e1 la librer\u00eda en el dispositivo. D\u00e9jelo vac\u00edo para utilizar la configuraci\u00f3n por defecto.", - "OptionPlainStorageFolders": "Ver todas las carpetas como carpetas de almacenamiento sin formato.", - "OptionPlainStorageFoldersHelp": "Si est\u00e1 activado, todas las carpetas se representan en DIDL como \"object.container.storageFolder\" en lugar de un tipo m\u00e1s espec\u00edfico, como por ejemplo \"object.container.person.musicArtist\".", - "OptionPlainVideoItems": "Mostrar todos los videos como elementos de video sin formato", - "OptionPlainVideoItemsHelp": "Si est\u00e1 habilitado, todos los v\u00eddeos est\u00e1n representados en DIDL como \"object.item.videoItem\" en lugar de un tipo m\u00e1s espec\u00edfico, como por ejemplo \"object.item.videoItem.movie\".", - "LabelSupportedMediaTypes": "Tipos de medio soportados:", - "TabIdentification": "Identificaci\u00f3n", - "TabDirectPlay": "Reproducci\u00f3n directa", - "TabContainers": "Contenedores", - "TabCodecs": "Codecs", - "TabResponses": "Respuestas", - "HeaderProfileInformation": "Informaci\u00f3n del perfil", - "LabelEmbedAlbumArtDidl": "Incorporar la car\u00e1tula del \u00e1lbum en didl", - "LabelEmbedAlbumArtDidlHelp": "Algunos dispositivos prefieren este m\u00e9todo para obtener la car\u00e1tula del \u00e1lbum. Otros pueden fallar al reproducir con esta opci\u00f3n habilitada.", - "LabelAlbumArtPN": "Car\u00e1tula del album PN:", - "LabelAlbumArtHelp": "PN utilizado para la car\u00e1tula del \u00e1lbum, dentro del atributo dlna:profileID en upnp:albumArtURI. Algunos clientes requieren un valor espec\u00edfico, independientemente del tama\u00f1o de la imagen.", - "LabelAlbumArtMaxWidth": "Anchura m\u00e1xima de la car\u00e1tula del album:", - "LabelAlbumArtMaxWidthHelp": "Resoluci\u00f3n m\u00e1xima de la car\u00e1tula del \u00e1lbum expuesta a trav\u00e9s de upnp:albumArtURI.", - "LabelAlbumArtMaxHeight": "Altura m\u00e1xima de la car\u00e1tula del album:", - "LabelAlbumArtMaxHeightHelp": "Resoluci\u00f3n m\u00e1xima de la car\u00e1tula del \u00e1lbum expuesta a trav\u00e9s de upnp:albumArtURI.", - "LabelIconMaxWidth": "Anchura m\u00e1xima de icono:", - "LabelIconMaxWidthHelp": "Resoluci\u00f3n m\u00e1xima de los iconos expuestos via upnp:icon.", - "LabelIconMaxHeight": "Altura m\u00e1xima de icono:", - "LabelIconMaxHeightHelp": "Resoluci\u00f3n m\u00e1xima de los iconos expuestos via upnp:icon.", - "LabelIdentificationFieldHelp": "Una subcadena insensible a may\u00fasculas o min\u00fasculas o una expresi\u00f3n regex.", - "HeaderProfileServerSettingsHelp": "Estos valores controlan el modo en que Media Browser se presentar\u00e1 en el dispositivo.", - "LabelMaxBitrate": "Bitrate m\u00e1ximo:", - "LabelMaxBitrateHelp": "Especificar una tasa de bits m\u00e1xima en entornos de ancho de banda limitado, o si el dispositivo impone su propio l\u00edmite.", - "OptionIgnoreTranscodeByteRangeRequests": "Ignorar las solicitudes de intervalo de bytes de transcodificaci\u00f3n", - "OptionIgnoreTranscodeByteRangeRequestsHelp": "Si est\u00e1 activado, estas solicitudes ser\u00e1n atendidas pero ignorar\u00e1n el encabezado de intervalo de bytes.", - "LabelFriendlyName": "Nombre amigable", - "LabelManufacturer": "Fabricante", - "LabelManufacturerUrl": "Url del fabricante", - "LabelModelName": "Nombre de modelo", - "LabelModelNumber": "N\u00famero de modelo", - "LabelModelDescription": "Descripci\u00f3n de modelo", - "LabelModelUrl": "Url del modelo", - "LabelSerialNumber": "N\u00famero de serie", - "LabelDeviceDescription": "Descripci\u00f3n del dispositivo", - "HeaderIdentificationCriteriaHelp": "Entre al menos un criterio de identificaci\u00f3n.", - "HeaderDirectPlayProfileHelp": "A\u00f1adir perfiles de reproducci\u00f3n directa para indicar qu\u00e9 formatos puede utilizar el dispositivo de forma nativa.", - "HeaderTranscodingProfileHelp": "A\u00f1adir perfiles de transcodificaci\u00f3n para indicar qu\u00e9 formatos se deben utilizar cuando se requiera transcodificaci\u00f3n.", - "HeaderResponseProfileHelp": "Perfiles de respuesta proporcionan una forma de personalizar la informaci\u00f3n que se env\u00eda al dispositivo cuando se reproducen ciertos tipos de medios.", - "LabelXDlnaCap": "X-Dlna cap:", - "LabelXDlnaCapHelp": "Determina el contenido del elemento X_DLNACAP en el espacio de nombre urn:schemas-dlna-org:device-1-0.", - "LabelXDlnaDoc": "X-Dlna doc:", - "LabelXDlnaDocHelp": "Determina el contenido del elemento X_DLNADOC en el espacio de nombreurn:schemas-dlna-org:device-1-0.", - "LabelSonyAggregationFlags": "Agregaci\u00f3n de banderas Sony:", - "LabelSonyAggregationFlagsHelp": "Determina el contenido del elemento aggregationFlags en el espacio de nombre urn:schemas-sonycom:av.", - "LabelTranscodingContainer": "Contenedor:", - "LabelTranscodingVideoCodec": "Codec de video:", - "LabelTranscodingVideoProfile": "Perfil de video:", - "LabelTranscodingAudioCodec": "Codec de audio:", - "OptionEnableM2tsMode": "Activar modo M2ts", - "OptionEnableM2tsModeHelp": "Activar modo m2ts cuando se codifique a mpegts", - "OptionEstimateContentLength": "Estimar longitud del contenido al transcodificar", - "OptionReportByteRangeSeekingWhenTranscoding": "Indicar que el servidor soporta la b\u00fasqueda de byte al transcodificar", - "OptionReportByteRangeSeekingWhenTranscodingHelp": "Esto es necesario para algunos dispositivos que no buscan el tiempo muy bien.", - "HeaderSubtitleDownloadingHelp": "Cuando Media Browser escanea los archivos de v\u00eddeo, puede buscar subt\u00edtulos faltantes y descargarlos usando un proveedor de subt\u00edtulos como OpenSubtitles.org.", - "HeaderDownloadSubtitlesFor": "Descarga subt\u00edtulos para:", - "MessageNoChapterProviders": "Instalar un plugin proveedor de cap\u00edtulos como ChapterDb o tagChimp para permitir opciones de cap\u00edtulo adicionales.", - "LabelSkipIfGraphicalSubsPresent": "Omitir si el video ya contiene subt\u00edtulos gr\u00e1ficos", - "LabelSkipIfGraphicalSubsPresentHelp": "Mantener versiones de texto de los subt\u00edtulos se traducir\u00e1 en una prestaci\u00f3n m\u00e1s eficiente para los clientes m\u00f3viles.", - "TabSubtitles": "Subt\u00edtulos", - "TabChapters": "Cap\u00edtulos", - "HeaderDownloadChaptersFor": "Descarga nombres de los cap\u00edtulos de:", - "LabelOpenSubtitlesUsername": "Usuario de Open Subtitles:", - "LabelOpenSubtitlesPassword": "Contrase\u00f1a de Open Subtitles:", - "HeaderChapterDownloadingHelp": "Cuando Media Browser escanea los archivos de v\u00eddeo, puede descargar nombres de los cap\u00edtulos desde la red utilizando plugins de cap\u00edtulos como ChapterDb y tagChimp.", - "LabelPlayDefaultAudioTrack": "\nReproducir pista de audio predeterminado, independientemente del idioma", - "LabelSubtitlePlaybackMode": "Modo de Subt\u00edtulo:", - "LabelDownloadLanguages": "Idiomas de descarga:", - "ButtonRegister": "Registrar", - "LabelSkipIfAudioTrackPresent": "Omitir si la pista de audio por defecto coincide con el idioma de descarga", - "LabelSkipIfAudioTrackPresentHelp": "Desactive esta opci\u00f3n para asegurar que todos los v\u00eddeos tienen subt\u00edtulos, sin importar el idioma de audio.", - "HeaderSendMessage": "Enviar mensaje", - "ButtonSend": "Enviar", - "LabelMessageText": "Mensaje de texto:", - "MessageNoAvailablePlugins": "No hay plugins disponibles.", - "LabelDisplayPluginsFor": "Mostrar plugins para:", - "PluginTabMediaBrowserClassic": "MB Classic", - "PluginTabMediaBrowserTheater": "MB Theater", - "TabOtherPlugins": "Otros", - "LabelEpisodeName": "Nombre episodio", - "LabelSeriesName": "Nombre de la serie", - "ValueSeriesNamePeriod": "Series.name", - "ValueSeriesNameUnderscore": "Series_name", - "ValueEpisodeNamePeriod": "Episode.name", - "ValueEpisodeNameUnderscore": "Episode_name", - "HeaderTypeText": "Entrar texto", - "LabelTypeText": "Texto", - "HeaderSearchForSubtitles": "B\u00fasqueda de Subt\u00edtulos", - "MessageNoSubtitleSearchResultsFound": "No se han encontrado resultados en la b\u00fasqueda.", - "TabDisplay": "Pantalla", - "TabLanguages": "Idiomas", - "TabWebClient": "Cliente web", - "LabelEnableThemeSongs": "Habilitar temas musicales", - "LabelEnableBackdrops": "Habilitar im\u00e1genes de fondo", - "LabelEnableThemeSongsHelp": "Si est\u00e1 habilitado, se reproducir\u00e1n temas musicales de fondo mientras navega por la biblioteca.", - "LabelEnableBackdropsHelp": "Si est\u00e1 habilitado, se mostrar\u00e1n im\u00e1genes de fondo en algunas p\u00e1ginas mientras navega por la biblioteca.", - "HeaderHomePage": "P\u00e1gina de inicio", - "HeaderSettingsForThisDevice": "Opciones para este dispositivo", - "OptionAuto": "Auto", - "OptionYes": "Si", - "OptionNo": "No", - "LabelHomePageSection1": "Secci\u00f3n uno de la p\u00e1gina de inicio:", - "LabelHomePageSection2": "Secci\u00f3n dos de la p\u00e1gina de inicio:", - "LabelHomePageSection3": "Secci\u00f3n tres de la p\u00e1gina de inicio:", - "LabelHomePageSection4": "Secci\u00f3n cuarta de la p\u00e1gina de inicio", - "OptionMyViewsButtons": "Mis vistas (botones)", - "OptionMyViews": "Mis vistas", - "OptionMyViewsSmall": "Mis vistas (peque\u00f1o)", - "OptionResumablemedia": "Continuar", - "OptionLatestMedia": "\u00daltimos medios", - "OptionLatestChannelMedia": "Ultimos elementos de canales", - "HeaderLatestChannelItems": "Ultimos elementos de canales", - "OptionNone": "Nada", - "HeaderLiveTv": "TV en vivo", - "HeaderReports": "Informes", - "HeaderMetadataManager": "Metadata Manager", - "HeaderPreferences": "Preferencias", - "MessageLoadingChannels": "Cargando contenidos del canal...", - "ButtonMarkRead": "Marcar como le\u00eddo", - "OptionDefaultSort": "Por defecto", - "OptionCommunityMostWatchedSort": "M\u00e1s visto", - "TabNextUp": "Siguiendo", - "MessageNoMovieSuggestionsAvailable": "No hay sugerencias de pel\u00edculas disponibles. Comience ver y calificar sus pel\u00edculas y vuelva para ver las recomendaciones.", - "MessageNoCollectionsAvailable": "Colecciones le permitir\u00e1 disfrutar de grupos personalizados de Pel\u00edculas, Series, Discos, Libros y Juegos. Haga click en el bot\u00f3n nuevo para empezar a crear Colecciones.", - "HeaderWelcomeToMediaBrowserWebClient": "Vienvenido al Cliente Web de Media Browser", - "ButtonDismiss": "Descartar", - "MessageLearnHowToCustomize": "Aprenda c\u00f3mo personalizar esta p\u00e1gina a sus propios gustos personales. Haga clic en su icono de usuario en la esquina superior derecha de la pantalla para ver y actualizar sus preferencias.", - "ButtonEditOtherUserPreferences": "Editar preferencias personales de este usuario.", - "LabelChannelStreamQuality": "Calidad preferida para la transmisi\u00f3n por Internet:", - "LabelChannelStreamQualityHelp": "En un entorno de bajo ancho de banda, limitar la calidad puede ayudar a asegurar una experiencia de streaming suave.", - "OptionBestAvailableStreamQuality": "Mejor disponible", - "LabelEnableChannelContentDownloadingFor": "Habilitar descargas de contenido para el canal:", - "LabelEnableChannelContentDownloadingForHelp": "Algunos canales soportan descargar contenido antes de ver. Habilite esta en ambientes de poco ancho de banda para descargar el contenido del canal durante las horas libres. El contenido se descarga como parte de la tarea programada de descargas de canal.", - "LabelChannelDownloadPath": "Ruta para descargas de contenidos de canales:", - "LabelChannelDownloadPathHelp": "Especifique una ruta personalizada si lo desea. D\u00e9jelo en blanco para utilizar un carpeta interna del programa.", - "LabelChannelDownloadAge": "Borrar contenido despues de: (d\u00edas)", - "LabelChannelDownloadAgeHelp": "Todo contenido descargado anterior se borrar\u00e1. Continuar\u00e1 estando disponible v\u00eda streaming de internet.", - "ChannelSettingsFormHelp": "Instale canales como Trailers y Vimeo desde el cat\u00e1logo de plugins.", - "LabelSelectCollection": "Seleccionar colecci\u00f3n:", - "ViewTypeMovies": "Pel\u00edculas", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Juegos", - "ViewTypeMusic": "M\u00fasica", - "ViewTypeBoxSets": "Colecciones", - "ViewTypeChannels": "Canales", - "ViewTypeLiveTV": "Tv en vivo", - "HeaderOtherDisplaySettings": "Configuraci\u00f3n de pantalla", - "HeaderMyViews": "Mis vistas", - "LabelSelectFolderGroups": "Agrupar autom\u00e1ticamente las siguientes carpetas en vistas tales como pel\u00edculas, m\u00fasica y televisi\u00f3n", - "LabelSelectFolderGroupsHelp": "Las carpetas que no est\u00e9n marcadas se mostrar\u00e1n por s\u00ed mismas en su propia secci\u00f3n.", - "OptionDisplayAdultContent": "Mostrar contenido para adultos", - "OptionLibraryFolders": "Vista de carpeta", - "TitleRemoteControl": "Control remoto", - "OptionLatestTvRecordings": "\u00daltimas grabaciones", - "LabelProtocolInfo": "Informaci\u00f3n de protocolo:", - "LabelProtocolInfoHelp": "El valor que se utilizar\u00e1 cuando se responde a una solicitud GetProtocolInfo desde el dispositivo.", - "TabXbmcMetadata": "Xbmc", - "HeaderXbmcMetadataHelp": "Media Browser incluye soporte nativo para XBMC, Nfo, metadatos e im\u00e1genes. Para activar o desactivar los metadatos XBMC, utilice la ficha Avanzadas para configurar opciones para sus tipos de medios.", - "LabelXbmcMetadataUser": "A\u00f1adir datos de reproducciones de usuario a los nfo\u00b4s para:", - "LabelXbmcMetadataUserHelp": "Activar esto para mantener sincronizados los datos de reproducci\u00f3n entre Media Browser y Xbmc.", - "LabelXbmcMetadataDateFormat": "Formato de fecha de estreno:", - "LabelXbmcMetadataDateFormatHelp": "Todas las fechas dentro de los nfo se leer\u00e1n y se escribir\u00e1n usando este formato.", - "LabelXbmcMetadataSaveImagePaths": "Grabar las rutas de las im\u00e1genes en los archivos nfo", - "LabelXbmcMetadataSaveImagePathsHelp": "\nEsto se recomienda si usted tiene los nombres de archivo de imagen que no se ajusten a las directrices de XBMC.", - "LabelXbmcMetadataEnablePathSubstitution": "Habilitar rutas de sustituci\u00f3n", - "LabelXbmcMetadataEnablePathSubstitutionHelp": "Permite la sustituci\u00f3n de las rutas de im\u00e1genes utilizando la configuraci\u00f3n de rutas de sustituci\u00f3n en las opciones del servidor.", - "LabelXbmcMetadataEnablePathSubstitutionHelp2": "Ver rutas de sustituci\u00f3n.", - "LabelGroupChannelsIntoViews": "Visualice los siguientes canales dentro de mis vistas:", - "LabelGroupChannelsIntoViewsHelp": "Si est\u00e1 activado, estos canales se mostrar\u00e1n directamente junto a Mis Vistas. Si est\u00e1 desactivada, ser\u00e1n mostrados separadamente en la vista de Canales.", - "LabelDisplayCollectionsView": "Mostrar una vista Colecciones para mostrar colecciones de pel\u00edculas", - "LabelXbmcMetadataEnableExtraThumbs": "Copiar extrafanart en extrathumbs", - "LabelXbmcMetadataEnableExtraThumbsHelp": "Cuando se descargan im\u00e1genes se pueden guardar tanto en extrafanart como en extrathumbs para una m\u00e1xima compatibilidad con el skin de XBMC.", - "TabServices": "Servicios", - "TabLogs": "Logs", - "HeaderServerLogFiles": "Archivos de log del servidor:", - "TabBranding": "Branding", - "HeaderBrandingHelp": "Personalizar la apariencia de Explorador de medios para satisfacer las necesidades de su grupo u organizaci\u00f3n.", - "LabelLoginDisclaimer": "Login renuncia:", - "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.", - "LabelAutomaticallyDonate": "Donar autom\u00e1ticamente esta cantidad cada mes", - "LabelAutomaticallyDonateHelp": "Usted puede cancelar en cualquier momento desde su cuenta de PayPal.", - "OptionList": "Lista", - "TabDashboard": "Panel de control", - "TitleServer": "Servidor", - "LabelCache": "Cach\u00e9:", - "LabelLogs": "Registros:", - "LabelMetadata": "Metadatos:", - "LabelImagesByName": "Im\u00e1genes por nombre:", - "LabelTranscodingTemporaryFiles": "Archivos temporales de transcodificaci\u00f3n:", - "HeaderLatestMusic": "\u00daltima m\u00fasica", - "HeaderBranding": "Branding", - "HeaderApiKeys": "Keys de Api", - "HeaderApiKeysHelp": "Se requieren aplicaciones externas para tener una clave de API con el fin de comunicarse con Media Browser. Las claves son emitidas al iniciar una sesi\u00f3n con una cuenta de Media Browser, o mediante la introducci\u00f3n manualmente de una clave en la aplicaci\u00f3n.", - "HeaderApiKey": "Clave Api", - "HeaderApp": "App", - "HeaderDevice": "Dispositivo", - "HeaderUser": "Usuario", - "HeaderDateIssued": "Fecha de emisi\u00f3n", - "LabelChapterName": "Chapter {0}", - "HeaderNewApiKey": "New Api Key", - "LabelAppName": "App name", - "LabelAppNameExample": "Example: Sickbeard, NzbDrone", - "HeaderNewApiKeyHelp": "Grant an application permission to communicate with Media Browser." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/es_MX.json b/MediaBrowser.Server.Implementations/Localization/Server/es_MX.json index 8b440e39b..c394039c5 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/es_MX.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/es_MX.json @@ -27,7 +27,7 @@ "AWindowsServiceHasBeenInstalled": "Se ha instalado un Servicio de Windows.", "WindowsServiceIntro1": "Media Browser Server se ejecuta normalmente como una aplicaci\u00f3n de escritorio con un icono en el \u00e1rea de notificaci\u00f3n, pero si prefiere ejecutarlo como un servicio de segundo plano, puede ser iniciado desde el panel de control de servicios de windows.", "WindowsServiceIntro2": "Si utiliza el servicio de Windows, tenga en cuenta que no se puede ejecutar simult\u00e1neamiente con el icono en el \u00e1rea de notificaci\u00f3n, por lo que tendr\u00e1 que finalizar desde el icono para poder ejecutar el servicio. Adicionalmente, el servicio deber\u00e1 ser configurado con privilegios administrativos a trav\u00e9s del panel de control del servicio. Tenga en cuenta que en este momento el servicio no es capaz de actualizarse a s\u00ed mismo, por lo que las nuevas versiones requerir\u00e1n de interacci\u00f3n manual.", - "WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click <b>Finish<\/b> to view the <b>Server Dashboard<\/b>.", + "WizardCompleted": "Esto es todo lo que necesitamos por ahora. Media Browser ha comenzado a recolectar informaci\u00f3n sobre su biblioteca de medios. Pruebe algunas de nuestras apps, despu\u00e9s haga clic en <b>Terminar<\/b> para desplegar el <b>Panel de Control del Servidor<\/b>.", "LabelConfigureSettings": "Configuraci\u00f3n de opciones", "LabelEnableVideoImageExtraction": "Habilitar extracci\u00f3n de im\u00e1genes de video", "VideoImageExtractionHelp": "Para videos que no cuenten con im\u00e1genes, y para los que no podemos encontrar im\u00e1genes en Internet. Esto incrementar\u00e1 un poco el tiempo de la exploraci\u00f3n inicial de las bibliotecas, pero resultar\u00e1 en una presentaci\u00f3n m\u00e1s agradable.", @@ -40,16 +40,36 @@ "OptionIAcceptTermsOfService": "Acepto los t\u00e9rminos del servicio.", "ButtonPrivacyPolicy": "Pol\u00edtica de privacidad", "ButtonTermsOfService": "T\u00e9rminos del Servicio", + "HeaderDeveloperOptions": "Opciones de Desarrollador", + "OptionEnableWebClientResponseCache": "Habilitar la cache de respuestas del cliente web", + "OptionDisableForDevelopmentHelp": "Configuralos como sean necesarios para prop\u00f3sitos de desarrollo en el cliente web.", + "OptionEnableWebClientResourceMinification": "Habilitar minificacion de recursos del cliente web", + "LabelDashboardSourcePath": "Ruta de origen del cliente web:", + "LabelDashboardSourcePathHelp": "Si esta ejecutando el servidor desde la fuente, especifique la ruta de acceso a la carpeta dashboard-ui. Todos los archivos de cliente web ser\u00e1n atendidos desde esta ruta.", + "ButtonConvertMedia": "Convertir Medios", + "ButtonOrganize": "Organizar", "ButtonOk": "Ok", "ButtonCancel": "Cancelar", "ButtonNew": "Nuevo", "HeaderTV": "TV", "HeaderAudio": "Audio", "HeaderVideo": "Video", - "OptionDetectArchiveFilesAsMedia": "Detect archive files as media", - "OptionDetectArchiveFilesAsMediaHelp": "If enabled, files with .rar and .zip extensions will be detected as media files.", - "LabelEnterConnectUserName": "User name or email:", - "LabelEnterConnectUserNameHelp": "This is your Media Browser online account user name or password.", + "HeaderPaths": "Rutas", + "CategorySync": "Sync", + "HeaderEasyPinCode": "Easy Pin Code", + "RegisterWithPayPal": "Register with PayPal", + "HeaderSyncRequiresSupporterMembership": "Sinc requiere de una Membres\u00eda de Aficionado", + "HeaderEnjoyDayTrial": "Disfrute de una Prueba Gratuita por 14 D\u00edas", + "LabelSyncTempPath": "Trayectoria de archivos temporales:", + "LabelSyncTempPathHelp": "Especifique una carpeta de trabajo personalizada para sinc. Los medios convertidos creados durante el proceso de sinc ser\u00e1n almacenados en este lugar.", + "LabelCustomCertificatePath": "Trayectoria del certificado personalizado:", + "LabelCustomCertificatePathHelp": "Proporcione su certificado ssl propio. Si se omite, el servidor crear\u00e1 un certificado auto-firmado.", + "TitleNotifications": "Notificaciones", + "ButtonDonateWithPayPal": "Donar con PayPal", + "OptionDetectArchiveFilesAsMedia": "Detectar archivos comprimidos como medios", + "OptionDetectArchiveFilesAsMediaHelp": "Al habilitarlo, los archivos con extensiones .rar y .zip ser\u00e1n detectados como archivos de medios.", + "LabelEnterConnectUserName": "Nombre de usuario o correo:", + "LabelEnterConnectUserNameHelp": "Este es el nombre de usuario de su cuenta en l\u00ednea de Media Browser o su contrase\u00f1a.", "HeaderSyncJobInfo": "Trabajo de Sinc", "FolderTypeMixed": "Contenido mezclado", "FolderTypeMovies": "Pel\u00edculas", @@ -63,12 +83,14 @@ "FolderTypeTvShows": "TV", "FolderTypeInherit": "Heredar", "LabelContentType": "Tipo de Contenido:", + "TitleScheduledTasks": "Tareas Programadas", "HeaderSetupLibrary": "Configurar su biblioteca de medios", "ButtonAddMediaFolder": "Agregar carpeta de medios", "LabelFolderType": "Tipo de carpeta:", "ReferToMediaLibraryWiki": "Consultar la wiki de la biblioteca de medios.", "LabelCountry": "Pa\u00eds:", "LabelLanguage": "Idioma:", + "ButtonJoinTheDevelopmentTeam": "Unirse al Equipo de Desarrollo.", "HeaderPreferredMetadataLanguage": "Idioma preferido para metadatos:", "LabelSaveLocalMetadata": "Guardar im\u00e1genes y metadatos en las carpetas de medios", "LabelSaveLocalMetadataHelp": "Guardar im\u00e1genes y metadatos directamente en las carpetas de medios los colocar\u00e1 en un lugar donde se pueden editar f\u00e1cilmente.", @@ -86,6 +108,8 @@ "TabCollectionTitles": "T\u00edtulos", "HeaderDeviceAccess": "Acceso a Dispositivos", "OptionEnableAccessFromAllDevices": "Habilitar acceso desde todos los dispositivos", + "OptionEnableAccessToAllChannels": "Habilitar acceso a todos los canales", + "OptionEnableAccessToAllLibraries": "Habilitar el acceso a todas las bibliotecas", "DeviceAccessHelp": "Esto solo aplica a dispositivos que pueden ser identificados de manera individual y no evitar\u00e1 acceso al navegador. Al filtrar el acceso de usuarios a dispositivos se impedir\u00e1 que utilicen nuevos dispositivos hasta que hayan sido aprobados aqu\u00ed.", "LabelDisplayMissingEpisodesWithinSeasons": "Mostar episodios no disponibles en las temporadas", "LabelUnairedMissingEpisodesWithinSeasons": "Mostrar episodios a\u00fan no emitidos en las temporadas", @@ -174,8 +198,8 @@ "OptionFolderSort": "Carpetas", "OptionBudget": "Presupuesto", "OptionRevenue": "Recaudaci\u00f3n", - "OptionPoster": "Cartel", - "OptionPosterCard": "Tarjeta de Cartel", + "OptionPoster": "P\u00f3ster", + "OptionPosterCard": "Tarjeta de P\u00f3ster", "OptionBackdrop": "Imagen de Fondo", "OptionTimeline": "L\u00ednea de Tiempo", "OptionThumb": "Miniatura", @@ -314,12 +338,14 @@ "OptionEpisodes": "Episodios", "OptionOtherVideos": "Otros Videos", "TitleMetadata": "Metadatos", - "LabelAutomaticUpdatesFanart": "Habilitar actualizaciones autom\u00e1ticas desde FanArt.tv", + "LabelAutomaticUpdates": "Habilitar actualizaciones autom\u00e1ticas", "LabelAutomaticUpdatesTmdb": "Habilitar actualizaciones autom\u00e1ticas desde TheMovieDB.org", "LabelAutomaticUpdatesTvdb": "Habilitar actualizaciones autom\u00e1ticas desde TheTVDB.com", "LabelAutomaticUpdatesFanartHelp": "Al habilitarlo, se descargar\u00e1n autom\u00e1ticamente nuevas im\u00e1genes conforme son a\u00f1adidas a fanart.tv. Las Im\u00e1genes existentes no ser\u00e1n reemplazadas.", "LabelAutomaticUpdatesTmdbHelp": "Al habilitarlo, se descargar\u00e1n autom\u00e1ticamente nuevas im\u00e1genes conforme son a\u00f1adidas a TheMovieDB.org. Las im\u00e1genes existentes no ser\u00e1n reemplazadas.", "LabelAutomaticUpdatesTvdbHelp": "Al habilitarlo, se descargar\u00e1n autom\u00e1ticamente nuevas im\u00e1genes conforme son a\u00f1adidas a TheTVDB.com. Las im\u00e1genes existentes no ser\u00e1n reemplazadas.", + "LabelFanartApiKey": "Clave api personal:", + "LabelFanartApiKeyHelp": "Solicitar fanart sin una clave API personal muestra los resultados que fueron aprobados hace 7 d\u00edas. Con una clave API personal se reduce a 48 horas y si eres miembro VIP de fanart ser\u00e1 alrededor de 10 minutos.", "ExtractChapterImagesHelp": "Extraer im\u00e1genes de cap\u00edtulos permite a los clientes mostrar men\u00fas gr\u00e1ficos de selecci\u00f3n de escenas. El proceso puede ser lento, intensivo en utilizaci\u00f3n del CPU y puede requerir varios gigabytes de espacio. Se ejecuta cuando se detectan nuevos videos, tambi\u00e9n como una tarea nocturna, programada a las 4:00 am. La programaci\u00f3n puede configurarse en el \u00e1rea de tareas programadas. No se recomienda ejecutar esta tarea durante horas pico de uso.", "LabelMetadataDownloadLanguage": "Lenguaje preferido para descargas:", "ButtonAutoScroll": "Auto-desplazamiento", @@ -487,6 +513,7 @@ "HeaderSystemPaths": "Rutas del Sistema", "LinkCommunity": "Comunidad", "LinkGithub": "Github", + "LinkApi": "Api", "LinkApiDocumentation": "Documentaci\u00f3n del API", "LabelFriendlyServerName": "Nombre amigable del servidor:", "LabelFriendlyServerNameHelp": "Este nombre ser\u00e1 usado para identificar este servidor. Si se deja en blanco, se usar\u00e1 el nombre de la computadora.", @@ -494,20 +521,25 @@ "LabelPreferredDisplayLanguageHelp": "La traducci\u00f3n de Media Browser es un proyecto en curso y a\u00fan no se ha completado.", "LabelReadHowYouCanContribute": "Lea acerca de c\u00f3mo puede contribuir.", "HeaderNewCollection": "Nueva Colecci\u00f3n", - "HeaderAddToCollection": "Agregar a Colecci\u00f3n.", "ButtonSubmit": "Enviar", - "NewCollectionNameExample": "Ejemplo: Colecci\u00f3n Guerra de las Galaxias", - "OptionSearchForInternetMetadata": "Buscar en internet ilustraciones y metadatos", "ButtonCreate": "Crear", - "LabelLocalHttpServerPortNumber": "N\u00famero de puerto local:", + "LabelCustomCss": "css personalizado:", + "LabelCustomCssHelp": "Aplicar tu propia css personalizada a la interfaz web.", + "LabelLocalHttpServerPortNumber": "N\u00famero de puerto http local:", "LabelLocalHttpServerPortNumberHelp": "El n\u00famero de puerto TCP con el que el servidor de HTTP de Media Browser deber\u00e1 vincularse", - "LabelPublicPort": "N\u00famero de puerto p\u00fablico:", - "LabelPublicPortHelp": "El n\u00famero de puerto p\u00fablico que deber\u00e1 mapearse hacia el puerto local.", + "LabelPublicHttpPort": "N\u00famero de puerto http publico:", + "LabelPublicHttpPortHelp": "El numero de puerto que debe ser mapeado a el puerto http local.", + "LabelPublicHttpsPort": "N\u00famero de puerto https publico:", + "LabelPublicHttpsPortHelp": "El n\u00famero de puerto p\u00fablico que deber\u00e1 ser mapeado al puerto local de https.", + "LabelEnableHttps": "Reportar https como una direcci\u00f3n externa", + "LabelEnableHttpsHelp": "Si se habilita, el servidor reportara a los clientes una url https como su direcci\u00f3n externa. Esto podr\u00eda inutilizar a los clientes que aun no soporten https.", + "LabelHttpsPort": "N\u00famero de puerto https local:", + "LabelHttpsPortHelp": "El n\u00famero de puerto tcp con el que el servidor https de Media Browser se encontrar\u00e1 enlazado.", "LabelWebSocketPortNumber": "N\u00famero de puerto WebSocket:", "LabelEnableAutomaticPortMap": "Habilitar mapeo autom\u00e1tico de puertos", "LabelEnableAutomaticPortMapHelp": "Intentar mapear autom\u00e1ticamente el puerto p\u00fablico con el puerto local via UPnP. Esto podr\u00eda no funcionar con algunos modelos de ruteadores.", - "LabelExternalDDNS": "DDNS Externo:", - "LabelExternalDDNSHelp": "Si dispone de una DNS din\u00e1mica, introducirla aqu\u00ed. Media Brower la utilizar\u00e1 para las conexiones remotas.", + "LabelExternalDDNS": "Direcci\u00f3n WAN externa:", + "LabelExternalDDNSHelp": "Si usted cuenta con un DNS din\u00e1mico ingr\u00e9selo aqu\u00ed. Las apps de Media Browser lo usar\u00e1n cuando se conecten de manera remota. D\u00e9jelo vac\u00edo para detecci\u00f3n autom\u00e1tica.", "TabResume": "Continuar", "TabWeather": "El tiempo", "TitleAppSettings": "Configuraci\u00f3n de la App", @@ -540,7 +572,7 @@ "ButtonEnterSupporterKey": "Capture la Clave de Aficionado", "DonationNextStep": "Cuando haya terminado, regrese y capture la clave de seguidor que recibir\u00e1 por correo electr\u00f3nico.", "AutoOrganizeHelp": "La organizaci\u00f3n autom\u00e1tica monitorea sus carpetas de descarga en busca de nuevos archivos y los mueve a sus carpetas de medios.", - "AutoOrganizeTvHelp": "La organizaci\u00f3n de archivos de TV s\u00f3lo a\u00f1adir\u00e1 episodios a series existentes. No crear\u00e1 carpetas para series nuevas.", + "AutoOrganizeTvHelp": "La organizaci\u00f3n de archivos de TV s\u00f3lo agregar\u00e1 episodios a series existentes. No crear\u00e1 carpetas para series nuevas.", "OptionEnableEpisodeOrganization": "Habilitar la organizaci\u00f3n de nuevos episodios", "LabelWatchFolder": "Carpeta de Inspecci\u00f3n:", "LabelWatchFolderHelp": "El servidor inspeccionar\u00e1 esta carpeta durante la tarea programada \"Organizar nuevos archivos de medios\".", @@ -575,6 +607,7 @@ "ButtonRestart": "Reiniciar", "ButtonShutdown": "Apagar", "ButtonUpdateNow": "Actualizar Ahora", + "TabHosting": "Hospedaje", "PleaseUpdateManually": "Por favor apague el servidor y actualice manualmente.", "NewServerVersionAvailable": "\u00a1Hay disponible una nueva versi\u00f3n de Media Browser Server!", "ServerUpToDate": "Media Browser Server est\u00e1 actualizado", @@ -636,6 +669,7 @@ "NotificationOptionInstallationFailed": "Falla de instalaci\u00f3n", "NotificationOptionNewLibraryContent": "Nuevo contenido agregado", "NotificationOptionNewLibraryContentMultiple": "Nuevo contenido agregado (varios)", + "NotificationOptionCameraImageUploaded": "Camera image uploaded", "SendNotificationHelp": "Por defecto, las notificaciones son enviadas a la bandeja de entrada del panel de control. Navegue el cat\u00e1logo de complementos para instalar opciones de notificaci\u00f3n adicionales.", "NotificationOptionServerRestartRequired": "Reinicio del servidor requerido", "LabelNotificationEnabled": "Habilitar esta notificaci\u00f3n", @@ -829,8 +863,8 @@ "OptionAuto": "Autom\u00e1tico", "OptionYes": "Si", "OptionNo": "No", - "HeaderOptions": "Options", - "HeaderIdentificationResult": "Identification Result", + "HeaderOptions": "Opciones", + "HeaderIdentificationResult": "Resultado de la Identificaci\u00f3n", "LabelHomePageSection1": "Pagina de Inicio secci\u00f3n uno:", "LabelHomePageSection2": "Pagina de Inicio secci\u00f3n dos:", "LabelHomePageSection3": "Pagina de Inicio secci\u00f3n tres:", @@ -853,9 +887,11 @@ "OptionDefaultSort": "Por defecto", "OptionCommunityMostWatchedSort": "M\u00e1s Visto", "TabNextUp": "A Continuaci\u00f3n", + "HeaderBecomeMediaBrowserSupporter": "Convertirse en un Aficionado de Media Browser", + "TextEnjoyBonusFeatures": "Enjoy Bonus Features", "MessageNoMovieSuggestionsAvailable": "No hay sugerencias de pel\u00edculas disponibles en este momento. Comienza a ver y a calificar tus pel\u00edculas, y regresa para ver tus recomendaciones.", - "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.", - "MessageNoPlaylistsAvailable": "Las listas de reproducci\u00f3n le permiten crear listas de contenidos a ser reproducidos de manera consecutiva. Para a\u00f1adir \u00edtems a una lista de reproducci\u00f3n, haga clic derecho o seleccione y mantenga, despu\u00e9s seleccione A\u00f1adir a Lista de Reproducci\u00f3n.", + "MessageNoCollectionsAvailable": "Las colecciones le permiten disfrutar de agrupaciones personalizadas de Pel\u00edculas, Series, \u00c1lbums, Libros y Juegos. Haga clic en el bot\u00f3n + para iniciar la creaci\u00f3n de Colecciones.", + "MessageNoPlaylistsAvailable": "Las listas de reproducci\u00f3n le permiten crear listas de contenidos a ser reproducidos de manera consecutiva. Para agregar \u00edtems a una lista de reproducci\u00f3n, haga clic derecho o seleccione y mantenga, despu\u00e9s seleccione Agregar a Lista de Reproducci\u00f3n.", "MessageNoPlaylistItemsAvailable": "Esta lista de reproducci\u00f3n se encuentra vac\u00eda.", "ButtonDismiss": "Descartar", "ButtonEditOtherUserPreferences": "Editar la contrase\u00f1a y preferencias personales de este perfil de usuario.", @@ -869,7 +905,6 @@ "LabelChannelDownloadAge": "Eliminar contenido despu\u00e9s de: (d\u00edas)", "LabelChannelDownloadAgeHelp": "El contenido descargado anterior a esto ser\u00e1 eliminado. Permanecer\u00e1 reproducible via transmisi\u00f3n en tiempo real por Internet.", "ChannelSettingsFormHelp": "Instale canales tales como Avances y Vimeo desde el cat\u00e1logo de complementos.", - "LabelSelectCollection": "Elegir colecci\u00f3n:", "ButtonOptions": "Opciones", "ViewTypeMovies": "Pel\u00edculas", "ViewTypeTvShows": "TV", @@ -917,7 +952,7 @@ "OptionLatestTvRecordings": "Grabaciones recientes", "LabelProtocolInfo": "Informaci\u00f3n del protocolo:", "LabelProtocolInfoHelp": "El valor que ser\u00e1 utilizado cuando se responde a solicitudes GetProtocolInfo desde el dispositivo.", - "TabKodiMetadata": "Kodi", + "TabNfo": "Nfo", "HeaderKodiMetadataHelp": "Media Browser incluye soporte nativo para metadados NFO e im\u00e1genes de Kodi. Para activar o desactivar metadatos de Kodi, utilice la pesta\u00f1a Avanzado para configurar opciones para sus tipos de medios.", "LabelKodiMetadataUser": "Sincronizar informaci\u00f3n de vistos a nfo's para:", "LabelKodiMetadataUserHelp": "Habilitar esto para mantener monitoreo de datos en sincron\u00eda entre Media Browser y Kodi.", @@ -931,6 +966,7 @@ "LabelGroupChannelsIntoViews": "Desplegar los siguientes canales directamente en mis vistas:", "LabelGroupChannelsIntoViewsHelp": "Al activarse, estos canales ser\u00e1n desplegados directamente junto con otras vistas. Si permanecen deshabilitados, ser\u00e1n desplegados dentro de una vista independiente de Canales.", "LabelDisplayCollectionsView": "Desplegar una vista de colecciones para mostrar las colecciones de pel\u00edculas", + "LabelDisplayCollectionsViewHelp": "Esto crear\u00e1 una vista separada para desplegar colecciones que usted haya creado o a las que tenga acceso. Para crear una colecci\u00f3n, haga clic derecho o presione y mantenga sobre cualquier pel\u00edcula y seleccione 'Agregar a Colecci\u00f3n'.", "LabelKodiMetadataEnableExtraThumbs": "Copiar extrafanart en extrathumbs", "LabelKodiMetadataEnableExtraThumbsHelp": "Cuando se descargan im\u00e1genes pueden ser almacenadas tanto en extrafanart como extrathumb para maximizar la compatibilidad con skins de Kodi.", "TabServices": "Servicios", @@ -995,7 +1031,7 @@ "LabelContext": "Contexto:", "OptionContextStreaming": "Transmisi\u00f3n", "OptionContextStatic": "Sinc.", - "ButtonAddToPlaylist": "A\u00f1adir a lista de reproducci\u00f3n", + "ButtonAddToPlaylist": "Agregar a lista de reproducci\u00f3n", "TabPlaylists": "Listas de reproducci\u00f3n", "ButtonClose": "Cerrar", "LabelAllLanguages": "Todos los lenguajes", @@ -1084,11 +1120,14 @@ "LabelDisplayFoldersView": "Mostrar una vista de carpetas para mostrar carpetas de medios simples", "ViewTypeLiveTvRecordingGroups": "Grabaciones", "ViewTypeLiveTvChannels": "Canales", - "LabelAllowLocalAccessWithoutPassword": "Permite acceso local sin una contrase\u00f1a", - "LabelAllowLocalAccessWithoutPasswordHelp": "Al habilitarse, no se requerir\u00e1 de una contrase\u00f1a cuando se inicie sesi\u00f3n desde su red local.", + "LabelEasyPinCode": "Easy pin code:", + "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Media Browser apps, and can also be used for easy in-network sign in.", + "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", + "LabelInNetworkSignInWithEasyPasswordHelp": "If enabled, you'll be able to use your easy pin code to sign in to Media Browser apps from inside your home network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", "HeaderPassword": "Contrase\u00f1a", "HeaderLocalAccess": "Acceso Local", "HeaderViewOrder": "Orden de Despliegue", + "ButtonResetEasyPassword": "Reset easy pin code", "LabelSelectUserViewOrder": "Seleccione el orden en que sus vistas ser\u00e1n desplegadas dentro de las apps de Media Browser", "LabelMetadataRefreshMode": "Modo de actualizaci\u00f3n de metadatos:", "LabelImageRefreshMode": "Modo de actualizaci\u00f3n de im\u00e1genes:", @@ -1162,7 +1201,7 @@ "OptionNoThemeSong": "Sin Canci\u00f3n del Tema", "OptionNoThemeVideo": "Sin Video del Tema", "LabelOneTimeDonationAmount": "Cantidad a donar:", - "ButtonDonate": "Donate", + "ButtonDonate": "Donar", "OptionActor": "Actor", "OptionComposer": "Compositor", "OptionDirector": "Director", @@ -1182,7 +1221,7 @@ "HeaderDeveloperInfo": "Info del desarrollador", "HeaderRevisionHistory": "Historial de Versiones", "ButtonViewWebsite": "Ver sitio web", - "LabelRecurringDonationCanBeCancelledHelp": "Las donaciones recurrente pueden ser canceladas en cualquier momento desde su cuenta PayPal.", + "LabelRecurringDonationCanBeCancelledHelp": "Las donaciones recurrentes pueden ser canceladas en cualquier momento desde su cuenta PayPal.", "HeaderXmlSettings": "Configuraci\u00f3n XML", "HeaderXmlDocumentAttributes": "Atributos del Documento XML", "HeaderXmlDocumentAttribute": "Atributo del Documento XML", @@ -1246,7 +1285,7 @@ "HeaderCameraUploadHelp": "Suba a Media Broswer fotos y videos tomados desde sus dispositivos m\u00f3viles de forma autom\u00e1tica.", "MessageNoDevicesSupportCameraUpload": "Actualmente no cuenta con ning\u00fan dispositivo que soporte subir desde la c\u00e1mara.", "LabelCameraUploadPath": "Ruta para subir desde la c\u00e1mara:", - "LabelCameraUploadPathHelp": "Seleccione una trayectoria personalizada de subida. Si no se especifica, una carpeta por omisi\u00f3n ser\u00e1 usada. Si usa una trayectoria personalizada, tambi\u00e9n ser\u00e1 necesario a\u00f1adirla en el \u00e1rea de configuraci\u00f3n de la biblioteca.", + "LabelCameraUploadPathHelp": "Seleccione una trayectoria personalizada de subida. Si no se especifica, una carpeta por omisi\u00f3n ser\u00e1 usada. Si usa una trayectoria personalizada, tambi\u00e9n ser\u00e1 necesario agregarla en el \u00e1rea de configuraci\u00f3n de la biblioteca.", "LabelCreateCameraUploadSubfolder": "Crear una subcarpeta para cada dispositivo", "LabelCreateCameraUploadSubfolderHelp": "Se pueden especificar carpetas espec\u00edficas para un dispositivo haciendo clic en \u00e9l desde la p\u00e1gina de Dispositivos.", "LabelCustomDeviceDisplayName": "Nombre a Desplegar:", @@ -1279,7 +1318,7 @@ "MessageNoTrailersFound": "No se encontraron avances. Instale el canal de avances para mejorar su experiencia con pel\u00edculas al agregar una biblioteca de avances desde el Internet.", "HeaderNewUsers": "Nuevos Usuarios", "ButtonSignUp": "Registrarse", - "ButtonForgotPassword": "\u00bfOlvidaste la contrase\u00f1a?", + "ButtonForgotPassword": "Olvid\u00e9 contrase\u00f1a", "OptionDisableUserPreferences": "Desactivar acceso a las preferencias de usuario", "OptionDisableUserPreferencesHelp": "Al activarse, s\u00f3lo los administradores podr\u00e1n configurar las im\u00e1genes del perfil del usuario, contrase\u00f1as y preferencias de idioma.", "HeaderSelectServer": "Seleccionar Servidor", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/fi.json b/MediaBrowser.Server.Implementations/Localization/Server/fi.json index 096026ba7..247e3cc37 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/fi.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/fi.json @@ -40,12 +40,32 @@ "OptionIAcceptTermsOfService": "I accept the terms of service", "ButtonPrivacyPolicy": "Privacy policy", "ButtonTermsOfService": "Terms of Service", + "HeaderDeveloperOptions": "Developer Options", + "OptionEnableWebClientResponseCache": "Enable web client response caching", + "OptionDisableForDevelopmentHelp": "Configure these as needed for web client development purposes.", + "OptionEnableWebClientResourceMinification": "Enable web client resource minification", + "LabelDashboardSourcePath": "Web client source path:", + "LabelDashboardSourcePathHelp": "If running the server from source, specify the path to the dashboard-ui folder. All web client files will be served from this location.", + "ButtonConvertMedia": "Convert media", + "ButtonOrganize": "Organize", "ButtonOk": "Ok", "ButtonCancel": "Lopeta", "ButtonNew": "New", "HeaderTV": "TV", "HeaderAudio": "Audio", "HeaderVideo": "Video", + "HeaderPaths": "Paths", + "CategorySync": "Sync", + "HeaderEasyPinCode": "Easy Pin Code", + "RegisterWithPayPal": "Register with PayPal", + "HeaderSyncRequiresSupporterMembership": "Sync Requires a Supporter Membership", + "HeaderEnjoyDayTrial": "Enjoy a 14 Day Free Trial", + "LabelSyncTempPath": "Temporary file path:", + "LabelSyncTempPathHelp": "Specify a custom sync working folder. Converted media created during the sync process will be stored here.", + "LabelCustomCertificatePath": "Custom certificate path:", + "LabelCustomCertificatePathHelp": "Supply your own ssl certificate. If omitted, the server will create a self-signed certificate.", + "TitleNotifications": "Notifications", + "ButtonDonateWithPayPal": "Donate with PayPal", "OptionDetectArchiveFilesAsMedia": "Detect archive files as media", "OptionDetectArchiveFilesAsMediaHelp": "If enabled, files with .rar and .zip extensions will be detected as media files.", "LabelEnterConnectUserName": "User name or email:", @@ -63,12 +83,14 @@ "FolderTypeTvShows": "TV", "FolderTypeInherit": "Inherit", "LabelContentType": "Content type:", + "TitleScheduledTasks": "Scheduled Tasks", "HeaderSetupLibrary": "Aseta sinun media kirjasto", "ButtonAddMediaFolder": "Lis\u00e4\u00e4 media kansio", "LabelFolderType": "Kansion tyyppi:", "ReferToMediaLibraryWiki": "Viittus media kirjaston wikiin.", "LabelCountry": "Maa:", "LabelLanguage": "Kieli:", + "ButtonJoinTheDevelopmentTeam": "Join the Development Team", "HeaderPreferredMetadataLanguage": "Ensisijainen kieli:", "LabelSaveLocalMetadata": "Tallenna kuvamateriaali ja metadata media kansioihin.", "LabelSaveLocalMetadataHelp": "Kuvamateriaalin ja metadatan tallentaminen suoraan kansioihin miss\u00e4 niit\u00e4 on helppo muuttaa.", @@ -86,6 +108,8 @@ "TabCollectionTitles": "Titles", "HeaderDeviceAccess": "Device Access", "OptionEnableAccessFromAllDevices": "Enable access from all devices", + "OptionEnableAccessToAllChannels": "Enable access to all channels", + "OptionEnableAccessToAllLibraries": "Enable access to all libraries", "DeviceAccessHelp": "This only applies to devices that can be uniquely identified and will not prevent browser access. Filtering user device access will prevent them from using new devices until they've been approved here.", "LabelDisplayMissingEpisodesWithinSeasons": "N\u00e4yt\u00e4 puuttuvat jaksot tuotantokausissa", "LabelUnairedMissingEpisodesWithinSeasons": "N\u00e4yt\u00e4 julkaisemattomat jaksot tuotantokausissa", @@ -299,7 +323,7 @@ "LabelCachePath": "Cache path:", "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.", "LabelImagesByNamePath": "Images by name path:", - "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, genre and studio images.", "LabelMetadataPath": "Metadata path:", "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.", "LabelTranscodingTempPath": "Transcoding temporary path:", @@ -314,12 +338,14 @@ "OptionEpisodes": "Episodes", "OptionOtherVideos": "Other Videos", "TitleMetadata": "Metadata", - "LabelAutomaticUpdatesFanart": "Enable automatic updates from FanArt.tv", + "LabelAutomaticUpdates": "Enable automatic updates", "LabelAutomaticUpdatesTmdb": "Enable automatic updates from TheMovieDB.org", "LabelAutomaticUpdatesTvdb": "Enable automatic updates from TheTVDB.com", "LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.", "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.", "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.", + "LabelFanartApiKey": "Personal api key:", + "LabelFanartApiKeyHelp": "Requests to fanart without a personal API key return results that were approved over 7 days ago. With a personal API key that drops to 48 hours and if you are also a fanart VIP member that will further drop to around 10 minutes.", "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", "LabelMetadataDownloadLanguage": "Preferred download language:", "ButtonAutoScroll": "Auto-scroll", @@ -487,6 +513,7 @@ "HeaderSystemPaths": "System Paths", "LinkCommunity": "Community", "LinkGithub": "Github", + "LinkApi": "Api", "LinkApiDocumentation": "Api Documentation", "LabelFriendlyServerName": "Friendly server name:", "LabelFriendlyServerNameHelp": "This name will be used to identify this server. If left blank, the computer name will be used.", @@ -494,20 +521,25 @@ "LabelPreferredDisplayLanguageHelp": "Translating Media Browser is an ongoing project and is not yet complete.", "LabelReadHowYouCanContribute": "Read about how you can contribute.", "HeaderNewCollection": "New Collection", - "HeaderAddToCollection": "Add to Collection", "ButtonSubmit": "Submit", - "NewCollectionNameExample": "Example: Star Wars Collection", - "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata", "ButtonCreate": "Create", - "LabelLocalHttpServerPortNumber": "Local port number:", + "LabelCustomCss": "Custom css:", + "LabelCustomCssHelp": "Apply your own custom css to the web interface.", + "LabelLocalHttpServerPortNumber": "Local http port number:", "LabelLocalHttpServerPortNumberHelp": "The tcp port number that Media Browser's http server should bind to.", - "LabelPublicPort": "Public port number:", - "LabelPublicPortHelp": "The public port number that should be mapped to the local port.", + "LabelPublicHttpPort": "Public http port number:", + "LabelPublicHttpPortHelp": "The public port number that should be mapped to the local http port.", + "LabelPublicHttpsPort": "Public https port number:", + "LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.", + "LabelEnableHttps": "Report https as external address", + "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.", + "LabelHttpsPort": "Local https port number:", + "LabelHttpsPortHelp": "The tcp port number that Media Browser's https server should bind to.", "LabelWebSocketPortNumber": "Web socket port number:", "LabelEnableAutomaticPortMap": "Enable automatic port mapping", "LabelEnableAutomaticPortMapHelp": "Attempt to automatically map the public port to the local port via UPnP. This may not work with some router models.", - "LabelExternalDDNS": "External DDNS:", - "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely.", + "LabelExternalDDNS": "External WAN Address:", + "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely. Leave empty for automatic detection.", "TabResume": "Resume", "TabWeather": "Weather", "TitleAppSettings": "App Settings", @@ -575,6 +607,7 @@ "ButtonRestart": "Restart", "ButtonShutdown": "Shutdown", "ButtonUpdateNow": "Update Now", + "TabHosting": "Hosting", "PleaseUpdateManually": "Please shutdown the server and update manually.", "NewServerVersionAvailable": "A new version of Media Browser Server is available!", "ServerUpToDate": "Media Browser Server is up to date", @@ -636,6 +669,7 @@ "NotificationOptionInstallationFailed": "Installation failure", "NotificationOptionNewLibraryContent": "New content added", "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", + "NotificationOptionCameraImageUploaded": "Camera image uploaded", "SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.", "NotificationOptionServerRestartRequired": "Server restart required", "LabelNotificationEnabled": "Enable this notification", @@ -853,6 +887,8 @@ "OptionDefaultSort": "Default", "OptionCommunityMostWatchedSort": "Most Watched", "TabNextUp": "Next Up", + "HeaderBecomeMediaBrowserSupporter": "Become a Media Browser Supporter", + "TextEnjoyBonusFeatures": "Enjoy Bonus Features", "MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.", "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.", "MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.", @@ -869,7 +905,6 @@ "LabelChannelDownloadAge": "Delete content after: (days)", "LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.", "ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.", - "LabelSelectCollection": "Select collection:", "ButtonOptions": "Options", "ViewTypeMovies": "Movies", "ViewTypeTvShows": "TV", @@ -917,7 +952,7 @@ "OptionLatestTvRecordings": "Latest recordings", "LabelProtocolInfo": "Protocol info:", "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.", - "TabKodiMetadata": "Kodi", + "TabNfo": "Nfo", "HeaderKodiMetadataHelp": "Media Browser includes native support for Kodi Nfo metadata and images. To enable or disable Kodi metadata, use the Advanced tab to configure options for your media types.", "LabelKodiMetadataUser": "Sync user watch data to nfo's for:", "LabelKodiMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Kodi.", @@ -931,6 +966,7 @@ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:", "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.", "LabelDisplayCollectionsView": "Display a collections view to show movie collections", + "LabelDisplayCollectionsViewHelp": "This will create a separate view to display collections that you've created or have access to. To create a collection, right-click or tap-hold any movie and select 'Add to Collection'. ", "LabelKodiMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs", "LabelKodiMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Kodi skin compatibility.", "TabServices": "Services", @@ -1084,11 +1120,14 @@ "LabelDisplayFoldersView": "Display a folders view to show plain media folders", "ViewTypeLiveTvRecordingGroups": "Recordings", "ViewTypeLiveTvChannels": "Channels", - "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password", - "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.", + "LabelEasyPinCode": "Easy pin code:", + "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Media Browser apps, and can also be used for easy in-network sign in.", + "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", + "LabelInNetworkSignInWithEasyPasswordHelp": "If enabled, you'll be able to use your easy pin code to sign in to Media Browser apps from inside your home network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", "HeaderPassword": "Password", "HeaderLocalAccess": "Local Access", "HeaderViewOrder": "View Order", + "ButtonResetEasyPassword": "Reset easy pin code", "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps", "LabelMetadataRefreshMode": "Metadata refresh mode:", "LabelImageRefreshMode": "Image refresh mode:", @@ -1279,7 +1318,7 @@ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.", "HeaderNewUsers": "New Users", "ButtonSignUp": "Sign up", - "ButtonForgotPassword": "Forgot password?", + "ButtonForgotPassword": "Forgot password", "OptionDisableUserPreferences": "Disable access to user preferences", "OptionDisableUserPreferencesHelp": "If enabled, only administrators will be able to configure user profile images, passwords, and language preferences.", "HeaderSelectServer": "Select Server", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/fr.json b/MediaBrowser.Server.Implementations/Localization/Server/fr.json index d1a95f0ad..58be84864 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/fr.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/fr.json @@ -27,7 +27,7 @@ "AWindowsServiceHasBeenInstalled": "Un service Windows a \u00e9t\u00e9 install\u00e9.", "WindowsServiceIntro1": "Media Browser fonctionne normalement en tant qu'application sur le bureau avec une ic\u00f4ne dans la barre des t\u00e2ches, mais si vous pr\u00e9f\u00e9rez le lancer en tant que service d'arri\u00e8re-plan, il peut \u00eatre d\u00e9marr\u00e9 via le gestionnaire de services Windows.", "WindowsServiceIntro2": "Si le service Windows est utilis\u00e9, veuillez noter qu'il ne peut pas fonctionner en m\u00eame temps que l'application dans la barre des t\u00e2ches, vous devrez donc fermer l'application de la barre des t\u00e2ches pour pouvoir ex\u00e9cuter le service. Le service devra aussi \u00eatre configur\u00e9 avec les droits administrateurs via le panneau de configuration. Veuillez noter qu'actuellement, la mise \u00e0 jour automatique du service n'est pas disponible, les mises \u00e0 jour devront donc se faire manuellement.", - "WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click <b>Finish<\/b> to view the <b>Server Dashboard<\/b>.", + "WizardCompleted": "C'est tout ce dont nous avons besoin pour le moment. Media Browser a commenc\u00e9 la collecte d'informations dans votre biblioth\u00e8que de m\u00e9dias. Consultez quelques-une de nos applications, puis cliquez sur <b>Terminer<\/b> pour consulter le <b>tableau de bord du serveur<\/b>.", "LabelConfigureSettings": "Configurer les param\u00e8tres", "LabelEnableVideoImageExtraction": "Activer l'extraction d'images des videos", "VideoImageExtractionHelp": "Pour les vid\u00e9os sans image et pour lesquelles nous n'avons pas trouv\u00e9 d'images sur Internet. Ce processus prolongera la mise \u00e0 jour initiale de la biblioth\u00e8que mais offrira un meilleur rendu visuel.", @@ -40,12 +40,32 @@ "OptionIAcceptTermsOfService": "J'accepte les conditions d'utilisation.", "ButtonPrivacyPolicy": "Politique de confidentialit\u00e9", "ButtonTermsOfService": "Conditions d'utilisation", + "HeaderDeveloperOptions": "Options de d\u00e9veloppement", + "OptionEnableWebClientResponseCache": "Activer la mise en cache des r\u00e9ponses du client web", + "OptionDisableForDevelopmentHelp": "Vous pouvez configurer ces options selon vos besoins de d\u00e9veloppement.", + "OptionEnableWebClientResourceMinification": "Activer la minimisation des ressources du client web", + "LabelDashboardSourcePath": "Chemin des fichiers sources du client web", + "LabelDashboardSourcePathHelp": "Si vous ex\u00e9cutez le serveur \u00e0 partir des sources, veuillez sp\u00e9cifier le chemin du r\u00e9pertoire dashboard-ui. Tous les fichiers du client web seront servis \u00e0 partir de cet endroit.", + "ButtonConvertMedia": "Convertir le m\u00e9dia", + "ButtonOrganize": "Organiser", "ButtonOk": "Ok", "ButtonCancel": "Annuler", "ButtonNew": "Nouveau", "HeaderTV": "TV", "HeaderAudio": "Audio", "HeaderVideo": "Vid\u00e9o", + "HeaderPaths": "Chemins", + "CategorySync": "Sync", + "HeaderEasyPinCode": "Code Easy Pin", + "RegisterWithPayPal": "S'enregistrer avec PayPal", + "HeaderSyncRequiresSupporterMembership": "Sync n\u00e9cessite un abonnement actif comme supporteur", + "HeaderEnjoyDayTrial": "Profitez d'une p\u00e9riode d'essai de 14 jours", + "LabelSyncTempPath": "R\u00e9pertoire de fichiers temporaires :", + "LabelSyncTempPathHelp": "Sp\u00e9cifiez un r\u00e9pertoire de travail pour la synchronisation. Les fichiers r\u00e9sultant de la conversion de m\u00e9dias au cours du processus de synchronisation seront stock\u00e9s ici.", + "LabelCustomCertificatePath": "Chemin vers le certificat personnalis\u00e9 :", + "LabelCustomCertificatePathHelp": "Fournissez votre propre certificat SSL. Sinon, le serveur cr\u00e9era un certificat auto-sign\u00e9.", + "TitleNotifications": "Notifications", + "ButtonDonateWithPayPal": "Faire un don avec Paypal", "OptionDetectArchiveFilesAsMedia": "Reconna\u00eetre les fichiers archives comme m\u00e9dias", "OptionDetectArchiveFilesAsMediaHelp": "Activez cette option pour reconna\u00eetre les fichiers portant l'extension .rar ou .zip comme des fichiers de m\u00e9dias. ", "LabelEnterConnectUserName": "Nom d'utilisateur ou adresse email :", @@ -63,12 +83,14 @@ "FolderTypeTvShows": "TV", "FolderTypeInherit": "H\u00e9rite", "LabelContentType": "Type de contenu :", + "TitleScheduledTasks": "T\u00e2ches planifi\u00e9es", "HeaderSetupLibrary": "Configurer votre biblioth\u00e8que de m\u00e9dia", "ButtonAddMediaFolder": "Ajouter un r\u00e9pertoire de m\u00e9dia", "LabelFolderType": "Type de r\u00e9pertoire:", "ReferToMediaLibraryWiki": "Se r\u00e9f\u00e9rer au wiki des biblioth\u00e8ques de m\u00e9dia", "LabelCountry": "Pays:", "LabelLanguage": "Langue:", + "ButtonJoinTheDevelopmentTeam": "Joignez-vous \u00e0 l'\u00e9quipe de d\u00e9veloppement", "HeaderPreferredMetadataLanguage": "Langue pr\u00e9f\u00e9r\u00e9e pour les m\u00e9tadonn\u00e9es:", "LabelSaveLocalMetadata": "Enregistrer les images et m\u00e9tadonn\u00e9es dans les r\u00e9pertoires de m\u00e9dia", "LabelSaveLocalMetadataHelp": "L'enregistrement des images et des m\u00e9tadonn\u00e9es dans le r\u00e9pertoire de m\u00e9dia les placera \u00e0 un endroit o\u00f9 elles seront facilement modifiables.", @@ -86,6 +108,8 @@ "TabCollectionTitles": "Titres", "HeaderDeviceAccess": "Acc\u00e8s \u00e0 l'appareil", "OptionEnableAccessFromAllDevices": "Autoriser l'acc\u00e8s \u00e0 tous les appareils", + "OptionEnableAccessToAllChannels": "Activer l'acc\u00e8s \u00e0 toutes les cha\u00eenes", + "OptionEnableAccessToAllLibraries": "Activer l'acc\u00e8s \u00e0 toutes les librairies", "DeviceAccessHelp": "Ceci ne s'applique qu'aux appareils qui peuvent \u00eatre identifi\u00e9s de mani\u00e8re unique et qui n'emp\u00eachent pas l'acc\u00e8s au navigateur. Le filtrage de l'acc\u00e8s aux appareil par utilisateur emp\u00eachera l'utilisation de nouveaux appareils jusqu'\u00e0 ce qu'ils soient approuv\u00e9s ici.", "LabelDisplayMissingEpisodesWithinSeasons": "Afficher les \u00e9pisodes manquants dans les saisons", "LabelUnairedMissingEpisodesWithinSeasons": "Afficher les \u00e9pisodes non diffus\u00e9s dans les saisons", @@ -201,7 +225,7 @@ "OptionDvd": "DVD", "OptionIso": "ISO", "Option3D": "3D", - "LabelFeatures": "Fonctionnalit\u00e9s:", + "LabelFeatures": "Caract\u00e9ristiques :", "LabelService": "Service :", "LabelStatus": "Statut:", "LabelVersion": "Version :", @@ -242,7 +266,7 @@ "OptionFileMetadataYearMismatch": "Conflit entre nom du fichier et les m\u00e9tadonn\u00e9es sur l'ann\u00e9e", "TabGeneral": "G\u00e9n\u00e9ral", "TitleSupport": "Assistance", - "TabLog": "Journal d'\u00e9v\u00e8nements", + "TabLog": "Journal d'\u00e9v\u00e9nements", "TabAbout": "\u00c0 propos", "TabSupporterKey": "Cl\u00e9 de membre supporteur", "TabBecomeSupporter": "Devenir un suporteur", @@ -257,7 +281,7 @@ "OptionDisableUser": "D\u00e9sactiver cet utilisateur", "OptionDisableUserHelp": "Si d\u00e9sactiv\u00e9, le serveur n'autorisera pas de connexion de cet utilisateur. Les connexions existantes seront interrompues.", "HeaderAdvancedControl": "Contr\u00f4le avanc\u00e9", - "LabelName": "Nom :", + "LabelName": "Nom", "ButtonHelp": "Aide", "OptionAllowUserToManageServer": "Autoriser la gestion du serveur \u00e0 cet utilisateur", "HeaderFeatureAccess": "Acc\u00e8s aux fonctionnalit\u00e9s", @@ -275,7 +299,7 @@ "OptionMetascore": "Metascore", "ButtonSelect": "S\u00e9lectionner", "ButtonGroupVersions": "Versions des groupes", - "ButtonAddToCollection": "Ajouter \u00e0 la collection", + "ButtonAddToCollection": "Ajouter \u00e0 une collection", "PismoMessage": "Utilisation de \"Pismo File Mount\" par une licence fournie.", "TangibleSoftwareMessage": "Utilisation de convertisseurs Tangible Solutions Java\/C# par licence fournie.", "HeaderCredits": "Cr\u00e9dits", @@ -299,7 +323,7 @@ "LabelCachePath": "Chemin du cache :", "LabelCachePathHelp": "Veuillez sp\u00e9cifier un emplacement personnalis\u00e9 pour les fichier temporaires du serveur, comme par exemple les images.", "LabelImagesByNamePath": "R\u00e9pertoire de stockage des images t\u00e9l\u00e9charg\u00e9es :", - "LabelImagesByNamePathHelp": "Veuillez sp\u00e9cifier un emplacement personnalis\u00e9 pour les images t\u00e9l\u00e9charg\u00e9es d'acteurs, artistes, genre, et studios.", + "LabelImagesByNamePathHelp": "Veuillez sp\u00e9cifier un emplacement personnalis\u00e9 pour les images t\u00e9l\u00e9charg\u00e9es d'acteurs, artistes, genre, et studios .", "LabelMetadataPath": "Chemin des m\u00e9tadonn\u00e9es :", "LabelMetadataPathHelp": "Veuillez sp\u00e9cifier un emplacement personnalis\u00e9 pour les images d'art et les m\u00e9tadonn\u00e9es t\u00e9l\u00e9charg\u00e9es. Par d\u00e9faut, stockage dans le r\u00e9pertoire de m\u00e9dias.", "LabelTranscodingTempPath": "Chemin d'acc\u00e8s du r\u00e9pertoire temporaire de transcodage :", @@ -314,12 +338,14 @@ "OptionEpisodes": "\u00c9pisodes", "OptionOtherVideos": "Autres vid\u00e9os", "TitleMetadata": "M\u00e9tadonn\u00e9es", - "LabelAutomaticUpdatesFanart": "Activer les mises \u00e0 jour automatique depuis FanArt.tv", + "LabelAutomaticUpdates": "Activer les mises \u00e0 jour automatiques", "LabelAutomaticUpdatesTmdb": "Activer les mises \u00e0 jour automatique depuis TheMovieDB.org", "LabelAutomaticUpdatesTvdb": "Activer les mises \u00e0 jour automatique depuis TheTVDB.com", "LabelAutomaticUpdatesFanartHelp": "Si activ\u00e9, les nouvelles images seront t\u00e9l\u00e9charg\u00e9es automatiquement lorsqu'elles sont ajout\u00e9es dans Fanart.tv. Les images existantes ne seront pas remplac\u00e9es.", "LabelAutomaticUpdatesTmdbHelp": "Si activ\u00e9, les nouvelles images seront t\u00e9l\u00e9charg\u00e9es automatiquement lorsqu'elles sont ajout\u00e9es dans TheMovieDB.org. Les images existantes ne seront pas remplac\u00e9es.", "LabelAutomaticUpdatesTvdbHelp": "Si activ\u00e9, les nouvelles images seront t\u00e9l\u00e9charg\u00e9es automatiquement lorsqu'elles sont ajout\u00e9es dans TheTVDB.com. Les images existantes ne seront pas remplac\u00e9es.", + "LabelFanartApiKey": "Cl\u00e9 d'api personnelle :", + "LabelFanartApiKeyHelp": "Les requ\u00eates de fanart sans cl\u00e9 d'api personnelle renvoient des r\u00e9sultats approuv\u00e9s il y a plus de 7 jours. Avec une cl\u00e9 d'api personnelle, cette valeur tombe \u00e0 48 heures, et si vous \u00eates aussi membre fanart VIP, cette valeur tombera encore plus, \u00e0 environ 10 minutes.", "ExtractChapterImagesHelp": "L'extraction d'images de chapitre permettra aux clients d'afficher des menus visuels pour la s\u00e9lection des sc\u00e8nes. Le processus peut \u00eatre long et consommateur de ressources processeur et peut n\u00e9cessiter de nombreux gigaoctets de stockage. Il s'ex\u00e9cute quand des vid\u00e9os sont d\u00e9couvertes et \u00e9galement comme t\u00e2che planifi\u00e9e \u00e0 4:00 (AM). La planification peut \u00eatre modifi\u00e9e dans les options du planificateur de tache. Il n'est pas conseill\u00e9 d'ex\u00e9cuter cette t\u00e2che pendant les heures d'usage intensif.", "LabelMetadataDownloadLanguage": "Langue de t\u00e9l\u00e9chargement pr\u00e9f\u00e9r\u00e9e:", "ButtonAutoScroll": "D\u00e9filement automatique", @@ -396,7 +422,7 @@ "LabelMaxScreenshotsPerItem": "Nombre maximum de captures d'\u00e9cran par item:", "LabelMinBackdropDownloadWidth": "Largeur minimum d'image d'arri\u00e8re-plan \u00e0 t\u00e9l\u00e9charger:", "LabelMinScreenshotDownloadWidth": "Largeur minimum de capture d'\u00e9cran \u00e0 t\u00e9l\u00e9charger:", - "ButtonAddScheduledTaskTrigger": "Ajout un d\u00e9clencheur", + "ButtonAddScheduledTaskTrigger": "Ajouter un d\u00e9clencheur", "HeaderAddScheduledTaskTrigger": "Ajouter un d\u00e9clencheur", "ButtonAdd": "Ajouter", "LabelTriggerType": "Type de d\u00e9clencheur:", @@ -449,7 +475,7 @@ "LabelFromHelp": "Exemple: D:\\Films (sur le serveur)", "LabelTo": "\u00c0:", "LabelToHelp": "Exemple: \\\\MonServeur\\Films (un chemin d'acc\u00e8s accessible par les clients)", - "ButtonAddPathSubstitution": "Ajouter Substitution", + "ButtonAddPathSubstitution": "Ajouter une substitution", "OptionSpecialEpisode": "Sp\u00e9ciaux", "OptionMissingEpisode": "\u00c9pisodes manquantes", "OptionUnairedEpisode": "\u00c9pisodes non diffus\u00e9s", @@ -487,6 +513,7 @@ "HeaderSystemPaths": "Chemins d'acc\u00e8s syst\u00e8me", "LinkCommunity": "Communaut\u00e9", "LinkGithub": "Github", + "LinkApi": "Api", "LinkApiDocumentation": "Documentation de l'API", "LabelFriendlyServerName": "Surnom du serveur:", "LabelFriendlyServerNameHelp": "Ce nom sera utilis\u00e9 pour identifier le serveur. Si laiss\u00e9 vide, le nom d'ordinateur sera utilis\u00e9.", @@ -494,20 +521,25 @@ "LabelPreferredDisplayLanguageHelp": "La traduction de Media Browser est un projet en cours et peut \u00eatre incompl\u00e8te par endroits.", "LabelReadHowYouCanContribute": "Lire comment vous pouvez contribuer.", "HeaderNewCollection": "Nouvelle collection", - "HeaderAddToCollection": "Ajouter \u00e0 la collection", "ButtonSubmit": "Soumettre", - "NewCollectionNameExample": "Exemple: Collection Star Wars", - "OptionSearchForInternetMetadata": "Rechercher sur Internet les images et m\u00e9tadonn\u00e9es", "ButtonCreate": "Cr\u00e9er", - "LabelLocalHttpServerPortNumber": "Num\u00e9ro de port local :", + "LabelCustomCss": "Css personnalis\u00e9e :", + "LabelCustomCssHelp": "Appliquez votre propre feuille de styles css personnalis\u00e9e \u00e0 l'interface web.", + "LabelLocalHttpServerPortNumber": "Num\u00e9ro de port http local :", "LabelLocalHttpServerPortNumberHelp": "Le num\u00e9ro de port TCP qui sera utilis\u00e9 par le serveur HTTP de Media Browser.", - "LabelPublicPort": "Num\u00e9ro de port public :", - "LabelPublicPortHelp": "Le num\u00e9ro de port public qui sera mapp\u00e9 sur le port local.", + "LabelPublicHttpPort": "Num\u00e9ro de port http public :", + "LabelPublicHttpPortHelp": "Le num\u00e9ro de port public \u00e0 mapper sur le port http local.", + "LabelPublicHttpsPort": "Num\u00e9ro de port https public :", + "LabelPublicHttpsPortHelp": "Le num\u00e9ro de port public \u00e0 mapper sur le port https local.", + "LabelEnableHttps": "Renvoyer une url https en tant qu'adresse externe", + "LabelEnableHttpsHelp": "Activez cette option pour que le serveur renvoie une adresse https aux clients pour son adresse externe. Ceci pourrait faire planter les clients qui ne supportent pas encore l'https.", + "LabelHttpsPort": "Num\u00e9ro de port https local :", + "LabelHttpsPortHelp": "Le num\u00e9ro de port tcp que le serveur https de Media Browser doit utiliser.", "LabelWebSocketPortNumber": "Num\u00e9ro de port \"Web socket\":", "LabelEnableAutomaticPortMap": "Autoriser le mapping automatique de port", "LabelEnableAutomaticPortMapHelp": "Essayer de mapper automatiquement le port public au port local via UPnP. Cela peut ne pas fonctionner avec certains mod\u00e8les de routeurs.", - "LabelExternalDDNS": "DDNS Externe", - "LabelExternalDDNSHelp": "Si vous avez un DNS dynamique, entrez-le ici. Les applications Media Browser pourront s'en servir pour les connexions \u00e0 distance.", + "LabelExternalDDNS": "Adresse WAN externe :", + "LabelExternalDDNSHelp": "Si vous poss\u00e9dez un DNS dynamique, entrez-le ici. Les applications Media Browser l'utiliseront pour se connecter \u00e0 distance. Laissez blanc pour conserver la d\u00e9tection automatique.", "TabResume": "Reprendre", "TabWeather": "M\u00e9t\u00e9o", "TitleAppSettings": "Param\u00e8tre de l'application", @@ -575,6 +607,7 @@ "ButtonRestart": "Red\u00e9marrer", "ButtonShutdown": "\u00c9teindre", "ButtonUpdateNow": "Mettre \u00e0 jour maintenant", + "TabHosting": "H\u00e9bergement", "PleaseUpdateManually": "Merci d'\u00e9teindre le serveur et de le mettre \u00e0 jour manuellement.", "NewServerVersionAvailable": "Une nouvelle version de Media Browser Server est disponible!", "ServerUpToDate": "Media Browser Server est \u00e0 jour", @@ -636,6 +669,7 @@ "NotificationOptionInstallationFailed": "\u00c9chec d'installation", "NotificationOptionNewLibraryContent": "Nouveau contenu ajout\u00e9", "NotificationOptionNewLibraryContentMultiple": "Nouveau contenu ajout\u00e9 (multiple)", + "NotificationOptionCameraImageUploaded": "L'image de l'appareil photo a \u00e9t\u00e9 upload\u00e9e", "SendNotificationHelp": "Par d\u00e9faut, les notifications sont d\u00e9livr\u00e9es dans la bo\u00eete de r\u00e9ception du tableau de bord. Consultez le catalogue de plugins pour installer des options de notifications suppl\u00e9mentaires.", "NotificationOptionServerRestartRequired": "Un red\u00e9marrage du serveur est requis", "LabelNotificationEnabled": "Activer cette notification", @@ -853,8 +887,10 @@ "OptionDefaultSort": "Par d\u00e9faut", "OptionCommunityMostWatchedSort": "Les plus lus", "TabNextUp": "Prochains \u00e0 voir", + "HeaderBecomeMediaBrowserSupporter": "Devenez supporteur de Media Browser", + "TextEnjoyBonusFeatures": "Profitez bien des fonctionnalit\u00e9s bonus", "MessageNoMovieSuggestionsAvailable": "Aucune suggestion de film n'est actuellement disponible. Commencez \u00e0 regarder et notez vos films pour avoir des suggestions.", - "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.", + "MessageNoCollectionsAvailable": "Les collections vous permettent de tirer parti de groupements personnalis\u00e9s de films, de s\u00e9ries, d'albums audio, de livres et de jeux. Cliquez sur le bouton + pour commencer \u00e0 cr\u00e9er des Collections.", "MessageNoPlaylistsAvailable": "Les listes de lectures vous permettent de cr\u00e9er des listes de contenus \u00e0 lire en continu en une fois. Pour ajouter un \u00e9l\u00e9ment \u00e0 la liste, faire un clic droit ou appuyer et maintenez, puis s\u00e9lectionnez Ajouter \u00e0 la liste de lecture", "MessageNoPlaylistItemsAvailable": "Cette liste de lecture est actuellement vide.", "ButtonDismiss": "Annuler", @@ -869,7 +905,6 @@ "LabelChannelDownloadAge": "Supprimer le contenu apr\u00e8s : (jours)", "LabelChannelDownloadAgeHelp": "Le contenu t\u00e9l\u00e9charg\u00e9 plus vieux que cette valeur sera supprim\u00e9. Il restera disponible \u00e0 la lecture par streaming Internet.", "ChannelSettingsFormHelp": "Installer des cha\u00eenes comme \"Trailers\" et \"Vimeo\" dans le catalogue des plugins.", - "LabelSelectCollection": "S\u00e9lectionner la collection :", "ButtonOptions": "Options", "ViewTypeMovies": "Films", "ViewTypeTvShows": "TV", @@ -917,7 +952,7 @@ "OptionLatestTvRecordings": "Les plus r\u00e9cents enregistrements", "LabelProtocolInfo": "Infos sur le protocole:", "LabelProtocolInfoHelp": "La valeur qui sera utilis\u00e9e pour r\u00e9pondre aux requ\u00eates GetProtocolInfo du p\u00e9riph\u00e9rique.", - "TabKodiMetadata": "Kodi", + "TabNfo": "Nfo", "HeaderKodiMetadataHelp": "Media Browser supporte nativement les m\u00e9tadonn\u00e9es Nfo et les images de Kodi. Pour activer ou d\u00e9sactiver les m\u00e9tadonn\u00e9es Kodi, utiliser l'onglet Avanc\u00e9 pour configurer les options de vos types de m\u00e9dias.", "LabelKodiMetadataUser": "Synchroniser les donn\u00e9es de visionnage utilisateur en nfo pour :", "LabelKodiMetadataUserHelp": "Activez cette option pour garder les donn\u00e9es de visionnage synchronis\u00e9es entre Media Browser et Kodi.", @@ -931,6 +966,7 @@ "LabelGroupChannelsIntoViews": "Afficher directement les cha\u00eenes suivantes dans mes vues.", "LabelGroupChannelsIntoViewsHelp": "Si activ\u00e9, ces cha\u00eenes seront directement affich\u00e9es \u00e0 c\u00f4t\u00e9 des autres vues. Si d\u00e9sactiv\u00e9, elles seront affich\u00e9es dans une vue de cha\u00eenes s\u00e9par\u00e9es.", "LabelDisplayCollectionsView": "Afficher un aper\u00e7u de collections pour montrer les collections de film", + "LabelDisplayCollectionsViewHelp": "Ceci cr\u00e9era une vue s\u00e9par\u00e9e pour l'affichage des collections que vous avez cr\u00e9\u00e9es ou auxquelles vous avez acc\u00e8s. Pour cr\u00e9er une collection, faites un clic-droit ou tapotez et maintenez l'\u00e9cran sur un film, puis choisissez 'Ajouter \u00e0 une collection'. ", "LabelKodiMetadataEnableExtraThumbs": "Copier les extrafanart dans les extrathumbs", "LabelKodiMetadataEnableExtraThumbsHelp": "Pendant le t\u00e9l\u00e9chargement, les images peuvent \u00eatre sauvegard\u00e9es en tant qu'extrafanart et extrathumbs pour am\u00e9liorer la compatibilit\u00e9 avec le skin Xbmc.", "TabServices": "Services", @@ -976,11 +1012,11 @@ "TabFilter": "Filtre", "ButtonView": "Affichage", "LabelPageSize": "Items par page :", - "LabelPath": "Chemin:", + "LabelPath": "Chemin", "LabelView": "Visualisation :", "TabUsers": "Utilisateurs", - "LabelSortName": "Clef de tri :", - "LabelDateAdded": "Date d'ajout:", + "LabelSortName": "Cl\u00e9 de tri", + "LabelDateAdded": "Date d'ajout", "HeaderFeatures": "Fonctionnalit\u00e9s", "HeaderAdvanced": "Avanc\u00e9", "ButtonSync": "Sync", @@ -1068,8 +1104,8 @@ "MessageApplicationUpdated": "Media Browser Server a \u00e9t\u00e9 mis \u00e0 jour.", "AuthenticationSucceededWithUserName": "{0} s'est authentifi\u00e9 avec succ\u00e8s", "FailedLoginAttemptWithUserName": "Echec d'une tentative de connexion de {0}", - "UserStartedPlayingItemWithValues": "{0} vient de commencer de lire {1}", - "UserStoppedPlayingItemWithValues": "{0} vient d'arr\u00eater de lire {1}", + "UserStartedPlayingItemWithValues": "{0} vient de commencer la lecture de {1}", + "UserStoppedPlayingItemWithValues": "{0} vient d'arr\u00eater la lecture de {1}", "AppDeviceValues": "Application : {0}, Appareil: {1}", "ProviderValue": "Fournisseur : {0}", "LabelChannelDownloadSizeLimit": "Taille limite de t\u00e9l\u00e9chargement (Go) :", @@ -1084,11 +1120,14 @@ "LabelDisplayFoldersView": "Afficher une vue mosa\u00efque pour montrer les dossiers media en int\u00e9gralit\u00e9.", "ViewTypeLiveTvRecordingGroups": "Enregistrements", "ViewTypeLiveTvChannels": "Cha\u00eenes", - "LabelAllowLocalAccessWithoutPassword": "Autoriser l'acc\u00e8s local sans un mot de passe", - "LabelAllowLocalAccessWithoutPasswordHelp": "Si activ\u00e9, le mot de passe ne sera pas requis pour s'authentifier depuis le r\u00e9seau local.", + "LabelEasyPinCode": "Code Easy Pin :", + "EasyPasswordHelp": "Votre code Easy Pin permet l'utilisation de l'acc\u00e8s offline dans les applications Media Browser compatibles, ainsi que l'authentification simplifi\u00e9e dans les r\u00e9seaux domestiques.", + "LabelInNetworkSignInWithEasyPassword": "Activer l'authentification simplifi\u00e9e dans les r\u00e9seaux domestiques avec mon code Easy Pin", + "LabelInNetworkSignInWithEasyPasswordHelp": "L'activation de cette option vous permet d'utiliser votre code Easy Pin pour vous connecter aux applications Media Browser depuis votre r\u00e9seau domestique. Votre mot de passe habituel ne sera n\u00e9cessaire que depuis l'ext\u00e9rieur. Si vous ne saisissez rien pour le code pin, vous n'aurez pas besoin de mot de passe depuis votre r\u00e9seau domestique.", "HeaderPassword": "Mot de passe", "HeaderLocalAccess": "Acc\u00e8s local", "HeaderViewOrder": "Ordre d'affichage", + "ButtonResetEasyPassword": "R\u00e9initialiser le code Easy Pin", "LabelSelectUserViewOrder": "Choisir l'ordre d'affichage qui sera utilis\u00e9 dans les applications de Media Browser", "LabelMetadataRefreshMode": "Mode de mise \u00e0 jour des m\u00e9tadonn\u00e9es :", "LabelImageRefreshMode": "Mode de mise \u00e0 jour des images :", @@ -1117,8 +1156,8 @@ "LabelTagline": "Slogan", "LabelOverview": "Synopsis", "LabelShortOverview": "R\u00e9sum\u00e9", - "LabelReleaseDate": "Date de sortie :", - "LabelYear": "Ann\u00e9e :", + "LabelReleaseDate": "Date de sortie", + "LabelYear": "Ann\u00e9e", "LabelPlaceOfBirth": "Lieu de naissance :", "LabelEndDate": "Date de fin:", "LabelAirDate": "Jours de diffusion", @@ -1128,9 +1167,9 @@ "LabelCustomRating": "Classification personnalis\u00e9e", "LabelBudget": "Budget", "LabelRevenue": "Box-office ($)", - "LabelOriginalAspectRatio": "Ratio d'aspect original:", + "LabelOriginalAspectRatio": "Ratio d'aspect original", "LabelPlayers": "Joueurs:", - "Label3DFormat": "Format 3D:", + "Label3DFormat": "Format 3D", "HeaderAlternateEpisodeNumbers": "Num\u00e9ros d'\u00e9pisode alternatif", "HeaderSpecialEpisodeInfo": "Information \u00e9pisode sp\u00e9cial", "HeaderExternalIds": "Identifiants externes", @@ -1250,7 +1289,7 @@ "LabelCreateCameraUploadSubfolder": "Cr\u00e9er un sous-dossier pour chaque appareil", "LabelCreateCameraUploadSubfolderHelp": "Des r\u00e9pertoires sp\u00e9cifiques peuvent \u00eatres affect\u00e9 aux appareils en cliquant sur le bouton correspondant dans la page des appareils.", "LabelCustomDeviceDisplayName": "Nom d'affichage:", - "LabelCustomDeviceDisplayNameHelp": "Entrez un nom d'affichage sp\u00e9cifique ou laissez vide pour utiliser le nom rapport\u00e9 par l'appareil.", + "LabelCustomDeviceDisplayNameHelp": "Entrez un nom d'affichage personnalis\u00e9 ou laissez vide pour utiliser le nom rapport\u00e9 par l'appareil.", "HeaderInviteUser": "Inviter un utilisateur", "LabelConnectGuestUserNameHelp": "C'est le nom d'utilisateur que votre ami(e) utilise pour se connecter au site Web de Media Browser, ou leur adresse mail.", "HeaderInviteUserHelp": "Partager vos m\u00e9dias avec vos amis est plus facile que jamais avec Connexion Media Browser.", @@ -1279,7 +1318,7 @@ "MessageNoTrailersFound": "Aucune bande-annonce trouv\u00e9e. Installez la cha\u00eene Bande-annonces pour am\u00e9liorer votre exp\u00e9rience, par l'ajout d'une biblioth\u00e8que de bandes-annonces disponibles sur Internet.", "HeaderNewUsers": "Nouveaux utilisateurs", "ButtonSignUp": "S'inscrire", - "ButtonForgotPassword": "Mot de passe oubli\u00e9 ?", + "ButtonForgotPassword": "Mot de passe oubli\u00e9", "OptionDisableUserPreferences": "D\u00e9sactiver l'acc\u00e8s aux pr\u00e9f\u00e9rences utilisateurs", "OptionDisableUserPreferencesHelp": "Si activ\u00e9, seuls les administrateurs seront capables de configurer les images de profil utilisateurs, les mots de passe, et les langues pr\u00e9f\u00e9r\u00e9es.", "HeaderSelectServer": "S\u00e9lectionner le serveur", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/he.json b/MediaBrowser.Server.Implementations/Localization/Server/he.json index bf3b05e80..5c80acb6c 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/he.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/he.json @@ -40,12 +40,32 @@ "OptionIAcceptTermsOfService": "I accept the terms of service", "ButtonPrivacyPolicy": "Privacy policy", "ButtonTermsOfService": "Terms of Service", + "HeaderDeveloperOptions": "Developer Options", + "OptionEnableWebClientResponseCache": "Enable web client response caching", + "OptionDisableForDevelopmentHelp": "Configure these as needed for web client development purposes.", + "OptionEnableWebClientResourceMinification": "Enable web client resource minification", + "LabelDashboardSourcePath": "Web client source path:", + "LabelDashboardSourcePathHelp": "If running the server from source, specify the path to the dashboard-ui folder. All web client files will be served from this location.", + "ButtonConvertMedia": "Convert media", + "ButtonOrganize": "Organize", "ButtonOk": "\u05d0\u05e9\u05e8", "ButtonCancel": "\u05d1\u05d8\u05dc", "ButtonNew": "\u05d7\u05d3\u05e9", "HeaderTV": "TV", "HeaderAudio": "Audio", "HeaderVideo": "Video", + "HeaderPaths": "Paths", + "CategorySync": "Sync", + "HeaderEasyPinCode": "Easy Pin Code", + "RegisterWithPayPal": "Register with PayPal", + "HeaderSyncRequiresSupporterMembership": "Sync Requires a Supporter Membership", + "HeaderEnjoyDayTrial": "Enjoy a 14 Day Free Trial", + "LabelSyncTempPath": "Temporary file path:", + "LabelSyncTempPathHelp": "Specify a custom sync working folder. Converted media created during the sync process will be stored here.", + "LabelCustomCertificatePath": "Custom certificate path:", + "LabelCustomCertificatePathHelp": "Supply your own ssl certificate. If omitted, the server will create a self-signed certificate.", + "TitleNotifications": "Notifications", + "ButtonDonateWithPayPal": "Donate with PayPal", "OptionDetectArchiveFilesAsMedia": "Detect archive files as media", "OptionDetectArchiveFilesAsMediaHelp": "If enabled, files with .rar and .zip extensions will be detected as media files.", "LabelEnterConnectUserName": "User name or email:", @@ -63,12 +83,14 @@ "FolderTypeTvShows": "TV", "FolderTypeInherit": "Inherit", "LabelContentType": "Content type:", + "TitleScheduledTasks": "Scheduled Tasks", "HeaderSetupLibrary": "\u05d4\u05d2\u05d3\u05e8 \u05d0\u05ea \u05e1\u05e4\u05e8\u05d9\u05d9\u05ea \u05d4\u05de\u05d3\u05d9\u05d4 \u05e9\u05dc\u05da", "ButtonAddMediaFolder": "\u05d4\u05d5\u05e1\u05e3 \u05ea\u05d9\u05e7\u05d9\u05d9\u05ea \u05de\u05d3\u05d9\u05d4", "LabelFolderType": "\u05e1\u05d5\u05d2 \u05d4\u05ea\u05d9\u05e7\u05d9\u05d9\u05d4:", "ReferToMediaLibraryWiki": "\u05e4\u05e0\u05d4 \u05dc\u05de\u05d9\u05d3\u05e2 \u05d0\u05d5\u05d3\u05d5\u05ea \u05e1\u05e4\u05e8\u05d9\u05d9\u05ea \u05d4\u05de\u05d3\u05d9\u05d4.", "LabelCountry": "\u05de\u05d3\u05d9\u05e0\u05d4:", "LabelLanguage": "\u05e9\u05e4\u05d4:", + "ButtonJoinTheDevelopmentTeam": "Join the Development Team", "HeaderPreferredMetadataLanguage": "\u05e9\u05e4\u05ea \u05de\u05d9\u05d3\u05e2 \u05de\u05d5\u05e2\u05d3\u05e4\u05ea:", "LabelSaveLocalMetadata": "\u05e9\u05de\u05d5\u05e8 \u05ea\u05de\u05d5\u05e0\u05d5\u05ea \u05e8\u05e7\u05e2 \u05d5\u05de\u05d9\u05d3\u05e2 \u05d1\u05ea\u05d5\u05da \u05e1\u05e4\u05e8\u05d9\u05d5\u05ea \u05d4\u05de\u05d3\u05d9\u05d4", "LabelSaveLocalMetadataHelp": "\u05e9\u05de\u05d9\u05e8\u05ea \u05ea\u05de\u05d5\u05e0\u05d5\u05ea \u05e8\u05e7\u05e2 \u05d5\u05de\u05d9\u05d3\u05e2 \u05d9\u05e9\u05d9\u05e8\u05d5\u05ea \u05d1\u05e1\u05e4\u05e8\u05d9\u05d5\u05ea \u05d4\u05de\u05d3\u05d9\u05d4 \u05ea\u05d0\u05e4\u05e9\u05e8 \u05e2\u05e8\u05d9\u05db\u05d4 \u05e0\u05d5\u05d7\u05d4 \u05d5\u05e7\u05dc\u05d4 \u05e9\u05dc\u05d4\u05dd.", @@ -86,6 +108,8 @@ "TabCollectionTitles": "\u05db\u05d5\u05ea\u05e8\u05d9\u05dd", "HeaderDeviceAccess": "Device Access", "OptionEnableAccessFromAllDevices": "Enable access from all devices", + "OptionEnableAccessToAllChannels": "Enable access to all channels", + "OptionEnableAccessToAllLibraries": "Enable access to all libraries", "DeviceAccessHelp": "This only applies to devices that can be uniquely identified and will not prevent browser access. Filtering user device access will prevent them from using new devices until they've been approved here.", "LabelDisplayMissingEpisodesWithinSeasons": "\u05d4\u05e6\u05d2 \u05e4\u05e8\u05e7\u05d9\u05dd \u05d7\u05e1\u05e8\u05d9\u05dd \u05d1\u05ea\u05d5\u05da \u05d4\u05e2\u05d5\u05e0\u05d5\u05ea", "LabelUnairedMissingEpisodesWithinSeasons": "\u05d4\u05e6\u05d2 \u05e4\u05e8\u05e7\u05d9\u05dd \u05e9\u05e2\u05d3\u05d9\u05df \u05d0\u05dc \u05e9\u05d5\u05d3\u05e8\u05d5 \u05d1\u05ea\u05d5\u05da \u05d4\u05e2\u05d5\u05e0\u05d5\u05ea", @@ -299,7 +323,7 @@ "LabelCachePath": "\u05e0\u05ea\u05d9\u05d1 cache:", "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.", "LabelImagesByNamePath": "\u05e0\u05ea\u05d9\u05d1 \u05ea\u05d9\u05e7\u05d9\u05d9\u05ea Images by name:", - "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, genre and studio images.", "LabelMetadataPath": "\u05e0\u05ea\u05d9\u05d1 Metadata:", "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.", "LabelTranscodingTempPath": "\u05e0\u05ea\u05d9\u05d1 \u05dc\u05e7\u05d9\u05d3\u05d5\u05d3 \u05d6\u05de\u05e0\u05d9:", @@ -314,12 +338,14 @@ "OptionEpisodes": "\u05e4\u05e8\u05e7\u05d9\u05dd", "OptionOtherVideos": "\u05e7\u05d8\u05e2\u05d9 \u05d5\u05d5\u05d9\u05d3\u05d9\u05d0\u05d5 \u05d0\u05d7\u05e8\u05d9\u05dd", "TitleMetadata": "Metadata", - "LabelAutomaticUpdatesFanart": "\u05d0\u05e4\u05e9\u05e8 \u05e2\u05d3\u05db\u05d5\u05e0\u05d9\u05dd \u05d0\u05d5\u05d8\u05d5\u05de\u05d8\u05d9\u05dd \u05de- FanArt.tv", + "LabelAutomaticUpdates": "Enable automatic updates", "LabelAutomaticUpdatesTmdb": "\u05d0\u05e4\u05e9\u05e8 \u05e2\u05d3\u05db\u05d5\u05e0\u05d9\u05dd \u05d0\u05d5\u05d8\u05d5\u05de\u05d8\u05d9\u05dd \u05de- TheMovieDB.org", "LabelAutomaticUpdatesTvdb": "\u05d0\u05e4\u05e9\u05e8 \u05e2\u05d9\u05d3\u05db\u05d5\u05e0\u05d9\u05dd \u05d0\u05d5\u05d8\u05d5\u05de\u05d8\u05d9\u05dd \u05de- TVDB.com", "LabelAutomaticUpdatesFanartHelp": "\u05d0\u05dd \u05de\u05d5\u05e4\u05e2\u05dc, \u05ea\u05de\u05d5\u05e0\u05d5\u05ea \u05d7\u05d3\u05e9\u05d5\u05ea \u05d9\u05e8\u05d3\u05d5 \u05d1\u05e6\u05d5\u05e8\u05d4 \u05d0\u05d5\u05d8\u05d5\u05de\u05d8\u05d9\u05ea \u05db\u05d0\u05e9\u05e8 \u05d4\u05df \u05e0\u05d5\u05e1\u05e4\u05d5\u05ea \u05dc- fanart.tv. \u05ea\u05de\u05d5\u05e0\u05d5\u05ea \u05e7\u05d9\u05d9\u05de\u05d5\u05ea \u05dc\u05d0 \u05d9\u05d5\u05d7\u05dc\u05e4\u05d5.", "LabelAutomaticUpdatesTmdbHelp": "\u05d0\u05dd \u05de\u05d5\u05e4\u05e2\u05dc, \u05ea\u05de\u05d5\u05e0\u05d5\u05ea \u05d7\u05d3\u05e9\u05d5\u05ea \u05d9\u05e8\u05d3\u05d5 \u05d1\u05e6\u05d5\u05e8\u05d4 \u05d0\u05d5\u05d8\u05d5\u05de\u05d8\u05d9\u05ea \u05db\u05d0\u05e9\u05e8 \u05d4\u05df \u05e0\u05d5\u05e1\u05e4\u05d5\u05ea \u05dc- TheMovieDB.org. \u05ea\u05de\u05d5\u05e0\u05d5\u05ea \u05e7\u05d9\u05d9\u05de\u05d5\u05ea \u05dc\u05d0 \u05d9\u05d5\u05d7\u05dc\u05e4\u05d5.", "LabelAutomaticUpdatesTvdbHelp": "\u05d0\u05dd \u05de\u05d5\u05e4\u05e2\u05dc, \u05ea\u05de\u05d5\u05e0\u05d5\u05ea \u05d7\u05d3\u05e9\u05d5\u05ea \u05d9\u05e8\u05d3\u05d5 \u05d1\u05e6\u05d5\u05e8\u05d4 \u05d0\u05d5\u05d8\u05d5\u05de\u05d8\u05d9\u05ea \u05db\u05d0\u05e9\u05e8 \u05d4\u05df \u05e0\u05d5\u05e1\u05e4\u05d5\u05ea \u05dc- TVDB.com. \u05ea\u05de\u05d5\u05e0\u05d5\u05ea \u05e7\u05d9\u05d9\u05de\u05d5\u05ea \u05dc\u05d0 \u05d9\u05d5\u05d7\u05dc\u05e4\u05d5.", + "LabelFanartApiKey": "Personal api key:", + "LabelFanartApiKeyHelp": "Requests to fanart without a personal API key return results that were approved over 7 days ago. With a personal API key that drops to 48 hours and if you are also a fanart VIP member that will further drop to around 10 minutes.", "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", "LabelMetadataDownloadLanguage": "\u05e9\u05e4\u05ea \u05d4\u05d5\u05e8\u05d3\u05d4 \u05de\u05d5\u05e2\u05d3\u05e4\u05ea:", "ButtonAutoScroll": "\u05d2\u05dc\u05d9\u05dc\u05d4 \u05d0\u05d5\u05d8\u05d5\u05de\u05d8\u05d9\u05ea", @@ -487,6 +513,7 @@ "HeaderSystemPaths": "\u05e0\u05ea\u05d9\u05d1\u05d9 \u05de\u05e2\u05e8\u05db\u05ea", "LinkCommunity": "\u05e7\u05d4\u05d9\u05dc\u05d4", "LinkGithub": "Github", + "LinkApi": "Api", "LinkApiDocumentation": "\u05de\u05e1\u05de\u05db\u05d9 \u05e2\u05e8\u05db\u05ea \u05e4\u05d9\u05ea\u05d5\u05d7", "LabelFriendlyServerName": "\u05e9\u05dd \u05e9\u05e8\u05ea \u05d9\u05d3\u05d9\u05d3\u05d5\u05ea\u05d9:", "LabelFriendlyServerNameHelp": "\u05d4\u05e9\u05dd \u05d9\u05ea\u05df \u05dc\u05d6\u05d9\u05d4\u05d5\u05d9 \u05d4\u05e9\u05e8\u05ea. \u05d0\u05dd \u05de\u05d5\u05e9\u05d0\u05e8 \u05e8\u05d9\u05e7, \u05e9\u05dd \u05d4\u05e9\u05e8\u05ea \u05d9\u05d4\u05d9\u05d4 \u05e9\u05dd \u05d4\u05de\u05d7\u05e9\u05d1.", @@ -494,20 +521,25 @@ "LabelPreferredDisplayLanguageHelp": "\u05ea\u05e8\u05d2\u05d5\u05dd Media Browser \u05d4\u05d5\u05d0 \u05ea\u05d4\u05dc\u05d9\u05da \u05d1\u05d4\u05ea\u05d4\u05d5\u05d5\u05ea \u05d5\u05e2\u05d3\u05d9\u05df \u05dc\u05d0 \u05de\u05d5\u05e9\u05dc\u05dd.", "LabelReadHowYouCanContribute": "\u05e7\u05e8\u05d0 \u05db\u05d9\u05e6\u05d3 \u05d0\u05ea\u05d4 \u05d9\u05db\u05d5\u05dc \u05dc\u05ea\u05e8\u05d5\u05dd.", "HeaderNewCollection": "\u05d0\u05d5\u05e4\u05e1\u05d9\u05dd \u05d7\u05d3\u05e9\u05d9\u05dd", - "HeaderAddToCollection": "Add to Collection", "ButtonSubmit": "Submit", - "NewCollectionNameExample": "\u05dc\u05d3\u05d5\u05d2\u05de\u05d0 :\u05d0\u05d5\u05e1\u05e3 \u05de\u05dc\u05d7\u05de\u05ea \u05d4\u05db\u05d5\u05db\u05d1\u05d9\u05dd", - "OptionSearchForInternetMetadata": "\u05d7\u05e4\u05e9 \u05d1\u05d0\u05d9\u05e0\u05e8\u05e0\u05d8 \u05d0\u05d7\u05e8\u05d9 \u05de\u05d9\u05d3\u05e2 \u05d5\u05ea\u05de\u05d5\u05e0\u05d5\u05ea", "ButtonCreate": "\u05e6\u05d5\u05e8", - "LabelLocalHttpServerPortNumber": "Local port number:", + "LabelCustomCss": "Custom css:", + "LabelCustomCssHelp": "Apply your own custom css to the web interface.", + "LabelLocalHttpServerPortNumber": "Local http port number:", "LabelLocalHttpServerPortNumberHelp": "The tcp port number that Media Browser's http server should bind to.", - "LabelPublicPort": "Public port number:", - "LabelPublicPortHelp": "The public port number that should be mapped to the local port.", + "LabelPublicHttpPort": "Public http port number:", + "LabelPublicHttpPortHelp": "The public port number that should be mapped to the local http port.", + "LabelPublicHttpsPort": "Public https port number:", + "LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.", + "LabelEnableHttps": "Report https as external address", + "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.", + "LabelHttpsPort": "Local https port number:", + "LabelHttpsPortHelp": "The tcp port number that Media Browser's https server should bind to.", "LabelWebSocketPortNumber": "\u05e4\u05d5\u05e8\u05d8 Web socket:", "LabelEnableAutomaticPortMap": "Enable automatic port mapping", "LabelEnableAutomaticPortMapHelp": "Attempt to automatically map the public port to the local port via UPnP. This may not work with some router models.", - "LabelExternalDDNS": "External DDNS:", - "LabelExternalDDNSHelp": "\u05d0\u05dd \u05d9\u05e9 \u05dc\u05da \u05db\u05ea\u05d5\u05d1\u05ea DNS \u05d3\u05d9\u05e0\u05d0\u05de\u05d9\u05ea \u05d4\u05db\u05e0\u05e1 \u05d0\u05d5\u05ea\u05d4 \u05db\u05d0\u05df. Media Browser \u05d9\u05e9\u05ea\u05de\u05e9 \u05d1\u05d4 \u05dc\u05d4\u05ea\u05d7\u05d1\u05e8\u05d5\u05ea \u05de\u05e8\u05d7\u05d5\u05e7.", + "LabelExternalDDNS": "External WAN Address:", + "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely. Leave empty for automatic detection.", "TabResume": "\u05d4\u05de\u05e9\u05da", "TabWeather": "\u05de\u05d6\u05d2 \u05d0\u05d5\u05d5\u05d9\u05e8", "TitleAppSettings": "\u05d4\u05d2\u05d3\u05e8\u05d5\u05ea \u05d0\u05e4\u05dc\u05d9\u05e7\u05e6\u05d9\u05d4", @@ -575,6 +607,7 @@ "ButtonRestart": "\u05d4\u05ea\u05d7\u05e8 \u05de\u05d7\u05d3\u05e9", "ButtonShutdown": "\u05db\u05d1\u05d4", "ButtonUpdateNow": "\u05e2\u05d3\u05db\u05df \u05e2\u05db\u05e9\u05d9\u05d5", + "TabHosting": "Hosting", "PleaseUpdateManually": "\u05d0\u05e0\u05d0, \u05db\u05d1\u05d4 \u05d0\u05ea \u05d4\u05e9\u05e8\u05ea \u05d5\u05e2\u05d3\u05db\u05df \u05d9\u05d3\u05e0\u05d9\u05ea.", "NewServerVersionAvailable": "\u05d2\u05e8\u05e1\u05d0 \u05d7\u05d3\u05e9\u05d4 \u05e9\u05dc Media Browser Server \u05e0\u05de\u05e6\u05d0\u05d4!", "ServerUpToDate": "Media Browser Server \u05de\u05e2\u05d5\u05d3\u05db\u05df", @@ -636,6 +669,7 @@ "NotificationOptionInstallationFailed": "\u05d4\u05ea\u05e7\u05e0\u05d4 \u05e0\u05db\u05e9\u05dc\u05d4", "NotificationOptionNewLibraryContent": "\u05ea\u05d5\u05db\u05df \u05d7\u05d3\u05e9 \u05e0\u05d5\u05e1\u05e3", "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", + "NotificationOptionCameraImageUploaded": "Camera image uploaded", "SendNotificationHelp": "\u05d1\u05e8\u05d9\u05e8\u05ea \u05d4\u05de\u05d7\u05d3\u05dc \u05d4\u05d9\u05d0 \u05e9\u05d4\u05ea\u05e8\u05d0\u05d5\u05ea \u05de\u05d2\u05d9\u05e2\u05d5\u05ea \u05dc\u05ea\u05d9\u05d1\u05ea \u05d4\u05d3\u05d5\u05d0\u05e8 \u05d4\u05e0\u05db\u05e0\u05e1 \u05e9\u05dc \u05dc\u05d5\u05d7 \u05d4\u05d1\u05e7\u05e8\u05d4. \u05e2\u05d9\u05d9\u05df \u05d1\u05e7\u05d8\u05dc\u05d5\u05d2 \u05d4\u05ea\u05d5\u05e1\u05e4\u05d9\u05dd \u05db\u05d3\u05d9 \u05dc\u05d4\u05ea\u05e7\u05d9\u05df \u05d0\u05e4\u05e9\u05e8\u05d5\u05d9\u05d5\u05ea \u05e0\u05d5\u05e1\u05e4\u05d5\u05ea \u05dc\u05e7\u05d1\u05dc\u05ea \u05d4\u05ea\u05e8\u05d0\u05d5\u05ea", "NotificationOptionServerRestartRequired": "\u05e0\u05d3\u05e8\u05e9\u05ea \u05d4\u05e4\u05e2\u05dc\u05d4 \u05de\u05d7\u05d3\u05e9 \u05e9\u05dc \u05d4\u05e9\u05e8\u05ea", "LabelNotificationEnabled": "\u05d0\u05e4\u05e9\u05e8 \u05d4\u05ea\u05e8\u05d0\u05d4 \u05d6\u05d5", @@ -853,6 +887,8 @@ "OptionDefaultSort": "Default", "OptionCommunityMostWatchedSort": "Most Watched", "TabNextUp": "Next Up", + "HeaderBecomeMediaBrowserSupporter": "Become a Media Browser Supporter", + "TextEnjoyBonusFeatures": "Enjoy Bonus Features", "MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.", "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.", "MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.", @@ -869,7 +905,6 @@ "LabelChannelDownloadAge": "Delete content after: (days)", "LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.", "ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.", - "LabelSelectCollection": "Select collection:", "ButtonOptions": "Options", "ViewTypeMovies": "Movies", "ViewTypeTvShows": "TV", @@ -917,7 +952,7 @@ "OptionLatestTvRecordings": "Latest recordings", "LabelProtocolInfo": "Protocol info:", "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.", - "TabKodiMetadata": "Kodi", + "TabNfo": "Nfo", "HeaderKodiMetadataHelp": "Media Browser includes native support for Kodi Nfo metadata and images. To enable or disable Kodi metadata, use the Advanced tab to configure options for your media types.", "LabelKodiMetadataUser": "Sync user watch data to nfo's for:", "LabelKodiMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Kodi.", @@ -931,6 +966,7 @@ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:", "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.", "LabelDisplayCollectionsView": "Display a collections view to show movie collections", + "LabelDisplayCollectionsViewHelp": "This will create a separate view to display collections that you've created or have access to. To create a collection, right-click or tap-hold any movie and select 'Add to Collection'. ", "LabelKodiMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs", "LabelKodiMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Kodi skin compatibility.", "TabServices": "Services", @@ -1084,11 +1120,14 @@ "LabelDisplayFoldersView": "Display a folders view to show plain media folders", "ViewTypeLiveTvRecordingGroups": "Recordings", "ViewTypeLiveTvChannels": "Channels", - "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password", - "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.", + "LabelEasyPinCode": "Easy pin code:", + "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Media Browser apps, and can also be used for easy in-network sign in.", + "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", + "LabelInNetworkSignInWithEasyPasswordHelp": "If enabled, you'll be able to use your easy pin code to sign in to Media Browser apps from inside your home network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", "HeaderPassword": "Password", "HeaderLocalAccess": "Local Access", "HeaderViewOrder": "View Order", + "ButtonResetEasyPassword": "Reset easy pin code", "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps", "LabelMetadataRefreshMode": "Metadata refresh mode:", "LabelImageRefreshMode": "Image refresh mode:", @@ -1279,7 +1318,7 @@ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.", "HeaderNewUsers": "New Users", "ButtonSignUp": "Sign up", - "ButtonForgotPassword": "Forgot password?", + "ButtonForgotPassword": "Forgot password", "OptionDisableUserPreferences": "Disable access to user preferences", "OptionDisableUserPreferencesHelp": "If enabled, only administrators will be able to configure user profile images, passwords, and language preferences.", "HeaderSelectServer": "Select Server", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/hr.json b/MediaBrowser.Server.Implementations/Localization/Server/hr.json index 80c558a55..184dae0ad 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/hr.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/hr.json @@ -40,12 +40,32 @@ "OptionIAcceptTermsOfService": "I accept the terms of service", "ButtonPrivacyPolicy": "Privacy policy", "ButtonTermsOfService": "Terms of Service", + "HeaderDeveloperOptions": "Developer Options", + "OptionEnableWebClientResponseCache": "Enable web client response caching", + "OptionDisableForDevelopmentHelp": "Configure these as needed for web client development purposes.", + "OptionEnableWebClientResourceMinification": "Enable web client resource minification", + "LabelDashboardSourcePath": "Web client source path:", + "LabelDashboardSourcePathHelp": "If running the server from source, specify the path to the dashboard-ui folder. All web client files will be served from this location.", + "ButtonConvertMedia": "Convert media", + "ButtonOrganize": "Organize", "ButtonOk": "Ok", "ButtonCancel": "Odustani", "ButtonNew": "Novo", "HeaderTV": "TV", "HeaderAudio": "Audio", "HeaderVideo": "Video", + "HeaderPaths": "Paths", + "CategorySync": "Sync", + "HeaderEasyPinCode": "Easy Pin Code", + "RegisterWithPayPal": "Register with PayPal", + "HeaderSyncRequiresSupporterMembership": "Sync Requires a Supporter Membership", + "HeaderEnjoyDayTrial": "Enjoy a 14 Day Free Trial", + "LabelSyncTempPath": "Temporary file path:", + "LabelSyncTempPathHelp": "Specify a custom sync working folder. Converted media created during the sync process will be stored here.", + "LabelCustomCertificatePath": "Custom certificate path:", + "LabelCustomCertificatePathHelp": "Supply your own ssl certificate. If omitted, the server will create a self-signed certificate.", + "TitleNotifications": "Notifications", + "ButtonDonateWithPayPal": "Donate with PayPal", "OptionDetectArchiveFilesAsMedia": "Detect archive files as media", "OptionDetectArchiveFilesAsMediaHelp": "If enabled, files with .rar and .zip extensions will be detected as media files.", "LabelEnterConnectUserName": "User name or email:", @@ -63,12 +83,14 @@ "FolderTypeTvShows": "TV", "FolderTypeInherit": "Inherit", "LabelContentType": "Content type:", + "TitleScheduledTasks": "Scheduled Tasks", "HeaderSetupLibrary": "Postavi svoju medijsku biblioteku", "ButtonAddMediaFolder": "Dodaj mapu sa medijem", "LabelFolderType": "Tip mape:", "ReferToMediaLibraryWiki": "Informirajte se o medijskoj bibilioteci wiki", "LabelCountry": "Zemlja:", "LabelLanguage": "Jezik:", + "ButtonJoinTheDevelopmentTeam": "Join the Development Team", "HeaderPreferredMetadataLanguage": "\u017deljeni metadata jezik:", "LabelSaveLocalMetadata": "Snimi ilustracije i metadata u medijske mape", "LabelSaveLocalMetadataHelp": "Snimljene ilustracije i metadata u medijskim mapama \u0107e biti postavljene na lokaciju gdje \u0107e se mo\u0107i jednostavno mjenjati.", @@ -86,6 +108,8 @@ "TabCollectionTitles": "Naslovi", "HeaderDeviceAccess": "Device Access", "OptionEnableAccessFromAllDevices": "Enable access from all devices", + "OptionEnableAccessToAllChannels": "Enable access to all channels", + "OptionEnableAccessToAllLibraries": "Enable access to all libraries", "DeviceAccessHelp": "This only applies to devices that can be uniquely identified and will not prevent browser access. Filtering user device access will prevent them from using new devices until they've been approved here.", "LabelDisplayMissingEpisodesWithinSeasons": "Prika\u017ei epizode koje nedostaju unutar sezone", "LabelUnairedMissingEpisodesWithinSeasons": "Prika\u017ei epizode koje nisu emitirane unutar sezone", @@ -299,7 +323,7 @@ "LabelCachePath": "Cache path:", "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.", "LabelImagesByNamePath": "Images by name path:", - "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, genre and studio images.", "LabelMetadataPath": "Metadata path:", "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.", "LabelTranscodingTempPath": "Transcoding temporary path:", @@ -314,12 +338,14 @@ "OptionEpisodes": "Episodes", "OptionOtherVideos": "Other Videos", "TitleMetadata": "Metadata", - "LabelAutomaticUpdatesFanart": "Enable automatic updates from FanArt.tv", + "LabelAutomaticUpdates": "Enable automatic updates", "LabelAutomaticUpdatesTmdb": "Enable automatic updates from TheMovieDB.org", "LabelAutomaticUpdatesTvdb": "Enable automatic updates from TheTVDB.com", "LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.", "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.", "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.", + "LabelFanartApiKey": "Personal api key:", + "LabelFanartApiKeyHelp": "Requests to fanart without a personal API key return results that were approved over 7 days ago. With a personal API key that drops to 48 hours and if you are also a fanart VIP member that will further drop to around 10 minutes.", "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", "LabelMetadataDownloadLanguage": "Preferred download language:", "ButtonAutoScroll": "Auto-scroll", @@ -487,6 +513,7 @@ "HeaderSystemPaths": "Sistemska putanja", "LinkCommunity": "Zajednica", "LinkGithub": "Github", + "LinkApi": "Api", "LinkApiDocumentation": "Api dokumentacija", "LabelFriendlyServerName": "Prijateljsko ime servera:", "LabelFriendlyServerNameHelp": "Ovo ime \u0107e se koristiti za identifikaciju servera. Ako ostavite prazno, ime ra\u010dunala \u0107e se koristi kao identifikator.", @@ -494,20 +521,25 @@ "LabelPreferredDisplayLanguageHelp": "Prevo\u0111enje Media Browsera je projekt u tjeku i nije jo\u0161 zavr\u0161en.", "LabelReadHowYouCanContribute": "Pro\u010ditajte kako mo\u017eete doprinjeti.", "HeaderNewCollection": "Nova kolekcija", - "HeaderAddToCollection": "Add to Collection", "ButtonSubmit": "Submit", - "NewCollectionNameExample": "Naprimjer: Star Wars Kolekcija", - "OptionSearchForInternetMetadata": "Potra\u017ei na internetu grafike i metadata", "ButtonCreate": "Kreiraj", - "LabelLocalHttpServerPortNumber": "Local port number:", + "LabelCustomCss": "Custom css:", + "LabelCustomCssHelp": "Apply your own custom css to the web interface.", + "LabelLocalHttpServerPortNumber": "Local http port number:", "LabelLocalHttpServerPortNumberHelp": "The tcp port number that Media Browser's http server should bind to.", - "LabelPublicPort": "Public port number:", - "LabelPublicPortHelp": "The public port number that should be mapped to the local port.", + "LabelPublicHttpPort": "Public http port number:", + "LabelPublicHttpPortHelp": "The public port number that should be mapped to the local http port.", + "LabelPublicHttpsPort": "Public https port number:", + "LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.", + "LabelEnableHttps": "Report https as external address", + "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.", + "LabelHttpsPort": "Local https port number:", + "LabelHttpsPortHelp": "The tcp port number that Media Browser's https server should bind to.", "LabelWebSocketPortNumber": "Port Web priklju\u010dka:", "LabelEnableAutomaticPortMap": "Enable automatic port mapping", "LabelEnableAutomaticPortMapHelp": "Attempt to automatically map the public port to the local port via UPnP. This may not work with some router models.", - "LabelExternalDDNS": "Vanjski DDNS:", - "LabelExternalDDNSHelp": "Ako imate dinami\u010dni DNS unesite ga ovdje. Media Browser aplikacije \u0107e ga koristiti kada se spajate sa udaljene lokacije.", + "LabelExternalDDNS": "External WAN Address:", + "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely. Leave empty for automatic detection.", "TabResume": "Nastavi", "TabWeather": "Vrijeme", "TitleAppSettings": "Postavke aplikacije", @@ -575,6 +607,7 @@ "ButtonRestart": "Ponovo pokreni", "ButtonShutdown": "Ugasi", "ButtonUpdateNow": "A\u017euriraj sad", + "TabHosting": "Hosting", "PleaseUpdateManually": "Molimo ugasite server i a\u017eurirati ru\u010dno", "NewServerVersionAvailable": "Nova verzija Media Browser-a je dostupna!", "ServerUpToDate": "Media Browser Server je ve\u0107 na trenutnoj verziji", @@ -636,6 +669,7 @@ "NotificationOptionInstallationFailed": "Instalacija nije izvr\u0161ena", "NotificationOptionNewLibraryContent": "Novi sadr\u017eaj dodan", "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", + "NotificationOptionCameraImageUploaded": "Camera image uploaded", "SendNotificationHelp": "Zadano je da se sve obavijesti dostave na upravlja\u010dku plo\u010du. Pretra\u017eite katalog dodataka kako bi instalirali dodatne opcije obavijesti.", "NotificationOptionServerRestartRequired": "Potrebno ponovo pokretanje servera", "LabelNotificationEnabled": "Omogu\u0107i ovu obavijest", @@ -853,6 +887,8 @@ "OptionDefaultSort": "Default", "OptionCommunityMostWatchedSort": "Most Watched", "TabNextUp": "Next Up", + "HeaderBecomeMediaBrowserSupporter": "Become a Media Browser Supporter", + "TextEnjoyBonusFeatures": "Enjoy Bonus Features", "MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.", "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.", "MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.", @@ -869,7 +905,6 @@ "LabelChannelDownloadAge": "Delete content after: (days)", "LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.", "ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.", - "LabelSelectCollection": "Select collection:", "ButtonOptions": "Options", "ViewTypeMovies": "Movies", "ViewTypeTvShows": "TV", @@ -917,7 +952,7 @@ "OptionLatestTvRecordings": "Latest recordings", "LabelProtocolInfo": "Protocol info:", "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.", - "TabKodiMetadata": "Kodi", + "TabNfo": "Nfo", "HeaderKodiMetadataHelp": "Media Browser includes native support for Kodi Nfo metadata and images. To enable or disable Kodi metadata, use the Advanced tab to configure options for your media types.", "LabelKodiMetadataUser": "Sync user watch data to nfo's for:", "LabelKodiMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Kodi.", @@ -931,6 +966,7 @@ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:", "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.", "LabelDisplayCollectionsView": "Display a collections view to show movie collections", + "LabelDisplayCollectionsViewHelp": "This will create a separate view to display collections that you've created or have access to. To create a collection, right-click or tap-hold any movie and select 'Add to Collection'. ", "LabelKodiMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs", "LabelKodiMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Kodi skin compatibility.", "TabServices": "Services", @@ -1084,11 +1120,14 @@ "LabelDisplayFoldersView": "Display a folders view to show plain media folders", "ViewTypeLiveTvRecordingGroups": "Recordings", "ViewTypeLiveTvChannels": "Channels", - "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password", - "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.", + "LabelEasyPinCode": "Easy pin code:", + "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Media Browser apps, and can also be used for easy in-network sign in.", + "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", + "LabelInNetworkSignInWithEasyPasswordHelp": "If enabled, you'll be able to use your easy pin code to sign in to Media Browser apps from inside your home network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", "HeaderPassword": "Password", "HeaderLocalAccess": "Local Access", "HeaderViewOrder": "View Order", + "ButtonResetEasyPassword": "Reset easy pin code", "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps", "LabelMetadataRefreshMode": "Metadata refresh mode:", "LabelImageRefreshMode": "Image refresh mode:", @@ -1279,7 +1318,7 @@ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.", "HeaderNewUsers": "New Users", "ButtonSignUp": "Sign up", - "ButtonForgotPassword": "Forgot password?", + "ButtonForgotPassword": "Forgot password", "OptionDisableUserPreferences": "Disable access to user preferences", "OptionDisableUserPreferencesHelp": "If enabled, only administrators will be able to configure user profile images, passwords, and language preferences.", "HeaderSelectServer": "Select Server", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/it.json b/MediaBrowser.Server.Implementations/Localization/Server/it.json index abce40acd..f8899d1fd 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/it.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/it.json @@ -27,7 +27,7 @@ "AWindowsServiceHasBeenInstalled": "Servizio Windows Installato", "WindowsServiceIntro1": "Media Browser Server, normalmente viene eseguito come un'applicazione desktop con un' icona nella barra, ma se invece si preferisce farlo funzionare come un servizio in background, pu\u00f2 essere avviato dal pannello di controllo dei servizi di Windows", "WindowsServiceIntro2": "Se si utilizza il servizio di Windows, si ricorda che non pu\u00f2 essere eseguito allo stesso tempo con l'icona di sistema, quindi devi chiudere l'applicazione al fine di eseguire il servizio. Il servizio dovr\u00e0 anche essere configurato con privilegi amministrativi tramite il pannello di controllo. Si prega di notare che in questo momento il servizio non \u00e8 in grado di Autoaggiornarsi, quindi le nuove versioni richiedono l'interazione manuale", - "WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click <b>Finish<\/b> to view the <b>Server Dashboard<\/b>.", + "WizardCompleted": "Questo \u00e8 tutto ci\u00f2 che ci serve per ora. Media Browser ha cominciato a raccogliere informazioni sulla tua libreria. Dai un'occhiata alle nostre app, e poi clicca su <b>Fine<\/b> per andare alla <b>Pagina Principale<\/b>", "LabelConfigureSettings": "Configura", "LabelEnableVideoImageExtraction": "Abilita estrazione immagine video", "VideoImageExtractionHelp": "Per i video che sono sprovvisti di immagini, e per i quali non siamo riusciti a trovare immagini su Internet.Questo aggiunger\u00e0 del tempo addizionale alla scansione della tua libreria ma si tradurr\u00e0 in una presentazione pi\u00f9 piacevole.", @@ -40,14 +40,34 @@ "OptionIAcceptTermsOfService": "Accetto i termini di servizio", "ButtonPrivacyPolicy": "Informativa sulla privacy", "ButtonTermsOfService": "Termini di Servizio", + "HeaderDeveloperOptions": "Opzioni Sviluppatore", + "OptionEnableWebClientResponseCache": "Abilita la cache del client web", + "OptionDisableForDevelopmentHelp": "Configura questi parametri per sviluppatori del client web", + "OptionEnableWebClientResourceMinification": "Enable web client resource minification", + "LabelDashboardSourcePath": "Percorso sorgente client web", + "LabelDashboardSourcePathHelp": "se si sta eseguendo il server da una sorgente, specifica il percorso dell'interfaccia. Tutti i file per i client saranno presi da questo percorso", + "ButtonConvertMedia": "Converti media", + "ButtonOrganize": "Organizza", "ButtonOk": "OK", "ButtonCancel": "Annulla", "ButtonNew": "Nuovo", "HeaderTV": "TV", "HeaderAudio": "Audio", "HeaderVideo": "Video", - "OptionDetectArchiveFilesAsMedia": "Detect archive files as media", - "OptionDetectArchiveFilesAsMediaHelp": "If enabled, files with .rar and .zip extensions will be detected as media files.", + "HeaderPaths": "Percorsi", + "CategorySync": "Sinc.zza", + "HeaderEasyPinCode": "Codice pin", + "RegisterWithPayPal": "Registra con PayPal", + "HeaderSyncRequiresSupporterMembership": "La sincronizzazione richiede un'iscrizione come supporter", + "HeaderEnjoyDayTrial": "Goditi la tua prova gratuita di 14 giorni", + "LabelSyncTempPath": "Percorso file temporanei", + "LabelSyncTempPathHelp": "Specifica una cartella per la sincronizzazione. I file multimediali convertiti durante la sincronizzazione verranno collocati qui.", + "LabelCustomCertificatePath": "Percorso certificati personalizzato:", + "LabelCustomCertificatePathHelp": "Fornisci il tuo certificato SSL. Se non impostato il server ne creer\u00e0 uno gi\u00e0 firmato.", + "TitleNotifications": "Notifiche", + "ButtonDonateWithPayPal": "Effettua una donazione con PayPal", + "OptionDetectArchiveFilesAsMedia": "Considera gli archivi come file multimediali", + "OptionDetectArchiveFilesAsMediaHelp": "se attivato, i file con estensione .rar e .zip saranno considerati come file multimediali.", "LabelEnterConnectUserName": "Nome Utente o email:", "LabelEnterConnectUserNameHelp": "Questo \u00e8 il tuo nome utente, o password, per il tuo account online di Media Browser.", "HeaderSyncJobInfo": "Attiv. di Sinc.", @@ -63,12 +83,14 @@ "FolderTypeTvShows": "Tv", "FolderTypeInherit": "ereditare", "LabelContentType": "Tipo di contenuto:", + "TitleScheduledTasks": "Compiti Pianificati", "HeaderSetupLibrary": "Configura la tua libreria", "ButtonAddMediaFolder": "Aggiungi cartella", "LabelFolderType": "Tipo cartella", "ReferToMediaLibraryWiki": "Fare riferimento alla wiki libreria multimediale.", "LabelCountry": "Nazione:", "LabelLanguage": "Lingua:", + "ButtonJoinTheDevelopmentTeam": "Unisciti al Team di Sviluppo", "HeaderPreferredMetadataLanguage": "Lingua dei metadati preferita:", "LabelSaveLocalMetadata": "Salva immagini e metadati nelle cartelle multimediali", "LabelSaveLocalMetadataHelp": "Il salvataggio di immagini e dei metadati direttamente nelle cartelle multimediali verranno messe in un posto dove possono essere facilmente modificate.", @@ -86,6 +108,8 @@ "TabCollectionTitles": "Titolo", "HeaderDeviceAccess": "Accesso dispositivo", "OptionEnableAccessFromAllDevices": "Abilitare l'accesso da tutti i dispositivi", + "OptionEnableAccessToAllChannels": "Abilita l'accesso a tutti i canali", + "OptionEnableAccessToAllLibraries": "Abilita l'accesso a tutte le librerie", "DeviceAccessHelp": "Questo vale solo per i dispositivi che possono essere identificati in modo univoco e non impedire l'accesso del browser. Filtraggio di accesso al dispositivo dell'utente impedir\u00e0 loro di usare nuovi dispositivi fino a quando non sono state approvate qui.", "LabelDisplayMissingEpisodesWithinSeasons": "Visualizza gli episodi mancanti nelle stagioni", "LabelUnairedMissingEpisodesWithinSeasons": "Visualizzare episodi mai andati in onda all'interno stagioni", @@ -275,7 +299,7 @@ "OptionMetascore": "Punteggio", "ButtonSelect": "Seleziona", "ButtonGroupVersions": "Versione Gruppo", - "ButtonAddToCollection": "Aggiungi alla Collezione", + "ButtonAddToCollection": "Aggiungi alla collezione", "PismoMessage": "Dona per avere una licenza di Pismo", "TangibleSoftwareMessage": "Utilizza Tangible Solutions Java\/C# con una licenza su donazione.", "HeaderCredits": "Crediti", @@ -299,7 +323,7 @@ "LabelCachePath": "Percorso Cache:", "LabelCachePathHelp": "Questa cartella contiene la cache come files e immagini .", "LabelImagesByNamePath": "Percorso immagini per nome:", - "LabelImagesByNamePathHelp": "Specificare un percorso personalizzato per le immagini attore, artista, genere e studio scaricate.", + "LabelImagesByNamePathHelp": "Specificare un percorso personalizzato per le immagini di attori, artisti, generi e case cinematografiche scaricate.", "LabelMetadataPath": "Percorso dei file METADATI:", "LabelMetadataPathHelp": "Specificare un percorso personalizzato per artwork e metadati scaricati, se non il si vuole salvare nelle cartelle multimediali.", "LabelTranscodingTempPath": "Cartella temporanea per la trascodifica:", @@ -314,12 +338,14 @@ "OptionEpisodes": "Episodi", "OptionOtherVideos": "Altri Video", "TitleMetadata": "Metadati", - "LabelAutomaticUpdatesFanart": "Abilita gli aggiornamenti automatici per FanArt.Tv", + "LabelAutomaticUpdates": "Abilita gli aggiornamenti automatici", "LabelAutomaticUpdatesTmdb": "Abilita gli aggiornamenti automatici per TheMovieDB.org", "LabelAutomaticUpdatesTvdb": "Abilita gli aggiornamenti automatici per TheTVDB.com", "LabelAutomaticUpdatesFanartHelp": "Se abilitato le nuove immagini verranno scaricate automaticamente da fanart.tv. Le immagini esistenti non verranno sovrascritte.", "LabelAutomaticUpdatesTmdbHelp": "Se abilitato le nuove immagini verranno scaricate automaticamente da ThemovieDb.org. Le immagini esistenti non verranno sovrascritte.", "LabelAutomaticUpdatesTvdbHelp": "Se abilitato le nuove immagini verranno scaricate automaticamente da TheTvDB.com. Le immagini esistenti non verranno sovrascritte.", + "LabelFanartApiKey": "Chiavi API personali", + "LabelFanartApiKeyHelp": "I risultati di richieste per fanart senza una chiave API personale che sono state approvate pi\u00f9 di 7 giorni fa. Con una chiave API personale questo tempo scende a 48 ore, e se sei un membro VIP scender\u00e0 ulteriormente a circa 10 minuti.", "ExtractChapterImagesHelp": "Estrazione di immagini dai capitoli permetter\u00e0 ai client di visualizzare i menu di selezione delle scene. Il processo pu\u00f2 essere lento, usare molta CPU e pu\u00f2 richiedere diversi gigabyte di spazio. Funziona quando vengono trovati i video, e anche come compito programmato alle 04:00. Il programma \u00e8 configurabile nella sezione operazioni pianificate. Non \u00e8 consigliabile eseguire questa operazione durante le ore di massimo utilizzo.", "LabelMetadataDownloadLanguage": "Lingua preferita per il download:", "ButtonAutoScroll": "Scorrimento automatico", @@ -487,6 +513,7 @@ "HeaderSystemPaths": "Percorsi di sistema", "LinkCommunity": "Comunit\u00e0", "LinkGithub": "Github", + "LinkApi": "API", "LinkApiDocumentation": "Documentazione Api", "LabelFriendlyServerName": "Nome condiviso del server:", "LabelFriendlyServerNameHelp": "Questo nome \u00e8 usato per identificare il server sulla rete.Se lasciato vuoto verra usato il nome del pc", @@ -494,20 +521,25 @@ "LabelPreferredDisplayLanguageHelp": "La traduzione nella tua lingua non \u00e8 ancora completa. Scusa.", "LabelReadHowYouCanContribute": "Leggi come puoi contribuire", "HeaderNewCollection": "Nuova collezione", - "HeaderAddToCollection": "Aggiungi alla Collezione", "ButtonSubmit": "Invia", - "NewCollectionNameExample": "Esempio: Collezione Star wars", - "OptionSearchForInternetMetadata": "Cerca su internet le immagini e i metadati", "ButtonCreate": "Crea", - "LabelLocalHttpServerPortNumber": "Numero di porta locale:", + "LabelCustomCss": "CSS Personalizzato", + "LabelCustomCssHelp": "Applica il tuo CSS personale all'interfaccia web", + "LabelLocalHttpServerPortNumber": "Porta HTTP locale", "LabelLocalHttpServerPortNumberHelp": "Il numero di porta TCP del server http del browser media a cui dovrebbe legarsi.", - "LabelPublicPort": "Numero di porta pubblica:", - "LabelPublicPortHelp": "Il numero di porta pubblica che dovrebbe essere mappato alla porta locale.", + "LabelPublicHttpPort": "Porta HTTP pubblica", + "LabelPublicHttpPortHelp": "Il numero di porta pubblica dovrebbe essere mappato verso la porta HTTP locale.", + "LabelPublicHttpsPort": "Numero porta HTTP pubblica", + "LabelPublicHttpsPortHelp": "Il numero della porta HTTP pubblica dovrebbe essere mappato verso la porta HTTP locale.", + "LabelEnableHttps": "Riporta HTTPS come indirizzo esterno", + "LabelEnableHttpsHelp": "se abilitato, il server riporter\u00e0 un url HTTPS ai client come il proprio indirizzo esterno. Questo potrebbe non far funzionare i client che ancora non supportano l'HTTPS", + "LabelHttpsPort": "Porta HTTPS locale", + "LabelHttpsPortHelp": "Il numero di porta TCP a cui il server HTTPS di Media Browser dovrebbe associarsi.", "LabelWebSocketPortNumber": "Numero porta web socket:", "LabelEnableAutomaticPortMap": "Abilita mappatura delle porte automatiche", "LabelEnableAutomaticPortMapHelp": "Tentativo di mappare automaticamente la porta pubblica alla porta locale tramite UPnP. Questo potrebbe non funzionare con alcuni modelli di router.", - "LabelExternalDDNS": "DDNS Esterno:", - "LabelExternalDDNSHelp": "Se possiedi un DNS dinamico inseriscilo qui. Media browser lo utilizzer\u00e0 per le connessioni remote.", + "LabelExternalDDNS": "Indirizzo WAN esterno", + "LabelExternalDDNSHelp": "Se hai un DNS dinamico inseriscilo qui. Le app Media Browser lo useranno durante la connessione in remoto. Lascia vuoto per la rilevazione automatica", "TabResume": "Riprendi", "TabWeather": "Tempo", "TitleAppSettings": "Impostazioni delle app", @@ -575,6 +607,7 @@ "ButtonRestart": "Riavvia", "ButtonShutdown": "Arresta Server", "ButtonUpdateNow": "Aggiorna Adesso", + "TabHosting": "Hosting", "PleaseUpdateManually": "Per favore Arresta il server ed aggiorna manualmente", "NewServerVersionAvailable": "Una nuova versione di Media Browser Server \u00e8 disponibile!!!", "ServerUpToDate": "Media Browser Server \u00e8 aggiornato.", @@ -636,6 +669,7 @@ "NotificationOptionInstallationFailed": "Installazione fallita", "NotificationOptionNewLibraryContent": "Nuovo contenuto aggiunto", "NotificationOptionNewLibraryContentMultiple": "Nuovi contenuti aggiunti", + "NotificationOptionCameraImageUploaded": "Immagine fotocamera caricata", "SendNotificationHelp": "Per impostazione predefinita, le notifiche vengono inviate alla casella della pagina principale. Sfoglia il catalogo plugin da installare opzioni di notifica aggiuntive.", "NotificationOptionServerRestartRequired": "Riavvio del server necessario", "LabelNotificationEnabled": "Abilita questa notifica", @@ -829,8 +863,8 @@ "OptionAuto": "Automatico", "OptionYes": "Si", "OptionNo": "No", - "HeaderOptions": "Options", - "HeaderIdentificationResult": "Identification Result", + "HeaderOptions": "Opzioni", + "HeaderIdentificationResult": "Risultati Identificazione", "LabelHomePageSection1": "Pagina Iniziale Sezione 1:", "LabelHomePageSection2": "Pagina Iniziale Sezione 2:", "LabelHomePageSection3": "Pagina Iniziale Sezione 3:", @@ -853,8 +887,10 @@ "OptionDefaultSort": "Predefinito", "OptionCommunityMostWatchedSort": "Pi\u00f9 visti", "TabNextUp": "Da vedere", + "HeaderBecomeMediaBrowserSupporter": "Diventa un Media Browser Supporter", + "TextEnjoyBonusFeatures": "Goditi le caratteristiche aggiuntive", "MessageNoMovieSuggestionsAvailable": "Nessun suggerimento di film attualmente disponibile. Iniziare a guardare e valutare i vostri film, e poi tornare per i suggerimenti.", - "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.", + "MessageNoCollectionsAvailable": "Le collezioni ti permettono di goderti raccolte personalizzate di Film, Serie TV, Album, Libri e Giochi. Clicca sul + per iniziare a creare le tue Collezioni", "MessageNoPlaylistsAvailable": "Playlist ti permettere di mettere in coda gli elementi da riprodurre.Usa il tasto destro o tap e tieni premuto quindi seleziona elemento da aggiungere", "MessageNoPlaylistItemsAvailable": "Questa playlist al momento \u00e8 vuota", "ButtonDismiss": "Cancella", @@ -869,7 +905,6 @@ "LabelChannelDownloadAge": "Elimina contenuto dopo: (giorni)", "LabelChannelDownloadAgeHelp": "Contenuti scaricati pi\u00f9 vecchi di questo limite sarnno cancellati. Rimarranno riproducibili via internet in streaming.", "ChannelSettingsFormHelp": "Installare canali come Trailer e Vimeo nel catalogo plugin.", - "LabelSelectCollection": "Seleziona Collezione:", "ButtonOptions": "Opzioni", "ViewTypeMovies": "Film", "ViewTypeTvShows": "Serie Tv", @@ -917,7 +952,7 @@ "OptionLatestTvRecordings": "Ultime registrazioni", "LabelProtocolInfo": "Info protocollo:", "LabelProtocolInfoHelp": "Il valore che verr\u00e0 utilizzato quando si risponde a richieste GetProtocolInfo dal dispositivo.", - "TabKodiMetadata": "Kodi", + "TabNfo": "Nfo", "HeaderKodiMetadataHelp": "Media Browser include il supporto nativo per i metadati Kodi Nfo e immagini. Per attivare o disattivare i metadati Kodi, utilizzare la scheda Avanzate per configurare le opzioni per i tipi di media.", "LabelKodiMetadataUser": "Sincronizza i dati utente a nfo di per:", "LabelKodiMetadataUserHelp": "Attivare questa opzione per mantenere i dati di orologi sincronizzati tra il Media Browser e Kodi.", @@ -931,6 +966,7 @@ "LabelGroupChannelsIntoViews": "Visualizzare i seguenti canali direttamente dentro le mie visite:", "LabelGroupChannelsIntoViewsHelp": "Se abilitata, questi canali verranno visualizzati direttamente con altre viste. Se disattivato, saranno visualizzati all'interno di una sezione Canali separata.", "LabelDisplayCollectionsView": "Mostra le Collezioni di film", + "LabelDisplayCollectionsViewHelp": "This will create a separate view to display collections that you've created or have access to. To create a collection, right-click or tap-hold any movie and select 'Add to Collection'. ", "LabelKodiMetadataEnableExtraThumbs": "Copia extrafanart in extrathumbs", "LabelKodiMetadataEnableExtraThumbsHelp": "Copia extrafanart in extrathumbs", "TabServices": "Servizi", @@ -1084,11 +1120,14 @@ "LabelDisplayFoldersView": "Visualizza cartelle come normali cartelle dei media", "ViewTypeLiveTvRecordingGroups": "Registrazioni", "ViewTypeLiveTvChannels": "canali", - "LabelAllowLocalAccessWithoutPassword": "Consenti di accedere localmente senza password", - "LabelAllowLocalAccessWithoutPasswordHelp": "Quando abilitato la password non \u00e8 necessaria", + "LabelEasyPinCode": "Easy pin code:", + "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Media Browser apps, and can also be used for easy in-network sign in.", + "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", + "LabelInNetworkSignInWithEasyPasswordHelp": "If enabled, you'll be able to use your easy pin code to sign in to Media Browser apps from inside your home network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", "HeaderPassword": "Password", "HeaderLocalAccess": "Accesso locale", "HeaderViewOrder": "Visualizza ordine", + "ButtonResetEasyPassword": "Reset easy pin code", "LabelSelectUserViewOrder": "Scegliere l'ordine vostre opinioni verranno visualizzati in applicazioni all'interno del browser media", "LabelMetadataRefreshMode": "Metadata (modo Aggiornamento)", "LabelImageRefreshMode": "Immagine (modo Aggiornamento)", @@ -1162,7 +1201,7 @@ "OptionNoThemeSong": "No Temi canzone", "OptionNoThemeVideo": "No tema video", "LabelOneTimeDonationAmount": "Importo della donazione:", - "ButtonDonate": "Donate", + "ButtonDonate": "Donazione", "OptionActor": "Attore", "OptionComposer": "Compositore", "OptionDirector": "Regista", @@ -1279,7 +1318,7 @@ "MessageNoTrailersFound": "Nessun Trailer trovato.Installa Il plug in dei trailer per importare la libreria dei trailer da internet", "HeaderNewUsers": "Nuovo Utente", "ButtonSignUp": "Iscriviti", - "ButtonForgotPassword": "Dimenticato la password?", + "ButtonForgotPassword": "Forgot password", "OptionDisableUserPreferences": "Disabilitare l'accesso alle preferenze dell'utente", "OptionDisableUserPreferencesHelp": "Se abilitato, solo gli amministratori saranno in grado di configurare le immagini del profilo utente, password e preferenze di lingua.", "HeaderSelectServer": "Selezionare il server", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/kk.json b/MediaBrowser.Server.Implementations/Localization/Server/kk.json index a6975ebba..1da578855 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/kk.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/kk.json @@ -27,30 +27,50 @@ "AWindowsServiceHasBeenInstalled": "Windows \u049b\u044b\u0437\u043c\u0435\u0442\u0456 \u043e\u0440\u043d\u0430\u0442\u044b\u043b\u0434\u044b.", "WindowsServiceIntro1": "Media Browser Server \u0436\u04af\u0439\u0435\u043b\u0456\u043a \u0442\u0430\u049b\u0442\u0430\u0434\u0430\u0493\u044b \u0431\u0435\u043b\u0433\u0456\u0448\u0435\u0441\u0456 \u0431\u0430\u0440 \u0436\u04b1\u043c\u044b\u0441 \u04af\u0441\u0442\u0435\u043b\u0456\u043d\u0456\u04a3 \u049b\u043e\u043b\u0434\u0430\u043d\u0431\u0430\u0441\u044b \u0440\u0435\u0442\u0456\u043d\u0434\u0435 \u04d9\u0434\u0435\u043f\u043a\u0456 \u043e\u0440\u044b\u043d\u0434\u0430\u043b\u0430\u0434\u044b, \u0431\u0456\u0440\u0430\u049b \u0435\u0433\u0435\u0440 \u0431\u04b1\u043d\u044b \u04e9\u04a3\u0434\u0456\u043a \u049b\u044b\u0437\u043c\u0435\u0442\u0456 \u0440\u0435\u0442\u0456\u043d\u0434\u0435 \u0442\u0435\u04a3\u0448\u0435\u0443\u0434\u0456 \u049b\u0430\u043b\u0430\u0441\u0430\u04a3\u044b\u0437, \u043e\u0440\u043d\u044b\u043d\u0430 \u0431\u04b1\u043b Windows \u049b\u044b\u0437\u043c\u0435\u0442\u0442\u0435\u0440 \u0434\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440\u0456 \u0430\u0440\u049b\u044b\u043b\u044b \u0456\u0441\u043a\u0435 \u049b\u043e\u0441\u044b\u043b\u0443\u044b \u043c\u04af\u043c\u043a\u0456\u043d.", "WindowsServiceIntro2": "\u0415\u0433\u0435\u0440 Windows \u049b\u044b\u0437\u043c\u0435\u0442\u0456 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0434\u0430 \u0431\u043e\u043b\u0441\u0430, \u0435\u0441\u043a\u0435\u0440\u0456\u04a3\u0456\u0437, \u0431\u04b1\u043b \u0441\u043e\u043b \u043c\u0435\u0437\u0433\u0456\u043b\u0434\u0435 \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\u0439 \u0436\u04af\u043c\u044b\u0441 \u0456\u0441\u0442\u0435\u0443\u0456 \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 \u04af\u0448\u0456\u043d \u0436\u04af\u0439\u0435\u043b\u0456\u043a \u0442\u0430\u049b\u0442\u0430\u0434\u0430\u043d \u0448\u044b\u0493\u0443\u044b\u04a3\u044b\u0437 \u049b\u0430\u0436\u0435\u0442. \u0421\u043e\u0493\u0430\u043d \u049b\u0430\u0442\u0430\u0440, \u049b\u044b\u0437\u043c\u0435\u0442\u0442\u0456 \u04d9\u043a\u0456\u043c\u0448\u0456 \u049b\u04b1\u049b\u044b\u049b\u0442\u0430\u0440\u044b\u043d\u0430 \u0438\u0435 \u0431\u043e\u043b\u044b\u043f \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 \u0442\u0435\u04a3\u0448\u0435\u0443 \u049b\u0430\u0436\u0435\u0442. \u041d\u0430\u0437\u0430\u0440 \u0430\u0443\u0434\u0430\u0440\u044b\u04a3\u044b\u0437! \u049a\u0430\u0437\u0456\u0440\u0433\u0456 \u0443\u0430\u049b\u044b\u0442\u0442\u0430 \u0431\u04b1\u043b \u049b\u044b\u0437\u043c\u0435\u0442 \u04e9\u0437\u0456\u043d\u0435\u043d-\u04e9\u0437\u0456 \u0436\u0430\u04a3\u0430\u0440\u0442\u044b\u043b\u043c\u0430\u0439\u0434\u044b, \u0441\u043e\u043d\u0434\u044b\u049b\u0442\u0430\u043d \u0436\u0430\u04a3\u0430 \u043d\u04b1\u0441\u049b\u0430\u043b\u0430\u0440 \u049b\u043e\u043b\u043c\u0435\u043d \u04e9\u0437\u0430\u0440\u0430 \u04d9\u0440\u0435\u043a\u0435\u0442\u0442\u0435\u0441\u0443\u0434\u0456 \u049b\u0430\u0436\u0435\u0442 \u0435\u0442\u0435\u0434\u0456.", - "WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click <b>Finish<\/b> to view the <b>Server Dashboard<\/b>.", + "WizardCompleted": "\u0411\u04b1\u043b \u04d9\u0437\u0456\u0440\u0448\u0435 \u0431\u0456\u0437\u0433\u0435 \u043a\u0435\u0440\u0435\u0433\u0456\u043d\u0456\u04a3 \u0431\u04d9\u0440\u0456. Media Browser \u0442\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430\u04a3\u044b\u0437 \u0442\u0443\u0440\u0430\u043b\u044b \u043c\u04d9\u043b\u0456\u043c\u0435\u0442\u0442\u0435\u0440\u0434\u0456 \u0436\u0438\u043d\u0430\u0443\u0434\u044b \u0431\u0430\u0441\u0442\u0430\u0434\u044b. \u041a\u0435\u0439\u0431\u0456\u0440 \u049b\u043e\u043b\u0434\u0430\u043d\u0431\u0430\u043b\u0430\u0440\u044b\u043c\u044b\u0437\u0431\u0435\u043d \u0442\u0430\u043d\u044b\u0441\u044b\u043f \u0448\u044b\u0493\u044b\u04a3\u044b\u0437 \u0434\u0430, <b>\u0421\u0435\u0440\u0432\u0435\u0440 \u0431\u0430\u049b\u044b\u043b\u0430\u0443 \u0442\u0430\u049b\u0442\u0430\u0441\u044b\u043d<\/b> \u043a\u04e9\u0440\u0443 \u04af\u0448\u0456\u043d \u043a\u0435\u0439\u0456\u043d <b>\u0414\u0430\u0439\u044b\u043d<\/b>\u0442\u04af\u0439\u043c\u0435\u0448\u0456\u0433\u0456\u043d \u0431\u0430\u0441\u044b\u04a3\u044b\u0437.", "LabelConfigureSettings": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440\u0434\u0456 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f\u043b\u0430\u0443", "LabelEnableVideoImageExtraction": "\u0411\u0435\u0439\u043d\u0435 \u0441\u0443\u0440\u0435\u0442\u0456\u043d \u0448\u044b\u0493\u0430\u0440\u044b\u043f \u0430\u043b\u0443\u0434\u044b \u049b\u043e\u0441\u0443", "VideoImageExtractionHelp": "\u04d8\u043b\u0456 \u0434\u0435 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0456 \u0436\u043e\u049b, \u0436\u04d9\u043d\u0435 \u043e\u043b\u0430\u0440 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0442\u0435 \u0442\u0430\u0431\u044b\u043b\u043c\u0430\u0493\u0430\u043d \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440 \u04af\u0448\u0456\u043d. \u0411\u04b1\u043b \u0442\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430\u043d\u044b\u04a3 \u0431\u0430\u0441\u0442\u0430\u043f\u049b\u044b \u0441\u043a\u0430\u043d\u0435\u0440\u043b\u0435\u0443\u0456 \u04af\u0448\u0456\u043d \u049b\u043e\u0441\u044b\u043c\u0448\u0430 \u0443\u0430\u049b\u044b\u0442 \u04af\u0441\u0442\u0435\u0439\u0434\u0456, \u0431\u0456\u0440\u0430\u049b \u043d\u04d9\u0442\u0438\u0436\u0435\u0441\u0456\u043d\u0434\u0435 \u04b1\u043d\u0430\u043c\u0434\u044b\u043b\u0430\u0443 \u043a\u04e9\u0440\u0441\u0435\u0442\u0456\u043c \u0431\u043e\u043b\u0430\u0434\u044b.", "LabelEnableChapterImageExtractionForMovies": "\u0424\u0438\u043b\u044c\u043c\u0434\u0435\u0440 \u04af\u0448\u0456\u043d \u0441\u0430\u0445\u043d\u0430 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0456\u043d \u0448\u044b\u0493\u0430\u0440\u044b\u043f \u0430\u043b\u0443\u0434\u044b \u049b\u043e\u0441\u0443", "LabelChapterImageExtractionForMoviesHelp": "\u0421\u0430\u0445\u043d\u0430 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0456\u043d \u0448\u044b\u0493\u0430\u0440\u044b\u043f \u0430\u043b\u0443 \u043a\u043b\u0438\u0435\u043d\u0442\u0442\u0435\u0440\u0433\u0435 \u0441\u0430\u0445\u043d\u0430 \u0431\u04e9\u043b\u0435\u043a\u0442\u0435\u0443\u0433\u0435 \u0430\u0440\u043d\u0430\u043b\u0493\u0430\u043d \u0441\u044b\u0437\u0431\u0430\u043b\u044b\u049b \u043c\u04d9\u0437\u0456\u0440\u043b\u0435\u0440\u0434\u0456 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0443 \u04af\u0448\u0456\u043d \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0435\u0434\u0456. \u0411\u04b1\u043b \u043f\u0440\u043e\u0446\u0435\u0441 \u0431\u0430\u044f\u0443, \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0434\u044b \u0442\u043e\u0437\u0434\u044b\u0440\u0430\u0442\u044b\u043d \u0436\u04d9\u043d\u0435 \u0431\u0456\u0440\u0430\u0437 \u0433\u0438\u0433\u0430\u0431\u0430\u0439\u0442 \u043a\u0435\u04a3\u0456\u0441\u0442\u0456\u043a\u0442\u0456 \u049b\u0430\u0436\u0435\u0442 \u0435\u0442\u0435\u0442\u0456\u043d \u0431\u043e\u043b\u0443\u044b \u043c\u04af\u043c\u043a\u0456\u043d. \u0411\u04b1\u043b \u0442\u04af\u043d\u0433\u0456 4:00 \u0441\u0430\u0493\u0430\u0442\u044b\u043d\u0430 \u0436\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0493\u0430\u043d \u0442\u0430\u043f\u0441\u044b\u0440\u043c\u0430 \u0440\u0435\u0442\u0456\u043d\u0434\u0435 \u0436\u04b1\u043c\u044b\u0441 \u0456\u0441\u0442\u0435\u0439\u0434\u0456, \u0434\u0435\u0433\u0435\u043d\u043c\u0435\u043d \u0431\u04b1\u043b \u0416\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0443\u0448\u044b \u0430\u0439\u043c\u0430\u0493\u044b\u043d\u0434\u0430 \u0442\u0435\u04a3\u0448\u0435\u043b\u0435\u0434\u0456. \u0411\u04b1\u043b \u0442\u0430\u043f\u0441\u044b\u0440\u043c\u0430\u043d\u044b \u049b\u0430\u0440\u0431\u0430\u043b\u0430\u0441 \u0441\u0430\u0493\u0430\u0442\u0442\u0430\u0440\u044b\u043d\u0434\u0430 \u043e\u0440\u044b\u043d\u0434\u0430\u0443 \u04b1\u0441\u044b\u043d\u044b\u043b\u043c\u0430\u0439\u0434\u044b.", "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", - "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 \u0436\u043e\u043b \u0436\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0493\u044b\u0448\u0442\u044b \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.", + "LabelEnableAutomaticPortMappingHelp": "\u049a\u0430\u0448\u044b\u049b\u0442\u0430\u043d \u043e\u04a3\u0430\u0439\u0442\u044b\u043b\u044b\u043f \u049b\u0430\u0442\u044b\u043d\u0430\u0441\u0443 \u04af\u0448\u0456\u043d UPnP \u0436\u043e\u043b \u0436\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0493\u044b\u0448\u0442\u044b \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 \u0436\u043e\u043b \u0436\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0493\u044b\u0448 \u04af\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.", "HeaderTermsOfService": "Media Browser \u049a\u044b\u0437\u043c\u0435\u0442 \u0448\u0430\u0440\u0442\u0442\u0430\u0440\u044b", "MessagePleaseAcceptTermsOfService": "\u0416\u0430\u043b\u0493\u0430\u0441\u0442\u044b\u0440\u043c\u0430\u0441 \u0431\u04b1\u0440\u044b\u043d \u049a\u044b\u0437\u043c\u0435\u0442 \u0448\u0430\u0440\u0442\u0442\u0430\u0440\u044b\u043d \u0436\u04d9\u043d\u0435 \u049a\u04b1\u043f\u0438\u044f\u043b\u044b\u043b\u044b\u049b \u0441\u0430\u044f\u0441\u0430\u0442\u044b\u043d \u049b\u0430\u0431\u044b\u043b\u0434\u0430\u04a3\u044b\u0437.", "OptionIAcceptTermsOfService": "\u049a\u044b\u0437\u043c\u0435\u0442 \u0448\u0430\u0440\u0442\u0442\u0430\u0440\u044b\u043d \u049b\u0430\u0431\u044b\u043b\u0434\u0430\u0439\u043c\u044b\u043d", "ButtonPrivacyPolicy": "\u049a\u04b1\u043f\u0438\u044f\u043b\u044b\u043b\u044b\u049b \u0441\u0430\u044f\u0441\u0430\u0442\u044b", "ButtonTermsOfService": "\u049a\u044b\u0437\u043c\u0435\u0442 \u0448\u0430\u0440\u0442\u0442\u0430\u0440\u044b", + "HeaderDeveloperOptions": "\u0416\u0430\u0441\u0430\u049b\u0442\u0430\u0443\u0448\u044b \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440\u0456", + "OptionEnableWebClientResponseCache": "\u0412\u0435\u0431-\u043a\u043b\u0438\u0435\u043d\u0442 \u04af\u043d \u049b\u0430\u0442\u0443 \u043a\u044d\u0448\u0442\u0435\u0443\u0456\u043d \u049b\u043e\u0441\u0443", + "OptionDisableForDevelopmentHelp": "\u0412\u0435\u0431-\u043a\u043b\u0438\u0435\u043d\u0442 \u0436\u0430\u0441\u0430\u049b\u0442\u0430\u0443 \u04af\u0448\u0456\u043d \u049b\u0430\u0436\u0435\u0442 \u0431\u043e\u043b\u0493\u0430\u043d\u0434\u0430 \u043c\u044b\u043d\u0430\u043b\u0430\u0440\u0434\u044b \u0442\u0435\u04a3\u0448\u0435\u04a3\u0456\u0437.", + "OptionEnableWebClientResourceMinification": "\u0412\u0435\u0431-\u043a\u043b\u0438\u0435\u043d\u0442 \u049b\u043e\u0440\u044b\u043d \u0430\u0437\u0430\u0439\u0442\u0443\u0434\u044b \u049b\u043e\u0441\u0443", + "LabelDashboardSourcePath": "\u0412\u0435\u0431-\u043a\u043b\u0438\u0435\u043d\u0442 \u043a\u04e9\u0437\u0456\u043d\u0456\u04a3 \u0436\u043e\u043b\u044b:", + "LabelDashboardSourcePathHelp": "\u0415\u0433\u0435\u0440 \u0441\u0435\u0440\u0432\u0435\u0440 \u049b\u0430\u0439\u043d\u0430\u0440 \u043a\u043e\u0434\u044b\u043d\u0430\u043d \u0436\u04b1\u043c\u044b\u0441 \u0456\u0441\u0442\u0435\u0441\u0435, dashboard-ui \u049b\u0430\u043b\u0442\u0430\u0441\u044b\u043d\u0430 \u0436\u043e\u043b\u0434\u044b \u0430\u043d\u044b\u049b\u0442\u0430\u04a3\u044b\u0437. \u0412\u0435\u0431-\u043a\u043b\u0438\u0435\u043d\u0442\u0442\u0456\u04a3 \u0431\u0430\u0440\u043b\u044b\u049b \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b \u043e\u0441\u044b \u0436\u0430\u0439\u0493\u0430\u0441\u044b\u043c\u0434\u0430\u043d \u0448\u044b\u0493\u0430\u0440\u044b\u043b\u0430\u0434\u044b.", + "ButtonConvertMedia": "\u0422\u0430\u0441\u0443\u0448\u044b\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0434\u0456 \u0442\u04af\u0440\u043b\u0435\u043d\u0434\u0456\u0440\u0443", + "ButtonOrganize": "\u04b0\u0439\u044b\u043c\u0434\u0430\u0441\u0442\u044b\u0440\u0443", "ButtonOk": "\u0416\u0430\u0440\u0430\u0439\u0434\u044b", "ButtonCancel": "\u0411\u043e\u043b\u0434\u044b\u0440\u043c\u0430\u0443", "ButtonNew": "\u0416\u0430\u0441\u0430\u0443", - "HeaderTV": "TV", + "HeaderTV": "\u0422\u0414", "HeaderAudio": "\u0414\u044b\u0431\u044b\u0441", "HeaderVideo": "\u0411\u0435\u0439\u043d\u0435", - "OptionDetectArchiveFilesAsMedia": "Detect archive files as media", - "OptionDetectArchiveFilesAsMediaHelp": "If enabled, files with .rar and .zip extensions will be detected as media files.", + "HeaderPaths": "\u0416\u043e\u043b\u0434\u0430\u0440", + "CategorySync": "\u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443", + "HeaderEasyPinCode": "\u041e\u04a3\u0430\u0439\u0442\u044b\u043b\u0493\u0430\u043d PIN-\u043a\u043e\u0434", + "RegisterWithPayPal": "PayPal \u0430\u0440\u049b\u044b\u043b\u044b \u0442\u0456\u0440\u043a\u0435\u043b\u0443", + "HeaderSyncRequiresSupporterMembership": "\u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443 \u04af\u0448\u0456\u043d \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u043b\u044b\u049b \u043c\u04af\u0448\u0435\u043b\u0456\u043a \u049b\u0430\u0436\u0435\u0442", + "HeaderEnjoyDayTrial": "14-\u043a\u04af\u043d\u0434\u0456\u043a \u0442\u0435\u0433\u0456\u043d \u0441\u044b\u043d\u0430\u043c\u0430\u043d\u044b \u0442\u0430\u043c\u0430\u0448\u0430\u043b\u0430\u043d\u044b\u04a3\u044b\u0437", + "LabelSyncTempPath": "\u0423\u0430\u049b\u044b\u0442\u0448\u0430 \u0444\u0430\u0439\u043b \u0436\u043e\u043b\u044b:", + "LabelSyncTempPathHelp": "\u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443 \u04af\u0448\u0456\u043d \u0442\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u0436\u04b1\u043c\u044b\u0441 \u049b\u0430\u043b\u0442\u0430\u043d\u044b \u0430\u043d\u044b\u049b\u0442\u0430\u04a3\u044b\u0437. \u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443\u043a\u0435\u0437\u0456\u043d\u0434\u0435 \u0436\u0430\u0441\u0430\u043b\u0493\u0430\u043d \u0442\u04af\u0440\u043b\u0435\u043d\u0434\u0456\u0440\u0456\u043b\u0433\u0435\u043d \u0442\u0430\u0441\u0443\u0448\u044b\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440 \u043e\u0441\u044b \u043e\u0440\u044b\u043d\u0434\u0430 \u0441\u0430\u049b\u0442\u0430\u043b\u0430\u0434\u044b.", + "LabelCustomCertificatePath": "\u041a\u0443\u04d9\u043b\u0456\u043a \u0436\u043e\u043b\u044b:", + "LabelCustomCertificatePathHelp": "\u04e8\u0437\u0456\u04a3\u0456\u0437\u0434\u0456\u04a3 SSL-\u043a\u0443\u04d9\u043b\u0456\u0433\u0456\u043d \u04b1\u0441\u044b\u043d\u044b\u04a3\u044b\u0437. \u0415\u0433\u0435\u0440 \u0431\u043e\u0441 \u049b\u0430\u043b\u0434\u044b\u0440\u044b\u043b\u0441\u0430, \u0441\u0435\u0440\u0432\u0435\u0440 \u04e9\u0437\u0456\u043d\u0456\u04a3-\u04e9\u0437\u0456 \u049b\u043e\u043b\u0442\u0430\u04a3\u0431\u0430\u0441\u044b \u0431\u0430\u0440 \u043a\u0443\u04d9\u043b\u0456\u043a\u0442\u0456 \u0436\u0430\u0441\u0430\u0439\u0434\u044b.", + "TitleNotifications": "\u0425\u0430\u0431\u0430\u0440\u043b\u0430\u043d\u0434\u044b\u0440\u0443\u043b\u0430\u0440", + "ButtonDonateWithPayPal": "PayPal \u0430\u0440\u049b\u044b\u043b\u044b \u049b\u0430\u0439\u044b\u0440\u043c\u0430\u043b\u0430\u0443", + "OptionDetectArchiveFilesAsMedia": "\u041c\u04b1\u0440\u0430\u0493\u0430\u0442\u0442\u0430\u043b\u0493\u0430\u043d \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u0434\u044b \u0442\u0430\u0441\u0443\u0448\u044b\u0434\u0435\u0440\u0435\u043a \u0440\u0435\u0442\u0456\u043d\u0434\u0435 \u0442\u0430\u0431\u0443", + "OptionDetectArchiveFilesAsMediaHelp": "\u049a\u043e\u0441\u044b\u043b\u0493\u0430\u043d\u0434\u0430, .rar \u0436\u04d9\u043d\u0435 .zip \u043a\u0435\u04a3\u0435\u0439\u0442\u0456\u043c\u0434\u0435\u0440\u0456 \u0431\u0430\u0440 \u0444\u0430\u0439\u043b\u0434\u0430\u0440 \u0442\u0430\u0441\u0443\u0448\u044b \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b \u0440\u0435\u0442\u0456\u043d\u0434\u0435 \u0442\u0430\u0431\u044b\u043b\u0430\u0434\u044b.", "LabelEnterConnectUserName": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b \u0430\u0442\u044b \u043d\u0435\u043c\u0435\u0441\u0435 \u049b\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437\u0456", "LabelEnterConnectUserNameHelp": "\u0411\u04b1\u043b - \u0441\u0456\u0437\u0434\u0456\u04a3 Media Browser \u0436\u0435\u043b\u0456\u043b\u0456\u043a \u0442\u0456\u0440\u043a\u0435\u043b\u0433\u0456\u04a3\u0456\u0437\u0434\u0456\u04a3 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b \u0430\u0442\u044b \u043d\u0435\u043c\u0435\u0441\u0435 \u049b\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437\u0456.", - "HeaderSyncJobInfo": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443 \u0436\u04b1\u043c\u044b\u0441\u044b", + "HeaderSyncJobInfo": "\u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443 \u0436\u04b1\u043c\u044b\u0441\u044b", "FolderTypeMixed": "\u0410\u0440\u0430\u043b\u0430\u0441 \u043c\u0430\u0437\u043c\u04b1\u043d", "FolderTypeMovies": "\u0424\u0438\u043b\u044c\u043c\u0434\u0435\u0440", "FolderTypeMusic": "\u041c\u0443\u0437\u044b\u043a\u0430", @@ -63,12 +83,14 @@ "FolderTypeTvShows": "\u0422\u0414", "FolderTypeInherit": "\u041c\u04b1\u0440\u0430\u0493\u0430 \u0438\u0435\u043b\u0435\u043d\u0443", "LabelContentType": "\u041c\u0430\u0437\u043c\u04b1\u043d \u0442\u04af\u0440\u0456:", + "TitleScheduledTasks": "\u0416\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0493\u0430\u043d \u0442\u0430\u043f\u0441\u044b\u0440\u043c\u0430\u043b\u0430\u0440", "HeaderSetupLibrary": "\u0422\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430\u043d\u044b \u043e\u0440\u043d\u0430\u0442\u0443 \u0436\u04d9\u043d\u0435 \u0442\u0435\u04a3\u0448\u0435\u0443", "ButtonAddMediaFolder": "\u0422\u0430\u0441\u0443\u0448\u044b \u049b\u0430\u043b\u0442\u0430\u0441\u044b\u043d \u04af\u0441\u0442\u0435\u0443", "LabelFolderType": "\u049a\u0430\u043b\u0442\u0430 \u0442\u04af\u0440\u0456:", "ReferToMediaLibraryWiki": "\u0422\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430 \u0442\u0443\u0440\u0430\u043b\u044b \u0443\u0438\u043a\u0438 \u0456\u0448\u0456\u043d\u0435\u043d \u049b\u0430\u0440\u0430\u04a3\u044b\u0437.", "LabelCountry": "\u0415\u043b:", "LabelLanguage": "\u0422\u0456\u043b:", + "ButtonJoinTheDevelopmentTeam": "\u0416\u0430\u0441\u0430\u049b\u0442\u0430\u0443\u0448\u044b\u043b\u0430\u0440 \u0442\u043e\u0431\u044b\u043d\u0430 \u043a\u0456\u0440\u0443", "HeaderPreferredMetadataLanguage": "\u041c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440 \u0442\u0456\u043b\u0456\u043d\u0456\u04a3 \u0442\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0456:", "LabelSaveLocalMetadata": "\u0421\u0443\u0440\u0435\u0442\u0442\u0435\u043c\u0435 v\u0435\u043d \u043c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0456 \u0442\u0430\u0441\u0443\u0448\u044b \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440\u044b \u0456\u0448\u0456\u043d\u0434\u0435 \u0441\u0430\u049b\u0442\u0430\u0443", "LabelSaveLocalMetadataHelp": "\u0421\u0443\u0440\u0435\u0442\u0442\u0435\u043c\u0435 \u043c\u0435\u043d \u043c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0456 \u0442\u0456\u043a\u0435\u043b\u0435\u0439 \u0442\u0430\u0441\u0443\u0448\u044b \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440\u044b \u0456\u0448\u0456\u043d\u0434\u0435 \u0441\u0430\u049b\u0442\u0430\u043b\u0443\u044b \u043e\u043b\u0430\u0440\u0434\u044b \u0436\u0435\u04a3\u0456\u043b \u04e9\u04a3\u0434\u0435\u0439 \u0430\u043b\u0430\u0442\u044b\u043d \u043e\u0440\u044b\u043d\u0493\u0430 \u049b\u043e\u044f\u0434\u044b.", @@ -86,6 +108,8 @@ "TabCollectionTitles": "\u0422\u0443\u044b\u043d\u0434\u044b\u043b\u0430\u0440", "HeaderDeviceAccess": "\u049a\u04b1\u0440\u044b\u043b\u0493\u044b\u0493\u0430 \u049b\u0430\u0442\u044b\u043d\u0430\u0441", "OptionEnableAccessFromAllDevices": "\u0411\u0430\u0440\u043b\u044b\u049b \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u043b\u0430\u0440\u0434\u0430\u043d \u049b\u0430\u0442\u044b\u043d\u0430\u0441\u0443\u0434\u044b \u049b\u043e\u0441\u0443", + "OptionEnableAccessToAllChannels": "\u0411\u0430\u0440\u043b\u044b\u049b \u0430\u0440\u043d\u0430\u043b\u0430\u0440\u0493\u0430 \u049b\u0430\u0442\u044b\u043d\u0430\u0441\u0443\u0434\u044b \u049b\u043e\u0441\u0443", + "OptionEnableAccessToAllLibraries": "\u0411\u0430\u0440\u043b\u044b\u049b \u0442\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430\u043b\u0430\u0440\u0493\u0430 \u049b\u0430\u0442\u044b\u043d\u0430\u0441\u0443\u0434\u044b \u049b\u043e\u0441\u0443", "DeviceAccessHelp": "\u0411\u04b1\u043b \u0442\u0435\u043a \u049b\u0430\u043d\u0430 \u0431\u0456\u0440\u0435\u0433\u0435\u0439 \u0430\u043d\u044b\u049b\u0442\u0430\u043b\u0443\u044b \u043c\u04af\u043c\u043a\u0456\u043d \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u043b\u0430\u0440 \u04af\u0448\u0456\u043d \u049b\u043e\u043b\u0434\u0430\u043d\u044b\u043b\u0430\u0434\u044b \u0436\u04d9\u043d\u0435 \u0448\u043e\u043b\u0493\u044b\u0448\u043f\u0435\u043d \u049b\u0430\u043d\u0442\u044b\u043d\u0430\u0441\u0443\u0493\u0430 \u0442\u044b\u0439\u044b\u043c \u0441\u0430\u043b\u043c\u0430\u0439\u0434\u044b. \u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u0441\u044b\u043d\u0430\u043d \u049b\u0430\u0442\u044b\u043d\u0430\u0441\u0443\u0434\u044b \u0441\u04af\u0437\u0433\u0456\u043b\u0435\u0443\u0456 \u0436\u0430\u04a3\u0430 \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u043b\u0430\u0440\u0434\u044b \u043c\u04b1\u043d\u0434\u0430 \u0431\u0435\u043a\u0456\u0442\u0456\u043b\u0433\u0435\u043d\u0448\u0435 \u0434\u0435\u0439\u0456\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0493\u0430 \u0442\u044b\u0439\u044b\u043c \u0441\u0430\u043b\u0430\u0434\u044b.", "LabelDisplayMissingEpisodesWithinSeasons": "\u0416\u043e\u049b \u044d\u043f\u0438\u0437\u043e\u0434\u0442\u0430\u0440\u0434\u044b \u043c\u0430\u0443\u0441\u044b\u043c \u0456\u0448\u0456\u043d\u0434\u0435 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0443", "LabelUnairedMissingEpisodesWithinSeasons": "\u041a\u04e9\u0440\u0441\u0435\u0442\u0456\u043b\u043c\u0435\u0433\u0435\u043d \u044d\u043f\u0438\u0437\u043e\u0434\u0442\u0430\u0440\u0434\u044b \u043c\u0430\u0443\u0441\u044b\u043c \u0456\u0448\u0456\u043d\u0434\u0435 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0443", @@ -195,13 +219,13 @@ "HeaderLatestSongs": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u04a3\u0433\u0456 \u04d9\u0443\u0435\u043d\u0434\u0435\u0440", "HeaderRecentlyPlayed": "\u0416\u0430\u049b\u044b\u043d\u0434\u0430 \u043e\u0439\u043d\u0430\u0442\u044b\u043b\u0493\u0430\u043d\u0434\u0430\u0440", "HeaderFrequentlyPlayed": "\u0416\u0438\u0456 \u043e\u0439\u043d\u0430\u0442\u044b\u043b\u0493\u0430\u043d\u0434\u0430\u0440", - "DevBuildWarning": "\u0416\u0430\u0441\u0430\u049b\u0442\u0430\u0443 \u049b\u04b1\u0440\u0430\u0441\u0442\u044b\u0440\u043c\u0430\u043b\u0430\u0440 \u0441\u04b1\u0440\u0430\u043f\u044b\u043b \u049b\u044b\u0440\u043b\u044b \u0431\u043e\u043b\u044b\u043f \u0442\u0430\u0431\u044b\u043b\u0430\u0434\u044b. \u0416\u0438\u0456 \u0448\u044b\u0493\u0430\u0440\u043b\u044b\u043f \u043c\u044b\u043d\u0430 \u049b\u04b1\u0440\u0430\u0441\u0442\u044b\u0440\u043c\u0430\u043b\u0430\u0440 \u0442\u043e\u043b\u044b\u049b \u0441\u044b\u043d\u0430\u049b\u0442\u0430\u043c\u0430\u043b\u0430\u0443\u0434\u0430\u043d \u04e9\u0442\u043f\u0435\u0433\u0435\u043d. \u049a\u043e\u043b\u0434\u0430\u043d\u0431\u0430 \u0431\u04b1\u0437\u044b\u043b\u0443 \u043c\u04af\u043c\u043a\u0456\u043d \u0436\u04d9\u043d\u0435 \u0430\u049b\u044b\u0440 \u0430\u044f\u0493\u044b\u043d\u0434\u0430 \u043c\u04af\u043c\u043a\u0456\u043d\u0434\u0456\u043a\u0442\u0435\u0440 \u0431\u04af\u0442\u0456\u043d\u0434\u0435\u0439 \u0436\u04b1\u043c\u044b\u0441 \u0456\u0441\u0442\u0435\u043c\u0435\u0443\u0456 \u043c\u04af\u043c\u043a\u0456\u043d.", + "DevBuildWarning": "\u0416\u0430\u0441\u0430\u049b\u0442\u0430\u0443 \u049b\u04b1\u0440\u0430\u0441\u0442\u044b\u0440\u043c\u0430\u043b\u0430\u0440 \u0441\u04b1\u0440\u0430\u043f\u044b\u043b \u049b\u044b\u0440\u043b\u044b \u0431\u043e\u043b\u044b\u043f \u0442\u0430\u0431\u044b\u043b\u0430\u0434\u044b. \u0416\u0438\u0456 \u0448\u044b\u0493\u0430\u0440\u043b\u044b\u043f \u043c\u044b\u043d\u0430 \u049b\u04b1\u0440\u0430\u0441\u0442\u044b\u0440\u043c\u0430\u043b\u0430\u0440 \u0442\u043e\u043b\u044b\u049b \u0441\u044b\u043d\u0430\u049b\u0442\u0430\u043c\u0430\u043b\u0430\u0443\u0434\u0430\u043d \u04e9\u0442\u043f\u0435\u0433\u0435\u043d. \u049a\u043e\u043b\u0434\u0430\u043d\u0431\u0430 \u0431\u04b1\u0437\u044b\u043b\u0443 \u043c\u04af\u043c\u043a\u0456\u043d \u0436\u04d9\u043d\u0435 \u0430\u049b\u044b\u0440 \u0430\u044f\u0493\u044b\u043d\u0434\u0430 \u0435\u0440\u0435\u043a\u0448\u0435\u043b\u0456\u043a\u0442\u0435\u0440 \u0431\u04af\u0442\u0456\u043d\u0434\u0435\u0439 \u0436\u04b1\u043c\u044b\u0441 \u0456\u0441\u0442\u0435\u043c\u0435\u0443\u0456 \u043c\u04af\u043c\u043a\u0456\u043d.", "LabelVideoType": "\u0411\u0435\u0439\u043d\u0435 \u0442\u04af\u0440\u0456:", "OptionBluray": "BluRay", "OptionDvd": "DVD", "OptionIso": "ISO", "Option3D": "3D", - "LabelFeatures": "\u041c\u04d9\u043b\u0456\u043c\u0435\u0442\u0442\u0435\u0440:", + "LabelFeatures": "\u0415\u0440\u0435\u043a\u0448\u0435\u043b\u0456\u043a\u0442\u0435\u0440:", "LabelService": "\u049a\u044b\u0437\u043c\u0435\u0442:", "LabelStatus": "\u041a\u04af\u0439:", "LabelVersion": "\u041d\u04b1\u0441\u049b\u0430:", @@ -217,12 +241,12 @@ "LabelArtistsHelp": "\u0411\u0456\u0440\u043d\u0435\u0448\u0443\u0456\u043d (;) \u0430\u0440\u049b\u044b\u043b\u044b \u0431\u04e9\u043b\u0456\u04a3\u0456\u0437", "HeaderLatestMovies": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456 \u0444\u0438\u043b\u044c\u043c\u0434\u0435\u0440", "HeaderLatestTrailers": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043b\u0435\u0440", - "OptionHasSpecialFeatures": "\u041c\u04d9\u043b\u0456\u043c\u0435\u0442\u0442\u0435\u0440", + "OptionHasSpecialFeatures": "\u0410\u0440\u043d\u0430\u0439\u044b \u0435\u0440\u0435\u043a\u0448\u0435\u043b\u0456\u043a\u0442\u0435\u0440", "OptionImdbRating": "IMDb \u0431\u0430\u0493\u0430\u043b\u0430\u0443\u044b", "OptionParentalRating": "\u0416\u0430\u0441\u0442\u0430\u0441 \u0441\u0430\u043d\u0430\u0442", "OptionPremiereDate": "\u0422\u04b1\u0441\u0430\u0443\u043a\u0435\u0441\u0435\u0440 \u043a\u04af\u043d-\u0430\u0439\u044b", "TabBasic": "\u041d\u0435\u0433\u0456\u0437\u0433\u0456\u043b\u0435\u0440", - "TabAdvanced": "\u049a\u043e\u0441\u044b\u043c\u0448\u0430", + "TabAdvanced": "\u041a\u0435\u04a3\u0435\u0439\u0442\u0456\u043b\u0433\u0435\u043d", "HeaderStatus": "\u041a\u04af\u0439", "OptionContinuing": "\u0416\u0430\u043b\u0493\u0430\u0441\u0443\u0434\u0430", "OptionEnded": "\u0410\u044f\u049b\u0442\u0430\u043b\u0434\u044b", @@ -241,11 +265,11 @@ "OptionMissingOverview": "\u0416\u0430\u043b\u043f\u044b \u0448\u043e\u043b\u0443 \u0436\u043e\u049b", "OptionFileMetadataYearMismatch": "\u0424\u0430\u0439\u043b\/\u043c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a \u0436\u044b\u043b\u044b \u0441\u04d9\u0439\u043a\u0435\u0441 \u0435\u043c\u0435\u0441", "TabGeneral": "\u0416\u0430\u043b\u043f\u044b", - "TitleSupport": "\u049a\u043e\u043b\u0434\u0430\u0443", + "TitleSupport": "\u0416\u0430\u049b\u0442\u0430\u0443", "TabLog": "\u0416\u04b1\u0440\u043d\u0430\u043b", "TabAbout": "\u0422\u0443\u0440\u0430\u043b\u044b", - "TabSupporterKey": "\u049a\u043e\u043b\u0434\u0430\u0443\u0448\u044b \u043a\u0456\u043b\u0442\u0456", - "TabBecomeSupporter": "\u049a\u043e\u043b\u0434\u0430\u0443\u0448\u044b \u0431\u043e\u043b\u0443", + "TabSupporterKey": "\u0416\u0430\u049b\u0442\u0430\u0443\u0448\u044b \u043a\u0456\u043b\u0442\u0456", + "TabBecomeSupporter": "\u0416\u0430\u049b\u0442\u0430\u0443\u0448\u044b \u0431\u043e\u043b\u0443", "MediaBrowserHasCommunity": "Media Browser \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043b\u0430\u0440\u044b \u0431\u0435\u043d \u049b\u043e\u043b\u0434\u0430\u0443\u0448\u044b\u043b\u0430\u0440\u0434\u044b\u04a3 \u0434\u0430\u043c\u0443\u0434\u0430\u0493\u044b \u049b\u0430\u0443\u044b\u043c\u0434\u0430\u0441\u0442\u044b\u0493\u044b \u0431\u0430\u0440.", "CheckoutKnowledgeBase": "Media Browser \u0435\u04a3 \u04af\u043b\u043a\u0435\u043d \u049b\u0430\u0439\u0442\u0430\u0440\u044b\u043c\u0434\u044b\u043b\u044b\u0493\u044b\u043d \u0430\u043b\u0443 \u0436\u04e9\u043d\u0456\u043d\u0434\u0435 \u043a\u04e9\u043c\u0435\u043a\u0442\u0435\u0441\u0443 \u04af\u0448\u0456\u043d \u0411\u0456\u043b\u0456\u043c \u049b\u043e\u0440\u044b\u043d \u049b\u0430\u0440\u0430\u043f \u0448\u044b\u0493\u044b\u04a3\u044b\u0437.", "SearchKnowledgeBase": "\u0411\u0456\u043b\u0456\u043c \u049b\u043e\u0440\u044b\u043d\u0430\u043d \u0456\u0437\u0434\u0435\u0443", @@ -260,7 +284,7 @@ "LabelName": "\u0410\u0442\u044b:", "ButtonHelp": "\u0410\u043d\u044b\u049b\u0442\u0430\u043c\u0430", "OptionAllowUserToManageServer": "\u0411\u0443\u043b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u0493\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0434\u0456 \u0431\u0430\u0441\u049b\u0430\u0440\u0443 \u04af\u0448\u0456\u043d \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0443", - "HeaderFeatureAccess": "\u041c\u04af\u043c\u043a\u0456\u043d\u0434\u0456\u043a\u0442\u0435\u0440\u0433\u0435 \u049b\u0430\u0442\u044b\u043d\u0430\u0441", + "HeaderFeatureAccess": "\u0415\u0440\u0435\u043a\u0448\u0435\u043b\u0456\u043a\u0442\u0435\u0440\u0433\u0435 \u049b\u0430\u0442\u044b\u043d\u0430\u0441\u0443", "OptionAllowMediaPlayback": "\u0422\u0430\u0441\u0443\u0448\u044b\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0434\u0456 \u043e\u0439\u043d\u0430\u0442\u0443\u044b\u043d\u0430 \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0443", "OptionAllowBrowsingLiveTv": "\u042d\u0444\u0438\u0440\u043b\u0456\u043a \u0422\u0414 \u0448\u043e\u043b\u0443\u044b\u043d\u0430 \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0443", "OptionAllowDeleteLibraryContent": "\u0422\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430 \u043c\u0430\u0437\u043c\u04b1\u043d\u044b\u043d \u0436\u043e\u044e \u04af\u0448\u0456\u043d \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0443", @@ -275,16 +299,16 @@ "OptionMetascore": "Metascore \u0431\u0430\u0493\u0430\u043b\u0430\u0443\u044b", "ButtonSelect": "\u0411\u04e9\u043b\u0435\u043a\u0442\u0435\u0443", "ButtonGroupVersions": "\u041d\u04b1\u0441\u049b\u0430\u043b\u0430\u0440\u0434\u044b \u0442\u043e\u043f\u0442\u0430\u0441\u0442\u044b\u0440\u0443", - "ButtonAddToCollection": "\u0416\u0438\u044b\u043d\u0442\u044b\u049b\u049b\u0430 \u049b\u043e\u0441\u0443", + "ButtonAddToCollection": "\u0416\u0438\u044b\u043d\u0442\u044b\u049b\u049b\u0430 \u04af\u0441\u0442\u0435\u0443", "PismoMessage": "\u0421\u044b\u0439\u043b\u0430\u043d\u0493\u0430\u043d \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u044f \u0430\u0440\u049b\u044b\u043b\u044b Pismo File Mount \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0434\u0430.", "TangibleSoftwareMessage": "\u0421\u044b\u0439\u043b\u0430\u043d\u0493\u0430\u043d \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u044f \u0430\u0440\u049b\u044b\u043b\u044b Tangible Solutions Java\/C# \u0442\u04af\u0440\u043b\u0435\u043d\u0434\u0456\u0440\u0433\u0456\u0448\u0442\u0435\u0440\u0456 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0434\u0430.", - "HeaderCredits": "\u049a\u0430\u0442\u044b\u0441\u049b\u0430\u043d\u0434\u0430\u0440", - "PleaseSupportOtherProduces": "\u0411\u0456\u0437 \u049b\u043e\u043b\u0434\u0430\u043d\u0430\u0442\u044b\u043d \u0431\u0430\u0441\u049b\u0430 \u0430\u0448\u044b\u049b \u04e9\u043d\u0456\u043c\u0434\u0435\u0440\u0434\u0456 \u049b\u043e\u043b\u0434\u0430\u04a3\u044b\u0437:", + "HeaderCredits": "\u0428\u044b\u0493\u0430\u0440\u043c\u0430\u0448\u044b\u043b\u044b\u049b\u0442\u044b \u0440\u0430\u0441\u0442\u0430\u0443", + "PleaseSupportOtherProduces": "\u0411\u0456\u0437 \u049b\u043e\u043b\u0434\u0430\u043d\u0430\u0442\u044b\u043d \u0431\u0430\u0441\u049b\u0430 \u0442\u0435\u0433\u0456\u043d \u04e9\u043d\u0456\u043c\u0434\u0435\u0440\u0434\u0456 \u0436\u0430\u049b\u0442\u0430\u04a3\u044b\u0437:", "VersionNumber": "\u041d\u04b1\u0441\u049b\u0430\u0441\u044b: {0}", "TabPaths": "\u0416\u043e\u043b\u0434\u0430\u0440", "TabServer": "\u0421\u0435\u0440\u0432\u0435\u0440", "TabTranscoding": "\u049a\u0430\u0439\u0442\u0430 \u043a\u043e\u0434\u0442\u0430\u0443", - "TitleAdvanced": "\u049a\u043e\u0441\u044b\u043c\u0448\u0430", + "TitleAdvanced": "\u041a\u0435\u04a3\u0435\u0439\u0442\u0456\u043b\u0433\u0435\u043d", "LabelAutomaticUpdateLevel": "\u0410\u0432\u0442\u043e\u0436\u0430\u04a3\u0430\u0440\u0442\u0443 \u0434\u0435\u04a3\u0433\u0435\u0439\u0456", "OptionRelease": "\u0420\u0435\u0441\u043c\u0438 \u0448\u044b\u0493\u0430\u0440\u044b\u043b\u044b\u043c", "OptionBeta": "\u0411\u0435\u0442\u0430 \u043d\u04b1\u0441\u049b\u0430", @@ -296,10 +320,10 @@ "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": "\u041a\u0435\u0448\u043a\u0435 \u049b\u0430\u0440\u0430\u0439 \u0436\u043e\u043b:", + "LabelCachePath": "\u041a\u044d\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": "\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.", + "LabelImagesByNamePathHelp": "\u0416\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u044b\u043d\u0493\u0430\u043d \u0430\u043a\u0442\u0435\u0440, \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": "\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:", @@ -314,12 +338,14 @@ "OptionEpisodes": "\u042d\u043f\u0438\u0437\u043e\u0434\u0442\u0430\u0440", "OptionOtherVideos": "\u0411\u0430\u0441\u049b\u0430 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440", "TitleMetadata": "\u041c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a", - "LabelAutomaticUpdatesFanart": "FanArt.tv \u043a\u04e9\u0437\u0456\u043d\u0435\u043d \u0430\u0432\u0442\u043e\u0436\u0430\u04a3\u0430\u0440\u0442\u0443\u0434\u044b \u049b\u043e\u0441\u0443", + "LabelAutomaticUpdates": "\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0442\u044b \u0442\u04af\u0440\u0434\u0435 \u0436\u0430\u04a3\u0430\u0440\u0442\u0443\u043b\u0430\u0440\u0434\u044b \u049b\u043e\u0441\u0443", "LabelAutomaticUpdatesTmdb": "TheMovieDB.org \u043a\u04e9\u0437\u0456\u043d\u0435\u043d \u0430\u0432\u0442\u043e\u0436\u0430\u04a3\u0430\u0440\u0442\u0443\u0434\u044b \u049b\u043e\u0441\u0443", "LabelAutomaticUpdatesTvdb": "TheTVDB.com \u043a\u04e9\u0437\u0456\u043d\u0435\u043d \u0430\u0432\u0442\u043e\u0436\u0430\u04a3\u0430\u0440\u0442\u0443\u0434\u044b \u049b\u043e\u0441\u0443", "LabelAutomaticUpdatesFanartHelp": "\u049a\u043e\u0441\u044b\u043b\u0493\u0430\u043d\u0434\u0430, \u0436\u0430\u04a3\u0430 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440 fanart.tv \u0434\u0435\u0440\u0435\u049b\u043e\u0440\u044b\u043d\u0430 \u04af\u0441\u0442\u0435\u043b\u0433\u0435\u043d \u0431\u043e\u0439\u0434\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0442\u044b \u0442\u04af\u0440\u0434\u0435 \u0436\u04af\u043a\u0442\u0435\u043b\u0456\u043f \u0430\u043b\u044b\u043d\u0430\u0434\u044b. \u0411\u0430\u0440 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440 \u0430\u0443\u044b\u0441\u0442\u044b\u0440\u044b\u043b\u043c\u0430\u0439\u0434\u044b.", "LabelAutomaticUpdatesTmdbHelp": "\u049a\u043e\u0441\u044b\u043b\u0493\u0430\u043d\u0434\u0430, \u0436\u0430\u04a3\u0430 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440 TheMovieDB.org \u0434\u0435\u0440\u0435\u049b\u043e\u0440\u044b\u043d\u0430 \u04af\u0441\u0442\u0435\u043b\u0433\u0435\u043d \u0431\u043e\u0439\u0434\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0442\u044b \u0442\u04af\u0440\u0434\u0435 \u0436\u04af\u043a\u0442\u0435\u043b\u0456\u043f \u0430\u043b\u044b\u043d\u0430\u0434\u044b. \u0411\u0430\u0440 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440 \u0430\u0443\u044b\u0441\u0442\u044b\u0440\u044b\u043b\u043c\u0430\u0439\u0434\u044b.", "LabelAutomaticUpdatesTvdbHelp": "\u049a\u043e\u0441\u044b\u043b\u0493\u0430\u043d\u0434\u0430, \u0436\u0430\u04a3\u0430 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440 TheTVDB.com \u0434\u0435\u0440\u0435\u049b\u043e\u0440\u044b\u043d\u0430 \u04af\u0441\u0442\u0435\u043b\u0433\u0435\u043d \u0431\u043e\u0439\u0434\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0442\u044b \u0442\u04af\u0440\u0434\u0435 \u0436\u04af\u043a\u0442\u0435\u043b\u0456\u043f \u0430\u043b\u044b\u043d\u0430\u0434\u044b. \u0411\u0430\u0440 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440 \u0430\u0443\u044b\u0441\u0442\u044b\u0440\u044b\u043b\u043c\u0430\u0439\u0434\u044b.", + "LabelFanartApiKey": "\u0416\u0435\u043a\u0435 api-\u043a\u0456\u043b\u0442:", + "LabelFanartApiKeyHelp": "\u0416\u0435\u043a\u0435 API-\u043a\u0456\u043b\u0442\u0456\u0441\u0456\u0437 Fanart \u04af\u0448\u0456\u043d \u0436\u0456\u0431\u0435\u0440\u0456\u043b\u0433\u0435\u043d \u0441\u0430\u0443\u0430\u043b\u0434\u0430\u0440\u0493\u0430 7 \u043a\u04af\u043d\u0456\u043d\u0435\u043d \u0431\u04b1\u0440\u044b\u043d \u0440\u0430\u0441\u0442\u0430\u043b\u0493\u0430\u043d \u043d\u04d9\u0442\u0438\u0436\u0435\u043b\u0435\u0440 \u049b\u0430\u0439\u0442\u0430\u0440\u044b\u043b\u0430\u0434\u044b. \u0416\u0435\u043a\u0435 API-\u043a\u0456\u043b\u0442\u0456\u043c\u0435\u043d \u0431\u04b1\u043b 48 \u0441\u0430\u0493\u0430\u0442\u049b\u0430 \u0434\u0435\u0439\u0456\u043d \u049b\u044b\u0441\u049b\u0430\u0440\u0442\u044b\u043b\u0430\u0434\u044b, \u0430\u043b,\u0441\u043e\u043d\u0434\u0430\u0439-\u0430\u049b, Fanart VIP-\u043c\u04af\u0448\u0435\u0441\u0456 \u0431\u043e\u043b\u0441\u0430\u04a3\u044b\u0437, \u0431\u04b1\u043b \u0448\u0430\u043c\u0430\u043c\u0435\u043d 10 \u043c\u0438\u043d\u04e9\u0442\u043a\u0435 \u0434\u0435\u0439\u0456\u043d \u0442\u0430\u0493\u044b \u0434\u0430 \u049b\u044b\u0441\u049b\u0430\u0440\u0442\u044b\u043b\u0430\u0434\u044b.", "ExtractChapterImagesHelp": "\u0421\u0430\u0445\u043d\u0430 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0456\u043d \u0448\u044b\u0493\u0430\u0440\u044b\u043f \u0430\u043b\u0443 \u043a\u043b\u0438\u0435\u043d\u0442\u0442\u0435\u0440\u0433\u0435 \u0441\u0430\u0445\u043d\u0430 \u0431\u04e9\u043b\u0435\u043a\u0442\u0435\u0443\u0433\u0435 \u0430\u0440\u043d\u0430\u043b\u0493\u0430\u043d \u0441\u044b\u0437\u0431\u0430\u043b\u044b\u049b \u043c\u04d9\u0437\u0456\u0440\u043b\u0435\u0440\u0434\u0456 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0443 \u04af\u0448\u0456\u043d \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0435\u0434\u0456. \u0411\u04b1\u043b \u043f\u0440\u043e\u0446\u0435\u0441 \u0431\u0430\u044f\u0443, \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0434\u044b \u0442\u043e\u0437\u0434\u044b\u0440\u0430\u0442\u044b\u043d \u0436\u04d9\u043d\u0435 \u0431\u0456\u0440\u0430\u0437 \u0433\u0438\u0433\u0430\u0431\u0430\u0439\u0442 \u043a\u0435\u04a3\u0456\u0441\u0442\u0456\u043a\u0442\u0456 \u049b\u0430\u0436\u0435\u0442 \u0435\u0442\u0435\u0442\u0456\u043d \u0431\u043e\u043b\u0443\u044b \u043c\u04af\u043c\u043a\u0456\u043d. \u041e\u043b \u0431\u0435\u0439\u043d\u0435\u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b \u0442\u0430\u0431\u044b\u043b\u0493\u0430\u043d\u0434\u0430, \u0436\u04d9\u043d\u0435 \u0442\u0430\u04a3\u0493\u044b 4:00 \u0441\u0430\u0493\u0430\u0442\u044b\u043d\u0430 \u0436\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0493\u0430\u043d \u0442\u0430\u043f\u0441\u044b\u0440\u043c\u0430 \u0440\u0435\u0442\u0456\u043d\u0434\u0435 \u0436\u04b1\u043c\u044b\u0441 \u0456\u0441\u0442\u0435\u0439\u0434\u0456. \u041e\u0440\u044b\u043d\u0434\u0430\u0443 \u043a\u0435\u0441\u0442\u0435\u0441\u0456 \u0416\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0443\u0448\u044b \u0430\u0439\u043c\u0430\u0493\u044b\u043d\u0434\u0430 \u0442\u0435\u04a3\u0448\u0435\u043b\u0435\u0434\u0456. \u0411\u04b1\u043b \u0442\u0430\u043f\u0441\u044b\u0440\u043c\u0430\u043d\u044b \u049b\u0430\u0440\u0431\u0430\u043b\u0430\u0441 \u0441\u0430\u0493\u0430\u0442\u0442\u0430\u0440\u044b\u043d\u0434\u0430 \u0436\u04b1\u043c\u044b\u0441 \u0456\u0441\u0442\u0435\u0442\u043a\u0456\u0437\u0443 \u04b1\u0441\u044b\u043d\u044b\u043b\u043c\u0430\u0439\u0434\u044b.", "LabelMetadataDownloadLanguage": "\u0416\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443 \u0442\u0456\u043b\u0456\u043d\u0456\u04a3 \u0442\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0456:", "ButtonAutoScroll": "\u0410\u0432\u0442\u043e\u0430\u0439\u043d\u0430\u043b\u0434\u044b\u0440\u0443", @@ -435,7 +461,7 @@ "HeaderAwardsAndReviews": "\u041c\u0430\u0440\u0430\u043f\u0430\u0442\u0442\u0430\u0440 \u043c\u0435\u043d \u043f\u0456\u043a\u0456\u0440\u0441\u0430\u0440\u0430\u043f\u0442\u0430\u0440", "HeaderSoundtracks": "\u0424\u0438\u043b\u044c\u043c\u0434\u0456\u04a3 \u043c\u0443\u0437\u044b\u043a\u0430\u0441\u044b", "HeaderMusicVideos": "\u041c\u0443\u0437\u044b\u043a\u0430\u043b\u044b\u049b \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440", - "HeaderSpecialFeatures": "\u0410\u0440\u043d\u0430\u0439\u044b \u043c\u04d9\u043b\u0456\u043c\u0435\u0442\u0442\u0435\u0440", + "HeaderSpecialFeatures": "\u0410\u0440\u043d\u0430\u0439\u044b \u0435\u0440\u0435\u043a\u0448\u0435\u043b\u0456\u043a\u0442\u0435\u0440", "HeaderCastCrew": "\u0422\u04af\u0441\u0456\u0440\u0443\u0433\u0435 \u049b\u0430\u0442\u044b\u0441\u049b\u0430\u043d\u0434\u0430\u0440", "HeaderAdditionalParts": "\u0416\u0430\u043b\u0493\u0430\u0441\u0430\u0442\u044b\u043d \u0431\u04e9\u043b\u0456\u043c\u0434\u0435\u0440", "ButtonSplitVersionsApart": "\u041d\u04af\u0441\u049b\u0430\u043b\u0430\u0440\u0434\u044b \u049b\u0430\u0439\u0442\u0430 \u0431\u04e9\u043b\u0443", @@ -482,11 +508,12 @@ "SystemDlnaProfilesHelp": "\u0416\u04af\u0439\u0435\u043b\u0456\u043a \u043f\u0440\u043e\u0444\u0438\u043b\u044c\u0434\u0435\u0440 \u0442\u0435\u043a \u043e\u049b\u0443 \u04af\u0448\u0456\u043d. \u0416\u04af\u0439\u0435\u043b\u0456\u043a \u043f\u0440\u043e\u0444\u0438\u043b\u044c\u0434\u0456\u04a3 \u04e9\u0437\u0433\u0435\u0440\u0456\u0441\u0442\u0435\u0440\u0456 \u0436\u0430\u04a3\u0430 \u0442\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u043f\u0440\u043e\u0444\u0438\u043b\u044c\u0433\u0435 \u0436\u0430\u0437\u044b\u043b\u0430\u0434\u044b.", "TitleDashboard": "\u0411\u0430\u049b\u044b\u043b\u0430\u0443 \u0442\u0430\u049b\u0442\u0430\u0441\u044b", "TabHome": "\u0411\u0430\u0441\u0442\u044b", - "TabInfo": "\u0410\u049b\u043f\u0430\u0440\u0430\u0442", + "TabInfo": "\u041f\u0440\u043e\u0444\u0430\u0439\u043b \u0442\u0443\u0440\u0430\u043b\u044b", "HeaderLinks": "\u0421\u0456\u043b\u0442\u0435\u043c\u0435\u043b\u0435\u0440", "HeaderSystemPaths": "\u0416\u04af\u0439\u0435\u043b\u0456\u043a \u0436\u043e\u043b\u0434\u0430\u0440", "LinkCommunity": "\u049a\u0430\u0443\u044b\u043c\u0434\u0430\u0441\u0442\u044b\u049b", "LinkGithub": "Github \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439\u0456", + "LinkApi": "API", "LinkApiDocumentation": "API \u049b\u04b1\u0436\u0430\u0442\u0442\u0430\u043c\u0430\u0441\u044b", "LabelFriendlyServerName": "\u0421\u0435\u0440\u0432\u0435\u0440\u0434\u0456\u04a3 \u043e\u04a3\u0430\u0439 \u0430\u0442\u044b:", "LabelFriendlyServerNameHelp": "\u0411\u04b1\u043b \u0430\u0442\u0430\u0443 \u043e\u0441\u044b \u0441\u0435\u0440\u0432\u0435\u0440\u0434\u0456 \u0430\u043d\u044b\u049b\u0442\u0430\u0443 \u04af\u0448\u0456\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u043b\u0430\u0434\u044b. \u0415\u0433\u0435\u0440 \u04e9\u0440\u0456\u0441 \u0431\u043e\u0441 \u049b\u0430\u043b\u0434\u044b\u0440\u044b\u043b\u0441\u0430, \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440 \u0430\u0442\u044b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u043b\u0430\u0434\u044b.", @@ -494,20 +521,25 @@ "LabelPreferredDisplayLanguageHelp": "Media Browser \u0442\u04d9\u0440\u0436\u0456\u043c\u0435\u043b\u0435\u0443\u0456 \u0434\u0430\u043c\u044b\u0442\u043f\u0430\u043b\u044b \u0436\u043e\u0431\u0430 \u0431\u043e\u043b\u044b\u043f \u0442\u0430\u0431\u044b\u043b\u0430\u0434\u044b, \u0436\u04d9\u043d\u0435 \u0431\u04b1\u043b \u04d9\u043b\u0456 \u0434\u0435 \u0430\u044f\u049b\u0442\u0430\u043b\u0493\u0430\u043d \u0435\u043c\u0435\u0441.", "LabelReadHowYouCanContribute": "\u049a\u0430\u043b\u0430\u0439 \u0456\u0441\u043a\u0435\u0440\u043b\u0435\u0441\u0443 \u043c\u04af\u043c\u043a\u0456\u043d\u0434\u0456\u0433\u0456\u04a3\u0456\u0437 \u0442\u0443\u0440\u0430\u043b\u044b \u043e\u049b\u044b\u04a3\u044b\u0437.", "HeaderNewCollection": "\u0416\u0430\u04a3\u0430 \u0436\u0438\u044b\u043d\u0442\u044b\u049b", - "HeaderAddToCollection": "\u0416\u0438\u044b\u043d\u0442\u044b\u049b\u049b\u0430 \u049b\u043e\u0441\u0443", "ButtonSubmit": "\u0416\u0456\u0431\u0435\u0440\u0443", - "NewCollectionNameExample": "\u041c\u044b\u0441\u0430\u043b: \u0416\u04b1\u043b\u0434\u044b\u0437 \u0441\u043e\u0493\u044b\u0441\u0442\u0430\u0440\u044b (\u0436\u0438\u044b\u043d\u0442\u044b\u049b)", - "OptionSearchForInternetMetadata": "\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 \u0456\u0437\u0434\u0435\u0443", "ButtonCreate": "\u0416\u0430\u0441\u0430\u0443", - "LabelLocalHttpServerPortNumber": "\u0416\u0435\u0440\u0433\u0456\u043b\u0456\u043a\u0442\u0456 \u043f\u043e\u0440\u0442 \u043d\u04e9\u043c\u0456\u0440\u0456:", + "LabelCustomCss": "\u0422\u0435\u04a3\u0448\u0435\u0443\u043b\u0456 css:", + "LabelCustomCssHelp": "\u04e8\u0437\u0456\u04a3\u0456\u0437\u0434\u0456\u04a3 \u0442\u0435\u04a3\u0448\u0435\u0443\u043b\u0456 css \u043a\u043e\u0434\u044b\u043d \u0432\u0435\u0431-\u0442\u0456\u043b\u0434\u0435\u0441\u0443\u0434\u0435 \u049b\u043e\u043b\u0434\u0430\u043d\u044b\u04a3\u044b\u0437.", + "LabelLocalHttpServerPortNumber": "\u0416\u0435\u0440\u0433\u0456\u043b\u0456\u043a\u0442\u0456 http-\u043f\u043e\u0440\u0442 \u043d\u04e9\u043c\u0456\u0440\u0456:", "LabelLocalHttpServerPortNumberHelp": "Media Browser HTTP \u0441\u0435\u0440\u0432\u0435\u0440\u0456 \u0431\u0430\u0439\u043b\u0430\u0441\u0442\u044b\u0440\u044b\u043b\u0443\u044b \u0442\u0438\u0456\u0441\u0442\u0456 TCP \u043f\u043e\u0440\u0442 \u043d\u04e9\u043c\u0456\u0440\u0456.", - "LabelPublicPort": "\u0416\u0430\u0440\u0438\u044f \u043f\u043e\u0440\u0442 \u043d\u04e9\u043c\u0456\u0440\u0456:", - "LabelPublicPortHelp": "\u0416\u0435\u0440\u0433\u0456\u043b\u0456\u043a\u0442\u0456 \u043f\u043e\u0440\u0442\u049b\u0430 \u0441\u0430\u043b\u044b\u0441\u0442\u044b\u0440\u044b\u043b\u0443\u044b \u0442\u0438\u0456\u0441\u0442\u0456 \u0436\u0430\u0440\u0438\u044f \u043f\u043e\u0440\u0442 \u043d\u04e9\u043c\u0456\u0440\u0456.", + "LabelPublicHttpPort": "\u0416\u0430\u0440\u0438\u044f http-\u043f\u043e\u0440\u0442 \u043d\u04e9\u043c\u0456\u0440\u0456:", + "LabelPublicHttpPortHelp": "\u0416\u0435\u0440\u0433\u0456\u043b\u0456\u043a\u0442\u0456 http-\u043f\u043e\u0440\u0442\u044b\u043d\u0430 \u0441\u0430\u043b\u044b\u0441\u0442\u044b\u0440\u044b\u043b\u0443\u044b \u0442\u0438\u0456\u0441 \u0436\u0430\u0440\u0438\u044f \u043f\u043e\u0440\u0442 \u043d\u04e9\u043c\u0456\u0440\u0456.", + "LabelPublicHttpsPort": "\u0416\u0430\u0440\u0438\u044f https-\u043f\u043e\u0440\u0442 \u043d\u04e9\u043c\u0456\u0440\u0456:", + "LabelPublicHttpsPortHelp": "\u0416\u0435\u0440\u0433\u0456\u043b\u0456\u043a\u0442\u0456 https-\u043f\u043e\u0440\u0442\u044b\u043d\u0430 \u0441\u0430\u043b\u044b\u0441\u0442\u044b\u0440\u044b\u043b\u0443\u044b \u0442\u0438\u0456\u0441 \u0436\u0430\u0440\u0438\u044f \u043f\u043e\u0440\u0442 \u043d\u04e9\u043c\u0456\u0440\u0456.", + "LabelEnableHttps": "HTTPS \u0445\u0430\u0442\u0442\u0430\u043c\u0430\u0441\u044b \u0441\u044b\u0440\u0442\u049b\u044b \u043c\u0435\u043a\u0435\u043d\u0435\u0436\u0430\u0439 \u0440\u0435\u0442\u0456\u043d\u0434\u0435 \u0431\u0430\u044f\u043d\u0434\u0430\u0443", + "LabelEnableHttpsHelp": "\u0415\u0433\u0435\u0440 \u049b\u043e\u0441\u044b\u043b\u0441\u0430, \u043a\u043b\u0438\u0435\u043d\u0442\u0442\u0435\u0440 \u04af\u0448\u0456\u043d \u0441\u0435\u0440\u0432\u0435\u0440 https url \u0441\u044b\u0440\u0442\u049b\u044b \u043c\u0435\u043a\u0435\u043d\u0436\u0430\u0439 \u0440\u0435\u0442\u0456\u043d\u0434\u0435 \u0431\u0430\u044f\u043d\u0434\u0430\u0439\u0434\u044b. \u0411\u04b1\u043b \u04d9\u043b\u0456 \u0434\u0435 https \u049b\u043e\u043b\u0434\u0430\u043c\u0430\u0439\u0442\u044b\u043d \u043a\u043b\u0438\u0435\u043d\u0442\u0442\u0435\u0440\u0434\u0456\u04a3 \u0436\u04b1\u043c\u044b\u0441\u044b\u043d \u04af\u0437\u0443\u0456 \u043c\u04af\u043c\u043a\u0456\u043d.", + "LabelHttpsPort": "\u0416\u0435\u0440\u0433\u0456\u043b\u0456\u043a\u0442\u0456 https-\u043f\u043e\u0440\u0442 \u043d\u04e9\u043c\u0456\u0440\u0456:", + "LabelHttpsPortHelp": "Media Browser https-\u0441\u0435\u0440\u0432\u0435\u0440\u0456 \u0431\u0430\u0439\u043b\u0430\u0441\u0442\u044b\u0440\u044b\u043b\u0443\u0493\u0430 \u0442\u0438\u0456\u0441\u0442\u0456 tcp-\u043f\u043e\u0440\u0442 \u043d\u04e9\u043c\u0456\u0440\u0456.", "LabelWebSocketPortNumber": "\u0412\u0435\u0431-\u0441\u043e\u043a\u0435\u0442 \u043f\u043e\u0440\u0442\u044b\u043d\u044b\u04a3 \u043d\u04e9\u043c\u0456\u0440\u0456:", "LabelEnableAutomaticPortMap": "\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0442\u044b \u0442\u04af\u0440\u0434\u0435 \u043f\u043e\u0440\u0442 \u0441\u0430\u043b\u044b\u0441\u0442\u044b\u0440\u0443\u044b\u043d \u049b\u043e\u0441\u0443", "LabelEnableAutomaticPortMapHelp": "\u0416\u0430\u0440\u0438\u044f \u043f\u043e\u0440\u0442\u0442\u044b \u0436\u0435\u0440\u0433\u0456\u043b\u0456\u043a\u0442\u0456 \u043f\u043e\u0440\u0442\u049b\u0430 UPnP \u0430\u0440\u049b\u044b\u043b\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0442\u044b \u0442\u04af\u0440\u0434\u0435 \u0441\u0430\u043b\u044b\u0441\u0442\u044b\u0440\u0443 \u04d9\u0440\u0435\u043a\u0435\u0442\u0456. \u0411\u04b1\u043b \u043a\u0435\u0439\u0431\u0456\u0440 \u0436\u043e\u043b \u0436\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0493\u044b\u0448 \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.", - "LabelExternalDDNS": "\u0421\u044b\u0440\u0442\u049b\u044b DDNS:", - "LabelExternalDDNSHelp": "\u0415\u0433\u0435\u0440 dynamic DNS \u0431\u043e\u043b\u0441\u0430, \u0431\u04b1\u043d\u044b \u043c\u04b1\u043d\u0434\u0430 \u0435\u043d\u0433\u0456\u0437\u0456\u04a3\u0456\u0437. Media Browser \u049b\u043e\u043b\u0434\u0430\u043d\u0431\u0430\u043b\u0430\u0440\u044b \u0431\u04b1\u043d\u044b \u049b\u0430\u0448\u044b\u049b\u0442\u0430\u043d \u049b\u043e\u0441\u044b\u043b\u0493\u0430\u043d\u0434\u0430 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0430\u0434\u044b.", + "LabelExternalDDNS": "\u0421\u044b\u0440\u0442\u049b\u044b WAN-\u043c\u0435\u043a\u0435\u043d\u0436\u0430\u0439:", + "LabelExternalDDNSHelp": "\u0415\u0433\u0435\u0440 \u0441\u0456\u0437\u0434\u0435 dynamic DNS \u0431\u043e\u043b\u0441\u0430, \u0431\u04b1\u043d\u044b \u043e\u0441\u044b \u0436\u0435\u0440\u0434\u0435 \u0435\u043d\u0433\u0456\u0437\u0456\u04a3\u0456\u0437. Media Browser \u049b\u043e\u043b\u0434\u0430\u043d\u0431\u0430\u043b\u0430\u0440\u044b \u0441\u044b\u0440\u0442\u0442\u0430\u043d \u049b\u043e\u0441\u044b\u043b\u0493\u0430\u043d\u0434\u0430 \u043e\u0441\u044b\u043d\u044b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0430\u0434\u044b. \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0442\u044b \u0442\u04af\u0440\u0434\u0435 \u0442\u0430\u0431\u044b\u043b\u0443 \u04af\u0448\u0456\u043d \u0431\u043e\u0441 \u049b\u0430\u043b\u0434\u044b\u0440\u044b\u04a3\u044b\u0437.", "TabResume": "\u0416\u0430\u043b\u0493\u0430\u0441\u0442\u044b\u0440\u0443", "TabWeather": "\u0410\u0443\u0430 \u0440\u0430\u0439\u044b", "TitleAppSettings": "\u049a\u043e\u043b\u0434\u0430\u043d\u0431\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440\u0456", @@ -534,11 +566,11 @@ "LabelEpisodeNumber": "\u042d\u043f\u0438\u0437\u043e\u0434 \u043d\u04e9\u043c\u0456\u0440\u0456:", "LabelEndingEpisodeNumber": "\u0410\u044f\u049b\u0442\u0430\u0443\u0448\u044b \u044d\u043f\u0438\u0437\u043e\u0434\u0442\u044b\u04a3 \u043d\u04e9\u043c\u0456\u0440\u0456:", "LabelEndingEpisodeNumberHelp": "\u0411\u04b1\u043b \u0442\u0435\u043a \u049b\u0430\u043d\u0430 \u0431\u0456\u0440\u043d\u0435\u0448\u0435 \u044d\u043f\u0438\u0437\u043e\u0434\u044b \u0431\u0430\u0440 \u0444\u0430\u0439\u043b\u0434\u0430\u0440 \u04af\u0448\u0456\u043d", - "HeaderSupportTheTeam": "Media Browser \u0442\u043e\u0431\u044b\u043d \u049b\u043e\u043b\u0434\u0430\u0443", + "HeaderSupportTheTeam": "Media Browser \u0442\u043e\u0431\u044b\u043d \u0436\u0430\u049b\u0442\u0430\u04a3\u044b\u0437", "LabelSupportAmount": "\u0421\u043e\u043c\u0430\u0441\u044b (USD)", - "HeaderSupportTheTeamHelp": "\u04ae\u043b\u0435\u0441 \u049b\u043e\u0441\u044b\u043f \u0431\u04b1\u043b \u0436\u043e\u0431\u0430\u043d\u044b\u04a3 \u04d9\u0437\u0456\u0440\u043b\u0435\u0443\u0456 \u0436\u0430\u043b\u0493\u0430\u0441\u0430\u0442\u044b\u043d\u0430 \u049b\u0430\u043c\u0442\u0430\u043c\u0430\u0441\u044b\u0437 \u0435\u0442\u0443 \u04af\u0448\u0456\u043d \u043a\u04e9\u043c\u0435\u043a \u0431\u0435\u0440\u0456\u04a3\u0456\u0437. \u0411\u0430\u0440\u043b\u044b\u049b \u049b\u0430\u0439\u044b\u0440\u043c\u0430\u043b\u0434\u044b\u049b\u0442\u044b\u04a3 \u04d9\u043b\u0434\u0435\u049b\u0430\u043d\u0448\u0430 \u0431\u04e9\u043b\u0456\u0433\u0456\u043d \u0442\u04d9\u0443\u0435\u043b\u0434\u0456\u043c\u0456\u0437 \u0431\u0430\u0441\u049b\u0430 \u0430\u0448\u044b\u049b \u049b\u04b1\u0440\u0430\u043b\u0434\u0430\u0440\u044b \u04af\u0448\u0456\u043d \u0456\u0441\u043a\u0435\u0440\u043b\u0435\u0441\u0435\u043c\u0456\u0437.", - "ButtonEnterSupporterKey": "\u049a\u043e\u043b\u0434\u0430\u0443\u0448\u044b \u043a\u0456\u043b\u0442\u0456\u043d \u0435\u043d\u0433\u0456\u0437\u0443", - "DonationNextStep": "\u0410\u044f\u049b\u0442\u0430\u043b\u044b\u0441\u044b\u043c\u0435\u043d, \u043a\u0435\u0440\u0456 \u049b\u0430\u0439\u0442\u044b\u04a3\u044b\u0437 \u0436\u0430\u043d\u0435 \u042d-\u043f\u043e\u0448\u0442\u0430 \u0430\u0440\u049b\u044b\u043b\u044b \u0430\u043b\u044b\u043d\u0493\u0430\u043d \u049b\u043e\u043b\u0434\u0430\u0443\u0448\u044b \u043a\u0456\u043b\u0442\u0456\u043d \u0435\u043d\u0433\u0456\u0437\u0456\u04a3\u0456\u0437.", + "HeaderSupportTheTeamHelp": "\u04ae\u043b\u0435\u0441 \u049b\u043e\u0441\u044b\u043f \u0431\u04b1\u043b \u0436\u043e\u0431\u0430\u043d\u044b\u04a3 \u04d9\u0437\u0456\u0440\u043b\u0435\u0443\u0456 \u0436\u0430\u043b\u0493\u0430\u0441\u0430\u0442\u044b\u043d\u0430 \u049b\u0430\u043c\u0442\u0430\u043c\u0430\u0441\u044b\u0437 \u0435\u0442\u0443 \u04af\u0448\u0456\u043d \u043a\u04e9\u043c\u0435\u043a \u0431\u0435\u0440\u0456\u04a3\u0456\u0437. \u0411\u0430\u0440\u043b\u044b\u049b \u049b\u0430\u0439\u044b\u0440\u043c\u0430\u043b\u0434\u044b\u049b\u0442\u044b\u04a3 \u04d9\u043b\u0434\u0435\u049b\u0430\u043d\u0448\u0430 \u0431\u04e9\u043b\u0456\u0433\u0456\u043d \u0431\u0456\u0437 \u0442\u04d9\u0443\u0435\u043b\u0434\u0456 \u0431\u043e\u043b\u0493\u0430\u043d \u0431\u0430\u0441\u049b\u0430 \u0442\u0435\u0433\u0456\u043d \u049b\u04b1\u0440\u0430\u043b\u0434\u0430\u0440\u044b \u04af\u0448\u0456\u043d \u0456\u0441\u043a\u0435\u0440\u043b\u0435\u0441\u0435\u043c\u0456\u0437.", + "ButtonEnterSupporterKey": "\u0416\u0430\u049b\u0442\u0430\u0443\u0448\u044b \u043a\u0456\u043b\u0442\u0456\u043d \u0435\u043d\u0433\u0456\u0437\u0443", + "DonationNextStep": "\u0410\u044f\u049b\u0442\u0430\u043b\u044b\u0441\u044b\u043c\u0435\u043d, \u043a\u0435\u0440\u0456 \u049b\u0430\u0439\u0442\u044b\u04a3\u044b\u0437 \u0436\u0430\u043d\u0435 \u042d-\u043f\u043e\u0448\u0442\u0430 \u0430\u0440\u049b\u044b\u043b\u044b \u0430\u043b\u044b\u043d\u0493\u0430\u043d \u0436\u0430\u049b\u0442\u0430\u0443\u0448\u044b \u043a\u0456\u043b\u0442\u0456\u043d \u0435\u043d\u0433\u0456\u0437\u0456\u04a3\u0456\u0437.", "AutoOrganizeHelp": "\u0410\u0432\u0442\u043e\u04b1\u0439\u044b\u043c\u0434\u0430\u0441\u0442\u044b\u0440\u0443 \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443 \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440\u044b\u043d\u0434\u0430\u0493\u044b \u0436\u0430\u04a3\u0430 \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u0434\u044b \u0431\u0430\u049b\u044b\u043b\u0430\u0439\u0434\u044b \u0436\u04d9\u043d\u0435 \u0431\u04b1\u043b\u0430\u0440\u0434\u044b \u0442\u0430\u0441\u0443\u0448\u044b \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440\u044b\u043d\u0430 \u0436\u044b\u043b\u0436\u044b\u0442\u0430\u0434\u044b.", "AutoOrganizeTvHelp": "\u0422\u0414 \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b\u043d \u04b1\u0439\u044b\u043c\u0434\u0430\u0441\u0442\u044b\u0440\u0443 \u043a\u0435\u0437\u0456\u043d\u0434\u0435 \u044d\u043f\u0438\u0437\u043e\u0434\u0442\u0430\u0440 \u0442\u0435\u043a \u049b\u0430\u043d\u0430 \u0431\u0430\u0440 \u0441\u0435\u0440\u0438\u0430\u043b\u0434\u0430\u0440\u0493\u0430 \u04af\u0441\u0442\u0435\u043b\u0456\u043d\u0435\u0434\u0456.", "OptionEnableEpisodeOrganization": "\u0416\u0430\u04a3\u0430 \u044d\u043f\u0438\u0437\u043e\u0434 \u04b1\u0439\u044b\u043c\u0434\u0430\u0441\u0442\u044b\u0440\u0443\u044b\u043d \u049b\u043e\u0441\u0443", @@ -552,7 +584,7 @@ "HeaderEpisodeFilePattern": "\u042d\u043f\u0438\u0437\u043e\u0434 \u0444\u0430\u0439\u043b\u044b\u043d\u044b\u04a3 \u04af\u043b\u0433\u0456\u0441\u0456", "LabelEpisodePattern": "\u042d\u043f\u0438\u0437\u043e\u0434 \u04af\u043b\u0433\u0456\u0441\u0456:", "LabelMultiEpisodePattern": "\u0411\u0456\u0440\u043d\u0435\u0448\u0435 \u044d\u043f\u0438\u0437\u043e\u0434 \u04af\u043b\u0433\u0456\u0441\u0456:", - "HeaderSupportedPatterns": "\u049a\u043e\u043b\u0434\u0430\u043d\u044b\u0441\u0442\u0430\u0493\u044b \u04af\u043b\u0433\u0456\u043b\u0435\u0440", + "HeaderSupportedPatterns": "\u049a\u043e\u043b\u0434\u0430\u0443\u0434\u0430\u0493\u044b \u04af\u043b\u0433\u0456\u043b\u0435\u0440", "HeaderTerm": "\u0421\u04e9\u0439\u043b\u0435\u043c\u0448\u0435", "HeaderPattern": "\u04ae\u043b\u0433\u0456", "HeaderResult": "\u041d\u04d9\u0442\u0438\u0436\u0435", @@ -570,11 +602,12 @@ "HeaderRunningTasks": "\u041e\u0440\u044b\u043d\u0434\u0430\u043b\u044b\u043f \u0436\u0430\u0442\u049b\u0430\u043d \u0442\u0430\u043f\u0441\u044b\u0440\u043c\u0430\u043b\u0430\u0440", "HeaderActiveDevices": "\u0411\u0435\u043b\u0441\u0435\u043d\u0434\u0456 \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u043b\u0430\u0440", "HeaderPendingInstallations": "\u0411\u04e9\u0433\u0435\u043b\u0456\u0441 \u043e\u0440\u043d\u0430\u0442\u044b\u043c\u0434\u0430\u0440", - "HeaderServerInformation": "\u0421\u0435\u0440\u0432\u0435\u0440 \u043c\u04d9\u043b\u0456\u043c\u0435\u0442\u0456", + "HeaderServerInformation": "\u0421\u0435\u0440\u0432\u0435\u0440 \u0442\u0443\u0440\u0430\u043b\u044b", "ButtonRestartNow": "\u049a\u0430\u0437\u0456\u0440 \u049b\u0430\u0439\u0442\u0430 \u0456\u0441\u043a\u0435 \u049b\u043e\u0441\u0443", "ButtonRestart": "\u049a\u0430\u0439\u0442\u0430 \u0456\u0441\u043a\u0435 \u049b\u043e\u0441\u0443", "ButtonShutdown": "\u0416\u04b1\u043c\u044b\u0441\u0442\u044b \u0430\u044f\u049b\u0442\u0430\u0443", "ButtonUpdateNow": "\u049a\u0430\u0437\u0456\u0440 \u0436\u0430\u04a3\u0430\u0440\u0442\u0443", + "TabHosting": "\u0425\u043e\u0441\u0442\u0438\u043d\u0433", "PleaseUpdateManually": "\u0421\u0435\u0440\u0432\u0435\u0440 \u0436\u04b1\u043c\u044b\u0441\u044b\u043d \u0430\u044f\u049b\u0442\u0430\u04a3\u044b\u0437 \u0434\u0430 \u049b\u043e\u043b\u043c\u0435\u043d \u0436\u0430\u04a3\u0430\u0440\u0442\u044b\u04a3\u044b\u0437.", "NewServerVersionAvailable": "Media Browser Server \u0436\u0430\u04a3\u0430 \u043d\u04b1\u0441\u049b\u0430\u0441\u044b \u049b\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456!", "ServerUpToDate": "Media Browser Server \u043a\u04af\u0439\u0456: \u0436\u0430\u04a3\u0430\u0440\u0442\u044b\u043b\u0493\u0430\u043d", @@ -584,20 +617,20 @@ "LabelDownMixAudioScale": "\u041a\u0435\u043c\u0456\u0442\u0456\u043b\u0456\u043f \u043c\u0438\u043a\u0448\u0435\u0440\u043b\u0435\u043d\u0433\u0435\u043d\u0434\u0435 \u0434\u044b\u0431\u044b\u0441 \u04e9\u0442\u0435\u043c\u0456:", "LabelDownMixAudioScaleHelp": "\u0414\u044b\u0431\u044b\u0441\u0442\u044b \u043a\u0435\u043c\u0456\u0442\u0456\u043b\u0456\u043f \u043c\u0438\u043a\u0448\u0435\u0440\u043b\u0435\u043d\u0433\u0435\u043d\u0434\u0435 \u04e9\u0442\u0435\u043c\u0434\u0435\u0443. \u0411\u0430\u0441\u0442\u0430\u043f\u049b\u044b \u0434\u0435\u04a3\u0433\u0435\u0439 \u043c\u04d9\u043d\u0456\u043d \u04e9\u0437\u0433\u0435\u0440\u0442\u043f\u0435\u0443 \u04af\u0448\u0456\u043d 1 \u0441\u0430\u043d\u044b\u043d \u043e\u0440\u043d\u0430\u0442\u044b\u04a3\u044b\u0437..", "ButtonLinkKeys": "\u041a\u0456\u043b\u0442\u0442\u0435\u0440\u0434\u0456 \u0430\u0443\u044b\u0441\u0442\u044b\u0440\u0443", - "LabelOldSupporterKey": "\u049a\u043e\u043b\u0434\u0430\u0443\u0448\u044b\u043d\u044b\u04a3 \u0435\u0441\u043a\u0456 \u043a\u0456\u043b\u0442\u0456", - "LabelNewSupporterKey": "\u049a\u043e\u043b\u0434\u0430\u0443\u0448\u044b\u043d\u044b\u04a3 \u0436\u0430\u04a3\u0430 \u043a\u0456\u043b\u0442\u0456", + "LabelOldSupporterKey": "\u0416\u0430\u049b\u0442\u0430\u0443\u0448\u044b\u043d\u044b\u04a3 \u0435\u0441\u043a\u0456 \u043a\u0456\u043b\u0442\u0456", + "LabelNewSupporterKey": "\u0416\u0430\u049b\u0442\u0430\u0443\u0448\u044b\u043d\u044b\u04a3 \u0436\u0430\u04a3\u0430 \u043a\u0456\u043b\u0442\u0456", "HeaderMultipleKeyLinking": "\u0416\u0430\u04a3\u0430 \u043a\u0456\u043b\u0442\u043a\u0435 \u0430\u0443\u044b\u0441\u0442\u044b\u0440\u0443", - "MultipleKeyLinkingHelp": "\u0415\u0433\u0435\u0440 \u0436\u0430\u04a3\u0430 \u049b\u043e\u043b\u0434\u0430\u0443\u0448\u044b \u043a\u0456\u043b\u0442\u0456 \u049b\u0430\u0431\u044b\u043b\u0434\u0430\u043d\u0441\u0430, \u0435\u0441\u043a\u0456 \u043a\u0456\u043b\u0442 \u0442\u0456\u0440\u043a\u0435\u043c\u0435\u043b\u0435\u0440\u0456\u043d \u0436\u0430\u04a3\u0430\u0441\u044b\u043d\u0430 \u0430\u0443\u044b\u0441\u0442\u044b\u0440\u0443 \u04af\u0448\u0456\u043d \u0431\u04b1\u043b \u043f\u0456\u0448\u0456\u043d\u0434\u0456 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u04a3\u044b\u0437.", + "MultipleKeyLinkingHelp": "\u0415\u0433\u0435\u0440 \u0436\u0430\u04a3\u0430 \u0436\u0430\u049b\u0442\u0430\u0443\u0448\u044b \u043a\u0456\u043b\u0442\u0456 \u049b\u0430\u0431\u044b\u043b\u0434\u0430\u043d\u0441\u0430, \u0435\u0441\u043a\u0456 \u043a\u0456\u043b\u0442 \u0442\u0456\u0440\u043a\u0435\u043c\u0435\u043b\u0435\u0440\u0456\u043d \u0436\u0430\u04a3\u0430\u0441\u044b\u043d\u0430 \u0430\u0443\u044b\u0441\u0442\u044b\u0440\u0443 \u04af\u0448\u0456\u043d \u0431\u04b1\u043b \u043f\u0456\u0448\u0456\u043d\u0434\u0456 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u04a3\u044b\u0437.", "LabelCurrentEmailAddress": "\u042d-\u043f\u043e\u0448\u0442\u0430\u043d\u044b\u04a3 \u0430\u0493\u044b\u043c\u0434\u044b\u049b \u043c\u0435\u043a\u0435\u043d\u0436\u0430\u0439\u044b", "LabelCurrentEmailAddressHelp": "\u0416\u0430\u04a3\u0430 \u043a\u0456\u043b\u0442 \u0436\u0456\u0431\u0435\u0440\u0456\u043b\u0433\u0435\u043d \u0430\u0493\u044b\u043c\u0434\u044b\u049b \u044d-\u043f\u043e\u0448\u0442\u0430 \u043c\u0435\u043a\u0435\u043d\u0436\u0430\u0439\u044b.", "HeaderForgotKey": "\u041a\u0456\u043b\u0442\u0442\u0456 \u04b1\u043c\u044b\u0442\u044b\u04a3\u044b\u0437 \u0431\u0430?", "LabelEmailAddress": "\u042d-\u043f\u043e\u0448\u0442\u0430\u043d\u044b\u04a3 \u043c\u0435\u043a\u0435\u043d\u0436\u0430\u0439\u044b", "LabelSupporterEmailAddress": "\u041a\u0456\u043b\u0442\u0442\u0456 \u0441\u0430\u0442\u044b\u043f \u0430\u043b\u0443 \u04af\u0448\u0456\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u043b\u0493\u0430\u043d \u044d-\u043f\u043e\u0448\u0442\u0430 \u043c\u0435\u043a\u0435\u043d\u0436\u0430\u0439\u044b.", "ButtonRetrieveKey": "\u041a\u0456\u043b\u0442\u0442\u0456 \u049b\u0430\u0439\u0442\u0430 \u0430\u043b\u0443", - "LabelSupporterKey": "\u049a\u043e\u043b\u0434\u0430\u0443\u0448\u044b \u043a\u0456\u043b\u0442\u0456 (\u042d-\u043f\u043e\u0448\u0442\u0430\u0434\u0430\u043d \u043a\u0456\u0440\u0456\u0441\u0442\u0456\u0440\u0456\u04a3\u0456\u0437)", - "LabelSupporterKeyHelp": "\u049a\u0430\u0443\u044b\u043c\u0434\u0430\u0441\u0442\u044b\u049b Media Browser \u0430\u0440\u043d\u0430\u043f \u0436\u0430\u0441\u0430\u049b\u0442\u0430\u0493\u0430\u043d \u049b\u043e\u0441\u044b\u043c\u0448\u0430 \u0430\u0440\u0442\u044b\u049b\u0448\u044b\u043b\u044b\u049b\u0442\u0430\u0440\u0434\u0430\u043d \u0434\u04d9\u0443\u0440\u0435\u043d \u0441\u04af\u0440\u0443\u0434\u0456 \u0431\u0430\u0441\u0442\u0430\u0443 \u04af\u0448\u0456\u043d \u049b\u043e\u043b\u0434\u0430\u0443\u0448\u044b \u043a\u0456\u043b\u0442\u0456\u043d \u0435\u043d\u0433\u0456\u0437\u0456\u04a3\u0456\u0437.", - "MessageInvalidKey": "\u049a\u043e\u043b\u0434\u0430\u0443\u0448\u044b \u043a\u0456\u043b\u0442\u0456 \u0436\u043e\u049b \u043d\u0435\u043c\u0435\u0441\u0435 \u0434\u04b1\u0440\u044b\u0441 \u0435\u043c\u0435\u0441", - "ErrorMessageInvalidKey": "\u049a\u0430\u0439 \u0435\u0440\u0435\u043a\u0448\u0435 \u043c\u0430\u0437\u043c\u04b1\u043d \u0431\u043e\u043b\u0441\u0430 \u0436\u0430\u0437\u044b\u043b\u0443 \u04af\u0448\u0456\u043d, \u0441\u0456\u0437 \u0441\u043e\u043d\u0434\u0430\u0439-\u0430\u049b Media Browser \u049b\u043e\u043b\u0434\u0430\u0443\u0448\u044b\u0441\u044b \u0431\u043e\u043b\u0443\u044b\u04a3\u044b\u0437 \u049b\u0430\u0436\u0435\u0442. \u04d8\u0437\u0456\u0440\u043b\u0435\u0443\u0456 \u0436\u0430\u043b\u0493\u0430\u0441\u0443\u0434\u0430\u0493\u044b \u043d\u0435\u0433\u0456\u0437\u0433\u0456 \u04e9\u043d\u0456\u043c \u04af\u0448\u0456\u043d \u04af\u043b\u0435\u0441 \u049b\u043e\u0441\u044b\u04a3\u044b\u0437 \u0436\u04d9\u043d\u0435 \u049b\u043e\u043b\u0434\u0430\u04a3\u044b\u0437.", + "LabelSupporterKey": "\u0416\u0430\u049b\u0442\u0430\u0443\u0448\u044b \u043a\u0456\u043b\u0442\u0456 (\u042d-\u043f\u043e\u0448\u0442\u0430\u0434\u0430\u043d \u043a\u0456\u0440\u0456\u0441\u0442\u0456\u0440\u0456\u04a3\u0456\u0437)", + "LabelSupporterKeyHelp": "\u049a\u0430\u0443\u044b\u043c\u0434\u0430\u0441\u0442\u044b\u049b Media Browser \u0430\u0440\u043d\u0430\u043f \u0436\u0430\u0441\u0430\u049b\u0442\u0430\u0493\u0430\u043d \u049b\u043e\u0441\u044b\u043c\u0448\u0430 \u0430\u0440\u0442\u044b\u049b\u0448\u044b\u043b\u044b\u049b\u0442\u0430\u0440\u0434\u044b \u0442\u0430\u043c\u0430\u0448\u0430\u043b\u0430\u0443\u044b\u043d \u0431\u0430\u0441\u0442\u0430\u0443 \u04af\u0448\u0456\u043d \u0436\u0430\u049b\u0442\u0430\u0443\u0448\u044b \u043a\u0456\u043b\u0442\u0456\u043d \u0435\u043d\u0433\u0456\u0437\u0456\u04a3\u0456\u0437.", + "MessageInvalidKey": "\u0416\u0430\u049b\u0442\u0430\u0443\u0448\u044b \u043a\u0456\u043b\u0442\u0456 \u0436\u043e\u049b \u043d\u0435\u043c\u0435\u0441\u0435 \u0434\u04b1\u0440\u044b\u0441 \u0435\u043c\u0435\u0441", + "ErrorMessageInvalidKey": "\u049a\u0430\u0439 \u0435\u0440\u0435\u043a\u0448\u0435 \u043c\u0430\u0437\u043c\u04b1\u043d \u0431\u043e\u043b\u0441\u0430 \u0436\u0430\u0437\u044b\u043b\u0443 \u04af\u0448\u0456\u043d, \u0441\u0456\u0437 \u0441\u043e\u043d\u0434\u0430\u0439-\u0430\u049b Media Browser \u0436\u0430\u049b\u0442\u0430\u0443\u0448\u044b\u0441\u044b \u0431\u043e\u043b\u0443\u044b\u04a3\u044b\u0437 \u049b\u0430\u0436\u0435\u0442. \u04d8\u0437\u0456\u0440\u043b\u0435\u0443\u0456 \u0436\u0430\u043b\u0493\u0430\u0441\u0443\u0434\u0430\u0493\u044b \u043d\u0435\u0433\u0456\u0437\u0433\u0456 \u04e9\u043d\u0456\u043c \u04af\u0448\u0456\u043d \u04af\u043b\u0435\u0441 \u049b\u043e\u0441\u044b\u04a3\u044b\u0437 \u0436\u04d9\u043d\u0435 \u0436\u0430\u049b\u0442\u0430\u04a3\u044b\u0437.", "HeaderDisplaySettings": "\u0411\u0435\u0439\u043d\u0435\u043b\u0435\u0443 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440\u0456", "TabPlayTo": "\u049a\u04b1\u0440\u044b\u043b\u0493\u044b\u0434\u0430 \u043e\u0439\u043d\u0430\u0442\u0443", "LabelEnableDlnaServer": "DLNA \u0441\u0435\u0440\u0432\u0435\u0440\u0456\u043d \u049b\u043e\u0441\u0443", @@ -636,6 +669,7 @@ "NotificationOptionInstallationFailed": "\u041e\u0440\u043d\u0430\u0442\u0443 \u0441\u04d9\u0442\u0441\u0456\u0437\u0434\u0456\u0433\u0456", "NotificationOptionNewLibraryContent": "\u0416\u0430\u04a3\u0430 \u043c\u0430\u0437\u043c\u04b1\u043d \u04af\u0441\u0442\u0435\u043b\u0433\u0435\u043d", "NotificationOptionNewLibraryContentMultiple": "\u0416\u0430\u04a3\u0430 \u043c\u0430\u0437\u043c\u04b1\u043d \u049b\u043e\u0441\u044b\u043b\u0434\u044b (\u043a\u04e9\u043f\u0442\u0435\u0433\u0435\u043d)", + "NotificationOptionCameraImageUploaded": "\u041a\u0430\u043c\u0435\u0440\u0430\u0434\u0430\u043d \u0444\u043e\u0442\u043e\u0441\u0443\u0440\u0435\u0442 \u0436\u04af\u043a\u0442\u0435\u043b\u0433\u0435\u043d", "SendNotificationHelp": "\u0425\u0430\u0431\u0430\u0440\u043b\u0430\u043d\u0434\u044b\u0440\u0443\u043b\u0430\u0440 \u0431\u0430\u049b\u044b\u043b\u0430\u0443 \u0442\u0430\u049b\u0442\u0430\u0441\u044b\u043d\u0434\u0430\u0493\u044b \u04d9\u0434\u0435\u043f\u043a\u0456 \u043a\u0456\u0440\u0456\u0441 \u0436\u04d9\u0448\u0456\u0433\u0456\u043d\u0435 \u0436\u0435\u0442\u043a\u0456\u0437\u0456\u043b\u0435\u0434\u0456. \u049a\u043e\u0441\u044b\u043c\u0448\u0430 \u0445\u0430\u0431\u0430\u0440\u043b\u0430\u043d\u0434\u044b\u0440\u0443 \u049b\u04b1\u0440\u0430\u043b\u0434\u0430\u0440\u044b\u043d \u043e\u0440\u043d\u0430\u0442\u0443 \u04af\u0448\u0456\u043d \u043f\u043b\u0430\u0433\u0438\u043d\u0434\u0435\u0440 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0456\u043d \u0448\u043e\u043b\u044b\u04a3\u044b\u0437.", "NotificationOptionServerRestartRequired": "\u0421\u0435\u0440\u0432\u0435\u0440\u0434\u0456 \u049b\u0430\u0439\u0442\u0430 \u0456\u0441\u043a\u0435 \u049b\u043e\u0441\u0443 \u049b\u0430\u0436\u0435\u0442", "LabelNotificationEnabled": "\u0411\u04b1\u043b \u0445\u0430\u0431\u0430\u0440\u043b\u0430\u043d\u0434\u044b\u0440\u043c\u0430\u043d\u044b \u049b\u043e\u0441\u0443", @@ -646,7 +680,7 @@ "CategorySystem": "\u0416\u04af\u0439\u0435", "CategoryApplication": "\u049a\u043e\u043b\u0434\u0430\u043d\u0431\u0430", "CategoryPlugin": "\u041f\u043b\u0430\u0433\u0438\u043d", - "LabelMessageTitle": "\u0425\u0430\u0431\u0430\u0440\u0434\u044b\u04a3 \u0431\u0430\u0441\u0442\u0430\u049b\u044b\u0440\u044b\u0431\u044b", + "LabelMessageTitle": "\u0425\u0430\u0431\u0430\u0440 \u043c\u04d9\u0442\u0456\u043d\u0456:", "LabelAvailableTokens": "\u049a\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456 \u0442\u0430\u04a3\u0431\u0430\u043b\u0430\u0443\u044b\u0448\u0442\u0430\u0440:", "AdditionalNotificationServices": "\u049a\u043e\u0441\u044b\u043c\u0448\u0430 \u0445\u0430\u0431\u0430\u0440\u043b\u0430\u043d\u0434\u044b\u0440\u0443 \u049b\u044b\u0437\u043c\u0435\u0442\u0442\u0435\u0440\u0456\u043d \u043e\u0440\u043d\u0430\u0442\u0443 \u04af\u0448\u0456\u043d \u043f\u043b\u0430\u0433\u0438\u043d\u0434\u0435\u0440 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0456\u043d \u0448\u043e\u043b\u044b\u04a3\u044b\u0437.", "OptionAllUsers": "\u0411\u0430\u0440\u043b\u044b\u049b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043b\u0430\u0440", @@ -690,7 +724,7 @@ "ButtonVolumeDown": "\u04ae\u043d\u0434\u0456\u043b\u0456\u043a\u0442\u0456 \u0442\u04e9\u043c\u0435\u043d\u0434\u0435\u0442\u0443", "ButtonMute": "\u0414\u044b\u0431\u044b\u0441\u0442\u044b \u04e9\u0448\u0456\u0440\u0443", "HeaderLatestMedia": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456 \u0442\u0430\u0441\u0443\u0448\u044b\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440", - "OptionSpecialFeatures": "\u0410\u0440\u043d\u0430\u0439\u044b \u043c\u04d9\u043b\u0456\u043c\u0435\u0442\u0442\u0435\u0440", + "OptionSpecialFeatures": "\u0410\u0440\u043d\u0430\u0439\u044b \u0435\u0440\u0435\u043a\u0448\u0435\u043b\u0456\u043a\u0442\u0435\u0440", "HeaderCollections": "\u0416\u0438\u044b\u043d\u0442\u044b\u049b\u0442\u0430\u0440", "LabelProfileCodecsHelp": "\u04ae\u0442\u0456\u0440 \u0430\u0440\u049b\u044b\u043b\u044b \u0431\u04e9\u043b\u0456\u043f \u0430\u043b\u044b\u043d\u0493\u0430\u043d. \u0411\u0430\u0440\u043b\u044b\u049b \u043a\u043e\u0434\u0435\u043a\u0442\u0435\u0440\u0433\u0435 \u049b\u043e\u043b\u0434\u0430\u043d\u0443 \u04af\u0448\u0456\u043d \u0431\u04b1\u043b \u0431\u043e\u0441 \u049b\u0430\u043b\u0434\u044b\u0440\u044b\u043b\u0443 \u043c\u04af\u043c\u043a\u0456\u043d.", "LabelProfileContainersHelp": "\u04ae\u0442\u0456\u0440 \u0430\u0440\u049b\u044b\u043b\u044b \u0431\u04e9\u043b\u0456\u043f \u0430\u043b\u044b\u043d\u0493\u0430\u043d. \u0411\u0430\u0440\u043b\u044b\u049b \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043b\u0435\u0440\u0433\u0435 \u049b\u043e\u043b\u0434\u0430\u043d\u0443 \u04af\u0448\u0456\u043d \u0431\u04b1\u043b \u0431\u043e\u0441 \u049b\u0430\u043b\u0434\u044b\u0440\u044b\u043b\u0443 \u043c\u04af\u043c\u043a\u0456\u043d.", @@ -725,7 +759,7 @@ "TabContainers": "\u041a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043b\u0435\u0440", "TabCodecs": "\u041a\u043e\u0434\u0435\u043a\u0442\u0435\u0440", "TabResponses": "\u04ae\u043d \u049b\u0430\u0442\u0443\u043b\u0430\u0440", - "HeaderProfileInformation": "\u041f\u0440\u043e\u0444\u0430\u0439\u043b \u0430\u049b\u043f\u0430\u0440\u0430\u0442\u044b", + "HeaderProfileInformation": "\u041f\u0440\u043e\u0444\u0430\u0439\u043b \u043c\u04d9\u043b\u0456\u043c\u0435\u0442\u0442\u0435\u0440\u0456", "LabelEmbedAlbumArtDidl": "Didl \u0456\u0448\u0456\u043d\u0435 \u0430\u043b\u044c\u0431\u043e\u043c \u0441\u0443\u0440\u0435\u0442\u0456\u043d \u0435\u043d\u0434\u0456\u0440\u0443", "LabelEmbedAlbumArtDidlHelp": "\u041a\u0435\u0439\u0431\u0456\u0440 \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u043b\u0430\u0440\u0493\u0430 \u0430\u043b\u044c\u0431\u043e\u043c \u0441\u0443\u0440\u0435\u0442\u0456\u043d \u0430\u043b\u0443 \u04af\u0448\u0456\u043d \u043e\u0441\u044b \u04d9\u0434\u0456\u0441 \u049b\u0430\u0436\u0435\u0442. \u0411\u0430\u0441\u049b\u0430\u043b\u0430\u0440 \u04af\u0448\u0456\u043d, \u043e\u0441\u044b \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u049b\u043e\u0441\u044b\u043b\u0493\u0430\u043d\u0434\u0430, \u043e\u0439\u043d\u0430\u0442\u0443 \u0441\u04d9\u0442\u0441\u0456\u0437 \u0431\u043e\u043b\u0443\u044b \u043c\u04af\u043c\u043a\u0456\u043d.", "LabelAlbumArtPN": "\u0410\u043b\u044c\u0431\u043e\u043c \u0441\u0443\u0440\u0435\u0442\u0456 PN:", @@ -744,10 +778,10 @@ "LabelMaxBitrateHelp": "\u04e8\u0442\u043a\u0456\u0437\u0443 \u043c\u04af\u043c\u043a\u0456\u043d\u0434\u0456\u0433\u0456 \u0448\u0435\u043a\u0442\u0435\u043b\u0433\u0435\u043d \u043e\u0440\u0442\u0430\u043b\u0430\u0440\u0434\u0430\u0493\u044b \u0435\u04a3 \u0436\u043e\u0493\u0430\u0440\u044b \u049b\u0430\u0440\u049b\u044b\u043d\u044b\u043d, \u043d\u0435\u043c\u0435\u0441\u0435 \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u0493\u0430 \u049b\u0430\u0436\u0435\u0442 \u0431\u043e\u043b\u0441\u0430 - \u04e9\u0437 \u0448\u0435\u0433\u0456\u043d \u0430\u043d\u044b\u049b\u0442\u0430\u04a3\u044b\u0437.", "LabelMaxStreamingBitrate": "\u0415\u04a3 \u0436\u043e\u0493\u0430\u0440\u044b \u0430\u0493\u044b\u043d\u043c\u0435\u043d \u0442\u0430\u0441\u044b\u043c\u0430\u043b\u0434\u0430\u0443 \u049b\u0430\u0440\u049b\u044b\u043d\u044b:", "LabelMaxStreamingBitrateHelp": "\u0410\u0493\u044b\u043d\u043c\u0435\u043d \u0442\u0430\u0441\u044b\u043c\u0430\u043b\u0434\u0430\u0443 \u043a\u0435\u0437\u0456\u043d\u0434\u0435 \u0435\u04a3 \u0436\u043e\u0493\u0430\u0440\u044b \u049b\u0430\u0440\u049b\u044b\u043d\u0434\u044b \u0430\u043d\u044b\u049b\u0442\u0430\u04a3\u044b\u0437.", - "LabelMaxStaticBitrate": "\u0415\u04a3 \u0436\u043e\u0493\u0430\u0440\u044b \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443 \u049b\u0430\u0440\u049b\u044b\u043d\u044b:", - "LabelMaxStaticBitrateHelp": "\u0416\u043e\u0493\u0430\u0440\u044b \u0441\u0430\u043f\u0430\u043c\u0435\u043d \u043c\u0430\u0437\u043c\u04b1\u043d\u0434\u044b \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443 \u043a\u0435\u0437\u0456\u043d\u0434\u0435 \u0435\u04a3 \u0436\u043e\u0493\u0430\u0440\u044b \u049b\u0430\u0440\u049b\u044b\u043d\u0434\u044b \u0430\u043d\u044b\u049b\u0442\u0430\u04a3\u044b\u0437.", - "LabelMusicStaticBitrate": "\u041c\u0443\u0437\u044b\u043a\u0430\u043d\u044b \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443 \u049b\u0430\u0440\u049b\u044b\u043d\u044b:", - "LabelMusicStaticBitrateHelp": "\u041c\u0443\u0437\u044b\u043a\u0430\u043d\u044b \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443 \u043a\u0435\u0437\u0456\u043d\u0434\u0435 \u0435\u04a3 \u0436\u043e\u0493\u0430\u0440\u044b \u049b\u0430\u0440\u049b\u044b\u043d\u0434\u044b \u0430\u043d\u044b\u049b\u0442\u0430\u0443", + "LabelMaxStaticBitrate": "\u0415\u04a3 \u0436\u043e\u0493\u0430\u0440\u044b \u04af\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443 \u049b\u0430\u0440\u049b\u044b\u043d\u044b:", + "LabelMaxStaticBitrateHelp": "\u0416\u043e\u0493\u0430\u0440\u044b \u0441\u0430\u043f\u0430\u043c\u0435\u043d \u043c\u0430\u0437\u043c\u04b1\u043d\u0434\u044b \u04af\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443 \u043a\u0435\u0437\u0456\u043d\u0434\u0435 \u0435\u04a3 \u0436\u043e\u0493\u0430\u0440\u044b \u049b\u0430\u0440\u049b\u044b\u043d\u0434\u044b \u0430\u043d\u044b\u049b\u0442\u0430\u04a3\u044b\u0437.", + "LabelMusicStaticBitrate": "\u041c\u0443\u0437\u044b\u043a\u0430\u043d\u044b \u04af\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443 \u049b\u0430\u0440\u049b\u044b\u043d\u044b:", + "LabelMusicStaticBitrateHelp": "\u041c\u0443\u0437\u044b\u043a\u0430\u043d\u044b \u04af\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443 \u043a\u0435\u0437\u0456\u043d\u0434\u0435 \u0435\u04a3 \u0436\u043e\u0493\u0430\u0440\u044b \u049b\u0430\u0440\u049b\u044b\u043d\u0434\u044b \u0430\u043d\u044b\u049b\u0442\u0430\u0443", "LabelMusicStreamingTranscodingBitrate": "\u041c\u0443\u0437\u044b\u043a\u0430\u043d\u044b \u049b\u0430\u0439\u0442\u0430 \u043a\u043e\u0434\u0442\u0430\u0443 \u049b\u0430\u0440\u049b\u044b\u043d\u044b:", "LabelMusicStreamingTranscodingBitrateHelp": "\u041c\u0443\u0437\u044b\u043a\u0430\u043d\u044b \u0430\u0493\u044b\u043d\u043c\u0435\u043d \u0442\u0430\u0441\u044b\u043c\u0430\u043b\u0434\u0430\u0443 \u043a\u0435\u0437\u0456\u043d\u0434\u0435 \u0435\u04a3 \u0436\u043e\u0493\u0430\u0440\u044b \u049b\u0430\u0440\u049b\u044b\u043d\u0434\u044b \u0430\u043d\u044b\u049b\u0442\u0430\u04a3\u044b\u0437", "OptionIgnoreTranscodeByteRangeRequests": "\u049a\u0430\u0439\u0442\u0430 \u043a\u043e\u0434\u0442\u0430\u0443 \u0431\u0430\u0439\u0442 \u0430\u0443\u049b\u044b\u043c\u044b \u0441\u04b1\u0440\u0430\u043d\u044b\u0441\u0442\u0430\u0440\u044b\u043d \u0435\u043b\u0435\u043c\u0435\u0443", @@ -762,8 +796,8 @@ "LabelSerialNumber": "\u0421\u0435\u0440\u0438\u044f\u043b\u044b\u049b \u043d\u04e9\u043c\u0456\u0440\u0456", "LabelDeviceDescription": "\u049a\u04b1\u0440\u044b\u043b\u0493\u044b \u0441\u0438\u043f\u0430\u0442\u0442\u0430\u043c\u0430\u0441\u044b", "HeaderIdentificationCriteriaHelp": "\u0415\u04a3 \u043a\u0435\u043c\u0456\u043d\u0434\u0435 \u0430\u043d\u044b\u049b\u0442\u0430\u0443\u0434\u044b\u04a3 \u0431\u0456\u0440 \u0448\u0430\u0440\u0442\u044b\u043d \u0435\u043d\u0433\u0456\u0437\u0456\u04a3\u0456\u0437.", - "HeaderDirectPlayProfileHelp": "\u049a\u04b1\u0440\u044b\u043b\u0493\u044b\u043d\u044b\u04a3 \u049b\u0430\u043d\u0434\u0430\u0439 \u043f\u0456\u0448\u0456\u043c\u0434\u0435\u0440\u0434\u0456 \u04d9\u0434\u0435\u043f\u043a\u0456 \u04e9\u04a3\u0434\u0435\u0442\u0435\u0442\u0456\u043d \u043c\u04af\u043c\u043a\u0456\u043d\u0434\u0456\u0433\u0456\u043d \u043a\u04e9\u0440\u0441\u0435\u0442\u0443 \u04b1\u0448\u0456\u043d \u0442\u0456\u043a\u0435\u043b\u0435\u0439 \u043e\u0439\u043d\u0430\u0442\u0443 \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b\u043d \u049b\u043e\u0441\u0443.", - "HeaderTranscodingProfileHelp": "\u049a\u0430\u0436\u0435\u0442 \u0431\u043e\u043b\u0493\u0430\u043d\u0434\u0430 \u049b\u0430\u043d\u0434\u0430\u0439 \u043f\u0456\u0448\u0456\u043c\u0434\u0435\u0440\u0434\u0456 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443 \u043c\u0456\u043d\u0434\u0435\u0442\u0456\u043b\u0456\u0433\u0456\u043d \u043a\u04e9\u0440\u0441\u0435\u0442\u0443 \u04b1\u0448\u0456\u043d \u049b\u0430\u0439\u0442\u0430 \u043a\u043e\u0434\u0442\u0430\u0443 \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b\u043d \u049b\u043e\u0441\u0443.", + "HeaderDirectPlayProfileHelp": "\u049a\u04b1\u0440\u044b\u043b\u0493\u044b\u043d\u044b\u04a3 \u049b\u0430\u043d\u0434\u0430\u0439 \u043f\u0456\u0448\u0456\u043c\u0434\u0435\u0440\u0434\u0456 \u04d9\u0434\u0435\u043f\u043a\u0456 \u04e9\u04a3\u0434\u0435\u0442\u0435\u0442\u0456\u043d \u043c\u04af\u043c\u043a\u0456\u043d\u0434\u0456\u0433\u0456\u043d \u043a\u04e9\u0440\u0441\u0435\u0442\u0443 \u04b1\u0448\u0456\u043d \u0442\u0456\u043a\u0435\u043b\u0435\u0439 \u043e\u0439\u043d\u0430\u0442\u0443 \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b\u043d \u04af\u0441\u0442\u0435\u0443.", + "HeaderTranscodingProfileHelp": "\u049a\u0430\u0436\u0435\u0442 \u0431\u043e\u043b\u0493\u0430\u043d\u0434\u0430 \u049b\u0430\u043d\u0434\u0430\u0439 \u043f\u0456\u0448\u0456\u043c\u0434\u0435\u0440\u0434\u0456 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443 \u043c\u0456\u043d\u0434\u0435\u0442\u0456\u043b\u0456\u0433\u0456\u043d \u043a\u04e9\u0440\u0441\u0435\u0442\u0443 \u04b1\u0448\u0456\u043d \u049b\u0430\u0439\u0442\u0430 \u043a\u043e\u0434\u0442\u0430\u0443 \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b\u043d \u04af\u0441\u0442\u0435\u0443.", "HeaderResponseProfileHelp": "\u041a\u0435\u0439\u0431\u0456\u0440 \u0442\u0430\u0441\u0443\u0448\u044b\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440 \u0442\u04af\u0440\u043b\u0435\u0440\u0456\u043d \u043e\u0439\u043d\u0430\u0442\u049b\u0430\u043d\u0434\u0430 \u04af\u043d \u049b\u0430\u0442\u0443 \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u0493\u0430 \u0436\u0456\u0431\u0435\u0440\u0456\u043b\u0435\u0442\u0456\u043d \u0430\u049b\u043f\u0430\u0440\u0430\u0442\u0442\u044b \u0442\u0435\u04a3\u0448\u0435\u0443 \u04af\u0448\u0456\u043d \u0436\u043e\u043b \u0431\u0435\u0440\u0435\u0434\u0456.", "LabelXDlnaCap": "X-Dlna \u0441\u0438\u043f\u0430\u0442\u0442\u0430\u0440\u044b:", "LabelXDlnaCapHelp": "urn:schemas-dlna-org:device-1-0 \u0430\u0442\u0430\u0443\u043b\u0430\u0440 \u043a\u0435\u04a3\u0456\u0441\u0442\u0456\u0433\u0456\u043d\u0434\u0435\u0433\u0456 X_DLNACAP \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0456 \u043c\u0430\u0437\u043c\u04b1\u043d\u044b\u043d \u0430\u043d\u044b\u049b\u0442\u0430\u0439\u0434\u044b.", @@ -778,7 +812,7 @@ "OptionEnableM2tsMode": "M2ts \u0440\u0435\u0436\u0456\u043c\u0456\u043d \u049b\u043e\u0441\u0443", "OptionEnableM2tsModeHelp": "Mpegts \u04af\u0448\u0456\u043d \u043a\u043e\u0434\u0442\u0430\u0443 \u043a\u0435\u0437\u0456\u043d\u0434\u0435 m2ts \u0440\u0435\u0436\u0456\u043c\u0456\u043d \u049b\u043e\u0441\u0443.", "OptionEstimateContentLength": "\u049a\u0430\u0439\u0442\u0430 \u043a\u043e\u0434\u0442\u0430\u0443 \u043a\u0435\u0437\u0456\u043d\u0434\u0435 \u043c\u0430\u0437\u043c\u04b1\u043d \u04b1\u0437\u044b\u043d\u0434\u044b\u0493\u044b\u043d \u0431\u0430\u0493\u0430\u043b\u0430\u0443", - "OptionReportByteRangeSeekingWhenTranscoding": "\u049a\u0430\u0439\u0442\u0430 \u043a\u043e\u0434\u0442\u0430\u0443 \u043a\u0435\u0437\u0456\u043d\u0434\u0435 \u0441\u0435\u0440\u0432\u0435\u0440 \u0431\u0430\u0439\u0442 \u0456\u0440\u0456\u043a\u0442\u0435\u0443\u0456\u043d \u049b\u043e\u043b\u0434\u0430\u0441\u0430 \u0445\u0430\u0431\u0430\u0440\u043b\u0430\u0443", + "OptionReportByteRangeSeekingWhenTranscoding": "\u049a\u0430\u0439\u0442\u0430 \u043a\u043e\u0434\u0442\u0430\u0443 \u043a\u0435\u0437\u0456\u043d\u0434\u0435 \u0441\u0435\u0440\u0432\u0435\u0440 \u0431\u0430\u0439\u0442 \u0456\u0440\u0456\u043a\u0442\u0435\u0443\u0456\u043d \u049b\u043e\u043b\u0434\u0430\u0441\u0430 \u0431\u0430\u044f\u043d\u0434\u0430\u0443", "OptionReportByteRangeSeekingWhenTranscodingHelp": "\u0411\u04b1\u043b \u0443\u0430\u049b\u044b\u0442 \u0456\u0440\u0456\u043a\u0442\u0435\u0443\u0456 \u043e\u043d\u0448\u0430 \u0435\u043c\u0435\u0441 \u043a\u0435\u0439\u0431\u0456\u0440 \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u043b\u0430\u0440 \u04af\u0448\u0456\u043d \u049b\u0430\u0436\u0435\u0442.", "HeaderSubtitleDownloadingHelp": "Media Browser \u0431\u0435\u0439\u043d\u0435\u0444\u0430\u0439\u043b\u0434\u0430\u0440\u0434\u044b \u0441\u043a\u0430\u043d\u0435\u0440\u043b\u0435\u0433\u0435\u043d\u0434\u0435 \u0431\u04b1\u043b \u0436\u043e\u049b \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440\u0434\u0456 \u0456\u0437\u0434\u0435\u0443 \u0436\u04d9\u043d\u0435 OpenSubtitles.org \u0441\u0438\u044f\u049b\u0442\u044b \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440 \u0436\u0435\u0442\u043a\u0456\u0437\u0443\u0448\u0456 \u0430\u0440\u049b\u044b\u043b\u044b \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443\u044b \u043c\u04af\u043c\u043a\u0456\u043d.", "HeaderDownloadSubtitlesFor": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440\u0434\u0456 \u043c\u044b\u043d\u0430\u0493\u0430\u043d \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443:", @@ -829,8 +863,8 @@ "OptionAuto": "\u0410\u0432\u0442\u043e", "OptionYes": "\u0418\u04d9", "OptionNo": "\u0416\u043e\u049b", - "HeaderOptions": "Options", - "HeaderIdentificationResult": "Identification Result", + "HeaderOptions": "\u041d\u04b1\u0441\u049b\u0430\u043b\u0430\u0440", + "HeaderIdentificationResult": "\u0410\u043d\u044b\u049b\u0442\u0430\u0443 \u043d\u04d9\u0442\u0438\u0436\u0435\u0441\u0456", "LabelHomePageSection1": "\u0411\u0430\u0441\u0442\u044b \u0431\u0435\u0442 1-\u0431\u04e9\u043b\u0456\u043c:", "LabelHomePageSection2": "\u0411\u0430\u0441\u0442\u044b \u0431\u0435\u0442 2-\u0431\u04e9\u043b\u0456\u043c:", "LabelHomePageSection3": "\u0411\u0430\u0441\u0442\u044b \u0431\u0435\u0442 3-\u0431\u04e9\u043b\u0456\u043c:", @@ -844,7 +878,7 @@ "HeaderLatestChannelItems": "\u0410\u0440\u043d\u0430\u043b\u0430\u0440\u0434\u044b\u04a3 \u0435\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0435\u0440\u0456", "OptionNone": "\u0415\u0448\u049b\u0430\u043d\u0434\u0430\u0439", "HeaderLiveTv": "\u042d\u0444\u0438\u0440\u043b\u0456\u043a \u0422\u0414", - "HeaderReports": "\u0415\u0441\u0435\u043f\u0442\u0435\u0440", + "HeaderReports": "\u0411\u0430\u044f\u043d\u0434\u0430\u043c\u0430\u043b\u0430\u0440", "HeaderMetadataManager": "\u041c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a \u0440\u0435\u0442\u0442\u0435\u0443\u0448\u0456", "HeaderPreferences": "\u0422\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0434\u0435\u0440", "MessageLoadingChannels": "\u0410\u0440\u043d\u0430\u043d\u044b\u04a3 \u043c\u0430\u0437\u043c\u04b1\u043d\u044b\u043d \u0436\u04af\u043a\u0442\u0435\u0443\u0434\u0435...", @@ -853,8 +887,10 @@ "OptionDefaultSort": "\u04d8\u0434\u0435\u043f\u043a\u0456", "OptionCommunityMostWatchedSort": "\u0415\u04a3 \u043a\u04e9\u043f \u049b\u0430\u0440\u0430\u043b\u0493\u0430\u043d\u0434\u0430\u0440", "TabNextUp": "\u041a\u0435\u0437\u0435\u043a\u0442\u0435\u0433\u0456\u043b\u0435\u0440", + "HeaderBecomeMediaBrowserSupporter": "Media Browser \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u044b \u0431\u043e\u043b\u044b\u04a3\u044b\u0437", + "TextEnjoyBonusFeatures": "\u0421\u044b\u0439\u0430\u049b\u044b \u0435\u0440\u0435\u043a\u0448\u0435\u043b\u0456\u043a\u0442\u0435\u0440\u043c\u0435\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u04a3\u044b\u0437", "MessageNoMovieSuggestionsAvailable": "\u0415\u0448\u049b\u0430\u043d\u0434\u0430\u0439 \u0444\u0438\u043b\u044c\u043c \u04b1\u0441\u044b\u043d\u044b\u0441\u0442\u0430\u0440\u044b \u0430\u0493\u044b\u043c\u0434\u0430 \u049b\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456 \u0435\u043c\u0435\u0441. \u0424\u0438\u043b\u044c\u043c\u0434\u0435\u0440\u0434\u0456 \u049b\u0430\u0440\u0430\u0443\u0434\u044b \u0436\u04d9\u043d\u0435 \u0431\u0430\u0493\u0430\u043b\u0430\u0443\u0434\u044b \u0431\u0430\u0441\u0442\u0430\u04a3\u044b\u0437, \u0441\u043e\u043d\u0434\u0430 \u0430\u0440\u043d\u0430\u043b\u0493\u0430\u043d \u04b1\u0441\u044b\u043d\u044b\u0442\u0430\u0440\u044b\u04a3\u044b\u0437\u0434\u044b \u043a\u04e9\u0440\u0443 \u04af\u0448\u0456\u043d \u049b\u0430\u0439\u0442\u0430 \u043a\u0435\u043b\u0456\u04a3\u0456\u0437.", - "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.", + "MessageNoCollectionsAvailable": "\u0416\u0438\u044b\u043d\u0442\u044b\u049b\u0442\u0430\u0440 \u0441\u0456\u0437\u0433\u0435 \u0424\u0438\u043b\u044c\u043c\u0434\u0435\u0440\u0434\u0456\u04a3, \u0421\u0435\u0440\u0438\u0430\u043b\u0434\u0430\u0440\u0434\u044b\u04a3, \u0410\u043b\u044c\u0431\u043e\u043c\u0434\u0430\u0440\u0434\u044b\u04a3, \u041a\u0456\u0442\u0430\u043f\u0442\u0430\u0440\u0434\u044b\u04a3, \u0436\u04d9\u043d\u0435 \u041e\u0439\u044b\u043d\u0434\u0430\u0440\u0434\u044b\u04a3 \u0436\u0435\u043a\u0435\u043b\u0435\u043d\u0433\u0435\u043d \u0442\u043e\u043f\u0442\u0430\u0443\u043b\u0430\u0440\u044b\u043c\u0435\u043d \u0442\u0430\u043c\u0430\u0448\u0430\u043b\u0430\u043d\u0443 \u04af\u0448\u0456\u043d \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0435\u0434\u0456. \u0416\u0438\u044b\u043d\u0442\u044b\u049b\u0442\u0430\u0440 \u0436\u0430\u0441\u0430\u0443\u044b\u043d \u0431\u0430\u0441\u0442\u0430\u0443 \u04af\u0448\u0456\u043d \"+\" \u0442\u04af\u0439\u043c\u0435\u0448\u0456\u0433\u0456\u043d \u0431\u0430\u0441\u044b\u04a3\u044b\u0437.", "MessageNoPlaylistsAvailable": "\u041e\u0439\u043d\u0430\u0442\u0443 \u0442\u0456\u0437\u0456\u043c\u0434\u0435\u0440\u0456 \u0431\u0456\u0440 \u043a\u0435\u0437\u0434\u0435 \u043e\u0439\u043d\u0430\u0442\u0443 \u04af\u0448\u0456\u043d \u043c\u0430\u0437\u043c\u04b1\u043d \u0442\u0456\u0437\u0456\u043c\u0456\u043d \u0436\u0430\u0441\u0430\u0443\u0493\u0430 \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0435\u0434\u0456. \u041e\u0439\u043d\u0430\u0442\u0443 \u0442\u0456\u0437\u0456\u043c\u0434\u0435\u0440\u0433\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0435\u0440\u0434\u0456 \u04af\u0441\u0442\u0435\u0443 \u04af\u0448\u0456\u043d, \u0442\u0456\u043d\u0442\u0443\u0456\u0440\u0434\u0456\u04a3 \u043e\u04a3 \u0436\u0430\u049b \u0442\u04af\u0439\u043c\u0435\u0448\u0456\u0433\u0456\u043d \u0431\u0430\u0441\u044b\u04a3\u044b\u0437 \u043d\u0435\u043c\u0435\u0441\u0435 \u0442\u04af\u0440\u0442\u0456\u043f \u0436\u04d9\u043d\u0435 \u04b1\u0441\u0442\u0430\u043f \u0442\u04b1\u0440\u044b\u04a3\u044b\u0437, \u0441\u043e\u043d\u0434\u0430 \u041e\u0439\u043d\u0430\u0442\u0443 \u0442\u0456\u0437\u0456\u043c\u0456\u043d\u0435 \u04af\u0441\u0442\u0435\u0443 \u0434\u0435\u0433\u0435\u043d\u0434\u0456 \u0442\u0430\u04a3\u0434\u0430\u04a3\u044b\u0437.", "MessageNoPlaylistItemsAvailable": "\u041e\u0441\u044b \u043e\u0439\u043d\u0430\u0442\u0443 \u0442\u0456\u0437\u0456\u043c \u0430\u0493\u044b\u043c\u0434\u0430\u0493\u044b \u0443\u0430\u049b\u044b\u0442\u0442\u0430 \u0431\u043e\u0441.", "ButtonDismiss": "\u0416\u0430\u0441\u044b\u0440\u0443", @@ -869,8 +905,7 @@ "LabelChannelDownloadAge": "\u041c\u0430\u0437\u043c\u04b1\u043d \u0436\u043e\u0439\u044b\u043b\u0443\u044b \u043a\u0435\u043b\u0435\u0441\u0456\u0434\u0435\u043d \u043a\u0435\u0439\u0456\u043d, \u043a\u04af\u043d:", "LabelChannelDownloadAgeHelp": "\u0411\u04b1\u0434\u0430\u043d \u0431\u04b1\u0440\u044b\u043d\u0493\u044b \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u044b\u043d\u0493\u0430\u043d \u043c\u0430\u0437\u043c\u04af\u043d \u0436\u043e\u0439\u044b\u043b\u0430\u0434\u044b. \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u0430\u0440\u049b\u044b\u043b\u044b \u0430\u0493\u044b\u043d\u043c\u0435\u043d \u0442\u0430\u0441\u044b\u043c\u0430\u043b\u0434\u0430\u0443 \u04d9\u0434\u0456\u0441\u0456\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u043f \u043e\u0439\u043d\u0430\u0442\u0443 \u0456\u0441\u0442\u0435 \u049b\u0430\u043b\u0430\u0434\u044b.", "ChannelSettingsFormHelp": "\u041f\u043b\u0430\u0433\u0438\u043d \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0456\u043d\u0434\u0435\u0433\u0456 Trailers \u0436\u04d9\u043d\u0435 Vimeo \u0441\u0438\u044f\u049b\u0442\u044b \u0430\u0440\u043d\u0430\u043b\u0430\u0440\u0434\u044b \u043e\u0440\u043d\u0430\u0442\u044b\u04a3\u044b\u0437.", - "LabelSelectCollection": "\u0416\u0438\u044b\u043d\u0442\u044b\u049b\u0442\u044b \u0442\u0430\u04a3\u0434\u0430\u0443:", - "ButtonOptions": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440", + "ButtonOptions": "\u041d\u04b1\u0441\u049b\u0430\u043b\u0430\u0440", "ViewTypeMovies": "\u041a\u0438\u043d\u043e", "ViewTypeTvShows": "\u0422\u0414", "ViewTypeGames": "\u041e\u0439\u044b\u043d\u0434\u0430\u0440", @@ -915,12 +950,12 @@ "OptionLibraryFolders": "\u0422\u0430\u0441\u0443\u0448\u044b \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440\u044b", "TitleRemoteControl": "\u049a\u0430\u0448\u044b\u049b\u0442\u0430\u043d \u0431\u0430\u0441\u049b\u0430\u0440\u0443", "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:", + "LabelProtocolInfo": "\u041f\u0440\u043e\u0442\u043e\u049b\u043e\u043b \u0442\u0443\u0440\u0430\u043b\u044b:", "LabelProtocolInfoHelp": "\u0411\u04b1\u043b \u043c\u04d9\u043d \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u043d\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.", - "TabKodiMetadata": "Kodi", - "HeaderKodiMetadataHelp": "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.", - "LabelKodiMetadataUser": "\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-\u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b\u043c\u0435\u043d \u043c\u044b\u043d\u0430\u0443 \u04af\u0448\u0456\u043d \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443:", - "LabelKodiMetadataUserHelp": "\u041a\u04e9\u0440\u0456\u043b\u0433\u0435\u043d \u043a\u04af\u0439\u0434\u0456 Media Browser \u0436\u04d9\u043d\u0435 Kodi \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.", + "TabNfo": "NFO-\u0444\u0430\u0439\u043b\u0434\u0430\u0440", + "HeaderKodiMetadataHelp": "Media Browser \u0431\u0430\u0493\u0434\u0430\u0440\u043b\u0430\u043c\u0430\u0441\u044b Kodi 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. Kodi \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.", + "LabelKodiMetadataUser": "\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-\u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b\u043c\u0435\u043d \u043c\u044b\u043d\u0430\u0443 \u04af\u0448\u0456\u043d \u04af\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443:", + "LabelKodiMetadataUserHelp": "\u041a\u04e9\u0440\u0456\u043b\u0433\u0435\u043d \u043a\u04af\u0439\u0434\u0456 Media Browser \u0436\u04d9\u043d\u0435 Kodi \u0430\u0440\u0430\u0441\u044b\u043d\u0434\u0430 \u04af\u043d\u0434\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.", "LabelKodiMetadataDateFormat": "\u0428\u044b\u0493\u0430\u0440\u0443 \u043a\u04af\u043d\u0456\u043d\u0456\u04a3 \u043f\u0456\u0448\u0456\u043c\u0456:", "LabelKodiMetadataDateFormatHelp": "\u041e\u0441\u044b \u043f\u0456\u0448\u0456\u043c\u0434\u0456 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u043f nfo \u0456\u0448\u0456\u043d\u0434\u0435\u0433\u0456 \u0431\u0430\u0440\u043b\u044b\u049b \u043a\u04af\u043d\u0434\u0435\u0440\u0456 \u043e\u049b\u044b\u043b\u0430\u0434\u044b \u0436\u04d9\u043d\u0435 \u0436\u0430\u0437\u044b\u043b\u0430\u0434\u044b.", "LabelKodiMetadataSaveImagePaths": "\u0421\u0443\u0440\u0435\u0442 \u0436\u043e\u043b\u0434\u0430\u0440\u044b\u043d NFO-\u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b\u043d\u0434\u0430 \u0441\u0430\u049b\u0442\u0430\u0443", @@ -931,12 +966,13 @@ "LabelGroupChannelsIntoViews": "\u041c\u0435\u043d\u0456\u04a3 \u0430\u0441\u043f\u0435\u043a\u0442\u0442\u0435\u0440\u0456\u043c\u0434\u0435 \u0442\u0456\u043a\u0435\u043b\u0435\u0439 \u043a\u0435\u043b\u0435\u0441\u0456 \u0430\u0440\u043d\u0430\u043b\u0430\u0440\u0434\u044b \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0443:", "LabelGroupChannelsIntoViewsHelp": "\u0415\u0433\u0435\u0440 \u049b\u043e\u0441\u044b\u043b\u0441\u0430, \u043e\u0441\u044b \u0430\u0440\u043d\u0430\u043b\u0430\u0440 \u0431\u0430\u0441\u049b\u0430 \u0430\u0441\u043f\u0435\u043a\u0442\u0442\u0435\u0440\u043c\u0435\u043d \u049b\u0430\u0442\u0430\u0440 \u0442\u0456\u043a\u0435\u043b\u0435\u0439 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u043d\u0435\u0434\u0456. \u0415\u0433\u0435\u0440 \u0430\u0436\u044b\u0440\u0430\u0442\u044b\u043b\u0441\u0430, \u043e\u043b\u0430\u0440 \u0431\u04e9\u043b\u0435\u043a \u0410\u0440\u043d\u0430\u043b\u0430\u0440 \u043a\u04e9\u0440\u0456\u043d\u0456\u0441\u0456\u043d\u0434\u0435 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u043d\u0435\u0434\u0456.", "LabelDisplayCollectionsView": "\u0424\u0438\u043b\u044c\u043c\u0434\u0435\u0440 \u0436\u0438\u043d\u0430\u049b\u0442\u0430\u0440\u044b\u043d \u043a\u04e9\u0440\u0441\u0435\u0442\u0443 \u04af\u0448\u0456\u043d \u0416\u0438\u044b\u043d\u0442\u044b\u049b\u0442\u0430\u0440 \u0430\u0441\u043f\u0435\u043a\u0442\u0456\u043d \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0443", + "LabelDisplayCollectionsViewHelp": "\u0411\u04b1\u043b \u0441\u0456\u0437 \u0436\u0430\u0441\u0430\u0493\u0430\u043d \u043d\u0435\u043c\u0435\u0441\u0435 \u049b\u043e\u043b \u0436\u0435\u0442\u043a\u0456\u0437\u0435 \u0430\u043b\u0430\u0442\u044b\u043d \u0436\u0438\u044b\u043d\u0442\u044b\u049b\u0442\u0430\u0440\u0434\u044b \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0443 \u04af\u0448\u0456\u043d \u0431\u04e9\u043b\u0435\u043a \u0430\u0441\u043f\u0435\u043a\u0442\u0442\u0456 \u0436\u0430\u0441\u0430\u0439\u0434\u044b. \u0416\u0438\u044b\u043d\u0442\u044b\u049b\u0442\u044b \u0436\u0430\u0441\u0430\u0443 \u04af\u0448\u0456\u043d, \u043a\u0435\u0437 \u043a\u0435\u043b\u0433\u0435\u043d \u0444\u0438\u043b\u044c\u043c\u043d\u0456\u04a3 \u04af\u0441\u0442\u0456\u043d\u0434\u0435 \u0442\u0456\u043d\u0442\u0443\u0456\u0440\u0434\u0456\u04a3 \u043e\u04a3 \u0436\u0430\u049b \u0442\u04af\u0439\u043c\u0435\u0448\u0456\u0433\u043d \u0431\u0430\u0441\u044b\u04a3\u044b\u0437 \u043d\u0435\u043c\u0435\u0441\u0435 \u0442\u04af\u0440\u0442\u0456\u04a3\u0456\u0437 \u0434\u0435 \u04b1\u0441\u0442\u0430\u043f \u0442\u04b1\u0440\u044b\u04a3\u044b\u0437 \u0436\u04d9\u043d\u0435 \"\u0416\u0438\u044b\u043d\u0442\u044b\u049b\u049b\u0430 \u04af\u0441\u0442\u0435\u0443\" \u0434\u0435\u0433\u0435\u043d\u0434\u0456 \u0442\u0430\u04a3\u0434\u0430\u04a3\u044b\u0437.", "LabelKodiMetadataEnableExtraThumbs": "\u04d8\u0434\u0435\u043f\u043a\u0456 extrafanart \u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0456\u043d extrathumbs \u0456\u0448\u0456\u043d\u0435 \u043a\u04e9\u0448\u0456\u0440\u0443", "LabelKodiMetadataEnableExtraThumbsHelp": "\u0421\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0434\u0456 \u0436\u04af\u043a\u0442\u0435\u0433\u0435\u043d \u043a\u0435\u0437\u0434\u0435, \u043e\u043b\u0430\u0440 Kodi \u049b\u0430\u0431\u044b\u0493\u044b\u043c\u0435\u043d \u0435\u04a3 \u0436\u043e\u0493\u0430\u0440\u044b \u0441\u0438\u044b\u0441\u044b\u043c\u0434\u044b\u0493\u044b \u04af\u0448\u0456\u043d extrafanart \u0436\u04d9\u043d\u0435 extrathumbs \u0435\u043a\u0435\u0443\u0456\u043d\u0434\u0435 \u0441\u0430\u049b\u0442\u0430\u043b\u0430\u0434\u044b.", "TabServices": "\u049a\u044b\u0437\u043c\u0435\u0442\u0442\u0435\u0440", "TabLogs": "\u0416\u04b1\u0440\u043d\u0430\u043b\u0434\u0430\u0440", "HeaderServerLogFiles": "\u0421\u0435\u0440\u0432\u0435\u0440\u0434\u0456\u04a3 \u0436\u04b1\u0440\u043d\u0430\u043b \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b:", - "TabBranding": "\u0411\u0440\u0435\u043d\u0434\u0438\u043d\u0433", + "TabBranding": "\u0411\u0435\u0437\u0435\u043d\u0434\u0456\u0440\u0443", "HeaderBrandingHelp": "\u0422\u043e\u0431\u044b\u04a3\u044b\u0437\u0434\u044b\u04a3 \u043d\u0435 \u04b1\u0439\u044b\u043c\u044b\u04a3\u044b\u0437\u0434\u044b\u04a3 \u043c\u04b1\u049b\u0442\u0430\u0436\u0434\u044b\u049b\u0442\u0430\u0440\u044b\u043d\u0430 \u04af\u0439\u043b\u0435\u0441\u0456\u043c\u0434\u0456 Media Browser \u0431\u0435\u0437\u0435\u043d\u0434\u0456\u0440\u0443\u0456\u043d \u0442\u0435\u04a3\u0448\u0435\u0443.", "LabelLoginDisclaimer": "\u041a\u0456\u0440\u0433\u0435\u043d\u0434\u0435\u0433\u0456 \u0435\u0441\u043a\u0435\u0440\u0442\u0443:", "LabelLoginDisclaimerHelp": "\u0411\u04b1\u043b \u043a\u0456\u0440\u0443 \u0431\u0435\u0442\u0456\u043d\u0456\u04a3 \u0442\u04e9\u043c\u0435\u043d\u0456\u043d\u0434\u0435 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u043d\u0435\u0434\u0456.", @@ -945,13 +981,13 @@ "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": "\u041a\u0435\u0448:", + "LabelCache": "\u041a\u044d\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", + "HeaderBranding": "\u0411\u0435\u0437\u0435\u043d\u0434\u0456\u0440\u0443", "HeaderApiKeys": "API \u043a\u0456\u043b\u0442\u0442\u0435\u0440\u0456", "HeaderApiKeysHelp": "\u0421\u044b\u0440\u0442\u049b\u044b \u049b\u043e\u043b\u0434\u0430\u043d\u0431\u0430\u043b\u0430\u0440 Media Browser \u0431\u0430\u0493\u0434\u0430\u0440\u043b\u0430\u043c\u0430\u0441\u044b\u043c\u0435\u043d \u049b\u0430\u0442\u044b\u043d\u0430\u0441\u0443 \u04af\u0448\u0456\u043d API \u043a\u0456\u043b\u0442\u0456 \u049b\u0430\u0436\u0435\u0442 \u0435\u0442\u0435\u0434\u0456. \u041a\u0456\u043b\u0442\u0442\u0435\u0440 Media Browser \u0442\u0456\u0440\u043a\u0435\u043b\u0433\u0456\u0441\u0456\u043d\u0435 \u043a\u0456\u0440\u0433\u0435\u043d\u0434\u0435, \u043d\u0435\u043c\u0435\u0441\u0435 \u043a\u0456\u043b\u0442\u0442\u0456 \u049b\u043e\u043b\u0434\u0430\u043d\u0431\u0430\u0493\u0430 \u049b\u043e\u043b\u043c\u0435\u043d \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0456\u043b\u0433\u0435\u043d\u0434\u0435 \u0431\u0435\u0440\u0456\u043b\u0435\u0434\u0456.", "HeaderApiKey": "API \u043a\u0456\u043b\u0442\u0456", @@ -981,20 +1017,20 @@ "TabUsers": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043b\u0430\u0440", "LabelSortName": "\u0421\u04b1\u0440\u044b\u043f\u0442\u0430\u043b\u0430\u0442\u044b\u043d \u0430\u0442\u044b:", "LabelDateAdded": "\u04ae\u0441\u0442\u0435\u043b\u0433\u0435\u043d \u043a\u04af\u043d\u0456", - "HeaderFeatures": "\u041c\u04d9\u043b\u0456\u043c\u0435\u0442\u0442\u0435\u0440", - "HeaderAdvanced": "\u049a\u043e\u0441\u044b\u043c\u0448\u0430", - "ButtonSync": "\u0421\u0438\u043d\u0445\u0440\u043e", + "HeaderFeatures": "\u0415\u0440\u0435\u043a\u0448\u0435\u043b\u0456\u043a\u0442\u0435\u0440", + "HeaderAdvanced": "\u041a\u0435\u04a3\u0435\u0439\u0442\u0456\u043b\u0433\u0435\u043d", + "ButtonSync": "\u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443", "TabScheduledTasks": "\u0416\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0443\u0448\u044b", "HeaderChapters": "\u0421\u0430\u0445\u043d\u0430\u043b\u0430\u0440", "HeaderResumeSettings": "\u0416\u0430\u043b\u0493\u0430\u0441\u0442\u044b\u0440\u0443 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440\u0456", - "TabSync": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443", + "TabSync": "\u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\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", "OptionProtocolHls": "Http \u0422\u0456\u043a\u0435\u043b\u0435\u0439 \u0430\u0493\u044b\u043d\u043c\u0435\u043d \u0442\u0430\u0441\u044b\u043c\u0430\u043b\u0434\u0430\u0443 (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", - "OptionContextStatic": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443", + "OptionContextStatic": "\u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443", "ButtonAddToPlaylist": "\u041e\u0439\u043d\u0430\u0442\u0443 \u0442\u0456\u0437\u0456\u043c\u0456\u043d\u0435 \u04af\u0441\u0442\u0435\u0443", "TabPlaylists": "\u041e\u0439\u043d\u0430\u0442\u0443 \u0442\u0456\u0437\u0456\u043c\u0434\u0435\u0440\u0456", "ButtonClose": "\u0416\u0430\u0431\u0443", @@ -1024,7 +1060,7 @@ "OptionStub": "\u0422\u044b\u0493\u044b\u043d", "HeaderEpisodes": "\u042d\u043f\u0438\u0437\u043e\u0434\u0442\u0430\u0440:", "OptionSeason0": "0-\u043c\u0430\u0443\u0441\u044b\u043c", - "LabelReport": "\u0415\u0441\u0435\u043f:", + "LabelReport": "\u0411\u0430\u044f\u043d\u0434\u0430\u043c\u0430:", "OptionReportSongs": "\u04d8\u0443\u0435\u043d\u0434\u0435\u0440", "OptionReportSeries": "\u0421\u0435\u0440\u0438\u0430\u043b\u0434\u0430\u0440", "OptionReportSeasons": "\u041c\u0430\u0443\u0441\u044b\u043c\u0434\u0430\u0440", @@ -1084,11 +1120,14 @@ "LabelDisplayFoldersView": "\u041a\u04d9\u0434\u0456\u043c\u0433\u0456 \u0442\u0430\u0441\u0443\u0448\u044b \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440\u044b\u043d \u043a\u04e9\u0440\u0441\u0435\u0442\u0443 \u04af\u0448\u0456\u043d \u049a\u0430\u043b\u0442\u0430\u043b\u0430\u0440 \u0430\u0441\u043f\u0435\u043a\u0442\u0456\u043d \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0443", "ViewTypeLiveTvRecordingGroups": "\u0416\u0430\u0437\u0431\u0430\u043b\u0430\u0440", "ViewTypeLiveTvChannels": "\u0410\u0440\u043d\u0430\u043b\u0430\u0440", - "LabelAllowLocalAccessWithoutPassword": "\u049a\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437\u0441\u0456\u0437 \u0436\u0435\u0440\u0433\u0456\u043b\u0456\u043a\u0442\u0456 \u049b\u0430\u0442\u044b\u043d\u0441\u0443 \u04af\u0448\u0456\u043d \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0443", - "LabelAllowLocalAccessWithoutPasswordHelp": "\u049a\u043e\u0441\u044b\u043b\u0493\u0430\u043d \u0431\u043e\u043b\u0441\u0430, \u04af\u0439\u0456\u04a3\u0456\u0437\u0434\u0435\u0433\u0456 \u0436\u0435\u043b\u0456 \u0456\u0448\u0456\u043d\u0435\u043d \u043a\u0456\u0440\u0433\u0435\u043d\u0434\u0435 \u049b\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437 \u049b\u0430\u0436\u0435\u0442 \u0431\u043e\u043b\u043c\u0430\u0439\u0434\u044b.", + "LabelEasyPinCode": "\u041e\u04a3\u0430\u0439\u0442\u044b\u043b\u0493\u0430\u043d PIN-\u043a\u043e\u0434:", + "EasyPasswordHelp": "\u041e\u04a3\u0430\u0439\u0442\u044b\u043b\u0493\u0430\u043d PIN-\u043a\u043e\u0434\u044b\u04a3\u044b\u0437 \u049b\u043e\u043b\u0434\u0430\u0443\u0434\u0430\u0493\u044b Media Browser \u049b\u043e\u043b\u0434\u0430\u043d\u0431\u0430\u043b\u0430\u0440\u044b\u043d\u0430\u043d \u0434\u0435\u0440\u0431\u0435\u0441 \u049b\u0430\u0442\u044b\u043d\u0430\u0441\u0443 \u04af\u0448\u0456\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u043b\u0430\u0434\u044b, \u0436\u04d9\u043d\u0435 \u0436\u0435\u043b\u0456 \u0456\u0448\u0456\u043d\u0434\u0435 \u043e\u04a3\u0430\u0439\u0442\u044b\u043b\u044b\u043f \u043a\u0456\u0440\u0443 \u04af\u0448\u0456\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u043b\u0443\u044b \u043c\u04af\u043c\u043a\u0456\u043d.", + "LabelInNetworkSignInWithEasyPassword": "\u041e\u04a3\u0430\u0439\u0442\u044b\u043b\u0493\u0430\u043d PIN-\u043a\u043e\u0434\u044b\u043c \u0430\u0440\u049b\u044b\u043b\u044b \u0436\u0435\u043b\u0456 \u0456\u0448\u0456\u043d\u0434\u0435 \u043e\u04a3\u0430\u0439\u0442\u044b\u043b\u044b\u043f \u043a\u0456\u0440\u0443\u0434\u0456 \u049b\u043e\u0441\u0443", + "LabelInNetworkSignInWithEasyPasswordHelp": "\u0415\u0433\u0435\u0440 \u049b\u043e\u0441\u044b\u043b\u0441\u0430, \u04af\u0439 \u0436\u0435\u043b\u0456\u0441\u0456 \u0456\u0448\u0456\u043d\u0435\u043d Media Browser \u049b\u043e\u043b\u0434\u0430\u043d\u0431\u0430\u043b\u0430\u0440\u044b\u043d\u0430 \u043a\u0456\u0440\u0443 \u04af\u0448\u0456\u043d \u043e\u04a3\u0430\u0439\u0442\u044b\u043b\u0493\u0430\u043d PIN-\u043a\u043e\u0434\u044b\u04a3\u044b\u0437\u0434\u044b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u044b\u04a3\u044b\u0437 \u043c\u04af\u043c\u043a\u0456\u043d. \u0421\u0456\u0437\u0434\u0456\u04a3 \u049b\u0430\u043b\u044b\u043f\u0442\u044b \u049b\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437\u0456\u04a3\u0456\u0437 \u0442\u0435\u043a \u049b\u0430\u043d\u0430 \u04af\u0439 \u0441\u044b\u0440\u0442\u044b\u043d\u0434\u0430 \u049b\u0430\u0436\u0435\u0442 \u0431\u043e\u043b\u0430\u0434\u044b. \u0415\u0433\u0435\u0440 PIN-\u043a\u043e\u0434 \u0431\u043e\u0441 \u049b\u0430\u043b\u0434\u044b\u0440\u044b\u043b\u0441\u0430, \u04af\u0439 \u0436\u0435\u043b\u0456\u0441\u0456\u043d\u0434\u0435 \u049b\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437\u0456\u04a3\u0456\u0437 \u049b\u0430\u0436\u0435\u0442 \u0431\u043e\u043b\u043c\u0430\u0439\u0434\u044b.", "HeaderPassword": "\u049a\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437", "HeaderLocalAccess": "\u0416\u0435\u0440\u0433\u0456\u043b\u0456\u043a\u0442\u0456 \u049b\u0430\u0442\u044b\u043d\u0430\u0441", "HeaderViewOrder": "\u0410\u0441\u043f\u0435\u043a\u0442\u0442\u0435\u0440 \u0440\u0435\u0442\u0456", + "ButtonResetEasyPassword": "\u041e\u04a3\u0430\u0439\u0442\u044b\u043b\u0493\u0430\u043d PIN-\u043a\u043e\u0434\u0442\u044b \u044b\u0441\u044b\u0440\u0443", "LabelSelectUserViewOrder": "Media Browser \u049b\u043e\u043b\u0434\u0430\u043d\u0431\u0430\u043b\u0430\u0440\u044b\u043d\u0434\u0430 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u043d\u0435\u0442\u0456\u043d \u041c\u0435\u043d\u0456\u04a3 \u0430\u0441\u043f\u0435\u043a\u0442\u0442\u0435\u0440\u0456\u043c \u0440\u0435\u0442\u0456\u043d \u0442\u0430\u04a3\u0434\u0430\u04a3\u044b\u0437", "LabelMetadataRefreshMode": "\u041c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0434\u0456 \u043a\u04e9\u043a\u0435\u0439\u0442\u0435\u0441\u0442\u0456 \u0435\u0442\u0443 \u0440\u0435\u0436\u0456\u043c\u0456:", "LabelImageRefreshMode": "\u0421\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0434\u0456 \u043a\u04e9\u043a\u0435\u0439\u0442\u0435\u0441\u0442\u0456 \u0435\u0442\u0443 \u0440\u0435\u0436\u0456\u043c\u0456:", @@ -1098,7 +1137,7 @@ "OptionAddMissingDataOnly": "\u0422\u0435\u043a \u049b\u0430\u043d\u0430 \u0436\u043e\u043a \u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0434\u0456 \u04af\u0441\u0442\u0435\u0443", "OptionLocalRefreshOnly": "\u0422\u0435\u043a \u049b\u0430\u043d\u0430 \u0436\u0435\u0440\u0433\u0456\u043b\u0456\u043a\u0442\u0456 \u043a\u04e9\u043a\u0435\u0439\u0442\u0435\u0441\u0442\u0456 \u0435\u0442\u0443", "HeaderRefreshMetadata": "\u041c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0434\u0456 \u043a\u04e9\u043a\u0435\u0439\u0442\u0435\u0441\u0442\u0456 \u0435\u0442\u0443", - "HeaderPersonInfo": "\u0422\u04b1\u043b\u0493\u0430 \u0442\u0443\u0440\u0430\u043b\u044b \u0430\u049b\u043f\u0430\u0440\u0430\u0442", + "HeaderPersonInfo": "\u0422\u04b1\u043b\u0493\u0430 \u0442\u0443\u0440\u0430\u043b\u044b", "HeaderIdentifyItem": "\u042d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0456 \u0430\u043d\u044b\u049b\u0442\u0430\u0443", "HeaderIdentifyItemHelp": "\u0406\u0437\u0434\u0435\u0443\u0434\u0456\u04a3 \u0431\u0456\u0440 \u043d\u0435 \u0431\u0456\u0440\u043d\u0435\u0448\u0435 \u0448\u0430\u0440\u0442\u044b\u043d \u0435\u043d\u0433\u0456\u0437\u0456\u04a3\u0456\u0437. \u0406\u0437\u0434\u0435\u0443 \u043d\u04d9\u0442\u0438\u0436\u0435\u043b\u0435\u0440\u0456\u043d \u043a\u04e9\u0431\u0435\u0439\u0442\u0443 \u04af\u0448\u0456\u043d \u0448\u0430\u0440\u0442\u0442\u044b \u0430\u043b\u0430\u0441\u0442\u0430\u04a3\u044b\u0437.", "HeaderConfirmDeletion": "\u0416\u043e\u044e\u0434\u044b \u0440\u0430\u0441\u0442\u0430\u0443", @@ -1132,7 +1171,7 @@ "LabelPlayers": "\u041e\u0439\u044b\u043d\u0448\u044b\u043b\u0430\u0440:", "Label3DFormat": "3D \u043f\u0456\u0448\u0456\u043c\u0456:", "HeaderAlternateEpisodeNumbers": "\u0411\u0430\u043b\u0430\u043c\u0430\u043b\u044b \u044d\u043f\u0438\u0437\u043e\u0434 \u043d\u04e9\u043c\u0456\u0440\u043b\u0435\u0440\u0456", - "HeaderSpecialEpisodeInfo": "\u0410\u0440\u043d\u0430\u0439\u044b \u044d\u043f\u0438\u0437\u043e\u0434 \u0430\u049b\u043f\u0430\u0440\u0430\u0442\u044b", + "HeaderSpecialEpisodeInfo": "\u0410\u0440\u043d\u0430\u0439\u044b \u044d\u043f\u0438\u0437\u043e\u0434 \u0442\u0443\u0440\u0430\u043b\u044b", "HeaderExternalIds": "\u0421\u044b\u0440\u0442\u049b\u044b \u0441\u04d9\u0439\u043a\u0435\u0441\u0442\u0435\u043d\u0434\u0456\u0440\u0433\u0456\u0448\u0442\u0435\u0440:", "LabelDvdSeasonNumber": "DVD \u043c\u0430\u0443\u0441\u044b\u043c \u043d\u04e9\u043c\u0456\u0440\u0456", "LabelDvdEpisodeNumber": "DVD \u044d\u043f\u0438\u0437\u043e\u0434 \u043d\u04e9\u043c\u0456\u0440\u0456", @@ -1154,15 +1193,15 @@ "TabDonate": "\u049a\u0430\u0439\u044b\u0440\u043c\u0430\u043b\u0434\u044b\u049b", "HeaderDonationType": "\u049a\u0430\u0439\u044b\u0440\u043c\u0430\u043b\u0434\u044b\u049b \u0442\u04af\u0440\u0456:", "OptionMakeOneTimeDonation": "\u0411\u04e9\u043b\u0435\u043a \u049b\u0430\u0439\u044b\u0440\u043c\u0430\u043b\u0434\u044b\u049b \u0436\u0430\u0441\u0430\u0443", - "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 \u0436\u04d9\u043d\u0435 \u049b\u043e\u043b\u0434\u0430\u0443\u0448\u044b \u043a\u0456\u043b\u0442\u0456 \u0436\u0430\u0441\u0430\u043b\u043c\u0430\u0439\u0434\u044b.", - "OptionLifeTimeSupporterMembership": "\u0492\u04b1\u043c\u044b\u0440\u043b\u044b\u049b \u049b\u043e\u043b\u0434\u0430\u0443\u0448\u044b \u043c\u04af\u0448\u0435\u043b\u0456\u0433\u0456", - "OptionYearlySupporterMembership": "\u0416\u044b\u043b\u0434\u044b\u049b \u049b\u043e\u043b\u0434\u0430\u0443\u0448\u044b \u043c\u04af\u0448\u0435\u043b\u0456\u0433\u0456", - "OptionMonthlySupporterMembership": "\u0410\u0439\u043b\u044b\u049b \u049b\u043e\u043b\u0434\u0430\u0443\u0448\u044b \u043c\u04af\u0448\u0435\u043b\u0456\u0433\u0456", + "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 \u0436\u04d9\u043d\u0435 \u0436\u0430\u049b\u0442\u0430\u0443\u0448\u044b \u043a\u0456\u043b\u0442\u0456 \u0436\u0430\u0441\u0430\u043b\u043c\u0430\u0439\u0434\u044b.", + "OptionLifeTimeSupporterMembership": "\u0492\u04b1\u043c\u044b\u0440\u043b\u044b\u049b \u0436\u0430\u049b\u0442\u0430\u0443\u0448\u044b \u043c\u04af\u0448\u0435\u043b\u0456\u0433\u0456", + "OptionYearlySupporterMembership": "\u0416\u044b\u043b\u0434\u044b\u049b \u0436\u0430\u049b\u0442\u0430\u0443\u0448\u044b \u043c\u04af\u0448\u0435\u043b\u0456\u0433\u0456", + "OptionMonthlySupporterMembership": "\u0410\u0439\u043b\u044b\u049b \u0436\u0430\u049b\u0442\u0430\u0443\u0448\u044b \u043c\u04af\u0448\u0435\u043b\u0456\u0433\u0456", "OptionNoTrailer": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440\u0441\u0456\u0437", "OptionNoThemeSong": "\u0422\u0430\u049b\u044b\u0440\u044b\u043f\u0442\u044b\u049b \u04d9\u0443\u0435\u043d\u0441\u0456\u0437", "OptionNoThemeVideo": "\u0422\u0430\u049b\u044b\u0440\u044b\u043f\u0442\u044b\u049b \u0431\u0435\u0439\u043d\u0435\u0441\u0456\u0437", "LabelOneTimeDonationAmount": "\u049a\u0430\u0439\u044b\u0440\u043c\u0430\u043b\u0434\u044b\u049b \u049b\u043e\u0440\u044b\u0442\u044b\u043d\u0434\u044b\u0441\u044b:", - "ButtonDonate": "Donate", + "ButtonDonate": "\u049a\u0430\u0439\u044b\u0440\u043c\u0430\u043b\u0430\u0443", "OptionActor": "\u0410\u043a\u0442\u0435\u0440", "OptionComposer": "\u041a\u043e\u043c\u043f\u043e\u0437\u0438\u0442\u043e\u0440", "OptionDirector": "\u0420\u0435\u0436\u0438\u0441\u0441\u0435\u0440", @@ -1171,15 +1210,15 @@ "OptionWriter": "\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439\u0448\u0456", "LabelAirDays": "\u042d\u0444\u0438\u0440 \u043a\u04af\u043d\u0434\u0435\u0440\u0456:", "LabelAirTime": "\u042d\u0444\u0438\u0440 \u0443\u0430\u049b\u044b\u0442\u044b:", - "HeaderMediaInfo": "\u0422\u0430\u0441\u0443\u0448\u044b\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440 \u043c\u04d9\u043b\u0456\u043c\u0435\u0442\u0456", - "HeaderPhotoInfo": "\u0424\u043e\u0442\u043e\u0441\u0443\u0440\u0435\u0442 \u043c\u04d9\u043b\u0456\u043c\u0435\u0442\u0456", + "HeaderMediaInfo": "\u0422\u0430\u0441\u0443\u0448\u044b\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440 \u0442\u0443\u0440\u0430\u043b\u044b", + "HeaderPhotoInfo": "\u0424\u043e\u0442\u043e\u0441\u0443\u0440\u0435\u0442 \u0442\u0443\u0440\u0430\u043b\u044b", "HeaderInstall": "\u041e\u0440\u043d\u0430\u0442\u0443", "LabelSelectVersionToInstall": "\u041e\u0440\u043d\u0430\u0442\u044b\u043c \u043d\u04b1\u0441\u049b\u0430\u0441\u044b\u043d \u0442\u0430\u04a3\u0434\u0430\u0443:", - "LinkSupporterMembership": "\u049a\u043e\u043b\u0434\u0430\u0443\u0448\u044b \u043c\u04af\u0448\u0435\u043b\u0456\u0433\u0456 \u0442\u0443\u0440\u0430\u043b\u044b \u0442\u0430\u043d\u044b\u0441\u044b\u04a3\u044b\u0437", - "MessageSupporterPluginRequiresMembership": "\u0411\u04b1\u043b \u043f\u043b\u0430\u0433\u0438\u043d\u0433\u0435 14 \u043a\u04af\u043d\u0434\u0456\u043a \u0442\u0430\u043d\u044b\u0441\u0442\u044b\u0440\u0443 \u043a\u0435\u0437\u0435\u04a3\u0456\u043d\u0435\u043d \u043a\u0435\u0439\u0456\u043d \u0431\u0435\u043b\u0441\u0435\u043d\u0434\u0456 \u049b\u043e\u043b\u0434\u0430\u0443\u0448\u044b \u043c\u04af\u0448\u0435\u043b\u0456\u0433\u0456\u043d \u049b\u0430\u0436\u0435\u0442 \u0435\u0442\u0435\u0434\u0456.", - "MessagePremiumPluginRequiresMembership": "\u0411\u04b1\u043b \u043f\u043b\u0430\u0433\u0438\u043d\u0434\u0456 \u0441\u0430\u0442\u044b\u043f \u0430\u043b\u0443 \u04af\u0448\u0456\u043d 14 \u043a\u04af\u043d\u0434\u0456\u043a \u0442\u0430\u043d\u044b\u0441\u0442\u044b\u0440\u0443 \u043a\u0435\u0437\u0435\u04a3\u0456\u043d\u0435\u043d \u043a\u0435\u0439\u0456\u043d \u0431\u0435\u043b\u0441\u0435\u043d\u0434\u0456 \u049b\u043e\u043b\u0434\u0430\u0443\u0448\u044b \u043c\u04af\u0448\u0435\u043b\u0456\u0433\u0456\u043d \u049b\u0430\u0436\u0435\u0442 \u0435\u0442\u0435\u0434\u0456.", + "LinkSupporterMembership": "\u0416\u0430\u049b\u0442\u0430\u0443\u0448\u044b \u043c\u04af\u0448\u0435\u043b\u0456\u0433\u0456 \u0442\u0443\u0440\u0430\u043b\u044b \u0442\u0430\u043d\u044b\u0441\u044b\u04a3\u044b\u0437", + "MessageSupporterPluginRequiresMembership": "\u0411\u04b1\u043b \u043f\u043b\u0430\u0433\u0438\u043d\u0433\u0435 14 \u043a\u04af\u043d\u0434\u0456\u043a \u0442\u0435\u0433\u0456\u043d \u0441\u044b\u043d\u0430\u043c\u0430\u0434\u0430\u043d \u043a\u0435\u0439\u0456\u043d \u0431\u0435\u043b\u0441\u0435\u043d\u0434\u0456 \u0436\u0430\u049b\u0442\u0430\u0443\u0448\u044b \u043c\u04af\u0448\u0435\u043b\u0456\u0433\u0456\u043d \u049b\u0430\u0436\u0435\u0442 \u0435\u0442\u0435\u0434\u0456.", + "MessagePremiumPluginRequiresMembership": "\u0411\u04b1\u043b \u043f\u043b\u0430\u0433\u0438\u043d\u0434\u0456 \u0441\u0430\u0442\u044b\u043f \u0430\u043b\u0443 \u04af\u0448\u0456\u043d 14 \u043a\u04af\u043d\u0434\u0456\u043a \u0442\u0435\u0433\u0456\u043d \u0441\u044b\u043d\u0430\u043c\u0430\u0434\u0430\u043d \u043a\u0435\u0439\u0456\u043d \u0431\u0435\u043b\u0441\u0435\u043d\u0434\u0456 \u0436\u0430\u049b\u0442\u0430\u0443\u0448\u044b \u043c\u04af\u0448\u0435\u043b\u0456\u0433\u0456\u043d \u049b\u0430\u0436\u0435\u0442 \u0435\u0442\u0435\u0434\u0456.", "HeaderReviews": "\u041f\u0456\u043a\u0456\u0440\u043b\u0435\u0440", - "HeaderDeveloperInfo": "\u0416\u0430\u0441\u0430\u049b\u0442\u0430\u0443\u0448\u044b \u0442\u0443\u0440\u0430\u043b\u044b", + "HeaderDeveloperInfo": "\u0416\u0430\u0441\u0430\u049b\u0442\u0430\u0443\u0448\u044b\u043b\u0430\u0440 \u0442\u0443\u0440\u0430\u043b\u044b", "HeaderRevisionHistory": "\u04e8\u0437\u0433\u0435\u0440\u0456\u0441\u0442\u0435\u0440 \u0442\u0430\u0440\u0438\u0445\u044b", "ButtonViewWebsite": "\u0492\u0430\u043b\u0430\u043c\u0442\u043e\u0440 \u0441\u0430\u0439\u0442\u044b\u043d \u049b\u0430\u0440\u0430\u0443", "LabelRecurringDonationCanBeCancelledHelp": "\u049a\u0430\u0439\u0442\u0430\u043b\u0430\u043c\u0430 \u049b\u0430\u0439\u044b\u0440\u043c\u0430\u043b\u0434\u044b\u049b\u0442\u0430\u0440 PayPal \u0435\u0441\u0435\u043f \u0448\u043e\u0442\u044b \u0430\u0440\u049b\u044b\u043b\u044b \u04d9\u0440 \u0443\u0430\u049b\u044b\u0442\u0442\u0430 \u0434\u0430 \u0431\u043e\u043b\u0434\u044b\u0440\u044b\u043b\u043c\u0430\u0443\u044b \u043c\u04af\u043c\u043a\u0456\u043d.", @@ -1192,7 +1231,7 @@ "LabelExtractChaptersDuringLibraryScanHelp": "\u049a\u043e\u0441\u044b\u043b\u0493\u0430\u043d\u0434\u0430, \u0441\u0430\u0445\u043d\u0430 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0456 \u0442\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430\u043d\u044b \u0441\u043a\u0430\u043d\u0435\u0440\u043b\u0435\u0443 \u043c\u0435\u0437\u0433\u0456\u043b\u0456\u043d\u0434\u0435, \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440 \u0441\u044b\u0440\u0442\u0442\u0430\u043d \u0430\u043b\u044b\u043d\u0493\u0430\u043d\u0434\u0430, \u0448\u044b\u0493\u0430\u0440\u044b\u043f \u0430\u043b\u044b\u043d\u0430\u0434\u044b. \u0410\u0436\u044b\u0440\u0430\u0442\u044b\u043b\u0493\u0430\u043d\u0434\u0430, \u0431\u04b1\u043b\u0430\u0440 \u0441\u0430\u0445\u043d\u0430 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0456\u043d\u0435 \u0436\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0493\u0430\u043d \u0442\u0430\u043f\u0441\u044b\u0440\u043c\u0430\u0441\u044b \u043c\u0435\u0437\u0433\u0456\u043b\u0456\u043d\u0434\u0435, \u0442\u04b1\u0440\u0430\u049b\u0442\u044b \u0442\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430\u043d\u044b \u0441\u043a\u0430\u043d\u0435\u0440\u043b\u0435\u0443\u0456\u043d \u0436\u044b\u043b\u0434\u0430\u043c\u044b\u0440\u0430\u049b \u0430\u044f\u049b\u0442\u0430\u043b\u0443\u044b \u04b1\u0448\u0456\u043d \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0456\u043f, \u0448\u044b\u0493\u0430\u0440\u044b\u043f \u0430\u043b\u044b\u043d\u0430\u0434\u044b.", "LabelConnectGuestUserName": "\u041e\u043b\u0430\u0440\u0434\u044b\u04a3 Media Browser \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b \u0430\u0442\u044b \u043d\u0435\u043c\u0435\u0441\u0435 \u044d-\u043f\u043e\u0448\u0442\u0430 \u043c\u0435\u043a\u0435\u043d\u0436\u0430\u0439\u044b:", "LabelConnectUserName": "Media Browser \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b \u0430\u0442\u044b\/\u044d-\u043f\u043e\u0448\u0442\u0430\u0441\u044b:", - "LabelConnectUserNameHelp": "\u0421\u0435\u0440\u0432\u0435\u0440\u0434\u0456\u04a3 IP \u043c\u0435\u043a\u0435\u043d\u0436\u0430\u0439\u044b\u043d \u0431\u0456\u043b\u043c\u0435\u0439 \u0442\u04b1\u0440\u044b\u043f \u04d9\u0440\u049b\u0430\u0439\u0441\u044b Media Browser \u049b\u043e\u043b\u0434\u0430\u043d\u0431\u0430\u0441\u044b\u043d\u0430\u043d \u043a\u0456\u0440\u0443-\u049b\u0430\u0442\u044b\u043d\u0430\u0441\u0442\u044b \u0436\u0435\u04a3\u0456\u043b\u0434\u0435\u0442\u0443\u0456\u043d \u049b\u043e\u0441\u0443 \u04af\u0448\u0456\u043d \u043e\u0441\u044b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043d\u044b Media Browser \u0442\u0456\u0440\u043a\u0435\u043b\u0433\u0456\u0441\u0456\u043d\u0435 \u0431\u0430\u0439\u043b\u0430\u043d\u044b\u0441\u0442\u044b\u0440\u044b\u04a3\u044b\u0437.", + "LabelConnectUserNameHelp": "\u0421\u0435\u0440\u0432\u0435\u0440\u0434\u0456\u04a3 IP \u043c\u0435\u043a\u0435\u043d\u0436\u0430\u0439\u044b\u043d \u0431\u0456\u043b\u043c\u0435\u0439 \u0442\u04b1\u0440\u044b\u043f \u04d9\u0440\u049b\u0430\u0439\u0441\u044b Media Browser \u049b\u043e\u043b\u0434\u0430\u043d\u0431\u0430\u0441\u044b\u043d\u0430\u043d \u043e\u04a3\u0430\u0439\u0442\u044b\u043b\u0493\u0430\u043d \u043a\u0456\u0440\u0443-\u049b\u0430\u0442\u044b\u043d\u0430\u0441\u0442\u044b \u049b\u043e\u0441\u0443 \u04af\u0448\u0456\u043d \u043e\u0441\u044b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043d\u044b Media Browser \u0442\u0456\u0440\u043a\u0435\u043b\u0433\u0456\u0441\u0456\u043d\u0435 \u0431\u0430\u0439\u043b\u0430\u043d\u044b\u0441\u0442\u044b\u0440\u044b\u04a3\u044b\u0437.", "ButtonLearnMoreAboutMediaBrowserConnect": "Media Browser Connect \u0442\u0443\u0440\u0430\u043b\u044b \u043a\u04e9\u0431\u0456\u0440\u0435\u043a \u0431\u0456\u043b\u0443", "LabelExternalPlayers": "\u0421\u044b\u0440\u0442\u049b\u044b \u043e\u0439\u043d\u0430\u0442\u049b\u044b\u0448\u0442\u0430\u0440:", "LabelExternalPlayersHelp": "\u0421\u044b\u0440\u0442\u049b\u044b \u043e\u0439\u043d\u0430\u0442\u049b\u044b\u0448\u0442\u0430\u0440\u0434\u0430 \u043c\u0430\u0437\u043c\u04b1\u043d\u0434\u044b \u043e\u0439\u043d\u0430\u0442\u0443 \u04af\u0448\u0456\u043d \u0442\u04af\u0439\u043c\u0435\u0448\u0456\u043a\u0442\u0435\u0440\u0434\u0456 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0443. \u0411\u04b1\u043b \u0442\u0435\u043a \u049b\u0430\u043d\u0430 URL \u0441\u0445\u0435\u043c\u0430\u043b\u0430\u0440\u044b\u043d \u049b\u043e\u043b\u0434\u0430\u0439\u0442\u044b\u043d, \u04d9\u0434\u0435\u0442\u0442\u0435, Android \u0436\u04d9\u043d\u0435 iOS, \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u043b\u0430\u0440\u0434\u0430 \u049b\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456. \u0421\u044b\u0440\u0442\u049b\u044b \u043e\u0439\u043d\u0430\u0442\u049b\u044b\u0448\u0442\u0430\u0440, \u049b\u0430\u0493\u0438\u0434\u0430 \u0431\u043e\u0439\u044b\u043d\u0448\u0430, \u0430\u043b\u044b\u0441\u0442\u0430\u043d \u0431\u0430\u0441\u049b\u0430\u0440\u0443\u0434\u044b \u0436\u04d9\u043d\u0435 \u0436\u0430\u043b\u0493\u0430\u0441\u0442\u044b\u0440\u0443\u0434\u044b \u049b\u043e\u043b\u0434\u0430\u043c\u0430\u0439\u0434\u044b.", @@ -1216,13 +1255,13 @@ "TabCinemaMode": "\u041a\u0438\u043d\u043e\u0442\u0435\u0430\u0442\u0440 \u0440\u0435\u0436\u0456\u043c\u0456", "TitlePlayback": "\u041e\u0439\u043d\u0430\u0442\u0443", "LabelEnableCinemaModeFor": "\u041c\u044b\u043d\u0430\u0443 \u04af\u0448\u0456\u043d \u043a\u0438\u043d\u043e\u0442\u0435\u0430\u0442\u0440 \u0440\u0435\u0436\u0456\u043c\u0456\u043d \u049b\u043e\u0441\u0443:", - "CinemaModeConfigurationHelp": "\u041a\u0438\u043d\u043e\u0442\u0435\u0430\u0442\u0440 \u0440\u0435\u0436\u0456\u043c\u0456 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043b\u0435\u0440\u0434\u0456 \u0436\u04d9\u043d\u0435 \u0442\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u043a\u04e9\u0440\u043d\u0435\u0443\u0434\u0456 \u0431\u0430\u0441\u0442\u044b \u049b\u0430\u0441\u0438\u0435\u0442\u0442\u0456\u04a3 \u0430\u043b\u0434\u044b\u043d\u0434\u0430 \u043e\u0439\u043d\u0430\u0442\u0443 \u049b\u0430\u0431\u0456\u043b\u0435\u0442\u0456\u043c\u0435\u043d \u043a\u0438\u043d\u043e \u043a\u04e9\u0440\u0441\u0435\u0442\u0435\u0442\u0456\u043d \u0437\u0430\u043b \u04d9\u0441\u0435\u0440\u0456\u043d \u049b\u043e\u043d\u0430\u049b\u0436\u0430\u0439\u044b\u04a3\u044b\u0437\u0493\u0430 \u0442\u0456\u043a\u0435\u043b\u0435\u0439 \u0436\u0435\u0442\u043a\u0456\u0437\u0435\u0434\u0456.", + "CinemaModeConfigurationHelp": "\u041a\u0438\u043d\u043e\u0442\u0435\u0430\u0442\u0440 \u0440\u0435\u0436\u0456\u043c\u0456 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043b\u0435\u0440\u0434\u0456 \u0436\u04d9\u043d\u0435 \u0442\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u043a\u04e9\u0440\u043d\u0435\u0443\u0434\u0456 \u0431\u0430\u0441\u0442\u044b \u0435\u0440\u0435\u043a\u0448\u0435\u043b\u0456\u043a\u0442\u0456\u04a3 \u0430\u043b\u0434\u044b\u043d\u0434\u0430 \u043e\u0439\u043d\u0430\u0442\u0443 \u049b\u0430\u0431\u0456\u043b\u0435\u0442\u0456\u043c\u0435\u043d \u043a\u0438\u043d\u043e \u043a\u04e9\u0440\u0441\u0435\u0442\u0435\u0442\u0456\u043d \u0437\u0430\u043b \u04d9\u0441\u0435\u0440\u0456\u043d \u049b\u043e\u043d\u0430\u049b\u0436\u0430\u0439\u044b\u04a3\u044b\u0437\u0493\u0430 \u0442\u0456\u043a\u0435\u043b\u0435\u0439 \u0436\u0435\u0442\u043a\u0456\u0437\u0435\u0434\u0456.", "OptionTrailersFromMyMovies": "\u0422\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430 \u0444\u0438\u043b\u044c\u043c\u0434\u0435\u0440\u0456\u043d\u0434\u0435\u0433\u0456 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043b\u0435\u0440\u0456\u043d \u049b\u0430\u043c\u0442\u0443", "OptionUpcomingMoviesInTheaters": "\u0416\u0430\u04a3\u0430 \u0436\u04d9\u043d\u0435 \u043a\u04af\u0442\u0456\u043b\u0433\u0435\u043d \u0444\u0438\u043b\u044c\u043c\u0434\u0435\u0440\u0456\u043d\u0434\u0435\u0433\u0456 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043b\u0435\u0440\u0456\u043d \u049b\u0430\u043c\u0442\u0443", "LabelLimitIntrosToUnwatchedContent": "\u0422\u0435\u043a \u049b\u0430\u043d\u0430 \u049b\u0430\u0440\u0430\u043b\u043c\u0430\u0493\u0430\u043d \u043c\u0430\u0437\u043c\u04b1\u043d\u0493\u0430 \u0430\u0440\u043d\u0430\u043b\u0493\u0430\u043d \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043b\u0435\u0440\u0434\u0456 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443", "LabelEnableIntroParentalControl": "\u0417\u0438\u044f\u0442\u0442\u044b \u0430\u0442\u0430-\u0430\u043d\u0430\u043b\u044b\u049b \u0431\u0430\u049b\u044b\u043b\u0430\u0443\u0434\u044b \u049b\u043e\u0441\u0443", "LabelEnableIntroParentalControlHelp": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440\u043b\u0435\u0440 \u0436\u0430\u0441\u0442\u0430\u0441 \u0441\u0430\u043d\u0430\u0442\u044b \u0442\u0435\u043a \u049b\u0430\u043d\u0430 \u049b\u0430\u0440\u0430\u0443\u0493\u0430 \u0430\u0440\u043d\u0430\u043b\u0493\u0430\u043d \u043c\u0430\u0437\u043c\u04b1\u043d\u0493\u0430 \u0442\u0435\u04a3 \u043d\u0435\u043c\u0435\u0441\u0435 \u043a\u0435\u043c \u0431\u043e\u043b\u044b\u043f \u0442\u0430\u04a3\u0434\u0430\u043b\u0430\u0434\u044b.", - "LabelTheseFeaturesRequireSupporterHelpAndTrailers": "\u041e\u0441\u044b \u043c\u04d9\u043b\u0456\u043c\u0435\u0442\u0442\u0435\u0440 \u0431\u0435\u043b\u0441\u0435\u043d\u0434\u0456 \u049b\u043e\u043b\u0434\u0430\u0443\u0448\u044b \u043c\u04af\u0448\u0435\u043b\u0456\u0433\u0456\u043d \u0436\u04d9\u043d\u0435 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043b\u0435\u0440 \u0430\u0440\u043d\u0430\u0441\u044b \u043f\u043b\u0430\u0433\u0438\u043d\u0456\u043d \u043e\u0440\u043d\u0430\u0442\u0443 \u049b\u0430\u0436\u0435\u0442 \u0435\u0442\u0435\u0434\u0456.", + "LabelTheseFeaturesRequireSupporterHelpAndTrailers": "\u041e\u0441\u044b \u0435\u0440\u0435\u043a\u0448\u0435\u043b\u0456\u043a\u0442\u0435\u0440\u0433\u0435 \u0431\u0435\u043b\u0441\u0435\u043d\u0434\u0456 \u0436\u0430\u049b\u0442\u0430\u0443\u0448\u044b \u043c\u04af\u0448\u0435\u043b\u0456\u0433\u0456\u043d \u0436\u04d9\u043d\u0435 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043b\u0435\u0440 \u0430\u0440\u043d\u0430\u0441\u044b \u043f\u043b\u0430\u0433\u0438\u043d\u0456\u043d \u043e\u0440\u043d\u0430\u0442\u0443 \u049b\u0430\u0436\u0435\u0442 \u0435\u0442\u0435\u0434\u0456.", "OptionTrailersFromMyMoviesHelp": "\u0416\u0435\u0440\u0433\u0456\u043b\u0456\u043a\u0442\u0456 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043b\u0435\u0440 \u043e\u0440\u043d\u0430\u0442\u0443\u044b\u043d \u0436\u04d9\u043d\u0435 \u0442\u0435\u04a3\u0448\u0435\u0443\u0456\u043d \u049b\u0430\u0436\u0435\u0442 \u0435\u0442\u0435\u0434\u0456.", "LabelCustomIntrosPath": "\u0422\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u043a\u04e9\u0440\u043d\u0435\u0443\u043b\u0435\u0440 \u0436\u043e\u043b\u044b:", "LabelCustomIntrosPathHelp": "\u0411\u0435\u0439\u043d\u0435 \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b \u0431\u0430\u0440 \u049b\u0430\u043b\u0442\u0430. \u0411\u0435\u0439\u043d\u0435 \u043a\u0435\u0437\u0434\u0435\u0439\u0441\u043e\u049b \u0442\u0430\u04a3\u0434\u0430\u043b\u0430\u0434\u044b \u0434\u0430 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043b\u0435\u0440\u0434\u0435\u043d \u043a\u0435\u0439\u0456\u043d \u043e\u0439\u043d\u0430\u0442\u044b\u043b\u0430\u0434\u044b.", @@ -1270,7 +1309,7 @@ "OptionEveryday": "\u041a\u04af\u043d \u0441\u0430\u0439\u044b\u043d", "OptionWeekdays": "\u0416\u04b1\u043c\u044b\u0441 \u043a\u04af\u043d\u0434\u0435\u0440\u0456", "OptionWeekends": "\u0414\u0435\u043c\u0430\u043b\u044b\u0441 \u043a\u04af\u043d\u0434\u0435\u0440\u0456", - "MessageProfileInfoSynced": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u044b\u043d\u044b\u04a3 \u0430\u049b\u043f\u0430\u0440\u0430\u0442\u044b Media Browser Connect \u0430\u0440\u049b\u044b\u043b\u044b \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u043b\u0430\u0434\u044b.", + "MessageProfileInfoSynced": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u044b\u043d\u044b\u04a3 \u0430\u049b\u043f\u0430\u0440\u0430\u0442\u044b Media Browser Connect \u0430\u0440\u049b\u044b\u043b\u044b \u04af\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0456\u043b\u0435\u0434\u0456.", "HeaderOptionalLinkMediaBrowserAccount": "\u049a\u0430\u043b\u0430\u0443 \u0431\u043e\u0439\u044b\u043d\u0448\u0430: Media Browser \u0442\u0456\u0440\u043a\u0435\u043b\u0433\u0456\u04a3\u0456\u0437\u0431\u0435\u043d \u0431\u0430\u0439\u043b\u0430\u043d\u044b\u0441\u0442\u044b\u0440\u0443", "ButtonTrailerReel": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440\u043b\u0435\u0440\u0434\u0456 \u0436\u0430\u043f\u0441\u044b\u0440\u0443", "HeaderTrailerReel": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440\u043b\u0435\u0440\u0434\u0456 \u0436\u0430\u043f\u0441\u044b\u0440\u0443", @@ -1279,7 +1318,7 @@ "MessageNoTrailersFound": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440\u043b\u0435\u0440 \u0442\u0430\u0431\u044b\u043b\u043c\u0430\u0434\u044b. \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u0445\u0430\u043d\u0430\u0441\u044b\u043d \u04af\u0441\u0442\u0435\u0443 \u0430\u0440\u049b\u044b\u043b\u044b \u0444\u0438\u043b\u044c\u043c\u0434\u0435\u043d \u0430\u043b\u044b\u043d\u0430\u0442\u044b\u043d \u0442\u04d9\u0436\u0456\u0440\u0438\u0431\u0435\u04a3\u0456\u0437\u0434\u0456 \u0436\u0430\u049b\u0441\u0430\u0440\u0442\u0443 \u04af\u0448\u0456\u043d Trailer \u0430\u0440\u043d\u0430\u0441\u044b\u043d \u043e\u0440\u043d\u0430\u0442\u044b\u04a3\u044b\u0437", "HeaderNewUsers": "\u0416\u0430\u04a3\u0430 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043b\u0430\u0440", "ButtonSignUp": "\u0422\u0456\u0440\u043a\u0435\u043b\u0443", - "ButtonForgotPassword": "\u049a\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437\u0434\u0456 \u04b1\u043c\u044b\u0442\u044b\u04a3\u044b\u0437 \u0431\u0430?", + "ButtonForgotPassword": "\u049a\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437\u0434\u0456 \u0435\u0441\u043a\u0435 \u0441\u0430\u043b\u0443", "OptionDisableUserPreferences": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b \u0442\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0434\u0435\u0440\u0456\u043d\u0435 \u049b\u0430\u0442\u044b\u043d\u0430\u0441\u0443\u0434\u044b \u0430\u0436\u044b\u0440\u0430\u0442\u0443", "OptionDisableUserPreferencesHelp": "\u0415\u0433\u0435\u0440 \u049b\u043e\u0441\u044b\u043b\u0441\u0430, \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u044b\u043d, \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0456\u043d, \u049b\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437\u0434\u0435\u0440\u0456\u043d \u0436\u04d9\u043d\u0435 \u0442\u0456\u043b\u0434\u0456\u043a \u0442\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0434\u0435\u0440\u0456\u043d \u0442\u0435\u043a \u049b\u0430\u043d\u0430 \u04d9\u043a\u0456\u043c\u0448\u0456\u043b\u0435\u0440 \u0442\u0435\u04a3\u0448\u0435\u0443\u0456 \u043c\u04af\u043c\u043a\u0456\u043d.", "HeaderSelectServer": "\u0421\u0435\u0440\u0432\u0435\u0440\u0434\u0456 \u0442\u0430\u04a3\u0434\u0430\u0443", @@ -1292,7 +1331,7 @@ "HeaderLatestItems": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0435\u0440", "LabelSelectLastestItemsFolders": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0435\u0440\u0434\u0456\u04a3 \u043a\u0435\u043b\u0435\u0441\u0456 \u0431\u04e9\u043b\u0456\u043c\u0434\u0435\u0440\u0456\u043d\u0435\u043d \u0442\u0430\u0441\u0443\u0448\u044b \u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u043c\u0435\u043d \u049b\u0430\u043c\u0442\u0443", "HeaderShareMediaFolders": "\u0422\u0430\u0441\u0443\u0448\u044b \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440\u043c\u0435\u043d \u043e\u0440\u0442\u0430\u049b\u0442\u0430\u0441\u0443", - "MessageGuestSharingPermissionsHelp": "\u041c\u04d9\u043b\u043c\u0435\u0442\u0442\u0435\u0440\u0434\u0456\u04a3 \u043a\u04e9\u0431\u0456 \u04d9\u0434\u0435\u043f\u043a\u0456\u0434\u0435 \u049b\u043e\u043d\u0430\u049b\u0442\u0430\u0440\u0493\u0430 \u049b\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456 \u0435\u043c\u0435\u0441, \u0431\u0456\u0440\u0430\u049b \u043a\u0435\u0440\u0435\u043a \u0431\u043e\u043b\u0441\u0430 \u049b\u043e\u0441\u044b\u043b\u0430\u0434\u044b.", + "MessageGuestSharingPermissionsHelp": "\u0415\u0440\u0435\u043a\u0448\u0435\u043b\u0456\u043a\u0442\u0435\u0440\u0434\u0456\u04a3 \u043a\u04e9\u0431\u0456 \u04d9\u0434\u0435\u043f\u043a\u0456\u0434\u0435 \u049b\u043e\u043d\u0430\u049b\u0442\u0430\u0440\u0493\u0430 \u049b\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456 \u0435\u043c\u0435\u0441, \u0431\u0456\u0440\u0430\u049b \u043a\u0435\u0440\u0435\u043a \u0431\u043e\u043b\u0441\u0430 \u049b\u043e\u0441\u044b\u043b\u0430\u0434\u044b.", "HeaderInvitations": "\u0428\u0430\u049b\u044b\u0440\u0443\u043b\u0430\u0440", "LabelForgotPasswordUsernameHelp": "\u0415\u0441\u043a\u0435 \u0441\u0430\u043b\u0441\u0430\u04a3\u044b\u0437, \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b \u0430\u0442\u044b\u04a3\u044b\u0437\u0434\u044b \u0435\u043d\u0433\u0456\u0437\u0456\u04a3\u0456\u0437.", "HeaderForgotPassword": "\u049a\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437\u0434\u0456 \u04b1\u043c\u044b\u0442\u044b\u04a3\u044b\u0437 \u0431\u0430?", @@ -1309,11 +1348,11 @@ "LabelEnableSingleImageInDidlLimit": "\u0416\u0430\u043b\u0493\u044b\u0437 \u043a\u0456\u0440\u0456\u0441\u0442\u0456\u0440\u0456\u043b\u0433\u0435\u043d \u0441\u0443\u0440\u0435\u0442\u043a\u0435 \u0448\u0435\u043a\u0442\u0435\u0443", "LabelEnableSingleImageInDidlLimitHelp": "\u0415\u0433\u0435\u0440 \u0431\u0456\u0440\u043d\u0435\u0448\u0435 \u0441\u0443\u0440\u0435\u0442 Didl \u0456\u0448\u0456\u043d\u0435 \u043a\u0456\u0440\u0456\u0441\u0442\u0456\u0440\u0456\u043b\u0441\u0435, \u043a\u0435\u0439\u0431\u0456\u0440 \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u043b\u0430\u0440\u0434\u0430 \u0442\u0438\u0456\u0441\u0442\u0456 \u0442\u04af\u0440\u0434\u0435 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u043d\u0431\u0435\u0439\u0434\u0456.", "TabActivity": "\u04d8\u0440\u0435\u043a\u0435\u0442\u0442\u0435\u0440", - "TitleSync": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443", - "OptionAllowSyncContent": "\u041c\u0435\u0434\u0438\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0434\u0456 \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u043c\u0435\u043d \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443\u0493\u0430 \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0443", + "TitleSync": "\u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443", + "OptionAllowSyncContent": "\u041c\u0435\u0434\u0438\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0434\u0456 \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u043c\u0435\u043d \u04af\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443\u0433\u0435 \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0443", "NameSeasonUnknown": "\u0411\u0435\u043b\u0433\u0456\u0441\u0456\u0437 \u043c\u0430\u0443\u0441\u044b\u043c", "NameSeasonNumber": "{0}-\u0441\u0435\u0437\u043e\u043d", "LabelNewUserNameHelp": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b \u0430\u0442\u0442\u0430\u0440\u044b\u043d\u0434\u0430 \u04d9\u0440\u0456\u043f\u0442\u0435\u0440 (a-z), \u0441\u0430\u043d\u0434\u0430\u0440 (0-9), \u0441\u044b\u0437\u044b\u049b\u0448\u0430\u043b\u0430\u0440 (-), \u0430\u0441\u0442\u044b\u04a3\u0493\u044b \u0441\u044b\u0437\u044b\u049b\u0442\u0430\u0440 (_), \u0434\u04d9\u0439\u0435\u043a\u0448\u0435\u043b\u0435\u0440 (') \u0436\u04d9\u043d\u0435 \u043d\u04af\u043a\u0442\u0435\u043b\u0435\u0440 (.) \u0431\u043e\u043b\u0443\u044b \u043c\u04af\u043c\u043a\u0456\u043d", "TabJobs": "\u0416\u04b1\u043c\u044b\u0441\u0442\u0430\u0440", - "TabSyncJobs": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443 \u0436\u04b1\u043c\u044b\u0441\u0442\u0430\u0440\u044b" + "TabSyncJobs": "\u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443 \u0436\u04b1\u043c\u044b\u0441\u0442\u0430\u0440\u044b" }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/ko.json b/MediaBrowser.Server.Implementations/Localization/Server/ko.json index f4ad42b47..98094e213 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/ko.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/ko.json @@ -40,12 +40,32 @@ "OptionIAcceptTermsOfService": "I accept the terms of service", "ButtonPrivacyPolicy": "Privacy policy", "ButtonTermsOfService": "Terms of Service", + "HeaderDeveloperOptions": "Developer Options", + "OptionEnableWebClientResponseCache": "Enable web client response caching", + "OptionDisableForDevelopmentHelp": "Configure these as needed for web client development purposes.", + "OptionEnableWebClientResourceMinification": "Enable web client resource minification", + "LabelDashboardSourcePath": "Web client source path:", + "LabelDashboardSourcePathHelp": "If running the server from source, specify the path to the dashboard-ui folder. All web client files will be served from this location.", + "ButtonConvertMedia": "Convert media", + "ButtonOrganize": "Organize", "ButtonOk": "Ok", "ButtonCancel": "Cancel", "ButtonNew": "New", "HeaderTV": "TV", "HeaderAudio": "Audio", "HeaderVideo": "Video", + "HeaderPaths": "Paths", + "CategorySync": "Sync", + "HeaderEasyPinCode": "Easy Pin Code", + "RegisterWithPayPal": "Register with PayPal", + "HeaderSyncRequiresSupporterMembership": "Sync Requires a Supporter Membership", + "HeaderEnjoyDayTrial": "Enjoy a 14 Day Free Trial", + "LabelSyncTempPath": "Temporary file path:", + "LabelSyncTempPathHelp": "Specify a custom sync working folder. Converted media created during the sync process will be stored here.", + "LabelCustomCertificatePath": "Custom certificate path:", + "LabelCustomCertificatePathHelp": "Supply your own ssl certificate. If omitted, the server will create a self-signed certificate.", + "TitleNotifications": "Notifications", + "ButtonDonateWithPayPal": "Donate with PayPal", "OptionDetectArchiveFilesAsMedia": "Detect archive files as media", "OptionDetectArchiveFilesAsMediaHelp": "If enabled, files with .rar and .zip extensions will be detected as media files.", "LabelEnterConnectUserName": "User name or email:", @@ -63,12 +83,14 @@ "FolderTypeTvShows": "TV", "FolderTypeInherit": "Inherit", "LabelContentType": "Content type:", + "TitleScheduledTasks": "Scheduled Tasks", "HeaderSetupLibrary": "Setup your media library", "ButtonAddMediaFolder": "Add media folder", "LabelFolderType": "Folder type:", "ReferToMediaLibraryWiki": "Refer to the media library wiki.", "LabelCountry": "Country:", "LabelLanguage": "Language:", + "ButtonJoinTheDevelopmentTeam": "Join the Development Team", "HeaderPreferredMetadataLanguage": "Preferred metadata language:", "LabelSaveLocalMetadata": "Save artwork and metadata into media folders", "LabelSaveLocalMetadataHelp": "Saving artwork and metadata directly into media folders will put them in a place where they can be easily edited.", @@ -86,6 +108,8 @@ "TabCollectionTitles": "Titles", "HeaderDeviceAccess": "Device Access", "OptionEnableAccessFromAllDevices": "Enable access from all devices", + "OptionEnableAccessToAllChannels": "Enable access to all channels", + "OptionEnableAccessToAllLibraries": "Enable access to all libraries", "DeviceAccessHelp": "This only applies to devices that can be uniquely identified and will not prevent browser access. Filtering user device access will prevent them from using new devices until they've been approved here.", "LabelDisplayMissingEpisodesWithinSeasons": "Display missing episodes within seasons", "LabelUnairedMissingEpisodesWithinSeasons": "Display unaired episodes within seasons", @@ -299,7 +323,7 @@ "LabelCachePath": "Cache path:", "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.", "LabelImagesByNamePath": "Images by name path:", - "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, genre and studio images.", "LabelMetadataPath": "Metadata path:", "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.", "LabelTranscodingTempPath": "Transcoding temporary path:", @@ -314,12 +338,14 @@ "OptionEpisodes": "Episodes", "OptionOtherVideos": "Other Videos", "TitleMetadata": "Metadata", - "LabelAutomaticUpdatesFanart": "Enable automatic updates from FanArt.tv", + "LabelAutomaticUpdates": "Enable automatic updates", "LabelAutomaticUpdatesTmdb": "Enable automatic updates from TheMovieDB.org", "LabelAutomaticUpdatesTvdb": "Enable automatic updates from TheTVDB.com", "LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.", "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.", "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.", + "LabelFanartApiKey": "Personal api key:", + "LabelFanartApiKeyHelp": "Requests to fanart without a personal API key return results that were approved over 7 days ago. With a personal API key that drops to 48 hours and if you are also a fanart VIP member that will further drop to around 10 minutes.", "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", "LabelMetadataDownloadLanguage": "Preferred download language:", "ButtonAutoScroll": "Auto-scroll", @@ -487,6 +513,7 @@ "HeaderSystemPaths": "System Paths", "LinkCommunity": "Community", "LinkGithub": "Github", + "LinkApi": "Api", "LinkApiDocumentation": "Api Documentation", "LabelFriendlyServerName": "Friendly server name:", "LabelFriendlyServerNameHelp": "This name will be used to identify this server. If left blank, the computer name will be used.", @@ -494,20 +521,25 @@ "LabelPreferredDisplayLanguageHelp": "Translating Media Browser is an ongoing project and is not yet complete.", "LabelReadHowYouCanContribute": "Read about how you can contribute.", "HeaderNewCollection": "New Collection", - "HeaderAddToCollection": "Add to Collection", "ButtonSubmit": "Submit", - "NewCollectionNameExample": "Example: Star Wars Collection", - "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata", "ButtonCreate": "Create", - "LabelLocalHttpServerPortNumber": "Local port number:", + "LabelCustomCss": "Custom css:", + "LabelCustomCssHelp": "Apply your own custom css to the web interface.", + "LabelLocalHttpServerPortNumber": "Local http port number:", "LabelLocalHttpServerPortNumberHelp": "The tcp port number that Media Browser's http server should bind to.", - "LabelPublicPort": "Public port number:", - "LabelPublicPortHelp": "The public port number that should be mapped to the local port.", + "LabelPublicHttpPort": "Public http port number:", + "LabelPublicHttpPortHelp": "The public port number that should be mapped to the local http port.", + "LabelPublicHttpsPort": "Public https port number:", + "LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.", + "LabelEnableHttps": "Report https as external address", + "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.", + "LabelHttpsPort": "Local https port number:", + "LabelHttpsPortHelp": "The tcp port number that Media Browser's https server should bind to.", "LabelWebSocketPortNumber": "Web socket port number:", "LabelEnableAutomaticPortMap": "Enable automatic port mapping", "LabelEnableAutomaticPortMapHelp": "Attempt to automatically map the public port to the local port via UPnP. This may not work with some router models.", - "LabelExternalDDNS": "External DDNS:", - "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely.", + "LabelExternalDDNS": "External WAN Address:", + "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely. Leave empty for automatic detection.", "TabResume": "Resume", "TabWeather": "Weather", "TitleAppSettings": "App Settings", @@ -575,6 +607,7 @@ "ButtonRestart": "Restart", "ButtonShutdown": "Shutdown", "ButtonUpdateNow": "Update Now", + "TabHosting": "Hosting", "PleaseUpdateManually": "Please shutdown the server and update manually.", "NewServerVersionAvailable": "A new version of Media Browser Server is available!", "ServerUpToDate": "Media Browser Server is up to date", @@ -636,6 +669,7 @@ "NotificationOptionInstallationFailed": "Installation failure", "NotificationOptionNewLibraryContent": "New content added", "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", + "NotificationOptionCameraImageUploaded": "Camera image uploaded", "SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.", "NotificationOptionServerRestartRequired": "Server restart required", "LabelNotificationEnabled": "Enable this notification", @@ -853,6 +887,8 @@ "OptionDefaultSort": "Default", "OptionCommunityMostWatchedSort": "Most Watched", "TabNextUp": "Next Up", + "HeaderBecomeMediaBrowserSupporter": "Become a Media Browser Supporter", + "TextEnjoyBonusFeatures": "Enjoy Bonus Features", "MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.", "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.", "MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.", @@ -869,7 +905,6 @@ "LabelChannelDownloadAge": "Delete content after: (days)", "LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.", "ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.", - "LabelSelectCollection": "Select collection:", "ButtonOptions": "Options", "ViewTypeMovies": "Movies", "ViewTypeTvShows": "TV", @@ -917,7 +952,7 @@ "OptionLatestTvRecordings": "Latest recordings", "LabelProtocolInfo": "Protocol info:", "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.", - "TabKodiMetadata": "Kodi", + "TabNfo": "Nfo", "HeaderKodiMetadataHelp": "Media Browser includes native support for Kodi Nfo metadata and images. To enable or disable Kodi metadata, use the Advanced tab to configure options for your media types.", "LabelKodiMetadataUser": "Sync user watch data to nfo's for:", "LabelKodiMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Kodi.", @@ -931,6 +966,7 @@ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:", "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.", "LabelDisplayCollectionsView": "Display a collections view to show movie collections", + "LabelDisplayCollectionsViewHelp": "This will create a separate view to display collections that you've created or have access to. To create a collection, right-click or tap-hold any movie and select 'Add to Collection'. ", "LabelKodiMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs", "LabelKodiMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Kodi skin compatibility.", "TabServices": "Services", @@ -1084,11 +1120,14 @@ "LabelDisplayFoldersView": "Display a folders view to show plain media folders", "ViewTypeLiveTvRecordingGroups": "Recordings", "ViewTypeLiveTvChannels": "Channels", - "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password", - "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.", + "LabelEasyPinCode": "Easy pin code:", + "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Media Browser apps, and can also be used for easy in-network sign in.", + "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", + "LabelInNetworkSignInWithEasyPasswordHelp": "If enabled, you'll be able to use your easy pin code to sign in to Media Browser apps from inside your home network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", "HeaderPassword": "Password", "HeaderLocalAccess": "Local Access", "HeaderViewOrder": "View Order", + "ButtonResetEasyPassword": "Reset easy pin code", "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps", "LabelMetadataRefreshMode": "Metadata refresh mode:", "LabelImageRefreshMode": "Image refresh mode:", @@ -1279,7 +1318,7 @@ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.", "HeaderNewUsers": "New Users", "ButtonSignUp": "Sign up", - "ButtonForgotPassword": "Forgot password?", + "ButtonForgotPassword": "Forgot password", "OptionDisableUserPreferences": "Disable access to user preferences", "OptionDisableUserPreferencesHelp": "If enabled, only administrators will be able to configure user profile images, passwords, and language preferences.", "HeaderSelectServer": "Select Server", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/ms.json b/MediaBrowser.Server.Implementations/Localization/Server/ms.json index 4fee2e9c0..0b591e6ba 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/ms.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/ms.json @@ -40,12 +40,32 @@ "OptionIAcceptTermsOfService": "I accept the terms of service", "ButtonPrivacyPolicy": "Privacy policy", "ButtonTermsOfService": "Terms of Service", + "HeaderDeveloperOptions": "Developer Options", + "OptionEnableWebClientResponseCache": "Enable web client response caching", + "OptionDisableForDevelopmentHelp": "Configure these as needed for web client development purposes.", + "OptionEnableWebClientResourceMinification": "Enable web client resource minification", + "LabelDashboardSourcePath": "Web client source path:", + "LabelDashboardSourcePathHelp": "If running the server from source, specify the path to the dashboard-ui folder. All web client files will be served from this location.", + "ButtonConvertMedia": "Convert media", + "ButtonOrganize": "Organize", "ButtonOk": "Ok", "ButtonCancel": "Cancel", "ButtonNew": "New", "HeaderTV": "TV", "HeaderAudio": "Audio", "HeaderVideo": "Video", + "HeaderPaths": "Paths", + "CategorySync": "Sync", + "HeaderEasyPinCode": "Easy Pin Code", + "RegisterWithPayPal": "Register with PayPal", + "HeaderSyncRequiresSupporterMembership": "Sync Requires a Supporter Membership", + "HeaderEnjoyDayTrial": "Enjoy a 14 Day Free Trial", + "LabelSyncTempPath": "Temporary file path:", + "LabelSyncTempPathHelp": "Specify a custom sync working folder. Converted media created during the sync process will be stored here.", + "LabelCustomCertificatePath": "Custom certificate path:", + "LabelCustomCertificatePathHelp": "Supply your own ssl certificate. If omitted, the server will create a self-signed certificate.", + "TitleNotifications": "Notifications", + "ButtonDonateWithPayPal": "Donate with PayPal", "OptionDetectArchiveFilesAsMedia": "Detect archive files as media", "OptionDetectArchiveFilesAsMediaHelp": "If enabled, files with .rar and .zip extensions will be detected as media files.", "LabelEnterConnectUserName": "User name or email:", @@ -63,12 +83,14 @@ "FolderTypeTvShows": "TV", "FolderTypeInherit": "Inherit", "LabelContentType": "Content type:", + "TitleScheduledTasks": "Scheduled Tasks", "HeaderSetupLibrary": "Setup your media library", "ButtonAddMediaFolder": "Add media folder", "LabelFolderType": "Folder type:", "ReferToMediaLibraryWiki": "Refer to the media library wiki.", "LabelCountry": "Country:", "LabelLanguage": "Language:", + "ButtonJoinTheDevelopmentTeam": "Join the Development Team", "HeaderPreferredMetadataLanguage": "Preferred metadata language:", "LabelSaveLocalMetadata": "Save artwork and metadata into media folders", "LabelSaveLocalMetadataHelp": "Saving artwork and metadata directly into media folders will put them in a place where they can be easily edited.", @@ -86,6 +108,8 @@ "TabCollectionTitles": "Titles", "HeaderDeviceAccess": "Device Access", "OptionEnableAccessFromAllDevices": "Enable access from all devices", + "OptionEnableAccessToAllChannels": "Enable access to all channels", + "OptionEnableAccessToAllLibraries": "Enable access to all libraries", "DeviceAccessHelp": "This only applies to devices that can be uniquely identified and will not prevent browser access. Filtering user device access will prevent them from using new devices until they've been approved here.", "LabelDisplayMissingEpisodesWithinSeasons": "Display missing episodes within seasons", "LabelUnairedMissingEpisodesWithinSeasons": "Display unaired episodes within seasons", @@ -299,7 +323,7 @@ "LabelCachePath": "Cache path:", "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.", "LabelImagesByNamePath": "Images by name path:", - "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, genre and studio images.", "LabelMetadataPath": "Metadata path:", "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.", "LabelTranscodingTempPath": "Transcoding temporary path:", @@ -314,12 +338,14 @@ "OptionEpisodes": "Episodes", "OptionOtherVideos": "Other Videos", "TitleMetadata": "Metadata", - "LabelAutomaticUpdatesFanart": "Enable automatic updates from FanArt.tv", + "LabelAutomaticUpdates": "Enable automatic updates", "LabelAutomaticUpdatesTmdb": "Enable automatic updates from TheMovieDB.org", "LabelAutomaticUpdatesTvdb": "Enable automatic updates from TheTVDB.com", "LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.", "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.", "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.", + "LabelFanartApiKey": "Personal api key:", + "LabelFanartApiKeyHelp": "Requests to fanart without a personal API key return results that were approved over 7 days ago. With a personal API key that drops to 48 hours and if you are also a fanart VIP member that will further drop to around 10 minutes.", "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", "LabelMetadataDownloadLanguage": "Preferred download language:", "ButtonAutoScroll": "Auto-scroll", @@ -487,6 +513,7 @@ "HeaderSystemPaths": "System Paths", "LinkCommunity": "Community", "LinkGithub": "Github", + "LinkApi": "Api", "LinkApiDocumentation": "Api Documentation", "LabelFriendlyServerName": "Friendly server name:", "LabelFriendlyServerNameHelp": "This name will be used to identify this server. If left blank, the computer name will be used.", @@ -494,20 +521,25 @@ "LabelPreferredDisplayLanguageHelp": "Translating Media Browser is an ongoing project and is not yet complete.", "LabelReadHowYouCanContribute": "Read about how you can contribute.", "HeaderNewCollection": "New Collection", - "HeaderAddToCollection": "Add to Collection", "ButtonSubmit": "Submit", - "NewCollectionNameExample": "Example: Star Wars Collection", - "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata", "ButtonCreate": "Create", - "LabelLocalHttpServerPortNumber": "Local port number:", + "LabelCustomCss": "Custom css:", + "LabelCustomCssHelp": "Apply your own custom css to the web interface.", + "LabelLocalHttpServerPortNumber": "Local http port number:", "LabelLocalHttpServerPortNumberHelp": "The tcp port number that Media Browser's http server should bind to.", - "LabelPublicPort": "Public port number:", - "LabelPublicPortHelp": "The public port number that should be mapped to the local port.", + "LabelPublicHttpPort": "Public http port number:", + "LabelPublicHttpPortHelp": "The public port number that should be mapped to the local http port.", + "LabelPublicHttpsPort": "Public https port number:", + "LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.", + "LabelEnableHttps": "Report https as external address", + "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.", + "LabelHttpsPort": "Local https port number:", + "LabelHttpsPortHelp": "The tcp port number that Media Browser's https server should bind to.", "LabelWebSocketPortNumber": "Web socket port number:", "LabelEnableAutomaticPortMap": "Enable automatic port mapping", "LabelEnableAutomaticPortMapHelp": "Attempt to automatically map the public port to the local port via UPnP. This may not work with some router models.", - "LabelExternalDDNS": "External DDNS:", - "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely.", + "LabelExternalDDNS": "External WAN Address:", + "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely. Leave empty for automatic detection.", "TabResume": "Resume", "TabWeather": "Weather", "TitleAppSettings": "App Settings", @@ -575,6 +607,7 @@ "ButtonRestart": "Restart", "ButtonShutdown": "Shutdown", "ButtonUpdateNow": "Update Now", + "TabHosting": "Hosting", "PleaseUpdateManually": "Please shutdown the server and update manually.", "NewServerVersionAvailable": "A new version of Media Browser Server is available!", "ServerUpToDate": "Media Browser Server is up to date", @@ -636,6 +669,7 @@ "NotificationOptionInstallationFailed": "Installation failure", "NotificationOptionNewLibraryContent": "New content added", "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", + "NotificationOptionCameraImageUploaded": "Camera image uploaded", "SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.", "NotificationOptionServerRestartRequired": "Server restart required", "LabelNotificationEnabled": "Enable this notification", @@ -853,6 +887,8 @@ "OptionDefaultSort": "Default", "OptionCommunityMostWatchedSort": "Most Watched", "TabNextUp": "Next Up", + "HeaderBecomeMediaBrowserSupporter": "Become a Media Browser Supporter", + "TextEnjoyBonusFeatures": "Enjoy Bonus Features", "MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.", "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.", "MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.", @@ -869,7 +905,6 @@ "LabelChannelDownloadAge": "Delete content after: (days)", "LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.", "ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.", - "LabelSelectCollection": "Select collection:", "ButtonOptions": "Options", "ViewTypeMovies": "Movies", "ViewTypeTvShows": "TV", @@ -917,7 +952,7 @@ "OptionLatestTvRecordings": "Latest recordings", "LabelProtocolInfo": "Protocol info:", "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.", - "TabKodiMetadata": "Kodi", + "TabNfo": "Nfo", "HeaderKodiMetadataHelp": "Media Browser includes native support for Kodi Nfo metadata and images. To enable or disable Kodi metadata, use the Advanced tab to configure options for your media types.", "LabelKodiMetadataUser": "Sync user watch data to nfo's for:", "LabelKodiMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Kodi.", @@ -931,6 +966,7 @@ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:", "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.", "LabelDisplayCollectionsView": "Display a collections view to show movie collections", + "LabelDisplayCollectionsViewHelp": "This will create a separate view to display collections that you've created or have access to. To create a collection, right-click or tap-hold any movie and select 'Add to Collection'. ", "LabelKodiMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs", "LabelKodiMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Kodi skin compatibility.", "TabServices": "Services", @@ -1084,11 +1120,14 @@ "LabelDisplayFoldersView": "Display a folders view to show plain media folders", "ViewTypeLiveTvRecordingGroups": "Recordings", "ViewTypeLiveTvChannels": "Channels", - "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password", - "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.", + "LabelEasyPinCode": "Easy pin code:", + "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Media Browser apps, and can also be used for easy in-network sign in.", + "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", + "LabelInNetworkSignInWithEasyPasswordHelp": "If enabled, you'll be able to use your easy pin code to sign in to Media Browser apps from inside your home network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", "HeaderPassword": "Password", "HeaderLocalAccess": "Local Access", "HeaderViewOrder": "View Order", + "ButtonResetEasyPassword": "Reset easy pin code", "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps", "LabelMetadataRefreshMode": "Metadata refresh mode:", "LabelImageRefreshMode": "Image refresh mode:", @@ -1279,7 +1318,7 @@ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.", "HeaderNewUsers": "New Users", "ButtonSignUp": "Sign up", - "ButtonForgotPassword": "Forgot password?", + "ButtonForgotPassword": "Forgot password", "OptionDisableUserPreferences": "Disable access to user preferences", "OptionDisableUserPreferencesHelp": "If enabled, only administrators will be able to configure user profile images, passwords, and language preferences.", "HeaderSelectServer": "Select Server", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/nb.json b/MediaBrowser.Server.Implementations/Localization/Server/nb.json index ec84af51e..ebbd9e5a0 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/nb.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/nb.json @@ -4,8 +4,8 @@ "LabelGithub": "Github", "LabelSwagger": "Swagger", "LabelStandard": "Standard", - "LabelApiDocumentation": "Api Documentation", - "LabelDeveloperResources": "Developer Resources", + "LabelApiDocumentation": "Api Dokumentasjon", + "LabelDeveloperResources": "Utvikler Ressurser", "LabelBrowseLibrary": "Browse biblioteket", "LabelConfigureMediaBrowser": "Konfigurer Media Browser", "LabelOpenLibraryViewer": "\u00c5pne Biblioteket", @@ -19,7 +19,7 @@ "TitleMediaBrowser": "Media Browser", "ThisWizardWillGuideYou": "Denne wizarden vil guide deg gjennom server-konfigurasjonen. For \u00e5 begynne, vennligst velg ditt foretrukne spr\u00e5k.", "TellUsAboutYourself": "Fortell om deg selv", - "ButtonQuickStartGuide": "Quick start guide", + "ButtonQuickStartGuide": "Hurtig start veiledning", "LabelYourFirstName": "Ditt fornavn", "MoreUsersCanBeAddedLater": "Du kan legge til flere brukere senere via Dashboard", "UserProfilesIntro": "Media Browser inkluderer innebygd st\u00f8tte for bruker profiler som tilbyr brukere innstillinger for visning, avspillerstatus og begrensning p\u00e5 innhold.", @@ -27,7 +27,7 @@ "AWindowsServiceHasBeenInstalled": "Windows Service har blitt installert", "WindowsServiceIntro1": "Media Browser Server kj\u00f8rer normalt som en desktop-applikasjon med et tray-ikon, men om du foretrekker at det kj\u00f8res som en bakgrunnsprosess, kan du i stedet starte den fra windows service control panel.", "WindowsServiceIntro2": "Hvis du bruker Windows, v\u00e6r oppmerksom p\u00e5 at det ikke kan kj\u00f8res samtidig som ikonet, slik at du trenger \u00e5 g\u00e5 ut av \"trayen\" for \u00e5 kj\u00f8re tjenesten. Tjenesten m\u00e5 ogs\u00e5 konfigureres med administratorrettigheter via kontrollpanelet. V\u00e6r oppmerksom p\u00e5 at p\u00e5 denne tiden tjenesten ikke er i stand til selv-oppdatering, s\u00e5 nye versjoner vil kreve manuell interaksjon.", - "WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click <b>Finish<\/b> to view the <b>Server Dashboard<\/b>.", + "WizardCompleted": "Det er alt vi trenger for n\u00e5. Media Browser har begynt \u00e5 samle inn informasjon om ditt media bibliotek. Sjekk ut noen av v\u00e5re apps, og klikk s\u00e5 <b>Ferdig<\/b> for \u00e5 vise <b>Server Dashboard<\/b>.", "LabelConfigureSettings": "Konfigurer innstillinger", "LabelEnableVideoImageExtraction": "Aktiver videobildet utvinning", "VideoImageExtractionHelp": "For videoer som ikke allerede har bilder, og at vi ikke klarer \u00e5 finne internettbilder for. Dette vil tilf\u00f8re noen ytterligere tid til den opprinnelige biblioteket s\u00f8king, men vil resultere i en mer tiltalende presentasjon.", @@ -35,20 +35,40 @@ "LabelChapterImageExtractionForMoviesHelp": "Utpakking i kapittelbilder vil tillate kunder \u00e5 vise grafiske scenevalgmenyer. Prosessen kan v\u00e6re treg, cpu-intensive og kan kreve flere Gigabyte med plass. Den kj\u00f8rer som en nattlig planlagt oppgave p\u00e5 04.00 AM, selv om dette er konfigurerbart i planlagte oppgaver omr\u00e5det. Det er ikke anbefalt \u00e5 kj\u00f8re denne oppgaven il\u00f8pet av toppbelastede timer.", "LabelEnableAutomaticPortMapping": "Sl\u00e5 p\u00e5 automatisk port mapping", "LabelEnableAutomaticPortMappingHelp": "UPnP tillater automatiserte routere konfigurasjoner for enkel ekstern tilgang. Denne funksjonen s\u00f8ttes ikke av alle routere.", - "HeaderTermsOfService": "Media Browser Terms of Service", - "MessagePleaseAcceptTermsOfService": "Please accept the terms of service and privacy policy before continuing.", - "OptionIAcceptTermsOfService": "I accept the terms of service", - "ButtonPrivacyPolicy": "Privacy policy", - "ButtonTermsOfService": "Terms of Service", + "HeaderTermsOfService": "Media Browser Vilk\u00e5r for Service", + "MessagePleaseAcceptTermsOfService": "Vennligst aksepter v\u00e5re service vilk\u00e5r og personvern policy f\u00f8r du fortsetter.", + "OptionIAcceptTermsOfService": "Jeg aksepterer service vilk\u00e5rene", + "ButtonPrivacyPolicy": "Personvern policy", + "ButtonTermsOfService": "Service Vilk\u00e5r", + "HeaderDeveloperOptions": "Utvikler opsjoner", + "OptionEnableWebClientResponseCache": "Aktiver web klient respons caching", + "OptionDisableForDevelopmentHelp": "Konfigurer disse ved behov for web klient utvikler form\u00e5l.", + "OptionEnableWebClientResourceMinification": "Aktiver web klient ressurs minifisering", + "LabelDashboardSourcePath": "Web klient kilde sti:", + "LabelDashboardSourcePathHelp": "If running the server from source, specify the path to the dashboard-ui folder. All web client files will be served from this location.", + "ButtonConvertMedia": "Convert media", + "ButtonOrganize": "Organize", "ButtonOk": "Ok", "ButtonCancel": "avbryt", "ButtonNew": "Ny", "HeaderTV": "TV", "HeaderAudio": "Lyd", "HeaderVideo": "Video", + "HeaderPaths": "Stier", + "CategorySync": "Sync", + "HeaderEasyPinCode": "Easy Pin Code", + "RegisterWithPayPal": "Register with PayPal", + "HeaderSyncRequiresSupporterMembership": "Sync Requires a Supporter Membership", + "HeaderEnjoyDayTrial": "Enjoy a 14 Day Free Trial", + "LabelSyncTempPath": "Temporary file path:", + "LabelSyncTempPathHelp": "Specify a custom sync working folder. Converted media created during the sync process will be stored here.", + "LabelCustomCertificatePath": "Custom certificate path:", + "LabelCustomCertificatePathHelp": "Supply your own ssl certificate. If omitted, the server will create a self-signed certificate.", + "TitleNotifications": "Notifications", + "ButtonDonateWithPayPal": "Doner med PayPal", "OptionDetectArchiveFilesAsMedia": "Detect archive files as media", "OptionDetectArchiveFilesAsMediaHelp": "If enabled, files with .rar and .zip extensions will be detected as media files.", - "LabelEnterConnectUserName": "User name or email:", + "LabelEnterConnectUserName": "Brukernavn eller epost:", "LabelEnterConnectUserNameHelp": "This is your Media Browser online account user name or password.", "HeaderSyncJobInfo": "Sync Job", "FolderTypeMixed": "Mixed content", @@ -63,12 +83,14 @@ "FolderTypeTvShows": "TV", "FolderTypeInherit": "Inherit", "LabelContentType": "Content type:", + "TitleScheduledTasks": "Scheduled Tasks", "HeaderSetupLibrary": "Konfigurer media-biblioteket", "ButtonAddMediaFolder": "Legg til media-mappe", "LabelFolderType": "Mappe typpe", "ReferToMediaLibraryWiki": "Se i media-bibliotek wikien", "LabelCountry": "LAnd", "LabelLanguage": "Spr\u00e5k:", + "ButtonJoinTheDevelopmentTeam": "Join the Development Team", "HeaderPreferredMetadataLanguage": "Foretrukket spr\u00e5k for metadata", "LabelSaveLocalMetadata": "Lagre cover og metadata i medie-mappene", "LabelSaveLocalMetadataHelp": "Lagring av artwork og metadata direkte gjennom media mapper vil legge dem en plass hvor de lett kan editeres.", @@ -86,6 +108,8 @@ "TabCollectionTitles": "Titler", "HeaderDeviceAccess": "Device Access", "OptionEnableAccessFromAllDevices": "Enable access from all devices", + "OptionEnableAccessToAllChannels": "Enable access to all channels", + "OptionEnableAccessToAllLibraries": "Enable access to all libraries", "DeviceAccessHelp": "This only applies to devices that can be uniquely identified and will not prevent browser access. Filtering user device access will prevent them from using new devices until they've been approved here.", "LabelDisplayMissingEpisodesWithinSeasons": "Vis episoder som sesongen mangler", "LabelUnairedMissingEpisodesWithinSeasons": "Vis episoder som enn\u00e5 ikke har blitt sendt", @@ -275,7 +299,7 @@ "OptionMetascore": "Metascore", "ButtonSelect": "Velg", "ButtonGroupVersions": "Gruppe Versjoner", - "ButtonAddToCollection": "Legg Til I Samling", + "ButtonAddToCollection": "Add to Collection", "PismoMessage": "Utnytte Pismo File Mount gjennom en donert lisens.", "TangibleSoftwareMessage": "Utnytte konkrete l\u00f8sninger Java \/ C # omformere gjennom en donert lisens.", "HeaderCredits": "Credits", @@ -299,7 +323,7 @@ "LabelCachePath": "Buffer sti:", "LabelCachePathHelp": "Definer en tilpasset lokalisering for server cashe filer, som bilder.", "LabelImagesByNamePath": "Bilder etter navn sti:", - "LabelImagesByNamePathHelp": "Definer en tilpasset lokalisering for nedlastede skuespillere, sjanger og studio bilder.", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, genre and studio images.", "LabelMetadataPath": "Metadata sti:", "LabelMetadataPathHelp": "Definer en tilpasset lokalisering for nedlastede artwork og metadata, hvis ikke skjer lagring innen media mappene.", "LabelTranscodingTempPath": "Transcoding midlertidig sti", @@ -314,12 +338,14 @@ "OptionEpisodes": "Episoder", "OptionOtherVideos": "Andre Videoer", "TitleMetadata": "Metadata", - "LabelAutomaticUpdatesFanart": "Aktiver automatisk oppdatering fra FanArt.tv", + "LabelAutomaticUpdates": "Enable automatic updates", "LabelAutomaticUpdatesTmdb": "Aktiver automatisk oppdateringer fra TheMovieDB.org", "LabelAutomaticUpdatesTvdb": "Aktiver automatisk oppdateringer fra TheTVDB.com", "LabelAutomaticUpdatesFanartHelp": "Hvis aktivert vil nye bilder bli nedlastet automatisk n\u00e5r de blir lagt til fanar.tv. Eksisterende bilder vil ikke bli erstattet.", "LabelAutomaticUpdatesTmdbHelp": "Hvis aktivert vil nye bilder bli nedlastet automatisk n\u00e5r de blir lagt til i TheMovieDB.org. Ekisterende bilder vil ikke bli erstattet.", "LabelAutomaticUpdatesTvdbHelp": "Hvis aktivert vil nye bilder bli nedlastet automatisk n\u00e5r de blir lagt til i TheTVDB.com. Ekisterende bilder vil ikke bli erstattet.", + "LabelFanartApiKey": "Personal api key:", + "LabelFanartApiKeyHelp": "Requests to fanart without a personal API key return results that were approved over 7 days ago. With a personal API key that drops to 48 hours and if you are also a fanart VIP member that will further drop to around 10 minutes.", "ExtractChapterImagesHelp": "Utpakking av kapittelbilder vil tillate kunder \u00e5 vise grafiske scenevalgmenyer. Prosessen kan v\u00e6re treg, cpu-intensive og kan kreve flere Gigabyte med plass. Det kj\u00f8rer n\u00e5r videoene blir oppdaget, og ogs\u00e5 som en nattlig planlagt oppgave p\u00e5 04.00 AM. Tidsplanen er konfigurerbart i planlagte oppgaver omr\u00e5det. Det er ikke anbefalt \u00e5 kj\u00f8re denne oppgaven ved toppbelastede timer.", "LabelMetadataDownloadLanguage": "Foretrukket nedlastingsspr\u00e5k:", "ButtonAutoScroll": "Auto-scroll", @@ -487,6 +513,7 @@ "HeaderSystemPaths": "System Stier", "LinkCommunity": "Samfunn", "LinkGithub": "Github", + "LinkApi": "Api", "LinkApiDocumentation": "Api Dokumentasjon", "LabelFriendlyServerName": "Vennlig server navn:", "LabelFriendlyServerNameHelp": "Dette navnet vil bli brukt for \u00e5 identifisere denne serveren. Hvis feltet er tomt, vil maskinens navn bli brukt.", @@ -494,20 +521,25 @@ "LabelPreferredDisplayLanguageHelp": "Oversetting av Media Browser er ett p\u00e5g\u00e5ende prosjekt og er enda ikke fullstendig ferdig.", "LabelReadHowYouCanContribute": "Les mer om hvordan du kan bidra.", "HeaderNewCollection": "Ny Samling", - "HeaderAddToCollection": "Legg Til I Samling", "ButtonSubmit": "Send", - "NewCollectionNameExample": "Eksempel: Star Wars Samling", - "OptionSearchForInternetMetadata": "S\u00f8k p\u00e5 internet for artwork og metadata", "ButtonCreate": "Opprett", - "LabelLocalHttpServerPortNumber": "Lokal port nummer:", + "LabelCustomCss": "Custom css:", + "LabelCustomCssHelp": "Apply your own custom css to the web interface.", + "LabelLocalHttpServerPortNumber": "Local http port number:", "LabelLocalHttpServerPortNumberHelp": "tcp port nummeret som Media Browser sin https server skal bindes mot.", - "LabelPublicPort": "Offentlig port nummer:", - "LabelPublicPortHelp": "Det offentlige port nummeret som m\u00e5 mappes til den lokale porten.", + "LabelPublicHttpPort": "Public http port number:", + "LabelPublicHttpPortHelp": "The public port number that should be mapped to the local http port.", + "LabelPublicHttpsPort": "Public https port number:", + "LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.", + "LabelEnableHttps": "Report https as external address", + "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.", + "LabelHttpsPort": "Local https port number:", + "LabelHttpsPortHelp": "The tcp port number that Media Browser's https server should bind to.", "LabelWebSocketPortNumber": "Web socker port nummer:", "LabelEnableAutomaticPortMap": "Aktiver automatisk port mapping", "LabelEnableAutomaticPortMapHelp": "Fors\u00f8k automatisk mapping av den offentlige port til den lokale port via UPnP. Dette kan fungerer d\u00e5rlig med noen ruter modeller.", - "LabelExternalDDNS": "Ekstern DDNS:", - "LabelExternalDDNSHelp": "Hvis du har en dynamisk DNS, skriv den her. Media Browser applikasjoner vil bruke denne n\u00e5r ekstern forbindelse opprettes.", + "LabelExternalDDNS": "External WAN Address:", + "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely. Leave empty for automatic detection.", "TabResume": "Forsette", "TabWeather": "V\u00e6r", "TitleAppSettings": "App Innstillinger", @@ -575,6 +607,7 @@ "ButtonRestart": "Restart", "ButtonShutdown": "Sl\u00e5 Av", "ButtonUpdateNow": "Oppdater N\u00e5", + "TabHosting": "Hosting", "PleaseUpdateManually": "Vennligst sl\u00e5 av serveren og oppdater manuelt.", "NewServerVersionAvailable": "En ny versjon av Media Browser er tilgjengelig!", "ServerUpToDate": "Media Browser Server er oppdatert", @@ -636,6 +669,7 @@ "NotificationOptionInstallationFailed": "Installasjon feilet", "NotificationOptionNewLibraryContent": "Nytt innhold er lagt til", "NotificationOptionNewLibraryContentMultiple": "Nytt innhold lagt til (flere)", + "NotificationOptionCameraImageUploaded": "Camera image uploaded", "SendNotificationHelp": "Som standard blir varslinger sent til dashbord innboksen. Bla igjennom programtillegg katalogen for \u00e5 installere valgfrie varslings-alternativer.", "NotificationOptionServerRestartRequired": "Server omstart beh\u00f8ves", "LabelNotificationEnabled": "Sl\u00e5 p\u00e5 denne varslingen", @@ -853,6 +887,8 @@ "OptionDefaultSort": "Standard", "OptionCommunityMostWatchedSort": "Mest Sett", "TabNextUp": "Neste", + "HeaderBecomeMediaBrowserSupporter": "Become a Media Browser Supporter", + "TextEnjoyBonusFeatures": "Enjoy Bonus Features", "MessageNoMovieSuggestionsAvailable": "Ingen film forslag er forel\u00f8pig tilgjengelig. Start med \u00e5 se og ranger filmer. Kom deretter tilbake for \u00e5 f\u00e5 forslag p\u00e5 anbefalinger.", "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.", "MessageNoPlaylistsAvailable": "Spillelister tillater deg \u00e5 lage lister over innhold til \u00e5 spille etter hverandre p\u00e5 en gang. For \u00e5 legge til elementer i spillelister, h\u00f8yreklikk eller trykk og hold, og velg Legg til i spilleliste.", @@ -869,7 +905,6 @@ "LabelChannelDownloadAge": "Slett innhold etter: (dager)", "LabelChannelDownloadAgeHelp": "Nedlastet innhold eldre enn dette vil bli slettet. Det vil v\u00e6re avspillbart via internett streaming.", "ChannelSettingsFormHelp": "Installer kanaler som eksempel Trailers og Vimeo i programtillegg katalogen.", - "LabelSelectCollection": "Velg samling:", "ButtonOptions": "Alternativer", "ViewTypeMovies": "Filmer", "ViewTypeTvShows": "TV", @@ -917,7 +952,7 @@ "OptionLatestTvRecordings": "Siste opptak", "LabelProtocolInfo": "Protokoll info:", "LabelProtocolInfoHelp": "Verdien som blir brukt for \u00e5 gi respons til GetProtocolInfo foresp\u00f8rsler fra enheten.", - "TabKodiMetadata": "Kodi", + "TabNfo": "Nfo", "HeaderKodiMetadataHelp": "Media Browser inkluderer innebygd st\u00f8tte for Kodi Nfo metadata og bilder. For \u00e5 aktivere eller deaktivere Kodi metadata, bruker du fanen Avansert for \u00e5 konfigurere alternativer for medietyper.", "LabelKodiMetadataUser": "Synk bruker sett data til nfo'er for:", "LabelKodiMetadataUserHelp": "Aktiver dette for \u00e5 holde sett data i synk mellom Media Browser og Kodi.", @@ -931,6 +966,7 @@ "LabelGroupChannelsIntoViews": "Via f\u00f8lgende kanaler direkte gjennom Mitt Syn:", "LabelGroupChannelsIntoViewsHelp": "Hvis sl\u00e5tt p\u00e5 vil disse kanalene bli vist direkte sammen med andre visninger. Hvis avsl\u00e5tt, vil de bli vist sammen med separerte Kanaler visning.", "LabelDisplayCollectionsView": "Vis en samling for \u00e5 vise film samlinger", + "LabelDisplayCollectionsViewHelp": "This will create a separate view to display collections that you've created or have access to. To create a collection, right-click or tap-hold any movie and select 'Add to Collection'. ", "LabelKodiMetadataEnableExtraThumbs": "kopier extrafanart inn til extrathumbs", "LabelKodiMetadataEnableExtraThumbsHelp": "Ved nedlasting av bilder kan de bli lagret inn til b\u00e5de extrafanart og extrathumbs for maksimum Kodi skin kompabilitet.", "TabServices": "Tjenester", @@ -1084,11 +1120,14 @@ "LabelDisplayFoldersView": "Vis alle mapper som rene lagringsmapper", "ViewTypeLiveTvRecordingGroups": "Opptak", "ViewTypeLiveTvChannels": "Kanaler", - "LabelAllowLocalAccessWithoutPassword": "Tillat lokal tilkobling uten passord", - "LabelAllowLocalAccessWithoutPasswordHelp": "N\u00e5r aktivert, vil ikke ett passord v\u00e6re p\u00e5krevd for innlogging fra ditt lokale hjemme nettverk.", + "LabelEasyPinCode": "Easy pin code:", + "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Media Browser apps, and can also be used for easy in-network sign in.", + "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", + "LabelInNetworkSignInWithEasyPasswordHelp": "If enabled, you'll be able to use your easy pin code to sign in to Media Browser apps from inside your home network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", "HeaderPassword": "Passord", "HeaderLocalAccess": "Lokal Tilkobling", "HeaderViewOrder": "Visnings rekkef\u00f8lge", + "ButtonResetEasyPassword": "Reset easy pin code", "LabelSelectUserViewOrder": "Velg rekkef\u00f8lge dine visninger vil bli vist inn i Media Browser apps", "LabelMetadataRefreshMode": "Metadata oppfrisknings modus:", "LabelImageRefreshMode": "Bilde oppfrisknings modus:", @@ -1279,7 +1318,7 @@ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.", "HeaderNewUsers": "Nye Brukere", "ButtonSignUp": "Registrering", - "ButtonForgotPassword": "Glemt passord?", + "ButtonForgotPassword": "Forgot password", "OptionDisableUserPreferences": "Deaktiver tillgang til bruker preferanser", "OptionDisableUserPreferencesHelp": "Hvis ativert, vil kun administratorer kunne konfigurere bruker profil bilder, passord og spr\u00e5k preferanser.", "HeaderSelectServer": "Velg Server", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/nl.json b/MediaBrowser.Server.Implementations/Localization/Server/nl.json index fc65c6a82..9912a31dc 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/nl.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/nl.json @@ -27,7 +27,7 @@ "AWindowsServiceHasBeenInstalled": "Er is een Windows service ge\u00efnstalleerd.", "WindowsServiceIntro1": "Media Browser Server werkt normaal als een desktop applicatie met een pictogram in het systeemvak, maar wanneer u het liever op de achtergrond als service laat draaien, dan kan dit worden ingesteld vanuit het Windows services configuratie scherm.", "WindowsServiceIntro2": "Wanneer u de Windows-service gebruikt, dan dient u er rekening mee te houden dat het niet op hetzelfde moment als de desktop applicatie kan worden uitgevoerd. Het is daarom vereist de desktop applicatie eerst af te sluiten voordat u de service gebruikt. De service moet worden geconfigureerd met beheerdersrechten via het configuratie scherm. Houd er rekening mee dat op dit moment de service niet automatisch kan worden bijgewerkt, zodat nieuwe versies dus handmatige interactie vereisen.", - "WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click <b>Finish<\/b> to view the <b>Server Dashboard<\/b>.", + "WizardCompleted": "Dat is alles wat we nu nodig hebben. Media Browser is begonnen met verzamelen van informatie over uw media bibliotheek. Probeer eens wat van onze apps en klik dan <b>Voltooien<\/b> om het <b>Server Dashboard<\/b> te bekijken.", "LabelConfigureSettings": "Configureer instellingen", "LabelEnableVideoImageExtraction": "Videobeeld uitpakken inschakelen", "VideoImageExtractionHelp": "Voor video's die nog geen afbeeldingen hebben, en waarvoor geen afbeeldingen op Internet te vinden zijn. Dit voegt extra tijd toe aan de oorspronkelijke bibliotheek scan, maar resulteert in een mooiere weergave.", @@ -40,12 +40,32 @@ "OptionIAcceptTermsOfService": "Ik accepteer de voorwaarden", "ButtonPrivacyPolicy": "Privacybeleid", "ButtonTermsOfService": "Service voorwaarden", + "HeaderDeveloperOptions": "Ontwikkelaar Opties", + "OptionEnableWebClientResponseCache": "Web cli\u00ebnt reactie caching inschakelen", + "OptionDisableForDevelopmentHelp": "Configureer deze zo nodig voor web cli\u00ebnt ontwikkelingsdoeleinden.", + "OptionEnableWebClientResourceMinification": "Web cli\u00ebnt bron verkleining inschakelen", + "LabelDashboardSourcePath": "Web client bron pad:", + "LabelDashboardSourcePathHelp": "Wanneer U de server draait vanaf de bron, geeft u het pad naar de map dashboard-ui op. Alle web cli\u00ebnt bestanden worden geladen vanaf deze locatie.", + "ButtonConvertMedia": "Converteer media", + "ButtonOrganize": "Organiseren", "ButtonOk": "Ok", "ButtonCancel": "Annuleren", "ButtonNew": "Nieuw", "HeaderTV": "TV", "HeaderAudio": "Audio", "HeaderVideo": "Video", + "HeaderPaths": "Paden", + "CategorySync": "Sync", + "HeaderEasyPinCode": "Easy Pin Code", + "RegisterWithPayPal": "Registreer met PayPal", + "HeaderSyncRequiresSupporterMembership": "Sync Vereist een Supporter lidmaatschap", + "HeaderEnjoyDayTrial": "Geniet van een 14-daagse gratis proefversie", + "LabelSyncTempPath": "Pad voor tijdelijke bestanden:", + "LabelSyncTempPathHelp": "Geef een afwijkende sync werk directory op. Tijdens het sync proces aangemaakte geconverteerde media zal hier opgeslagen worden.", + "LabelCustomCertificatePath": "Aangepast certificaat pad:", + "LabelCustomCertificatePathHelp": "Gebruik uw eigen ssl certificaat. Indien weggelaten zal de server een zelf-ondertekend certificaat aanmaken.", + "TitleNotifications": "Meldingen", + "ButtonDonateWithPayPal": "Doneer met PayPal", "OptionDetectArchiveFilesAsMedia": "Herken archief bestanden als media", "OptionDetectArchiveFilesAsMediaHelp": "Indien ingeschakeld zullen bestanden met .rar en .zip extensies herkend worden als media bestanden.", "LabelEnterConnectUserName": "Gebruikersnaam of e-mail:", @@ -63,12 +83,14 @@ "FolderTypeTvShows": "TV", "FolderTypeInherit": "overerven", "LabelContentType": "Inhoud type:", + "TitleScheduledTasks": "Geplande Taken", "HeaderSetupLibrary": "Stel uw mediabibliotheek in", "ButtonAddMediaFolder": "Mediamap toevoegen", "LabelFolderType": "Maptype:", "ReferToMediaLibraryWiki": "Raadpleeg de mediabibliotheek wiki.", "LabelCountry": "Land:", "LabelLanguage": "Taal:", + "ButtonJoinTheDevelopmentTeam": "Word lid van het Ontwikkel Team", "HeaderPreferredMetadataLanguage": "Gewenste metadata taal:", "LabelSaveLocalMetadata": "Sla afbeeldingen en metadata op in de mediamappen", "LabelSaveLocalMetadataHelp": "Door afbeeldingen en metadata op te slaan in de mediamappen kunnen ze makkelijker worden gevonden en bewerkt.", @@ -86,6 +108,8 @@ "TabCollectionTitles": "Titels", "HeaderDeviceAccess": "Apparaat Toegang", "OptionEnableAccessFromAllDevices": "Toegang vanaf alle apparaten toestaan", + "OptionEnableAccessToAllChannels": "Toegang tot alle kanalen inschakelen", + "OptionEnableAccessToAllLibraries": "Toegang tot alle bibliotheken inschakelen", "DeviceAccessHelp": "Dit geldt alleen voor apparaten die uniek ge\u00efdentificeerd kunnen worden en voorkomen niet toegang via een webbrowser. Filteren van apparaat toegang voor gebruikers voorkomt dat zij nieuwe apparaten gebruiken totdat deze hier zijn goedgekeurd.", "LabelDisplayMissingEpisodesWithinSeasons": "Toon ontbrekende afleveringen binnen een seizoen", "LabelUnairedMissingEpisodesWithinSeasons": "Toon komende afleveringen binnen een seizoen", @@ -275,7 +299,7 @@ "OptionMetascore": "Metascore", "ButtonSelect": "Selecteer", "ButtonGroupVersions": "Groepeer Versies", - "ButtonAddToCollection": "Toevoegen aan verzameling", + "ButtonAddToCollection": "Voeg toe aan Collectie", "PismoMessage": "Pismo File Mount (met een geschonken licentie).", "TangibleSoftwareMessage": "Gebruik makend van concrete oplossingen als Java \/ C converters door een geschonken licentie.", "HeaderCredits": "Credits", @@ -299,7 +323,7 @@ "LabelCachePath": "Cache pad:", "LabelCachePathHelp": "Deze locatie bevat server cache-bestanden, zoals afbeeldingen.", "LabelImagesByNamePath": "Afbeeldingen op naam pad:", - "LabelImagesByNamePathHelp": "Deze locatie bevat afbeeldingen van: acteurs, artiesten, genres en studio's.", + "LabelImagesByNamePathHelp": "Geef een locatie op voor gedownloade afbeeldingen van acteurs, genre en studio.", "LabelMetadataPath": "Metadata pad:", "LabelMetadataPathHelp": "Geef een aangepaste locatie op voor gedownloade afbeeldingen en metadata, indien niet opgeslagen in mediamappen.", "LabelTranscodingTempPath": "Tijdelijk Transcodeer pad:", @@ -314,12 +338,14 @@ "OptionEpisodes": "Afleveringen", "OptionOtherVideos": "Overige Video's", "TitleMetadata": "Metadata", - "LabelAutomaticUpdatesFanart": "Schakel de automatische update in van FanArt.tv", + "LabelAutomaticUpdates": "Automatische updates inschakelen", "LabelAutomaticUpdatesTmdb": "Schakel de automatische update in van TheMovieDB.org", "LabelAutomaticUpdatesTvdb": "Schakel de automatische update in van TheTVDB.com", "LabelAutomaticUpdatesFanartHelp": "Indien ingeschakeld, worden nieuwe afbeeldingen automatisch gedownload wanneer ze zijn toegevoegd aan fanart.tv. Bestaande afbeeldingen zullen niet worden vervangen.", "LabelAutomaticUpdatesTmdbHelp": "Indien ingeschakeld, worden nieuwe afbeeldingen automatisch gedownload wanneer ze zijn toegevoegd aan TheMovieDB.org. Bestaande afbeeldingen zullen niet worden vervangen.", "LabelAutomaticUpdatesTvdbHelp": "Indien ingeschakeld, worden nieuwe afbeeldingen automatisch gedownload wanneer ze zijn toegevoegd aan TheTVDB.com. Bestaande afbeeldingen zullen niet worden vervangen.", + "LabelFanartApiKey": "Persoonlijke api sleutel:", + "LabelFanartApiKeyHelp": "Verzoeken om fanart zonder een persoonlijke API sleutel geven resultaten terug die meer dan 7 dagen geleden goedgekeurd zijn. Een persoonlijke API sleutel brengt dat terug tot 48 uur en als u ook een fanart VIP lid bent wordt dit tot 10 minuten teruggebracht.", "ExtractChapterImagesHelp": "Uitpakken van hoofdstuk afbeeldingen geeft de cli\u00ebnt de mogelijkheid om grafische scene selectie menu's te tonen. Het proces kan traag en cpu-intensief zijn en kan enkele gigabytes aan ruimte vereisen. Het word uitgevoerd als nachtelijke taak om 4:00. Deze taak is in te stellen via de geplande taken. Het wordt niet aanbevolen om deze taak uit te voeren tijdens de piekuren.", "LabelMetadataDownloadLanguage": "Voorkeurs taal:", "ButtonAutoScroll": "Auto-scroll", @@ -487,6 +513,7 @@ "HeaderSystemPaths": "Systeem Paden", "LinkCommunity": "Gemeenschap", "LinkGithub": "Github", + "LinkApi": "Api", "LinkApiDocumentation": "Api Documentatie", "LabelFriendlyServerName": "Aangepaste servernaam", "LabelFriendlyServerNameHelp": "Deze naam wordt gebruikt om deze server te identificeren. Indien leeg gelaten, zal de naam van de computer worden gebruikt.", @@ -494,20 +521,25 @@ "LabelPreferredDisplayLanguageHelp": "Het vertalen van Media Browser is een doorlopend project en is nog niet voltooid.", "LabelReadHowYouCanContribute": "Lees meer over hoe u kunt bijdragen.", "HeaderNewCollection": "Nieuwe Verzamling", - "HeaderAddToCollection": "Toevoegen aan verzameling", "ButtonSubmit": "Uitvoeren", - "NewCollectionNameExample": "Voorbeeld: Star Wars Collectie", - "OptionSearchForInternetMetadata": "Zoeken op het internet voor afbeeldingen en metadata", "ButtonCreate": "Cre\u00ebren", - "LabelLocalHttpServerPortNumber": "Lokaal poort nummer:", + "LabelCustomCss": "Aangepaste css:", + "LabelCustomCssHelp": "Uw eigen aangepaste css voor de web-interface toepassen.", + "LabelLocalHttpServerPortNumber": "Lokale http poort nummer:", "LabelLocalHttpServerPortNumberHelp": "De TCP poort waarop de Media Browser Server beschikbaar is.", - "LabelPublicPort": "Publieke poort nummer:", - "LabelPublicPortHelp": "Het poortnummer op het internet waarop Media Browser beschikbaar is.", + "LabelPublicHttpPort": "Publieke http poort nummer:", + "LabelPublicHttpPortHelp": "Het publieke poortnummer dat moet worden toegewezen aan de lokale http poort.", + "LabelPublicHttpsPort": "Publieke https poort nummer:", + "LabelPublicHttpsPortHelp": "Het publieke poortnummer dat moet worden toegewezen aan de lokale https poort.", + "LabelEnableHttps": "Rapporteer https als extern adres", + "LabelEnableHttpsHelp": "Indien ingeschakeld, zal de server een https url rapporteren aan de cli\u00ebnt als het externe adres. Dit kan cli\u00ebnten die nog geen ondersteuning voor https hebben onbruikbaar maken.", + "LabelHttpsPort": "Lokale https poort nummer:", + "LabelHttpsPortHelp": "Het TCP-poortnummer waar Media Browser https server zich aan moet binden.", "LabelWebSocketPortNumber": "Web socket poortnummer:", "LabelEnableAutomaticPortMap": "Schakel automatisch poort vertalen in", "LabelEnableAutomaticPortMapHelp": "Probeer om de publieke poort automatisch te vertalen naar de lokale poort via UPnP. Dit werk niet op alle routers.", - "LabelExternalDDNS": "Externe DDNS:", - "LabelExternalDDNSHelp": "Als u een dynamische DNS heeft kun u die hier invoeren. Media Browser apps zullen het gebruiken om op afstand verbinding te maken.", + "LabelExternalDDNS": "Extern WAN Adres:", + "LabelExternalDDNSHelp": "Wanneer u een dynamische DNS heeft voer het dan hier in. Media Browser apps zullen het gebruiken bij het op afstand aansluiten. Laat leeg voor automatische detectie.", "TabResume": "Hervatten", "TabWeather": "Weer", "TitleAppSettings": "App Instellingen", @@ -575,6 +607,7 @@ "ButtonRestart": "Herstart", "ButtonShutdown": "Afsluiten", "ButtonUpdateNow": "Nu bijwerken", + "TabHosting": "Hosting", "PleaseUpdateManually": "Sluit de server a.u.b. af en werk handmatig bij.", "NewServerVersionAvailable": "Er is een nieuwe versie van Media Browser Server beschikbaar!", "ServerUpToDate": "Media Browser Server is up-to-date", @@ -587,7 +620,7 @@ "LabelOldSupporterKey": "Oude supporter sleutel", "LabelNewSupporterKey": "Nieuwe supporter sleutel", "HeaderMultipleKeyLinking": "Verplaats naar nieuwe sleutel", - "MultipleKeyLinkingHelp": "Als je een nieuwe supportersleutel ontvangen hebt, gebruik dan dit formulier om de registratie van de oude sleutel over te zetten naar de nieuwe sleutel.", + "MultipleKeyLinkingHelp": "Als u een nieuwe supportersleutel ontvangen hebt, gebruik dan dit formulier om de registratie van de oude sleutel over te zetten naar de nieuwe sleutel.", "LabelCurrentEmailAddress": "Huidige e-mailadres", "LabelCurrentEmailAddressHelp": "De huidige e-mailadres waar uw nieuwe sleutel naar is verzonden.", "HeaderForgotKey": "Sleutel vergeten", @@ -636,6 +669,7 @@ "NotificationOptionInstallationFailed": "Mislukken van de installatie", "NotificationOptionNewLibraryContent": "Nieuwe content toegevoegd", "NotificationOptionNewLibraryContentMultiple": "Nieuwe content toegevoegd (meerdere)", + "NotificationOptionCameraImageUploaded": "Camera afbeelding ge\u00fcpload", "SendNotificationHelp": "Meldingen worden geplaatst in de inbox op het dashboard. Blader door de Plug-in catalogus om aanvullende opties voor meldingen te installeren.", "NotificationOptionServerRestartRequired": "Server herstart nodig", "LabelNotificationEnabled": "Deze melding inschakelen", @@ -829,8 +863,8 @@ "OptionAuto": "Auto", "OptionYes": "Ja", "OptionNo": "Nee", - "HeaderOptions": "Options", - "HeaderIdentificationResult": "Identification Result", + "HeaderOptions": "Opties", + "HeaderIdentificationResult": "Identificatie Resultaat", "LabelHomePageSection1": "Startpagina sectie 1:", "LabelHomePageSection2": "Startpagina sectie 2:", "LabelHomePageSection3": "Startpagina sectie 3:", @@ -853,9 +887,11 @@ "OptionDefaultSort": "Standaard", "OptionCommunityMostWatchedSort": "Meest bekeken", "TabNextUp": "Volgend", + "HeaderBecomeMediaBrowserSupporter": "Word een Media Browser Supporter", + "TextEnjoyBonusFeatures": "Enjoy Bonus Features", "MessageNoMovieSuggestionsAvailable": "Er zijn momenteel geen film suggesties beschikbaar. Begin met het bekijken en waardeer uw films, kom daarna terug om uw aanbevelingen te bekijken.", - "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.", - "MessageNoPlaylistsAvailable": "Met afspeellijsten kan je een lijst maken waarvan de items achter elkaar afgespeeld worden. Om een item toe te voegen klik je met rechts of tik en hou je het vast om het te selecteren, klik vervolgens op Toevoegen aan afspeellijst.", + "MessageNoCollectionsAvailable": "Collecties maken het u mogelijk om Films, Series, Albums, Boeken en Games te groeperen. Klik op de + knop om Collecties aan te maken.", + "MessageNoPlaylistsAvailable": "Met afspeellijsten kunt u een lijst maken waarvan de items achter elkaar afgespeeld worden. Om een item toe te voegen klikt u met rechts of tik en houd het vast om het te selecteren, klik vervolgens op Toevoegen aan afspeellijst.", "MessageNoPlaylistItemsAvailable": "De afspeellijst is momenteel leeg.", "ButtonDismiss": "Afwijzen", "ButtonEditOtherUserPreferences": "Wijzig het gebruikersprofiel, wachtwoord en persoonlijke voorkeuren voor deze gebruiker.", @@ -869,7 +905,6 @@ "LabelChannelDownloadAge": "Verwijder inhoud na: (dagen)", "LabelChannelDownloadAgeHelp": "Gedownloade inhoud die ouder is zal worden verwijderd. Afspelen via internet streaming blijft mogelijk.", "ChannelSettingsFormHelp": "Installeer kanalen zoals Trailers en Vimeo in de Plug-in catalogus.", - "LabelSelectCollection": "Selecteer verzameling:", "ButtonOptions": "Opties", "ViewTypeMovies": "Films", "ViewTypeTvShows": "TV", @@ -917,20 +952,21 @@ "OptionLatestTvRecordings": "Nieuwste opnames", "LabelProtocolInfo": "Protocol info:", "LabelProtocolInfoHelp": "De waarde die wordt gebruikt bij het reageren op GetProtocolInfo verzoeken van het apparaat.", - "TabKodiMetadata": "Kodi", + "TabNfo": "Nfo", "HeaderKodiMetadataHelp": "Media Browser heeft standaard ondersteuning voor Kodi NFO metadata en afbeeldingen. Om Kodi metadata aan of uit te zetten gebruikt u het tabblad Geavanceerd om opties voor uw mediatypen te configureren.", "LabelKodiMetadataUser": "Synchroniseer gekeken informatie toe aan NFO's voor (gebruiker):", "LabelKodiMetadataUserHelp": "Schakel in om gekeken informatie tussen Media Browser en Kodi te synchroniseren.", "LabelKodiMetadataDateFormat": "Uitgave datum formaat:", "LabelKodiMetadataDateFormatHelp": "Alle datums in NFO's zullen gelezen en geschreven worden met dit formaat.", "LabelKodiMetadataSaveImagePaths": "Bewaar afbeeldingspaden in NFO-bestanden", - "LabelKodiMetadataSaveImagePathsHelp": "Dit wordt aanbevolen als je bestandsnamen hebt die niet voldoen aan Kodi richtlijnen.", + "LabelKodiMetadataSaveImagePathsHelp": "Dit wordt aanbevolen als u bestandsnamen hebt die niet voldoen aan Kodi richtlijnen.", "LabelKodiMetadataEnablePathSubstitution": "Pad vervanging inschakelen", "LabelKodiMetadataEnablePathSubstitutionHelp": "Stelt pad vervanging in voor afbeeldingspaden en maakt gebruik van de Pad Vervangen instellingen van de server.", "LabelKodiMetadataEnablePathSubstitutionHelp2": "Bekijk pad vervanging.", "LabelGroupChannelsIntoViews": "Toon de volgende kanalen binnen mijn overzichten:", "LabelGroupChannelsIntoViewsHelp": "Indien ingeschakeld, zullen deze kanalen direct naast andere overzichten worden weergegeven. Indien uitgeschakeld, zullen ze worden weergegeven in een aparte kanalen overzicht.", "LabelDisplayCollectionsView": "Toon verzamelingen in mijn overzichten om film verzamelingen weer te geven", + "LabelDisplayCollectionsViewHelp": "Hiermee wordt een aparte weergave gemaakt waarin collecties worden weergegeven die u hebt aangemaakt of toegang toe hebt. Klik rechts op een film of druk en houd vast en kies 'Voeg toe aan Collectie'. ", "LabelKodiMetadataEnableExtraThumbs": "Kopieer extrafanart naar extrathumbs", "LabelKodiMetadataEnableExtraThumbsHelp": "Als er afbeeldingen gedownload worden kunnen deze direct in extrafanart en extrathumbs opgeslagen worden voor maximale Kodi skin compatibiliteit.", "TabServices": "Meta Diensten", @@ -1084,11 +1120,14 @@ "LabelDisplayFoldersView": "Toon een mappenweergave als u gewoon Mediamappen wilt weergeven", "ViewTypeLiveTvRecordingGroups": "Opnamen", "ViewTypeLiveTvChannels": "Kanalen", - "LabelAllowLocalAccessWithoutPassword": "Lokale toegang toestaan zonder wachtwoord", - "LabelAllowLocalAccessWithoutPasswordHelp": "Als dit ingeschakeld is dan kan er in het thuisnetwerk zonder wachtwoord aangemeld worden.", + "LabelEasyPinCode": "Easy pin code:", + "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Media Browser apps, and can also be used for easy in-network sign in.", + "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", + "LabelInNetworkSignInWithEasyPasswordHelp": "If enabled, you'll be able to use your easy pin code to sign in to Media Browser apps from inside your home network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", "HeaderPassword": "Wachtwoord", "HeaderLocalAccess": "Lokale toegang", "HeaderViewOrder": "Weergave volgorde", + "ButtonResetEasyPassword": "Reset easy pin code", "LabelSelectUserViewOrder": "Kies de volgorde van uw weergaven die zullen worden weergegeven in Media Browser applicaties", "LabelMetadataRefreshMode": "Metadata vernieuw mode:", "LabelImageRefreshMode": "Afbeelding vernieuw mode:", @@ -1154,7 +1193,7 @@ "TabDonate": "Doneer", "HeaderDonationType": "Donatie soort:", "OptionMakeOneTimeDonation": "Doe een aparte donatie", - "OptionOneTimeDescription": "Dit is een extra donatie voor het team om te laten zien dat je ze steunt. Het geeft geen extra voordelen en geeft je geen supporter sleutel.", + "OptionOneTimeDescription": "Dit is een extra donatie voor het team om te laten zien dat u hen steunt. Het geeft geen extra voordelen en geeft u geen supporter sleutel.", "OptionLifeTimeSupporterMembership": "Levenslang supporter lidmaatschap", "OptionYearlySupporterMembership": "Jaarlijkse supporter lidmaatschap", "OptionMonthlySupporterMembership": "maandelijks supporter lidmaatschap", @@ -1162,7 +1201,7 @@ "OptionNoThemeSong": "Geen thema muziek", "OptionNoThemeVideo": "Geen thema film", "LabelOneTimeDonationAmount": "Donatie bedrag:", - "ButtonDonate": "Donate", + "ButtonDonate": "Doneren", "OptionActor": "Acteur", "OptionComposer": "Componist", "OptionDirector": "Regiseur", @@ -1182,7 +1221,7 @@ "HeaderDeveloperInfo": "Informatie ontwikkelaar", "HeaderRevisionHistory": "Versie geschiedenis", "ButtonViewWebsite": "Bekijk website", - "LabelRecurringDonationCanBeCancelledHelp": "Terugkerende donaties kunnen op elk moment stop gezet worden in je PayPal account.", + "LabelRecurringDonationCanBeCancelledHelp": "Terugkerende donaties kunnen op elk moment stop gezet worden in uw PayPal account.", "HeaderXmlSettings": "Xml Instellingen", "HeaderXmlDocumentAttributes": "Xml Document Attributen", "HeaderXmlDocumentAttribute": "Xml Document Attribuut", @@ -1216,7 +1255,7 @@ "TabCinemaMode": "Cinema mode", "TitlePlayback": "Afspelen", "LabelEnableCinemaModeFor": "Schakel cinema mode in voor:", - "CinemaModeConfigurationHelp": "Cinema mode brengt de theater ervaring naar je woonkamer met de mogelijkheid om trailers en eigen intro's voor de film af te spelen", + "CinemaModeConfigurationHelp": "Cinema mode brengt de theater ervaring naar uw woonkamer met de mogelijkheid om trailers en eigen intro's voor de film af te spelen", "OptionTrailersFromMyMovies": "Voeg trailers van films uit mijn bibliotheek toe", "OptionUpcomingMoviesInTheaters": "Voeg trailers van nieuwe en verwachte films toe", "LabelLimitIntrosToUnwatchedContent": "Gebruik alleen trailers van films die nog niet gekeken zijn", @@ -1243,8 +1282,8 @@ "TitleDevices": "Apparaten", "TabCameraUpload": "Camera upload", "TabDevices": "Apparaten", - "HeaderCameraUploadHelp": "Upload automatisch foto's en video's van je mobiele apparaten naar Media Browser.", - "MessageNoDevicesSupportCameraUpload": "Je hebt op dit moment geen apparaten die camera upload ondersteunen.", + "HeaderCameraUploadHelp": "Upload automatisch foto's en video's van uw mobiele apparaten naar Media Browser.", + "MessageNoDevicesSupportCameraUpload": "U hebt op dit moment geen apparaten die camera upload ondersteunen.", "LabelCameraUploadPath": "Camera upload pad:", "LabelCameraUploadPathHelp": "Geef een eigen upload pad op, indien gewenst. Deze map moet ook aan de bibliotheek instellingen toegevoegd worden. Als er niets opgegeven is wordt de standaard map gebruikt.", "LabelCreateCameraUploadSubfolder": "Maak een submap voor elk apparaat", @@ -1252,8 +1291,8 @@ "LabelCustomDeviceDisplayName": "Weergave naam:", "LabelCustomDeviceDisplayNameHelp": "Geef een eigen weergave naam op of laat deze leeg om de naam te gebruiken die het apparaat opgeeft.", "HeaderInviteUser": "Nodig gebruiker uit", - "LabelConnectGuestUserNameHelp": "Dit is de gebruikersnaam die je vriend(in) gebruikt om aan te melden op de Media Browser website of zijn of haar email adres.", - "HeaderInviteUserHelp": "Je media met vrienden delen is makkelijker dan ooit met Media Browser Connect.", + "LabelConnectGuestUserNameHelp": "Dit is de gebruikersnaam die uw vriend(in) gebruikt om zich aan te melden op de Media Browser website of zijn of haar email adres.", + "HeaderInviteUserHelp": "Uw media met vrienden delen is makkelijker dan ooit met Media Browser Connect.", "ButtonSendInvitation": "Stuur uitnodiging", "HeaderSignInWithConnect": "Meld aan met Media Browser Connect", "HeaderGuests": "Gasten", @@ -1271,7 +1310,7 @@ "OptionWeekdays": "Week dagen", "OptionWeekends": "Weekend", "MessageProfileInfoSynced": "Gebruikersprofiel informatie is gesynchroniseerd met Media Browser Connect.", - "HeaderOptionalLinkMediaBrowserAccount": "Optioneel: Koppel je Media Browser account", + "HeaderOptionalLinkMediaBrowserAccount": "Optioneel: Koppel uw Media Browser account", "ButtonTrailerReel": "Trailer reel", "HeaderTrailerReel": "Trailer reel", "OptionPlayUnwatchedTrailersOnly": "Speel alleen ongeziene trailers", @@ -1279,11 +1318,11 @@ "MessageNoTrailersFound": "Geen trailers gevonden. Installeer het Trailers kanaal en verbeter uw film ervaring door middel van een bibliotheek met internet trailers.", "HeaderNewUsers": "Nieuwe gebruikers", "ButtonSignUp": "Aanmelden", - "ButtonForgotPassword": "Wachtwoord vergeten?", + "ButtonForgotPassword": "Wachtwoord vergeten", "OptionDisableUserPreferences": "Voorkom toegang tot gebruikers voorkeuren", "OptionDisableUserPreferencesHelp": "Indien ingeschakeld kunnen alleen beheerders profiel afbeeldingen, wachtwoorden en taalinstellingen wijzigen.", "HeaderSelectServer": "Selecteer server", - "MessageNoServersAvailableToConnect": "Er zijn geen servers beschikbaar om mee te verbinden. Als je uitgenodigd bent om een server te delen accepteer dit hieronder of door op de link in het emailbericht te klikken.", + "MessageNoServersAvailableToConnect": "Er zijn geen servers beschikbaar om mee te verbinden. Als u uitgenodigd bent om een server te delen accepteer dit hieronder of door op de link in het emailbericht te klikken.", "TitleNewUser": "Nieuwe gebruiker", "ButtonConfigurePassword": "Configureer wachtwoord", "HeaderDashboardUserPassword": "Wachtwoorden van gebruikers worden door de gebruiker in het gebruikersprofiel beheerd.", @@ -1294,7 +1333,7 @@ "HeaderShareMediaFolders": "Deel media mappen", "MessageGuestSharingPermissionsHelp": "De meeste features zijn niet direct beschikbaar voor gasten maar kunnen aangezet worden waar gewenst.", "HeaderInvitations": "Uitnodigingen", - "LabelForgotPasswordUsernameHelp": "Vul je gebruikersnaam in, als je deze weet.", + "LabelForgotPasswordUsernameHelp": "Vul uw gebruikersnaam in, als u deze weet.", "HeaderForgotPassword": "Wachtwoord vergeten", "TitleForgotPassword": "Wachtwoord vergeten", "TitlePasswordReset": "Wachtwoord resetten", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/pl.json b/MediaBrowser.Server.Implementations/Localization/Server/pl.json index 770746e92..42af12177 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/pl.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/pl.json @@ -40,12 +40,32 @@ "OptionIAcceptTermsOfService": "I accept the terms of service", "ButtonPrivacyPolicy": "Privacy policy", "ButtonTermsOfService": "Terms of Service", + "HeaderDeveloperOptions": "Developer Options", + "OptionEnableWebClientResponseCache": "Enable web client response caching", + "OptionDisableForDevelopmentHelp": "Configure these as needed for web client development purposes.", + "OptionEnableWebClientResourceMinification": "Enable web client resource minification", + "LabelDashboardSourcePath": "Web client source path:", + "LabelDashboardSourcePathHelp": "If running the server from source, specify the path to the dashboard-ui folder. All web client files will be served from this location.", + "ButtonConvertMedia": "Convert media", + "ButtonOrganize": "Organize", "ButtonOk": "Ok", "ButtonCancel": "Anuluj", "ButtonNew": "New", "HeaderTV": "TV", "HeaderAudio": "Audio", "HeaderVideo": "Video", + "HeaderPaths": "Paths", + "CategorySync": "Sync", + "HeaderEasyPinCode": "Easy Pin Code", + "RegisterWithPayPal": "Register with PayPal", + "HeaderSyncRequiresSupporterMembership": "Sync Requires a Supporter Membership", + "HeaderEnjoyDayTrial": "Enjoy a 14 Day Free Trial", + "LabelSyncTempPath": "Temporary file path:", + "LabelSyncTempPathHelp": "Specify a custom sync working folder. Converted media created during the sync process will be stored here.", + "LabelCustomCertificatePath": "Custom certificate path:", + "LabelCustomCertificatePathHelp": "Supply your own ssl certificate. If omitted, the server will create a self-signed certificate.", + "TitleNotifications": "Notifications", + "ButtonDonateWithPayPal": "Donate with PayPal", "OptionDetectArchiveFilesAsMedia": "Detect archive files as media", "OptionDetectArchiveFilesAsMediaHelp": "If enabled, files with .rar and .zip extensions will be detected as media files.", "LabelEnterConnectUserName": "User name or email:", @@ -63,12 +83,14 @@ "FolderTypeTvShows": "TV", "FolderTypeInherit": "Inherit", "LabelContentType": "Content type:", + "TitleScheduledTasks": "Scheduled Tasks", "HeaderSetupLibrary": "Ustaw swoj\u0105 bibliotek\u0119", "ButtonAddMediaFolder": "Dodaj folder", "LabelFolderType": "Typ folderu:", "ReferToMediaLibraryWiki": "Odnie\u015b si\u0119 do wiki biblioteki.", "LabelCountry": "Kraj:", "LabelLanguage": "J\u0119zyk:", + "ButtonJoinTheDevelopmentTeam": "Join the Development Team", "HeaderPreferredMetadataLanguage": "Preferowany j\u0119zyk metadanych:", "LabelSaveLocalMetadata": "Save artwork and metadata into media folders", "LabelSaveLocalMetadataHelp": "Saving artwork and metadata directly into media folders will put them in a place where they can be easily edited.", @@ -86,6 +108,8 @@ "TabCollectionTitles": "Titles", "HeaderDeviceAccess": "Device Access", "OptionEnableAccessFromAllDevices": "Enable access from all devices", + "OptionEnableAccessToAllChannels": "Enable access to all channels", + "OptionEnableAccessToAllLibraries": "Enable access to all libraries", "DeviceAccessHelp": "This only applies to devices that can be uniquely identified and will not prevent browser access. Filtering user device access will prevent them from using new devices until they've been approved here.", "LabelDisplayMissingEpisodesWithinSeasons": "Wy\u015bwietl brakuj\u0105ce odcinki w sezonach", "LabelUnairedMissingEpisodesWithinSeasons": "Wy\u015bwietl nie wydanie odcinki w sezonach", @@ -299,7 +323,7 @@ "LabelCachePath": "Cache path:", "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.", "LabelImagesByNamePath": "Images by name path:", - "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, genre and studio images.", "LabelMetadataPath": "Metadata path:", "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.", "LabelTranscodingTempPath": "Transcoding temporary path:", @@ -314,12 +338,14 @@ "OptionEpisodes": "Odcinki", "OptionOtherVideos": "Inne widea", "TitleMetadata": "Metadata", - "LabelAutomaticUpdatesFanart": "Enable automatic updates from FanArt.tv", + "LabelAutomaticUpdates": "Enable automatic updates", "LabelAutomaticUpdatesTmdb": "Enable automatic updates from TheMovieDB.org", "LabelAutomaticUpdatesTvdb": "Enable automatic updates from TheTVDB.com", "LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.", "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.", "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.", + "LabelFanartApiKey": "Personal api key:", + "LabelFanartApiKeyHelp": "Requests to fanart without a personal API key return results that were approved over 7 days ago. With a personal API key that drops to 48 hours and if you are also a fanart VIP member that will further drop to around 10 minutes.", "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", "LabelMetadataDownloadLanguage": "Preferred download language:", "ButtonAutoScroll": "Auto-scroll", @@ -487,6 +513,7 @@ "HeaderSystemPaths": "System Paths", "LinkCommunity": "Community", "LinkGithub": "Github", + "LinkApi": "Api", "LinkApiDocumentation": "Api Documentation", "LabelFriendlyServerName": "Friendly server name:", "LabelFriendlyServerNameHelp": "This name will be used to identify this server. If left blank, the computer name will be used.", @@ -494,20 +521,25 @@ "LabelPreferredDisplayLanguageHelp": "Translating Media Browser is an ongoing project and is not yet complete.", "LabelReadHowYouCanContribute": "Read about how you can contribute.", "HeaderNewCollection": "New Collection", - "HeaderAddToCollection": "Add to Collection", "ButtonSubmit": "Submit", - "NewCollectionNameExample": "Example: Star Wars Collection", - "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata", "ButtonCreate": "Create", - "LabelLocalHttpServerPortNumber": "Local port number:", + "LabelCustomCss": "Custom css:", + "LabelCustomCssHelp": "Apply your own custom css to the web interface.", + "LabelLocalHttpServerPortNumber": "Local http port number:", "LabelLocalHttpServerPortNumberHelp": "The tcp port number that Media Browser's http server should bind to.", - "LabelPublicPort": "Public port number:", - "LabelPublicPortHelp": "The public port number that should be mapped to the local port.", + "LabelPublicHttpPort": "Public http port number:", + "LabelPublicHttpPortHelp": "The public port number that should be mapped to the local http port.", + "LabelPublicHttpsPort": "Public https port number:", + "LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.", + "LabelEnableHttps": "Report https as external address", + "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.", + "LabelHttpsPort": "Local https port number:", + "LabelHttpsPortHelp": "The tcp port number that Media Browser's https server should bind to.", "LabelWebSocketPortNumber": "Web socket port number:", "LabelEnableAutomaticPortMap": "Enable automatic port mapping", "LabelEnableAutomaticPortMapHelp": "Attempt to automatically map the public port to the local port via UPnP. This may not work with some router models.", - "LabelExternalDDNS": "External DDNS:", - "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely.", + "LabelExternalDDNS": "External WAN Address:", + "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely. Leave empty for automatic detection.", "TabResume": "Resume", "TabWeather": "Weather", "TitleAppSettings": "App Settings", @@ -575,6 +607,7 @@ "ButtonRestart": "Restart", "ButtonShutdown": "Shutdown", "ButtonUpdateNow": "Update Now", + "TabHosting": "Hosting", "PleaseUpdateManually": "Please shutdown the server and update manually.", "NewServerVersionAvailable": "A new version of Media Browser Server is available!", "ServerUpToDate": "Media Browser Server is up to date", @@ -636,6 +669,7 @@ "NotificationOptionInstallationFailed": "Installation failure", "NotificationOptionNewLibraryContent": "New content added", "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", + "NotificationOptionCameraImageUploaded": "Camera image uploaded", "SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.", "NotificationOptionServerRestartRequired": "Server restart required", "LabelNotificationEnabled": "Enable this notification", @@ -853,6 +887,8 @@ "OptionDefaultSort": "Default", "OptionCommunityMostWatchedSort": "Most Watched", "TabNextUp": "Next Up", + "HeaderBecomeMediaBrowserSupporter": "Become a Media Browser Supporter", + "TextEnjoyBonusFeatures": "Enjoy Bonus Features", "MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.", "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.", "MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.", @@ -869,7 +905,6 @@ "LabelChannelDownloadAge": "Delete content after: (days)", "LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.", "ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.", - "LabelSelectCollection": "Select collection:", "ButtonOptions": "Options", "ViewTypeMovies": "Movies", "ViewTypeTvShows": "TV", @@ -917,7 +952,7 @@ "OptionLatestTvRecordings": "Latest recordings", "LabelProtocolInfo": "Protocol info:", "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.", - "TabKodiMetadata": "Kodi", + "TabNfo": "Nfo", "HeaderKodiMetadataHelp": "Media Browser includes native support for Kodi Nfo metadata and images. To enable or disable Kodi metadata, use the Advanced tab to configure options for your media types.", "LabelKodiMetadataUser": "Sync user watch data to nfo's for:", "LabelKodiMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Kodi.", @@ -931,6 +966,7 @@ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:", "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.", "LabelDisplayCollectionsView": "Display a collections view to show movie collections", + "LabelDisplayCollectionsViewHelp": "This will create a separate view to display collections that you've created or have access to. To create a collection, right-click or tap-hold any movie and select 'Add to Collection'. ", "LabelKodiMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs", "LabelKodiMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Kodi skin compatibility.", "TabServices": "Services", @@ -1084,11 +1120,14 @@ "LabelDisplayFoldersView": "Display a folders view to show plain media folders", "ViewTypeLiveTvRecordingGroups": "Recordings", "ViewTypeLiveTvChannels": "Channels", - "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password", - "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.", + "LabelEasyPinCode": "Easy pin code:", + "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Media Browser apps, and can also be used for easy in-network sign in.", + "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", + "LabelInNetworkSignInWithEasyPasswordHelp": "If enabled, you'll be able to use your easy pin code to sign in to Media Browser apps from inside your home network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", "HeaderPassword": "Password", "HeaderLocalAccess": "Local Access", "HeaderViewOrder": "View Order", + "ButtonResetEasyPassword": "Reset easy pin code", "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps", "LabelMetadataRefreshMode": "Metadata refresh mode:", "LabelImageRefreshMode": "Image refresh mode:", @@ -1279,7 +1318,7 @@ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.", "HeaderNewUsers": "New Users", "ButtonSignUp": "Sign up", - "ButtonForgotPassword": "Forgot password?", + "ButtonForgotPassword": "Forgot password", "OptionDisableUserPreferences": "Disable access to user preferences", "OptionDisableUserPreferencesHelp": "If enabled, only administrators will be able to configure user profile images, passwords, and language preferences.", "HeaderSelectServer": "Select Server", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json b/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json index e6b983d26..b150edd8d 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json @@ -27,12 +27,12 @@ "AWindowsServiceHasBeenInstalled": "Foi instalado um Servi\u00e7o do Windows.", "WindowsServiceIntro1": "O Servidor Media Browser normalmente \u00e9 executado como uma aplica\u00e7\u00e3o de desktop com um \u00edcone na bandeja do sistema, mas se preferir executar como servi\u00e7o pode inici\u00e1-lo no painel de controle de servi\u00e7os do Windows", "WindowsServiceIntro2": "Se usar o servi\u00e7o do Windows, por favor certifique-se que n\u00e3o esteja sendo executado ao mesmo tempo que o \u00edcone na bandeja, se estiver ter\u00e1 que sair da app antes de executar o servi\u00e7o. O servi\u00e7o necessita ser configurado com privil\u00e9gios de administrador no painel de controle. Neste momento o servi\u00e7o n\u00e3o pode se auto-atualizar, por isso novas vers\u00f5es exigir\u00e3o intera\u00e7\u00e3o manual.", - "WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click <b>Finish<\/b> to view the <b>Server Dashboard<\/b>.", + "WizardCompleted": "Isso \u00e9 tudo o que \u00e9 necess\u00e1rio no momento. O Media Browser come\u00e7ou a coletar as informa\u00e7\u00f5es de sua biblioteca de m\u00eddias. Verifique algumas de nossas apps e ent\u00e3o clique <b>Terminar<\/b> para ver o <b>Painel do Servidor<\/b>.", "LabelConfigureSettings": "Configurar ajustes", "LabelEnableVideoImageExtraction": "Ativar extra\u00e7\u00e3o de imagens de v\u00eddeo", "VideoImageExtractionHelp": "Para v\u00eddeos que n\u00e3o tenham imagens e que n\u00e3o possamos encontrar imagens na internet. Isto aumentar\u00e1 o tempo do rastreamento inicial da biblioteca mas resultar\u00e1 em uma apresenta\u00e7\u00e3o mais bonita.", "LabelEnableChapterImageExtractionForMovies": "Extrair imagens de cap\u00edtulos dos Filmes", - "LabelChapterImageExtractionForMoviesHelp": "Extrair imagens de cap\u00edtulos permitir\u00e1 aos clientes exibir menus gr\u00e1ficos de sele\u00e7\u00e3o de cenas. O processo pode ser lento, uso intensivo de cpu e pode exigir bastante espa\u00e7o em disco. Ele ser\u00e1 executado \u00e0s 4:00hs, embora isto possa ser configur\u00e1vel na \u00e1rea de tarefas agendadas. N\u00e3o \u00e9 recomendado executar esta tarefa durante as horas de pico de uso.", + "LabelChapterImageExtractionForMoviesHelp": "Extrair imagens de cap\u00edtulos permitir\u00e1 aos clientes exibir menus gr\u00e1ficos de sele\u00e7\u00e3o de cenas. O processo pode ser lento, ocasionar uso intensivo de cpu e pode exigir bastante espa\u00e7o em disco. Ele ser\u00e1 executado \u00e0s 4:00hs, embora isto possa ser configur\u00e1vel na \u00e1rea de tarefas agendadas. N\u00e3o \u00e9 recomendado executar esta tarefa durante as horas de pico de uso.", "LabelEnableAutomaticPortMapping": "Ativar mapeamento de porta autom\u00e1tico", "LabelEnableAutomaticPortMappingHelp": "UPnP permite uma configura\u00e7\u00e3o automatizada do roteador para acesso remoto f\u00e1cil. Isto pode n\u00e3o funcionar em alguns modelos de roteadores.", "HeaderTermsOfService": "Termos de Servi\u00e7o do Media Browser", @@ -40,14 +40,34 @@ "OptionIAcceptTermsOfService": "Aceito os termos de servi\u00e7o", "ButtonPrivacyPolicy": "Pol\u00edtica de privacidade", "ButtonTermsOfService": "Termos de Servi\u00e7o", + "HeaderDeveloperOptions": "Op\u00e7\u00f5es de Desenvolvedor", + "OptionEnableWebClientResponseCache": "Ativar o cache de resposta do client web", + "OptionDisableForDevelopmentHelp": "Configure esta op\u00e7\u00e3o de acordo ao prop\u00f3sito de desenvolvimento do cliente web", + "OptionEnableWebClientResourceMinification": "Ativar a minimiza\u00e7\u00e3o de recursos do cliente web", + "LabelDashboardSourcePath": "Caminho fonte do cliente web:", + "LabelDashboardSourcePathHelp": "Se executar o servidor a partir do c\u00f3digo, especifique o caminho para a pasta da interface do painel. Todos os arquivos do cliente web ser\u00e3o usados nesta localiza\u00e7\u00e3o.", + "ButtonConvertMedia": "Converter m\u00eddia", + "ButtonOrganize": "Organizar", "ButtonOk": "Ok", "ButtonCancel": "Cancelar", "ButtonNew": "Novo", "HeaderTV": "TV", "HeaderAudio": "\u00c1udio", "HeaderVideo": "V\u00eddeo", - "OptionDetectArchiveFilesAsMedia": "Detect archive files as media", - "OptionDetectArchiveFilesAsMediaHelp": "If enabled, files with .rar and .zip extensions will be detected as media files.", + "HeaderPaths": "Caminhos", + "CategorySync": "Sincroniza\u00e7\u00e3o", + "HeaderEasyPinCode": "Easy Pin Code", + "RegisterWithPayPal": "Registrar com PayPal", + "HeaderSyncRequiresSupporterMembership": "Sincroniza\u00e7\u00e3o Necessita de uma Filia\u00e7\u00e3o de Colaborador", + "HeaderEnjoyDayTrial": "Aproveite um per\u00edodo de 14 dias gr\u00e1tis para testes", + "LabelSyncTempPath": "Caminho de arquivo tempor\u00e1rio:", + "LabelSyncTempPathHelp": "Especifique uma pasta de trabalho para a sincroniza\u00e7\u00e3o personalizada. M\u00eddias convertidas criadas durante o processo de sincroniza\u00e7\u00e3o ser\u00e3o aqui armazenadas.", + "LabelCustomCertificatePath": "Caminho do certificado personalizado:", + "LabelCustomCertificatePathHelp": "Forne\u00e7a seu pr\u00f3prio certificado ssl. Se omitido, o servidor criar\u00e1 um certificado auto-assinado.", + "TitleNotifications": "Notifica\u00e7\u00f5es", + "ButtonDonateWithPayPal": "Doe atrav\u00e9s do PayPal", + "OptionDetectArchiveFilesAsMedia": "Detectar arquivos compactados como m\u00eddia", + "OptionDetectArchiveFilesAsMediaHelp": "Se ativado, arquivos com extens\u00f5es .rar e .zip ser\u00e3o detectados como arquivos de m\u00eddia.", "LabelEnterConnectUserName": "Nome de usu\u00e1rio ou email:", "LabelEnterConnectUserNameHelp": "Este \u00e9 o nome de usu\u00e1rio ou senha de sua conta online do Media Browser.", "HeaderSyncJobInfo": "Tarefa de Sincroniza\u00e7\u00e3o", @@ -63,12 +83,14 @@ "FolderTypeTvShows": "TV", "FolderTypeInherit": "Herdar", "LabelContentType": "Tipo de conte\u00fado:", + "TitleScheduledTasks": "Tarefas Agendadas", "HeaderSetupLibrary": "Configurar sua biblioteca de m\u00eddias", "ButtonAddMediaFolder": "Adicionar pasta de m\u00eddias", "LabelFolderType": "Tipo de pasta:", "ReferToMediaLibraryWiki": "Consultar wiki da biblioteca de m\u00eddias", "LabelCountry": "Pa\u00eds:", "LabelLanguage": "Idioma:", + "ButtonJoinTheDevelopmentTeam": "Junte-se ao Time de Desenvolvimento", "HeaderPreferredMetadataLanguage": "Idioma preferido dos metadados:", "LabelSaveLocalMetadata": "Salvar artwork e metadados dentro das pastas da m\u00eddia", "LabelSaveLocalMetadataHelp": "Salvar artwork e metadados diretamente nas pastas da m\u00eddia as deixar\u00e1 em um local f\u00e1cil para edit\u00e1-las.", @@ -86,6 +108,8 @@ "TabCollectionTitles": "T\u00edtulos", "HeaderDeviceAccess": "Acesso ao Dispositivo", "OptionEnableAccessFromAllDevices": "Ativar o acesso de todos os dispositivos", + "OptionEnableAccessToAllChannels": "Ativar o acesso a todos os canais", + "OptionEnableAccessToAllLibraries": "Ativar o acesso a todas as bibliotecas", "DeviceAccessHelp": "Isto apenas aplica para dispositivos que podem ser identificados como \u00fanicos e n\u00e3o evitar\u00e3o o acesso do navegador. Filtrar o acesso ao dispositivo do usu\u00e1rio evitar\u00e1 que sejam usados novos dispositivos at\u00e9 que sejam aprovados aqui.", "LabelDisplayMissingEpisodesWithinSeasons": "Exibir epis\u00f3dios que faltam dentro das temporadas", "LabelUnairedMissingEpisodesWithinSeasons": "Exibir epis\u00f3dios por estrear dentro das temporadas", @@ -299,7 +323,7 @@ "LabelCachePath": "Caminho do cache:", "LabelCachePathHelp": "Defina uma localiza\u00e7\u00e3o para os arquivos de cache como, por exemplo, imagens.", "LabelImagesByNamePath": "Caminho do Images by name:", - "LabelImagesByNamePathHelp": "Defina uma localiza\u00e7\u00e3o para imagens baixadas para ator, artista, g\u00eanero e est\u00fadio.", + "LabelImagesByNamePathHelp": "Defina uma localiza\u00e7\u00e3o para imagens baixadas para ator, g\u00eanero e est\u00fadio.", "LabelMetadataPath": "Caminho dos Metadados:", "LabelMetadataPathHelp": "Defina uma localiza\u00e7\u00e3o para artwork e metadados baixados, caso n\u00e3o sejam salvos dentro das pastas de m\u00eddia.", "LabelTranscodingTempPath": "Caminho tempor\u00e1rio para transcodifica\u00e7\u00e3o:", @@ -314,12 +338,14 @@ "OptionEpisodes": "Epis\u00f3dios", "OptionOtherVideos": "Outros V\u00eddeos", "TitleMetadata": "Metadados", - "LabelAutomaticUpdatesFanart": "Ativar atualiza\u00e7\u00f5es autom\u00e1ticas de FanArt.tv", + "LabelAutomaticUpdates": "Ativar atualiza\u00e7\u00f5es autom\u00e1ticas", "LabelAutomaticUpdatesTmdb": "Ativar atualiza\u00e7\u00f5es autom\u00e1ticas de The MovieDB.org", "LabelAutomaticUpdatesTvdb": "Ativar atualiza\u00e7\u00f5es autom\u00e1ticas de TheTVDB.com", "LabelAutomaticUpdatesFanartHelp": "Se ativado, novas imagens ser\u00e3o automaticamente baixadas ao serem adicionadas ao fanart.tv. As Imagens atuais n\u00e3o ser\u00e3o substitu\u00eddas.", "LabelAutomaticUpdatesTmdbHelp": "Se ativado, novas imagens ser\u00e3o automaticamente baixadas ao serem adicionadas ao TheMovieDB.org. As Imagens atuais n\u00e3o ser\u00e3o substitu\u00eddas.", "LabelAutomaticUpdatesTvdbHelp": "Se ativado, novas imagens ser\u00e3o automaticamente baixadas ao serem adicionadas ao TheTVDB.com. As Imagens atuais n\u00e3o ser\u00e3o substitu\u00eddas.", + "LabelFanartApiKey": "Chave de api pessoal:", + "LabelFanartApiKeyHelp": "Solicita\u00e7\u00f5es para fanart sem uma chave de API pessoal retornar\u00e3o resultados que foram aprovados h\u00e1 mais de 7 dias atr\u00e1s. Com uma chave de API pessoal isso diminui para 48 horas e se voc\u00ea for um membro VIP da fanart, isso diminuir\u00e1 para 10 minutos.", "ExtractChapterImagesHelp": "Extrair imagens de cap\u00edtulos permitir\u00e1 aos clientes exibir menus gr\u00e1ficos de sele\u00e7\u00e3o de cenas. O processo pode ser lento, demandar uso intensivo de cpu e pode exigir bastante espa\u00e7o em disco. Ele ser\u00e1 executado quando os v\u00eddeos forem descobertos e tamb\u00e9m como uma tarefa agendada executada \u00e0s 4 da manh\u00e3. O agendamento pode ser configurado na \u00e1rea de tarefas agendadas. N\u00e3o \u00e9 recomendado executar esta tarefa durante as horas de pico de uso.", "LabelMetadataDownloadLanguage": "Idioma preferido para download:", "ButtonAutoScroll": "Auto-rolagem", @@ -487,6 +513,7 @@ "HeaderSystemPaths": "Caminhos do Sistema", "LinkCommunity": "Comunidade", "LinkGithub": "Github", + "LinkApi": "Api", "LinkApiDocumentation": "Documenta\u00e7\u00e3o da Api", "LabelFriendlyServerName": "Nome amig\u00e1vel do servidor:", "LabelFriendlyServerNameHelp": "Este nome ser\u00e1 usado para identificar este servidor. Se deixado em branco, ser\u00e1 usado o nome do computador.", @@ -494,20 +521,25 @@ "LabelPreferredDisplayLanguageHelp": "A tradu\u00e7\u00e3o do Media Browser \u00e9 um projeto cont\u00ednuo e ainda n\u00e3o finalizado.", "LabelReadHowYouCanContribute": "Leia sobre como voc\u00ea pode contribuir.", "HeaderNewCollection": "Nova Cole\u00e7\u00e3o", - "HeaderAddToCollection": "Adicionar \u00e0 Cole\u00e7\u00e3o", "ButtonSubmit": "Enviar", - "NewCollectionNameExample": "Exemplo: Cole\u00e7\u00e3o Star Wars", - "OptionSearchForInternetMetadata": "Buscar artwork e metadados na internet", "ButtonCreate": "Criar", - "LabelLocalHttpServerPortNumber": "N\u00famero da porta local:", + "LabelCustomCss": "Css personalizado:", + "LabelCustomCssHelp": "Aplique o seu css personalizado para a interface web", + "LabelLocalHttpServerPortNumber": "N\u00famero da porta local de http:", "LabelLocalHttpServerPortNumberHelp": "O n\u00famero da porta tcp que o servidor http do Media Browser utilizar\u00e1.", - "LabelPublicPort": "N\u00famero da porta p\u00fablica:", - "LabelPublicPortHelp": "O n\u00famero da porta p\u00fablica que deve ser mapeado para a porta local.", + "LabelPublicHttpPort": "N\u00famero da porta p\u00fablica de http:", + "LabelPublicHttpPortHelp": "O n\u00famero da porta p\u00fablica que dever\u00e1 ser mapeada para a porta local de http.", + "LabelPublicHttpsPort": "N\u00famero da porta p\u00fablica de https:", + "LabelPublicHttpsPortHelp": "O n\u00famero da porta p\u00fablica que dever\u00e1 ser mapeada para a porta local de https.", + "LabelEnableHttps": "Reportar https como um endere\u00e7o externo", + "LabelEnableHttpsHelp": "Se ativado, o servidor ir\u00e1 reportar uma url https para os clientes como um endere\u00e7o externo. Isto pode prejudicar o funcionamento de clientes que ainda n\u00e3o suportam https.", + "LabelHttpsPort": "N\u00famero da porta local de https:", + "LabelHttpsPortHelp": "O n\u00famero da porta tcp que o servidor https do Media Browser dever\u00e1 se vincular.", "LabelWebSocketPortNumber": "N\u00famero da porta do web socket:", "LabelEnableAutomaticPortMap": "Habilitar mapeamento autom\u00e1tico de portas", "LabelEnableAutomaticPortMapHelp": "Tentativa de mapear automaticamente a porta p\u00fablica para a local atrav\u00e9s de uPnP. Isto poder\u00e1 n\u00e3o funcionar em alguns modelos de roteadores.", - "LabelExternalDDNS": "DDNS Externo:", - "LabelExternalDDNSHelp": "Se voc\u00ea tem um DNS din\u00e2mico digite aqui. O Media Browser o usar\u00e1 quando conectar remotamente.", + "LabelExternalDDNS": "Endere\u00e7o WAN externo:", + "LabelExternalDDNSHelp": "Se voc\u00ea tiver um DNS din\u00e2mico, digite aqui. As apps do Media Browser o usar\u00e3o para conectar-se remotamente. Deixe em branco para detec\u00e7\u00e3o autom\u00e1tica.", "TabResume": "Retomar", "TabWeather": "Tempo", "TitleAppSettings": "Configura\u00e7\u00f5es da App", @@ -575,6 +607,7 @@ "ButtonRestart": "Reiniciar", "ButtonShutdown": "Desligar", "ButtonUpdateNow": "Atualizar Agora", + "TabHosting": "Hospedagem", "PleaseUpdateManually": "Por favor, desligue o servidor e atualize-o manualmente.", "NewServerVersionAvailable": "Uma nova vers\u00e3o do Servidor Media Browser est\u00e1 dispon\u00edvel!", "ServerUpToDate": "O Servidor Media Browser est\u00e1 atualizado", @@ -636,6 +669,7 @@ "NotificationOptionInstallationFailed": "Falha na instala\u00e7\u00e3o", "NotificationOptionNewLibraryContent": "Novo conte\u00fado adicionado", "NotificationOptionNewLibraryContentMultiple": "Novo conte\u00fado adicionado (m\u00faltiplo)", + "NotificationOptionCameraImageUploaded": "Imagem da c\u00e2mera carregada", "SendNotificationHelp": "Por padr\u00e3o, notifica\u00e7\u00f5es s\u00e3o entregues \u00e0 caixa de entrada do painel. Explore o cat\u00e1logo de plugins para instalar op\u00e7\u00f5es adicionais de notifica\u00e7\u00f5es.", "NotificationOptionServerRestartRequired": "Necessidade de reiniciar servidor", "LabelNotificationEnabled": "Ativar esta notifica\u00e7\u00e3o", @@ -829,8 +863,8 @@ "OptionAuto": "Auto", "OptionYes": "Sim", "OptionNo": "N\u00e3o", - "HeaderOptions": "Options", - "HeaderIdentificationResult": "Identification Result", + "HeaderOptions": "Op\u00e7\u00f5es", + "HeaderIdentificationResult": "Resultado da Identifica\u00e7\u00e3o", "LabelHomePageSection1": "Tela de in\u00edcio se\u00e7\u00e3o 1:", "LabelHomePageSection2": "Tela de in\u00edcio se\u00e7\u00e3o 2:", "LabelHomePageSection3": "Tela de in\u00edcio se\u00e7\u00e3o 3:", @@ -853,8 +887,10 @@ "OptionDefaultSort": "Padr\u00e3o", "OptionCommunityMostWatchedSort": "Mais Assistidos", "TabNextUp": "Pr\u00f3ximos", + "HeaderBecomeMediaBrowserSupporter": "Torne-se um Colaborador do Media Browser", + "TextEnjoyBonusFeatures": "Aproveite Funcionalidades Extras", "MessageNoMovieSuggestionsAvailable": "N\u00e3o existem sugest\u00f5es de filmes dispon\u00edveis atualmente. Comece por assistir e avaliar seus filmes e, ent\u00e3o, volte para verificar suas recomenda\u00e7\u00f5es.", - "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.", + "MessageNoCollectionsAvailable": "Cole\u00e7\u00f5es permitem que voc\u00ea aproveite grupos personalizados de Filmes, S\u00e9ries, \u00c1lbuns, Livros e Jogos. Clique no bot\u00e3o + para come\u00e7ar a criar Cole\u00e7\u00f5es.", "MessageNoPlaylistsAvailable": "Listas de reprodu\u00e7\u00e3o permitem criar listas com conte\u00fado para reproduzir consecutivamente, de uma s\u00f3 vez. Para adicionar itens \u00e0s listas de reprodu\u00e7\u00e3o, clique com o bot\u00e3o direito ou toque a tela por alguns segundos, depois selecione Adicionar \u00e0 Lista de Reprodu\u00e7\u00e3o.", "MessageNoPlaylistItemsAvailable": "Esta lista de reprodu\u00e7\u00e3o est\u00e1 vazia.", "ButtonDismiss": "Descartar", @@ -869,7 +905,6 @@ "LabelChannelDownloadAge": "Excluir conte\u00fado depois de: (dias)", "LabelChannelDownloadAgeHelp": "O conte\u00fado transferido que for mais velho que este valor ser\u00e1 exclu\u00eddo. Poder\u00e1 seguir reproduzindo-o atrav\u00e9s de streaming da internet.", "ChannelSettingsFormHelp": "Instalar canais como, por exemplo, Trailers e Vimeo no cat\u00e1logo de plugins.", - "LabelSelectCollection": "Selecione cole\u00e7\u00e3o:", "ButtonOptions": "Op\u00e7\u00f5es", "ViewTypeMovies": "Filmes", "ViewTypeTvShows": "TV", @@ -917,7 +952,7 @@ "OptionLatestTvRecordings": "\u00daltimas grava\u00e7\u00f5es", "LabelProtocolInfo": "Informa\u00e7\u00e3o do protocolo:", "LabelProtocolInfoHelp": "O valor que ser\u00e1 usado ao responder os pedidos GetProtocolInfo do dispositivo.", - "TabKodiMetadata": "Kodi", + "TabNfo": "Nfo", "HeaderKodiMetadataHelp": "O Media Browser inclui suporte nativo aos metadados e imagens Nfo do Kodi. Para ativar ou desativar os metadados do Kodi, use a aba Avan\u00e7ado e configure as op\u00e7\u00f5es dos seus tipos de m\u00eddia.", "LabelKodiMetadataUser": "Sincronizar informa\u00e7\u00f5es do que o usu\u00e1rio assiste aos nfo's para:", "LabelKodiMetadataUserHelp": "Ativar esta op\u00e7\u00e3o para manter os dados sincronizados entre o Media Browser e o Kodi.", @@ -931,6 +966,7 @@ "LabelGroupChannelsIntoViews": "Exibir os seguintes canais diretamente dentro de minhas visualiza\u00e7\u00f5es:", "LabelGroupChannelsIntoViewsHelp": "Se ativados, estes canais ser\u00e3o exibidos imediatamente ao lado de outras visualiza\u00e7\u00f5es. Se desativado, eles ser\u00e3o exibidos dentro de uma visualiza\u00e7\u00e3o separada de Canais.", "LabelDisplayCollectionsView": "Exibir uma visualiza\u00e7\u00e3o de cole\u00e7\u00f5es para mostrar colet\u00e2neas de filmes", + "LabelDisplayCollectionsViewHelp": "Esta op\u00e7\u00e3o criar\u00e1 uma visualiza\u00e7\u00e3o separada para exibir cole\u00e7\u00f5es criadas ou acessadas por voc\u00ea. Para criar uma cole\u00e7\u00e3o, clique com o bot\u00e3o direito ou toque e segure qualquer filme e selecione 'Adicionar \u00e0 Cole\u00e7\u00e3o'.", "LabelKodiMetadataEnableExtraThumbs": "Copiar extrafanart para extrathumbs", "LabelKodiMetadataEnableExtraThumbsHelp": "Ao fazer download das imagens, elas podem ser salvas em ambas extrafanart e extrathumbs para uma maior compatibilidade com as skins do Kodi.", "TabServices": "Servi\u00e7os", @@ -1084,11 +1120,14 @@ "LabelDisplayFoldersView": "Exibir visualiza\u00e7\u00e3o de pastas para mostrar pastas simples de m\u00eddia", "ViewTypeLiveTvRecordingGroups": "Grava\u00e7\u00f5es", "ViewTypeLiveTvChannels": "Canais", - "LabelAllowLocalAccessWithoutPassword": "Permtir acesso local sem senha", - "LabelAllowLocalAccessWithoutPasswordHelp": "Quando ativado, uma senha n\u00e3o ser\u00e1 necess\u00e1ria para entrar atrav\u00e9s de sua rede dom\u00e9stica.", + "LabelEasyPinCode": "Easy pin code:", + "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Media Browser apps, and can also be used for easy in-network sign in.", + "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", + "LabelInNetworkSignInWithEasyPasswordHelp": "If enabled, you'll be able to use your easy pin code to sign in to Media Browser apps from inside your home network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", "HeaderPassword": "Senha", "HeaderLocalAccess": "Acesso Local", "HeaderViewOrder": "Ordem da Visualiza\u00e7\u00e3o", + "ButtonResetEasyPassword": "Reset easy pin code", "LabelSelectUserViewOrder": "Escolha a ordem em que suas visualiza\u00e7\u00f5es ser\u00e3o exibidas dentro das apps do Media Browser", "LabelMetadataRefreshMode": "Modo de atualiza\u00e7\u00e3o dos metadados:", "LabelImageRefreshMode": "Modo de atualiza\u00e7\u00e3o das imagens:", @@ -1162,7 +1201,7 @@ "OptionNoThemeSong": "Nenhuma M\u00fasica-tema", "OptionNoThemeVideo": "Nenhum V\u00eddeo-tema", "LabelOneTimeDonationAmount": "Valor da doa\u00e7\u00e3o:", - "ButtonDonate": "Donate", + "ButtonDonate": "Doar", "OptionActor": "Ator", "OptionComposer": "Compositor", "OptionDirector": "Diretor", @@ -1279,7 +1318,7 @@ "MessageNoTrailersFound": "Nenhum trailer encontrado. Instale o canal Trailer para melhorar sua experi\u00eancia com filmes, adicionando uma biblioteca de trailers da internet.", "HeaderNewUsers": "Novos Usu\u00e1rios", "ButtonSignUp": "Entrar", - "ButtonForgotPassword": "Esqueceu a senha?", + "ButtonForgotPassword": "Esqueci a senha", "OptionDisableUserPreferences": "Desativar acesso \u00e0s prefer\u00eancias do usu\u00e1rio.", "OptionDisableUserPreferencesHelp": "Se ativado, apenas administradores poder\u00e3o configurar imagens do perfil do usu\u00e1rio, senhas e prefer\u00eancias de idioma.", "HeaderSelectServer": "Selecionar Servidor", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json b/MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json index 8cc022025..d7113fc6f 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json @@ -40,12 +40,32 @@ "OptionIAcceptTermsOfService": "I accept the terms of service", "ButtonPrivacyPolicy": "Privacy policy", "ButtonTermsOfService": "Terms of Service", + "HeaderDeveloperOptions": "Developer Options", + "OptionEnableWebClientResponseCache": "Enable web client response caching", + "OptionDisableForDevelopmentHelp": "Configure these as needed for web client development purposes.", + "OptionEnableWebClientResourceMinification": "Enable web client resource minification", + "LabelDashboardSourcePath": "Web client source path:", + "LabelDashboardSourcePathHelp": "If running the server from source, specify the path to the dashboard-ui folder. All web client files will be served from this location.", + "ButtonConvertMedia": "Convert media", + "ButtonOrganize": "Organize", "ButtonOk": "Ok", "ButtonCancel": "Cancelar", "ButtonNew": "Novo", "HeaderTV": "TV", "HeaderAudio": "Audio", "HeaderVideo": "Video", + "HeaderPaths": "Paths", + "CategorySync": "Sync", + "HeaderEasyPinCode": "Easy Pin Code", + "RegisterWithPayPal": "Register with PayPal", + "HeaderSyncRequiresSupporterMembership": "Sync Requires a Supporter Membership", + "HeaderEnjoyDayTrial": "Enjoy a 14 Day Free Trial", + "LabelSyncTempPath": "Temporary file path:", + "LabelSyncTempPathHelp": "Specify a custom sync working folder. Converted media created during the sync process will be stored here.", + "LabelCustomCertificatePath": "Custom certificate path:", + "LabelCustomCertificatePathHelp": "Supply your own ssl certificate. If omitted, the server will create a self-signed certificate.", + "TitleNotifications": "Notifications", + "ButtonDonateWithPayPal": "Donate with PayPal", "OptionDetectArchiveFilesAsMedia": "Detect archive files as media", "OptionDetectArchiveFilesAsMediaHelp": "If enabled, files with .rar and .zip extensions will be detected as media files.", "LabelEnterConnectUserName": "User name or email:", @@ -63,12 +83,14 @@ "FolderTypeTvShows": "TV", "FolderTypeInherit": "Inherit", "LabelContentType": "Content type:", + "TitleScheduledTasks": "Scheduled Tasks", "HeaderSetupLibrary": "Configurar biblioteca", "ButtonAddMediaFolder": "Adicionar pasta de media", "LabelFolderType": "Tipo de pasta", "ReferToMediaLibraryWiki": "Consulte a wiki", "LabelCountry": "Pa\u00eds:", "LabelLanguage": "Idioma:", + "ButtonJoinTheDevelopmentTeam": "Join the Development Team", "HeaderPreferredMetadataLanguage": "Idioma preferido para metadados", "LabelSaveLocalMetadata": "Guardar imagens e metadados nas pastas multim\u00e9dia", "LabelSaveLocalMetadataHelp": "Guardar imagens e metadados diretamente nas pastas multim\u00e9dia, vai coloc\u00e1-los num local de f\u00e1cil acesso para poderem ser editados facilmente.", @@ -86,6 +108,8 @@ "TabCollectionTitles": "T\u00edtulos", "HeaderDeviceAccess": "Device Access", "OptionEnableAccessFromAllDevices": "Enable access from all devices", + "OptionEnableAccessToAllChannels": "Enable access to all channels", + "OptionEnableAccessToAllLibraries": "Enable access to all libraries", "DeviceAccessHelp": "This only applies to devices that can be uniquely identified and will not prevent browser access. Filtering user device access will prevent them from using new devices until they've been approved here.", "LabelDisplayMissingEpisodesWithinSeasons": "Mostrar epis\u00f3dios em falta dentro das temporadas", "LabelUnairedMissingEpisodesWithinSeasons": "Mostrar epis\u00f3dios por estrear dentro das temporadas", @@ -299,7 +323,7 @@ "LabelCachePath": "Localiza\u00e7\u00e3o da cache:", "LabelCachePathHelp": "Defina uma localiza\u00e7\u00e3o para ficheiros de cache do servidor, como por exemplo, imagens.", "LabelImagesByNamePath": "Localiza\u00e7\u00e3o das imagens por nome:", - "LabelImagesByNamePathHelp": "Defina uma localiza\u00e7\u00e3o para imagens de atores, artistas, g\u00e9neros e est\u00fadios.", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, genre and studio images.", "LabelMetadataPath": "Localiza\u00e7\u00e3o dos metadados:", "LabelMetadataPathHelp": "Defina uma localiza\u00e7\u00e3o para imagens e metadados transferidos que n\u00e3o foram configurados para serem armazenados nas pastas multim\u00e9dia.", "LabelTranscodingTempPath": "Localiza\u00e7\u00e3o tempor\u00e1ria das transcodifica\u00e7\u00f5es:", @@ -314,12 +338,14 @@ "OptionEpisodes": "Epis\u00f3dios", "OptionOtherVideos": "Outros V\u00eddeos", "TitleMetadata": "Metadados", - "LabelAutomaticUpdatesFanart": "Ativar atualiza\u00e7\u00f5es autom\u00e1ticas do FanArt.tv", + "LabelAutomaticUpdates": "Enable automatic updates", "LabelAutomaticUpdatesTmdb": "Ativar atualiza\u00e7\u00f5es autom\u00e1ticas do TheMovieDB.org", "LabelAutomaticUpdatesTvdb": "Ativar atualiza\u00e7\u00f5es autom\u00e1ticas do TheTVDB.com", "LabelAutomaticUpdatesFanartHelp": "Se ativado, novas imagens ser\u00e3o automaticamente transferidas ao serem adicionadas ao fanart.tv. As imagens existentes n\u00e3o ser\u00e3o substitu\u00eddas.", "LabelAutomaticUpdatesTmdbHelp": "Se ativado, novas imagens ser\u00e3o automaticamente transferidas ao serem adicionadas ao TheMovieDB.org. As imagens existentes n\u00e3o ser\u00e3o substitu\u00eddas.", "LabelAutomaticUpdatesTvdbHelp": "Se ativado, novas imagens ser\u00e3o automaticamente transferidas ao serem adicionadas ao TheTVDB.com. As imagens existentes n\u00e3o ser\u00e3o substitu\u00eddas.", + "LabelFanartApiKey": "Personal api key:", + "LabelFanartApiKeyHelp": "Requests to fanart without a personal API key return results that were approved over 7 days ago. With a personal API key that drops to 48 hours and if you are also a fanart VIP member that will further drop to around 10 minutes.", "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", "LabelMetadataDownloadLanguage": "Preferred download language:", "ButtonAutoScroll": "Scroll autom\u00e1tico", @@ -487,6 +513,7 @@ "HeaderSystemPaths": "Localiza\u00e7\u00f5es de Sistema", "LinkCommunity": "Comunidade", "LinkGithub": "Github", + "LinkApi": "Api", "LinkApiDocumentation": "Documenta\u00e7\u00e3o da API", "LabelFriendlyServerName": "Nome amig\u00e1vel do servidor:", "LabelFriendlyServerNameHelp": "Ser\u00e1 usado este nome para identificar o servidor. Se n\u00e3o for preenchido, ser\u00e1 usado o nome do computador.", @@ -494,20 +521,25 @@ "LabelPreferredDisplayLanguageHelp": "A tradu\u00e7\u00e3o do Media Browser \u00e9 um projeto em andamento e ainda n\u00e3o est\u00e1 completo.", "LabelReadHowYouCanContribute": "Leia sobre como pode contribuir.", "HeaderNewCollection": "Nova Cole\u00e7\u00e3o", - "HeaderAddToCollection": "Add to Collection", "ButtonSubmit": "Submit", - "NewCollectionNameExample": "Exemplo: Cole\u00e7\u00e3o Guerra das Estrelas", - "OptionSearchForInternetMetadata": "Procurar na internet por imagens e metadados", "ButtonCreate": "Criar", - "LabelLocalHttpServerPortNumber": "Local port number:", + "LabelCustomCss": "Custom css:", + "LabelCustomCssHelp": "Apply your own custom css to the web interface.", + "LabelLocalHttpServerPortNumber": "Local http port number:", "LabelLocalHttpServerPortNumberHelp": "The tcp port number that Media Browser's http server should bind to.", - "LabelPublicPort": "Public port number:", - "LabelPublicPortHelp": "The public port number that should be mapped to the local port.", + "LabelPublicHttpPort": "Public http port number:", + "LabelPublicHttpPortHelp": "The public port number that should be mapped to the local http port.", + "LabelPublicHttpsPort": "Public https port number:", + "LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.", + "LabelEnableHttps": "Report https as external address", + "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.", + "LabelHttpsPort": "Local https port number:", + "LabelHttpsPortHelp": "The tcp port number that Media Browser's https server should bind to.", "LabelWebSocketPortNumber": "N\u00famero da porta da Web socket:", "LabelEnableAutomaticPortMap": "Enable automatic port mapping", "LabelEnableAutomaticPortMapHelp": "Attempt to automatically map the public port to the local port via UPnP. This may not work with some router models.", - "LabelExternalDDNS": "DDNS Externo:", - "LabelExternalDDNSHelp": "Se tem um DNS din\u00e2mico insira-o aqui. As aplica\u00e7\u00f5es Media Browser ir\u00e3o us\u00e1-lo ao conectarem-se remotamente.", + "LabelExternalDDNS": "External WAN Address:", + "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely. Leave empty for automatic detection.", "TabResume": "Retomar", "TabWeather": "Tempo", "TitleAppSettings": "Configura\u00e7\u00f5es da Aplica\u00e7\u00e3o", @@ -575,6 +607,7 @@ "ButtonRestart": "Reiniciar", "ButtonShutdown": "Encerrar", "ButtonUpdateNow": "Atualizar Agora", + "TabHosting": "Hosting", "PleaseUpdateManually": "Por favor encerre o servidor e atualize manualmente.", "NewServerVersionAvailable": "Est\u00e1 dispon\u00edvel uma nova vers\u00e3o do Media Browser!", "ServerUpToDate": "O Media Browser est\u00e1 atualizado", @@ -636,6 +669,7 @@ "NotificationOptionInstallationFailed": "Falha na instala\u00e7\u00e3o", "NotificationOptionNewLibraryContent": "Adicionado novo conte\u00fado", "NotificationOptionNewLibraryContentMultiple": "Novo conte\u00fado adicionado (m\u00faltiplo)", + "NotificationOptionCameraImageUploaded": "Camera image uploaded", "SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.", "NotificationOptionServerRestartRequired": "\u00c9 necess\u00e1rio reiniciar o servidor", "LabelNotificationEnabled": "Ativar esta notifica\u00e7\u00e3o", @@ -853,6 +887,8 @@ "OptionDefaultSort": "Default", "OptionCommunityMostWatchedSort": "Most Watched", "TabNextUp": "Next Up", + "HeaderBecomeMediaBrowserSupporter": "Become a Media Browser Supporter", + "TextEnjoyBonusFeatures": "Enjoy Bonus Features", "MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.", "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.", "MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.", @@ -869,7 +905,6 @@ "LabelChannelDownloadAge": "Delete content after: (days)", "LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.", "ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.", - "LabelSelectCollection": "Select collection:", "ButtonOptions": "Options", "ViewTypeMovies": "Movies", "ViewTypeTvShows": "TV", @@ -917,7 +952,7 @@ "OptionLatestTvRecordings": "Latest recordings", "LabelProtocolInfo": "Protocol info:", "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.", - "TabKodiMetadata": "Kodi", + "TabNfo": "Nfo", "HeaderKodiMetadataHelp": "Media Browser includes native support for Kodi Nfo metadata and images. To enable or disable Kodi metadata, use the Advanced tab to configure options for your media types.", "LabelKodiMetadataUser": "Sync user watch data to nfo's for:", "LabelKodiMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Kodi.", @@ -931,6 +966,7 @@ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:", "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.", "LabelDisplayCollectionsView": "Display a collections view to show movie collections", + "LabelDisplayCollectionsViewHelp": "This will create a separate view to display collections that you've created or have access to. To create a collection, right-click or tap-hold any movie and select 'Add to Collection'. ", "LabelKodiMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs", "LabelKodiMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Kodi skin compatibility.", "TabServices": "Services", @@ -1084,11 +1120,14 @@ "LabelDisplayFoldersView": "Display a folders view to show plain media folders", "ViewTypeLiveTvRecordingGroups": "Recordings", "ViewTypeLiveTvChannels": "Channels", - "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password", - "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.", + "LabelEasyPinCode": "Easy pin code:", + "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Media Browser apps, and can also be used for easy in-network sign in.", + "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", + "LabelInNetworkSignInWithEasyPasswordHelp": "If enabled, you'll be able to use your easy pin code to sign in to Media Browser apps from inside your home network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", "HeaderPassword": "Password", "HeaderLocalAccess": "Local Access", "HeaderViewOrder": "View Order", + "ButtonResetEasyPassword": "Reset easy pin code", "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps", "LabelMetadataRefreshMode": "Metadata refresh mode:", "LabelImageRefreshMode": "Image refresh mode:", @@ -1279,7 +1318,7 @@ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.", "HeaderNewUsers": "New Users", "ButtonSignUp": "Sign up", - "ButtonForgotPassword": "Forgot password?", + "ButtonForgotPassword": "Forgot password", "OptionDisableUserPreferences": "Disable access to user preferences", "OptionDisableUserPreferencesHelp": "If enabled, only administrators will be able to configure user profile images, passwords, and language preferences.", "HeaderSelectServer": "Select Server", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/ru.json b/MediaBrowser.Server.Implementations/Localization/Server/ru.json index 7e58a6597..73bc7ffbc 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/ru.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/ru.json @@ -1,7 +1,7 @@ { "LabelExit": "\u0412\u044b\u0445\u043e\u0434", "LabelVisitCommunity": "\u041f\u043e\u0441\u0435\u0449\u0435\u043d\u0438\u0435 \u0421\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u0430", - "LabelGithub": "\u0420\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 Github", + "LabelGithub": "GitHub", "LabelSwagger": "\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 Swagger", "LabelStandard": "\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442", "LabelApiDocumentation": "\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u043f\u043e API", @@ -32,22 +32,42 @@ "LabelEnableVideoImageExtraction": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u0430 \u0438\u0437 \u0432\u0438\u0434\u0435\u043e", "VideoImageExtractionHelp": "\u0414\u043b\u044f \u0432\u0438\u0434\u0435\u043e, \u0433\u0434\u0435 \u0435\u0449\u0451 \u200b\u200b\u043d\u0435 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432, \u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043d\u0430\u0439\u0442\u0438 \u0432 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u0431\u0430\u0432\u043b\u0435\u043d\u043e \u0435\u0449\u0451 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043a \u043f\u0435\u0440\u0432\u043e\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u0441\u043a\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438, \u043d\u043e \u044d\u0442\u043e \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u0442 \u043a \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u0438\u0432\u043b\u0435\u043a\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u043f\u0440\u0435\u0437\u0435\u043d\u0442\u0430\u0446\u0438\u0438.", "LabelEnableChapterImageExtractionForMovies": "\u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0442\u044c \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u0441\u0446\u0435\u043d \u0434\u043b\u044f \u0444\u0438\u043b\u044c\u043c\u043e\u0432", - "LabelChapterImageExtractionForMoviesHelp": "\u0418\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432 \u0441\u0446\u0435\u043d \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043c\u0435\u043d\u044e \u0432\u044b\u0431\u043e\u0440\u0430 \u0441\u0446\u0435\u043d\u044b. \u0414\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u044b\u043c, \u043d\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u0438 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0433\u0438\u0433\u0430\u0431\u0430\u0439\u0442 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0430. \u041e\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043a\u0430\u043a \u0437\u0430\u0434\u0430\u0447\u0430, \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u0430\u044f \u043d\u0430 4:00 \u0443\u0442\u0440\u0430, \u043e\u0434\u043d\u0430\u043a\u043e, \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0432 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u00ab\u041f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u0430\u00bb. \u041d\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443 \u0432 \u0447\u0430\u0441\u044b \u043f\u0438\u043a.", + "LabelChapterImageExtractionForMoviesHelp": "\u0418\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432 \u0441\u0446\u0435\u043d \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043c\u0435\u043d\u044e \u0432\u044b\u0431\u043e\u0440\u0430 \u0441\u0446\u0435\u043d\u044b. \u0414\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u044b\u043c, \u043d\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u0438 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0433\u0438\u0433\u0430\u0431\u0430\u0439\u0442 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0430. \u041e\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043a\u0430\u043a \u0437\u0430\u0434\u0430\u0447\u0430, \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u0430\u044f \u043d\u0430 4:00 \u0443\u0442\u0440\u0430, \u043e\u0434\u043d\u0430\u043a\u043e, \u0435\u0451 \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0432 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u041d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447. \u041d\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443 \u0432 \u0447\u0430\u0441\u044b \u043f\u0438\u043a.", "LabelEnableAutomaticPortMapping": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0430\u0432\u0442\u043e\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u0440\u0442\u043e\u0432", - "LabelEnableAutomaticPortMappingHelp": "UPnP \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0442\u043e\u0440\u0430 \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430.\u042d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043d\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \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.", + "LabelEnableAutomaticPortMappingHelp": "UPnP \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0442\u043e\u0440\u0430 \u0434\u043b\u044f \u0443\u043f\u0440\u043e\u0449\u0451\u043d\u0438\u044f \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430.\u042d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043d\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \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.", "HeaderTermsOfService": "\u0423\u0441\u043b\u043e\u0432\u0438\u044f \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0443\u0441\u043b\u0443\u0433 Media Browser", "MessagePleaseAcceptTermsOfService": "\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435 \u0441\u043e\u0433\u043b\u0430\u0441\u0438\u0435 \u0441 \u0423\u0441\u043b\u043e\u0432\u0438\u044f\u043c\u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0443\u0441\u043b\u0443\u0433 \u0438 \u041f\u043e\u043b\u0438\u0442\u0438\u043a\u043e\u0439 \u043a\u043e\u043d\u0444\u0438\u0434\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438, \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c.", "OptionIAcceptTermsOfService": "\u042f \u0441\u043e\u0433\u043b\u0430\u0448\u0430\u044e\u0441\u044c \u0441 \u0423\u0441\u043b\u043e\u0432\u0438\u044f\u043c\u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0443\u0441\u043b\u0443\u0433", "ButtonPrivacyPolicy": "\u041f\u043e\u043b\u0438\u0442\u0438\u043a\u0430 \u043a\u043e\u043d\u0444\u0438\u0434\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438", "ButtonTermsOfService": "\u0423\u0441\u043b\u043e\u0432\u0438\u044f \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0443\u0441\u043b\u0443\u0433", + "HeaderDeveloperOptions": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432", + "OptionEnableWebClientResponseCache": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0442\u043a\u043b\u0438\u043a\u043e\u0432 \u0432\u0435\u0431-\u043a\u043b\u0438\u0435\u043d\u0442\u0430", + "OptionDisableForDevelopmentHelp": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u0442\u0435 \u0434\u0430\u043d\u043d\u043e\u0435, \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438, \u0432 \u0446\u0435\u043b\u044f\u0445 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u0435\u0431-\u043a\u043b\u0438\u0435\u043d\u0442\u0430.", + "OptionEnableWebClientResourceMinification": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043c\u0438\u043d\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044e \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0432\u0435\u0431-\u043a\u043b\u0438\u0435\u043d\u0442\u0430", + "LabelDashboardSourcePath": "\u041f\u0443\u0442\u044c \u043a \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0443 \u0432\u0435\u0431-\u043a\u043b\u0438\u0435\u043d\u0442\u0430:", + "LabelDashboardSourcePathHelp": "\u0415\u0441\u043b\u0438 \u0441\u0435\u0440\u0432\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043e\u0442 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0445 \u043a\u043e\u0434\u043e\u0432, \u0443\u043a\u0430\u0436\u0438\u0442\u0435 \u043f\u0443\u0442\u044c \u043a \u043f\u0430\u043f\u043a\u0435 dashboard-ui. \u0412\u0441\u0435 \u0444\u0430\u0439\u043b\u044b \u0432\u0435\u0431-\u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0431\u0443\u0434\u0443\u0442 \u043f\u043e\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0441 \u044d\u0442\u043e\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u0438\u044f.", + "ButtonConvertMedia": "\u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0435", + "ButtonOrganize": "\u0420\u0435\u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c", "ButtonOk": "\u041e\u041a", "ButtonCancel": "\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c", "ButtonNew": "\u0421\u043e\u0437\u0434\u0430\u0442\u044c", "HeaderTV": "\u0422\u0412", "HeaderAudio": "\u0410\u0443\u0434\u0438\u043e", "HeaderVideo": "\u0412\u0438\u0434\u0435\u043e", - "OptionDetectArchiveFilesAsMedia": "\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u0430\u0440\u0445\u0438\u0432\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u043a\u0430\u043a \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0435", - "OptionDetectArchiveFilesAsMediaHelp": "\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u0444\u0430\u0439\u043b\u044b \u0441 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f\u043c\u0438 .rar \u0438 .zip \u0431\u0443\u0434\u0443\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u044b \u043a\u0430\u043a \u043c\u0435\u0434\u0438\u0430\u0444\u0430\u0439\u043b\u044b.", + "HeaderPaths": "\u041f\u0443\u0442\u0438", + "CategorySync": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044f", + "HeaderEasyPinCode": "\u0423\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u044b\u0439 PIN-\u043a\u043e\u0434", + "RegisterWithPayPal": "\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 PayPal", + "HeaderSyncRequiresSupporterMembership": "\u0414\u043b\u044f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0447\u043b\u0435\u043d\u0441\u0442\u0432\u043e \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430", + "HeaderEnjoyDayTrial": "\u0412\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435\u0441\u044c 14-\u0434\u043d\u0435\u0432\u043d\u044b\u043c \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u043c \u043f\u0440\u043e\u0431\u043d\u044b\u043c \u043f\u0435\u0440\u0438\u043e\u0434\u043e\u043c", + "LabelSyncTempPath": "\u041f\u0443\u0442\u044c \u043a\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u043c\u0443 \u0444\u0430\u0439\u043b\u0443:", + "LabelSyncTempPathHelp": "\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0447\u0443\u044e \u043f\u0430\u043f\u043a\u0443 \u0434\u043b\u044f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438. \u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0435, \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0435 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438, \u0431\u0443\u0434\u0443\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c\u0441\u044f \u0437\u0434\u0435\u0441\u044c.", + "LabelCustomCertificatePath": "\u041f\u0443\u0442\u044c \u043a \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0443:", + "LabelCustomCertificatePathHelp": "\u041f\u043e\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u0441\u0432\u043e\u0439 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 SSL-\u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442. \u0415\u0441\u043b\u0438 \u043e\u043d \u043d\u0435 \u0443\u043a\u0430\u0437\u0430\u043d, \u0441\u0435\u0440\u0432\u0435\u0440 \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u0441\u0430\u043c\u043e\u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442.", + "TitleNotifications": "\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f", + "ButtonDonateWithPayPal": "\u041f\u043e\u0436\u0435\u0440\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 PayPal", + "OptionDetectArchiveFilesAsMedia": "\u0410\u0440\u0445\u0438\u0432\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u043a\u0430\u043a \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0435", + "OptionDetectArchiveFilesAsMediaHelp": "\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u0444\u0430\u0439\u043b\u044b \u0441 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f\u043c\u0438 .RAR \u0438 .ZIP \u0431\u0443\u0434\u0443\u0442 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043a\u0430\u043a \u043c\u0435\u0434\u0438\u0430\u0444\u0430\u0439\u043b\u044b.", "LabelEnterConnectUserName": "\u0418\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438\u043b\u0438 \u042d-\u043f\u043e\u0447\u0442\u0430", "LabelEnterConnectUserNameHelp": "\u042d\u0442\u043e - \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u044c \u0432\u0430\u0448\u0435\u0439 \u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u0443\u0447\u0451\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438 Media Browser.", "HeaderSyncJobInfo": "\u0417\u0430\u0434\u0430\u043d\u0438\u0435 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438", @@ -63,12 +83,14 @@ "FolderTypeTvShows": "\u0422\u0412", "FolderTypeInherit": "\u041d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u043c\u044b\u0439", "LabelContentType": "\u0422\u0438\u043f \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f:", + "TitleScheduledTasks": "\u041d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044b\u0435 \u0437\u0430\u0434\u0430\u0447\u0438", "HeaderSetupLibrary": "\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438", "ButtonAddMediaFolder": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043a\u0443", "LabelFolderType": "\u0422\u0438\u043f \u043f\u0430\u043f\u043a\u0438:", "ReferToMediaLibraryWiki": "\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435\u0441\u044c \u043a \u0432\u0438\u043a\u0438 \u043f\u043e \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0435.", "LabelCountry": "\u0421\u0442\u0440\u0430\u043d\u0430:", "LabelLanguage": "\u042f\u0437\u044b\u043a:", + "ButtonJoinTheDevelopmentTeam": "\u0412\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432", "HeaderPreferredMetadataLanguage": "\u041f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u0435\u043c\u044b\u0439 \u044f\u0437\u044b\u043a \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445:", "LabelSaveLocalMetadata": "\u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0438 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0432\u043d\u0443\u0442\u0440\u044c \u043c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043e\u043a", "LabelSaveLocalMetadataHelp": "\u041f\u0440\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0438 \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0439 \u0438 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0432\u043d\u0443\u0442\u0440\u044c \u043c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043e\u043a, \u043e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u0432 \u0442\u0430\u043a\u043e\u043c \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0438, \u0433\u0434\u0435 \u0438\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043b\u0435\u0433\u043a\u043e \u043f\u0440\u0430\u0432\u0438\u0442\u044c.", @@ -86,6 +108,8 @@ "TabCollectionTitles": "\u041f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f", "HeaderDeviceAccess": "\u0414\u043e\u0441\u0442\u0443\u043f \u0441 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430", "OptionEnableAccessFromAllDevices": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u0441\u043e \u0432\u0441\u0435\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432", + "OptionEnableAccessToAllChannels": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a\u043e \u0432\u0441\u0435\u043c \u043a\u0430\u043d\u0430\u043b\u0430\u043c", + "OptionEnableAccessToAllLibraries": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a\u043e \u0432\u0441\u0435\u043c \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0430\u043c", "DeviceAccessHelp": "\u042d\u0442\u043e \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043a \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043e\u0434\u043d\u043e\u0437\u043d\u0430\u0447\u043d\u043e \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u043d\u044b \u0438 \u043d\u0435 \u043f\u0440\u0435\u043f\u044f\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0443 \u0447\u0435\u0440\u0435\u0437 \u0431\u0440\u0430\u0443\u0437\u0435\u0440. \u0424\u0438\u043b\u044c\u0442\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u0437\u0430\u043f\u0440\u0435\u0442\u0438\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430, \u043f\u043e\u043a\u0430 \u043e\u043d\u0438 \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u043e\u0434\u043e\u0431\u0440\u0435\u043d\u044b \u0442\u0443\u0442.", "LabelDisplayMissingEpisodesWithinSeasons": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u044d\u043f\u0438\u0437\u043e\u0434\u044b \u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 \u0441\u0435\u0437\u043e\u043d\u043e\u0432", "LabelUnairedMissingEpisodesWithinSeasons": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0435 \u044d\u043f\u0438\u0437\u043e\u0434\u044b \u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 \u0441\u0435\u0437\u043e\u043d\u043e\u0432", @@ -184,7 +208,7 @@ "OptionCriticRating": "\u041e\u0446\u0435\u043d\u043a\u0430 \u043a\u0440\u0438\u0442\u0438\u043a\u043e\u0432", "OptionVideoBitrate": "\u041f\u043e\u0442\u043e\u043a. \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0432\u0438\u0434\u0435\u043e", "OptionResumable": "\u0412\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u0438\u043c\u044b\u0435", - "ScheduledTasksHelp": "\u0429\u0451\u043b\u043a\u043d\u0438\u0442\u0435 \u043f\u043e \u0437\u0430\u0434\u0430\u0447\u0435, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0435\u0433\u043e \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u0435.", + "ScheduledTasksHelp": "\u0429\u0451\u043b\u043a\u043d\u0438\u0442\u0435 \u043f\u043e \u0437\u0430\u0434\u0430\u0447\u0435, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0435\u0451 \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u0435.", "ScheduledTasksTitle": "\u041f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a", "TabMyPlugins": "\u041c\u043e\u0438 \u043f\u043b\u0430\u0433\u0438\u043d\u044b", "TabCatalog": "\u041a\u0430\u0442\u0430\u043b\u043e\u0433", @@ -195,7 +219,7 @@ "HeaderLatestSongs": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u043c\u0435\u043b\u043e\u0434\u0438\u0438", "HeaderRecentlyPlayed": "\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u0435 \u043d\u0435\u0434\u0430\u0432\u043d\u043e", "HeaderFrequentlyPlayed": "\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u0435 \u0447\u0430\u0441\u0442\u043e", - "DevBuildWarning": "\u0420\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c\u044b\u0435 \u0441\u0431\u043e\u0440\u043a\u0438 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0441\u044b\u0440\u044b\u043c\u0438 \u0438 \u043d\u0435\u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u044b\u043c\u0438. \u0412\u044b\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0447\u0430\u0441\u0442\u043e, \u044d\u0442\u0438 \u0441\u0431\u043e\u0440\u043a\u0438 \u043d\u0435 \u0431\u044b\u043b\u0438 \u043e\u0442\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0434\u043e \u043a\u043e\u043d\u0446\u0430. \u0420\u0430\u0431\u043e\u0442\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0430\u0432\u0430\u0440\u0438\u0439\u043d\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0442\u044c\u0441\u044f, \u0430 \u043c\u043d\u043e\u0433\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043c\u043e\u0433\u0443\u0442 \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u043e\u0432\u0441\u0435\u043c.", + "DevBuildWarning": "\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043e\u0447\u043d\u044b\u0435 \u0441\u0431\u043e\u0440\u043a\u0438 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0441\u044b\u0440\u044b\u043c\u0438 \u0438 \u043d\u0435\u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u044b\u043c\u0438. \u0412\u044b\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0447\u0430\u0441\u0442\u043e, \u044d\u0442\u0438 \u0441\u0431\u043e\u0440\u043a\u0438 \u043d\u0435 \u0431\u044b\u043b\u0438 \u043e\u0442\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0434\u043e \u043a\u043e\u043d\u0446\u0430. \u0420\u0430\u0431\u043e\u0442\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0430\u0432\u0430\u0440\u0438\u0439\u043d\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0442\u044c\u0441\u044f, \u0430 \u043c\u043d\u043e\u0433\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043c\u043e\u0433\u0443\u0442 \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u043e\u0432\u0441\u0435\u043c.", "LabelVideoType": "\u0422\u0438\u043f \u0432\u0438\u0434\u0435\u043e:", "OptionBluray": "BluRay", "OptionDvd": "DVD", @@ -222,7 +246,7 @@ "OptionParentalRating": "\u0412\u043e\u0437\u0440\u0430\u0441\u0442\u043d\u0430\u044f \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f", "OptionPremiereDate": "\u0414\u0430\u0442\u0430 \u043f\u0440\u0435\u043c\u044c\u0435\u0440\u044b", "TabBasic": "\u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0435", - "TabAdvanced": "\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e", + "TabAdvanced": "\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u043e\u0435", "HeaderStatus": "\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435", "OptionContinuing": "\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u0442\u0441\u044f", "OptionEnded": "\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u043b\u0441\u044f", @@ -275,20 +299,20 @@ "OptionMetascore": "\u041e\u0446\u0435\u043d\u043a\u0430 Metascore", "ButtonSelect": "\u0412\u044b\u0431\u0440\u0430\u0442\u044c", "ButtonGroupVersions": "\u0413\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0435\u0440\u0441\u0438\u0438", - "ButtonAddToCollection": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e", + "ButtonAddToCollection": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438", "PismoMessage": "Pismo File Mount \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u043e \u043f\u043e\u0434\u0430\u0440\u0435\u043d\u043d\u043e\u0439 \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u0438.", "TangibleSoftwareMessage": "\u041a\u043e\u043d\u0432\u0435\u0440\u0442\u0435\u0440\u044b Java\/C# \u043e\u0442 Tangible Solutions \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u043f\u043e \u043f\u043e\u0434\u0430\u0440\u0435\u043d\u043d\u043e\u0439 \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u0438.", - "HeaderCredits": "\u0423\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u0438", + "HeaderCredits": "\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u0430\u0432\u0442\u043e\u0440\u0441\u0442\u0432\u0430", "PleaseSupportOtherProduces": "\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0442\u0435 \u0438 \u0438\u043d\u043e\u0435 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0435 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043c\u044b \u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f:", "VersionNumber": "\u0412\u0435\u0440\u0441\u0438\u044f {0}", "TabPaths": "\u041f\u0443\u0442\u0438", "TabServer": "\u0421\u0435\u0440\u0432\u0435\u0440", "TabTranscoding": "\u041f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0430", - "TitleAdvanced": "\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e", + "TitleAdvanced": "\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u043e\u0435", "LabelAutomaticUpdateLevel": "\u0421\u0442\u0435\u043f\u0435\u043d\u044c \u0430\u0432\u0442\u043e\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f", "OptionRelease": "\u041e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u0432\u044b\u043f\u0443\u0441\u043a", "OptionBeta": "\u0411\u0435\u0442\u0430-\u0432\u0435\u0440\u0441\u0438\u044f", - "OptionDev": "\u0420\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c\u0430\u044f (\u043d\u0435\u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e)", + "OptionDev": "\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043e\u0447\u043d\u0430\u044f (\u043d\u0435\u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u0430\u044f)", "LabelAllowServerAutoRestart": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a \u0434\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439", "LabelAllowServerAutoRestartHelp": "\u0421\u0435\u0440\u0432\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u043f\u0435\u0440\u0438\u043e\u0434\u044b \u043f\u0440\u043e\u0441\u0442\u043e\u044f, \u043a\u043e\u0433\u0434\u0430 \u043d\u0438\u043a\u0430\u043a\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u043d\u0435 \u0430\u043a\u0442\u0438\u0432\u043d\u044b.", "LabelEnableDebugLogging": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u044b\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u0416\u0443\u0440\u043d\u0430\u043b\u0435", @@ -299,7 +323,7 @@ "LabelCachePath": "\u041f\u0443\u0442\u044c \u043a\u043e \u043a\u0435\u0448\u0443:", "LabelCachePathHelp": "\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\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 \u0440\u0438\u0441\u0443\u043d\u043a\u0430\u043c \u0447\u0435\u0440\u0435\u0437 \u0438\u043c\u044f:", - "LabelImagesByNamePathHelp": "\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\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.", + "LabelImagesByNamePathHelp": "\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\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, \u0436\u0430\u043d\u0440\u043e\u0432 \u0438 \u0441\u0442\u0443\u0434\u0438\u0439.", "LabelMetadataPath": "\u041f\u0443\u0442\u044c \u043a \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u043c:", "LabelMetadataPathHelp": "\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\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 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 \u043c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043e\u043a.", "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:", @@ -314,13 +338,15 @@ "OptionEpisodes": "\u0422\u0412 \u044d\u043f\u0438\u0437\u043e\u0434\u044b", "OptionOtherVideos": "\u0414\u0440\u0443\u0433\u0438\u0435 \u0432\u0438\u0434\u0435\u043e", "TitleMetadata": "\u041c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435", - "LabelAutomaticUpdatesFanart": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0430\u0432\u0442\u043e\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441 FanArt.tv", + "LabelAutomaticUpdates": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0430\u0432\u0442\u043e\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f", "LabelAutomaticUpdatesTmdb": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0430\u0432\u0442\u043e\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441 TheMovieDB.org", "LabelAutomaticUpdatesTvdb": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0430\u0432\u0442\u043e\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441 TheTVDB.com", "LabelAutomaticUpdatesFanartHelp": "\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u043d\u043e\u0432\u044b\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u0441\u0440\u0430\u0437\u0443 \u043f\u0440\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u043d\u0430 fanart.tv. \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u043c\u0435\u0449\u0430\u0442\u044c\u0441\u044f.", "LabelAutomaticUpdatesTmdbHelp": "\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u043d\u043e\u0432\u044b\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u0441\u0440\u0430\u0437\u0443 \u043f\u0440\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u043d\u0430 TheMovieDB.org. \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u043c\u0435\u0449\u0430\u0442\u044c\u0441\u044f.", "LabelAutomaticUpdatesTvdbHelp": "\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u043d\u043e\u0432\u044b\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u0441\u0440\u0430\u0437\u0443 \u043f\u0440\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u043d\u0430 TheTVDB.com. \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u043c\u0435\u0449\u0430\u0442\u044c\u0441\u044f.", - "ExtractChapterImagesHelp": "\u0418\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432 \u0441\u0446\u0435\u043d \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043c\u0435\u043d\u044e \u0432\u044b\u0431\u043e\u0440\u0430 \u0441\u0446\u0435\u043d\u044b. \u0414\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u044b\u043c, \u043d\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u0438 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0433\u0438\u0433\u0430\u0431\u0430\u0439\u0442 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0430. \u041e\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u0440\u0438 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u0438\u0438 \u043d\u043e\u0432\u044b\u0445 \u0432\u0438\u0434\u0435\u043e, \u0430 \u0442\u0430\u043a\u0436\u0435, \u043a\u0430\u043a \u0437\u0430\u0434\u0430\u0447\u0430, \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u0430\u044f \u043d\u0430 4:00 \u0443\u0442\u0440\u0430. \u0420\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0432 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u00ab\u041f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u0430\u00bb. \u041d\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443 \u0432 \u0447\u0430\u0441\u044b \u043f\u0438\u043a.", + "LabelFanartApiKey": "\u041b\u0438\u0447\u043d\u044b\u0439 API-\u043a\u043b\u044e\u0447:", + "LabelFanartApiKeyHelp": "\u0417\u0430\u043f\u0440\u043e\u0441\u044b \u043a Fanart \u0431\u0435\u0437 \u043b\u0438\u0447\u043d\u043e\u0433\u043e API-\u043a\u043b\u044e\u0447\u0430 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u044b\u043b\u0438 \u043e\u0434\u043e\u0431\u0440\u0435\u043d\u044b \u0441\u0432\u044b\u0448\u0435 7 \u0434\u043d\u0435\u0439 \u043d\u0430\u0437\u0430\u0434. \u0421 \u043b\u0438\u0447\u043d\u044b\u043c API-\u043a\u043b\u044e\u0447\u043e\u043c - \u0441\u0440\u043e\u043a \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u0442\u0441\u044f \u0434\u043e 48 \u0447\u0430\u0441\u043e\u0432, \u0430 \u0435\u0441\u043b\u0438 \u0432\u044b \u0442\u0430\u043a\u0436\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0435\u0441\u044c VIP-\u0447\u043b\u0435\u043d\u043e\u043c Fanart, \u0442\u043e \u0443\u043c\u0435\u043d\u044c\u0448\u0438\u0442\u0441\u044f \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u0447\u0442\u0438 \u0434\u043e 10 \u043c\u0438\u043d\u0443\u0442.", + "ExtractChapterImagesHelp": "\u0418\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432 \u0441\u0446\u0435\u043d \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043c\u0435\u043d\u044e \u0432\u044b\u0431\u043e\u0440\u0430 \u0441\u0446\u0435\u043d\u044b. \u0414\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u044b\u043c, \u043d\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u0438 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0433\u0438\u0433\u0430\u0431\u0430\u0439\u0442 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0430. \u041e\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u0440\u0438 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u0438\u0438 \u043d\u043e\u0432\u044b\u0445 \u0432\u0438\u0434\u0435\u043e, \u0430 \u0442\u0430\u043a\u0436\u0435, \u043a\u0430\u043a \u0437\u0430\u0434\u0430\u0447\u0430, \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u0430\u044f \u043d\u0430 4:00 \u0443\u0442\u0440\u0430. \u0420\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0432 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u041d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447. \u041d\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443 \u0432 \u0447\u0430\u0441\u044b \u043f\u0438\u043a.", "LabelMetadataDownloadLanguage": "\u041f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u0435\u043c\u044b\u0439 \u044f\u0437\u044b\u043a \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u043e\u0433\u043e:", "ButtonAutoScroll": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0430\u0432\u0442\u043e\u043f\u0440\u043e\u043a\u0440\u0443\u0442\u043a\u0443", "LabelImageSavingConvention": "\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432:", @@ -355,7 +381,7 @@ "TabSettings": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b", "ButtonRefreshGuideData": "\u041f\u043e\u0434\u043d\u043e\u0432\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0433\u0438\u0434\u0430", "ButtonRefresh": "\u041f\u043e\u0434\u043d\u043e\u0432\u0438\u0442\u044c", - "ButtonAdvancedRefresh": "\u041f\u043e\u0434\u043d\u043e\u0432\u0438\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e", + "ButtonAdvancedRefresh": "\u041f\u043e\u0434\u043d\u043e\u0432\u0438\u0442\u044c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u043e", "OptionPriority": "\u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442", "OptionRecordOnAllChannels": "\u0417\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0443 \u0441\u043e \u0432\u0441\u0435\u0445 \u043a\u0430\u043d\u0430\u043b\u043e\u0432", "OptionRecordAnytime": "\u0417\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0443 \u0432 \u043b\u044e\u0431\u043e\u0435 \u0432\u0440\u0435\u043c\u044f", @@ -482,11 +508,12 @@ "SystemDlnaProfilesHelp": "\u0421\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0435 \u043f\u0440\u043e\u0444\u0438\u043b\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0447\u0442\u0435\u043d\u0438\u044f. \u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043a \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u043c\u0443 \u043f\u0440\u043e\u0444\u0438\u043b\u044e \u0431\u0443\u0434\u0443\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u044b \u0432 \u043d\u043e\u0432\u043e\u043c \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c\u043e\u043c \u043f\u0440\u043e\u0444\u0438\u043b\u0435.", "TitleDashboard": "\u0418\u043d\u0444\u043e\u043f\u0430\u043d\u0435\u043b\u044c", "TabHome": "\u0413\u043b\u0430\u0432\u043d\u043e\u0435", - "TabInfo": "\u0421\u0432\u0435\u0434\u0435\u043d\u0438\u044f", + "TabInfo": "\u041e \u043f\u0440\u043e\u0444\u0438\u043b\u0435", "HeaderLinks": "\u0421\u0441\u044b\u043b\u043a\u0438", "HeaderSystemPaths": "\u0421\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0435 \u043f\u0443\u0442\u0438", "LinkCommunity": "\u0421\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e", - "LinkGithub": "\u0420\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 Github", + "LinkGithub": "GitHub", + "LinkApi": "API", "LinkApiDocumentation": "\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u043f\u043e API", "LabelFriendlyServerName": "\u041f\u043e\u043d\u044f\u0442\u043d\u043e\u0435 \u0438\u043c\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u0430:", "LabelFriendlyServerNameHelp": "\u0414\u0430\u043d\u043d\u043e\u0435 \u0438\u043c\u044f \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u0432\u0430\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430. \u0415\u0441\u043b\u0438 \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u043b\u0435 \u043d\u0435\u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u043c, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0438\u043c\u044f \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0430.", @@ -494,20 +521,25 @@ "LabelPreferredDisplayLanguageHelp": "\u041f\u0435\u0440\u0435\u0432\u043e\u0434 Media Browser \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c \u043d\u0430\u0445\u043e\u0434\u044f\u0449\u0438\u043c\u0441\u044f \u0432 \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0438 \u0438 \u0432\u0441\u0451 \u0435\u0449\u0451 \u043d\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d.", "LabelReadHowYouCanContribute": "\u0427\u0438\u0442\u0430\u0439\u0442\u0435 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0432\u043d\u0435\u0441\u0442\u0438 \u0441\u0432\u043e\u0439 \u0432\u043a\u043b\u0430\u0434.", "HeaderNewCollection": "\u041d\u043e\u0432\u0430\u044f \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f", - "HeaderAddToCollection": "\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0432 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e", "ButtonSubmit": "\u0412\u043d\u0435\u0441\u0442\u0438", - "NewCollectionNameExample": "\u041f\u0440\u0438\u043c\u0435\u0440: \u0417\u0432\u0451\u0437\u0434\u043d\u044b\u0435 \u0432\u043e\u0439\u043d\u044b (\u041a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f)", - "OptionSearchForInternetMetadata": "\u0418\u0441\u043a\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 \u0432 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435", "ButtonCreate": "\u0421\u043e\u0437\u0434\u0430\u0442\u044c", - "LabelLocalHttpServerPortNumber": "\u041d\u043e\u043c\u0435\u0440 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u043e\u0440\u0442\u0430:", + "LabelCustomCss": "\u041d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c\u044b\u0435 css:", + "LabelCustomCssHelp": "\u041f\u0440\u0438\u043c\u0435\u043d\u044f\u0439\u0442\u0435 \u0441\u0432\u043e\u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c\u044b\u0435 css \u043a \u0432\u0435\u0431-\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443.", + "LabelLocalHttpServerPortNumber": "\u041d\u043e\u043c\u0435\u0440 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e HTTP-\u043f\u043e\u0440\u0442\u0430:", "LabelLocalHttpServerPortNumberHelp": "TCP-\u043f\u043e\u0440\u0442, \u043a\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 HTTP-\u0441\u0435\u0440\u0432\u0435\u0440 Media Browser \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u043c\u0435\u0442\u044c \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0443.", - "LabelPublicPort": "\u041d\u043e\u043c\u0435\u0440 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u043e\u0433\u043e \u043f\u043e\u0440\u0442\u0430:", - "LabelPublicPortHelp": "\u041d\u043e\u043c\u0435\u0440 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u043e\u0433\u043e \u043f\u043e\u0440\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u043c\u0435\u0442\u044c \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u043c \u043f\u043e\u0440\u0442\u043e\u043c.", + "LabelPublicHttpPort": "\u041d\u043e\u043c\u0435\u0440 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u043e\u0433\u043e HTTP-\u043f\u043e\u0440\u0442\u0430:", + "LabelPublicHttpPortHelp": "\u041f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 \u043d\u043e\u043c\u0435\u0440 \u043f\u043e\u0440\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0441 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u043c HTTP-\u043f\u043e\u0440\u0442\u043e\u043c.", + "LabelPublicHttpsPort": "\u041d\u043e\u043c\u0435\u0440 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u043e\u0433\u043e HTTPS-\u043f\u043e\u0440\u0442\u0430:", + "LabelPublicHttpsPortHelp": "\u041f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 \u043d\u043e\u043c\u0435\u0440 \u043f\u043e\u0440\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0441 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u043c HTTPS-\u043f\u043e\u0440\u0442\u043e\u043c.", + "LabelEnableHttps": "\u0412\u044b\u0434\u0430\u0432\u0430\u0442\u044c HTTPS \u043a\u0430\u043a \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u0430\u0434\u0440\u0435\u0441", + "LabelEnableHttpsHelp": "\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u0441\u0435\u0440\u0432\u0435\u0440 \u0432\u044b\u0434\u0430\u0441\u0442 HTTPS URL \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c, \u043a\u0430\u043a \u0435\u0433\u043e \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u0430\u0434\u0440\u0435\u0441. \u042d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0435\u0440\u0432\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0435\u0449\u0451 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b https.", + "LabelHttpsPort": "\u041d\u043e\u043c\u0435\u0440 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e HTTPS-\u043f\u043e\u0440\u0442\u0430:", + "LabelHttpsPortHelp": "\u041d\u043e\u043c\u0435\u0440 TCP-\u043f\u043e\u0440\u0442\u0430, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 HTTPS-\u0441\u0435\u0440\u0432\u0435\u0440 Media Browser \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d.", "LabelWebSocketPortNumber": "\u041d\u043e\u043c\u0435\u0440 \u043f\u043e\u0440\u0442\u0430 \u0432\u0435\u0431-\u0441\u043e\u043a\u0435\u0442\u0430:", "LabelEnableAutomaticPortMap": "\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", "LabelEnableAutomaticPortMapHelp": "\u041f\u043e\u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 \u043f\u043e\u0440\u0442 \u0441 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u043c \u043f\u043e\u0440\u0442\u043e\u043c \u0447\u0435\u0440\u0435\u0437 UPnP. \u042d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043d\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \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.", - "LabelExternalDDNS": "\u0412\u043d\u0435\u0448\u043d\u0438\u0439 DDNS-\u0434\u043e\u043c\u0435\u043d:", - "LabelExternalDDNSHelp": "\u0415\u0441\u043b\u0438 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0439 DNS, \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u0435\u0433\u043e \u0437\u0434\u0435\u0441\u044c. \u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f Media Browser \u0431\u0443\u0434\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043f\u0440\u0438 \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u043e\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438.", + "LabelExternalDDNS": "\u0412\u043d\u0435\u0448\u043d\u0438\u0439 WAN-\u0430\u0434\u0440\u0435\u0441:", + "LabelExternalDDNSHelp": "\u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0439 DNS, \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u0435\u0433\u043e \u0437\u0434\u0435\u0441\u044c. \u042d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438 Media Browser \u043f\u0440\u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u043d\u043e\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438. \u041e\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u043f\u0443\u0441\u0442\u044b\u043c \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u0438\u044f.", "TabResume": "\u0412\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435", "TabWeather": "\u041f\u043e\u0433\u043e\u0434\u0430", "TitleAppSettings": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f", @@ -519,7 +551,7 @@ "LabelMinResumeDurationHelp": "\u041f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0432\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u0438\u043c\u044b\u043c\u0438 \u043f\u0440\u0438 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043c\u0435\u043d\u0435\u0435 \u0434\u0430\u043d\u043d\u043e\u0433\u043e", "TitleAutoOrganize": "\u0410\u0432\u0442\u043e\u0440\u0435\u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044f", "TabActivityLog": "\u0416\u0443\u0440\u043d\u0430\u043b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439", - "HeaderName": "\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435", + "HeaderName": "\u0418\u043c\u044f (\u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435)", "HeaderDate": "\u0414\u0430\u0442\u0430", "HeaderSource": "\u041e\u0442\u043a\u0443\u0434\u0430", "HeaderDestination": "\u041a\u0443\u0434\u0430", @@ -534,7 +566,7 @@ "LabelEpisodeNumber": "\u041d\u043e\u043c\u0435\u0440 \u044d\u043f\u0438\u0437\u043e\u0434\u0430:", "LabelEndingEpisodeNumber": "\u041d\u043e\u043c\u0435\u0440 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0433\u043e \u044d\u043f\u0438\u0437\u043e\u0434\u0430:", "LabelEndingEpisodeNumberHelp": "\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u043e\u0432, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0445 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u044d\u043f\u0438\u0437\u043e\u0434\u043e\u0432", - "HeaderSupportTheTeam": "\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0434\u043b\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u044b Media Browser", + "HeaderSupportTheTeam": "\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0442\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 Media Browser", "LabelSupportAmount": "\u0421\u0443\u043c\u043c\u0430 (USD)", "HeaderSupportTheTeamHelp": "\u041f\u043e\u043c\u043e\u0433\u0438\u0442\u0435 \u043f\u043e\u0436\u0435\u0440\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u044f\u043c\u0438 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0435 \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0435 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u0427\u0430\u0441\u0442\u044c \u0432\u0441\u0435\u0445 \u043f\u043e\u0436\u0435\u0440\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u043b\u043e\u0436\u0435\u043d\u0430 \u0432 \u0438\u043d\u043e\u0435 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0435 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u0435, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043c\u044b \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c.", "ButtonEnterSupporterKey": "\u0412\u0432\u0435\u0441\u0442\u0438 \u043a\u043b\u044e\u0447 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430", @@ -570,11 +602,12 @@ "HeaderRunningTasks": "\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0449\u0438\u0435\u0441\u044f \u0437\u0430\u0434\u0430\u0447\u0438", "HeaderActiveDevices": "\u0410\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430", "HeaderPendingInstallations": "\u041e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438", - "HeaderServerInformation": "\u0421\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0435", + "HeaderServerInformation": "\u041e \u0441\u0435\u0440\u0432\u0435\u0440\u0435", "ButtonRestartNow": "\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043d\u0435\u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e", "ButtonRestart": "\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c", "ButtonShutdown": "\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443", "ButtonUpdateNow": "\u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u043d\u0435\u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e", + "TabHosting": "\u0425\u043e\u0441\u0442\u0438\u043d\u0433", "PleaseUpdateManually": "\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u0435 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u0435 \u0432\u0440\u0443\u0447\u043d\u0443\u044e.", "NewServerVersionAvailable": "\u0418\u043c\u0435\u0435\u0442\u0441\u044f \u043d\u043e\u0432\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f Media Browser Server!", "ServerUpToDate": "Media Browser Server - \u043e\u0431\u043d\u043e\u0432\u043b\u0451\u043d", @@ -595,7 +628,7 @@ "LabelSupporterEmailAddress": "\u0410\u0434\u0440\u0435\u0441 \u042d-\u043f\u043e\u0447\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u044b\u043b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u0434\u043b\u044f \u043f\u0440\u0438\u043e\u0431\u0440\u0435\u0442\u0435\u043d\u0438\u044f \u043a\u043b\u044e\u0447\u0430.", "ButtonRetrieveKey": "\u0412\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043a\u043b\u044e\u0447", "LabelSupporterKey": "\u041a\u043b\u044e\u0447 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430 (\u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0438\u0437 \u043f\u0438\u0441\u044c\u043c\u0430 \u043f\u043e \u042d-\u043f\u043e\u0447\u0442\u0435)", - "LabelSupporterKeyHelp": "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043a\u043b\u044e\u0447 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0447\u0430\u0442\u044c \u043d\u0430\u0441\u043b\u0430\u0436\u0434\u0430\u0442\u044c\u0441\u044f \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u044b\u043b\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u044b \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e\u043c \u0434\u043b\u044f Media Browser.", + "LabelSupporterKeyHelp": "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043a\u043b\u044e\u0447 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0447\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u044b\u043b\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u044b \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e\u043c \u0434\u043b\u044f Media Browser.", "MessageInvalidKey": "\u041a\u043b\u044e\u0447 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0438\u043b\u0438 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c.", "ErrorMessageInvalidKey": "\u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043b\u044e\u0431\u043e\u0435 \u043f\u0440\u0435\u043c\u0438\u0443\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435, \u0432\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0442\u0430\u043a\u0436\u0435 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u043e\u043c Media Browser. \u0421\u0434\u0435\u043b\u0430\u0439\u0442\u0435 \u043f\u043e\u0436\u0435\u0440\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0442\u0435 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0443\u044e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043e\u0441\u043d\u043e\u0432\u043e\u043f\u043e\u043b\u0430\u0433\u0430\u044e\u0449\u0435\u0433\u043e \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430.", "HeaderDisplaySettings": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f", @@ -636,6 +669,7 @@ "NotificationOptionInstallationFailed": "\u0421\u0431\u043e\u0439 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438", "NotificationOptionNewLibraryContent": "\u041d\u043e\u0432\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e", "NotificationOptionNewLibraryContentMultiple": "\u041d\u043e\u0432\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e (\u043c\u043d\u043e\u0433\u043e\u043a\u0440\u0430\u0442\u043d\u043e)", + "NotificationOptionCameraImageUploaded": "\u0424\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u044f \u0441 \u043a\u0430\u043c\u0435\u0440\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0430", "SendNotificationHelp": "\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432 \u044f\u0449\u0438\u043a \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0432 \u00ab\u0418\u043d\u0444\u043e\u043f\u0430\u043d\u0435\u043b\u0438\u00bb. \u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439.", "NotificationOptionServerRestartRequired": "\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0430", "LabelNotificationEnabled": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u043e\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435", @@ -646,7 +680,7 @@ "CategorySystem": "\u0421\u0438\u0441\u0442\u0435\u043c\u0430", "CategoryApplication": "\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435", "CategoryPlugin": "\u041f\u043b\u0430\u0433\u0438\u043d", - "LabelMessageTitle": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f:", + "LabelMessageTitle": "\u0422\u0435\u043a\u0441\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f:", "LabelAvailableTokens": "\u0418\u043c\u0435\u044e\u0449\u0438\u0435\u0441\u044f \u043c\u0430\u0440\u043a\u0435\u0440\u044b:", "AdditionalNotificationServices": "\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u043b\u0443\u0436\u0431\u044b \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439.", "OptionAllUsers": "\u0412\u0441\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438", @@ -778,7 +812,7 @@ "OptionEnableM2tsMode": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0440\u0435\u0436\u0438\u043c M2ts", "OptionEnableM2tsModeHelp": "\u0412\u043a\u043b\u044e\u0447\u0430\u0439\u0442\u0435 \u0440\u0435\u0436\u0438\u043c M2ts \u043f\u0440\u0438 \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0434\u043b\u044f mpegts.", "OptionEstimateContentLength": "\u0420\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u0434\u043b\u0438\u043d\u0443 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0435", - "OptionReportByteRangeSeekingWhenTranscoding": "\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u044f\u0442\u044c \u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u043f\u043e\u0431\u0430\u0439\u0442\u043e\u0432\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u043e\u0442\u043a\u0438 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0435", + "OptionReportByteRangeSeekingWhenTranscoding": "\u0412\u044b\u0434\u0430\u0432\u0430\u0442\u044c, \u0447\u0442\u043e \u0441\u0435\u0440\u0432\u0435\u0440 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043f\u043e\u0431\u0430\u0439\u0442\u043e\u0432\u0443\u044e \u043f\u0435\u0440\u0435\u043c\u043e\u0442\u043a\u0443 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0435", "OptionReportByteRangeSeekingWhenTranscodingHelp": "\u042d\u0442\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u0435\u043b\u0430\u044e\u0442 \u043f\u043e\u0432\u0440\u0435\u043c\u0451\u043d\u043d\u0443\u044e \u043f\u0435\u0440\u0435\u043c\u043e\u0442\u043a\u0443 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e.", "HeaderSubtitleDownloadingHelp": "\u0412 Media Browser \u043f\u0440\u0438 \u0441\u043a\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0432\u0438\u0434\u0435\u043e\u0444\u0430\u0439\u043b\u043e\u0432 \u0438\u043c\u0435\u044e\u0442\u0441\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043f\u043e\u0438\u0441\u043a \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u044e\u0449\u0438\u0445 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u043e\u0432 \u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0438\u0445 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u043e\u0441\u0442\u0430\u0432\u0449\u0438\u043a\u0430 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u043e\u0432, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, OpenSubtitles.org.", "HeaderDownloadSubtitlesFor": "\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u043e\u0432 \u0434\u043b\u044f:", @@ -853,8 +887,10 @@ "OptionDefaultSort": "\u0423\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u0435", "OptionCommunityMostWatchedSort": "\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043d\u044b\u0435 \u0431\u043e\u043b\u044c\u0448\u0435", "TabNextUp": "\u041e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0435", + "HeaderBecomeMediaBrowserSupporter": "\u0421\u0442\u0430\u043d\u044c\u0442\u0435 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u043e\u043c Media Browser", + "TextEnjoyBonusFeatures": "\u0412\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435\u0441\u044c \u0431\u043e\u043d\u0443\u0441\u043d\u044b\u043c\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438", "MessageNoMovieSuggestionsAvailable": "\u0412 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u043d\u0435 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u043c\u044b\u0445 \u0444\u0438\u043b\u044c\u043c\u043e\u0432. \u041d\u0430\u0447\u043d\u0438\u0442\u0435 \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0438 \u043e\u0446\u0435\u043d\u0438\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0438 \u0444\u0438\u043b\u044c\u043c\u044b, \u0438 \u0442\u043e\u0433\u0434\u0430 \u0432\u0435\u0440\u043d\u0438\u0442\u0435\u0441\u044c \u043d\u0430\u0437\u0430\u0434, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438.", - "MessageNoCollectionsAvailable": "\u041a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0442 \u0432\u0430\u043c \u043d\u0430\u0441\u043b\u0430\u0436\u0434\u0430\u0442\u044c\u0441\u044f \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0444\u0438\u043b\u044c\u043c\u043e\u0432, \u0441\u0435\u0440\u0438\u0430\u043b\u043e\u0432, \u0430\u043b\u044c\u0431\u043e\u043c\u043e\u0432, \u043a\u043d\u0438\u0433 \u0438 \u0438\u0433\u0440. \u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u043a\u043d\u043e\u043f\u043a\u0443 +, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u043a \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439.", + "MessageNoCollectionsAvailable": "\u041a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0442 \u0432\u0430\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0444\u0438\u043b\u044c\u043c\u043e\u0432, \u0441\u0435\u0440\u0438\u0430\u043b\u043e\u0432, \u0430\u043b\u044c\u0431\u043e\u043c\u043e\u0432, \u043a\u043d\u0438\u0433 \u0438 \u0438\u0433\u0440. \u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u043a\u043d\u043e\u043f\u043a\u0443 +, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u043a \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439.", "MessageNoPlaylistsAvailable": "\u0421\u043f\u0438\u0441\u043a\u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0441\u043f\u0438\u0441\u043a\u043e\u0432 \u0438\u0437 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 \u0440\u0430\u0437\u043e\u043c. \u0427\u0442\u043e\u0431\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0432\u043e \u0441\u043f\u0438\u0441\u043a\u0438, \u0449\u0435\u043b\u043a\u043d\u0438\u0442\u0435 \u043f\u0440\u0430\u0432\u043e\u0439 \u043a\u043d\u043e\u043f\u043a\u043e\u0439 \u043c\u044b\u0448\u0438 \u0438\u043b\u0438 \u043a\u043e\u0441\u043d\u0438\u0442\u0435\u0441\u044c \u0438 \u0443\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0439\u0442\u0435, \u0437\u0430\u0442\u0435\u043c \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u00ab\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432\u043e \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f\u00bb.", "MessageNoPlaylistItemsAvailable": "\u0414\u0430\u043d\u043d\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0432 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u043f\u0443\u0441\u0442.", "ButtonDismiss": "\u0421\u043a\u0440\u044b\u0442\u044c", @@ -869,7 +905,6 @@ "LabelChannelDownloadAge": "\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437, \u0434\u043d\u0438:", "LabelChannelDownloadAgeHelp": "\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u0441\u0442\u0430\u0440\u0448\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u0443\u0434\u0430\u043b\u0435\u043d\u043e. \u041e\u043d\u043e \u043e\u0441\u0442\u0430\u043d\u0435\u0442\u0441\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043c\u044b\u043c \u043f\u043e \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u0442\u0440\u0430\u043d\u0441\u043b\u044f\u0446\u0438\u0438.", "ChannelSettingsFormHelp": "\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u043a\u0430\u043d\u0430\u043b\u044b (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: Trailers \u0438\u043b\u0438 Vimeo) \u0438\u0437 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432.", - "LabelSelectCollection": "\u0412\u044b\u0431\u043e\u0440 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438:", "ButtonOptions": "\u0412\u0430\u0440\u0438\u0430\u043d\u0442\u044b", "ViewTypeMovies": "\u041a\u0438\u043d\u043e", "ViewTypeTvShows": "\u0422\u0412", @@ -915,9 +950,9 @@ "OptionLibraryFolders": "\u041c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043a\u0438", "TitleRemoteControl": "\u0423\u0434\u0430\u043b\u0451\u043d\u043d\u043e\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435", "OptionLatestTvRecordings": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0437\u0430\u043f\u0438\u0441\u0438", - "LabelProtocolInfo": "\u0421\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0435:", + "LabelProtocolInfo": "\u041e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0435:", "LabelProtocolInfoHelp": "\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u043e\u0442\u043a\u043b\u0438\u043a\u0435 \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u044b GetProtocolInfo \u043e\u0442 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430.", - "TabKodiMetadata": "Kodi", + "TabNfo": "NFO-\u0444\u0430\u0439\u043b\u044b", "HeaderKodiMetadataHelp": "\u0412 Media Browser \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u0430\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0434\u043b\u044f Kodi-\u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0432 NFO-\u0444\u0430\u0439\u043b\u0430\u0445 \u0438 \u0434\u043b\u044f \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432. \u0414\u043b\u044f \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f Kodi-\u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0432\u043a\u043b\u0430\u0434\u043a\u0443 \u00ab\u0421\u043b\u0443\u0436\u0431\u044b\u00bb, \u0447\u0442\u043e\u0431\u044b \u0434\u043b\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043f\u043e \u0442\u0438\u043f\u0430\u043c \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445.", "LabelKodiMetadataUser": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043e \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435 \u0441 NFO-\u0444\u0430\u0439\u043b\u0430\u043c\u0438 \u0434\u043b\u044f:", "LabelKodiMetadataUserHelp": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u0435, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044e \u0434\u0430\u043d\u043d\u044b\u0445 \u043e \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043d\u043e\u043c \u043c\u0435\u0436\u0434\u0443 Media Browser \u0438 Kodi.", @@ -931,14 +966,15 @@ "LabelGroupChannelsIntoViews": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 \u043c\u043e\u0438\u0445 \u0430\u0441\u043f\u0435\u043a\u0442\u043e\u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u043a\u0430\u043d\u0430\u043b\u043e\u0432:", "LabelGroupChannelsIntoViewsHelp": "\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u0434\u0430\u043d\u043d\u044b\u0435 \u043a\u0430\u043d\u0430\u043b\u044b \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u043d\u0430\u0440\u044f\u0434\u0443 \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0430\u0441\u043f\u0435\u043a\u0442\u0430\u043c\u0438. \u041f\u0440\u0438 \u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u043e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0430\u0441\u043f\u0435\u043a\u0442\u0430 \u00ab\u041a\u0430\u043d\u0430\u043b\u044b\u00bb.", "LabelDisplayCollectionsView": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u0430\u0441\u043f\u0435\u043a\u0442 \u041a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u0444\u0438\u043b\u044c\u043c\u043e\u0432", + "LabelDisplayCollectionsViewHelp": "\u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0430\u0441\u043f\u0435\u043a\u0442 \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439, \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0445 \u0432\u0430\u043c\u0438 \u0438\u043b\u0438 \u043a \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0438\u043c\u0435\u0435\u0442\u0435 \u0434\u043e\u0441\u0442\u0443\u043f. \u0427\u0442\u043e\u0431\u044b \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e, \u0449\u0435\u043b\u043a\u043d\u0438\u0442\u0435 \u043f\u0440\u0430\u0432\u043e\u0439 \u043a\u043d\u043e\u043f\u043a\u043e\u0439 \u043c\u044b\u0448\u0438 \u0438\u043b\u0438 \u043a\u043e\u0441\u043d\u0438\u0442\u0435\u0441\u044c \u0438 \u0443\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0439\u0442\u0435 \u043b\u044e\u0431\u043e\u0439 \u0444\u0438\u043b\u044c\u043c, \u0438 \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \"\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438\".", "LabelKodiMetadataEnableExtraThumbs": "\u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c extrafanart \u0432\u043d\u0443\u0442\u0440\u044c extrathumbs", "LabelKodiMetadataEnableExtraThumbsHelp": "\u041f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432, \u0438\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u044c extrafanart \u0438 extrathumbs \u0434\u043b\u044f \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u0438 \u0441 \u043e\u0431\u043e\u043b\u043e\u0447\u043a\u043e\u0439 Kodi.", "TabServices": "\u0421\u043b\u0443\u0436\u0431\u044b", "TabLogs": "\u0416\u0443\u0440\u043d\u0430\u043b\u044b", "HeaderServerLogFiles": "\u0424\u0430\u0439\u043b\u044b \u0436\u0443\u0440\u043d\u0430\u043b\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430:", - "TabBranding": "\u0411\u0440\u0435\u043d\u0434\u0438\u043d\u0433", - "HeaderBrandingHelp": "\u041e\u0431\u043e\u0441\u043e\u0431\u044c\u0442\u0435 \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u0432\u0438\u0434 Media Browser \u0434\u043b\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u044f \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u044f\u043c \u0432\u0430\u0448\u0435\u0439 \u0433\u0440\u0443\u043f\u043f\u044b \u0438\u043b\u0438 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438.", - "LabelLoginDisclaimer": "\u041e\u0433\u043e\u0432\u043e\u0440\u043a\u0430 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u0432\u0445\u043e\u0434\u0430:", + "TabBranding": "\u041e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u0435", + "HeaderBrandingHelp": "\u041f\u043e\u0434\u0441\u0442\u0440\u043e\u0439\u0442\u0435 \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u0435 Media Browser \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u0432\u0430\u0448\u0435\u0439 \u0433\u0440\u0443\u043f\u043f\u044b \u0438\u043b\u0438 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438.", + "LabelLoginDisclaimer": "\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u0432\u0445\u043e\u0434\u0435:", "LabelLoginDisclaimerHelp": "\u042d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0432 \u043d\u0438\u0436\u043d\u0435\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0432\u0445\u043e\u0434\u0430 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443.", "LabelAutomaticallyDonate": "\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0436\u0435\u0440\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u0441\u0443\u043c\u043c\u0443 \u043a\u0430\u0436\u0434\u044b\u0439 \u043c\u0435\u0441\u044f\u0446", "LabelAutomaticallyDonateHelp": "\u041c\u043e\u0436\u043d\u043e \u0432 \u043b\u044e\u0431\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043e\u0442\u043c\u0435\u043d\u0438\u0442\u044c \u044d\u0442\u043e \u0447\u0435\u0440\u0435\u0437 \u0441\u0432\u043e\u044e \u0443\u0447\u0435\u0442\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c PayPal.", @@ -951,7 +987,7 @@ "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": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u0438\u0437 \u043c\u0443\u0437\u044b\u043a\u0438", - "HeaderBranding": "\u0411\u0440\u0435\u043d\u0434\u0438\u043d\u0433", + "HeaderBranding": "\u041e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u0435", "HeaderApiKeys": "API-\u043a\u043b\u044e\u0447\u0438", "HeaderApiKeysHelp": "\u0412\u043d\u0435\u0448\u043d\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f API-\u043a\u043b\u044e\u0447 \u0434\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a Media Browser. \u041a\u043b\u044e\u0447\u0438 \u0432\u044b\u0434\u0430\u044e\u0442\u0441\u044f \u043f\u0440\u0438 \u0432\u0445\u043e\u0434\u0435 \u0441 \u0443\u0447\u0451\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u044c\u044e Media Browser \u0438\u043b\u0438 \u043a\u043b\u044e\u0447 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e \u0432\u0440\u0443\u0447\u043d\u0443\u044e.", "HeaderApiKey": "API-\u043a\u043b\u044e\u0447", @@ -982,7 +1018,7 @@ "LabelSortName": "\u0421\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c\u043e\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435:", "LabelDateAdded": "\u0414\u0430\u0442\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f:", "HeaderFeatures": "\u041c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u044b", - "HeaderAdvanced": "\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e", + "HeaderAdvanced": "\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u043e\u0435", "ButtonSync": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c", "TabScheduledTasks": "\u041f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a", "HeaderChapters": "\u0421\u0446\u0435\u043d\u044b", @@ -1084,12 +1120,15 @@ "LabelDisplayFoldersView": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u0430\u0441\u043f\u0435\u043a\u0442 \u041f\u0430\u043f\u043a\u0438, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043e\u0431\u044b\u0447\u043d\u044b\u0435 \u043c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043a\u0438", "ViewTypeLiveTvRecordingGroups": "\u0417\u0430\u043f\u0438\u0441\u0438", "ViewTypeLiveTvChannels": "\u041a\u0430\u043d\u0430\u043b\u044b", - "LabelAllowLocalAccessWithoutPassword": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0434\u043e\u0441\u0442\u0443\u043f \u0431\u0435\u0437 \u043f\u0430\u0440\u043e\u043b\u044f", - "LabelAllowLocalAccessWithoutPasswordHelp": "\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438, \u043f\u0430\u0440\u043e\u043b\u044c \u043d\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0432\u0445\u043e\u0434\u0430 \u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 \u0432\u0430\u0448\u0435\u0439 \u0434\u043e\u043c\u0430\u0448\u043d\u0435\u0439 \u0441\u0435\u0442\u0438.", + "LabelEasyPinCode": "\u0423\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u044b\u0439 PIN-\u043a\u043e\u0434:", + "EasyPasswordHelp": "\u0412\u0430\u0448 \u0443\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u044b\u0439 PIN-\u043a\u043e\u0434 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043d\u043e\u043c\u043d\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0441 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 Media Browser, \u0438 \u043c\u043e\u0436\u0435\u0442 \u0442\u0430\u043a\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0443\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u043e\u0433\u043e \u0432\u043d\u0443\u0442\u0440\u0438\u0441\u0435\u0442\u0435\u0432\u043e\u0433\u043e \u0432\u0445\u043e\u0434\u0430.", + "LabelInNetworkSignInWithEasyPassword": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0438\u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u0432\u0445\u043e\u0434 \u0441 \u043c\u043e\u0438\u043c \u0443\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u044b\u043c PIN-\u043a\u043e\u0434\u043e\u043c", + "LabelInNetworkSignInWithEasyPasswordHelp": "\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u0432\u044b \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0430\u0448 \u0443\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u044b\u0439 PIN-\u043a\u043e\u0434 \u0434\u043b\u044f \u0432\u0445\u043e\u0434\u0430 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f Media Browser \u0438\u0437\u043d\u0443\u0442\u0440\u0438 \u0432\u0430\u0448\u0435\u0439 \u0434\u043e\u043c\u0430\u0448\u043d\u0435\u0439 \u0441\u0435\u0442\u0438. \u0412\u0430\u0448 \u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u043f\u0430\u0440\u043e\u043b\u044c \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u043d\u0435 \u0434\u043e\u043c\u0430. \u0415\u0441\u043b\u0438 PIN-\u043a\u043e\u0434 \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u043c, \u0442\u043e \u0432\u0430\u043c \u043d\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0430\u0440\u043e\u043b\u044c \u0432\u043d\u0443\u0442\u0440\u0438 \u0432\u0430\u0448\u0435\u0439 \u0434\u043e\u043c\u0430\u0448\u043d\u0435\u0439 \u0441\u0435\u0442\u0438.", "HeaderPassword": "\u041f\u0430\u0440\u043e\u043b\u044c", "HeaderLocalAccess": "\u041b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0434\u043e\u0441\u0442\u0443\u043f", "HeaderViewOrder": "\u041f\u043e\u0440\u044f\u0434\u043e\u043a \u0430\u0441\u043f\u0435\u043a\u0442\u043e\u0432", - "LabelSelectUserViewOrder": "\u0423\u043f\u043e\u0440\u044f\u0434\u043e\u0447\u044c\u0442\u0435 \u0430\u0441\u043f\u0435\u043a\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 Media Browser", + "ButtonResetEasyPassword": "\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c \u0443\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u044b\u0439 PIN-\u043a\u043e\u0434", + "LabelSelectUserViewOrder": "\u0412\u044b\u0431\u043e\u0440 \u043f\u043e\u0440\u044f\u0434\u043a\u0430 \u0430\u0441\u043f\u0435\u043a\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 Media Browser", "LabelMetadataRefreshMode": "\u0420\u0435\u0436\u0438\u043c \u043f\u043e\u0434\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445:", "LabelImageRefreshMode": "\u0420\u0435\u0436\u0438\u043c \u043f\u043e\u0434\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432:", "OptionDownloadMissingImages": "\u041f\u043e\u0434\u0433\u0440\u0443\u0437\u043a\u0430 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432", @@ -1098,7 +1137,7 @@ "OptionAddMissingDataOnly": "\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0442\u0441\u0443\u0442-\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445", "OptionLocalRefreshOnly": "\u041f\u043e\u0434\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0435", "HeaderRefreshMetadata": "\u041f\u043e\u0434\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445", - "HeaderPersonInfo": "\u0421\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e \u043f\u0435\u0440\u0441\u043e\u043d\u0435", + "HeaderPersonInfo": "\u041e \u043f\u0435\u0440\u0441\u043e\u043d\u0435", "HeaderIdentifyItem": "\u0420\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u043d\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430", "HeaderIdentifyItemHelp": "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043e\u0434\u043d\u043e \u0438\u043b\u0438 \u0431\u043e\u043b\u0435\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u0439 \u043f\u043e\u0438\u0441\u043a\u0430. \u0414\u043b\u044f \u043f\u0440\u0438\u0440\u043e\u0441\u0442\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u043f\u043e\u0438\u0441\u043a\u0430 \u0443\u0431\u0435\u0440\u0438\u0442\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u0435.", "HeaderConfirmDeletion": "\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f", @@ -1132,7 +1171,7 @@ "LabelPlayers": "\u0418\u0433\u0440\u043e\u043a\u0438:", "Label3DFormat": "\u0424\u043e\u0440\u043c\u0430\u0442 3D:", "HeaderAlternateEpisodeNumbers": "\u0410\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0435 \u043d\u043e\u043c\u0435\u0440\u0430 \u044d\u043f\u0438\u0437\u043e\u0434\u043e\u0432", - "HeaderSpecialEpisodeInfo": "\u0421\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u043c \u044d\u043f\u0438\u0437\u043e\u0434\u0435", + "HeaderSpecialEpisodeInfo": "\u041e \u0441\u043f\u0435\u0446\u044d\u043f\u0438\u0437\u043e\u0434\u0435", "HeaderExternalIds": "\u0412\u043d\u0435\u0448\u043d\u0438\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b:", "LabelDvdSeasonNumber": "\u041d\u043e\u043c\u0435\u0440 DVD-\u0441\u0435\u0437\u043e\u043d\u0430:", "LabelDvdEpisodeNumber": "\u041d\u043e\u043c\u0435\u0440 DVD-\u044d\u043f\u0438\u0437\u043e\u0434\u0430:", @@ -1171,15 +1210,15 @@ "OptionWriter": "\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0441\u0442", "LabelAirDays": "\u0414\u043d\u0438 \u044d\u0444\u0438\u0440\u0430:", "LabelAirTime": "\u0412\u0440\u0435\u043c\u044f \u044d\u0444\u0438\u0440\u0430:", - "HeaderMediaInfo": "\u0421\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445", - "HeaderPhotoInfo": "\u0421\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e \u0444\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0438", + "HeaderMediaInfo": "\u041e \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445", + "HeaderPhotoInfo": "\u041e \u0444\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0438", "HeaderInstall": "\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430", "LabelSelectVersionToInstall": "\u0412\u044b\u0431\u043e\u0440 \u0432\u0435\u0440\u0441\u0438\u0438 \u0434\u043b\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438:", "LinkSupporterMembership": "\u0423\u0437\u043d\u0430\u0442\u044c \u043e \u0447\u043b\u0435\u043d\u0441\u0442\u0432\u0435 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430", "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.", "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.", "HeaderReviews": "\u041e\u0442\u0437\u044b\u0432\u044b", - "HeaderDeveloperInfo": "\u0421\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u0445", + "HeaderDeveloperInfo": "\u041e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u0445", "HeaderRevisionHistory": "\u0418\u0441\u0442\u043e\u0440\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439", "ButtonViewWebsite": "\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432\u0435\u0431\u0441\u0430\u0439\u0442", "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.", @@ -1192,7 +1231,7 @@ "LabelExtractChaptersDuringLibraryScanHelp": "\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u0441\u0446\u0435\u043d \u0431\u0443\u0434\u0443\u0442 \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u044b, \u043a\u043e\u0433\u0434\u0430 \u0432\u0438\u0434\u0435\u043e \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0441\u043a\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438. \u041f\u0440\u0438 \u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u043e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u044b \u0432 \u0442\u0435\u0447\u0435\u043d\u0438\u0435 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 \u00ab\u0420\u0438\u0441\u0443\u043d\u043a\u0438 \u0441\u0446\u0435\u043d\u00bb, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044f \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e\u043c\u0443 \u0441\u043a\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0442\u044c\u0441\u044f \u0431\u044b\u0441\u0442\u0440\u0435\u0435.", "LabelConnectGuestUserName": "\u0418\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f Media Browser \u0438\u043b\u0438 \u0430\u0434\u0440\u0435\u0441 \u044d-\u043f\u043e\u0447\u0442\u044b:", "LabelConnectUserName": "\u0418\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f Media Browser \/ \u044d-\u043f\u043e\u0447\u0442\u0430:", - "LabelConnectUserNameHelp": "\u0421\u043e\u0435\u0434\u0438\u043d\u0438\u0442\u0435 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f c \u0443\u0447\u0451\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u044c\u044e Media Browser, \u0447\u0442\u043e\u0431\u044b \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0443\u0434\u043e\u0431\u043d\u043e\u043c\u0443 \u0432\u0445\u043e\u0434\u0443 \u0438\u0437 \u043b\u044e\u0431\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f Media Browser \u0431\u0435\u0437 \u043d\u0430\u0434\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u0437\u043d\u0430\u0442\u044c IP-\u0430\u0434\u0440\u0435\u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430.", + "LabelConnectUserNameHelp": "\u0421\u043e\u0435\u0434\u0438\u043d\u0438\u0442\u0435 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f c \u0443\u0447\u0451\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u044c\u044e Media Browser, \u0447\u0442\u043e\u0431\u044b \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0443\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u043e\u043c\u0443 \u0432\u0445\u043e\u0434\u0443 \u0438\u0437 \u043b\u044e\u0431\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f Media Browser \u0431\u0435\u0437 \u043d\u0430\u0434\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u0437\u043d\u0430\u0442\u044c IP-\u0430\u0434\u0440\u0435\u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430.", "ButtonLearnMoreAboutMediaBrowserConnect": "\u0423\u0437\u043d\u0430\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0435 \u043e Media Browser Connect", "LabelExternalPlayers": "\u0412\u043d\u0435\u0448\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0433\u0440\u044b\u0432\u0430\u0442\u0435\u043b\u0438:", "LabelExternalPlayersHelp": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442\u0441\u044f \u043a\u043d\u043e\u043f\u043a\u0438 \u0434\u043b\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f \u0432\u043e \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u043f\u0440\u043e\u0438\u0433\u0440\u044b\u0432\u0430\u0442\u0435\u043b\u044f\u0445. \u041e\u043d\u0438 \u0438\u043c\u0435\u044e\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u0445, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0449\u0438\u0445 URL-\u0441\u0445\u0435\u043c\u044b, \u043e\u0431\u044b\u0447\u043d\u043e, \u0432 Android \u0438 iOS. \u0412\u043e \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u043f\u0440\u043e\u0438\u0433\u0440\u044b\u0432\u0430\u0442\u0435\u043b\u044f\u0445, \u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u043e\u0433\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u0432\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f.", @@ -1210,7 +1249,7 @@ "LabelSubtitleFormatHelp": "\u041f\u0440\u0438\u043c\u0435\u0440: srt", "ButtonLearnMore": "\u0423\u0437\u043d\u0430\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0435", "TabPlayback": "\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435", - "HeaderTrailersAndExtras": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440\u044b \u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u044b", + "HeaderTrailersAndExtras": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440\u044b \u0438 \u0434\u043e\u043f. \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u044b", "OptionFindTrailers": "\u041d\u0430\u0445\u043e\u0434\u0438\u0442\u044c \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u044b \u0432 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438", "HeaderLanguagePreferences": "\u042f\u0437\u044b\u043a\u043e\u0432\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438", "TabCinemaMode": "\u0420\u0435\u0436\u0438\u043c \u043a\u0438\u043d\u043e\u0442\u0435\u0430\u0442\u0440\u0430", @@ -1241,16 +1280,16 @@ "LabelDateAddedBehaviorHelp": "\u0415\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0432 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445, \u0442\u043e \u043e\u043d\u043e \u0432\u0441\u0435\u0433\u0434\u0430 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043e \u043b\u044e\u0431\u043e\u0433\u043e \u0438\u0437 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432.", "LabelNumberTrailerToPlay": "\u0427\u0438\u0441\u043b\u043e \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043e\u0432 \u0434\u043b\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f:", "TitleDevices": "\u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430", - "TabCameraUpload": "\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0441 \u043a\u0430\u043c\u0435\u0440\u044b", + "TabCameraUpload": "\u0421 \u043a\u0430\u043c\u0435\u0440\u044b", "TabDevices": "\u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430", "HeaderCameraUploadHelp": "\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u043e\u0442\u0441\u043d\u044f\u0442\u044b\u0445 \u0444\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0439 \u0438 \u0432\u0438\u0434\u0435\u043e \u0438\u0437 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432 \u0432 Media Browser.", "MessageNoDevicesSupportCameraUpload": "\u041d\u0435\u0442 \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0449\u0438\u0445 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 \u0441 \u043a\u0430\u043c\u0435\u0440\u044b.", "LabelCameraUploadPath": "\u041f\u0443\u0442\u044c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u043e\u0433\u043e \u0441 \u043a\u0430\u043c\u0435\u0440\u044b:", - "LabelCameraUploadPathHelp": "\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u043f\u0443\u0442\u044c, \u043f\u043e \u0436\u0435\u043b\u0430\u043d\u0438\u044e. \u0415\u0441\u043b\u0438 \u043d\u0435 \u0437\u0430\u0434\u0430\u043d\u043e, \u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0430 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430\u044f \u043f\u0430\u043f\u043a\u0430. \u0415\u0441\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u043f\u0443\u0442\u044c, \u0442\u043e \u0435\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0442\u0430\u043a\u0436\u0435 \u0432 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438.", + "LabelCameraUploadPathHelp": "\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u043f\u0443\u0442\u044c, \u043f\u043e \u0436\u0435\u043b\u0430\u043d\u0438\u044e. \u0415\u0441\u043b\u0438 \u043d\u0435 \u0437\u0430\u0434\u0430\u043d\u043e, \u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0430 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430\u044f \u043f\u0430\u043f\u043a\u0430. \u0415\u0441\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u043f\u0443\u0442\u044c, \u0442\u043e \u0435\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0442\u0430\u043a\u0436\u0435 \u0432 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438.", "LabelCreateCameraUploadSubfolder": "\u0421\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u043e\u0434\u043f\u0430\u043f\u043a\u0443 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430", "LabelCreateCameraUploadSubfolderHelp": "\u0421\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043f\u0430\u043f\u043a\u0438 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u044b \u0434\u043b\u044f \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u043f\u0440\u0438 \u0449\u0435\u043b\u0447\u043a\u0435 \u043d\u0430 \u043d\u0451\u043c \u0441\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \"\u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\".", "LabelCustomDeviceDisplayName": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u043e\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435:", - "LabelCustomDeviceDisplayNameHelp": "\u041f\u0440\u0438\u0432\u0435\u0434\u0438\u0442\u0435 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c\u043e\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u043e\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u043f\u043e\u043b\u0435 \u043d\u0435\u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u043c, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435, \u0441\u043e\u043e\u0431\u0449\u0451\u043d\u043d\u043e\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u043c.", + "LabelCustomDeviceDisplayNameHelp": "\u041f\u0440\u0438\u0432\u0435\u0434\u0438\u0442\u0435 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c\u043e\u0435 \u0438\u043c\u044f \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u043e\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u043f\u043e\u043b\u0435 \u043d\u0435\u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u043c, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043c\u044f, \u0432\u044b\u0434\u0430\u043d\u043d\u043e\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u043c.", "HeaderInviteUser": "\u041f\u0440\u0438\u0433\u043b\u0430\u0448\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f", "LabelConnectGuestUserNameHelp": "\u0418\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0432\u0430\u0448 \u0434\u0440\u0443\u0433 \u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0432\u0445\u043e\u0434\u0430 \u043d\u0430 \u0432\u0435\u0431-\u0441\u0430\u0439\u0442 Media Browser, \u0438\u043b\u0438 \u0430\u0434\u0440\u0435\u0441 \u044d-\u043f\u043e\u0447\u0442\u044b.", "HeaderInviteUserHelp": "Media Browser Connect \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u0440\u0443\u0437\u044c\u044f\u043c \u043e\u0431\u0449\u0435\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0432\u0430\u0448\u0438\u043c \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u043c.", @@ -1279,7 +1318,7 @@ "MessageNoTrailersFound": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440\u044b \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u044b. \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u043a\u0430\u043d\u0430\u043b \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0443\u0441\u0438\u043b\u0438\u0442\u044c \u0432\u0430\u0448\u0435 \u0432\u043f\u0435\u0447\u0430\u0442\u043b\u0435\u043d\u0438\u0435 \u043e\u0442 \u0444\u0438\u043b\u044c\u043c\u0430 \u043f\u0443\u0442\u0451\u043c \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u043e\u0431\u0440\u0430\u043d\u0438\u044f \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043e\u0432.", "HeaderNewUsers": "\u041d\u043e\u0432\u044b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438", "ButtonSignUp": "\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f", - "ButtonForgotPassword": "\u0417\u0430\u0431\u044b\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u044c?", + "ButtonForgotPassword": "\u041d\u0430\u043f\u043e\u043c\u043d\u0438\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c", "OptionDisableUserPreferences": "\u0417\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c", "OptionDisableUserPreferencesHelp": "\u0415\u0441\u043b\u0438 \u0444\u043b\u0430\u0436\u043e\u043a \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d, \u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u044b \u0441\u043c\u043e\u0433\u0443\u0442 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0444\u0438\u043b\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0440\u0438\u0441\u0443\u043d\u043a\u0438, \u043f\u0430\u0440\u043e\u043b\u0438 \u0438 \u044f\u0437\u044b\u043a\u043e\u0432\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438.", "HeaderSelectServer": "\u0412\u044b\u0431\u043e\u0440 \u0441\u0435\u0440\u0432\u0435\u0440\u0430", @@ -1290,7 +1329,7 @@ "HeaderLibraryAccess": "\u0414\u043e\u0441\u0442\u0443\u043f \u043a \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0435", "HeaderChannelAccess": "\u0414\u043e\u0441\u0442\u0443\u043f \u043a \u043a\u0430\u043d\u0430\u043b\u0430\u043c", "HeaderLatestItems": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b", - "LabelSelectLastestItemsFolders": "\u041e\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0440\u0430\u0437\u0434\u0435\u043b\u043e\u0432 \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0445", + "LabelSelectLastestItemsFolders": "\u041e\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u0435 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0440\u0430\u0437\u0434\u0435\u043b\u043e\u0432 \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0445", "HeaderShareMediaFolders": "\u041e\u0431\u0449\u0438\u0439 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043a\u0430\u043c", "MessageGuestSharingPermissionsHelp": "\u041c\u043d\u043e\u0433\u0438\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0434\u043b\u044f \u0433\u043e\u0441\u0442\u0435\u0439, \u043d\u043e \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u044b \u043f\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438.", "HeaderInvitations": "\u041f\u0440\u0438\u0433\u043b\u0430\u0448\u0435\u043d\u0438\u044f", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json index 1935fba93..93ef75dc3 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/server.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json @@ -40,12 +40,32 @@ "OptionIAcceptTermsOfService": "I accept the terms of service", "ButtonPrivacyPolicy": "Privacy policy", "ButtonTermsOfService": "Terms of Service", + "HeaderDeveloperOptions": "Developer Options", + "OptionEnableWebClientResponseCache": "Enable web client response caching", + "OptionDisableForDevelopmentHelp": "Configure these as needed for web client development purposes.", + "OptionEnableWebClientResourceMinification": "Enable web client resource minification", + "LabelDashboardSourcePath": "Web client source path:", + "LabelDashboardSourcePathHelp": "If running the server from source, specify the path to the dashboard-ui folder. All web client files will be served from this location.", + "ButtonConvertMedia": "Convert media", + "ButtonOrganize": "Organize", "ButtonOk": "Ok", "ButtonCancel": "Cancel", "ButtonNew": "New", "HeaderTV": "TV", "HeaderAudio": "Audio", "HeaderVideo": "Video", + "HeaderPaths": "Paths", + "CategorySync": "Sync", + "HeaderEasyPinCode": "Easy Pin Code", + "RegisterWithPayPal": "Register with PayPal", + "HeaderSyncRequiresSupporterMembership": "Sync Requires a Supporter Membership", + "HeaderEnjoyDayTrial": "Enjoy a 14 Day Free Trial", + "LabelSyncTempPath": "Temporary file path:", + "LabelSyncTempPathHelp": "Specify a custom sync working folder. Converted media created during the sync process will be stored here.", + "LabelCustomCertificatePath": "Custom certificate path:", + "LabelCustomCertificatePathHelp": "Supply your own ssl certificate. If omitted, the server will create a self-signed certificate.", + "TitleNotifications": "Notifications", + "ButtonDonateWithPayPal": "Donate with PayPal", "OptionDetectArchiveFilesAsMedia": "Detect archive files as media", "OptionDetectArchiveFilesAsMediaHelp": "If enabled, files with .rar and .zip extensions will be detected as media files.", "LabelEnterConnectUserName": "User name or email:", @@ -63,12 +83,14 @@ "FolderTypeTvShows": "TV", "FolderTypeInherit": "Inherit", "LabelContentType": "Content type:", + "TitleScheduledTasks": "Scheduled Tasks", "HeaderSetupLibrary": "Setup your media library", "ButtonAddMediaFolder": "Add media folder", "LabelFolderType": "Folder type:", "ReferToMediaLibraryWiki": "Refer to the media library wiki.", "LabelCountry": "Country:", "LabelLanguage": "Language:", + "ButtonJoinTheDevelopmentTeam": "Join the Development Team", "HeaderPreferredMetadataLanguage": "Preferred metadata language:", "LabelSaveLocalMetadata": "Save artwork and metadata into media folders", "LabelSaveLocalMetadataHelp": "Saving artwork and metadata directly into media folders will put them in a place where they can be easily edited.", @@ -86,6 +108,8 @@ "TabCollectionTitles": "Titles", "HeaderDeviceAccess": "Device Access", "OptionEnableAccessFromAllDevices": "Enable access from all devices", + "OptionEnableAccessToAllChannels": "Enable access to all channels", + "OptionEnableAccessToAllLibraries": "Enable access to all libraries", "DeviceAccessHelp": "This only applies to devices that can be uniquely identified and will not prevent browser access. Filtering user device access will prevent them from using new devices until they've been approved here.", "LabelDisplayMissingEpisodesWithinSeasons": "Display missing episodes within seasons", "LabelUnairedMissingEpisodesWithinSeasons": "Display unaired episodes within seasons", @@ -299,7 +323,7 @@ "LabelCachePath": "Cache path:", "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.", "LabelImagesByNamePath": "Images by name path:", - "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, genre and studio images.", "LabelMetadataPath": "Metadata path:", "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.", "LabelTranscodingTempPath": "Transcoding temporary path:", @@ -314,12 +338,14 @@ "OptionEpisodes": "Episodes", "OptionOtherVideos": "Other Videos", "TitleMetadata": "Metadata", - "LabelAutomaticUpdatesFanart": "Enable automatic updates from FanArt.tv", + "LabelAutomaticUpdates": "Enable automatic updates", "LabelAutomaticUpdatesTmdb": "Enable automatic updates from TheMovieDB.org", "LabelAutomaticUpdatesTvdb": "Enable automatic updates from TheTVDB.com", "LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.", "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.", "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.", + "LabelFanartApiKey": "Personal api key:", + "LabelFanartApiKeyHelp": "Requests to fanart without a personal API key return results that were approved over 7 days ago. With a personal API key that drops to 48 hours and if you are also a fanart VIP member that will further drop to around 10 minutes.", "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", "LabelMetadataDownloadLanguage": "Preferred download language:", "ButtonAutoScroll": "Auto-scroll", @@ -489,6 +515,7 @@ "HeaderSystemPaths": "System Paths", "LinkCommunity": "Community", "LinkGithub": "Github", + "LinkApi": "Api", "LinkApiDocumentation": "Api Documentation", "LabelFriendlyServerName": "Friendly server name:", "LabelFriendlyServerNameHelp": "This name will be used to identify this server. If left blank, the computer name will be used.", @@ -496,20 +523,25 @@ "LabelPreferredDisplayLanguageHelp": "Translating Media Browser is an ongoing project and is not yet complete.", "LabelReadHowYouCanContribute": "Read about how you can contribute.", "HeaderNewCollection": "New Collection", - "HeaderAddToCollection": "Add to Collection", "ButtonSubmit": "Submit", - "NewCollectionNameExample": "Example: Star Wars Collection", - "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata", "ButtonCreate": "Create", - "LabelLocalHttpServerPortNumber": "Local port number:", + "LabelCustomCss": "Custom css:", + "LabelCustomCssHelp": "Apply your own custom css to the web interface.", + "LabelLocalHttpServerPortNumber": "Local http port number:", "LabelLocalHttpServerPortNumberHelp": "The tcp port number that Media Browser's http server should bind to.", - "LabelPublicPort": "Public port number:", - "LabelPublicPortHelp": "The public port number that should be mapped to the local port.", + "LabelPublicHttpPort": "Public http port number:", + "LabelPublicHttpPortHelp": "The public port number that should be mapped to the local http port.", + "LabelPublicHttpsPort": "Public https port number:", + "LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.", + "LabelEnableHttps": "Report https as external address", + "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.", + "LabelHttpsPort": "Local https port number:", + "LabelHttpsPortHelp": "The tcp port number that Media Browser's https server should bind to.", "LabelWebSocketPortNumber": "Web socket port number:", "LabelEnableAutomaticPortMap": "Enable automatic port mapping", "LabelEnableAutomaticPortMapHelp": "Attempt to automatically map the public port to the local port via UPnP. This may not work with some router models.", - "LabelExternalDDNS": "External DDNS:", - "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely.", + "LabelExternalDDNS": "External WAN Address:", + "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely. Leave empty for automatic detection.", "TabResume": "Resume", "TabWeather": "Weather", "TitleAppSettings": "App Settings", @@ -578,6 +610,7 @@ "ButtonRestart": "Restart", "ButtonShutdown": "Shutdown", "ButtonUpdateNow": "Update Now", + "TabHosting": "Hosting", "PleaseUpdateManually": "Please shutdown the server and update manually.", "NewServerVersionAvailable": "A new version of Media Browser Server is available!", "ServerUpToDate": "Media Browser Server is up to date", @@ -639,6 +672,7 @@ "NotificationOptionInstallationFailed": "Installation failure", "NotificationOptionNewLibraryContent": "New content added", "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", + "NotificationOptionCameraImageUploaded": "Camera image uploaded", "SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.", "NotificationOptionServerRestartRequired": "Server restart required", "LabelNotificationEnabled": "Enable this notification", @@ -862,6 +896,8 @@ "OptionDefaultSort": "Default", "OptionCommunityMostWatchedSort": "Most Watched", "TabNextUp": "Next Up", + "HeaderBecomeMediaBrowserSupporter": "Become a Media Browser Supporter", + "TextEnjoyBonusFeatures": "Enjoy Bonus Features", "MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.", "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.", "MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.", @@ -878,7 +914,6 @@ "LabelChannelDownloadAge": "Delete content after: (days)", "LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.", "ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.", - "LabelSelectCollection": "Select collection:", "ButtonOptions": "Options", "ViewTypeMovies": "Movies", "ViewTypeTvShows": "TV", @@ -926,7 +961,7 @@ "OptionLatestTvRecordings": "Latest recordings", "LabelProtocolInfo": "Protocol info:", "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.", - "TabKodiMetadata": "Kodi", + "TabNfo": "Nfo", "HeaderKodiMetadataHelp": "Media Browser includes native support for Kodi Nfo metadata and images. To enable or disable Kodi metadata, use the Advanced tab to configure options for your media types.", "LabelKodiMetadataUser": "Sync user watch data to nfo's for:", "LabelKodiMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Kodi.", @@ -940,6 +975,7 @@ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:", "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.", "LabelDisplayCollectionsView": "Display a collections view to show movie collections", + "LabelDisplayCollectionsViewHelp": "This will create a separate view to display collections that you've created or have access to. To create a collection, right-click or tap-hold any movie and select 'Add to Collection'. ", "LabelKodiMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs", "LabelKodiMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Kodi skin compatibility.", "TabServices": "Services", @@ -1097,11 +1133,14 @@ "LabelDisplayFoldersView": "Display a folders view to show plain media folders", "ViewTypeLiveTvRecordingGroups": "Recordings", "ViewTypeLiveTvChannels": "Channels", - "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password", - "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.", + "LabelEasyPinCode": "Easy pin code:", + "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Media Browser apps, and can also be used for easy in-network sign in.", + "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", + "LabelInNetworkSignInWithEasyPasswordHelp": "If enabled, you'll be able to use your easy pin code to sign in to Media Browser apps from inside your home network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", "HeaderPassword": "Password", "HeaderLocalAccess": "Local Access", "HeaderViewOrder": "View Order", + "ButtonResetEasyPassword": "Reset easy pin code", "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps", "LabelMetadataRefreshMode": "Metadata refresh mode:", "LabelImageRefreshMode": "Image refresh mode:", @@ -1295,7 +1334,7 @@ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.", "HeaderNewUsers": "New Users", "ButtonSignUp": "Sign up", - "ButtonForgotPassword": "Forgot password?", + "ButtonForgotPassword": "Forgot password", "OptionDisableUserPreferences": "Disable access to user preferences", "OptionDisableUserPreferencesHelp": "If enabled, only administrators will be able to configure user profile images, passwords, and language preferences.", "HeaderSelectServer": "Select Server", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/sv.json b/MediaBrowser.Server.Implementations/Localization/Server/sv.json index 0b42c976e..e3d1d54a8 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/sv.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/sv.json @@ -4,8 +4,8 @@ "LabelGithub": "Github", "LabelSwagger": "Swagger", "LabelStandard": "F\u00f6rval", - "LabelApiDocumentation": "Api Documentation", - "LabelDeveloperResources": "Developer Resources", + "LabelApiDocumentation": "Api Dokumentation", + "LabelDeveloperResources": "Resurser f\u00f6r utvecklare", "LabelBrowseLibrary": "Bl\u00e4ddra i biblioteket", "LabelConfigureMediaBrowser": "Konfigurera Media Browser", "LabelOpenLibraryViewer": "\u00d6ppna biblioteksbl\u00e4ddraren", @@ -19,7 +19,7 @@ "TitleMediaBrowser": "Media Browser", "ThisWizardWillGuideYou": "Den h\u00e4r guiden hj\u00e4lper dig att g\u00f6ra de f\u00f6rsta inst\u00e4llningarna. F\u00f6r att b\u00f6rja var v\u00e4nlig v\u00e4lj \u00f6nskat spr\u00e5k.", "TellUsAboutYourself": "Ber\u00e4tta om dig sj\u00e4lv", - "ButtonQuickStartGuide": "Quick start guide", + "ButtonQuickStartGuide": "Snabbstartguide", "LabelYourFirstName": "Ditt f\u00f6rnamn:", "MoreUsersCanBeAddedLater": "Flera anv\u00e4ndare kan skapas senare i Kontrollpanelen.", "UserProfilesIntro": "Media Browser har inbyggt st\u00f6d f\u00f6r anv\u00e4ndarprofiler, s\u00e5 varje anv\u00e4ndare kan ha sina egna utseendeinst\u00e4llningar, visad-markeringar och f\u00f6r\u00e4ldral\u00e5s.", @@ -35,23 +35,43 @@ "LabelChapterImageExtractionForMoviesHelp": "Detta m\u00f6jligg\u00f6r grafisk visning av menyer f\u00f6r val av kapitel. Processen kan vara tids- och CPU-kr\u00e4vande och beh\u00f6va flera gigabyte lagringsutrymme. Processen k\u00f6rs varje natt kl 04:00 men intervallet kan anpassas enligt \u00f6nskem\u00e5l i Schemal\u00e4ggaren. Vi rekommenderar inte att den k\u00f6rs vid tider d\u00e5 anv\u00e4ndare \u00e4r aktiva.", "LabelEnableAutomaticPortMapping": "Aktivera automatisk koppling av portar", "LabelEnableAutomaticPortMappingHelp": "UPnP m\u00f6jligg\u00f6r automatisk inst\u00e4llning av din router s\u00e5 att du enkelt kan n\u00e5 Media Browser fr\u00e5n Internet. Detta kanske inte fungerar med alla routrar.", - "HeaderTermsOfService": "Media Browser Terms of Service", - "MessagePleaseAcceptTermsOfService": "Please accept the terms of service and privacy policy before continuing.", - "OptionIAcceptTermsOfService": "I accept the terms of service", - "ButtonPrivacyPolicy": "Privacy policy", - "ButtonTermsOfService": "Terms of Service", + "HeaderTermsOfService": "Media Browser Villkor", + "MessagePleaseAcceptTermsOfService": "V\u00e4nligen acceptera anv\u00e4ndarvillkoren och sekretesspolicy innan du forts\u00e4tter.", + "OptionIAcceptTermsOfService": "Jag accepterar anv\u00e4ndarvillkoren", + "ButtonPrivacyPolicy": "sekretesspolicy", + "ButtonTermsOfService": "Anv\u00e4ndarvillkor", + "HeaderDeveloperOptions": "Developer Options", + "OptionEnableWebClientResponseCache": "Enable web client response caching", + "OptionDisableForDevelopmentHelp": "Configure these as needed for web client development purposes.", + "OptionEnableWebClientResourceMinification": "Enable web client resource minification", + "LabelDashboardSourcePath": "Web client source path:", + "LabelDashboardSourcePathHelp": "If running the server from source, specify the path to the dashboard-ui folder. All web client files will be served from this location.", + "ButtonConvertMedia": "Convert media", + "ButtonOrganize": "Organize", "ButtonOk": "OK", "ButtonCancel": "Avbryt", "ButtonNew": "Nytillkommet", "HeaderTV": "TV", "HeaderAudio": "Ljud", "HeaderVideo": "Video", - "OptionDetectArchiveFilesAsMedia": "Detect archive files as media", - "OptionDetectArchiveFilesAsMediaHelp": "If enabled, files with .rar and .zip extensions will be detected as media files.", - "LabelEnterConnectUserName": "User name or email:", + "HeaderPaths": "Paths", + "CategorySync": "Sync", + "HeaderEasyPinCode": "Easy Pin Code", + "RegisterWithPayPal": "Register with PayPal", + "HeaderSyncRequiresSupporterMembership": "Sync Requires a Supporter Membership", + "HeaderEnjoyDayTrial": "Enjoy a 14 Day Free Trial", + "LabelSyncTempPath": "Temporary file path:", + "LabelSyncTempPathHelp": "Specify a custom sync working folder. Converted media created during the sync process will be stored here.", + "LabelCustomCertificatePath": "Custom certificate path:", + "LabelCustomCertificatePathHelp": "Supply your own ssl certificate. If omitted, the server will create a self-signed certificate.", + "TitleNotifications": "Notifications", + "ButtonDonateWithPayPal": "Donate with PayPal", + "OptionDetectArchiveFilesAsMedia": "Identifiera arkivfiler som media", + "OptionDetectArchiveFilesAsMediaHelp": "Om aktiverad, kommer filer med .rar och .zip f\u00f6rl\u00e4ngningar att uppt\u00e4ckas som mediefiler.", + "LabelEnterConnectUserName": "Anv\u00e4ndarnamn eller email:", "LabelEnterConnectUserNameHelp": "This is your Media Browser online account user name or password.", - "HeaderSyncJobInfo": "Sync Job", - "FolderTypeMixed": "Mixed content", + "HeaderSyncJobInfo": "Synk jobb", + "FolderTypeMixed": "Blandat inneh\u00e5ll", "FolderTypeMovies": "Filmer", "FolderTypeMusic": "Musik", "FolderTypeAdultVideos": "Inneh\u00e5ll f\u00f6r vuxna", @@ -61,14 +81,16 @@ "FolderTypeGames": "Spel", "FolderTypeBooks": "B\u00f6cker", "FolderTypeTvShows": "TV", - "FolderTypeInherit": "Inherit", - "LabelContentType": "Content type:", + "FolderTypeInherit": "\u00c4rv", + "LabelContentType": "Inneh\u00e5llstyp:", + "TitleScheduledTasks": "Scheduled Tasks", "HeaderSetupLibrary": "Konfigurera mediabiblioteket", "ButtonAddMediaFolder": "Skapa mediamapp", "LabelFolderType": "Typ av mapp:", "ReferToMediaLibraryWiki": "Se avsnittet om mediabibliotek i v\u00e5r Wiki.", "LabelCountry": "Land:", "LabelLanguage": "Spr\u00e5k:", + "ButtonJoinTheDevelopmentTeam": "Join the Development Team", "HeaderPreferredMetadataLanguage": "\u00d6nskat spr\u00e5k f\u00f6r metadata:", "LabelSaveLocalMetadata": "Spara grafik och metadata i mediamapparna", "LabelSaveLocalMetadataHelp": "Om grafik och metadata sparas tillsammans med media \u00e4r de enkelt \u00e5tkomliga f\u00f6r redigering.", @@ -84,8 +106,10 @@ "TabImages": "Bilder", "TabNotifications": "Meddelanden", "TabCollectionTitles": "Titlar", - "HeaderDeviceAccess": "Device Access", - "OptionEnableAccessFromAllDevices": "Enable access from all devices", + "HeaderDeviceAccess": "Enhets\u00e5tkomst", + "OptionEnableAccessFromAllDevices": "Aktivera \u00e5tkomst fr\u00e5n alla enheter", + "OptionEnableAccessToAllChannels": "Aktivera \u00e5tkomst till alla kanaler", + "OptionEnableAccessToAllLibraries": "Enable access to all libraries", "DeviceAccessHelp": "This only applies to devices that can be uniquely identified and will not prevent browser access. Filtering user device access will prevent them from using new devices until they've been approved here.", "LabelDisplayMissingEpisodesWithinSeasons": "Visa saknade avsnitt i s\u00e4songer", "LabelUnairedMissingEpisodesWithinSeasons": "Visa \u00e4nnu ej s\u00e4nda avsnitt i s\u00e4songer", @@ -258,24 +282,24 @@ "OptionDisableUserHelp": "Sp\u00e4rrade anv\u00e4ndare till\u00e5ts ej kontakta servern. Eventuella p\u00e5g\u00e5ende anslutningar avbryts omedelbart.", "HeaderAdvancedControl": "Avancerade anv\u00e4ndarinst\u00e4llningar", "LabelName": "Namn:", - "ButtonHelp": "Help", + "ButtonHelp": "Hj\u00e4lp", "OptionAllowUserToManageServer": "Till\u00e5t denna anv\u00e4ndare att administrera servern", "HeaderFeatureAccess": "Tillg\u00e5ng till funktioner", "OptionAllowMediaPlayback": "Till\u00e5t mediauppspelning", "OptionAllowBrowsingLiveTv": "Till\u00e5t bl\u00e4ddring i live-TV", - "OptionAllowDeleteLibraryContent": "Allow deletion of library content", + "OptionAllowDeleteLibraryContent": "Till\u00e5t radering av biblioteksinneh\u00e5ll", "OptionAllowManageLiveTv": "Till\u00e5t denna anv\u00e4ndare att administrera TV-inspelningar", - "OptionAllowRemoteControlOthers": "Allow remote control of other users", - "OptionAllowRemoteSharedDevices": "Allow remote control of shared devices", - "OptionAllowRemoteSharedDevicesHelp": "Dlna devices are considered shared until a user begins controlling it.", - "HeaderRemoteControl": "Remote Control", + "OptionAllowRemoteControlOthers": "Till\u00e5t fj\u00e4rrstyrning av andra anv\u00e4ndare", + "OptionAllowRemoteSharedDevices": "Till\u00e5t fj\u00e4rrstyrning av delade enheter", + "OptionAllowRemoteSharedDevicesHelp": "DLNA-enheter betraktas som delade tills en anv\u00e4ndare b\u00f6rjar kontrollera den.", + "HeaderRemoteControl": "Fj\u00e4rrkontroll", "OptionMissingTmdbId": "TMDB-ID saknas", "OptionIsHD": "HD", "OptionIsSD": "SD", "OptionMetascore": "Metabetyg", "ButtonSelect": "V\u00e4lj", "ButtonGroupVersions": "Gruppera versioner", - "ButtonAddToCollection": "L\u00e4gg till samling", + "ButtonAddToCollection": "Add to Collection", "PismoMessage": "Anv\u00e4nder Pismo File Mount baserat p\u00e5 en sk\u00e4nkt licens", "TangibleSoftwareMessage": "Anv\u00e4nder Tangible Solutions Java\/C#-konverterare baserat p\u00e5 en sk\u00e4nkt licens.", "HeaderCredits": "Tack till", @@ -299,7 +323,7 @@ "LabelCachePath": "Plats f\u00f6r cache:", "LabelCachePathHelp": "Ange en plats f\u00f6r serverns cachefiler, t ex bilder.", "LabelImagesByNamePath": "Plats f\u00f6r bilddatabasen (ImagesByName):", - "LabelImagesByNamePathHelp": "Ange en plats f\u00f6r nerladdade sk\u00e5despelar-, artist-, genre- och studiobilder.", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, genre and studio images.", "LabelMetadataPath": "Plats f\u00f6r metadata:", "LabelMetadataPathHelp": "Ange en plats f\u00f6r nerladdad grafik och metadata, om du inte vill spara dessa i mediamapparna.", "LabelTranscodingTempPath": "Mellanlagringsplats f\u00f6r omkodning:", @@ -314,12 +338,14 @@ "OptionEpisodes": "Avsnitt", "OptionOtherVideos": "Andra videor", "TitleMetadata": "Metadata", - "LabelAutomaticUpdatesFanart": "Till\u00e5t automatiska uppdateringar fr\u00e5n FanArt.tv", + "LabelAutomaticUpdates": "Aktivera automatiska uppdateringar", "LabelAutomaticUpdatesTmdb": "Till\u00e5t automatiska uppdateringar fr\u00e5n TheMovieDB.org", "LabelAutomaticUpdatesTvdb": "Till\u00e5t automatiska uppdateringar fr\u00e5n TheTVDB.com", "LabelAutomaticUpdatesFanartHelp": "Om aktiverat h\u00e4mtas nya bilder automatiskt efter hand som de blir tillg\u00e4ngliga p\u00e5 fanart.tv. Befintliga bilder p\u00e5verkas ej.", "LabelAutomaticUpdatesTmdbHelp": "Om aktiverat h\u00e4mtas nya bilder automatiskt efter hand som de blir tillg\u00e4ngliga p\u00e5 TheMovieDB.org. Befintliga bilder p\u00e5verkas ej.", "LabelAutomaticUpdatesTvdbHelp": "Om aktiverat h\u00e4mtas nya bilder automatiskt efter hand som de blir tillg\u00e4ngliga p\u00e5 TheTVDB.com. Befintliga bilder p\u00e5verkas ej.", + "LabelFanartApiKey": "Personlig api-nyckel:", + "LabelFanartApiKeyHelp": "Requests to fanart without a personal API key return results that were approved over 7 days ago. With a personal API key that drops to 48 hours and if you are also a fanart VIP member that will further drop to around 10 minutes.", "ExtractChapterImagesHelp": "Detta m\u00f6jligg\u00f6r grafisk visning av menyer f\u00f6r val av kapitel. Processen kan vara tids- och CPU-kr\u00e4vande och beh\u00f6va flera gigabyte lagringsutrymme. Processen k\u00f6rs varje natt kl 04:00 men intervallet kan anpassas enligt \u00f6nskem\u00e5l i Schemal\u00e4ggaren. Vi rekommenderar inte att den k\u00f6rs vid tider d\u00e5 anv\u00e4ndare \u00e4r aktiva.", "LabelMetadataDownloadLanguage": "\u00d6nskat spr\u00e5k:", "ButtonAutoScroll": "Rulla listor automatiskt", @@ -487,27 +513,33 @@ "HeaderSystemPaths": "Systems\u00f6kv\u00e4gar", "LinkCommunity": "Anv\u00e4ndargrupper", "LinkGithub": "Github", + "LinkApi": "Api", "LinkApiDocumentation": "API-dokumentation", "LabelFriendlyServerName": "Ditt \u00f6nskade servernamn:", "LabelFriendlyServerNameHelp": "Det h\u00e4r namnet anv\u00e4nds f\u00f6r att identifiera servern, om det l\u00e4mnas tomt kommer datorns namn att anv\u00e4ndas.", - "LabelPreferredDisplayLanguage": "Preferred display language:", + "LabelPreferredDisplayLanguage": "F\u00f6redraget visningsspr\u00e5k:", "LabelPreferredDisplayLanguageHelp": "\u00d6vers\u00e4ttningen av Media Browser \u00e4r ett p\u00e5g\u00e5ende projekt och \u00e4nnu ej f\u00e4rdigst\u00e4llt.", "LabelReadHowYouCanContribute": "L\u00e4s om hur du kan bidra.", "HeaderNewCollection": "Ny samling", - "HeaderAddToCollection": "L\u00e4gg till samling", "ButtonSubmit": "Bekr\u00e4fta", - "NewCollectionNameExample": "Exemple: Star Wars-samling", - "OptionSearchForInternetMetadata": "S\u00f6k p\u00e5 internet efter grafik och metadata", "ButtonCreate": "Skapa", - "LabelLocalHttpServerPortNumber": "Lokalt portnummer:", + "LabelCustomCss": "Custom css:", + "LabelCustomCssHelp": "Apply your own custom css to the web interface.", + "LabelLocalHttpServerPortNumber": "Local http port number:", "LabelLocalHttpServerPortNumberHelp": "TCP-portnumret som Media Browsers http-server skall knytas till.", - "LabelPublicPort": "Publikt portnummer:", - "LabelPublicPortHelp": "Publikt portnummer som den lokala porten skall knytas till.", + "LabelPublicHttpPort": "Public http port number:", + "LabelPublicHttpPortHelp": "The public port number that should be mapped to the local http port.", + "LabelPublicHttpsPort": "Public https port number:", + "LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.", + "LabelEnableHttps": "Report https as external address", + "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.", + "LabelHttpsPort": "Local https port number:", + "LabelHttpsPortHelp": "The tcp port number that Media Browser's https server should bind to.", "LabelWebSocketPortNumber": "Webanslutningens portnummer:", "LabelEnableAutomaticPortMap": "Aktivera automatisk koppling av portar", "LabelEnableAutomaticPortMapHelp": "Automatisk l\u00e4nkning av publik och lokal port via UPnP. Detta kanske inte fungerar med alla routrar.", - "LabelExternalDDNS": "Extern DDNS:", - "LabelExternalDDNSHelp": "Om du har en dynamisk DNS skriv in den h\u00e4r. Media Browser-appar kommer att anv\u00e4nda den n\u00e4r de fj\u00e4rransluts.", + "LabelExternalDDNS": "External WAN Address:", + "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely. Leave empty for automatic detection.", "TabResume": "\u00c5teruppta", "TabWeather": "V\u00e4der", "TitleAppSettings": "Programinst\u00e4llningar", @@ -575,6 +607,7 @@ "ButtonRestart": "Starta om", "ButtonShutdown": "St\u00e4ng av", "ButtonUpdateNow": "Uppdatera nu", + "TabHosting": "Hosting", "PleaseUpdateManually": "Var god st\u00e4ng av servern och uppdatera manuellt.", "NewServerVersionAvailable": "En ny version av Media Browser Server finns tillg\u00e4nglig!", "ServerUpToDate": "Media Browser Server \u00e4r uppdaterad till den senaste versionen", @@ -587,7 +620,7 @@ "LabelOldSupporterKey": "Tidigare donationskod", "LabelNewSupporterKey": "Ny donationskod", "HeaderMultipleKeyLinking": "Transfer to New Key", - "MultipleKeyLinkingHelp": "If you received a new supporter key, use this form to transfer the old key's registrations to your new one.", + "MultipleKeyLinkingHelp": "Om du f\u00e5tt en ny supporter nyckel, anv\u00e4nd detta formul\u00e4r f\u00f6r att \u00f6verf\u00f6ra gamla nyckelns registreringar till din nya.", "LabelCurrentEmailAddress": "Nuvarande e-postadress", "LabelCurrentEmailAddressHelp": "Den e-postadress den nya koden skickades till.", "HeaderForgotKey": "Gl\u00f6mt koden", @@ -636,6 +669,7 @@ "NotificationOptionInstallationFailed": "Fel vid installation", "NotificationOptionNewLibraryContent": "Nytt inneh\u00e5ll har tillkommit", "NotificationOptionNewLibraryContentMultiple": "Nytillkommet inneh\u00e5ll finns (flera objekt)", + "NotificationOptionCameraImageUploaded": "Camera image uploaded", "SendNotificationHelp": "Meddelanden visas f\u00f6rvalt i kontrollpanelens inkorg. S\u00f6k efter fler meddelandetill\u00e4gg i till\u00e4ggskatalogen.", "NotificationOptionServerRestartRequired": "Servern m\u00e5ste startas om", "LabelNotificationEnabled": "Aktivera denna meddelandetyp", @@ -829,7 +863,7 @@ "OptionAuto": "Auto", "OptionYes": "Ja", "OptionNo": "Nej", - "HeaderOptions": "Options", + "HeaderOptions": "Alternativ", "HeaderIdentificationResult": "Identification Result", "LabelHomePageSection1": "Startsidans sektion 1:", "LabelHomePageSection2": "Startsidans sektion 2:", @@ -853,12 +887,14 @@ "OptionDefaultSort": "F\u00f6rval", "OptionCommunityMostWatchedSort": "Oftast visade", "TabNextUp": "N\u00e4stkommande", + "HeaderBecomeMediaBrowserSupporter": "Become a Media Browser Supporter", + "TextEnjoyBonusFeatures": "Enjoy Bonus Features", "MessageNoMovieSuggestionsAvailable": "Det finns inga filmf\u00f6rslag f\u00f6r tillf\u00e4llet. Efter att ha sett ett antal filmer kan du \u00e5terkomma hit f\u00f6r att se dina f\u00f6rslag.", - "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.", + "MessageNoCollectionsAvailable": "Samlingar g\u00f6r det m\u00f6jligt att avnjuta personliga grupperingar av filmer, serier, Album, b\u00f6cker och spel. Klicka p\u00e5 knappen + f\u00f6r att b\u00f6rja skapa samlingar.", "MessageNoPlaylistsAvailable": "Spellistor l\u00e5ter dig skapa listor med inneh\u00e5ll att spela upp i ordning. F\u00f6r att l\u00e4gga till objekt i spellistor, h\u00f6gerklicka eller tryck-och-h\u00e5ll och v\u00e4lj \"l\u00e4gg till i spellista\".", "MessageNoPlaylistItemsAvailable": "Den h\u00e4r spellistan \u00e4r tom.", "ButtonDismiss": "Avvisa", - "ButtonEditOtherUserPreferences": "Edit this user's profile, password and personal preferences.", + "ButtonEditOtherUserPreferences": "Redigera denna anv\u00e4ndarens profil, l\u00f6senord och personliga preferenser", "LabelChannelStreamQuality": "\u00d6nskad kvalitet vid str\u00f6mning via Internet:", "LabelChannelStreamQualityHelp": "N\u00e4r bandbredden \u00e4r begr\u00e4nsad kan en l\u00e4gre kvalitet ge en mera st\u00f6rningsfri upplevelse.", "OptionBestAvailableStreamQuality": "B\u00e4sta tillg\u00e4ngliga", @@ -869,14 +905,13 @@ "LabelChannelDownloadAge": "Radera inneh\u00e5ll efter (dagar):", "LabelChannelDownloadAgeHelp": "Nedladdat inneh\u00e5ll \u00e4ldre \u00e4n s\u00e5 raderas. Det \u00e4r fortfarande tillg\u00e4ngligt via str\u00f6mning fr\u00e5n Internet.", "ChannelSettingsFormHelp": "Installera kanaler, t ex Trailers och Vimeo, via till\u00e4ggskatalogen.", - "LabelSelectCollection": "V\u00e4lj samling:", "ButtonOptions": "Alternativ", "ViewTypeMovies": "Filmer", "ViewTypeTvShows": "TV", "ViewTypeGames": "Spel", "ViewTypeMusic": "Musik", - "ViewTypeMusicGenres": "Genres", - "ViewTypeMusicArtists": "Artists", + "ViewTypeMusicGenres": "Genrer", + "ViewTypeMusicArtists": "Artister", "ViewTypeBoxSets": "Samlingar", "ViewTypeChannels": "Kanaler", "ViewTypeLiveTV": "Live-TV", @@ -917,7 +952,7 @@ "OptionLatestTvRecordings": "Senaste inspelningar", "LabelProtocolInfo": "Protokollinfo:", "LabelProtocolInfoHelp": "V\u00e4rde att anv\u00e4nda vid svar p\u00e5 GetProtocolInfo-beg\u00e4ran fr\u00e5n enheter.", - "TabKodiMetadata": "Kodi", + "TabNfo": "Nfo", "HeaderKodiMetadataHelp": "Media Browser har inbyggt st\u00f6d f\u00f6r Kodi Nfo-metadata och bilder. F\u00f6r att aktivera eller avaktivera Kodi-metadata, anv\u00e4nd \"Avancerat\"-fliken f\u00f6r att g\u00f6ra inst\u00e4llningar f\u00f6r olika mediatyper.", "LabelKodiMetadataUser": "Sync user watch data to nfo's for:", "LabelKodiMetadataUserHelp": "Aktivera detta f\u00f6r att synkronisera bevakade data mellan Media Browser och Kodi.", @@ -931,6 +966,7 @@ "LabelGroupChannelsIntoViews": "Visa dessa kanaler direkt i mina vyer:", "LabelGroupChannelsIntoViewsHelp": "Om aktiverat kommer dessa kanaler att visas tillsammans med andra vyer. Annars visas de i en separat vy f\u00f6r Kanaler.", "LabelDisplayCollectionsView": "Vy som visar filmsamlingar", + "LabelDisplayCollectionsViewHelp": "This will create a separate view to display collections that you've created or have access to. To create a collection, right-click or tap-hold any movie and select 'Add to Collection'. ", "LabelKodiMetadataEnableExtraThumbs": "Kopiera extrafanart till extrathumbs", "LabelKodiMetadataEnableExtraThumbsHelp": "N\u00e4r bilder h\u00e4mtas fr\u00e5n Internet kan de sparas i b\u00e5de extrafanart- och extrathumbs-mapparna f\u00f6r att ge maximal kompatibilitet med Kodi-skins.", "TabServices": "Tj\u00e4nster", @@ -1084,11 +1120,14 @@ "LabelDisplayFoldersView": "Vy som visar vanliga lagringsmappar", "ViewTypeLiveTvRecordingGroups": "Inspelningar", "ViewTypeLiveTvChannels": "Kanaler", - "LabelAllowLocalAccessWithoutPassword": "Till\u00e5t lokal \u00e5tkomst utan l\u00f6senord", - "LabelAllowLocalAccessWithoutPasswordHelp": "G\u00f6r att l\u00f6senord ej kr\u00e4vs vid inloggning fr\u00e5n hemman\u00e4tverket.", + "LabelEasyPinCode": "Easy pin code:", + "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Media Browser apps, and can also be used for easy in-network sign in.", + "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", + "LabelInNetworkSignInWithEasyPasswordHelp": "If enabled, you'll be able to use your easy pin code to sign in to Media Browser apps from inside your home network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", "HeaderPassword": "L\u00f6senord", "HeaderLocalAccess": "Lokal \u00e5tkomst", "HeaderViewOrder": "Visningsordning", + "ButtonResetEasyPassword": "Reset easy pin code", "LabelSelectUserViewOrder": "V\u00e4lj i vilken ordning dina vyer skall visas i Media Browser-appar", "LabelMetadataRefreshMode": "Metod f\u00f6r uppdatering av metadata:", "LabelImageRefreshMode": "Metod f\u00f6r uppdatering av bilder:", @@ -1162,7 +1201,7 @@ "OptionNoThemeSong": "Ledmotiv saknas", "OptionNoThemeVideo": "Temavideo saknas", "LabelOneTimeDonationAmount": "Bidragsbelopp:", - "ButtonDonate": "Donate", + "ButtonDonate": "Donera", "OptionActor": "Sk\u00e5despelare", "OptionComposer": "Komposit\u00f6r", "OptionDirector": "Regiss\u00f6r", @@ -1255,7 +1294,7 @@ "LabelConnectGuestUserNameHelp": "This is the username that your friend uses to sign in to the Media Browser website, or their email address.", "HeaderInviteUserHelp": "Att dela dina media med v\u00e4nner \u00e4r enklare \u00e4n n\u00e5gonsin med Media Browser Connect.", "ButtonSendInvitation": "Skicka inbjudan", - "HeaderSignInWithConnect": "Sign in with Media Browser Connect", + "HeaderSignInWithConnect": "Logga in med Media Browser Connect", "HeaderGuests": "G\u00e4ster", "HeaderLocalUsers": "Lokala anv\u00e4ndare", "HeaderPendingInvitations": "V\u00e4ntande inbjudningar", @@ -1264,27 +1303,27 @@ "HeaderAccessScheduleHelp": "Skapa ett schema f\u00f6r att begr\u00e4nsa \u00e5tkomsten till vissa tider.", "ButtonAddSchedule": "Skapa schema", "LabelAccessDay": "Veckodag:", - "LabelAccessStart": "Start time:", - "LabelAccessEnd": "End time:", + "LabelAccessStart": "Starttid:", + "LabelAccessEnd": "Sluttid:", "HeaderSchedule": "Schedule", - "OptionEveryday": "Every day", - "OptionWeekdays": "Weekdays", - "OptionWeekends": "Weekends", + "OptionEveryday": "Varje dag", + "OptionWeekdays": "Veckodagar", + "OptionWeekends": "Helger", "MessageProfileInfoSynced": "User profile information synced with Media Browser Connect.", "HeaderOptionalLinkMediaBrowserAccount": "Optional: Link your Media Browser account", - "ButtonTrailerReel": "Trailer reel", - "HeaderTrailerReel": "Trailer Reel", - "OptionPlayUnwatchedTrailersOnly": "Play only unwatched trailers", - "HeaderTrailerReelHelp": "Start a trailer reel to play a long running playlist of trailers.", + "ButtonTrailerReel": "Trailer rulle", + "HeaderTrailerReel": "Trailer rulle", + "OptionPlayUnwatchedTrailersOnly": "Spela endast osedda trailers", + "HeaderTrailerReelHelp": "Starta en trailer rulle f\u00f6r att spela en l\u00e5ng spellista med trailers.", "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.", "HeaderNewUsers": "New Users", - "ButtonSignUp": "Sign up", - "ButtonForgotPassword": "Forgot password?", - "OptionDisableUserPreferences": "Disable access to user preferences", - "OptionDisableUserPreferencesHelp": "If enabled, only administrators will be able to configure user profile images, passwords, and language preferences.", - "HeaderSelectServer": "Select Server", - "MessageNoServersAvailableToConnect": "No servers are available to connect to. If you've been invited to share a server, make sure to accept it below or by clicking the link in the email.", - "TitleNewUser": "New User", + "ButtonSignUp": "Registrera dig", + "ButtonForgotPassword": "Forgot password", + "OptionDisableUserPreferences": "Inaktivera tillg\u00e5ng till anv\u00e4ndarinst\u00e4llningar", + "OptionDisableUserPreferencesHelp": "Om aktiverad, kommer endast administrat\u00f6rer att kunna konfigurera anv\u00e4ndarprofilbilder, l\u00f6senord och spr\u00e5kinst\u00e4llningar.", + "HeaderSelectServer": "V\u00e4lj Server", + "MessageNoServersAvailableToConnect": "Inga servrar finns tillg\u00e4ngliga f\u00f6r att ansluta till. Om du har blivit inbjuden att dela en server, se till att acceptera den nedan eller genom att klicka p\u00e5 l\u00e4nken i e-postmeddelandet.", + "TitleNewUser": "Ny Anv\u00e4ndare", "ButtonConfigurePassword": "Configure Password", "HeaderDashboardUserPassword": "User passwords are managed within each user's personal profile settings.", "HeaderLibraryAccess": "Library Access", @@ -1295,14 +1334,14 @@ "MessageGuestSharingPermissionsHelp": "Most features are initially unavailable to guests but can be enabled as needed.", "HeaderInvitations": "Invitations", "LabelForgotPasswordUsernameHelp": "Enter your username, if you remember it.", - "HeaderForgotPassword": "Forgot Password", - "TitleForgotPassword": "Forgot Password", + "HeaderForgotPassword": "Gl\u00f6mt L\u00f6senord", + "TitleForgotPassword": "Gl\u00f6mt L\u00f6senord", "TitlePasswordReset": "Password Reset", "LabelPasswordRecoveryPinCode": "Pin code:", - "HeaderPasswordReset": "Password Reset", + "HeaderPasswordReset": "\u00c5terst\u00e4llning av l\u00f6senordet", "HeaderParentalRatings": "Parental Ratings", - "HeaderVideoTypes": "Video Types", - "HeaderYears": "Years", + "HeaderVideoTypes": "Videotyper", + "HeaderYears": "\u00c5r", "HeaderAddTag": "Add Tag", "LabelBlockItemsWithTags": "Block items with tags:", "LabelTag": "Tag:", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/tr.json b/MediaBrowser.Server.Implementations/Localization/Server/tr.json index 40557cd87..4fd8a764a 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/tr.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/tr.json @@ -40,12 +40,32 @@ "OptionIAcceptTermsOfService": "I accept the terms of service", "ButtonPrivacyPolicy": "Privacy policy", "ButtonTermsOfService": "Terms of Service", + "HeaderDeveloperOptions": "Developer Options", + "OptionEnableWebClientResponseCache": "Enable web client response caching", + "OptionDisableForDevelopmentHelp": "Configure these as needed for web client development purposes.", + "OptionEnableWebClientResourceMinification": "Enable web client resource minification", + "LabelDashboardSourcePath": "Web client source path:", + "LabelDashboardSourcePathHelp": "If running the server from source, specify the path to the dashboard-ui folder. All web client files will be served from this location.", + "ButtonConvertMedia": "Convert media", + "ButtonOrganize": "Organize", "ButtonOk": "Tamam", "ButtonCancel": "\u0130ptal", "ButtonNew": "Yeni", "HeaderTV": "TV", "HeaderAudio": "Audio", "HeaderVideo": "Video", + "HeaderPaths": "Paths", + "CategorySync": "Sync", + "HeaderEasyPinCode": "Easy Pin Code", + "RegisterWithPayPal": "Register with PayPal", + "HeaderSyncRequiresSupporterMembership": "Sync Requires a Supporter Membership", + "HeaderEnjoyDayTrial": "Enjoy a 14 Day Free Trial", + "LabelSyncTempPath": "Temporary file path:", + "LabelSyncTempPathHelp": "Specify a custom sync working folder. Converted media created during the sync process will be stored here.", + "LabelCustomCertificatePath": "Custom certificate path:", + "LabelCustomCertificatePathHelp": "Supply your own ssl certificate. If omitted, the server will create a self-signed certificate.", + "TitleNotifications": "Notifications", + "ButtonDonateWithPayPal": "Donate with PayPal", "OptionDetectArchiveFilesAsMedia": "Detect archive files as media", "OptionDetectArchiveFilesAsMediaHelp": "If enabled, files with .rar and .zip extensions will be detected as media files.", "LabelEnterConnectUserName": "User name or email:", @@ -63,12 +83,14 @@ "FolderTypeTvShows": "TV", "FolderTypeInherit": "Inherit", "LabelContentType": "Content type:", + "TitleScheduledTasks": "Scheduled Tasks", "HeaderSetupLibrary": "Medya k\u00fct\u00fcphaneni kur", "ButtonAddMediaFolder": "Yeni Media Klas\u00f6r\u00fc", "LabelFolderType": "Klas\u00f6r T\u00fcr\u00fc:", "ReferToMediaLibraryWiki": "Refer to the media library wiki.", "LabelCountry": "\u00dclke", "LabelLanguage": "Dil", + "ButtonJoinTheDevelopmentTeam": "Join the Development Team", "HeaderPreferredMetadataLanguage": "Tercih edilen Meta Dili:", "LabelSaveLocalMetadata": "Medya meta dosyalar\u0131n\u0131 ayn\u0131 klas\u00f6rlere i\u015fle", "LabelSaveLocalMetadataHelp": "Saving artwork and metadata directly into media folders will put them in a place where they can be easily edited.", @@ -86,6 +108,8 @@ "TabCollectionTitles": "Titles", "HeaderDeviceAccess": "Device Access", "OptionEnableAccessFromAllDevices": "Enable access from all devices", + "OptionEnableAccessToAllChannels": "Enable access to all channels", + "OptionEnableAccessToAllLibraries": "Enable access to all libraries", "DeviceAccessHelp": "This only applies to devices that can be uniquely identified and will not prevent browser access. Filtering user device access will prevent them from using new devices until they've been approved here.", "LabelDisplayMissingEpisodesWithinSeasons": "Sezondaki kay\u0131p b\u00f6l\u00fcmleri g\u00f6ster", "LabelUnairedMissingEpisodesWithinSeasons": "Display unaired episodes within seasons", @@ -299,7 +323,7 @@ "LabelCachePath": "Cache path:", "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.", "LabelImagesByNamePath": "Images by name path:", - "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, genre and studio images.", "LabelMetadataPath": "Metadata path:", "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.", "LabelTranscodingTempPath": "Transcoding temporary path:", @@ -314,12 +338,14 @@ "OptionEpisodes": "Episodes", "OptionOtherVideos": "Di\u011fer Videolar", "TitleMetadata": "Metadata", - "LabelAutomaticUpdatesFanart": "Enable automatic updates from FanArt.tv", + "LabelAutomaticUpdates": "Enable automatic updates", "LabelAutomaticUpdatesTmdb": "Enable automatic updates from TheMovieDB.org", "LabelAutomaticUpdatesTvdb": "Enable automatic updates from TheTVDB.com", "LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.", "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.", "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.", + "LabelFanartApiKey": "Personal api key:", + "LabelFanartApiKeyHelp": "Requests to fanart without a personal API key return results that were approved over 7 days ago. With a personal API key that drops to 48 hours and if you are also a fanart VIP member that will further drop to around 10 minutes.", "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", "LabelMetadataDownloadLanguage": "Preferred download language:", "ButtonAutoScroll": "Auto-scroll", @@ -487,6 +513,7 @@ "HeaderSystemPaths": "System Paths", "LinkCommunity": "Community", "LinkGithub": "Github", + "LinkApi": "Api", "LinkApiDocumentation": "Api D\u00f6k\u00fcmanlar\u0131", "LabelFriendlyServerName": "Friendly server name:", "LabelFriendlyServerNameHelp": "This name will be used to identify this server. If left blank, the computer name will be used.", @@ -494,20 +521,25 @@ "LabelPreferredDisplayLanguageHelp": "Translating Media Browser is an ongoing project and is not yet complete.", "LabelReadHowYouCanContribute": "Read about how you can contribute.", "HeaderNewCollection": "Yeni Koleksiyon", - "HeaderAddToCollection": "Add to Collection", "ButtonSubmit": "Submit", - "NewCollectionNameExample": "Example: Star Wars Collection", - "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata", "ButtonCreate": "Create", - "LabelLocalHttpServerPortNumber": "Local port number:", + "LabelCustomCss": "Custom css:", + "LabelCustomCssHelp": "Apply your own custom css to the web interface.", + "LabelLocalHttpServerPortNumber": "Local http port number:", "LabelLocalHttpServerPortNumberHelp": "The tcp port number that Media Browser's http server should bind to.", - "LabelPublicPort": "Public port number:", - "LabelPublicPortHelp": "The public port number that should be mapped to the local port.", + "LabelPublicHttpPort": "Public http port number:", + "LabelPublicHttpPortHelp": "The public port number that should be mapped to the local http port.", + "LabelPublicHttpsPort": "Public https port number:", + "LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.", + "LabelEnableHttps": "Report https as external address", + "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.", + "LabelHttpsPort": "Local https port number:", + "LabelHttpsPortHelp": "The tcp port number that Media Browser's https server should bind to.", "LabelWebSocketPortNumber": "Web socket port number:", "LabelEnableAutomaticPortMap": "Enable automatic port mapping", "LabelEnableAutomaticPortMapHelp": "Attempt to automatically map the public port to the local port via UPnP. This may not work with some router models.", - "LabelExternalDDNS": "External DDNS:", - "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely.", + "LabelExternalDDNS": "External WAN Address:", + "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely. Leave empty for automatic detection.", "TabResume": "Resume", "TabWeather": "Weather", "TitleAppSettings": "App Settings", @@ -575,6 +607,7 @@ "ButtonRestart": "Restart", "ButtonShutdown": "Shutdown", "ButtonUpdateNow": "Update Now", + "TabHosting": "Hosting", "PleaseUpdateManually": "Please shutdown the server and update manually.", "NewServerVersionAvailable": "A new version of Media Browser Server is available!", "ServerUpToDate": "Media Browser Server G\u00fcncel", @@ -636,6 +669,7 @@ "NotificationOptionInstallationFailed": "Installation failure", "NotificationOptionNewLibraryContent": "New content added", "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", + "NotificationOptionCameraImageUploaded": "Camera image uploaded", "SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.", "NotificationOptionServerRestartRequired": "Sunucu yeniden ba\u015flat\u0131lmal\u0131", "LabelNotificationEnabled": "Enable this notification", @@ -853,6 +887,8 @@ "OptionDefaultSort": "Default", "OptionCommunityMostWatchedSort": "Most Watched", "TabNextUp": "Sonraki hafta", + "HeaderBecomeMediaBrowserSupporter": "Become a Media Browser Supporter", + "TextEnjoyBonusFeatures": "Enjoy Bonus Features", "MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.", "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.", "MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.", @@ -869,7 +905,6 @@ "LabelChannelDownloadAge": "Delete content after: (days)", "LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.", "ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.", - "LabelSelectCollection": "Select collection:", "ButtonOptions": "Options", "ViewTypeMovies": "Movies", "ViewTypeTvShows": "TV", @@ -917,7 +952,7 @@ "OptionLatestTvRecordings": "Latest recordings", "LabelProtocolInfo": "Protocol info:", "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.", - "TabKodiMetadata": "Kodi", + "TabNfo": "Nfo", "HeaderKodiMetadataHelp": "Media Browser includes native support for Kodi Nfo metadata and images. To enable or disable Kodi metadata, use the Advanced tab to configure options for your media types.", "LabelKodiMetadataUser": "Sync user watch data to nfo's for:", "LabelKodiMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Kodi.", @@ -931,6 +966,7 @@ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:", "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.", "LabelDisplayCollectionsView": "Display a collections view to show movie collections", + "LabelDisplayCollectionsViewHelp": "This will create a separate view to display collections that you've created or have access to. To create a collection, right-click or tap-hold any movie and select 'Add to Collection'. ", "LabelKodiMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs", "LabelKodiMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Kodi skin compatibility.", "TabServices": "Services", @@ -1084,11 +1120,14 @@ "LabelDisplayFoldersView": "Display a folders view to show plain media folders", "ViewTypeLiveTvRecordingGroups": "Recordings", "ViewTypeLiveTvChannels": "Channels", - "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password", - "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.", + "LabelEasyPinCode": "Easy pin code:", + "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Media Browser apps, and can also be used for easy in-network sign in.", + "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", + "LabelInNetworkSignInWithEasyPasswordHelp": "If enabled, you'll be able to use your easy pin code to sign in to Media Browser apps from inside your home network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", "HeaderPassword": "Password", "HeaderLocalAccess": "Local Access", "HeaderViewOrder": "View Order", + "ButtonResetEasyPassword": "Reset easy pin code", "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps", "LabelMetadataRefreshMode": "Metadata refresh mode:", "LabelImageRefreshMode": "Image refresh mode:", @@ -1279,7 +1318,7 @@ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.", "HeaderNewUsers": "New Users", "ButtonSignUp": "Sign up", - "ButtonForgotPassword": "Forgot password?", + "ButtonForgotPassword": "Forgot password", "OptionDisableUserPreferences": "Disable access to user preferences", "OptionDisableUserPreferencesHelp": "If enabled, only administrators will be able to configure user profile images, passwords, and language preferences.", "HeaderSelectServer": "Select Server", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/uk.json b/MediaBrowser.Server.Implementations/Localization/Server/uk.json new file mode 100644 index 000000000..f6d79e3a7 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Localization/Server/uk.json @@ -0,0 +1,1358 @@ +{ + "LabelExit": "\u0412\u0438\u0439\u0442\u0438", + "LabelVisitCommunity": "Visit Community", + "LabelGithub": "Github", + "LabelSwagger": "Swagger", + "LabelStandard": "Standard", + "LabelApiDocumentation": "Api Documentation", + "LabelDeveloperResources": "Developer Resources", + "LabelBrowseLibrary": "Browse Library", + "LabelConfigureMediaBrowser": "Configure Media Browser", + "LabelOpenLibraryViewer": "Open Library Viewer", + "LabelRestartServer": "\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 \u0441\u0435\u0440\u0432\u0435\u0440", + "LabelShowLogWindow": "Show Log Window", + "LabelPrevious": "\u041d\u0430\u0437\u0430\u0434", + "LabelFinish": "Finish", + "LabelNext": "\u0412\u043f\u0435\u0440\u0435\u0434", + "LabelYoureDone": "You're Done!", + "WelcomeToMediaBrowser": "Welcome to Media Browser!", + "TitleMediaBrowser": "Media Browser", + "ThisWizardWillGuideYou": "This wizard will help guide you through the setup process. To begin, please select your preferred language.", + "TellUsAboutYourself": "Tell us about yourself", + "ButtonQuickStartGuide": "Quick start guide", + "LabelYourFirstName": "\u0406\u043c\u2019\u044f", + "MoreUsersCanBeAddedLater": "More users can be added later within the Dashboard.", + "UserProfilesIntro": "Media Browser includes built-in support for user profiles, enabling each user to have their own display settings, playstate and parental controls.", + "LabelWindowsService": "Windows Service", + "AWindowsServiceHasBeenInstalled": "A Windows Service has been installed.", + "WindowsServiceIntro1": "Media Browser Server normally runs as a desktop application with a tray icon, but if you prefer to run it as a background service, it can be started from the windows services control panel instead.", + "WindowsServiceIntro2": "If using the windows service, please note that it cannot be run at the same time as the tray icon, so you'll need to exit the tray in order to run the service. The service will also need to be configured with administrative privileges via the control panel. Please note that at this time the service is unable to self-update, so new versions will require manual interaction.", + "WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click <b>Finish<\/b> to view the <b>Server Dashboard<\/b>.", + "LabelConfigureSettings": "Configure settings", + "LabelEnableVideoImageExtraction": "Enable video image extraction", + "VideoImageExtractionHelp": "For videos that don't already have images, and that we're unable to find internet images for. This will add some additional time to the initial library scan but will result in a more pleasing presentation.", + "LabelEnableChapterImageExtractionForMovies": "Extract chapter image extraction for Movies", + "LabelChapterImageExtractionForMoviesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", + "LabelEnableAutomaticPortMapping": "Enable automatic port mapping", + "LabelEnableAutomaticPortMappingHelp": "UPnP allows automated router configuration for easy remote access. This may not work with some router models.", + "HeaderTermsOfService": "Media Browser Terms of Service", + "MessagePleaseAcceptTermsOfService": "Please accept the terms of service and privacy policy before continuing.", + "OptionIAcceptTermsOfService": "I accept the terms of service", + "ButtonPrivacyPolicy": "Privacy policy", + "ButtonTermsOfService": "Terms of Service", + "HeaderDeveloperOptions": "Developer Options", + "OptionEnableWebClientResponseCache": "Enable web client response caching", + "OptionDisableForDevelopmentHelp": "Configure these as needed for web client development purposes.", + "OptionEnableWebClientResourceMinification": "Enable web client resource minification", + "LabelDashboardSourcePath": "Web client source path:", + "LabelDashboardSourcePathHelp": "If running the server from source, specify the path to the dashboard-ui folder. All web client files will be served from this location.", + "ButtonConvertMedia": "Convert media", + "ButtonOrganize": "Organize", + "ButtonOk": "Ok", + "ButtonCancel": "\u0421\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438", + "ButtonNew": "\u041d\u043e\u0432\u0438\u0439", + "HeaderTV": "\u0422\u0411", + "HeaderAudio": "\u0410\u0443\u0434\u0456\u043e", + "HeaderVideo": "\u0412\u0456\u0434\u0435\u043e", + "HeaderPaths": "Paths", + "CategorySync": "Sync", + "HeaderEasyPinCode": "Easy Pin Code", + "RegisterWithPayPal": "Register with PayPal", + "HeaderSyncRequiresSupporterMembership": "Sync Requires a Supporter Membership", + "HeaderEnjoyDayTrial": "Enjoy a 14 Day Free Trial", + "LabelSyncTempPath": "Temporary file path:", + "LabelSyncTempPathHelp": "Specify a custom sync working folder. Converted media created during the sync process will be stored here.", + "LabelCustomCertificatePath": "Custom certificate path:", + "LabelCustomCertificatePathHelp": "Supply your own ssl certificate. If omitted, the server will create a self-signed certificate.", + "TitleNotifications": "\u0421\u043f\u043e\u0432\u0456\u0449\u0435\u043d\u043d\u044f", + "ButtonDonateWithPayPal": "Donate with PayPal", + "OptionDetectArchiveFilesAsMedia": "Detect archive files as media", + "OptionDetectArchiveFilesAsMediaHelp": "If enabled, files with .rar and .zip extensions will be detected as media files.", + "LabelEnterConnectUserName": "\u0406\u043c\u2019\u044f \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0430\u0431\u043e email:", + "LabelEnterConnectUserNameHelp": "This is your Media Browser online account user name or password.", + "HeaderSyncJobInfo": "Sync Job", + "FolderTypeMixed": "Mixed content", + "FolderTypeMovies": "Movies", + "FolderTypeMusic": "\u041c\u0443\u0437\u0438\u043a\u0430", + "FolderTypeAdultVideos": "Adult videos", + "FolderTypePhotos": "\u0421\u0432\u0456\u0442\u043b\u0438\u043d\u0438", + "FolderTypeMusicVideos": "Music videos", + "FolderTypeHomeVideos": "Home videos", + "FolderTypeGames": "\u0406\u0433\u0440\u0438", + "FolderTypeBooks": "\u041a\u043d\u0438\u0433\u0438", + "FolderTypeTvShows": "\u0422\u0411", + "FolderTypeInherit": "Inherit", + "LabelContentType": "Content type:", + "TitleScheduledTasks": "Scheduled Tasks", + "HeaderSetupLibrary": "Setup your media library", + "ButtonAddMediaFolder": "Add media folder", + "LabelFolderType": "Folder type:", + "ReferToMediaLibraryWiki": "Refer to the media library wiki.", + "LabelCountry": "\u041a\u0440\u0430\u0457\u043d\u0430:", + "LabelLanguage": "\u041c\u043e\u0432\u0430:", + "ButtonJoinTheDevelopmentTeam": "Join the Development Team", + "HeaderPreferredMetadataLanguage": "Preferred metadata language:", + "LabelSaveLocalMetadata": "Save artwork and metadata into media folders", + "LabelSaveLocalMetadataHelp": "Saving artwork and metadata directly into media folders will put them in a place where they can be easily edited.", + "LabelDownloadInternetMetadata": "Download artwork and metadata from the internet", + "LabelDownloadInternetMetadataHelp": "Media Browser can download information about your media to enable rich presentations.", + "TabPreferences": "Preferences", + "TabPassword": "Password", + "TabLibraryAccess": "Library Access", + "TabAccess": "Access", + "TabImage": "Image", + "TabProfile": "\u041f\u0440\u043e\u0444\u0456\u043b\u044c", + "TabMetadata": "\u041c\u0435\u0442\u0430\u0434\u0430\u043d\u0456", + "TabImages": "\u0417\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043d\u044f", + "TabNotifications": "\u041f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f", + "TabCollectionTitles": "Titles", + "HeaderDeviceAccess": "Device Access", + "OptionEnableAccessFromAllDevices": "Enable access from all devices", + "OptionEnableAccessToAllChannels": "Enable access to all channels", + "OptionEnableAccessToAllLibraries": "Enable access to all libraries", + "DeviceAccessHelp": "This only applies to devices that can be uniquely identified and will not prevent browser access. Filtering user device access will prevent them from using new devices until they've been approved here.", + "LabelDisplayMissingEpisodesWithinSeasons": "Display missing episodes within seasons", + "LabelUnairedMissingEpisodesWithinSeasons": "Display unaired episodes within seasons", + "HeaderVideoPlaybackSettings": "Video Playback Settings", + "HeaderPlaybackSettings": "Playback Settings", + "LabelAudioLanguagePreference": "Audio language preference:", + "LabelSubtitleLanguagePreference": "Subtitle language preference:", + "OptionDefaultSubtitles": "Default", + "OptionOnlyForcedSubtitles": "Only forced subtitles", + "OptionAlwaysPlaySubtitles": "Always play subtitles", + "OptionNoSubtitles": "No Subtitles", + "OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.", + "OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.", + "OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.", + "OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.", + "TabProfiles": "\u041f\u0440\u043e\u0444\u0456\u043b\u0456", + "TabSecurity": "\u0411\u0435\u0437\u043f\u0435\u043a\u0430", + "ButtonAddUser": "\u0414\u043e\u0434\u0430\u0442\u0438 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430", + "ButtonAddLocalUser": "Add Local User", + "ButtonInviteUser": "Invite User", + "ButtonSave": "\u0417\u0431\u0435\u0440\u0456\u0433\u0442\u0438", + "ButtonResetPassword": "\u0421\u043a\u0438\u043d\u0443\u0442\u0438 \u043f\u0430\u0440\u043e\u043b\u044c", + "LabelNewPassword": "\u041d\u043e\u0432\u0438\u0439 \u043f\u0430\u0440\u043e\u043b\u044c:", + "LabelNewPasswordConfirm": "New password confirm:", + "HeaderCreatePassword": "\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u043f\u0430\u0440\u043e\u043b\u044c", + "LabelCurrentPassword": "\u041f\u043e\u0442\u043e\u0447\u043d\u0438\u0439 \u043f\u0430\u0440\u043e\u043b\u044c:", + "LabelMaxParentalRating": "Maximum allowed parental rating:", + "MaxParentalRatingHelp": "Content with a higher rating will be hidden from this user.", + "LibraryAccessHelp": "Select the media folders to share with this user. Administrators will be able to edit all folders using the metadata manager.", + "ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.", + "ButtonDeleteImage": "Delete Image", + "LabelSelectUsers": "Select users:", + "ButtonUpload": "Upload", + "HeaderUploadNewImage": "Upload New Image", + "LabelDropImageHere": "Drop image here", + "ImageUploadAspectRatioHelp": "1:1 Aspect Ratio Recommended. JPG\/PNG only.", + "MessageNothingHere": "Nothing here.", + "MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.", + "TabSuggested": "Suggested", + "TabLatest": "Latest", + "TabUpcoming": "Upcoming", + "TabShows": "Shows", + "TabEpisodes": "\u0415\u043f\u0456\u0437\u043e\u0434\u0438", + "TabGenres": "\u0416\u0430\u043d\u0440\u0438", + "TabPeople": "\u041b\u044e\u0434\u0438", + "TabNetworks": "\u041c\u0435\u0440\u0435\u0436\u0456", + "HeaderUsers": "\u041a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0456", + "HeaderFilters": "\u0424\u0456\u043b\u044c\u0442\u0440\u0438:", + "ButtonFilter": "\u0424\u0456\u043b\u044c\u0442\u0440", + "OptionFavorite": "\u0423\u043b\u044e\u0431\u043b\u0435\u043d\u0435", + "OptionLikes": "\u041f\u043e\u0434\u043e\u0431\u0430\u0454\u0442\u044c\u0441\u044f", + "OptionDislikes": "\u041d\u0435 \u043f\u043e\u0434\u043e\u0431\u0430\u0454\u0442\u044c\u0441\u044f", + "OptionActors": "\u0410\u043a\u0442\u043e\u0440\u0438", + "OptionGuestStars": "Guest Stars", + "OptionDirectors": "Directors", + "OptionWriters": "Writers", + "OptionProducers": "Producers", + "HeaderResume": "Resume", + "HeaderNextUp": "Next Up", + "NoNextUpItemsMessage": "None found. Start watching your shows!", + "HeaderLatestEpisodes": "Latest Episodes", + "HeaderPersonTypes": "Person Types:", + "TabSongs": "Songs", + "TabAlbums": "Albums", + "TabArtists": "Artists", + "TabAlbumArtists": "Album Artists", + "TabMusicVideos": "Music Videos", + "ButtonSort": "Sort", + "HeaderSortBy": "Sort By:", + "HeaderSortOrder": "Sort Order:", + "OptionPlayed": "Played", + "OptionUnplayed": "Unplayed", + "OptionAscending": "Ascending", + "OptionDescending": "Descending", + "OptionRuntime": "Runtime", + "OptionReleaseDate": "Release Date", + "OptionPlayCount": "Play Count", + "OptionDatePlayed": "Date Played", + "OptionDateAdded": "Date Added", + "OptionAlbumArtist": "Album Artist", + "OptionArtist": "\u0410\u043a\u0442\u043e\u0440", + "OptionAlbum": "\u0410\u043b\u044c\u0431\u043e\u043c", + "OptionTrackName": "Track Name", + "OptionCommunityRating": "Community Rating", + "OptionNameSort": "\u0406\u043c\u2019\u044f", + "OptionFolderSort": "\u0422\u0435\u043a\u0438", + "OptionBudget": "\u0411\u044e\u0434\u0436\u0435\u0442", + "OptionRevenue": "\u0417\u0431\u043e\u0440\u0438", + "OptionPoster": "Poster", + "OptionPosterCard": "Poster card", + "OptionBackdrop": "Backdrop", + "OptionTimeline": "Timeline", + "OptionThumb": "Thumb", + "OptionThumbCard": "Thumb card", + "OptionBanner": "Banner", + "OptionCriticRating": "Critic Rating", + "OptionVideoBitrate": "Video Bitrate", + "OptionResumable": "Resumable", + "ScheduledTasksHelp": "Click a task to adjust its schedule.", + "ScheduledTasksTitle": "Scheduled Tasks", + "TabMyPlugins": "My Plugins", + "TabCatalog": "Catalog", + "PluginsTitle": "\u0414\u043e\u0434\u0430\u0442\u043a\u0438", + "HeaderAutomaticUpdates": "\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0435 \u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f", + "HeaderNowPlaying": "Now Playing", + "HeaderLatestAlbums": "Latest Albums", + "HeaderLatestSongs": "Latest Songs", + "HeaderRecentlyPlayed": "Recently Played", + "HeaderFrequentlyPlayed": "Frequently Played", + "DevBuildWarning": "Dev builds are the bleeding edge. Released often, these build have not been tested. The application may crash and entire features may not work at all.", + "LabelVideoType": "\u0422\u0438\u043f \u0432\u0456\u0434\u0435\u043e:", + "OptionBluray": "Bluray", + "OptionDvd": "Dvd", + "OptionIso": "Iso", + "Option3D": "3D", + "LabelFeatures": "Features:", + "LabelService": "Service:", + "LabelStatus": "Status:", + "LabelVersion": "\u0412\u0435\u0440\u0441\u0456\u044f:", + "LabelLastResult": "Last result:", + "OptionHasSubtitles": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u0438", + "OptionHasTrailer": "Trailer", + "OptionHasThemeSong": "Theme Song", + "OptionHasThemeVideo": "Theme Video", + "TabMovies": "Movies", + "TabStudios": "Studios", + "TabTrailers": "Trailers", + "LabelArtists": "Artists:", + "LabelArtistsHelp": "Separate multiple using ;", + "HeaderLatestMovies": "Latest Movies", + "HeaderLatestTrailers": "Latest Trailers", + "OptionHasSpecialFeatures": "Special Features", + "OptionImdbRating": "IMDb Rating", + "OptionParentalRating": "Parental Rating", + "OptionPremiereDate": "Premiere Date", + "TabBasic": "Basic", + "TabAdvanced": "Advanced", + "HeaderStatus": "Status", + "OptionContinuing": "Continuing", + "OptionEnded": "Ended", + "HeaderAirDays": "Air Days", + "OptionSunday": "Sunday", + "OptionMonday": "Monday", + "OptionTuesday": "Tuesday", + "OptionWednesday": "Wednesday", + "OptionThursday": "Thursday", + "OptionFriday": "Friday", + "OptionSaturday": "Saturday", + "HeaderManagement": "Management", + "LabelManagement": "Management:", + "OptionMissingImdbId": "Missing IMDb Id", + "OptionMissingTvdbId": "Missing TheTVDB Id", + "OptionMissingOverview": "Missing Overview", + "OptionFileMetadataYearMismatch": "File\/Metadata Years Mismatched", + "TabGeneral": "General", + "TitleSupport": "Support", + "TabLog": "Log", + "TabAbout": "About", + "TabSupporterKey": "Supporter Key", + "TabBecomeSupporter": "Become a Supporter", + "MediaBrowserHasCommunity": "Media Browser has a thriving community of users and contributors.", + "CheckoutKnowledgeBase": "Check out our knowledge base to help you get the most out of Media Browser.", + "SearchKnowledgeBase": "Search the Knowledge Base", + "VisitTheCommunity": "Visit the Community", + "VisitMediaBrowserWebsite": "Visit the Media Browser Web Site", + "VisitMediaBrowserWebsiteLong": "Visit the Media Browser Web site to catch the latest news and keep up with the developer blog.", + "OptionHideUser": "Hide this user from login screens", + "OptionHideUserFromLoginHelp": "Useful for private or hidden administrator accounts. The user will need to sign in manually by entering their username and password.", + "OptionDisableUser": "Disable this user", + "OptionDisableUserHelp": "If disabled the server will not allow any connections from this user. Existing connections will be abruptly terminated.", + "HeaderAdvancedControl": "Advanced Control", + "LabelName": "Name:", + "ButtonHelp": "Help", + "OptionAllowUserToManageServer": "Allow this user to manage the server", + "HeaderFeatureAccess": "Feature Access", + "OptionAllowMediaPlayback": "Allow media playback", + "OptionAllowBrowsingLiveTv": "Allow browsing of live tv", + "OptionAllowDeleteLibraryContent": "Allow deletion of library content", + "OptionAllowManageLiveTv": "Allow management of live tv recordings", + "OptionAllowRemoteControlOthers": "Allow remote control of other users", + "OptionAllowRemoteSharedDevices": "Allow remote control of shared devices", + "OptionAllowRemoteSharedDevicesHelp": "Dlna devices are considered shared until a user begins controlling it.", + "HeaderRemoteControl": "Remote Control", + "OptionMissingTmdbId": "Missing Tmdb Id", + "OptionIsHD": "HD", + "OptionIsSD": "SD", + "OptionMetascore": "Metascore", + "ButtonSelect": "Select", + "ButtonGroupVersions": "Group Versions", + "ButtonAddToCollection": "Add to Collection", + "PismoMessage": "Utilizing Pismo File Mount through a donated license.", + "TangibleSoftwareMessage": "Utilizing Tangible Solutions Java\/C# converters through a donated license.", + "HeaderCredits": "Credits", + "PleaseSupportOtherProduces": "Please support other free products we utilize:", + "VersionNumber": "Version {0}", + "TabPaths": "Paths", + "TabServer": "Server", + "TabTranscoding": "Transcoding", + "TitleAdvanced": "Advanced", + "LabelAutomaticUpdateLevel": "Automatic update level", + "OptionRelease": "Official Release", + "OptionBeta": "Beta", + "OptionDev": "Dev (Unstable)", + "LabelAllowServerAutoRestart": "Allow the server to restart automatically to apply updates", + "LabelAllowServerAutoRestartHelp": "The server will only restart during idle periods, when no users are active.", + "LabelEnableDebugLogging": "Enable debug logging", + "LabelRunServerAtStartup": "Run server at startup", + "LabelRunServerAtStartupHelp": "This will start the tray icon on windows startup. To start the windows service, uncheck this and run the service from the windows control panel. Please note that you cannot run both at the same time, so you will need to exit the tray icon before starting the service.", + "ButtonSelectDirectory": "Select Directory", + "LabelCustomPaths": "Specify custom paths where desired. Leave fields empty to use the defaults.", + "LabelCachePath": "Cache path:", + "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.", + "LabelImagesByNamePath": "Images by name path:", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, genre and studio images.", + "LabelMetadataPath": "Metadata path:", + "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.", + "LabelTranscodingTempPath": "Transcoding temporary path:", + "LabelTranscodingTempPathHelp": "This folder contains working files used by the transcoder. Specify a custom path, or leave empty to use the default within the server's data folder.", + "TabBasics": "Basics", + "TabTV": "TV", + "TabGames": "Games", + "TabMusic": "Music", + "TabOthers": "Others", + "HeaderExtractChapterImagesFor": "Extract chapter images for:", + "OptionMovies": "Movies", + "OptionEpisodes": "Episodes", + "OptionOtherVideos": "Other Videos", + "TitleMetadata": "Metadata", + "LabelAutomaticUpdates": "Enable automatic updates", + "LabelAutomaticUpdatesTmdb": "Enable automatic updates from TheMovieDB.org", + "LabelAutomaticUpdatesTvdb": "Enable automatic updates from TheTVDB.com", + "LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.", + "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.", + "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.", + "LabelFanartApiKey": "Personal api key:", + "LabelFanartApiKeyHelp": "Requests to fanart without a personal API key return results that were approved over 7 days ago. With a personal API key that drops to 48 hours and if you are also a fanart VIP member that will further drop to around 10 minutes.", + "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", + "LabelMetadataDownloadLanguage": "Preferred download language:", + "ButtonAutoScroll": "Auto-scroll", + "LabelImageSavingConvention": "Image saving convention:", + "LabelImageSavingConventionHelp": "Media Browser recognizes images from most major media applications. Choosing your downloading convention is useful if you also use other products.", + "OptionImageSavingCompatible": "Compatible - Media Browser\/Kodi\/Plex", + "OptionImageSavingStandard": "Standard - MB2", + "ButtonSignIn": "Sign In", + "TitleSignIn": "Sign In", + "HeaderPleaseSignIn": "Please sign in", + "LabelUser": "User:", + "LabelPassword": "Password:", + "ButtonManualLogin": "Manual Login", + "PasswordLocalhostMessage": "Passwords are not required when logging in from localhost.", + "TabGuide": "Guide", + "TabChannels": "Channels", + "TabCollections": "Collections", + "HeaderChannels": "Channels", + "TabRecordings": "Recordings", + "TabScheduled": "Scheduled", + "TabSeries": "Series", + "TabFavorites": "Favorites", + "TabMyLibrary": "My Library", + "ButtonCancelRecording": "Cancel Recording", + "HeaderPrePostPadding": "Pre\/Post Padding", + "LabelPrePaddingMinutes": "Pre-padding minutes:", + "OptionPrePaddingRequired": "Pre-padding is required in order to record.", + "LabelPostPaddingMinutes": "Post-padding minutes:", + "OptionPostPaddingRequired": "Post-padding is required in order to record.", + "HeaderWhatsOnTV": "What's On", + "HeaderUpcomingTV": "Upcoming TV", + "TabStatus": "Status", + "TabSettings": "Settings", + "ButtonRefreshGuideData": "Refresh Guide Data", + "ButtonRefresh": "Refresh", + "ButtonAdvancedRefresh": "Advanced Refresh", + "OptionPriority": "Priority", + "OptionRecordOnAllChannels": "Record program on all channels", + "OptionRecordAnytime": "Record program at any time", + "OptionRecordOnlyNewEpisodes": "Record only new episodes", + "HeaderDays": "Days", + "HeaderActiveRecordings": "Active Recordings", + "HeaderLatestRecordings": "Latest Recordings", + "HeaderAllRecordings": "All Recordings", + "ButtonPlay": "Play", + "ButtonEdit": "Edit", + "ButtonRecord": "Record", + "ButtonDelete": "Delete", + "ButtonRemove": "Remove", + "OptionRecordSeries": "Record Series", + "HeaderDetails": "Details", + "TitleLiveTV": "Live TV", + "LabelNumberOfGuideDays": "Number of days of guide data to download:", + "LabelNumberOfGuideDaysHelp": "Downloading more days worth of guide data provides the ability to schedule out further in advance and view more listings, but it will also take longer to download. Auto will choose based on the number of channels.", + "LabelActiveService": "Active Service:", + "LabelActiveServiceHelp": "Multiple tv plugins can be installed but only one can be active at a time.", + "OptionAutomatic": "Auto", + "LiveTvPluginRequired": "A Live TV service provider plugin is required in order to continue.", + "LiveTvPluginRequiredHelp": "Please install one of our available plugins, such as Next Pvr or ServerWmc.", + "LabelCustomizeOptionsPerMediaType": "Customize for media type:", + "OptionDownloadThumbImage": "Thumb", + "OptionDownloadMenuImage": "Menu", + "OptionDownloadLogoImage": "Logo", + "OptionDownloadBoxImage": "Box", + "OptionDownloadDiscImage": "Disc", + "OptionDownloadBannerImage": "Banner", + "OptionDownloadBackImage": "Back", + "OptionDownloadArtImage": "Art", + "OptionDownloadPrimaryImage": "Primary", + "HeaderFetchImages": "Fetch Images:", + "HeaderImageSettings": "Image Settings", + "TabOther": "Other", + "LabelMaxBackdropsPerItem": "Maximum number of backdrops per item:", + "LabelMaxScreenshotsPerItem": "Maximum number of screenshots per item:", + "LabelMinBackdropDownloadWidth": "Minimum backdrop download width:", + "LabelMinScreenshotDownloadWidth": "Minimum screenshot download width:", + "ButtonAddScheduledTaskTrigger": "Add Trigger", + "HeaderAddScheduledTaskTrigger": "Add Trigger", + "ButtonAdd": "Add", + "LabelTriggerType": "Trigger Type:", + "OptionDaily": "Daily", + "OptionWeekly": "Weekly", + "OptionOnInterval": "On an interval", + "OptionOnAppStartup": "On application startup", + "OptionAfterSystemEvent": "After a system event", + "LabelDay": "Day:", + "LabelTime": "Time:", + "LabelEvent": "Event:", + "OptionWakeFromSleep": "Wake from sleep", + "LabelEveryXMinutes": "Every:", + "HeaderTvTuners": "Tuners", + "HeaderGallery": "Gallery", + "HeaderLatestGames": "Latest Games", + "HeaderRecentlyPlayedGames": "Recently Played Games", + "TabGameSystems": "Game Systems", + "TitleMediaLibrary": "Media Library", + "TabFolders": "Folders", + "TabPathSubstitution": "Path Substitution", + "LabelSeasonZeroDisplayName": "Season 0 display name:", + "LabelEnableRealtimeMonitor": "Enable real time monitoring", + "LabelEnableRealtimeMonitorHelp": "Changes will be processed immediately, on supported file systems.", + "ButtonScanLibrary": "Scan Library", + "HeaderNumberOfPlayers": "Players:", + "OptionAnyNumberOfPlayers": "Any", + "Option1Player": "1+", + "Option2Player": "2+", + "Option3Player": "3+", + "Option4Player": "4+", + "HeaderMediaFolders": "Media Folders", + "HeaderThemeVideos": "Theme Videos", + "HeaderThemeSongs": "Theme Songs", + "HeaderScenes": "Scenes", + "HeaderAwardsAndReviews": "Awards and Reviews", + "HeaderSoundtracks": "Soundtracks", + "HeaderMusicVideos": "Music Videos", + "HeaderSpecialFeatures": "Special Features", + "HeaderCastCrew": "Cast & Crew", + "HeaderAdditionalParts": "Additional Parts", + "ButtonSplitVersionsApart": "Split Versions Apart", + "ButtonPlayTrailer": "Trailer", + "LabelMissing": "Missing", + "LabelOffline": "Offline", + "PathSubstitutionHelp": "Path substitutions are used for mapping a path on the server to a path that clients are able to access. By allowing clients direct access to media on the server they may be able to play them directly over the network and avoid using server resources to stream and transcode them.", + "HeaderFrom": "From", + "HeaderTo": "To", + "LabelFrom": "From:", + "LabelFromHelp": "Example: D:\\Movies (on the server)", + "LabelTo": "To:", + "LabelToHelp": "Example: \\\\MyServer\\Movies (a path clients can access)", + "ButtonAddPathSubstitution": "Add Substitution", + "OptionSpecialEpisode": "Specials", + "OptionMissingEpisode": "Missing Episodes", + "OptionUnairedEpisode": "Unaired Episodes", + "OptionEpisodeSortName": "Episode Sort Name", + "OptionSeriesSortName": "Series Name", + "OptionTvdbRating": "Tvdb Rating", + "HeaderTranscodingQualityPreference": "Transcoding Quality Preference:", + "OptionAutomaticTranscodingHelp": "The server will decide quality and speed", + "OptionHighSpeedTranscodingHelp": "Lower quality, but faster encoding", + "OptionHighQualityTranscodingHelp": "Higher quality, but slower encoding", + "OptionMaxQualityTranscodingHelp": "Best quality with slower encoding and high CPU usage", + "OptionHighSpeedTranscoding": "Higher speed", + "OptionHighQualityTranscoding": "Higher quality", + "OptionMaxQualityTranscoding": "Max quality", + "OptionEnableDebugTranscodingLogging": "Enable debug transcoding logging", + "OptionEnableDebugTranscodingLoggingHelp": "This will create very large log files and is only recommended as needed for troubleshooting purposes.", + "OptionUpscaling": "Allow clients to request upscaled video", + "OptionUpscalingHelp": "In some cases this will result in improved video quality but will increase CPU usage.", + "EditCollectionItemsHelp": "Add or remove any movies, series, albums, books or games you wish to group within this collection.", + "HeaderAddTitles": "Add Titles", + "LabelEnableDlnaPlayTo": "Enable DLNA Play To", + "LabelEnableDlnaPlayToHelp": "Media Browser can detect devices within your network and offer the ability to remote control them.", + "LabelEnableDlnaDebugLogging": "Enable DLNA debug logging", + "LabelEnableDlnaDebugLoggingHelp": "This will create large log files and should only be used as needed for troubleshooting purposes.", + "LabelEnableDlnaClientDiscoveryInterval": "Client discovery interval (seconds)", + "LabelEnableDlnaClientDiscoveryIntervalHelp": "Determines the duration in seconds between SSDP searches performed by Media Browser.", + "HeaderCustomDlnaProfiles": "Custom Profiles", + "HeaderSystemDlnaProfiles": "System Profiles", + "CustomDlnaProfilesHelp": "Create a custom profile to target a new device or override a system profile.", + "SystemDlnaProfilesHelp": "System profiles are read-only. Changes to a system profile will be saved to a new custom profile.", + "TitleDashboard": "Dashboard", + "TabHome": "Home", + "TabInfo": "Info", + "HeaderLinks": "Links", + "HeaderSystemPaths": "System Paths", + "LinkCommunity": "Community", + "LinkGithub": "Github", + "LinkApi": "Api", + "LinkApiDocumentation": "Api Documentation", + "LabelFriendlyServerName": "Friendly server name:", + "LabelFriendlyServerNameHelp": "This name will be used to identify this server. If left blank, the computer name will be used.", + "LabelPreferredDisplayLanguage": "Preferred display language:", + "LabelPreferredDisplayLanguageHelp": "Translating Media Browser is an ongoing project and is not yet complete.", + "LabelReadHowYouCanContribute": "Read about how you can contribute.", + "HeaderNewCollection": "New Collection", + "ButtonSubmit": "Submit", + "ButtonCreate": "Create", + "LabelCustomCss": "Custom css:", + "LabelCustomCssHelp": "Apply your own custom css to the web interface.", + "LabelLocalHttpServerPortNumber": "Local http port number:", + "LabelLocalHttpServerPortNumberHelp": "The tcp port number that Media Browser's http server should bind to.", + "LabelPublicHttpPort": "Public http port number:", + "LabelPublicHttpPortHelp": "The public port number that should be mapped to the local http port.", + "LabelPublicHttpsPort": "Public https port number:", + "LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.", + "LabelEnableHttps": "Report https as external address", + "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.", + "LabelHttpsPort": "Local https port number:", + "LabelHttpsPortHelp": "The tcp port number that Media Browser's https server should bind to.", + "LabelWebSocketPortNumber": "Web socket port number:", + "LabelEnableAutomaticPortMap": "Enable automatic port mapping", + "LabelEnableAutomaticPortMapHelp": "Attempt to automatically map the public port to the local port via UPnP. This may not work with some router models.", + "LabelExternalDDNS": "External WAN Address:", + "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely. Leave empty for automatic detection.", + "TabResume": "Resume", + "TabWeather": "Weather", + "TitleAppSettings": "App Settings", + "LabelMinResumePercentage": "Min resume percentage:", + "LabelMaxResumePercentage": "Max resume percentage:", + "LabelMinResumeDuration": "Min resume duration (seconds):", + "LabelMinResumePercentageHelp": "Titles are assumed unplayed if stopped before this time", + "LabelMaxResumePercentageHelp": "Titles are assumed fully played if stopped after this time", + "LabelMinResumeDurationHelp": "Titles shorter than this will not be resumable", + "TitleAutoOrganize": "Auto-Organize", + "TabActivityLog": "Activity Log", + "HeaderName": "Name", + "HeaderDate": "Date", + "HeaderSource": "Source", + "HeaderDestination": "Destination", + "HeaderProgram": "Program", + "HeaderClients": "Clients", + "LabelCompleted": "Completed", + "LabelFailed": "Failed", + "LabelSkipped": "Skipped", + "HeaderEpisodeOrganization": "Episode Organization", + "LabelSeries": "Series:", + "LabelSeasonNumber": "Season number:", + "LabelEpisodeNumber": "Episode number:", + "LabelEndingEpisodeNumber": "Ending episode number:", + "LabelEndingEpisodeNumberHelp": "Only required for multi-episode files", + "HeaderSupportTheTeam": "Support the Media Browser Team", + "LabelSupportAmount": "Amount (USD)", + "HeaderSupportTheTeamHelp": "Help ensure the continued development of this project by donating. A portion of all donations will be contributed to other free tools we depend on.", + "ButtonEnterSupporterKey": "Enter supporter key", + "DonationNextStep": "Once complete, please return and enter your supporter key, which you will receive by email.", + "AutoOrganizeHelp": "Auto-organize monitors your download folders for new files and moves them to your media directories.", + "AutoOrganizeTvHelp": "TV file organizing will only add episodes to existing series. It will not create new series folders.", + "OptionEnableEpisodeOrganization": "Enable new episode organization", + "LabelWatchFolder": "Watch folder:", + "LabelWatchFolderHelp": "The server will poll this folder during the 'Organize new media files' scheduled task.", + "ButtonViewScheduledTasks": "View scheduled tasks", + "LabelMinFileSizeForOrganize": "Minimum file size (MB):", + "LabelMinFileSizeForOrganizeHelp": "Files under this size will be ignored.", + "LabelSeasonFolderPattern": "Season folder pattern:", + "LabelSeasonZeroFolderName": "Season zero folder name:", + "HeaderEpisodeFilePattern": "Episode file pattern", + "LabelEpisodePattern": "Episode pattern:", + "LabelMultiEpisodePattern": "Multi-Episode pattern:", + "HeaderSupportedPatterns": "Supported Patterns", + "HeaderTerm": "Term", + "HeaderPattern": "Pattern", + "HeaderResult": "Result", + "LabelDeleteEmptyFolders": "Delete empty folders after organizing", + "LabelDeleteEmptyFoldersHelp": "Enable this to keep the download directory clean.", + "LabelDeleteLeftOverFiles": "Delete left over files with the following extensions:", + "LabelDeleteLeftOverFilesHelp": "Separate with ;. For example: .nfo;.txt", + "OptionOverwriteExistingEpisodes": "Overwrite existing episodes", + "LabelTransferMethod": "Transfer method", + "OptionCopy": "Copy", + "OptionMove": "Move", + "LabelTransferMethodHelp": "Copy or move files from the watch folder", + "HeaderLatestNews": "Latest News", + "HeaderHelpImproveMediaBrowser": "Help Improve Media Browser", + "HeaderRunningTasks": "Running Tasks", + "HeaderActiveDevices": "Active Devices", + "HeaderPendingInstallations": "Pending Installations", + "HeaderServerInformation": "Server Information", + "ButtonRestartNow": "Restart Now", + "ButtonRestart": "Restart", + "ButtonShutdown": "Shutdown", + "ButtonUpdateNow": "Update Now", + "TabHosting": "Hosting", + "PleaseUpdateManually": "Please shutdown the server and update manually.", + "NewServerVersionAvailable": "A new version of Media Browser Server is available!", + "ServerUpToDate": "Media Browser Server is up to date", + "ErrorConnectingToMediaBrowserRepository": "There was an error connecting to the remote Media Browser repository.", + "LabelComponentsUpdated": "The following components have been installed or updated:", + "MessagePleaseRestartServerToFinishUpdating": "Please restart the server to finish applying updates.", + "LabelDownMixAudioScale": "Audio boost when downmixing:", + "LabelDownMixAudioScaleHelp": "Boost audio when downmixing. Set to 1 to preserve original volume value.", + "ButtonLinkKeys": "Transfer Key", + "LabelOldSupporterKey": "Old supporter key", + "LabelNewSupporterKey": "New supporter key", + "HeaderMultipleKeyLinking": "Transfer to New Key", + "MultipleKeyLinkingHelp": "If you received a new supporter key, use this form to transfer the old key's registrations to your new one.", + "LabelCurrentEmailAddress": "Current email address", + "LabelCurrentEmailAddressHelp": "The current email address to which your new key was sent.", + "HeaderForgotKey": "Forgot Key", + "LabelEmailAddress": "Email address", + "LabelSupporterEmailAddress": "The email address that was used to purchase the key.", + "ButtonRetrieveKey": "Retrieve Key", + "LabelSupporterKey": "Supporter Key (paste from email)", + "LabelSupporterKeyHelp": "Enter your supporter key to start enjoying additional benefits the community has developed for Media Browser.", + "MessageInvalidKey": "Supporter key is missing or invalid.", + "ErrorMessageInvalidKey": "In order for any premium content to be registered, you must also be a Media Browser Supporter. Please donate and support the continued development of the core product. Thank you.", + "HeaderDisplaySettings": "Display Settings", + "TabPlayTo": "Play To", + "LabelEnableDlnaServer": "Enable Dlna server", + "LabelEnableDlnaServerHelp": "Allows UPnP devices on your network to browse and play Media Browser content.", + "LabelEnableBlastAliveMessages": "Blast alive messages", + "LabelEnableBlastAliveMessagesHelp": "Enable this if the server is not detected reliably by other UPnP devices on your network.", + "LabelBlastMessageInterval": "Alive message interval (seconds)", + "LabelBlastMessageIntervalHelp": "Determines the duration in seconds between server alive messages.", + "LabelDefaultUser": "Default user:", + "LabelDefaultUserHelp": "Determines which user library should be displayed on connected devices. This can be overridden for each device using profiles.", + "TitleDlna": "DLNA", + "TitleChannels": "Channels", + "HeaderServerSettings": "Server Settings", + "LabelWeatherDisplayLocation": "Weather display location:", + "LabelWeatherDisplayLocationHelp": "US zip code \/ City, State, Country \/ City, Country", + "LabelWeatherDisplayUnit": "Weather display unit:", + "OptionCelsius": "Celsius", + "OptionFahrenheit": "Fahrenheit", + "HeaderRequireManualLogin": "Require manual username entry for:", + "HeaderRequireManualLoginHelp": "When disabled clients may present a login screen with a visual selection of users.", + "OptionOtherApps": "Other apps", + "OptionMobileApps": "Mobile apps", + "HeaderNotificationList": "Click on a notification to configure it's sending options.", + "NotificationOptionApplicationUpdateAvailable": "Application update available", + "NotificationOptionApplicationUpdateInstalled": "Application update installed", + "NotificationOptionPluginUpdateInstalled": "Plugin update installed", + "NotificationOptionPluginInstalled": "Plugin installed", + "NotificationOptionPluginUninstalled": "Plugin uninstalled", + "NotificationOptionVideoPlayback": "Video playback started", + "NotificationOptionAudioPlayback": "Audio playback started", + "NotificationOptionGamePlayback": "Game playback started", + "NotificationOptionVideoPlaybackStopped": "Video playback stopped", + "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", + "NotificationOptionGamePlaybackStopped": "Game playback stopped", + "NotificationOptionTaskFailed": "Scheduled task failure", + "NotificationOptionInstallationFailed": "Installation failure", + "NotificationOptionNewLibraryContent": "New content added", + "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", + "NotificationOptionCameraImageUploaded": "Camera image uploaded", + "SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.", + "NotificationOptionServerRestartRequired": "Server restart required", + "LabelNotificationEnabled": "Enable this notification", + "LabelMonitorUsers": "Monitor activity from:", + "LabelSendNotificationToUsers": "Send the notification to:", + "LabelUseNotificationServices": "Use the following services:", + "CategoryUser": "User", + "CategorySystem": "System", + "CategoryApplication": "Application", + "CategoryPlugin": "Plugin", + "LabelMessageTitle": "Message title:", + "LabelAvailableTokens": "Available tokens:", + "AdditionalNotificationServices": "Browse the plugin catalog to install additional notification services.", + "OptionAllUsers": "All users", + "OptionAdminUsers": "Administrators", + "OptionCustomUsers": "Custom", + "ButtonArrowUp": "Up", + "ButtonArrowDown": "Down", + "ButtonArrowLeft": "Left", + "ButtonArrowRight": "Right", + "ButtonBack": "Back", + "ButtonInfo": "Info", + "ButtonOsd": "On screen display", + "ButtonPageUp": "Page Up", + "ButtonPageDown": "Page Down", + "PageAbbreviation": "PG", + "ButtonHome": "Home", + "ButtonSearch": "Search", + "ButtonSettings": "Settings", + "ButtonTakeScreenshot": "Capture Screenshot", + "ButtonLetterUp": "Letter Up", + "ButtonLetterDown": "Letter Down", + "PageButtonAbbreviation": "PG", + "LetterButtonAbbreviation": "A", + "TabNowPlaying": "Now Playing", + "TabNavigation": "Navigation", + "TabControls": "Controls", + "ButtonFullscreen": "Toggle fullscreen", + "ButtonScenes": "Scenes", + "ButtonSubtitles": "Subtitles", + "ButtonAudioTracks": "Audio tracks", + "ButtonPreviousTrack": "Previous track", + "ButtonNextTrack": "Next track", + "ButtonStop": "Stop", + "ButtonPause": "Pause", + "ButtonNext": "Next", + "ButtonPrevious": "Previous", + "LabelGroupMoviesIntoCollections": "Group movies into collections", + "LabelGroupMoviesIntoCollectionsHelp": "When displaying movie lists, movies belonging to a collection will be displayed as one grouped item.", + "NotificationOptionPluginError": "Plugin failure", + "ButtonVolumeUp": "Volume up", + "ButtonVolumeDown": "Volume down", + "ButtonMute": "Mute", + "HeaderLatestMedia": "Latest Media", + "OptionSpecialFeatures": "Special Features", + "HeaderCollections": "Collections", + "LabelProfileCodecsHelp": "Separated by comma. This can be left empty to apply to all codecs.", + "LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.", + "HeaderResponseProfile": "Response Profile", + "LabelType": "Type:", + "LabelPersonRole": "Role:", + "LabelPersonRoleHelp": "Role is generally only applicable to actors.", + "LabelProfileContainer": "Container:", + "LabelProfileVideoCodecs": "Video codecs:", + "LabelProfileAudioCodecs": "Audio codecs:", + "LabelProfileCodecs": "Codecs:", + "HeaderDirectPlayProfile": "Direct Play Profile", + "HeaderTranscodingProfile": "Transcoding Profile", + "HeaderCodecProfile": "Codec Profile", + "HeaderCodecProfileHelp": "Codec profiles indicate the limitations of a device when playing specific codecs. If a limitation applies then the media will be transcoded, even if the codec is configured for direct play.", + "HeaderContainerProfile": "Container Profile", + "HeaderContainerProfileHelp": "Container profiles indicate the limitations of a device when playing specific formats. If a limitation applies then the media will be transcoded, even if the format is configured for direct play.", + "OptionProfileVideo": "Video", + "OptionProfileAudio": "Audio", + "OptionProfileVideoAudio": "Video Audio", + "OptionProfilePhoto": "Photo", + "LabelUserLibrary": "User library:", + "LabelUserLibraryHelp": "Select which user library to display to the device. Leave empty to inherit the default setting.", + "OptionPlainStorageFolders": "Display all folders as plain storage folders", + "OptionPlainStorageFoldersHelp": "If enabled, all folders are represented in DIDL as \"object.container.storageFolder\" instead of a more specific type, such as \"object.container.person.musicArtist\".", + "OptionPlainVideoItems": "Display all videos as plain video items", + "OptionPlainVideoItemsHelp": "If enabled, all videos are represented in DIDL as \"object.item.videoItem\" instead of a more specific type, such as \"object.item.videoItem.movie\".", + "LabelSupportedMediaTypes": "Supported Media Types:", + "TabIdentification": "Identification", + "HeaderIdentification": "Identification", + "TabDirectPlay": "Direct Play", + "TabContainers": "Containers", + "TabCodecs": "Codecs", + "TabResponses": "Responses", + "HeaderProfileInformation": "Profile Information", + "LabelEmbedAlbumArtDidl": "Embed album art in Didl", + "LabelEmbedAlbumArtDidlHelp": "Some devices prefer this method for obtaining album art. Others may fail to play with this option enabled.", + "LabelAlbumArtPN": "Album art PN:", + "LabelAlbumArtHelp": "PN used for album art, within the dlna:profileID attribute on upnp:albumArtURI. Some clients require a specific value, regardless of the size of the image.", + "LabelAlbumArtMaxWidth": "Album art max width:", + "LabelAlbumArtMaxWidthHelp": "Max resolution of album art exposed via upnp:albumArtURI.", + "LabelAlbumArtMaxHeight": "Album art max height:", + "LabelAlbumArtMaxHeightHelp": "Max resolution of album art exposed via upnp:albumArtURI.", + "LabelIconMaxWidth": "Icon max width:", + "LabelIconMaxWidthHelp": "Max resolution of icons exposed via upnp:icon.", + "LabelIconMaxHeight": "Icon max height:", + "LabelIconMaxHeightHelp": "Max resolution of icons exposed via upnp:icon.", + "LabelIdentificationFieldHelp": "A case-insensitive substring or regex expression.", + "HeaderProfileServerSettingsHelp": "These values control how Media Browser will present itself to the device.", + "LabelMaxBitrate": "Max bitrate:", + "LabelMaxBitrateHelp": "Specify a max bitrate in bandwidth constrained environments, or if the device imposes it's own limit.", + "LabelMaxStreamingBitrate": "Max streaming bitrate:", + "LabelMaxStreamingBitrateHelp": "Specify a max bitrate when streaming.", + "LabelMaxStaticBitrate": "Max sync bitrate:", + "LabelMaxStaticBitrateHelp": "Specify a max bitrate when syncing content at high quality.", + "LabelMusicStaticBitrate": "Music sync bitrate:", + "LabelMusicStaticBitrateHelp": "Specify a max bitrate when syncing music", + "LabelMusicStreamingTranscodingBitrate": "Music transcoding bitrate:", + "LabelMusicStreamingTranscodingBitrateHelp": "Specify a max bitrate when streaming music", + "OptionIgnoreTranscodeByteRangeRequests": "Ignore transcode byte range requests", + "OptionIgnoreTranscodeByteRangeRequestsHelp": "If enabled, these requests will be honored but will ignore the byte range header.", + "LabelFriendlyName": "Friendly name", + "LabelManufacturer": "Manufacturer", + "LabelManufacturerUrl": "Manufacturer url", + "LabelModelName": "Model name", + "LabelModelNumber": "Model number", + "LabelModelDescription": "Model description", + "LabelModelUrl": "Model url", + "LabelSerialNumber": "Serial number", + "LabelDeviceDescription": "Device description", + "HeaderIdentificationCriteriaHelp": "Enter at least one identification criteria.", + "HeaderDirectPlayProfileHelp": "Add direct play profiles to indicate which formats the device can handle natively.", + "HeaderTranscodingProfileHelp": "Add transcoding profiles to indicate which formats should be used when transcoding is required.", + "HeaderResponseProfileHelp": "Response profiles provide a way to customize information sent to the device when playing certain kinds of media.", + "LabelXDlnaCap": "X-Dlna cap:", + "LabelXDlnaCapHelp": "Determines the content of the X_DLNACAP element in the urn:schemas-dlna-org:device-1-0 namespace.", + "LabelXDlnaDoc": "X-Dlna doc:", + "LabelXDlnaDocHelp": "Determines the content of the X_DLNADOC element in the urn:schemas-dlna-org:device-1-0 namespace.", + "LabelSonyAggregationFlags": "Sony aggregation flags:", + "LabelSonyAggregationFlagsHelp": "Determines the content of the aggregationFlags element in the urn:schemas-sonycom:av namespace.", + "LabelTranscodingContainer": "Container:", + "LabelTranscodingVideoCodec": "Video codec:", + "LabelTranscodingVideoProfile": "Video profile:", + "LabelTranscodingAudioCodec": "Audio codec:", + "OptionEnableM2tsMode": "Enable M2ts mode", + "OptionEnableM2tsModeHelp": "Enable m2ts mode when encoding to mpegts.", + "OptionEstimateContentLength": "Estimate content length when transcoding", + "OptionReportByteRangeSeekingWhenTranscoding": "Report that the server supports byte seeking when transcoding", + "OptionReportByteRangeSeekingWhenTranscodingHelp": "This is required for some devices that don't time seek very well.", + "HeaderSubtitleDownloadingHelp": "When Media Browser scans your video files it can search for missing subtitles, and download them using a subtitle provider such as OpenSubtitles.org.", + "HeaderDownloadSubtitlesFor": "Download subtitles for:", + "MessageNoChapterProviders": "Install a chapter provider plugin such as ChapterDb to enable additional chapter options.", + "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains graphical subtitles", + "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.", + "TabSubtitles": "Subtitles", + "TabChapters": "Chapters", + "HeaderDownloadChaptersFor": "Download chapter names for:", + "LabelOpenSubtitlesUsername": "Open Subtitles username:", + "LabelOpenSubtitlesPassword": "Open Subtitles password:", + "HeaderChapterDownloadingHelp": "When Media Browser scans your video files it can download friendly chapter names from the internet using chapter plugins such as ChapterDb.", + "LabelPlayDefaultAudioTrack": "Play default audio track regardless of language", + "LabelSubtitlePlaybackMode": "Subtitle mode:", + "LabelDownloadLanguages": "Download languages:", + "ButtonRegister": "Register", + "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language", + "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.", + "HeaderSendMessage": "Send Message", + "ButtonSend": "Send", + "LabelMessageText": "Message text:", + "MessageNoAvailablePlugins": "No available plugins.", + "LabelDisplayPluginsFor": "Display plugins for:", + "PluginTabMediaBrowserClassic": "MB Classic", + "PluginTabMediaBrowserTheater": "MB Theater", + "LabelEpisodeNamePlain": "Episode name", + "LabelSeriesNamePlain": "Series name", + "ValueSeriesNamePeriod": "Series.name", + "ValueSeriesNameUnderscore": "Series_name", + "ValueEpisodeNamePeriod": "Episode.name", + "ValueEpisodeNameUnderscore": "Episode_name", + "LabelSeasonNumberPlain": "Season number", + "LabelEpisodeNumberPlain": "Episode number", + "LabelEndingEpisodeNumberPlain": "Ending episode number", + "HeaderTypeText": "Enter Text", + "LabelTypeText": "Text", + "HeaderSearchForSubtitles": "Search for Subtitles", + "MessageNoSubtitleSearchResultsFound": "No search results founds.", + "TabDisplay": "Display", + "TabLanguages": "Languages", + "TabWebClient": "Web Client", + "LabelEnableThemeSongs": "Enable theme songs", + "LabelEnableBackdrops": "Enable backdrops", + "LabelEnableThemeSongsHelp": "If enabled, theme songs will be played in the background while browsing the library.", + "LabelEnableBackdropsHelp": "If enabled, backdrops will be displayed in the background of some pages while browsing the library.", + "HeaderHomePage": "Home Page", + "HeaderSettingsForThisDevice": "Settings for This Device", + "OptionAuto": "Auto", + "OptionYes": "Yes", + "OptionNo": "No", + "HeaderOptions": "Options", + "HeaderIdentificationResult": "Identification Result", + "LabelHomePageSection1": "Home page section 1:", + "LabelHomePageSection2": "Home page section 2:", + "LabelHomePageSection3": "Home page section 3:", + "LabelHomePageSection4": "Home page section 4:", + "OptionMyViewsButtons": "My views (buttons)", + "OptionMyViews": "My views", + "OptionMyViewsSmall": "My views (small)", + "OptionResumablemedia": "Resume", + "OptionLatestMedia": "Latest media", + "OptionLatestChannelMedia": "Latest channel items", + "HeaderLatestChannelItems": "Latest Channel Items", + "OptionNone": "None", + "HeaderLiveTv": "Live TV", + "HeaderReports": "Reports", + "HeaderMetadataManager": "Metadata Manager", + "HeaderPreferences": "Preferences", + "MessageLoadingChannels": "Loading channel content...", + "MessageLoadingContent": "Loading content...", + "ButtonMarkRead": "Mark Read", + "OptionDefaultSort": "Default", + "OptionCommunityMostWatchedSort": "Most Watched", + "TabNextUp": "Next Up", + "HeaderBecomeMediaBrowserSupporter": "Become a Media Browser Supporter", + "TextEnjoyBonusFeatures": "Enjoy Bonus Features", + "MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.", + "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.", + "MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.", + "MessageNoPlaylistItemsAvailable": "This playlist is currently empty.", + "ButtonDismiss": "Dismiss", + "ButtonEditOtherUserPreferences": "Edit this user's profile, password and personal preferences.", + "LabelChannelStreamQuality": "Preferred internet stream quality:", + "LabelChannelStreamQualityHelp": "In a low bandwidth environment, limiting quality can help ensure a smooth streaming experience.", + "OptionBestAvailableStreamQuality": "Best available", + "LabelEnableChannelContentDownloadingFor": "Enable channel content downloading for:", + "LabelEnableChannelContentDownloadingForHelp": "Some channels support downloading content prior to viewing. Enable this in low bandwidth enviornments to download channel content during off hours. Content is downloaded as part of the channel download scheduled task.", + "LabelChannelDownloadPath": "Channel content download path:", + "LabelChannelDownloadPathHelp": "Specify a custom download path if desired. Leave empty to download to an internal program data folder.", + "LabelChannelDownloadAge": "Delete content after: (days)", + "LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.", + "ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.", + "ButtonOptions": "Options", + "ViewTypeMovies": "Movies", + "ViewTypeTvShows": "TV", + "ViewTypeGames": "Games", + "ViewTypeMusic": "Music", + "ViewTypeMusicGenres": "Genres", + "ViewTypeMusicArtists": "Artists", + "ViewTypeBoxSets": "Collections", + "ViewTypeChannels": "Channels", + "ViewTypeLiveTV": "Live TV", + "ViewTypeLiveTvNowPlaying": "Now Airing", + "ViewTypeLatestGames": "Latest Games", + "ViewTypeRecentlyPlayedGames": "Recently Played", + "ViewTypeGameFavorites": "Favorites", + "ViewTypeGameSystems": "Game Systems", + "ViewTypeGameGenres": "Genres", + "ViewTypeTvResume": "Resume", + "ViewTypeTvNextUp": "Next Up", + "ViewTypeTvLatest": "Latest", + "ViewTypeTvShowSeries": "Series", + "ViewTypeTvGenres": "Genres", + "ViewTypeTvFavoriteSeries": "Favorite Series", + "ViewTypeTvFavoriteEpisodes": "Favorite Episodes", + "ViewTypeMovieResume": "Resume", + "ViewTypeMovieLatest": "Latest", + "ViewTypeMovieMovies": "Movies", + "ViewTypeMovieCollections": "Collections", + "ViewTypeMovieFavorites": "Favorites", + "ViewTypeMovieGenres": "Genres", + "ViewTypeMusicLatest": "Latest", + "ViewTypeMusicAlbums": "Albums", + "ViewTypeMusicAlbumArtists": "Album Artists", + "HeaderOtherDisplaySettings": "Display Settings", + "ViewTypeMusicSongs": "Songs", + "ViewTypeMusicFavorites": "Favorites", + "ViewTypeMusicFavoriteAlbums": "Favorite Albums", + "ViewTypeMusicFavoriteArtists": "Favorite Artists", + "ViewTypeMusicFavoriteSongs": "Favorite Songs", + "HeaderMyViews": "My Views", + "LabelSelectFolderGroups": "Automatically group content from the following folders into views such as Movies, Music and TV:", + "LabelSelectFolderGroupsHelp": "Folders that are unchecked will be displayed by themselves in their own view.", + "OptionDisplayAdultContent": "Display adult content", + "OptionLibraryFolders": "Media folders", + "TitleRemoteControl": "Remote Control", + "OptionLatestTvRecordings": "Latest recordings", + "LabelProtocolInfo": "Protocol info:", + "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.", + "TabNfo": "Nfo", + "HeaderKodiMetadataHelp": "Media Browser includes native support for Kodi Nfo metadata and images. To enable or disable Kodi metadata, use the Advanced tab to configure options for your media types.", + "LabelKodiMetadataUser": "Sync user watch data to nfo's for:", + "LabelKodiMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Kodi.", + "LabelKodiMetadataDateFormat": "Release date format:", + "LabelKodiMetadataDateFormatHelp": "All dates within nfo's will be read and written to using this format.", + "LabelKodiMetadataSaveImagePaths": "Save image paths within nfo files", + "LabelKodiMetadataSaveImagePathsHelp": "This is recommended if you have image file names that don't conform to Kodi guidelines.", + "LabelKodiMetadataEnablePathSubstitution": "Enable path substitution", + "LabelKodiMetadataEnablePathSubstitutionHelp": "Enables path substitution of image paths using the server's path substitution settings.", + "LabelKodiMetadataEnablePathSubstitutionHelp2": "See path substitution.", + "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:", + "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.", + "LabelDisplayCollectionsView": "Display a collections view to show movie collections", + "LabelDisplayCollectionsViewHelp": "This will create a separate view to display collections that you've created or have access to. To create a collection, right-click or tap-hold any movie and select 'Add to Collection'. ", + "LabelKodiMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs", + "LabelKodiMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Kodi skin compatibility.", + "TabServices": "Services", + "TabLogs": "Logs", + "HeaderServerLogFiles": "Server log files:", + "TabBranding": "Branding", + "HeaderBrandingHelp": "Customize the appearance of Media Browser to fit the needs of your group or organization.", + "LabelLoginDisclaimer": "Login disclaimer:", + "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.", + "LabelAutomaticallyDonate": "Automatically donate this amount every month", + "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.", + "OptionList": "List", + "TabDashboard": "Dashboard", + "TitleServer": "Server", + "LabelCache": "Cache:", + "LabelLogs": "Logs:", + "LabelMetadata": "Metadata:", + "LabelImagesByName": "Images by name:", + "LabelTranscodingTemporaryFiles": "Transcoding temporary files:", + "HeaderLatestMusic": "Latest Music", + "HeaderBranding": "Branding", + "HeaderApiKeys": "Api Keys", + "HeaderApiKeysHelp": "External applications are required to have an Api key in order to communicate with Media Browser. Keys are issued by logging in with a Media Browser account, or by manually granting the application a key.", + "HeaderApiKey": "Api Key", + "HeaderApp": "App", + "HeaderDevice": "Device", + "HeaderUser": "User", + "HeaderDateIssued": "Date Issued", + "LabelChapterName": "Chapter {0}", + "HeaderNewApiKey": "New Api Key", + "LabelAppName": "App name", + "LabelAppNameExample": "Example: Sickbeard, NzbDrone", + "HeaderNewApiKeyHelp": "Grant an application permission to communicate with Media Browser.", + "HeaderHttpHeaders": "Http Headers", + "HeaderIdentificationHeader": "Identification Header", + "LabelValue": "Value:", + "LabelMatchType": "Match type:", + "OptionEquals": "Equals", + "OptionRegex": "Regex", + "OptionSubstring": "Substring", + "TabView": "View", + "TabSort": "Sort", + "TabFilter": "Filter", + "ButtonView": "View", + "LabelPageSize": "Item limit:", + "LabelPath": "Path:", + "LabelView": "View:", + "TabUsers": "Users", + "LabelSortName": "Sort name:", + "LabelDateAdded": "Date added:", + "HeaderFeatures": "Features", + "HeaderAdvanced": "Advanced", + "ButtonSync": "Sync", + "TabScheduledTasks": "Scheduled Tasks", + "HeaderChapters": "Chapters", + "HeaderResumeSettings": "Resume Settings", + "TabSync": "Sync", + "TitleUsers": "Users", + "LabelProtocol": "Protocol:", + "OptionProtocolHttp": "Http", + "OptionProtocolHls": "Http Live Streaming", + "LabelContext": "Context:", + "OptionContextStreaming": "Streaming", + "OptionContextStatic": "Sync", + "ButtonAddToPlaylist": "Add to playlist", + "TabPlaylists": "Playlists", + "ButtonClose": "Close", + "LabelAllLanguages": "All languages", + "HeaderBrowseOnlineImages": "Browse Online Images", + "LabelSource": "Source:", + "OptionAll": "All", + "LabelImage": "Image:", + "ButtonBrowseImages": "Browse Images", + "HeaderImages": "Images", + "HeaderBackdrops": "Backdrops", + "HeaderScreenshots": "Screenshots", + "HeaderAddUpdateImage": "Add\/Update Image", + "LabelJpgPngOnly": "JPG\/PNG only", + "LabelImageType": "Image type:", + "OptionPrimary": "Primary", + "OptionArt": "Art", + "OptionBox": "Box", + "OptionBoxRear": "Box rear", + "OptionDisc": "Disc", + "OptionLogo": "Logo", + "OptionMenu": "Menu", + "OptionScreenshot": "Screenshot", + "OptionLocked": "Locked", + "OptionUnidentified": "Unidentified", + "OptionMissingParentalRating": "Missing parental rating", + "OptionStub": "Stub", + "HeaderEpisodes": "Episodes:", + "OptionSeason0": "Season 0", + "LabelReport": "Report:", + "OptionReportSongs": "Songs", + "OptionReportSeries": "Series", + "OptionReportSeasons": "Seasons", + "OptionReportTrailers": "Trailers", + "OptionReportMusicVideos": "Music videos", + "OptionReportMovies": "Movies", + "OptionReportHomeVideos": "Home videos", + "OptionReportGames": "Games", + "OptionReportEpisodes": "Episodes", + "OptionReportCollections": "Collections", + "OptionReportBooks": "Books", + "OptionReportArtists": "Artists", + "OptionReportAlbums": "Albums", + "OptionReportAdultVideos": "Adult videos", + "ButtonMore": "More", + "HeaderActivity": "Activity", + "ScheduledTaskStartedWithName": "{0} started", + "ScheduledTaskCancelledWithName": "{0} was cancelled", + "ScheduledTaskCompletedWithName": "{0} completed", + "ScheduledTaskFailed": "Scheduled task completed", + "PluginInstalledWithName": "{0} was installed", + "PluginUpdatedWithName": "{0} was updated", + "PluginUninstalledWithName": "{0} was uninstalled", + "ScheduledTaskFailedWithName": "{0} failed", + "ItemAddedWithName": "{0} was added to the library", + "ItemRemovedWithName": "{0} was removed from the library", + "DeviceOnlineWithName": "{0} is connected", + "UserOnlineFromDevice": "{0} is online from {1}", + "DeviceOfflineWithName": "{0} has disconnected", + "UserOfflineFromDevice": "{0} has disconnected from {1}", + "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", + "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", + "LabelRunningTimeValue": "Running time: {0}", + "LabelIpAddressValue": "Ip address: {0}", + "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", + "UserCreatedWithName": "User {0} has been created", + "UserPasswordChangedWithName": "Password has been changed for user {0}", + "UserDeletedWithName": "User {0} has been deleted", + "MessageServerConfigurationUpdated": "Server configuration has been updated", + "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", + "MessageApplicationUpdated": "Media Browser Server has been updated", + "AuthenticationSucceededWithUserName": "{0} successfully authenticated", + "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", + "UserStartedPlayingItemWithValues": "{0} has started playing {1}", + "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", + "AppDeviceValues": "App: {0}, Device: {1}", + "ProviderValue": "Provider: {0}", + "LabelChannelDownloadSizeLimit": "Download size limit (GB):", + "LabelChannelDownloadSizeLimitHelpText": "Limit the size of the channel download folder.", + "HeaderRecentActivity": "Recent Activity", + "HeaderPeople": "People", + "HeaderDownloadPeopleMetadataFor": "Download biography and images for:", + "OptionComposers": "Composers", + "OptionOthers": "Others", + "HeaderDownloadPeopleMetadataForHelp": "Enabling additional options will provide more on-screen information but will result in slower library scans.", + "ViewTypeFolders": "Folders", + "LabelDisplayFoldersView": "Display a folders view to show plain media folders", + "ViewTypeLiveTvRecordingGroups": "Recordings", + "ViewTypeLiveTvChannels": "Channels", + "LabelEasyPinCode": "Easy pin code:", + "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Media Browser apps, and can also be used for easy in-network sign in.", + "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", + "LabelInNetworkSignInWithEasyPasswordHelp": "If enabled, you'll be able to use your easy pin code to sign in to Media Browser apps from inside your home network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", + "HeaderPassword": "Password", + "HeaderLocalAccess": "Local Access", + "HeaderViewOrder": "View Order", + "ButtonResetEasyPassword": "Reset easy pin code", + "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps", + "LabelMetadataRefreshMode": "Metadata refresh mode:", + "LabelImageRefreshMode": "Image refresh mode:", + "OptionDownloadMissingImages": "Download missing images", + "OptionReplaceExistingImages": "Replace existing images", + "OptionRefreshAllData": "Refresh all data", + "OptionAddMissingDataOnly": "Add missing data only", + "OptionLocalRefreshOnly": "Local refresh only", + "HeaderRefreshMetadata": "Refresh Metadata", + "HeaderPersonInfo": "Person Info", + "HeaderIdentifyItem": "Identify Item", + "HeaderIdentifyItemHelp": "Enter one or more search criteria. Remove criteria to increase search results.", + "HeaderConfirmDeletion": "Confirm Deletion", + "LabelFollowingFileWillBeDeleted": "The following file will be deleted:", + "LabelIfYouWishToContinueWithDeletion": "If you wish to continue, please confirm by entering the value of:", + "ButtonIdentify": "Identify", + "LabelAlbumArtist": "Album artist:", + "LabelAlbum": "Album:", + "LabelCommunityRating": "Community rating:", + "LabelVoteCount": "Vote count:", + "LabelMetascore": "Metascore:", + "LabelCriticRating": "Critic rating:", + "LabelCriticRatingSummary": "Critic rating summary:", + "LabelAwardSummary": "Award summary:", + "LabelWebsite": "Website:", + "LabelTagline": "Tagline:", + "LabelOverview": "Overview:", + "LabelShortOverview": "Short overview:", + "LabelReleaseDate": "Release date:", + "LabelYear": "Year:", + "LabelPlaceOfBirth": "Place of birth:", + "LabelEndDate": "End date:", + "LabelAirDate": "Air days:", + "LabelAirTime:": "Air time:", + "LabelRuntimeMinutes": "Run time (minutes):", + "LabelParentalRating": "Parental rating:", + "LabelCustomRating": "Custom rating:", + "LabelBudget": "Budget", + "LabelRevenue": "Revenue ($):", + "LabelOriginalAspectRatio": "Original aspect ratio:", + "LabelPlayers": "Players:", + "Label3DFormat": "3D format:", + "HeaderAlternateEpisodeNumbers": "Alternate Episode Numbers", + "HeaderSpecialEpisodeInfo": "Special Episode Info", + "HeaderExternalIds": "External Id's:", + "LabelDvdSeasonNumber": "Dvd season number:", + "LabelDvdEpisodeNumber": "Dvd episode number:", + "LabelAbsoluteEpisodeNumber": "Absolute episode number:", + "LabelAirsBeforeSeason": "Airs before season:", + "LabelAirsAfterSeason": "Airs after season:", + "LabelAirsBeforeEpisode": "Airs before episode:", + "LabelTreatImageAs": "Treat image as:", + "LabelDisplayOrder": "Display order:", + "LabelDisplaySpecialsWithinSeasons": "Display specials within seasons they aired in", + "HeaderCountries": "Countries", + "HeaderGenres": "Genres", + "HeaderPlotKeywords": "Plot Keywords", + "HeaderStudios": "Studios", + "HeaderTags": "Tags", + "HeaderMetadataSettings": "Metadata Settings", + "LabelLockItemToPreventChanges": "Lock this item to prevent future changes", + "MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item, or the global default value.", + "TabDonate": "Donate", + "HeaderDonationType": "Donation type:", + "OptionMakeOneTimeDonation": "Make a separate donation", + "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits and will not produce a supporter key.", + "OptionLifeTimeSupporterMembership": "Lifetime supporter membership", + "OptionYearlySupporterMembership": "Yearly supporter membership", + "OptionMonthlySupporterMembership": "Monthly supporter membership", + "OptionNoTrailer": "No Trailer", + "OptionNoThemeSong": "No Theme Song", + "OptionNoThemeVideo": "No Theme Video", + "LabelOneTimeDonationAmount": "Donation amount:", + "ButtonDonate": "Donate", + "OptionActor": "Actor", + "OptionComposer": "Composer", + "OptionDirector": "Director", + "OptionGuestStar": "Guest star", + "OptionProducer": "Producer", + "OptionWriter": "Writer", + "LabelAirDays": "Air days:", + "LabelAirTime": "Air time:", + "HeaderMediaInfo": "Media 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.", + "HeaderXmlSettings": "Xml Settings", + "HeaderXmlDocumentAttributes": "Xml Document Attributes", + "HeaderXmlDocumentAttribute": "Xml Document Attribute", + "XmlDocumentAttributeListHelp": "These attributes are applied to the root element of every xml response.", + "OptionSaveMetadataAsHidden": "Save metadata and images as hidden files", + "LabelExtractChaptersDuringLibraryScan": "Extract chapter images during the library scan", + "LabelExtractChaptersDuringLibraryScanHelp": "If enabled, chapter images will be extracted when videos are imported during the library scan. If disabled they will be extracted during the chapter images scheduled task, allowing the regular library scan to complete faster.", + "LabelConnectGuestUserName": "Their Media Browser username or email address:", + "LabelConnectUserName": "Media Browser username\/email:", + "LabelConnectUserNameHelp": "Connect this user to a Media Browser account to enable easy sign-in access from Media Browser any app without having to know the server ip address.", + "ButtonLearnMoreAboutMediaBrowserConnect": "Learn more about Media Browser Connect", + "LabelExternalPlayers": "External players:", + "LabelExternalPlayersHelp": "Display buttons to play content in external players. This is only available on devices that support url schemes, generally Android and iOS. With external players there is generally no support for remote control or resuming.", + "HeaderSubtitleProfile": "Subtitle Profile", + "HeaderSubtitleProfiles": "Subtitle Profiles", + "HeaderSubtitleProfilesHelp": "Subtitle profiles describe the subtitle formats supported by the device.", + "LabelFormat": "Format:", + "LabelMethod": "Method:", + "LabelDidlMode": "Didl mode:", + "OptionCaptionInfoExSamsung": "CaptionInfoEx (Samsung)", + "OptionResElement": "res element", + "OptionEmbedSubtitles": "Embed within container", + "OptionExternallyDownloaded": "External download", + "OptionHlsSegmentedSubtitles": "Hls segmented subtitles", + "LabelSubtitleFormatHelp": "Example: srt", + "ButtonLearnMore": "Learn more", + "TabPlayback": "Playback", + "HeaderTrailersAndExtras": "Trailers & Extras", + "OptionFindTrailers": "Find trailers from the internet automatically", + "HeaderLanguagePreferences": "Language Preferences", + "TabCinemaMode": "Cinema Mode", + "TitlePlayback": "Playback", + "LabelEnableCinemaModeFor": "Enable cinema mode for:", + "CinemaModeConfigurationHelp": "Cinema mode brings the theater experience straight to your living room with the ability to play trailers and custom intros before the main feature.", + "OptionTrailersFromMyMovies": "Include trailers from movies in my library", + "OptionUpcomingMoviesInTheaters": "Include trailers from new and upcoming movies", + "LabelLimitIntrosToUnwatchedContent": "Only use trailers from unwatched content", + "LabelEnableIntroParentalControl": "Enable smart parental control", + "LabelEnableIntroParentalControlHelp": "Trailers will only be selected with a parental rating equal to or less than the content being watched.", + "LabelTheseFeaturesRequireSupporterHelpAndTrailers": "These features require an active supporter membership and installation of the Trailer channel plugin.", + "OptionTrailersFromMyMoviesHelp": "Requires setup of local trailers.", + "LabelCustomIntrosPath": "Custom intros path:", + "LabelCustomIntrosPathHelp": "A folder containing video files. A video will be randomly selected and played after trailers.", + "ValueSpecialEpisodeName": "Special - {0}", + "LabelSelectInternetTrailersForCinemaMode": "Internet trailers:", + "OptionUpcomingDvdMovies": "Include trailers from new and upcoming movies on Dvd & Blu-ray", + "OptionUpcomingStreamingMovies": "Include trailers from new and upcoming movies on Netflix", + "LabelDisplayTrailersWithinMovieSuggestions": "Display trailers within movie suggestions", + "LabelDisplayTrailersWithinMovieSuggestionsHelp": "Requires installation of the Trailer channel.", + "CinemaModeConfigurationHelp2": "Individual users will have the ability to disable cinema mode within their own preferences.", + "LabelEnableCinemaMode": "Enable cinema mode", + "HeaderCinemaMode": "Cinema Mode", + "LabelDateAddedBehavior": "Date added behavior for new content:", + "OptionDateAddedImportTime": "Use date scanned into the library", + "OptionDateAddedFileTime": "Use file creation date", + "LabelDateAddedBehaviorHelp": "If a metadata value is present it will always be used before either of these options.", + "LabelNumberTrailerToPlay": "Number of trailers to play:", + "TitleDevices": "Devices", + "TabCameraUpload": "Camera Upload", + "TabDevices": "Devices", + "HeaderCameraUploadHelp": "Automatically upload photos and videos taken from your mobile devices into Media Browser.", + "MessageNoDevicesSupportCameraUpload": "You currently don't have any devices that support camera upload.", + "LabelCameraUploadPath": "Camera upload path:", + "LabelCameraUploadPathHelp": "Select a custom upload path, if desired. If unspecified a default folder will be used. If using a custom path it will also need to be added in the library setup area.", + "LabelCreateCameraUploadSubfolder": "Create a subfolder for each device", + "LabelCreateCameraUploadSubfolderHelp": "Specific folders can be assigned to a device by clicking on it from the Devices page.", + "LabelCustomDeviceDisplayName": "Display name:", + "LabelCustomDeviceDisplayNameHelp": "Supply a custom display name or leave empty to use the name reported by the device.", + "HeaderInviteUser": "Invite User", + "LabelConnectGuestUserNameHelp": "This is the username that your friend uses to sign in to the Media Browser website, or their email address.", + "HeaderInviteUserHelp": "Sharing your media with friends is easier than ever before with Media Browser Connect.", + "ButtonSendInvitation": "Send Invitation", + "HeaderSignInWithConnect": "Sign in with Media Browser Connect", + "HeaderGuests": "Guests", + "HeaderLocalUsers": "Local Users", + "HeaderPendingInvitations": "Pending Invitations", + "TabParentalControl": "Parental Control", + "HeaderAccessSchedule": "Access Schedule", + "HeaderAccessScheduleHelp": "Create an access schedule to limit access to certain hours.", + "ButtonAddSchedule": "Add Schedule", + "LabelAccessDay": "Day of week:", + "LabelAccessStart": "Start time:", + "LabelAccessEnd": "End time:", + "HeaderSchedule": "Schedule", + "OptionEveryday": "Every day", + "OptionWeekdays": "Weekdays", + "OptionWeekends": "Weekends", + "MessageProfileInfoSynced": "User profile information synced with Media Browser Connect.", + "HeaderOptionalLinkMediaBrowserAccount": "Optional: Link your Media Browser account", + "ButtonTrailerReel": "Trailer reel", + "HeaderTrailerReel": "Trailer Reel", + "OptionPlayUnwatchedTrailersOnly": "Play only unwatched trailers", + "HeaderTrailerReelHelp": "Start a trailer reel to play a long running playlist of trailers.", + "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.", + "HeaderNewUsers": "New Users", + "ButtonSignUp": "Sign up", + "ButtonForgotPassword": "Forgot password", + "OptionDisableUserPreferences": "Disable access to user preferences", + "OptionDisableUserPreferencesHelp": "If enabled, only administrators will be able to configure user profile images, passwords, and language preferences.", + "HeaderSelectServer": "Select Server", + "MessageNoServersAvailableToConnect": "No servers are available to connect to. If you've been invited to share a server, make sure to accept it below or by clicking the link in the email.", + "TitleNewUser": "New User", + "ButtonConfigurePassword": "Configure Password", + "HeaderDashboardUserPassword": "User passwords are managed within each user's personal profile settings.", + "HeaderLibraryAccess": "Library Access", + "HeaderChannelAccess": "Channel Access", + "HeaderLatestItems": "Latest Items", + "LabelSelectLastestItemsFolders": "Include media from the following sections in Latest Items", + "HeaderShareMediaFolders": "Share Media Folders", + "MessageGuestSharingPermissionsHelp": "Most features are initially unavailable to guests but can be enabled as needed.", + "HeaderInvitations": "Invitations", + "LabelForgotPasswordUsernameHelp": "Enter your username, if you remember it.", + "HeaderForgotPassword": "Forgot Password", + "TitleForgotPassword": "Forgot Password", + "TitlePasswordReset": "Password Reset", + "LabelPasswordRecoveryPinCode": "Pin code:", + "HeaderPasswordReset": "Password Reset", + "HeaderParentalRatings": "Parental Ratings", + "HeaderVideoTypes": "Video Types", + "HeaderYears": "Years", + "HeaderAddTag": "Add Tag", + "LabelBlockItemsWithTags": "Block items with tags:", + "LabelTag": "Tag:", + "LabelEnableSingleImageInDidlLimit": "Limit to single embedded image", + "LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.", + "TabActivity": "Activity", + "TitleSync": "Sync", + "OptionAllowSyncContent": "Allow syncing media to devices", + "NameSeasonUnknown": "Season Unknown", + "NameSeasonNumber": "Season {0}", + "LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)", + "TabJobs": "Jobs", + "TabSyncJobs": "Sync Jobs" +}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/vi.json b/MediaBrowser.Server.Implementations/Localization/Server/vi.json index 0164a55d2..d6330bf1e 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/vi.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/vi.json @@ -40,12 +40,32 @@ "OptionIAcceptTermsOfService": "I accept the terms of service", "ButtonPrivacyPolicy": "Privacy policy", "ButtonTermsOfService": "Terms of Service", + "HeaderDeveloperOptions": "Developer Options", + "OptionEnableWebClientResponseCache": "Enable web client response caching", + "OptionDisableForDevelopmentHelp": "Configure these as needed for web client development purposes.", + "OptionEnableWebClientResourceMinification": "Enable web client resource minification", + "LabelDashboardSourcePath": "Web client source path:", + "LabelDashboardSourcePathHelp": "If running the server from source, specify the path to the dashboard-ui folder. All web client files will be served from this location.", + "ButtonConvertMedia": "Convert media", + "ButtonOrganize": "Organize", "ButtonOk": "Ok", "ButtonCancel": "Tho\u00e1t", "ButtonNew": "M\u1edbi", "HeaderTV": "TV", "HeaderAudio": "Audio", "HeaderVideo": "Video", + "HeaderPaths": "Paths", + "CategorySync": "Sync", + "HeaderEasyPinCode": "Easy Pin Code", + "RegisterWithPayPal": "Register with PayPal", + "HeaderSyncRequiresSupporterMembership": "Sync Requires a Supporter Membership", + "HeaderEnjoyDayTrial": "Enjoy a 14 Day Free Trial", + "LabelSyncTempPath": "Temporary file path:", + "LabelSyncTempPathHelp": "Specify a custom sync working folder. Converted media created during the sync process will be stored here.", + "LabelCustomCertificatePath": "Custom certificate path:", + "LabelCustomCertificatePathHelp": "Supply your own ssl certificate. If omitted, the server will create a self-signed certificate.", + "TitleNotifications": "Notifications", + "ButtonDonateWithPayPal": "Donate with PayPal", "OptionDetectArchiveFilesAsMedia": "Detect archive files as media", "OptionDetectArchiveFilesAsMediaHelp": "If enabled, files with .rar and .zip extensions will be detected as media files.", "LabelEnterConnectUserName": "User name or email:", @@ -63,12 +83,14 @@ "FolderTypeTvShows": "TV", "FolderTypeInherit": "Inherit", "LabelContentType": "Content type:", + "TitleScheduledTasks": "Scheduled Tasks", "HeaderSetupLibrary": "C\u00e0i \u0111\u1eb7t th\u01b0 vi\u1ec7n media c\u1ee7a b\u1ea1n", "ButtonAddMediaFolder": "Th\u00eam m\u1ed9t th\u01b0 m\u1ee5c media", "LabelFolderType": "Lo\u1ea1i th\u01b0 m\u1ee5c", "ReferToMediaLibraryWiki": "Tham kh\u1ea3o th\u01b0 vi\u1ec7n wiki media.", "LabelCountry": "Qu\u1ed1c gia:", "LabelLanguage": "Ng\u00f4n ng\u1eef", + "ButtonJoinTheDevelopmentTeam": "Join the Development Team", "HeaderPreferredMetadataLanguage": "Ng\u00f4n ng\u1eef metadata \u01b0a th\u00edch", "LabelSaveLocalMetadata": "L\u01b0u c\u00e1c \u1ea3nh ngh\u1ec7 thu\u1eadt v\u00e0 metadata v\u00e0o trong c\u00e1c th\u01b0 m\u1ee5c media", "LabelSaveLocalMetadataHelp": "L\u01b0u c\u00e1c \u1ea3nh ngh\u1ec7 thu\u1eadt v\u00e0 metadata v\u00e0o trong c\u00e1c th\u01b0 m\u1ee5c media, s\u1ebd \u0111\u01b0a ch\u00fang v\u00e0o m\u1ed9t n\u01a1i b\u1ea1n c\u00f3 th\u1ec3 ch\u1ec9nh s\u1eeda d\u1ec5 d\u00e0ng h\u01a1n.", @@ -86,6 +108,8 @@ "TabCollectionTitles": "Ti\u00eau \u0111\u1ec1", "HeaderDeviceAccess": "Device Access", "OptionEnableAccessFromAllDevices": "Enable access from all devices", + "OptionEnableAccessToAllChannels": "Enable access to all channels", + "OptionEnableAccessToAllLibraries": "Enable access to all libraries", "DeviceAccessHelp": "This only applies to devices that can be uniquely identified and will not prevent browser access. Filtering user device access will prevent them from using new devices until they've been approved here.", "LabelDisplayMissingEpisodesWithinSeasons": "Display missing episodes within seasons", "LabelUnairedMissingEpisodesWithinSeasons": "Display unaired episodes within seasons", @@ -299,7 +323,7 @@ "LabelCachePath": "Cache path:", "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.", "LabelImagesByNamePath": "Images by name path:", - "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, genre and studio images.", "LabelMetadataPath": "Metadata path:", "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.", "LabelTranscodingTempPath": "Transcoding temporary path:", @@ -314,12 +338,14 @@ "OptionEpisodes": "Episodes", "OptionOtherVideos": "Other Videos", "TitleMetadata": "Metadata", - "LabelAutomaticUpdatesFanart": "Enable automatic updates from FanArt.tv", + "LabelAutomaticUpdates": "Enable automatic updates", "LabelAutomaticUpdatesTmdb": "Enable automatic updates from TheMovieDB.org", "LabelAutomaticUpdatesTvdb": "Enable automatic updates from TheTVDB.com", "LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.", "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.", "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.", + "LabelFanartApiKey": "Personal api key:", + "LabelFanartApiKeyHelp": "Requests to fanart without a personal API key return results that were approved over 7 days ago. With a personal API key that drops to 48 hours and if you are also a fanart VIP member that will further drop to around 10 minutes.", "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", "LabelMetadataDownloadLanguage": "Preferred download language:", "ButtonAutoScroll": "Auto-scroll", @@ -487,6 +513,7 @@ "HeaderSystemPaths": "C\u00e1c \u0111\u01b0\u1eddng d\u1eabn h\u1ec7 th\u1ed1ng", "LinkCommunity": "Community", "LinkGithub": "Github", + "LinkApi": "Api", "LinkApiDocumentation": "Api Documentation", "LabelFriendlyServerName": "Friendly server name:", "LabelFriendlyServerNameHelp": "This name will be used to identify this server. If left blank, the computer name will be used.", @@ -494,20 +521,25 @@ "LabelPreferredDisplayLanguageHelp": "Translating Media Browser is an ongoing project and is not yet complete.", "LabelReadHowYouCanContribute": "Read about how you can contribute.", "HeaderNewCollection": "New Collection", - "HeaderAddToCollection": "Add to Collection", "ButtonSubmit": "Submit", - "NewCollectionNameExample": "Example: Star Wars Collection", - "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata", "ButtonCreate": "Create", - "LabelLocalHttpServerPortNumber": "Local port number:", + "LabelCustomCss": "Custom css:", + "LabelCustomCssHelp": "Apply your own custom css to the web interface.", + "LabelLocalHttpServerPortNumber": "Local http port number:", "LabelLocalHttpServerPortNumberHelp": "The tcp port number that Media Browser's http server should bind to.", - "LabelPublicPort": "Public port number:", - "LabelPublicPortHelp": "The public port number that should be mapped to the local port.", + "LabelPublicHttpPort": "Public http port number:", + "LabelPublicHttpPortHelp": "The public port number that should be mapped to the local http port.", + "LabelPublicHttpsPort": "Public https port number:", + "LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.", + "LabelEnableHttps": "Report https as external address", + "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.", + "LabelHttpsPort": "Local https port number:", + "LabelHttpsPortHelp": "The tcp port number that Media Browser's https server should bind to.", "LabelWebSocketPortNumber": "Web socket port number:", "LabelEnableAutomaticPortMap": "Enable automatic port mapping", "LabelEnableAutomaticPortMapHelp": "Attempt to automatically map the public port to the local port via UPnP. This may not work with some router models.", - "LabelExternalDDNS": "External DDNS:", - "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely.", + "LabelExternalDDNS": "External WAN Address:", + "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely. Leave empty for automatic detection.", "TabResume": "Resume", "TabWeather": "Weather", "TitleAppSettings": "App Settings", @@ -575,6 +607,7 @@ "ButtonRestart": "Restart", "ButtonShutdown": "Shutdown", "ButtonUpdateNow": "Update Now", + "TabHosting": "Hosting", "PleaseUpdateManually": "Please shutdown the server and update manually.", "NewServerVersionAvailable": "A new version of Media Browser Server is available!", "ServerUpToDate": "Media Browser Server is up to date", @@ -636,6 +669,7 @@ "NotificationOptionInstallationFailed": "Installation failure", "NotificationOptionNewLibraryContent": "New content added", "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", + "NotificationOptionCameraImageUploaded": "Camera image uploaded", "SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.", "NotificationOptionServerRestartRequired": "Server restart required", "LabelNotificationEnabled": "Enable this notification", @@ -853,6 +887,8 @@ "OptionDefaultSort": "Default", "OptionCommunityMostWatchedSort": "Most Watched", "TabNextUp": "Next Up", + "HeaderBecomeMediaBrowserSupporter": "Become a Media Browser Supporter", + "TextEnjoyBonusFeatures": "Enjoy Bonus Features", "MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.", "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.", "MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.", @@ -869,7 +905,6 @@ "LabelChannelDownloadAge": "Delete content after: (days)", "LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.", "ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.", - "LabelSelectCollection": "Select collection:", "ButtonOptions": "Options", "ViewTypeMovies": "Movies", "ViewTypeTvShows": "TV", @@ -917,7 +952,7 @@ "OptionLatestTvRecordings": "Latest recordings", "LabelProtocolInfo": "Protocol info:", "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.", - "TabKodiMetadata": "Kodi", + "TabNfo": "Nfo", "HeaderKodiMetadataHelp": "Media Browser includes native support for Kodi Nfo metadata and images. To enable or disable Kodi metadata, use the Advanced tab to configure options for your media types.", "LabelKodiMetadataUser": "Sync user watch data to nfo's for:", "LabelKodiMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Kodi.", @@ -931,6 +966,7 @@ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:", "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.", "LabelDisplayCollectionsView": "Display a collections view to show movie collections", + "LabelDisplayCollectionsViewHelp": "This will create a separate view to display collections that you've created or have access to. To create a collection, right-click or tap-hold any movie and select 'Add to Collection'. ", "LabelKodiMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs", "LabelKodiMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Kodi skin compatibility.", "TabServices": "Services", @@ -1084,11 +1120,14 @@ "LabelDisplayFoldersView": "Display a folders view to show plain media folders", "ViewTypeLiveTvRecordingGroups": "Recordings", "ViewTypeLiveTvChannels": "Channels", - "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password", - "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.", + "LabelEasyPinCode": "Easy pin code:", + "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Media Browser apps, and can also be used for easy in-network sign in.", + "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", + "LabelInNetworkSignInWithEasyPasswordHelp": "If enabled, you'll be able to use your easy pin code to sign in to Media Browser apps from inside your home network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", "HeaderPassword": "Password", "HeaderLocalAccess": "Local Access", "HeaderViewOrder": "View Order", + "ButtonResetEasyPassword": "Reset easy pin code", "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps", "LabelMetadataRefreshMode": "Metadata refresh mode:", "LabelImageRefreshMode": "Image refresh mode:", @@ -1279,7 +1318,7 @@ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.", "HeaderNewUsers": "New Users", "ButtonSignUp": "Sign up", - "ButtonForgotPassword": "Forgot password?", + "ButtonForgotPassword": "Forgot password", "OptionDisableUserPreferences": "Disable access to user preferences", "OptionDisableUserPreferencesHelp": "If enabled, only administrators will be able to configure user profile images, passwords, and language preferences.", "HeaderSelectServer": "Select Server", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/zh_CN.json b/MediaBrowser.Server.Implementations/Localization/Server/zh_CN.json index 953dfdfc4..56bd68f6e 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/zh_CN.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/zh_CN.json @@ -40,12 +40,32 @@ "OptionIAcceptTermsOfService": "I accept the terms of service", "ButtonPrivacyPolicy": "Privacy policy", "ButtonTermsOfService": "Terms of Service", + "HeaderDeveloperOptions": "Developer Options", + "OptionEnableWebClientResponseCache": "Enable web client response caching", + "OptionDisableForDevelopmentHelp": "Configure these as needed for web client development purposes.", + "OptionEnableWebClientResourceMinification": "Enable web client resource minification", + "LabelDashboardSourcePath": "Web client source path:", + "LabelDashboardSourcePathHelp": "If running the server from source, specify the path to the dashboard-ui folder. All web client files will be served from this location.", + "ButtonConvertMedia": "Convert media", + "ButtonOrganize": "Organize", "ButtonOk": "\u786e\u5b9a", "ButtonCancel": "\u53d6\u6d88", "ButtonNew": "\u65b0\u589e", "HeaderTV": "TV", "HeaderAudio": "\u97f3\u9891", "HeaderVideo": "\u89c6\u9891", + "HeaderPaths": "Paths", + "CategorySync": "Sync", + "HeaderEasyPinCode": "Easy Pin Code", + "RegisterWithPayPal": "Register with PayPal", + "HeaderSyncRequiresSupporterMembership": "Sync Requires a Supporter Membership", + "HeaderEnjoyDayTrial": "Enjoy a 14 Day Free Trial", + "LabelSyncTempPath": "Temporary file path:", + "LabelSyncTempPathHelp": "Specify a custom sync working folder. Converted media created during the sync process will be stored here.", + "LabelCustomCertificatePath": "Custom certificate path:", + "LabelCustomCertificatePathHelp": "Supply your own ssl certificate. If omitted, the server will create a self-signed certificate.", + "TitleNotifications": "Notifications", + "ButtonDonateWithPayPal": "Donate with PayPal", "OptionDetectArchiveFilesAsMedia": "Detect archive files as media", "OptionDetectArchiveFilesAsMediaHelp": "If enabled, files with .rar and .zip extensions will be detected as media files.", "LabelEnterConnectUserName": "User name or email:", @@ -63,12 +83,14 @@ "FolderTypeTvShows": "TV", "FolderTypeInherit": "Inherit", "LabelContentType": "Content type:", + "TitleScheduledTasks": "Scheduled Tasks", "HeaderSetupLibrary": "\u8bbe\u7f6e\u4f60\u7684\u5a92\u4f53\u5e93", "ButtonAddMediaFolder": "\u6dfb\u52a0\u5a92\u4f53\u6587\u4ef6\u5939", "LabelFolderType": "\u6587\u4ef6\u5939\u7c7b\u578b\uff1a", "ReferToMediaLibraryWiki": "\u8bf7\u53c2\u9605\u5a92\u4f53\u5e93\u7ef4\u57fa\u3002", "LabelCountry": "\u56fd\u5bb6\uff1a", "LabelLanguage": "\u8bed\u8a00\uff1a", + "ButtonJoinTheDevelopmentTeam": "Join the Development Team", "HeaderPreferredMetadataLanguage": "\u9996\u9009\u5a92\u4f53\u8d44\u6599\u8bed\u8a00\uff1a", "LabelSaveLocalMetadata": "\u4fdd\u5b58\u5a92\u4f53\u56fe\u50cf\u53ca\u8d44\u6599\u5230\u5a92\u4f53\u6240\u5728\u6587\u4ef6\u5939", "LabelSaveLocalMetadataHelp": "\u76f4\u63a5\u4fdd\u5b58\u5a92\u4f53\u56fe\u50cf\u53ca\u8d44\u6599\u5230\u5a92\u4f53\u6240\u5728\u6587\u4ef6\u5939\u4ee5\u65b9\u4fbf\u7f16\u8f91\u3002", @@ -86,6 +108,8 @@ "TabCollectionTitles": "\u6807\u9898", "HeaderDeviceAccess": "Device Access", "OptionEnableAccessFromAllDevices": "Enable access from all devices", + "OptionEnableAccessToAllChannels": "Enable access to all channels", + "OptionEnableAccessToAllLibraries": "Enable access to all libraries", "DeviceAccessHelp": "This only applies to devices that can be uniquely identified and will not prevent browser access. Filtering user device access will prevent them from using new devices until they've been approved here.", "LabelDisplayMissingEpisodesWithinSeasons": "\u663e\u793a\u6bcf\u5b63\u91cc\u7f3a\u5c11\u7684\u5267\u96c6", "LabelUnairedMissingEpisodesWithinSeasons": "\u663e\u793a\u6bcf\u5b63\u91cc\u672a\u53d1\u5e03\u7684\u5267\u96c6", @@ -275,7 +299,7 @@ "OptionMetascore": "\u8bc4\u5206", "ButtonSelect": "\u9009\u62e9", "ButtonGroupVersions": "\u7248\u672c\u53f7", - "ButtonAddToCollection": "\u52a0\u5165\u5408\u96c6", + "ButtonAddToCollection": "Add to Collection", "PismoMessage": "\u901a\u8fc7\u6350\u8d60\u83b7\u53d6Pismo File Mount\u7684\u4f7f\u7528\u6388\u6743\u3002", "TangibleSoftwareMessage": "\u901a\u8fc7\u6350\u8d60\u7684\u8bb8\u53ef\u8bc1\u4f7f\u7528Java \/ C\uff03\u8f6c\u6362\u5668\u5207\u5b9e\u53ef\u884c\u7684\u89e3\u51b3\u65b9\u6848\u3002", "HeaderCredits": "\u5236\u4f5c\u4eba\u5458\u540d\u5355", @@ -299,7 +323,7 @@ "LabelCachePath": "\u7f13\u5b58\u8def\u5f84\uff1a", "LabelCachePathHelp": "\u81ea\u5b9a\u4e49\u670d\u52a1\u5668\u7f13\u5b58\u6587\u4ef6\u4f4d\u7f6e\uff0c\u4f8b\u5982\u56fe\u7247\u4f4d\u7f6e\u3002", "LabelImagesByNamePath": "\u6309\u540d\u79f0\u5f52\u7c7b\u7684\u56fe\u7247\u8def\u5f84\uff1a", - "LabelImagesByNamePathHelp": "\u81ea\u5b9a\u4e49\u4e0b\u8f7d\u7684\u6f14\u5458\u3001\u827a\u672f\u5bb6\u3001\u98ce\u683c\u548c\u5de5\u4f5c\u5ba4\u56fe\u7247\u4f4d\u7f6e\u3002", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, genre and studio images.", "LabelMetadataPath": "\u5a92\u4f53\u8d44\u6599\u8def\u5f84\uff1a", "LabelMetadataPathHelp": "\u5982\u679c\u4e0d\u4fdd\u5b58\u5a92\u4f53\u6587\u4ef6\u5939\u5185\uff0c\u8bf7\u81ea\u5b9a\u4e49\u4e0b\u8f7d\u7684\u5a92\u4f53\u8d44\u6599\u548c\u56fe\u50cf\u4f4d\u7f6e\u3002", "LabelTranscodingTempPath": "\u4e34\u65f6\u89e3\u7801\u8def\u5f84\uff1a", @@ -314,12 +338,14 @@ "OptionEpisodes": "\u5267\u96c6", "OptionOtherVideos": "\u5176\u4ed6\u89c6\u9891", "TitleMetadata": "\u5a92\u4f53\u8d44\u6599", - "LabelAutomaticUpdatesFanart": "\u542f\u7528\u4eceFanArt.tv\u81ea\u52a8\u66f4\u65b0", + "LabelAutomaticUpdates": "Enable automatic updates", "LabelAutomaticUpdatesTmdb": "\u542f\u7528\u4eceTheMovieDB.org\u81ea\u52a8\u66f4\u65b0", "LabelAutomaticUpdatesTvdb": "\u542f\u7528\u4eceTheTVDB.com\u81ea\u52a8\u66f4\u65b0", "LabelAutomaticUpdatesFanartHelp": "\u5982\u679c\u542f\u7528\uff0c\u4e00\u65e6\u6709\u65b0\u7684\u56fe\u50cf\u6dfb\u52a0\u5230fanart.tv\uff0c\u5b83\u4eec\u5c06\u88ab\u81ea\u52a8\u4e0b\u8f7d\u3002\u73b0\u6709\u7684\u56fe\u50cf\u4e0d\u4f1a\u88ab\u53d6\u4ee3\u3002", "LabelAutomaticUpdatesTmdbHelp": "\u5982\u679c\u542f\u7528\uff0c\u4e00\u65e6\u6709\u65b0\u7684\u56fe\u50cf\u6dfb\u52a0\u5230TheMovieDB.org\u4e0a\uff0c\u5b83\u4eec\u5c06\u88ab\u81ea\u52a8\u4e0b\u8f7d\u3002\u73b0\u6709\u7684\u56fe\u50cf\u4e0d\u4f1a\u88ab\u53d6\u4ee3\u3002", "LabelAutomaticUpdatesTvdbHelp": "\u5982\u679c\u542f\u7528\uff0c\u4e00\u65e6\u6709\u65b0\u7684\u56fe\u50cf\u6dfb\u52a0\u5230TheTVDB.com\u4e0a\uff0c\u5b83\u4eec\u5c06\u88ab\u81ea\u52a8\u4e0b\u8f7d\u3002\u73b0\u6709\u7684\u56fe\u50cf\u4e0d\u4f1a\u88ab\u53d6\u4ee3\u3002", + "LabelFanartApiKey": "Personal api key:", + "LabelFanartApiKeyHelp": "Requests to fanart without a personal API key return results that were approved over 7 days ago. With a personal API key that drops to 48 hours and if you are also a fanart VIP member that will further drop to around 10 minutes.", "ExtractChapterImagesHelp": "\u4ece\u7ae0\u8282\u4e2d\u63d0\u53d6\u7684\u56fe\u7247\u5c06\u5141\u8bb8\u5ba2\u6237\u7aef\u663e\u793a\u56fe\u5f62\u9009\u62e9\u83dc\u5355\u3002\u8fd9\u4e2a\u8fc7\u7a0b\u53ef\u80fd\u4f1a\u5f88\u6162\uff0c \u66f4\u591a\u7684\u5360\u7528CPU\u8d44\u6e90\uff0c\u5e76\u4e14\u4f1a\u9700\u8981\u51e0\u4e2aGB\u7684\u786c\u76d8\u7a7a\u95f4\u3002\u5b83\u88ab\u9ed8\u8ba4\u8bbe\u7f6e\u4e8e\u6bcf\u665a\u51cc\u66684\u70b9\u8fd0\u884c\uff0c\u867d\u7136\u8fd9\u53ef\u4ee5\u5728\u8ba1\u5212\u4efb\u52a1\u4e2d\u914d\u7f6e\uff0c\u4f46\u6211\u4eec\u4e0d\u5efa\u8bae\u5728\u9ad8\u5cf0\u4f7f\u7528\u65f6\u95f4\u8fd0\u884c\u8be5\u4efb\u52a1\u3002", "LabelMetadataDownloadLanguage": "\u9996\u9009\u4e0b\u8f7d\u8bed\u8a00\uff1a", "ButtonAutoScroll": "\u81ea\u52a8\u6eda\u52a8", @@ -487,6 +513,7 @@ "HeaderSystemPaths": "\u7cfb\u7edf\u8def\u5f84", "LinkCommunity": "\u793e\u533a", "LinkGithub": "Github", + "LinkApi": "Api", "LinkApiDocumentation": "Api \u6587\u6863", "LabelFriendlyServerName": "\u597d\u8bb0\u7684\u670d\u52a1\u5668\u540d\u79f0\uff1a", "LabelFriendlyServerNameHelp": "\u6b64\u540d\u79f0\u5c06\u7528\u505a\u670d\u52a1\u5668\u540d\uff0c\u5982\u679c\u7559\u7a7a\uff0c\u5c06\u4f7f\u7528\u8ba1\u7b97\u673a\u540d\u3002", @@ -494,20 +521,25 @@ "LabelPreferredDisplayLanguageHelp": "\u7ffb\u8bd1Media Browser\u662f\u4e00\u4e2a\u6b63\u5728\u8fdb\u884c\u7684\u9879\u76ee\uff0c\u5c1a\u672a\u5168\u90e8\u5b8c\u6210\u3002", "LabelReadHowYouCanContribute": "\u9605\u8bfb\u5173\u4e8e\u5982\u4f55\u4e3aMedia Browser\u8d21\u732e\u529b\u91cf\u3002", "HeaderNewCollection": "\u65b0\u5408\u96c6", - "HeaderAddToCollection": "\u52a0\u5165\u5408\u96c6", "ButtonSubmit": "\u63d0\u4ea4", - "NewCollectionNameExample": "\u4f8b\u5982\uff1a\u661f\u7403\u5927\u6218\u5408\u96c6", - "OptionSearchForInternetMetadata": "\u5728\u4e92\u8054\u7f51\u4e0a\u641c\u7d22\u5a92\u4f53\u56fe\u50cf\u548c\u8d44\u6599", "ButtonCreate": "\u521b\u5efa", - "LabelLocalHttpServerPortNumber": "Local port number:", + "LabelCustomCss": "Custom css:", + "LabelCustomCssHelp": "Apply your own custom css to the web interface.", + "LabelLocalHttpServerPortNumber": "Local http port number:", "LabelLocalHttpServerPortNumberHelp": "The tcp port number that Media Browser's http server should bind to.", - "LabelPublicPort": "Public port number:", - "LabelPublicPortHelp": "The public port number that should be mapped to the local port.", + "LabelPublicHttpPort": "Public http port number:", + "LabelPublicHttpPortHelp": "The public port number that should be mapped to the local http port.", + "LabelPublicHttpsPort": "Public https port number:", + "LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.", + "LabelEnableHttps": "Report https as external address", + "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.", + "LabelHttpsPort": "Local https port number:", + "LabelHttpsPortHelp": "The tcp port number that Media Browser's https server should bind to.", "LabelWebSocketPortNumber": "Web Socket\u7aef\u53e3\u53f7\uff1a", "LabelEnableAutomaticPortMap": "Enable automatic port mapping", "LabelEnableAutomaticPortMapHelp": "Attempt to automatically map the public port to the local port via UPnP. This may not work with some router models.", - "LabelExternalDDNS": "\u5916\u90e8DDNS\uff1a", - "LabelExternalDDNSHelp": "\u5982\u679c\u4f60\u5728\u8fd9\u91cc\u8f93\u5165\u52a8\u6001\u7684DNS\u3002Media Browser\u7684\u5ba2\u6237\u7aef\u7a0b\u5e8f\u5c06\u53ef\u4ee5\u4f7f\u7528\u5b83\u8fdb\u884c\u8fdc\u7a0b\u8fde\u63a5\u3002", + "LabelExternalDDNS": "External WAN Address:", + "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely. Leave empty for automatic detection.", "TabResume": "\u6062\u590d\u64ad\u653e", "TabWeather": "\u5929\u6c14", "TitleAppSettings": "\u5ba2\u6237\u7aef\u7a0b\u5e8f\u8bbe\u7f6e", @@ -575,6 +607,7 @@ "ButtonRestart": "\u91cd\u542f", "ButtonShutdown": "\u5173\u673a", "ButtonUpdateNow": "\u73b0\u5728\u66f4\u65b0", + "TabHosting": "Hosting", "PleaseUpdateManually": "\u8bf7\u5173\u95ed\u670d\u52a1\u5668\u5e76\u624b\u52a8\u66f4\u65b0\u3002", "NewServerVersionAvailable": "Media Browser\u670d\u52a1\u5668\u6709\u65b0\u7248\u672c\u53ef\u7528\uff01", "ServerUpToDate": "Media Browser\u670d\u52a1\u5668\u662f\u6700\u65b0\u7684", @@ -636,6 +669,7 @@ "NotificationOptionInstallationFailed": "\u5b89\u88c5\u5931\u8d25", "NotificationOptionNewLibraryContent": "\u6dfb\u52a0\u65b0\u5185\u5bb9", "NotificationOptionNewLibraryContentMultiple": "\u65b0\u7684\u5185\u5bb9\u52a0\u5165\uff08\u591a\u4e2a\uff09", + "NotificationOptionCameraImageUploaded": "Camera image uploaded", "SendNotificationHelp": "\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u901a\u77e5\u88ab\u53d1\u9001\u5230\u63a7\u5236\u53f0\u7684\u6536\u4ef6\u7bb1\u3002\u6d4f\u89c8\u63d2\u4ef6\u76ee\u5f55\u53ef\u4ee5\u5b89\u88c5\u989d\u5916\u7684\u901a\u77e5\u9009\u9879\u3002", "NotificationOptionServerRestartRequired": "\u9700\u8981\u91cd\u65b0\u542f\u52a8\u670d\u52a1\u5668", "LabelNotificationEnabled": "\u542f\u7528\u6b64\u901a\u77e5", @@ -853,6 +887,8 @@ "OptionDefaultSort": "\u9ed8\u8ba4", "OptionCommunityMostWatchedSort": "\u6700\u53d7\u77a9\u76ee", "TabNextUp": "\u4e0b\u4e00\u4e2a", + "HeaderBecomeMediaBrowserSupporter": "Become a Media Browser Supporter", + "TextEnjoyBonusFeatures": "Enjoy Bonus Features", "MessageNoMovieSuggestionsAvailable": "\u6ca1\u6709\u53ef\u7528\u7684\u7535\u5f71\u5efa\u8bae\u3002\u5f00\u59cb\u89c2\u770b\u4f60\u7684\u7535\u5f71\u5e76\u8fdb\u884c\u8bc4\u5206\uff0c\u518d\u56de\u8fc7\u5934\u6765\u67e5\u770b\u4f60\u7684\u5efa\u8bae\u3002", "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.", "MessageNoPlaylistsAvailable": "\u64ad\u653e\u5217\u8868\u5141\u8bb8\u60a8\u521b\u5efa\u4e00\u4e2a\u5185\u5bb9\u5217\u8868\u6765\u8fde\u7eed\u64ad\u653e\u3002\u5c06\u9879\u76ee\u6dfb\u52a0\u5230\u64ad\u653e\u5217\u8868\uff0c\u53f3\u952e\u5355\u51fb\u6216\u70b9\u51fb\u5e76\u6309\u4f4f\uff0c\u7136\u540e\u9009\u62e9\u201c\u6dfb\u52a0\u5230\u64ad\u653e\u5217\u8868\u201d\u3002", @@ -869,7 +905,6 @@ "LabelChannelDownloadAge": "\u8fc7\u591a\u4e45\u5220\u9664\u5185\u5bb9: (\u5929\u6570)", "LabelChannelDownloadAgeHelp": "\u4e0b\u8f7d\u7684\u5185\u5bb9\u8d85\u8fc7\u6b64\u671f\u9650\u5c06\u88ab\u5220\u9664\u3002\u5b83\u4ecd\u53ef\u901a\u8fc7\u4e92\u8054\u7f51\u6d41\u5a92\u4f53\u64ad\u653e\u3002", "ChannelSettingsFormHelp": "\u5728\u63d2\u4ef6\u76ee\u5f55\u91cc\u5b89\u88c5\u9891\u9053\uff0c\u4f8b\u5982\uff1aTrailers \u548c Vimeo", - "LabelSelectCollection": "\u9009\u62e9\u5408\u96c6\uff1a", "ButtonOptions": "Options", "ViewTypeMovies": "\u7535\u5f71", "ViewTypeTvShows": "\u7535\u89c6", @@ -917,7 +952,7 @@ "OptionLatestTvRecordings": "\u6700\u65b0\u5f55\u5236\u7684\u8282\u76ee", "LabelProtocolInfo": "\u534f\u8bae\u4fe1\u606f\uff1a", "LabelProtocolInfoHelp": "\u5f53\u54cd\u5e94\u6765\u81ea\u8bbe\u5907\u7684 GetProtocolInfo\uff08\u83b7\u53d6\u534f\u8bae\u4fe1\u606f\uff09\u8bf7\u6c42\u65f6\uff0c\u8be5\u503c\u5c06\u88ab\u4f7f\u7528\u3002", - "TabKodiMetadata": "Kodi", + "TabNfo": "Nfo", "HeaderKodiMetadataHelp": "Media Browser includes native support for Kodi Nfo metadata and images. To enable or disable Kodi metadata, use the Advanced tab to configure options for your media types.", "LabelKodiMetadataUser": "Sync user watch data to nfo's for:", "LabelKodiMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Kodi.", @@ -931,6 +966,7 @@ "LabelGroupChannelsIntoViews": "\u5728\u6211\u7684\u754c\u9762\u91cc\u76f4\u63a5\u663e\u793a\u4ee5\u4e0b\u9891\u9053\uff1a", "LabelGroupChannelsIntoViewsHelp": "\u5982\u679c\u542f\u7528\uff0c\u8fd9\u4e9b\u9891\u9053\u5c06\u548c\u5176\u4ed6\u7684\u754c\u9762\u89c6\u56fe\u5e76\u5217\u663e\u793a\u3002\u5982\u679c\u7981\u7528\uff0c\u5b83\u4eec\u5c06\u88ab\u663e\u793a\u5728\u4e00\u4e2a\u5355\u72ec\u7684\u754c\u9762\u89c6\u56fe\u91cc\u3002", "LabelDisplayCollectionsView": "\u663e\u793a\u5408\u96c6\u89c6\u56fe\u6765\u5448\u73b0\u7535\u5f71\u5408\u96c6", + "LabelDisplayCollectionsViewHelp": "This will create a separate view to display collections that you've created or have access to. To create a collection, right-click or tap-hold any movie and select 'Add to Collection'. ", "LabelKodiMetadataEnableExtraThumbs": "\u590d\u5236\u540c\u4eba\u753b\u5230extrathumbs\u6587\u4ef6\u5939", "LabelKodiMetadataEnableExtraThumbsHelp": "\u4e3a\u4e86\u6700\u5927\u5316\u517c\u5bb9Kodi\u76ae\u80a4\uff0c\u4e0b\u8f7d\u7684\u56fe\u7247\u540c\u65f6\u50a8\u5b58\u5728 extrafanart \u548c extrathumbs \u6587\u4ef6\u5939\u3002", "TabServices": "\u670d\u52a1", @@ -1084,11 +1120,14 @@ "LabelDisplayFoldersView": "\u663e\u793a\u4e00\u4e2a\u6587\u4ef6\u5939\u89c6\u56fe\u6765\u5448\u73b0\u5e73\u9762\u5a92\u4f53\u6587\u4ef6\u5939", "ViewTypeLiveTvRecordingGroups": "\u5f55\u5236", "ViewTypeLiveTvChannels": "\u9891\u9053", - "LabelAllowLocalAccessWithoutPassword": "\u5141\u8bb8\u672c\u5730\u8bbf\u95ee\u4e0d\u4f7f\u7528\u5bc6\u7801", - "LabelAllowLocalAccessWithoutPasswordHelp": "\u5f53\u542f\u7528\u65f6\uff0c\u4ece\u60a8\u7684\u5bb6\u5ead\u7f51\u7edc\u4e2d\u767b\u5f55\u65f6\u5c06\u4e0d\u9700\u8981\u5bc6\u7801\u3002", + "LabelEasyPinCode": "Easy pin code:", + "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Media Browser apps, and can also be used for easy in-network sign in.", + "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", + "LabelInNetworkSignInWithEasyPasswordHelp": "If enabled, you'll be able to use your easy pin code to sign in to Media Browser apps from inside your home network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", "HeaderPassword": "\u5bc6\u7801", "HeaderLocalAccess": "\u672c\u5730\u8bbf\u95ee", "HeaderViewOrder": "\u67e5\u770b\u987a\u5e8f", + "ButtonResetEasyPassword": "Reset easy pin code", "LabelSelectUserViewOrder": "\u60a8\u6240\u9009\u62e9\u7684\u67e5\u770b\u987a\u5e8f\u5c06\u663e\u793a\u5728Media Browser \u7684\u5404\u79cdApp\u4e0a\u9762", "LabelMetadataRefreshMode": "\u5a92\u4f53\u8d44\u6599\u5237\u65b0\u6a21\u5f0f\uff1a", "LabelImageRefreshMode": "\u56fe\u7247\u5237\u65b0\u6a21\u5f0f\uff1a", @@ -1279,7 +1318,7 @@ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.", "HeaderNewUsers": "New Users", "ButtonSignUp": "Sign up", - "ButtonForgotPassword": "Forgot password?", + "ButtonForgotPassword": "Forgot password", "OptionDisableUserPreferences": "Disable access to user preferences", "OptionDisableUserPreferencesHelp": "If enabled, only administrators will be able to configure user profile images, passwords, and language preferences.", "HeaderSelectServer": "Select Server", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json b/MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json index c1a9ab4e3..2e6f40e43 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json @@ -40,12 +40,32 @@ "OptionIAcceptTermsOfService": "I accept the terms of service", "ButtonPrivacyPolicy": "Privacy policy", "ButtonTermsOfService": "Terms of Service", + "HeaderDeveloperOptions": "Developer Options", + "OptionEnableWebClientResponseCache": "Enable web client response caching", + "OptionDisableForDevelopmentHelp": "Configure these as needed for web client development purposes.", + "OptionEnableWebClientResourceMinification": "Enable web client resource minification", + "LabelDashboardSourcePath": "Web client source path:", + "LabelDashboardSourcePathHelp": "If running the server from source, specify the path to the dashboard-ui folder. All web client files will be served from this location.", + "ButtonConvertMedia": "Convert media", + "ButtonOrganize": "Organize", "ButtonOk": "OK", "ButtonCancel": "\u53d6\u6d88", "ButtonNew": "\u5275\u5efa", "HeaderTV": "TV", "HeaderAudio": "Audio", "HeaderVideo": "Video", + "HeaderPaths": "Paths", + "CategorySync": "Sync", + "HeaderEasyPinCode": "Easy Pin Code", + "RegisterWithPayPal": "Register with PayPal", + "HeaderSyncRequiresSupporterMembership": "Sync Requires a Supporter Membership", + "HeaderEnjoyDayTrial": "Enjoy a 14 Day Free Trial", + "LabelSyncTempPath": "Temporary file path:", + "LabelSyncTempPathHelp": "Specify a custom sync working folder. Converted media created during the sync process will be stored here.", + "LabelCustomCertificatePath": "Custom certificate path:", + "LabelCustomCertificatePathHelp": "Supply your own ssl certificate. If omitted, the server will create a self-signed certificate.", + "TitleNotifications": "Notifications", + "ButtonDonateWithPayPal": "Donate with PayPal", "OptionDetectArchiveFilesAsMedia": "Detect archive files as media", "OptionDetectArchiveFilesAsMediaHelp": "If enabled, files with .rar and .zip extensions will be detected as media files.", "LabelEnterConnectUserName": "User name or email:", @@ -63,12 +83,14 @@ "FolderTypeTvShows": "TV", "FolderTypeInherit": "Inherit", "LabelContentType": "Content type:", + "TitleScheduledTasks": "Scheduled Tasks", "HeaderSetupLibrary": "\u8a2d\u7f6e\u4f60\u7684\u5a92\u9ad4\u5eab", "ButtonAddMediaFolder": "\u6dfb\u52a0\u5a92\u9ad4\u6587\u4ef6\u593e", "LabelFolderType": "\u5a92\u9ad4\u6587\u4ef6\u593e\u985e\u578b\uff1a", "ReferToMediaLibraryWiki": "\u53c3\u7167\u5a92\u9ad4\u5eab\u7ef4\u57fa", "LabelCountry": "\u570b\u5bb6\uff1a", "LabelLanguage": "\u8a9e\u8a00\uff1a", + "ButtonJoinTheDevelopmentTeam": "Join the Development Team", "HeaderPreferredMetadataLanguage": "\u9996\u9078\u5a92\u9ad4\u8cc7\u6599\u8a9e\u8a00\uff1a", "LabelSaveLocalMetadata": "\u4fdd\u5b58\u5a92\u9ad4\u5716\u50cf\u53ca\u8cc7\u6599\u5230\u5a92\u9ad4\u6a94\u6848\u6240\u5728\u7684\u6587\u4ef6\u593e", "LabelSaveLocalMetadataHelp": "\u76f4\u63a5\u4fdd\u5b58\u5a92\u9ad4\u5716\u50cf\u53ca\u8cc7\u6599\u5230\u5a92\u9ad4\u6240\u5728\u7684\u6587\u4ef6\u593e\u80fd\u4f7f\u7de8\u8f2f\u5de5\u4f5c\u66f4\u5bb9\u6613\u3002", @@ -86,6 +108,8 @@ "TabCollectionTitles": "\u6a19\u984c", "HeaderDeviceAccess": "Device Access", "OptionEnableAccessFromAllDevices": "Enable access from all devices", + "OptionEnableAccessToAllChannels": "Enable access to all channels", + "OptionEnableAccessToAllLibraries": "Enable access to all libraries", "DeviceAccessHelp": "This only applies to devices that can be uniquely identified and will not prevent browser access. Filtering user device access will prevent them from using new devices until they've been approved here.", "LabelDisplayMissingEpisodesWithinSeasons": "\u986f\u793a\u7bc0\u76ee\u5b63\u5ea6\u5167\u7f3a\u5c11\u7684\u55ae\u5143", "LabelUnairedMissingEpisodesWithinSeasons": "\u5728\u7bc0\u76ee\u5b63\u5ea6\u5167\u986f\u793a\u9084\u672a\u767c\u4f48\u7684\u55ae\u5143", @@ -299,7 +323,7 @@ "LabelCachePath": "\u7de9\u5b58\u8def\u5f91\uff1a", "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.", "LabelImagesByNamePath": "\u540d\u7a31\u5716\u50cf\u6587\u4ef6\u593e\u8def\u5f91\uff1a", - "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, genre and studio images.", "LabelMetadataPath": "\u5a92\u9ad4\u8cc7\u6599\u6587\u4ef6\u593e\u8def\u5f91\uff1a", "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.", "LabelTranscodingTempPath": "\u8f49\u78bc\u81e8\u6642\u8def\u5f91\uff1a", @@ -314,12 +338,14 @@ "OptionEpisodes": "Episodes", "OptionOtherVideos": "\u5176\u4ed6\u8996\u983b", "TitleMetadata": "Metadata", - "LabelAutomaticUpdatesFanart": "\u5f9eFanArt.tv\u81ea\u52d5\u66f4\u65b0", + "LabelAutomaticUpdates": "Enable automatic updates", "LabelAutomaticUpdatesTmdb": "\u5f9eTheMovieDB.org\u81ea\u52d5\u66f4\u65b0", "LabelAutomaticUpdatesTvdb": "\u5f9eTheTVDB.com\u81ea\u52d5\u66f4\u65b0", "LabelAutomaticUpdatesFanartHelp": "\u5982\u679c\u555f\u7528\uff0c\u82e5\u6709\u65b0\u7684\u5716\u50cf\u6dfb\u52a0\u5230fanart.tv\uff0c\u5b83\u5011\u5c07\u6703\u88ab\u81ea\u52d5\u4e0b\u8f09\u3002\u73fe\u6709\u7684\u5f71\u50cf\u4e0d\u6703\u88ab\u53d6\u4ee3\u3002", "LabelAutomaticUpdatesTmdbHelp": "\u5982\u679c\u555f\u7528\uff0c\u82e5\u6709\u65b0\u7684\u5716\u50cf\u6dfb\u52a0\u5230TheMovieDB.org\uff0c\u5b83\u5011\u5c07\u6703\u88ab\u81ea\u52d5\u4e0b\u8f09\u3002\u73fe\u6709\u7684\u5f71\u50cf\u4e0d\u6703\u88ab\u53d6\u4ee3\u3002", "LabelAutomaticUpdatesTvdbHelp": "\u5982\u679c\u555f\u7528\uff0c\u82e5\u6709\u65b0\u7684\u5716\u50cf\u6dfb\u52a0\u5230TheTVDB.com\uff0c\u5b83\u5011\u5c07\u6703\u88ab\u81ea\u52d5\u4e0b\u8f09\u3002\u73fe\u6709\u7684\u5f71\u50cf\u4e0d\u6703\u88ab\u53d6\u4ee3\u3002", + "LabelFanartApiKey": "Personal api key:", + "LabelFanartApiKeyHelp": "Requests to fanart without a personal API key return results that were approved over 7 days ago. With a personal API key that drops to 48 hours and if you are also a fanart VIP member that will further drop to around 10 minutes.", "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", "LabelMetadataDownloadLanguage": "Preferred download language:", "ButtonAutoScroll": "\u81ea\u52d5\u6efe\u52d5", @@ -487,6 +513,7 @@ "HeaderSystemPaths": "\u7cfb\u7d71\u8def\u5f91", "LinkCommunity": "\u793e\u5340", "LinkGithub": "Github", + "LinkApi": "Api", "LinkApiDocumentation": "API\u6587\u6a94", "LabelFriendlyServerName": "\u53cb\u597d\u4f3a\u670d\u5668\u540d\u7a31\uff1a", "LabelFriendlyServerNameHelp": "\u6b64\u540d\u7a31\u5c07\u7528\u65bc\u6a19\u8b58\u4f3a\u670d\u5668\u3002\u5982\u679c\u7559\u7a7a\uff0c\u8a08\u7b97\u6a5f\u540d\u7a31\u5c07\u88ab\u4f7f\u7528\u3002", @@ -494,20 +521,25 @@ "LabelPreferredDisplayLanguageHelp": "\u7ffb\u8b6fMedia Browser\u662f\u4e00\u500b\u6b63\u5728\u9032\u884c\u7684\u9805\u76ee\uff0c\u5c1a\u672a\u5b8c\u6210\u3002", "LabelReadHowYouCanContribute": "\u95b1\u8b80\u95dc\u65bc\u5982\u4f55\u70baMedia Browser\u8ca2\u737b\u3002", "HeaderNewCollection": "\u65b0\u5408\u96c6", - "HeaderAddToCollection": "Add to Collection", "ButtonSubmit": "Submit", - "NewCollectionNameExample": "\u4f8b\u5b50\uff1a\u661f\u7403\u5927\u6230\u5408\u96c6", - "OptionSearchForInternetMetadata": "\u5728\u4e92\u806f\u7db2\u4e0a\u641c\u7d22\u5a92\u9ad4\u5716\u50cf\u548c\u8cc7\u6599", "ButtonCreate": "\u5275\u5efa", - "LabelLocalHttpServerPortNumber": "Local port number:", + "LabelCustomCss": "Custom css:", + "LabelCustomCssHelp": "Apply your own custom css to the web interface.", + "LabelLocalHttpServerPortNumber": "Local http port number:", "LabelLocalHttpServerPortNumberHelp": "The tcp port number that Media Browser's http server should bind to.", - "LabelPublicPort": "Public port number:", - "LabelPublicPortHelp": "The public port number that should be mapped to the local port.", + "LabelPublicHttpPort": "Public http port number:", + "LabelPublicHttpPortHelp": "The public port number that should be mapped to the local http port.", + "LabelPublicHttpsPort": "Public https port number:", + "LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.", + "LabelEnableHttps": "Report https as external address", + "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.", + "LabelHttpsPort": "Local https port number:", + "LabelHttpsPortHelp": "The tcp port number that Media Browser's https server should bind to.", "LabelWebSocketPortNumber": "\u7db2\u7d61\u5957\u63a5\u7aef\u53e3\uff1a", "LabelEnableAutomaticPortMap": "Enable automatic port mapping", "LabelEnableAutomaticPortMapHelp": "Attempt to automatically map the public port to the local port via UPnP. This may not work with some router models.", - "LabelExternalDDNS": "\u5916\u90e8DDNS\uff1a", - "LabelExternalDDNSHelp": "\u5982\u679c\u4f60\u9019\u88e1\u8f38\u5165\u4e00\u500b\u52d5\u614bDNS\uff0cMedia Browser\u7684\u5ba2\u6236\u7aef\u80fd\u5920\u5f9e\u9019\u88e1\u4f5c\u9060\u7a0b\u9023\u63a5\u3002", + "LabelExternalDDNS": "External WAN Address:", + "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely. Leave empty for automatic detection.", "TabResume": "\u6062\u5fa9\u64ad\u653e", "TabWeather": "\u5929\u6c23", "TitleAppSettings": "\u5ba2\u6236\u7aef\u8a2d\u7f6e", @@ -575,6 +607,7 @@ "ButtonRestart": "Restart", "ButtonShutdown": "Shutdown", "ButtonUpdateNow": "Update Now", + "TabHosting": "Hosting", "PleaseUpdateManually": "Please shutdown the server and update manually.", "NewServerVersionAvailable": "A new version of Media Browser Server is available!", "ServerUpToDate": "Media Browser Server is up to date", @@ -636,6 +669,7 @@ "NotificationOptionInstallationFailed": "Installation failure", "NotificationOptionNewLibraryContent": "New content added", "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", + "NotificationOptionCameraImageUploaded": "Camera image uploaded", "SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.", "NotificationOptionServerRestartRequired": "Server restart required", "LabelNotificationEnabled": "Enable this notification", @@ -853,6 +887,8 @@ "OptionDefaultSort": "Default", "OptionCommunityMostWatchedSort": "Most Watched", "TabNextUp": "Next Up", + "HeaderBecomeMediaBrowserSupporter": "Become a Media Browser Supporter", + "TextEnjoyBonusFeatures": "Enjoy Bonus Features", "MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.", "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.", "MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.", @@ -869,7 +905,6 @@ "LabelChannelDownloadAge": "Delete content after: (days)", "LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.", "ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.", - "LabelSelectCollection": "Select collection:", "ButtonOptions": "Options", "ViewTypeMovies": "Movies", "ViewTypeTvShows": "TV", @@ -917,7 +952,7 @@ "OptionLatestTvRecordings": "Latest recordings", "LabelProtocolInfo": "Protocol info:", "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.", - "TabKodiMetadata": "Kodi", + "TabNfo": "Nfo", "HeaderKodiMetadataHelp": "Media Browser includes native support for Kodi Nfo metadata and images. To enable or disable Kodi metadata, use the Advanced tab to configure options for your media types.", "LabelKodiMetadataUser": "Sync user watch data to nfo's for:", "LabelKodiMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Kodi.", @@ -931,6 +966,7 @@ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:", "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.", "LabelDisplayCollectionsView": "Display a collections view to show movie collections", + "LabelDisplayCollectionsViewHelp": "This will create a separate view to display collections that you've created or have access to. To create a collection, right-click or tap-hold any movie and select 'Add to Collection'. ", "LabelKodiMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs", "LabelKodiMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Kodi skin compatibility.", "TabServices": "Services", @@ -1084,11 +1120,14 @@ "LabelDisplayFoldersView": "Display a folders view to show plain media folders", "ViewTypeLiveTvRecordingGroups": "Recordings", "ViewTypeLiveTvChannels": "Channels", - "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password", - "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.", + "LabelEasyPinCode": "Easy pin code:", + "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Media Browser apps, and can also be used for easy in-network sign in.", + "LabelInNetworkSignInWithEasyPassword": "Enable in-network sign in with my easy pin code", + "LabelInNetworkSignInWithEasyPasswordHelp": "If enabled, you'll be able to use your easy pin code to sign in to Media Browser apps from inside your home network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.", "HeaderPassword": "Password", "HeaderLocalAccess": "Local Access", "HeaderViewOrder": "View Order", + "ButtonResetEasyPassword": "Reset easy pin code", "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps", "LabelMetadataRefreshMode": "Metadata refresh mode:", "LabelImageRefreshMode": "Image refresh mode:", @@ -1279,7 +1318,7 @@ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.", "HeaderNewUsers": "New Users", "ButtonSignUp": "Sign up", - "ButtonForgotPassword": "Forgot password?", + "ButtonForgotPassword": "Forgot password", "OptionDisableUserPreferences": "Disable access to user preferences", "OptionDisableUserPreferencesHelp": "If enabled, only administrators will be able to configure user profile images, passwords, and language preferences.", "HeaderSelectServer": "Select Server", diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/SocketSharpLogger.cs b/MediaBrowser.Server.Implementations/Logging/PatternsLogger.cs index 427671b30..00b6cc5a8 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/SocketSharpLogger.cs +++ b/MediaBrowser.Server.Implementations/Logging/PatternsLogger.cs @@ -1,13 +1,18 @@ -using MediaBrowser.Model.Logging; +using Patterns.Logging; using System; -namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp +namespace MediaBrowser.Server.Implementations.Logging { - public class SocketSharpLogger : SocketHttpListener.Logging.ILogger + public class PatternsLogger : ILogger { - private readonly ILogger _logger; + private readonly Model.Logging.ILogger _logger; - public SocketSharpLogger(ILogger logger) + public PatternsLogger() + : this(new Model.Logging.NullLogger()) + { + } + + public PatternsLogger(Model.Logging.ILogger logger) { _logger = logger; } @@ -46,5 +51,13 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp { _logger.Warn(message, paramList); } + + public void Log(LogSeverity severity, string message, params object[] paramList) + { + } + + public void LogMultiline(string message, LogSeverity severity, System.Text.StringBuilder additionalContent) + { + } } } diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 433b76657..f63b37c09 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -49,8 +49,9 @@ <SpecificVersion>False</SpecificVersion> <HintPath>..\ThirdParty\libwebp\Imazen.WebP.dll</HintPath> </Reference> - <Reference Include="MediaBrowser.Naming"> - <HintPath>..\packages\MediaBrowser.Naming.1.0.0.29\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll</HintPath> + <Reference Include="MediaBrowser.Naming, Version=1.0.5509.27636, Culture=neutral, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\packages\MediaBrowser.Naming.1.0.0.32\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll</HintPath> </Reference> <Reference Include="Mono.Nat, Version=1.2.21.0, Culture=neutral, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> @@ -60,11 +61,16 @@ <SpecificVersion>False</SpecificVersion> <HintPath>..\packages\morelinq.1.1.0\lib\net35\MoreLinq.dll</HintPath> </Reference> + <Reference Include="Patterns.Logging"> + <HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath> + <Private>True</Private> + </Reference> <Reference Include="ServiceStack.Api.Swagger"> <HintPath>..\ThirdParty\ServiceStack\ServiceStack.Api.Swagger.dll</HintPath> </Reference> - <Reference Include="SocketHttpListener"> - <HintPath>..\ThirdParty\SocketHttpListener\SocketHttpListener.dll</HintPath> + <Reference Include="SocketHttpListener, Version=1.0.5501.2204, Culture=neutral, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\packages\SocketHttpListener.1.0.0.1\lib\net45\SocketHttpListener.dll</HintPath> </Reference> <Reference Include="System" /> <Reference Include="System.Core" /> @@ -111,6 +117,7 @@ <Compile Include="Collections\CollectionManager.cs" /> <Compile Include="Collections\CollectionsDynamicFolder.cs" /> <Compile Include="Collections\ManualCollectionsFolder.cs" /> + <Compile Include="Collections\CollectionImageProvider.cs" /> <Compile Include="Configuration\ServerConfigurationManager.cs" /> <Compile Include="Connect\ConnectData.cs" /> <Compile Include="Connect\ConnectManager.cs" /> @@ -164,7 +171,6 @@ <Compile Include="HttpServer\ServerLogger.cs" /> <Compile Include="HttpServer\Security\SessionContext.cs" /> <Compile Include="HttpServer\SocketSharp\SharpWebSocket.cs" /> - <Compile Include="HttpServer\SocketSharp\SocketSharpLogger.cs" /> <Compile Include="HttpServer\StreamWriter.cs" /> <Compile Include="HttpServer\SwaggerService.cs" /> <Compile Include="Drawing\ImageProcessor.cs" /> @@ -204,7 +210,6 @@ <Compile Include="Library\UserViewManager.cs" /> <Compile Include="Library\Validators\ArtistsPostScanTask.cs" /> <Compile Include="Library\Validators\ArtistsValidator.cs" /> - <Compile Include="Library\Validators\BoxSetPostScanTask.cs" /> <Compile Include="Library\Validators\GameGenresPostScanTask.cs" /> <Compile Include="Library\Validators\GameGenresValidator.cs" /> <Compile Include="Library\Validators\GenresPostScanTask.cs" /> @@ -224,6 +229,7 @@ <Compile Include="LiveTv\RecordingImageProvider.cs" /> <Compile Include="LiveTv\RefreshChannelsScheduledTask.cs" /> <Compile Include="Localization\LocalizationManager.cs" /> + <Compile Include="Logging\PatternsLogger.cs" /> <Compile Include="MediaEncoder\EncodingManager.cs" /> <Compile Include="Photos\DynamicImageProvider.cs" /> <Compile Include="News\NewsEntryPoint.cs" /> @@ -300,6 +306,8 @@ <Compile Include="Sorting\VideoBitRateComparer.cs" /> <Compile Include="Sync\AppSyncProvider.cs" /> <Compile Include="Sync\CloudSyncProvider.cs" /> + <Compile Include="Sync\SyncRegistrationInfo.cs" /> + <Compile Include="Sync\SyncConfig.cs" /> <Compile Include="Sync\SyncJobProcessor.cs" /> <Compile Include="Sync\SyncManager.cs" /> <Compile Include="Sync\SyncRepository.cs" /> @@ -396,8 +404,6 @@ <EmbeddedResource Include="Localization\Server\vi.json" /> <EmbeddedResource Include="Localization\JavaScript\pl.json" /> <EmbeddedResource Include="Localization\Server\pl.json" /> - <EmbeddedResource Include="Localization\JavaScript\es_ES.json" /> - <EmbeddedResource Include="Localization\Server\es_ES.json" /> <EmbeddedResource Include="Localization\Server\ko.json" /> <EmbeddedResource Include="Localization\JavaScript\en_GB.json" /> <EmbeddedResource Include="Localization\JavaScript\tr.json" /> @@ -409,6 +415,10 @@ <EmbeddedResource Include="Localization\JavaScript\fi.json" /> <EmbeddedResource Include="Localization\Server\fi.json" /> <None Include="app.config" /> + <EmbeddedResource Include="Localization\JavaScript\bg_BG.json" /> + <EmbeddedResource Include="Localization\JavaScript\uk.json" /> + <EmbeddedResource Include="Localization\Server\bg_BG.json" /> + <EmbeddedResource Include="Localization\Server\uk.json" /> <None Include="packages.config" /> </ItemGroup> <ItemGroup> diff --git a/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs b/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs index a0b604645..56557d6e1 100644 --- a/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs +++ b/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs @@ -215,7 +215,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder try { - File.Delete(image); + _fileSystem.DeleteFile(image); } catch (IOException ex) { diff --git a/MediaBrowser.Server.Implementations/News/NewsEntryPoint.cs b/MediaBrowser.Server.Implementations/News/NewsEntryPoint.cs index eebb04031..0b1947970 100644 --- a/MediaBrowser.Server.Implementations/News/NewsEntryPoint.cs +++ b/MediaBrowser.Server.Implementations/News/NewsEntryPoint.cs @@ -107,7 +107,8 @@ namespace MediaBrowser.Server.Implementations.News { Date = i.Date, Name = i.Title, - Description = i.Link, + Description = i.Description, + Url = i.Link, UserIds = _userManager.Users.Select(u => u.Id.ToString("N")).ToList() }, cancellationToken)); diff --git a/MediaBrowser.Server.Implementations/Notifications/CoreNotificationTypes.cs b/MediaBrowser.Server.Implementations/Notifications/CoreNotificationTypes.cs index 405bf407a..d8acbe06c 100644 --- a/MediaBrowser.Server.Implementations/Notifications/CoreNotificationTypes.cs +++ b/MediaBrowser.Server.Implementations/Notifications/CoreNotificationTypes.cs @@ -1,7 +1,6 @@ using MediaBrowser.Controller; using MediaBrowser.Controller.Localization; using MediaBrowser.Controller.Notifications; -using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Notifications; using System; using System.Collections.Generic; @@ -137,6 +136,13 @@ namespace MediaBrowser.Server.Implementations.Notifications Type = NotificationType.VideoPlaybackStopped.ToString(), DefaultTitle = "{UserName} has finished playing {ItemName} on {DeviceName}.", Variables = new List<string>{"UserName", "ItemName", "DeviceName", "AppName"} + }, + + new NotificationTypeInfo + { + Type = NotificationType.CameraImageUploaded.ToString(), + DefaultTitle = "A new camera image has been uploaded from {DeviceName}.", + Variables = new List<string>{"DeviceName"} } }; @@ -171,10 +177,14 @@ namespace MediaBrowser.Server.Implementations.Notifications { note.Category = _localization.GetLocalizedString("CategoryUser"); } - else if (note.Type.IndexOf("Plugin", StringComparison.OrdinalIgnoreCase) != -1) + else if (note.Type.IndexOf("Plugin", StringComparison.OrdinalIgnoreCase) != -1) { note.Category = _localization.GetLocalizedString("CategoryPlugin"); } + else if (note.Type.IndexOf("CameraImageUploaded", StringComparison.OrdinalIgnoreCase) != -1) + { + note.Category = _localization.GetLocalizedString("CategorySync"); + } else { note.Category = _localization.GetLocalizedString("CategorySystem"); diff --git a/MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs b/MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs index e74225887..5e02b2bac 100644 --- a/MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs +++ b/MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs @@ -11,6 +11,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Model.Extensions; namespace MediaBrowser.Server.Implementations.Notifications { diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index cd7928290..99c59abc5 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -1,7 +1,6 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Persistence; -using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; diff --git a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs index dbaf23656..369e8512f 100644 --- a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs +++ b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs @@ -14,7 +14,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.Photos { - public abstract class BaseDynamicImageProvider<T> : IHasChangeMonitor + public abstract class BaseDynamicImageProvider<T> : IHasChangeMonitor, IForcedProvider where T : IHasImages { protected IFileSystem FileSystem { get; private set; } diff --git a/MediaBrowser.Server.Implementations/Photos/PhotoAlbumImageProvider.cs b/MediaBrowser.Server.Implementations/Photos/PhotoAlbumImageProvider.cs index 7c10f2767..6a3759f13 100644 --- a/MediaBrowser.Server.Implementations/Photos/PhotoAlbumImageProvider.cs +++ b/MediaBrowser.Server.Implementations/Photos/PhotoAlbumImageProvider.cs @@ -17,7 +17,7 @@ namespace MediaBrowser.Server.Implementations.Photos protected override Task<List<BaseItem>> GetItemsWithImages(IHasImages item) { var photoAlbum = (PhotoAlbum)item; - var items = GetFinalItems(photoAlbum.RecursiveChildren.Where(i => i is Photo).ToList()); + var items = GetFinalItems(photoAlbum.GetRecursiveChildren(i => i is Photo).ToList()); return Task.FromResult(items); } diff --git a/MediaBrowser.Server.Implementations/Playlists/ManualPlaylistsFolder.cs b/MediaBrowser.Server.Implementations/Playlists/ManualPlaylistsFolder.cs index 89395a00b..980c3d14a 100644 --- a/MediaBrowser.Server.Implementations/Playlists/ManualPlaylistsFolder.cs +++ b/MediaBrowser.Server.Implementations/Playlists/ManualPlaylistsFolder.cs @@ -16,15 +16,14 @@ namespace MediaBrowser.Server.Implementations.Playlists public override bool IsVisible(User user) { - return base.IsVisible(user) && GetRecursiveChildren(user, false) + return base.IsVisible(user) && GetChildren(user, false) .OfType<Playlist>() .Any(i => i.IsVisible(user)); } protected override IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user) { - return RecursiveChildren - .OfType<Playlist>(); + return GetRecursiveChildren(i => i is Playlist); } public override bool IsHidden diff --git a/MediaBrowser.Server.Implementations/Playlists/PlaylistManager.cs b/MediaBrowser.Server.Implementations/Playlists/PlaylistManager.cs index 8da9ba222..c511f40e0 100644 --- a/MediaBrowser.Server.Implementations/Playlists/PlaylistManager.cs +++ b/MediaBrowser.Server.Implementations/Playlists/PlaylistManager.cs @@ -81,8 +81,7 @@ namespace MediaBrowser.Server.Implementations.Playlists var folder = item as Folder; if (folder != null) { - options.MediaType = folder.GetRecursiveChildren() - .Where(i => !i.IsFolder && i.SupportsAddingToPlaylist) + options.MediaType = folder.GetRecursiveChildren(i => !i.IsFolder && i.SupportsAddingToPlaylist) .Select(i => i.MediaType) .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i)); } diff --git a/MediaBrowser.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs b/MediaBrowser.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs index 2a115c8dd..7132db2ef 100644 --- a/MediaBrowser.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs +++ b/MediaBrowser.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs @@ -145,8 +145,8 @@ namespace MediaBrowser.Server.Implementations.ScheduledTasks /// <returns>Task.</returns> public async Task Execute(CancellationToken cancellationToken, IProgress<double> progress) { - var videos = _libraryManager.RootFolder.RecursiveChildren - .OfType<Video>() + var videos = _libraryManager.RootFolder.GetRecursiveChildren(i => i is Video) + .Cast<Video>() .ToList(); var numComplete = 0; diff --git a/MediaBrowser.Server.Implementations/ServerApplicationPaths.cs b/MediaBrowser.Server.Implementations/ServerApplicationPaths.cs index d9973afe7..8a04f29a2 100644 --- a/MediaBrowser.Server.Implementations/ServerApplicationPaths.cs +++ b/MediaBrowser.Server.Implementations/ServerApplicationPaths.cs @@ -198,19 +198,6 @@ namespace MediaBrowser.Server.Implementations } /// <summary> - /// Gets the artists path. - /// </summary> - /// <value>The artists path.</value> - public string ArtistsPath - { - get - { - return Path.Combine(ItemsByNamePath, "artists"); - } - } - - - /// <summary> /// Gets the game genre path. /// </summary> /// <value>The game genre path.</value> diff --git a/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs b/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs index 7a23d8e08..ef2fef746 100644 --- a/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs +++ b/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs @@ -99,22 +99,22 @@ namespace MediaBrowser.Server.Implementations.ServerManager /// <summary> /// Starts this instance. /// </summary> - public void Start(IEnumerable<string> urlPrefixes) + public void Start(IEnumerable<string> urlPrefixes, string certificatePath) { - ReloadHttpServer(urlPrefixes); + ReloadHttpServer(urlPrefixes, certificatePath); } /// <summary> /// Restarts the Http Server, or starts it if not currently running /// </summary> - private void ReloadHttpServer(IEnumerable<string> urlPrefixes) + private void ReloadHttpServer(IEnumerable<string> urlPrefixes, string certificatePath) { _logger.Info("Loading Http Server"); try { HttpServer = _applicationHost.Resolve<IHttpServer>(); - HttpServer.StartServer(urlPrefixes); + HttpServer.StartServer(urlPrefixes, certificatePath); } catch (SocketException ex) { diff --git a/MediaBrowser.Server.Implementations/Session/HttpSessionController.cs b/MediaBrowser.Server.Implementations/Session/HttpSessionController.cs index 4a64d3753..4d5c40853 100644 --- a/MediaBrowser.Server.Implementations/Session/HttpSessionController.cs +++ b/MediaBrowser.Server.Implementations/Session/HttpSessionController.cs @@ -209,6 +209,12 @@ namespace MediaBrowser.Server.Implementations.Session return SendMessage(command.Name, command.Arguments, cancellationToken); } + public Task SendMessage<T>(string name, T data, CancellationToken cancellationToken) + { + // Not supported or needed right now + return Task.FromResult(true); + } + private string ToQueryString(Dictionary<string, string> nvc) { var array = (from item in nvc diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs index d9ec9b7e4..4bce7db9f 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs @@ -2,7 +2,6 @@ using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller; -using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Dto; @@ -11,7 +10,6 @@ using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Security; using MediaBrowser.Controller.Session; @@ -307,21 +305,21 @@ namespace MediaBrowser.Server.Implementations.Session /// <param name="libraryItem">The library item.</param> private void UpdateNowPlayingItem(SessionInfo session, PlaybackProgressInfo info, BaseItem libraryItem) { - var runtimeTicks = libraryItem == null ? null : libraryItem.RunTimeTicks; - if (string.IsNullOrWhiteSpace(info.MediaSourceId)) { info.MediaSourceId = info.ItemId; } - if (!string.Equals(info.ItemId, info.MediaSourceId) && - !string.IsNullOrWhiteSpace(info.MediaSourceId)) + if (!string.IsNullOrWhiteSpace(info.ItemId) && info.Item == null && libraryItem != null) { - runtimeTicks = _libraryManager.GetItemById(new Guid(info.MediaSourceId)).RunTimeTicks; - } + var runtimeTicks = libraryItem.RunTimeTicks; + + if (!string.Equals(info.ItemId, info.MediaSourceId) && + !string.IsNullOrWhiteSpace(info.MediaSourceId)) + { + runtimeTicks = _libraryManager.GetItemById(new Guid(info.MediaSourceId)).RunTimeTicks; + } - if (!string.IsNullOrWhiteSpace(info.ItemId) && libraryItem != null) - { var current = session.NowPlayingItem; if (current == null || !string.Equals(current.Id, info.ItemId, StringComparison.OrdinalIgnoreCase)) @@ -711,7 +709,7 @@ namespace MediaBrowser.Server.Implementations.Session info.MediaSourceId = info.ItemId; } - if (!string.IsNullOrWhiteSpace(info.ItemId) && libraryItem != null) + if (!string.IsNullOrWhiteSpace(info.ItemId) && info.Item == null && libraryItem != null) { var current = session.NowPlayingItem; @@ -870,14 +868,14 @@ namespace MediaBrowser.Server.Implementations.Session { if (items.Any(i => !session.QueueableMediaTypes.Contains(i.MediaType, StringComparer.OrdinalIgnoreCase))) { - throw new ArgumentException(string.Format("{0} is unable to queue the requested media type.", session.DeviceName ?? session.Id.ToString())); + throw new ArgumentException(string.Format("{0} is unable to queue the requested media type.", session.DeviceName ?? session.Id)); } } else { if (items.Any(i => !session.PlayableMediaTypes.Contains(i.MediaType, StringComparer.OrdinalIgnoreCase))) { - throw new ArgumentException(string.Format("{0} is unable to play the requested media type.", session.DeviceName ?? session.Id.ToString())); + throw new ArgumentException(string.Format("{0} is unable to play the requested media type.", session.DeviceName ?? session.Id)); } } @@ -895,14 +893,28 @@ namespace MediaBrowser.Server.Implementations.Session { var item = _libraryManager.GetItemById(new Guid(id)); + var byName = item as IItemByName; + + if (byName != null) + { + var itemFilter = byName.GetItemFilter(); + + var items = user == null ? + _libraryManager.RootFolder.GetRecursiveChildren(i => !i.IsFolder && itemFilter(i)) : + user.RootFolder.GetRecursiveChildren(user, i => !i.IsFolder && itemFilter(i)); + + items = items.OrderBy(i => i.SortName); + + return items; + } + if (item.IsFolder) { var folder = (Folder)item; - var items = user == null ? folder.RecursiveChildren : - folder.GetRecursiveChildren(user); - - items = items.Where(i => !i.IsFolder); + var items = user == null ? + folder.GetRecursiveChildren(i => !i.IsFolder) : + folder.GetRecursiveChildren(user, i => !i.IsFolder); items = items.OrderBy(i => i.SortName); @@ -914,37 +926,9 @@ namespace MediaBrowser.Server.Implementations.Session private IEnumerable<BaseItem> TranslateItemForInstantMix(string id, User user) { - var item = _libraryManager.GetItemById(new Guid(id)); - - var audio = item as Audio; + var item = _libraryManager.GetItemById(id); - if (audio != null) - { - return _musicManager.GetInstantMixFromSong(audio, user); - } - - var artist = item as MusicArtist; - - if (artist != null) - { - return _musicManager.GetInstantMixFromArtist(artist.Name, user); - } - - var album = item as MusicAlbum; - - if (album != null) - { - return _musicManager.GetInstantMixFromAlbum(album, user); - } - - var genre = item as MusicGenre; - - if (genre != null) - { - return _musicManager.GetInstantMixFromGenres(new[] { genre.Name }, user); - } - - return new BaseItem[] { }; + return _musicManager.GetInstantMixFromItem(item, user); } public Task SendBrowseCommand(string controllingSessionId, string sessionId, BrowseRequest command, CancellationToken cancellationToken) @@ -1356,7 +1340,14 @@ namespace MediaBrowser.Server.Implementations.Session if (saveCapabilities) { - await SaveCapabilities(session.DeviceId, capabilities).ConfigureAwait(false); + try + { + await SaveCapabilities(session.DeviceId, capabilities).ConfigureAwait(false); + } + catch (Exception ex) + { + _logger.ErrorException("Error saving device capabilities", ex); + } } } @@ -1632,5 +1623,47 @@ namespace MediaBrowser.Server.Implementations.Session return Sessions.FirstOrDefault(i => string.Equals(i.DeviceId, deviceId) && string.Equals(i.Client, client)); } + + public Task SendMessageToUserSessions<T>(string userId, string name, T data, + CancellationToken cancellationToken) + { + var sessions = Sessions.Where(i => i.IsActive && i.SessionController != null && i.ContainsUser(userId)).ToList(); + + var tasks = sessions.Select(session => Task.Run(async () => + { + try + { + await session.SessionController.SendMessage(name, data, cancellationToken).ConfigureAwait(false); + } + catch (Exception ex) + { + _logger.ErrorException("Error sending message", ex); + } + + }, cancellationToken)); + + return Task.WhenAll(tasks); + } + + public Task SendMessageToUserDeviceSessions<T>(string deviceId, string name, T data, + CancellationToken cancellationToken) + { + var sessions = Sessions.Where(i => i.IsActive && i.SessionController != null && string.Equals(i.DeviceId, deviceId, StringComparison.OrdinalIgnoreCase)).ToList(); + + var tasks = sessions.Select(session => Task.Run(async () => + { + try + { + await session.SessionController.SendMessage(name, data, cancellationToken).ConfigureAwait(false); + } + catch (Exception ex) + { + _logger.ErrorException("Error sending message", ex); + } + + }, cancellationToken)); + + return Task.WhenAll(tasks); + } } }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Session/WebSocketController.cs b/MediaBrowser.Server.Implementations/Session/WebSocketController.cs index 7d1057397..19aaaf8a5 100644 --- a/MediaBrowser.Server.Implementations/Session/WebSocketController.cs +++ b/MediaBrowser.Server.Implementations/Session/WebSocketController.cs @@ -90,7 +90,7 @@ namespace MediaBrowser.Server.Implementations.Session public Task SendPlayCommand(PlayRequest command, CancellationToken cancellationToken) { - return SendMessage(new WebSocketMessage<PlayRequest> + return SendMessageInternal(new WebSocketMessage<PlayRequest> { MessageType = "Play", Data = command @@ -100,7 +100,7 @@ namespace MediaBrowser.Server.Implementations.Session public Task SendPlaystateCommand(PlaystateRequest command, CancellationToken cancellationToken) { - return SendMessage(new WebSocketMessage<PlaystateRequest> + return SendMessageInternal(new WebSocketMessage<PlaystateRequest> { MessageType = "Playstate", Data = command @@ -110,7 +110,7 @@ namespace MediaBrowser.Server.Implementations.Session public Task SendLibraryUpdateInfo(LibraryUpdateInfo info, CancellationToken cancellationToken) { - return SendMessages(new WebSocketMessage<LibraryUpdateInfo> + return SendMessagesInternal(new WebSocketMessage<LibraryUpdateInfo> { MessageType = "LibraryChanged", Data = info @@ -126,7 +126,7 @@ namespace MediaBrowser.Server.Implementations.Session /// <returns>Task.</returns> public Task SendRestartRequiredNotification(SystemInfo info, CancellationToken cancellationToken) { - return SendMessages(new WebSocketMessage<SystemInfo> + return SendMessagesInternal(new WebSocketMessage<SystemInfo> { MessageType = "RestartRequired", Data = info @@ -143,7 +143,7 @@ namespace MediaBrowser.Server.Implementations.Session /// <returns>Task.</returns> public Task SendUserDataChangeInfo(UserDataChangeInfo info, CancellationToken cancellationToken) { - return SendMessages(new WebSocketMessage<UserDataChangeInfo> + return SendMessagesInternal(new WebSocketMessage<UserDataChangeInfo> { MessageType = "UserDataChanged", Data = info @@ -158,7 +158,7 @@ namespace MediaBrowser.Server.Implementations.Session /// <returns>Task.</returns> public Task SendServerShutdownNotification(CancellationToken cancellationToken) { - return SendMessages(new WebSocketMessage<string> + return SendMessagesInternal(new WebSocketMessage<string> { MessageType = "ServerShuttingDown", Data = string.Empty @@ -173,7 +173,7 @@ namespace MediaBrowser.Server.Implementations.Session /// <returns>Task.</returns> public Task SendServerRestartNotification(CancellationToken cancellationToken) { - return SendMessages(new WebSocketMessage<string> + return SendMessagesInternal(new WebSocketMessage<string> { MessageType = "ServerRestarting", Data = string.Empty @@ -183,7 +183,7 @@ namespace MediaBrowser.Server.Implementations.Session public Task SendGeneralCommand(GeneralCommand command, CancellationToken cancellationToken) { - return SendMessage(new WebSocketMessage<GeneralCommand> + return SendMessageInternal(new WebSocketMessage<GeneralCommand> { MessageType = "GeneralCommand", Data = command @@ -193,7 +193,7 @@ namespace MediaBrowser.Server.Implementations.Session public Task SendSessionEndedNotification(SessionInfoDto sessionInfo, CancellationToken cancellationToken) { - return SendMessages(new WebSocketMessage<SessionInfoDto> + return SendMessagesInternal(new WebSocketMessage<SessionInfoDto> { MessageType = "SessionEnded", Data = sessionInfo @@ -203,7 +203,7 @@ namespace MediaBrowser.Server.Implementations.Session public Task SendPlaybackStartNotification(SessionInfoDto sessionInfo, CancellationToken cancellationToken) { - return SendMessages(new WebSocketMessage<SessionInfoDto> + return SendMessagesInternal(new WebSocketMessage<SessionInfoDto> { MessageType = "PlaybackStart", Data = sessionInfo @@ -213,7 +213,7 @@ namespace MediaBrowser.Server.Implementations.Session public Task SendPlaybackStoppedNotification(SessionInfoDto sessionInfo, CancellationToken cancellationToken) { - return SendMessages(new WebSocketMessage<SessionInfoDto> + return SendMessagesInternal(new WebSocketMessage<SessionInfoDto> { MessageType = "PlaybackStopped", Data = sessionInfo @@ -221,7 +221,17 @@ namespace MediaBrowser.Server.Implementations.Session }, cancellationToken); } - private Task SendMessage<T>(WebSocketMessage<T> message, CancellationToken cancellationToken) + public Task SendMessage<T>(string name, T data, CancellationToken cancellationToken) + { + return SendMessagesInternal(new WebSocketMessage<T> + { + Data = data, + MessageType = name + + }, cancellationToken); + } + + private Task SendMessageInternal<T>(WebSocketMessage<T> message, CancellationToken cancellationToken) { if (SkipSending()) return Task.FromResult(true); @@ -230,7 +240,7 @@ namespace MediaBrowser.Server.Implementations.Session return socket.SendAsync(message, cancellationToken); } - private Task SendMessages<T>(WebSocketMessage<T> message, CancellationToken cancellationToken) + private Task SendMessagesInternal<T>(WebSocketMessage<T> message, CancellationToken cancellationToken) { if (SkipSending()) return Task.FromResult(true); diff --git a/MediaBrowser.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs b/MediaBrowser.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs index 8707f2e5b..c7bbca060 100644 --- a/MediaBrowser.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs +++ b/MediaBrowser.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs @@ -72,6 +72,8 @@ namespace MediaBrowser.Server.Implementations.Sorting private int CompareEpisodeToSpecial(Episode x, Episode y) { + // http://thetvdb.com/wiki/index.php?title=Special_Episodes + var xSeason = x.PhysicalSeasonNumber ?? -1; var ySeason = y.AirsAfterSeasonNumber ?? y.AirsBeforeSeasonNumber ?? -1; diff --git a/MediaBrowser.Server.Implementations/Sync/SyncConfig.cs b/MediaBrowser.Server.Implementations/Sync/SyncConfig.cs new file mode 100644 index 000000000..52c774330 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Sync/SyncConfig.cs @@ -0,0 +1,29 @@ +using MediaBrowser.Common.Configuration; +using MediaBrowser.Model.Sync; +using System.Collections.Generic; + +namespace MediaBrowser.Server.Implementations.Sync +{ + public class SyncConfigurationFactory : IConfigurationFactory + { + public IEnumerable<ConfigurationStore> GetConfigurations() + { + return new List<ConfigurationStore> + { + new ConfigurationStore + { + ConfigurationType = typeof(SyncOptions), + Key = "sync" + } + }; + } + } + + public static class SyncExtensions + { + public static SyncOptions GetSyncOptions(this IConfigurationManager config) + { + return config.GetConfiguration<SyncOptions>("sync"); + } + } +} diff --git a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs index 698806d09..8cad50b91 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs @@ -1,4 +1,6 @@ -using MediaBrowser.Common.Progress; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.IO; +using MediaBrowser.Common.Progress; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; @@ -16,6 +18,7 @@ using MediaBrowser.Model.Sync; using MoreLinq; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -31,8 +34,11 @@ namespace MediaBrowser.Server.Implementations.Sync private readonly IUserManager _userManager; private readonly ITVSeriesManager _tvSeriesManager; private readonly IMediaEncoder _mediaEncoder; + private readonly ISubtitleEncoder _subtitleEncoder; + private readonly IConfigurationManager _config; + private readonly IFileSystem _fileSystem; - public SyncJobProcessor(ILibraryManager libraryManager, ISyncRepository syncRepo, ISyncManager syncManager, ILogger logger, IUserManager userManager, ITVSeriesManager tvSeriesManager, IMediaEncoder mediaEncoder) + public SyncJobProcessor(ILibraryManager libraryManager, ISyncRepository syncRepo, ISyncManager syncManager, ILogger logger, IUserManager userManager, ITVSeriesManager tvSeriesManager, IMediaEncoder mediaEncoder, ISubtitleEncoder subtitleEncoder, IConfigurationManager config, IFileSystem fileSystem) { _libraryManager = libraryManager; _syncRepo = syncRepo; @@ -41,6 +47,9 @@ namespace MediaBrowser.Server.Implementations.Sync _userManager = userManager; _tvSeriesManager = tvSeriesManager; _mediaEncoder = mediaEncoder; + _subtitleEncoder = subtitleEncoder; + _config = config; + _fileSystem = fileSystem; } public async Task EnsureJobItems(SyncJob job) @@ -81,6 +90,10 @@ namespace MediaBrowser.Server.Implementations.Sync continue; } + var index = jobItems.Count == 0 ? + 0 : + (jobItems.Select(i => i.JobItemIndex).Max() + 1); + jobItem = new SyncJobItem { Id = Guid.NewGuid().ToString("N"), @@ -88,7 +101,8 @@ namespace MediaBrowser.Server.Implementations.Sync ItemName = GetSyncJobItemName(item), JobId = job.Id, TargetId = job.TargetId, - DateCreated = DateTime.UtcNow + DateCreated = DateTime.UtcNow, + JobItemIndex = index }; await _syncRepo.Create(jobItem).ConfigureAwait(false); @@ -274,18 +288,14 @@ namespace MediaBrowser.Server.Implementations.Sync var itemByName = item as IItemByName; if (itemByName != null) { - var items = user.RootFolder - .GetRecursiveChildren(user); - - return itemByName.GetTaggedItems(items); + return user.RootFolder + .GetRecursiveChildren(user, itemByName.GetItemFilter()); } if (item.IsFolder) { var folder = (Folder)item; - var items = folder.GetRecursiveChildren(user); - - items = items.Where(i => !i.IsFolder); + var items = folder.GetRecursiveChildren(user, i => !i.IsFolder); if (!folder.IsPreSorted) { @@ -326,31 +336,64 @@ namespace MediaBrowser.Server.Implementations.Sync Statuses = new List<SyncJobItemStatus> { SyncJobItemStatus.Queued, SyncJobItemStatus.Converting } }); - var jobItems = result.Items; - var index = 0; + await SyncJobItems(result.Items, true, progress, cancellationToken).ConfigureAwait(false); - foreach (var item in jobItems) + CleanDeadSyncFiles(); + } + + private void CleanDeadSyncFiles() + { + // TODO + // Clean files in sync temp folder that are not linked to any sync jobs + } + + public async Task SyncJobItems(SyncJobItem[] items, bool enableConversion, IProgress<double> progress, CancellationToken cancellationToken) + { + if (items.Length > 0) { - double percent = index; - percent /= result.TotalRecordCount; + if (!SyncRegistrationInfo.Instance.IsRegistered) + { + _logger.Debug("Cancelling sync job processing. Please obtain a supporter membership."); + return; + } + } - progress.Report(100 * percent); + var numComplete = 0; + foreach (var item in items) + { cancellationToken.ThrowIfCancellationRequested(); + double percentPerItem = 1; + percentPerItem /= items.Length; + var startingPercent = numComplete * percentPerItem * 100; + var innerProgress = new ActionableProgress<double>(); + innerProgress.RegisterAction(p => progress.Report(startingPercent + (percentPerItem * p))); + + // Pull it fresh from the db just to make sure it wasn't deleted or cancelled while another item was converting + var jobItem = enableConversion ? _syncRepo.GetJobItem(item.Id) : item; - var job = _syncRepo.GetJob(item.JobId); - await ProcessJobItem(job, item, innerProgress, cancellationToken).ConfigureAwait(false); + if (jobItem != null) + { + var job = _syncRepo.GetJob(jobItem.JobId); + if (jobItem.Status != SyncJobItemStatus.Cancelled) + { + await ProcessJobItem(job, jobItem, enableConversion, innerProgress, cancellationToken).ConfigureAwait(false); + } - job = _syncRepo.GetJob(item.JobId); - await UpdateJobStatus(job).ConfigureAwait(false); + job = _syncRepo.GetJob(jobItem.JobId); + await UpdateJobStatus(job).ConfigureAwait(false); + } - index++; + numComplete++; + double percent = numComplete; + percent /= items.Length; + progress.Report(100 * percent); } } - private async Task ProcessJobItem(SyncJob job, SyncJobItem jobItem, IProgress<double> progress, CancellationToken cancellationToken) + private async Task ProcessJobItem(SyncJob job, SyncJobItem jobItem, bool enableConversion, IProgress<double> progress, CancellationToken cancellationToken) { var item = _libraryManager.GetItemById(jobItem.ItemId); if (item == null) @@ -378,12 +421,12 @@ namespace MediaBrowser.Server.Implementations.Sync var video = item as Video; if (video != null) { - await Sync(jobItem, video, user, deviceProfile, progress, cancellationToken).ConfigureAwait(false); + await Sync(jobItem, video, user, deviceProfile, enableConversion, progress, cancellationToken).ConfigureAwait(false); } else if (item is Audio) { - await Sync(jobItem, (Audio)item, user, deviceProfile, progress, cancellationToken).ConfigureAwait(false); + await Sync(jobItem, (Audio)item, user, deviceProfile, enableConversion, progress, cancellationToken).ConfigureAwait(false); } else if (item is Photo) @@ -397,7 +440,7 @@ namespace MediaBrowser.Server.Implementations.Sync } } - private async Task Sync(SyncJobItem jobItem, Video item, User user, DeviceProfile profile, IProgress<double> progress, CancellationToken cancellationToken) + private async Task Sync(SyncJobItem jobItem, Video item, User user, DeviceProfile profile, bool enableConversion, IProgress<double> progress, CancellationToken cancellationToken) { var options = new VideoOptions { @@ -410,19 +453,36 @@ namespace MediaBrowser.Server.Implementations.Sync var streamInfo = new StreamBuilder().BuildVideoItem(options); var mediaSource = streamInfo.MediaSource; + var externalSubs = streamInfo.GetExternalSubtitles("dummy", false); + + // Mark as requiring conversion if transcoding the video, or if any subtitles need to be extracted + var requiresConversion = streamInfo.PlayMethod == PlayMethod.Transcode || externalSubs.Any(i => RequiresExtraction(i, mediaSource)); + + if (requiresConversion && !enableConversion) + { + return; + } jobItem.MediaSourceId = streamInfo.MediaSourceId; + jobItem.TemporaryPath = GetTemporaryPath(jobItem); - if (streamInfo.PlayMethod == PlayMethod.Transcode) + if (requiresConversion) { jobItem.Status = SyncJobItemStatus.Converting; - jobItem.RequiresConversion = true; + } + + if (streamInfo.PlayMethod == PlayMethod.Transcode) + { + // Save the job item now since conversion could take a while await _syncRepo.Update(jobItem).ConfigureAwait(false); try { - jobItem.OutputPath = await _mediaEncoder.EncodeVideo(new EncodingJobOptions(streamInfo, profile), progress, - cancellationToken); + jobItem.OutputPath = await _mediaEncoder.EncodeVideo(new EncodingJobOptions(streamInfo, profile) + { + OutputDirectory = jobItem.TemporaryPath + + }, progress, cancellationToken); } catch (OperationCanceledException) { @@ -439,11 +499,11 @@ namespace MediaBrowser.Server.Implementations.Sync await _syncRepo.Update(jobItem).ConfigureAwait(false); return; } + + jobItem.MediaSource = await GetEncodedMediaSource(jobItem.OutputPath, user, true).ConfigureAwait(false); } else { - jobItem.RequiresConversion = false; - if (mediaSource.Protocol == MediaProtocol.File) { jobItem.OutputPath = mediaSource.Path; @@ -456,6 +516,16 @@ namespace MediaBrowser.Server.Implementations.Sync { throw new InvalidOperationException(string.Format("Cannot direct stream {0} protocol", mediaSource.Protocol)); } + + jobItem.MediaSource = mediaSource; + } + + if (externalSubs.Count > 0) + { + // Save the job item now since conversion could take a while + await _syncRepo.Update(jobItem).ConfigureAwait(false); + + await ConvertSubtitles(jobItem, externalSubs, streamInfo, cancellationToken).ConfigureAwait(false); } jobItem.Progress = 50; @@ -463,7 +533,82 @@ namespace MediaBrowser.Server.Implementations.Sync await _syncRepo.Update(jobItem).ConfigureAwait(false); } - private async Task Sync(SyncJobItem jobItem, Audio item, User user, DeviceProfile profile, IProgress<double> progress, CancellationToken cancellationToken) + private bool RequiresExtraction(SubtitleStreamInfo stream, MediaSourceInfo mediaSource) + { + var originalStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Subtitle && i.Index == stream.Index); + + return originalStream != null && !originalStream.IsExternal; + } + + private async Task ConvertSubtitles(SyncJobItem jobItem, + IEnumerable<SubtitleStreamInfo> subtitles, + StreamInfo streamInfo, + CancellationToken cancellationToken) + { + var files = new List<ItemFileInfo>(); + + var mediaStreams = jobItem.MediaSource.MediaStreams + .Where(i => i.Type != MediaStreamType.Subtitle || !i.IsExternal) + .ToList(); + + var startingIndex = mediaStreams.Count == 0 ? + 0 : + (mediaStreams.Select(i => i.Index).Max() + 1); + + foreach (var subtitle in subtitles) + { + var fileInfo = await ConvertSubtitles(jobItem.TemporaryPath, streamInfo, subtitle, cancellationToken).ConfigureAwait(false); + + // Reset this to a value that will be based on the output media + fileInfo.Index = startingIndex; + files.Add(fileInfo); + + mediaStreams.Add(new MediaStream + { + Index = startingIndex, + Codec = subtitle.Format, + IsForced = subtitle.IsForced, + IsExternal = true, + Language = subtitle.Language, + Path = fileInfo.Path + }); + + startingIndex++; + } + + jobItem.AdditionalFiles.AddRange(files); + + jobItem.MediaSource.MediaStreams = mediaStreams; + } + + private async Task<ItemFileInfo> ConvertSubtitles(string temporaryPath, StreamInfo streamInfo, SubtitleStreamInfo subtitleStreamInfo, CancellationToken cancellationToken) + { + var subtitleStreamIndex = subtitleStreamInfo.Index; + + var filename = Guid.NewGuid() + "." + subtitleStreamInfo.Format.ToLower(); + + var path = Path.Combine(temporaryPath, filename); + + Directory.CreateDirectory(Path.GetDirectoryName(path)); + + using (var stream = await _subtitleEncoder.GetSubtitles(streamInfo.ItemId, streamInfo.MediaSourceId, subtitleStreamIndex, subtitleStreamInfo.Format, 0, null, cancellationToken).ConfigureAwait(false)) + { + using (var fs = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true)) + { + await stream.CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, cancellationToken).ConfigureAwait(false); + } + } + + return new ItemFileInfo + { + Name = Path.GetFileName(path), + Path = path, + Type = ItemFileType.Subtitles, + Index = subtitleStreamIndex + }; + } + + private async Task Sync(SyncJobItem jobItem, Audio item, User user, DeviceProfile profile, bool enableConversion, IProgress<double> progress, CancellationToken cancellationToken) { var options = new AudioOptions { @@ -478,16 +623,25 @@ namespace MediaBrowser.Server.Implementations.Sync var mediaSource = streamInfo.MediaSource; jobItem.MediaSourceId = streamInfo.MediaSourceId; + jobItem.TemporaryPath = GetTemporaryPath(jobItem); if (streamInfo.PlayMethod == PlayMethod.Transcode) { + if (!enableConversion) + { + return; + } + jobItem.Status = SyncJobItemStatus.Converting; - jobItem.RequiresConversion = true; await _syncRepo.Update(jobItem).ConfigureAwait(false); try { - jobItem.OutputPath = await _mediaEncoder.EncodeAudio(new EncodingJobOptions(streamInfo, profile), progress, cancellationToken); + jobItem.OutputPath = await _mediaEncoder.EncodeAudio(new EncodingJobOptions(streamInfo, profile) + { + OutputDirectory = jobItem.TemporaryPath + + }, progress, cancellationToken); } catch (OperationCanceledException) { @@ -504,11 +658,11 @@ namespace MediaBrowser.Server.Implementations.Sync await _syncRepo.Update(jobItem).ConfigureAwait(false); return; } + + jobItem.MediaSource = await GetEncodedMediaSource(jobItem.OutputPath, user, false).ConfigureAwait(false); } else { - jobItem.RequiresConversion = false; - if (mediaSource.Protocol == MediaProtocol.File) { jobItem.OutputPath = mediaSource.Path; @@ -521,6 +675,8 @@ namespace MediaBrowser.Server.Implementations.Sync { throw new InvalidOperationException(string.Format("Cannot direct stream {0} protocol", mediaSource.Protocol)); } + + jobItem.MediaSource = mediaSource; } jobItem.Progress = 50; @@ -551,5 +707,65 @@ namespace MediaBrowser.Server.Implementations.Sync // TODO: Download return mediaSource.Path; } + + private string GetTemporaryPath(SyncJobItem jobItem) + { + var basePath = _config.GetSyncOptions().TemporaryPath; + + if (string.IsNullOrWhiteSpace(basePath)) + { + basePath = Path.Combine(_config.CommonApplicationPaths.ProgramDataPath, "sync"); + } + + return Path.Combine(basePath, jobItem.JobId, jobItem.Id); + } + + private async Task<MediaSourceInfo> GetEncodedMediaSource(string path, User user, bool isVideo) + { + var item = _libraryManager.ResolvePath(new FileInfo(path)); + + await item.RefreshMetadata(CancellationToken.None).ConfigureAwait(false); + + var hasMediaSources = item as IHasMediaSources; + + var mediaSources = hasMediaSources.GetMediaSources(false).ToList(); + + var preferredAudio = string.IsNullOrEmpty(user.Configuration.AudioLanguagePreference) + ? new string[] { } + : new[] { user.Configuration.AudioLanguagePreference }; + + var preferredSubs = string.IsNullOrEmpty(user.Configuration.SubtitleLanguagePreference) + ? new List<string> { } + : new List<string> { user.Configuration.SubtitleLanguagePreference }; + + foreach (var source in mediaSources) + { + if (isVideo) + { + source.DefaultAudioStreamIndex = + MediaStreamSelector.GetDefaultAudioStreamIndex(source.MediaStreams, preferredAudio, user.Configuration.PlayDefaultAudioTrack); + + var defaultAudioIndex = source.DefaultAudioStreamIndex; + var audioLangage = defaultAudioIndex == null + ? null + : source.MediaStreams.Where(i => i.Type == MediaStreamType.Audio && i.Index == defaultAudioIndex).Select(i => i.Language).FirstOrDefault(); + + source.DefaultAudioStreamIndex = + MediaStreamSelector.GetDefaultSubtitleStreamIndex(source.MediaStreams, preferredSubs, user.Configuration.SubtitleMode, audioLangage); + } + else + { + var audio = source.MediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Audio); + + if (audio != null) + { + source.DefaultAudioStreamIndex = audio.Index; + } + + } + } + + return mediaSources.FirstOrDefault(); + } } } diff --git a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs index b8f199e6b..5ead8f02b 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs @@ -1,5 +1,8 @@ using MediaBrowser.Common; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Events; using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.IO; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Dto; @@ -12,7 +15,9 @@ using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Sync; using MediaBrowser.Controller.TV; using MediaBrowser.Model.Dlna; +using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Events; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Querying; using MediaBrowser.Model.Sync; @@ -22,6 +27,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading; using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.Sync @@ -37,10 +43,16 @@ namespace MediaBrowser.Server.Implementations.Sync private readonly IApplicationHost _appHost; private readonly ITVSeriesManager _tvSeriesManager; private readonly Func<IMediaEncoder> _mediaEncoder; + private readonly IFileSystem _fileSystem; + private readonly Func<ISubtitleEncoder> _subtitleEncoder; + private readonly IConfigurationManager _config; private ISyncProvider[] _providers = { }; - public SyncManager(ILibraryManager libraryManager, ISyncRepository repo, IImageProcessor imageProcessor, ILogger logger, IUserManager userManager, Func<IDtoService> dtoService, IApplicationHost appHost, ITVSeriesManager tvSeriesManager, Func<IMediaEncoder> mediaEncoder) + public event EventHandler<GenericEventArgs<SyncJobCreationResult>> SyncJobCreated; + public event EventHandler<GenericEventArgs<SyncJob>> SyncJobCancelled; + + public SyncManager(ILibraryManager libraryManager, ISyncRepository repo, IImageProcessor imageProcessor, ILogger logger, IUserManager userManager, Func<IDtoService> dtoService, IApplicationHost appHost, ITVSeriesManager tvSeriesManager, Func<IMediaEncoder> mediaEncoder, IFileSystem fileSystem, Func<ISubtitleEncoder> subtitleEncoder, IConfigurationManager config) { _libraryManager = libraryManager; _repo = repo; @@ -51,6 +63,9 @@ namespace MediaBrowser.Server.Implementations.Sync _appHost = appHost; _tvSeriesManager = tvSeriesManager; _mediaEncoder = mediaEncoder; + _fileSystem = fileSystem; + _subtitleEncoder = subtitleEncoder; + _config = config; } public void AddParts(IEnumerable<ISyncProvider> providers) @@ -60,7 +75,7 @@ namespace MediaBrowser.Server.Implementations.Sync public async Task<SyncJobCreationResult> CreateJob(SyncJobRequest request) { - var processor = new SyncJobProcessor(_libraryManager, _repo, this, _logger, _userManager, _tvSeriesManager, _mediaEncoder()); + var processor = GetSyncJobProcessor(); var user = _userManager.GetUserById(request.UserId); @@ -88,14 +103,14 @@ namespace MediaBrowser.Server.Implementations.Sync var target = GetSyncTargets(request.UserId) .FirstOrDefault(i => string.Equals(request.TargetId, i.Id)); - + if (target == null) { throw new ArgumentException("Sync target not found."); } var jobId = Guid.NewGuid().ToString("N"); - + var job = new SyncJob { Id = jobId, @@ -124,10 +139,38 @@ namespace MediaBrowser.Server.Implementations.Sync await processor.EnsureJobItems(job).ConfigureAwait(false); - return new SyncJobCreationResult + // If it already has a converting status then is must have been aborted during conversion + var jobItemsResult = _repo.GetJobItems(new SyncJobItemQuery + { + Statuses = new List<SyncJobItemStatus> { SyncJobItemStatus.Queued, SyncJobItemStatus.Converting }, + JobId = jobId + }); + + await processor.SyncJobItems(jobItemsResult.Items, false, new Progress<double>(), CancellationToken.None) + .ConfigureAwait(false); + + jobItemsResult = _repo.GetJobItems(new SyncJobItemQuery + { + Statuses = new List<SyncJobItemStatus> { SyncJobItemStatus.Queued, SyncJobItemStatus.Converting }, + JobId = jobId + }); + + var returnResult = new SyncJobCreationResult { - Job = GetJob(jobId) + Job = GetJob(jobId), + JobItems = jobItemsResult.Items.ToList() }; + + if (SyncJobCreated != null) + { + EventHelper.FireEventIfNotNull(SyncJobCreated, this, new GenericEventArgs<SyncJobCreationResult> + { + Argument = returnResult + + }, _logger); + } + + return returnResult; } public Task UpdateJob(SyncJob job) @@ -164,7 +207,7 @@ namespace MediaBrowser.Server.Implementations.Sync if (item == null) { - var processor = new SyncJobProcessor(_libraryManager, _repo, this, _logger, _userManager, _tvSeriesManager, _mediaEncoder()); + var processor = GetSyncJobProcessor(); var user = _userManager.GetUserById(job.UserId); @@ -255,9 +298,25 @@ namespace MediaBrowser.Server.Implementations.Sync } } - public Task CancelJob(string id) + public async Task CancelJob(string id) { - return _repo.DeleteJob(id); + var job = GetJob(id); + + if (job == null) + { + throw new ArgumentException("Job not found."); + } + + await _repo.DeleteJob(id).ConfigureAwait(false); + + if (SyncJobCancelled != null) + { + EventHelper.FireEventIfNotNull(SyncJobCancelled, this, new GenericEventArgs<SyncJob> + { + Argument = job + + }, _logger); + } } public SyncJob GetJob(string id) @@ -392,11 +451,14 @@ namespace MediaBrowser.Server.Implementations.Sync jobItem.Status = SyncJobItemStatus.Synced; jobItem.Progress = 100; - if (jobItem.RequiresConversion) + if (!string.IsNullOrWhiteSpace(jobItem.TemporaryPath)) { try { - File.Delete(jobItem.OutputPath); + _fileSystem.DeleteDirectory(jobItem.TemporaryPath, true); + } + catch (DirectoryNotFoundException) + { } catch (Exception ex) { @@ -406,11 +468,16 @@ namespace MediaBrowser.Server.Implementations.Sync await _repo.Update(jobItem).ConfigureAwait(false); - var processor = new SyncJobProcessor(_libraryManager, _repo, this, _logger, _userManager, _tvSeriesManager, _mediaEncoder()); + var processor = GetSyncJobProcessor(); await processor.UpdateJobStatus(jobItem.JobId).ConfigureAwait(false); } + private SyncJobProcessor GetSyncJobProcessor() + { + return new SyncJobProcessor(_libraryManager, _repo, this, _logger, _userManager, _tvSeriesManager, _mediaEncoder(), _subtitleEncoder(), _config, _fileSystem); + } + public SyncJobItem GetJobItem(string id) { return _repo.GetJobItem(id); @@ -439,7 +506,15 @@ namespace MediaBrowser.Server.Implementations.Sync SyncJobId = jobItem.JobId, SyncJobItemId = jobItem.Id, ServerId = _appHost.SystemId, - UserId = job.UserId + UserId = job.UserId, + AdditionalFiles = jobItem.AdditionalFiles.Select(i => new ItemFileInfo + { + ImageType = i.ImageType, + Name = i.Name, + Type = i.Type, + Index = i.Index + + }).ToList() }; var dtoOptions = new DtoOptions(); @@ -456,14 +531,11 @@ namespace MediaBrowser.Server.Implementations.Sync syncedItem.Item = _dtoService().GetBaseItemDto(libraryItem, dtoOptions); - // TODO: this should be the media source of the transcoded output - syncedItem.Item.MediaSources = syncedItem.Item.MediaSources - .Where(i => string.Equals(i.Id, jobItem.MediaSourceId)) - .ToList(); - var mediaSource = syncedItem.Item.MediaSources .FirstOrDefault(i => string.Equals(i.Id, jobItem.MediaSourceId)); + syncedItem.Item.MediaSources = new List<MediaSourceInfo>(); + // This will be null for items that are not audio/video if (mediaSource == null) { @@ -472,6 +544,7 @@ namespace MediaBrowser.Server.Implementations.Sync else { syncedItem.OriginalFileName = Path.GetFileName(mediaSource.Path); + syncedItem.Item.MediaSources.Add(mediaSource); } return syncedItem; @@ -511,7 +584,12 @@ namespace MediaBrowser.Server.Implementations.Sync var job = _repo.GetJob(jobItem.JobId); var user = _userManager.GetUserById(job.UserId); - if (user == null) + if (jobItem.IsMarkedForRemoval) + { + // Tell the device to remove it since it has been marked for removal + response.ItemIdsToRemove.Add(jobItem.ItemId); + } + else if (user == null) { // Tell the device to remove it since the user is gone now response.ItemIdsToRemove.Add(jobItem.ItemId); @@ -575,5 +653,86 @@ namespace MediaBrowser.Server.Implementations.Sync return true; } + + public async Task ReEnableJobItem(string id) + { + var jobItem = _repo.GetJobItem(id); + + if (jobItem.Status != SyncJobItemStatus.Failed && jobItem.Status != SyncJobItemStatus.Cancelled) + { + throw new ArgumentException("Operation is not valid for this job item"); + } + + jobItem.Status = SyncJobItemStatus.Queued; + jobItem.Progress = 0; + jobItem.IsMarkedForRemoval = false; + + await _repo.Update(jobItem).ConfigureAwait(false); + + var processor = GetSyncJobProcessor(); + + await processor.UpdateJobStatus(jobItem.JobId).ConfigureAwait(false); + } + + public async Task CancelJobItem(string id) + { + var jobItem = _repo.GetJobItem(id); + + if (jobItem.Status != SyncJobItemStatus.Queued && jobItem.Status != SyncJobItemStatus.Transferring && jobItem.Status != SyncJobItemStatus.Converting) + { + throw new ArgumentException("Operation is not valid for this job item"); + } + + jobItem.Status = SyncJobItemStatus.Cancelled; + jobItem.Progress = 0; + jobItem.IsMarkedForRemoval = true; + + await _repo.Update(jobItem).ConfigureAwait(false); + + var processor = GetSyncJobProcessor(); + + await processor.UpdateJobStatus(jobItem.JobId).ConfigureAwait(false); + } + + public async Task MarkJobItemForRemoval(string id) + { + var jobItem = _repo.GetJobItem(id); + + if (jobItem.Status != SyncJobItemStatus.Synced) + { + throw new ArgumentException("Operation is not valid for this job item"); + } + + jobItem.IsMarkedForRemoval = true; + + await _repo.Update(jobItem).ConfigureAwait(false); + + var processor = GetSyncJobProcessor(); + + await processor.UpdateJobStatus(jobItem.JobId).ConfigureAwait(false); + } + + public async Task UnmarkJobItemForRemoval(string id) + { + var jobItem = _repo.GetJobItem(id); + + if (jobItem.Status != SyncJobItemStatus.Synced) + { + throw new ArgumentException("Operation is not valid for this job item"); + } + + jobItem.IsMarkedForRemoval = false; + + await _repo.Update(jobItem).ConfigureAwait(false); + + var processor = GetSyncJobProcessor(); + + await processor.UpdateJobStatus(jobItem.JobId).ConfigureAwait(false); + } + + public QueryResult<string> GetLibraryItemIds(SyncJobItemQuery query) + { + return _repo.GetLibraryItemIds(query); + } } } diff --git a/MediaBrowser.Server.Implementations/Sync/SyncRegistrationInfo.cs b/MediaBrowser.Server.Implementations/Sync/SyncRegistrationInfo.cs new file mode 100644 index 000000000..40b84b1c2 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Sync/SyncRegistrationInfo.cs @@ -0,0 +1,31 @@ +using MediaBrowser.Common.Security; +using System.Threading.Tasks; + +namespace MediaBrowser.Server.Implementations.Sync +{ + public class SyncRegistrationInfo : IRequiresRegistration + { + private readonly ISecurityManager _securityManager; + + public static SyncRegistrationInfo Instance; + + public SyncRegistrationInfo(ISecurityManager securityManager) + { + _securityManager = securityManager; + Instance = this; + } + + private bool _registered; + public bool IsRegistered + { + get { return _registered; } + } + + public async Task LoadRegistrationInfoAsync() + { + var info = await _securityManager.GetRegistrationStatus("sync").ConfigureAwait(false); + + _registered = info.IsValid; + } + } +} diff --git a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs index 151860d84..6d77749e0 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs @@ -1,7 +1,9 @@ using MediaBrowser.Controller; using MediaBrowser.Controller.Sync; +using MediaBrowser.Model.Dto; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Querying; +using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Sync; using MediaBrowser.Server.Implementations.Persistence; using System; @@ -28,15 +30,18 @@ namespace MediaBrowser.Server.Implementations.Sync private IDbCommand _saveJobCommand; private IDbCommand _saveJobItemCommand; - public SyncRepository(ILogger logger, IServerApplicationPaths appPaths) + private readonly IJsonSerializer _json; + + public SyncRepository(ILogger logger, IServerApplicationPaths appPaths, IJsonSerializer json) { _logger = logger; _appPaths = appPaths; + _json = json; } public async Task Initialize() { - var dbFile = Path.Combine(_appPaths.DataPath, "sync11.db"); + var dbFile = Path.Combine(_appPaths.DataPath, "sync14.db"); _connection = await SqliteExtensions.ConnectToDb(dbFile, _logger).ConfigureAwait(false); @@ -45,7 +50,7 @@ namespace MediaBrowser.Server.Implementations.Sync "create table if not exists SyncJobs (Id GUID PRIMARY KEY, TargetId TEXT NOT NULL, Name TEXT NOT NULL, Quality TEXT NOT NULL, Status TEXT NOT NULL, Progress FLOAT, UserId TEXT NOT NULL, ItemIds TEXT NOT NULL, Category TEXT, ParentId TEXT, UnwatchedOnly BIT, ItemLimit INT, SyncNewContent BIT, DateCreated DateTime, DateLastModified DateTime, ItemCount int)", "create index if not exists idx_SyncJobs on SyncJobs(Id)", - "create table if not exists SyncJobItems (Id GUID PRIMARY KEY, ItemId TEXT, ItemName TEXT, MediaSourceId TEXT, JobId TEXT, RequiresConversion BIT, OutputPath TEXT, Status TEXT, TargetId TEXT, DateCreated DateTime, Progress FLOAT)", + "create table if not exists SyncJobItems (Id GUID PRIMARY KEY, ItemId TEXT, ItemName TEXT, MediaSourceId TEXT, JobId TEXT, TemporaryPath TEXT, OutputPath TEXT, Status TEXT, TargetId TEXT, DateCreated DateTime, Progress FLOAT, AdditionalFiles TEXT, MediaSource TEXT, IsMarkedForRemoval BIT, JobItemIndex INT)", "create index if not exists idx_SyncJobItems on SyncJobs(Id)", //pragmas @@ -90,23 +95,27 @@ namespace MediaBrowser.Server.Implementations.Sync _saveJobCommand.Parameters.Add(_saveJobCommand, "@ItemCount"); _saveJobItemCommand = _connection.CreateCommand(); - _saveJobItemCommand.CommandText = "replace into SyncJobItems (Id, ItemId, ItemName, MediaSourceId, JobId, RequiresConversion, OutputPath, Status, TargetId, DateCreated, Progress) values (@Id, @ItemId, @ItemName, @MediaSourceId, @JobId, @RequiresConversion, @OutputPath, @Status, @TargetId, @DateCreated, @Progress)"; + _saveJobItemCommand.CommandText = "replace into SyncJobItems (Id, ItemId, ItemName, MediaSourceId, JobId, TemporaryPath, OutputPath, Status, TargetId, DateCreated, Progress, AdditionalFiles, MediaSource, IsMarkedForRemoval, JobItemIndex) values (@Id, @ItemId, @ItemName, @MediaSourceId, @JobId, @TemporaryPath, @OutputPath, @Status, @TargetId, @DateCreated, @Progress, @AdditionalFiles, @MediaSource, @IsMarkedForRemoval, @JobItemIndex)"; _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@Id"); _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@ItemId"); _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@ItemName"); _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@MediaSourceId"); _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@JobId"); - _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@RequiresConversion"); + _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@TemporaryPath"); _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@OutputPath"); _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@Status"); _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@TargetId"); _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@DateCreated"); _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@Progress"); + _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@AdditionalFiles"); + _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@MediaSource"); + _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@IsMarkedForRemoval"); + _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@JobItemIndex"); } private const string BaseJobSelectText = "select Id, TargetId, Name, Quality, Status, Progress, UserId, ItemIds, Category, ParentId, UnwatchedOnly, ItemLimit, SyncNewContent, DateCreated, DateLastModified, ItemCount from SyncJobs"; - private const string BaseJobItemSelectText = "select Id, ItemId, ItemName, MediaSourceId, JobId, RequiresConversion, OutputPath, Status, TargetId, DateCreated, Progress from SyncJobItems"; + private const string BaseJobItemSelectText = "select Id, ItemId, ItemName, MediaSourceId, JobId, TemporaryPath, OutputPath, Status, TargetId, DateCreated, Progress, AdditionalFiles, MediaSource, IsMarkedForRemoval, JobItemIndex from SyncJobItems"; public SyncJob GetJob(string id) { @@ -450,7 +459,7 @@ namespace MediaBrowser.Server.Implementations.Sync return null; } - public QueryResult<SyncJobItem> GetJobItems(SyncJobItemQuery query) + private QueryResult<T> GetJobItemReader<T>(SyncJobItemQuery query, string baseSelectText, Func<IDataReader, T> itemFactory) { if (query == null) { @@ -459,7 +468,7 @@ namespace MediaBrowser.Server.Implementations.Sync using (var cmd = _connection.CreateCommand()) { - cmd.CommandText = BaseJobItemSelectText; + cmd.CommandText = baseSelectText; var whereClauses = new List<string>(); @@ -488,7 +497,7 @@ namespace MediaBrowser.Server.Implementations.Sync var startIndex = query.StartIndex ?? 0; if (startIndex > 0) { - whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM SyncJobItems ORDER BY DateCreated LIMIT {0})", + whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM SyncJobItems ORDER BY JobItemIndex, DateCreated LIMIT {0})", startIndex.ToString(_usCulture))); } @@ -497,7 +506,7 @@ namespace MediaBrowser.Server.Implementations.Sync cmd.CommandText += " where " + string.Join(" AND ", whereClauses.ToArray()); } - cmd.CommandText += " ORDER BY DateCreated"; + cmd.CommandText += " ORDER BY JobItemIndex, DateCreated"; if (query.Limit.HasValue) { @@ -506,14 +515,14 @@ namespace MediaBrowser.Server.Implementations.Sync cmd.CommandText += "; select count (Id) from SyncJobItems" + whereTextWithoutPaging; - var list = new List<SyncJobItem>(); + var list = new List<T>(); var count = 0; using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) { while (reader.Read()) { - list.Add(GetJobItem(reader)); + list.Add(itemFactory(reader)); } if (reader.NextResult() && reader.Read()) @@ -522,7 +531,7 @@ namespace MediaBrowser.Server.Implementations.Sync } } - return new QueryResult<SyncJobItem>() + return new QueryResult<T>() { Items = list.ToArray(), TotalRecordCount = count @@ -530,6 +539,16 @@ namespace MediaBrowser.Server.Implementations.Sync } } + public QueryResult<string> GetLibraryItemIds(SyncJobItemQuery query) + { + return GetJobItemReader(query, "select ItemId from SyncJobItems", GetItemId); + } + + public QueryResult<SyncJobItem> GetJobItems(SyncJobItemQuery query) + { + return GetJobItemReader(query, BaseJobItemSelectText, GetJobItem); + } + public Task Create(SyncJobItem jobItem) { return Update(jobItem); @@ -557,12 +576,16 @@ namespace MediaBrowser.Server.Implementations.Sync _saveJobItemCommand.GetParameter(index++).Value = jobItem.ItemName; _saveJobItemCommand.GetParameter(index++).Value = jobItem.MediaSourceId; _saveJobItemCommand.GetParameter(index++).Value = jobItem.JobId; - _saveJobItemCommand.GetParameter(index++).Value = jobItem.RequiresConversion; + _saveJobItemCommand.GetParameter(index++).Value = jobItem.TemporaryPath; _saveJobItemCommand.GetParameter(index++).Value = jobItem.OutputPath; _saveJobItemCommand.GetParameter(index++).Value = jobItem.Status.ToString(); _saveJobItemCommand.GetParameter(index++).Value = jobItem.TargetId; _saveJobItemCommand.GetParameter(index++).Value = jobItem.DateCreated; _saveJobItemCommand.GetParameter(index++).Value = jobItem.Progress; + _saveJobItemCommand.GetParameter(index++).Value = _json.SerializeToString(jobItem.AdditionalFiles); + _saveJobItemCommand.GetParameter(index++).Value = jobItem.MediaSource == null ? null : _json.SerializeToString(jobItem.MediaSource); + _saveJobItemCommand.GetParameter(index++).Value = jobItem.IsMarkedForRemoval; + _saveJobItemCommand.GetParameter(index++).Value = jobItem.JobItemIndex; _saveJobItemCommand.Transaction = transaction; @@ -620,8 +643,11 @@ namespace MediaBrowser.Server.Implementations.Sync } info.JobId = reader.GetString(4); - info.RequiresConversion = reader.GetBoolean(5); + if (!reader.IsDBNull(5)) + { + info.TemporaryPath = reader.GetString(5); + } if (!reader.IsDBNull(6)) { info.OutputPath = reader.GetString(6); @@ -634,16 +660,44 @@ namespace MediaBrowser.Server.Implementations.Sync info.TargetId = reader.GetString(8); - info.DateCreated = reader.GetDateTime(9); + info.DateCreated = reader.GetDateTime(9).ToUniversalTime(); if (!reader.IsDBNull(10)) { info.Progress = reader.GetDouble(10); } + if (!reader.IsDBNull(11)) + { + var json = reader.GetString(11); + + if (!string.IsNullOrWhiteSpace(json)) + { + info.AdditionalFiles = _json.DeserializeFromString<List<ItemFileInfo>>(json); + } + } + + if (!reader.IsDBNull(12)) + { + var json = reader.GetString(12); + + if (!string.IsNullOrWhiteSpace(json)) + { + info.MediaSource = _json.DeserializeFromString<MediaSourceInfo>(json); + } + } + + info.IsMarkedForRemoval = reader.GetBoolean(13); + info.JobItemIndex = reader.GetInt32(14); + return info; } + private string GetItemId(IDataReader reader) + { + return reader.GetString(0); + } + /// <summary> /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// </summary> diff --git a/MediaBrowser.Server.Implementations/Sync/SyncScheduledTask.cs b/MediaBrowser.Server.Implementations/Sync/SyncScheduledTask.cs index c2925551b..b68a97817 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncScheduledTask.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncScheduledTask.cs @@ -1,4 +1,6 @@ -using MediaBrowser.Common.ScheduledTasks; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.IO; +using MediaBrowser.Common.ScheduledTasks; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Sync; @@ -11,7 +13,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.Sync { - public class SyncScheduledTask : IScheduledTask, IConfigurableScheduledTask + public class SyncScheduledTask : IScheduledTask, IConfigurableScheduledTask, IHasKey { private readonly ILibraryManager _libraryManager; private readonly ISyncRepository _syncRepo; @@ -20,8 +22,11 @@ namespace MediaBrowser.Server.Implementations.Sync private readonly IUserManager _userManager; private readonly ITVSeriesManager _tvSeriesManager; private readonly IMediaEncoder _mediaEncoder; + private readonly ISubtitleEncoder _subtitleEncoder; + private readonly IConfigurationManager _config; + private readonly IFileSystem _fileSystem; - public SyncScheduledTask(ILibraryManager libraryManager, ISyncRepository syncRepo, ISyncManager syncManager, ILogger logger, IUserManager userManager, ITVSeriesManager tvSeriesManager, IMediaEncoder mediaEncoder) + public SyncScheduledTask(ILibraryManager libraryManager, ISyncRepository syncRepo, ISyncManager syncManager, ILogger logger, IUserManager userManager, ITVSeriesManager tvSeriesManager, IMediaEncoder mediaEncoder, ISubtitleEncoder subtitleEncoder, IConfigurationManager config, IFileSystem fileSystem) { _libraryManager = libraryManager; _syncRepo = syncRepo; @@ -30,11 +35,14 @@ namespace MediaBrowser.Server.Implementations.Sync _userManager = userManager; _tvSeriesManager = tvSeriesManager; _mediaEncoder = mediaEncoder; + _subtitleEncoder = subtitleEncoder; + _config = config; + _fileSystem = fileSystem; } public string Name { - get { return "Sync preparation"; } + get { return "Convert media"; } } public string Description @@ -46,14 +54,14 @@ namespace MediaBrowser.Server.Implementations.Sync { get { - return "Library"; + return "Sync"; } } public Task Execute(CancellationToken cancellationToken, IProgress<double> progress) { - return new SyncJobProcessor(_libraryManager, _syncRepo, _syncManager, _logger, _userManager, _tvSeriesManager, _mediaEncoder).Sync(progress, - cancellationToken); + return new SyncJobProcessor(_libraryManager, _syncRepo, _syncManager, _logger, _userManager, _tvSeriesManager, _mediaEncoder, _subtitleEncoder, _config, _fileSystem) + .Sync(progress, cancellationToken); } public IEnumerable<ITaskTrigger> GetDefaultTriggers() @@ -67,12 +75,17 @@ namespace MediaBrowser.Server.Implementations.Sync public bool IsHidden { - get { return true; } + get { return false; } } public bool IsEnabled { get { return true; } } + + public string Key + { + get { return "SyncPrepare"; } + } } } diff --git a/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs b/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs index 66e771aa3..6700e9054 100644 --- a/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs +++ b/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs @@ -36,8 +36,8 @@ namespace MediaBrowser.Server.Implementations.TV ? new string[] { } : new[] { request.ParentId }; - var items = GetAllLibraryItems(user, parentIds) - .OfType<Series>(); + var items = GetAllLibraryItems(user, parentIds, i => i is Series) + .Cast<Series>(); // Avoid implicitly captured closure var episodes = GetNextUpEpisodes(request, user, items); @@ -54,8 +54,9 @@ namespace MediaBrowser.Server.Implementations.TV throw new ArgumentException("User not found"); } - var items = parentsFolders.SelectMany(i => i.GetRecursiveChildren(user)) - .OfType<Series>(); + var items = parentsFolders + .SelectMany(i => i.GetRecursiveChildren(user, s => s is Series)) + .Cast<Series>(); // Avoid implicitly captured closure var episodes = GetNextUpEpisodes(request, user, items); @@ -63,7 +64,7 @@ namespace MediaBrowser.Server.Implementations.TV return GetResult(episodes, null, request); } - private IEnumerable<BaseItem> GetAllLibraryItems(User user, string[] parentIds) + private IEnumerable<BaseItem> GetAllLibraryItems(User user, string[] parentIds, Func<BaseItem,bool> filter) { if (parentIds.Length > 0) { @@ -71,7 +72,7 @@ namespace MediaBrowser.Server.Implementations.TV { var folder = (Folder)_libraryManager.GetItemById(new Guid(i)); - return folder.GetRecursiveChildren(user); + return folder.GetRecursiveChildren(user, filter); }); } @@ -81,7 +82,7 @@ namespace MediaBrowser.Server.Implementations.TV throw new ArgumentException("User not found"); } - return user.RootFolder.GetRecursiveChildren(user); + return user.RootFolder.GetRecursiveChildren(user, filter); } public IEnumerable<Episode> GetNextUpEpisodes(NextUpQuery request, User user, IEnumerable<Series> series) @@ -92,7 +93,8 @@ namespace MediaBrowser.Server.Implementations.TV return FilterSeries(request, series) .AsParallel() .Select(i => GetNextUp(i, currentUser)) - .Where(i => i.Item1 != null) + // Include if an episode was found, and either the series is not unwatched or the specific series was requested + .Where(i => i.Item1 != null && (!i.Item3 || !string.IsNullOrWhiteSpace(request.SeriesId))) .OrderByDescending(i => { var episode = i.Item1; @@ -122,10 +124,11 @@ namespace MediaBrowser.Server.Implementations.TV /// <param name="series">The series.</param> /// <param name="user">The user.</param> /// <returns>Task{Episode}.</returns> - private Tuple<Episode, DateTime> GetNextUp(Series series, User user) + private Tuple<Episode, DateTime, bool> GetNextUp(Series series, User user) { // Get them in display order, then reverse var allEpisodes = series.GetSeasons(user, true, true) + .Where(i => !i.IndexNumber.HasValue || i.IndexNumber.Value != 0) .SelectMany(i => i.GetEpisodes(user, true, true)) .Reverse() .ToList(); @@ -160,10 +163,13 @@ namespace MediaBrowser.Server.Implementations.TV if (lastWatched != null) { - return new Tuple<Episode, DateTime>(nextUp, lastWatchedDate); + return new Tuple<Episode, DateTime, bool>(nextUp, lastWatchedDate, false); } - return new Tuple<Episode, DateTime>(null, lastWatchedDate); + var firstEpisode = allEpisodes.LastOrDefault(i => i.LocationType != LocationType.Virtual && !i.IsPlayed(user)); + + // Return the first episode + return new Tuple<Episode, DateTime, bool>(firstEpisode, DateTime.MinValue, true); } private IEnumerable<Series> FilterSeries(NextUpQuery request, IEnumerable<Series> items) diff --git a/MediaBrowser.Server.Implementations/Themes/AppThemeManager.cs b/MediaBrowser.Server.Implementations/Themes/AppThemeManager.cs index 9845f3867..2711c08aa 100644 --- a/MediaBrowser.Server.Implementations/Themes/AppThemeManager.cs +++ b/MediaBrowser.Server.Implementations/Themes/AppThemeManager.cs @@ -33,7 +33,7 @@ namespace MediaBrowser.Server.Implementations.Themes { get { - return Path.Combine(_appPaths.ItemsByNamePath, "appthemes"); + return Path.Combine(_appPaths.ProgramDataPath, "appthemes"); } } diff --git a/MediaBrowser.Server.Implementations/Udp/UdpServer.cs b/MediaBrowser.Server.Implementations/Udp/UdpServer.cs index 91a4940ae..9dbffa922 100644 --- a/MediaBrowser.Server.Implementations/Udp/UdpServer.cs +++ b/MediaBrowser.Server.Implementations/Udp/UdpServer.cs @@ -83,9 +83,7 @@ namespace MediaBrowser.Server.Implementations.Udp private async void RespondToV1Message(string endpoint) { - var info = _appHost.GetSystemInfo(); - - var localAddress = info.LocalAddress; + var localAddress = _appHost.LocalApiUrl; if (!string.IsNullOrEmpty(localAddress)) { @@ -110,15 +108,15 @@ namespace MediaBrowser.Server.Implementations.Udp private async void RespondToV2Message(string endpoint) { - var info = _appHost.GetSystemInfo(); + var localUrl = _appHost.LocalApiUrl; - if (!string.IsNullOrEmpty(info.LocalAddress)) + if (!string.IsNullOrEmpty(localUrl)) { var response = new ServerDiscoveryInfo { - Address = info.LocalAddress, - Id = info.Id, - Name = info.ServerName + Address = localUrl, + Id = _appHost.SystemId, + Name = _appHost.FriendlyName }; await SendAsync(Encoding.UTF8.GetBytes(_json.SerializeToString(response)), endpoint); diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config index b23446eee..55023c565 100644 --- a/MediaBrowser.Server.Implementations/packages.config +++ b/MediaBrowser.Server.Implementations/packages.config @@ -1,6 +1,8 @@ <?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="MediaBrowser.Naming" version="1.0.0.29" targetFramework="net45" />
+ <package id="MediaBrowser.Naming" version="1.0.0.32" targetFramework="net45" />
<package id="Mono.Nat" version="1.2.21.0" targetFramework="net45" />
<package id="morelinq" version="1.1.0" targetFramework="net45" />
+ <package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
+ <package id="SocketHttpListener" version="1.0.0.1" targetFramework="net45" />
</packages>
\ No newline at end of file diff --git a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj index e780f447f..232caba4f 100644 --- a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj +++ b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj @@ -57,6 +57,11 @@ <SpecificVersion>False</SpecificVersion> <HintPath>..\packages\Mono.Posix.4.0.0.0\lib\net40\Mono.Posix.dll</HintPath> </Reference> + <Reference Include="Mono.Security, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\ThirdParty\Mono.Security\Mono.Security.dll</HintPath> + <Private>False</Private> + </Reference> <Reference Include="System" /> <Reference Include="ServiceStack.Interfaces"> <HintPath>..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll</HintPath> @@ -70,6 +75,7 @@ <Link>Properties\SharedVersion.cs</Link> </Compile> <Compile Include="Native\BaseMonoApp.cs" /> + <Compile Include="Networking\CertificateGenerator.cs" /> <Compile Include="Program.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Native\NativeApp.cs" /> diff --git a/MediaBrowser.Server.Mono/Networking/CertificateGenerator.cs b/MediaBrowser.Server.Mono/Networking/CertificateGenerator.cs new file mode 100644 index 000000000..6e37322cb --- /dev/null +++ b/MediaBrowser.Server.Mono/Networking/CertificateGenerator.cs @@ -0,0 +1,68 @@ +using MediaBrowser.Model.Logging; +using Mono.Security.X509; +using System; +using System.Collections; +using System.Security.Cryptography; + +namespace MediaBrowser.Server.Mono.Networking +{ + internal class CertificateGenerator + { + private const string MonoTestRootAgency = "<RSAKeyValue><Modulus>v/4nALBxCE+9JgEC0LnDUvKh6e96PwTpN4Rj+vWnqKT7IAp1iK/JjuqvAg6DQ2vTfv0dTlqffmHH51OyioprcT5nzxcSTsZb/9jcHScG0s3/FRIWnXeLk/fgm7mSYhjUaHNI0m1/NTTktipicjKxo71hGIg9qucCWnDum+Krh/k=</Modulus><Exponent>AQAB</Exponent><P>9jbKxMXEruW2CfZrzhxtull4O8P47+mNsEL+9gf9QsRO1jJ77C+jmzfU6zbzjf8+ViK+q62tCMdC1ZzulwdpXQ==</P><Q>x5+p198l1PkK0Ga2mRh0SIYSykENpY2aLXoyZD/iUpKYAvATm0/wvKNrE4dKJyPCA+y3hfTdgVag+SP9avvDTQ==</Q><DP>ISSjCvXsUfbOGG05eddN1gXxL2pj+jegQRfjpk7RAsnWKvNExzhqd5x+ZuNQyc6QH5wxun54inP4RTUI0P/IaQ==</DP><DQ>R815VQmR3RIbPqzDXzv5j6CSH6fYlcTiQRtkBsUnzhWmkd/y3XmamO+a8zJFjOCCx9CcjpVuGziivBqi65lVPQ==</DQ><InverseQ>iYiu0KwMWI/dyqN3RJYUzuuLj02/oTD1pYpwo2rvNCXU1Q5VscOeu2DpNg1gWqI+1RrRCsEoaTNzXB1xtKNlSw==</InverseQ><D>nIfh1LYF8fjRBgMdAH/zt9UKHWiaCnc+jXzq5tkR8HVSKTVdzitD8bl1JgAfFQD8VjSXiCJqluexy/B5SGrCXQ49c78NIQj0hD+J13Y8/E0fUbW1QYbhj6Ff7oHyhaYe1WOQfkp2t/h+llHOdt1HRf7bt7dUknYp7m8bQKGxoYE=</D></RSAKeyValue>"; + + internal static void CreateSelfSignCertificatePfx( + string fileName, + string hostname, + ILogger logger) + { + if (string.IsNullOrWhiteSpace(fileName)) + { + throw new ArgumentNullException("fileName"); + } + + byte[] sn = Guid.NewGuid().ToByteArray(); + string subject = string.Format("CN={0}", hostname); + string issuer = subject; + DateTime notBefore = DateTime.Now.AddDays(-2); + DateTime notAfter = DateTime.Now.AddYears(10); + + RSA issuerKey = RSA.Create(); + issuerKey.FromXmlString(MonoTestRootAgency); + RSA subjectKey = RSA.Create(); + + // serial number MUST be positive + if ((sn[0] & 0x80) == 0x80) + sn[0] -= 0x80; + + issuer = subject; + issuerKey = subjectKey; + + X509CertificateBuilder cb = new X509CertificateBuilder(3); + cb.SerialNumber = sn; + cb.IssuerName = issuer; + cb.NotBefore = notBefore; + cb.NotAfter = notAfter; + cb.SubjectName = subject; + cb.SubjectPublicKey = subjectKey; + + // signature + cb.Hash = "SHA256"; + byte[] rawcert = cb.Sign(issuerKey); + + PKCS12 p12 = new PKCS12(); + + + ArrayList list = new ArrayList(); + // we use a fixed array to avoid endianess issues + // (in case some tools requires the ID to be 1). + list.Add(new byte[4] { 1, 0, 0, 0 }); + Hashtable attributes = new Hashtable(1); + attributes.Add(PKCS9.localKeyId, list); + + p12.AddCertificate(new X509Certificate(rawcert), attributes); + + p12.AddPkcs8ShroudedKeyBag(subjectKey, attributes); + p12.SaveToFile(fileName); + } + } +} diff --git a/MediaBrowser.Server.Mono/Networking/NetworkManager.cs b/MediaBrowser.Server.Mono/Networking/NetworkManager.cs index 60c250115..e8c623fd1 100644 --- a/MediaBrowser.Server.Mono/Networking/NetworkManager.cs +++ b/MediaBrowser.Server.Mono/Networking/NetworkManager.cs @@ -24,16 +24,26 @@ namespace MediaBrowser.Server.Mono.Networking /// <returns>IEnumerable{NetworkShare}.</returns> public IEnumerable<NetworkShare> GetNetworkShares(string path) { - return new List<NetworkShare> (); + return new List<NetworkShare>(); } /// <summary> /// Gets available devices within the domain /// </summary> /// <returns>PC's in the Domain</returns> - public IEnumerable<FileSystemEntryInfo> GetNetworkDevices() + public IEnumerable<FileSystemEntryInfo> GetNetworkDevices() { - return new List<FileSystemEntryInfo> (); + return new List<FileSystemEntryInfo>(); + } + + /// <summary> + /// Generates a self signed certificate at the locatation specified by <paramref name="certificatePath"/>. + /// </summary> + /// <param name="certificatePath">The path to generate the certificate.</param> + /// <param name="hostname">The common name for the certificate.</param> + public void GenerateSelfSignedSslCertificate(string certificatePath, string hostname) + { + CertificateGenerator.CreateSelfSignCertificatePfx(certificatePath, hostname, Logger); } } } diff --git a/MediaBrowser.Server.Mono/Program.cs b/MediaBrowser.Server.Mono/Program.cs index 1cd0b5ae6..10a6c6fb9 100644 --- a/MediaBrowser.Server.Mono/Program.cs +++ b/MediaBrowser.Server.Mono/Program.cs @@ -78,7 +78,7 @@ namespace MediaBrowser.Server.Mono var nativeApp = new NativeApp(); - _appHost = new ApplicationHost(appPaths, logManager, options, fileSystem, "MBServer.Mono", false, nativeApp); + _appHost = new ApplicationHost(appPaths, logManager, options, fileSystem, "MBServer.Mono", nativeApp); if (options.ContainsOption("-v")) { Console.WriteLine (_appHost.ApplicationVersion.ToString()); diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index fa068a7de..1ded0c254 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -2,6 +2,7 @@ using MediaBrowser.Common; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Events; +using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Implementations; using MediaBrowser.Common.Implementations.ScheduledTasks; using MediaBrowser.Common.IO; @@ -43,6 +44,7 @@ using MediaBrowser.Dlna; using MediaBrowser.Dlna.ConnectionManager; using MediaBrowser.Dlna.ContentDirectory; using MediaBrowser.Dlna.Main; +using MediaBrowser.Dlna.MediaReceiverRegistrar; using MediaBrowser.LocalMetadata.Providers; using MediaBrowser.MediaEncoding.BdInfo; using MediaBrowser.MediaEncoding.Encoder; @@ -111,33 +113,6 @@ namespace MediaBrowser.Server.Startup.Common } /// <summary> - /// Gets the name of the web application that can be used for url building. - /// All api urls will be of the form {protocol}://{host}:{port}/{appname}/... - /// </summary> - /// <value>The name of the web application.</value> - public string WebApplicationName - { - get { return "mediabrowser"; } - } - - /// <summary> - /// Gets the HTTP server URL prefix. - /// </summary> - /// <value>The HTTP server URL prefix.</value> - private IEnumerable<string> HttpServerUrlPrefixes - { - get - { - var list = new List<string> - { - "http://+:" + ServerConfigurationManager.Configuration.HttpServerPortNumber + "/" + WebApplicationName + "/" - }; - - return list; - } - } - - /// <summary> /// Gets the configuration manager. /// </summary> /// <returns>IConfigurationManager.</returns> @@ -225,8 +200,6 @@ namespace MediaBrowser.Server.Startup.Common private readonly StartupOptions _startupOptions; private readonly string _remotePackageName; - private bool _supportsNativeWebSocket; - internal INativeApp NativeApp { get; set; } /// <summary> @@ -237,20 +210,17 @@ namespace MediaBrowser.Server.Startup.Common /// <param name="options">The options.</param> /// <param name="fileSystem">The file system.</param> /// <param name="remotePackageName">Name of the remote package.</param> - /// <param name="supportsNativeWebSocket">if set to <c>true</c> [supports native web socket].</param> /// <param name="nativeApp">The native application.</param> public ApplicationHost(ServerApplicationPaths applicationPaths, ILogManager logManager, StartupOptions options, IFileSystem fileSystem, string remotePackageName, - bool supportsNativeWebSocket, INativeApp nativeApp) : base(applicationPaths, logManager, fileSystem) { _startupOptions = options; _remotePackageName = remotePackageName; - _supportsNativeWebSocket = supportsNativeWebSocket; NativeApp = nativeApp; SetBaseExceptionMessage(); @@ -354,6 +324,9 @@ namespace MediaBrowser.Server.Startup.Common public override async Task Init(IProgress<double> progress) { + HttpPort = ServerConfigurationManager.Configuration.HttpServerPortNumber; + HttpsPort = ServerConfigurationManager.Configuration.HttpsPortNumber; + PerformPreInitMigrations(); await base.Init(progress).ConfigureAwait(false); @@ -365,11 +338,11 @@ namespace MediaBrowser.Server.Startup.Common { var migrations = new List<IVersionMigration> { - new MigrateUserFolders(ApplicationPaths), + new MigrateUserFolders(ApplicationPaths, FileSystemManager), new RenameXbmcOptions(ServerConfigurationManager), new RenameXmlOptions(ServerConfigurationManager), - new DeprecatePlugins(ApplicationPaths), - new DeleteDlnaProfiles(ApplicationPaths) + new DeprecatePlugins(ApplicationPaths, FileSystemManager), + new DeleteDlnaProfiles(ApplicationPaths, FileSystemManager) }; foreach (var task in migrations) @@ -435,7 +408,7 @@ namespace MediaBrowser.Server.Startup.Common SyncRepository = await GetSyncRepository().ConfigureAwait(false); RegisterSingleInstance(SyncRepository); - UserManager = new UserManager(LogManager.GetLogger("UserManager"), ServerConfigurationManager, UserRepository, XmlSerializer, NetworkManager, () => ImageProcessor, () => DtoService, () => ConnectManager, this, JsonSerializer); + UserManager = new UserManager(LogManager.GetLogger("UserManager"), ServerConfigurationManager, UserRepository, XmlSerializer, NetworkManager, () => ImageProcessor, () => DtoService, () => ConnectManager, this, JsonSerializer, FileSystemManager); RegisterSingleInstance(UserManager); LibraryManager = new LibraryManager(Logger, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, () => LibraryMonitor, FileSystemManager, () => ProviderManager); @@ -447,7 +420,7 @@ namespace MediaBrowser.Server.Startup.Common LibraryMonitor = new LibraryMonitor(LogManager, TaskManager, LibraryManager, ServerConfigurationManager, FileSystemManager); RegisterSingleInstance(LibraryMonitor); - ProviderManager = new ProviderManager(HttpClient, ServerConfigurationManager, LibraryMonitor, LogManager, FileSystemManager); + ProviderManager = new ProviderManager(HttpClient, ServerConfigurationManager, LibraryMonitor, LogManager, FileSystemManager, ApplicationPaths); RegisterSingleInstance(ProviderManager); SeriesOrderManager = new SeriesOrderManager(); @@ -455,19 +428,7 @@ namespace MediaBrowser.Server.Startup.Common RegisterSingleInstance<ISearchEngine>(() => new SearchEngine(LogManager, LibraryManager, UserManager)); - if (IsFirstRun) - { - ServerConfigurationManager.Configuration.EnableWin8HttpListener = false; - ServerConfigurationManager.SaveConfiguration(); - _supportsNativeWebSocket = false; - } - - if (!ServerConfigurationManager.Configuration.EnableWin8HttpListener) - { - _supportsNativeWebSocket = false; - } - - HttpServer = ServerFactory.CreateServer(this, LogManager, "Media Browser", WebApplicationName, "dashboard/index.html", _supportsNativeWebSocket); + HttpServer = ServerFactory.CreateServer(this, LogManager, "Media Browser", "web/index.html"); RegisterSingleInstance(HttpServer, false); progress.Report(10); @@ -483,10 +444,10 @@ namespace MediaBrowser.Server.Startup.Common TVSeriesManager = new TVSeriesManager(UserManager, UserDataManager, LibraryManager); RegisterSingleInstance(TVSeriesManager); - SyncManager = new SyncManager(LibraryManager, SyncRepository, ImageProcessor, LogManager.GetLogger("SyncManager"), UserManager, () => DtoService, this, TVSeriesManager, () => MediaEncoder); + SyncManager = new SyncManager(LibraryManager, SyncRepository, ImageProcessor, LogManager.GetLogger("SyncManager"), UserManager, () => DtoService, this, TVSeriesManager, () => MediaEncoder, FileSystemManager, () => SubtitleEncoder, ServerConfigurationManager); RegisterSingleInstance(SyncManager); - DtoService = new DtoService(Logger, LibraryManager, UserDataManager, ItemRepository, ImageProcessor, ServerConfigurationManager, FileSystemManager, ProviderManager, () => ChannelManager, SyncManager, this); + DtoService = new DtoService(Logger, LibraryManager, UserDataManager, ItemRepository, ImageProcessor, ServerConfigurationManager, FileSystemManager, ProviderManager, () => ChannelManager, SyncManager, this, () => DeviceManager); RegisterSingleInstance(DtoService); var encryptionManager = new EncryptionManager(); @@ -495,7 +456,7 @@ namespace MediaBrowser.Server.Startup.Common ConnectManager = new ConnectManager(LogManager.GetLogger("Connect"), ApplicationPaths, JsonSerializer, encryptionManager, HttpClient, this, ServerConfigurationManager, UserManager, ProviderManager); RegisterSingleInstance(ConnectManager); - DeviceManager = new DeviceManager(new DeviceRepository(ApplicationPaths, JsonSerializer, Logger), UserManager, FileSystemManager, LibraryMonitor, ConfigurationManager, LogManager.GetLogger("DeviceManager")); + DeviceManager = new DeviceManager(new DeviceRepository(ApplicationPaths, JsonSerializer, Logger, FileSystemManager), UserManager, FileSystemManager, LibraryMonitor, ConfigurationManager, LogManager.GetLogger("DeviceManager")); RegisterSingleInstance(DeviceManager); SessionManager = new SessionManager(UserDataManager, Logger, UserRepository, LibraryManager, UserManager, musicManager, DtoService, ImageProcessor, ItemRepository, JsonSerializer, this, HttpClient, AuthenticationRepository, DeviceManager); @@ -530,12 +491,15 @@ namespace MediaBrowser.Server.Startup.Common LiveTvManager = new LiveTvManager(this, ServerConfigurationManager, FileSystemManager, Logger, ItemRepository, ImageProcessor, UserDataManager, DtoService, UserManager, LibraryManager, TaskManager, LocalizationManager, JsonSerializer); RegisterSingleInstance(LiveTvManager); - UserViewManager = new UserViewManager(LibraryManager, LocalizationManager, FileSystemManager, UserManager, ChannelManager, LiveTvManager, ApplicationPaths, playlistManager); + UserViewManager = new UserViewManager(LibraryManager, LocalizationManager, UserManager, ChannelManager, LiveTvManager, playlistManager, CollectionManager, ServerConfigurationManager); RegisterSingleInstance(UserViewManager); var contentDirectory = new ContentDirectory(dlnaManager, UserDataManager, ImageProcessor, LibraryManager, ServerConfigurationManager, UserManager, LogManager.GetLogger("UpnpContentDirectory"), HttpClient, LocalizationManager, ChannelManager); RegisterSingleInstance<IContentDirectory>(contentDirectory); + var mediaRegistrar = new MediaReceiverRegistrar(LogManager.GetLogger("MediaReceiverRegistrar"), HttpClient, ServerConfigurationManager); + RegisterSingleInstance<IMediaReceiverRegistrar>(mediaRegistrar); + NotificationManager = new NotificationManager(LogManager, UserManager, ServerConfigurationManager); RegisterSingleInstance(NotificationManager); @@ -572,9 +536,9 @@ namespace MediaBrowser.Server.Startup.Common SetStaticProperties(); - await ((UserManager)UserManager).Initialize().ConfigureAwait(false); - SetKernelProperties(); + + await ((UserManager)UserManager).Initialize().ConfigureAwait(false); } protected override INetworkManager CreateNetworkManager(ILogger logger) @@ -593,10 +557,10 @@ namespace MediaBrowser.Server.Startup.Common new FFmpegValidator(Logger, ApplicationPaths).Validate(info); - MediaEncoder = new MediaEncoder(LogManager.GetLogger("MediaEncoder"), - JsonSerializer, - info.EncoderPath, - info.ProbePath, + MediaEncoder = new MediaEncoder(LogManager.GetLogger("MediaEncoder"), + JsonSerializer, + info.EncoderPath, + info.ProbePath, info.Version, ServerConfigurationManager, FileSystemManager, @@ -663,7 +627,7 @@ namespace MediaBrowser.Server.Startup.Common private async Task<ISyncRepository> GetSyncRepository() { - var repo = new SyncRepository(LogManager.GetLogger("SyncRepository"), ServerConfigurationManager.ApplicationPaths); + var repo = new SyncRepository(LogManager.GetLogger("SyncRepository"), ServerConfigurationManager.ApplicationPaths, JsonSerializer); await repo.Initialize().ConfigureAwait(false); @@ -750,16 +714,11 @@ namespace MediaBrowser.Server.Startup.Common /// </summary> protected override void FindParts() { - // TODO: Remove after next release - if (!IsFirstRun && !ServerConfigurationManager.Configuration.IsPortAuthorized) - { - ServerConfigurationManager.Configuration.IsPortAuthorized = true; - ConfigurationManager.SaveConfiguration(); - } - if (!ServerConfigurationManager.Configuration.IsPortAuthorized) { RegisterServerWithAdministratorAccess(); + ServerConfigurationManager.Configuration.IsPortAuthorized = true; + ConfigurationManager.SaveConfiguration(); } base.FindParts(); @@ -803,14 +762,33 @@ namespace MediaBrowser.Server.Startup.Common SyncManager.AddParts(GetExports<ISyncProvider>()); } + private string CertificatePath { get; set; } + + private IEnumerable<string> GetUrlPrefixes() + { + var prefixes = new List<string> + { + "http://+:" + ServerConfigurationManager.Configuration.HttpServerPortNumber + "/" + }; + + if (!string.IsNullOrWhiteSpace(CertificatePath)) + { + prefixes.Add("https://+:" + ServerConfigurationManager.Configuration.HttpsPortNumber + "/"); + } + + return prefixes; + } + /// <summary> /// Starts the server. /// </summary> private void StartServer() { + CertificatePath = GetCertificatePath(true); + try { - ServerManager.Start(HttpServerUrlPrefixes); + ServerManager.Start(GetUrlPrefixes(), CertificatePath); } catch (Exception ex) { @@ -820,6 +798,39 @@ namespace MediaBrowser.Server.Startup.Common } } + private string GetCertificatePath(bool generateCertificate) + { + if (!string.IsNullOrWhiteSpace(ServerConfigurationManager.Configuration.CertificatePath)) + { + // Custom cert + return ServerConfigurationManager.Configuration.CertificatePath; + } + + // Generate self-signed cert + var certHost = GetHostnameFromExternalDns(ServerConfigurationManager.Configuration.WanDdns); + var certPath = Path.Combine(ServerConfigurationManager.ApplicationPaths.ProgramDataPath, "ssl", "cert_" + certHost.GetMD5().ToString("N") + ".pfx"); + + if (generateCertificate) + { + if (!File.Exists(certPath)) + { + Directory.CreateDirectory(Path.GetDirectoryName(certPath)); + + try + { + NetworkManager.GenerateSelfSignedSslCertificate(certPath, certHost); + } + catch (Exception ex) + { + Logger.ErrorException("Error creating ssl cert", ex); + return null; + } + } + } + + return certPath; + } + /// <summary> /// Called when [configuration updated]. /// </summary> @@ -829,11 +840,34 @@ namespace MediaBrowser.Server.Startup.Common { base.OnConfigurationUpdated(sender, e); - if (!HttpServer.UrlPrefixes.SequenceEqual(HttpServerUrlPrefixes, StringComparer.OrdinalIgnoreCase)) + var requiresRestart = false; + + // Don't do anything if these haven't been set yet + if (HttpPort != 0 && HttpsPort != 0) + { + // Need to restart if ports have changed + if (ServerConfigurationManager.Configuration.HttpServerPortNumber != HttpPort || + ServerConfigurationManager.Configuration.HttpsPortNumber != HttpsPort) + { + ServerConfigurationManager.Configuration.IsPortAuthorized = false; + ServerConfigurationManager.SaveConfiguration(); + + requiresRestart = true; + } + } + + if (!HttpServer.UrlPrefixes.SequenceEqual(GetUrlPrefixes(), StringComparer.OrdinalIgnoreCase)) { - ServerConfigurationManager.Configuration.IsPortAuthorized = false; - ServerConfigurationManager.SaveConfiguration(); + requiresRestart = true; + } + if (!string.Equals(CertificatePath, GetCertificatePath(false), StringComparison.OrdinalIgnoreCase)) + { + requiresRestart = true; + } + + if (requiresRestart) + { NotifyPendingRestart(); } } @@ -965,8 +999,7 @@ namespace MediaBrowser.Server.Startup.Common HasPendingRestart = HasPendingRestart, Version = ApplicationVersion.ToString(), IsNetworkDeployed = CanSelfUpdate, - WebSocketPortNumber = HttpServerPort, - SupportsNativeWebSocket = true, + WebSocketPortNumber = HttpPort, FailedPluginAssemblies = FailedAssemblies.ToList(), InProgressInstallations = InstallationManager.CurrentInstallations.Select(i => i.Item1).ToList(), CompletedInstallations = InstallationManager.CompletedInstallations.ToList(), @@ -977,7 +1010,9 @@ namespace MediaBrowser.Server.Startup.Common InternalMetadataPath = ApplicationPaths.InternalMetadataPath, CachePath = ApplicationPaths.CachePath, MacAddress = GetMacAddress(), - HttpServerPortNumber = HttpServerPort, + HttpServerPortNumber = HttpPort, + SupportsHttps = SupportsHttps, + HttpsPortNumber = HttpsPort, OperatingSystem = OperatingSystemDisplayName, CanSelfRestart = CanSelfRestart, CanSelfUpdate = CanSelfUpdate, @@ -988,30 +1023,50 @@ namespace MediaBrowser.Server.Startup.Common IsRunningAsService = IsRunningAsService, SupportsRunningAsService = SupportsRunningAsService, ServerName = FriendlyName, - LocalAddress = GetLocalIpAddress() + LocalAddress = LocalApiUrl }; } - /// <summary> - /// Gets the local ip address. - /// </summary> - /// <returns>System.String.</returns> - private string GetLocalIpAddress() + public bool EnableHttps { - // Return the first matched address, if found, or the first known local address - var address = HttpServerIpAddresses.FirstOrDefault(); + get + { + return SupportsHttps && ServerConfigurationManager.Configuration.EnableHttps; + } + } + + public bool SupportsHttps + { + get { return !string.IsNullOrWhiteSpace(HttpServer.CertificatePath); } + } - if (!string.IsNullOrWhiteSpace(address)) + public string LocalApiUrl + { + get { - address = string.Format("http://{0}:{1}", - address, - ServerConfigurationManager.Configuration.HttpServerPortNumber.ToString(CultureInfo.InvariantCulture)); + // Return the first matched address, if found, or the first known local address + var address = LocalIpAddress; + + if (!string.IsNullOrWhiteSpace(address)) + { + address = string.Format("http://{0}:{1}", + address, + HttpPort.ToString(CultureInfo.InvariantCulture)); + } + + return address; } + } - return address; + public string LocalIpAddress + { + get + { + return HttpServerIpAddresses.FirstOrDefault(); + } } - public IEnumerable<string> HttpServerIpAddresses + private IEnumerable<string> HttpServerIpAddresses { get { @@ -1047,10 +1102,9 @@ namespace MediaBrowser.Server.Startup.Common } } - public int HttpServerPort - { - get { return ServerConfigurationManager.Configuration.HttpServerPortNumber; } - } + public int HttpPort { get; private set; } + + public int HttpsPort { get; private set; } /// <summary> /// Gets the mac address. @@ -1183,5 +1237,28 @@ namespace MediaBrowser.Server.Startup.Common NativeApp.ConfigureAutoRun(autorun); } } + + /// <summary> + /// This returns localhost in the case of no external dns, and the hostname if the + /// dns is prefixed with a valid Uri prefix. + /// </summary> + /// <param name="externalDns">The external dns prefix to get the hostname of.</param> + /// <returns>The hostname in <paramref name="externalDns"/></returns> + private static string GetHostnameFromExternalDns(string externalDns) + { + if (string.IsNullOrWhiteSpace(externalDns)) + { + return "localhost"; + } + + try + { + return new Uri(externalDns).Host; + } + catch (Exception e) + { + return externalDns; + } + } } } diff --git a/MediaBrowser.Server.Startup.Common/Browser/BrowserLauncher.cs b/MediaBrowser.Server.Startup.Common/Browser/BrowserLauncher.cs index 97f6b89d7..617ff4cae 100644 --- a/MediaBrowser.Server.Startup.Common/Browser/BrowserLauncher.cs +++ b/MediaBrowser.Server.Startup.Common/Browser/BrowserLauncher.cs @@ -18,8 +18,7 @@ namespace MediaBrowser.Server.Startup.Common.Browser /// <param name="logger">The logger.</param> public static void OpenDashboardPage(string page, IServerApplicationHost appHost, ILogger logger) { - var url = "http://localhost:" + appHost.HttpServerPort + "/" + - appHost.WebApplicationName + "/web/" + page; + var url = "http://localhost:" + appHost.HttpPort + "/web/" + page; OpenUrl(url, logger); } @@ -69,8 +68,7 @@ namespace MediaBrowser.Server.Startup.Common.Browser /// <param name="logger">The logger.</param> public static void OpenSwagger(IServerApplicationHost appHost, ILogger logger) { - OpenUrl("http://localhost:" + appHost.HttpServerPort + "/" + - appHost.WebApplicationName + "/swagger-ui/index.html", logger); + OpenUrl("http://localhost:" + appHost.HttpPort + "/swagger-ui/index.html", logger); } /// <summary> diff --git a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs index e4a9e8434..65e5be7a7 100644 --- a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs +++ b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs @@ -37,10 +37,10 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg switch (environment.SystemArchitecture) { case Architecture.X86_X64: - info.Version = "20140716"; + info.Version = "20150124"; break; case Architecture.X86: - info.Version = "20140923"; + info.Version = "20150124"; break; } break; @@ -51,10 +51,10 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg switch (environment.SystemArchitecture) { case Architecture.X86_X64: - info.Version = "20140923"; + info.Version = "20150110"; break; case Architecture.X86: - info.Version = "20140716"; + info.Version = "20150110"; break; } break; @@ -63,7 +63,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg info.FFMpegFilename = "ffmpeg.exe"; info.FFProbeFilename = "ffprobe.exe"; - info.Version = "20141111"; + info.Version = "20150110"; info.ArchiveType = "7z"; switch (environment.SystemArchitecture) @@ -92,14 +92,14 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg case Architecture.X86_X64: return new[] { - "http://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-20141111-git-48efe9e-win64-static.7z", - "https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/windows/ffmpeg-20141111-git-48efe9e-win64-static.7z" + "http://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-20150110-git-4df01d5-win64-static.7z", + "https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/windows/ffmpeg-20150110-git-4df01d5-win64-static.7z" }; case Architecture.X86: return new[] { - "http://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-20141111-git-48efe9e-win32-static.7z", - "https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/windows/ffmpeg-20141111-git-48efe9e-win32-static.7z" + "http://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-20150110-git-4df01d5-win32-static.7z", + "https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/windows/ffmpeg-20150110-git-4df01d5-win32-static.7z" }; } break; @@ -111,12 +111,12 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg case Architecture.X86_X64: return new[] { - "https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/osx/ffmpeg-x64-2.4.1.7z" + "https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/osx/ffmpeg-x64-2.5.3.7z" }; case Architecture.X86: return new[] { - "https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/osx/ffmpeg-x86-2.4.2.7z" + "https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/osx/ffmpeg-x86-2.5.3.7z" }; } break; @@ -128,14 +128,14 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg case Architecture.X86_X64: return new[] { - "http://ffmpeg.gusari.org/static/64bit/ffmpeg.static.64bit.latest.tar.gz", - "https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/linux/ffmpeg.static.64bit.2014-07-16.tar.gz" + "http://johnvansickle.com/ffmpeg/releases/ffmpeg-release-64bit-static.tar.xz", + "https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/linux/ffmpeg-release-64bit-static.tar.xz" }; case Architecture.X86: return new[] { - "http://ffmpeg.gusari.org/static/32bit/ffmpeg.static.32bit.latest.tar.gz", - "https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/linux/ffmpeg.static.32bit.2014-07-16.tar.gz" + "http://johnvansickle.com/ffmpeg/releases/ffmpeg-release-32bit-static.tar.xz", + "https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/linux/ffmpeg-release-32bit-static.tar.xz" }; } break; diff --git a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs index 229fee18d..406863b84 100644 --- a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs +++ b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs @@ -129,7 +129,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg { try { - Directory.Delete(path, true); + _fileSystem.DeleteDirectory(path, true); } catch (Exception ex) { @@ -228,9 +228,9 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg string.Equals(filename, downloadinfo.FFMpegFilename, StringComparison.OrdinalIgnoreCase); })) { - File.Copy(file, Path.Combine(targetFolder, Path.GetFileName(file)), true); - - SetFilePermissions(targetFolder, file); + var targetFile = Path.Combine(targetFolder, Path.GetFileName(file)); + File.Copy(file, targetFile, true); + SetFilePermissions(targetFile); } } finally @@ -239,12 +239,12 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg } } - private void SetFilePermissions(string targetFolder, string file) + private void SetFilePermissions(string path) { // Linux: File permission to 666, and user's execute bit if (_environment.OperatingSystem == OperatingSystem.Bsd || _environment.OperatingSystem == OperatingSystem.Linux || _environment.OperatingSystem == OperatingSystem.Osx) { - Syscall.chmod(Path.Combine(targetFolder, Path.GetFileName(file)), FilePermissions.DEFFILEMODE | FilePermissions.S_IXUSR); + Syscall.chmod(path, FilePermissions.DEFFILEMODE | FilePermissions.S_IRWXU | FilePermissions.S_IXGRP | FilePermissions.S_IXOTH); } } @@ -272,7 +272,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg { try { - File.Delete(path); + _fileSystem.DeleteFile(path); } catch (IOException ex) { @@ -380,10 +380,10 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg } Extract7zArchive(tempFile, fontsDirectory); - + try { - File.Delete(tempFile); + _fileSystem.DeleteFile(tempFile); } catch (IOException ex) { diff --git a/MediaBrowser.Server.Startup.Common/Migrations/DeleteDlnaProfiles.cs b/MediaBrowser.Server.Startup.Common/Migrations/DeleteDlnaProfiles.cs index 8fe841ffc..166c2627f 100644 --- a/MediaBrowser.Server.Startup.Common/Migrations/DeleteDlnaProfiles.cs +++ b/MediaBrowser.Server.Startup.Common/Migrations/DeleteDlnaProfiles.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Controller; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller; using System.IO; namespace MediaBrowser.Server.Startup.Common.Migrations @@ -6,10 +7,12 @@ namespace MediaBrowser.Server.Startup.Common.Migrations public class DeleteDlnaProfiles : IVersionMigration { private readonly IServerApplicationPaths _appPaths; + private readonly IFileSystem _fileSystem; - public DeleteDlnaProfiles(IServerApplicationPaths appPaths) + public DeleteDlnaProfiles(IServerApplicationPaths appPaths, IFileSystem fileSystem) { _appPaths = appPaths; + _fileSystem = fileSystem; } public void Run() @@ -23,7 +26,7 @@ namespace MediaBrowser.Server.Startup.Common.Migrations { try { - File.Delete(Path.Combine(_appPaths.ConfigurationDirectoryPath, "dlna", "system", filename + ".xml")); + _fileSystem.DeleteFile(Path.Combine(_appPaths.ConfigurationDirectoryPath, "dlna", "system", filename + ".xml")); } catch { @@ -31,7 +34,7 @@ namespace MediaBrowser.Server.Startup.Common.Migrations } try { - File.Delete(Path.Combine(_appPaths.ConfigurationDirectoryPath, "dlna", "user", filename + ".xml")); + _fileSystem.DeleteFile(Path.Combine(_appPaths.ConfigurationDirectoryPath, "dlna", "user", filename + ".xml")); } catch { diff --git a/MediaBrowser.Server.Startup.Common/Migrations/DeprecatePlugins.cs b/MediaBrowser.Server.Startup.Common/Migrations/DeprecatePlugins.cs index ce4665b26..afdd4e623 100644 --- a/MediaBrowser.Server.Startup.Common/Migrations/DeprecatePlugins.cs +++ b/MediaBrowser.Server.Startup.Common/Migrations/DeprecatePlugins.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Controller; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller; using System.IO; namespace MediaBrowser.Server.Startup.Common.Migrations @@ -6,10 +7,12 @@ namespace MediaBrowser.Server.Startup.Common.Migrations public class DeprecatePlugins : IVersionMigration { private readonly IServerApplicationPaths _appPaths; + private readonly IFileSystem _fileSystem; - public DeprecatePlugins(IServerApplicationPaths appPaths) + public DeprecatePlugins(IServerApplicationPaths appPaths, IFileSystem fileSystem) { _appPaths = appPaths; + _fileSystem = fileSystem; } public void Run() @@ -21,7 +24,7 @@ namespace MediaBrowser.Server.Startup.Common.Migrations { try { - File.Delete(Path.Combine(_appPaths.PluginsPath, filename)); + _fileSystem.DeleteFile(Path.Combine(_appPaths.PluginsPath, filename)); } catch { diff --git a/MediaBrowser.Server.Startup.Common/Migrations/MigrateUserFolders.cs b/MediaBrowser.Server.Startup.Common/Migrations/MigrateUserFolders.cs index 5e3df5701..cb566d6cf 100644 --- a/MediaBrowser.Server.Startup.Common/Migrations/MigrateUserFolders.cs +++ b/MediaBrowser.Server.Startup.Common/Migrations/MigrateUserFolders.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Controller; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller; using System; using System.IO; using System.Linq; @@ -8,10 +9,12 @@ namespace MediaBrowser.Server.Startup.Common.Migrations public class MigrateUserFolders : IVersionMigration { private readonly IServerApplicationPaths _appPaths; + private readonly IFileSystem _fileSystem; - public MigrateUserFolders(IServerApplicationPaths appPaths) + public MigrateUserFolders(IServerApplicationPaths appPaths, IFileSystem fileSystem) { _appPaths = appPaths; + _fileSystem = fileSystem; } public void Run() @@ -25,7 +28,7 @@ namespace MediaBrowser.Server.Startup.Common.Migrations foreach (var folder in folders) { - Directory.Delete(folder.FullName, true); + _fileSystem.DeleteDirectory(folder.FullName, true); } } catch (IOException) diff --git a/MediaBrowser.ServerApplication/BackgroundServiceInstaller.cs b/MediaBrowser.ServerApplication/BackgroundServiceInstaller.cs index 27ddfeb95..15cab6c19 100644 --- a/MediaBrowser.ServerApplication/BackgroundServiceInstaller.cs +++ b/MediaBrowser.ServerApplication/BackgroundServiceInstaller.cs @@ -25,7 +25,7 @@ namespace MediaBrowser.ServerApplication Description = "The windows background service for Media Browser Server.", // Will ensure the network is available - ServicesDependedOn = new[] { "LanmanServer" } + ServicesDependedOn = new[] { "LanmanServer", "Tcpip" } }; // Microsoft didn't add the ability to add a diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs index adc8eecb1..6e8774eea 100644 --- a/MediaBrowser.ServerApplication/MainStartup.cs +++ b/MediaBrowser.ServerApplication/MainStartup.cs @@ -203,7 +203,7 @@ namespace MediaBrowser.ServerApplication { var fileSystem = new NativeFileSystem(logManager.GetLogger("FileSystem"), false); - var nativeApp = new WindowsApp + var nativeApp = new WindowsApp(fileSystem) { IsRunningAsService = runService }; @@ -213,7 +213,6 @@ namespace MediaBrowser.ServerApplication options, fileSystem, "MBServer", - true, nativeApp); var initProgress = new Progress<double>(); diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index af96dc265..8df2d3ab0 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -63,10 +63,6 @@ <Reference Include="MediaBrowser.IsoMounter"> <HintPath>..\packages\MediaBrowser.IsoMounting.3.0.69\lib\net45\MediaBrowser.IsoMounter.dll</HintPath> </Reference> - <Reference Include="NLog, Version=3.1.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL"> - <SpecificVersion>False</SpecificVersion> - <HintPath>..\packages\NLog.3.1.0.0\lib\net45\NLog.dll</HintPath> - </Reference> <Reference Include="pfmclrapi"> <HintPath>..\packages\MediaBrowser.IsoMounting.3.0.69\lib\net45\pfmclrapi.dll</HintPath> </Reference> @@ -113,6 +109,7 @@ <Compile Include="Native\Standby.cs" /> <Compile Include="Native\ServerAuthorization.cs" /> <Compile Include="Native\WindowsApp.cs" /> + <Compile Include="Networking\CertificateGenerator.cs" /> <Compile Include="Networking\NativeMethods.cs" /> <Compile Include="Networking\NetworkManager.cs" /> <Compile Include="Networking\NetworkShares.cs" /> diff --git a/MediaBrowser.ServerApplication/Native/Autorun.cs b/MediaBrowser.ServerApplication/Native/Autorun.cs index 0262f711e..593bb7955 100644 --- a/MediaBrowser.ServerApplication/Native/Autorun.cs +++ b/MediaBrowser.ServerApplication/Native/Autorun.cs @@ -1,4 +1,5 @@ -using System; +using MediaBrowser.Common.IO; +using System; using System.IO; namespace MediaBrowser.ServerApplication.Native @@ -12,7 +13,8 @@ namespace MediaBrowser.ServerApplication.Native /// Configures the specified autorun. /// </summary> /// <param name="autorun">if set to <c>true</c> [autorun].</param> - public static void Configure(bool autorun) + /// <param name="fileSystem">The file system.</param> + public static void Configure(bool autorun, IFileSystem fileSystem) { var shortcutPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.StartMenu), "Media Browser 3", "Media Browser Server.lnk"); @@ -26,7 +28,7 @@ namespace MediaBrowser.ServerApplication.Native else { //Remove our shortcut from the startup folder for this user - File.Delete(Path.Combine(startupPath, Path.GetFileName(shortcutPath) ?? "MBstartup.lnk")); + fileSystem.DeleteFile(Path.Combine(startupPath, Path.GetFileName(shortcutPath) ?? "MBstartup.lnk")); } } } diff --git a/MediaBrowser.ServerApplication/Native/WindowsApp.cs b/MediaBrowser.ServerApplication/Native/WindowsApp.cs index 45070e6ec..476fb58b9 100644 --- a/MediaBrowser.ServerApplication/Native/WindowsApp.cs +++ b/MediaBrowser.ServerApplication/Native/WindowsApp.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Common.Net; +using MediaBrowser.Common.IO; +using MediaBrowser.Common.Net; using MediaBrowser.IsoMounter; using MediaBrowser.Model.Logging; using MediaBrowser.Server.Startup.Common; @@ -10,6 +11,13 @@ namespace MediaBrowser.ServerApplication.Native { public class WindowsApp : INativeApp { + private readonly IFileSystem _fileSystem; + + public WindowsApp(IFileSystem fileSystem) + { + _fileSystem = fileSystem; + } + public List<Assembly> GetAssembliesWithParts() { var list = new List<Assembly>(); @@ -89,7 +97,7 @@ namespace MediaBrowser.ServerApplication.Native public void ConfigureAutoRun(bool autorun) { - Autorun.Configure(autorun); + Autorun.Configure(autorun, _fileSystem); } public INetworkManager CreateNetworkManager(ILogger logger) diff --git a/MediaBrowser.ServerApplication/Networking/CertificateGenerator.cs b/MediaBrowser.ServerApplication/Networking/CertificateGenerator.cs new file mode 100644 index 000000000..a7b0d6c32 --- /dev/null +++ b/MediaBrowser.ServerApplication/Networking/CertificateGenerator.cs @@ -0,0 +1,244 @@ +using MediaBrowser.Model.Logging; +using System; +using System.IO; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace MediaBrowser.ServerApplication.Networking +{ + // Copied from: http://blogs.msdn.com/b/dcook/archive/2014/05/16/9143036.aspx + // In case anybody is interested, source code is attached and is free for use by anybody as long as you don't hold me or Microsoft liable for it -- + // I have no idea whether this is actually the right or best way to do this. Give it the X500 distinguished name, validity start and end dates, + // and an optional password for encrypting the key data, and it will give you the PFX file data. Let me know if you find any bugs or have any suggestions. + internal class CertificateGenerator + { + internal static void CreateSelfSignCertificatePfx( + string fileName, + string hostname, + ILogger logger) + { + if (string.IsNullOrWhiteSpace(fileName)) + { + throw new ArgumentNullException("fileName"); + } + + string x500 = string.Format("CN={0}", hostname); + + DateTime startTime = DateTime.Now.AddDays(-2); + DateTime endTime = DateTime.Now.AddYears(10); + + byte[] pfxData = CreateSelfSignCertificatePfx( + x500, + startTime, + endTime); + + File.WriteAllBytes(fileName, pfxData); + } + + private static byte[] CreateSelfSignCertificatePfx( + string x500, + DateTime startTime, + DateTime endTime) + { + byte[] pfxData; + + if (x500 == null) + { + x500 = ""; + } + + SystemTime startSystemTime = ToSystemTime(startTime); + SystemTime endSystemTime = ToSystemTime(endTime); + string containerName = Guid.NewGuid().ToString(); + + GCHandle dataHandle = new GCHandle(); + IntPtr providerContext = IntPtr.Zero; + IntPtr cryptKey = IntPtr.Zero; + IntPtr certContext = IntPtr.Zero; + IntPtr certStore = IntPtr.Zero; + IntPtr storeCertContext = IntPtr.Zero; + IntPtr passwordPtr = IntPtr.Zero; + RuntimeHelpers.PrepareConstrainedRegions(); + try + { + Check(NativeMethods.CryptAcquireContextW( + out providerContext, + containerName, + null, + 1, // PROV_RSA_FULL + 8)); // CRYPT_NEWKEYSET + + Check(NativeMethods.CryptGenKey( + providerContext, + 1, // AT_KEYEXCHANGE + 1 | 2048 << 16, // CRYPT_EXPORTABLE 2048 bit key + out cryptKey)); + + IntPtr errorStringPtr; + int nameDataLength = 0; + byte[] nameData; + + // errorStringPtr gets a pointer into the middle of the x500 string, + // so x500 needs to be pinned until after we've copied the value + // of errorStringPtr. + dataHandle = GCHandle.Alloc(x500, GCHandleType.Pinned); + + if (!NativeMethods.CertStrToNameW( + 0x00010001, // X509_ASN_ENCODING | PKCS_7_ASN_ENCODING + dataHandle.AddrOfPinnedObject(), + 3, // CERT_X500_NAME_STR = 3 + IntPtr.Zero, + null, + ref nameDataLength, + out errorStringPtr)) + { + string error = Marshal.PtrToStringUni(errorStringPtr); + throw new ArgumentException(error); + } + + nameData = new byte[nameDataLength]; + + if (!NativeMethods.CertStrToNameW( + 0x00010001, // X509_ASN_ENCODING | PKCS_7_ASN_ENCODING + dataHandle.AddrOfPinnedObject(), + 3, // CERT_X500_NAME_STR = 3 + IntPtr.Zero, + nameData, + ref nameDataLength, + out errorStringPtr)) + { + string error = Marshal.PtrToStringUni(errorStringPtr); + throw new ArgumentException(error); + } + + dataHandle.Free(); + + dataHandle = GCHandle.Alloc(nameData, GCHandleType.Pinned); + CryptoApiBlob nameBlob = new CryptoApiBlob( + nameData.Length, + dataHandle.AddrOfPinnedObject()); + + CryptKeyProviderInformation kpi = new CryptKeyProviderInformation(); + kpi.ContainerName = containerName; + kpi.ProviderType = 1; // PROV_RSA_FULL + kpi.KeySpec = 1; // AT_KEYEXCHANGE + + CryptAlgorithmIdentifier sha256Identifier = new CryptAlgorithmIdentifier(); + sha256Identifier.pszObjId = "1.2.840.113549.1.1.11"; + + certContext = NativeMethods.CertCreateSelfSignCertificate( + providerContext, + ref nameBlob, + 0, + ref kpi, + ref sha256Identifier, + ref startSystemTime, + ref endSystemTime, + IntPtr.Zero); + Check(certContext != IntPtr.Zero); + dataHandle.Free(); + + certStore = NativeMethods.CertOpenStore( + "Memory", // sz_CERT_STORE_PROV_MEMORY + 0, + IntPtr.Zero, + 0x2000, // CERT_STORE_CREATE_NEW_FLAG + IntPtr.Zero); + Check(certStore != IntPtr.Zero); + + Check(NativeMethods.CertAddCertificateContextToStore( + certStore, + certContext, + 1, // CERT_STORE_ADD_NEW + out storeCertContext)); + + NativeMethods.CertSetCertificateContextProperty( + storeCertContext, + 2, // CERT_KEY_PROV_INFO_PROP_ID + 0, + ref kpi); + + CryptoApiBlob pfxBlob = new CryptoApiBlob(); + Check(NativeMethods.PFXExportCertStoreEx( + certStore, + ref pfxBlob, + passwordPtr, + IntPtr.Zero, + 7)); // EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY + + pfxData = new byte[pfxBlob.DataLength]; + dataHandle = GCHandle.Alloc(pfxData, GCHandleType.Pinned); + pfxBlob.Data = dataHandle.AddrOfPinnedObject(); + Check(NativeMethods.PFXExportCertStoreEx( + certStore, + ref pfxBlob, + passwordPtr, + IntPtr.Zero, + 7)); // EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY + dataHandle.Free(); + } + finally + { + if (passwordPtr != IntPtr.Zero) + { + Marshal.ZeroFreeCoTaskMemUnicode(passwordPtr); + } + + if (dataHandle.IsAllocated) + { + dataHandle.Free(); + } + + if (certContext != IntPtr.Zero) + { + NativeMethods.CertFreeCertificateContext(certContext); + } + + if (storeCertContext != IntPtr.Zero) + { + NativeMethods.CertFreeCertificateContext(storeCertContext); + } + + if (certStore != IntPtr.Zero) + { + NativeMethods.CertCloseStore(certStore, 0); + } + + if (cryptKey != IntPtr.Zero) + { + NativeMethods.CryptDestroyKey(cryptKey); + } + + if (providerContext != IntPtr.Zero) + { + NativeMethods.CryptReleaseContext(providerContext, 0); + NativeMethods.CryptAcquireContextW( + out providerContext, + containerName, + null, + 1, // PROV_RSA_FULL + 0x10); // CRYPT_DELETEKEYSET + } + } + + return pfxData; + } + + private static SystemTime ToSystemTime(DateTime dateTime) + { + long fileTime = dateTime.ToFileTime(); + SystemTime systemTime; + Check(NativeMethods.FileTimeToSystemTime(ref fileTime, out systemTime)); + return systemTime; + } + + private static void Check(bool nativeCallSucceeded) + { + if (!nativeCallSucceeded) + { + int error = Marshal.GetHRForLastWin32Error(); + Marshal.ThrowExceptionForHR(error); + } + } + } +} diff --git a/MediaBrowser.ServerApplication/Networking/NativeMethods.cs b/MediaBrowser.ServerApplication/Networking/NativeMethods.cs index 20f7ac23d..037b1f75b 100644 --- a/MediaBrowser.ServerApplication/Networking/NativeMethods.cs +++ b/MediaBrowser.ServerApplication/Networking/NativeMethods.cs @@ -47,9 +47,108 @@ namespace MediaBrowser.ServerApplication.Networking /// <returns>System.Int32.</returns> [DllImport("Netapi32", SetLastError = true), SuppressUnmanagedCodeSecurity] - public static extern int NetApiBufferFree( IntPtr pBuf); + + [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool FileTimeToSystemTime( + [In] ref long fileTime, + out SystemTime systemTime); + + [DllImport("AdvApi32.dll", SetLastError = true, ExactSpelling = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CryptAcquireContextW( + out IntPtr providerContext, + [MarshalAs(UnmanagedType.LPWStr)] string container, + [MarshalAs(UnmanagedType.LPWStr)] string provider, + int providerType, + int flags); + + [DllImport("AdvApi32.dll", SetLastError = true, ExactSpelling = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CryptReleaseContext( + IntPtr providerContext, + int flags); + + [DllImport("AdvApi32.dll", SetLastError = true, ExactSpelling = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CryptGenKey( + IntPtr providerContext, + int algorithmId, + int flags, + out IntPtr cryptKeyHandle); + + [DllImport("AdvApi32.dll", SetLastError = true, ExactSpelling = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CryptDestroyKey( + IntPtr cryptKeyHandle); + + [DllImport("Crypt32.dll", SetLastError = true, ExactSpelling = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CertStrToNameW( + int certificateEncodingType, + IntPtr x500, + int strType, + IntPtr reserved, + [MarshalAs(UnmanagedType.LPArray)] [Out] byte[] encoded, + ref int encodedLength, + out IntPtr errorString); + + [DllImport("Crypt32.dll", SetLastError = true, ExactSpelling = true)] + public static extern IntPtr CertCreateSelfSignCertificate( + IntPtr providerHandle, + [In] ref CryptoApiBlob subjectIssuerBlob, + int flags, + [In] ref CryptKeyProviderInformation keyProviderInformation, + [In] ref CryptAlgorithmIdentifier algorithmIdentifier, + [In] ref SystemTime startTime, + [In] ref SystemTime endTime, + IntPtr extensions); + + [DllImport("Crypt32.dll", SetLastError = true, ExactSpelling = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CertFreeCertificateContext( + IntPtr certificateContext); + + [DllImport("Crypt32.dll", SetLastError = true, ExactSpelling = true)] + public static extern IntPtr CertOpenStore( + [MarshalAs(UnmanagedType.LPStr)] string storeProvider, + int messageAndCertificateEncodingType, + IntPtr cryptProvHandle, + int flags, + IntPtr parameters); + + [DllImport("Crypt32.dll", SetLastError = true, ExactSpelling = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CertCloseStore( + IntPtr certificateStoreHandle, + int flags); + + [DllImport("Crypt32.dll", SetLastError = true, ExactSpelling = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CertAddCertificateContextToStore( + IntPtr certificateStoreHandle, + IntPtr certificateContext, + int addDisposition, + out IntPtr storeContextPtr); + + [DllImport("Crypt32.dll", SetLastError = true, ExactSpelling = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CertSetCertificateContextProperty( + IntPtr certificateContext, + int propertyId, + int flags, + [In] ref CryptKeyProviderInformation data); + + [DllImport("Crypt32.dll", SetLastError = true, ExactSpelling = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool PFXExportCertStoreEx( + IntPtr certificateStoreHandle, + ref CryptoApiBlob pfxBlob, + IntPtr password, + IntPtr reserved, + int flags); } //create a _SERVER_INFO_100 STRUCTURE @@ -69,4 +168,59 @@ namespace MediaBrowser.ServerApplication.Networking [MarshalAs(UnmanagedType.LPWStr)] internal string sv100_name; } + + [StructLayout(LayoutKind.Sequential)] + public struct SystemTime + { + public short Year; + public short Month; + public short DayOfWeek; + public short Day; + public short Hour; + public short Minute; + public short Second; + public short Milliseconds; + } + + [StructLayout(LayoutKind.Sequential)] + public struct CryptObjIdBlob + { + public uint cbData; + public IntPtr pbData; + } + + [StructLayout(LayoutKind.Sequential)] + public struct CryptAlgorithmIdentifier + { + [MarshalAs(UnmanagedType.LPStr)] + public String pszObjId; + public CryptObjIdBlob Parameters; + } + + [StructLayout(LayoutKind.Sequential)] + public struct CryptoApiBlob + { + public int DataLength; + public IntPtr Data; + + public CryptoApiBlob(int dataLength, IntPtr data) + { + this.DataLength = dataLength; + this.Data = data; + } + } + + [StructLayout(LayoutKind.Sequential)] + public struct CryptKeyProviderInformation + { + [MarshalAs(UnmanagedType.LPWStr)] + public string ContainerName; + [MarshalAs(UnmanagedType.LPWStr)] + public string ProviderName; + public int ProviderType; + public int Flags; + public int ProviderParameterCount; + public IntPtr ProviderParameters; // PCRYPT_KEY_PROV_PARAM + public int KeySpec; + } } diff --git a/MediaBrowser.ServerApplication/Networking/NetworkManager.cs b/MediaBrowser.ServerApplication/Networking/NetworkManager.cs index fc4d26363..978a29db0 100644 --- a/MediaBrowser.ServerApplication/Networking/NetworkManager.cs +++ b/MediaBrowser.ServerApplication/Networking/NetworkManager.cs @@ -156,6 +156,16 @@ namespace MediaBrowser.ServerApplication.Networking } /// <summary> + /// Generates a self signed certificate at the locatation specified by <paramref name="certificatePath"/>. + /// </summary> + /// <param name="certificatePath">The path to generate the certificate.</param> + /// <param name="hostname">The common name for the certificate.</param> + public void GenerateSelfSignedSslCertificate(string certificatePath, string hostname) + { + CertificateGenerator.CreateSelfSignCertificatePfx(certificatePath, hostname, Logger); + } + + /// <summary> /// Gets the network prefix. /// </summary> /// <value>The network prefix.</value> diff --git a/MediaBrowser.ServerApplication/packages.config b/MediaBrowser.ServerApplication/packages.config index cc5b794ab..db8524463 100644 --- a/MediaBrowser.ServerApplication/packages.config +++ b/MediaBrowser.ServerApplication/packages.config @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <packages> <package id="MediaBrowser.IsoMounting" version="3.0.69" targetFramework="net45" /> - <package id="NLog" version="3.1.0.0" targetFramework="net45" /> <package id="System.Data.SQLite.Core" version="1.0.94.0" targetFramework="net45" /> </packages>
\ No newline at end of file diff --git a/MediaBrowser.Tests/MediaEncoding/Subtitles/SrtParserTests.cs b/MediaBrowser.Tests/MediaEncoding/Subtitles/SrtParserTests.cs index 6724ca597..8ea4398e9 100644 --- a/MediaBrowser.Tests/MediaEncoding/Subtitles/SrtParserTests.cs +++ b/MediaBrowser.Tests/MediaEncoding/Subtitles/SrtParserTests.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Threading; using MediaBrowser.MediaEncoding.Subtitles; +using MediaBrowser.Model.Logging; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace MediaBrowser.Tests.MediaEncoding.Subtitles @@ -92,7 +93,7 @@ namespace MediaBrowser.Tests.MediaEncoding.Subtitles } }; - var sut = new SrtParser(); + var sut = new SrtParser(new NullLogger()); var stream = File.OpenRead(@"MediaEncoding\Subtitles\TestSubtitles\unit.srt"); diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs index 6e3439079..dcafa9417 100644 --- a/MediaBrowser.WebDashboard/Api/DashboardService.cs +++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs @@ -1,12 +1,11 @@ -using System.Globalization; -using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.Extensions; using MediaBrowser.Common.IO; -using MediaBrowser.Common.Net; using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Localization; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Plugins; +using MediaBrowser.Model.Extensions; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Net; using MediaBrowser.Model.Serialization; @@ -14,6 +13,7 @@ using ServiceStack; using ServiceStack.Web; using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Threading.Tasks; @@ -134,7 +134,7 @@ namespace MediaBrowser.WebDashboard.Api { var page = ServerEntryPoint.Instance.PluginConfigurationPages.First(p => p.Name.Equals(request.Name, StringComparison.OrdinalIgnoreCase)); - return ResultFactory.GetStaticResult(Request, page.Plugin.Version.ToString().GetMD5(), null, null, MimeTypes.GetMimeType("page.html"), () => GetPackageCreator().ModifyHtml(page.GetHtmlStream(), null)); + return ResultFactory.GetStaticResult(Request, page.Plugin.Version.ToString().GetMD5(), null, null, MimeTypes.GetMimeType("page.html"), () => GetPackageCreator().ModifyHtml(page.GetHtmlStream(), null, false)); } /// <summary> @@ -249,8 +249,10 @@ namespace MediaBrowser.WebDashboard.Api /// <returns>Task{Stream}.</returns> private Task<Stream> GetResourceStream(string path, string localizationCulture) { + var minify = _serverConfigurationManager.Configuration.EnableDashboardResourceMinification; + return GetPackageCreator() - .GetResource(path, localizationCulture, _appHost.ApplicationVersion.ToString()); + .GetResource(path, localizationCulture, _appHost.ApplicationVersion.ToString(), minify); } private PackageCreator GetPackageCreator() @@ -275,11 +277,11 @@ namespace MediaBrowser.WebDashboard.Api try { - Directory.Delete(path, true); + _fileSystem.DeleteDirectory(path, true); } catch (IOException) { - + } var creator = GetPackageCreator(); @@ -321,7 +323,7 @@ namespace MediaBrowser.WebDashboard.Api private async Task DumpFile(string resourceVirtualPath, string destinationFilePath, string culture, string appVersion) { - using (var stream = await GetPackageCreator().GetResource(resourceVirtualPath, culture, appVersion).ConfigureAwait(false)) + using (var stream = await GetPackageCreator().GetResource(resourceVirtualPath, culture, appVersion, true).ConfigureAwait(false)) { using (var fs = _fileSystem.GetFileStream(destinationFilePath, FileMode.Create, FileAccess.Write, FileShare.Read)) { diff --git a/MediaBrowser.WebDashboard/Api/PackageCreator.cs b/MediaBrowser.WebDashboard/Api/PackageCreator.cs index a6707bac3..3eb98e95d 100644 --- a/MediaBrowser.WebDashboard/Api/PackageCreator.cs +++ b/MediaBrowser.WebDashboard/Api/PackageCreator.cs @@ -10,6 +10,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using WebMarkupMin.Core.Minifiers; +using WebMarkupMin.Core.Settings; namespace MediaBrowser.WebDashboard.Api { @@ -30,9 +31,9 @@ namespace MediaBrowser.WebDashboard.Api _jsonSerializer = jsonSerializer; } - public async Task<Stream> GetResource(string path, + public async Task<Stream> GetResource(string path, string localizationCulture, - string appVersion) + string appVersion, bool enableMinification) { var isHtml = IsHtml(path); @@ -40,11 +41,11 @@ namespace MediaBrowser.WebDashboard.Api if (path.Equals("scripts/all.js", StringComparison.OrdinalIgnoreCase)) { - resourceStream = await GetAllJavascript(localizationCulture, appVersion).ConfigureAwait(false); + resourceStream = await GetAllJavascript(localizationCulture, appVersion, enableMinification).ConfigureAwait(false); } else if (path.Equals("css/all.css", StringComparison.OrdinalIgnoreCase)) { - resourceStream = await GetAllCss().ConfigureAwait(false); + resourceStream = await GetAllCss(enableMinification).ConfigureAwait(false); } else { @@ -57,7 +58,7 @@ namespace MediaBrowser.WebDashboard.Api // jQuery ajax doesn't seem to handle if-modified-since correctly if (isHtml) { - resourceStream = await ModifyHtml(resourceStream, localizationCulture).ConfigureAwait(false); + resourceStream = await ModifyHtml(resourceStream, localizationCulture, enableMinification).ConfigureAwait(false); } } @@ -106,8 +107,9 @@ namespace MediaBrowser.WebDashboard.Api /// </summary> /// <param name="sourceStream">The source stream.</param> /// <param name="localizationCulture">The localization culture.</param> + /// <param name="enableMinification">if set to <c>true</c> [enable minification].</param> /// <returns>Task{Stream}.</returns> - public async Task<Stream> ModifyHtml(Stream sourceStream, string localizationCulture) + public async Task<Stream> ModifyHtml(Stream sourceStream, string localizationCulture, bool enableMinification) { using (sourceStream) { @@ -128,16 +130,27 @@ namespace MediaBrowser.WebDashboard.Api html = html.Replace("<html>", "<html lang=\"" + lang + "\">"); } - //try - //{ - // var minifier = new HtmlMinifier(new HtmlMinificationSettings(true)); + if (enableMinification) + { + try + { + var minifier = new HtmlMinifier(new HtmlMinificationSettings()); + var result = minifier.Minify(html, false); - // html = minifier.Minify(html).MinifiedContent; - //} - //catch (Exception ex) - //{ - // Logger.ErrorException("Error minifying html", ex); - //} + if (result.Errors.Count > 0) + { + _logger.Error("Error minifying html: " + result.Errors[0].Message); + } + else + { + html = result.MinifiedContent; + } + } + catch (Exception ex) + { + _logger.ErrorException("Error minifying html", ex); + } + } } var version = GetType().Assembly.GetName().Version; @@ -221,7 +234,6 @@ namespace MediaBrowser.WebDashboard.Api var files = new[] { "scripts/all.js" + versionString, - "thirdparty/jstree3.0.8/jstree.min.js", "thirdparty/swipebox-master/js/jquery.swipebox.min.js" + versionString }; @@ -236,7 +248,7 @@ namespace MediaBrowser.WebDashboard.Api /// Gets a stream containing all concatenated javascript /// </summary> /// <returns>Task{Stream}.</returns> - private async Task<Stream> GetAllJavascript(string culture, string version) + private async Task<Stream> GetAllJavascript(string culture, string version, bool enableMinification) { var memoryStream = new MemoryStream(); var newLineBytes = Encoding.UTF8.GetBytes(Environment.NewLine); @@ -250,6 +262,8 @@ namespace MediaBrowser.WebDashboard.Api await AppendResource(memoryStream, "thirdparty/cast_sender.js", newLineBytes).ConfigureAwait(false); await AppendResource(memoryStream, "thirdparty/browser.js", newLineBytes).ConfigureAwait(false); + await AppendResource(memoryStream, "thirdparty/jstree3.0.8/jstree.js", newLineBytes).ConfigureAwait(false); + await AppendLocalization(memoryStream, culture).ConfigureAwait(false); await memoryStream.WriteAsync(newLineBytes, 0, newLineBytes.Length).ConfigureAwait(false); @@ -264,6 +278,7 @@ namespace MediaBrowser.WebDashboard.Api foreach (var file in new[] { + "thirdparty/apiclient/logger.js", "thirdparty/apiclient/md5.js", "thirdparty/apiclient/sha1.js", "thirdparty/apiclient/store.js", @@ -303,15 +318,25 @@ namespace MediaBrowser.WebDashboard.Api var js = builder.ToString(); - try + if (enableMinification) { - var result = new CrockfordJsMinifier().Minify(js, false, Encoding.UTF8); + try + { + var result = new CrockfordJsMinifier().Minify(js, false, Encoding.UTF8); - js = result.MinifiedContent; - } - catch (Exception ex) - { - _logger.ErrorException("Error minifying javascript", ex); + if (result.Errors.Count > 0) + { + _logger.Error("Error minifying javascript: " + result.Errors[0].Message); + } + else + { + js = result.MinifiedContent; + } + } + catch (Exception ex) + { + _logger.ErrorException("Error minifying javascript", ex); + } } var bytes = Encoding.UTF8.GetBytes(js); @@ -341,6 +366,7 @@ namespace MediaBrowser.WebDashboard.Api "mediaplayer-video.js", "nowplayingbar.js", "nowplayingpage.js", + "taskbutton.js", "ratingdialog.js", "aboutpage.js", @@ -356,6 +382,7 @@ namespace MediaBrowser.WebDashboard.Api "channelsettings.js", "connectlogin.js", "dashboardgeneral.js", + "dashboardhosting.js", "dashboardpage.js", "device.js", "devices.js", @@ -414,7 +441,7 @@ namespace MediaBrowser.WebDashboard.Api "metadataconfigurationpage.js", "metadataimagespage.js", "metadatasubtitles.js", - "metadatakodi.js", + "metadatanfo.js", "moviegenres.js", "moviecollections.js", "movies.js", @@ -517,7 +544,7 @@ namespace MediaBrowser.WebDashboard.Api /// Gets all CSS. /// </summary> /// <returns>Task{Stream}.</returns> - private async Task<Stream> GetAllCss() + private async Task<Stream> GetAllCss(bool enableMinification) { var files = new[] { @@ -538,7 +565,8 @@ namespace MediaBrowser.WebDashboard.Api "userimage.css", "livetv.css", "nowplaying.css", - "icons.css" + "icons.css", + "materialize.css" }; var builder = new StringBuilder(); @@ -560,16 +588,26 @@ namespace MediaBrowser.WebDashboard.Api var css = builder.ToString(); - //try - //{ - // var result = new KristensenCssMinifier().Minify(builder.ToString(), false, Encoding.UTF8); + if (enableMinification) + { + try + { + var result = new KristensenCssMinifier().Minify(builder.ToString(), false, Encoding.UTF8); - // css = result.MinifiedContent; - //} - //catch (Exception ex) - //{ - // Logger.ErrorException("Error minifying css", ex); - //} + if (result.Errors.Count > 0) + { + _logger.Error("Error minifying css: " + result.Errors[0].Message); + } + else + { + css = result.MinifiedContent; + } + } + catch (Exception ex) + { + _logger.ErrorException("Error minifying css", ex); + } + } var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(css)); diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 89721f01b..2884a7cd0 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -57,9 +57,9 @@ <Reference Include="ServiceStack.Interfaces">
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll</HintPath>
</Reference>
- <Reference Include="WebMarkupMin.Core, Version=0.9.9.0, Culture=neutral, PublicKeyToken=99472178d266584b, processorArchitecture=MSIL">
+ <Reference Include="WebMarkupMin.Core, Version=0.9.11.0, Culture=neutral, PublicKeyToken=99472178d266584b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\WebMarkupMin.Core.0.9.9\lib\net40\WebMarkupMin.Core.dll</HintPath>
+ <HintPath>..\packages\WebMarkupMin.Core.0.9.11\lib\net40\WebMarkupMin.Core.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
@@ -90,9 +90,18 @@ <Content Include="dashboard-ui\css\images\server.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\css\images\splash.png">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\css\images\tour\dashboard\help.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\css\materialize.css">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\dashboardhosting.html">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\forgotpasswordpin.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -102,6 +111,9 @@ <Content Include="dashboard-ui\mysyncjob.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\scripts\dashboardhosting.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\scripts\forgotpassword.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -117,6 +129,9 @@ <Content Include="dashboard-ui\scripts\syncsettings.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\scripts\taskbutton.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\scripts\usernew.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -141,6 +156,9 @@ <Content Include="dashboard-ui\thirdparty\apiclient\device.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\thirdparty\apiclient\logger.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\thirdparty\apiclient\mediabrowser.apiclient.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -462,7 +480,7 @@ <Content Include="dashboard-ui\librarypathmapping.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\metadatakodi.html">
+ <Content Include="dashboard-ui\metadatanfo.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\mypreferencesdisplay.html">
@@ -777,7 +795,7 @@ <Content Include="dashboard-ui\scripts\librarypathmapping.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\scripts\metadatakodi.js">
+ <Content Include="dashboard-ui\scripts\metadatanfo.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\mypreferencesdisplay.js">
@@ -2150,16 +2168,6 @@ </Content>
</ItemGroup>
<ItemGroup>
- <Content Include="dashboard-ui\css\images\supporter\donatepaypal.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- </ItemGroup>
- <ItemGroup>
- <Content Include="dashboard-ui\css\images\supporter\registerpaypal.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- </ItemGroup>
- <ItemGroup>
<Content Include="dashboard-ui\css\images\notifications\done.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -2229,7 +2237,6 @@ </Content>
</ItemGroup>
<ItemGroup>
- <None Include="app.config" />
<None Include="dashboard-ui\css\fonts\mblogo.woff">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
diff --git a/MediaBrowser.WebDashboard/app.config b/MediaBrowser.WebDashboard/app.config deleted file mode 100644 index 7e2967809..000000000 --- a/MediaBrowser.WebDashboard/app.config +++ /dev/null @@ -1,36 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<configuration> - <configSections> - <sectionGroup name="webMarkupMin"> - <section name="core" type="WebMarkupMin.Core.Configuration.CoreConfiguration, WebMarkupMin.Core" /> - </sectionGroup> - </configSections> - - - - - - - -<webMarkupMin xmlns="http://tempuri.org/WebMarkupMin.Configuration.xsd"> - <core> - <css> - <minifiers> - <add name="NullCssMinifier" displayName="Null CSS Minifier" type="WebMarkupMin.Core.Minifiers.NullCssMinifier, WebMarkupMin.Core" /> - <add name="KristensenCssMinifier" displayName="Mads Kristensen's CSS minifier" type="WebMarkupMin.Core.Minifiers.KristensenCssMinifier, WebMarkupMin.Core" /> - </minifiers> - </css> - <js> - <minifiers> - <add name="NullJsMinifier" displayName="Null JS Minifier" type="WebMarkupMin.Core.Minifiers.NullJsMinifier, WebMarkupMin.Core" /> - <add name="CrockfordJsMinifier" displayName="Douglas Crockford's JS Minifier" type="WebMarkupMin.Core.Minifiers.CrockfordJsMinifier, WebMarkupMin.Core" /> - </minifiers> - </js> - <logging> - <loggers> - <add name="NullLogger" displayName="Null Logger" type="WebMarkupMin.Core.Loggers.NullLogger, WebMarkupMin.Core" /> - <add name="ThrowExceptionLogger" displayName="Throw exception logger" type="WebMarkupMin.Core.Loggers.ThrowExceptionLogger, WebMarkupMin.Core" /> - </loggers> - </logging> - </core> - </webMarkupMin></configuration>
\ No newline at end of file diff --git a/MediaBrowser.WebDashboard/packages.config b/MediaBrowser.WebDashboard/packages.config index a7cbac285..aed67fb69 100644 --- a/MediaBrowser.WebDashboard/packages.config +++ b/MediaBrowser.WebDashboard/packages.config @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <packages> <package id="MediaBrowser.ApiClient.Javascript" version="3.0.249" targetFramework="net45" /> - <package id="WebMarkupMin.Core" version="0.9.9" targetFramework="net45" /> + <package id="WebMarkupMin.Core" version="0.9.11" targetFramework="net45" /> </packages>
\ No newline at end of file diff --git a/MediaBrowser.XbmcMetadata/EntryPoint.cs b/MediaBrowser.XbmcMetadata/EntryPoint.cs index 38c583bd3..d07633268 100644 --- a/MediaBrowser.XbmcMetadata/EntryPoint.cs +++ b/MediaBrowser.XbmcMetadata/EntryPoint.cs @@ -50,8 +50,7 @@ namespace MediaBrowser.XbmcMetadata return; } - var items = _libraryManager.RootFolder.RecursiveChildren; - items = person.GetTaggedItems(items).ToList(); + var items = _libraryManager.RootFolder.GetRecursiveChildren(person.GetItemFilter()); foreach (var item in items) { diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index 7b2dbdeb4..7b580dacd 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -1,5 +1,5 @@ using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Extensions; +using MediaBrowser.Model.Extensions; using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; @@ -130,6 +130,12 @@ namespace MediaBrowser.XbmcMetadata.Parsers item.SetProviderId(MetadataProviders.Imdb, imdbId); } + // If the file is just an imdb url, don't go any further + if (index == 0) + { + return; + } + xml = xml.Substring(0, index + 1); } diff --git a/MediaBrowser.XbmcMetadata/Savers/ArtistNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/ArtistNfoSaver.cs index c592ec4b7..b8ea74588 100644 --- a/MediaBrowser.XbmcMetadata/Savers/ArtistNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/ArtistNfoSaver.cs @@ -51,8 +51,8 @@ namespace MediaBrowser.XbmcMetadata.Savers } var albums = artist - .RecursiveChildren - .OfType<MusicAlbum>() + .GetRecursiveChildren(i => i is MusicAlbum) + .Cast<MusicAlbum>() .ToList(); AddAlbums(albums, writer); diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs index da5126676..aa19b0968 100644 --- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs @@ -19,6 +19,7 @@ using System.Linq; using System.Text; using System.Threading; using System.Xml; +using MediaBrowser.Model.Extensions; namespace MediaBrowser.XbmcMetadata.Savers { diff --git a/MediaBrowser.sln b/MediaBrowser.sln index b25eb58ba..f73971374 100644 --- a/MediaBrowser.sln +++ b/MediaBrowser.sln @@ -10,6 +10,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Performance1.psess = Performance1.psess Performance19.psess = Performance19.psess Performance2.psess = Performance2.psess + Performance3.psess = Performance3.psess + Performance4.psess = Performance4.psess EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget (2)", ".nuget (2)", "{E60FB157-87E2-4A41-8B04-27EA49B63B4D}" @@ -518,4 +520,7 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(Performance) = preSolution + HasPerformanceSessions = true + EndGlobalSection EndGlobal diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index d7d4a2120..271bc7864 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <metadata> <id>MediaBrowser.Common.Internal</id> - <version>3.0.540</version> + <version>3.0.551</version> <title>MediaBrowser.Common.Internal</title> <authors>Luke</authors> <owners>ebr,Luke,scottisafool</owners> @@ -12,7 +12,7 @@ <description>Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.</description> <copyright>Copyright © Media Browser 2013</copyright> <dependencies> - <dependency id="MediaBrowser.Common" version="3.0.540" /> + <dependency id="MediaBrowser.Common" version="3.0.551" /> <dependency id="NLog" version="3.1.0.0" /> <dependency id="SimpleInjector" version="2.6.1" /> </dependencies> diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index c8f2f24cb..31d2c918c 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <metadata> <id>MediaBrowser.Common</id> - <version>3.0.540</version> + <version>3.0.551</version> <title>MediaBrowser.Common</title> <authors>Media Browser Team</authors> <owners>ebr,Luke,scottisafool</owners> diff --git a/Nuget/MediaBrowser.Model.Signed.nuspec b/Nuget/MediaBrowser.Model.Signed.nuspec index c79313850..e202c66fa 100644 --- a/Nuget/MediaBrowser.Model.Signed.nuspec +++ b/Nuget/MediaBrowser.Model.Signed.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <metadata> <id>MediaBrowser.Model.Signed</id> - <version>3.0.540</version> + <version>3.0.551</version> <title>MediaBrowser.Model - Signed Edition</title> <authors>Media Browser Team</authors> <owners>ebr,Luke,scottisafool</owners> diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index 807e49e7f..34df8a854 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <metadata> <id>MediaBrowser.Server.Core</id> - <version>3.0.540</version> + <version>3.0.551</version> <title>Media Browser.Server.Core</title> <authors>Media Browser Team</authors> <owners>ebr,Luke,scottisafool</owners> @@ -12,7 +12,7 @@ <description>Contains core components required to build plugins for Media Browser Server.</description> <copyright>Copyright © Media Browser 2013</copyright> <dependencies> - <dependency id="MediaBrowser.Common" version="3.0.540" /> + <dependency id="MediaBrowser.Common" version="3.0.551" /> </dependencies> </metadata> <files> diff --git a/SharedVersion.cs b/SharedVersion.cs index 238d57f0c..5af3efc1c 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; -//[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5490.2")] +[assembly: AssemblyVersion("3.0.*")] +//[assembly: AssemblyVersion("3.0.5490.2")] |
