diff options
Diffstat (limited to 'Emby.Server.Implementations')
150 files changed, 3560 insertions, 3102 deletions
diff --git a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs index ef5fa8bef9..aa19948e36 100644 --- a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs +++ b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs @@ -132,7 +132,7 @@ namespace Emby.Server.Implementations.AppBase } else { - _configurationFactories = [.._configurationFactories, factory]; + _configurationFactories = [.. _configurationFactories, factory]; } _configurationStores = _configurationFactories diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 3e98a5276c..69e23bcb63 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -14,6 +14,7 @@ using System.Reflection; using System.Security.Cryptography.X509Certificates; using System.Threading.Tasks; using Emby.Naming.Common; +using Emby.Naming.Video; using Emby.Photos; using Emby.Server.Implementations.Chapters; using Emby.Server.Implementations.Collections; @@ -25,6 +26,8 @@ using Emby.Server.Implementations.Dto; using Emby.Server.Implementations.HttpServer.Security; using Emby.Server.Implementations.IO; using Emby.Server.Implementations.Library; +using Emby.Server.Implementations.Library.Search; +using Emby.Server.Implementations.Library.SimilarItems; using Emby.Server.Implementations.Localization; using Emby.Server.Implementations.Playlists; using Emby.Server.Implementations.Plugins; @@ -90,9 +93,16 @@ using MediaBrowser.Model.Net; using MediaBrowser.Model.Serialization; using MediaBrowser.Model.System; using MediaBrowser.Model.Tasks; +using MediaBrowser.Providers.Books; +using MediaBrowser.Providers.Books.ComicBookInfo; +using MediaBrowser.Providers.Books.ComicInfo; using MediaBrowser.Providers.Lyric; using MediaBrowser.Providers.Manager; +using MediaBrowser.Providers.Plugins.ListenBrainz; +using MediaBrowser.Providers.Plugins.ListenBrainz.Api; using MediaBrowser.Providers.Plugins.Tmdb; +using MediaBrowser.Providers.Plugins.Tmdb.Movies; +using MediaBrowser.Providers.Plugins.Tmdb.TV; using MediaBrowser.Providers.Subtitles; using MediaBrowser.XbmcMetadata.Providers; using Microsoft.AspNetCore.Http; @@ -483,6 +493,19 @@ namespace Emby.Server.Implementations serviceCollection.AddScoped<ISystemManager, SystemManager>(); serviceCollection.AddSingleton<TmdbClientManager>(); + serviceCollection.AddSingleton<TmdbMovieSimilarProvider>(); + serviceCollection.AddSingleton<TmdbSeriesSimilarProvider>(); + + serviceCollection.AddSingleton<ListenBrainzLabsClient>(); + serviceCollection.AddSingleton<ListenBrainzSimilarArtistProvider>(); + + // register the generic local metadata provider for comic files + serviceCollection.AddSingleton<ComicProvider>(); + + // register the actual implementations of the local metadata provider for comic files + serviceCollection.AddSingleton<IComicProvider, ComicBookInfoProvider>(); + serviceCollection.AddSingleton<IComicProvider, ExternalComicInfoProvider>(); + serviceCollection.AddSingleton<IComicProvider, InternalComicInfoProvider>(); serviceCollection.AddSingleton(NetManager); @@ -528,15 +551,20 @@ namespace Emby.Server.Implementations serviceCollection.AddTransient(provider => new Lazy<ILibraryMonitor>(provider.GetRequiredService<ILibraryMonitor>)); serviceCollection.AddTransient(provider => new Lazy<IProviderManager>(provider.GetRequiredService<IProviderManager>)); serviceCollection.AddTransient(provider => new Lazy<IUserViewManager>(provider.GetRequiredService<IUserViewManager>)); + serviceCollection.AddTransient(provider => new Lazy<IExternalDataManager>(provider.GetRequiredService<IExternalDataManager>)); serviceCollection.AddSingleton<ILibraryManager, LibraryManager>(); serviceCollection.AddSingleton<NamingOptions>(); + serviceCollection.AddSingleton<VideoListResolver>(); serviceCollection.AddSingleton<IMusicManager, MusicManager>(); serviceCollection.AddSingleton<ILibraryMonitor, LibraryMonitor>(); serviceCollection.AddSingleton<DotIgnoreIgnoreRule>(); - serviceCollection.AddSingleton<ISearchEngine, SearchEngine>(); + serviceCollection.AddSingleton<ISimilarItemsManager, SimilarItemsManager>(); + + serviceCollection.AddSingleton<ISearchManager, SearchManager>(); + serviceCollection.AddSingleton<ISearchProvider, SqlSearchProvider>(); serviceCollection.AddSingleton<IWebSocketManager, WebSocketManager>(); @@ -693,6 +721,9 @@ namespace Emby.Server.Implementations GetExports<IExternalUrlProvider>()); Resolve<IMediaSourceManager>().AddParts(GetExports<IMediaSourceProvider>()); + + Resolve<ISimilarItemsManager>().AddParts(GetExports<ISimilarItemsProvider>()); + Resolve<ISearchManager>().AddParts(GetExports<ISearchProvider>()); } /// <summary> diff --git a/Emby.Server.Implementations/Chapters/ChapterManager.cs b/Emby.Server.Implementations/Chapters/ChapterManager.cs index 8a4721ce62..69cbe533c6 100644 --- a/Emby.Server.Implementations/Chapters/ChapterManager.cs +++ b/Emby.Server.Implementations/Chapters/ChapterManager.cs @@ -240,15 +240,15 @@ public class ChapterManager : IChapterManager public void SaveChapters(BaseItem item, IReadOnlyList<ChapterInfo> chapters) { if (!Supports(item)) - { - _logger.LogWarning("Attempted to save chapters for unsupported item type {Type}: {Name} ({Id})", item.GetType().Name, item.Name, item.Id); - return; - } + { + _logger.LogWarning("Attempted to save chapters for unsupported item type {Type}: {Name} ({Id})", item.GetType().Name, item.Name, item.Id); + return; + } // Remove any chapters that are outside of the runtime of the item var validChapters = chapters.Where(c => c.StartPositionTicks < item.RunTimeTicks).ToList(); _chapterRepository.SaveChapters(item.Id, validChapters); -} + } /// <inheritdoc /> public ChapterInfo? GetChapter(Guid baseItemId, int index) diff --git a/Emby.Server.Implementations/Collections/CollectionManager.cs b/Emby.Server.Implementations/Collections/CollectionManager.cs index 0ede5665f9..295efd456c 100644 --- a/Emby.Server.Implementations/Collections/CollectionManager.cs +++ b/Emby.Server.Implementations/Collections/CollectionManager.cs @@ -4,12 +4,15 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Data.Enums; using Jellyfin.Database.Implementations.Entities; +using Jellyfin.Extensions; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Collections; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; @@ -29,6 +32,7 @@ namespace Emby.Server.Implementations.Collections private readonly ILibraryMonitor _iLibraryMonitor; private readonly ILogger<CollectionManager> _logger; private readonly IProviderManager _providerManager; + private readonly ILinkedChildrenService _linkedChildrenService; private readonly ILocalizationManager _localizationManager; private readonly IApplicationPaths _appPaths; @@ -42,6 +46,7 @@ namespace Emby.Server.Implementations.Collections /// <param name="iLibraryMonitor">The library monitor.</param> /// <param name="loggerFactory">The logger factory.</param> /// <param name="providerManager">The provider manager.</param> + /// <param name="linkedChildrenService">The linked children service.</param> public CollectionManager( ILibraryManager libraryManager, IApplicationPaths appPaths, @@ -49,13 +54,15 @@ namespace Emby.Server.Implementations.Collections IFileSystem fileSystem, ILibraryMonitor iLibraryMonitor, ILoggerFactory loggerFactory, - IProviderManager providerManager) + IProviderManager providerManager, + ILinkedChildrenService linkedChildrenService) { _libraryManager = libraryManager; _fileSystem = fileSystem; _iLibraryMonitor = iLibraryMonitor; _logger = loggerFactory.CreateLogger<CollectionManager>(); _providerManager = providerManager; + _linkedChildrenService = linkedChildrenService; _localizationManager = localizationManager; _appPaths = appPaths; } @@ -120,6 +127,22 @@ namespace Emby.Server.Implementations.Collections return EnsureLibraryFolder(GetCollectionsFolderPath(), createIfNeeded); } + /// <inheritdoc /> + public IEnumerable<BoxSet> GetCollectionsContainingItem(User user, Guid itemId) + { + ArgumentNullException.ThrowIfNull(user); + + if (itemId.IsEmpty()) + { + return Enumerable.Empty<BoxSet>(); + } + + return _linkedChildrenService + .GetManualLinkedParentIds(itemId, BaseItemKind.BoxSet) + .Select(parentId => _libraryManager.GetItemById<BoxSet>(parentId, user)) + .OfType<BoxSet>(); + } + private IEnumerable<BoxSet> GetCollections(User user) { var folder = GetCollectionsFolder(false).GetAwaiter().GetResult(); diff --git a/Emby.Server.Implementations/Devices/DeviceId.cs b/Emby.Server.Implementations/Devices/DeviceId.cs index 0b3c3bbd4f..4929568935 100644 --- a/Emby.Server.Implementations/Devices/DeviceId.cs +++ b/Emby.Server.Implementations/Devices/DeviceId.cs @@ -1,5 +1,3 @@ -#pragma warning disable CS1591 - using System; using System.Globalization; using System.IO; @@ -10,6 +8,9 @@ using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.Devices { + /// <summary> + /// Provides the persistent unique identifier of this server installation. + /// </summary> public class DeviceId { private readonly IApplicationPaths _appPaths; @@ -18,12 +19,20 @@ namespace Emby.Server.Implementations.Devices private string? _id; + /// <summary> + /// Initializes a new instance of the <see cref="DeviceId"/> class. + /// </summary> + /// <param name="appPaths">Instance of the <see cref="IApplicationPaths"/> interface.</param> + /// <param name="logger">Instance of the <see cref="ILogger{DeviceId}"/> interface.</param> public DeviceId(IApplicationPaths appPaths, ILogger<DeviceId> logger) { _appPaths = appPaths; _logger = logger; } + /// <summary> + /// Gets the device id, loading it from disk or generating and persisting a new one if none exists. + /// </summary> public string Value => _id ??= GetDeviceId(); private string CachePath => Path.Combine(_appPaths.DataPath, "device.txt"); diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 321c7da1c4..8cbf42585d 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -71,6 +71,8 @@ namespace Emby.Server.Implementations.Dto { BaseItemKind.Person, [ BaseItemKind.Audio, + BaseItemKind.AudioBook, + BaseItemKind.Book, BaseItemKind.Episode, BaseItemKind.Movie, BaseItemKind.LiveTvProgram, @@ -167,9 +169,13 @@ namespace Emby.Server.Implementations.Dto // Batch-fetch user data for all items Dictionary<Guid, UserItemData>? userDataBatch = null; + IReadOnlyDictionary<Guid, VersionResumeData>? resumeDataBatch = null; if (user is not null && options.EnableUserData) { userDataBatch = _userDataRepository.GetUserDataBatch(accessibleItems, user); + + // For items with alternate versions, the most recently played version drives resume. + resumeDataBatch = _userDataRepository.GetResumeUserDataBatch(accessibleItems, user); } // Pre-compute collection folders once to avoid N+1 queries in CanDelete @@ -248,7 +254,8 @@ namespace Emby.Server.Implementations.Dto allCollectionFolders, childCountBatch, playedCountBatch, - artistsBatch); + artistsBatch, + resumeDataBatch?.GetValueOrDefault(item.Id)); if (item is LiveTvChannel tvChannel) { @@ -309,7 +316,8 @@ namespace Emby.Server.Implementations.Dto List<Folder>? allCollectionFolders = null, Dictionary<Guid, int>? childCountBatch = null, Dictionary<Guid, (int Played, int Total)>? playedCountBatch = null, - IReadOnlyDictionary<string, MusicArtist[]>? artistsBatch = null) + IReadOnlyDictionary<string, MusicArtist[]>? artistsBatch = null, + VersionResumeData? resumeData = null) { var dto = new BaseItemDto { @@ -353,7 +361,8 @@ namespace Emby.Server.Implementations.Dto options, userData, childCountBatch, - playedCountBatch); + playedCountBatch, + resumeData); } if (item is IHasMediaSources @@ -369,7 +378,7 @@ namespace Emby.Server.Implementations.Dto AttachStudios(dto, item); } - AttachBasicFields(dto, item, owner, options, artistsBatch); + AttachBasicFields(dto, item, owner, options, artistsBatch, user); if (options.ContainsField(ItemFields.CanDelete)) { @@ -538,7 +547,8 @@ namespace Emby.Server.Implementations.Dto DtoOptions options, UserItemData? userData = null, Dictionary<Guid, int>? childCountBatch = null, - Dictionary<Guid, (int Played, int Total)>? playedCountBatch = null) + Dictionary<Guid, (int Played, int Total)>? playedCountBatch = null, + VersionResumeData? resumeData = null) { if (item.IsFolder) { @@ -600,6 +610,9 @@ namespace Emby.Server.Implementations.Dto // Use pre-fetched user data dto.UserData = GetUserItemDataDto(userData, item.Id); item.FillUserDataDtoValues(dto.UserData, userData, dto, user, options); + + // For items with alternate versions, the most recently played version drives resume. + resumeData?.ApplyTo(dto.UserData); } else { @@ -943,7 +956,8 @@ namespace Emby.Server.Implementations.Dto /// <param name="owner">The owner.</param> /// <param name="options">The options.</param> /// <param name="artistsBatch">Optional pre-fetched artist lookup shared across a batch of items.</param> - private void AttachBasicFields(BaseItemDto dto, BaseItem item, BaseItem? owner, DtoOptions options, IReadOnlyDictionary<string, MusicArtist[]>? artistsBatch = null) + /// <param name="user">The user, for per-user values such as the accessible media source count.</param> + private void AttachBasicFields(BaseItemDto dto, BaseItem item, BaseItem? owner, DtoOptions options, IReadOnlyDictionary<string, MusicArtist[]>? artistsBatch = null, User? user = null) { if (options.ContainsField(ItemFields.DateCreated)) { @@ -1257,7 +1271,12 @@ namespace Emby.Server.Implementations.Dto if (options.ContainsField(ItemFields.MediaSourceCount)) { - var mediaSourceCount = video.MediaSourceCount; + // Match the per-user filtering of the media sources: versions the user cannot + // access are not selectable, so they must not count towards the badge either. + var mediaSourceCount = user is null + || (!video.PrimaryVersionId.HasValue && video.LinkedAlternateVersions.Length == 0 && !video.HasLocalAlternateVersions) + ? video.MediaSourceCount + : video.GetAllVersions().Count(v => v.Id.Equals(video.Id) || v.IsVisibleStandalone(user)); if (mediaSourceCount != 1) { dto.MediaSourceCount = mediaSourceCount; @@ -1366,6 +1385,25 @@ namespace Emby.Server.Implementations.Dto } } + if (options.GetImageLimit(ImageType.Primary) > 0) + { + var episodeSeason = episode.Season; + var seasonPrimaryTag = episodeSeason is not null + ? GetTagAndFillBlurhash(dto, episodeSeason, ImageType.Primary) + : null; + + if (seasonPrimaryTag is not null) + { + dto.ParentPrimaryImageItemId = episodeSeason!.Id; + dto.ParentPrimaryImageTag = seasonPrimaryTag; + } + else if (episodeSeries is not null && dto.SeriesPrimaryImageTag is not null) + { + dto.ParentPrimaryImageItemId = episodeSeries.Id; + dto.ParentPrimaryImageTag = dto.SeriesPrimaryImageTag; + } + } + if (options.ContainsField(ItemFields.SeriesStudio)) { episodeSeries ??= episode.Series; @@ -1504,6 +1542,21 @@ namespace Emby.Server.Implementations.Dto private void AddInheritedImages(BaseItemDto dto, BaseItem item, DtoOptions options, BaseItem? owner) { + if (item is UserView { ViewType: CollectionType.playlists } playlistsView + && options.GetImageLimit(ImageType.Primary) > 0 + && !playlistsView.DisplayParentId.IsEmpty()) + { + var displayParent = _libraryManager.GetItemById(playlistsView.DisplayParentId); + var displayParentPrimaryImage = displayParent?.GetImageInfo(ImageType.Primary, 0); + + if (displayParentPrimaryImage is not null) + { + dto.ImageTags?.Remove(ImageType.Primary); + dto.ParentPrimaryImageItemId = displayParent!.Id; + dto.ParentPrimaryImageTag = GetTagAndFillBlurhash(dto, displayParent, displayParentPrimaryImage); + } + } + if (!item.SupportsInheritedParentImages) { return; diff --git a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs index 373b0994a6..dc7f972c13 100644 --- a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs +++ b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs @@ -1,5 +1,6 @@ using System; using System.Buffers; +using System.Globalization; using System.IO.Pipelines; using System.Net; using System.Net.WebSockets; @@ -69,6 +70,11 @@ namespace Emby.Server.Implementations.HttpServer /// <inheritdoc /> public IPAddress? RemoteEndPoint { get; } + /// <summary> + /// Gets or initializes the UI culture captured from the upgrade request. + /// </summary> + public CultureInfo? RequestUICulture { get; init; } + /// <inheritdoc /> public Func<WebSocketMessageInfo, Task>? OnReceive { get; set; } @@ -82,6 +88,17 @@ namespace Emby.Server.Implementations.HttpServer public WebSocketState State => _socket.State; /// <inheritdoc /> + public void ApplyRequestCulture() + { + if (RequestUICulture is null) + { + return; + } + + CultureInfo.CurrentUICulture = RequestUICulture; + } + + /// <inheritdoc /> public async Task SendAsync(OutboundWebSocketMessage message, CancellationToken cancellationToken) { var json = JsonSerializer.SerializeToUtf8Bytes(message, _jsonOptions); @@ -110,8 +127,12 @@ namespace Emby.Server.Implementations.HttpServer { receiveResult = await _socket.ReceiveAsync(memory, cancellationToken).ConfigureAwait(false); } - catch (WebSocketException ex) + catch (Exception ex) when (ex is WebSocketException or ObjectDisposedException or OperationCanceledException) { + // ObjectDisposedException/OperationCanceledException: the socket was torn + // down underneath us (e.g. by the keep-alive watchdog after the connection + // was declared lost). Fall through so Closed is still raised and the + // session can release this connection. _logger.LogWarning("WS {IP} error receiving data: {Message}", RemoteEndPoint, ex.Message); break; } diff --git a/Emby.Server.Implementations/HttpServer/WebSocketManager.cs b/Emby.Server.Implementations/HttpServer/WebSocketManager.cs index cb5b3993b8..072034c4bf 100644 --- a/Emby.Server.Implementations/HttpServer/WebSocketManager.cs +++ b/Emby.Server.Implementations/HttpServer/WebSocketManager.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Net.WebSockets; using System.Threading.Tasks; @@ -47,14 +48,18 @@ namespace Emby.Server.Implementations.HttpServer _logger.LogInformation("WS {IP} request", context.Connection.RemoteIpAddress); WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync().ConfigureAwait(false); - var connection = new WebSocketConnection( _loggerFactory.CreateLogger<WebSocketConnection>(), webSocket, authorizationInfo, context.GetNormalizedRemoteIP()) { - OnReceive = ProcessWebSocketMessageReceived + RequestUICulture = CultureInfo.CurrentUICulture + }; + connection.OnReceive = result => + { + connection.ApplyRequestCulture(); + return ProcessWebSocketMessageReceived(result); }; await using (connection.ConfigureAwait(false)) { diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs index 199407044b..ede9b27592 100644 --- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs @@ -691,7 +691,7 @@ namespace Emby.Server.Implementations.IO } catch (Exception ex) when (ex is UnauthorizedAccessException or DirectoryNotFoundException or SecurityException) { - _logger.LogError(ex, "Failed to enumerate path {Path}", path); + _logger.LogWarning("Failed to enumerate path \"{Path}\": {Message}", path, ex.Message); return Enumerable.Empty<string>(); } } diff --git a/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs b/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs index 095934f896..b701e7eb6d 100644 --- a/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs +++ b/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.IO; +using Jellyfin.Api.Extensions; using Jellyfin.Data.Enums; using Jellyfin.Database.Implementations.Enums; using MediaBrowser.Common.Configuration; @@ -14,7 +15,6 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; -using MediaBrowser.Model.Querying; namespace Emby.Server.Implementations.Images { @@ -28,38 +28,7 @@ namespace Emby.Server.Implementations.Images { var view = (CollectionFolder)item; var viewType = view.CollectionType; - - BaseItemKind[] includeItemTypes; - - switch (viewType) - { - case CollectionType.movies: - includeItemTypes = new[] { BaseItemKind.Movie }; - break; - case CollectionType.tvshows: - includeItemTypes = new[] { BaseItemKind.Series }; - break; - case CollectionType.music: - includeItemTypes = new[] { BaseItemKind.MusicArtist }; // Music albums usually don't have dedicated backdrops, so use artist instead - break; - case CollectionType.musicvideos: - includeItemTypes = new[] { BaseItemKind.MusicVideo }; - break; - case CollectionType.books: - includeItemTypes = new[] { BaseItemKind.Book, BaseItemKind.AudioBook }; - break; - case CollectionType.boxsets: - includeItemTypes = new[] { BaseItemKind.BoxSet }; - break; - case CollectionType.homevideos: - case CollectionType.photos: - includeItemTypes = new[] { BaseItemKind.Video, BaseItemKind.Photo }; - break; - default: - includeItemTypes = new[] { BaseItemKind.Video, BaseItemKind.Audio, BaseItemKind.Photo, BaseItemKind.Movie, BaseItemKind.Series }; - break; - } - + var includeItemTypes = DtoExtensions.GetBaseItemKindsForCollectionType(viewType); var recursive = viewType != CollectionType.playlists; return view.GetItemList(new InternalItemsQuery @@ -67,12 +36,9 @@ namespace Emby.Server.Implementations.Images CollapseBoxSetItems = false, Recursive = recursive, DtoOptions = new DtoOptions(false), - ImageTypes = new[] { ImageType.Primary }, + ImageTypes = [ImageType.Primary], Limit = 8, - OrderBy = new[] - { - (ItemSortBy.Random, SortOrder.Ascending) - }, + OrderBy = [(ItemSortBy.Random, SortOrder.Ascending)], IncludeItemTypes = includeItemTypes }); } diff --git a/Emby.Server.Implementations/Library/ExternalDataManager.cs b/Emby.Server.Implementations/Library/ExternalDataManager.cs index 4ad0f999bf..2c18e56df7 100644 --- a/Emby.Server.Implementations/Library/ExternalDataManager.cs +++ b/Emby.Server.Implementations/Library/ExternalDataManager.cs @@ -1,6 +1,5 @@ using System; using System.IO; -using System.Linq; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Controller.Chapters; @@ -52,26 +51,33 @@ public class ExternalDataManager : IExternalDataManager /// <inheritdoc/> public async Task DeleteExternalItemDataAsync(BaseItem item, CancellationToken cancellationToken) { - var validPaths = _pathManager.GetExtractedDataPaths(item).Where(Directory.Exists).ToList(); - var itemId = item.Id; - if (validPaths.Count > 0) - { - foreach (var path in validPaths) - { - try - { - Directory.Delete(path, true); - } - catch (Exception ex) - { - _logger.LogWarning("Unable to prune external item data at {Path}: {Exception}", path, ex); - } - } - } + DeleteExternalItemFiles(item); + var itemId = item.Id; await _keyframeManager.DeleteKeyframeDataAsync(itemId, cancellationToken).ConfigureAwait(false); await _mediaSegmentManager.DeleteSegmentsAsync(itemId, cancellationToken).ConfigureAwait(false); await _trickplayManager.DeleteTrickplayDataAsync(itemId, cancellationToken).ConfigureAwait(false); await _chapterManager.DeleteChapterDataAsync(itemId, cancellationToken).ConfigureAwait(false); } + + /// <inheritdoc/> + public void DeleteExternalItemFiles(BaseItem item) + { + foreach (var path in _pathManager.GetExtractedDataPaths(item)) + { + if (!Directory.Exists(path)) + { + continue; + } + + try + { + Directory.Delete(path, true); + } + catch (Exception ex) + { + _logger.LogWarning("Unable to prune external item data at {Path}: {Exception}", path, ex); + } + } + } } diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 11f1496086..3691f4e19d 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -13,6 +13,7 @@ using System.Threading.Tasks; using BitFaster.Caching.Lru; using Emby.Naming.Common; using Emby.Naming.TV; +using Emby.Naming.Video; using Emby.Server.Implementations.Library.Resolvers; using Emby.Server.Implementations.Library.Validators; using Emby.Server.Implementations.Playlists; @@ -87,6 +88,8 @@ namespace Emby.Server.Implementations.Library private readonly IPathManager _pathManager; private readonly FastConcurrentLru<Guid, BaseItem> _cache; private readonly DotIgnoreIgnoreRule _dotIgnoreIgnoreRule; + private readonly IMediaStreamRepository _mediaStreamRepository; + private readonly Lazy<IExternalDataManager> _externalDataManagerFactory; /// <summary> /// The _root folder sync lock. @@ -129,6 +132,8 @@ namespace Emby.Server.Implementations.Library /// <param name="peopleRepository">The people repository.</param> /// <param name="pathManager">The path manager.</param> /// <param name="dotIgnoreIgnoreRule">The .ignore rule handler.</param> + /// <param name="mediaStreamRepository">The media stream repository.</param> + /// <param name="externalDataManagerFactory">The external data manager (lazy, to break the DI cycle through ChapterManager).</param> public LibraryManager( IServerApplicationHost appHost, ILoggerFactory loggerFactory, @@ -151,7 +156,9 @@ namespace Emby.Server.Implementations.Library IDirectoryService directoryService, IPeopleRepository peopleRepository, IPathManager pathManager, - DotIgnoreIgnoreRule dotIgnoreIgnoreRule) + DotIgnoreIgnoreRule dotIgnoreIgnoreRule, + IMediaStreamRepository mediaStreamRepository, + Lazy<IExternalDataManager> externalDataManagerFactory) { _appHost = appHost; _logger = loggerFactory.CreateLogger<LibraryManager>(); @@ -181,6 +188,9 @@ namespace Emby.Server.Implementations.Library _configurationManager.ConfigurationUpdated += ConfigurationUpdated; + _mediaStreamRepository = mediaStreamRepository; + _externalDataManagerFactory = externalDataManagerFactory; + RecordConfigurationValues(_configurationManager.Configuration); } @@ -390,6 +400,12 @@ namespace Emby.Server.Implementations.Library } } + var externalDataManager = _externalDataManagerFactory.Value; + foreach (var (item, _, _) in pathMaps) + { + externalDataManager.DeleteExternalItemFiles(item); + } + _persistenceService.DeleteItem([.. pathMaps.Select(f => f.Item.Id)]); } @@ -570,6 +586,13 @@ namespace Emby.Server.Implementations.Library item.SetParent(null); + var externalDataManager = _externalDataManagerFactory.Value; + externalDataManager.DeleteExternalItemFiles(item); + foreach (var child in children) + { + externalDataManager.DeleteExternalItemFiles(child); + } + _persistenceService.DeleteItem([item.Id, .. children.Select(f => f.Id)]); _cache.TryRemove(item.Id, out _); foreach (var child in children) @@ -787,6 +810,42 @@ namespace Emby.Server.Implementations.Library CollectionType? collectionType = null) => ResolvePath(fileInfo, directoryService ?? new DirectoryService(_fileSystem), null, parent, collectionType); + private void SetAdditionalPartsFromStack(Video altVideo, string path) + { + if (altVideo.AdditionalParts is { Length: > 0 }) + { + return; + } + + var directory = Path.GetDirectoryName(path); + if (string.IsNullOrEmpty(directory)) + { + return; + } + + IEnumerable<FileSystemMetadata> siblings; + try + { + siblings = _fileSystem.GetFiles(directory); + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Failed to enumerate siblings to detect stack for {Path}", path); + return; + } + + var stacks = StackResolver.Resolve(siblings, _namingOptions); + foreach (var stack in stacks) + { + if (stack.Files.Count > 1 + && string.Equals(stack.Files[0], path, StringComparison.OrdinalIgnoreCase)) + { + altVideo.AdditionalParts = stack.Files.Skip(1).ToArray(); + return; + } + } + } + /// <inheritdoc /> public Video? ResolveAlternateVersion(string path, Type expectedVideoType, Folder? parent, CollectionType? collectionType) { @@ -1945,7 +2004,8 @@ namespace Emby.Server.Implementations.Library query.TopParentIds.Length == 0 && string.IsNullOrEmpty(query.AncestorWithPresentationUniqueKey) && string.IsNullOrEmpty(query.SeriesPresentationUniqueKey) && - query.ItemIds.Length == 0) + query.ItemIds.Length == 0 && + query.OwnerIds.Length == 0) { var userViews = UserViewManager.GetUserViews(new UserViewQuery { @@ -2307,6 +2367,10 @@ namespace Emby.Server.Implementations.Library { altVideo.OwnerId = video.Id; altVideo.SetPrimaryVersionId(video.Id); + // ResolveAlternateVersion only sees the alternate's primary file. + // If the alternate is itself a stack (e.g. 1080p part1 + part2), + // detect its parts from sibling files so its AdditionalParts persist. + SetAdditionalPartsFromStack(altVideo, path); allItems.Add(altVideo); } } @@ -2386,8 +2450,14 @@ namespace Emby.Server.Implementations.Library var outdated = forceUpdate ? item.ImageInfos.Where(i => i.Path is not null).ToArray() : item.ImageInfos.Where(ImageNeedsRefresh).ToArray(); - // Skip image processing if current or live tv source - if (outdated.Length == 0 || item.SourceType != SourceType.Library) + + var parentItem = item.GetParent(); + var isLiveTvShow = item.SourceType != SourceType.Library && + parentItem is not null && + parentItem.SourceType != SourceType.Library; // not a channel + + // Skip image processing if current or live tv show + if (outdated.Length == 0 || isLiveTvShow) { RegisterItem(item); return; @@ -2510,6 +2580,10 @@ namespace Emby.Server.Implementations.Library { altVideo.OwnerId = video.Id; altVideo.SetPrimaryVersionId(video.Id); + // ResolveAlternateVersion only sees the alternate's primary file. + // If the alternate is itself a stack (e.g. 1080p part1 + part2), + // detect its parts from sibling files so its AdditionalParts persist. + SetAdditionalPartsFromStack(altVideo, path); allItems.Add(altVideo); } } @@ -3344,6 +3418,12 @@ namespace Emby.Server.Implementations.Library return _peopleRepository.GetPeopleNames(query); } + /// <inheritdoc/> + public IReadOnlyDictionary<Guid, IReadOnlyList<string>> GetPeopleNamesByItems(IReadOnlyList<Guid> itemIds, IReadOnlyList<string> personTypes) + { + return _peopleRepository.GetPeopleNamesByItems(itemIds, personTypes); + } + public void UpdatePeople(BaseItem item, List<PersonInfo> people) { UpdatePeopleAsync(item, people, CancellationToken.None).GetAwaiter().GetResult(); @@ -3800,5 +3880,11 @@ namespace Emby.Server.Implementations.Library SetTopParentOrAncestorIds(query); return _itemRepository.GetQueryFiltersLegacy(query); } + + /// <inheritdoc /> + public IReadOnlyList<string> GetMediaStreamLanguages(MediaStreamType mediaStreamType) + { + return _mediaStreamRepository.GetMediaStreamLanguages(mediaStreamType); + } } } diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index fdb4c7328b..97e00177b6 100644 --- a/Emby.Server.Implementations/Library/MediaSourceManager.cs +++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs @@ -24,6 +24,7 @@ using MediaBrowser.Common.Extensions; using MediaBrowser.Controller; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.MediaEncoding; @@ -127,6 +128,11 @@ namespace Emby.Server.Implementations.Library return true; } + if (stream.IsVobSubSubtitleStream) + { + return true; + } + return false; } @@ -171,6 +177,7 @@ namespace Emby.Server.Implementations.Library public async Task<IReadOnlyList<MediaSourceInfo>> GetPlaybackMediaSources(BaseItem item, User user, bool allowMediaProbe, bool enablePathSubstitution, CancellationToken cancellationToken) { var mediaSources = GetStaticMediaSources(item, enablePathSubstitution, user); + ResolveSymlinkPaths(mediaSources, enablePathSubstitution); // If file is strm or main media stream is missing, force a metadata refresh with remote probing if (allowMediaProbe && mediaSources[0].Type != MediaSourceType.Placeholder @@ -187,6 +194,7 @@ namespace Emby.Server.Implementations.Library cancellationToken).ConfigureAwait(false); mediaSources = GetStaticMediaSources(item, enablePathSubstitution, user); + ResolveSymlinkPaths(mediaSources, enablePathSubstitution); } var dynamicMediaSources = await GetDynamicMediaSources(item, cancellationToken).ConfigureAwait(false); @@ -221,7 +229,11 @@ namespace Emby.Server.Implementations.Library list.Add(source); } - return SortMediaSources(list).ToArray(); + var preferredId = mediaSources.Count > 0 && Guid.TryParse(mediaSources[0].Id, out var topSourceId) + ? topSourceId + : item.Id; + + return SortMediaSources(list, preferredId).ToArray(); } /// <inheritdoc />> @@ -319,6 +331,28 @@ namespace Emby.Server.Implementations.Library } } + /// <summary> + /// Resolves symlinked file paths on the supplied sources to the real on-disk target. + /// Skipped when <paramref name="enablePathSubstitution"/> is set because the path may + /// already have been rewritten to a UNC/URL meant for the client to consume directly. + /// </summary> + private static void ResolveSymlinkPaths(IReadOnlyList<MediaSourceInfo> sources, bool enablePathSubstitution) + { + if (enablePathSubstitution) + { + return; + } + + foreach (var source in sources) + { + if (source.Protocol == MediaProtocol.File + && FileSystemHelper.ResolveLinkTarget(source.Path, returnFinalTarget: true) is { Exists: true } target) + { + source.Path = target.FullName; + } + } + } + private static void SetKeyProperties(IMediaSourceProvider provider, MediaSourceInfo mediaSource) { var prefix = provider.GetType().FullName.GetMD5().ToString("N", CultureInfo.InvariantCulture) + LiveStreamIdDelimiter; @@ -356,6 +390,12 @@ namespace Emby.Server.Implementations.Library if (user is not null) { + sources = sources + .Where(source => !Guid.TryParse(source.Id, out var sourceId) + || sourceId.Equals(item.Id) + || _libraryManager.GetItemById<BaseItem>(sourceId, user) is not null) + .ToArray(); + foreach (var source in sources) { SetDefaultAudioAndSubtitleStreamIndices(item, source, user); @@ -370,6 +410,59 @@ namespace Emby.Server.Implementations.Library source.SupportsDirectStream = user.HasPermission(PermissionKind.EnablePlaybackRemuxing); } } + + sources = SetAlternateVersionResumeStates(item, sources, user); + } + + return sources; + } + + /// <summary> + /// When the queried item is a primary, moves the most recently played version to the front so + /// that resuming without an explicit source selection plays the version that was last watched. + /// A directly queried alternate version keeps its own source first. Per-user playback position + /// is not surfaced on the source itself; it is carried by each version's own UserData. + /// </summary> + /// <param name="item">The queried item.</param> + /// <param name="sources">The item's media sources.</param> + /// <param name="user">The user.</param> + /// <returns>The media sources, reordered when a version drives resume.</returns> + private IReadOnlyList<MediaSourceInfo> SetAlternateVersionResumeStates(BaseItem item, IReadOnlyList<MediaSourceInfo> sources, User user) + { + // For a video, multiple sources means alternate versions. + if (item is not Video video || sources.Count < 2) + { + return sources; + } + + var versions = video.GetAllVersions(); + if (versions.Count < 2) + { + return sources; + } + + var userDataByVersion = _userDataManager.GetUserDataBatch(versions, user); + var dataBySourceId = new Dictionary<string, UserItemData>(versions.Count, StringComparer.OrdinalIgnoreCase); + foreach (var version in versions) + { + if (userDataByVersion.TryGetValue(version.Id, out var data)) + { + dataBySourceId[version.Id.ToString("N", CultureInfo.InvariantCulture)] = data; + } + } + + // Reorder only for a resumable (in-progress) version; + // a completed version has no position to resume, so it must not be pulled to the front here. + var resumeSource = VersionPlaybackSelector.SelectMostRecentlyPlayed( + sources, + source => source.Id is not null ? dataBySourceId.GetValueOrDefault(source.Id) : null, + data => data.PlaybackPositionTicks > 0); + + if (resumeSource is not null && !video.PrimaryVersionId.HasValue && !ReferenceEquals(sources[0], resumeSource)) + { + var reordered = new List<MediaSourceInfo>(sources.Count) { resumeSource }; + reordered.AddRange(sources.Where(s => !ReferenceEquals(s, resumeSource))); + return reordered; } return sources; @@ -440,10 +533,6 @@ namespace Emby.Server.Implementations.Library if (string.Equals(user.AudioLanguagePreference, "OriginalLanguage", StringComparison.OrdinalIgnoreCase)) { - originalLanguage = !string.IsNullOrWhiteSpace(originalLanguage) - ? originalLanguage.Split(',').FirstOrDefault() - : null; - if (user.PlayDefaultAudioTrack) { source.DefaultAudioStreamIndex = MediaStreamSelector.GetDefaultAudioStreamIndex( @@ -498,17 +587,7 @@ namespace Emby.Server.Implementations.Library var allowRememberingSelection = item is null || item.EnableRememberingTrackSelections; - var originalLanguage = item?.OriginalLanguage ?? item switch - { - Episode episode => episode.Series.OriginalLanguage, - Video video => video.GetOwner() switch - { - Episode ownerEpisode => ownerEpisode.OriginalLanguage ?? ownerEpisode.Series.OriginalLanguage, - BaseItem owner => owner.OriginalLanguage, - null => null - }, - _ => null - }; + var originalLanguage = item?.GetInheritedOriginalLanguage(); SetDefaultAudioStreamIndex(source, userData, user, allowRememberingSelection, originalLanguage); SetDefaultSubtitleStreamIndex(source, userData, user, allowRememberingSelection); @@ -524,24 +603,32 @@ namespace Emby.Server.Implementations.Library } } - private static IEnumerable<MediaSourceInfo> SortMediaSources(IEnumerable<MediaSourceInfo> sources) + private static IEnumerable<MediaSourceInfo> SortMediaSources(IEnumerable<MediaSourceInfo> sources, Guid preferredItemId = default) { - return sources.OrderBy(i => - { - if (i.VideoType.HasValue && i.VideoType.Value == VideoType.VideoFile) + // The source belonging to the queried item sorts first so it stays the default that gets played. + var preferredId = preferredItemId.IsEmpty() + ? null + : preferredItemId.ToString("N", CultureInfo.InvariantCulture); + + return sources + .OrderByDescending(i => preferredId is not null && string.Equals(i.Id, preferredId, StringComparison.OrdinalIgnoreCase)) + .ThenBy(i => { - return 0; - } + if (i.VideoType.HasValue && i.VideoType.Value == VideoType.VideoFile) + { + return 0; + } - return 1; - }).ThenBy(i => i.Video3DFormat.HasValue ? 1 : 0) - .ThenByDescending(i => - { - var stream = i.VideoStream; + return 1; + }) + .ThenBy(i => i.Video3DFormat.HasValue ? 1 : 0) + .ThenByDescending(i => + { + var stream = i.VideoStream; - return stream?.Width ?? 0; - }) - .Where(i => i.Type != MediaSourceType.Placeholder); + return stream?.Width ?? 0; + }) + .Where(i => i.Type != MediaSourceType.Placeholder); } public async Task<Tuple<LiveStreamResponse, IDirectStreamProvider>> OpenLiveStreamInternal(LiveStreamRequest request, CancellationToken cancellationToken) diff --git a/Emby.Server.Implementations/Library/PathExtensions.cs b/Emby.Server.Implementations/Library/PathExtensions.cs index cfa3e7c31d..7591359ea4 100644 --- a/Emby.Server.Implementations/Library/PathExtensions.cs +++ b/Emby.Server.Implementations/Library/PathExtensions.cs @@ -45,7 +45,7 @@ namespace Emby.Server.Implementations.Library '[' => ']', '(' => ')', '{' => '}', - _ => '\0' + _ => '\0' }; if (attributeCloser != '\0' && (str[attributeEnd] == '=' || str[attributeEnd] == '-')) { diff --git a/Emby.Server.Implementations/Library/PathManager.cs b/Emby.Server.Implementations/Library/PathManager.cs index ef5edb9afa..fad948ad97 100644 --- a/Emby.Server.Implementations/Library/PathManager.cs +++ b/Emby.Server.Implementations/Library/PathManager.cs @@ -121,7 +121,11 @@ public class PathManager : IPathManager } paths.Add(GetTrickplayDirectory(item, false)); - paths.Add(GetTrickplayDirectory(item, true)); + if (!string.IsNullOrEmpty(item.Path)) + { + paths.Add(GetTrickplayDirectory(item, true)); + } + paths.Add(GetChapterImageFolderPath(item)); return paths; diff --git a/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs index 1e885aad6e..7d51a0daa0 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs @@ -1,5 +1,3 @@ -#nullable disable - #pragma warning disable CS1591 using System; @@ -18,7 +16,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Books { private readonly string[] _validExtensions = { ".azw", ".azw3", ".cb7", ".cbr", ".cbt", ".cbz", ".epub", ".mobi", ".pdf" }; - protected override Book Resolve(ItemResolveArgs args) + protected override Book? Resolve(ItemResolveArgs args) { var collectionType = args.GetCollectionType(); @@ -47,13 +45,14 @@ namespace Emby.Server.Implementations.Library.Resolvers.Books Path = args.Path, Name = result.Name ?? string.Empty, IndexNumber = result.Index, + ParentIndexNumber = result.ParentIndex, ProductionYear = result.Year, SeriesName = result.SeriesName ?? Path.GetFileName(Path.GetDirectoryName(args.Path)), IsInMixedFolder = true, }; } - private Book GetBook(ItemResolveArgs args) + private Book? GetBook(ItemResolveArgs args) { var bookFiles = args.FileSystemChildren.Where(f => { @@ -78,6 +77,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Books Path = bookFiles[0].FullName, Name = result.Name ?? string.Empty, IndexNumber = result.Index, + ParentIndexNumber = result.ParentIndex, ProductionYear = result.Year, SeriesName = result.SeriesName ?? string.Empty, }; diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs index 98e8f5350b..68b66ab7f5 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs @@ -28,15 +28,16 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies public partial class MovieResolver : BaseVideoResolver<Video>, IMultiItemResolver { private readonly IImageProcessor _imageProcessor; + private readonly VideoListResolver _videoListResolver; - private static readonly CollectionType[] _validCollectionTypes = new[] - { + private static readonly CollectionType[] _validCollectionTypes = + [ CollectionType.movies, CollectionType.homevideos, CollectionType.musicvideos, CollectionType.tvshows, CollectionType.photos - }; + ]; /// <summary> /// Initializes a new instance of the <see cref="MovieResolver"/> class. @@ -45,10 +46,12 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies /// <param name="logger">The logger.</param> /// <param name="namingOptions">The naming options.</param> /// <param name="directoryService">The directory service.</param> - public MovieResolver(IImageProcessor imageProcessor, ILogger<MovieResolver> logger, NamingOptions namingOptions, IDirectoryService directoryService) + /// <param name="videoListResolver">The video list resolver.</param> + public MovieResolver(IImageProcessor imageProcessor, ILogger<MovieResolver> logger, NamingOptions namingOptions, IDirectoryService directoryService, VideoListResolver videoListResolver) : base(logger, namingOptions, directoryService) { _imageProcessor = imageProcessor; + _videoListResolver = videoListResolver; } /// <summary> @@ -228,7 +231,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies if (collectionType == CollectionType.tvshows) { - return ResolveVideos<Episode>(parent, files, false, collectionType, true); + return ResolveVideos<Episode>(parent, files, true, collectionType, true); } return null; @@ -274,7 +277,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies .Where(f => f is not null) .ToList(); - var resolverResult = VideoListResolver.Resolve(videoInfos, NamingOptions, supportMultiEditions, parseName, parent.ContainingFolderPath); + var resolverResult = _videoListResolver.Resolve(videoInfos, supportMultiEditions, parseName, parent.ContainingFolderPath, collectionType); var result = new MultiItemResolverResult { @@ -302,7 +305,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies ProductionYear = video.Year, Name = parseName ? video.Name : firstVideo.Name, AdditionalParts = additionalParts, - LocalAlternateVersions = video.AlternateVersions.Select(i => i.Path).ToArray() + LocalAlternateVersions = video.AlternateVersions.Select(av => av.Files[0].Path).ToArray() }; SetVideoType(videoItem, firstVideo); @@ -331,9 +334,13 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies for (var j = 0; j < current.AlternateVersions.Count; j++) { - if (ContainsFile(current.AlternateVersions[j], file)) + var alternate = current.AlternateVersions[j]; + for (var k = 0; k < alternate.Files.Count; k++) { - return true; + if (ContainsFile(alternate.Files[k], file)) + { + return true; + } } } } diff --git a/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs index 14798dda65..74c1f69616 100644 --- a/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs @@ -1,6 +1,7 @@ #nullable disable using System; +using System.Collections.Generic; using System.IO; using System.Linq; using Jellyfin.Data.Enums; @@ -46,7 +47,16 @@ namespace Emby.Server.Implementations.Library.Resolvers } // It's a directory-based playlist if the directory contains a playlist file - var filePaths = Directory.EnumerateFiles(args.Path, "*", new EnumerationOptions { IgnoreInaccessible = true }); + IEnumerable<string> filePaths; + try + { + filePaths = Directory.EnumerateFiles(args.Path, "*", new EnumerationOptions { IgnoreInaccessible = true }); + } + catch (IOException) + { + return null; + } + if (filePaths.Any(f => f.EndsWith(PlaylistXmlSaver.DefaultPlaylistFilename, StringComparison.OrdinalIgnoreCase))) { return new Playlist diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs index c81a0adb89..8d40eab006 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs @@ -31,7 +31,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV /// </summary> /// <param name="logger">The logger.</param> /// <param name="namingOptions">The naming options.</param> - public SeriesResolver(ILogger<SeriesResolver> logger, NamingOptions namingOptions) + public SeriesResolver(ILogger<SeriesResolver> logger, NamingOptions namingOptions) { _logger = logger; _namingOptions = namingOptions; @@ -57,6 +57,11 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV return null; } + if (args.Parent is not null && args.Parent.IsRoot) + { + return null; + } + var seriesInfo = Naming.TV.SeriesResolver.Resolve(_namingOptions, args.Path); var collectionType = args.GetCollectionType(); @@ -69,7 +74,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV return new Series { Path = args.Path, - Name = seriesInfo.Name + Name = seriesInfo.Name, + ProductionYear = seriesInfo.Year }; } } diff --git a/Emby.Server.Implementations/Library/Search/SearchManager.cs b/Emby.Server.Implementations/Library/Search/SearchManager.cs new file mode 100644 index 0000000000..a5be3f07bd --- /dev/null +++ b/Emby.Server.Implementations/Library/Search/SearchManager.cs @@ -0,0 +1,458 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Jellyfin.Data.Enums; +using Jellyfin.Database.Implementations; +using Jellyfin.Database.Implementations.Entities; +using Jellyfin.Extensions; +using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Persistence; +using MediaBrowser.Model.Querying; +using MediaBrowser.Model.Search; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; + +namespace Emby.Server.Implementations.Library.Search; + +/// <summary> +/// Manages search providers and orchestrates search operations. +/// </summary> +public class SearchManager : ISearchManager +{ + private readonly ILibraryManager _libraryManager; + private readonly IUserManager _userManager; + private readonly IDbContextFactory<JellyfinDbContext> _dbProvider; + private readonly IItemQueryHelpers _queryHelpers; + private readonly ILogger<SearchManager> _logger; + private IExternalSearchProvider[] _externalProviders = []; + private IInternalSearchProvider[] _internalProviders = []; + + /// <summary> + /// Initializes a new instance of the <see cref="SearchManager"/> class. + /// </summary> + /// <param name="libraryManager">The library manager.</param> + /// <param name="userManager">The user manager.</param> + /// <param name="dbProvider">The database context factory.</param> + /// <param name="queryHelpers">The shared item query helpers.</param> + /// <param name="logger">The logger.</param> + public SearchManager( + ILibraryManager libraryManager, + IUserManager userManager, + IDbContextFactory<JellyfinDbContext> dbProvider, + IItemQueryHelpers queryHelpers, + ILogger<SearchManager> logger) + { + _libraryManager = libraryManager; + _userManager = userManager; + _dbProvider = dbProvider; + _queryHelpers = queryHelpers; + _logger = logger; + } + + /// <inheritdoc/> + public void AddParts(IEnumerable<ISearchProvider> providers) + { + var allProviders = providers.OrderBy(p => p.Priority).ToArray(); + + _externalProviders = allProviders.OfType<IExternalSearchProvider>().ToArray(); + _internalProviders = allProviders.OfType<IInternalSearchProvider>().ToArray(); + + _logger.LogInformation( + "Registered {ExternalCount} external search providers: {ExternalProviders}. Fallback providers: {FallbackProviders}", + _externalProviders.Length, + string.Join(", ", _externalProviders.Select(p => $"{p.Name} (priority {p.Priority})")), + string.Join(", ", _internalProviders.Select(p => $"{p.Name} (priority {p.Priority})"))); + } + + /// <inheritdoc/> + public IReadOnlyList<ISearchProvider> GetProviders() + { + return [.. _externalProviders, .. _internalProviders]; + } + + /// <inheritdoc/> + public async Task<IReadOnlyList<SearchResult>> GetSearchResultsAsync( + SearchProviderQuery query, + CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(query); + ArgumentException.ThrowIfNullOrWhiteSpace(query.SearchTerm); + + var searchTerm = query.SearchTerm.Trim().RemoveDiacritics(); + + var externalTask = CollectFromProvidersAsync(_externalProviders, query, searchTerm, cancellationToken); + var internalTask = _internalProviders.Length > 0 + ? CollectFromProvidersAsync(_internalProviders, query, searchTerm, cancellationToken) + : Task.FromResult<IReadOnlyList<SearchResult>>([]); + + await Task.WhenAll(externalTask, internalTask).ConfigureAwait(false); + + var externalResults = await externalTask.ConfigureAwait(false); + var fromExternal = externalResults.Count > 0; + IReadOnlyList<SearchResult> results; + if (fromExternal) + { + results = externalResults; + } + else + { + results = await internalTask.ConfigureAwait(false); + if (_internalProviders.Length > 0) + { + _logger.LogDebug("No results from external providers, using internal provider results"); + } + } + + // Internal providers apply user-access filtering inline in their queries. External + // providers don't know about user permissions, so they may return IDs from hidden + // libraries or items the user is otherwise blocked from. Run the post-filter only + // when results came from externals to close that gap. The Items controller's second + // roundtrip via folder.GetItems applies most of these again, but it does not restrict + // by TopParentIds when ItemIds is set. + if (fromExternal && results.Count > 0 && query.UserId.HasValue && !query.UserId.Value.IsEmpty()) + { + var user = _userManager.GetUserById(query.UserId.Value); + if (user is not null) + { + results = await FilterByUserAccessAsync(results, user, cancellationToken).ConfigureAwait(false); + } + } + + return results; + } + + private async Task<IReadOnlyList<SearchResult>> FilterByUserAccessAsync( + IReadOnlyList<SearchResult> candidates, + User user, + CancellationToken cancellationToken) + { + // SetUser populates parental rating + blocked/allowed tags. ConfigureUserAccess populates + // TopParentIds for the user's accessible libraries — we call it before assigning ItemIds + // because LibraryManager.AddUserToQuery skips TopParentIds when ItemIds is non-empty. + var accessFilter = new InternalItemsQuery(user); + _libraryManager.ConfigureUserAccess(accessFilter, user); + + Guid[] candidateIds = [.. candidates.Select(c => c.ItemId)]; + + var dbContext = await _dbProvider.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); + await using (dbContext.ConfigureAwait(false)) + { + var baseQuery = dbContext.BaseItems + .AsNoTracking() + .WhereOneOrMany(candidateIds, e => e.Id); + + baseQuery = _queryHelpers.ApplyAccessFiltering(dbContext, baseQuery, accessFilter); + + var allowedCount = await baseQuery.CountAsync(cancellationToken).ConfigureAwait(false); + if (allowedCount == candidates.Count) + { + return candidates; + } + + var allowedIds = await baseQuery + .Select(e => e.Id) + .ToHashSetAsync(cancellationToken) + .ConfigureAwait(false); + + var filtered = candidates.Where(c => allowedIds.Contains(c.ItemId)).ToList(); + if (filtered.Count < candidates.Count) + { + _logger.LogDebug( + "Dropped {Dropped} of {Total} search candidates due to user access filtering", + candidates.Count - filtered.Count, + candidates.Count); + } + + return filtered; + } + } + + /// <inheritdoc/> + public async Task<QueryResult<SearchHintInfo>> GetSearchHintsAsync(SearchQuery query, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(query); + ArgumentException.ThrowIfNullOrWhiteSpace(query.SearchTerm); + + var providerQuery = BuildProviderQuery(query); + var candidates = await GetSearchResultsAsync(providerQuery, cancellationToken).ConfigureAwait(false); + if (candidates.Count == 0) + { + return new QueryResult<SearchHintInfo>(); + } + + var candidateScores = BuildScoreLookup(candidates); + var user = query.UserId.IsEmpty() ? null : _userManager.GetUserById(query.UserId); + + var excludeItemTypes = BuildExcludeItemTypes(query); + var includeItemTypes = BuildIncludeItemTypes(query); + + var internalQuery = new InternalItemsQuery(user) + { + ItemIds = candidateScores.Keys.ToArray(), + ExcludeItemTypes = excludeItemTypes.ToArray(), + IncludeItemTypes = includeItemTypes.Count > 0 ? includeItemTypes.ToArray() : [], + MediaTypes = query.MediaTypes.ToArray(), + IncludeItemsByName = !query.ParentId.HasValue, + ParentId = query.ParentId ?? Guid.Empty, + Recursive = true, + IsKids = query.IsKids, + IsMovie = query.IsMovie, + IsNews = query.IsNews, + IsSeries = query.IsSeries, + IsSports = query.IsSports, + DtoOptions = new DtoOptions + { + Fields = + [ + ItemFields.AirTime, + ItemFields.DateCreated, + ItemFields.ChannelInfo, + ItemFields.ParentId + ] + } + }; + + // MusicArtist items are "ItemsByName" entities - virtual items that aggregate content by artist name + // rather than being stored as regular library items. They require special handling: + // 1. Convert ParentId to AncestorIds (to filter by library folder) + // 2. Set IncludeItemsByName = true (to include these virtual items in results) + // 3. Clear IncludeItemTypes (GetAllArtists handles type filtering internally) + // 4. Use GetAllArtists() instead of GetItemList() to query the artist index + IReadOnlyList<BaseItem> items; + if (internalQuery.IncludeItemTypes.Length == 1 && internalQuery.IncludeItemTypes[0] == BaseItemKind.MusicArtist) + { + if (!internalQuery.ParentId.IsEmpty()) + { + internalQuery.AncestorIds = [internalQuery.ParentId]; + internalQuery.ParentId = Guid.Empty; + } + + internalQuery.IncludeItemsByName = true; + internalQuery.IncludeItemTypes = []; + items = _libraryManager.GetAllArtists(internalQuery).Items.Select(i => i.Item).ToList(); + } + else + { + items = _libraryManager.GetItemList(internalQuery); + } + + var orderedResults = items + .Select(item => new SearchHintInfo { Item = item }) + .OrderByDescending(hint => candidateScores.GetValueOrDefault(hint.Item.Id, 0f)) + .ToList(); + + var totalCount = orderedResults.Count; + + if (query.StartIndex.HasValue) + { + orderedResults = orderedResults.Skip(query.StartIndex.Value).ToList(); + } + + if (query.Limit.HasValue) + { + orderedResults = orderedResults.Take(query.Limit.Value).ToList(); + } + + return new QueryResult<SearchHintInfo>(query.StartIndex, totalCount, orderedResults); + } + + private async Task<IReadOnlyList<SearchResult>> CollectFromProvidersAsync( + IEnumerable<ISearchProvider> providers, + SearchProviderQuery providerQuery, + string searchTerm, + CancellationToken cancellationToken) + { + var requestedLimit = providerQuery.Limit ?? 100; + var applicable = providers.Where(p => p.CanSearch(providerQuery)).ToArray(); + if (applicable.Length == 0) + { + return []; + } + + var perProvider = await Task.WhenAll( + applicable.Select(p => CollectFromProviderAsync(p, providerQuery, searchTerm, requestedLimit, cancellationToken))) + .ConfigureAwait(false); + + var bestScores = new Dictionary<Guid, float>(); + foreach (var providerResults in perProvider) + { + foreach (var result in providerResults) + { + UpdateBestScore(bestScores, result); + } + } + + return bestScores + .Select(kvp => new SearchResult(kvp.Key, kvp.Value)) + .OrderByDescending(r => r.Score) + .Take(requestedLimit) + .ToList(); + } + + private async Task<IReadOnlyList<SearchResult>> CollectFromProviderAsync( + ISearchProvider provider, + SearchProviderQuery providerQuery, + string searchTerm, + int requestedLimit, + CancellationToken cancellationToken) + { + try + { + var results = provider is IExternalSearchProvider externalProvider + ? await CollectFromExternalProviderAsync(externalProvider, providerQuery, requestedLimit, cancellationToken).ConfigureAwait(false) + : await provider.SearchAsync(providerQuery, cancellationToken).ConfigureAwait(false); + + _logger.LogDebug( + "Provider {Provider} returned {Count} candidates for search term '{SearchTerm}'", + provider.Name, + results.Count, + searchTerm); + return results; + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Search provider {Provider} failed for term '{SearchTerm}'", provider.Name, searchTerm); + return []; + } + } + + private static async Task<IReadOnlyList<SearchResult>> CollectFromExternalProviderAsync( + IExternalSearchProvider provider, + SearchProviderQuery providerQuery, + int requestedLimit, + CancellationToken cancellationToken) + { + var results = new List<SearchResult>(); + await foreach (var result in provider.SearchAsync(providerQuery, cancellationToken).ConfigureAwait(false)) + { + results.Add(result); + if (results.Count >= requestedLimit) + { + break; + } + } + + return results; + } + + private static void UpdateBestScore(Dictionary<Guid, float> bestScores, SearchResult result) + { + if (!bestScores.TryGetValue(result.ItemId, out var existingScore) || result.Score > existingScore) + { + bestScores[result.ItemId] = result.Score; + } + } + + private static Dictionary<Guid, float> BuildScoreLookup(IReadOnlyList<SearchResult> results) + { + var lookup = new Dictionary<Guid, float>(results.Count); + foreach (var result in results) + { + lookup[result.ItemId] = result.Score; + } + + return lookup; + } + + private static SearchProviderQuery BuildProviderQuery(SearchQuery query) + { + var excludeItemTypes = BuildExcludeItemTypes(query); + var includeItemTypes = BuildIncludeItemTypes(query); + + // Remove any excluded types from includes + if (includeItemTypes.Count > 0 && excludeItemTypes.Count > 0) + { + includeItemTypes.RemoveAll(excludeItemTypes.Contains); + } + + return new SearchProviderQuery + { + SearchTerm = query.SearchTerm, + UserId = query.UserId.IsEmpty() ? null : query.UserId, + IncludeItemTypes = includeItemTypes.ToArray(), + ExcludeItemTypes = excludeItemTypes.ToArray(), + MediaTypes = query.MediaTypes.ToArray(), + Limit = query.Limit, + ParentId = query.ParentId + }; + } + + private static List<BaseItemKind> BuildExcludeItemTypes(SearchQuery query) + { + var excludeItemTypes = query.ExcludeItemTypes.ToList(); + + excludeItemTypes.Add(BaseItemKind.Year); + excludeItemTypes.Add(BaseItemKind.Folder); + excludeItemTypes.Add(BaseItemKind.CollectionFolder); + + if (!query.IncludeGenres) + { + AddIfMissing(excludeItemTypes, BaseItemKind.Genre); + AddIfMissing(excludeItemTypes, BaseItemKind.MusicGenre); + } + + if (!query.IncludePeople) + { + AddIfMissing(excludeItemTypes, BaseItemKind.Person); + } + + if (!query.IncludeStudios) + { + AddIfMissing(excludeItemTypes, BaseItemKind.Studio); + } + + if (!query.IncludeArtists) + { + AddIfMissing(excludeItemTypes, BaseItemKind.MusicArtist); + } + + return excludeItemTypes; + } + + private static List<BaseItemKind> BuildIncludeItemTypes(SearchQuery query) + { + var includeItemTypes = query.IncludeItemTypes.ToList(); + if (query.IncludeMedia) + { + return includeItemTypes; + } + + if (query.IncludeGenres && IsEmptyOrContains(includeItemTypes, BaseItemKind.Genre)) + { + AddIfMissing(includeItemTypes, BaseItemKind.Genre); + AddIfMissing(includeItemTypes, BaseItemKind.MusicGenre); + } + + if (query.IncludePeople && IsEmptyOrContains(includeItemTypes, BaseItemKind.Person)) + { + AddIfMissing(includeItemTypes, BaseItemKind.Person); + } + + if (query.IncludeStudios && IsEmptyOrContains(includeItemTypes, BaseItemKind.Studio)) + { + AddIfMissing(includeItemTypes, BaseItemKind.Studio); + } + + if (query.IncludeArtists && IsEmptyOrContains(includeItemTypes, BaseItemKind.MusicArtist)) + { + AddIfMissing(includeItemTypes, BaseItemKind.MusicArtist); + } + + return includeItemTypes; + } + + private static bool IsEmptyOrContains(List<BaseItemKind> list, BaseItemKind value) + => list.Count == 0 || list.Contains(value); + + private static void AddIfMissing(List<BaseItemKind> list, BaseItemKind value) + { + if (!list.Contains(value)) + { + list.Add(value); + } + } +} diff --git a/Emby.Server.Implementations/Library/Search/SqlSearchProvider.cs b/Emby.Server.Implementations/Library/Search/SqlSearchProvider.cs new file mode 100644 index 0000000000..bc766f1c8c --- /dev/null +++ b/Emby.Server.Implementations/Library/Search/SqlSearchProvider.cs @@ -0,0 +1,230 @@ +#pragma warning disable RS0030 // Do not use banned APIs +#pragma warning disable CA1862 // Use the 'StringComparison' method overloads to perform case-insensitive string comparisons + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Jellyfin.Data.Enums; +using Jellyfin.Database.Implementations; +using Jellyfin.Database.Implementations.Entities; +using Jellyfin.Extensions; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Persistence; +using MediaBrowser.Model.Configuration; +using Microsoft.EntityFrameworkCore; + +namespace Emby.Server.Implementations.Library.Search; + +/// <summary> +/// Built-in SQL-based search provider that queries the library database directly. +/// </summary> +public class SqlSearchProvider : IInternalSearchProvider +{ + private const int DefaultSearchLimit = 100; + private const float ExactMatchScore = 100f; + private const float PrefixMatchScore = 80f; + private const float WordPrefixMatchScore = 75f; + private const float ContainsMatchScore = 50f; + + private static readonly Guid _placeholderId = Guid.Parse("00000000-0000-0000-0000-000000000001"); + + private readonly IDbContextFactory<JellyfinDbContext> _dbProvider; + private readonly IItemTypeLookup _itemTypeLookup; + private readonly ILibraryManager _libraryManager; + private readonly IUserManager _userManager; + private readonly IItemQueryHelpers _queryHelpers; + + /// <summary> + /// Initializes a new instance of the <see cref="SqlSearchProvider"/> class. + /// </summary> + /// <param name="dbProvider">The database context factory.</param> + /// <param name="itemTypeLookup">The item type lookup.</param> + /// <param name="libraryManager">The library manager.</param> + /// <param name="userManager">The user manager.</param> + /// <param name="queryHelpers">The shared item query helpers.</param> + public SqlSearchProvider( + IDbContextFactory<JellyfinDbContext> dbProvider, + IItemTypeLookup itemTypeLookup, + ILibraryManager libraryManager, + IUserManager userManager, + IItemQueryHelpers queryHelpers) + { + _dbProvider = dbProvider; + _itemTypeLookup = itemTypeLookup; + _libraryManager = libraryManager; + _userManager = userManager; + _queryHelpers = queryHelpers; + } + + /// <inheritdoc/> + public string Name => "Database"; + + /// <inheritdoc/> + public MetadataPluginType Type => MetadataPluginType.SearchProvider; + + /// <inheritdoc/> + public int Priority => 100; // Low priority - runs as fallback + + /// <inheritdoc/> + public bool CanSearch(SearchProviderQuery query) + { + // SQL search can always handle any query + return true; + } + + /// <inheritdoc/> + public async Task<IReadOnlyList<SearchResult>> SearchAsync(SearchProviderQuery query, CancellationToken cancellationToken) + { + ArgumentNullException.ThrowIfNull(query); + ArgumentException.ThrowIfNullOrWhiteSpace(query.SearchTerm); + + var rawSearchTerm = query.SearchTerm.Trim().RemoveDiacritics(); + if (string.IsNullOrEmpty(rawSearchTerm)) + { + return []; + } + + var cleanSearchTerm = rawSearchTerm.GetCleanValue(); + if (string.IsNullOrEmpty(cleanSearchTerm)) + { + return []; + } + + var cleanPrefix = cleanSearchTerm + " "; + // OriginalTitle is stored mixed-case and isn't pre-normalized like CleanName, + // so match it via a case-insensitive LIKE rather than a per-row case conversion + // that may not translate to SQL on every provider. + var likeOriginal = $"%{rawSearchTerm}%"; + var limit = query.Limit ?? DefaultSearchLimit; + + var dbContext = await _dbProvider.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); + await using (dbContext.ConfigureAwait(false)) + { + // Lightweight projection: select only what's needed to score and identify items. + var dbQuery = dbContext.BaseItems + .AsNoTracking() + .Where(e => e.Id != _placeholderId) + .Where(e => !e.IsVirtualItem) + .Where(e => e.CleanName!.Contains(cleanSearchTerm) + || (e.OriginalTitle != null && EF.Functions.Like(e.OriginalTitle, likeOriginal))); + + dbQuery = ApplyTypeFilter(dbQuery, query.IncludeItemTypes, query.ExcludeItemTypes); + dbQuery = ApplyMediaTypeFilter(dbQuery, query.MediaTypes); + dbQuery = ApplyParentFilter(dbQuery, query.ParentId); + dbQuery = ApplyUserAccessFilter(dbContext, dbQuery, query.UserId); + + // Compute the score in SQL: the ternary translates to a CASE WHEN. CleanName is + // the pre-normalized (lowercase, diacritic-stripped) form, so we score against it + // directly without any per-row case conversion. Items that match only via + // OriginalTitle fall through to the Contains tier. + // Tie-break by Id for deterministic ordering so the explicit OrderBy + Take + // satisfies EF Core's row-limiting-with-OrderBy requirement. + var scored = dbQuery.Select(e => new + { + e.Id, + Score = + (e.CleanName == cleanSearchTerm) ? ExactMatchScore + : e.CleanName!.StartsWith(cleanSearchTerm) ? PrefixMatchScore + : e.CleanName!.Contains(cleanPrefix) ? WordPrefixMatchScore + : ContainsMatchScore + }); + + return await scored + .OrderByDescending(x => x.Score) + .ThenBy(x => x.Id) + .Take(limit) + .Select(x => new SearchResult(x.Id, x.Score)) + .ToArrayAsync(cancellationToken) + .ConfigureAwait(false); + } + } + + private IQueryable<BaseItemEntity> ApplyTypeFilter( + IQueryable<BaseItemEntity> query, + BaseItemKind[] includeItemTypes, + BaseItemKind[] excludeItemTypes) + { + if (includeItemTypes.Length > 0) + { + var includeTypeNames = MapKindsToTypeNames(includeItemTypes); + if (includeTypeNames.Count > 0) + { + query = query.Where(e => includeTypeNames.Contains(e.Type)); + } + } + else if (excludeItemTypes.Length > 0) + { + var excludeTypeNames = MapKindsToTypeNames(excludeItemTypes); + if (excludeTypeNames.Count > 0) + { + query = query.Where(e => !excludeTypeNames.Contains(e.Type)); + } + } + + return query; + } + + private static IQueryable<BaseItemEntity> ApplyMediaTypeFilter( + IQueryable<BaseItemEntity> query, + MediaType[] mediaTypes) + { + if (mediaTypes.Length == 0) + { + return query; + } + + var mediaTypeNames = mediaTypes.Select(m => m.ToString()).ToArray(); + return query.Where(e => e.MediaType != null && mediaTypeNames.Contains(e.MediaType)); + } + + private static IQueryable<BaseItemEntity> ApplyParentFilter( + IQueryable<BaseItemEntity> query, + Guid? parentId) + { + if (!parentId.HasValue || parentId.Value.IsEmpty()) + { + return query; + } + + var pid = parentId.Value; + return query.Where(e => e.ParentId == pid || e.Parents!.Any(p => p.ParentItemId == pid)); + } + + private IQueryable<BaseItemEntity> ApplyUserAccessFilter( + JellyfinDbContext dbContext, + IQueryable<BaseItemEntity> query, + Guid? userId) + { + if (!userId.HasValue || userId.Value.IsEmpty()) + { + return query; + } + + var user = _userManager.GetUserById(userId.Value); + if (user is null) + { + return query; + } + + var accessFilter = new InternalItemsQuery(user); + _libraryManager.ConfigureUserAccess(accessFilter, user); + return _queryHelpers.ApplyAccessFiltering(dbContext, query, accessFilter); + } + + private List<string> MapKindsToTypeNames(BaseItemKind[] kinds) + { + var list = new List<string>(kinds.Length); + foreach (var kind in kinds) + { + if (_itemTypeLookup.BaseItemKindNames.TryGetValue(kind, out var name) && name is not null) + { + list.Add(name); + } + } + + return list; + } +} diff --git a/Emby.Server.Implementations/Library/SearchEngine.cs b/Emby.Server.Implementations/Library/SearchEngine.cs deleted file mode 100644 index c682118597..0000000000 --- a/Emby.Server.Implementations/Library/SearchEngine.cs +++ /dev/null @@ -1,200 +0,0 @@ -#pragma warning disable CS1591 - -using System; -using System.Collections.Generic; -using System.Linq; -using Jellyfin.Data.Enums; -using Jellyfin.Database.Implementations.Entities; -using Jellyfin.Database.Implementations.Enums; -using Jellyfin.Extensions; -using MediaBrowser.Controller.Dto; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Querying; -using MediaBrowser.Model.Search; - -namespace Emby.Server.Implementations.Library -{ - public class SearchEngine : ISearchEngine - { - private readonly ILibraryManager _libraryManager; - private readonly IUserManager _userManager; - - public SearchEngine(ILibraryManager libraryManager, IUserManager userManager) - { - _libraryManager = libraryManager; - _userManager = userManager; - } - - public QueryResult<SearchHintInfo> GetSearchHints(SearchQuery query) - { - User? user = null; - if (!query.UserId.IsEmpty()) - { - user = _userManager.GetUserById(query.UserId); - } - - var results = GetSearchHints(query, user); - var totalRecordCount = results.Count; - - if (query.StartIndex.HasValue) - { - results = results.GetRange(query.StartIndex.Value, totalRecordCount - query.StartIndex.Value); - } - - if (query.Limit.HasValue && query.Limit.Value > 0) - { - results = results.GetRange(0, Math.Min(query.Limit.Value, results.Count)); - } - - return new QueryResult<SearchHintInfo>( - query.StartIndex, - totalRecordCount, - results); - } - - private static void AddIfMissing(List<BaseItemKind> list, BaseItemKind value) - { - if (!list.Contains(value)) - { - list.Add(value); - } - } - - /// <summary> - /// Gets the search hints. - /// </summary> - /// <param name="query">The query.</param> - /// <param name="user">The user.</param> - /// <returns>IEnumerable{SearchHintResult}.</returns> - /// <exception cref="ArgumentException"><c>query.SearchTerm</c> is <c>null</c> or empty.</exception> - private List<SearchHintInfo> GetSearchHints(SearchQuery query, User? user) - { - var searchTerm = query.SearchTerm; - - ArgumentException.ThrowIfNullOrEmpty(searchTerm); - - searchTerm = searchTerm.Trim().RemoveDiacritics(); - - var excludeItemTypes = query.ExcludeItemTypes.ToList(); - var includeItemTypes = query.IncludeItemTypes.ToList(); - - excludeItemTypes.Add(BaseItemKind.Year); - excludeItemTypes.Add(BaseItemKind.Folder); - - if (query.IncludeGenres && (includeItemTypes.Count == 0 || includeItemTypes.Contains(BaseItemKind.Genre))) - { - if (!query.IncludeMedia) - { - AddIfMissing(includeItemTypes, BaseItemKind.Genre); - AddIfMissing(includeItemTypes, BaseItemKind.MusicGenre); - } - } - else - { - AddIfMissing(excludeItemTypes, BaseItemKind.Genre); - AddIfMissing(excludeItemTypes, BaseItemKind.MusicGenre); - } - - if (query.IncludePeople && (includeItemTypes.Count == 0 || includeItemTypes.Contains(BaseItemKind.Person))) - { - if (!query.IncludeMedia) - { - AddIfMissing(includeItemTypes, BaseItemKind.Person); - } - } - else - { - AddIfMissing(excludeItemTypes, BaseItemKind.Person); - } - - if (query.IncludeStudios && (includeItemTypes.Count == 0 || includeItemTypes.Contains(BaseItemKind.Studio))) - { - if (!query.IncludeMedia) - { - AddIfMissing(includeItemTypes, BaseItemKind.Studio); - } - } - else - { - AddIfMissing(excludeItemTypes, BaseItemKind.Studio); - } - - if (query.IncludeArtists && (includeItemTypes.Count == 0 || includeItemTypes.Contains(BaseItemKind.MusicArtist))) - { - if (!query.IncludeMedia) - { - AddIfMissing(includeItemTypes, BaseItemKind.MusicArtist); - } - } - else - { - AddIfMissing(excludeItemTypes, BaseItemKind.MusicArtist); - } - - AddIfMissing(excludeItemTypes, BaseItemKind.CollectionFolder); - AddIfMissing(excludeItemTypes, BaseItemKind.Folder); - var mediaTypes = query.MediaTypes.ToList(); - - if (includeItemTypes.Count > 0) - { - excludeItemTypes.Clear(); - mediaTypes.Clear(); - } - - var searchQuery = new InternalItemsQuery(user) - { - SearchTerm = searchTerm, - ExcludeItemTypes = excludeItemTypes.ToArray(), - IncludeItemTypes = includeItemTypes.ToArray(), - Limit = query.Limit, - IncludeItemsByName = !query.ParentId.HasValue, - ParentId = query.ParentId ?? Guid.Empty, - OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Ascending) }, - Recursive = true, - - IsKids = query.IsKids, - IsMovie = query.IsMovie, - IsNews = query.IsNews, - IsSeries = query.IsSeries, - IsSports = query.IsSports, - MediaTypes = mediaTypes.ToArray(), - - DtoOptions = new DtoOptions - { - Fields = new ItemFields[] - { - ItemFields.AirTime, - ItemFields.DateCreated, - ItemFields.ChannelInfo, - ItemFields.ParentId - } - } - }; - - IReadOnlyList<BaseItem> mediaItems; - - if (searchQuery.IncludeItemTypes.Length == 1 && searchQuery.IncludeItemTypes[0] == BaseItemKind.MusicArtist) - { - if (!searchQuery.ParentId.IsEmpty()) - { - searchQuery.AncestorIds = [searchQuery.ParentId]; - searchQuery.ParentId = Guid.Empty; - } - - searchQuery.IncludeItemsByName = true; - searchQuery.IncludeItemTypes = Array.Empty<BaseItemKind>(); - mediaItems = _libraryManager.GetAllArtists(searchQuery).Items.Select(i => i.Item).ToList(); - } - else - { - mediaItems = _libraryManager.GetItemList(searchQuery); - } - - return mediaItems.Select(i => new SearchHintInfo - { - Item = i - }).ToList(); - } - } -} diff --git a/Emby.Server.Implementations/Library/SimilarItems/AudioSimilarItemsProvider.cs b/Emby.Server.Implementations/Library/SimilarItems/AudioSimilarItemsProvider.cs new file mode 100644 index 0000000000..1cc670b8ee --- /dev/null +++ b/Emby.Server.Implementations/Library/SimilarItems/AudioSimilarItemsProvider.cs @@ -0,0 +1,55 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Jellyfin.Data.Enums; +using Jellyfin.Database.Implementations.Enums; +using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Configuration; + +namespace Emby.Server.Implementations.Library.SimilarItems; + +/// <summary> +/// Provides similar items for audio tracks. +/// </summary> +public class AudioSimilarItemsProvider : ILocalSimilarItemsProvider<Audio> +{ + private readonly ILibraryManager _libraryManager; + + /// <summary> + /// Initializes a new instance of the <see cref="AudioSimilarItemsProvider"/> class. + /// </summary> + /// <param name="libraryManager">The library manager.</param> + public AudioSimilarItemsProvider(ILibraryManager libraryManager) + { + _libraryManager = libraryManager; + } + + /// <inheritdoc/> + public string Name => "Local Genre/Tag"; + + /// <inheritdoc/> + public MetadataPluginType Type => MetadataPluginType.LocalSimilarityProvider; + + /// <inheritdoc/> + public Task<IReadOnlyList<BaseItem>> GetSimilarItemsAsync(Audio item, SimilarItemsQuery query, CancellationToken cancellationToken) + { + var internalQuery = new InternalItemsQuery(query.User) + { + Genres = item.Genres, + Tags = item.Tags, + Limit = query.Limit, + DtoOptions = query.DtoOptions ?? new DtoOptions(), + ExcludeItemIds = [.. query.ExcludeItemIds], + ExcludeArtistIds = [.. query.ExcludeArtistIds], + IncludeItemTypes = [BaseItemKind.Audio], + EnableGroupByMetadataKey = false, + EnableTotalRecordCount = true, + OrderBy = [(ItemSortBy.Random, SortOrder.Ascending)] + }; + + return Task.FromResult(_libraryManager.GetItemList(internalQuery)); + } +} diff --git a/Emby.Server.Implementations/Library/SimilarItems/LiveTvProgramSimilarItemsProvider.cs b/Emby.Server.Implementations/Library/SimilarItems/LiveTvProgramSimilarItemsProvider.cs new file mode 100644 index 0000000000..7665ee2f79 --- /dev/null +++ b/Emby.Server.Implementations/Library/SimilarItems/LiveTvProgramSimilarItemsProvider.cs @@ -0,0 +1,94 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Jellyfin.Data.Enums; +using Jellyfin.Database.Implementations.Enums; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Model.Configuration; + +namespace Emby.Server.Implementations.Library.SimilarItems; + +/// <summary> +/// Provides similar items for Live TV programs. +/// </summary> +public class LiveTvProgramSimilarItemsProvider : ILocalSimilarItemsProvider<LiveTvProgram> +{ + private readonly ILibraryManager _libraryManager; + private readonly IServerConfigurationManager _serverConfigurationManager; + + /// <summary> + /// Initializes a new instance of the <see cref="LiveTvProgramSimilarItemsProvider"/> class. + /// </summary> + /// <param name="libraryManager">The library manager.</param> + /// <param name="serverConfigurationManager">The server configuration manager.</param> + public LiveTvProgramSimilarItemsProvider( + ILibraryManager libraryManager, + IServerConfigurationManager serverConfigurationManager) + { + _libraryManager = libraryManager; + _serverConfigurationManager = serverConfigurationManager; + } + + /// <inheritdoc/> + public string Name => "Local Genre/Tag"; + + /// <inheritdoc/> + public MetadataPluginType Type => MetadataPluginType.LocalSimilarityProvider; + + /// <inheritdoc/> + public Task<IReadOnlyList<BaseItem>> GetSimilarItemsAsync(LiveTvProgram item, SimilarItemsQuery query, CancellationToken cancellationToken) + { + BaseItemKind[] includeItemTypes; + bool enableGroupByMetadataKey; + bool enableTotalRecordCount; + + if (item.IsMovie) + { + // Movie-like program + var itemTypes = new List<BaseItemKind> { BaseItemKind.Movie }; + + if (_serverConfigurationManager.Configuration.EnableExternalContentInSuggestions) + { + itemTypes.Add(BaseItemKind.Trailer); + itemTypes.Add(BaseItemKind.LiveTvProgram); + } + + includeItemTypes = [.. itemTypes]; + enableGroupByMetadataKey = true; + enableTotalRecordCount = false; + } + else if (item.IsSeries) + { + // Series-like program + includeItemTypes = [BaseItemKind.Series]; + enableGroupByMetadataKey = false; + enableTotalRecordCount = true; + } + else + { + // Default - match same type + includeItemTypes = [item.GetBaseItemKind()]; + enableGroupByMetadataKey = false; + enableTotalRecordCount = true; + } + + var internalQuery = new InternalItemsQuery(query.User) + { + Genres = item.Genres, + Tags = item.Tags, + Limit = query.Limit, + DtoOptions = query.DtoOptions ?? new DtoOptions(), + ExcludeItemIds = [.. query.ExcludeItemIds], + IncludeItemTypes = includeItemTypes, + EnableGroupByMetadataKey = enableGroupByMetadataKey, + EnableTotalRecordCount = enableTotalRecordCount, + OrderBy = [(ItemSortBy.Random, SortOrder.Ascending)] + }; + + return Task.FromResult(_libraryManager.GetItemList(internalQuery)); + } +} diff --git a/Emby.Server.Implementations/Library/SimilarItems/MovieSimilarItemsProvider.cs b/Emby.Server.Implementations/Library/SimilarItems/MovieSimilarItemsProvider.cs new file mode 100644 index 0000000000..57d1f7c770 --- /dev/null +++ b/Emby.Server.Implementations/Library/SimilarItems/MovieSimilarItemsProvider.cs @@ -0,0 +1,342 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Jellyfin.Data.Enums; +using Jellyfin.Database.Implementations; +using Jellyfin.Database.Implementations.Entities; +using Jellyfin.Extensions; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Persistence; +using MediaBrowser.Model.Configuration; +using Microsoft.EntityFrameworkCore; +using BaseItemDto = MediaBrowser.Controller.Entities.BaseItem; + +namespace Emby.Server.Implementations.Library.SimilarItems; + +/// <summary> +/// Provides similar items for movies and trailers using weighted scoring. +/// </summary> +public sealed class MovieSimilarItemsProvider : ILocalSimilarItemsProvider<Movie>, ILocalSimilarItemsProvider<Trailer>, IBatchLocalSimilarItemsProvider +{ + private const int GenreWeight = 10; + private const int TagWeight = 5; + private const int StudioWeight = 5; + private const int DirectorWeight = 50; + private const int ActorWeight = 15; + + // Caps the batch fan-out so downstream IN-list sizes (per-source scores, accessible-id + // load, navigation includes) stay bounded regardless of caller input. + private const int MaxBatchSourceItems = 64; + + private static readonly (ItemValueType Type, int Weight)[] _itemValueDimensions = + [ + (ItemValueType.Genre, GenreWeight), + (ItemValueType.Tags, TagWeight), + (ItemValueType.Studios, StudioWeight) + ]; + + private static readonly Dictionary<string, int> _personTypeWeights = new(StringComparer.Ordinal) + { + [nameof(PersonKind.Director)] = DirectorWeight, + [nameof(PersonKind.Actor)] = ActorWeight, + [nameof(PersonKind.GuestStar)] = ActorWeight, + }; + + private static readonly string[] _scoredPersonTypes = [.. _personTypeWeights.Keys]; + + private readonly IDbContextFactory<JellyfinDbContext> _dbProvider; + private readonly IItemQueryHelpers _queryHelpers; + private readonly IServerConfigurationManager _serverConfigurationManager; + private readonly ILibraryManager _libraryManager; + + /// <summary> + /// Initializes a new instance of the <see cref="MovieSimilarItemsProvider"/> class. + /// </summary> + /// <param name="dbProvider">The database context factory.</param> + /// <param name="queryHelpers">The shared query helpers.</param> + /// <param name="serverConfigurationManager">The server configuration manager.</param> + /// <param name="libraryManager">The library manager.</param> + public MovieSimilarItemsProvider( + IDbContextFactory<JellyfinDbContext> dbProvider, + IItemQueryHelpers queryHelpers, + IServerConfigurationManager serverConfigurationManager, + ILibraryManager libraryManager) + { + _dbProvider = dbProvider; + _queryHelpers = queryHelpers; + _serverConfigurationManager = serverConfigurationManager; + _libraryManager = libraryManager; + } + + /// <inheritdoc/> + public string Name => "Local Genre/Tag"; + + /// <inheritdoc/> + public MetadataPluginType Type => MetadataPluginType.LocalSimilarityProvider; + + /// <inheritdoc/> + public async Task<IReadOnlyList<BaseItemDto>> GetSimilarItemsAsync(Movie item, SimilarItemsQuery query, CancellationToken cancellationToken) + { + var results = await GetBatchSimilarItemsAsync([item], query, cancellationToken).ConfigureAwait(false); + return results.TryGetValue(item.Id, out var items) ? items : []; + } + + /// <inheritdoc/> + public async Task<IReadOnlyList<BaseItemDto>> GetSimilarItemsAsync(Trailer item, SimilarItemsQuery query, CancellationToken cancellationToken) + { + var results = await GetBatchSimilarItemsAsync([item], query, cancellationToken).ConfigureAwait(false); + return results.TryGetValue(item.Id, out var items) ? items : []; + } + + bool ILocalSimilarItemsProvider.Supports(Type itemType) + => typeof(Movie).IsAssignableFrom(itemType) || typeof(Trailer).IsAssignableFrom(itemType); + + Task<IReadOnlyList<BaseItem>> ILocalSimilarItemsProvider.GetSimilarItemsAsync(BaseItem item, SimilarItemsQuery query, CancellationToken cancellationToken) + => item switch + { + Movie movie => GetSimilarItemsAsync(movie, query, cancellationToken), + Trailer trailer => GetSimilarItemsAsync(trailer, query, cancellationToken), + _ => throw new ArgumentException($"Unsupported item type {item.GetType()}", nameof(item)) + }; + + /// <inheritdoc/> + public async Task<Dictionary<Guid, IReadOnlyList<BaseItemDto>>> GetBatchSimilarItemsAsync( + IReadOnlyList<BaseItemDto> sourceItems, + SimilarItemsQuery query, + CancellationToken cancellationToken) + { + var includeItemTypes = new List<BaseItemKind> { BaseItemKind.Movie }; + if (_serverConfigurationManager.Configuration.EnableExternalContentInSuggestions) + { + includeItemTypes.Add(BaseItemKind.Trailer); + includeItemTypes.Add(BaseItemKind.LiveTvProgram); + } + + var limit = query.Limit ?? 50; + var dtoOptions = query.DtoOptions ?? new DtoOptions(); + + if (sourceItems.Count > MaxBatchSourceItems) + { + sourceItems = sourceItems.Take(MaxBatchSourceItems).ToList(); + } + + var context = await _dbProvider.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); + await using (context.ConfigureAwait(false)) + { + // Phase 1: Score all candidates per source item + var sourceIds = sourceItems.Select(i => i.Id).ToList(); + var perSourceScores = await ComputeBatchScoresAsync(sourceIds, context, cancellationToken).ConfigureAwait(false); + + var allCandidateIds = new HashSet<Guid>(); + foreach (var (_, scores) in perSourceScores) + { + allCandidateIds.UnionWith( + scores.OrderByDescending(kvp => kvp.Value) + .Take(limit * 3) + .Select(kvp => kvp.Key)); + } + + var result = new Dictionary<Guid, IReadOnlyList<BaseItemDto>>(); + if (allCandidateIds.Count == 0) + { + return result; + } + + // Phase 2: One access filter for all candidates + var filter = new InternalItemsQuery(query.User) + { + IncludeItemTypes = [.. includeItemTypes], + ExcludeItemIds = [.. query.ExcludeItemIds], + DtoOptions = dtoOptions, + EnableGroupByMetadataKey = true, + EnableTotalRecordCount = false, + IsMovie = true, + IsPlayed = false + }; + + if (query.User is not null) + { + _libraryManager.ConfigureUserAccess(filter, query.User); + } + + _queryHelpers.PrepareFilterQuery(filter); + var baseQuery = _queryHelpers.PrepareItemQuery(context, filter); + baseQuery = _queryHelpers.TranslateQuery(baseQuery, context, filter); + + var allCandidateIdsList = allCandidateIds.ToList(); + var accessibleItems = await baseQuery + .WhereOneOrMany(allCandidateIdsList, e => e.Id) + .Select(e => new { e.Id, e.PresentationUniqueKey }) + .ToListAsync(cancellationToken).ConfigureAwait(false); + + // Phase 3: Pick top IDs per source, dedup by PresentationUniqueKey + var allOrderedIds = new HashSet<Guid>(); + var perSourceOrderedIds = new Dictionary<Guid, List<Guid>>(); + + foreach (var item in sourceItems) + { + if (!perSourceScores.TryGetValue(item.Id, out var scores)) + { + continue; + } + + var orderedIds = accessibleItems + .Where(x => scores.ContainsKey(x.Id)) + .OrderByDescending(x => scores.GetValueOrDefault(x.Id)) + .DistinctBy(x => x.PresentationUniqueKey) + .Take(limit) + .Select(x => x.Id) + .ToList(); + + if (orderedIds.Count > 0) + { + perSourceOrderedIds[item.Id] = orderedIds; + allOrderedIds.UnionWith(orderedIds); + } + } + + if (allOrderedIds.Count == 0) + { + return result; + } + + // Phase 4: One entity load for all results + var allOrderedIdsList = allOrderedIds.ToList(); + var entities = await _queryHelpers.ApplyNavigations( + context.BaseItems.AsNoTracking().WhereOneOrMany(allOrderedIdsList, e => e.Id), + filter) + .AsSplitQuery() + .ToListAsync(cancellationToken).ConfigureAwait(false); + + var entitiesById = entities + .Select(e => _queryHelpers.DeserializeBaseItem(e, filter.SkipDeserialization)) + .Where(dto => dto is not null) + .ToDictionary(i => i!.Id); + + // Phase 5: Split by source, preserving score order + foreach (var (sourceId, orderedIds) in perSourceOrderedIds) + { + var items = orderedIds + .Where(entitiesById.ContainsKey) + .Select(id => entitiesById[id]!) + .ToList(); + + if (items.Count > 0) + { + result[sourceId] = items; + } + } + + return result; + } + } + + private static async Task<Dictionary<Guid, Dictionary<Guid, int>>> ComputeBatchScoresAsync(List<Guid> sourceIds, JellyfinDbContext context, CancellationToken cancellationToken) + { + var result = new Dictionary<Guid, Dictionary<Guid, int>>(); + foreach (var id in sourceIds) + { + result[id] = []; + } + + foreach (var (valueType, weight) in _itemValueDimensions) + { + var sourceRows = await context.ItemValuesMap.AsNoTracking() + .Where(m => sourceIds.Contains(m.ItemId) && m.ItemValue.Type == valueType) + .Select(m => new { m.ItemId, Key = m.ItemValue.CleanValue }) + .ToListAsync(cancellationToken).ConfigureAwait(false); + + var sourceMap = sourceRows.GroupBy(r => r.ItemId).ToDictionary(g => g.Key, g => g.Select(x => x.Key).ToHashSet()); + var allKeys = sourceMap.Values.SelectMany(v => v).Distinct().ToList(); + if (allKeys.Count == 0) + { + continue; + } + + var candidateRows = await context.ItemValuesMap.AsNoTracking() + .Where(m => m.ItemValue.Type == valueType && allKeys.Contains(m.ItemValue.CleanValue)) + .Select(m => new { m.ItemId, Key = m.ItemValue.CleanValue }) + .ToListAsync(cancellationToken).ConfigureAwait(false); + + var keyToCandidates = candidateRows.GroupBy(r => r.Key).ToDictionary(g => g.Key, g => g.Select(x => x.ItemId).ToList()); + ApplyDimensionScores(sourceIds, sourceMap, keyToCandidates, weight, result); + } + + var personSourceRows = await context.PeopleBaseItemMap.AsNoTracking() + .Where(m => sourceIds.Contains(m.ItemId) && _scoredPersonTypes.Contains(m.People.PersonType)) + .Select(m => new { m.ItemId, m.PeopleId, m.People.PersonType }) + .ToListAsync(cancellationToken).ConfigureAwait(false); + + if (personSourceRows.Count > 0) + { + var personCandidateRows = await context.PeopleBaseItemMap.AsNoTracking() + .Where(m => context.PeopleBaseItemMap + .Where(s => sourceIds.Contains(s.ItemId) && _scoredPersonTypes.Contains(s.People.PersonType)) + .Select(s => s.PeopleId) + .Contains(m.PeopleId)) + .Select(m => new { m.ItemId, m.PeopleId }) + .ToListAsync(cancellationToken).ConfigureAwait(false); + + var personToCandidates = personCandidateRows + .GroupBy(r => r.PeopleId) + .ToDictionary(g => g.Key, g => g.Select(x => x.ItemId).ToList()); + + foreach (var weightGroup in personSourceRows.GroupBy(r => _personTypeWeights[r.PersonType!])) + { + var sourceMap = weightGroup + .GroupBy(r => r.ItemId) + .ToDictionary(g => g.Key, g => g.Select(x => x.PeopleId).ToHashSet()); + ApplyDimensionScores(sourceIds, sourceMap, personToCandidates, weightGroup.Key, result); + } + } + + foreach (var sourceId in sourceIds) + { + var scoreMap = result[sourceId]; + scoreMap.Remove(sourceId); + if (scoreMap.Count == 0) + { + result.Remove(sourceId); + } + } + + return result; + } + + private static void ApplyDimensionScores<TKey>( + List<Guid> sourceIds, + Dictionary<Guid, HashSet<TKey>> sourceMap, + Dictionary<TKey, List<Guid>> keyToCandidates, + int weight, + Dictionary<Guid, Dictionary<Guid, int>> result) + where TKey : notnull + { + foreach (var sourceId in sourceIds) + { + if (!sourceMap.TryGetValue(sourceId, out var sourceKeys)) + { + continue; + } + + var scoreMap = result[sourceId]; + foreach (var key in sourceKeys) + { + if (!keyToCandidates.TryGetValue(key, out var candidates)) + { + continue; + } + + foreach (var candidateId in candidates) + { + scoreMap[candidateId] = scoreMap.GetValueOrDefault(candidateId) + weight; + } + } + } + } +} diff --git a/Emby.Server.Implementations/Library/SimilarItems/MusicAlbumSimilarItemsProvider.cs b/Emby.Server.Implementations/Library/SimilarItems/MusicAlbumSimilarItemsProvider.cs new file mode 100644 index 0000000000..c13045deda --- /dev/null +++ b/Emby.Server.Implementations/Library/SimilarItems/MusicAlbumSimilarItemsProvider.cs @@ -0,0 +1,55 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Jellyfin.Data.Enums; +using Jellyfin.Database.Implementations.Enums; +using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Configuration; + +namespace Emby.Server.Implementations.Library.SimilarItems; + +/// <summary> +/// Provides similar items for music albums. +/// </summary> +public class MusicAlbumSimilarItemsProvider : ILocalSimilarItemsProvider<MusicAlbum> +{ + private readonly ILibraryManager _libraryManager; + + /// <summary> + /// Initializes a new instance of the <see cref="MusicAlbumSimilarItemsProvider"/> class. + /// </summary> + /// <param name="libraryManager">The library manager.</param> + public MusicAlbumSimilarItemsProvider(ILibraryManager libraryManager) + { + _libraryManager = libraryManager; + } + + /// <inheritdoc/> + public string Name => "Local Genre/Tag"; + + /// <inheritdoc/> + public MetadataPluginType Type => MetadataPluginType.LocalSimilarityProvider; + + /// <inheritdoc/> + public Task<IReadOnlyList<BaseItem>> GetSimilarItemsAsync(MusicAlbum item, SimilarItemsQuery query, CancellationToken cancellationToken) + { + var internalQuery = new InternalItemsQuery(query.User) + { + Genres = item.Genres, + Tags = item.Tags, + Limit = query.Limit, + DtoOptions = query.DtoOptions ?? new DtoOptions(), + ExcludeItemIds = [.. query.ExcludeItemIds], + ExcludeArtistIds = [.. query.ExcludeArtistIds], + IncludeItemTypes = [BaseItemKind.MusicAlbum], + EnableGroupByMetadataKey = false, + EnableTotalRecordCount = true, + OrderBy = [(ItemSortBy.Random, SortOrder.Ascending)] + }; + + return Task.FromResult(_libraryManager.GetItemList(internalQuery)); + } +} diff --git a/Emby.Server.Implementations/Library/SimilarItems/MusicArtistSimilarItemsProvider.cs b/Emby.Server.Implementations/Library/SimilarItems/MusicArtistSimilarItemsProvider.cs new file mode 100644 index 0000000000..3331419442 --- /dev/null +++ b/Emby.Server.Implementations/Library/SimilarItems/MusicArtistSimilarItemsProvider.cs @@ -0,0 +1,55 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Jellyfin.Data.Enums; +using Jellyfin.Database.Implementations.Enums; +using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Configuration; + +namespace Emby.Server.Implementations.Library.SimilarItems; + +/// <summary> +/// Provides similar items for music artists. +/// </summary> +public class MusicArtistSimilarItemsProvider : ILocalSimilarItemsProvider<MusicArtist> +{ + private readonly ILibraryManager _libraryManager; + + /// <summary> + /// Initializes a new instance of the <see cref="MusicArtistSimilarItemsProvider"/> class. + /// </summary> + /// <param name="libraryManager">The library manager.</param> + public MusicArtistSimilarItemsProvider(ILibraryManager libraryManager) + { + _libraryManager = libraryManager; + } + + /// <inheritdoc/> + public string Name => "Local Genre/Tag"; + + /// <inheritdoc/> + public MetadataPluginType Type => MetadataPluginType.LocalSimilarityProvider; + + /// <inheritdoc/> + public Task<IReadOnlyList<BaseItem>> GetSimilarItemsAsync(MusicArtist item, SimilarItemsQuery query, CancellationToken cancellationToken) + { + var internalQuery = new InternalItemsQuery(query.User) + { + Genres = item.Genres, + Tags = item.Tags, + Limit = query.Limit, + DtoOptions = query.DtoOptions ?? new DtoOptions(), + ExcludeItemIds = [.. query.ExcludeItemIds], + ExcludeArtistIds = [.. query.ExcludeArtistIds], + IncludeItemTypes = [BaseItemKind.MusicArtist], + EnableGroupByMetadataKey = false, + EnableTotalRecordCount = true, + OrderBy = [(ItemSortBy.Random, SortOrder.Ascending)] + }; + + return Task.FromResult(_libraryManager.GetItemList(internalQuery)); + } +} diff --git a/Emby.Server.Implementations/Library/SimilarItems/SeriesSimilarItemsProvider.cs b/Emby.Server.Implementations/Library/SimilarItems/SeriesSimilarItemsProvider.cs new file mode 100644 index 0000000000..0366fb752e --- /dev/null +++ b/Emby.Server.Implementations/Library/SimilarItems/SeriesSimilarItemsProvider.cs @@ -0,0 +1,54 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Jellyfin.Data.Enums; +using Jellyfin.Database.Implementations.Enums; +using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Configuration; + +namespace Emby.Server.Implementations.Library.SimilarItems; + +/// <summary> +/// Provides similar items for TV series. +/// </summary> +public class SeriesSimilarItemsProvider : ILocalSimilarItemsProvider<Series> +{ + private readonly ILibraryManager _libraryManager; + + /// <summary> + /// Initializes a new instance of the <see cref="SeriesSimilarItemsProvider"/> class. + /// </summary> + /// <param name="libraryManager">The library manager.</param> + public SeriesSimilarItemsProvider(ILibraryManager libraryManager) + { + _libraryManager = libraryManager; + } + + /// <inheritdoc/> + public string Name => "Local Genre/Tag"; + + /// <inheritdoc/> + public MetadataPluginType Type => MetadataPluginType.LocalSimilarityProvider; + + /// <inheritdoc/> + public Task<IReadOnlyList<BaseItem>> GetSimilarItemsAsync(Series item, SimilarItemsQuery query, CancellationToken cancellationToken) + { + var internalQuery = new InternalItemsQuery(query.User) + { + Genres = item.Genres, + Tags = item.Tags, + Limit = query.Limit, + DtoOptions = query.DtoOptions ?? new DtoOptions(), + ExcludeItemIds = [.. query.ExcludeItemIds], + IncludeItemTypes = [BaseItemKind.Series], + EnableGroupByMetadataKey = false, + EnableTotalRecordCount = true, + OrderBy = [(ItemSortBy.Random, SortOrder.Ascending)] + }; + + return Task.FromResult(_libraryManager.GetItemList(internalQuery)); + } +} diff --git a/Emby.Server.Implementations/Library/SimilarItems/SimilarItemsManager.cs b/Emby.Server.Implementations/Library/SimilarItems/SimilarItemsManager.cs new file mode 100644 index 0000000000..d923cff07e --- /dev/null +++ b/Emby.Server.Implementations/Library/SimilarItems/SimilarItemsManager.cs @@ -0,0 +1,638 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using Jellyfin.Data.Enums; +using Jellyfin.Database.Implementations.Entities; +using Jellyfin.Database.Implementations.Enums; +using Jellyfin.Extensions.Json; +using MediaBrowser.Common.Extensions; +using MediaBrowser.Controller; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Configuration; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Querying; +using Microsoft.Extensions.Logging; + +namespace Emby.Server.Implementations.Library.SimilarItems; + +/// <summary> +/// Manages similar items providers and orchestrates similar items operations. +/// </summary> +public class SimilarItemsManager : ISimilarItemsManager +{ + private readonly ILogger<SimilarItemsManager> _logger; + private readonly IServerApplicationPaths _appPaths; + private readonly ILibraryManager _libraryManager; + private readonly IFileSystem _fileSystem; + private readonly IServerConfigurationManager _serverConfigurationManager; + private ISimilarItemsProvider[] _similarItemsProviders = []; + + /// <summary> + /// Initializes a new instance of the <see cref="SimilarItemsManager"/> class. + /// </summary> + /// <param name="logger">The logger.</param> + /// <param name="appPaths">The server application paths.</param> + /// <param name="libraryManager">The library manager.</param> + /// <param name="fileSystem">The file system.</param> + /// <param name="serverConfigurationManager">The server configuration manager.</param> + public SimilarItemsManager( + ILogger<SimilarItemsManager> logger, + IServerApplicationPaths appPaths, + ILibraryManager libraryManager, + IFileSystem fileSystem, + IServerConfigurationManager serverConfigurationManager) + { + _logger = logger; + _appPaths = appPaths; + _libraryManager = libraryManager; + _fileSystem = fileSystem; + _serverConfigurationManager = serverConfigurationManager; + } + + /// <inheritdoc/> + public void AddParts(IEnumerable<ISimilarItemsProvider> providers) + { + _similarItemsProviders = providers.ToArray(); + } + + /// <inheritdoc/> + public IReadOnlyList<ISimilarItemsProvider> GetSimilarItemsProviders<T>() + where T : BaseItem + { + var itemType = typeof(T); + return _similarItemsProviders + .Where(p => (p is ILocalSimilarItemsProvider local && local.Supports(itemType)) + || (p is IRemoteSimilarItemsProvider remote && remote.Supports(itemType))) + .ToList(); + } + + /// <inheritdoc/> + public async Task<IReadOnlyList<BaseItem>> GetSimilarItemsAsync( + BaseItem item, + IReadOnlyList<Guid> excludeArtistIds, + User? user, + DtoOptions dtoOptions, + int? limit, + LibraryOptions? libraryOptions, + CancellationToken cancellationToken) + { + ArgumentNullException.ThrowIfNull(item); + ArgumentNullException.ThrowIfNull(excludeArtistIds); + + var itemType = item.GetType(); + var requestedLimit = limit ?? 50; + var itemKind = item.GetBaseItemKind(); + + // Ensure ProviderIds is included in DtoOptions for matching remote provider responses + if (!dtoOptions.Fields.Contains(ItemFields.ProviderIds)) + { + dtoOptions.Fields = dtoOptions.Fields.Concat([ItemFields.ProviderIds]).ToArray(); + } + + // Local providers are always enabled. Remote providers must be explicitly enabled. + var localProviders = _similarItemsProviders + .OfType<ILocalSimilarItemsProvider>() + .Where(p => p.Supports(itemType)) + .ToList(); + var remoteProviders = _similarItemsProviders + .OfType<IRemoteSimilarItemsProvider>() + .Where(p => p.Supports(itemType)); + var matchingProviders = new List<ISimilarItemsProvider>(localProviders); + + var typeOptions = libraryOptions?.GetTypeOptions(itemType.Name); + if (typeOptions?.SimilarItemProviders?.Length > 0) + { + matchingProviders.AddRange(remoteProviders + .Where(p => typeOptions.SimilarItemProviders.Contains(p.Name, StringComparer.OrdinalIgnoreCase))); + } + + var orderConfig = typeOptions?.SimilarItemProviderOrder is { Length: > 0 } order + ? order + : typeOptions?.SimilarItemProviders; + var orderedProviders = matchingProviders + .OrderBy(p => GetConfiguredSimilarProviderOrder(orderConfig, p.Name)) + .ToList(); + + var allResults = new List<(BaseItem Item, float Score)>(); + var excludeIds = new HashSet<Guid> { item.Id }; + var excludeKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { item.GetPresentationUniqueKey() }; + foreach (var (providerOrder, provider) in orderedProviders.Index()) + { + if (allResults.Count >= requestedLimit || cancellationToken.IsCancellationRequested) + { + break; + } + + try + { + if (provider is ILocalSimilarItemsProvider localProvider) + { + var query = new SimilarItemsQuery + { + User = user, + Limit = requestedLimit - allResults.Count, + DtoOptions = dtoOptions, + ExcludeItemIds = [.. excludeIds], + ExcludeArtistIds = excludeArtistIds + }; + + var items = await localProvider.GetSimilarItemsAsync(item, query, cancellationToken).ConfigureAwait(false); + + foreach (var (position, resultItem) in items.Index()) + { + var isNewId = excludeIds.Add(resultItem.Id); + var isNewKey = excludeKeys.Add(resultItem.GetPresentationUniqueKey()); + if (isNewId && isNewKey) + { + var score = CalculateScore(null, providerOrder, position); + allResults.Add((resultItem, score)); + } + } + } + else if (provider is IRemoteSimilarItemsProvider remoteProvider) + { + var cachePath = GetSimilarItemsCachePath(provider.Name, itemType.Name, item.Id); + + var cachedReferences = await TryReadSimilarItemsCacheAsync(cachePath, cancellationToken).ConfigureAwait(false); + if (cachedReferences is not null) + { + var resolvedItems = ResolveRemoteReferences(cachedReferences, providerOrder, user, dtoOptions, itemKind, excludeIds, excludeKeys); + allResults.AddRange(resolvedItems); + continue; + } + + var query = new SimilarItemsQuery + { + User = user, + Limit = requestedLimit - allResults.Count, + DtoOptions = dtoOptions, + ExcludeItemIds = [.. excludeIds], + ExcludeArtistIds = excludeArtistIds + }; + + // Collect references in batches and resolve against local library. + // Stop fetching once we have enough resolved local items. + const int BatchSize = 20; + var remaining = requestedLimit - allResults.Count; + var collectedReferences = new List<SimilarItemReference>(); + var pendingBatch = new List<SimilarItemReference>(); + + await foreach (var reference in remoteProvider.GetSimilarItemsAsync(item, query, cancellationToken).ConfigureAwait(false)) + { + collectedReferences.Add(reference); + pendingBatch.Add(reference); + + if (pendingBatch.Count >= BatchSize) + { + var resolvedItems = ResolveRemoteReferences(pendingBatch, providerOrder, user, dtoOptions, itemKind, excludeIds, excludeKeys); + allResults.AddRange(resolvedItems); + remaining -= resolvedItems.Count; + pendingBatch.Clear(); + + if (remaining <= 0) + { + break; + } + } + } + + // Resolve any remaining references in the last partial batch + if (pendingBatch.Count > 0) + { + var resolvedItems = ResolveRemoteReferences(pendingBatch, providerOrder, user, dtoOptions, itemKind, excludeIds, excludeKeys); + allResults.AddRange(resolvedItems); + } + + if (collectedReferences.Count > 0 && provider.CacheDuration is not null) + { + await SaveSimilarItemsCacheAsync(cachePath, collectedReferences, provider.CacheDuration.Value, cancellationToken).ConfigureAwait(false); + } + } + } + catch (OperationCanceledException) + { + break; + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Similar items provider {ProviderName} failed for item {ItemId}", provider.Name, item.Id); + } + } + + return allResults + .OrderByDescending(x => x.Score) + .Select(x => x.Item) + .Take(requestedLimit) + .ToList(); + } + + /// <inheritdoc/> + public async Task<IReadOnlyList<SimilarItemsRecommendation>> GetMovieRecommendationsAsync( + User? user, + Guid parentId, + int categoryLimit, + int itemLimit, + DtoOptions dtoOptions, + CancellationToken cancellationToken) + { + ArgumentNullException.ThrowIfNull(dtoOptions); + + var recentlyPlayedMovies = _libraryManager.GetItemList(new InternalItemsQuery(user) + { + IncludeItemTypes = [BaseItemKind.Movie], + OrderBy = [(ItemSortBy.DatePlayed, SortOrder.Descending), (ItemSortBy.Random, SortOrder.Descending)], + Limit = 7, + ParentId = parentId, + Recursive = true, + IsPlayed = true, + EnableGroupByMetadataKey = true, + DtoOptions = dtoOptions + }); + + var itemTypes = new List<BaseItemKind> { BaseItemKind.Movie }; + if (_serverConfigurationManager.Configuration.EnableExternalContentInSuggestions) + { + itemTypes.Add(BaseItemKind.Trailer); + itemTypes.Add(BaseItemKind.LiveTvProgram); + } + + var likedMovies = _libraryManager.GetItemList(new InternalItemsQuery(user) + { + IncludeItemTypes = itemTypes.ToArray(), + IsMovie = true, + OrderBy = [(ItemSortBy.Random, SortOrder.Descending)], + Limit = 10, + IsFavoriteOrLiked = true, + ExcludeItemIds = recentlyPlayedMovies.Select(i => i.Id).ToArray(), + EnableGroupByMetadataKey = true, + ParentId = parentId, + Recursive = true, + DtoOptions = dtoOptions + }); + + var mostRecentMovies = recentlyPlayedMovies.Take(Math.Min(recentlyPlayedMovies.Count, 6)).ToList(); + var recentDirectors = GetPeopleNames(mostRecentMovies, [PersonType.Director]); + var recentActors = GetPeopleNames(mostRecentMovies, [PersonType.Actor, PersonType.GuestStar]); + + // Cap baseline items to categoryLimit - the round-robin can't use more categories than that. + var recentlyPlayedBaseline = recentlyPlayedMovies.Count > categoryLimit + ? recentlyPlayedMovies.Take(categoryLimit).ToList() + : recentlyPlayedMovies; + var likedBaseline = likedMovies.Count > categoryLimit + ? likedMovies.Take(categoryLimit).ToList() + : likedMovies; + + var batchQuery = new SimilarItemsQuery + { + User = user, + Limit = itemLimit, + DtoOptions = dtoOptions + }; + + var similarToRecentlyPlayed = await GetSimilarItemsRecommendationsAsync( + recentlyPlayedBaseline, + RecommendationType.SimilarToRecentlyPlayed, + batchQuery, + cancellationToken).ConfigureAwait(false); + + var similarToLiked = await GetSimilarItemsRecommendationsAsync( + likedBaseline, + RecommendationType.SimilarToLikedItem, + batchQuery, + cancellationToken).ConfigureAwait(false); + + var hasDirectorFromRecentlyPlayed = GetPersonRecommendations(user, recentDirectors, itemLimit, dtoOptions, RecommendationType.HasDirectorFromRecentlyPlayed, itemTypes); + var hasActorFromRecentlyPlayed = GetPersonRecommendations(user, recentActors, itemLimit, dtoOptions, RecommendationType.HasActorFromRecentlyPlayed, itemTypes); + + // Use a single enumerator per list, listed twice so MoveNext advances it + // twice per round-robin pass (giving these categories double weight). + // IMPORTANT: Declare as IEnumerator<T> to box the List<T>.Enumerator struct once; + // using var would box separately per list insertion, creating independent copies. + IEnumerator<SimilarItemsRecommendation> similarToRecentlyPlayedEnum = similarToRecentlyPlayed.GetEnumerator(); + IEnumerator<SimilarItemsRecommendation> similarToLikedEnum = similarToLiked.GetEnumerator(); + + var categoryTypes = new List<IEnumerator<SimilarItemsRecommendation>> + { + similarToRecentlyPlayedEnum, + similarToRecentlyPlayedEnum, + similarToLikedEnum, + similarToLikedEnum, + hasDirectorFromRecentlyPlayed.GetEnumerator(), + hasActorFromRecentlyPlayed.GetEnumerator() + }; + + var categories = new List<SimilarItemsRecommendation>(); + while (categories.Count < categoryLimit) + { + var allEmpty = true; + foreach (var category in categoryTypes) + { + if (category.MoveNext()) + { + categories.Add(category.Current); + allEmpty = false; + + if (categories.Count >= categoryLimit) + { + break; + } + } + } + + if (allEmpty) + { + break; + } + } + + return [.. categories.OrderBy(i => i.RecommendationType)]; + } + + private async Task<IReadOnlyList<SimilarItemsRecommendation>> GetSimilarItemsRecommendationsAsync( + IReadOnlyList<BaseItem> baselineItems, + RecommendationType recommendationType, + SimilarItemsQuery query, + CancellationToken cancellationToken) + { + var batchProvider = _similarItemsProviders + .OfType<IBatchLocalSimilarItemsProvider>() + .FirstOrDefault(); + + if (batchProvider is null || baselineItems.Count == 0) + { + return []; + } + + var batchResults = await batchProvider.GetBatchSimilarItemsAsync(baselineItems, query, cancellationToken).ConfigureAwait(false); + + var recommendations = new List<SimilarItemsRecommendation>(baselineItems.Count); + foreach (var baseline in baselineItems) + { + if (batchResults.TryGetValue(baseline.Id, out var similar) && similar.Count > 0) + { + recommendations.Add(new SimilarItemsRecommendation + { + BaselineItemName = baseline.Name, + CategoryId = baseline.Id, + RecommendationType = recommendationType, + Items = similar + }); + } + } + + return recommendations; + } + + private IEnumerable<SimilarItemsRecommendation> GetPersonRecommendations( + User? user, + IReadOnlyList<string> names, + int itemLimit, + DtoOptions dtoOptions, + RecommendationType type, + IReadOnlyList<BaseItemKind> itemTypes) + { + var personTypes = type == RecommendationType.HasDirectorFromRecentlyPlayed + ? [PersonType.Director] + : Array.Empty<string>(); + + foreach (var name in names) + { + var items = _libraryManager.GetItemList(new InternalItemsQuery(user) + { + Person = name, + Limit = itemLimit + 2, + PersonTypes = personTypes, + IncludeItemTypes = itemTypes.ToArray(), + IsMovie = true, + IsPlayed = false, + EnableGroupByMetadataKey = true, + DtoOptions = dtoOptions + }) + .DistinctBy(i => i.GetProviderId(MetadataProvider.Imdb) ?? Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture)) + .Take(itemLimit) + .ToList(); + + if (items.Count > 0) + { + yield return new SimilarItemsRecommendation + { + BaselineItemName = name, + CategoryId = name.GetMD5(), + RecommendationType = type, + Items = items + }; + } + } + } + + private IReadOnlyList<string> GetPeopleNames(IReadOnlyList<BaseItem> items, IReadOnlyList<string> personTypes) + { + var itemIds = items.Select(i => i.Id).ToArray(); + return _libraryManager.GetPeopleNamesByItems(itemIds, personTypes) + .Values + .SelectMany(names => names) + .Distinct() + .ToArray(); + } + + private List<(BaseItem Item, float Score)> ResolveRemoteReferences( + IReadOnlyList<SimilarItemReference> references, + int providerOrder, + User? user, + DtoOptions dtoOptions, + BaseItemKind itemKind, + HashSet<Guid> excludeIds, + HashSet<string> excludeKeys) + { + if (references.Count == 0) + { + return []; + } + + var resolvedByKey = new Dictionary<string, (BaseItem Item, float Score)>(StringComparer.OrdinalIgnoreCase); + var providerLookup = new Dictionary<(string ProviderName, string ProviderId), (float? Score, int Position)>(StringTupleComparer.Instance); + + foreach (var (position, match) in references.Index()) + { + var lookupKey = (match.ProviderName, match.ProviderId); + if (!providerLookup.TryGetValue(lookupKey, out var existing)) + { + providerLookup[lookupKey] = (match.Score, position); + } + else if (match.Score > existing.Score || (match.Score == existing.Score && position < existing.Position)) + { + providerLookup[lookupKey] = (match.Score, position); + } + } + + var allProviderIds = providerLookup + .GroupBy(kvp => kvp.Key.ProviderName) + .ToDictionary(g => g.Key, g => g.Select(x => x.Key.ProviderId).ToArray()); + + var query = new InternalItemsQuery(user) + { + HasAnyProviderIds = allProviderIds, + IncludeItemTypes = [itemKind], + DtoOptions = dtoOptions + }; + + var items = _libraryManager.GetItemList(query); + + foreach (var item in items) + { + if (excludeIds.Contains(item.Id)) + { + continue; + } + + var presentationKey = item.GetPresentationUniqueKey(); + if (excludeKeys.Contains(presentationKey)) + { + continue; + } + + foreach (var providerName in allProviderIds.Keys) + { + if (item.TryGetProviderId(providerName, out var itemProviderId) && providerLookup.TryGetValue((providerName, itemProviderId), out var matchInfo)) + { + var score = CalculateScore(matchInfo.Score, providerOrder, matchInfo.Position); + if (!resolvedByKey.TryGetValue(presentationKey, out var existing) || existing.Score < score) + { + resolvedByKey[presentationKey] = (item, score); + } + + break; + } + } + } + + foreach (var (key, entry) in resolvedByKey) + { + excludeIds.Add(entry.Item.Id); + excludeKeys.Add(key); + } + + return [.. resolvedByKey.Values]; + } + + private static float CalculateScore(float? matchScore, int providerOrder, int position) + { + // Use provider-supplied score if available, otherwise derive from position + var baseScore = matchScore ?? (1.0f - (position * 0.02f)); + + // Apply small boost based on provider order (higher priority providers get small bonus) + var priorityBoost = Math.Max(0, 10 - providerOrder) * 0.005f; + + return Math.Clamp(baseScore + priorityBoost, 0f, 1f); + } + + private static int GetConfiguredSimilarProviderOrder(string[]? orderConfig, string providerName) + { + if (orderConfig is null || orderConfig.Length == 0) + { + return int.MaxValue; + } + + var index = Array.FindIndex(orderConfig, name => string.Equals(name, providerName, StringComparison.OrdinalIgnoreCase)); + return index >= 0 ? index : int.MaxValue; + } + + private string GetSimilarItemsCachePath(string providerName, string baseItemType, Guid itemId) + { + var dataPath = Path.Combine( + _appPaths.CachePath, + $"{providerName.ToLowerInvariant()}-similar-{baseItemType.ToLowerInvariant()}"); + return Path.Combine(dataPath, $"{itemId.ToString("N", CultureInfo.InvariantCulture)}.json"); + } + + private async Task<List<SimilarItemReference>?> TryReadSimilarItemsCacheAsync(string cachePath, CancellationToken cancellationToken) + { + var fileInfo = _fileSystem.GetFileSystemInfo(cachePath); + if (!fileInfo.Exists || fileInfo.Length == 0) + { + return null; + } + + try + { + var stream = File.OpenRead(cachePath); + await using (stream.ConfigureAwait(false)) + { + var cache = await JsonSerializer.DeserializeAsync<SimilarItemsCache>(stream, JsonDefaults.Options, cancellationToken).ConfigureAwait(false); + if (cache?.References is not null && DateTime.UtcNow < cache.ExpiresAt) + { + return cache.References; + } + } + } + catch (IOException ex) + { + _logger.LogWarning(ex, "Failed to read similar items cache from {CachePath}", cachePath); + } + catch (JsonException ex) + { + _logger.LogWarning(ex, "Failed to parse similar items cache from {CachePath}", cachePath); + } + + return null; + } + + private async Task SaveSimilarItemsCacheAsync(string cachePath, List<SimilarItemReference> references, TimeSpan cacheDuration, CancellationToken cancellationToken) + { + try + { + var directory = Path.GetDirectoryName(cachePath); + if (!string.IsNullOrEmpty(directory)) + { + Directory.CreateDirectory(directory); + } + + var cache = new SimilarItemsCache + { + References = references, + ExpiresAt = DateTime.UtcNow.Add(cacheDuration) + }; + + var stream = File.Create(cachePath); + await using (stream.ConfigureAwait(false)) + { + await JsonSerializer.SerializeAsync(stream, cache, JsonDefaults.Options, cancellationToken).ConfigureAwait(false); + } + } + catch (IOException ex) + { + _logger.LogWarning(ex, "Failed to save similar items cache to {CachePath}", cachePath); + } + } + + private sealed class SimilarItemsCache + { + public List<SimilarItemReference>? References { get; set; } + + public DateTime ExpiresAt { get; set; } + } + + private sealed class StringTupleComparer : IEqualityComparer<(string Key, string Value)> + { + public static readonly StringTupleComparer Instance = new(); + + public bool Equals((string Key, string Value) x, (string Key, string Value) y) + => string.Equals(x.Key, y.Key, StringComparison.OrdinalIgnoreCase) && + string.Equals(x.Value, y.Value, StringComparison.OrdinalIgnoreCase); + + public int GetHashCode((string Key, string Value) obj) + => HashCode.Combine( + StringComparer.OrdinalIgnoreCase.GetHashCode(obj.Key), + StringComparer.OrdinalIgnoreCase.GetHashCode(obj.Value)); + } +} diff --git a/Emby.Server.Implementations/Library/SplashscreenPostScanTask.cs b/Emby.Server.Implementations/Library/SplashscreenPostScanTask.cs index 71ce3b6012..7c605036cf 100644 --- a/Emby.Server.Implementations/Library/SplashscreenPostScanTask.cs +++ b/Emby.Server.Implementations/Library/SplashscreenPostScanTask.cs @@ -80,7 +80,7 @@ public class SplashscreenPostScanTask : ILibraryPostScanTask ImageTypes = [imageType], Limit = 30, // TODO max parental rating configurable - MaxParentalRating = new(10, null), + MaxParentalRating = new(13, null), OrderBy = [ (ItemSortBy.Random, SortOrder.Ascending) diff --git a/Emby.Server.Implementations/Library/UserDataManager.cs b/Emby.Server.Implementations/Library/UserDataManager.cs index 1281f1587f..40cd2bb69c 100644 --- a/Emby.Server.Implementations/Library/UserDataManager.cs +++ b/Emby.Server.Implementations/Library/UserDataManager.cs @@ -247,6 +247,103 @@ namespace Emby.Server.Implementations.Library return result; } + /// <inheritdoc /> + public VersionResumeData? GetResumeUserData(User user, BaseItem item) + { + return GetResumeUserDataBatch([item], user).GetValueOrDefault(item.Id); + } + + /// <inheritdoc /> + public IReadOnlyDictionary<Guid, VersionResumeData> GetResumeUserDataBatch(IReadOnlyList<BaseItem> items, User user) + { + ArgumentNullException.ThrowIfNull(user); + + var result = new Dictionary<Guid, VersionResumeData>(); + + // Candidate primaries: a directly queried version (PrimaryVersionId set) keeps its own data. + // Linked alternates are already known in memory; only the local-alternate existence check + // would otherwise hit the database (one query per item via Video.HasLocalAlternateVersions), + // so collect those ids and resolve them all in a single query below. + List<Video>? candidates = null; + List<Guid>? localProbeIds = null; + foreach (var item in items) + { + if (item is not Video video || video.PrimaryVersionId.HasValue) + { + continue; + } + + (candidates ??= []).Add(video); + + if (video.LinkedAlternateVersions.Length == 0) + { + (localProbeIds ??= []).Add(video.Id); + } + } + + if (candidates is null) + { + return result; + } + + HashSet<Guid>? withLocalAlternates = null; + if (localProbeIds is not null) + { + using var dbContext = _repository.CreateDbContext(); + withLocalAlternates = dbContext.LinkedChildren + .Where(lc => lc.ChildType == Jellyfin.Database.Implementations.Entities.LinkedChildType.LocalAlternateVersion + && localProbeIds.Contains(lc.ParentId)) + .Select(lc => lc.ParentId) + .Distinct() + .ToHashSet(); + } + + List<(Guid PrimaryId, IReadOnlyList<Video> Versions)>? versionGroups = null; + List<BaseItem>? allVersions = null; + + foreach (var video in candidates) + { + // Only items that actually have alternate versions aggregate over them. + if (video.LinkedAlternateVersions.Length == 0 + && (withLocalAlternates is null || !withLocalAlternates.Contains(video.Id))) + { + continue; + } + + var versions = video.GetAllVersions(); + if (versions.Count < 2) + { + continue; + } + + (versionGroups ??= []).Add((video.Id, versions)); + (allVersions ??= []).AddRange(versions); + } + + if (versionGroups is null) + { + return result; + } + + var userDataByVersion = GetUserDataBatch(allVersions!.DistinctBy(i => i.Id).ToList(), user); + + foreach (var (primaryId, versions) in versionGroups) + { + // Consider both in-progress and completed versions so a finished alternate still marks the primary as played. + var resumeVersion = VersionPlaybackSelector.SelectMostRecentlyPlayed( + versions, + version => userDataByVersion.GetValueOrDefault(version.Id), + data => data.PlaybackPositionTicks > 0 || data.Played); + + if (resumeVersion is not null) + { + result[primaryId] = new VersionResumeData(resumeVersion.Id, userDataByVersion[resumeVersion.Id]); + } + } + + return result; + } + /// <summary> /// Gets the internal key. /// </summary> @@ -281,6 +378,10 @@ namespace Emby.Server.Implementations.Library var dto = GetUserItemDataDto(userData, item.Id); item.FillUserDataDtoValues(dto, userData, itemDto, user, options); + + // For an item with alternate versions, surface the most recently played version's resume point. + GetResumeUserData(user, item)?.ApplyTo(dto); + return dto; } @@ -385,5 +486,41 @@ namespace Emby.Server.Implementations.Library return playedToCompletion; } + + /// <inheritdoc /> + public void ResetPlaybackStreamSelections(User user, BaseItem item) + { + ArgumentNullException.ThrowIfNull(user); + ArgumentNullException.ThrowIfNull(item); + + using var dbContext = _repository.CreateDbContext(); + var rows = dbContext.UserData + .Where(e => e.ItemId == item.Id && e.UserId == user.Id + && (e.AudioStreamIndex != null || e.SubtitleStreamIndex != null)) + .ToList(); + + if (rows.Count == 0) + { + return; + } + + foreach (var row in rows) + { + row.AudioStreamIndex = null; + row.SubtitleStreamIndex = null; + } + + dbContext.SaveChanges(); + + var cacheKey = GetCacheKey(user.InternalId, item.Id); + if (_cache.TryGet(cacheKey, out var cached)) + { + cached.AudioStreamIndex = null; + cached.SubtitleStreamIndex = null; + _cache.AddOrUpdate(cacheKey, cached); + } + + item.UserData = dbContext.UserData.Where(e => e.ItemId == item.Id).AsNoTracking().ToArray(); + } } } diff --git a/Emby.Server.Implementations/Localization/Core/ab.json b/Emby.Server.Implementations/Localization/Core/ab.json index d6d257c5ba..d67f2d67e9 100644 --- a/Emby.Server.Implementations/Localization/Core/ab.json +++ b/Emby.Server.Implementations/Localization/Core/ab.json @@ -1,5 +1,3 @@ { - "Albums": "аальбомқәа", - "AppDeviceValues": "Апп: {0}, Априбор: {1}", - "Application": "Апрограмма" + "AppDeviceValues": "Апп: {0}, Априбор: {1}" } diff --git a/Emby.Server.Implementations/Localization/Core/af.json b/Emby.Server.Implementations/Localization/Core/af.json index 80c1bd0940..308341ad49 100644 --- a/Emby.Server.Implementations/Localization/Core/af.json +++ b/Emby.Server.Implementations/Localization/Core/af.json @@ -1,11 +1,8 @@ { "Artists": "Kunstenare", - "Channels": "Kanale", "Folders": "Lêergidse", "Favorites": "Gunstelinge", "HeaderFavoriteShows": "Gunsteling Vertonings", - "ValueSpecialEpisodeName": "Spesiale - {0}", - "HeaderAlbumArtists": "Album kunstenaars", "Books": "Boeke", "HeaderNextUp": "Volgende", "Movies": "Flieks", @@ -13,24 +10,13 @@ "HeaderContinueWatching": "Hou aan kyk", "HeaderFavoriteEpisodes": "Gunsteling Episodes", "Photos": "Foto's", - "Playlists": "Snitlyste", - "HeaderFavoriteArtists": "Gunsteling Kunstenaars", - "HeaderFavoriteAlbums": "Gunsteling Albums", - "Sync": "Sinkroniseer", - "HeaderFavoriteSongs": "Gunsteling Liedjies", - "Songs": "Liedjies", - "DeviceOnlineWithName": "{0} is aanlyn", - "DeviceOfflineWithName": "{0} is ontkoppel", "Collections": "Versamelings", "Inherit": "Ontvang", "HeaderLiveTV": "Lewendige TV", - "Application": "Program", "AppDeviceValues": "App: {0}, Toestel: {1}", "VersionNumber": "Weergawe {0}", - "ValueHasBeenAddedToLibrary": "{0} is by jou media biblioteek bygevoeg", "UserStoppedPlayingItemWithValues": "{0} het klaar {1} op {2} gespeel", "UserStartedPlayingItemWithValues": "{0} is besig om {1} op {2} te speel", - "UserPolicyUpdatedWithName": "Gebruiker beleid is verander vir {0}", "UserPasswordChangedWithName": "Gebruiker {0} se wagwoord is verander", "UserOnlineFromDevice": "{0} is aanlyn van {1}", "UserOfflineFromDevice": "{0} is ontkoppel van {1}", @@ -38,19 +24,13 @@ "UserDownloadingItemWithValues": "{0} is besig om {1} af te laai", "UserDeletedWithName": "Gebruiker {0} is verwyder", "UserCreatedWithName": "Gebruiker {0} is geskep", - "User": "Gebruiker", "TvShows": "TV Programme", - "System": "Stelsel", "SubtitleDownloadFailureFromForItem": "Ondertitels het misluk om af te laai van {0} vir {1}", "StartupEmbyServerIsLoading": "Jellyfin Bediener is besig om te laai. Probeer weer in 'n kort tyd.", - "ServerNameNeedsToBeRestarted": "{0} moet herbegin word", - "ScheduledTaskStartedWithName": "{0} het begin", "ScheduledTaskFailedWithName": "{0} het misluk", - "ProviderValue": "Voorsiener: {0}", "PluginUpdatedWithName": "{0} was opgedateer", "PluginUninstalledWithName": "{0} was verwyder", "PluginInstalledWithName": "{0} is geïnstalleer", - "Plugin": "Inprop module", "NotificationOptionVideoPlaybackStopped": "Video terugspeel het gestop", "NotificationOptionVideoPlayback": "Video terugspeel het begin", "NotificationOptionUserLockedOut": "Gebruiker uitgeslyt", @@ -74,23 +54,14 @@ "MusicVideos": "Musiek Videos", "Music": "Musiek", "MixedContent": "Gemengde inhoud", - "MessageServerConfigurationUpdated": "Bediener konfigurasie is opgedateer", - "MessageNamedServerConfigurationUpdatedWithValue": "Bediener konfigurasie seksie {0} is opgedateer", - "MessageApplicationUpdatedTo": "Jellyfin Bediener is opgedateer na {0}", - "MessageApplicationUpdated": "Jellyfin Bediener is opgedateer", "Latest": "Nuutste", "LabelRunningTimeValue": "Werktyd: {0}", "LabelIpAddressValue": "IP adres: {0}", - "ItemRemovedWithName": "{0} is uit versameling verwyder", - "ItemAddedWithName": "{0} is by die versameling gevoeg", "HomeVideos": "Tuis Videos", - "HeaderRecordingGroups": "Groep Opnames", "Genres": "Genres", "FailedLoginAttemptWithUserName": "Mislukte aanmeldpoging van {0}", "ChapterNameValue": "Hoofstuk {0}", - "CameraImageUploadedFrom": "'n Nuwe kamera foto is opgelaai vanaf {0}", "AuthenticationSucceededWithUserName": "{0} suksesvol geverifieer", - "Albums": "Albums", "TasksChannelsCategory": "Internet kanale", "TasksApplicationCategory": "aansoek", "TasksLibraryCategory": "biblioteek", diff --git a/Emby.Server.Implementations/Localization/Core/ar.json b/Emby.Server.Implementations/Localization/Core/ar.json index e48939b4d7..17af935562 100644 --- a/Emby.Server.Implementations/Localization/Core/ar.json +++ b/Emby.Server.Implementations/Localization/Core/ar.json @@ -1,41 +1,24 @@ { - "Albums": "الألبومات", "AppDeviceValues": "التطبيق: {0}، الجهاز: {1}", - "Application": "التطبيق", "Artists": "الفنانون", "AuthenticationSucceededWithUserName": "تمت مصادقة {0} بنجاح", "Books": "الكتب", - "CameraImageUploadedFrom": "تم رفع صورة كاميرا جديدة من {0}", - "Channels": "القنوات", "ChapterNameValue": "الفصل {0}", "Collections": "المجموعات", - "DeviceOfflineWithName": "انقطع اتصال {0}", - "DeviceOnlineWithName": "{0} متصل", "FailedLoginAttemptWithUserName": "محاولة تسجيل دخول فاشلة من {0}", "Favorites": "المفضلة", "Folders": "المجلدات", "Genres": "الأنواع", - "HeaderAlbumArtists": "فنانو الألبوم", "HeaderContinueWatching": "متابعة المشاهدة", - "HeaderFavoriteAlbums": "الألبومات المفضلة", - "HeaderFavoriteArtists": "الفنانون المفضلون", "HeaderFavoriteEpisodes": "الحلقات المفضلة", "HeaderFavoriteShows": "المسلسلات المفضلة", - "HeaderFavoriteSongs": "الأغاني المفضلة", "HeaderLiveTV": "البث التلفزيوني المباشر", "HeaderNextUp": "التالي", - "HeaderRecordingGroups": "مجموعات التسجيل", "HomeVideos": "فيديوهات منزلية", "Inherit": "وراثة", - "ItemAddedWithName": "تمت إضافة {0} إلى المكتبة", - "ItemRemovedWithName": "تمت إزالة {0} من المكتبة", "LabelIpAddressValue": "عنوان IP: {0}", "LabelRunningTimeValue": "مدة التشغيل: {0}", "Latest": "الأحدث", - "MessageApplicationUpdated": "تم تحديث خادم Jellyfin", - "MessageApplicationUpdatedTo": "تم تحديث خادم Jellyfin إلى {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "تم تحديث قسم إعدادات الخادم {0}", - "MessageServerConfigurationUpdated": "تم تحديث إعدادات الخادم", "MixedContent": "محتوى مختلط", "Movies": "الأفلام", "Music": "الموسيقى", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "بدأ تشغيل الفيديو", "NotificationOptionVideoPlaybackStopped": "توقف تشغيل الفيديو", "Photos": "الصور", - "Playlists": "قوائم التشغيل", - "Plugin": "الملحق", "PluginInstalledWithName": "تم تثبيت {0}", "PluginUninstalledWithName": "تمت إزالة {0}", "PluginUpdatedWithName": "تم تحديث {0}", - "ProviderValue": "المزوّد: {0}", "ScheduledTaskFailedWithName": "فشلت {0}", - "ScheduledTaskStartedWithName": "بدأت {0}", - "ServerNameNeedsToBeRestarted": "يحتاج {0} إلى إعادة التشغيل", "Shows": "المسلسلات", - "Songs": "الأغاني", "StartupEmbyServerIsLoading": "يتم الآن تحميل خادم Jellyfin. يرجى المحاولة مرة أخرى بعد قليل.", "SubtitleDownloadFailureFromForItem": "فشل تنزيل الترجمات من {0} لـ {1}", - "Sync": "مزامنة", - "System": "النظام", "TvShows": "البرامج التلفزيونية", - "User": "المستخدم", "UserCreatedWithName": "تم إنشاء المستخدم {0}", "UserDeletedWithName": "تم حذف المستخدم {0}", "UserDownloadingItemWithValues": "{0} يقوم بتنزيل {1}", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "انقطع اتصال {0} من {1}", "UserOnlineFromDevice": "{0} متصل من {1}", "UserPasswordChangedWithName": "تم تغيير كلمة المرور للمستخدم {0}", - "UserPolicyUpdatedWithName": "تم تحديث سياسة المستخدم لـ {0}", "UserStartedPlayingItemWithValues": "{0} يقوم بتشغيل {1} على {2}", "UserStoppedPlayingItemWithValues": "أنهى {0} تشغيل {1} على {2}", - "ValueHasBeenAddedToLibrary": "تمت إضافة {0} إلى مكتبة المحتوى الخاصة بك", - "ValueSpecialEpisodeName": "خاص - {0}", "VersionNumber": "الإصدار {0}", "TaskCleanCacheDescription": "يحذف ملفات ذاكرة التخزين المؤقت التي لم يعد النظام بحاجة إليها.", "TaskCleanCache": "تنظيف مجلد ذاكرة التخزين المؤقت", @@ -136,5 +107,6 @@ "TaskMoveTrickplayImagesDescription": "ينقل ملفات معاينات التنقل الحالية وفقاً لإعدادات المكتبة.", "CleanupUserDataTask": "مهمة تنظيف بيانات المستخدم", "CleanupUserDataTaskDescription": "ينظف جميع بيانات المستخدم (مثل حالة المشاهدة وحالة المفضلة وغيرها) للمحتوى الذي لم يعد موجوداً لمدة 90 يوماً على الأقل.", - "Original": "فريد" + "Original": "فريد", + "LyricDownloadFailureFromForItem": "فشل تحميل الكلمات من {0} إلى {1}" } diff --git a/Emby.Server.Implementations/Localization/Core/as.json b/Emby.Server.Implementations/Localization/Core/as.json index 7c7dd26e92..bc0c2c5ff5 100644 --- a/Emby.Server.Implementations/Localization/Core/as.json +++ b/Emby.Server.Implementations/Localization/Core/as.json @@ -1,18 +1,13 @@ { - "Albums": "এলবাম", - "Application": "আবেদন", "AppDeviceValues": "এপ্: {0}, ডিভাইচ: {1}", "Artists": "শিল্পী", - "Channels": "চেনেলস", "Default": "ডিফল্ট", "AuthenticationSucceededWithUserName": "{0} সফলভাবে প্রমাণিত", "Books": "পুস্তক", "Movies": "চলচ্চিত্ৰ", - "CameraImageUploadedFrom": "একটি নতুন ক্যামেরা চিত্র আপলোড করা হয়েছে {0}", "Collections": "সংগ্রহ", "HeaderFavoriteShows": "প্রিয় শোসমূহ", "Latest": "শেহতীয়া", - "MessageApplicationUpdated": "জেলিফিন চাইভাৰ আপডেট কৰা হৈছে", "MixedContent": "মিশ্ৰিত সমগ্ৰতা", "NewVersionIsAvailable": "ডাউনলোড কৰিবলৈ জেলিফিন চাইভাৰৰ এটা নতুন সংস্কৰণ উপলব্ধ আছে.", "NotificationOptionCameraImageUploaded": "কেমেৰাৰ চিত্ৰ আপল'ড কৰা হ'ল", @@ -21,20 +16,14 @@ "Folders": "ফোল্ডাৰ", "Forced": "বলপূর্বক", "Genres": "শ্রেণী", - "HeaderAlbumArtists": "অ্যালবাম শিল্পী", "HeaderContinueWatching": "দেখা চালিয়ে যান", "FailedLoginAttemptWithUserName": "লগইন ব্যর্থ চেষ্টা কৰা হৈছে থেকে {0}", - "HeaderFavoriteAlbums": "প্রিয় অ্যালবামসমূহ", - "HeaderFavoriteArtists": "প্রিয় শিল্পীসমূহ", "HeaderFavoriteEpisodes": "প্রিয় পর্বসমূহ", - "HeaderFavoriteSongs": "প্ৰিয় গীত", "HeaderLiveTV": "প্ৰতিবেদন টিভি", "HeaderNextUp": "পৰৱৰ্তী অংশ", - "HeaderRecordingGroups": "অলংকৰণ গোষ্ঠীসমূহ", "HearingImpaired": "শ্ৰবণ অক্ষম", "HomeVideos": "ঘৰৰ ভিডিঅ'সমূহ", "Inherit": "উত্তপ্ত কৰা", - "MessageServerConfigurationUpdated": "চাইভাৰ কনফিগাৰেশ্যন আপডেট কৰা হৈছে", "NotificationOptionApplicationUpdateAvailable": "অ্যাপ্লিকেশ্যন আপডেট উপলব্ধ", "NotificationOptionApplicationUpdateInstalled": "অ্যাপ্লিকেশ্যন আপডেট ইনষ্টল কৰা হ'ল", "NotificationOptionAudioPlayback": "অডিঅ' প্লেবেক আৰম্ভ হ'ল", diff --git a/Emby.Server.Implementations/Localization/Core/az.json b/Emby.Server.Implementations/Localization/Core/az.json new file mode 100644 index 0000000000..6ab18c8534 --- /dev/null +++ b/Emby.Server.Implementations/Localization/Core/az.json @@ -0,0 +1,19 @@ +{ + "Books": "Kitablar", + "HomeVideos": "Ev Videoları", + "Latest": "Ən son", + "MixedContent": "Qarışıq məzmun", + "Movies": "Filmlər", + "Music": "Musiqi", + "MusicVideos": "Musiqi Videoları", + "NameSeasonUnknown": "Mövsüm Naməlum", + "NewVersionIsAvailable": "Jellyfin Serverin yeni versiyası yükləmək üçün əlçatandır.", + "NotificationOptionApplicationUpdateAvailable": "Tətbiq yeniləməsi mövcuddur", + "NotificationOptionApplicationUpdateInstalled": "Tətbiq yeniləməsi quraşdırılıb", + "NotificationOptionAudioPlayback": "Audio oxutma başladı", + "NotificationOptionAudioPlaybackStopped": "Audio oxutma dayandırıldı", + "NotificationOptionCameraImageUploaded": "Kamera şəkli yükləndi", + "NotificationOptionInstallationFailed": "Quraşdırma uğursuzluğu", + "NotificationOptionNewLibraryContent": "Yeni məzmun əlavə edildi", + "NotificationOptionPluginError": "Plugin uğursuzluğu" +} diff --git a/Emby.Server.Implementations/Localization/Core/be.json b/Emby.Server.Implementations/Localization/Core/be.json index 543d227e73..5d0ef65842 100644 --- a/Emby.Server.Implementations/Localization/Core/be.json +++ b/Emby.Server.Implementations/Localization/Core/be.json @@ -1,17 +1,10 @@ { - "Sync": "Сінхранізаваць", - "Playlists": "Плэй-лісты", "Latest": "Апошняе", "LabelIpAddressValue": "IP-адрас: {0}", - "ItemAddedWithName": "{0} дададзены ў бібліятэку", - "MessageApplicationUpdated": "Сервер Jellyfin абноўлены", "NotificationOptionApplicationUpdateInstalled": "Абнаўленне праграмы ўсталявана", "PluginInstalledWithName": "{0} быў усталяваны", "UserCreatedWithName": "Карыстальнік {0} быў створаны", - "Albums": "Альбомы", - "Application": "Праграма", "AuthenticationSucceededWithUserName": "{0} паспяхова аўтарызаваны", - "Channels": "Каналы", "ChapterNameValue": "Раздзел {0}", "Collections": "Калекцыі", "Default": "Прадвызначана", @@ -21,16 +14,11 @@ "External": "Знешні", "Genres": "Жанры", "HeaderContinueWatching": "Працягнуць прагляд", - "HeaderFavoriteAlbums": "Абраныя альбомы", "HeaderFavoriteEpisodes": "Абраныя серыі", "HeaderFavoriteShows": "Абраныя шоу", - "HeaderFavoriteSongs": "Абраныя песні", "HeaderLiveTV": "Прамы эфір", - "HeaderAlbumArtists": "Выканаўцы альбома", "LabelRunningTimeValue": "Працягласць: {0}", "HomeVideos": "Хатнія відэа", - "ItemRemovedWithName": "{0} выдалены з бібліятэкі", - "MessageApplicationUpdatedTo": "Сервер Jellyfin абноўлены да версіі {0}", "Movies": "Фільмы", "Music": "Музыка", "MusicVideos": "Музычныя кліпы", @@ -41,19 +29,13 @@ "NotificationOptionPluginUpdateInstalled": "Абнаўленне плагіна ўсталявана", "NotificationOptionServerRestartRequired": "Патрабуецца перазапуск сервера", "Photos": "Фотаздымкі", - "Plugin": "Плагін", "PluginUninstalledWithName": "{0} быў выдалены", "PluginUpdatedWithName": "{0} быў абноўлены", - "ProviderValue": "Пастаўшчык: {0}", - "Songs": "Песні", - "System": "Сістэма", - "User": "Карыстальнік", "UserDeletedWithName": "Карыстальнік {0} быў выдалены", "UserDownloadingItemWithValues": "{0} спампоўваецца {1}", "TaskOptimizeDatabase": "Аптымізацыя базы даных", "Artists": "Выканаўцы", "UserOfflineFromDevice": "{0} адлучыўся ад {1}", - "UserPolicyUpdatedWithName": "Палітыка карыстальніка абноўлена для {0}", "TaskCleanActivityLogDescription": "Выдаляе запісы старэйшыя за зададзены ўзрост ў журнале актыўнасці.", "TaskRefreshChapterImagesDescription": "Стварае мініяцюры для відэа, якія маюць раздзелы.", "TaskCleanLogsDescription": "Выдаляе файлы журналу, якім больш за {0} дзён.", @@ -65,17 +47,10 @@ "TasksApplicationCategory": "Праграма", "AppDeviceValues": "Праграма: {0}, Прылада: {1}", "Books": "Кнігі", - "CameraImageUploadedFrom": "Новая выява камеры была загружана з {0}", - "DeviceOfflineWithName": "{0} адлучыўся", - "DeviceOnlineWithName": "{0} падлучаны", "Forced": "Прымусова", - "HeaderRecordingGroups": "Групы запісаў", "HeaderNextUp": "Наступнае", - "HeaderFavoriteArtists": "Абраныя выканаўцы", "HearingImpaired": "Са слабым слыхам", "Inherit": "Атрымаць у спадчыну", - "MessageNamedServerConfigurationUpdatedWithValue": "Канфігурацыя сервера (секцыя {0}) абноўлена", - "MessageServerConfigurationUpdated": "Канфігурацыя сервера абноўлена", "MixedContent": "Змешаны змест", "NameSeasonUnknown": "Невядомы сезон", "NotificationOptionInstallationFailed": "Збой усталёўкі", @@ -91,8 +66,6 @@ "NotificationOptionVideoPlayback": "Пачалося прайграванне відэа", "NotificationOptionVideoPlaybackStopped": "Прайграванне відэа спынена", "ScheduledTaskFailedWithName": "{0} не атрымалася", - "ScheduledTaskStartedWithName": "{0} пачалося", - "ServerNameNeedsToBeRestarted": "{0} патрабуе перазапуску", "Shows": "Шоу", "StartupEmbyServerIsLoading": "Jellyfin Server загружаецца. Калі ласка, паўтарыце спробу крыху пазней.", "SubtitleDownloadFailureFromForItem": "Субцітры для {1} не ўдалося спампаваць з {0}", @@ -103,8 +76,6 @@ "UserPasswordChangedWithName": "Пароль быў зменены для карыстальніка {0}", "UserStartedPlayingItemWithValues": "{0} прайграваецца {1} на {2}", "UserStoppedPlayingItemWithValues": "{0} скончыў прайграванне {1} на {2}", - "ValueHasBeenAddedToLibrary": "{0} быў дададзены ў вашу медыятэку", - "ValueSpecialEpisodeName": "Спецвыпуск - {0}", "VersionNumber": "Версія {0}", "TasksMaintenanceCategory": "Абслугоўванне", "TasksLibraryCategory": "Бібліятэка", diff --git a/Emby.Server.Implementations/Localization/Core/bg-BG.json b/Emby.Server.Implementations/Localization/Core/bg-BG.json index 7340180241..0710a39708 100644 --- a/Emby.Server.Implementations/Localization/Core/bg-BG.json +++ b/Emby.Server.Implementations/Localization/Core/bg-BG.json @@ -1,41 +1,24 @@ { - "Albums": "Албуми", "AppDeviceValues": "Програма: {0}, Устройство: {1}", - "Application": "Програма", "Artists": "Артисти", "AuthenticationSucceededWithUserName": "{0} се удостовери успешно", "Books": "Книги", - "CameraImageUploadedFrom": "Нова снимка от камера беше качена от {0}", - "Channels": "Канали", "ChapterNameValue": "Глава {0}", "Collections": "Колекции", - "DeviceOfflineWithName": "{0} се разкачи", - "DeviceOnlineWithName": "{0} е свързан", "FailedLoginAttemptWithUserName": "Неуспешен опит за влизане от {0}", "Favorites": "Любими", "Folders": "Папки", "Genres": "Жанрове", - "HeaderAlbumArtists": "Изпълнители на албума", "HeaderContinueWatching": "Продължаване на гледането", - "HeaderFavoriteAlbums": "Любими албуми", - "HeaderFavoriteArtists": "Любими изпълнители", "HeaderFavoriteEpisodes": "Любими епизоди", "HeaderFavoriteShows": "Любими сериали", - "HeaderFavoriteSongs": "Любими песни", "HeaderLiveTV": "Телевизия на живо", "HeaderNextUp": "Следва", - "HeaderRecordingGroups": "Запис групи", "HomeVideos": "Домашни Клипове", "Inherit": "Наследяване", - "ItemAddedWithName": "{0} е добавено към библиотеката", - "ItemRemovedWithName": "{0} е премахнато от библиотеката", "LabelIpAddressValue": "IP адрес: {0}", "LabelRunningTimeValue": "Продължителност: {0}", "Latest": "Последни", - "MessageApplicationUpdated": "Сървърът беше обновен", - "MessageApplicationUpdatedTo": "Сървърът беше обновен до {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "Секцията {0} от сървърната конфигурация беше актуализирана", - "MessageServerConfigurationUpdated": "Конфигурацията на сървъра беше актуализирана", "MixedContent": "Смесено съдържание", "Movies": "Филми", "Music": "Музика", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "Възпроизвеждането на видео започна", "NotificationOptionVideoPlaybackStopped": "Възпроизвеждането на видео е спряно", "Photos": "Снимки", - "Playlists": "Списъци", - "Plugin": "Добавка", "PluginInstalledWithName": "{0} е инсталиранa", "PluginUninstalledWithName": "{0} е деинсталиранa", "PluginUpdatedWithName": "{0} е обновенa", - "ProviderValue": "Доставчик: {0}", "ScheduledTaskFailedWithName": "{0} се провали", - "ScheduledTaskStartedWithName": "{0} започна", - "ServerNameNeedsToBeRestarted": "{0} трябва да се рестартира", "Shows": "Сериали", - "Songs": "Песни", "StartupEmbyServerIsLoading": "Сървърът зарежда. Моля, опитайте отново след малко.", "SubtitleDownloadFailureFromForItem": "Субтитрите за {1} от {0} не можаха да бъдат изтеглени", - "Sync": "Синхронизиране", - "System": "Система", "TvShows": "Телевизионни сериали", - "User": "Потребител", "UserCreatedWithName": "Потребителят {0} е създаден", "UserDeletedWithName": "Потребителят {0} е изтрит", "UserDownloadingItemWithValues": "{0} изтегля {1}", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "{0} се разкачи от {1}", "UserOnlineFromDevice": "{0} е на линия от {1}", "UserPasswordChangedWithName": "Паролата на потребителя {0} е променена", - "UserPolicyUpdatedWithName": "Потребителската политика за {0} се актуализира", "UserStartedPlayingItemWithValues": "{0} пусна {1}", "UserStoppedPlayingItemWithValues": "{0} спря {1}", - "ValueHasBeenAddedToLibrary": "{0} беше добавен във Вашата библиотека", - "ValueSpecialEpisodeName": "Специални - {0}", "VersionNumber": "Версия {0}", "TaskDownloadMissingSubtitlesDescription": "Търси Интернет за липсващи субтитри, на база конфигурацията за мета-данни.", "TaskDownloadMissingSubtitles": "Изтегляне на липсващи субтитри", diff --git a/Emby.Server.Implementations/Localization/Core/bn.json b/Emby.Server.Implementations/Localization/Core/bn.json index c6cfbe3c67..eb7fdf2b68 100644 --- a/Emby.Server.Implementations/Localization/Core/bn.json +++ b/Emby.Server.Implementations/Localization/Core/bn.json @@ -1,31 +1,19 @@ { - "DeviceOnlineWithName": "{0}-এর সাথে সংযুক্ত হয়েছে", - "DeviceOfflineWithName": "{0}-এর সাথে সংযোগ বিচ্ছিন্ন হয়েছে", "Collections": "সংগ্রহশালা", "ChapterNameValue": "অধ্যায় {0}", - "Channels": "চ্যানেলসমূহ", - "CameraImageUploadedFrom": "{0} থেকে একটি নতুন ক্যামেরার চিত্র আপলোড করা হয়েছে", "Books": "পুস্তকসমূহ", "AuthenticationSucceededWithUserName": "{0} সফলভাবে অথেন্টিকেট করেছেন", "Artists": "শিল্পীগণ", - "Application": "অ্যাপ্লিকেশন", - "Albums": "অ্যালবামসমূহ", "HeaderFavoriteEpisodes": "প্রিয় পর্বগুলো", - "HeaderFavoriteArtists": "প্রিয় শিল্পীরা", - "HeaderFavoriteAlbums": "প্রিয় এলবামগুলো", "HeaderContinueWatching": "দেখতে থাকুন", - "HeaderAlbumArtists": "অ্যালবাম শিল্পীবৃন্দ", "Genres": "ধরণ", "Folders": "ফোল্ডারসমূহ", "Favorites": "পছন্দসমূহ", "FailedLoginAttemptWithUserName": "{0} লগিন করতে ব্যর্থ হয়েছে", "AppDeviceValues": "অ্যাপ: {0}, ডিভাইস: {1}", "VersionNumber": "সংস্করণ {0}", - "ValueSpecialEpisodeName": "বিশেষ পর্ব - {0}", - "ValueHasBeenAddedToLibrary": "আপনার লাইব্রেরিতে {0} যোগ করা হয়েছে", "UserStoppedPlayingItemWithValues": "{2}তে {1} প্লে শেষ করেছেন {0}", "UserStartedPlayingItemWithValues": "{2}তে {1} প্লে করেছেন {0}", - "UserPolicyUpdatedWithName": "{0} এর জন্য ব্যবহার নীতি আপডেট করা হয়েছে", "UserPasswordChangedWithName": "ব্যবহারকারী {0} এর পাসওয়ার্ড পরিবর্তিত হয়েছে", "UserOnlineFromDevice": "{0}, {1} থেকে অনলাইন আছে", "UserOfflineFromDevice": "{0} {1} থেকে বিচ্ছিন্ন হয়ে গেছে", @@ -33,23 +21,14 @@ "UserDownloadingItemWithValues": "{0}, {1} ডাউনলোড করছে", "UserDeletedWithName": "ব্যবহারকারী {0}কে বাদ দেয়া হয়েছে", "UserCreatedWithName": "ব্যবহারকারী {0} সৃষ্টি করা হয়েছে", - "User": "ব্যবহারকারী", "TvShows": "টিভি শোগুলো", - "System": "সিস্টেম", - "Sync": "সমন্বয় করুন", "SubtitleDownloadFailureFromForItem": "{0} থেকে {1} এর জন্য সাবটাইটেল ডাউনলোড ব্যর্থ হয়েছে", "StartupEmbyServerIsLoading": "জেলিফিন সার্ভার লোড হচ্ছে। দয়া করে একটু পরে আবার চেষ্টা করুন।", - "Songs": "সঙ্গীত সমূহ", "Shows": "শো সমূহ", - "ServerNameNeedsToBeRestarted": "{0} রিস্টার্ট করা প্রয়োজন", - "ScheduledTaskStartedWithName": "{0} শুরু হয়েছে", "ScheduledTaskFailedWithName": "{0} ব্যর্থ", - "ProviderValue": "প্রদানকারী: {0}", "PluginUpdatedWithName": "{0} আপডেট করা হয়েছে", "PluginUninstalledWithName": "{0} আনইন্সটল হয়েছে", "PluginInstalledWithName": "{0} ইন্সটল হয়েছে", - "Plugin": "প্লাগিন", - "Playlists": "প্লে লিস্ট সমূহ", "Photos": "ছবিসমূহ", "NotificationOptionVideoPlaybackStopped": "ভিডিও প্লেব্যাক বন্ধ হয়েছে", "NotificationOptionVideoPlayback": "ভিডিও প্লেব্যাক শুরু হয়েছে", @@ -75,21 +54,13 @@ "Music": "গান", "Movies": "চলচ্চিত্রসমূহ", "MixedContent": "মিশ্র কন্টেন্ট", - "MessageServerConfigurationUpdated": "সার্ভারের কনফিগারেশন আপডেট করা হয়েছে", - "HeaderRecordingGroups": "রেকর্ডিং গ্রুপগুলো", - "MessageNamedServerConfigurationUpdatedWithValue": "সার্ভার কনফিগারেশন সেকশন {0} আপডেট করা হয়েছে", - "MessageApplicationUpdatedTo": "জেলিফিন সার্ভার {0} তে আপডেট করা হয়েছে", - "MessageApplicationUpdated": "জেলিফিন সার্ভার আপডেট করা হয়েছে", "Latest": "সর্বশেষ", "LabelRunningTimeValue": "চলার সময়: {0}", "LabelIpAddressValue": "আইপি এড্রেস: {0}", - "ItemRemovedWithName": "{0} লাইব্রেরি থেকে বাদ দেয়া হয়েছে", - "ItemAddedWithName": "{0} লাইব্রেরিতে যোগ করা হয়েছে", "Inherit": "উত্তরাধিকারসূত্র থেকে গ্রহণ করুন", "HomeVideos": "হোম ভিডিও", "HeaderNextUp": "এরপরে আসছে", "HeaderLiveTV": "লাইভ টিভি", - "HeaderFavoriteSongs": "প্রিয় গানগুলো", "HeaderFavoriteShows": "প্রিয় শোগুলো", "TasksLibraryCategory": "লাইব্রেরি", "TasksMaintenanceCategory": "রক্ষণাবেক্ষণ", diff --git a/Emby.Server.Implementations/Localization/Core/br.json b/Emby.Server.Implementations/Localization/Core/br.json new file mode 100644 index 0000000000..cedc87e5a6 --- /dev/null +++ b/Emby.Server.Implementations/Localization/Core/br.json @@ -0,0 +1,63 @@ +{ + "Artists": "Arzourien", + "AuthenticationSucceededWithUserName": "{0} kennasket gant berzh", + "Books": "Levrioù", + "ChapterNameValue": "Pennad {0}", + "Collections": "Dastumadegoù", + "Default": "Dre ziouer", + "External": "Diavaez", + "FailedLoginAttemptWithUserName": "Kennaskañ c'hwitet gant {0}", + "Favorites": "Sinedoù", + "Folders": "Teuliadoù", + "Forced": "Rediet", + "Genres": "Doareoù", + "HeaderContinueWatching": "Kenderc'hel da sellet", + "HeaderFavoriteEpisodes": "Rannoù Karetañ", + "HeaderFavoriteShows": "Heuliadennoù Karetañ", + "HeaderLiveTV": "TV war-eeun", + "HeaderNextUp": "Da c'houde", + "HearingImpaired": "Tud fall o C'hleved", + "HomeVideos": "Videoioù Personel", + "Inherit": "Hêrezhiñ", + "LabelIpAddressValue": "Chomlec'h IP : {0}", + "LabelRunningTimeValue": "Padelezh : {0}", + "Latest": "Diwezhañ", + "AppDeviceValues": "Arload : {0}, Trobarzhell : {1}", + "LyricDownloadFailureFromForItem": "C'hwitet eo pellgargañ ar c'homzoù eus {0} evit {1}", + "MixedContent": "Danvez mesket", + "Movies": "Filmoù", + "Music": "Sonerezh", + "MusicVideos": "Videoioù Sonerezh", + "NameInstallFailed": "{0} c'hwitet war ar staliadur", + "NameSeasonNumber": "Koulzad {0}", + "NameSeasonUnknown": "Koulzad Dianav", + "NewVersionIsAvailable": "Ur stumm Servijer Jellyfin nevez a c'haller pellgargañ.", + "NotificationOptionApplicationUpdateAvailable": "Hizivadur an arload zo da gaout", + "NotificationOptionApplicationUpdateInstalled": "Hizivadur an arload staliet", + "NotificationOptionAudioPlayback": "Lenn aodio lañset", + "NotificationOptionAudioPlaybackStopped": "Lenn aodio ehanet", + "Original": "Orin", + "Photos": "Fotoioù", + "Shows": "Heuliadennoù", + "Undefined": "Dianav", + "TasksMaintenanceCategory": "Trezalc’h", + "TasksLibraryCategory": "Levraoueg", + "TasksApplicationCategory": "Arload", + "NotificationOptionInstallationFailed": "C'hwitet war staliañ", + "NotificationOptionPluginError": "Fazi Askouezh", + "NotificationOptionPluginInstalled": "Askouezh staliet", + "NotificationOptionPluginUninstalled": "Askouezh distaliet", + "ScheduledTaskFailedWithName": "c'hwitadenn war {0}", + "TvShows": "Heuliadennoù TV", + "VersionNumber": "Stumm {0}", + "TasksChannelsCategory": "Chadennoù enlinenn", + "TaskAudioNormalization": "Normalizadur an aodio", + "TaskRefreshPeople": "Freskaat ar gomedianed", + "TaskUpdatePlugins": "Hizivaat an askouezhioù", + "TaskRefreshChannels": "Freskaat ar chadennoù", + "TaskOptimizeDatabase": "Gwellekaat an diaz roadennoù", + "TaskKeyframeExtractor": "Eztenner skeudennoù-alc'hwez", + "NotificationOptionCameraImageUploaded": "Karget eo skeudenn ar benveg", + "NotificationOptionNewLibraryContent": "Danvez nevez ouzhpennet", + "NotificationOptionPluginUpdateInstalled": "Staliet eo hizivadur an askouezh" +} diff --git a/Emby.Server.Implementations/Localization/Core/bs.json b/Emby.Server.Implementations/Localization/Core/bs.json index 3bf5ebd35a..aa7fe4eb24 100644 --- a/Emby.Server.Implementations/Localization/Core/bs.json +++ b/Emby.Server.Implementations/Localization/Core/bs.json @@ -1,52 +1,32 @@ { - "Albums": "Albumi", "Artists": "Umjetnici", "Books": "Knjige", - "Channels": "Kanalima", "Collections": "Zbirke", "Default": "Zadano", "Favorites": "Omiljeni", "Folders": "Mape", "Genres": "Žanrovi", - "HeaderAlbumArtists": "Umjetnici albuma", "HeaderContinueWatching": "Nastavi gledati", "Movies": "Filmovi", "MusicVideos": "Muzički spotovi", "Photos": "Slike", - "Playlists": "Plejliste", "Shows": "Pokazuje", - "Songs": "Pjesme", - "ValueSpecialEpisodeName": "Posebno - {0}", "AppDeviceValues": "Aplikacija: {0}, Uređaj: {1}", - "Application": "Prijava", "AuthenticationSucceededWithUserName": "{0} uspješno autentificirano", - "CameraImageUploadedFrom": "Nova slika s kamere je postavljena sa {0}", "ChapterNameValue": "Poglavlje {0}", - "DeviceOfflineWithName": "{0} se odspojio", - "DeviceOnlineWithName": "{0} je povezan", "External": "Vanjsko", "FailedLoginAttemptWithUserName": "Neuspjeli pokušaj prijave sa {0}", "Forced": "Prisilno", - "HeaderFavoriteAlbums": "Omiljeni albumi", - "HeaderFavoriteArtists": "Omiljeni umjetnici", "HeaderFavoriteEpisodes": "Omiljene epizode", "HeaderFavoriteShows": "Omiljene emisije", - "HeaderFavoriteSongs": "Omiljene pjesme", "HeaderLiveTV": "TV uživo", "HeaderNextUp": "Slijedi", - "HeaderRecordingGroups": "Grupe za snimanje", "HearingImpaired": "Oštećen sluh", "HomeVideos": "Kućni videozapisi", "Inherit": "Nasljedi", - "ItemAddedWithName": "{0} je dodan u biblioteku", - "ItemRemovedWithName": "{0} je uklonjen iz biblioteke", "LabelIpAddressValue": "IP adresa: {0}", "LabelRunningTimeValue": "Trajanje: {0}", "Latest": "Posljednje dodano", - "MessageApplicationUpdated": "Jellyfin Server je ažuriran", - "MessageApplicationUpdatedTo": "Jellyfin Server je ažuriran na {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "Sekcija za konfiguraciju servera {0} je ažurirana", - "MessageServerConfigurationUpdated": "Konfiguracija servera je ažurirana", "MixedContent": "Miješani sadržaj", "Music": "Muzika", "NameInstallFailed": "{0} instalacija je propala", @@ -69,21 +49,14 @@ "NotificationOptionUserLockedOut": "Korisnik je zaključan", "NotificationOptionVideoPlayback": "Pokrenuto je reproduciranje videa", "NotificationOptionVideoPlaybackStopped": "Reprodukcija videa je zaustavljena", - "Plugin": "Plugin", "PluginInstalledWithName": "{0} je instaliran", "PluginUninstalledWithName": "{0} je deinstaliran", "PluginUpdatedWithName": "{0} je ažurirano", - "ProviderValue": "Pružatelj: {0}", "ScheduledTaskFailedWithName": "{0} nije uspjelo", - "ScheduledTaskStartedWithName": "{0} počelo", - "ServerNameNeedsToBeRestarted": "{0} treba ponovo pokrenuti", "StartupEmbyServerIsLoading": "Jellyfin Server se učitava. Molimo pokušajte ponovo za kratko vrijeme.", "SubtitleDownloadFailureFromForItem": "Podtitlovi nisu uspjeli preuzeti sa {0} za {1}", - "Sync": "Sinkronizacija", - "System": "Sistem", "TvShows": "TV serije", "Undefined": "Nedefinirano", - "User": "Korisnik", "UserCreatedWithName": "Korisnik {0} je kreiran", "UserDeletedWithName": "Korisnik {0} je izbrisan", "UserDownloadingItemWithValues": "{0} preuzima {1}", @@ -91,10 +64,8 @@ "UserOfflineFromDevice": "{0} se odspojio od {1}", "UserOnlineFromDevice": "{0} je online od {1}", "UserPasswordChangedWithName": "Lozinka je promijenjena za korisnika {0}", - "UserPolicyUpdatedWithName": "Pravila za korisnike su ažurirana za {0}", "UserStartedPlayingItemWithValues": "{0} igra protiv {1} na {2}", "UserStoppedPlayingItemWithValues": "{0} je završio igru protiv {1} na {2}", - "ValueHasBeenAddedToLibrary": "{0} je dodan u vašu medijsku biblioteku", "VersionNumber": "Verzija {0}", "TasksMaintenanceCategory": "Održavanje", "TasksLibraryCategory": "Biblioteka", diff --git a/Emby.Server.Implementations/Localization/Core/ca.json b/Emby.Server.Implementations/Localization/Core/ca.json index f9543e6f4c..6c81726ee6 100644 --- a/Emby.Server.Implementations/Localization/Core/ca.json +++ b/Emby.Server.Implementations/Localization/Core/ca.json @@ -1,41 +1,24 @@ { - "Albums": "Àlbums", "AppDeviceValues": "Aplicació: {0}, Dispositiu: {1}", - "Application": "Aplicació", "Artists": "Artistes", "AuthenticationSucceededWithUserName": "{0} s'ha autenticat correctament", "Books": "Llibres", - "CameraImageUploadedFrom": "S'ha pujat una nova imatge de càmera des de {0}", - "Channels": "Canals", "ChapterNameValue": "Capítol {0}", "Collections": "Col·leccions", - "DeviceOfflineWithName": "{0} s'ha desconnectat", - "DeviceOnlineWithName": "{0} està connectat", "FailedLoginAttemptWithUserName": "Intent de connexió fallit des de {0}", "Favorites": "Preferits", "Folders": "Directoris", "Genres": "Gèneres", - "HeaderAlbumArtists": "Artistes de l'àlbum", "HeaderContinueWatching": "Continueu mirant", - "HeaderFavoriteAlbums": "Àlbums preferits", - "HeaderFavoriteArtists": "Artistes preferits", "HeaderFavoriteEpisodes": "Episodis preferits", "HeaderFavoriteShows": "Sèries preferides", - "HeaderFavoriteSongs": "Cançons preferides", "HeaderLiveTV": "TV en directe", "HeaderNextUp": "A continuació", - "HeaderRecordingGroups": "Grups musicals", "HomeVideos": "Vídeos domèstics", "Inherit": "Heretat", - "ItemAddedWithName": "{0} s'ha afegit a la mediateca", - "ItemRemovedWithName": "{0} s'ha eliminat de la mediateca", "LabelIpAddressValue": "Adreça IP: {0}", "LabelRunningTimeValue": "Temps en marxa: {0}", "Latest": "Darrers", - "MessageApplicationUpdated": "El servidor de Jellyfin ha estat actualitzat", - "MessageApplicationUpdatedTo": "El servidor de Jellyfin ha estat actualitzat a {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "La secció {0} de la configuració del servidor ha estat actualitzada", - "MessageServerConfigurationUpdated": "S'ha actualitzat la configuració del servidor", "MixedContent": "Contingut barrejat", "Movies": "Pel·lícules", "Music": "Música", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "Reproducció de vídeo iniciada", "NotificationOptionVideoPlaybackStopped": "Reproducció de vídeo aturada", "Photos": "Fotos", - "Playlists": "Llistes de reproducció", - "Plugin": "Complement", "PluginInstalledWithName": "S'ha instal·lat {0}", "PluginUninstalledWithName": "S'ha desinstal·lat {0}", "PluginUpdatedWithName": "S'ha actualitzat {0}", - "ProviderValue": "Proveïdor: {0}", "ScheduledTaskFailedWithName": "{0} ha fallat", - "ScheduledTaskStartedWithName": "S'ha iniciat {0}", - "ServerNameNeedsToBeRestarted": "S'ha de reiniciar {0}", "Shows": "Sèries", - "Songs": "Cançons", "StartupEmbyServerIsLoading": "El servidor de Jellyfin s'està carregant. Proveu-ho de nou en una estona.", "SubtitleDownloadFailureFromForItem": "Els subtítols per a {1} no s'han pogut baixar de {0}", - "Sync": "Sincronitza", - "System": "Sistema", "TvShows": "Sèries de TV", - "User": "Usuari", "UserCreatedWithName": "S'ha creat l'usuari {0}", "UserDeletedWithName": "S'ha eliminat l'usuari {0}", "UserDownloadingItemWithValues": "{0} està descarregant {1}", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "{0} s'ha desconnectat de {1}", "UserOnlineFromDevice": "{0} està connectat des de {1}", "UserPasswordChangedWithName": "S'ha canviat la contrasenya per a l'usuari {0}", - "UserPolicyUpdatedWithName": "La política d'usuari s'ha actualitzat per a {0}", "UserStartedPlayingItemWithValues": "{0} ha començat a reproduir {1} a {2}", "UserStoppedPlayingItemWithValues": "{0} ha parat de reproduir {1} a {2}", - "ValueHasBeenAddedToLibrary": "S'ha afegit {0} a la mediateca", - "ValueSpecialEpisodeName": "Especial - {0}", "VersionNumber": "Versió {0}", "TaskDownloadMissingSubtitlesDescription": "Cerca a internet els subtítols que faltin a partir de la configuració de metadades.", "TaskDownloadMissingSubtitles": "Descàrrega dels subtítols que faltin", @@ -135,5 +106,7 @@ "TaskMoveTrickplayImages": "Migració de la ubicació de la imatge de previsualització", "TaskMoveTrickplayImagesDescription": "Mou els fitxers existents d'imatges de previsualització segons la configuració de la mediateca.", "CleanupUserDataTaskDescription": "Neteja totes les dades d'usuari (estat de la visualització, estat dels preferits, etc.) del contingut multimèdia que no ha estat present durant almenys 90 dies.", - "CleanupUserDataTask": "Tasca de neteja de dades d'usuari" + "CleanupUserDataTask": "Tasca de neteja de dades d'usuari", + "Original": "Original", + "LyricDownloadFailureFromForItem": "No s'han pogut descarregar les lletres des de {0} per a {1}" } diff --git a/Emby.Server.Implementations/Localization/Core/chr.json b/Emby.Server.Implementations/Localization/Core/chr.json index 85d1f4c881..7e039bafc2 100644 --- a/Emby.Server.Implementations/Localization/Core/chr.json +++ b/Emby.Server.Implementations/Localization/Core/chr.json @@ -1,44 +1,30 @@ { "ChapterNameValue": "Didanedi {0}", - "HeaderAlbumArtists": "Didanidanolisgisgi", - "HeaderFavoriteAlbums": "Dvganidi didanidisgisgi", "HeaderLiveTV": "Anigadi didanidisgosgi", - "HeaderRecordingGroups": "Didanisquodiisgisgi", "HomeVideos": "Diganadi dinagadisgisgi", "Inherit": "Anigwe", - "MessageApplicationUpdatedTo": "Tsenigwidinonvhi Jellyfin Server tsadanidigwe anigadi {0}", "MixedContent": "Ganinidi dininoladisgisgi", "Movies": "Anidvnisgisgi", "MusicVideos": "Danodisgisgi didanidisgosgi", "NotificationOptionAudioPlayback": "Didanidigwe diganuyisgisgi anigadi", "NotificationOptionInstallationFailed": "Diudvdi anadvnatisgisgi", "NotificationOptionPluginUninstalled": "Ditsigvhnidv anawvdisgisgi", - "Albums": "Anigawidaniyv", - "Application": "Didanvyi", "Artists": "Dinidaniyi", "AuthenticationSucceededWithUserName": "{0} Sesoquonisdi nagadani", "Books": "Didanedi", - "CameraImageUploadedFrom": "Anigawidaniyv nasgi didagwalanvyi {0}", - "Channels": "Diganadasgi", "Collections": "Diganadisgi", "Default": "Dinadi", - "DeviceOfflineWithName": "{0} Aniyvolehvi nasgi", "External": "Amohdi", "Favorites": "Nvdayelvdisgi", "Folders": "Didanididisgi", "Forced": "Ganedi", "Genres": "Diganadisgi", "HeaderContinueWatching": "Uwoditsu asdanidisgisgi", - "HeaderFavoriteArtists": "Dvganidi dinidanolisgisgi", "HeaderFavoriteEpisodes": "Dvganidi didanidilisgadisgisgi", "HeaderFavoriteShows": "Dvganidi didanididanolisgisgi)", - "HeaderFavoriteSongs": "Dvganidi danodisgisgi", "HeaderNextUp": "Anidvli uwodoli", "HearingImpaired": "Anitsunidi talunidisgisgi", - "ItemAddedWithName": "{0} Dinigwe anididanidisgi", "Latest": "Uwodoli", - "MessageApplicationUpdated": "Tsenigwidinonvhi Jellyfin Server tsadanidigwe", - "MessageServerConfigurationUpdated": "Sedanidvdi anigadi diganidinonvhi", "Music": "Danodisgisgi", "NameSeasonUnknown": "Tsunita anidvdisgi", "NewVersionIsAvailable": "Danodigwe anigadi Jellyfin Server tsadanidigwe adisdi uwodvdi diganidinonvhi.", diff --git a/Emby.Server.Implementations/Localization/Core/cs.json b/Emby.Server.Implementations/Localization/Core/cs.json index 3fc1895842..28f0e2df97 100644 --- a/Emby.Server.Implementations/Localization/Core/cs.json +++ b/Emby.Server.Implementations/Localization/Core/cs.json @@ -1,41 +1,24 @@ { - "Albums": "Alba", "AppDeviceValues": "Aplikace: {0}, Zařízení: {1}", - "Application": "Aplikace", "Artists": "Umělci", "AuthenticationSucceededWithUserName": "{0} úspěšně ověřen", "Books": "Knihy", - "CameraImageUploadedFrom": "Z {0} byla nahrána nová fotografie z fotoaparátu", - "Channels": "Kanály", "ChapterNameValue": "Kapitola {0}", "Collections": "Kolekce", - "DeviceOfflineWithName": "{0} se odpojil", - "DeviceOnlineWithName": "{0} je připojen", "FailedLoginAttemptWithUserName": "Neúspěšný pokus o přihlášení z {0}", "Favorites": "Oblíbené", "Folders": "Složky", "Genres": "Žánry", - "HeaderAlbumArtists": "Umělci alba", "HeaderContinueWatching": "Pokračovat ve sledování", - "HeaderFavoriteAlbums": "Oblíbená alba", - "HeaderFavoriteArtists": "Oblíbení interpreti", "HeaderFavoriteEpisodes": "Oblíbené epizody", "HeaderFavoriteShows": "Oblíbené seriály", - "HeaderFavoriteSongs": "Oblíbená hudba", "HeaderLiveTV": "TV vysílání", "HeaderNextUp": "Další díly", - "HeaderRecordingGroups": "Skupiny nahrávek", "HomeVideos": "Domácí videa", "Inherit": "Zdědit", - "ItemAddedWithName": "{0} byl přidán do knihovny", - "ItemRemovedWithName": "{0} byl odstraněn z knihovny", "LabelIpAddressValue": "IP adresa: {0}", "LabelRunningTimeValue": "Délka média: {0}", "Latest": "Nejnovější", - "MessageApplicationUpdated": "Jellyfin Server byl aktualizován", - "MessageApplicationUpdatedTo": "Jellyfin server byl aktualizován na verzi {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "Konfigurace sekce {0} na serveru byla aktualizována", - "MessageServerConfigurationUpdated": "Konfigurace serveru aktualizována", "MixedContent": "Smíšený obsah", "Movies": "Filmy", "Music": "Hudba", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "Přehrávání videa zahájeno", "NotificationOptionVideoPlaybackStopped": "Přehrávání videa ukončeno", "Photos": "Fotky", - "Playlists": "Seznamy skladeb", - "Plugin": "Zásuvný modul", "PluginInstalledWithName": "{0} byl nainstalován", "PluginUninstalledWithName": "{0} byl odinstalován", "PluginUpdatedWithName": "{0} byl aktualizován", - "ProviderValue": "Poskytl: {0}", "ScheduledTaskFailedWithName": "{0} selhalo", - "ScheduledTaskStartedWithName": "{0} zahájeno", - "ServerNameNeedsToBeRestarted": "{0} vyžaduje restart", "Shows": "Seriály", - "Songs": "Skladby", "StartupEmbyServerIsLoading": "Jellyfin Server je spouštěn. Zkuste to prosím v brzké době znovu.", "SubtitleDownloadFailureFromForItem": "Stažení titulků pro {1} z {0} selhalo", - "Sync": "Synchronizace", - "System": "Systém", "TvShows": "Seriály", - "User": "Uživatel", "UserCreatedWithName": "Uživatel {0} byl vytvořen", "UserDeletedWithName": "Uživatel {0} byl smazán", "UserDownloadingItemWithValues": "{0} stahuje {1}", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "{0} se odpojil ze zařízení {1}", "UserOnlineFromDevice": "{0} se připojil ze zařízení {1}", "UserPasswordChangedWithName": "Provedena změna hesla pro uživatele {0}", - "UserPolicyUpdatedWithName": "Zásady uživatele pro {0} byly aktualizovány", "UserStartedPlayingItemWithValues": "{0} spustil přehrávání {1}", "UserStoppedPlayingItemWithValues": "{0} zastavil přehrávání {1}", - "ValueHasBeenAddedToLibrary": "{0} byl přidán do vaší knihovny médií", - "ValueSpecialEpisodeName": "Speciál - {0}", "VersionNumber": "Verze {0}", "TaskDownloadMissingSubtitlesDescription": "Vyhledá na internetu chybějící titulky na základě nastavení metadat.", "TaskDownloadMissingSubtitles": "Stáhnout chybějící titulky", @@ -136,5 +107,6 @@ "TaskMoveTrickplayImagesDescription": "Přesune existující soubory Trickplay podle nastavení knihovny.", "CleanupUserDataTaskDescription": "Odstraní všechna uživatelská data (stav zhlédnutí, oblíbené atd.) z médií, které již neexistují více než 90 dní.", "CleanupUserDataTask": "Pročistit uživatelská data", - "Original": "Originál" + "Original": "Originál", + "LyricDownloadFailureFromForItem": "Nepodařilo se stáhnout texty pro {1} ze služby {0}" } diff --git a/Emby.Server.Implementations/Localization/Core/cy.json b/Emby.Server.Implementations/Localization/Core/cy.json index af0e89bf80..e4d8ee7731 100644 --- a/Emby.Server.Implementations/Localization/Core/cy.json +++ b/Emby.Server.Implementations/Localization/Core/cy.json @@ -1,16 +1,11 @@ { - "DeviceOnlineWithName": "Mae {0} wedi'i gysylltu", - "DeviceOfflineWithName": "Mae {0} wedi datgysylltu", "Default": "Diofyn", "Collections": "Casgliadau", "ChapterNameValue": "Pennod {0}", - "Channels": "Sianeli", - "CameraImageUploadedFrom": "Mae delwedd camera newydd wedi'i lanlwytho o {0}", "Books": "Llyfrau", "AuthenticationSucceededWithUserName": "{0} wedi’i ddilysu’n llwyddiannus", "Artists": "Crewyr", "AppDeviceValues": "Ap: {0}, Dyfais: {1}", - "Albums": "Albwmau", "Genres": "Genres", "Folders": "Ffolderi", "Favorites": "Ffefrynnau", @@ -20,9 +15,7 @@ "TaskRefreshPeople": "Adnewyddu Pobl", "TasksChannelsCategory": "Sianeli Internet", "VersionNumber": "Fersiwn {0}", - "ScheduledTaskStartedWithName": "{0} wedi dechrau", "ScheduledTaskFailedWithName": "{0} wedi methu", - "ProviderValue": "Darparwr: {0}", "NotificationOptionInstallationFailed": "Fethu Gosod", "NameSeasonUnknown": "Tymor Anhysbys", "NameSeasonNumber": "Tymor {0}", @@ -30,31 +23,20 @@ "MixedContent": "Cynnwys amrywiol", "HomeVideos": "Genres", "HeaderNextUp": "Nesaf i Fyny", - "HeaderFavoriteArtists": "Ffefryn Artistiaid", - "HeaderFavoriteAlbums": "Ffefryn Albwmau", "HeaderContinueWatching": "Parhewch i Wylio", "TasksApplicationCategory": "Rhaglen", "TasksLibraryCategory": "Llyfrgell", "TasksMaintenanceCategory": "Cynnal a Chadw", - "System": "System", - "Plugin": "Ategyn", "Music": "Cerddoriaeth", "Latest": "Diweddaraf", "Inherit": "Etifeddu", "Forced": "Orfodi", - "Application": "Rhaglen", - "HeaderAlbumArtists": "Artistiaid albwm", - "Sync": "Cysoni", - "Songs": "Caneuon", "Shows": "Rhaglenni", - "Playlists": "Rhestri Chwarae", "Photos": "Lluniau", - "ValueSpecialEpisodeName": "Arbennig - {0}", "Movies": "Ffilmiau", "Undefined": "Heb ddiffiniad", "TvShows": "Rhaglenni teledu", "HeaderLiveTV": "Teledu Byw", - "User": "Defnyddiwr", "TaskCleanLogsDescription": "Dileu ffeiliau log sy'n fwy na {0} diwrnod oed.", "TaskCleanLogs": "Glanhau ffolder log", "TaskRefreshLibraryDescription": "Sganio'ch llyfrgell gyfryngau am ffeiliau newydd ac yn adnewyddu metaddata.", @@ -65,13 +47,9 @@ "NotificationOptionPluginError": "Methodd ategyn", "NotificationOptionAudioPlaybackStopped": "Stopiwyd chwarae sain", "NotificationOptionAudioPlayback": "Dechreuwyd chwarae sain", - "MessageServerConfigurationUpdated": "Mae gosodiadau gweinydd wedi'i ddiweddaru", - "MessageNamedServerConfigurationUpdatedWithValue": "Mae adran gosodiadau gweinydd {0} wedi'i diweddaru", "FailedLoginAttemptWithUserName": "Cais mewngofnodi wedi methu o {0}", - "ValueHasBeenAddedToLibrary": "{0} wedi'i hychwanegu at eich llyfrgell gyfryngau", "UserStoppedPlayingItemWithValues": "{0} wedi gorffen chwarae {1} ar {2}", "UserStartedPlayingItemWithValues": "{0} yn chwarae {1} ar {2}", - "UserPolicyUpdatedWithName": "Polisi defnyddiwr wedi'i newid ar gyfer {0}", "UserPasswordChangedWithName": "Cyfrinair wedi'i newid ar gyfer defnyddiwr {0}", "UserOnlineFromDevice": "Mae {0} ar-lein o {1}", "UserOfflineFromDevice": "Mae {0} wedi datgysylltu o {1}", @@ -80,7 +58,6 @@ "UserDeletedWithName": "Defnyddiwr {0} wedi'i ddileu", "UserCreatedWithName": "Defnyddiwr {0} wedi'i greu", "StartupEmbyServerIsLoading": "Gweinydd Jellyfin yn llwytho. Triwch eto mewn ychydig.", - "ServerNameNeedsToBeRestarted": "Mae angen ailddechrau {0}", "PluginUpdatedWithName": "{0} wedi'i ddiweddaru", "PluginUninstalledWithName": "{0} wedi'i ddadosod", "PluginInstalledWithName": "{0} wedi'i osod", @@ -98,13 +75,7 @@ "NotificationOptionApplicationUpdateAvailable": "Diweddariad ap ar gael", "NewVersionIsAvailable": "Mae fersiwn diweddarach o'r gweinydd Jellyfin ar gael.", "NameInstallFailed": "Gosodiad {0} wedi methu", - "MessageApplicationUpdatedTo": "Gweinydd Jellyfin wedi'i ddiweddaru i {0}", - "MessageApplicationUpdated": "Gweinydd Jellyfin wedi'i ddiweddaru", "LabelIpAddressValue": "Cyfeiriad IP: {0}", - "ItemRemovedWithName": "{0} wedi'i dynnu o'r llyfrgell", - "ItemAddedWithName": "{0} wedi'i adio i'r llyfrgell", - "HeaderRecordingGroups": "Grwpiau Recordio", - "HeaderFavoriteSongs": "Ffefryn Ganeuon", "HeaderFavoriteShows": "Ffefryn Shoeau", "HeaderFavoriteEpisodes": "Ffefryn Rhaglenni", "TaskDownloadMissingSubtitlesDescription": "Chwilio'r rhyngrwyd am is-deitlau coll yn seiliedig ar gosodiadau metaddata.", diff --git a/Emby.Server.Implementations/Localization/Core/da.json b/Emby.Server.Implementations/Localization/Core/da.json index 7d905f3300..de56b6fd66 100644 --- a/Emby.Server.Implementations/Localization/Core/da.json +++ b/Emby.Server.Implementations/Localization/Core/da.json @@ -1,41 +1,24 @@ { - "Albums": "Albummer", "AppDeviceValues": "App: {0}, Enhed: {1}", - "Application": "Applikation", "Artists": "Kunstnere", "AuthenticationSucceededWithUserName": "{0} er logget ind", "Books": "Bøger", - "CameraImageUploadedFrom": "Et nyt kamerabillede er blevet uploadet fra {0}", - "Channels": "Kanaler", "ChapterNameValue": "Kapitel {0}", "Collections": "Samlinger", - "DeviceOfflineWithName": "{0} har afbrudt forbindelsen", - "DeviceOnlineWithName": "{0} er forbundet", "FailedLoginAttemptWithUserName": "Mislykket loginforsøg fra {0}", "Favorites": "Favoritter", "Folders": "Mapper", "Genres": "Genrer", - "HeaderAlbumArtists": "Albumkunstnere", - "HeaderContinueWatching": "Fortsæt afspilning", - "HeaderFavoriteAlbums": "Favoritalbum", - "HeaderFavoriteArtists": "Favoritkunstnere", + "HeaderContinueWatching": "Fortsæt med at se", "HeaderFavoriteEpisodes": "Yndlingsafsnit", "HeaderFavoriteShows": "Yndlingsserier", - "HeaderFavoriteSongs": "Yndlingssange", "HeaderLiveTV": "Live-TV", "HeaderNextUp": "Næste", - "HeaderRecordingGroups": "Optagelsesgrupper", "HomeVideos": "Hjemmevideoer", "Inherit": "Nedarv", - "ItemAddedWithName": "{0} blev tilføjet til biblioteket", - "ItemRemovedWithName": "{0} blev fjernet fra biblioteket", "LabelIpAddressValue": "IP-adresse: {0}", "LabelRunningTimeValue": "Spilletid: {0}", "Latest": "Seneste", - "MessageApplicationUpdated": "Jellyfin Server er blevet opdateret", - "MessageApplicationUpdatedTo": "Jellyfin Server er blevet opdateret til {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "Serverkonfiguration sektion {0} er blevet opdateret", - "MessageServerConfigurationUpdated": "Serverkonfigurationen er blevet opdateret", "MixedContent": "Blandet indhold", "Movies": "Film", "Music": "Musik", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "Videoafspilning påbegyndt", "NotificationOptionVideoPlaybackStopped": "Videoafspilning blev stoppet", "Photos": "Fotos", - "Playlists": "Afspilningslister", - "Plugin": "Plugin", "PluginInstalledWithName": "{0} blev installeret", "PluginUninstalledWithName": "{0} blev afinstalleret", "PluginUpdatedWithName": "{0} blev opdateret", - "ProviderValue": "Udbyder: {0}", "ScheduledTaskFailedWithName": "{0} mislykkedes", - "ScheduledTaskStartedWithName": "{0} påbegyndte", - "ServerNameNeedsToBeRestarted": "{0} skal genstartes", "Shows": "Serier", - "Songs": "Sange", "StartupEmbyServerIsLoading": "Jellyfin er i gang med at starte. Prøv igen om et øjeblik.", "SubtitleDownloadFailureFromForItem": "Undertekster kunne ikke hentes fra {0} til {1}", - "Sync": "Synkroniser", - "System": "System", "TvShows": "TV-serier", - "User": "Bruger", "UserCreatedWithName": "Bruger {0} er blevet oprettet", "UserDeletedWithName": "Brugeren {0} er nu slettet", "UserDownloadingItemWithValues": "{0} henter {1}", @@ -85,16 +59,13 @@ "UserOfflineFromDevice": "{0} har afbrudt fra {1}", "UserOnlineFromDevice": "{0} er online fra {1}", "UserPasswordChangedWithName": "Adgangskode er ændret for brugeren {0}", - "UserPolicyUpdatedWithName": "Brugerpolitikken er blevet opdateret for {0}", "UserStartedPlayingItemWithValues": "{0} afspiller {1} på {2}", "UserStoppedPlayingItemWithValues": "{0} har afsluttet afspilning af {1} på {2}", - "ValueHasBeenAddedToLibrary": "{0} er blevet tilføjet til dit mediebibliotek", - "ValueSpecialEpisodeName": "Special - {0}", "VersionNumber": "Version {0}", "TaskDownloadMissingSubtitlesDescription": "Søger på internettet efter manglende undertekster baseret på metadata-konfigurationen.", "TaskDownloadMissingSubtitles": "Hent manglende undertekster", "TaskUpdatePluginsDescription": "Henter og installerer opdateringer for plugins, som er konfigurerede til at blive opdateret automatisk.", - "TaskUpdatePlugins": "Opdater plugins", + "TaskUpdatePlugins": "Opdatér plugins", "TaskCleanLogsDescription": "Sletter log-filer som er mere end {0} dage gamle.", "TaskCleanLogs": "Ryd log-mappe", "TaskRefreshLibraryDescription": "Scanner dit mediebibliotek for nye filer og opdateret metadata.", @@ -108,10 +79,10 @@ "TaskRefreshChapterImages": "Udtræk kapitelbilleder", "TaskRefreshChapterImagesDescription": "Laver miniaturebilleder for videoer, der har kapitler.", "TaskRefreshChannelsDescription": "Opdaterer information for internetkanaler.", - "TaskRefreshChannels": "Opdater kanaler", + "TaskRefreshChannels": "Opdatér kanaler", "TaskCleanTranscodeDescription": "Fjerner omkodningsfiler, som er mere end 1 dag gamle.", "TaskCleanTranscode": "Tøm omkodningsmappen", - "TaskRefreshPeople": "Opdater personer", + "TaskRefreshPeople": "Opdatér personer", "TaskRefreshPeopleDescription": "Opdaterer metadata for skuespillere og instruktører i dit mediebibliotek.", "TaskCleanActivityLogDescription": "Sletter linjer i aktivitetsloggen ældre end den konfigurerede alder.", "TaskCleanActivityLog": "Ryd aktivitetslog", @@ -119,7 +90,7 @@ "Forced": "Tvunget", "Default": "Standard", "TaskOptimizeDatabaseDescription": "Komprimerer databasen for at frigøre plads. Denne handling køres efter at have scannet mediebiblioteket, eller efter at have lavet ændringer til databasen.", - "TaskOptimizeDatabase": "Optimer database", + "TaskOptimizeDatabase": "Optimér database", "TaskKeyframeExtractorDescription": "Udtrækker rammer fra videofiler for at lave mere præcise HLS-playlister. Denne opgave kan tage lang tid.", "TaskKeyframeExtractor": "Udtræk nøglerammer", "External": "Ekstern", @@ -128,12 +99,14 @@ "TaskRefreshTrickplayImagesDescription": "Laver trickplay-billeder for videoer i aktiverede biblioteker.", "TaskAudioNormalizationDescription": "Skanner filer for data vedrørende lydnormalisering.", "TaskAudioNormalization": "Lydnormalisering", - "TaskDownloadMissingLyricsDescription": "Søger på internettet efter manglende sangtekster baseret på metadata-konfigurationen", + "TaskDownloadMissingLyricsDescription": "Download sangtekster", "TaskDownloadMissingLyrics": "Hent manglende sangtekster", "TaskExtractMediaSegments": "Scan for mediesegmenter", "TaskMoveTrickplayImages": "Migrer billedelokationer for trickplay-billeder", "TaskMoveTrickplayImagesDescription": "Flyt eksisterende trickplay-billeder jævnfør biblioteksindstillinger.", "TaskExtractMediaSegmentsDescription": "Udtrækker eller henter mediesegmenter fra plugins som understøtter MediaSegment.", "CleanupUserDataTask": "Brugerdata oprydningsopgave", - "CleanupUserDataTaskDescription": "Rydder alle brugerdata (eks. visning- og favoritstatus) fra medier, der har været utilgængelige i mindst 90 dage." + "CleanupUserDataTaskDescription": "Rydder alle brugerdata (eks. visning- og favoritstatus) fra medier, der har været utilgængelige i mindst 90 dage.", + "LyricDownloadFailureFromForItem": "Sangtekster kunne ikke downloades fra {0} til {1}", + "Original": "Original" } diff --git a/Emby.Server.Implementations/Localization/Core/de.json b/Emby.Server.Implementations/Localization/Core/de.json index b628f45ea7..8ac5fdf6fc 100644 --- a/Emby.Server.Implementations/Localization/Core/de.json +++ b/Emby.Server.Implementations/Localization/Core/de.json @@ -1,41 +1,24 @@ { - "Albums": "Alben", "AppDeviceValues": "App: {0}, Gerät: {1}", - "Application": "Anwendung", "Artists": "Interpreten", "AuthenticationSucceededWithUserName": "{0} erfolgreich authentifiziert", "Books": "Bücher", - "CameraImageUploadedFrom": "Ein neues Kamerabild wurde von {0} hochgeladen", - "Channels": "Kanäle", "ChapterNameValue": "Kapitel {0}", "Collections": "Sammlungen", - "DeviceOfflineWithName": "{0} ist offline", - "DeviceOnlineWithName": "{0} ist online", "FailedLoginAttemptWithUserName": "Anmeldung von {0} fehlgeschlagen", "Favorites": "Favoriten", "Folders": "Verzeichnisse", "Genres": "Genres", - "HeaderAlbumArtists": "Album-Interpreten", "HeaderContinueWatching": "Weiterschauen", - "HeaderFavoriteAlbums": "Lieblingsalben", - "HeaderFavoriteArtists": "Lieblingsinterpreten", "HeaderFavoriteEpisodes": "Lieblingsfolgen", "HeaderFavoriteShows": "Lieblingsserien", - "HeaderFavoriteSongs": "Lieblingssongs", "HeaderLiveTV": "Live TV", "HeaderNextUp": "Als Nächstes", - "HeaderRecordingGroups": "Aufnahme-Gruppen", "HomeVideos": "Heimvideos", "Inherit": "Vererben", - "ItemAddedWithName": "{0} wurde der Bibliothek hinzugefügt", - "ItemRemovedWithName": "{0} wurde aus der Bibliothek entfernt", "LabelIpAddressValue": "IP-Adresse: {0}", "LabelRunningTimeValue": "Laufzeit: {0}", "Latest": "Neueste", - "MessageApplicationUpdated": "Jellyfin-Server wurde aktualisiert", - "MessageApplicationUpdatedTo": "Jellyfin-Server wurde auf Version {0} aktualisiert", - "MessageNamedServerConfigurationUpdatedWithValue": "Der Server-Einstellungsbereich {0} wurde aktualisiert", - "MessageServerConfigurationUpdated": "Servereinstellungen wurden aktualisiert", "MixedContent": "Gemischte Inhalte", "Movies": "Filme", "Music": "Musik", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "Video wird abgespielt", "NotificationOptionVideoPlaybackStopped": "Videowiedergabe gestoppt", "Photos": "Fotos", - "Playlists": "Wiedergabelisten", - "Plugin": "Plugin", "PluginInstalledWithName": "{0} wurde installiert", "PluginUninstalledWithName": "{0} wurde deinstalliert", "PluginUpdatedWithName": "{0} wurde aktualisiert", - "ProviderValue": "Anbieter: {0}", "ScheduledTaskFailedWithName": "{0} ist fehlgeschlagen", - "ScheduledTaskStartedWithName": "{0} wurde gestartet", - "ServerNameNeedsToBeRestarted": "{0} muss neu gestartet werden", "Shows": "Serien", - "Songs": "Lieder", "StartupEmbyServerIsLoading": "Jellyfin-Server lädt. Bitte versuche es gleich noch einmal.", "SubtitleDownloadFailureFromForItem": "Untertitel von {0} für {1} konnten nicht heruntergeladen werden", - "Sync": "Synchronisation", - "System": "System", "TvShows": "Serien", - "User": "Benutzer", "UserCreatedWithName": "Benutzer {0} wurde erstellt", "UserDeletedWithName": "Benutzer {0} wurde gelöscht", "UserDownloadingItemWithValues": "{0} lädt {1} herunter", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "{0} wurde getrennt von {1}", "UserOnlineFromDevice": "{0} ist online von {1}", "UserPasswordChangedWithName": "Das Passwort für Benutzer {0} wurde geändert", - "UserPolicyUpdatedWithName": "Benutzerrichtlinie von {0} wurde aktualisiert", "UserStartedPlayingItemWithValues": "{0} hat die Wiedergabe von {1} auf {2} gestartet", "UserStoppedPlayingItemWithValues": "{0} hat die Wiedergabe von {1} auf {2} beendet", - "ValueHasBeenAddedToLibrary": "{0} wurde deiner Bibliothek hinzugefügt", - "ValueSpecialEpisodeName": "Extra – {0}", "VersionNumber": "Version {0}", "TaskDownloadMissingSubtitlesDescription": "Sucht im Internet basierend auf den Metadaten-Einstellungen nach fehlenden Untertiteln.", "TaskDownloadMissingSubtitles": "Fehlende Untertitel herunterladen", @@ -136,5 +107,6 @@ "TaskMoveTrickplayImagesDescription": "Trickplay-Bilder werden entsprechend der Bibliothekseinstellungen verschoben.", "CleanupUserDataTask": "Aufgabe zur Bereinigung von Benutzerdaten", "CleanupUserDataTaskDescription": "Löscht alle Benutzerdaten (Abspielstatus, Favoritenstatus, usw.) von Medien, die seit mindestens 90 Tagen nicht mehr vorhanden sind.", - "Original": "Original" + "Original": "Original", + "LyricDownloadFailureFromForItem": "Fehler beim Download der Songtexte von {0} für {1}" } diff --git a/Emby.Server.Implementations/Localization/Core/el.json b/Emby.Server.Implementations/Localization/Core/el.json index 0443207ea6..c0ad2c165a 100644 --- a/Emby.Server.Implementations/Localization/Core/el.json +++ b/Emby.Server.Implementations/Localization/Core/el.json @@ -1,41 +1,24 @@ { - "Albums": "Άλμπουμ", "AppDeviceValues": "Εφαρμογή: {0}, Συσκευή: {1}", - "Application": "Εφαρμογή", "Artists": "Καλλιτέχνες", "AuthenticationSucceededWithUserName": "Ο χρήστης {0} επαληθεύτηκε επιτυχώς", "Books": "Βιβλία", - "CameraImageUploadedFrom": "Μια νέα φωτογραφία φορτώθηκε από {0}", - "Channels": "Κανάλια", "ChapterNameValue": "Κεφάλαιο {0}", "Collections": "Συλλογές", - "DeviceOfflineWithName": "Ο/Η {0} αποσυνδέθηκε", - "DeviceOnlineWithName": "Ο/Η {0} συνδέθηκε", "FailedLoginAttemptWithUserName": "Αποτυχία προσπάθειας σύνδεσης από {0}", "Favorites": "Αγαπημένα", "Folders": "Φάκελοι", "Genres": "Είδη", - "HeaderAlbumArtists": "Καλλιτέχνες άλμπουμ", "HeaderContinueWatching": "Συνεχίστε την παρακολούθηση", - "HeaderFavoriteAlbums": "Αγαπημένα Άλμπουμ", - "HeaderFavoriteArtists": "Αγαπημένοι Καλλιτέχνες", "HeaderFavoriteEpisodes": "Αγαπημένα Επεισόδια", "HeaderFavoriteShows": "Αγαπημένες Σειρές", - "HeaderFavoriteSongs": "Αγαπημένα Τραγούδια", "HeaderLiveTV": "Ζωντανή Τηλεόραση", "HeaderNextUp": "Επόμενο", - "HeaderRecordingGroups": "Ομάδες Ηχογράφησης", "HomeVideos": "Προσωπικά Βίντεο", "Inherit": "Κληρονόμηση", - "ItemAddedWithName": "Το {0} προστέθηκε στη βιβλιοθήκη", - "ItemRemovedWithName": "Το {0} διαγράφτηκε από τη βιβλιοθήκη", "LabelIpAddressValue": "Διεύθυνση IP: {0}", "LabelRunningTimeValue": "Διάρκεια: {0}", "Latest": "Πρόσφατα", - "MessageApplicationUpdated": "Ο διακομιστής Jellyfin έχει ενημερωθεί", - "MessageApplicationUpdatedTo": "Ο διακομιστής Jellyfin αναβαθμίστηκε στην έκδοση {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "Η ενότητα {0} ρύθμισης παραμέτρων του διακομιστή έχει ενημερωθεί", - "MessageServerConfigurationUpdated": "Η ρύθμιση παραμέτρων του διακομιστή έχει ενημερωθεί", "MixedContent": "Ανάμεικτο Περιεχόμενο", "Movies": "Ταινίες", "Music": "Μουσική", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "Η αναπαραγωγή βίντεο ξεκίνησε", "NotificationOptionVideoPlaybackStopped": "Η αναπαραγωγή βίντεο σταμάτησε", "Photos": "Φωτογραφίες", - "Playlists": "Λίστες αναπαραγωγής", - "Plugin": "Πρόσθετο", "PluginInstalledWithName": "Το {0} εγκαταστάθηκε", "PluginUninstalledWithName": "Το {0} έχει απεγκατασταθεί", "PluginUpdatedWithName": "Το {0} ενημερώθηκε", - "ProviderValue": "Πάροχος: {0}", "ScheduledTaskFailedWithName": "{0} αποτυχία", - "ScheduledTaskStartedWithName": "{0} ξεκίνησε", - "ServerNameNeedsToBeRestarted": "{0} χρειάζεται επανεκκίνηση", "Shows": "Σειρές", - "Songs": "Τραγούδια", "StartupEmbyServerIsLoading": "Ο διακομιστής Jellyfin φορτώνει. Περιμένετε λίγο και δοκιμάστε ξανά.", - "SubtitleDownloadFailureFromForItem": "Αποτυχίες μεταφόρτωσης υποτίτλων από {0} για {1}", - "Sync": "Συγχρονισμός", - "System": "Σύστημα", + "SubtitleDownloadFailureFromForItem": "Αποτυχία λήψης υποτίτλων από {0} για {1}", "TvShows": "Τηλεοπτικές Σειρές", - "User": "Χρήστης", "UserCreatedWithName": "Ο χρήστης {0} δημιουργήθηκε", "UserDeletedWithName": "Ο χρήστης {0} έχει διαγραφεί", "UserDownloadingItemWithValues": "{0} κατεβάζει {1}", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "{0} αποσυνδέθηκε από {1}", "UserOnlineFromDevice": "{0} είναι online απο {1}", "UserPasswordChangedWithName": "Ο κωδικός του χρήστη {0} έχει αλλάξει", - "UserPolicyUpdatedWithName": "Η πολιτική χρήστη έχει ενημερωθεί για {0}", "UserStartedPlayingItemWithValues": "{0} παίζει {1} σε {2}", "UserStoppedPlayingItemWithValues": "{0} τελείωσε να παίζει {1} σε {2}", - "ValueHasBeenAddedToLibrary": "{0} προστέθηκαν στη βιβλιοθήκη πολυμέσων σας", - "ValueSpecialEpisodeName": "Σπέσιαλ - {0}", "VersionNumber": "Έκδοση {0}", "TaskRefreshPeople": "Ανανέωση Ατόμων", "TaskCleanLogsDescription": "Διαγράφει αρχεία καταγραφής που είναι πάνω από {0} ημέρες.", @@ -135,5 +106,7 @@ "TaskExtractMediaSegments": "Σάρωση τμημάτων πολυμέσων", "TaskExtractMediaSegmentsDescription": "Εξάγει ή βρίσκει τμήματα πολυμέσων από επεκτάσεις που χρησιμοποιούν το MediaSegment.", "CleanupUserDataTaskDescription": "Καθαρίζει όλα τα δεδομένα χρήστη (κατάσταση παρακολούθησης, κατάσταση αγαπημένων κ.λπ.) από πολυμέσα που δεν υπάρχουν πλέον για τουλάχιστον 90 ημέρες.", - "CleanupUserDataTask": "Εργασία εκκαθάρισης δεδομένων χρήστη" + "CleanupUserDataTask": "Εργασία εκκαθάρισης δεδομένων χρήστη", + "LyricDownloadFailureFromForItem": "Αποτυχία λήψης στίχων από {0} για {1}", + "Original": "Πρωτότυπο" } diff --git a/Emby.Server.Implementations/Localization/Core/en-GB.json b/Emby.Server.Implementations/Localization/Core/en-GB.json index b0094e33c3..298d60d277 100644 --- a/Emby.Server.Implementations/Localization/Core/en-GB.json +++ b/Emby.Server.Implementations/Localization/Core/en-GB.json @@ -1,41 +1,24 @@ { - "Albums": "Albums", "AppDeviceValues": "App: {0}, Device: {1}", - "Application": "Application", "Artists": "Artists", "AuthenticationSucceededWithUserName": "{0} successfully authenticated", "Books": "Books", - "CameraImageUploadedFrom": "A new camera image has been uploaded from {0}", - "Channels": "Channels", "ChapterNameValue": "Chapter {0}", "Collections": "Collections", - "DeviceOfflineWithName": "{0} has disconnected", - "DeviceOnlineWithName": "{0} is connected", "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", "Favorites": "Favourites", "Folders": "Folders", "Genres": "Genres", - "HeaderAlbumArtists": "Album artists", "HeaderContinueWatching": "Continue Watching", - "HeaderFavoriteAlbums": "Favourite Albums", - "HeaderFavoriteArtists": "Favourite Artists", "HeaderFavoriteEpisodes": "Favourite Episodes", "HeaderFavoriteShows": "Favourite Shows", - "HeaderFavoriteSongs": "Favourite Songs", "HeaderLiveTV": "Live TV", "HeaderNextUp": "Next Up", - "HeaderRecordingGroups": "Recording Groups", "HomeVideos": "Home Videos", "Inherit": "Inherit", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", "LabelIpAddressValue": "IP address: {0}", "LabelRunningTimeValue": "Running time: {0}", "Latest": "Latest", - "MessageApplicationUpdated": "Jellyfin Server has been updated", - "MessageApplicationUpdatedTo": "Jellyfin Server has been updated to {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageServerConfigurationUpdated": "Server configuration has been updated", "MixedContent": "Mixed content", "Movies": "Movies", "Music": "Music", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "Video playback started", "NotificationOptionVideoPlaybackStopped": "Video playback stopped", "Photos": "Photos", - "Playlists": "Playlists", - "Plugin": "Plugin", "PluginInstalledWithName": "{0} was installed", "PluginUninstalledWithName": "{0} was uninstalled", "PluginUpdatedWithName": "{0} was updated", - "ProviderValue": "Provider: {0}", "ScheduledTaskFailedWithName": "{0} failed", - "ScheduledTaskStartedWithName": "{0} started", - "ServerNameNeedsToBeRestarted": "{0} needs to be restarted", "Shows": "Shows", - "Songs": "Songs", "StartupEmbyServerIsLoading": "Jellyfin Server is loading. Please try again shortly.", "SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}", - "Sync": "Sync", - "System": "System", "TvShows": "TV Shows", - "User": "User", "UserCreatedWithName": "User {0} has been created", "UserDeletedWithName": "User {0} has been deleted", "UserDownloadingItemWithValues": "{0} is downloading {1}", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "{0} has disconnected from {1}", "UserOnlineFromDevice": "{0} is online from {1}", "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserPolicyUpdatedWithName": "User policy has been updated for {0}", "UserStartedPlayingItemWithValues": "{0} has started playing {1}", "UserStoppedPlayingItemWithValues": "{0} has finished playing {1} on {2}", - "ValueHasBeenAddedToLibrary": "{0} has been added to your media library", - "ValueSpecialEpisodeName": "Special - {0}", "VersionNumber": "Version {0}", "TaskDownloadMissingSubtitlesDescription": "Searches the internet for missing subtitles based on metadata configuration.", "TaskDownloadMissingSubtitles": "Download missing subtitles", @@ -135,5 +106,7 @@ "TaskMoveTrickplayImages": "Migrate Trickplay Image Location", "TaskMoveTrickplayImagesDescription": "Moves existing trickplay files according to the library settings.", "CleanupUserDataTask": "User data cleanup task", - "CleanupUserDataTaskDescription": "Cleans all user data (Watch state, favourite status etc) from media that is no longer present for at least 90 days." + "CleanupUserDataTaskDescription": "Cleans all user data (Watch state, favourite status etc) from media that is no longer present for at least 90 days.", + "LyricDownloadFailureFromForItem": "Lyrics failed to download from {0} for {1}", + "Original": "Original" } diff --git a/Emby.Server.Implementations/Localization/Core/en-US.json b/Emby.Server.Implementations/Localization/Core/en-US.json index 9b5049c8c7..856941c61a 100644 --- a/Emby.Server.Implementations/Localization/Core/en-US.json +++ b/Emby.Server.Implementations/Localization/Core/en-US.json @@ -1,45 +1,29 @@ { - "Albums": "Albums", "AppDeviceValues": "App: {0}, Device: {1}", - "Application": "Application", "Artists": "Artists", "AuthenticationSucceededWithUserName": "{0} successfully authenticated", "Books": "Books", - "CameraImageUploadedFrom": "A new camera image has been uploaded from {0}", - "Channels": "Channels", "ChapterNameValue": "Chapter {0}", "Collections": "Collections", "Default": "Default", - "DeviceOfflineWithName": "{0} has disconnected", - "DeviceOnlineWithName": "{0} is connected", "External": "External", "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", "Favorites": "Favorites", "Folders": "Folders", "Forced": "Forced", "Genres": "Genres", - "HeaderAlbumArtists": "Album artists", "HeaderContinueWatching": "Continue Watching", - "HeaderFavoriteAlbums": "Favorite Albums", - "HeaderFavoriteArtists": "Favorite Artists", "HeaderFavoriteEpisodes": "Favorite Episodes", "HeaderFavoriteShows": "Favorite Shows", - "HeaderFavoriteSongs": "Favorite Songs", "HeaderLiveTV": "Live TV", "HeaderNextUp": "Next Up", - "HeaderRecordingGroups": "Recording Groups", "HearingImpaired": "Hearing Impaired", "HomeVideos": "Home Videos", "Inherit": "Inherit", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", "LabelIpAddressValue": "IP address: {0}", "LabelRunningTimeValue": "Running time: {0}", "Latest": "Latest", - "MessageApplicationUpdated": "Jellyfin Server has been updated", - "MessageApplicationUpdatedTo": "Jellyfin Server has been updated to {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageServerConfigurationUpdated": "Server configuration has been updated", + "LyricDownloadFailureFromForItem": "Lyrics failed to download from {0} for {1}", "MixedContent": "Mixed content", "Movies": "Movies", "Music": "Music", @@ -66,24 +50,15 @@ "NotificationOptionVideoPlaybackStopped": "Video playback stopped", "Original": "Original", "Photos": "Photos", - "Playlists": "Playlists", - "Plugin": "Plugin", "PluginInstalledWithName": "{0} was installed", "PluginUninstalledWithName": "{0} was uninstalled", "PluginUpdatedWithName": "{0} was updated", - "ProviderValue": "Provider: {0}", "ScheduledTaskFailedWithName": "{0} failed", - "ScheduledTaskStartedWithName": "{0} started", - "ServerNameNeedsToBeRestarted": "{0} needs to be restarted", "Shows": "Shows", - "Songs": "Songs", "StartupEmbyServerIsLoading": "Jellyfin Server is loading. Please try again shortly.", "SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}", - "Sync": "Sync", - "System": "System", "TvShows": "TV Shows", "Undefined": "Undefined", - "User": "User", "UserCreatedWithName": "User {0} has been created", "UserDeletedWithName": "User {0} has been deleted", "UserDownloadingItemWithValues": "{0} is downloading {1}", @@ -91,11 +66,8 @@ "UserOfflineFromDevice": "{0} has disconnected from {1}", "UserOnlineFromDevice": "{0} is online from {1}", "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserPolicyUpdatedWithName": "User policy has been updated for {0}", "UserStartedPlayingItemWithValues": "{0} is playing {1} on {2}", "UserStoppedPlayingItemWithValues": "{0} has finished playing {1} on {2}", - "ValueHasBeenAddedToLibrary": "{0} has been added to your media library", - "ValueSpecialEpisodeName": "Special - {0}", "VersionNumber": "Version {0}", "TasksMaintenanceCategory": "Maintenance", "TasksLibraryCategory": "Library", diff --git a/Emby.Server.Implementations/Localization/Core/enm.json b/Emby.Server.Implementations/Localization/Core/enm.json deleted file mode 100644 index 0967ef424b..0000000000 --- a/Emby.Server.Implementations/Localization/Core/enm.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/Emby.Server.Implementations/Localization/Core/eo.json b/Emby.Server.Implementations/Localization/Core/eo.json index 42cce1096f..133a2755a8 100644 --- a/Emby.Server.Implementations/Localization/Core/eo.json +++ b/Emby.Server.Implementations/Localization/Core/eo.json @@ -7,35 +7,22 @@ "NameInstallFailed": "{0} instalado fiaskis", "Music": "Muziko", "Movies": "Filmoj", - "ItemRemovedWithName": "{0} forigis el la plurmediteko", - "ItemAddedWithName": "{0} aldonis al la plurmediteko", "HeaderLiveTV": "TV-etero", "HeaderContinueWatching": "Daŭrigi Spektadon", - "HeaderAlbumArtists": "Artistoj de albumo", "Folders": "Dosierujoj", - "DeviceOnlineWithName": "{0} estas konektita", "Default": "Defaŭlte", "Collections": "Kolektoj", "ChapterNameValue": "Ĉapitro {0}", - "Channels": "Kanaloj", "Books": "Libroj", "Artists": "Artistoj", - "Application": "Aplikaĵo", "AppDeviceValues": "Aplikaĵo: {0}, Aparato: {1}", - "Albums": "Albumoj", "TasksLibraryCategory": "Plurmediteko", "VersionNumber": "Versio {0}", "UserDownloadingItemWithValues": "{0} elŝutas {1}", "UserCreatedWithName": "Uzanto {0} kreiĝis", - "User": "Uzanto", - "System": "Sistemo", - "Songs": "Kantoj", - "ScheduledTaskStartedWithName": "{0} lanĉis", "ScheduledTaskFailedWithName": "{0} malsukcesis", "PluginUninstalledWithName": "{0} malinstaliĝis", "PluginInstalledWithName": "{0} instaliĝis", - "Plugin": "Kromprogramo", - "Playlists": "Ludlistoj", "Photos": "Fotoj", "NotificationOptionPluginUninstalled": "Kromprogramo malinstaliĝis", "NotificationOptionNewLibraryContent": "Nova enhavo aldoniĝis", @@ -43,36 +30,28 @@ "MusicVideos": "Muzikvideoj", "LabelIpAddressValue": "IP-adreso: {0}", "Genres": "Ĝenroj", - "DeviceOfflineWithName": "{0} malkonektis", - "HeaderFavoriteArtists": "Favorataj Artistoj", "Shows": "Serioj", "HeaderFavoriteShows": "Favorataj Serioj", "TvShows": "TV-serioj", "Favorites": "Favorataj", "TaskCleanLogs": "Purigi Ĵurnalan Katalogon", "TaskRefreshLibrary": "Skani Plurmeditekon", - "ValueSpecialEpisodeName": "Speciala - {0}", "TaskOptimizeDatabase": "Optimumigi datenbazon", "TaskRefreshChannels": "Refreŝigi Kanalojn", "TaskUpdatePlugins": "Ĝisdatigi Kromprogramojn", "TaskRefreshPeople": "Refreŝigi Homojn", "TasksChannelsCategory": "Interretaj Kanaloj", - "ProviderValue": "Provizanto: {0}", "NotificationOptionPluginError": "Kromprogramo malsukcesis", "MixedContent": "Miksita enhavo", "TasksApplicationCategory": "Aplikaĵo", "TasksMaintenanceCategory": "Prizorgado", "Undefined": "Nedifinita", - "Sync": "Sinkronigo", "Latest": "Plej novaj", "Inherit": "Hereda", "HomeVideos": "Hejmaj Videoj", "HeaderNextUp": "Sekva Plue", - "HeaderFavoriteSongs": "Favorataj Kantoj", "HeaderFavoriteEpisodes": "Favorataj Epizodoj", - "HeaderFavoriteAlbums": "Favorataj Albumoj", "Forced": "Forcita", - "ServerNameNeedsToBeRestarted": "{0} devas esti relanĉita", "NotificationOptionVideoPlayback": "La videoludado lanĉis", "NotificationOptionServerRestartRequired": "Servila relanĉigo bezonata", "TaskOptimizeDatabaseDescription": "Kompaktigas datenbazon kaj trunkas liberan lokon. Lanĉi ĉi tiun taskon post la plurmediteka skanado aŭ fari aliajn ŝanĝojn, kiuj implicas datenbazajn modifojn, povus plibonigi rendimenton.", @@ -85,22 +64,16 @@ "TaskCleanCacheDescription": "Forigas stapla dosierojn ne plu necesajn de la sistemo.", "TaskCleanActivityLogDescription": "Forigas aktivecan ĵurnalaĵojn pli malnovajn ol la agordita aĝo.", "TaskCleanTranscodeDescription": "Forigas transkodajn dosierojn aĝajn pli ol unu tagon.", - "ValueHasBeenAddedToLibrary": "{0} estis aldonita al via plurmediteko", "SubtitleDownloadFailureFromForItem": "Subtekstoj malsukcesis elŝuti de {0} por {1}", "StartupEmbyServerIsLoading": "Jellyfin Server ŝarĝas. Provi denove baldaŭ.", "TaskRefreshChapterImagesDescription": "Kreas bildetojn por videoj kiuj havas ĉapitrojn.", "UserStoppedPlayingItemWithValues": "{0} finis ludi {1} ĉe {2}", - "UserPolicyUpdatedWithName": "Uzanta politiko estis ĝisdatigita por {0}", "UserPasswordChangedWithName": "Pasvorto estis ŝanĝita por uzanto {0}", "UserStartedPlayingItemWithValues": "{0} ludas {1} ĉe {2}", "UserLockedOutWithName": "Uzanto {0} estas elŝlosita", "UserOnlineFromDevice": "{0} estas enreta de {1}", "UserOfflineFromDevice": "{0} malkonektis de {1}", "UserDeletedWithName": "Uzanto {0} estis forigita", - "MessageServerConfigurationUpdated": "Servila agordaro estis ĝisdatigita", - "MessageNamedServerConfigurationUpdatedWithValue": "Servila agorda sekcio {0} estis ĝisdatigita", - "MessageApplicationUpdatedTo": "Jellyfin Server estis ĝisdatigita al {0}", - "MessageApplicationUpdated": "Jellyfin Server estis ĝisdatigita", "TaskRefreshChannelsDescription": "Refreŝigas informon pri interretaj kanaloj.", "TaskDownloadMissingSubtitles": "Elŝuti mankantajn subtekstojn", "TaskCleanTranscode": "Malplenigi Transkodadan Katalogon", @@ -116,9 +89,7 @@ "NotificationOptionApplicationUpdateInstalled": "Aplikaĵa ĝisdatigo instalita", "NotificationOptionApplicationUpdateAvailable": "Ĝisdatigo de aplikaĵo havebla", "LabelRunningTimeValue": "Ludada tempo: {0}", - "HeaderRecordingGroups": "Rikordadaj Grupoj", "FailedLoginAttemptWithUserName": "Malsukcesa ensaluta provo de {0}", - "CameraImageUploadedFrom": "Nova kamera bildo estis alŝutita de {0}", "AuthenticationSucceededWithUserName": "{0} sukcese aŭtentikigis", "TaskKeyframeExtractorDescription": "Eltiras ĉefkadrojn el videodosieroj por krei pli precizajn HLS-ludlistojn. Ĉi tiu tasko povas funkcii dum longa tempo.", "TaskKeyframeExtractor": "Eltiri Ĉefkadrojn", diff --git a/Emby.Server.Implementations/Localization/Core/es-AR.json b/Emby.Server.Implementations/Localization/Core/es-AR.json index 7fda507797..bccfdd4c19 100644 --- a/Emby.Server.Implementations/Localization/Core/es-AR.json +++ b/Emby.Server.Implementations/Localization/Core/es-AR.json @@ -1,41 +1,24 @@ { - "Albums": "Álbumes", "AppDeviceValues": "Aplicación: {0}, Dispositivo: {1}", - "Application": "Aplicación", "Artists": "Artistas", "AuthenticationSucceededWithUserName": "{0} autenticado correctamente", "Books": "Libros", - "CameraImageUploadedFrom": "Se ha subido una nueva imagen de cámara desde {0}", - "Channels": "Canales", "ChapterNameValue": "Capítulo {0}", "Collections": "Colecciones", - "DeviceOfflineWithName": "{0} se ha desconectado", - "DeviceOnlineWithName": "{0} está conectado", "FailedLoginAttemptWithUserName": "Error al intentar iniciar sesión de {0}", "Favorites": "Favoritos", "Folders": "Carpetas", "Genres": "Géneros", - "HeaderAlbumArtists": "Artistas del álbum", "HeaderContinueWatching": "Seguir viendo", - "HeaderFavoriteAlbums": "Álbumes favoritos", - "HeaderFavoriteArtists": "Artistas favoritos", "HeaderFavoriteEpisodes": "Capítulos favoritos", "HeaderFavoriteShows": "Series favoritas", - "HeaderFavoriteSongs": "Canciones favoritas", "HeaderLiveTV": "TV en vivo", "HeaderNextUp": "Siguiente", - "HeaderRecordingGroups": "Grupos de grabación", "HomeVideos": "Videos caseros", "Inherit": "Heredar", - "ItemAddedWithName": "{0} se ha añadido a la biblioteca", - "ItemRemovedWithName": "{0} ha sido eliminado de la biblioteca", "LabelIpAddressValue": "Dirección IP: {0}", "LabelRunningTimeValue": "Tiempo de funcionamiento: {0}", "Latest": "Últimos", - "MessageApplicationUpdated": "El servidor Jellyfin fue actualizado", - "MessageApplicationUpdatedTo": "Se ha actualizado el servidor Jellyfin a la versión {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "Se ha actualizado la sección {0} de la configuración del servidor", - "MessageServerConfigurationUpdated": "Se ha actualizado la configuración del servidor", "MixedContent": "Contenido mezclado", "Movies": "Películas", "Music": "Música", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "Se inició la reproducción de video", "NotificationOptionVideoPlaybackStopped": "Reproducción de video detenida", "Photos": "Fotos", - "Playlists": "Listas de reproducción", - "Plugin": "Complemento", "PluginInstalledWithName": "{0} fue instalado", "PluginUninstalledWithName": "{0} fue desinstalado", "PluginUpdatedWithName": "{0} fue actualizado", - "ProviderValue": "Proveedor: {0}", "ScheduledTaskFailedWithName": "{0} falló", - "ScheduledTaskStartedWithName": "{0} iniciado", - "ServerNameNeedsToBeRestarted": "{0} necesita ser reiniciado", "Shows": "Series", - "Songs": "Canciones", "StartupEmbyServerIsLoading": "El servidor Jellyfin se está cargando. Vuelve a intentarlo en breve.", "SubtitleDownloadFailureFromForItem": "Falló la descarga de subtitulos desde {0} para {1}", - "Sync": "Sincronizar", - "System": "Sistema", "TvShows": "Series de TV", - "User": "Usuario", "UserCreatedWithName": "El usuario {0} ha sido creado", "UserDeletedWithName": "El usuario {0} ha sido borrado", "UserDownloadingItemWithValues": "{0} está descargando {1}", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "{0} se ha desconectado de {1}", "UserOnlineFromDevice": "{0} está en línea desde {1}", "UserPasswordChangedWithName": "Se ha cambiado la contraseña para el usuario {0}", - "UserPolicyUpdatedWithName": "Las política de usuario ha sido actualizada para {0}", "UserStartedPlayingItemWithValues": "{0} está reproduciendo {1} en {2}", "UserStoppedPlayingItemWithValues": "{0} ha terminado de reproducir {1} en {2}", - "ValueHasBeenAddedToLibrary": "{0} ha sido añadido a tu biblioteca multimedia", - "ValueSpecialEpisodeName": "Especial - {0}", "VersionNumber": "Versión {0}", "TaskDownloadMissingSubtitlesDescription": "Busca en internet los subtítulos que falten basándose en la configuración de los metadatos.", "TaskDownloadMissingSubtitles": "Descargar subtítulos faltantes", @@ -135,5 +106,7 @@ "TaskMoveTrickplayImagesDescription": "Mueve archivos existentes de trickplay de acuerdo a la configuración de la biblioteca.", "TaskMoveTrickplayImages": "Migrar Ubicación de Imagen de Trickplay", "CleanupUserDataTaskDescription": "Limpia todos los datos del usuario (estado de visualización, estado de los favoritos, etc.) que no están presentes en la biblioteca por al menos 90 días.", - "CleanupUserDataTask": "Tarea de limpieza de datos de usuarios" + "CleanupUserDataTask": "Tarea de limpieza de datos de usuarios", + "LyricDownloadFailureFromForItem": "No se pudo descargar la letra desde {0} para {1}", + "Original": "Original" } diff --git a/Emby.Server.Implementations/Localization/Core/es-MX.json b/Emby.Server.Implementations/Localization/Core/es-MX.json index d03d3ed2ff..ac489b9e77 100644 --- a/Emby.Server.Implementations/Localization/Core/es-MX.json +++ b/Emby.Server.Implementations/Localization/Core/es-MX.json @@ -1,41 +1,24 @@ { - "Albums": "Álbumes", "AppDeviceValues": "App: {0}, Dispositivo: {1}", - "Application": "Aplicación", "Artists": "Artistas", "AuthenticationSucceededWithUserName": "{0} autenticado con éxito", "Books": "Libros", - "CameraImageUploadedFrom": "Una nueva imagen de cámara ha sido subida desde {0}", - "Channels": "Canales", "ChapterNameValue": "Capítulo {0}", "Collections": "Colecciones", - "DeviceOfflineWithName": "{0} se ha desconectado", - "DeviceOnlineWithName": "{0} está conectado", "FailedLoginAttemptWithUserName": "Intento fallido de inicio de sesión de {0}", "Favorites": "Favoritos", "Folders": "Carpetas", "Genres": "Géneros", - "HeaderAlbumArtists": "Artistas del Álbum", "HeaderContinueWatching": "Continuar viendo", - "HeaderFavoriteAlbums": "Álbumes favoritos", - "HeaderFavoriteArtists": "Artistas favoritos", "HeaderFavoriteEpisodes": "Episodios favoritos", "HeaderFavoriteShows": "Programas favoritos", - "HeaderFavoriteSongs": "Canciones favoritas", "HeaderLiveTV": "TV en vivo", "HeaderNextUp": "A continuación", - "HeaderRecordingGroups": "Grupos de grabación", "HomeVideos": "Videos Caseros", "Inherit": "Heredar", - "ItemAddedWithName": "{0} fue agregado a la biblioteca", - "ItemRemovedWithName": "{0} fue removido de la biblioteca", "LabelIpAddressValue": "Dirección IP: {0}", "LabelRunningTimeValue": "Tiempo corriendo: {0}", "Latest": "Recientes", - "MessageApplicationUpdated": "El servidor Jellyfin ha sido actualizado", - "MessageApplicationUpdatedTo": "El servidor Jellyfin ha sido actualizado a {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "Se ha actualizado la sección {0} de la configuración del servidor", - "MessageServerConfigurationUpdated": "Se ha actualizado la configuración del servidor", "MixedContent": "Contenido mezclado", "Movies": "Películas", "Music": "Música", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "Reproducción de video iniciada", "NotificationOptionVideoPlaybackStopped": "Reproducción de video detenida", "Photos": "Fotos", - "Playlists": "Listas de reproducción", - "Plugin": "Complemento", "PluginInstalledWithName": "{0} fue instalado", "PluginUninstalledWithName": "{0} fue desinstalado", "PluginUpdatedWithName": "{0} fue actualizado", - "ProviderValue": "Proveedor: {0}", "ScheduledTaskFailedWithName": "{0} falló", - "ScheduledTaskStartedWithName": "{0} iniciado", - "ServerNameNeedsToBeRestarted": "{0} necesita ser reiniciado", "Shows": "Programas", - "Songs": "Canciones", "StartupEmbyServerIsLoading": "El servidor Jellyfin está cargando. Por favor, intente de nuevo pronto.", "SubtitleDownloadFailureFromForItem": "Falló la descarga de subtítulos desde {0} para {1}", - "Sync": "Sincronizar", - "System": "Sistema", "TvShows": "Programas de TV", - "User": "Usuario", "UserCreatedWithName": "El usuario {0} ha sido creado", "UserDeletedWithName": "El usuario {0} ha sido eliminado", "UserDownloadingItemWithValues": "{0} está descargando {1}", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "{0} se ha desconectado desde {1}", "UserOnlineFromDevice": "{0} está en línea desde {1}", "UserPasswordChangedWithName": "Se ha cambiado la contraseña para el usuario {0}", - "UserPolicyUpdatedWithName": "La política de usuario ha sido actualizada para {0}", "UserStartedPlayingItemWithValues": "{0} está reproduciendo {1} en {2}", "UserStoppedPlayingItemWithValues": "{0} ha terminado de reproducir {1} en {2}", - "ValueHasBeenAddedToLibrary": "{0} se ha añadido a tu biblioteca de medios", - "ValueSpecialEpisodeName": "Especial - {0}", "VersionNumber": "Versión {0}", "TaskDownloadMissingSubtitlesDescription": "Busca subtítulos faltantes en Internet basándose en la configuración de metadatos.", "TaskDownloadMissingSubtitles": "Descargar subtítulos faltantes", diff --git a/Emby.Server.Implementations/Localization/Core/es.json b/Emby.Server.Implementations/Localization/Core/es.json index 4f6a3544e4..563dce8fe6 100644 --- a/Emby.Server.Implementations/Localization/Core/es.json +++ b/Emby.Server.Implementations/Localization/Core/es.json @@ -1,41 +1,24 @@ { - "Albums": "Álbumes", "AppDeviceValues": "Aplicación: {0}, Dispositivo: {1}", - "Application": "Aplicación", "Artists": "Artistas", "AuthenticationSucceededWithUserName": "{0} autenticado correctamente", "Books": "Libros", - "CameraImageUploadedFrom": "Se ha subido una nueva imagen por cámara desde {0}", - "Channels": "Canales", "ChapterNameValue": "Capítulo {0}", "Collections": "Colecciones", - "DeviceOfflineWithName": "{0} se ha desconectado", - "DeviceOnlineWithName": "{0} está conectado", "FailedLoginAttemptWithUserName": "Intento fallido de inicio de sesión de {0}", "Favorites": "Favoritos", "Folders": "Carpetas", "Genres": "Géneros", - "HeaderAlbumArtists": "Artistas del álbum", "HeaderContinueWatching": "Seguir viendo", - "HeaderFavoriteAlbums": "Álbumes favoritos", - "HeaderFavoriteArtists": "Artistas favoritos", "HeaderFavoriteEpisodes": "Episodios favoritos", "HeaderFavoriteShows": "Series favoritas", - "HeaderFavoriteSongs": "Canciones favoritas", "HeaderLiveTV": "Televisión en directo", "HeaderNextUp": "Siguiente", - "HeaderRecordingGroups": "Grupos de grabación", "HomeVideos": "Vídeos caseros", "Inherit": "Heredar", - "ItemAddedWithName": "{0} se ha añadido a la biblioteca", - "ItemRemovedWithName": "{0} ha sido eliminado de la biblioteca", "LabelIpAddressValue": "Dirección IP: {0}", "LabelRunningTimeValue": "Duración: {0}", "Latest": "Últimas", - "MessageApplicationUpdated": "Se ha actualizado el servidor Jellyfin", - "MessageApplicationUpdatedTo": "Se ha actualizado el servidor Jellyfin a la versión {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "La sección {0} de configuración del servidor ha sido actualizada", - "MessageServerConfigurationUpdated": "Se ha actualizado la configuración del servidor", "MixedContent": "Contenido mixto", "Movies": "Películas", "Music": "Música", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "Se inició la reproducción de vídeo", "NotificationOptionVideoPlaybackStopped": "Reproducción de vídeo detenida", "Photos": "Fotos", - "Playlists": "Listas de reproducción", - "Plugin": "Plugin", "PluginInstalledWithName": "{0} se ha instalado", "PluginUninstalledWithName": "{0} se ha desinstalado", "PluginUpdatedWithName": "{0} se actualizó", - "ProviderValue": "Proveedor: {0}", "ScheduledTaskFailedWithName": "{0} falló", - "ScheduledTaskStartedWithName": "{0} iniciada", - "ServerNameNeedsToBeRestarted": "{0} necesita ser reiniciado", "Shows": "Series", - "Songs": "Canciones", "StartupEmbyServerIsLoading": "Jellyfin Server se está cargando. Vuelve a intentarlo en breve.", "SubtitleDownloadFailureFromForItem": "Fallo en la descarga de subtítulos desde {0} para {1}", - "Sync": "Sincronizar", - "System": "Sistema", "TvShows": "Series", - "User": "Usuario", "UserCreatedWithName": "El usuario {0} ha sido creado", "UserDeletedWithName": "El usuario {0} ha sido borrado", "UserDownloadingItemWithValues": "{0} está descargando {1}", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "{0} se ha desconectado desde {1}", "UserOnlineFromDevice": "{0} está en línea desde {1}", "UserPasswordChangedWithName": "Se ha cambiado la contraseña para el usuario {0}", - "UserPolicyUpdatedWithName": "Actualizada política de usuario para {0}", "UserStartedPlayingItemWithValues": "{0} está reproduciendo {1} en {2}", "UserStoppedPlayingItemWithValues": "{0} ha terminado de reproducir {1} en {2}", - "ValueHasBeenAddedToLibrary": "{0} ha sido añadido a tu biblioteca multimedia", - "ValueSpecialEpisodeName": "Especial - {0}", "VersionNumber": "Versión {0}", "TasksMaintenanceCategory": "Mantenimiento", "TasksLibraryCategory": "Biblioteca", @@ -136,5 +107,6 @@ "TaskMoveTrickplayImages": "Migrar la ubicación de la imagen de Trickplay", "CleanupUserDataTask": "Tarea de limpieza de datos del usuario", "CleanupUserDataTaskDescription": "Limpia todos los datos del usuario (estado de visualización, favoritos, etc.) de los medios que ya no están disponibles desde hace al menos 90 días.", - "Original": "Original" + "Original": "Original", + "LyricDownloadFailureFromForItem": "No se pudieron descargar las letras desde {0} para {1}" } diff --git a/Emby.Server.Implementations/Localization/Core/es_419.json b/Emby.Server.Implementations/Localization/Core/es_419.json index dec82b73e3..4404354a88 100644 --- a/Emby.Server.Implementations/Localization/Core/es_419.json +++ b/Emby.Server.Implementations/Localization/Core/es_419.json @@ -1,29 +1,19 @@ { "LabelRunningTimeValue": "Tiempo en ejecución: {0}", - "ValueSpecialEpisodeName": "Especial - {0}", - "Sync": "Sincronizar", - "Songs": "Canciones", "Shows": "Programas", - "Playlists": "Listas de reproducción", "Photos": "Fotos", "Movies": "Películas", "HeaderNextUp": "A continuación", "HeaderLiveTV": "TV en vivo", - "HeaderFavoriteSongs": "Canciones favoritas", - "HeaderFavoriteArtists": "Artistas favoritos", - "HeaderFavoriteAlbums": "Álbumes favoritos", "HeaderFavoriteEpisodes": "Episodios favoritos", "HeaderFavoriteShows": "Programas favoritos", "HeaderContinueWatching": "Continuar viendo", - "HeaderAlbumArtists": "Artistas de álbum", "Genres": "Géneros", "Folders": "Carpetas", "Favorites": "Favoritos", "Collections": "Colecciones", - "Channels": "Canales", "Books": "Libros", "Artists": "Artistas", - "Albums": "Álbumes", "TaskDownloadMissingSubtitlesDescription": "Busca subtítulos faltantes en Internet basándose en la configuración de metadatos.", "TaskDownloadMissingSubtitles": "Descargar subtítulos faltantes", "TaskRefreshChannelsDescription": "Actualiza la información de canales de Internet.", @@ -47,10 +37,8 @@ "TasksLibraryCategory": "Biblioteca", "TasksMaintenanceCategory": "Mantenimiento", "VersionNumber": "Versión {0}", - "ValueHasBeenAddedToLibrary": "{0} se ha añadido a tu biblioteca de medios", "UserStoppedPlayingItemWithValues": "{0} ha terminado de reproducir {1} en {2}", "UserStartedPlayingItemWithValues": "{0} está reproduciendo {1} en {2}", - "UserPolicyUpdatedWithName": "La política de usuario ha sido actualizada para {0}", "UserPasswordChangedWithName": "Se ha cambiado la contraseña para el usuario {0}", "UserOnlineFromDevice": "{0} está en línea desde {1}", "UserOfflineFromDevice": "{0} se ha desconectado desde {1}", @@ -58,19 +46,13 @@ "UserDownloadingItemWithValues": "{0} está descargando {1}", "UserDeletedWithName": "El usuario {0} ha sido eliminado", "UserCreatedWithName": "El usuario {0} ha sido creado", - "User": "Usuario", "TvShows": "Programas de TV", - "System": "Sistema", "SubtitleDownloadFailureFromForItem": "Falló la descarga de subtítulos desde {0} para {1}", "StartupEmbyServerIsLoading": "El servidor Jellyfin está cargando. Por favor, intente de nuevo pronto.", - "ServerNameNeedsToBeRestarted": "{0} debe ser reiniciado", - "ScheduledTaskStartedWithName": "{0} iniciado", "ScheduledTaskFailedWithName": "{0} falló", - "ProviderValue": "Proveedor: {0}", "PluginUpdatedWithName": "{0} fue actualizado", "PluginUninstalledWithName": "{0} fue desinstalado", "PluginInstalledWithName": "{0} fue instalado", - "Plugin": "Complemento", "NotificationOptionVideoPlaybackStopped": "Reproducción de video detenida", "NotificationOptionVideoPlayback": "Reproducción de video iniciada", "NotificationOptionUserLockedOut": "Usuario bloqueado", @@ -94,24 +76,13 @@ "MusicVideos": "Videos musicales", "Music": "Música", "MixedContent": "Contenido mezclado", - "MessageServerConfigurationUpdated": "Se ha actualizado la configuración del servidor", - "MessageNamedServerConfigurationUpdatedWithValue": "Se ha actualizado la sección {0} de la configuración del servidor", - "MessageApplicationUpdatedTo": "El servidor Jellyfin ha sido actualizado a {0}", - "MessageApplicationUpdated": "El servidor Jellyfin ha sido actualizado", "Latest": "Recientes", "LabelIpAddressValue": "Dirección IP: {0}", - "ItemRemovedWithName": "{0} fue removido de la biblioteca", - "ItemAddedWithName": "{0} fue agregado a la biblioteca", "Inherit": "Heredar", "HomeVideos": "Videos caseros", - "HeaderRecordingGroups": "Grupos de grabación", "FailedLoginAttemptWithUserName": "Intento de inicio de sesión fallido desde {0}", - "DeviceOnlineWithName": "{0} está conectado", - "DeviceOfflineWithName": "{0} se ha desconectado", "ChapterNameValue": "Capítulo {0}", - "CameraImageUploadedFrom": "Una nueva imagen de cámara ha sido subida desde {0}", "AuthenticationSucceededWithUserName": "{0} autenticado con éxito", - "Application": "Aplicación", "AppDeviceValues": "Aplicación: {0}, Dispositivo: {1}", "TaskCleanActivityLogDescription": "Elimina las entradas del registro de actividad anteriores al periodo configurado.", "TaskCleanActivityLog": "Limpiar registro de actividades", @@ -135,5 +106,7 @@ "TaskExtractMediaSegments": "Escaneo de segmentos de medios", "TaskMoveTrickplayImages": "Migrar la ubicación de la imagen de Trickplay", "CleanupUserDataTask": "Tarea de limpieza de datos de usuario", - "CleanupUserDataTaskDescription": "Limpia todos los datos de usuario (estado de visualización, favoritos, etc.) que no están presentes en la biblioteca por al menos 90 días." + "CleanupUserDataTaskDescription": "Limpia todos los datos de usuario (estado de visualización, favoritos, etc.) que no están presentes en la biblioteca por al menos 90 días.", + "LyricDownloadFailureFromForItem": "No se pudo descargar las letras de {0} para {1}", + "Original": "Original" } diff --git a/Emby.Server.Implementations/Localization/Core/es_DO.json b/Emby.Server.Implementations/Localization/Core/es_DO.json index 8d991fa74a..a1b9944125 100644 --- a/Emby.Server.Implementations/Localization/Core/es_DO.json +++ b/Emby.Server.Implementations/Localization/Core/es_DO.json @@ -1,35 +1,24 @@ { - "Channels": "Canales", "Books": "Libros", - "Albums": "Álbumes", "Collections": "Colecciones", "Artists": "Artistas", - "DeviceOnlineWithName": "{0} está conectado", - "DeviceOfflineWithName": "{0} se ha desconectado", "ChapterNameValue": "Capítulo {0}", - "CameraImageUploadedFrom": "Se ha subido una nueva imagen de cámara desde {0}", "AuthenticationSucceededWithUserName": "{0} autenticado con éxito", - "Application": "Aplicación", "AppDeviceValues": "App: {0}, Dispositivo: {1}", "HeaderContinueWatching": "Continuar Viendo", - "HeaderAlbumArtists": "Artistas del álbum", "Genres": "Géneros", "Folders": "Carpetas", "Favorites": "Favoritos", "FailedLoginAttemptWithUserName": "Intento de inicio de sesión fallido desde {0}", - "HeaderFavoriteSongs": "Canciones Favoritas", "HeaderFavoriteEpisodes": "Episodios Favoritos", - "HeaderFavoriteArtists": "Artistas Favoritos", "External": "Externo", "Default": "Predeterminado", "Movies": "Películas", - "MessageNamedServerConfigurationUpdatedWithValue": "La sección {0} de la configuración ha sido actualizada", "MixedContent": "Contenido mixto", "Music": "Música", "NotificationOptionCameraImageUploaded": "Imagen de la cámara subida", "NotificationOptionServerRestartRequired": "Se necesita reiniciar el servidor", "NotificationOptionVideoPlayback": "Reproducción de video iniciada", - "Sync": "Sincronizar", "Shows": "Series", "UserDownloadingItemWithValues": "{0} está descargando {1}", "UserOfflineFromDevice": "{0} se ha desconectado desde {1}", @@ -48,17 +37,12 @@ "HeaderFavoriteShows": "Programas favoritos", "TaskCleanActivityLog": "Limpiar registro de actividades", "UserPasswordChangedWithName": "Se ha cambiado la contraseña para el usuario {0}", - "System": "Sistema", - "User": "Usuario", "Forced": "Forzado", "PluginInstalledWithName": "{0} ha sido instalado", - "HeaderFavoriteAlbums": "Álbumes favoritos", "TaskUpdatePlugins": "Actualizar Plugins", "Latest": "Recientes", "UserStoppedPlayingItemWithValues": "{0} ha terminado de reproducir {1} en {2}", - "Songs": "Canciones", "NotificationOptionPluginError": "Falla de plugin", - "ScheduledTaskStartedWithName": "{0} iniciado", "TasksApplicationCategory": "Aplicación", "UserDeletedWithName": "El usuario {0} ha sido eliminado", "TaskRefreshChapterImages": "Extraer imágenes de los capítulos", @@ -71,34 +55,26 @@ "NotificationOptionAudioPlaybackStopped": "Reproducción de audio detenida", "TasksLibraryCategory": "Biblioteca", "NotificationOptionPluginInstalled": "Plugin instalado", - "UserPolicyUpdatedWithName": "La política de usuario ha sido actualizada para {0}", "VersionNumber": "Versión {0}", "HeaderNextUp": "A continuación", - "ValueHasBeenAddedToLibrary": "{0} se ha añadido a tu biblioteca", "LabelIpAddressValue": "Dirección IP: {0}", "NameSeasonNumber": "Temporada {0}", "NotificationOptionNewLibraryContent": "Nuevo contenido agregado", - "Plugin": "Plugin", "NotificationOptionAudioPlayback": "Reproducción de audio iniciada", "NotificationOptionTaskFailed": "Falló la tarea programada", "LabelRunningTimeValue": "Tiempo en ejecución: {0}", "SubtitleDownloadFailureFromForItem": "Falló la descarga de subtítulos desde {0} para {1}", "TaskRefreshLibrary": "Escanear biblioteca de medios", - "ServerNameNeedsToBeRestarted": "{0} debe ser reiniciado", "TasksMaintenanceCategory": "Mantenimiento", - "ProviderValue": "Proveedor: {0}", "UserCreatedWithName": "El usuario {0} ha sido creado", "PluginUninstalledWithName": "{0} ha sido desinstalado", - "ValueSpecialEpisodeName": "Especial - {0}", "ScheduledTaskFailedWithName": "{0} falló", "TaskCleanLogs": "Limpiar directorio de registros", "NameInstallFailed": "Falló la instalación de {0}", "UserLockedOutWithName": "El usuario {0} ha sido bloqueado", "TaskRefreshLibraryDescription": "Escanea tu biblioteca de medios para encontrar archivos nuevos y actualizar los metadatos.", "StartupEmbyServerIsLoading": "El servidor Jellyfin está cargando. Por favor, intente de nuevo en un momento.", - "Playlists": "Listas de reproducción", "TaskDownloadMissingSubtitlesDescription": "Busca subtítulos faltantes en Internet basándose en la configuración de metadatos.", - "MessageServerConfigurationUpdated": "Se ha actualizado la configuración del servidor", "TaskRefreshPeople": "Actualizar personas", "NotificationOptionVideoPlaybackStopped": "Reproducción de video detenida", "HeaderLiveTV": "TV en vivo", @@ -108,15 +84,10 @@ "TaskCleanCache": "Limpiar directorio caché", "TaskRefreshChapterImagesDescription": "Crea miniaturas para videos que tienen capítulos.", "Inherit": "Heredar", - "HeaderRecordingGroups": "Grupos de grabación", - "ItemAddedWithName": "{0} fue agregado a la biblioteca", "TaskOptimizeDatabase": "Optimizar base de datos", "TaskKeyframeExtractor": "Extractor de Fotogramas Clave", "HearingImpaired": "Discapacidad auditiva", "HomeVideos": "Videos caseros", - "ItemRemovedWithName": "{0} fue removido de la biblioteca", - "MessageApplicationUpdated": "El servidor Jellyfin ha sido actualizado", - "MessageApplicationUpdatedTo": "El servidor Jellyfin ha sido actualizado a {0}", "MusicVideos": "Videos musicales", "NewVersionIsAvailable": "Una nueva versión de Jellyfin está disponible para descargar.", "PluginUpdatedWithName": "{0} ha sido actualizado", diff --git a/Emby.Server.Implementations/Localization/Core/et.json b/Emby.Server.Implementations/Localization/Core/et.json index d751e35af2..e6bf1f25b5 100644 --- a/Emby.Server.Implementations/Localization/Core/et.json +++ b/Emby.Server.Implementations/Localization/Core/et.json @@ -1,7 +1,6 @@ { "TaskCleanActivityLogDescription": "Kustutab määratud ajast vanemad tegevuslogi kirjed.", "UserDownloadingItemWithValues": "{0} laadib alla {1}", - "HeaderRecordingGroups": "Salvestusrühmad", "TaskOptimizeDatabaseDescription": "Tihendab ja puhastab andmebaasi. Selle toimingu tegemine pärast meediakogu andmebaasiga seotud muudatuste skannimist võib jõudlust parandada.", "TaskOptimizeDatabase": "Optimeeri andmebaasi", "TaskDownloadMissingSubtitlesDescription": "Otsib veebist puuduvaid subtiitreid vastavalt määratud metaandmete seadetele.", @@ -29,30 +28,19 @@ "TasksLibraryCategory": "Meediakogu", "TasksMaintenanceCategory": "Hooldus", "VersionNumber": "Versioon {0}", - "ValueSpecialEpisodeName": "Eriepisood - {0}", - "ValueHasBeenAddedToLibrary": "{0} lisati meediakogusse", "UserStartedPlayingItemWithValues": "{0} taasesitab {1} seadmes {2}", "UserPasswordChangedWithName": "Kasutaja {0} parool muudeti", "UserLockedOutWithName": "Kasutaja {0} lukustati", "UserDeletedWithName": "Kasutaja {0} kustutati", "UserCreatedWithName": "Kasutaja {0} on loodud", - "ScheduledTaskStartedWithName": "{0} käivitati", - "ProviderValue": "Allikas: {0}", "StartupEmbyServerIsLoading": "Jellyfin server laadib. Proovi varsti uuesti.", - "User": "Kasutaja", "Undefined": "Määratlemata", "TvShows": "Sarjad", - "System": "Süsteem", - "Sync": "Sünkrooni", - "Songs": "Lood", "Shows": "Sarjad", - "ServerNameNeedsToBeRestarted": "{0} tuleb taaskäivitada", "ScheduledTaskFailedWithName": "{0} nurjus", "PluginUpdatedWithName": "{0} uuendati", "PluginUninstalledWithName": "{0} eemaldati", "PluginInstalledWithName": "{0} paigaldati", - "Plugin": "Plugin", - "Playlists": "Esitusloendid", "Photos": "Fotod", "NotificationOptionVideoPlaybackStopped": "Video taasesitus lõppes", "NotificationOptionVideoPlayback": "Video taasesitus algas", @@ -78,46 +66,29 @@ "Music": "Muusika", "Movies": "Filmid", "MixedContent": "Segatud sisu", - "MessageServerConfigurationUpdated": "Serveri seadistust uuendati", - "MessageNamedServerConfigurationUpdatedWithValue": "Serveri seadistusosa {0} uuendati", - "MessageApplicationUpdatedTo": "Jellyfin server uuendati versioonile {0}", - "MessageApplicationUpdated": "Jellyfin server uuendati", "Latest": "Uusimad", "LabelRunningTimeValue": "Kestus: {0}", "LabelIpAddressValue": "IP aadress: {0}", - "ItemRemovedWithName": "{0} eemaldati meediakogust", - "ItemAddedWithName": "{0} lisati meediakogusse", "Inherit": "Päri", "HomeVideos": "Koduvideod", "HeaderNextUp": "Järgmisena", "HeaderLiveTV": "Otse TV", - "HeaderFavoriteSongs": "Lemmiklood", "HeaderFavoriteShows": "Lemmiksarjad", "HeaderFavoriteEpisodes": "Lemmikepisoodid", - "HeaderFavoriteArtists": "Lemmikesitajad", - "HeaderFavoriteAlbums": "Lemmikalbumid", "HeaderContinueWatching": "Jätka vaatamist", - "HeaderAlbumArtists": "Albumi esitajad", "Genres": "Žanrid", "Forced": "Sunnitud", "Folders": "Kaustad", "Favorites": "Lemmikud", "FailedLoginAttemptWithUserName": "Sisselogimine nurjus aadressilt {0}", - "DeviceOnlineWithName": "{0} on ühendatud", - "DeviceOfflineWithName": "{0} katkestas ühenduse", "Default": "Vaikimisi", "ChapterNameValue": "Peatükk {0}", - "Channels": "Kanalid", - "CameraImageUploadedFrom": "Uus kaamera pilt laaditi üles allikalt {0}", "Books": "Raamatud", "AuthenticationSucceededWithUserName": "{0} autentimine õnnestus", "Artists": "Esitajad", - "Application": "Rakendus", "AppDeviceValues": "Rakendus: {0}, seade: {1}", - "Albums": "Albumid", "UserOfflineFromDevice": "{0} katkestas ühenduse seadmega {1}", "SubtitleDownloadFailureFromForItem": "Subtiitrite allalaadimine {0} > {1} nurjus", - "UserPolicyUpdatedWithName": "Kasutaja {0} õigusi värskendati", "UserStoppedPlayingItemWithValues": "{0} lõpetas {1} taasesituse seadmes {2}", "UserOnlineFromDevice": "{0} on ühendatud seadmest {1}", "External": "Väline", @@ -135,5 +106,7 @@ "TaskExtractMediaSegmentsDescription": "Eraldab või võtab meedialõigud MediaSegment'i toega pluginatest.", "TaskMoveTrickplayImages": "Muuda trickplay piltide asukoht", "CleanupUserDataTask": "Puhasta kasutajaandmed", - "CleanupUserDataTaskDescription": "Puhastab kõik kasutajaandmed (vaatamise olek, lemmikute olek jne) meediast, mida pole enam vähemalt 90 päeva saadaval olnud." + "CleanupUserDataTaskDescription": "Puhastab kõik kasutajaandmed (vaatamise olek, lemmikute olek jne) meediast, mida pole enam vähemalt 90 päeva saadaval olnud.", + "LyricDownloadFailureFromForItem": "Laulusõnade hankimine teenusest {0} loole {1} nurjus", + "Original": "Algne" } diff --git a/Emby.Server.Implementations/Localization/Core/eu.json b/Emby.Server.Implementations/Localization/Core/eu.json index 9e1390484f..71c351adcd 100644 --- a/Emby.Server.Implementations/Localization/Core/eu.json +++ b/Emby.Server.Implementations/Localization/Core/eu.json @@ -1,23 +1,16 @@ { - "ValueSpecialEpisodeName": "Berezia - {0}", - "Sync": "Sinkronizatu", - "Songs": "Abestiak", "Shows": "Serieak", - "Playlists": "Erreprodukzio-zerrendak", "Photos": "Argazkiak", "MusicVideos": "Bideo musikalak", "Movies": "Filmak", "HeaderContinueWatching": "Ikusten jarraitu", - "HeaderAlbumArtists": "Albumeko artistak", "Genres": "Generoak", "Folders": "Karpetak", "Favorites": "Gogokoak", "Default": "Lehenetsia", "Collections": "Bildumak", - "Channels": "Kanalak", "Books": "Liburuak", "Artists": "Artistak", - "Albums": "Albumak", "TaskOptimizeDatabase": "Datu basea optimizatu", "TaskDownloadMissingSubtitlesDescription": "Falta diren azpitituluak bilatzen ditu interneten metadatuen konfigurazioaren arabera.", "TaskDownloadMissingSubtitles": "Falta diren azpitituluak deskargatu", @@ -44,10 +37,8 @@ "TasksLibraryCategory": "Liburutegia", "TasksMaintenanceCategory": "Mantenua", "VersionNumber": "Bertsioa {0}", - "ValueHasBeenAddedToLibrary": "{0} zure multimedia liburutegian gehitu da", "UserStoppedPlayingItemWithValues": "{0} {1} ikusten bukatu du {2}-(e)n", "UserStartedPlayingItemWithValues": "{0} {1} ikusten ari da {2}-(e)n", - "UserPolicyUpdatedWithName": "{0} erabiltzailearen politikak aldatu dira", "UserPasswordChangedWithName": "{0} erabiltzailearen pasahitza aldatu da", "UserOnlineFromDevice": "{0} online dago {1}-(e)tik", "UserOfflineFromDevice": "{0} {1}-(e)tik deskonektatu da", @@ -55,19 +46,14 @@ "UserDownloadingItemWithValues": "{0} {1} deskargatzen ari da", "UserDeletedWithName": "{0} Erabiltzailea ezabatu da", "UserCreatedWithName": "{0} Erabiltzailea sortu da", - "User": "Erabiltzailea", "Undefined": "Ezezaguna", "TvShows": "TB serieak", - "System": "Sistema", "SubtitleDownloadFailureFromForItem": "{1}-en azpitutuluak {0}-tik deskargatzeak huts egin du", "StartupEmbyServerIsLoading": "Jellyfin zerbitzaria kargatzen. Saiatu berriro beranduago.", - "ServerNameNeedsToBeRestarted": "{0} berrabiarazi behar da", - "ScheduledTaskStartedWithName": "{0} hasi da", "ScheduledTaskFailedWithName": "{0} huts egin du", "PluginUpdatedWithName": "{0} eguneratu da", "PluginUninstalledWithName": "{0} desinstalatu da", "PluginInstalledWithName": "{0} instalatu da", - "Plugin": "Plugin", "NotificationOptionVideoPlaybackStopped": "Bideoa geldituta", "NotificationOptionVideoPlayback": "Bideoa martxan", "NotificationOptionUserLockedOut": "Erabiltzailea blokeatua", @@ -90,37 +76,22 @@ "NameInstallFailed": "{0} instalazioak huts egin du", "Music": "Musika", "MixedContent": "Eduki mistoa", - "MessageServerConfigurationUpdated": "Zerbitzariaren konfigurazioa eguneratu da", - "MessageNamedServerConfigurationUpdatedWithValue": "Zerbitzariaren {0} konfigurazio atala eguneratu da", - "MessageApplicationUpdatedTo": "Jellyfin zerbitzaria {0}-ra eguneratu da", - "MessageApplicationUpdated": "Jellyfin zerbitzaria eguneratu da", "Latest": "Azkena", "LabelRunningTimeValue": "Iraupena: {0}", "LabelIpAddressValue": "IP helbidea: {0}", - "ItemRemovedWithName": "{0} liburutegitik kendu da", - "ItemAddedWithName": "{0} liburutegira gehitu da", "HomeVideos": "Etxeko bideoak", "HeaderNextUp": "Hurrengoa", "HeaderLiveTV": "Zuzeneko TB", - "HeaderFavoriteSongs": "Gogoko abestiak", "HeaderFavoriteShows": "Gogoko serieak", "HeaderFavoriteEpisodes": "Gogoko atalak", - "HeaderFavoriteArtists": "Gogoko artistak", - "HeaderFavoriteAlbums": "Gogoko albumak", "Forced": "Behartuta", "FailedLoginAttemptWithUserName": "{0}-tik saioa hasteak huts egin du", "External": "Kanpokoa", - "DeviceOnlineWithName": "{0} konektatu da", - "DeviceOfflineWithName": "{0} deskonektatu da", "ChapterNameValue": "{0} Kapitulua", - "CameraImageUploadedFrom": "{0}-tik kamera irudi berri bat igo da", "AuthenticationSucceededWithUserName": "{0} ongi autentifikatu da", - "Application": "Aplikazioa", "AppDeviceValues": "App: {0}, Gailua: {1}", "HearingImpaired": "Entzumen urritasuna", - "ProviderValue": "Hornitzailea: {0}", "TaskKeyframeExtractorDescription": "Bideo fitxategietako fotograma gakoak ateratzen ditu HLS erreprodukzio-zerrenda zehatzagoak sortzeko. Zeregin honek denbora asko iraun dezake.", - "HeaderRecordingGroups": "Grabaketa taldeak", "Inherit": "Oinordetu", "TaskOptimizeDatabaseDescription": "Datu-basea trinkotu eta bertatik espazioa askatzen du. Liburutegia eskaneatu ondoren edo datu-basean aldaketak egin ondoren ataza hau exekutatzeak errendimendua hobetu lezake.", "TaskKeyframeExtractor": "Fotograma gakoen erauzgailua", @@ -135,5 +106,7 @@ "TaskMoveTrickplayImagesDescription": "Lehendik dauden trickplay fitxategiak liburutegiaren ezarpenen arabera mugitzen dira.", "TaskAudioNormalizationDescription": "Audio normalizazio datuak lortzeko fitxategiak eskaneatzen ditu.", "CleanupUserDataTaskDescription": "Gutxienez 90 egunez dagoeneko existitzen ez den multimediatik erabiltzaile-datu guztiak (ikusteko egoera, gogokoen egoera, etab.) garbitzen ditu.", - "CleanupUserDataTask": "Erabiltzaileen datuak garbitzeko zeregina" + "CleanupUserDataTask": "Erabiltzaileen datuak garbitzeko zeregina", + "LyricDownloadFailureFromForItem": "Ezin izan dira {1}-ren letrak deskargatu {0}-tik", + "Original": "Jatorrizkoa" } diff --git a/Emby.Server.Implementations/Localization/Core/fa.json b/Emby.Server.Implementations/Localization/Core/fa.json index 435485db7c..17ed54b117 100644 --- a/Emby.Server.Implementations/Localization/Core/fa.json +++ b/Emby.Server.Implementations/Localization/Core/fa.json @@ -1,41 +1,24 @@ { - "Albums": "آلبومها", "AppDeviceValues": "برنامه: {0} ، دستگاه: {1}", - "Application": "برنامه", "Artists": "هنرمندان", "AuthenticationSucceededWithUserName": "{0} با موفقیت تایید اعتبار شد", "Books": "کتابها", - "CameraImageUploadedFrom": "یک عکس جدید از دوربین ارسال شده است {0}", - "Channels": "کانالها", "ChapterNameValue": "قسمت {0}", "Collections": "مجموعهها", - "DeviceOfflineWithName": "ارتباط {0} قطع شد", - "DeviceOnlineWithName": "{0} متصل شد", "FailedLoginAttemptWithUserName": "تلاش برای ورود از {0} ناموفق بود", "Favorites": "مورد علاقهها", "Folders": "پوشهها", "Genres": "ژانرها", - "HeaderAlbumArtists": "هنرمندان آلبوم", "HeaderContinueWatching": "ادامه تماشا", - "HeaderFavoriteAlbums": "آلبومهای مورد علاقه", - "HeaderFavoriteArtists": "هنرمندان مورد علاقه", "HeaderFavoriteEpisodes": "قسمتهای مورد علاقه", "HeaderFavoriteShows": "سریالهای مورد علاقه", - "HeaderFavoriteSongs": "آهنگهای مورد علاقه", "HeaderLiveTV": "پخش زنده", "HeaderNextUp": "قسمت بعدی", - "HeaderRecordingGroups": "گروههای ضبط", "HomeVideos": "ویدیوهای خانگی", "Inherit": "به ارث برده", - "ItemAddedWithName": "{0} به کتابخانه افزوده شد", - "ItemRemovedWithName": "{0} از کتابخانه حذف شد", "LabelIpAddressValue": "آدرس آی پی: {0}", "LabelRunningTimeValue": "زمان اجرا: {0}", "Latest": "جدیدترینها", - "MessageApplicationUpdated": "سرور Jellyfin بروزرسانی شد", - "MessageApplicationUpdatedTo": "سرور Jellyfin به نسخه {0} بروزرسانی شد", - "MessageNamedServerConfigurationUpdatedWithValue": "پکربندی بخش {0} سرور بروزرسانی شد", - "MessageServerConfigurationUpdated": "پیکربندی سرور بروزرسانی شد", "MixedContent": "محتوای مخلوط", "Movies": "فیلم ها", "Music": "موسیقی", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "پخش ویدیو آغاز شد", "NotificationOptionVideoPlaybackStopped": "پخش ویدیو متوقف شد", "Photos": "عکسها", - "Playlists": "لیستهای پخش", - "Plugin": "افزونه", "PluginInstalledWithName": "{0} نصب شد", "PluginUninstalledWithName": "{0} حذف شد", "PluginUpdatedWithName": "{0} آپدیت شد", - "ProviderValue": "ارائه دهنده: {0}", "ScheduledTaskFailedWithName": "{0} شکست خورد", - "ScheduledTaskStartedWithName": "{0} شروع شد", - "ServerNameNeedsToBeRestarted": "{0} نیاز به راه اندازی مجدد دارد", "Shows": "سریالها", - "Songs": "موسیقیها", "StartupEmbyServerIsLoading": "سرور Jellyfin در حال بارگیری است. لطفا کمی بعد دوباره تلاش کنید.", "SubtitleDownloadFailureFromForItem": "بارگیری زیرنویس برای {1} از {0} شکست خورد", - "Sync": "همگامسازی", - "System": "سیستم", "TvShows": "سریالهای تلویزیونی", - "User": "کاربر", "UserCreatedWithName": "کاربر {0} ایجاد شد", "UserDeletedWithName": "کاربر {0} حذف شد", "UserDownloadingItemWithValues": "{0} در حال بارگیری {1} میباشد", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "ارتباط {0} از {1} قطع شد", "UserOnlineFromDevice": "{0} از {1} آنلاین میباشد", "UserPasswordChangedWithName": "گذرواژه برای کاربر {0} تغییر کرد", - "UserPolicyUpdatedWithName": "سیاست کاربری برای {0} بروزرسانی شد", "UserStartedPlayingItemWithValues": "{0} در حال پخش {1} بر روی {2} است", "UserStoppedPlayingItemWithValues": "{0} پخش {1} را بر روی {2} به پایان رساند", - "ValueHasBeenAddedToLibrary": "{0} به کتابخانهی رسانهی شما افزوده شد", - "ValueSpecialEpisodeName": "ویژه - {0}", "VersionNumber": "نسخه {0}", "TaskCleanTranscodeDescription": "فایلهای کدگذاری که قدیمیتر از یک روز هستند را حذف میکند.", "TaskCleanTranscode": "پاکسازی مسیر کد گذاری", diff --git a/Emby.Server.Implementations/Localization/Core/fi.json b/Emby.Server.Implementations/Localization/Core/fi.json index d3237db8b0..d080eb0236 100644 --- a/Emby.Server.Implementations/Localization/Core/fi.json +++ b/Emby.Server.Implementations/Localization/Core/fi.json @@ -8,57 +8,33 @@ "Music": "Musiikki", "Movies": "Elokuvat", "MixedContent": "Sekalainen sisältö", - "MessageServerConfigurationUpdated": "Palvelimen asetukset on päivitetty", - "MessageNamedServerConfigurationUpdatedWithValue": "Palvelimen asetusten osio {0} on päivitetty", - "MessageApplicationUpdatedTo": "Jellyfin-palvelin on päivitetty versioon {0}", - "MessageApplicationUpdated": "Jellyfin-palvelin on päivitetty", "Latest": "Viimeisimmät", "LabelRunningTimeValue": "Kesto: {0}", "LabelIpAddressValue": "IP-osoite: {0}", - "ItemRemovedWithName": "{0} poistettiin kirjastosta", - "ItemAddedWithName": "{0} lisättiin kirjastoon", "Inherit": "Peri", "HomeVideos": "Kotivideot", - "HeaderRecordingGroups": "Tallennusryhmät", "HeaderNextUp": "Seuraavaksi", - "HeaderFavoriteSongs": "Suosikkikappaleet", "HeaderFavoriteShows": "Suosikkisarjat", "HeaderFavoriteEpisodes": "Suosikkijaksot", - "HeaderFavoriteArtists": "Suosikkiesittäjät", - "HeaderFavoriteAlbums": "Suosikkialbumit", "HeaderContinueWatching": "Jatka katselua", - "HeaderAlbumArtists": "Albumin esittäjät", "Genres": "Tyylilajit", "Folders": "Kansiot", "Favorites": "Suosikit", "FailedLoginAttemptWithUserName": "Epäonnistunut kirjautumisyritys lähteestä \"{0}\"", - "DeviceOnlineWithName": "{0} on yhdistetty", - "DeviceOfflineWithName": "{0} on katkaissut yhteyden", "Collections": "Kokoelmat", "ChapterNameValue": "Kappale {0}", - "Channels": "Kanavat", - "CameraImageUploadedFrom": "Uusi kameran kuva on sirretty lähteestä {0}", "Books": "Kirjat", "AuthenticationSucceededWithUserName": "{0} todennus onnistunut", "Artists": "Artistit", - "Application": "Sovellus", "AppDeviceValues": "Sovellus: {0}, Laite: {1}", - "Albums": "Albumit", - "User": "Käyttäjä", - "System": "Järjestelmä", "ScheduledTaskFailedWithName": "{0} epäonnistui", "PluginUpdatedWithName": "{0} päivitettiin", "PluginInstalledWithName": "{0} asennettiin", "Photos": "Valokuvat", - "ScheduledTaskStartedWithName": "\"{0}\" käynnistetty", "PluginUninstalledWithName": "{0} poistettiin", - "Playlists": "Soittolistat", "VersionNumber": "Versio {0}", - "ValueSpecialEpisodeName": "Erikoisjakso - {0}", - "ValueHasBeenAddedToLibrary": "\"{0}\" on lisätty mediakirjastoon", "UserStoppedPlayingItemWithValues": "{0} lopetti kohteen \"{1}\" toiston sijainnissa \"{2}\"", "UserStartedPlayingItemWithValues": "{0} toistaa kohdetta \"{1}\" sijainnissa \"{2}\"", - "UserPolicyUpdatedWithName": "Käyttäjän {0} käyttöoikeudet on päivitetty", "UserPasswordChangedWithName": "Käyttäjän {0} salasana on vaihdettu", "UserOnlineFromDevice": "{0} on yhdistänyt sijainnista \"{1}\"", "UserOfflineFromDevice": "{0} on katkaissut yhteyden sijainnista \"{1}\"", @@ -67,14 +43,9 @@ "UserDeletedWithName": "Käyttäjä {0} on poistettu", "UserCreatedWithName": "Käyttäjä {0} on luotu", "TvShows": "Sarjat", - "Sync": "Synkronointi", "SubtitleDownloadFailureFromForItem": "Tekstityksen lataus lähteestä \"{0}\" kohteelle \"{1}\" epäonnistui", "StartupEmbyServerIsLoading": "Jellyfin-palvelin on latautumassa. Yritä hetken kuluttua uudelleen.", - "Songs": "Kappaleet", "Shows": "Sarjat", - "ServerNameNeedsToBeRestarted": "\"{0}\" on käynnistettävä uudelleen", - "ProviderValue": "Lähde: {0}", - "Plugin": "Lisäosa", "NotificationOptionVideoPlaybackStopped": "Videon toisto lopetettu", "NotificationOptionVideoPlayback": "Videon toisto aloitettu", "NotificationOptionUserLockedOut": "Käyttäjä on lukittu", @@ -135,5 +106,7 @@ "TaskMoveTrickplayImages": "Siirrä Trickplay-kuvien sijainti", "TaskMoveTrickplayImagesDescription": "Siirtää olemassa olevia trickplay-tiedostoja kirjaston asetusten mukaan.", "CleanupUserDataTask": "Käyttäjätietojen puhdistustehtävä", - "CleanupUserDataTaskDescription": "Puhdistaa kaikki käyttäjätiedot (katselutila, suosikit ym.) medioista, joita ei ole ollut saatavilla yli 90 päivään." + "CleanupUserDataTaskDescription": "Puhdistaa kaikki käyttäjätiedot (katselutila, suosikit ym.) medioista, joita ei ole ollut saatavilla yli 90 päivään.", + "LyricDownloadFailureFromForItem": "Sanoitusten lataus kohteesta {0} kappaleelle {1} epäonnistui", + "Original": "Alkuperäinen" } diff --git a/Emby.Server.Implementations/Localization/Core/fil.json b/Emby.Server.Implementations/Localization/Core/fil.json index 28c1d2be5e..30d90e9f98 100644 --- a/Emby.Server.Implementations/Localization/Core/fil.json +++ b/Emby.Server.Implementations/Localization/Core/fil.json @@ -1,10 +1,7 @@ { "VersionNumber": "Bersyon {0}", - "ValueSpecialEpisodeName": "Espesyal - {0}", - "ValueHasBeenAddedToLibrary": "Naidagdag na ang {0} sa iyong librerya ng medya", "UserStoppedPlayingItemWithValues": "Natapos ni {0} ang {1} sa {2}", "UserStartedPlayingItemWithValues": "Si {0} ay nagpla-play ng {1} sa {2}", - "UserPolicyUpdatedWithName": "Ang user policy ay nai-update para kay {0}", "UserPasswordChangedWithName": "Napalitan na ang password ni {0}", "UserOnlineFromDevice": "Si {0} ay naka-konekta galing sa {1}", "UserOfflineFromDevice": "Si {0} ay na-diskonekta galing sa {1}", @@ -12,23 +9,14 @@ "UserDownloadingItemWithValues": "Nagdadownload si {0} ng {1}", "UserDeletedWithName": "Natanggal na is user {0}", "UserCreatedWithName": "Nagawa na si user {0}", - "User": "User", "TvShows": "Mga Palabas sa Telebisyon", - "System": "Sistema", - "Sync": "Pag-sync", "SubtitleDownloadFailureFromForItem": "Hindi nai-download ang subtitles {0} para sa {1}", "StartupEmbyServerIsLoading": "Naglo-load ang Jellyfin Server. Mangyaring subukan ulit sandali.", - "Songs": "Mga Kanta", "Shows": "Mga Pelikula", - "ServerNameNeedsToBeRestarted": "Kailangan irestart ang {0}", - "ScheduledTaskStartedWithName": "Nagsimula na ang {0}", "ScheduledTaskFailedWithName": "Hindi gumana ang {0}", - "ProviderValue": "Tagapagtustos: {0}", "PluginUpdatedWithName": "Naiupdate na ang {0}", "PluginUninstalledWithName": "Naiuninstall na ang {0}", "PluginInstalledWithName": "Nainstall na ang {0}", - "Plugin": "Plugin", - "Playlists": "Mga Playlist", "Photos": "Mga Larawan", "NotificationOptionVideoPlaybackStopped": "Huminto na ang pelikula", "NotificationOptionVideoPlayback": "Nagsimula na ang pelikula", @@ -54,42 +42,25 @@ "Music": "Mga Kanta", "Movies": "Mga Pelikula", "MixedContent": "Halo-halong content", - "MessageServerConfigurationUpdated": "Naiupdate na ang server configuration", - "MessageNamedServerConfigurationUpdatedWithValue": "Naiupdate na ang server configuration section {0}", - "MessageApplicationUpdatedTo": "Ang bersyon ng Jellyfin Server ay naiupdate sa {0}", - "MessageApplicationUpdated": "Naiupdate na ang Jellyfin Server", "Latest": "Pinakabago", "LabelRunningTimeValue": "Oras: {0}", "LabelIpAddressValue": "IP address: {0}", - "ItemRemovedWithName": "Naitanggal ang {0} sa librerya", - "ItemAddedWithName": "Naidagdag ang {0} sa librerya", "Inherit": "Manahin", - "HeaderRecordingGroups": "Pagtatalang Grupo", "HeaderNextUp": "Susunod", "HeaderLiveTV": "Live TV", - "HeaderFavoriteSongs": "Mga Paboritong Kanta", "HeaderFavoriteShows": "Mga Paboritong Pelikula", "HeaderFavoriteEpisodes": "Mga Paboritong Yugto", - "HeaderFavoriteArtists": "Mga Paboritong Artista", - "HeaderFavoriteAlbums": "Mga Paboritong Album", "HeaderContinueWatching": "Magpatuloy sa Panonood", - "HeaderAlbumArtists": "Mga Artista ng Album", "Genres": "Mga Kategorya", "Folders": "Mga Folder", "Favorites": "Mga Paborito", "FailedLoginAttemptWithUserName": "Maling login galing kay/sa {0}", - "DeviceOnlineWithName": "Nakakonekta si/ang {0}", - "DeviceOfflineWithName": "Nadiskonekta si/ang {0}", "Collections": "Mga Koleksyon", "ChapterNameValue": "Kabanata {0}", - "Channels": "Mga Channel", - "CameraImageUploadedFrom": "May bagong larawan na naupload galing sa/kay {0}", "Books": "Mga Libro", "AuthenticationSucceededWithUserName": "Napatunayan si/ang {0}", "Artists": "Mga Artista", - "Application": "Aplikasyon", "AppDeviceValues": "Aplikasyon: {0}, Aparato: {1}", - "Albums": "Mga Album", "TaskRefreshLibrary": "Suriin and Librerya ng Medya", "TaskRefreshChapterImagesDescription": "Gumawa ng larawan para sa mga pelikula na may kabanata.", "TaskRefreshChapterImages": "Kunin ang mga larawan ng kabanata", diff --git a/Emby.Server.Implementations/Localization/Core/fo.json b/Emby.Server.Implementations/Localization/Core/fo.json index 044abc7fa3..4fb9f4329c 100644 --- a/Emby.Server.Implementations/Localization/Core/fo.json +++ b/Emby.Server.Implementations/Localization/Core/fo.json @@ -2,21 +2,15 @@ "Artists": "Listafólk", "Collections": "Søvn", "Default": "Sjálvgildi", - "DeviceOfflineWithName": "{0} hevur slitið sambandið", "External": "Ytri", "Genres": "Greinar", - "Albums": "Album", "AppDeviceValues": "App: {0}, Eind: {1}", - "Application": "Nýtsluskipan", "Books": "Bøkur", - "Channels": "Rásir", "ChapterNameValue": "Kapittul {0}", - "DeviceOnlineWithName": "{0} er sambundið", "Favorites": "Yndis", "Folders": "Mappur", "Forced": "Kravt", "FailedLoginAttemptWithUserName": "Miseydnað innritanarroynd frá {0}", "HeaderFavoriteEpisodes": "Yndispartar", - "HeaderFavoriteSongs": "Yndissangir", "LabelIpAddressValue": "IP atsetur: {0}" } diff --git a/Emby.Server.Implementations/Localization/Core/fr-CA.json b/Emby.Server.Implementations/Localization/Core/fr-CA.json index b05e0d10b4..e05cce47b0 100644 --- a/Emby.Server.Implementations/Localization/Core/fr-CA.json +++ b/Emby.Server.Implementations/Localization/Core/fr-CA.json @@ -1,41 +1,24 @@ { - "Albums": "Albums", "AppDeviceValues": "App : {0}, Appareil : {1}", - "Application": "Application", "Artists": "Artistes", "AuthenticationSucceededWithUserName": "{0} authentifié avec succès", "Books": "Livres", - "CameraImageUploadedFrom": "Une nouvelle photo a été téléversée depuis {0}", - "Channels": "Chaînes", "ChapterNameValue": "Chapitre {0}", "Collections": "Collections", - "DeviceOfflineWithName": "{0} s'est déconnecté", - "DeviceOnlineWithName": "{0} est connecté", "FailedLoginAttemptWithUserName": "Tentative de connexion échouée par {0}", "Favorites": "Favoris", "Folders": "Dossiers", "Genres": "Genres", - "HeaderAlbumArtists": "Artistes de l'album", "HeaderContinueWatching": "Reprendre le visionnement", - "HeaderFavoriteAlbums": "Albums favoris", - "HeaderFavoriteArtists": "Artistes favoris", "HeaderFavoriteEpisodes": "Épisodes favoris", "HeaderFavoriteShows": "Séries favorites", - "HeaderFavoriteSongs": "Chansons favorites", "HeaderLiveTV": "TV en direct", "HeaderNextUp": "À Suivre", - "HeaderRecordingGroups": "Groupes d'enregistrements", "HomeVideos": "Vidéos personnelles", "Inherit": "Hérite", - "ItemAddedWithName": "{0} a été ajouté à la médiathèque", - "ItemRemovedWithName": "{0} a été supprimé de la médiathèque", "LabelIpAddressValue": "Adresse IP : {0}", "LabelRunningTimeValue": "Durée : {0}", "Latest": "Plus récent", - "MessageApplicationUpdated": "Le serveur Jellyfin a été mis à jour", - "MessageApplicationUpdatedTo": "Le serveur Jellyfin a été mis à jour vers la version {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "La configuration de la section {0} du serveur a été mise à jour", - "MessageServerConfigurationUpdated": "La configuration du serveur a été mise à jour", "MixedContent": "Contenu mixte", "Movies": "Films", "Music": "Musique", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "Lecture vidéo démarrée", "NotificationOptionVideoPlaybackStopped": "Lecture vidéo arrêtée", "Photos": "Photos", - "Playlists": "Listes de lecture", - "Plugin": "Extension", "PluginInstalledWithName": "{0} a été installé", "PluginUninstalledWithName": "{0} a été désinstallé", "PluginUpdatedWithName": "{0} a été mis à jour", - "ProviderValue": "Fournisseur : {0}", "ScheduledTaskFailedWithName": "{0} a échoué", - "ScheduledTaskStartedWithName": "{0} a commencé", - "ServerNameNeedsToBeRestarted": "{0} doit être redémarré", "Shows": "Séries", - "Songs": "Chansons", "StartupEmbyServerIsLoading": "Serveur Jellyfin en cours de chargement. Réessayez dans quelques instants.", "SubtitleDownloadFailureFromForItem": "Échec du téléchargement des sous-titres depuis {0} pour {1}", - "Sync": "Synchroniser", - "System": "Système", "TvShows": "Séries Télé", - "User": "Utilisateur", "UserCreatedWithName": "L'utilisateur {0} a été créé", "UserDeletedWithName": "L'utilisateur {0} supprimé", "UserDownloadingItemWithValues": "{0} télécharge {1}", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "{0} s'est déconnecté de {1}", "UserOnlineFromDevice": "{0} s'est connecté de {1}", "UserPasswordChangedWithName": "Le mot de passe de utilisateur {0} a été modifié", - "UserPolicyUpdatedWithName": "La politique de l'utilisateur a été mise à jour pour {0}", "UserStartedPlayingItemWithValues": "{0} joue {1} sur {2}", "UserStoppedPlayingItemWithValues": "{0} a terminé la lecture de {1} sur {2}", - "ValueHasBeenAddedToLibrary": "{0} a été ajouté à votre médiathèque", - "ValueSpecialEpisodeName": "Spécial - {0}", "VersionNumber": "Version {0}", "TasksLibraryCategory": "Médiathèque", "TasksMaintenanceCategory": "Entretien", @@ -135,5 +106,7 @@ "TaskMoveTrickplayImages": "Changer l'emplacement des images Trickplay", "TaskExtractMediaSegmentsDescription": "Extrait ou obtient des segments de média à partir des plugins compatibles avec MediaSegment.", "CleanupUserDataTaskDescription": "Nettoie toutes les données utilisateur (état de la montre, statut favori, etc.) des supports qui ne sont plus présents depuis au moins 90 jours.", - "CleanupUserDataTask": "Tâche de nettoyage des données utilisateur" + "CleanupUserDataTask": "Tâche de nettoyage des données utilisateur", + "LyricDownloadFailureFromForItem": "Le téléchargement des paroles a échoué de {0} pour {1}", + "Original": "Original" } diff --git a/Emby.Server.Implementations/Localization/Core/fr.json b/Emby.Server.Implementations/Localization/Core/fr.json index 8937b1d0c9..ceba1dcb41 100644 --- a/Emby.Server.Implementations/Localization/Core/fr.json +++ b/Emby.Server.Implementations/Localization/Core/fr.json @@ -1,41 +1,24 @@ { - "Albums": "Albums", "AppDeviceValues": "Application : {0}, Appareil : {1}", - "Application": "Application", "Artists": "Artistes", "AuthenticationSucceededWithUserName": "{0} authentifié avec succès", "Books": "Livres", - "CameraImageUploadedFrom": "Une photo a été téléchargée depuis {0}", - "Channels": "Chaînes", "ChapterNameValue": "Chapitre {0}", "Collections": "Collections", - "DeviceOfflineWithName": "{0} s'est déconnecté", - "DeviceOnlineWithName": "{0} est connecté", "FailedLoginAttemptWithUserName": "Échec de connexion depuis {0}", "Favorites": "Favoris", "Folders": "Dossiers", "Genres": "Genres", - "HeaderAlbumArtists": "Artistes d'albums", "HeaderContinueWatching": "Continuer de regarder", - "HeaderFavoriteAlbums": "Albums favoris", - "HeaderFavoriteArtists": "Artistes préférés", "HeaderFavoriteEpisodes": "Épisodes favoris", "HeaderFavoriteShows": "Séries favorites", - "HeaderFavoriteSongs": "Chansons préférées", "HeaderLiveTV": "TV en direct", "HeaderNextUp": "Prochain à venir", - "HeaderRecordingGroups": "Groupes d'enregistrements", "HomeVideos": "Vidéos personnelles", "Inherit": "Hériter", - "ItemAddedWithName": "{0} a été ajouté à la médiathèque", - "ItemRemovedWithName": "{0} a été supprimé de la médiathèque", "LabelIpAddressValue": "Adresse IP : {0}", "LabelRunningTimeValue": "Durée : {0}", "Latest": "Derniers", - "MessageApplicationUpdated": "Le serveur Jellyfin a été mis à jour", - "MessageApplicationUpdatedTo": "Le serveur Jellyfin a été mis à jour en version {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "La configuration de la section {0} du serveur a été mise à jour", - "MessageServerConfigurationUpdated": "La configuration du serveur a été mise à jour", "MixedContent": "Contenu mixte", "Movies": "Films", "Music": "Musique", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "Lecture vidéo démarrée", "NotificationOptionVideoPlaybackStopped": "Lecture vidéo arrêtée", "Photos": "Photos", - "Playlists": "Listes de lecture", - "Plugin": "Extension", "PluginInstalledWithName": "{0} a été installé", "PluginUninstalledWithName": "{0} a été désinstallé", "PluginUpdatedWithName": "{0} a été mis à jour", - "ProviderValue": "Fournisseur : {0}", "ScheduledTaskFailedWithName": "{0} a échoué", - "ScheduledTaskStartedWithName": "{0} a démarré", - "ServerNameNeedsToBeRestarted": "{0} doit être redémarré", "Shows": "Séries", - "Songs": "Chansons", "StartupEmbyServerIsLoading": "Le serveur Jellyfin est en cours de chargement. Veuillez réessayer dans quelques instants.", "SubtitleDownloadFailureFromForItem": "Échec du téléchargement des sous-titres depuis {0} pour {1}", - "Sync": "Synchroniser", - "System": "Système", "TvShows": "Séries TV", - "User": "Utilisateur", "UserCreatedWithName": "L'utilisateur {0} a été créé", "UserDeletedWithName": "L'utilisateur {0} a été supprimé", "UserDownloadingItemWithValues": "{0} est en train de télécharger {1}", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "{0} s'est déconnecté depuis {1}", "UserOnlineFromDevice": "{0} s'est connecté depuis {1}", "UserPasswordChangedWithName": "Le mot de passe pour l'utilisateur {0} a été modifié", - "UserPolicyUpdatedWithName": "La politique de l'utilisateur a été mise à jour pour {0}", "UserStartedPlayingItemWithValues": "{0} est en train de lire {1} sur {2}", "UserStoppedPlayingItemWithValues": "{0} vient d'arrêter la lecture de {1} sur {2}", - "ValueHasBeenAddedToLibrary": "{0} a été ajouté à votre médiathèque", - "ValueSpecialEpisodeName": "Spécial - {0}", "VersionNumber": "Version {0}", "TasksChannelsCategory": "Chaînes en ligne", "TaskDownloadMissingSubtitlesDescription": "Recherche les sous-titres manquants sur Internet en se basant sur la configuration des métadonnées.", @@ -135,5 +106,7 @@ "TaskExtractMediaSegmentsDescription": "Extrait ou obtient des segments de média à partir des plugins compatibles avec MediaSegment.", "TaskMoveTrickplayImagesDescription": "Déplace les fichiers trickplay existants en fonction des paramètres de la bibliothèque.", "CleanupUserDataTaskDescription": "Nettoie toutes les données utilisateur (état de la montre, statut favori, etc.) des supports qui ne sont plus présents depuis au moins 90 jours.", - "CleanupUserDataTask": "Tâche de nettoyage des données utilisateur" + "CleanupUserDataTask": "Tâche de nettoyage des données utilisateur", + "LyricDownloadFailureFromForItem": "Le téléchargement des paroles à échoué de {0} pour {1}", + "Original": "Original" } diff --git a/Emby.Server.Implementations/Localization/Core/ga.json b/Emby.Server.Implementations/Localization/Core/ga.json index ee6e8b8368..1ee606cc64 100644 --- a/Emby.Server.Implementations/Localization/Core/ga.json +++ b/Emby.Server.Implementations/Localization/Core/ga.json @@ -1,15 +1,10 @@ { - "Albums": "Albaim", "Artists": "Ealaíontóirí", "AuthenticationSucceededWithUserName": "D'éirigh le fíordheimhniú {0}", "Books": "Leabhair", - "CameraImageUploadedFrom": "Uaslódáladh íomhá ceamara nua ó {0}", - "Channels": "Cainéil", "ChapterNameValue": "Caibidil {0}", "Collections": "Bailiúcháin", "Default": "Réamhshocrú", - "DeviceOfflineWithName": "Tá {0} dícheangailte", - "DeviceOnlineWithName": "Tá {0} nasctha", "External": "Seachtrach", "FailedLoginAttemptWithUserName": "Theip ar iarracht logáil isteach ó {0}", "Favorites": "Ceanáin", @@ -36,32 +31,20 @@ "TaskOptimizeDatabaseDescription": "Comhdhlúthaíonn bunachar sonraí agus gearrtar spás saor in aisce. Má ritheann tú an tasc seo tar éis scanadh a dhéanamh ar an leabharlann nó athruithe eile a dhéanamh a thugann le tuiscint gur cheart go bhfeabhsófaí an fheidhmíocht.", "TaskMoveTrickplayImagesDescription": "Bogtar comhaid trickplay atá ann cheana de réir socruithe na leabharlainne.", "AppDeviceValues": "Aip: {0}, Gléas: {1}", - "Application": "Feidhmchlár", "Folders": "Fillteáin", "Forced": "Éigean", "Genres": "Seánraí", - "HeaderAlbumArtists": "Ealaíontóirí albam", "HeaderContinueWatching": "Leanúint ar aghaidh ag Breathnú", - "HeaderFavoriteAlbums": "Albam is fearr leat", - "HeaderFavoriteArtists": "Ealaíontóirí is Fearr", "HeaderFavoriteEpisodes": "Eipeasóid is fearr leat", "HeaderFavoriteShows": "Seónna is Fearr", - "HeaderFavoriteSongs": "Amhráin is fearr leat", "HeaderLiveTV": "Teilifís beo", "HeaderNextUp": "Ar Aghaidh Suas", - "HeaderRecordingGroups": "Grúpaí Taifeadta", "HearingImpaired": "Lag éisteachta", "HomeVideos": "Físeáin Baile", "Inherit": "Oidhreacht", - "ItemAddedWithName": "Cuireadh {0} leis an leabharlann", - "ItemRemovedWithName": "Baineadh {0} den leabharlann", "LabelIpAddressValue": "Seoladh IP: {0}", "LabelRunningTimeValue": "Am rite: {0}", "Latest": "Is déanaí", - "MessageApplicationUpdated": "Tá Freastalaí Jellyfin nuashonraithe", - "MessageApplicationUpdatedTo": "Nuashonraíodh Freastalaí Jellyfin go {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "Nuashonraíodh an chuid cumraíochta freastalaí {0}", - "MessageServerConfigurationUpdated": "Nuashonraíodh cumraíocht an fhreastalaí", "MixedContent": "Ábhar measctha", "Movies": "Scannáin", "Music": "Ceol", @@ -87,24 +70,15 @@ "NotificationOptionVideoPlayback": "Cuireadh tús le hathsheinm físe", "NotificationOptionVideoPlaybackStopped": "Cuireadh deireadh le hathsheinm físe", "Photos": "Grianghraif", - "Playlists": "Seinmliostaí", - "Plugin": "Breiseán", "PluginInstalledWithName": "Suiteáladh {0}", "PluginUninstalledWithName": "Díshuiteáladh {0}", "PluginUpdatedWithName": "Nuashonraíodh {0}", - "ProviderValue": "Soláthraí: {0}", "ScheduledTaskFailedWithName": "Theip ar {0}", - "ScheduledTaskStartedWithName": "Thosaigh {0}", - "ServerNameNeedsToBeRestarted": "Ní mór {0} a atosú", "Shows": "Seónna", - "Songs": "Amhráin", "StartupEmbyServerIsLoading": "Tá freastalaí Jellyfin á luchtú. Bain triail eile as gan mhoill.", "SubtitleDownloadFailureFromForItem": "Theip ar fhotheidil a íoslódáil ó {0} le haghaidh {1}", - "Sync": "Sioncrónaigh", - "System": "Córas", "TvShows": "Seónna Teilifíse", "Undefined": "Neamhshainithe", - "User": "Úsáideoir", "UserCreatedWithName": "Cruthaíodh úsáideoir {0}", "UserDeletedWithName": "Scriosadh úsáideoir {0}", "UserDownloadingItemWithValues": "Tá {0} á íoslódáil {1}", @@ -112,11 +86,8 @@ "UserOfflineFromDevice": "Tá {0} dícheangailte ó {1}", "UserOnlineFromDevice": "Tá {0} ar líne ó {1}", "UserPasswordChangedWithName": "Athraíodh pasfhocal don úsáideoir {0}", - "UserPolicyUpdatedWithName": "Nuashonraíodh polasaí úsáideora le haghaidh {0}", "UserStartedPlayingItemWithValues": "Tá {0} ag seinnt {1} ar {2}", "UserStoppedPlayingItemWithValues": "Chríochnaigh {0} ag imirt {1} ar {2}", - "ValueHasBeenAddedToLibrary": "Cuireadh {0} le do leabharlann meán", - "ValueSpecialEpisodeName": "Speisialta - {0}", "VersionNumber": "Leagan {0}", "TasksMaintenanceCategory": "Cothabháil", "TasksLibraryCategory": "Leabharlann", @@ -136,5 +107,6 @@ "TaskDownloadMissingSubtitles": "Íosluchtaigh fotheidil ar iarraidh", "CleanupUserDataTask": "Tasc glantacháin sonraí úsáideora", "CleanupUserDataTaskDescription": "Glanann sé gach sonraí úsáideora (stádas faire, stádas is fearr leat srl.) ó mheáin nach bhfuil i láthair a thuilleadh ar feadh 90 lá ar a laghad.", - "Original": "Bunaidh" + "Original": "Bunaidh", + "LyricDownloadFailureFromForItem": "Theip ar liricí a íoslódáil ó {0} do {1}" } diff --git a/Emby.Server.Implementations/Localization/Core/gl.json b/Emby.Server.Implementations/Localization/Core/gl.json index fc5c3fd53d..a68db0076a 100644 --- a/Emby.Server.Implementations/Localization/Core/gl.json +++ b/Emby.Server.Implementations/Localization/Core/gl.json @@ -1,13 +1,9 @@ { - "Albums": "Álbums", "Collections": "Coleccións", "ChapterNameValue": "Capítulo {0}", - "Channels": "Canles", - "CameraImageUploadedFrom": "Cargouse unha nova imaxe de cámara dende {0}", "Books": "Libros", "AuthenticationSucceededWithUserName": "{0} autenticouse correctamente", "Artists": "Artistas", - "Application": "Aplicación", "NotificationOptionServerRestartRequired": "Necesario o reinicio do servidor", "NotificationOptionPluginUpdateInstalled": "Actualización do plugin instalada", "NotificationOptionPluginUninstalled": "Plugin desinstalado", @@ -28,63 +24,41 @@ "Music": "Música", "Movies": "Películas", "MixedContent": "Contido mixto", - "MessageServerConfigurationUpdated": "Actualizouse a configuración do servidor", - "MessageNamedServerConfigurationUpdatedWithValue": "Actualizouse a sección de configuración {0} do servidor", - "MessageApplicationUpdatedTo": "O servidor Jellyfin actualizouse a {0}", - "MessageApplicationUpdated": "O servidor Jellyfin actualizouse", "Latest": "Último", "LabelRunningTimeValue": "Tempo en execución: {0}", "LabelIpAddressValue": "Enderezo IP: {0}", - "ItemRemovedWithName": "{0} eliminouse da biblioteca", - "ItemAddedWithName": "{0} engadiuse á biblioteca", "Inherit": "Herdar", "HomeVideos": "Videos caseiros", - "HeaderRecordingGroups": "Grupos de grabación", "HeaderNextUp": "De seguido", "HeaderLiveTV": "TV en directo", - "HeaderFavoriteSongs": "Cancións favoritas", "HeaderFavoriteShows": "Series de TV favoritas", "HeaderFavoriteEpisodes": "Episodios favoritos", - "HeaderFavoriteArtists": "Artistas favoritos", - "HeaderFavoriteAlbums": "Álbums favoritos", "HeaderContinueWatching": "Seguir vendo", - "HeaderAlbumArtists": "Artistas do álbum", "Genres": "Xéneros", "Forced": "Forzado", "Folders": "Cartafoles", "Favorites": "Favoritos", "FailedLoginAttemptWithUserName": "Fallo de intento de inicio de sesión dende {0}", - "DeviceOnlineWithName": "{0} conectouse", - "DeviceOfflineWithName": "{0} desconectouse", "Default": "Por defecto", "AppDeviceValues": "Aplicación: {0}, Dispositivo: {1}", "TaskCleanLogs": "Limpar directorio de rexistros", "TaskCleanActivityLog": "Limpar rexistro de actividade", "TasksChannelsCategory": "Canles da Internet", "TaskUpdatePlugins": "Actualizar plugins", - "User": "Usuario", "Undefined": "Sen definir", "TvShows": "Programas de TV", - "System": "Sistema", - "Sync": "Sincronizar", "SubtitleDownloadFailureFromForItem": "Fallou a descarga de subtítulos para {1} dende {0}", "StartupEmbyServerIsLoading": "O servidor Jellyfin está cargando. Por favor, ténteo axiña outra vez.", - "Songs": "Cancións", "Shows": "Programas", - "ServerNameNeedsToBeRestarted": "{0} precisa ser reiniciado", - "ScheduledTaskStartedWithName": "{0} comezou", "ScheduledTaskFailedWithName": "{0} fallou", - "ProviderValue": "Provedor: {0}", "PluginUpdatedWithName": "{0} foi actualizado", "PluginUninstalledWithName": "{0} foi desinstalado", "PluginInstalledWithName": "{0} foi instalado", - "Playlists": "Listas de reproducción", "Photos": "Fotos", "UserLockedOutWithName": "O usuario {0} foi bloqueado", "UserDownloadingItemWithValues": "{0} está a ser transferido {1}", "UserDeletedWithName": "O usuario {0} foi borrado", "UserCreatedWithName": "O usuario {0} foi creado", - "Plugin": "Plugin", "NotificationOptionVideoPlaybackStopped": "Reproducción de vídeo detida", "NotificationOptionVideoPlayback": "Reproducción de vídeo iniciada", "NotificationOptionUserLockedOut": "Usuario bloqueado", @@ -109,12 +83,9 @@ "TaskCleanCache": "Limpar directorio de caché", "TaskCleanActivityLogDescription": "Borra do rexistro de actividade as entradas anteriores á data configurada.", "TasksApplicationCategory": "Aplicación", - "ValueSpecialEpisodeName": "Especial - {0}", - "ValueHasBeenAddedToLibrary": "{0} engadiuse á túa biblioteca de medios", "TasksLibraryCategory": "Biblioteca", "TasksMaintenanceCategory": "Mantemento", "VersionNumber": "Versión {0}", - "UserPolicyUpdatedWithName": "A política de usuario foi actualizada para {0}", "UserPasswordChangedWithName": "Cambiouse o contrasinal para o usuario {0}", "UserOnlineFromDevice": "{0} está en liña desde {1}", "UserOfflineFromDevice": "{0} desconectouse dende {1}", @@ -135,5 +106,6 @@ "TaskRefreshTrickplayImages": "Xerar miniaturas de previsualización", "TaskAudioNormalizationDescription": "Escanea ficheiros á procura de datos de normalización de volume.", "CleanupUserDataTask": "Tarefa de limpeza de datos dos usuarios", - "CleanupUserDataTaskDescription": "Limpa todos os datos do usuario (estado de visualización, de favorito etc.) dos medios ausentes polo menos 90 días." + "CleanupUserDataTaskDescription": "Limpa todos os datos do usuario (estado de visualización, de favorito etc.) dos medios ausentes polo menos 90 días.", + "Original": "Orixinal" } diff --git a/Emby.Server.Implementations/Localization/Core/gsw.json b/Emby.Server.Implementations/Localization/Core/gsw.json index 9be6f05ee1..b95e5edecc 100644 --- a/Emby.Server.Implementations/Localization/Core/gsw.json +++ b/Emby.Server.Implementations/Localization/Core/gsw.json @@ -1,41 +1,24 @@ { - "Albums": "Alben", "AppDeviceValues": "App: {0}, Gerät: {1}", - "Application": "Applikation", "Artists": "Künstler", "AuthenticationSucceededWithUserName": "{0} hat sich angemeldet", "Books": "Bücher", - "CameraImageUploadedFrom": "Ein neues Foto wurde von {0} hochgeladen", - "Channels": "Kanäle", "ChapterNameValue": "Kapitel {0}", "Collections": "Sammlungen", - "DeviceOfflineWithName": "{0} wurde getrennt", - "DeviceOnlineWithName": "{0} ist verbunden", "FailedLoginAttemptWithUserName": "Fählgschlagene Ameldeversuech vo {0}", "Favorites": "Favorite", "Folders": "Ordner", "Genres": "Genre", - "HeaderAlbumArtists": "Album-Künschtler", "HeaderContinueWatching": "weiter schauen", - "HeaderFavoriteAlbums": "Lieblingsalben", - "HeaderFavoriteArtists": "Lieblings-Künstler", "HeaderFavoriteEpisodes": "Lieblingsepisoden", "HeaderFavoriteShows": "Lieblingsserien", - "HeaderFavoriteSongs": "Lieblingslieder", "HeaderLiveTV": "Live-Fernseh", "HeaderNextUp": "Als Nächstes", - "HeaderRecordingGroups": "Aufnahme-Gruppen", "HomeVideos": "Heimvideos", "Inherit": "Vererben", - "ItemAddedWithName": "{0} wurde der Bibliothek hinzugefügt", - "ItemRemovedWithName": "{0} wurde aus der Bibliothek entfernt", "LabelIpAddressValue": "IP-Adresse: {0}", "LabelRunningTimeValue": "Laufzeit: {0}", "Latest": "Neueste", - "MessageApplicationUpdated": "Jellyfin-Server wurde aktualisiert", - "MessageApplicationUpdatedTo": "Jellyfin-Server wurde auf Version {0} aktualisiert", - "MessageNamedServerConfigurationUpdatedWithValue": "Der Server-Einstellungsbereich {0} wurde aktualisiert", - "MessageServerConfigurationUpdated": "Serveriistöuige send aktualisiert worde", "MixedContent": "Gmeschti Inhäut", "Movies": "Film", "Music": "Musig", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "Videowedergab gstartet", "NotificationOptionVideoPlaybackStopped": "Videowedergab gstoppt", "Photos": "Fotis", - "Playlists": "Wedergabeliste", - "Plugin": "Plugin", "PluginInstalledWithName": "{0} esch installiert worde", "PluginUninstalledWithName": "{0} esch deinstalliert worde", "PluginUpdatedWithName": "{0} esch updated worde", - "ProviderValue": "Aabieter: {0}", "ScheduledTaskFailedWithName": "{0} esch fäugschlage", - "ScheduledTaskStartedWithName": "{0} het gstartet", - "ServerNameNeedsToBeRestarted": "{0} mues nöi gstartet wärde", "Shows": "Serie", - "Songs": "Lieder", "StartupEmbyServerIsLoading": "Jellyfin Server ladt. Bitte grad noeinisch probiere.", "SubtitleDownloadFailureFromForItem": "Ondertetle vo {0} för {1} hend ned chönne abeglade wärde", - "Sync": "Synchronisation", - "System": "System", "TvShows": "Färnsehserie", - "User": "Benotzer", "UserCreatedWithName": "Benotzer {0} esch erstöut worde", "UserDeletedWithName": "Benotzer {0} esch glösche worde", "UserDownloadingItemWithValues": "{0} ladt {1} abe", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "{0} esch vo {1} trennt worde", "UserOnlineFromDevice": "{0} esch online vo {1}", "UserPasswordChangedWithName": "S'Passwort för Benotzer {0} esch gänderet worde", - "UserPolicyUpdatedWithName": "Benotzerrechtlinie för {0} esch aktualisiert worde", "UserStartedPlayingItemWithValues": "{0} hed d'Wedergab vo {1} of {2} gstartet", "UserStoppedPlayingItemWithValues": "{0} het d'Wedergab vo {1} of {2} gstoppt", - "ValueHasBeenAddedToLibrary": "{0} esch dinnere Biblithek hinzuegfüegt worde", - "ValueSpecialEpisodeName": "Extra - {0}", "VersionNumber": "Version {0}", "TaskCleanLogs": "Lösche Log Pfad", "TaskRefreshLibraryDescription": "Scanne alle Bibliotheken für hinzugefügte Datein und erneuere Metadaten.", diff --git a/Emby.Server.Implementations/Localization/Core/he.json b/Emby.Server.Implementations/Localization/Core/he.json index 606f464503..48056b0bb8 100644 --- a/Emby.Server.Implementations/Localization/Core/he.json +++ b/Emby.Server.Implementations/Localization/Core/he.json @@ -1,41 +1,24 @@ { - "Albums": "אלבומים", "AppDeviceValues": "יישום: {0}, מכשיר: {1}", - "Application": "יישום", "Artists": "אומנים", "AuthenticationSucceededWithUserName": "{0} אומת בהצלחה", "Books": "ספרים", - "CameraImageUploadedFrom": "תמונת מצלמה חדשה הועלתה מתוך {0}", - "Channels": "ערוצים", "ChapterNameValue": "פרק {0}", "Collections": "אוספים", - "DeviceOfflineWithName": "{0} התנתק", - "DeviceOnlineWithName": "{0} מחובר", "FailedLoginAttemptWithUserName": "ניסיון כניסה שגוי דרך {0}", "Favorites": "מועדפים", "Folders": "תיקיות", "Genres": "ז׳אנרים", - "HeaderAlbumArtists": "אמני האלבום", "HeaderContinueWatching": "המשך צפייה", - "HeaderFavoriteAlbums": "אלבומים מועדפים", - "HeaderFavoriteArtists": "אמנים מועדפים", "HeaderFavoriteEpisodes": "פרקים מועדפים", "HeaderFavoriteShows": "תוכניות מועדפות", - "HeaderFavoriteSongs": "שירים מועדפים", "HeaderLiveTV": "שידורים חיים", "HeaderNextUp": "הבא בתור", - "HeaderRecordingGroups": "קבוצות הקלטה", "HomeVideos": "סרטונים בייתים", "Inherit": "הורש", - "ItemAddedWithName": "{0} נוסף לספרייה", - "ItemRemovedWithName": "{0} נמחק מהספרייה", "LabelIpAddressValue": "Ip כתובת: {0}", "LabelRunningTimeValue": "משך צפייה: {0}", "Latest": "אחרון", - "MessageApplicationUpdated": "שרת Jellyfin עודכן", - "MessageApplicationUpdatedTo": "שרת Jellyfin עודכן לגרסה {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "סעיף הגדרת השרת {0} עודכן", - "MessageServerConfigurationUpdated": "תצורת השרת עודכנה", "MixedContent": "תוכן מעורב", "Movies": "סרטים", "Music": "מוזיקה", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "ניגון וידאו החל", "NotificationOptionVideoPlaybackStopped": "ניגון וידאו הופסק", "Photos": "צילומים", - "Playlists": "רשימות נגינה", - "Plugin": "תוסף", "PluginInstalledWithName": "{0} הותקן", "PluginUninstalledWithName": "{0} הוסר", "PluginUpdatedWithName": "{0} עודכן", - "ProviderValue": "ספק: {0}", "ScheduledTaskFailedWithName": "{0} נכשל", - "ScheduledTaskStartedWithName": "{0} החל", - "ServerNameNeedsToBeRestarted": "{0} דורש הפעלה מחדש", "Shows": "סדרות", - "Songs": "שירים", "StartupEmbyServerIsLoading": "שרת Jellyfin בתהליך טעינה. נא לנסות שוב בקרוב.", "SubtitleDownloadFailureFromForItem": "הורדת כתוביות מ־{0} עבור {1} נכשלה", - "Sync": "סנכרון", - "System": "מערכת", "TvShows": "סדרות טלוויזיה", - "User": "משתמש", "UserCreatedWithName": "המשתמש {0} נוצר", "UserDeletedWithName": "המשתמש {0} הוסר", "UserDownloadingItemWithValues": "{0} מוריד את {1}", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "{0} התנתק מ־{1}", "UserOnlineFromDevice": "{0} מחובר מ־{1}", "UserPasswordChangedWithName": "הסיסמה שונתה עבור המשתמש {0}", - "UserPolicyUpdatedWithName": "מדיניות המשתמש {0} עודכנה", "UserStartedPlayingItemWithValues": "{0} מנגן את {1} על {2}", "UserStoppedPlayingItemWithValues": "{0} סיים לנגן את {1} על {2}", - "ValueHasBeenAddedToLibrary": "{0} התווסף לספריית המדיה שלך", - "ValueSpecialEpisodeName": "מיוחד- {0}", "VersionNumber": "גרסה {0}", "TaskRefreshLibrary": "סרוק ספריית מדיה", "TaskRefreshChapterImages": "חלץ תמונות פרקים", @@ -135,5 +106,7 @@ "TaskExtractMediaSegmentsDescription": "מחלץ חלקי מדיה מתוספים המאפשרים זאת.", "TaskMoveTrickplayImagesDescription": "הזזת קבצי Trickplay קיימים בהתאם להגדרות הספרייה.", "CleanupUserDataTaskDescription": "ניקוי כל המידע של המשתמש (מצב צפייה, מועדפים וכו) ממדיה שאינה קיימת מעל 90 יום.", - "CleanupUserDataTask": "משימת ניקוי מידע משתמש" + "CleanupUserDataTask": "משימת ניקוי מידע משתמש", + "LyricDownloadFailureFromForItem": "הורדת המילים מ-{0} עבור {1} נכשלה", + "Original": "מקור" } diff --git a/Emby.Server.Implementations/Localization/Core/he_IL.json b/Emby.Server.Implementations/Localization/Core/he_IL.json index e8812c8a1d..b551608fd0 100644 --- a/Emby.Server.Implementations/Localization/Core/he_IL.json +++ b/Emby.Server.Implementations/Localization/Core/he_IL.json @@ -1,27 +1,112 @@ { "Books": "ספרים", "NameSeasonNumber": "עונה {0}", - "Channels": "ערוצים", "Movies": "סרטים", "Music": "מוזיקה", "Collections": "אוספים", - "Albums": "אלבומים", - "Application": "אפליקציה", "Artists": "אמנים", "ChapterNameValue": "פרק {0}", "External": "חיצונית", "Favorites": "מועדפים", "Folders": "תיקיות", "Genres": "ז'אנרים", - "HeaderAlbumArtists": "אמני אלבומים", "HeaderContinueWatching": "להמשיך לצפות", - "HeaderFavoriteAlbums": "אלבומים אהובים", - "HeaderFavoriteArtists": "אמנים אהובים", "HeaderFavoriteEpisodes": "פרקים אהובים", "HeaderFavoriteShows": "תוכניות אהובות", - "HeaderFavoriteSongs": "שירים אהובים", "HeaderLiveTV": "טלוויזיה בשידור חי", "HeaderNextUp": "הבא", "HearingImpaired": "ללקויי שמיעה", - "HomeVideos": "סרטונים ביתיים" + "HomeVideos": "סרטונים ביתיים", + "AppDeviceValues": "אפליקציה: {0}, מכשיר: {1}", + "AuthenticationSucceededWithUserName": "{0} אומת בהצלחה", + "Default": "בררת מחדל", + "FailedLoginAttemptWithUserName": "התחברות נכשלה מ {0}", + "Forced": "בכוח", + "Inherit": "ירש", + "LabelIpAddressValue": "כתובת IP: {0}", + "LabelRunningTimeValue": "זמן ריצה: {0}", + "Latest": "הכי חדש", + "LyricDownloadFailureFromForItem": "מילות שיר נכשלו לרדת מ{0} בשביל {1}", + "MixedContent": "תוכן מעורב", + "MusicVideos": "סרטוני מוזיקה", + "NameInstallFailed": "{0} התכנות כושלות", + "NameSeasonUnknown": "עונה לא ידוע", + "NewVersionIsAvailable": "גרסה חדשה של שרת Jellyfin זמינה להורדה.", + "NotificationOptionApplicationUpdateAvailable": "גרסת אפליקציה חדשה זמינה להורדה", + "NotificationOptionApplicationUpdateInstalled": "עדכון אפליקציה הותקן", + "NotificationOptionAudioPlayback": "החלה השמעת אודיו", + "NotificationOptionAudioPlaybackStopped": "ניגון השמע הופסק", + "NotificationOptionCameraImageUploaded": "תמונת מצלמה עודכן", + "NotificationOptionInstallationFailed": "התקנה נכשלה", + "NotificationOptionNewLibraryContent": "תוכן חדש נוסף", + "NotificationOptionPluginError": "תוסף נכשל", + "NotificationOptionPluginInstalled": "תוסף הותקן", + "NotificationOptionPluginUninstalled": "תוסף נמחק", + "NotificationOptionPluginUpdateInstalled": "עידכון לתוסף הותקן", + "NotificationOptionServerRestartRequired": "נדרש התחול מחדש לשרת", + "NotificationOptionTaskFailed": "כשל במשימה מתוכננת", + "NotificationOptionUserLockedOut": "המשתמש ננעל", + "NotificationOptionVideoPlayback": "החלה הפעלת וידאו", + "NotificationOptionVideoPlaybackStopped": "הפעלת הסרטון הופסקה", + "Original": "מקורי", + "Photos": "תמונות", + "PluginInstalledWithName": "{0} הותקן", + "PluginUninstalledWithName": "{0} נמחק", + "PluginUpdatedWithName": "{0} עודכן", + "ScheduledTaskFailedWithName": "{0} נכשל", + "Shows": "סדרות", + "StartupEmbyServerIsLoading": "שרת Jellyfin נטען. אנא נסה שוב בקרוב.", + "SubtitleDownloadFailureFromForItem": "הורדת הכתוביות מ-{0} עבור {1} נכשלה", + "TvShows": "תוכניות טלויזיה", + "Undefined": "לא מוגדר", + "UserCreatedWithName": "המשתמש {0} נוצר", + "UserDeletedWithName": "המשתמש {0} נמחק", + "UserDownloadingItemWithValues": "{0} מוריד את {1}", + "UserLockedOutWithName": "המשתמש {0} ננעל בחוץ", + "UserOfflineFromDevice": "{0} התנתק מ-{1}", + "UserOnlineFromDevice": "{0} מחובר מ-{1}", + "UserPasswordChangedWithName": "הסיסמה שונתה עבור המשתמש {0}", + "UserStartedPlayingItemWithValues": "{0} מנגן ב-{1} ב-{2}", + "UserStoppedPlayingItemWithValues": "{0} סיים לנגן את {1} ב-{2}", + "VersionNumber": "גרסה {0}", + "TasksMaintenanceCategory": "תחזוקה", + "TasksLibraryCategory": "ספריה", + "TasksApplicationCategory": "אפליקציה", + "TasksChannelsCategory": "ערוצי אינטרנט", + "TaskCleanActivityLog": "נקה יומן פעילות", + "TaskCleanActivityLogDescription": "מוחק רשומות יומן פעילות ישנות יותר מהגיל שהוגדר.", + "TaskCleanCache": "נקה ספריית מטמון", + "TaskCleanCacheDescription": "מוחק קבצי מטמון שאינם נחוצים עוד על ידי המערכת.", + "TaskRefreshChapterImages": "חלץ תמונות פרק", + "TaskRefreshChapterImagesDescription": "יוצר תמונות ממוזערות עבור סרטונים שיש להם פרקים.", + "TaskAudioNormalization": "נורמליזציה של שמע", + "TaskAudioNormalizationDescription": "סורק קבצים לאיתור נתוני נרמול שמע.", + "TaskRefreshLibrary": "סרוק ספריית מדיה", + "TaskRefreshLibraryDescription": "סורק את ספריית המדיה שלך לאיתור קבצים חדשים ומרענן מטא-דאטה.", + "TaskCleanLogs": "נקה ספריית יומן", + "TaskCleanLogsDescription": "מוחק קבצי יומן שגילם עולה על {0} ימים.", + "TaskRefreshPeople": "רענן אנשים", + "TaskRefreshPeopleDescription": "מעדכן מטא-דאטה עבור שחקנים ובמאים בספריית המדיה שלך.", + "TaskRefreshTrickplayImages": "צור תמונות Trickplay", + "TaskRefreshTrickplayImagesDescription": "יוצר תצוגות מקדימות של trickplay עבור סרטונים בספריות מופעלות.", + "TaskUpdatePlugins": "עדכן פלאגינים", + "TaskUpdatePluginsDescription": "מוריד ומתקין עדכונים עבור תוספים שתצורתם נקבעה לעדכון אוטומטי.", + "TaskCleanTranscode": "נקה ספריית קידוד", + "TaskCleanTranscodeDescription": "תמחוק את קבצי הקידוד בני יותר מיום.", + "TaskRefreshChannels": "רענן ערוצים", + "TaskRefreshChannelsDescription": "מרענן את פרטי ערוץ האינטרנט.", + "TaskDownloadMissingLyrics": "הורד מילות שיר חסרות", + "TaskDownloadMissingLyricsDescription": "הורדות מילים לשירים", + "TaskDownloadMissingSubtitles": "הורד כתוביות חסרות", + "TaskDownloadMissingSubtitlesDescription": "מחפש באינטרנט אחר כתוביות חסרות בהתבסס על תצורת מטא-דאטה.", + "TaskOptimizeDatabase": "בצע אופטימיזציה של מסד הנתונים", + "TaskOptimizeDatabaseDescription": "דוחס את מסד הנתונים וקיצוץ שטח פנוי. הפעלת משימה זו לאחר סריקת הספרייה או ביצוע שינויים אחרים שמשמעותם שינויים בבסיס הנתונים עשויה לשפר את הביצועים.", + "TaskKeyframeExtractor": "מחלץ פריים מרכזי", + "TaskKeyframeExtractorDescription": "מחלץ פריימים מרכזיים מקבצי וידאו כדי ליצור רשימות השמעה HLS מדויקות יותר. משימה זו עשויה להימשך זמן רב.", + "TaskExtractMediaSegments": "סריקת מקטעי מדיה", + "TaskExtractMediaSegmentsDescription": "מחלץ או משיג קטעי מדיה מתוספים התומכים ב-MediaSegment.", + "TaskMoveTrickplayImages": "העברת מיקום תמונת Trickplay", + "TaskMoveTrickplayImagesDescription": "מעביר קבצי trickplay קיימים בהתאם להגדרות הספרייה.", + "CleanupUserDataTask": "משימת ניקוי נתוני משתמש", + "CleanupUserDataTaskDescription": "מנקה את כל נתוני המשתמש (מצב צפייה, סטטוס מועדף וכו') ממדיה שכבר לא הייתה קיימת במשך 90 יום לפחות." } diff --git a/Emby.Server.Implementations/Localization/Core/hi.json b/Emby.Server.Implementations/Localization/Core/hi.json index 9968c56b21..e98a5fbac1 100644 --- a/Emby.Server.Implementations/Localization/Core/hi.json +++ b/Emby.Server.Implementations/Localization/Core/hi.json @@ -1,31 +1,20 @@ { - "Albums": "एल्बम", - "HeaderRecordingGroups": "रिकॉर्डिंग समूह", "HeaderNextUp": "इसके बाद", "HeaderLiveTV": "लाइव टीवी", - "HeaderFavoriteSongs": "पसंदीदा गीत", "HeaderFavoriteShows": "पसंदीदा शो", "HeaderFavoriteEpisodes": "पसंदीदा प्रकरण", - "HeaderFavoriteArtists": "पसंदीदा कलाकार", - "HeaderFavoriteAlbums": "पसंदीदा एलबम्स", "HeaderContinueWatching": "देखना जारी रखें", - "HeaderAlbumArtists": "एल्बम कलाकार", "Genres": "शैलियां", "Forced": "बलपूर्वक", "Folders": "फ़ोल्डर", "Favorites": "पसंदीदा", "FailedLoginAttemptWithUserName": "{0} से संप्रवेश असफल हुआ", - "DeviceOnlineWithName": "{0} कनेक्ट हो गया है", - "DeviceOfflineWithName": "{0} डिस्कनेक्ट हो गया है", "Default": "प्राथमिक", "Collections": "संग्रह", "ChapterNameValue": "अध्याय {0}", - "Channels": "चैनल", - "CameraImageUploadedFrom": "{0} से एक नया कैमरा छवि अपलोड की गई है", "Books": "पुस्तकें", "AuthenticationSucceededWithUserName": "{0} सफलतापूर्वक प्रमाणित किया गया", "Artists": "कलाकार", - "Application": "एप्लिकेशन", "AppDeviceValues": "एप: {0}, उपकरण: {1}", "NotificationOptionPluginUninstalled": "प्लगइन अनइंस्टाल हो गया", "NotificationOptionPluginInstalled": "प्लगइन इनस्टॉल हो गया", @@ -44,13 +33,8 @@ "Music": "संगीत", "Movies": "फ़िल्म", "MixedContent": "मिला-जुला कंटेंट", - "MessageServerConfigurationUpdated": "सर्वर कॉन्फ़िगरेशन अपडेट हो गया है", - "MessageNamedServerConfigurationUpdatedWithValue": "सर्वर कॉन्फ़िगरेशन भाग {0} अपडेट हो गया है", - "MessageApplicationUpdatedTo": "जैलीफिन सर्वर {0} में अपडेट हो गया है", - "MessageApplicationUpdated": "जैलीफिन सर्वर अपडेट हो गया है", "Latest": "सबसे नया", "LabelIpAddressValue": "आई पी एड्रेस: {0}", - "ItemRemovedWithName": "{0} लाइब्रेरी में से निकाल दिया है", "HomeVideos": "होम चलचित्र", "NotificationOptionVideoPlayback": "वीडियो प्लेबैक शुरू हुआ", "NotificationOptionUserLockedOut": "उपयोगकर्ता लॉक हो गया", @@ -59,22 +43,16 @@ "NotificationOptionPluginUpdateInstalled": "प्लगइन अद्यतन स्थापित", "NotificationOptionNewLibraryContent": "नई सामग्री जोड़ी गई", "LabelRunningTimeValue": "चलने का समय: {0}", - "ItemAddedWithName": "{0} को लाइब्रेरी में जोड़ा गया", "Inherit": "इनहेरिट", "NotificationOptionVideoPlaybackStopped": "चलचित्र रुका हुआ", "PluginUninstalledWithName": "{0} अनइंस्टॉल हुए", "PluginInstalledWithName": "{0} इंस्टॉल हुए", - "Plugin": "प्लग-इन", - "Playlists": "प्लेलिस्ट", "Photos": "तस्वीरें", "External": "बाहरी", "PluginUpdatedWithName": "{0} अपडेट हुए", - "ScheduledTaskStartedWithName": "{0} शुरू हुए", - "Songs": "गाने", "UserStartedPlayingItemWithValues": "{0} {2} पर {1} खेल रहे हैं", "UserStoppedPlayingItemWithValues": "{0} ने {2} पर {1} खेलना खत्म किया", "StartupEmbyServerIsLoading": "जेलीफ़िन सर्वर लोड हो रहा है। कृपया शीघ्र ही पुन: प्रयास करें।", - "ServerNameNeedsToBeRestarted": "{0} रीस्टार्ट करने की आवश्यकता है", "UserCreatedWithName": "उपयोगकर्ता {0} बनाया गया", "UserDownloadingItemWithValues": "{0} डाउनलोड हो रहा है", "UserOfflineFromDevice": "{0} {1} से डिस्कनेक्ट हो गया है", @@ -83,20 +61,13 @@ "Shows": "शो", "UserPasswordChangedWithName": "उपयोगकर्ता {0} के लिए पासवर्ड बदल दिया गया है", "UserDeletedWithName": "उपयोगकर्ता {0} हटा दिया गया", - "UserPolicyUpdatedWithName": "{0} के लिए उपयोगकर्ता नीति अपडेट कर दी गई है", - "User": "उपयोगकर्ता", "SubtitleDownloadFailureFromForItem": "{1} के लिए {0} से उपशीर्षक डाउनलोड करने में विफल", - "ProviderValue": "प्रदाता: {0}", "ScheduledTaskFailedWithName": "{0}असफल", "UserLockedOutWithName": "उपयोगकर्ता {0} को लॉक आउट कर दिया गया है", - "System": "प्रणाली", "TvShows": "टीवी शो", "HearingImpaired": "मूक बधिर", - "ValueSpecialEpisodeName": "विशेष - {0}", "TasksMaintenanceCategory": "रखरखाव", - "Sync": "समाकलयति", "VersionNumber": "{0} पाठान्तर", - "ValueHasBeenAddedToLibrary": "{0} आपके माध्यम ग्रन्थालय में उपजात हो गया हैं", "TasksLibraryCategory": "संग्रहालय", "TaskOptimizeDatabase": "जानकारी प्रवृद्धि", "TaskDownloadMissingSubtitles": "लापता अनुलेख डाउनलोड करें", diff --git a/Emby.Server.Implementations/Localization/Core/hr.json b/Emby.Server.Implementations/Localization/Core/hr.json index 5800764587..8794339fb1 100644 --- a/Emby.Server.Implementations/Localization/Core/hr.json +++ b/Emby.Server.Implementations/Localization/Core/hr.json @@ -1,41 +1,24 @@ { - "Albums": "Albumi", "AppDeviceValues": "Aplikacija: {0}, Uređaj: {1}", - "Application": "Aplikacija", "Artists": "Izvođači", "AuthenticationSucceededWithUserName": "{0} uspješno ovjerena", "Books": "Knjige", - "CameraImageUploadedFrom": "Nova fotografija sa kamere je učitana iz {0}", - "Channels": "Kanali", "ChapterNameValue": "Poglavlje {0}", "Collections": "Zbirke", - "DeviceOfflineWithName": "{0} je prekinuo vezu", - "DeviceOnlineWithName": "{0} je povezan", "FailedLoginAttemptWithUserName": "Neuspješan pokušaj prijave od {0}", "Favorites": "Favoriti", "Folders": "Mape", "Genres": "Žanrovi", - "HeaderAlbumArtists": "Izvođači albuma", "HeaderContinueWatching": "Nastavi gledati", - "HeaderFavoriteAlbums": "Omiljeni albumi", - "HeaderFavoriteArtists": "Omiljeni izvođači", "HeaderFavoriteEpisodes": "Omiljene epizode", "HeaderFavoriteShows": "Omiljene serije", - "HeaderFavoriteSongs": "Omiljene pjesme", "HeaderLiveTV": "TV uživo", "HeaderNextUp": "Sljedeće na redu", - "HeaderRecordingGroups": "Grupa snimka", "HomeVideos": "Kućni video", "Inherit": "Naslijedi", - "ItemAddedWithName": "{0} je dodano u biblioteku", - "ItemRemovedWithName": "{0} je uklonjeno iz biblioteke", "LabelIpAddressValue": "IP adresa: {0}", "LabelRunningTimeValue": "Vrijeme rada: {0}", "Latest": "Najnovije", - "MessageApplicationUpdated": "Jellyfin server je ažuriran", - "MessageApplicationUpdatedTo": "Jellyfin server je ažuriran na {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "Dio konfiguracije servera {0} je ažuriran", - "MessageServerConfigurationUpdated": "Konfiguracija servera je ažurirana", "MixedContent": "Miješani sadržaj", "Movies": "Filmovi", "Music": "Glazba", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "Reprodukcija videa započela", "NotificationOptionVideoPlaybackStopped": "Reprodukcija videa zaustavljena", "Photos": "Fotografije", - "Playlists": "Popisi za reprodukciju", - "Plugin": "Dodatak", "PluginInstalledWithName": "{0} je instalirano", "PluginUninstalledWithName": "{0} je deinstalirano", "PluginUpdatedWithName": "{0} je ažurirano", - "ProviderValue": "Pružatelj: {0}", "ScheduledTaskFailedWithName": "{0} neuspjelo", - "ScheduledTaskStartedWithName": "{0} pokrenuto", - "ServerNameNeedsToBeRestarted": "{0} treba ponovno pokrenuti", "Shows": "Emisije", - "Songs": "Pjesme", "StartupEmbyServerIsLoading": "Jellyfin server se učitava. Pokušajte ponovo uskoro.", "SubtitleDownloadFailureFromForItem": "Titlovi nisu uspješno preuzeti od {0} za {1}", - "Sync": "Sinkronizacija", - "System": "Sustav", "TvShows": "TV emisije", - "User": "Korisnik", "UserCreatedWithName": "Korisnik {0} je kreiran", "UserDeletedWithName": "Korisnik {0} je obrisan", "UserDownloadingItemWithValues": "{0} preuzima {1}", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "{0} prekinuo vezu od {1}", "UserOnlineFromDevice": "{0} povezan od {1}", "UserPasswordChangedWithName": "Lozinka je promijenjena za korisnika {0}", - "UserPolicyUpdatedWithName": "Pravila za korisnika ažurirana su za {0}", "UserStartedPlayingItemWithValues": "{0} je pokrenuo reprodukciju {1} na {2}", "UserStoppedPlayingItemWithValues": "{0} je završio reprodukciju {1} na {2}", - "ValueHasBeenAddedToLibrary": "{0} je dodano u biblioteku medija", - "ValueSpecialEpisodeName": "Posebno – {0}", "VersionNumber": "Verzija {0}", "TaskRefreshLibraryDescription": "Skenira biblioteku medija radi novih datoteka i osvježava metapodatke.", "TaskRefreshLibrary": "Skeniraj biblioteku medija", diff --git a/Emby.Server.Implementations/Localization/Core/ht.json b/Emby.Server.Implementations/Localization/Core/ht.json index 183c422a85..da90a92339 100644 --- a/Emby.Server.Implementations/Localization/Core/ht.json +++ b/Emby.Server.Implementations/Localization/Core/ht.json @@ -1,33 +1,22 @@ { "Books": "Liv", "TasksLibraryCategory": "Libreri", - "Albums": "Albòm yo", "Artists": "Atis yo", - "Application": "Aplikasyon", - "Channels": "Kanal yo", "ChapterNameValue": "Chapit {0}", "Default": "Defo", - "DeviceOnlineWithName": "{0} konekte", - "DeviceOfflineWithName": "{0} dekonekte", "External": "Extèn", "Collections": "Koleksyon yo", "Favorites": "Pi Renmen", "Folders": "Dosye", "Genres": "Jan yo", "Forced": "Fòse", - "HeaderAlbumArtists": "Albòm Atis", "HeaderContinueWatching": "Kontinye Kade", - "HeaderFavoriteAlbums": "Albòm Pi Renmen", - "HeaderFavoriteArtists": "Atis Pi Renmen", "HeaderFavoriteEpisodes": "Epizòd Pi Renmen", "HeaderFavoriteShows": "Emisyon Pi Renmen", - "HeaderFavoriteSongs": "Mizik Pi Renmen", "HeaderLiveTV": "Televizyon an Direk", "HeaderNextUp": "Pwochen an", "HomeVideos": "Videyo Lakay", "Latest": "Pi Resan", - "MessageApplicationUpdated": "Sèvè Jellyfin met a jou", - "MessageApplicationUpdatedTo": "Sèvè Jellyfin met a jou sou {0}", "Movies": "Fim", "MixedContent": "Kontni Melanje", "Music": "Mizik", @@ -42,12 +31,8 @@ "PluginUninstalledWithName": "{0} te dezenstale", "PluginUpdatedWithName": "{0} te mi a jou", "ScheduledTaskFailedWithName": "{0} echwe", - "ScheduledTaskStartedWithName": "{0} komanse", - "Songs": "Mizik yo", "Shows": "Emisyon yo", - "System": "Sistèm", "TvShows": "Emisyon Tele", - "User": "Itilizatè", "UserCreatedWithName": "Itilizatè {0} kreye", "UserDeletedWithName": "Itilizatè {0} a efase", "UserDownloadingItemWithValues": "{0} ap telechaje {1}", @@ -55,11 +40,10 @@ "UserStartedPlayingItemWithValues": "{0} ap jwe {1} sou {2}", "UserStoppedPlayingItemWithValues": "{0} fin jwe {1} sou {2}", "UserPasswordChangedWithName": "Modpas la chanje pou Itilizatè {0}", - "ValueSpecialEpisodeName": "Spesyal - {0}", "VersionNumber": "Vesyon {0}", "TasksApplicationCategory": "Aplikasyon", "TasksMaintenanceCategory": "Antretyen", "AppDeviceValues": "Aplikasyon: {0}, Aparèy: {1}", "AuthenticationSucceededWithUserName": "{0} otantifye avèk siksè", - "CameraImageUploadedFrom": "Une nouvelle image de la caméra a été téléchargée depuis {0}" + "Original": "Original" } diff --git a/Emby.Server.Implementations/Localization/Core/hu.json b/Emby.Server.Implementations/Localization/Core/hu.json index 31df91693c..1995d7a4cf 100644 --- a/Emby.Server.Implementations/Localization/Core/hu.json +++ b/Emby.Server.Implementations/Localization/Core/hu.json @@ -1,41 +1,24 @@ { - "Albums": "Albumok", - "AppDeviceValues": "Program: {0}, Eszköz: {1}", - "Application": "Alkalmazás", + "AppDeviceValues": "alkalmazás: {0}, eszköz: {1}", "Artists": "Előadók", "AuthenticationSucceededWithUserName": "{0} sikeresen hitelesítve", "Books": "Könyvek", - "CameraImageUploadedFrom": "Új kamerakép lett feltöltve innen: {0}", - "Channels": "Csatornák", "ChapterNameValue": "{0}. jelenet", "Collections": "Gyűjtemények", - "DeviceOfflineWithName": "{0} kijelentkezett", - "DeviceOnlineWithName": "{0} belépett", "FailedLoginAttemptWithUserName": "Sikertelen bejelentkezési kísérlet innen: {0}", "Favorites": "Kedvencek", "Folders": "Mappák", "Genres": "Műfajok", - "HeaderAlbumArtists": "Albumelőadók", "HeaderContinueWatching": "Megtekintés folytatása", - "HeaderFavoriteAlbums": "Kedvenc albumok", - "HeaderFavoriteArtists": "Kedvenc előadók", "HeaderFavoriteEpisodes": "Kedvenc epizódok", "HeaderFavoriteShows": "Kedvenc sorozatok", - "HeaderFavoriteSongs": "Kedvenc számok", "HeaderLiveTV": "Élő TV", "HeaderNextUp": "Következik", - "HeaderRecordingGroups": "Felvételi csoportok", "HomeVideos": "Otthoni videók", "Inherit": "Öröklés", - "ItemAddedWithName": "{0} hozzáadva a médiatárhoz", - "ItemRemovedWithName": "{0} eltávolítva a médiatárból", "LabelIpAddressValue": "IP-cím: {0}", "LabelRunningTimeValue": "Lejátszási idő: {0}", "Latest": "Legújabb", - "MessageApplicationUpdated": "A Jellyfin kiszolgáló frissítve lett", - "MessageApplicationUpdatedTo": "A Jellyfin kiszolgáló frissítve lett a következőre: {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "A kiszolgálókonfigurációs rész frissítve lett: {0}", - "MessageServerConfigurationUpdated": "A kiszolgálókonfiguráció frissítve lett", "MixedContent": "Vegyes tartalom", "Movies": "Filmek", "Music": "Zenék", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "Videólejátszás elkezdve", "NotificationOptionVideoPlaybackStopped": "Videólejátszás leállítva", "Photos": "Fényképek", - "Playlists": "Lejátszási listák", - "Plugin": "Bővítmény", "PluginInstalledWithName": "{0} telepítve", "PluginUninstalledWithName": "{0} eltávolítva", "PluginUpdatedWithName": "{0} frissítve", - "ProviderValue": "Szolgáltató: {0}", "ScheduledTaskFailedWithName": "{0} sikertelen", - "ScheduledTaskStartedWithName": "{0} elkezdve", - "ServerNameNeedsToBeRestarted": "A(z) {0} újraindítása szükséges", "Shows": "Sorozatok", - "Songs": "Számok", "StartupEmbyServerIsLoading": "A Jellyfin kiszolgáló betöltődik. Próbálja újra hamarosan.", "SubtitleDownloadFailureFromForItem": "Nem sikerült a felirat letöltése innen: {0}, ehhez: {1}", - "Sync": "Szinkronizálás", - "System": "Rendszer", "TvShows": "TV műsorok", - "User": "Felhasználó", "UserCreatedWithName": "{0} felhasználó létrehozva", "UserDeletedWithName": "{0} felhasználó törölve", "UserDownloadingItemWithValues": "{0} letölti: {1}", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "{0} kijelentkezett innen: {1}", "UserOnlineFromDevice": "{0} online innen: {1}", "UserPasswordChangedWithName": "{0} jelszava megváltozott", - "UserPolicyUpdatedWithName": "{0} felhasználói házirendje frissült", "UserStartedPlayingItemWithValues": "{0} elkezdte lejátszani a következőt: {1}, itt: {2}", "UserStoppedPlayingItemWithValues": "{0} befejezte a következő lejátszását: {1}, itt: {2}", - "ValueHasBeenAddedToLibrary": "{0} hozzáadva a médiatárhoz", - "ValueSpecialEpisodeName": "Különkiadás – {0}", "VersionNumber": "Verzió: {0}", "TaskCleanTranscode": "Átkódolási könyvtár ürítése", "TaskUpdatePluginsDescription": "Letölti és telepíti a frissítéseket azokhoz a bővítményekhez, amelyeknél az automatikus frissítés engedélyezve van.", @@ -136,5 +107,6 @@ "TaskExtractMediaSegmentsDescription": "Kinyeri vagy megszerzi a médiaszegmenseket a MediaSegment támogatással rendelkező bővítményekből.", "CleanupUserDataTaskDescription": "Legalább 90 napja nem elérhető médiákhoz kapcsolódó összes felhasználói adat (pl. megtekintési állapot, kedvencek) törlése.", "CleanupUserDataTask": "Felhasználói adatok tisztítása feladat", - "Original": "Eredeti" + "Original": "Eredeti", + "LyricDownloadFailureFromForItem": "Dalszöveg letöltése {0}-tól {1}-hez sikertelen" } diff --git a/Emby.Server.Implementations/Localization/Core/hy.json b/Emby.Server.Implementations/Localization/Core/hy.json index 563f842923..b79b540bf4 100644 --- a/Emby.Server.Implementations/Localization/Core/hy.json +++ b/Emby.Server.Implementations/Localization/Core/hy.json @@ -2,38 +2,27 @@ "TasksLibraryCategory": "Գրադարան", "TasksApplicationCategory": "Հավելված", "TaskCleanActivityLog": "Մաքրել ակտիվության մատյանը", - "Application": "Հավելված", "AuthenticationSucceededWithUserName": "{0} հաջողությամբ վավերականացվել են", "Books": "Գրքեր", - "CameraImageUploadedFrom": "Նոր լուսանկար է վերբեռնվել {0}-ի կողմից", - "Channels": "Ալիքներ", - "DeviceOfflineWithName": "{0}ը անջատվեց", "External": "Արտաքին", "FailedLoginAttemptWithUserName": "Ձախողված մուտքի փործ {0}-ի կողմից", "Folders": "Պանակներ", "HeaderContinueWatching": "Շարունակել դիտումը", "Inherit": "Ժառանգել", - "ItemAddedWithName": "{0}ը ավացված է գրադարանի մեջ", - "ItemRemovedWithName": "{0}ը հեռացված է գրադարանից", "LabelIpAddressValue": "IP հասցե` {0}", "Movies": "Ֆիլմեր", "Music": "Երաժշտություն", "NameSeasonNumber": "Սեզոն {0}", "Photos": "Լուսանկարներ", "PluginInstalledWithName": "{0}ն տեղադրված է", - "Songs": "Երգեր", - "System": "Համակարգ", "TvShows": "Հեռուստասերիալներ", - "User": "Օգտատեր", "VersionNumber": "Տարբերակ {0}", "TasksMaintenanceCategory": "Սպասարկում", "TasksChannelsCategory": "Ինտերնետային ալիքներ", "TaskRefreshPeople": "Թարմացնել մարդկանց", "TaskRefreshChannels": "Թարմացնել ալիքները", "TaskDownloadMissingSubtitles": "Ներբեռնել պակասող ենթագրերը", - "Albums": "Ալբոմներ", "AppDeviceValues": "Հավելված` {0}, Սարք `{1}", "ChapterNameValue": "Գլուխ {0}", - "Collections": "Հավաքածուներ", - "DeviceOnlineWithName": "{0}-ն միացված է" + "Collections": "Հավաքածուներ" } diff --git a/Emby.Server.Implementations/Localization/Core/id.json b/Emby.Server.Implementations/Localization/Core/id.json index fb228baf40..3502ec39ad 100644 --- a/Emby.Server.Implementations/Localization/Core/id.json +++ b/Emby.Server.Implementations/Localization/Core/id.json @@ -1,48 +1,31 @@ { - "Albums": "Album", "AuthenticationSucceededWithUserName": "{0} berhasil diautentikasi", "AppDeviceValues": "Aplikasi : {0}, Perangkat : {1}", "LabelRunningTimeValue": "Waktu berjalan: {0}", - "MessageApplicationUpdatedTo": "Jellyfin Server sudah diperbarui ke {0}", - "MessageApplicationUpdated": "Jellyfin Server sudah diperbarui", "Latest": "Terbaru", "LabelIpAddressValue": "Alamat IP: {0}", - "ItemRemovedWithName": "{0} sudah dihapus dari pustaka", - "ItemAddedWithName": "{0} telah dimasukkan ke dalam pustaka", "Inherit": "Warisi", "HomeVideos": "Video Rumahan", - "HeaderRecordingGroups": "Grup Rekaman", "HeaderNextUp": "Selanjutnya", "HeaderLiveTV": "Siaran langsung", - "HeaderFavoriteSongs": "Lagu Favorit", "HeaderFavoriteShows": "Tayangan Favorit", "HeaderFavoriteEpisodes": "Episode Favorit", - "HeaderFavoriteArtists": "Artis Favorit", - "HeaderFavoriteAlbums": "Album Favorit", "HeaderContinueWatching": "Lanjut Menonton", - "HeaderAlbumArtists": "Album Artis", "Genres": "Aliran", "Folders": "Folder", "Favorites": "Favorit", "Collections": "Koleksi", "Books": "Buku", "Artists": "Artis", - "Application": "Aplikasi", "ChapterNameValue": "Bagian {0}", - "Channels": "Saluran", "TvShows": "Seri TV", "SubtitleDownloadFailureFromForItem": "Subtitel gagal diunduh dari {0} untuk {1}", "StartupEmbyServerIsLoading": "Server Jellyfin sedang dimuat. Silakan coba lagi nanti.", - "Songs": "Lagu", - "Playlists": "Daftar putar", "NotificationOptionPluginUninstalled": "Plugin dihapus", "MusicVideos": "Video Musik", "VersionNumber": "Versi {0}", - "ValueSpecialEpisodeName": "Spesial - {0}", - "ValueHasBeenAddedToLibrary": "{0} telah ditambahkan ke pustaka media Anda", "UserStoppedPlayingItemWithValues": "{0} telah selesai memutar {1} pada {2}", "UserStartedPlayingItemWithValues": "{0} sedang memutar {1} pada {2}", - "UserPolicyUpdatedWithName": "Kebijakan pengguna telah diperbarui untuk {0}", "UserPasswordChangedWithName": "Kata sandi telah diubah untuk pengguna {0}", "UserOnlineFromDevice": "{0} sedang daring dari {1}", "UserOfflineFromDevice": "{0} telah terputus dari {1}", @@ -50,17 +33,10 @@ "UserDownloadingItemWithValues": "{0} sedang mengunduh {1}", "UserDeletedWithName": "Pengguna {0} telah dihapus", "UserCreatedWithName": "Pengguna {0} telah dibuat", - "User": "Pengguna", - "System": "Sistem", - "Sync": "Sinkron", "Shows": "Tayangan", - "ServerNameNeedsToBeRestarted": "{0} perlu dimuat ulang", - "ScheduledTaskStartedWithName": "{0} dimulai", "ScheduledTaskFailedWithName": "{0} gagal", - "ProviderValue": "Penyedia: {0}", "PluginUpdatedWithName": "{0} telah diperbarui", "PluginInstalledWithName": "{0} telah dipasang", - "Plugin": "Plugin", "Photos": "Foto", "NotificationOptionUserLockedOut": "Pengguna terkunci", "NotificationOptionTaskFailed": "Kegagalan tugas terjadwal", @@ -79,12 +55,7 @@ "NameInstallFailed": "{0} penginstalan gagal", "Music": "Musik", "Movies": "Film", - "MessageServerConfigurationUpdated": "Konfigurasi server telah diperbarui", - "MessageNamedServerConfigurationUpdatedWithValue": "Bagian konfigurasi server {0} telah diperbarui", "FailedLoginAttemptWithUserName": "Gagal upaya login dari {0}", - "CameraImageUploadedFrom": "Sebuah gambar kamera baru telah diunggah dari {0}", - "DeviceOfflineWithName": "{0} telah terputus", - "DeviceOnlineWithName": "{0} telah terhubung", "NotificationOptionVideoPlaybackStopped": "Pemutaran video berhenti", "NotificationOptionVideoPlayback": "Pemutaran video dimulai", "NotificationOptionAudioPlaybackStopped": "Pemutaran audio berhenti", @@ -135,5 +106,7 @@ "TaskExtractMediaSegments": "Scan Segmen media", "TaskMoveTrickplayImages": "Migrasikan Lokasi Gambar Trickplay", "TaskDownloadMissingLyrics": "Unduh Lirik yang Hilang", - "CleanupUserDataTask": "Tugas Pembersihan Data Pengguna" + "CleanupUserDataTask": "Tugas Pembersihan Data Pengguna", + "LyricDownloadFailureFromForItem": "Lirik gagal di download dari {0} untuk {1}", + "Original": "Asli" } diff --git a/Emby.Server.Implementations/Localization/Core/is.json b/Emby.Server.Implementations/Localization/Core/is.json index 900502ccdd..44e057e4de 100644 --- a/Emby.Server.Implementations/Localization/Core/is.json +++ b/Emby.Server.Implementations/Localization/Core/is.json @@ -1,36 +1,22 @@ { "LabelIpAddressValue": "IP tala: {0}", - "ItemRemovedWithName": "{0} var fjarlægt úr safninu", - "ItemAddedWithName": "{0} var bætt í safnið", "Inherit": "Erfa", "HomeVideos": "Heimamyndbönd", - "HeaderRecordingGroups": "Upptökuhópar", "HeaderNextUp": "Næst á dagskrá", "HeaderLiveTV": "Sjónvarp í beinni útsendingu", - "HeaderFavoriteSongs": "Uppáhalds Lög", "HeaderFavoriteShows": "Uppáhalds Sjónvarpsþættir", "HeaderFavoriteEpisodes": "Uppáhalds Þættir", - "HeaderFavoriteArtists": "Uppáhalds Listamenn", - "HeaderFavoriteAlbums": "Uppáhalds Plötur", "HeaderContinueWatching": "Halda áfram að horfa", - "HeaderAlbumArtists": "Listamaður á umslagi", "Genres": "Stefnur", "Folders": "Möppur", "Favorites": "Uppáhalds", "FailedLoginAttemptWithUserName": "{0} mistókst að auðkenna sig", - "DeviceOnlineWithName": "{0} hefur tengst", - "DeviceOfflineWithName": "{0} hefur aftengst", "Collections": "Söfn", "ChapterNameValue": "Kafli {0}", - "Channels": "Rásir", - "CameraImageUploadedFrom": "{0} hefur hlaðið upp nýrri ljósmynd úr myndavél sinni", "Books": "Bækur", "AuthenticationSucceededWithUserName": "Auðkenning fyrir {0} tókst", "Artists": "Listamenn", - "Application": "Forrit", "AppDeviceValues": "Snjallforrit: {0}, Tæki: {1}", - "Albums": "Plötur", - "Plugin": "Viðbótarvirkni", "Photos": "Ljósmyndir", "NotificationOptionVideoPlaybackStopped": "Myndbandsafspilun stöðvuð", "NotificationOptionVideoPlayback": "Myndbandsafspilun hafin", @@ -49,13 +35,8 @@ "NameSeasonUnknown": "Þáttaröð óþekkt", "NameSeasonNumber": "Þáttaröð {0}", "MixedContent": "Blandað efni", - "MessageServerConfigurationUpdated": "Stillingar þjóns hafa verið uppfærðar", - "MessageApplicationUpdatedTo": "Jellyfin þjónn hefur verið uppfærður í {0}", - "MessageApplicationUpdated": "Jellyfin þjónn hefur verið uppfærður", "Latest": "Nýjasta", "LabelRunningTimeValue": "spilunartími: {0}", - "User": "Notandi", - "System": "Kerfi", "NotificationOptionNewLibraryContent": "Nýju efni bætt við", "NewVersionIsAvailable": "Ný útgáfa af Jellyfin þjón er tilbúin til niðurhals.", "NameInstallFailed": "{0} uppsetning mistókst", @@ -65,10 +46,6 @@ "UserDeletedWithName": "Notanda {0} hefur verið eytt", "UserCreatedWithName": "Notandi {0} hefur verið stofnaður", "TvShows": "Sjónvarpsþættir", - "Sync": "Samstilla", - "Songs": "Lög", - "ServerNameNeedsToBeRestarted": "{0} þarf að vera endurræstur", - "ScheduledTaskStartedWithName": "{0} hafin", "ScheduledTaskFailedWithName": "{0} mistókst", "PluginUpdatedWithName": "{0} var uppfært", "PluginUninstalledWithName": "{0} var fjarlægt", @@ -76,21 +53,15 @@ "NotificationOptionTaskFailed": "Tímasett verkefni mistókst", "StartupEmbyServerIsLoading": "Jellyfin netþjónnin er að ræsa sig upp. Vinsamlegast reyndu aftur fljótlega.", "VersionNumber": "Útgáfa {0}", - "ValueHasBeenAddedToLibrary": "{0} hefur verið bætt við í gagnasafnið þitt", "UserStoppedPlayingItemWithValues": "{0} hefur lokið spilunar af {1} á {2}", "UserStartedPlayingItemWithValues": "{0} er að spila {1} á {2}", - "UserPolicyUpdatedWithName": "Notandaregla hefur verið uppfærð fyrir {0}", "UserPasswordChangedWithName": "Lykilorði fyrir notandann {0} hefur verið breytt", "UserOnlineFromDevice": "{0} hefur verið virkur síðan {1}", "UserOfflineFromDevice": "{0} hefur aftengst frá {1}", "UserLockedOutWithName": "Notandi {0} hefur verið læstur úti", "UserDownloadingItemWithValues": "{0} hleður niður {1}", "SubtitleDownloadFailureFromForItem": "Tókst ekki að hala niður skjátextum frá {0} til {1}", - "ProviderValue": "Efnisveita: {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "Stilling {0} hefur verið uppfærð á netþjón", - "ValueSpecialEpisodeName": "Sérstaktur - {0}", "Shows": "Þættir", - "Playlists": "Efnisskrár", "TaskRefreshChannelsDescription": "Endurhlaða upplýsingum netrása.", "TaskRefreshChannels": "Endurhlaða Rásir", "TaskCleanTranscodeDescription": "Eyða umkóðuðum skrám sem eru meira en einum degi eldri.", @@ -132,5 +103,8 @@ "TaskDownloadMissingLyrics": "Sækja söngtexta sem vantar", "TaskExtractMediaSegments": "Skönnun efnishluta", "CleanupUserDataTask": "Hreinsun notendagagna", - "CleanupUserDataTaskDescription": "Hreinsar öll notendagögn (spilunarstöðu, uppáhöld o.s.frv.) um gögn sem hafa ekki verið til staðar í að lámarki 90 daga." + "CleanupUserDataTaskDescription": "Hreinsar öll notendagögn (spilunarstöðu, uppáhöld o.s.frv.) um gögn sem hafa ekki verið til staðar í að lámarki 90 daga.", + "LyricDownloadFailureFromForItem": "Ekki tókst að niðurhala texta frá {0} fyrir {1}", + "Original": "Upprunaleg", + "TaskExtractMediaSegmentsDescription": "Sækir myndbúta úr viðbótum þar sem MediaSegment er virkt." } diff --git a/Emby.Server.Implementations/Localization/Core/it.json b/Emby.Server.Implementations/Localization/Core/it.json index 41d97442ed..f13944e6be 100644 --- a/Emby.Server.Implementations/Localization/Core/it.json +++ b/Emby.Server.Implementations/Localization/Core/it.json @@ -1,41 +1,24 @@ { - "Albums": "Album", "AppDeviceValues": "App: {0}, Dispositivo: {1}", - "Application": "Applicazione", "Artists": "Artisti", "AuthenticationSucceededWithUserName": "{0} autenticato correttamente", "Books": "Libri", - "CameraImageUploadedFrom": "È stata caricata una nuova fotografia da {0}", - "Channels": "Canali", "ChapterNameValue": "Capitolo {0}", "Collections": "Collezioni", - "DeviceOfflineWithName": "{0} si è disconnesso", - "DeviceOnlineWithName": "{0} è connesso", "FailedLoginAttemptWithUserName": "Tentativo di accesso non riuscito da {0}", "Favorites": "Preferiti", "Folders": "Cartelle", "Genres": "Generi", - "HeaderAlbumArtists": "Artisti dell'album", "HeaderContinueWatching": "Continua a guardare", - "HeaderFavoriteAlbums": "Album preferiti", - "HeaderFavoriteArtists": "Artisti preferiti", "HeaderFavoriteEpisodes": "Episodi preferiti", "HeaderFavoriteShows": "Serie TV preferite", - "HeaderFavoriteSongs": "Brani preferiti", "HeaderLiveTV": "Diretta TV", "HeaderNextUp": "Prossimo", - "HeaderRecordingGroups": "Gruppi di registrazione", "HomeVideos": "Video personali", "Inherit": "Eredita", - "ItemAddedWithName": "{0} è stato aggiunto alla libreria", - "ItemRemovedWithName": "{0} è stato rimosso dalla libreria", "LabelIpAddressValue": "Indirizzo IP: {0}", "LabelRunningTimeValue": "Durata: {0}", "Latest": "Novità", - "MessageApplicationUpdated": "Jellyfin Server è stato aggiornato", - "MessageApplicationUpdatedTo": "Jellyfin Server è stato aggiornato a {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "La sezione {0} della configurazione server è stata aggiornata", - "MessageServerConfigurationUpdated": "La configurazione del server è stata aggiornata", "MixedContent": "Contenuto misto", "Movies": "Film", "Music": "Musica", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "Riproduzione video iniziata", "NotificationOptionVideoPlaybackStopped": "Riproduzione video interrotta", "Photos": "Foto", - "Playlists": "Scalette", - "Plugin": "Plugin", "PluginInstalledWithName": "{0} è stato installato", "PluginUninstalledWithName": "{0} è stato disinstallato", "PluginUpdatedWithName": "{0} è stato aggiornato", - "ProviderValue": "Provider: {0}", "ScheduledTaskFailedWithName": "{0} non riuscito", - "ScheduledTaskStartedWithName": "{0} avviato", - "ServerNameNeedsToBeRestarted": "{0} deve essere riavviato", "Shows": "Serie TV", - "Songs": "Brani", "StartupEmbyServerIsLoading": "Jellyfin Server si sta avviando. Riprova più tardi.", "SubtitleDownloadFailureFromForItem": "Impossibile scaricare i sottotitoli da {0} per {1}", - "Sync": "Sincronizza", - "System": "Sistema", "TvShows": "Serie TV", - "User": "Utente", "UserCreatedWithName": "L'utente {0} è stato creato", "UserDeletedWithName": "L'utente {0} è stato eliminato", "UserDownloadingItemWithValues": "{0} sta scaricando {1}", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "{0} si è disconnesso da {1}", "UserOnlineFromDevice": "{0} è online su {1}", "UserPasswordChangedWithName": "La password è stata cambiata per l'utente {0}", - "UserPolicyUpdatedWithName": "La policy dell'utente è stata aggiornata per {0}", "UserStartedPlayingItemWithValues": "{0} ha avviato la riproduzione di {1} su {2}", "UserStoppedPlayingItemWithValues": "{0} ha interrotto la riproduzione di {1} su {2}", - "ValueHasBeenAddedToLibrary": "{0} è stato aggiunto alla tua libreria multimediale", - "ValueSpecialEpisodeName": "Speciale - {0}", "VersionNumber": "Versione {0}", "TaskRefreshChannelsDescription": "Aggiorna le informazioni dei canali internet.", "TaskDownloadMissingSubtitlesDescription": "Cerca su internet i sottotitoli mancanti basandosi sulle configurazioni dei metadati.", @@ -136,5 +107,6 @@ "TaskExtractMediaSegments": "Scansiona Segmento Media", "CleanupUserDataTask": "Task di pulizia dei dati utente", "CleanupUserDataTaskDescription": "Pulisce tutti i dati utente (stato di visione, status preferiti, ecc.) dai contenuti non più presenti da almeno 90 giorni.", - "Original": "Originale" + "Original": "Originale", + "LyricDownloadFailureFromForItem": "Scaricamento dei testi non riuscito da {0} per {1}" } diff --git a/Emby.Server.Implementations/Localization/Core/ja.json b/Emby.Server.Implementations/Localization/Core/ja.json index 7b0bdb296f..78b7ec744b 100644 --- a/Emby.Server.Implementations/Localization/Core/ja.json +++ b/Emby.Server.Implementations/Localization/Core/ja.json @@ -1,41 +1,24 @@ { - "Albums": "アルバム", "AppDeviceValues": "アプリ: {0}, デバイス: {1}", - "Application": "アプリケーション", "Artists": "アーティスト", "AuthenticationSucceededWithUserName": "{0} 認証に成功しました", "Books": "ブック", - "CameraImageUploadedFrom": "新しいカメライメージが {0}からアップロードされました", - "Channels": "チャンネル", "ChapterNameValue": "チャプター {0}", "Collections": "コレクション", - "DeviceOfflineWithName": "{0} が切断しました", - "DeviceOnlineWithName": "{0} が接続しました", "FailedLoginAttemptWithUserName": "{0} からのログインに失敗しました", "Favorites": "お気に入り", "Folders": "フォルダー", "Genres": "ジャンル", - "HeaderAlbumArtists": "アルバムアーティスト", "HeaderContinueWatching": "再生を続ける", - "HeaderFavoriteAlbums": "お気に入りのアルバム", - "HeaderFavoriteArtists": "お気に入りのアーティスト", "HeaderFavoriteEpisodes": "お気に入りのエピソード", "HeaderFavoriteShows": "お気に入りの番組", - "HeaderFavoriteSongs": "お気に入りの曲", "HeaderLiveTV": "ライブTV", "HeaderNextUp": "次", - "HeaderRecordingGroups": "レコーディンググループ", "HomeVideos": "ホームビデオ", "Inherit": "継承", - "ItemAddedWithName": "{0} をライブラリーに追加しました", - "ItemRemovedWithName": "{0} をライブラリーから削除しました", "LabelIpAddressValue": "IPアドレス: {0}", "LabelRunningTimeValue": "時間: {0}", "Latest": "最新", - "MessageApplicationUpdated": "Jellyfin Server を更新しました", - "MessageApplicationUpdatedTo": "Jellyfin Server を {0}に更新しました", - "MessageNamedServerConfigurationUpdatedWithValue": "サーバー設定項目の {0} を更新しました", - "MessageServerConfigurationUpdated": "サーバー設定を更新しました", "MixedContent": "ミックスコンテンツ", "Movies": "映画", "Music": "音楽", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "ビデオの再生を開始", "NotificationOptionVideoPlaybackStopped": "ビデオの再生を停止", "Photos": "フォト", - "Playlists": "プレイリスト", - "Plugin": "プラグイン", "PluginInstalledWithName": "{0} をインストールしました", "PluginUninstalledWithName": "{0} をアンインストールしました", "PluginUpdatedWithName": "{0} を更新しました", - "ProviderValue": "プロバイダ: {0}", "ScheduledTaskFailedWithName": "{0} が失敗しました", - "ScheduledTaskStartedWithName": "{0} を開始", - "ServerNameNeedsToBeRestarted": "{0} を再起動してください", "Shows": "番組", - "Songs": "曲", "StartupEmbyServerIsLoading": "Jellyfin Server は現在読み込み中です。しばらくしてからもう一度お試しください。", "SubtitleDownloadFailureFromForItem": "{0} から {1}の字幕のダウンロードに失敗しました", - "Sync": "同期", - "System": "システム", "TvShows": "テレビ番組", - "User": "ユーザー", "UserCreatedWithName": "ユーザー {0} が作成されました", "UserDeletedWithName": "User {0} を削除しました", "UserDownloadingItemWithValues": "{0} が {1} をダウンロードしています", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "{0} は {1} から切断しました", "UserOnlineFromDevice": "{0} は {1} からオンラインになりました", "UserPasswordChangedWithName": "ユーザー {0} のパスワードは変更されました", - "UserPolicyUpdatedWithName": "ユーザーポリシーが{0}に更新されました", "UserStartedPlayingItemWithValues": "{0} は {2}で{1} を再生しています", "UserStoppedPlayingItemWithValues": "{0} は{2}で{1} の再生が終わりました", - "ValueHasBeenAddedToLibrary": "{0} をメディアライブラリーに追加しました", - "ValueSpecialEpisodeName": "スペシャル - {0}", "VersionNumber": "バージョン {0}", "TaskCleanLogsDescription": "{0} 日以上前のログを消去します。", "TaskCleanLogs": "ログの掃除", @@ -135,5 +106,7 @@ "TaskDownloadMissingLyrics": "失われた歌詞をダウンロード", "TaskExtractMediaSegmentsDescription": "MediaSegment 対応プラグインからメディア セグメントを抽出または取得します。", "CleanupUserDataTask": "ユーザーデータのクリーンアップタスク", - "CleanupUserDataTaskDescription": "90日以上存在しないメディアに対して、視聴状態やお気に入り状態などのユーザーデータをすべて削除します。" + "CleanupUserDataTaskDescription": "90日以上存在しないメディアに対して、視聴状態やお気に入り状態などのユーザーデータをすべて削除します。", + "LyricDownloadFailureFromForItem": "歌詞", + "Original": "オリジナル" } diff --git a/Emby.Server.Implementations/Localization/Core/jbo.json b/Emby.Server.Implementations/Localization/Core/jbo.json index 1b47bb2f23..50d6d49601 100644 --- a/Emby.Server.Implementations/Localization/Core/jbo.json +++ b/Emby.Server.Implementations/Localization/Core/jbo.json @@ -1,7 +1,4 @@ { - "Albums": "lo albuma", "Artists": "lo larpra", - "Books": "lo cukta", - "HeaderAlbumArtists": "lo albuma larpra", - "Playlists": "lo zgipor" + "Books": "lo cukta" } diff --git a/Emby.Server.Implementations/Localization/Core/ka.json b/Emby.Server.Implementations/Localization/Core/ka.json index 4f291e466b..f7ca19d7f0 100644 --- a/Emby.Server.Implementations/Localization/Core/ka.json +++ b/Emby.Server.Implementations/Localization/Core/ka.json @@ -1,12 +1,8 @@ { "Genres": "ჟანრები", - "HeaderAlbumArtists": "ალბომის შემსრულებლები", - "HeaderFavoriteAlbums": "რჩეული ალბომები", "TasksApplicationCategory": "აპლიკაცია", - "Albums": "ალბომები", "AppDeviceValues": "აპლიკაცია: {0}, მოწყობილობა: {1}", - "Application": "აპლიკაცია", - "Artists": "არტისტი", + "Artists": "შემსრულებლები", "AuthenticationSucceededWithUserName": "{0} -ის ავთენტიკაცია წარმატებულია", "Books": "წიგნები", "Forced": "იძულებითი", @@ -15,106 +11,81 @@ "Movies": "ფილმები", "Music": "მუსიკა", "Photos": "ფოტოები", - "Playlists": "დასაკრავი სიები", - "Plugin": "მოდული", "Shows": "სერიალები", - "Songs": "სიმღერები", - "Sync": "სინქრონიზაცია", - "System": "სისტემა", "Undefined": "განუსაზღვრელი", - "User": "მომხმარებელი", "TasksMaintenanceCategory": "რემონტი", "TasksLibraryCategory": "ბიბლიოთეკა", "ChapterNameValue": "თავი {0}", "HeaderContinueWatching": "ყურების გაგრძელება", - "HeaderFavoriteArtists": "რჩეული შემსრულებლები", - "DeviceOfflineWithName": "{0} გამოეთიშა", "External": "გარე", "HeaderFavoriteEpisodes": "რჩეული ეპიზოდები", - "HeaderFavoriteSongs": "რჩეული სიმღერები", - "HeaderRecordingGroups": "ჩამწერი ჯგუფები", "HearingImpaired": "სმენადაქვეითებული", - "LabelRunningTimeValue": "ხანგრძლივობა: {0}", - "MessageApplicationUpdatedTo": "Jellyfin-ის სერვერი განახლდა {0}-ზე", - "MessageNamedServerConfigurationUpdatedWithValue": "სერვერის კონფიგურაციის სექცია {0} განახლდა", + "LabelRunningTimeValue": "გაშვების დრო: {0}", "MixedContent": "შერეული შემცველობა", - "MusicVideos": "მუსიკალური ვიდეოები", + "MusicVideos": "მუსიკის ვიდეოები", "NotificationOptionInstallationFailed": "დაყენების შეცდომა", "NotificationOptionApplicationUpdateInstalled": "აპლიკაციის განახლება დაყენებულია", "NotificationOptionAudioPlayback": "აუდიოს დაკვრა დაწყებულია", "NotificationOptionCameraImageUploaded": "კამერის გამოსახულება ატვირთულია", "NotificationOptionVideoPlaybackStopped": "ვიდეოს დაკვრა გაჩერებულია", "PluginUninstalledWithName": "{0} წაიშალა", - "ScheduledTaskStartedWithName": "{0} დაიწყო", "VersionNumber": "ვერსია {0}", "TasksChannelsCategory": "ინტერნეტ-არხები", - "ValueSpecialEpisodeName": "დამატებითი - {0}", - "TaskRefreshChannelsDescription": "ინტერნეტ-არხის ინფორმაციის განახლება.", - "Channels": "არხები", + "TaskRefreshChannelsDescription": "განაახლებს ინტერნეტ-არხის ინფორმაციას.", "Collections": "კოლექციები", - "Default": "ნაგულისხმები", + "Default": "ნაგულისხმევი", "Favorites": "რჩეულები", "Folders": "საქაღალდეები", "HeaderFavoriteShows": "რჩეული სერიალები", - "HeaderLiveTV": "ლაივ ტელევიზია", + "HeaderLiveTV": "ცოცხალი ტელევიზია", "HeaderNextUp": "შემდეგი", "HomeVideos": "სახლის ვიდეოები", "NameSeasonNumber": "სეზონი {0}", "NameSeasonUnknown": "სეზონი უცნობია", - "NotificationOptionPluginError": "მოდულის შეცდომა", - "NotificationOptionPluginInstalled": "მოდული დაყენებულია", + "NotificationOptionPluginError": "დამატების შეცდომა", + "NotificationOptionPluginInstalled": "დამატება დაყენებულია", "NotificationOptionPluginUninstalled": "მოდული წაიშალა", - "ProviderValue": "მომწოდებელი: {0}", - "ScheduledTaskFailedWithName": "{0} ვერ შესრულდა", + "ScheduledTaskFailedWithName": "{0} ჩავარდა", "TvShows": "სატელევიზიო სერიალები", "TaskRefreshPeople": "ხალხის განახლება", - "TaskUpdatePlugins": "მოდულების განახლება", + "TaskUpdatePlugins": "დამატებების განახლება", "TaskRefreshChannels": "არხების განახლება", "TaskOptimizeDatabase": "მონაცემთა ბაზის ოპტიმიზაცია", "TaskKeyframeExtractor": "საკვანძო კადრის გამომღები", - "DeviceOnlineWithName": "{0} დაკავშირდა", "LabelIpAddressValue": "IP მისამართი: {0}", - "NameInstallFailed": "{0}-ის დაყენების შეცდომა", + "NameInstallFailed": "{0}-ის დაყენების ჩავარდა", "NotificationOptionApplicationUpdateAvailable": "ხელმისაწვდომია აპლიკაციის განახლება", "NotificationOptionAudioPlaybackStopped": "აუდიოს დაკვრა გაჩერებულია", "NotificationOptionNewLibraryContent": "ახალი შემცველობა დამატებულია", - "NotificationOptionPluginUpdateInstalled": "მოდულიs განახლება დაყენებულია", + "NotificationOptionPluginUpdateInstalled": "დამატების განახლება დაყენებულია", "NotificationOptionServerRestartRequired": "საჭიროა სერვერის გადატვირთვა", - "NotificationOptionTaskFailed": "გეგმიური დავალების შეცდომა", + "NotificationOptionTaskFailed": "დაგეგმილი ამოცანა ჩავარდა", "NotificationOptionUserLockedOut": "მომხმარებელი დაიბლოკა", "NotificationOptionVideoPlayback": "ვიდეოს დაკვრა დაწყებულია", "PluginInstalledWithName": "{0} დაყენებულია", "PluginUpdatedWithName": "{0} განახლდა", "TaskCleanActivityLog": "აქტივობების ჟურნალის გასუფთავება", - "TaskCleanCache": "ქეშის საქაღალდის გასუფთავება", - "TaskRefreshChapterImages": "თავის სურათების გაშლა", + "TaskCleanCache": "კეშის საქაღალდის გასუფთავება", + "TaskRefreshChapterImages": "თავის სურათების ამოღება", "TaskRefreshLibrary": "მედიის ბიბლიოთეკის სკანირება", "TaskCleanLogs": "ჟურნალის საქაღალდის გასუფთავება", "TaskCleanTranscode": "ტრანსკოდირების საქაღალდის გასუფთავება", - "TaskDownloadMissingSubtitles": "მიუწვდომელი სუბტიტრების გადმოწერა", - "UserDownloadingItemWithValues": "{0} -ი {1}-ს იწერს", + "TaskDownloadMissingSubtitles": "ნაკლული სუბტიტრების გადმოწერა", + "UserDownloadingItemWithValues": "{0} იწერს {1}-ს", "FailedLoginAttemptWithUserName": "შესვლის წარუმატებელი მცდელობა {0}-დან", - "MessageApplicationUpdated": "Jellyfin-ის სერვერი განახლდა", - "MessageServerConfigurationUpdated": "სერვერის კონფიგურაცია განახლდა", - "ServerNameNeedsToBeRestarted": "საჭიროა {0}-ის გადატვირთვა", "UserCreatedWithName": "მომხმარებელი {0} შეიქმნა", - "UserDeletedWithName": "მომხმარებელი {0} წაშლილია", - "UserOnlineFromDevice": "{0}-ი დაკავშირდა {1}-დან", - "UserOfflineFromDevice": "{0}-ი {1}-დან გაეთიშა", - "ItemAddedWithName": "{0} ჩამატებულია ბიბლიოთეკაში", - "ItemRemovedWithName": "{0} წაშლილია ბიბლიოთეკიდან", + "UserDeletedWithName": "მომხმარებელი {0} წაიშალა", + "UserOnlineFromDevice": "{0} ხაზზეა {1}-დან", + "UserOfflineFromDevice": "{0} გაითიშა {1}-დან", "UserLockedOutWithName": "მომხმარებელი {0} დაბლოკილია", - "UserStartedPlayingItemWithValues": "{0} უყურებს {1}-ს {2}-ზე", + "UserStartedPlayingItemWithValues": "{0} უკრავს {1}-ს {2}-ზე", "UserPasswordChangedWithName": "მომხმარებელი {0}-სთვის პაროლი შეიცვალა", - "UserPolicyUpdatedWithName": "{0}-ის მომხმარებლის პოლიტიკა განახლდა", "UserStoppedPlayingItemWithValues": "{0}-მა დაასრულა {1}-ის ყურება {2}-ზე", "TaskRefreshChapterImagesDescription": "თავების მქონე ვიდეოებისთვის მინიატურების შექმნა.", "TaskKeyframeExtractorDescription": "უფრო ზუსტი HLS დასაკრავი სიებისითვის ვიდეოდან საკვანძო გადრების ამოღება. შეიძლება საკმაო დრო დასჭირდეს.", "NewVersionIsAvailable": "გადმოსაწერად ხელმისაწვდომია Jellyfin -ის ახალი ვერსია.", - "CameraImageUploadedFrom": "ახალი კამერის გამოსახულება ატვირთულია {0}-დან", "StartupEmbyServerIsLoading": "Jellyfin სერვერი იტვირთება. მოგვიანებით სცადეთ.", "SubtitleDownloadFailureFromForItem": "{0}-დან {1}-სთვის სუბტიტრების გადმოწერა ვერ შესრულდა", - "ValueHasBeenAddedToLibrary": "{0} დაემატა თქვენს მედიის ბიბლიოთეკას", "TaskCleanActivityLogDescription": "შლის მითითებულ ასაკზე ძველ ჟურნალის ჩანაწერებს.", "TaskCleanCacheDescription": "შლის სისტემისთვის არასაჭირო ქეშის ფაილებს.", "TaskRefreshLibraryDescription": "ეძებს ახალ ფაილებს თქვენს მედიის ბიბლიოთეკაში და ანახლებს მეტამონაცემებს.", @@ -125,15 +96,17 @@ "TaskDownloadMissingSubtitlesDescription": "ეძებს ბიბლიოთეკაში მიუწვდომელ სუბტიტრებს ინტერნეტში მეტამონაცემებზე დაყრდნობით.", "TaskOptimizeDatabaseDescription": "კუმშავს მონაცემთა ბაზას ადგილის გათავისუფლებლად. ამ ამოცანის ბიბლიოთეკის სკანირების ან ნებისმიერი ცვლილების, რომელიც ბაზაში რამეს აკეთებს, გაშვებას შეუძლია ბაზის წარმადობა გაზარდოს.", "TaskRefreshTrickplayImagesDescription": "ქმნის trickplay წინასწარ ხედებს ვიდეოებისთვის დაშვებულ ბიბლიოთეკებში.", - "TaskRefreshTrickplayImages": "Trickplay სურათების გენერირება", - "TaskAudioNormalization": "აუდიოს ნორმალიზება", + "TaskRefreshTrickplayImages": "Trickplay სურათების გენერაცია", + "TaskAudioNormalization": "აუდიოს ნორმალიზაცია", "TaskAudioNormalizationDescription": "აანალიზებს ფაილებს აუდიოს ნორმალიზაციისთვის.", "TaskDownloadMissingLyrics": "მიუწვდომელი ლირიკების ჩამოტვირთვა", - "TaskDownloadMissingLyricsDescription": "ჩამოტვირთავს ამჟამად ბიბლიოთეკაში არარსებულ ლირიკებს სიმღერებისთვის", - "TaskExtractMediaSegments": "მედია სეგმენტების სკანირება", + "TaskDownloadMissingLyricsDescription": "გადმოწერს ლირიკას სიმღერებისთვის", + "TaskExtractMediaSegments": "მედიის სეგმენტების სკანირება", "TaskExtractMediaSegmentsDescription": "მედია სეგმენტების სკანირება მხარდაჭერილი მოდულებისთვის.", - "TaskMoveTrickplayImages": "Trickplay სურათების მიგრაცია", + "TaskMoveTrickplayImages": "Trickplay-ის გამოსახულებების მდებარეობის მიგრაცია", "TaskMoveTrickplayImagesDescription": "გადააქვს trickplay ფაილები ბიბლიოთეკის პარამეტრებზე დაყრდნობით.", - "CleanupUserDataTask": "მომხმარებლების მონაცემების გასუფთავება", - "CleanupUserDataTaskDescription": "ასუფთავებს მომხმარებლების მონაცემებს (ყურების სტატუსი, ფავორიტები ანდ ა.შ) მედია ელემენტებისთვის რომლების 90 დღეზე მეტია აღარ არსებობენ." + "CleanupUserDataTask": "მომხმარებლების მონაცემების გასუფთავების ამოცანა", + "CleanupUserDataTaskDescription": "ასუფთავებს მომხმარებლების მონაცემებს (ყურების სტატუსი, ფავორიტები ანდ ა.შ) მედია ელემენტებისთვის რომლების 90 დღეზე მეტია აღარ არსებობენ.", + "LyricDownloadFailureFromForItem": "{1}-ისთვის {0}-დან ლირიკის გადმოწერა ჩავარდა", + "Original": "ორიგინალი" } diff --git a/Emby.Server.Implementations/Localization/Core/kab.json b/Emby.Server.Implementations/Localization/Core/kab.json index 9551f0e5c1..0d0932b585 100644 --- a/Emby.Server.Implementations/Localization/Core/kab.json +++ b/Emby.Server.Implementations/Localization/Core/kab.json @@ -1,14 +1,10 @@ { "Music": "Aẓawan", - "Sync": "Amtawi", "Photos": "Tiwlafin", "Movies": "Isura", "External": "Azɣaray", - "User": "Aseqdac", "Folders": "Ikaramen", "Favorites": "Ismenyifen", "Default": "Lexṣas", - "Collections": "Tigrummiwin", - "Channels": "Ibuda", - "Albums": "Iseɣraz" + "Collections": "Tigrummiwin" } diff --git a/Emby.Server.Implementations/Localization/Core/kk.json b/Emby.Server.Implementations/Localization/Core/kk.json index fc5fcf3c4d..ddcf60944d 100644 --- a/Emby.Server.Implementations/Localization/Core/kk.json +++ b/Emby.Server.Implementations/Localization/Core/kk.json @@ -1,41 +1,24 @@ { - "Albums": "Älbomdar", "AppDeviceValues": "Qoldanba: {0}, Qūrylğy: {1}", - "Application": "Qoldanba", "Artists": "Oryndauşylar", "AuthenticationSucceededWithUserName": "{0} tüpnūsqalyq rastaluy sättı aiaqtaldy", "Books": "Kıtaptar", - "CameraImageUploadedFrom": "{0} kamerasynan jaña suret jüktep salyndy", - "Channels": "Arnalar", "ChapterNameValue": "{0}-sahna", "Collections": "Jiyntyqtar", - "DeviceOfflineWithName": "{0} ajyratylğan", - "DeviceOnlineWithName": "{0} qosylğan", "FailedLoginAttemptWithUserName": "{0} tarapynan kıru äreketı sätsız aiaqtaldy", "Favorites": "Tañdaulylar", "Folders": "Qaltalar", "Genres": "Janrlar", - "HeaderAlbumArtists": "Älbom oryndauşylary", "HeaderContinueWatching": "Qaraudy jalğastyru", - "HeaderFavoriteAlbums": "Tañdauly älbomdar", - "HeaderFavoriteArtists": "Tañdauly oryndauşylar", "HeaderFavoriteEpisodes": "Tañdauly telebölımder", "HeaderFavoriteShows": "Tañdauly körsetımder", - "HeaderFavoriteSongs": "Tañdauly äuender", "HeaderLiveTV": "Efir", "HeaderNextUp": "Kezektı", - "HeaderRecordingGroups": "Jazba toptary", "HomeVideos": "Üilık beineler", "Inherit": "İelenu", - "ItemAddedWithName": "{0} tasyğyşhanağa üstelindı", - "ItemRemovedWithName": "{0} tasyğyşhanadan alastaldy", "LabelIpAddressValue": "IP-mekenjaiy: {0}", "LabelRunningTimeValue": "Oinatu uaqyty: {0}", "Latest": "Eñ keiıngı", - "MessageApplicationUpdated": "Jellyfin Serverı jañartyldy", - "MessageApplicationUpdatedTo": "Jellyfin Serverı {0} nūsqasyna jañartyldy", - "MessageNamedServerConfigurationUpdatedWithValue": "Server teñşelımderınıñ {0} bölımı jañartyldy", - "MessageServerConfigurationUpdated": "Server teñşelımderı jañartyldy", "MixedContent": "Aralas mazmūn", "Movies": "Filmder", "Music": "Muzyka", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "Beine oinatuy bastaldy", "NotificationOptionVideoPlaybackStopped": "Beine oinatuy toqtatyldy", "Photos": "Fotosuretter", - "Playlists": "Oinatu tızımderı", - "Plugin": "Plagin", "PluginInstalledWithName": "{0} ornatyldy", "PluginUninstalledWithName": "{0} joiyldy", "PluginUpdatedWithName": "{0} jañartyldy", - "ProviderValue": "Jetkızuşı: {0}", "ScheduledTaskFailedWithName": "{0} sätsız", - "ScheduledTaskStartedWithName": "{0} ıske qosyldy", - "ServerNameNeedsToBeRestarted": "{0} qaita ıske qosu qajet", "Shows": "Körsetımder", - "Songs": "Äuender", "StartupEmbyServerIsLoading": "Jellyfin Server jüktelude. Ärekettı köp ūzamai qaitalañyz.", "SubtitleDownloadFailureFromForItem": "{1} üşın subtitrlerdı {0} közınen jüktep alu sätsız", - "Sync": "Ündestıru", - "System": "Jüie", "TvShows": "TD-körsetımder", - "User": "Paidalanuşy", "UserCreatedWithName": "Paidalanuşy {0} jasalğan", "UserDeletedWithName": "Paidalanuşy {0} joiylğan", "UserDownloadingItemWithValues": "{0} — {1} jüktep aluda", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "{0} — {1} tarapynan ajyratyldy", "UserOnlineFromDevice": "{0} — {1} tarapynan qosyldy", "UserPasswordChangedWithName": "Paidalanuşy {0} üşın paröl özgertıldı", - "UserPolicyUpdatedWithName": "Paidalanuşy {0} üşın saiasattary jañartyldy", "UserStartedPlayingItemWithValues": "{0} — {2} tarapynan {1} oinatuda", "UserStoppedPlayingItemWithValues": "{0} — {2} tarapynan {1} oinatuyn toqtatty", - "ValueHasBeenAddedToLibrary": "{0} tasyğyşhanağa üstelındı", - "ValueSpecialEpisodeName": "Arnaiy - {0}", "VersionNumber": "Nūsqasy {0}", "Default": "Ädepkı", "TaskDownloadMissingSubtitles": "Joq subtitrlerdı jüktep alu", diff --git a/Emby.Server.Implementations/Localization/Core/km.json b/Emby.Server.Implementations/Localization/Core/km.json index c40b96cf24..b4057eb8eb 100644 --- a/Emby.Server.Implementations/Localization/Core/km.json +++ b/Emby.Server.Implementations/Localization/Core/km.json @@ -1,88 +1,62 @@ { - "Albums": "អាលប៊ុម", - "MessageApplicationUpdatedTo": "ម៉ាស៊ីនមេនៃJellyfinត្រូវបានអាប់ដេតទៅកាន់ {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "ការកំណត់ម៉ាស៊ីនមេ ផ្នែក {0} ត្រូវបានអាប់ដេត", - "MessageServerConfigurationUpdated": "ការកំណត់ម៉ាស៊ីនមេត្រូវបានអាប់ដេត", "AppDeviceValues": "កម្មវិធី: {0}, ឧបករណ៍: {1}", "MixedContent": "មាតិកាចម្រុះ", "UserLockedOutWithName": "អ្នកប្រើប្រាស់ {0} ត្រូវបានផ្អាក", - "Application": "កម្មវិធី", "Artists": "សិល្បករ", "AuthenticationSucceededWithUserName": "{0} បានផ្ទៀងផ្ទាត់ដោយជោគជ័យ", "Books": "សៀវភៅ", "NameSeasonNumber": "រដូវកាលទី {0}", "NotificationOptionPluginInstalled": "Plugin បានដំឡើងរួច", - "CameraImageUploadedFrom": "រូបភាពកាមេរ៉ាថ្មីត្រូវបានបង្ហោះពី {0}", - "Channels": "ប៉ុស្ត៍", "ChapterNameValue": "ជំពូក {0}", "Collections": "បណ្តុំ", "External": "ខាងក្រៅ", "Default": "លំនាំដើម", "NotificationOptionInstallationFailed": "ការដំឡើងមិនបានសម្រេច", - "DeviceOfflineWithName": "{0} បានផ្តាច់", "Folders": "ថតឯកសារ", - "DeviceOnlineWithName": "{0} បានភ្ចាប់", "HearingImpaired": "ខ្សោយការស្តាប់", "HomeVideos": "វីឌីអូថតខ្លួនឯង", "Favorites": "ចំណូលចិត្ត", "HeaderFavoriteEpisodes": "ភាគដែលចូលចិត្ត", "Forced": "បង្ខំ", "Genres": "ប្រភេទ", - "HeaderFavoriteArtists": "សិល្បករដែលចូលចិត្ត", "NotificationOptionApplicationUpdateAvailable": "កម្មវិធី យើងអាចអាប់ដេតបាន", "NotificationOptionApplicationUpdateInstalled": "កម្មវិធី ដែលបានដំឡើងរួច", "NotificationOptionAudioPlaybackStopped": "ការចាក់សម្លេងបានផ្អាក", "HeaderContinueWatching": "បន្តមើល", - "HeaderFavoriteAlbums": "អាល់ប៊ុមដែលចូលចិត្ត", "HeaderFavoriteShows": "រឿងភាគដែលចូលចិត្ត", "NewVersionIsAvailable": "មានជំនាន់ថ្មី ម៉ាស៊ីនមេJellyfin អាចទាញយកបាន.", - "HeaderAlbumArtists": "សិល្បករអាល់ប៊ុម", "NotificationOptionCameraImageUploaded": "រូបភាពពីកាំមេរ៉ាបានអាប់ឡូតរួច", - "HeaderFavoriteSongs": "ចម្រៀងដែលចូលចិត្ត", "HeaderNextUp": "បន្ទាប់", "HeaderLiveTV": "ទូរទស្សន៍ផ្សាយផ្ទាល់", "Movies": "រឿង", - "HeaderRecordingGroups": "ក្រុមនៃការថត", "Music": "តន្ត្រី", "Inherit": "មរតក", "MusicVideos": "វីដេអូតន្ត្រី", "NameInstallFailed": "{0} ការដំឡើងបានបរាជ័យ", "NotificationOptionNewLibraryContent": "មាតិកាថ្មីៗត្រូវបានបន្ថែម", - "ItemAddedWithName": "{0} ត្រូវបានបន្ថែមទៅបណ្ណាល័យ", "NameSeasonUnknown": "រដូវកាលមិនច្បាស់លាស់", - "ItemRemovedWithName": "{0} ត្រូវបានដកចេញពីបណ្ណាល័យ", "LabelIpAddressValue": "លេខ IP: {0}", "LabelRunningTimeValue": "ពេលវេលាកំពុងដំណើរការ: {0}", "Latest": "ចុងក្រោយ", "NotificationOptionAudioPlayback": "ការចាក់សំឡេងបានចាប់ផ្ដើម", "NotificationOptionPluginError": "Plugin មិនដំណើរការ", "NotificationOptionPluginUninstalled": "Plugin បានលុបចេញរួច", - "MessageApplicationUpdated": "ម៉ាស៊ីនមេនៃJellyfinត្រូវបានអាប់ដេត", "NotificationOptionPluginUpdateInstalled": "Plugin អាប់ដេតបានដំឡើងរួច", "NotificationOptionUserLockedOut": "អ្នកប្រើប្រាស់ត្រូវបានជាប់គាំង", "NotificationOptionServerRestartRequired": "តម្រូវឱ្យចាប់ផ្ដើមម៉ាស៊ីនមេឡើងវិញ", "Photos": "រូបថត", - "Playlists": "បញ្ជីចាក់", - "Plugin": "Plugin", "PluginInstalledWithName": "{0} ត្រូវបានដំឡើង", "NotificationOptionTaskFailed": "កិច្ចការដែលបានគ្រោងទុកបានបរាជ័យ", "PluginUpdatedWithName": "{0} ត្រូវបានអាប់ដេត", "NotificationOptionVideoPlayback": "ការចាក់វីដេអូបានចាប់ផ្តើម", - "Songs": "ចម្រៀង", - "ScheduledTaskStartedWithName": "{0} បានចាប់ផ្តើម", "NotificationOptionVideoPlaybackStopped": "ការចាក់វីដេអូបានបញ្ឈប់", "PluginUninstalledWithName": "{0} ត្រូវបានលុបចេញ", "Shows": "រឿងភាគ", - "ProviderValue": "អ្នកផ្តល់សេវា: {0}", "SubtitleDownloadFailureFromForItem": "សាប់ថាយថលបានបរាជ័យក្នុងការទាញយកពី {0} នៃ {1}", - "Sync": "ធ្វើអោយដំណាលគ្នា", - "System": "ប្រព័ន្ធ", "TvShows": "កម្មវិធីទូរទស្សន៍", "ScheduledTaskFailedWithName": "{0} បានបរាជ័យ", "Undefined": "មិនបានកំណត់", - "User": "អ្នកប្រើប្រាស់", "UserCreatedWithName": "អ្នកប្រើប្រាស់ {0} ត្រូវបានបង្កើតឡើង", - "ServerNameNeedsToBeRestarted": "{0} ចាំបាច់ត្រូវចាប់ផ្តើមឡើងវិញ", "StartupEmbyServerIsLoading": "ម៉ាស៊ីនមេJellyfin កំពុងដំណើរការ. សូមព្យាយាមម្តងទៀតក្នុងពេលឆាប់ៗនេះ.", "UserDeletedWithName": "អ្នកប្រើប្រាស់ {0} ត្រូវបានលុបចេញ", "UserOnlineFromDevice": "{0} បានឃើញអនឡានពី {1}", @@ -98,10 +72,7 @@ "UserPasswordChangedWithName": "ពាក្យសម្ងាត់ត្រូវបានផ្លាស់ប្តូរសម្រាប់អ្នកប្រើប្រាស់ {0}", "TaskCleanCache": "សម្អាតបញ្ជីឃ្លាំងសម្ងាត់", "TaskRefreshChapterImages": "ដកស្រង់រូបភាពតាមជំពូក", - "UserPolicyUpdatedWithName": "គោលការណ៍អ្នកប្រើប្រាស់ត្រូវបានធ្វើបច្ចុប្បន្នភាពសម្រាប់ {0}", "UserStoppedPlayingItemWithValues": "{0} បានបញ្ចប់ការចាក់ {1} នៅលើ {2}", - "ValueHasBeenAddedToLibrary": "{0} ត្រូវបានបញ្ចូលទៅក្នុងបណ្ណាល័យរឿងរបស់អ្នក", - "ValueSpecialEpisodeName": "ពិសេស - {0}", "TasksChannelsCategory": "ប៉ុស្តតាមអ៊ីនធឺណិត", "TaskAudioNormalization": "ធ្វើឱ្យមានតន្ត្រីមានសម្លេងស្មើគ្នា", "TaskCleanActivityLogDescription": "លុបកំណត់ហេតុសកម្មភាពចាស់ជាងអាយុដែលបានកំណត់រចនាសម្ព័ន្ធ.", diff --git a/Emby.Server.Implementations/Localization/Core/kn.json b/Emby.Server.Implementations/Localization/Core/kn.json index 0850600588..6009b50fe0 100644 --- a/Emby.Server.Implementations/Localization/Core/kn.json +++ b/Emby.Server.Implementations/Localization/Core/kn.json @@ -4,8 +4,6 @@ "TaskOptimizeDatabaseDescription": "ಡೇಟಾಬೇಸ್ ಅನ್ನು ಕಾಂಪ್ಯಾಕ್ಟ್ ಮಾಡುತ್ತದೆ ಮತ್ತು ಮುಕ್ತ ಜಾಗವನ್ನು ಮೊಟಕುಗೊಳಿಸುತ್ತದೆ. ಲೈಬ್ರರಿಯನ್ನು ಸ್ಕ್ಯಾನ್ ಮಾಡಿದ ನಂತರ ಈ ಕಾರ್ಯವನ್ನು ನಡೆಸುವುದು ಅಥವಾ ಡೇಟಾಬೇಸ್ ಮಾರ್ಪಾಡುಗಳನ್ನು ಸೂಚಿಸುವ ಇತರ ಬದಲಾವಣೆಗಳನ್ನು ಮಾಡುವುದರಿಂದ ಕಾರ್ಯಕ್ಷಮತೆಯನ್ನು ಸುಧಾರಿಸಬಹುದು.", "TaskKeyframeExtractor": "ಕೀಫ್ರೇಮ್ ಎಕ್ಸ್ಟ್ರಾಕ್ಟರ್", "TaskKeyframeExtractorDescription": "ಹೆಚ್ಚು ನಿಖರವಾದ HLS ಪ್ಲೇಪಟ್ಟಿಗಳನ್ನು ರಚಿಸಲು ವೀಡಿಯೊ ಫೈಲ್ಗಳಿಂದ ಕೀಫ್ರೇಮ್ಗಳನ್ನು ಹೊರತೆಗೆಯುತ್ತದೆ. ಈ ಕಾರ್ಯವು ದೀರ್ಘಕಾಲದವರೆಗೆ ನಡೆಯಬಹುದು.", - "ValueHasBeenAddedToLibrary": "{0} ಅನ್ನು ನಿಮ್ಮ ಮಾಧ್ಯಮ ಲೈಬ್ರರಿಗೆ ಸೇರಿಸಲಾಗಿದೆ", - "ValueSpecialEpisodeName": "ವಿಶೇಷ - {0}", "TasksLibraryCategory": "ಸಮೊಹ", "TasksApplicationCategory": "ಅಪ್ಲಿಕೇಶನ್", "TasksChannelsCategory": "ಇಂಟರ್ನೆಟ್ ಚಾನೆಲ್ಗಳು", @@ -13,8 +11,6 @@ "TaskCleanCacheDescription": "ಸಿಸ್ಟಮ್ಗೆ ಇನ್ನು ಮುಂದೆ ಅಗತ್ಯವಿಲ್ಲದ ಸಂಗ್ರಹ ಫೈಲ್ಗಳನ್ನು ಅಳಿಸುತ್ತದೆ.", "TaskRefreshLibrary": "ಸ್ಕ್ಯಾನ್ ಮೀಡಿಯಾ ಲೈಬ್ರರಿ", "UserOfflineFromDevice": "{1} ನಿಂದ {0} ಸಂಪರ್ಕ ಕಡಿತಗೊಂಡಿದೆ", - "Albums": "ಸಂಪುಟ", - "Application": "ಅಪ್ಲಿಕೇಶನ್", "AppDeviceValues": "ಅಪ್ಲಿಕೇಶನ್: {0}, ಸಾಧನ: {1}", "Artists": "ಕಲಾವಿದರು", "AuthenticationSucceededWithUserName": "{0} ಯಶಸ್ವಿಯಾಗಿ ದೃಢೀಕರಿಸಲಾಗಿದೆ", @@ -22,8 +18,6 @@ "ChapterNameValue": "ಅಧ್ಯಾಯ {0}", "Collections": "ಸಂಗ್ರಹಣೆಗಳು", "Default": "ಪೂರ್ವನಿಯೋಜಿತ", - "DeviceOfflineWithName": "{0} ಸಂಪರ್ಕ ಕಡಿತಗೊಂಡಿದೆ", - "DeviceOnlineWithName": "{0} ಸಂಪರ್ಕಗೊಂಡಿದೆ", "External": "ಹೊರಗಿನ", "FailedLoginAttemptWithUserName": "ವಿಫಲ ಲಾಗಿನ್ ಪ್ರಯತ್ನ ಸಂಖ್ಯೆ {0}", "Favorites": "ಮೆಚ್ಚಿನವುಗಳು", @@ -31,22 +25,11 @@ "Forced": "ಬಲವಂತವಾಗಿ", "Genres": "ಪ್ರಕಾರಗಳು", "HeaderContinueWatching": "ನೋಡುವುದನ್ನು ಮುಂದುವರಿಸಿ", - "HeaderFavoriteAlbums": "ಮೆಚ್ಚಿನ ಸಂಪುಟಗಳು", - "HeaderFavoriteArtists": "ಮೆಚ್ಚಿನ ಕಲಾವಿದರು", "HeaderFavoriteShows": "ಮೆಚ್ಚಿನ ಪ್ರದರ್ಶನಗಳು", - "HeaderFavoriteSongs": "ಮೆಚ್ಚಿನ ಹಾಡುಗಳು", "HeaderLiveTV": "ನೇರ ದೂರದರ್ಶನ", "HeaderNextUp": "ಮುಂದೆ", - "HeaderRecordingGroups": "ರೆಕಾರ್ಡಿಂಗ್ ಗುಂಪುಗಳು", - "MessageApplicationUpdated": "ಜೆಲ್ಲಿಫಿನ್ ಸರ್ವರ್ ಅನ್ನು ನವೀಕರಿಸಲಾಗಿದೆ", - "CameraImageUploadedFrom": "ಹೊಸ ಕ್ಯಾಮರಾ ಚಿತ್ರವನ್ನು {0} ನಿಂದ ಅಪ್ಲೋಡ್ ಮಾಡಲಾಗಿದೆ", - "Channels": "ಮೂಲಗಳು", - "HeaderAlbumArtists": "ಸಂಪುಟ ಕಲಾವಿದರು", "HeaderFavoriteEpisodes": "ಮೆಚ್ಚಿನ ಸಂಚಿಕೆಗಳು", "HearingImpaired": "ಮೂಗ", - "ItemAddedWithName": "{0} ಅನ್ನು ಸಂಕಲನಕ್ಕೆ ಸೇರಿಸಲಾಗಿದೆ", - "MessageApplicationUpdatedTo": "ಜೆಲ್ಲಿಫಿನ್ ಸರ್ವರ್ ಅನ್ನು {0} ಗೆ ನವೀಕರಿಸಲಾಗಿದೆ", - "MessageNamedServerConfigurationUpdatedWithValue": "ಸರ್ವರ್ ಕಾನ್ಫಿಗರೇಶನ್ ವಿಭಾಗ {0} ಅನ್ನು ನವೀಕರಿಸಲಾಗಿದೆ", "NewVersionIsAvailable": "ಜೆಲ್ಲಿಫಿನ್ ಸರ್ವರ್ನ ಹೊಸ ಆವೃತ್ತಿಯು ಡೌನ್ಲೋಡ್ಗೆ ಲಭ್ಯವಿದೆ.", "NotificationOptionAudioPlayback": "ಆಡಿಯೋ ಪ್ಲೇಬ್ಯಾಕ್ ಪ್ರಾರಂಭವಾಗಿದೆ", "NotificationOptionCameraImageUploaded": "ಕ್ಯಾಮರಾ ಚಿತ್ರವನ್ನು ಅಪ್ಲೋಡ್ ಮಾಡಲಾಗಿದೆ", @@ -55,13 +38,10 @@ "NotificationOptionVideoPlaybackStopped": "ವೀಡಿಯೊ ಪ್ಲೇಬ್ಯಾಕ್ ನಿಲ್ಲಿಸಲಾಗಿದೆ", "PluginUninstalledWithName": "{0} ಅನ್ನು ಅನ್ಇನ್ಸ್ಟಾಲ್ ಮಾಡಲಾಗಿದೆ", "ScheduledTaskFailedWithName": "{0} ವಿಫಲವಾಗಿದೆ", - "ScheduledTaskStartedWithName": "{0} ಪ್ರಾರಂಭವಾಯಿತು", - "ServerNameNeedsToBeRestarted": "{0} ಅನ್ನು ಮರುಪ್ರಾರಂಭಿಸಬೇಕಾಗಿದೆ", "UserCreatedWithName": "ಬಳಕೆದಾರ {0} ಅನ್ನು ರಚಿಸಲಾಗಿದೆ", "UserLockedOutWithName": "ಬಳಕೆದಾರ {0} ಅನ್ನು ಲಾಕ್ ಮಾಡಲಾಗಿದೆ", "UserOnlineFromDevice": "{1} ನಿಂದ {0} ಆನ್ಲೈನ್ನಲ್ಲಿದೆ", "UserPasswordChangedWithName": "{0} ಬಳಕೆದಾರರಿಗಾಗಿ ಪಾಸ್ವರ್ಡ್ ಅನ್ನು ಬದಲಾಯಿಸಲಾಗಿದೆ", - "UserPolicyUpdatedWithName": "ಬಳಕೆದಾರರ ನೀತಿಯನ್ನು {0} ಗೆ ನವೀಕರಿಸಲಾಗಿದೆ", "UserStartedPlayingItemWithValues": "{2} ರಂದು {0} ಆಡುತ್ತಿದೆ {1}", "UserStoppedPlayingItemWithValues": "{0} ಅವರು {1} ಅನ್ನು {2} ನಲ್ಲಿ ಆಡುವುದನ್ನು ಮುಗಿಸಿದ್ದಾರೆ", "VersionNumber": "ಆವೃತ್ತಿ {0}", @@ -76,23 +56,17 @@ "TaskCleanTranscodeDescription": "ಒಂದು ದಿನಕ್ಕಿಂತ ಹಳೆಯದಾದ ಟ್ರಾನ್ಸ್ಕೋಡ್ ಫೈಲ್ಗಳನ್ನು ಅಳಿಸುತ್ತದೆ.", "TaskDownloadMissingSubtitles": "ಕಾಣೆಯಾದ ಉಪಶೀರ್ಷಿಕೆಗಳನ್ನು ಡೌನ್ಲೋಡ್ ಮಾಡಿ", "Shows": "ಧಾರವಾಹಿಗಳು", - "Songs": "ಹಾಡುಗಳು", "StartupEmbyServerIsLoading": "ಜೆಲ್ಲಿಫಿನ್ ಸರ್ವರ್ ಲೋಡ್ ಆಗುತ್ತಿದೆ. ದಯವಿಟ್ಟು ಸ್ವಲ್ಪ ಸಮಯದ ನಂತರ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ.", "UserDeletedWithName": "ಬಳಕೆದಾರ {0} ಅನ್ನು ಅಳಿಸಲಾಗಿದೆ", "UserDownloadingItemWithValues": "{0} ಡೌನ್ಲೋಡ್ ಆಗುತ್ತಿದೆ {1}", "SubtitleDownloadFailureFromForItem": "ಉಪಶೀರ್ಷಿಕೆಗಳು {0} ನಿಂದ {1} ಗಾಗಿ ಡೌನ್ಲೋಡ್ ಮಾಡಲು ವಿಫಲವಾಗಿವೆ", - "Sync": "ಹೊಂದಿಕೆ", - "System": "ವ್ಯವಸ್ಥೆ", "TvShows": "ದೂರದರ್ಶನ ಕಾರ್ಯಕ್ರಮಗಳು", "Undefined": "ವ್ಯಾಖ್ಯಾನಿಸಲಾಗಿಲ್ಲ", - "User": "ಬಳಕೆದಾರ", "HomeVideos": "ಮುಖಪುಟ ವೀಡಿಯೊಗಳು", "Inherit": "ಪಾರಂಪರ್ಯವಾಗಿ", - "ItemRemovedWithName": "{0} ಅನ್ನು ಸಂಕಲನದಿಂದ ತೆಗೆದುಹಾಕಲಾಗಿದೆ", "LabelIpAddressValue": "IP ವಿಳಾಸ: {0}", "LabelRunningTimeValue": "ಅವಧಿ: {0}", "Latest": "ಹೊಸದಾದ", - "MessageServerConfigurationUpdated": "ಸರ್ವರ್ ಕಾನ್ಫಿಗರೇಶನ್ ಅನ್ನು ನವೀಕರಿಸಲಾಗಿದೆ", "MixedContent": "ಮಿಶ್ರ ವಿಷಯ", "Movies": "ಚಲನಚಿತ್ರಗಳು", "Music": "ಸಂಗೀತ", @@ -106,17 +80,14 @@ "NotificationOptionInstallationFailed": "ಸ್ಥಾಪನ ವೈಫಲ್ಯ", "NotificationOptionNewLibraryContent": "ಹೊಸ ವಿಷಯವನ್ನು ಒಳಗೊಂಡಿದೆ", "NotificationOptionPluginError": "ಪ್ಲಗಿನ್ ವೈಫಲ್ಯ", - "NotificationOptionPluginInstalled": "ಪ್ಲಗಿನ್ ವೈಫಲ್ಯ", + "NotificationOptionPluginInstalled": "ಪ್ಲಗಿನ್ ಸ್ಥಾಪಿಸಲಾಗಿದೆ", "NotificationOptionPluginUpdateInstalled": "ಪ್ಲಗಿನ್ ನವೀಕರಣವನ್ನು ಸ್ಥಾಪಿಸಲಾಗಿದೆ", "NotificationOptionServerRestartRequired": "ಸರ್ವರ್ ಮರುಪ್ರಾರಂಭದ ಅಗತ್ಯವಿದೆ", "NotificationOptionTaskFailed": "ನಿಗದಿತ ಕಾರ್ಯ ವೈಫಲ್ಯ", "NotificationOptionVideoPlayback": "ವೀಡಿಯೊ ಪ್ಲೇಬ್ಯಾಕ್ ಪ್ರಾರಂಭವಾಗಿದೆ", "Photos": "ಚಿತ್ರಗಳು", - "Playlists": "ಪ್ಲೇಪಟ್ಟಿಗಳು", - "Plugin": "ಪ್ಲಗಿನ್", "PluginInstalledWithName": "{0} ಅನ್ನು ಸ್ಥಾಪಿಸಲಾಗಿದೆ", "PluginUpdatedWithName": "{0} ಅನ್ನು ನವೀಕರಿಸಲಾಗಿದೆ", - "ProviderValue": "ಒದಗಿಸುವವರು: {0}", "TaskCleanLogs": "ಕ್ಲೀನ್ ಲಾಗ್ ಡೈರೆಕ್ಟರಿ", "TaskRefreshPeople": "ಜನರನ್ನು ರಿಫ್ರೆಶ್ ಮಾಡಿ", "TaskRefreshPeopleDescription": "ನಿಮ್ಮ ಮಾಧ್ಯಮ ಲೈಬ್ರರಿಯಲ್ಲಿ ನಟರು ಮತ್ತು ನಿರ್ದೇಶಕರಿಗಾಗಿ ಮೆಟಾಡೇಟಾವನ್ನು ನವೀಕರಿಸಿ.", diff --git a/Emby.Server.Implementations/Localization/Core/ko.json b/Emby.Server.Implementations/Localization/Core/ko.json index 0451dcc9f0..a210125d34 100644 --- a/Emby.Server.Implementations/Localization/Core/ko.json +++ b/Emby.Server.Implementations/Localization/Core/ko.json @@ -1,41 +1,24 @@ { - "Albums": "앨범", "AppDeviceValues": "앱: {0}, 장치: {1}", - "Application": "애플리케이션", "Artists": "아티스트", "AuthenticationSucceededWithUserName": "{0} 사용자가 성공적으로 인증됨", "Books": "도서", - "CameraImageUploadedFrom": "{0}에서 새로운 카메라 이미지가 업로드됨", - "Channels": "채널", "ChapterNameValue": "챕터 {0}", "Collections": "컬렉션", - "DeviceOfflineWithName": "{0}의 연결 끊김", - "DeviceOnlineWithName": "{0}이(가) 연결됨", "FailedLoginAttemptWithUserName": "{0}에서 로그인 실패", "Favorites": "즐겨찾기", "Folders": "폴더", "Genres": "장르", - "HeaderAlbumArtists": "앨범 음악가", "HeaderContinueWatching": "계속 시청하기", - "HeaderFavoriteAlbums": "즐겨찾는 앨범", - "HeaderFavoriteArtists": "즐겨찾는 아티스트", "HeaderFavoriteEpisodes": "즐겨찾는 에피소드", "HeaderFavoriteShows": "즐겨찾는 쇼", - "HeaderFavoriteSongs": "즐겨찾는 노래", "HeaderLiveTV": "실시간 TV", "HeaderNextUp": "다음으로", - "HeaderRecordingGroups": "녹화 그룹", "HomeVideos": "홈 비디오", "Inherit": "상속", - "ItemAddedWithName": "{0}가 라이브러리에 추가되었습니다", - "ItemRemovedWithName": "{0}가 라이브러리에서 제거됨", "LabelIpAddressValue": "IP 주소: {0}", "LabelRunningTimeValue": "상영 시간: {0}", "Latest": "최근", - "MessageApplicationUpdated": "Jellyfin 서버가 업데이트되었습니다", - "MessageApplicationUpdatedTo": "Jellyfin 서버가 {0}로 업데이트되었습니다", - "MessageNamedServerConfigurationUpdatedWithValue": "서버 환경 설정 {0} 섹션이 업데이트되었습니다", - "MessageServerConfigurationUpdated": "서버 환경 설정이 업데이트되었습니다", "MixedContent": "혼합 콘텐츠", "Movies": "영화", "Music": "음악", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "비디오 재생 시작됨", "NotificationOptionVideoPlaybackStopped": "비디오 재생 중지됨", "Photos": "사진", - "Playlists": "재생목록", - "Plugin": "플러그인", "PluginInstalledWithName": "{0} 설치됨", "PluginUninstalledWithName": "{0} 제거됨", "PluginUpdatedWithName": "{0} 업데이트됨", - "ProviderValue": "제공자: {0}", "ScheduledTaskFailedWithName": "{0} 실패", - "ScheduledTaskStartedWithName": "{0} 시작", - "ServerNameNeedsToBeRestarted": "{0}를 재시작해야합니다", "Shows": "시리즈", - "Songs": "노래", "StartupEmbyServerIsLoading": "Jellyfin 서버를 불러오고 있습니다. 잠시 후에 다시 시도하십시오.", "SubtitleDownloadFailureFromForItem": "{0}에서 {1} 자막 다운로드에 실패했습니다", - "Sync": "동기화", - "System": "시스템", "TvShows": "TV 쇼", - "User": "사용자", "UserCreatedWithName": "사용자 {0} 생성됨", "UserDeletedWithName": "사용자 {0} 삭제됨", "UserDownloadingItemWithValues": "{0} 사용자가 {1} 다운로드 중", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "{0} 사용자의 {1}에서 연결이 끊김", "UserOnlineFromDevice": "{0} 사용자가 {1}에서 접속함", "UserPasswordChangedWithName": "{0} 사용자 비밀번호 변경됨", - "UserPolicyUpdatedWithName": "{0} 사용자 정책 업데이트됨", "UserStartedPlayingItemWithValues": "{0} 사용자의 {2}에서 {1} 재생 중", "UserStoppedPlayingItemWithValues": "{0} 사용자의 {2}에서 {1} 재생을 마침", - "ValueHasBeenAddedToLibrary": "{0}가 미디어 라이브러리에 추가되었습니다", - "ValueSpecialEpisodeName": "스페셜 - {0}", "VersionNumber": "버전 {0}", "TasksApplicationCategory": "어플리케이션", "TasksMaintenanceCategory": "유지 보수", @@ -135,5 +106,7 @@ "TaskDownloadMissingLyrics": "누락된 가사 다운로드", "TaskDownloadMissingLyricsDescription": "가사 다운로드", "CleanupUserDataTask": "사용자 데이터 정리 작업", - "CleanupUserDataTaskDescription": "최소 90일 이상 존재하지 않는 미디어에 대한 사용자 데이터(시청 상태, 즐겨찾기 등)를 정리합니다." + "CleanupUserDataTaskDescription": "최소 90일 이상 존재하지 않는 미디어에 대한 사용자 데이터(시청 상태, 즐겨찾기 등)를 정리합니다.", + "LyricDownloadFailureFromForItem": "{1}에 대한 가사를 {0}에서 다운로드하지 못했습니다", + "Original": "원본" } diff --git a/Emby.Server.Implementations/Localization/Core/kw.json b/Emby.Server.Implementations/Localization/Core/kw.json index 613d531103..fc2e189e7f 100644 --- a/Emby.Server.Implementations/Localization/Core/kw.json +++ b/Emby.Server.Implementations/Localization/Core/kw.json @@ -1,21 +1,13 @@ { "Collections": "Kuntellow", - "DeviceOfflineWithName": "{0} re anjunyas", "External": "A-ves", "Folders": "Plegellow", - "HeaderFavoriteAlbums": "Albomow Drudh", - "HeaderFavoriteArtists": "Artydhyon Drudh", "HeaderFavoriteEpisodes": "Towlennow Drudh", - "HeaderFavoriteSongs": "Kanow Drudh", - "HeaderRecordingGroups": "Bagasow Rekordya", "HearingImpaired": "Klewans Aperys", "HomeVideos": "Gwydhyow Tre", "Inherit": "Herya", "LabelRunningTimeValue": "Prys ow ponya: {0}", "Latest": "Diwettha", - "MessageApplicationUpdated": "Servell Jellyfin re beu nowedhys", - "MessageApplicationUpdatedTo": "Servell Jellyfin re beu nowedhys dhe {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "Rann dewisyans servell {0} re beu nowedhys", "MixedContent": "Dalgh kemmyskys", "Movies": "Fylmow", "MusicVideos": "Gwydhyow Ilow", @@ -25,23 +17,16 @@ "NotificationOptionPluginError": "Defowt ystynnans", "NotificationOptionPluginUninstalled": "Ystynnans anynstallys", "NotificationOptionPluginUpdateInstalled": "Nowedheans ystynnans ynstallys", - "Application": "Gweythres", "Favorites": "Moyha Kerys", "Forced": "Konstrynys", - "Albums": "Albomow", "Books": "Lyvrow", - "Channels": "Kanolyow", "AppDeviceValues": "App: {0}, Devis: {1}", "Artists": "Artyhdyon", - "HeaderAlbumArtists": "Albom artydhyon", "HeaderNextUp": "Nessa", - "CameraImageUploadedFrom": "Skeusen kamera nowydh re beu ughkargys a-dhyworth {0}", "ChapterNameValue": "Chaptra {0}", "FailedLoginAttemptWithUserName": "Assay omgelm fyllys a-dhyworth {0}", "AuthenticationSucceededWithUserName": "{0} omgelmys yn sewen", "Default": "Defowt", - "DeviceOnlineWithName": "{0} yw junys", - "ItemRemovedWithName": "{0} a veu dileys a-dhyworth an lyverva", "LabelIpAddressValue": "Trigva PK: {)}", "Music": "Ilow", "HeaderContinueWatching": "Pesya Ow Kweles", @@ -50,8 +35,6 @@ "NotificationOptionCameraImageUploaded": "Skeusen kamera ughkargys", "HeaderFavoriteShows": "Diskwedhyansow Drudh", "HeaderLiveTV": "PW Yn Fyw", - "MessageServerConfigurationUpdated": "Dewisyans servell re beu nowedhys", - "ItemAddedWithName": "{0} a veu keworrys dhe'n lyverva", "NameInstallFailed": "{0} ynstallyans fyllys", "NotificationOptionNewLibraryContent": "Dalgh nowydh keworrys", "NewVersionIsAvailable": "Yma versyon nowydh a Servell Jellyfin neb yw kavadow rag iskarga.", @@ -62,8 +45,6 @@ "NotificationOptionServerRestartRequired": "Dastalleth servell yw res", "StartupEmbyServerIsLoading": "Yma Servell Jellyfin ow kargya. Assay arta yn berr mar pleg.", "SubtitleDownloadFailureFromForItem": "Istitlow a fyllis iskarga a-dhyworth {0] rag {1}", - "System": "Kevreyth", - "User": "Devnydhyer", "UserDeletedWithName": "Devnydhyer {0} re beu dileys", "UserLockedOutWithName": "Devnydhyer {0} re beu alhwedhys yn-mes", "UserStoppedPlayingItemWithValues": "{0} re worfennas gwari {1} war {2}", @@ -71,21 +52,15 @@ "UserOnlineFromDevice": "{0} yw warlinen a-dhyworth {1}", "NotificationOptionUserLockedOut": "Devnydhyer yw alhwedhys yn-mes", "Photos": "Skeusennow", - "Playlists": "Rolyow-gwari", - "Plugin": "Ystynnans", "PluginInstalledWithName": "{0} a veu ynstallys", - "UserPolicyUpdatedWithName": "Polici devnydhyer re beu nowedhys rag {0}", "PluginUpdatedWithName": "{0} a veu nowedhys", "ScheduledTaskFailedWithName": "{0} a fyllis", - "Songs": "Kanow", - "Sync": "Kesseni", "TvShows": "Towlennow PW", "Undefined": "Anstyrys", "UserCreatedWithName": "Devnydhyer {0} re beu gwruthys", "UserDownloadingItemWithValues": "Yma {0} owth iskarga {1}", "UserPasswordChangedWithName": "Ger-tremena re beu chanjys rag devnydhyer {0}", "UserStartedPlayingItemWithValues": "Yma {0} ow kwari {1} war {2}", - "ValueHasBeenAddedToLibrary": "{0} re beu keworrys dhe'th lyverva media", "VersionNumber": "Versyon {0}", "TasksLibraryCategory": "Lyverva", "TaskCleanActivityLog": "Glanhe Kovlyver Gwrians", @@ -96,10 +71,6 @@ "NotificationOptionVideoPlayback": "Gwareans gwydhyow yw dallethys", "PluginUninstalledWithName": "{0} a veu anynstallys", "NotificationOptionTaskFailed": "Defowt oberen towlennys", - "ProviderValue": "Provier: {0}", - "ScheduledTaskStartedWithName": "{0} a dhallathas", - "ServerNameNeedsToBeRestarted": "Yma edhom dhe {0} a vos dastallathys", - "ValueSpecialEpisodeName": "Arbennik - {0}", "TasksMaintenanceCategory": "Mentons", "TasksApplicationCategory": "Gweythres", "TasksChannelsCategory": "Kanolyow Kesrosweyth", diff --git a/Emby.Server.Implementations/Localization/Core/lb.json b/Emby.Server.Implementations/Localization/Core/lb.json index 2afec05dbd..e94709b083 100644 --- a/Emby.Server.Implementations/Localization/Core/lb.json +++ b/Emby.Server.Implementations/Localization/Core/lb.json @@ -1,38 +1,24 @@ { - "Albums": "Alben", - "Application": "Applikatioun", "Artists": "Kënschtler", "Books": "Bicher", - "Channels": "Kanäl", "Collections": "Kollektiounen", "Default": "Standard", "ChapterNameValue": "Kapitel {0}", - "DeviceOnlineWithName": "{0} ass Online", - "DeviceOfflineWithName": "{0} ass Offline", "External": "Extern", "Favorites": "Favoritten", "Folders": "Dossieren", "Forced": "Forcéiert", - "HeaderAlbumArtists": "Album Kënschtler", - "HeaderFavoriteAlbums": "Léifsten Alben", - "HeaderFavoriteArtists": "Léifsten Kënschtler", "HeaderFavoriteEpisodes": "Léifsten Episoden", "HeaderFavoriteShows": "Léifsten Shows", - "HeaderFavoriteSongs": "Léifsten Lidder", "Genres": "Generen", "HeaderContinueWatching": "Weider kucken", "Inherit": "Iwwerhuelen", "HeaderNextUp": "Als Nächst", - "HeaderRecordingGroups": "Opname Gruppen", "HearingImpaired": "Daaf", "HomeVideos": "Amateur Videoen", - "ItemRemovedWithName": "Element ewech geholl: {0}", "LabelIpAddressValue": "IP Adress: {0}", "LabelRunningTimeValue": "Lafzäit: {0}", "Latest": "Dat Aktuellst", - "MessageApplicationUpdatedTo": "Jellyfin Server aktualiséiert op {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "Server Konfiguratiounssektioun {0} aktualiséiert", - "MessageServerConfigurationUpdated": "Server Konfiguratioun aktualiséiert", "Movies": "Filmer", "Music": "Musek", "NameInstallFailed": "{0} Installatioun net gelongen", @@ -55,19 +41,11 @@ "NotificationOptionUserLockedOut": "Benotzer Gesperrt", "NotificationOptionVideoPlaybackStopped": "Video ofspillen gestoppt", "NotificationOptionVideoPlayback": "Video ofspillen gestartet", - "Plugin": "Plugin", "PluginUninstalledWithName": "{0} desinstalléiert", "PluginUpdatedWithName": "{0} aktualiséiert", - "ProviderValue": "Provider: {0}", "ScheduledTaskFailedWithName": "Aufgab: {0} net gelongen", - "Playlists": "Playlëschten", "Shows": "Shows", - "Songs": "Lidder", - "ServerNameNeedsToBeRestarted": "{0} muss nei gestart ginn", "StartupEmbyServerIsLoading": "Jellyfin Server luedt. Probéier méi spéit nach eng Kéier.", - "Sync": "Synchroniséieren", - "System": "System", - "User": "Benotzer", "TvShows": "TV Shows", "Undefined": "Net definéiert", "UserCreatedWithName": "Benotzer {0} erstellt", @@ -76,13 +54,10 @@ "UserLockedOutWithName": "Benotzer {0} gesperrt", "UserOnlineFromDevice": "{0} Benotzer Online um Gerät {1}", "UserPasswordChangedWithName": "Benotzer Passwuert geännert fir {0}", - "UserPolicyUpdatedWithName": "Benotzer Politik aktualiséiert fir: {0}", "UserStartedPlayingItemWithValues": "{0} spillt {1} op {2} oof", - "ValueHasBeenAddedToLibrary": "{0} der Bibliothéik bäigefüügt", "VersionNumber": "Versioun {0}", "TasksMaintenanceCategory": "Ënnerhalt", "TasksLibraryCategory": "Bibliothéik", - "ValueSpecialEpisodeName": "Spezial-Episodenumm", "TasksChannelsCategory": "Internet Kanäl", "TaskCleanActivityLog": "Aktivitéits Log botzen", "TaskCleanActivityLogDescription": "Läscht Aktivitéitslogs méi al wéi konfiguréiert.", @@ -106,18 +81,14 @@ "TaskKeyframeExtractor": "Schlësselbild Extrakter", "TaskExtractMediaSegments": "Mediesegment-Scan", "NewVersionIsAvailable": "Nei Versioun fir Jellyfin Server ass verfügbar.", - "CameraImageUploadedFrom": "En neit Kamera Bild gouf vu {0} eropgelueden", "PluginInstalledWithName": "{0} installéiert", "TaskMoveTrickplayImagesDescription": "Verschëfft existent Trickplay-Dateien no de Bibliothéik-Astellungen.", "AppDeviceValues": "App: {0}, Geräter: {1}", "FailedLoginAttemptWithUserName": "Net Gelongen Umeldung {0}", "HeaderLiveTV": "LiveTV", - "ItemAddedWithName": "Element derbäi gesat: {0}", "NotificationOptionServerRestartRequired": "Server Restart Erfuerderlech", - "ScheduledTaskStartedWithName": "Aufgab: {0} gestart", "AuthenticationSucceededWithUserName": "{0} Authentifikatioun gelongen", "MixedContent": "Gemëschten Inhalt", - "MessageApplicationUpdated": "Jellyfin Server Aktualiséiert", "SubtitleDownloadFailureFromForItem": "Ënnertitel Download Feeler vun {0} fir {1}", "TaskCleanLogsDescription": "Läscht Log-Dateien, déi méi al wéi {0} Deeg sinn.", "TaskUpdatePlugins": "Plugins aktualiséieren", diff --git a/Emby.Server.Implementations/Localization/Core/lt-LT.json b/Emby.Server.Implementations/Localization/Core/lt-LT.json index daff719ea7..ed26004a43 100644 --- a/Emby.Server.Implementations/Localization/Core/lt-LT.json +++ b/Emby.Server.Implementations/Localization/Core/lt-LT.json @@ -1,41 +1,24 @@ { - "Albums": "Albumai", "AppDeviceValues": "Programa: {0}, Įrenginys: {1}", - "Application": "Programėlė", "Artists": "Atlikėjai", "AuthenticationSucceededWithUserName": "{0} sėkmingai autentifikuota", "Books": "Knygos", - "CameraImageUploadedFrom": "Nauja nuotrauka įkelta iš kameros {0}", - "Channels": "Kanalai", "ChapterNameValue": "Scena{0}", "Collections": "Rinkiniai", - "DeviceOfflineWithName": "{0} buvo atjungtas", - "DeviceOnlineWithName": "{0} prisijungęs", "FailedLoginAttemptWithUserName": "Nesėkmingas {0} bandymas prisijungti", "Favorites": "Mėgstami", "Folders": "Katalogai", "Genres": "Žanrai", - "HeaderAlbumArtists": "Albumo atlikėjai", "HeaderContinueWatching": "Žiūrėti toliau", - "HeaderFavoriteAlbums": "Mėgstami albumai", - "HeaderFavoriteArtists": "Mėgstami atlikėjai", "HeaderFavoriteEpisodes": "Mėgstamiausios serijos", "HeaderFavoriteShows": "Mėgstamiausios TV Laidos", - "HeaderFavoriteSongs": "Mėgstamos Dainos", "HeaderLiveTV": "Tiesioginė TV", "HeaderNextUp": "Toliau", - "HeaderRecordingGroups": "Įrašų grupės", "HomeVideos": "Namų vaizdo įrašai", "Inherit": "Paveldėti", - "ItemAddedWithName": "{0} - buvo įkeltas į biblioteką", - "ItemRemovedWithName": "{0} - buvo pašalinta iš bibliotekos", "LabelIpAddressValue": "IP adresas: {0}", "LabelRunningTimeValue": "Trukmė: {0}", "Latest": "Naujausi", - "MessageApplicationUpdated": "\"Jellyfin Server\" atnaujintas", - "MessageApplicationUpdatedTo": "\"Jellyfin Server\" buvo atnaujinta iki {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "Serverio nustatymai (skyrius {0}) buvo atnaujinti", - "MessageServerConfigurationUpdated": "Serverio nustatymai buvo atnaujinti", "MixedContent": "Mišrus turinys", "Movies": "Filmai", "Music": "Muzika", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "Vaizdo įrašo atkūrimas pradėtas", "NotificationOptionVideoPlaybackStopped": "Vaizdo įrašo atkūrimas sustabdytas", "Photos": "Nuotraukos", - "Playlists": "Grojaraščiai", - "Plugin": "Įskiepis", "PluginInstalledWithName": "{0} buvo įdiegtas", "PluginUninstalledWithName": "{0} buvo pašalintas", "PluginUpdatedWithName": "{0} buvo atnaujintas", - "ProviderValue": "Paslaugos tiekėjas: {0}", "ScheduledTaskFailedWithName": "{0} nepavyko", - "ScheduledTaskStartedWithName": "{0} paleista", - "ServerNameNeedsToBeRestarted": "{0} reikia iš naujo paleisti", "Shows": "Laidos", - "Songs": "Kūriniai", "StartupEmbyServerIsLoading": "Jellyfin Server kraunasi. Netrukus pabandykite dar kartą.", "SubtitleDownloadFailureFromForItem": "{1} subtitrai buvo nesėkmingai parsiųsti iš {0}", - "Sync": "Sinchronizuoti", - "System": "Sistema", "TvShows": "TV laidos", - "User": "Naudotojas", "UserCreatedWithName": "Buvo sukurtas {0} naudotojas", "UserDeletedWithName": "Naudotojas {0} ištrintas", "UserDownloadingItemWithValues": "{0} siunčiasi {1}", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "{0} buvo atjungtas nuo {1}", "UserOnlineFromDevice": "{0} prisijungęs iš {1}", "UserPasswordChangedWithName": "Slaptažodis pakeistas naudotojui {0}", - "UserPolicyUpdatedWithName": "Naudotojo {0} teisės buvo pakeistos", "UserStartedPlayingItemWithValues": "{0} leidžia {1} į {2}", "UserStoppedPlayingItemWithValues": "{0} baigė leisti {1} į {2}", - "ValueHasBeenAddedToLibrary": "{0} pridėtas į mediateką", - "ValueSpecialEpisodeName": "Ypatingų - {0}", "VersionNumber": "Versija {0}", "TaskUpdatePluginsDescription": "Atsisiunčia ir įdiegia įskiepių, kurie sukonfigūruoti atnaujinti automatiškai, naujinius.", "TaskUpdatePlugins": "Atnaujinti įskieius", diff --git a/Emby.Server.Implementations/Localization/Core/lv.json b/Emby.Server.Implementations/Localization/Core/lv.json index 4bf6ed4752..4a1b248e76 100644 --- a/Emby.Server.Implementations/Localization/Core/lv.json +++ b/Emby.Server.Implementations/Localization/Core/lv.json @@ -1,15 +1,10 @@ { - "ServerNameNeedsToBeRestarted": "{0} ir vajadzīgs restarts", "NotificationOptionTaskFailed": "Plānota uzdevuma kļūme", - "HeaderRecordingGroups": "Ierakstu grupas", - "UserPolicyUpdatedWithName": "Lietotāju politika atjaunota priekš {0}", "SubtitleDownloadFailureFromForItem": "Subtitru lejupielāde no {0} priekš {1} neizdevās", "NotificationOptionVideoPlaybackStopped": "Video atskaņošana apturēta", "NotificationOptionVideoPlayback": "Video atskaņošana sākta", "NotificationOptionInstallationFailed": "Instalācija neizdevās", "AuthenticationSucceededWithUserName": "{0} veiksmīgi autentificējies", - "ValueSpecialEpisodeName": "Speciālais - {0}", - "ScheduledTaskStartedWithName": "{0} iesākts", "ScheduledTaskFailedWithName": "{0} neizdevās", "Photos": "Attēli", "NotificationOptionUserLockedOut": "Lietotājs bloķēts", @@ -17,7 +12,6 @@ "Inherit": "Pārmantot", "AppDeviceValues": "Lietotne: {0}, Ierīce: {1}", "VersionNumber": "Versija {0}", - "ValueHasBeenAddedToLibrary": "{0} tika pievienots jūsu multvides bibliotēkai", "UserStoppedPlayingItemWithValues": "{0} ir beidzis atskaņot {1} uz {2}", "UserStartedPlayingItemWithValues": "{0} atskaņo {1} uz {2}", "UserPasswordChangedWithName": "Lietotāja {0} parole tika nomainīta", @@ -27,23 +21,16 @@ "UserDownloadingItemWithValues": "{0} lejupielādē {1}", "UserDeletedWithName": "Lietotājs {0} ir izdzēsts", "UserCreatedWithName": "Lietotājs {0} ir ticis izveidots", - "User": "Lietotājs", "TvShows": "TV raidījumi", - "Sync": "Sinhronizācija", - "System": "Sistēma", "StartupEmbyServerIsLoading": "Jellyfin Serveris lādējas. Lūdzu mēģiniet vēlreiz pēc brīža.", - "Songs": "Dziesmas", "Shows": "Šovi", "PluginUpdatedWithName": "{0} tika atjaunots", "PluginUninstalledWithName": "{0} tika noņemts", "PluginInstalledWithName": "{0} tika uzstādīts", - "Plugin": "Paplašinājums", - "Playlists": "Atskaņošanas saraksti", "MixedContent": "Jaukts saturs", "HomeVideos": "Mājas video", "HeaderNextUp": "Nākamais", "ChapterNameValue": "{0}. nodaļa", - "Application": "Lietotne", "NotificationOptionServerRestartRequired": "Nepieciešams servera restarts", "NotificationOptionPluginUpdateInstalled": "Paplašinājuma atjauninājums uzstādīts", "NotificationOptionPluginUninstalled": "Paplašinājums noņemts", @@ -62,35 +49,19 @@ "MusicVideos": "Mūzikas video", "Music": "Mūzika", "Movies": "Filmas", - "MessageServerConfigurationUpdated": "Servera konfigurācija ir tikusi atjaunota", - "MessageNamedServerConfigurationUpdatedWithValue": "Servera konfigurācijas sadaļa {0} tika atjaunota", - "MessageApplicationUpdatedTo": "Jellyfin Server ir ticis atjaunots uz {0}", - "MessageApplicationUpdated": "Jellyfin Server ir ticis atjaunots", "Latest": "Jaunākais", "LabelIpAddressValue": "IP adrese: {0}", - "ItemRemovedWithName": "{0} tika noņemts no bibliotēkas", - "ItemAddedWithName": "{0} tika pievienots bibliotēkai", "HeaderLiveTV": "Tiešraides TV", "HeaderContinueWatching": "Turpini skatīties", - "HeaderAlbumArtists": "Albumu izpildītāji", "Genres": "Žanri", "Folders": "Mapes", "Favorites": "Izlase", "FailedLoginAttemptWithUserName": "Neizdevies ieiešanas mēģinājums no {0}", - "DeviceOnlineWithName": "Savienojums ar {0} ir izveidots", - "DeviceOfflineWithName": "Savienojums ar {0} ir pārtraukts", "Collections": "Kolekcijas", - "Channels": "Kanāli", - "CameraImageUploadedFrom": "Jauns kameras attēls tika augšupielādēts no {0}", "Books": "Grāmatas", "Artists": "Izpildītāji", - "Albums": "Albumi", - "ProviderValue": "Provider: {0}", - "HeaderFavoriteSongs": "Dziesmu izlase", "HeaderFavoriteShows": "Raidījumu izlase", "HeaderFavoriteEpisodes": "Sēriju izlase", - "HeaderFavoriteArtists": "Izpildītāju izlase", - "HeaderFavoriteAlbums": "Albumu izlase", "TaskCleanCacheDescription": "Nodzēš kešatmiņas datnes, kas vairs nav sistēmai vajadzīgas.", "TaskRefreshChapterImages": "Izvilkt nodaļu attēlus", "TasksApplicationCategory": "Lietotne", diff --git a/Emby.Server.Implementations/Localization/Core/lzh.json b/Emby.Server.Implementations/Localization/Core/lzh.json index 9fb53e41d5..6b61755d12 100644 --- a/Emby.Server.Implementations/Localization/Core/lzh.json +++ b/Emby.Server.Implementations/Localization/Core/lzh.json @@ -1,10 +1,8 @@ { - "Albums": "辑册", "Artists": "艺人", "AuthenticationSucceededWithUserName": "{0} 授之权矣", "Books": "册", "Genres": "类", - "HeaderAlbumArtists": "辑者", "Favorites": "至爱", "Folders": "箧", "HeaderContinueWatching": "接目未竟" diff --git a/Emby.Server.Implementations/Localization/Core/mi.json b/Emby.Server.Implementations/Localization/Core/mi.json index 3b20abb369..74fae52dca 100644 --- a/Emby.Server.Implementations/Localization/Core/mi.json +++ b/Emby.Server.Implementations/Localization/Core/mi.json @@ -1,9 +1,15 @@ { - "Albums": "Pukaemi", "AppDeviceValues": "Taupānga: {0}, Pūrere: {1}", - "Application": "Taupānga", "Artists": "Kaiwaiata", "AuthenticationSucceededWithUserName": "{0} has been successfully authenticated", "Books": "Ngā pukapuka", - "CameraImageUploadedFrom": "Kua tuku ake he whakaahua kāmera hou mai i {0}" + "Default": "Taunoa", + "Collections": "Kohinga", + "External": "Waho", + "Folders": "Kōpaki", + "Forced": "Kaha", + "Music": "Waiata", + "Movies": "Kiriata", + "Latest": "Hou", + "Inherit": "Riro" } diff --git a/Emby.Server.Implementations/Localization/Core/mk.json b/Emby.Server.Implementations/Localization/Core/mk.json index efef194e14..daf8112eef 100644 --- a/Emby.Server.Implementations/Localization/Core/mk.json +++ b/Emby.Server.Implementations/Localization/Core/mk.json @@ -1,11 +1,8 @@ { "ScheduledTaskFailedWithName": "{0} неуспешно", - "ProviderValue": "Провајдер: {0}", "PluginUpdatedWithName": "{0} беше надоградено", "PluginUninstalledWithName": "{0} беше успешно деинсталирано", "PluginInstalledWithName": "{0} беше успешно инсталирано", - "Plugin": "Додатоци", - "Playlists": "Плејлисти", "Photos": "Слики", "NotificationOptionVideoPlaybackStopped": "Видео стопирано", "NotificationOptionVideoPlayback": "Видео пуштено", @@ -31,49 +28,29 @@ "Music": "Музика", "Movies": "Филмови", "MixedContent": "Мешана содржина", - "MessageServerConfigurationUpdated": "Серверската конфигурација беше надградена", - "MessageNamedServerConfigurationUpdatedWithValue": "Секцијата на конфигурација на сервер {0} беше надоградена", - "MessageApplicationUpdatedTo": "Jellyfin беше надограден до {0}", - "MessageApplicationUpdated": "Jellyfin Серверот беше надограден", "Latest": "Последно", "LabelRunningTimeValue": "Време на работа: {0}", "LabelIpAddressValue": "ИП Адреса: {0}", - "ItemRemovedWithName": "{0} е избришано до Библиотеката", - "ItemAddedWithName": "{0} беше додадено во Библиотеката", "Inherit": "Следно", "HomeVideos": "Домашни Видеа", - "HeaderRecordingGroups": "Групи на снимање", "HeaderNextUp": "Следно", "HeaderLiveTV": "ТВ", - "HeaderFavoriteSongs": "Омилени Песни", "HeaderFavoriteShows": "Омилени Серии", "HeaderFavoriteEpisodes": "Омилени Епизоди", - "HeaderFavoriteArtists": "Омилени Изведувачи", - "HeaderFavoriteAlbums": "Омилени Албуми", "HeaderContinueWatching": "Продолжи со Гледање", - "HeaderAlbumArtists": "Изведувачи од Албуми", "Genres": "Жанрови", "Folders": "Папки", "Favorites": "Омилени", "FailedLoginAttemptWithUserName": "Неуспешен обид за најавување од {0}", - "DeviceOnlineWithName": "{0} е приклучен", - "DeviceOfflineWithName": "{0} се исклучи", "Collections": "Колекции", "ChapterNameValue": "Дел {0}", - "Channels": "Канали", - "CameraImageUploadedFrom": "Нова слика од камера беше поставена од {0}", "Books": "Книги", "AuthenticationSucceededWithUserName": "{0} успешно поврзан", "Artists": "Изведувачи", - "Application": "Апликација", "AppDeviceValues": "Апликација: {0}, Уред: {1}", - "Albums": "Албуми", "VersionNumber": "Верзија {0}", - "ValueSpecialEpisodeName": "Специјално - {0}", - "ValueHasBeenAddedToLibrary": "{0} е додадено во твојата библиотека", "UserStoppedPlayingItemWithValues": "{0} заврши со репродукција {1} во {2}", "UserStartedPlayingItemWithValues": "{0} пушти {1} на {2}", - "UserPolicyUpdatedWithName": "Полисата на користење беше надоградена за {0}", "UserPasswordChangedWithName": "Лозинката е сменета за корисникот {0}", "UserOnlineFromDevice": "{0} е приклучен од {1}", "UserOfflineFromDevice": "{0} е дисконектиран од {1}", @@ -81,16 +58,10 @@ "UserDownloadingItemWithValues": "{0} се спушта {1}", "UserDeletedWithName": "Корисникот {0} е избришан", "UserCreatedWithName": "Корисникот {0} е креиран", - "User": "Корисник", "TvShows": "ТВ Серии", - "System": "Систем", - "Sync": "Синхронизација", "SubtitleDownloadFailureFromForItem": "Преводот неуспешно се спушти од {0} за {1}", "StartupEmbyServerIsLoading": "Jellyfin Server се пушта. Ве молиме причекајте.", - "Songs": "Песни", "Shows": "Серии", - "ServerNameNeedsToBeRestarted": "{0} треба да се рестартира", - "ScheduledTaskStartedWithName": "{0} започна", "TaskRefreshChapterImages": "Извези Слики од Поглавје", "TaskCleanCacheDescription": "Ги брише кешираните фајлови што не се повеќе потребни од системот.", "TaskCleanCache": "Исчисти Го Кешот", diff --git a/Emby.Server.Implementations/Localization/Core/ml.json b/Emby.Server.Implementations/Localization/Core/ml.json index 5f098bccac..dbf2ed4648 100644 --- a/Emby.Server.Implementations/Localization/Core/ml.json +++ b/Emby.Server.Implementations/Localization/Core/ml.json @@ -1,32 +1,18 @@ { "AppDeviceValues": "അപ്ലിക്കേഷൻ: {0}, ഉപകരണം: {1}", - "Application": "അപ്ലിക്കേഷൻ", "AuthenticationSucceededWithUserName": "{0} വിജയകരമായി പ്രാമാണീകരിച്ചു", - "CameraImageUploadedFrom": "{0} എന്നതിൽ നിന്ന് ഒരു പുതിയ ക്യാമറ ചിത്രം അപ്ലോഡുചെയ്തു", "ChapterNameValue": "അധ്യായം {0}", - "DeviceOfflineWithName": "{0} വിച്ഛേദിച്ചു", - "DeviceOnlineWithName": "{0} ബന്ധിപ്പിച്ചു", "FailedLoginAttemptWithUserName": "{0}ൽ നിന്നുള്ള പ്രവേശന ശ്രമം പരാജയപ്പെട്ടു", "Forced": "നിർബന്ധിതമായി", - "HeaderFavoriteAlbums": "പ്രിയപ്പെട്ട ആൽബങ്ങൾ", - "HeaderFavoriteArtists": "പ്രിയപ്പെട്ട കലാകാരന്മാർ", "HeaderFavoriteEpisodes": "പ്രിയപ്പെട്ട എപ്പിസോഡുകൾ", "HeaderFavoriteShows": "പ്രിയപ്പെട്ട ഷോകൾ", - "HeaderFavoriteSongs": "പ്രിയപ്പെട്ട ഗാനങ്ങൾ", "HeaderLiveTV": "തത്സമയ ടിവി", "HeaderNextUp": "അടുത്തത്", - "HeaderRecordingGroups": "ഗ്രൂപ്പുകൾ റെക്കോർഡുചെയ്യുന്നു", "HomeVideos": "ഹോം വീഡിയോകൾ", "Inherit": "അനന്തരാവകാശം", - "ItemAddedWithName": "{0} ലൈബ്രറിയിൽ ചേർത്തു", - "ItemRemovedWithName": "{0} ലൈബ്രറിയിൽ നിന്ന് നീക്കംചെയ്തു", "LabelIpAddressValue": "IP വിലാസം: {0}", "LabelRunningTimeValue": "പ്രവർത്തന സമയം: {0}", "Latest": "ഏറ്റവും പുതിയ", - "MessageApplicationUpdated": "ജെല്ലിഫിൻ സെർവർ അപ്ഡേറ്റുചെയ്തു", - "MessageApplicationUpdatedTo": "ജെല്ലിഫിൻ സെർവർ {0 to ലേക്ക് അപ്ഡേറ്റുചെയ്തു", - "MessageNamedServerConfigurationUpdatedWithValue": "സെർവർ കോൺഫിഗറേഷൻ വിഭാഗം {0 അപ്ഡേറ്റുചെയ്തു", - "MessageServerConfigurationUpdated": "സെർവർ കോൺഫിഗറേഷൻ അപ്ഡേറ്റുചെയ്തു", "MixedContent": "മിശ്രിത ഉള്ളടക്കം", "Music": "സംഗീതം", "MusicVideos": "സംഗീത വീഡിയോകൾ", @@ -50,20 +36,14 @@ "NotificationOptionUserLockedOut": "ഉപയോക്താവ് ലോക്ക് out ട്ട് ചെയ്തു", "NotificationOptionVideoPlayback": "വീഡിയോ പ്ലേബാക്ക് ആരംഭിച്ചു", "NotificationOptionVideoPlaybackStopped": "വീഡിയോ പ്ലേബാക്ക് നിർത്തി", - "Plugin": "പ്ലഗിൻ", "PluginInstalledWithName": "{0} ഇൻസ്റ്റാളുചെയ്തു", "PluginUninstalledWithName": "{0 un അൺഇൻസ്റ്റാൾ ചെയ്തു", "PluginUpdatedWithName": "{0} അപ്ഡേറ്റുചെയ്തു", - "ProviderValue": "ദാതാവ്: {0}", "ScheduledTaskFailedWithName": "{0} പരാജയപ്പെട്ടു", - "ScheduledTaskStartedWithName": "{0} ആരംഭിച്ചു", - "ServerNameNeedsToBeRestarted": "{0} പുനരാരംഭിക്കേണ്ടതുണ്ട്", "StartupEmbyServerIsLoading": "ജെല്ലിഫിൻ സെർവർ ലോഡുചെയ്യുന്നു. ഉടൻ തന്നെ വീണ്ടും ശ്രമിക്കുക.", "SubtitleDownloadFailureFromForItem": "സബ്ടൈറ്റിലുകൾ {1} ന് {0 from ൽ നിന്ന് ഡ download ൺലോഡ് ചെയ്യുന്നതിൽ പരാജയപ്പെട്ടു", - "System": "സിസ്റ്റം", "TvShows": "ടിവി ഷോകൾ", "Undefined": "നിർവചിച്ചിട്ടില്ല", - "User": "ഉപയോക്താവ്", "UserCreatedWithName": "ഉപയോക്താവ് {0 created സൃഷ്ടിച്ചു", "UserDeletedWithName": "ഉപയോക്താവ് {0 deleted ഇല്ലാതാക്കി", "UserDownloadingItemWithValues": "{0} ഡൗൺലോഡുചെയ്യുന്നു {1}", @@ -71,10 +51,8 @@ "UserOfflineFromDevice": "{0} {1} ൽ നിന്ന് വിച്ഛേദിച്ചു", "UserOnlineFromDevice": "{0} {1} മുതൽ ഓൺലൈനിലാണ്", "UserPasswordChangedWithName": "{0} ഉപയോക്താവിനായി പാസ്വേഡ് മാറ്റി", - "UserPolicyUpdatedWithName": "{0} എന്നതിനായി ഉപയോക്തൃ നയം അപ്ഡേറ്റുചെയ്തു", "UserStartedPlayingItemWithValues": "{0} {2} ൽ {1} പ്ലേ ചെയ്യുന്നു", "UserStoppedPlayingItemWithValues": "{0} {2} ൽ {1 play കളിക്കുന്നത് പൂർത്തിയാക്കി", - "ValueHasBeenAddedToLibrary": "Media 0 your നിങ്ങളുടെ മീഡിയ ലൈബ്രറിയിലേക്ക് ചേർത്തു", "VersionNumber": "പതിപ്പ് {0}", "TasksMaintenanceCategory": "പരിപാലനം", "TasksLibraryCategory": "പുസ്തകശാല", @@ -100,16 +78,10 @@ "TaskRefreshChannelsDescription": "ഇന്റർനെറ്റ് ചാനൽ വിവരങ്ങൾ പുതുക്കുന്നു.", "TaskDownloadMissingSubtitles": "നഷ്ടമായ സബ്ടൈറ്റിലുകൾ ഡൗൺലോഡുചെയ്യുക", "TaskDownloadMissingSubtitlesDescription": "മെറ്റാഡാറ്റ കോൺഫിഗറേഷനെ അടിസ്ഥാനമാക്കി നഷ്ടമായ സബ്ടൈറ്റിലുകൾക്കായി ഇന്റർനെറ്റ് തിരയുന്നു.", - "ValueSpecialEpisodeName": "പ്രത്യേക - {0}", "Collections": "ശേഖരങ്ങൾ", "Folders": "ഫോൾഡറുകൾ", - "HeaderAlbumArtists": "കലാകാരന്റെ ആൽബം", - "Sync": "സമന്വയിപ്പിക്കുക", "Movies": "സിനിമകൾ", "Photos": "ഫോട്ടോകൾ", - "Albums": "ആൽബങ്ങൾ", - "Playlists": "പ്ലേലിസ്റ്റുകൾ", - "Songs": "ഗാനങ്ങൾ", "HeaderContinueWatching": "കാണുന്നത് തുടരുക", "Artists": "കലാകാരന്മാർ", "Shows": "ഷോകൾ", @@ -117,7 +89,6 @@ "Favorites": "പ്രിയപ്പെട്ടവ", "Books": "പുസ്തകങ്ങൾ", "Genres": "വിഭാഗങ്ങൾ", - "Channels": "ചാനലുകൾ", "TaskOptimizeDatabaseDescription": "ഡാറ്റാബേസ് ചുരുക്കുകയും സ്വതന്ത്ര ഇടം വെട്ടിച്ചുരുക്കുകയും ചെയ്യുന്നു. ലൈബ്രറി സ്കാൻ ചെയ്തതിനുശേഷം അല്ലെങ്കിൽ ഡാറ്റാബേസ് പരിഷ്ക്കരണങ്ങളെ സൂചിപ്പിക്കുന്ന മറ്റ് മാറ്റങ്ങൾ ചെയ്തതിന് ശേഷം ഈ ടാസ്ക് പ്രവർത്തിപ്പിക്കുന്നത് പ്രകടനം മെച്ചപ്പെടുത്തും.", "TaskOptimizeDatabase": "ഡാറ്റാബേസ് ഒപ്റ്റിമൈസ് ചെയ്യുക", "HearingImpaired": "കേൾവി തകരാറുകൾ", @@ -127,5 +98,10 @@ "TaskAudioNormalization": "സാധാരണ ശബ്ദ നിലയിലെത്തിലെത്തിക്കുക", "TaskAudioNormalizationDescription": "സാധാരണ ശബ്ദ നിലയിലെത്തിലെത്തിക്കുന്ന ഡാറ്റയ്ക്കായി ഫയലുകൾ സ്കാൻ ചെയ്യുക.", "TaskRefreshTrickplayImages": "ട്രിക്ക് പ്ലേ ചിത്രങ്ങൾ സൃഷ്ടിക്കുക", - "TaskRefreshTrickplayImagesDescription": "പ്രവർത്തനക്ഷമമാക്കിയ ലൈബ്രറികളിൽ വീഡിയോകൾക്കായി ട്രിക്ക്പ്ലേ പ്രിവ്യൂകൾ സൃഷ്ടിക്കുന്നു." + "TaskRefreshTrickplayImagesDescription": "പ്രവർത്തനക്ഷമമാക്കിയ ലൈബ്രറികളിൽ വീഡിയോകൾക്കായി ട്രിക്ക്പ്ലേ പ്രിവ്യൂകൾ സൃഷ്ടിക്കുന്നു.", + "Original": "ഓറിജിനൽ", + "TaskDownloadMissingLyrics": "ഇല്ലാത്ത വരികൾ ഡൗൺലോഡ് ചെയ്യുക", + "TaskDownloadMissingLyricsDescription": "പാട്ടുകളുടെ വരികൾ ഡൗൺലോഡ് ചെയ്യുന്നു", + "TaskExtractMediaSegments": "മീഡിയ സെഗ്മെന്റ് സ്കാൻ", + "TaskExtractMediaSegmentsDescription": "മീഡിയസെഗ്മെന്റ് പ്രാപ്തമാക്കിയ പ്ലഗിനുകളിൽ നിന്ന് മീഡിയ സെഗ്മെന്റുകൾ എക്സ്ട്രാക്റ്റുചെയ്യുന്നു അല്ലെങ്കിൽ നേടുന്നു." } diff --git a/Emby.Server.Implementations/Localization/Core/mn.json b/Emby.Server.Implementations/Localization/Core/mn.json index 63f4d0cef3..83caaf346f 100644 --- a/Emby.Server.Implementations/Localization/Core/mn.json +++ b/Emby.Server.Implementations/Localization/Core/mn.json @@ -2,15 +2,12 @@ "Books": "Номнууд", "HeaderNextUp": "Дараа нь", "HeaderContinueWatching": "Үргэлжлүүлэн үзэх", - "Songs": "Дуунууд", - "Playlists": "Тоглуулах жагсаалтууд", "Movies": "Кинонууд", "Latest": "Сүүлийн үеийн", "Genres": "Төрлүүд", "Favorites": "Дуртай", "Collections": "Цуглуулгууд", "Artists": "Уран бүтээлчид", - "Albums": "Дуут цомгууд", "TaskExtractMediaSegments": "Медиа сегмент шалга", "TaskExtractMediaSegmentsDescription": "MediaSegment идэвхжүүлсэн залгаасуудаас медиа сегментүүдийг задлах эсвэл олж авах.", "TaskMoveTrickplayImages": "Трикплэй зургуудын байршлыг шилжүүлэх", @@ -21,7 +18,6 @@ "TaskKeyframeExtractor": "Түлхүүр кадр гаргагч", "TaskCleanCache": "Кэш санг цэвэрлэх", "NewVersionIsAvailable": "Jellyfin Server-н шинэ хувилбар татаж авахад нээлттэй боллоо.", - "MessageNamedServerConfigurationUpdatedWithValue": "Server-н {0}-р хэсгийн тохиргоо шинэчлэгдлээ", "NotificationOptionAudioPlaybackStopped": "Дууг зогсоов", "NotificationOptionNewLibraryContent": "Шинэ агуулга орлоо", "NotificationOptionServerRestartRequired": "Server-г дахин асаана уу", @@ -33,7 +29,6 @@ "SubtitleDownloadFailureFromForItem": "{0}-г {1}-д зориулсан хадмал орчуулгыг татаж авч чадсангүй", "TaskRefreshLibraryDescription": "Таны медиа санг шинэ файлуудын хувьд шалгаж, мета мэдээллийг шинэчилнэ.", "UserOfflineFromDevice": "{0}-г {1}-с салгалаа", - "ValueHasBeenAddedToLibrary": "{0}-г медиа сан руу нэмэгдлээ", "TaskRefreshPeopleDescription": "Таны медиа санд байгаа жүжигчид болон найруулагчдын мета мэдээллийг шинэчилнэ.", "TaskCleanTranscodeDescription": "Нэг өдрөөс илүү настай транскодлох файлуудыг устгана.", "TaskRefreshChannelsDescription": "Интернет сувгуудын мэдээллийг шинэчлэх.", @@ -51,36 +46,21 @@ "TaskRefreshChannels": "Сувгуудыг шинэчлэх", "TaskDownloadMissingSubtitles": "Алга болсон хадмал орчуулгыг татах", "External": "Гадны", - "HeaderFavoriteArtists": "Дуртай уран бүтээлчид", "HeaderFavoriteEpisodes": "Дуртай ангиуд", "HeaderFavoriteShows": "Дуртай нэвтрүүлэг", - "HeaderFavoriteSongs": "Дуртай дуу", "AppDeviceValues": "Aпп: {0}, Төхөөрөмж: {1}", - "Application": "Aпп", "AuthenticationSucceededWithUserName": "{0} амжилттай нэвтэрлээ", - "CameraImageUploadedFrom": "{0}-с шинэ зураг байршуулагдлаа", - "Channels": "Сувгууд", "ChapterNameValue": "{0}-р бүлэг", "Default": "Анхдагч", - "DeviceOfflineWithName": "{0}-н холболт саллаа", - "DeviceOnlineWithName": "{0} холбогдлоо", "FailedLoginAttemptWithUserName": "{0}-н нэвтрэх оролдлого амжилтгүй", "Folders": "Хавтасууд", "Forced": "Хүчээр", - "HeaderAlbumArtists": "Цомгийн уран бүтээлчид", - "HeaderFavoriteAlbums": "Дуртай цомгууд", "HeaderLiveTV": "Шууд ТВ", - "HeaderRecordingGroups": "Бичлэгийн бүлгүүд", "HearingImpaired": "Сонсголын бэрхшээлтэй", "HomeVideos": "Үндсэн дүрсүүд", "Inherit": "Уламжлах", - "ItemAddedWithName": "{0}-г санд нэмлээ", - "ItemRemovedWithName": "{0}-с сангаас хаслаа", "LabelIpAddressValue": "IP хаяг: {0}", "LabelRunningTimeValue": "Үргэлжлэх хугацаа: {0}", - "MessageApplicationUpdated": "Jellyfin Server шинэчлэгдлээ", - "MessageApplicationUpdatedTo": "Jellyfin Server {0} болж шинэчлэгдлээ", - "MessageServerConfigurationUpdated": "Server-н тохиргоо шинэчлэгдлээ", "MixedContent": "Холимог агуулга", "Music": "Хөгжим", "MusicVideos": "Дууны клипүүд", @@ -99,28 +79,19 @@ "NotificationOptionUserLockedOut": "Хэрэглэгчийг түгжив", "NotificationOptionVideoPlayback": "Бичлэгийг тоглуулж эхлэв", "Photos": "Зургууд", - "Plugin": "Плагин", "PluginInstalledWithName": "{0}-г суулгалаа", "PluginUninstalledWithName": "{0}-г устгалаа", "PluginUpdatedWithName": "{0}-г шинэчиллээ", - "ProviderValue": "Нийлүүлэгч: {0}", - "ScheduledTaskStartedWithName": "{0}-г эхлүүлэв", - "ServerNameNeedsToBeRestarted": "{0}-г дахин асаана уу", "Shows": "Шоу", - "Sync": "Синхрончлох", - "System": "Систем", "TvShows": "ТВ нэвтрүүлгүүд", "Undefined": "Танисангүй", - "User": "Хэрэглэгч", "UserCreatedWithName": "Хэрэглэгч {0}-г үүсгэлээ", "UserDeletedWithName": "Хэрэглэгч {0}-г устгалаа", "UserDownloadingItemWithValues": "{0} нь {1}-г татаж байна", "UserLockedOutWithName": "Хэрэглэгч {0}-г түгжлээ", "UserOnlineFromDevice": "{0} нь {1}-тэй холбоотой байна", - "UserPolicyUpdatedWithName": "Хэрэглэгчийн журмыг {0}-д зориулан шинэчиллээ", "UserStartedPlayingItemWithValues": "{0}-г {2} дээр {1}-г тоглуулж байна", "UserStoppedPlayingItemWithValues": "{0}-г {2} дээр {1}-г тоглуулж дуусгалаа", - "ValueSpecialEpisodeName": "Онцгой - {0}", "VersionNumber": "Хувилбар {0}", "TasksMaintenanceCategory": "Засвар", "TasksLibraryCategory": "Сан", diff --git a/Emby.Server.Implementations/Localization/Core/mr.json b/Emby.Server.Implementations/Localization/Core/mr.json index 267222ecbe..f169d085d5 100644 --- a/Emby.Server.Implementations/Localization/Core/mr.json +++ b/Emby.Server.Implementations/Localization/Core/mr.json @@ -1,22 +1,13 @@ { "Books": "पुस्तकं", "Artists": "संगीतकार", - "Albums": "अल्बम", - "Playlists": "प्लेलिस्ट", - "HeaderAlbumArtists": "अल्बम संगीतकार", "Folders": "फोल्डर", "HeaderFavoriteEpisodes": "आवडते भाग", - "HeaderFavoriteSongs": "आवडती गाणी", "Movies": "चित्रपट", - "HeaderFavoriteArtists": "आवडते संगीतकार", "Shows": "कार्यक्रम", - "HeaderFavoriteAlbums": "आवडते अल्बम", - "Channels": "वाहिन्या", - "ValueSpecialEpisodeName": "विशेष - {0}", "HeaderFavoriteShows": "आवडते कार्यक्रम", "Favorites": "आवडीचे", "HeaderNextUp": "यानंतर", - "Songs": "गाणी", "HeaderLiveTV": "लाइव्ह टीव्ही", "Genres": "जाँनरे", "Photos": "चित्र", @@ -34,10 +25,8 @@ "UserOnlineFromDevice": "{0} हे {1} येथून ऑनलाइन आहेत", "UserDeletedWithName": "प्रयोक्ता {0} काढून टाकण्यात आले आहे", "UserCreatedWithName": "प्रयोक्ता {0} बनवण्यात आले आहे", - "User": "प्रयोक्ता", "TvShows": "टीव्ही कार्यक्रम", "StartupEmbyServerIsLoading": "जेलिफिन सर्व्हर लोड होत आहे. कृपया थोड्या वेळात पुन्हा प्रयत्न करा.", - "Plugin": "प्लगइन", "NotificationOptionCameraImageUploaded": "कॅमेरा चित्र अपलोड केले आहे", "NotificationOptionApplicationUpdateInstalled": "अॅप्लिकेशन अपडेट इन्स्टॉल केले आहे", "NotificationOptionApplicationUpdateAvailable": "अॅप्लिकेशन अपडेट उपलब्ध आहे", @@ -46,16 +35,9 @@ "NameSeasonNumber": "सीझन {0}", "MusicVideos": "संगीत व्हिडीयो", "Music": "संगीत", - "MessageApplicationUpdatedTo": "जेलिफिन सर्व्हर अपडेट होऊन {0} आवृत्तीवर पोहोचला आहे", - "MessageApplicationUpdated": "जेलिफिन सर्व्हर अपडेट केला गेला आहे", "Latest": "नवीनतम", "LabelIpAddressValue": "आयपी पत्ता: {0}", - "ItemRemovedWithName": "{0} हे संग्रहालयातून काढून टाकण्यात आले", - "ItemAddedWithName": "{0} हे संग्रहालयात जोडले गेले", "HomeVideos": "घरचे व्हिडीयो", - "HeaderRecordingGroups": "रेकॉर्डिंग गट", - "CameraImageUploadedFrom": "एक नवीन कॅमेरा चित्र {0} येथून अपलोड केले आहे", - "Application": "अॅप्लिकेशन", "AppDeviceValues": "अॅप: {0}, यंत्र: {1}", "Collections": "संग्रह", "ChapterNameValue": "धडा {0}", @@ -70,18 +52,12 @@ "TaskRefreshChapterImagesDescription": "अध्याय असलेल्या व्हिडियोंसाठी थंबनेल चित्र बनवतो.", "TaskRefreshChapterImages": "अध्याय चित्र काढून घ्या", "TasksMaintenanceCategory": "देखरेख", - "ValueHasBeenAddedToLibrary": "{0} हे तुमच्या माध्यम संग्रहात जोडण्यात आले आहे", "UserStoppedPlayingItemWithValues": "{0} यांचं {2} वर {1} पूर्णपणे प्ले करून झालं आहे", "UserStartedPlayingItemWithValues": "{0} हे {2} वर {1} प्ले करत आहे", "UserDownloadingItemWithValues": "{0} हे {1} डाउनलोड करत आहे", - "System": "प्रणाली", "Undefined": "अव्याख्यात", - "Sync": "सिंक", - "ServerNameNeedsToBeRestarted": "{0} याला बंद करून पुन्हा सुरू करायची गरज आहे", "SubtitleDownloadFailureFromForItem": "{0} येथून {1} यासाठी उपशिर्षक डाउनलोड करण्यात अपयश", - "ScheduledTaskStartedWithName": "{0} सुरू झाले", "ScheduledTaskFailedWithName": "{0} अपयशी झाले", - "ProviderValue": "पुरवणारा: {0}", "PluginUpdatedWithName": "{0} अपडेट केले", "PluginUninstalledWithName": "{0} अनिन्स्टॉल केले", "PluginInstalledWithName": "{0} इन्स्टॉल केले", @@ -109,19 +85,14 @@ "TaskCleanCacheDescription": "सिस्टमला यापुढे आवश्यक नसलेल्या कॅशे फाइल्स हटवा.", "TaskCleanActivityLogDescription": "कॉन्फिगर केलेल्या वयापेक्षा जुन्या क्रियाकलाप लॉग एंट्री हटवा.", "TaskCleanActivityLog": "क्रियाकलाप लॉग साफ करा", - "UserPolicyUpdatedWithName": "{0} साठी वापरकर्ता धोरण अपडेट केले गेले आहे", "UserOfflineFromDevice": "{0} {1} वरून डिस्कनेक्ट झाला आहे", "UserLockedOutWithName": "वापरकर्ता {0} लॉक केले गेले आहे", "NotificationOptionUserLockedOut": "वापरकर्ता लॉक आउट", "NameInstallFailed": "{0} स्थापना अयशस्वी", - "MessageServerConfigurationUpdated": "सर्व्हर कॉन्फिगरेशन अद्यतनित केले आहे", - "MessageNamedServerConfigurationUpdatedWithValue": "सर्व्हर कॉन्फिगरेशन विभाग {0} अद्यतनित केला गेला आहे", "Inherit": "वारसा", "Forced": "सक्ती केली आहे", "FailedLoginAttemptWithUserName": "{0} कडून लॉगिन करण्याचा प्रयत्न अयशस्वी झाला", "External": "बाहेरचा", - "DeviceOnlineWithName": "{0} कनेक्ट झाले", - "DeviceOfflineWithName": "{0} डिस्कनेक्ट झाला आहे", "AuthenticationSucceededWithUserName": "{0} यशस्वीरित्या प्रमाणीकृत", "HearingImpaired": "कर्णबधीर", "TaskRefreshTrickplayImages": "ट्रिकप्ले प्रतिमा तयार करा", diff --git a/Emby.Server.Implementations/Localization/Core/ms.json b/Emby.Server.Implementations/Localization/Core/ms.json index 743c14ac10..9fc61fadd5 100644 --- a/Emby.Server.Implementations/Localization/Core/ms.json +++ b/Emby.Server.Implementations/Localization/Core/ms.json @@ -1,41 +1,24 @@ { - "Albums": "Album", "AppDeviceValues": "Aplikasi: {0}, Peranti: {1}", - "Application": "Aplikasi", "Artists": "Artis", "AuthenticationSucceededWithUserName": "{0} berjaya disahkan", "Books": "Buku", - "CameraImageUploadedFrom": "Gambar baharu telah dimuat naik melalui {0}", - "Channels": "Saluran", "ChapterNameValue": "Bab {0}", "Collections": "Koleksi", - "DeviceOfflineWithName": "{0} telah dinyahsambung", - "DeviceOnlineWithName": "{0} telah disambung", "FailedLoginAttemptWithUserName": "Percubaan gagal log masuk daripada {0}", "Favorites": "Kegemaran", "Folders": "Folder-folder", "Genres": "Genre-genre", - "HeaderAlbumArtists": "Album artis-artis", "HeaderContinueWatching": "Teruskan Menonton", - "HeaderFavoriteAlbums": "Album-album Kegemaran", - "HeaderFavoriteArtists": "Artis-artis Kegemaran", "HeaderFavoriteEpisodes": "Episod-episod Kegemaran", "HeaderFavoriteShows": "Rancangan-rancangan Kegemaran", - "HeaderFavoriteSongs": "Lagu-lagu Kegemaran", "HeaderLiveTV": "TV Siaran Langsung", "HeaderNextUp": "Seterusnya", - "HeaderRecordingGroups": "Kumpulan-kumpulan Rakaman", "HomeVideos": "Video Peribadi", "Inherit": "Warisi", - "ItemAddedWithName": "{0} telah ditambah ke dalam pustaka", - "ItemRemovedWithName": "{0} telah dibuang daripada pustaka", "LabelIpAddressValue": "Alamat IP: {0}", "LabelRunningTimeValue": "Masa berjalan: {0}", "Latest": "Terbaharu", - "MessageApplicationUpdated": "Pelayan Jellyfin telah dikemas kini", - "MessageApplicationUpdatedTo": "Pelayan Jellyfin telah dikemas kini ke {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "Konfigurasi pelayan bahagian {0} telah dikemas kini", - "MessageServerConfigurationUpdated": "Konfigurasi pelayan telah dikemas kini", "MixedContent": "Kandungan campuran", "Movies": "Filem-filem", "Music": "Muzik", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "Ulangmain video bermula", "NotificationOptionVideoPlaybackStopped": "Ulangmain video dihentikan", "Photos": "Gambar-gambar", - "Playlists": "Senarai ulangmain", - "Plugin": "Plugin", "PluginInstalledWithName": "{0} telah dipasang", "PluginUninstalledWithName": "{0} telah dinyahpasang", "PluginUpdatedWithName": "{0} telah dikemaskini", - "ProviderValue": "Pembekal: {0}", "ScheduledTaskFailedWithName": "{0} gagal", - "ScheduledTaskStartedWithName": "{0} bermula", - "ServerNameNeedsToBeRestarted": "{0} perlu di ulangmula", "Shows": "Tayangan", - "Songs": "Lagu-lagu", "StartupEmbyServerIsLoading": "Pelayan Jellyfin sedang dimuatkan. Sila cuba sebentar lagi.", "SubtitleDownloadFailureFromForItem": "Muat turun sarikata gagal dari {0} untuk {1}", - "Sync": "Segerak", - "System": "Sistem", "TvShows": "Tayangan TV", - "User": "Pengguna", "UserCreatedWithName": "Pengguna {0} telah diwujudkan", "UserDeletedWithName": "Pengguna {0} telah dipadamkan", "UserDownloadingItemWithValues": "{0} sedang memuat turun {1}", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "{0} telah terputus dari {1}", "UserOnlineFromDevice": "{0} berada dalam talian dari {1}", "UserPasswordChangedWithName": "Kata laluan telah ditukar bagi pengguna {0}", - "UserPolicyUpdatedWithName": "Dasar pengguna telah dikemas kini untuk {0}", "UserStartedPlayingItemWithValues": "{0} sedang dimainkan {1} pada {2}", "UserStoppedPlayingItemWithValues": "{0} telah tamat dimainkan {1} pada {2}", - "ValueHasBeenAddedToLibrary": "{0} telah ditambah ke media library anda", - "ValueSpecialEpisodeName": "Khas - {0}", "VersionNumber": "Versi {0}", "TaskCleanActivityLog": "Log Aktiviti Bersih", "TasksChannelsCategory": "Saluran Internet", diff --git a/Emby.Server.Implementations/Localization/Core/mt.json b/Emby.Server.Implementations/Localization/Core/mt.json index aa3029a262..e237a80b70 100644 --- a/Emby.Server.Implementations/Localization/Core/mt.json +++ b/Emby.Server.Implementations/Localization/Core/mt.json @@ -1,28 +1,18 @@ { - "Albums": "Albums", "AppDeviceValues": "Applikazzjoni: {0}, Device: {1}", - "Application": "Applikazzjoni", "Artists": "Artisti", "AuthenticationSucceededWithUserName": "{1} awtentikat b'suċċess", "Books": "Kotba", - "CameraImageUploadedFrom": "Ttella' ritratt ġdid tal-kamera minn {1}", - "Channels": "Stazzjonijiet", "ChapterNameValue": "Kapitlu {0}", "Collections": "Kollezzjonijiet", - "DeviceOfflineWithName": "{0} tneħħa", - "DeviceOnlineWithName": "{0} tqabbad", "External": "Estern", "FailedLoginAttemptWithUserName": "Attentat fallut ta' login minn {0}", "Favorites": "Favoriti", "Forced": "Sfurzat", "Genres": "Ġeneri", - "HeaderAlbumArtists": "Artisti tal-album", "HeaderContinueWatching": "Kompli Ara", - "HeaderFavoriteAlbums": "Albums Favoriti", - "HeaderFavoriteArtists": "Artisti Favoriti", "HeaderFavoriteEpisodes": "Episodji Favoriti", "HeaderFavoriteShows": "Programmi Favoriti", - "HeaderFavoriteSongs": "Kanzunetti Favoriti", "HeaderNextUp": "Li Jmiss", "SubtitleDownloadFailureFromForItem": "Is-sottotitli ma setgħux jitniżżlu minn {0} għal {1}", "UserPasswordChangedWithName": "Il-password għall-utent {0} inbidlet", @@ -32,18 +22,11 @@ "Default": "Standard", "Folders": "Folders", "HeaderLiveTV": "TV Dirett", - "HeaderRecordingGroups": "Gruppi ta' Rikordjar", "HearingImpaired": "Nuqqas ta' Smigħ", "HomeVideos": "Filmati Personali", "Inherit": "Jiret", - "ItemAddedWithName": "{0} żdied fil-librerija", - "ItemRemovedWithName": "{0} tneħħa mil-librerija", "LabelIpAddressValue": "Indirizz tal-IP: {0}", "Latest": "Tal-Aħħar", - "MessageApplicationUpdated": "Il-Jellyfin Server ġie aġġornat", - "MessageApplicationUpdatedTo": "Il-JellyFin Server ġie aġġornat għal {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "Is-sezzjoni {0} tal-konfigurazzjoni tas-server ġiet aġġornata", - "MessageServerConfigurationUpdated": "Il-konfigurazzjoni tas-server ġiet aġġornata", "MixedContent": "Kontenut imħallat", "Movies": "Films", "Music": "Mużika", @@ -67,21 +50,12 @@ "NotificationOptionTaskFailed": "Falliment tat-task skedat", "NotificationOptionUserLockedOut": "Utent imsakkar", "Photos": "Ritratti", - "Playlists": "Playlists", - "Plugin": "Plugin", "PluginInstalledWithName": "{0} ġie installat", "PluginUninstalledWithName": "{0} tneħħa", "PluginUpdatedWithName": "{0} ġie aġġornat", - "ProviderValue": "Fornitur: {0}", "ScheduledTaskFailedWithName": "{0} falla", - "ScheduledTaskStartedWithName": "{0} beda", - "ServerNameNeedsToBeRestarted": "{0} jeħtieġ restart", - "Songs": "Kanzunetti", "StartupEmbyServerIsLoading": "Jellyfin Server qed jillowdja. Jekk jogħġbok erġa' pprova ftit tal-ħin oħra.", - "Sync": "Sinkronizza", - "System": "Sistema", "Undefined": "Bla Definizzjoni", - "User": "Utent", "UserCreatedWithName": "L-utent {0} inħoloq", "UserDeletedWithName": "L-utent {0} tħassar", "UserDownloadingItemWithValues": "{0} qed iniżżel {1}", @@ -93,11 +67,8 @@ "NotificationOptionVideoPlaybackStopped": "Il-playback tal-filmat twaqqaf", "Shows": "Serje", "TvShows": "Serje Televiżivi", - "UserPolicyUpdatedWithName": "Il-politka tal-utent ġiet aġġornata għal {0}", "UserStartedPlayingItemWithValues": "{0} qed jara {1} fuq {2}", "UserStoppedPlayingItemWithValues": "{0} waqaf jara {1} fuq {2}", - "ValueHasBeenAddedToLibrary": "{0} ġie miżjud mal-librerija tal-midja tiegħek", - "ValueSpecialEpisodeName": "Speċjali - {0}", "VersionNumber": "Verżjoni {0}", "TasksMaintenanceCategory": "Manutenzjoni", "TasksLibraryCategory": "Librerija", diff --git a/Emby.Server.Implementations/Localization/Core/my.json b/Emby.Server.Implementations/Localization/Core/my.json index f2cd501076..47728adfc5 100644 --- a/Emby.Server.Implementations/Localization/Core/my.json +++ b/Emby.Server.Implementations/Localization/Core/my.json @@ -1,10 +1,8 @@ { "Default": "ပုံသေ", "Collections": "စုစည်းမှုများ", - "Channels": "တီဗွီလိုင်းများ", "Books": "စာအုပ်များ", "Artists": "အနုပညာရှင်များ", - "Albums": "သီချင်းအခွေများ", "TaskOptimizeDatabaseDescription": "ဒေတာဘေ့စ်ကို ကျစ်လစ်စေပြီး နေရာလွတ်များကို ဖြတ်တောက်ပေးသည်။ စာကြည့်တိုက်ကို စကင်န်ဖတ်ပြီးနောက် ဤလုပ်ငန်းကို လုပ်ဆောင်ခြင်း သို့မဟုတ် ဒေတာဘေ့စ်မွမ်းမံမှုများ စွမ်းဆောင်ရည်ကို မြှင့်တင်ပေးနိုင်သည်ဟု ရည်ညွှန်းသော အခြားပြောင်းလဲမှုများကို လုပ်ဆောင်ခြင်း။.", "TaskOptimizeDatabase": "ဒေတာဘေ့စ်ကို အကောင်းဆုံးဖြစ်အောင်လုပ်ပါ", "TaskDownloadMissingSubtitlesDescription": "မက်တာဒေတာ ဖွဲ့စည်းမှုပုံစံအပေါ် အခြေခံ၍ ပျောက်ဆုံးနေသော စာတန်းထိုးများအတွက် အင်တာနက်ကို ရှာဖွေသည်။", @@ -32,11 +30,8 @@ "TasksLibraryCategory": "မီဒီယာတိုက်", "TasksMaintenanceCategory": "ပြုပြင် ထိန်းသိမ်းခြင်း", "VersionNumber": "ဗားရှင်း {0}", - "ValueSpecialEpisodeName": "အထူး- {0}", - "ValueHasBeenAddedToLibrary": "{0} ကို သင့်မီဒီယာဒစ်ဂျစ်တိုက်သို့ ပေါင်းထည့်လိုက်ပါပြီ", "UserStoppedPlayingItemWithValues": "{0} သည် {1} ကို {2} တွင် ဖွင့်ပြီးပါပြီ", "UserStartedPlayingItemWithValues": "{0} သည် {1} ကို {2} တွင် ပြသနေသည်", - "UserPolicyUpdatedWithName": "{0} အတွက် အသုံးပြုသူမူဝါဒကို အပ်ဒိတ်လုပ်ပြီးပါပြီ", "UserPasswordChangedWithName": "အသုံးပြုသူ {0} အတွက် စကားဝှက်ကို ပြောင်းထားသည်", "UserOnlineFromDevice": "{0} သည် {1} မှ အွန်လိုင်းဖြစ်သည်", "UserOfflineFromDevice": "{0} သည် {1} မှ ချိတ်ဆက်မှုပြတ်တောက်သွားသည်", @@ -44,24 +39,15 @@ "UserDownloadingItemWithValues": "{0} သည် {1} ကို ဒေါင်းလုဒ်လုပ်နေသည်", "UserDeletedWithName": "အသုံးပြုသူ {0} ကို ဖျက်လိုက်ပါပြီ", "UserCreatedWithName": "အသုံးပြုသူ {0} ကို ဖန်တီးပြီးပါပြီ", - "User": "အသုံးပြုသူ", "Undefined": "သတ်မှတ်မထားသော", "TvShows": "တီဗီ ဇာတ်လမ်းတွဲများ", - "System": "စနစ်", - "Sync": "ချိန်ကိုက်မည်", "SubtitleDownloadFailureFromForItem": "{1} အတွက် {0} မှ စာတန်းထိုးများ ဒေါင်းလုဒ်လုပ်ခြင်း မအောင်မြင်ပါ", "StartupEmbyServerIsLoading": "Jellyfin ဆာဗာကို အသင့်ပြင်နေပါသည်။ ခဏနေ ထပ်စမ်းကြည့်ပါ။", - "Songs": "သီချင်းများ", "Shows": "ဇာတ်လမ်းတွဲများ", - "ServerNameNeedsToBeRestarted": "{0} ကို ပြန်လည်စတင်ရန် လိုအပ်သည်", - "ScheduledTaskStartedWithName": "{0} စတင်ခဲ့သည်", "ScheduledTaskFailedWithName": "{0} မအောင်မြင်ပါ", - "ProviderValue": "ဝန်ဆောင်မှုပေးသူ- {0}", "PluginUpdatedWithName": "ပလပ်ခ်အင် {0} ကို အပ်ဒိတ်လုပ်ထားသည်", "PluginUninstalledWithName": "ပလပ်ခ်အင် {0} ကို ဖြုတ်လိုက်ပါပြီ", "PluginInstalledWithName": "ပလပ်ခ်အင် {0} ကို ထည့်သွင်းခဲ့သည်", - "Plugin": "ပလပ်အင်", - "Playlists": "အစီအစဉ်များ", "Photos": "ဓာတ်ပုံများ", "NotificationOptionVideoPlaybackStopped": "ဗီဒီယိုဖွင့်ခြင်း ရပ်သွားသည်", "NotificationOptionVideoPlayback": "ဗီဒီယိုဖွင့်ခြင်း စတင်ပါပြီ", @@ -87,38 +73,23 @@ "Music": "တေးဂီတ", "Movies": "ရုပ်ရှင်များ", "MixedContent": "ရောနှောပါဝင်မှု", - "MessageServerConfigurationUpdated": "ဆာဗာဖွဲ့စည်းပုံကို အပ်ဒိတ်လုပ်ပြီးပါပြီ", - "MessageNamedServerConfigurationUpdatedWithValue": "ဆာဗာဖွဲ့စည်းပုံကဏ္ဍ {0} ကို အပ်ဒိတ်လုပ်ပြီးပါပြီ", - "MessageApplicationUpdatedTo": "Jellyfin ဆာဗာကို {0} သို့ အပ်ဒိတ်လုပ်ထားသည်", - "MessageApplicationUpdated": "Jellyfin ဆာဗာကို အပ်ဒိတ်လုပ်ပြီးပါပြီ", "Latest": "နောက်ဆုံး", "LabelRunningTimeValue": "ကြာချိန် - {0}", "LabelIpAddressValue": "IP လိပ်စာ- {0}", - "ItemRemovedWithName": "{0} ကို ဒစ်ဂျစ်တိုက်မှ ဖယ်ရှားခဲ့သည်", - "ItemAddedWithName": "{0} ကို စာကြည့်တိုက်သို့ ထည့်ထားသည်", "Inherit": "ဆက်ခံ၍ လုပ်ဆောင်သည်", "HomeVideos": "ကိုယ်တိုင်ရိုက် ဗီဒီယိုများ", - "HeaderRecordingGroups": "အသံဖမ်းအဖွဲ့များ", "HeaderNextUp": "နောက်ထပ်", "HeaderLiveTV": "တီဗွီတိုက်ရိုက်", - "HeaderFavoriteSongs": "အကြိုက်ဆုံးသီချင်းများ", "HeaderFavoriteShows": "အကြိုက်ဆုံး ဇာတ်လမ်းတွဲများ", "HeaderFavoriteEpisodes": "အကြိုက်ဆုံး ဇာတ်လမ်းအပိုင်းများ", - "HeaderFavoriteArtists": "အကြိုက်ဆုံး အနုပညာရှင်များ", - "HeaderFavoriteAlbums": "အကြိုက်ဆုံး အယ်လ်ဘမ်များ", "HeaderContinueWatching": "ဆက်လက်ကြည့်ရှုပါ", - "HeaderAlbumArtists": "အယ်လ်ဘမ်အနုပညာရှင်များ", "Genres": "အမျိုးအစားများ", "Forced": "အတင်းအကြပ်", "Folders": "ဖိုလ်ဒါများ", "Favorites": "အကြိုက်ဆုံးများ", "FailedLoginAttemptWithUserName": "{0} မှ အကောင့်ဝင်ရန် မအောင်မြင်ပါ", - "DeviceOnlineWithName": "{0} ကို ချိတ်ဆက်ထားသည်", - "DeviceOfflineWithName": "{0} နှင့် အဆက်ပြတ်သွားပါပြီ", "ChapterNameValue": "အခန်း {0}", - "CameraImageUploadedFrom": "ကင်မရာပုံအသစ်ကို {0} မှ ထည့်သွင်းလိုက်သည်", "AuthenticationSucceededWithUserName": "{0} အောင်မြင်စွာ စစ်မှန်ကြောင်း အတည်ပြုပြီးပါပြီ", - "Application": "အပလီကေးရှင်း", "AppDeviceValues": "အက်ပ်- {0}၊ စက်- {1}", "External": "ပြင်ပ", "TaskKeyframeExtractorDescription": "ပိုမိုတိကျသည့် အိတ်ချ်အယ်လ်အက်စ် အစဉ်လိုက်ပြသမှုများ ဖန်တီးနိုင်ရန်အတွက် ဗီဒီယိုဖိုင်များမှ ကီးဖရိန်များကို ထုတ်နှုတ်ယူမည် ဖြစ်သည်။ ဤလုပ်ဆောင်မှုသည် အချိန်ကြာရှည်နိုင်သည်။", diff --git a/Emby.Server.Implementations/Localization/Core/nb.json b/Emby.Server.Implementations/Localization/Core/nb.json index 351b238f9d..752b74ec1c 100644 --- a/Emby.Server.Implementations/Localization/Core/nb.json +++ b/Emby.Server.Implementations/Localization/Core/nb.json @@ -1,41 +1,24 @@ { - "Albums": "Album", "AppDeviceValues": "App: {0}, Enhet: {1}", - "Application": "Program", "Artists": "Artister", "AuthenticationSucceededWithUserName": "{0} har logget inn", "Books": "Bøker", - "CameraImageUploadedFrom": "Et nytt kamerabilde har blitt lastet opp fra {0}", - "Channels": "Kanaler", "ChapterNameValue": "Kapittel {0}", "Collections": "Samlinger", - "DeviceOfflineWithName": "{0} har koblet fra", - "DeviceOnlineWithName": "{0} er tilkoblet", "FailedLoginAttemptWithUserName": "Mislykket påloggingsforsøk fra {0}", "Favorites": "Favoritter", "Folders": "Mapper", "Genres": "Sjangre", - "HeaderAlbumArtists": "Albumartister", "HeaderContinueWatching": "Fortsett å se", - "HeaderFavoriteAlbums": "Favorittalbum", - "HeaderFavoriteArtists": "Favorittartister", "HeaderFavoriteEpisodes": "Favorittepisoder", "HeaderFavoriteShows": "Favorittserier", - "HeaderFavoriteSongs": "Favorittsanger", "HeaderLiveTV": "Direkte-TV", "HeaderNextUp": "Neste", - "HeaderRecordingGroups": "Opptaksgrupper", "HomeVideos": "Hjemmelagde filmer", "Inherit": "Arve", - "ItemAddedWithName": "{0} ble lagt til i biblioteket", - "ItemRemovedWithName": "{0} ble fjernet fra biblioteket", "LabelIpAddressValue": "IP-adresse: {0}", "LabelRunningTimeValue": "Spilletid: {0}", "Latest": "Siste", - "MessageApplicationUpdated": "Jellyfin-serveren har blitt oppdatert", - "MessageApplicationUpdatedTo": "Jellyfin-serveren ble oppdatert til {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "Serverkonfigurasjonsseksjon {0} har blitt oppdatert", - "MessageServerConfigurationUpdated": "Serverkonfigurasjon har blitt oppdatert", "MixedContent": "Blandet innhold", "Movies": "Filmer", "Music": "Musikk", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "Videoavspilling startet", "NotificationOptionVideoPlaybackStopped": "Videoavspilling stoppet", "Photos": "Bilder", - "Playlists": "Spillelister", - "Plugin": "Programvareutvidelse", "PluginInstalledWithName": "{0} ble installert", "PluginUninstalledWithName": "{0} ble avinstallert", "PluginUpdatedWithName": "{0} ble oppdatert", - "ProviderValue": "Leverandør: {0}", "ScheduledTaskFailedWithName": "{0} mislykkes", - "ScheduledTaskStartedWithName": "{0} startet", - "ServerNameNeedsToBeRestarted": "{0} må startes på nytt", "Shows": "Serier", - "Songs": "Sanger", "StartupEmbyServerIsLoading": "Jellyfin Server laster. Prøv igjen snart.", "SubtitleDownloadFailureFromForItem": "Kunne ikke laste ned undertekster fra {0} for {1}", - "Sync": "Synkroniser", - "System": "System", "TvShows": "TV-serier", - "User": "Bruker", "UserCreatedWithName": "Bruker {0} er opprettet", "UserDeletedWithName": "Bruker {0} har blitt slettet", "UserDownloadingItemWithValues": "{0} laster ned {1}", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "{0} har koblet fra {1}", "UserOnlineFromDevice": "{0} er tilkoblet fra {1}", "UserPasswordChangedWithName": "Passordet for {0} er oppdatert", - "UserPolicyUpdatedWithName": "Brukerretningslinjene har blitt oppdatert for {0}", "UserStartedPlayingItemWithValues": "{0} har startet avspilling {1} på {2}", "UserStoppedPlayingItemWithValues": "{0} har stoppet avspilling {1}", - "ValueHasBeenAddedToLibrary": "{0} har blitt lagt til i mediebiblioteket ditt", - "ValueSpecialEpisodeName": "Spesialepisode - {0}", "VersionNumber": "Versjon {0}", "TasksChannelsCategory": "Internettkanaler", "TasksApplicationCategory": "Applikasjon", diff --git a/Emby.Server.Implementations/Localization/Core/ne.json b/Emby.Server.Implementations/Localization/Core/ne.json index 0e52e32c1b..ad6070c4c3 100644 --- a/Emby.Server.Implementations/Localization/Core/ne.json +++ b/Emby.Server.Implementations/Localization/Core/ne.json @@ -21,64 +21,39 @@ "Music": "संगीत", "Movies": "चलचित्रहरू", "MixedContent": "मिश्रित सामग्री", - "MessageServerConfigurationUpdated": "सर्भर कन्फिगरेसन अद्यावधिक गरिएको छ", - "MessageNamedServerConfigurationUpdatedWithValue": "सर्भर कन्फिगरेसन विभाग {0} अद्यावधिक गरिएको छ", - "MessageApplicationUpdatedTo": "जेलीफिन सर्भर {0} मा अद्यावधिक गरिएको छ", - "MessageApplicationUpdated": "जेलीफिन सर्भर अपडेट गरिएको छ", "Latest": "नविनतम", "LabelRunningTimeValue": "कुल समय: {0}", "LabelIpAddressValue": "आईपी ठेगाना: {0}", - "ItemRemovedWithName": "{0}लाई पुस्तकालयबाट हटाईयो", - "ItemAddedWithName": "{0} लाईब्रेरीमा थपियो", "Inherit": "उत्तराधिकार", "HomeVideos": "घरेलु भिडियोहरू", - "HeaderRecordingGroups": "रेकर्ड समूहहरू", "HeaderNextUp": "आगामी", "HeaderLiveTV": "प्रत्यक्ष टिभी", - "HeaderFavoriteSongs": "मनपर्ने गीतहरू", "HeaderFavoriteShows": "मनपर्ने कार्यक्रमहरू", "HeaderFavoriteEpisodes": "मनपर्ने एपिसोडहरू", - "HeaderFavoriteArtists": "मनपर्ने कलाकारहरू", - "HeaderFavoriteAlbums": "मनपर्ने एल्बमहरू", "HeaderContinueWatching": "हेर्न जारी राख्नुहोस्", - "HeaderAlbumArtists": "एल्बमका कलाकारहरू", "Genres": "विधाहरू", "Folders": "फोल्डरहरू", "Favorites": "मनपर्ने", "FailedLoginAttemptWithUserName": "असफल लग इन प्रयास {0} देखि", - "DeviceOnlineWithName": "{0}को साथ जडित", - "DeviceOfflineWithName": "{0}बाट विच्छेदन भयो", "Collections": "संग्रह", "ChapterNameValue": "अध्याय {0}", - "Channels": "च्यानलहरू", "AppDeviceValues": "अनुप्रयोग: {0}, उपकरण: {1}", "AuthenticationSucceededWithUserName": "{0} सफलतापूर्वक प्रमाणीकरण गरियो", - "CameraImageUploadedFrom": "{0}बाट नयाँ क्यामेरा छवि अपलोड गरिएको छ", "Books": "पुस्तकहरु", "Artists": "कलाकारहरू", - "Application": "अनुप्रयोगहरू", - "Albums": "एल्बमहरू", "TasksLibraryCategory": "पुस्तकालय", "TasksApplicationCategory": "अनुप्रयोग", "TasksMaintenanceCategory": "मर्मत", - "UserPolicyUpdatedWithName": "प्रयोगकर्ता नीति को लागी अद्यावधिक गरिएको छ {0}", "UserPasswordChangedWithName": "पासवर्ड प्रयोगकर्ताका लागि परिवर्तन गरिएको छ {0}", "UserOnlineFromDevice": "{0} बाट अनलाइन छ {1}", "UserOfflineFromDevice": "{0} बाट विच्छेदन भएको छ {1}", "UserLockedOutWithName": "प्रयोगकर्ता {0} लक गरिएको छ", "UserDeletedWithName": "प्रयोगकर्ता {0} हटाइएको छ", "UserCreatedWithName": "प्रयोगकर्ता {0} सिर्जना गरिएको छ", - "User": "प्रयोगकर्ता", "PluginInstalledWithName": "{0} सभएको थियो", "StartupEmbyServerIsLoading": "Jellyfin सर्भर लोड हुँदैछ। कृपया छिट्टै फेरि प्रयास गर्नुहोस्।", - "Songs": "गीतहरू", "Shows": "शोहरू", - "ServerNameNeedsToBeRestarted": "{0} लाई पुन: सुरु गर्नु पर्छ", - "ScheduledTaskStartedWithName": "{0} सुरु भयो", "ScheduledTaskFailedWithName": "{0} असफल", - "ProviderValue": "प्रदायक: {0}", - "Plugin": "प्लगइनहरू", - "Playlists": "प्लेलिस्टहरू", "Photos": "तस्बिरहरु", "NotificationOptionVideoPlaybackStopped": "भिडियो प्लेब्याक रोकियो", "NotificationOptionVideoPlayback": "भिडियो प्लेब्याक सुरु भयो", @@ -98,15 +73,11 @@ "TaskCleanActivityLog": "गतिविधि लग सफा गर्नुहोस्", "TasksChannelsCategory": "इन्टरनेट च्यानलहरू", "VersionNumber": "संस्करण {0}", - "ValueSpecialEpisodeName": "विशेष - {0}", - "ValueHasBeenAddedToLibrary": "{0} तपाईंको मिडिया लाइब्रेरीमा थपिएको छ", "UserStoppedPlayingItemWithValues": "{2} मा {0} हेरिसकेको छ{1}", "UserStartedPlayingItemWithValues": "{0} हेर्दै {1} मा {2}", "UserDownloadingItemWithValues": "{0} डाउनलोड गर्दै छ {1}", "Undefined": "अपरिभाषित", "TvShows": "टेलिभिजन कार्यक्रमहरू", - "System": "प्रणाली", - "Sync": "समकालीन", "SubtitleDownloadFailureFromForItem": "उपशीर्षकहरू {0} बाट {1} को लागि डाउनलोड गर्न असफल", "PluginUpdatedWithName": "{0} अद्यावधिक गरिएको थियो", "PluginUninstalledWithName": "{0} को स्थापना रद्द गरिएको थियो", diff --git a/Emby.Server.Implementations/Localization/Core/nl.json b/Emby.Server.Implementations/Localization/Core/nl.json index de4c277ce7..9aea3adc22 100644 --- a/Emby.Server.Implementations/Localization/Core/nl.json +++ b/Emby.Server.Implementations/Localization/Core/nl.json @@ -1,39 +1,23 @@ { "AppDeviceValues": "App: {0}, Apparaat: {1}", - "Application": "Applicatie", "Artists": "Artiesten", "AuthenticationSucceededWithUserName": "{0} is succesvol geauthenticeerd", "Books": "Boeken", - "CameraImageUploadedFrom": "Nieuwe camera-afbeelding toegevoegd vanaf {0}", - "Channels": "Kanalen", "ChapterNameValue": "Hoofdstuk {0}", "Collections": "Collecties", - "DeviceOfflineWithName": "Verbinding met {0} is verbroken", - "DeviceOnlineWithName": "{0} is verbonden", "FailedLoginAttemptWithUserName": "Mislukte aanmeldpoging van {0}", "Favorites": "Favorieten", "Folders": "Mappen", - "HeaderAlbumArtists": "Albumartiesten", "HeaderContinueWatching": "Verderkijken", - "HeaderFavoriteAlbums": "Favoriete albums", - "HeaderFavoriteArtists": "Favoriete artiesten", "HeaderFavoriteEpisodes": "Favoriete afleveringen", "HeaderFavoriteShows": "Favoriete series", - "HeaderFavoriteSongs": "Favoriete nummers", "HeaderLiveTV": "Live-tv", "HeaderNextUp": "Volgende", - "HeaderRecordingGroups": "Opnamegroepen", "HomeVideos": "Homevideo's", "Inherit": "Overnemen", - "ItemAddedWithName": "{0} is toegevoegd aan de bibliotheek", - "ItemRemovedWithName": "{0} is verwijderd uit de bibliotheek", "LabelIpAddressValue": "IP-adres: {0}", "LabelRunningTimeValue": "Looptijd: {0}", "Latest": "Nieuwste", - "MessageApplicationUpdated": "Jellyfin Server is bijgewerkt", - "MessageApplicationUpdatedTo": "Jellyfin Server is bijgewerkt naar {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "Sectie {0} van de serverconfiguratie is bijgewerkt", - "MessageServerConfigurationUpdated": "Serverconfiguratie is bijgewerkt", "MixedContent": "Gemengde inhoud", "Movies": "Films", "Music": "Muziek", @@ -59,23 +43,14 @@ "NotificationOptionVideoPlayback": "Afspelen van video gestart", "NotificationOptionVideoPlaybackStopped": "Afspelen van video gestopt", "Photos": "Foto's", - "Playlists": "Afspeellijsten", - "Plugin": "Plug-in", "PluginInstalledWithName": "{0} is geïnstalleerd", "PluginUninstalledWithName": "{0} is verwijderd", "PluginUpdatedWithName": "{0} is bijgewerkt", - "ProviderValue": "Aanbieder: {0}", "ScheduledTaskFailedWithName": "{0} is mislukt", - "ScheduledTaskStartedWithName": "{0} is gestart", - "ServerNameNeedsToBeRestarted": "{0} moet herstart worden", "Shows": "Series", - "Songs": "Nummers", "StartupEmbyServerIsLoading": "Jellyfin Server is aan het laden. Probeer het later opnieuw.", "SubtitleDownloadFailureFromForItem": "Ondertiteling kon niet gedownload worden van {0} voor {1}", - "Sync": "Synchronisatie", - "System": "Systeem", "TvShows": "Tv-series", - "User": "Gebruiker", "UserCreatedWithName": "Gebruiker {0} is aangemaakt", "UserDeletedWithName": "Gebruiker {0} is verwijderd", "UserDownloadingItemWithValues": "{0} downloadt {1}", @@ -83,11 +58,8 @@ "UserOfflineFromDevice": "Verbinding van {0} via {1} is verbroken", "UserOnlineFromDevice": "{0} is verbonden via {1}", "UserPasswordChangedWithName": "Wachtwoord voor {0} is gewijzigd", - "UserPolicyUpdatedWithName": "Gebruikersbeleid gewijzigd voor {0}", "UserStartedPlayingItemWithValues": "{0} speelt {1} af op {2}", "UserStoppedPlayingItemWithValues": "{0} heeft afspelen van {1} gestopt op {2}", - "ValueHasBeenAddedToLibrary": "{0} is toegevoegd aan je mediabibliotheek", - "ValueSpecialEpisodeName": "Special - {0}", "VersionNumber": "Versie {0}", "TaskDownloadMissingSubtitlesDescription": "Zoekt op het internet naar ontbrekende ondertiteling gebaseerd op metadataconfiguratie.", "TaskDownloadMissingSubtitles": "Ontbrekende ondertiteling downloaden", @@ -134,7 +106,7 @@ "TaskExtractMediaSegments": "Scannen op mediasegmenten", "CleanupUserDataTaskDescription": "Wist alle gebruikersgegevens (kijkstatus, favorieten, etc.) van media die al minstens 90 dagen niet meer aanwezig zijn.", "CleanupUserDataTask": "Opruimtaak gebruikersdata", - "Albums": "Albums", "Genres": "Genres", - "Original": "Oorspronkelijk" + "Original": "Oorspronkelijk", + "LyricDownloadFailureFromForItem": "Downloaden van liedteksten voor {1} van {0} mislukt" } diff --git a/Emby.Server.Implementations/Localization/Core/nn.json b/Emby.Server.Implementations/Localization/Core/nn.json index feb5fe2154..8c5da8c1de 100644 --- a/Emby.Server.Implementations/Localization/Core/nn.json +++ b/Emby.Server.Implementations/Localization/Core/nn.json @@ -1,41 +1,24 @@ { - "MessageServerConfigurationUpdated": "Tenarkonfigurasjonen har blitt oppdatert", - "MessageNamedServerConfigurationUpdatedWithValue": "Tenar konfigurasjon seksjon {0} har blitt oppdatert", - "MessageApplicationUpdatedTo": "Jellyfin-tenaren har blitt oppdatert til {0}", - "MessageApplicationUpdated": "Jellyfin-tenaren har blitt oppdatert", "Latest": "Nyaste", "LabelRunningTimeValue": "Speletid: {0}", "LabelIpAddressValue": "IP-adresse: {0}", - "ItemRemovedWithName": "{0} vart fjerna frå biblioteket", - "ItemAddedWithName": "{0} vart lagt til i biblioteket", "Inherit": "Arve", "HomeVideos": "Heimevideoar", - "HeaderRecordingGroups": "Innspelingsgrupper", "HeaderNextUp": "Neste", "HeaderLiveTV": "Direkte TV", - "HeaderFavoriteSongs": "Favorittsongar", "HeaderFavoriteShows": "Favorittseriar", "HeaderFavoriteEpisodes": "Favorittepisodar", - "HeaderFavoriteArtists": "Favorittartistar", - "HeaderFavoriteAlbums": "Favorittalbum", "HeaderContinueWatching": "Fortsett å sjå", - "HeaderAlbumArtists": "Albumartist", "Genres": "Sjangrar", "Folders": "Mapper", "Favorites": "Favorittar", "FailedLoginAttemptWithUserName": "Mislukka påloggingsforsøk frå {0}", - "DeviceOnlineWithName": "{0} er tilkopla", - "DeviceOfflineWithName": "{0} har kopla frå", "Collections": "Samlingar", "ChapterNameValue": "Kapittel {0}", - "Channels": "Kanalar", - "CameraImageUploadedFrom": "Eit nytt kamerabilete har blitt lasta opp frå {0}", "Books": "Bøker", "AuthenticationSucceededWithUserName": "{0} har logga inn", "Artists": "Artistar", - "Application": "Program", "AppDeviceValues": "App: {0}, Eining: {1}", - "Albums": "Album", "NotificationOptionServerRestartRequired": "Tenaren krev omstart", "NotificationOptionPluginUpdateInstalled": "Programvaretilleggoppdatering vart installert", "NotificationOptionPluginUninstalled": "Programvaretillegg avinstallert", @@ -56,7 +39,6 @@ "Music": "Musikk", "Movies": "Filmar", "MixedContent": "Blanda innhald", - "Sync": "Synkroniser", "TaskDownloadMissingSubtitlesDescription": "Søk Internettet for manglande undertekstar basert på metadatainnstillingar.", "TaskDownloadMissingSubtitles": "Last ned manglande undertekstar", "TaskRefreshChannelsDescription": "Oppdater internettkanalinformasjon.", @@ -80,11 +62,8 @@ "TasksLibraryCategory": "Bibliotek", "TasksMaintenanceCategory": "Vedlikehald", "VersionNumber": "Versjon {0}", - "ValueSpecialEpisodeName": "Spesialepisode - {0}", - "ValueHasBeenAddedToLibrary": "{0} har blitt lagt til i mediebiblioteket ditt", "UserStoppedPlayingItemWithValues": "{0} har fullført avspeling {1} på {2}", "UserStartedPlayingItemWithValues": "{0} spelar {1} på {2}", - "UserPolicyUpdatedWithName": "Brukarreglar har blitt oppdatert for {0}", "UserPasswordChangedWithName": "Passordet for {0} er oppdatert", "UserOnlineFromDevice": "{0} er direktekopla frå {1}", "UserOfflineFromDevice": "{0} har kopla frå {1}", @@ -92,22 +71,14 @@ "UserDownloadingItemWithValues": "{0} lastar ned {1}", "UserDeletedWithName": "Brukar {0} er sletta", "UserCreatedWithName": "Brukar {0} er oppretta", - "User": "Brukar", "TvShows": "TV-seriar", - "System": "System", "SubtitleDownloadFailureFromForItem": "Feila å laste ned undertekstar frå {0} for {1}", "StartupEmbyServerIsLoading": "Jellyfin-tenaren laster. Prøv igjen seinare.", - "Songs": "Sangar", "Shows": "Seriar", - "ServerNameNeedsToBeRestarted": "{0} må omstartast", - "ScheduledTaskStartedWithName": "{0} starta", "ScheduledTaskFailedWithName": "{0} feila", - "ProviderValue": "Leverandør: {0}", "PluginUpdatedWithName": "{0} blei oppdatert", "PluginUninstalledWithName": "{0} blei avinstallert", "PluginInstalledWithName": "{0} blei installert", - "Plugin": "Programvaretillegg", - "Playlists": "Spelelister", "Photos": "Bilete", "NotificationOptionVideoPlaybackStopped": "Videoavspeling stoppa", "NotificationOptionVideoPlayback": "Videoavspeling starta", diff --git a/Emby.Server.Implementations/Localization/Core/oc.json b/Emby.Server.Implementations/Localization/Core/oc.json index 0967ef424b..cad5640763 100644 --- a/Emby.Server.Implementations/Localization/Core/oc.json +++ b/Emby.Server.Implementations/Localization/Core/oc.json @@ -1 +1,3 @@ -{} +{ + "AppDeviceValues": "Aplicacion: {0}, Periferic: {1}" +} diff --git a/Emby.Server.Implementations/Localization/Core/or.json b/Emby.Server.Implementations/Localization/Core/or.json index 8251c12907..febc98d1a4 100644 --- a/Emby.Server.Implementations/Localization/Core/or.json +++ b/Emby.Server.Implementations/Localization/Core/or.json @@ -1,11 +1,8 @@ { "External": "ବହିଃସ୍ଥ", "Genres": "ଧରଣ", - "Albums": "ଆଲବମଗୁଡ଼ିକ", "Artists": "କଳାକାରଗୁଡ଼ିକ", - "Application": "ଆପ୍ଲିକେସନ", "Books": "ବହିଗୁଡ଼ିକ", - "Channels": "ଚ୍ୟାନେଲଗୁଡ଼ିକ", "ChapterNameValue": "ବିଭାଗ {0}", "Collections": "ସଂଗ୍ରହଗୁଡ଼ିକ", "Folders": "ଫୋଲ୍ଡରଗୁଡ଼ିକ" diff --git a/Emby.Server.Implementations/Localization/Core/pa.json b/Emby.Server.Implementations/Localization/Core/pa.json index b00291ccb4..e609ad52c8 100644 --- a/Emby.Server.Implementations/Localization/Core/pa.json +++ b/Emby.Server.Implementations/Localization/Core/pa.json @@ -24,11 +24,8 @@ "TasksLibraryCategory": "ਲਾਇਬ੍ਰੇਰੀ", "TasksMaintenanceCategory": "ਰੱਖ-ਰਖਾਅ", "VersionNumber": "ਵਰਜਨ {0}", - "ValueSpecialEpisodeName": "ਖਾਸ - {0}", - "ValueHasBeenAddedToLibrary": "{0} ਤੁਹਾਡੀ ਮੀਡੀਆ ਲਾਇਬ੍ਰੇਰੀ ਵਿੱਚ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ ਹੈ", "UserStoppedPlayingItemWithValues": "{0} ਨੇ {2} 'ਤੇ {1} ਖੇਡਣਾ ਪੂਰਾ ਕਰ ਲਿਆ ਹੈ", "UserStartedPlayingItemWithValues": "{0} {2} 'ਤੇ {1} ਖੇਡ ਰਿਹਾ ਹੈ", - "UserPolicyUpdatedWithName": "ਵਰਤੋਂਕਾਰ ਨੀਤੀ ਨੂੰ {0} ਲਈ ਅਪਡੇਟ ਕੀਤਾ ਗਿਆ ਹੈ", "UserPasswordChangedWithName": "{0} ਵਰਤੋਂਕਾਰ ਲਈ ਪਾਸਵਰਡ ਬਦਲਿਆ ਗਿਆ ਸੀ", "UserOnlineFromDevice": "{0} ਨੂੰ {1} ਤੋਂ ਆਨਲਾਈਨ ਹੈ", "UserOfflineFromDevice": "{0} ਤੋਂ ਡਿਸਕਨੈਕਟ ਹੋ ਗਿਆ ਹੈ {1}", @@ -36,24 +33,15 @@ "UserDownloadingItemWithValues": "{0} {1} ਨੂੰ ਡਾਊਨਲੋਡ ਕਰ ਰਿਹਾ ਹੈ", "UserDeletedWithName": "ਵਰਤੋਂਕਾਰ {0} ਨੂੰ ਹਟਾਇਆ ਗਿਆ", "UserCreatedWithName": "ਵਰਤੋਂਕਾਰ {0} ਬਣਾਇਆ ਗਿਆ ਹੈ", - "User": "ਵਰਤੋਂਕਾਰ", "Undefined": "ਪਰਿਭਾਸ਼ਤ", "TvShows": "ਟੀਵੀ ਸ਼ੋਅ", - "System": "ਸਿਸਟਮ", - "Sync": "ਸਿੰਕ", "SubtitleDownloadFailureFromForItem": "ਉਪਸਿਰਲੇਖ {1} ਲਈ {0} ਤੋਂ ਡਾਊਨਲੋਡ ਕਰਨ ਵਿੱਚ ਅਸਫਲ ਰਹੇ", "StartupEmbyServerIsLoading": "Jellyfin ਸਰਵਰ ਲੋਡ ਹੋ ਰਿਹਾ ਹੈ। ਛੇਤੀ ਹੀ ਫ਼ੇਰ ਕੋਸ਼ਿਸ਼ ਕਰੋ।", - "Songs": "ਗਾਣੇ", "Shows": "ਸ਼ੋਅ", - "ServerNameNeedsToBeRestarted": "{0} ਮੁੜ ਚਾਲੂ ਕਰਨ ਦੀ ਲੋੜ ਹੈ", - "ScheduledTaskStartedWithName": "{0} ਸ਼ੁਰੂ ਹੋਇਆ", "ScheduledTaskFailedWithName": "{0} ਅਸਫਲ", - "ProviderValue": "ਦੇਣ ਵਾਲੇ: {0}", "PluginUpdatedWithName": "{0} ਅਪਡੇਟ ਕੀਤਾ ਗਿਆ ਸੀ", "PluginUninstalledWithName": "{0} ਅਣਇੰਸਟੌਲ ਕੀਤਾ ਗਿਆ ਸੀ", "PluginInstalledWithName": "{0} ਲਗਾਇਆ ਗਿਆ ਸੀ", - "Plugin": "ਪਲੱਗਇਨ", - "Playlists": "ਪਲੇਸੂਚੀਆਂ", "Photos": "ਫੋਟੋਆਂ", "NotificationOptionVideoPlaybackStopped": "ਵੀਡੀਓ ਪਲੇਬੈਕ ਰੋਕਿਆ ਗਿਆ", "NotificationOptionVideoPlayback": "ਵੀਡੀਓ ਪਲੇਬੈਕ ਸ਼ੁਰੂ ਹੋਇਆ", @@ -79,45 +67,28 @@ "Music": "ਸੰਗੀਤ", "Movies": "ਫਿਲਮਾਂ", "MixedContent": "ਮਿਸ਼ਰਤ ਸਮੱਗਰੀ", - "MessageServerConfigurationUpdated": "ਸਰਵਰ ਕੌਂਫਿਗਰੇਸ਼ਨ ਨੂੰ ਅਪਡੇਟ ਕੀਤਾ ਗਿਆ ਹੈ", - "MessageNamedServerConfigurationUpdatedWithValue": "ਸਰਵਰ ਕੌਂਫਿਗਰੇਸ਼ਨ ਸੈਕਸ਼ਨ {0} ਅਪਡੇਟ ਕੀਤਾ ਗਿਆ ਹੈ", - "MessageApplicationUpdatedTo": "ਜੈਲੀਫਿਨ ਸਰਵਰ ਨੂੰ ਅੱਪਡੇਟ ਕੀਤਾ ਗਿਆ ਹੈ {0}", - "MessageApplicationUpdated": "ਜੈਲੀਫਿਨ ਸਰਵਰ ਅਪਡੇਟ ਕੀਤਾ ਗਿਆ ਹੈ", "Latest": "ਤਾਜ਼ਾ", "LabelRunningTimeValue": "ਚੱਲਦਾ ਸਮਾਂ: {0}", "LabelIpAddressValue": "IP ਪਤਾ: {0}", - "ItemRemovedWithName": "{0} ਲਾਇਬ੍ਰੇਰੀ ਵਿੱਚੋਂ ਹਟਾ ਦਿੱਤਾ ਗਿਆ ਸੀ", - "ItemAddedWithName": "{0} ਲਾਇਬ੍ਰੇਰੀ ਵਿੱਚ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ ਸੀ", "Inherit": "ਵਿਰਾਸਤ", "HomeVideos": "ਘਰੇਲੂ ਵੀਡੀਓ", - "HeaderRecordingGroups": "ਰਿਕਾਰਡਿੰਗ ਸਮੂਹ", "HeaderNextUp": "ਅੱਗੇ", "HeaderLiveTV": "ਲਾਈਵ ਟੀਵੀ", - "HeaderFavoriteSongs": "ਮਨਪਸੰਦ ਗਾਣੇ", "HeaderFavoriteShows": "ਮਨਪਸੰਦ ਸ਼ੋਅ", "HeaderFavoriteEpisodes": "ਮਨਪਸੰਦ ਐਪੀਸੋਡ", - "HeaderFavoriteArtists": "ਮਨਪਸੰਦ ਕਲਾਕਾਰ", - "HeaderFavoriteAlbums": "ਮਨਪਸੰਦ ਐਲਬਮ", "HeaderContinueWatching": "ਵੇਖਣਾ ਜਾਰੀ ਰੱਖੋ", - "HeaderAlbumArtists": "ਐਲਬਮ ਕਲਾਕਾਰ", "Genres": "ਸ਼ੈਲੀਆਂ", "Forced": "ਮਜਬੂਰ", "Folders": "ਫੋਲਡਰ", "Favorites": "ਮਨਪਸੰਦ", "FailedLoginAttemptWithUserName": "{0} ਤੋਂ ਲਾਗਇਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਫੇਲ ਹੋਈ", - "DeviceOnlineWithName": "{0} ਜੁੜਿਆ ਹੋਇਆ ਹੈ", - "DeviceOfflineWithName": "{0} ਡਿਸਕਨੈਕਟ ਹੋ ਗਿਆ ਹੈ", "Default": "ਡਿਫੌਲਟ", "Collections": "ਸੰਗ੍ਰਹਿਣ", "ChapterNameValue": "ਚੈਪਟਰ {0}", - "Channels": "ਚੈਨਲ", - "CameraImageUploadedFrom": "{0} ਤੋਂ ਇੱਕ ਨਵਾਂ ਕੈਮਰਾ ਚਿੱਤਰ ਅਪਲੋਡ ਕੀਤਾ ਗਿਆ ਹੈ", "Books": "ਕਿਤਾਬਾਂ", "AuthenticationSucceededWithUserName": "{0} ਸਫਲਤਾਪੂਰਕ ਪ੍ਰਮਾਣਿਤ", "Artists": "ਕਲਾਕਾਰ", - "Application": "ਐਪਲੀਕੇਸ਼ਨ", "AppDeviceValues": "ਐਪ: {0}, ਜੰਤਰ: {1}", - "Albums": "ਐਲਬਮਾਂ", "TaskOptimizeDatabase": "ਡਾਟਾਬੇਸ ਅਨੁਕੂਲ ਬਣਾਓ", "External": "ਬਾਹਰੀ", "HearingImpaired": "ਸੁਨਣ ਵਿਚ ਕਮਜ਼ੋਰ", diff --git a/Emby.Server.Implementations/Localization/Core/pl.json b/Emby.Server.Implementations/Localization/Core/pl.json index e5af2c7801..c4657bdd6e 100644 --- a/Emby.Server.Implementations/Localization/Core/pl.json +++ b/Emby.Server.Implementations/Localization/Core/pl.json @@ -1,41 +1,24 @@ { - "Albums": "Albumy", "AppDeviceValues": "Aplikacja: {0}, Urządzenie: {1}", - "Application": "Aplikacja", "Artists": "Wykonawcy", "AuthenticationSucceededWithUserName": "{0} został pomyślnie uwierzytelniony", "Books": "Książki", - "CameraImageUploadedFrom": "Nowy obraz został przekazany z {0}", - "Channels": "Kanały", "ChapterNameValue": "Rozdział {0}", "Collections": "Kolekcje", - "DeviceOfflineWithName": "{0} został rozłączony", - "DeviceOnlineWithName": "{0} połączył się", "FailedLoginAttemptWithUserName": "Nieudana próba logowania przez {0}", "Favorites": "Ulubione", "Folders": "Foldery", "Genres": "Gatunki", - "HeaderAlbumArtists": "Wykonawcy albumów", "HeaderContinueWatching": "Kontynuuj odtwarzanie", - "HeaderFavoriteAlbums": "Ulubione albumy", - "HeaderFavoriteArtists": "Ulubieni wykonawcy", "HeaderFavoriteEpisodes": "Ulubione odcinki", "HeaderFavoriteShows": "Ulubione seriale", - "HeaderFavoriteSongs": "Ulubione utwory", "HeaderLiveTV": "Telewizja", "HeaderNextUp": "Do obejrzenia", - "HeaderRecordingGroups": "Grupy nagrań", "HomeVideos": "Nagrania domowe", "Inherit": "Dziedzicz", - "ItemAddedWithName": "{0} zostało dodane do biblioteki", - "ItemRemovedWithName": "{0} zostało usunięte z biblioteki", "LabelIpAddressValue": "Adres IP: {0}", "LabelRunningTimeValue": "Czas trwania: {0}", "Latest": "Ostatnio dodane", - "MessageApplicationUpdated": "Serwer Jellyfin został zaktualizowany", - "MessageApplicationUpdatedTo": "Serwer Jellyfin został zaktualizowany do wersji {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "Sekcja {0} konfiguracji serwera została zaktualizowana", - "MessageServerConfigurationUpdated": "Konfiguracja serwera została zaktualizowana", "MixedContent": "Zawartość mieszana", "Movies": "Filmy", "Music": "Muzyka", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "Rozpoczęto odtwarzanie wideo", "NotificationOptionVideoPlaybackStopped": "Zatrzymano odtwarzanie wideo", "Photos": "Zdjęcia", - "Playlists": "Listy odtwarzania", - "Plugin": "Wtyczka", "PluginInstalledWithName": "{0} zostało zainstalowane", "PluginUninstalledWithName": "{0} odinstalowane", "PluginUpdatedWithName": "{0} zaktualizowane", - "ProviderValue": "Dostawca: {0}", "ScheduledTaskFailedWithName": "Nieudane {0}", - "ScheduledTaskStartedWithName": "Rozpoczęto {0}", - "ServerNameNeedsToBeRestarted": "{0} wymaga ponownego uruchomienia", "Shows": "Seriale", - "Songs": "Utwory", "StartupEmbyServerIsLoading": "Trwa wczytywanie serwera Jellyfin. Spróbuj ponownie za chwilę.", "SubtitleDownloadFailureFromForItem": "Nieudane pobieranie napisów z {0} dla {1}", - "Sync": "Synchronizacja", - "System": "System", "TvShows": "Seriale", - "User": "Użytkownik", "UserCreatedWithName": "Użytkownik {0} został utworzony", "UserDeletedWithName": "Użytkownik {0} został usunięty", "UserDownloadingItemWithValues": "{0} pobiera {1}", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "{0} z {1} został rozłączony", "UserOnlineFromDevice": "{0} połączył się z {1}", "UserPasswordChangedWithName": "Hasło użytkownika {0} zostało zmienione", - "UserPolicyUpdatedWithName": "Zmieniono zasady użytkowania dla {0}", "UserStartedPlayingItemWithValues": "{0} odtwarza {1} na {2}", "UserStoppedPlayingItemWithValues": "{0} zakończył odtwarzanie {1} na {2}", - "ValueHasBeenAddedToLibrary": "{0} został dodany do biblioteki mediów", - "ValueSpecialEpisodeName": "Specjalne - {0}", "VersionNumber": "Wersja {0}", "TaskDownloadMissingSubtitlesDescription": "Przeszukuje internet w poszukiwaniu brakujących napisów w oparciu o konfigurację metadanych.", "TaskDownloadMissingSubtitles": "Pobierz brakujące napisy", @@ -136,5 +107,6 @@ "TaskMoveTrickplayImagesDescription": "Przenosi istniejące pliki Trickplay zgodnie z ustawieniami biblioteki.", "CleanupUserDataTaskDescription": "Usuwa wszystkie dane użytkownika (stan oglądanych, status ulubionych itp.) z mediów, które nie są dostępne od co najmniej 90 dni.", "CleanupUserDataTask": "Zadanie czyszczenia danych użytkownika", - "Original": "Oryginalny" + "Original": "Oryginalny", + "LyricDownloadFailureFromForItem": "Błąd podczas pobierania tekstu piosenki z {0} dla {1}" } diff --git a/Emby.Server.Implementations/Localization/Core/pr.json b/Emby.Server.Implementations/Localization/Core/pr.json index fee7e65f1d..912f5c876a 100644 --- a/Emby.Server.Implementations/Localization/Core/pr.json +++ b/Emby.Server.Implementations/Localization/Core/pr.json @@ -2,48 +2,31 @@ "Books": "Scrolls", "AuthenticationSucceededWithUserName": "{0} passed yer trial", "Artists": "Artistas", - "Songs": "Shantees", - "Albums": "Tomes", "Photos": "Paintings", "NotificationOptionUserLockedOut": "Crewmate sent to the brig", "HeaderContinueWatching": "Continue Yer Journey", "Folders": "Chests", - "Application": "Captain", - "DeviceOnlineWithName": "{0} joined yer crew", - "DeviceOfflineWithName": "{0} abandoned ship", "AppDeviceValues": "Captain: {0}, Ship: {1}", - "CameraImageUploadedFrom": "Yer looking glass has glimpsed another painting from {0}", "Collections": "Barrels", - "ItemAddedWithName": "{0} is now with yer treasure", "Default": "Normal-like", "FailedLoginAttemptWithUserName": "Ye failed to enter from {0}", "Favorites": "Finest Loot", - "ItemRemovedWithName": "{0} was taken from yer treasure", "LabelIpAddressValue": "Ship's coordinates: {0}", "Genres": "types o' booty", "TaskDownloadMissingSubtitlesDescription": "Scours the seven seas o' the internet for subtitles that be missin' based on the captain's map o' metadata.", - "HeaderAlbumArtists": "Buccaneers o' the musical arts", - "HeaderFavoriteAlbums": "Beloved booty o' musical adventures", - "HeaderFavoriteArtists": "Treasured scallywags o' the creative seas", - "Channels": "Channels", "Forced": "Pressed", "External": "Outboard", "HeaderFavoriteEpisodes": "Treasured Tales", "HeaderFavoriteShows": "Treasured Tales", "ChapterNameValue": "Piece {0}", - "HeaderFavoriteSongs": "Treasured Chimes", "HeaderNextUp": "Incoming", "HeaderLiveTV": "Scrying Glass", "HearingImpaired": "Hard o' Hearing", "LabelRunningTimeValue": "Journey duration: {0}", - "MessageApplicationUpdated": "Yer Map of the Seas has been scribbled", "HomeVideos": "Yer Onboard Booty", "MixedContent": "Jumbled loot", "Music": "Tunes", "NameInstallFailed": "Ye couldn't bring {0} aboard yer ship", - "MessageApplicationUpdatedTo": "Yer Map of the Seas has been scribbled with {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "Yer Map Drawer has been rescribbled to {0}", - "MessageServerConfigurationUpdated": "Yer Map drawer has been rescribbled", "Inherit": "Carry on what be passed along", "Latest": "Newfangled", "Movies": "Moving pictures", @@ -55,17 +38,13 @@ "UserOfflineFromDevice": "{0} severed ties with {1}", "UserDownloadingItemWithValues": "{0} be haulin’ in {1}", "UserStartedPlayingItemWithValues": "{0} be playin’ {1} aboard {2}", - "ValueHasBeenAddedToLibrary": "{0} be stashed in yer treasure trove", "TaskCleanCacheDescription": "Wipes away cache cargo no longer called fer.", "TaskCleanLogsDescription": "Clears the logbook o’ entries older than {0} days.", "TaskRefreshPeopleDescription": "Refreshes the charts fer actors an’ directors in yer Treasure Trove.", "UserLockedOutWithName": "Matey {0} be denied boarding", "TaskAudioNormalization": "Steadyin’ the shanties", "TaskAudioNormalizationDescription": "Scans files fer shanty steadiyin’ data.", - "HeaderRecordingGroups": "Loggin' Groups", "MusicVideos": "Shanty films", - "Playlists": "Lists o’ plunder", - "Plugin": "Extra sail", "NotificationOptionVideoPlaybackStopped": "Video playback dropped anchor", "NameSeasonNumber": "Saga {0}", "NameSeasonUnknown": "Saga be Lost", @@ -87,23 +66,15 @@ "TaskRefreshPeople": "Freshen the Mateys", "PluginUninstalledWithName": "{0} sent t’ Davy Jones", "PluginUpdatedWithName": "{0} patched ‘n ready", - "ProviderValue": "Supplier o’ goods: {0}", - "ScheduledTaskStartedWithName": "{0} set sail", - "ServerNameNeedsToBeRestarted": "{0} be cravin’ a restart", "Shows": "Sagas", "SubtitleDownloadFailureFromForItem": "Subtitles be sunk fetchin’ from {0} fer {1}", - "Sync": "Match the tides", - "System": "The ship’s works", "TvShows": "TV Sagas", "Undefined": "Uncharted", - "User": "Matey", "UserCreatedWithName": "Matey {0} joined the crew", "UserDeletedWithName": "Matey {0} cast overboard", "UserOnlineFromDevice": "{0} be aboard ship from {1}", "UserPasswordChangedWithName": "New passphrase set fer Matey {0}", - "UserPolicyUpdatedWithName": "Ship rules be changed fer {0}", "UserStoppedPlayingItemWithValues": "{0} be done playin’ {1} on {2", - "ValueSpecialEpisodeName": "Special Tale – {0}", "VersionNumber": "Edition {0}", "TasksMaintenanceCategory": "Hull patchin’", "TasksLibraryCategory": "Treasure Trove", diff --git a/Emby.Server.Implementations/Localization/Core/pt-BR.json b/Emby.Server.Implementations/Localization/Core/pt-BR.json index 99f76c953f..1db500adf3 100644 --- a/Emby.Server.Implementations/Localization/Core/pt-BR.json +++ b/Emby.Server.Implementations/Localization/Core/pt-BR.json @@ -1,41 +1,24 @@ { - "Albums": "Álbuns", "AppDeviceValues": "App: {0}, Dispositivo: {1}", - "Application": "Aplicativo", "Artists": "Artistas", "AuthenticationSucceededWithUserName": "{0} autenticado com sucesso", "Books": "Livros", - "CameraImageUploadedFrom": "Uma nova imagem da câmera foi enviada de {0}", - "Channels": "Canais", "ChapterNameValue": "Capítulo {0}", "Collections": "Coleções", - "DeviceOfflineWithName": "{0} se desconectou", - "DeviceOnlineWithName": "{0} se conectou", "FailedLoginAttemptWithUserName": "Falha na tentativa de login de {0}", "Favorites": "Favoritos", "Folders": "Pastas", "Genres": "Gêneros", - "HeaderAlbumArtists": "Artistas do Álbum", "HeaderContinueWatching": "Continuar assistindo", - "HeaderFavoriteAlbums": "Álbuns Favoritos", - "HeaderFavoriteArtists": "Artistas favoritos", "HeaderFavoriteEpisodes": "Episódios favoritos", "HeaderFavoriteShows": "Séries favoritas", - "HeaderFavoriteSongs": "Músicas favoritas", "HeaderLiveTV": "TV ao Vivo", "HeaderNextUp": "A Seguir", - "HeaderRecordingGroups": "Grupos de Gravação", "HomeVideos": "Vídeos caseiros", "Inherit": "Herdar", - "ItemAddedWithName": "{0} foi adicionado à biblioteca", - "ItemRemovedWithName": "{0} foi removido da biblioteca", "LabelIpAddressValue": "Endereço IP: {0}", "LabelRunningTimeValue": "Tempo de execução: {0}", "Latest": "Recentes", - "MessageApplicationUpdated": "Servidor Jellyfin atualizado", - "MessageApplicationUpdatedTo": "Servidor Jellyfin atualizado para {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "A seção {0} da configuração do servidor foi atualizada", - "MessageServerConfigurationUpdated": "A configuração do servidor foi atualizada", "MixedContent": "Conteúdo misto", "Movies": "Filmes", "Music": "Música", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "Reprodução de vídeo iniciada", "NotificationOptionVideoPlaybackStopped": "Reprodução de vídeo parada", "Photos": "Fotos", - "Playlists": "Listas de Reprodução", - "Plugin": "Plugin", "PluginInstalledWithName": "{0} foi instalado", "PluginUninstalledWithName": "{0} foi desinstalado", "PluginUpdatedWithName": "{0} foi atualizado", - "ProviderValue": "Provedor: {0}", "ScheduledTaskFailedWithName": "{0} falhou", - "ScheduledTaskStartedWithName": "{0} iniciada", - "ServerNameNeedsToBeRestarted": "O servidor {0} precisa ser reiniciado", "Shows": "Séries", - "Songs": "Músicas", "StartupEmbyServerIsLoading": "O Servidor Jellyfin está carregando. Por favor, tente novamente mais tarde.", "SubtitleDownloadFailureFromForItem": "Houve um problema ao baixar as legendas de {0} para {1}", - "Sync": "Sincronizar", - "System": "Sistema", "TvShows": "Séries", - "User": "Usuário", "UserCreatedWithName": "O usuário {0} foi criado", "UserDeletedWithName": "O usuário {0} foi excluído", "UserDownloadingItemWithValues": "{0} está baixando {1}", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "{0} se desconectou de {1}", "UserOnlineFromDevice": "{0} está online em {1}", "UserPasswordChangedWithName": "A senha foi alterada para o usuário {0}", - "UserPolicyUpdatedWithName": "A política de usuário foi atualizada para {0}", "UserStartedPlayingItemWithValues": "{0} está reproduzindo {1} em {2}", "UserStoppedPlayingItemWithValues": "{0} parou de reproduzir {1} em {2}", - "ValueHasBeenAddedToLibrary": "{0} foi adicionado à sua biblioteca de mídia", - "ValueSpecialEpisodeName": "Especial - {0}", "VersionNumber": "Versão {0}", "TaskDownloadMissingSubtitlesDescription": "Procurar na internet por legendas faltando baseado na configuração de metadados.", "TaskDownloadMissingSubtitles": "Baixar legendas que estão faltando", @@ -135,5 +106,7 @@ "TaskExtractMediaSegmentsDescription": "Extrai ou obtém segmentos de mídia de plug-ins habilitados para MediaSegment.", "TaskMoveTrickplayImages": "Migrar o local da imagem do Trickplay", "CleanupUserDataTask": "Tarefa de limpeza de dados do usuário", - "CleanupUserDataTaskDescription": "Limpa todos os dados do usuário (estado de visualização, status de favorito, etc.) de mídias que não estão presentes por pelo menos 90 dias." + "CleanupUserDataTaskDescription": "Limpa todos os dados do usuário (estado de visualização, status de favorito, etc.) de mídias que não estão presentes por pelo menos 90 dias.", + "LyricDownloadFailureFromForItem": "Download das Letras falharam em {0} para o item {1}", + "Original": "Original" } diff --git a/Emby.Server.Implementations/Localization/Core/pt-PT.json b/Emby.Server.Implementations/Localization/Core/pt-PT.json index 93dfa7e7f5..ce7f6d120e 100644 --- a/Emby.Server.Implementations/Localization/Core/pt-PT.json +++ b/Emby.Server.Implementations/Localization/Core/pt-PT.json @@ -1,41 +1,24 @@ { - "Albums": "Álbuns", "AppDeviceValues": "Aplicação: {0}, Dispositivo: {1}", - "Application": "Aplicação", "Artists": "Artistas", "AuthenticationSucceededWithUserName": "{0} autenticado com sucesso", "Books": "Livros", - "CameraImageUploadedFrom": "Uma nova imagem da câmara foi enviada a partir de {0}", - "Channels": "Canais", "ChapterNameValue": "Capítulo {0}", "Collections": "Coleções", - "DeviceOfflineWithName": "{0} desligou-se", - "DeviceOnlineWithName": "{0} ligou-se", "FailedLoginAttemptWithUserName": "Tentativa de login falhada a partir de {0}", "Favorites": "Favoritos", "Folders": "Pastas", "Genres": "Géneros", - "HeaderAlbumArtists": "Artistas do álbum", "HeaderContinueWatching": "Continuar a ver", - "HeaderFavoriteAlbums": "Álbuns Favoritos", - "HeaderFavoriteArtists": "Artistas Favoritos", "HeaderFavoriteEpisodes": "Episódios Favoritos", "HeaderFavoriteShows": "Séries Favoritas", - "HeaderFavoriteSongs": "Músicas Favoritas", "HeaderLiveTV": "TV em Direto", "HeaderNextUp": "A Seguir", - "HeaderRecordingGroups": "Grupos de Gravação", "HomeVideos": "Vídeos Caseiros", "Inherit": "Herdar", - "ItemAddedWithName": "{0} foi adicionado à mediateca", - "ItemRemovedWithName": "{0} foi removido da mediateca", "LabelIpAddressValue": "Endereço IP: {0}", "LabelRunningTimeValue": "Duração: {0}", "Latest": "Mais Recente", - "MessageApplicationUpdated": "O servidor Jellyfin foi atualizado", - "MessageApplicationUpdatedTo": "O servidor Jellyfin foi atualizado para a versão {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "Configurações de servidor na secção {0} foram atualizadas", - "MessageServerConfigurationUpdated": "A configuração do servidor foi atualizada", "MixedContent": "Conteúdo Misto", "Movies": "Filmes", "Music": "Música", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "Reprodução do vídeo iniciada", "NotificationOptionVideoPlaybackStopped": "Reprodução do vídeo parada", "Photos": "Fotografias", - "Playlists": "Playlists", - "Plugin": "Extensão", "PluginInstalledWithName": "{0} foi instalado", "PluginUninstalledWithName": "{0} foi desinstalado", "PluginUpdatedWithName": "{0} foi atualizado", - "ProviderValue": "Provider: {0}", "ScheduledTaskFailedWithName": "{0} falhou", - "ScheduledTaskStartedWithName": "{0} iniciou", - "ServerNameNeedsToBeRestarted": "{0} necessita de ser reiniciado", "Shows": "Séries", - "Songs": "Músicas", "StartupEmbyServerIsLoading": "O servidor Jellyfin está a iniciar. Tente novamente mais tarde.", "SubtitleDownloadFailureFromForItem": "Falha na transferência de legendas a partir de {0} para {1}", - "Sync": "Sincronização", - "System": "Sistema", "TvShows": "Séries", - "User": "Utilizador", "UserCreatedWithName": "Utilizador {0} criado", "UserDeletedWithName": "Utilizador {0} apagado", "UserDownloadingItemWithValues": "{0} está a transferir {1}", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "{0} desligou-se a partir de {1}", "UserOnlineFromDevice": "{0} ligou-se a partir de {1}", "UserPasswordChangedWithName": "Palavra-passe alterada para o utilizador {0}", - "UserPolicyUpdatedWithName": "Política de utilizador alterada para {0}", "UserStartedPlayingItemWithValues": "{0} está a reproduzir {1} em {2}", "UserStoppedPlayingItemWithValues": "{0} terminou a reprodução de {1} em {2}", - "ValueHasBeenAddedToLibrary": "{0} foi adicionado à sua mediateca", - "ValueSpecialEpisodeName": "Especial - {0}", "VersionNumber": "Versão {0}", "TaskDownloadMissingSubtitlesDescription": "Procurar na internet por legendas em falta baseado na configuração de metadados.", "TaskDownloadMissingSubtitles": "Transferir legendas em falta", @@ -136,5 +107,6 @@ "TaskMoveTrickplayImagesDescription": "Move os ficheiros trickplay existentes de acordo com as definições da mediateca.", "CleanupUserDataTaskDescription": "Apaga todos os dados de utilizador (estados de reprodução, favoritos, etc) de arquivos média não presentes há 90 dias ou mais.", "CleanupUserDataTask": "Limpeza de dados de utilizador", - "Original": "Original" + "Original": "Original", + "LyricDownloadFailureFromForItem": "Erro ao descarregar letras de {0} para {1}" } diff --git a/Emby.Server.Implementations/Localization/Core/pt.json b/Emby.Server.Implementations/Localization/Core/pt.json index ce288223bb..ce338acf34 100644 --- a/Emby.Server.Implementations/Localization/Core/pt.json +++ b/Emby.Server.Implementations/Localization/Core/pt.json @@ -3,44 +3,30 @@ "Collections": "Coleções", "Books": "Livros", "Artists": "Artistas", - "Albums": "Álbuns", "HeaderNextUp": "A Seguir", - "HeaderFavoriteSongs": "Músicas Favoritas", - "HeaderFavoriteArtists": "Artistas Favoritos", - "HeaderFavoriteAlbums": "Álbuns Favoritos", "HeaderFavoriteEpisodes": "Episódios Favoritos", "HeaderFavoriteShows": "Séries Favoritas", "HeaderContinueWatching": "Continuar a ver", - "HeaderAlbumArtists": "Artistas do Álbum", "Genres": "Géneros", "Folders": "Pastas", "Favorites": "Favoritos", - "Channels": "Canais", "UserDownloadingItemWithValues": "{0} está sendo baixado {1}", "VersionNumber": "Versão {0}", - "ValueHasBeenAddedToLibrary": "{0} foi adicionado à sua mediateca", "UserStoppedPlayingItemWithValues": "{0} terminou a reprodução de {1} em {2}", "UserStartedPlayingItemWithValues": "{0} está reproduzindo {1} em {2}", - "UserPolicyUpdatedWithName": "A política do usuário {0} foi alterada", "UserPasswordChangedWithName": "A senha do usuário {0} foi alterada", "UserOnlineFromDevice": "{0} está online a partir de {1}", "UserOfflineFromDevice": "{0} desconectou-se a partir de {1}", "UserLockedOutWithName": "O usuário {0} foi bloqueado", "UserDeletedWithName": "O usuário {0} foi removido", "UserCreatedWithName": "O usuário {0} foi criado", - "User": "Usuário", "TvShows": "Séries", - "System": "Sistema", "SubtitleDownloadFailureFromForItem": "Falha na transferência de legendas de {0} para {1}", "StartupEmbyServerIsLoading": "O servidor Jellyfin está iniciando. Tente novamente dentro de momentos.", - "ServerNameNeedsToBeRestarted": "{0} necessita ser reiniciado", - "ScheduledTaskStartedWithName": "{0} iniciou", "ScheduledTaskFailedWithName": "{0} falhou", - "ProviderValue": "Fornecedor: {0}", "PluginUpdatedWithName": "{0} foi atualizado", "PluginUninstalledWithName": "{0} foi desinstalado", "PluginInstalledWithName": "{0} foi instalado", - "Plugin": "Plugin", "NotificationOptionVideoPlaybackStopped": "Reprodução de vídeo parada", "NotificationOptionVideoPlayback": "Reprodução de vídeo iniciada", "NotificationOptionUserLockedOut": "Usuário bloqueado", @@ -64,32 +50,17 @@ "MusicVideos": "Videoclipes", "Music": "Música", "MixedContent": "Conteúdo diverso", - "MessageServerConfigurationUpdated": "A configuração do servidor foi atualizada", - "MessageNamedServerConfigurationUpdatedWithValue": "As configurações do servidor na seção {0} foram atualizadas", - "MessageApplicationUpdatedTo": "O servidor Jellyfin foi atualizado para a versão {0}", - "MessageApplicationUpdated": "O servidor Jellyfin foi atualizado", "Latest": "Mais Recente", "LabelRunningTimeValue": "Duração: {0}", "LabelIpAddressValue": "Endereço de IP: {0}", - "ItemRemovedWithName": "{0} foi removido da mediateca", - "ItemAddedWithName": "{0} foi adicionado à mediateca", "Inherit": "Herdar", "HomeVideos": "Vídeos Caseiros", - "HeaderRecordingGroups": "Grupos de Gravação", - "ValueSpecialEpisodeName": "Especial - {0}", - "Sync": "Sincronização", - "Songs": "Músicas", "Shows": "Séries", - "Playlists": "Playlists", "Photos": "Fotografias", "Movies": "Filmes", "FailedLoginAttemptWithUserName": "Tentativa de início de sessão falhada a partir de {0}", - "DeviceOnlineWithName": "{0} está ligado", - "DeviceOfflineWithName": "{0} desligou-se", "ChapterNameValue": "Capítulo {0}", - "CameraImageUploadedFrom": "Uma nova imagem da câmara foi enviada a partir de {0}", "AuthenticationSucceededWithUserName": "{0} autenticado com sucesso", - "Application": "Aplicação", "AppDeviceValues": "Aplicação: {0}, Dispositivo: {1}", "TaskCleanCache": "Limpar Diretório de Cache", "TasksApplicationCategory": "Aplicação", @@ -136,5 +107,6 @@ "TaskMoveTrickplayImages": "Migrar a localização da imagem do Trickplay", "CleanupUserDataTask": "Task de limpeza de dados do usuário", "CleanupUserDataTaskDescription": "Remove todos os dados do usuário (progresso, favoritos etc) de mídias que não estão presentes há pelo menos 90 dias.", - "Original": "Original" + "Original": "Original", + "LyricDownloadFailureFromForItem": "Erro ao descarregar letras de {0} para {1}" } diff --git a/Emby.Server.Implementations/Localization/Core/ro.json b/Emby.Server.Implementations/Localization/Core/ro.json index 30214218f8..ea83b88951 100644 --- a/Emby.Server.Implementations/Localization/Core/ro.json +++ b/Emby.Server.Implementations/Localization/Core/ro.json @@ -1,11 +1,8 @@ { "HeaderNextUp": "Urmează", "VersionNumber": "Versiunea {0}", - "ValueSpecialEpisodeName": "Special - {0}", - "ValueHasBeenAddedToLibrary": "{0} a fost adăugat la biblioteca multimedia", "UserStoppedPlayingItemWithValues": "{0} a terminat rularea {1} pe {2}", "UserStartedPlayingItemWithValues": "{0} ruleaza {1} pe {2}", - "UserPolicyUpdatedWithName": "Politica utilizatorului {0} a fost actualizată", "UserPasswordChangedWithName": "Parola utilizatorului {0} a fost schimbată", "UserOnlineFromDevice": "{0} este conectat de la {1}", "UserOfflineFromDevice": "{0} s-a deconectat de la {1}", @@ -13,23 +10,14 @@ "UserDownloadingItemWithValues": "{0} descarcă {1}", "UserDeletedWithName": "Utilizatorul {0} a fost șters", "UserCreatedWithName": "Utilizatorul {0} a fost creat", - "User": "Utilizator", "TvShows": "Seriale TV", - "System": "Sistem", - "Sync": "Sincronizare", "SubtitleDownloadFailureFromForItem": "Subtitrările nu au putut fi descărcate de la {0} pentru {1}", "StartupEmbyServerIsLoading": "Se încarcă serverul Jellyfin. Încercați din nou în scurt timp.", - "Songs": "Melodii", "Shows": "Seriale", - "ServerNameNeedsToBeRestarted": "{0} trebuie să fie repornit", - "ScheduledTaskStartedWithName": "{0} pornit/ă", "ScheduledTaskFailedWithName": "{0} eșuat/ă", - "ProviderValue": "Furnizor: {0}", "PluginUpdatedWithName": "{0} a fost actualizat/ă", "PluginUninstalledWithName": "{0} a fost dezinstalat", "PluginInstalledWithName": "{0} a fost instalat", - "Plugin": "Extensie", - "Playlists": "Liste de redare", "Photos": "Fotografii", "NotificationOptionVideoPlaybackStopped": "Redarea video oprită", "NotificationOptionVideoPlayback": "Redare video începută", @@ -55,42 +43,25 @@ "Music": "Muzică", "Movies": "Filme", "MixedContent": "Conținut amestecat", - "MessageServerConfigurationUpdated": "Configurarea serverului a fost actualizată", - "MessageNamedServerConfigurationUpdatedWithValue": "Secțiunea de configurare a serverului {0} a fost acualizata", - "MessageApplicationUpdatedTo": "Jellyfin Server a fost actualizat la {0}", - "MessageApplicationUpdated": "Jellyfin Server a fost actualizat", "Latest": "Cele mai recente", "LabelRunningTimeValue": "Durată: {0}", "LabelIpAddressValue": "Adresa IP: {0}", - "ItemRemovedWithName": "{0} a fost eliminat din bibliotecă", - "ItemAddedWithName": "{0} a fost adăugat în bibliotecă", "Inherit": "Moștenit", "HomeVideos": "Filme personale", - "HeaderRecordingGroups": "Grupuri de înregistrare", "HeaderLiveTV": "TV în Direct", - "HeaderFavoriteSongs": "Melodii Favorite", "HeaderFavoriteShows": "Seriale TV Favorite", "HeaderFavoriteEpisodes": "Episoade Favorite", - "HeaderFavoriteArtists": "Artiști Favoriți", - "HeaderFavoriteAlbums": "Albume Favorite", "HeaderContinueWatching": "Vizionează în continuare", - "HeaderAlbumArtists": "Artiști album", "Genres": "Genuri", "Folders": "Dosare", "Favorites": "Preferate", "FailedLoginAttemptWithUserName": "Încercare de conectare eșuată pentru {0}", - "DeviceOnlineWithName": "{0} este conectat", - "DeviceOfflineWithName": "{0} s-a deconectat", "Collections": "Colecții", "ChapterNameValue": "Capitolul {0}", - "Channels": "Canale", - "CameraImageUploadedFrom": "O nouă fotografie a fost încărcată din {0}", "Books": "Cărți", "AuthenticationSucceededWithUserName": "{0} autentificare reușită", "Artists": "Artiști", - "Application": "Aplicație", "AppDeviceValues": "Aplicație: {0}, Dispozitiv: {1}", - "Albums": "Albume", "TaskDownloadMissingSubtitlesDescription": "Caută pe internet subtitrările lipsă pe baza configurației metadatelor.", "TaskDownloadMissingSubtitles": "Descarcă subtitrările lipsă", "TaskRefreshChannelsDescription": "Actualizează informațiile despre canalul de internet.", @@ -135,5 +106,7 @@ "TaskDownloadMissingLyrics": "Descarcă versurile lipsă", "TaskDownloadMissingLyricsDescription": "Descarcă versuri pentru melodii", "CleanupUserDataTask": "Sarcina de curatare a datelor utilizatorului", - "CleanupUserDataTaskDescription": "Sterge toate datele utilizatorului (starea vizionarii, starea favoritelor etc.) de pe suporturile media care nu mai sunt prezente timp de cel puțin 90 de zile." + "CleanupUserDataTaskDescription": "Sterge toate datele utilizatorului (starea vizionarii, starea favoritelor etc.) de pe suporturile media care nu mai sunt prezente timp de cel puțin 90 de zile.", + "LyricDownloadFailureFromForItem": "Versurile nu au putut fi descărcate din {0} pentru {1}", + "Original": "Original" } diff --git a/Emby.Server.Implementations/Localization/Core/ru.json b/Emby.Server.Implementations/Localization/Core/ru.json index 38920b6ede..40d5e3985d 100644 --- a/Emby.Server.Implementations/Localization/Core/ru.json +++ b/Emby.Server.Implementations/Localization/Core/ru.json @@ -1,41 +1,24 @@ { - "Albums": "Альбомы", "AppDeviceValues": "Приложение: {0}, Устройство: {1}", - "Application": "Приложение", "Artists": "Исполнители", "AuthenticationSucceededWithUserName": "{0} - авторизация успешна", "Books": "Книги", - "CameraImageUploadedFrom": "Новое фото загружено с камеры {0}", - "Channels": "Каналы", "ChapterNameValue": "Сцена {0}", "Collections": "Коллекции", - "DeviceOfflineWithName": "{0} - отключено", - "DeviceOnlineWithName": "{0} - подключено", "FailedLoginAttemptWithUserName": "Неудачная попытка входа с {0}", "Favorites": "Избранное", "Folders": "Папки", "Genres": "Жанры", - "HeaderAlbumArtists": "Исполнители альбома", "HeaderContinueWatching": "Продолжить просмотр", - "HeaderFavoriteAlbums": "Избранные альбомы", - "HeaderFavoriteArtists": "Избранные исполнители", "HeaderFavoriteEpisodes": "Избранные эпизоды", "HeaderFavoriteShows": "Избранные сериалы", - "HeaderFavoriteSongs": "Избранные композиции", "HeaderLiveTV": "Эфир", "HeaderNextUp": "Следующий", - "HeaderRecordingGroups": "Группы записей", "HomeVideos": "Домашние видео", "Inherit": "Наследуемое", - "ItemAddedWithName": "{0} - добавлено в медиатеку", - "ItemRemovedWithName": "{0} - изъято из медиатеки", "LabelIpAddressValue": "IP-адрес: {0}", "LabelRunningTimeValue": "Длительность: {0}", "Latest": "Последние", - "MessageApplicationUpdated": "Jellyfin Server был обновлён", - "MessageApplicationUpdatedTo": "Jellyfin Server был обновлён до {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "Конфигурация сервера (раздел {0}) была обновлена", - "MessageServerConfigurationUpdated": "Конфигурация сервера была обновлена", "MixedContent": "Смешанное содержание", "Movies": "Фильмы", "Music": "Музыка", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "Воспроизведение видео запущено", "NotificationOptionVideoPlaybackStopped": "Воспроизведение видео остановлено", "Photos": "Фото", - "Playlists": "Плей-листы", - "Plugin": "Плагин", "PluginInstalledWithName": "{0} - было установлено", "PluginUninstalledWithName": "{0} - было удалено", "PluginUpdatedWithName": "{0} - было обновлено", - "ProviderValue": "Поставщик: {0}", "ScheduledTaskFailedWithName": "{0} - неудачна", - "ScheduledTaskStartedWithName": "{0} - запущена", - "ServerNameNeedsToBeRestarted": "Необходим перезапуск {0}", "Shows": "Сериалы", - "Songs": "Композиции", "StartupEmbyServerIsLoading": "Jellyfin Server загружается. Повторите попытку в ближайшее время.", "SubtitleDownloadFailureFromForItem": "Субтитры к {1} не удалось загрузить с {0}", - "Sync": "Синхронизация", - "System": "Система", "TvShows": "Телесериалы", - "User": "Пользователь", "UserCreatedWithName": "Пользователь {0} был создан", "UserDeletedWithName": "Пользователь {0} был удалён", "UserDownloadingItemWithValues": "{0} загружает {1}", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "{0} отключился с {1}", "UserOnlineFromDevice": "{0} подключился с {1}", "UserPasswordChangedWithName": "Пароль пользователя {0} был изменён", - "UserPolicyUpdatedWithName": "Политики пользователя {0} были обновлены", "UserStartedPlayingItemWithValues": "{0} - воспроизведение «{1}» на {2}", "UserStoppedPlayingItemWithValues": "{0} - воспроизведение остановлено «{1}» на {2}", - "ValueHasBeenAddedToLibrary": "{0} добавлено в медиатеку", - "ValueSpecialEpisodeName": "Спецэпизод - {0}", "VersionNumber": "Версия {0}", "TaskDownloadMissingSubtitles": "Загрузка отсутствующих субтитров", "TaskRefreshChannels": "Обновление каналов", @@ -135,5 +106,7 @@ "TaskExtractMediaSegmentsDescription": "Извлекает или получает медиасегменты из плагинов MediaSegment.", "TaskMoveTrickplayImagesDescription": "Перемещает существующие файлы trickplay в соответствии с настройками медиатеки.", "CleanupUserDataTask": "Задача очистки пользовательских данных", - "CleanupUserDataTaskDescription": "Очищает все пользовательские данные (состояние просмотра, статус избранного и т.д.) с медиа, отсутствующих по меньшей мере в течение 90 дней." + "CleanupUserDataTaskDescription": "Очищает все пользовательские данные (состояние просмотра, статус избранного и т.д.) с медиа, отсутствующих по меньшей мере в течение 90 дней.", + "Original": "Оригинальный", + "LyricDownloadFailureFromForItem": "Не получилось скачать текст песни с {0} для {1}" } diff --git a/Emby.Server.Implementations/Localization/Core/si.json b/Emby.Server.Implementations/Localization/Core/si.json index 0967ef424b..8efc0d1f2e 100644 --- a/Emby.Server.Implementations/Localization/Core/si.json +++ b/Emby.Server.Implementations/Localization/Core/si.json @@ -1 +1,15 @@ -{} +{ + "AppDeviceValues": "ඇප්: {0}, උපාංග: {1}", + "Artists": "කලාකරුවන්", + "AuthenticationSucceededWithUserName": "{0} සාර්ථකව තහවුරු කරන ලදී", + "Books": "පොත්", + "ChapterNameValue": "{0} වෙනි පරිච්ඡේදය", + "Collections": "සංහිතා", + "Default": "පෙරනිමි", + "External": "බාහිර", + "FailedLoginAttemptWithUserName": "{0} වෙතින් සිදුකළ පිවිසීමේ උත්සාහය අසාර්ථක විය", + "Favorites": "ප්රියතමයන්", + "Folders": "ෆෝල්ඩර", + "Forced": "නියමිත", + "Genres": "ප්රභේද" +} diff --git a/Emby.Server.Implementations/Localization/Core/sk.json b/Emby.Server.Implementations/Localization/Core/sk.json index 184e9b0a5c..7ae8857e5d 100644 --- a/Emby.Server.Implementations/Localization/Core/sk.json +++ b/Emby.Server.Implementations/Localization/Core/sk.json @@ -1,41 +1,24 @@ { - "Albums": "Albumy", "AppDeviceValues": "Aplikácia: {0}, Zariadenie: {1}", - "Application": "Aplikácia", "Artists": "Interpreti", "AuthenticationSucceededWithUserName": "{0} úspešne overený", "Books": "Knihy", - "CameraImageUploadedFrom": "Z {0} bola nahraná nová fotografia", - "Channels": "Kanály", "ChapterNameValue": "Kapitola {0}", "Collections": "Kolekcie", - "DeviceOfflineWithName": "{0} sa odpojil", - "DeviceOnlineWithName": "{0} je pripojený", "FailedLoginAttemptWithUserName": "Neúspešný pokus o prihlásenie z {0}", "Favorites": "Obľúbené", "Folders": "Priečinky", "Genres": "Žánre", - "HeaderAlbumArtists": "Interpreti albumu", "HeaderContinueWatching": "Pokračovať v pozeraní", - "HeaderFavoriteAlbums": "Obľúbené albumy", - "HeaderFavoriteArtists": "Obľúbení interpreti", "HeaderFavoriteEpisodes": "Obľúbené epizódy", "HeaderFavoriteShows": "Obľúbené seriály", - "HeaderFavoriteSongs": "Obľúbené skladby", "HeaderLiveTV": "Živá TV", "HeaderNextUp": "Nasleduje", - "HeaderRecordingGroups": "Skupiny nahrávok", "HomeVideos": "Domáce videá", "Inherit": "Zdediť", - "ItemAddedWithName": "{0} bol pridaný do knižnice", - "ItemRemovedWithName": "{0} bol odstránený z knižnice", "LabelIpAddressValue": "IP adresa: {0}", "LabelRunningTimeValue": "Dĺžka: {0}", "Latest": "Najnovšie", - "MessageApplicationUpdated": "Jellyfin Server bol aktualizovaný", - "MessageApplicationUpdatedTo": "Jellyfin Server bol aktualizovaný na verziu {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "Sekcia {0} konfigurácie servera bola aktualizovaná", - "MessageServerConfigurationUpdated": "Konfigurácia servera bola aktualizovaná", "MixedContent": "Zmiešaný obsah", "Movies": "Filmy", "Music": "Hudba", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "Spustené prehrávanie videa", "NotificationOptionVideoPlaybackStopped": "Zastavené prehrávanie videa", "Photos": "Fotky", - "Playlists": "Playlisty", - "Plugin": "Zásuvný modul", "PluginInstalledWithName": "{0} bol nainštalovaný", "PluginUninstalledWithName": "{0} bol odinštalovaný", "PluginUpdatedWithName": "{0} bol aktualizovaný", - "ProviderValue": "Poskytovateľ: {0}", "ScheduledTaskFailedWithName": "{0} zlyhalo", - "ScheduledTaskStartedWithName": "{0} zahájených", - "ServerNameNeedsToBeRestarted": "{0} vyžaduje reštart", "Shows": "Seriály", - "Songs": "Skladby", "StartupEmbyServerIsLoading": "Jellyfin Server sa spúšťa. Prosím, skúste to o chvíľu znova.", "SubtitleDownloadFailureFromForItem": "Sťahovanie titulkov z {0} pre {1} zlyhalo", - "Sync": "Synchronizácia", - "System": "Systém", "TvShows": "TV seriály", - "User": "Používateľ", "UserCreatedWithName": "Používateľ {0} bol vytvorený", "UserDeletedWithName": "Používateľ {0} bol vymazaný", "UserDownloadingItemWithValues": "{0} sťahuje {1}", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "{0} sa odpojil od {1}", "UserOnlineFromDevice": "{0} je online z {1}", "UserPasswordChangedWithName": "Heslo používateľa {0} bolo zmenené", - "UserPolicyUpdatedWithName": "Používateľské zásady pre {0} boli aktualizované", "UserStartedPlayingItemWithValues": "{0} spustil prehrávanie {1} na {2}", "UserStoppedPlayingItemWithValues": "{0} ukončil prehrávanie {1} na {2}", - "ValueHasBeenAddedToLibrary": "{0} bol pridaný do vašej knižnice médií", - "ValueSpecialEpisodeName": "Špeciál - {0}", "VersionNumber": "Verzia {0}", "TaskDownloadMissingSubtitlesDescription": "Vyhľadá na internete chýbajúce titulky podľa toho, ako sú nakonfigurované metadáta.", "TaskDownloadMissingSubtitles": "Stiahnuť chýbajúce titulky", @@ -135,5 +106,7 @@ "TaskDownloadMissingLyrics": "Stiahnuť chýbajúce texty piesní", "TaskDownloadMissingLyricsDescription": "Stiahne texty pre piesne", "CleanupUserDataTask": "Prečistiť používateľské dáta", - "CleanupUserDataTaskDescription": "Vyčistí všetky dáta používateľa (stav sledovania, stav obľúbených atď.) z médií, ktoré už neexistujú aspoň 90 dní." + "CleanupUserDataTaskDescription": "Vyčistí všetky dáta používateľa (stav sledovania, stav obľúbených atď.) z médií, ktoré už neexistujú aspoň 90 dní.", + "LyricDownloadFailureFromForItem": "Text piesne sa nepodarilo stiahnuť z {0} pre {1}", + "Original": "Originál" } diff --git a/Emby.Server.Implementations/Localization/Core/sl-SI.json b/Emby.Server.Implementations/Localization/Core/sl-SI.json index 35c5b4a914..a1b5b714af 100644 --- a/Emby.Server.Implementations/Localization/Core/sl-SI.json +++ b/Emby.Server.Implementations/Localization/Core/sl-SI.json @@ -1,41 +1,24 @@ { - "Albums": "Albumi", "AppDeviceValues": "Aplikacija: {0}, Naprava: {1}", - "Application": "Aplikacija", "Artists": "Izvajalci", "AuthenticationSucceededWithUserName": "{0} se je uspešno prijavil/a", "Books": "Knjige", - "CameraImageUploadedFrom": "Nova fotografija je bila naložena iz {0}", - "Channels": "Kanali", "ChapterNameValue": "Poglavje {0}", "Collections": "Zbirke", - "DeviceOfflineWithName": "{0} je prekinil povezavo", - "DeviceOnlineWithName": "{0} je povezan", "FailedLoginAttemptWithUserName": "Neuspešen poskus prijave z {0}", "Favorites": "Priljubljeno", "Folders": "Mape", "Genres": "Zvrsti", - "HeaderAlbumArtists": "Izvajalci albuma", "HeaderContinueWatching": "Nadaljuj ogled", - "HeaderFavoriteAlbums": "Priljubljeni albumi", - "HeaderFavoriteArtists": "Priljubljeni izvajalci", "HeaderFavoriteEpisodes": "Priljubljene epizode", "HeaderFavoriteShows": "Priljubljene serije", - "HeaderFavoriteSongs": "Priljubljene pesmi", "HeaderLiveTV": "TV v živo", "HeaderNextUp": "Sledi", - "HeaderRecordingGroups": "Zbirke posnetkov", "HomeVideos": "Domači posnetki", "Inherit": "Podeduj", - "ItemAddedWithName": "{0} je dodan v knjižnico", - "ItemRemovedWithName": "{0} je bil odstranjen iz knjižnice", "LabelIpAddressValue": "IP naslov: {0}", "LabelRunningTimeValue": "Čas trajanja: {0}", "Latest": "Najnovejše", - "MessageApplicationUpdated": "Jellyfin strežnik je bil posodobljen", - "MessageApplicationUpdatedTo": "Jellyfin strežnik je bil posodobljen na {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "Oddelek nastavitev {0} je bil posodobljen", - "MessageServerConfigurationUpdated": "Nastavitve strežnika so bile posodobljene", "MixedContent": "Mešane vsebine", "Movies": "Filmi", "Music": "Glasba", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "Predvajanje videa se je začelo", "NotificationOptionVideoPlaybackStopped": "Predvajanje videa se je ustavilo", "Photos": "Fotografije", - "Playlists": "Seznami predvajanja", - "Plugin": "Dodatek", "PluginInstalledWithName": "{0} je bil nameščen", "PluginUninstalledWithName": "{0} je bil odstranjen", "PluginUpdatedWithName": "{0} je bil posodobljen", - "ProviderValue": "Ponudnik: {0}", "ScheduledTaskFailedWithName": "{0} ni uspelo", - "ScheduledTaskStartedWithName": "{0} začeto", - "ServerNameNeedsToBeRestarted": "{0} mora biti ponovno zagnan", "Shows": "Serije", - "Songs": "Pesmi", "StartupEmbyServerIsLoading": "Jellyfin strežnik se zaganja. Poskusite ponovno kasneje.", "SubtitleDownloadFailureFromForItem": "Neuspešen prenos podnapisov iz {0} za {1}", - "Sync": "Sinhroniziraj", - "System": "Sistem", "TvShows": "TV serije", - "User": "Uporabnik", "UserCreatedWithName": "Uporabnik {0} je bil ustvarjen", "UserDeletedWithName": "Uporabnik {0} je bil izbrisan", "UserDownloadingItemWithValues": "{0} prenaša {1}", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "{0} je prekinil povezavo z {1}", "UserOnlineFromDevice": "{0} je aktiven na {1}", "UserPasswordChangedWithName": "Geslo za uporabnika {0} je bilo spremenjeno", - "UserPolicyUpdatedWithName": "Pravilnik uporabe je bil posodobljen za uporabnika {0}", "UserStartedPlayingItemWithValues": "{0} predvaja {1} na {2}", "UserStoppedPlayingItemWithValues": "{0} je nehal predvajati {1} na {2}", - "ValueHasBeenAddedToLibrary": "{0} je bil dodan vaši knjižnici", - "ValueSpecialEpisodeName": "Posebna epizoda - {0}", "VersionNumber": "Različica {0}", "TaskDownloadMissingSubtitles": "Prenesi manjkajoče podnapise", "TaskRefreshChannelsDescription": "Osveži podatke spletnih kanalov.", @@ -135,5 +106,7 @@ "TaskAudioNormalization": "Normalizacija zvoka", "TaskAudioNormalizationDescription": "Pregled datotek za podatke o normalizaciji zvoka.", "CleanupUserDataTask": "Čiščenje uporabniških podatkov", - "CleanupUserDataTaskDescription": "Izbriše vse uporabniške podatke (stanje ogleda, priljubljene itd.) za vsebine, ki že več kot 90 dni niso na voljo." + "CleanupUserDataTaskDescription": "Izbriše vse uporabniške podatke (stanje ogleda, priljubljene itd.) za vsebine, ki že več kot 90 dni niso na voljo.", + "LyricDownloadFailureFromForItem": "Besedila ni bilo mogoče prenesti iz {0} za {1}", + "Original": "Original" } diff --git a/Emby.Server.Implementations/Localization/Core/sn.json b/Emby.Server.Implementations/Localization/Core/sn.json index 74720e7646..45a459cbe1 100644 --- a/Emby.Server.Implementations/Localization/Core/sn.json +++ b/Emby.Server.Implementations/Localization/Core/sn.json @@ -1,28 +1,18 @@ { - "HeaderAlbumArtists": "Vaimbi vemadambarefu", "HeaderContinueWatching": "Simudzira kuona", - "HeaderFavoriteSongs": "Nziyo dzaunofarira", - "Albums": "Dambarefu", "AppDeviceValues": "Apu: {0}, Dhivhaisi: {1}", - "Application": "Purogiramu", "Artists": "Vaimbi", "AuthenticationSucceededWithUserName": "apinda", "Books": "Mabhuku", - "CameraImageUploadedFrom": "Mufananidzo mutsva vabva pakamera {0}", - "Channels": "Machanewo", "ChapterNameValue": "Chikamu {0}", "Collections": "Akafanana", "Default": "Zvakasarudzwa Kare", - "DeviceOfflineWithName": "{0} haasisipo", - "DeviceOnlineWithName": "{0} aripo", "External": "Zvekunze", "FailedLoginAttemptWithUserName": "Vatadza kuloga chimboedza kushandisa {0}", "Favorites": "Zvaunofarira", "Folders": "Mafoodha", "Forced": "Zvekumanikidzira", "Genres": "Mhando", - "HeaderFavoriteAlbums": "Madambarefu aunofarira", - "HeaderFavoriteArtists": "Vaimbi vaunofarira", "HeaderFavoriteEpisodes": "Maepisodhi aunofarira", "HeaderFavoriteShows": "Masirisi aunofarira" } diff --git a/Emby.Server.Implementations/Localization/Core/sq.json b/Emby.Server.Implementations/Localization/Core/sq.json index 5a284e20b9..e13f7b09e1 100644 --- a/Emby.Server.Implementations/Localization/Core/sq.json +++ b/Emby.Server.Implementations/Localization/Core/sq.json @@ -1,5 +1,4 @@ { - "MessageApplicationUpdatedTo": "Serveri Jellyfin u përditesua në versionin {0}", "Inherit": "Trashgimi", "TaskDownloadMissingSubtitlesDescription": "Kërkon në internet për titra që mungojnë bazuar tek konfigurimi i metadata-ve.", "TaskDownloadMissingSubtitles": "Shkarko titra që mungojnë", @@ -24,11 +23,8 @@ "TasksLibraryCategory": "Libraria", "TasksMaintenanceCategory": "Mirëmbajtje", "VersionNumber": "Versioni {0}", - "ValueSpecialEpisodeName": "Speciale - {0}", - "ValueHasBeenAddedToLibrary": "{0} u shtua tek libraria juaj", "UserStoppedPlayingItemWithValues": "{0} mbaroi së shikuari {1} tek {2}", "UserStartedPlayingItemWithValues": "{0} po shikon {1} tek {2}", - "UserPolicyUpdatedWithName": "Politika e përdoruesit u përditësua për {0}", "UserPasswordChangedWithName": "Fjalëkalimi u ndryshua për përdoruesin {0}", "UserOnlineFromDevice": "{0} është në linjë nga {1}", "UserOfflineFromDevice": "{0} u shkëput nga {1}", @@ -36,23 +32,14 @@ "UserDownloadingItemWithValues": "{0} po shkarkon {1}", "UserDeletedWithName": "Përdoruesi {0} u fshi", "UserCreatedWithName": "Përdoruesi {0} u krijua", - "User": "Përdoruesi", "TvShows": "Seriale TV", - "System": "Sistemi", - "Sync": "Sinkronizo", "SubtitleDownloadFailureFromForItem": "Titrat deshtuan të shkarkohen nga {0} për {1}", "StartupEmbyServerIsLoading": "Serveri Jellyfin po ngarkohet. Ju lutemi provoni përseri pas pak.", - "Songs": "Këngët", "Shows": "Serialet", - "ServerNameNeedsToBeRestarted": "{0} duhet të ristartoj", - "ScheduledTaskStartedWithName": "{0} filloi", "ScheduledTaskFailedWithName": "{0} dështoi", - "ProviderValue": "Ofruesi: {0}", "PluginUpdatedWithName": "{0} u përditësua", "PluginUninstalledWithName": "{0} u çinstalua", "PluginInstalledWithName": "{0} u instalua", - "Plugin": "Plugin", - "Playlists": "Listat për luajtje", "Photos": "Fotografitë", "NotificationOptionVideoPlaybackStopped": "Luajtja e videos ndaloi", "NotificationOptionVideoPlayback": "Luajtja e videos filloi", @@ -78,41 +65,25 @@ "Music": "Muzikë", "Movies": "Filmat", "MixedContent": "Përmbajtje e përzier", - "MessageServerConfigurationUpdated": "Konfigurimet e serverit u përditësuan", - "MessageNamedServerConfigurationUpdatedWithValue": "Seksioni i konfigurimit të serverit {0} u përditësua", - "MessageApplicationUpdated": "Serveri Jellyfin u përditësua", "Latest": "Të fundit", "LabelRunningTimeValue": "Kohëzgjatja: {0}", "LabelIpAddressValue": "Adresa IP: {0}", - "ItemRemovedWithName": "{0} u fshi nga libraria", - "ItemAddedWithName": "{0} u shtua tek libraria", "HomeVideos": "Video personale", - "HeaderRecordingGroups": "Grupet e regjistrimit", "HeaderNextUp": "Në vazhdim", "HeaderLiveTV": "TV Live", - "HeaderFavoriteSongs": "Kënget e preferuara", "HeaderFavoriteShows": "Serialet e preferuar", "HeaderFavoriteEpisodes": "Episodet e preferuar", - "HeaderFavoriteArtists": "Artistët e preferuar", - "HeaderFavoriteAlbums": "Albumet e preferuar", "HeaderContinueWatching": "Vazhdo të shikosh", - "HeaderAlbumArtists": "Artistët e albumeve", "Genres": "Zhanret", "Folders": "Skedarët", "Favorites": "Të preferuarat", "FailedLoginAttemptWithUserName": "Përpjekja për hyrje dështoi nga {0}", - "DeviceOnlineWithName": "{0} u lidh", - "DeviceOfflineWithName": "{0} u shkëput", "Collections": "Koleksionet", "ChapterNameValue": "Kapituj", - "Channels": "Kanalet", - "CameraImageUploadedFrom": "Një foto e re nga kamera u ngarkua nga {0}", "Books": "Librat", "AuthenticationSucceededWithUserName": "{0} u identifikua me sukses", "Artists": "Artistët", - "Application": "Aplikacioni", "AppDeviceValues": "Aplikacioni: {0}, Pajisja: {1}", - "Albums": "Albumet", "TaskCleanActivityLogDescription": "Pastro të dhënat mbi aktivitetin më të vjetra sesa koha e përcaktuar.", "TaskCleanActivityLog": "Pastro të dhënat mbi aktivitetin", "Undefined": "I papërcaktuar", @@ -135,5 +106,7 @@ "TaskAudioNormalization": "Normalizimi i audios", "TaskAudioNormalizationDescription": "Skannon skedarët për të dhëna të normalizimit të audios.", "CleanupUserDataTaskDescription": "Pastron të gjitha të dhënat e përdorueseve (gjendja e shikimit, statusi i të preferuarave etj.) nga mediat që nuk janë më të pranishme për të paktën 90 ditë.", - "CleanupUserDataTask": "Veprim për pastrimin të dhënave të përdorueseve" + "CleanupUserDataTask": "Veprim për pastrimin të dhënave të përdorueseve", + "LyricDownloadFailureFromForItem": "Teksti i këngës nuk arriti të shkarkohej nga {0} për {1}", + "Original": "Origjinal" } diff --git a/Emby.Server.Implementations/Localization/Core/sr.json b/Emby.Server.Implementations/Localization/Core/sr.json index 52f4124657..92f309c80c 100644 --- a/Emby.Server.Implementations/Localization/Core/sr.json +++ b/Emby.Server.Implementations/Localization/Core/sr.json @@ -1,9 +1,6 @@ { - "UserPolicyUpdatedWithName": "Корисничке смернице ажуриране за {0}", "NotificationOptionUserLockedOut": "Корисник закључан", "VersionNumber": "Верзија {0}", - "ValueSpecialEpisodeName": "Специјал - {0}", - "ValueHasBeenAddedToLibrary": "{0} је додато у вашу медијску библиотеку", "UserStoppedPlayingItemWithValues": "{0} завршио пуштање {1} на {2}", "UserStartedPlayingItemWithValues": "{0} пушта {1} на {2}", "UserPasswordChangedWithName": "Лозинка је промењена за корисника {0}", @@ -13,23 +10,14 @@ "UserDownloadingItemWithValues": "{0} преузима {1}", "UserDeletedWithName": "Корисник {0} је обрисан", "UserCreatedWithName": "Корисник {0} је направљен", - "User": "Корисник", "TvShows": "ТВ серије", - "System": "Систем", - "Sync": "Усклади", "SubtitleDownloadFailureFromForItem": "Неуспело преузимање титлова за {1} са {0}", "StartupEmbyServerIsLoading": "Џелифин сервер се подиже. Покушајте поново убрзо.", - "Songs": "Песме", "Shows": "Серије", - "ServerNameNeedsToBeRestarted": "{0} треба поново покренути", - "ScheduledTaskStartedWithName": "{0} покренуто", "ScheduledTaskFailedWithName": "{0} неуспело", - "ProviderValue": "Пружалац: {0}", "PluginUpdatedWithName": "{0} ажуриран", "PluginUninstalledWithName": "{0} деинсталиран", "PluginInstalledWithName": "{0} инсталиран", - "Plugin": "Прикључак", - "Playlists": "Листе", "Photos": "Фотографије", "NotificationOptionVideoPlaybackStopped": "Заустављено пуштање видеа", "NotificationOptionVideoPlayback": "Покренуто пуштање видеа", @@ -54,43 +42,26 @@ "Music": "Музика", "Movies": "Филмови", "MixedContent": "Мешовит садржај", - "MessageServerConfigurationUpdated": "Серверска поставка је ажурирана", - "MessageNamedServerConfigurationUpdatedWithValue": "Одељак серверске поставке {0} је ажуриран", - "MessageApplicationUpdatedTo": "Џелифин сервер је ажуриран на {0}", - "MessageApplicationUpdated": "Џелифин сервер је ажуриран", "Latest": "Последње", "LabelRunningTimeValue": "Време рада: {0}", "LabelIpAddressValue": "ИП адреса: {0}", - "ItemRemovedWithName": "{0} уклоњено из библиотеке", - "ItemAddedWithName": "{0} додато у библиотеку", "Inherit": "Наследи", "HomeVideos": "Кућни Видео", - "HeaderRecordingGroups": "Групе снимања", "HeaderNextUp": "Следи", "HeaderLiveTV": "ТВ уживо", - "HeaderFavoriteSongs": "Омиљене песме", "HeaderFavoriteShows": "Омиљене серије", "HeaderFavoriteEpisodes": "Омиљене епизоде", - "HeaderFavoriteArtists": "Омиљени извођачи", - "HeaderFavoriteAlbums": "Омиљени албуми", "HeaderContinueWatching": "Настави гледање", - "HeaderAlbumArtists": "Извођачи албума", "Genres": "Жанрови", "Folders": "Фасцикле", "Favorites": "Омиљено", "FailedLoginAttemptWithUserName": "Неуспели покушај пријавe са {0}", - "DeviceOnlineWithName": "{0} је повезан", - "DeviceOfflineWithName": "{0} је прекинуо везу", "Collections": "Колекције", "ChapterNameValue": "Поглавље {0}", - "Channels": "Канали", - "CameraImageUploadedFrom": "Нова фотографија је учитана са {0}", "Books": "Књиге", "AuthenticationSucceededWithUserName": "{0} Успешна аутентификација", "Artists": "Извођачи", - "Application": "Апликација", "AppDeviceValues": "Апликација: {0}, Уређај: {1}", - "Albums": "Албуми", "TaskDownloadMissingSubtitlesDescription": "Претражује интернет за недостајуће титлове на основу конфигурације метаподатака.", "TaskDownloadMissingSubtitles": "Преузмите недостајуће титлове", "TaskRefreshChannelsDescription": "Освежава информације о интернет каналу.", @@ -135,5 +106,7 @@ "CleanupUserDataTask": "Задатак чишћења корисничких података", "CleanupUserDataTaskDescription": "Чисти све корисничке податке (напредак гледања, ознаке за омиљено...) медија који нису доступни 90 дана или дуже.", "TaskMoveTrickplayImages": "Промени локацију сличица за визуелно премотавање", - "TaskDownloadMissingLyricsDescription": "Преузми стихове песама" + "TaskDownloadMissingLyricsDescription": "Преузми стихове песама", + "LyricDownloadFailureFromForItem": "Није успело преузимање стихова са {0} за {1}", + "Original": "Изворно" } diff --git a/Emby.Server.Implementations/Localization/Core/sv.json b/Emby.Server.Implementations/Localization/Core/sv.json index 015f59af25..7384967122 100644 --- a/Emby.Server.Implementations/Localization/Core/sv.json +++ b/Emby.Server.Implementations/Localization/Core/sv.json @@ -1,41 +1,24 @@ { - "Albums": "Album", "AppDeviceValues": "Applikation: {0}, Enhet: {1}", - "Application": "Applikation", "Artists": "Artister", "AuthenticationSucceededWithUserName": "{0} har autentiserats", "Books": "Böcker", - "CameraImageUploadedFrom": "En ny kamerabild har laddats upp från {0}", - "Channels": "Kanaler", "ChapterNameValue": "Kapitel {0}", "Collections": "Samlingar", - "DeviceOfflineWithName": "{0} har kopplat ned", - "DeviceOnlineWithName": "{0} är ansluten", "FailedLoginAttemptWithUserName": "Misslyckat inloggningsförsök från {0}", "Favorites": "Favoriter", "Folders": "Mappar", "Genres": "Genrer", - "HeaderAlbumArtists": "Albumartister", "HeaderContinueWatching": "Fortsätt titta", - "HeaderFavoriteAlbums": "Favoritalbum", - "HeaderFavoriteArtists": "Favoritartister", "HeaderFavoriteEpisodes": "Favoritavsnitt", "HeaderFavoriteShows": "Favoritserier", - "HeaderFavoriteSongs": "Favoritlåtar", "HeaderLiveTV": "Direktsänd TV", "HeaderNextUp": "Nästa", - "HeaderRecordingGroups": "Inspelningsgrupper", "HomeVideos": "Hemmavideor", "Inherit": "Ärv", - "ItemAddedWithName": "{0} lades till i biblioteket", - "ItemRemovedWithName": "{0} togs bort från biblioteket", "LabelIpAddressValue": "IP-adress: {0}", "LabelRunningTimeValue": "Speltid: {0}", "Latest": "Senaste", - "MessageApplicationUpdated": "Jellyfin Server har uppdaterats", - "MessageApplicationUpdatedTo": "Jellyfin Server har uppdaterats till {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "Serverinställningarna {0} har uppdaterats", - "MessageServerConfigurationUpdated": "Serverkonfigurationen har uppdaterats", "MixedContent": "Blandat innehåll", "Movies": "Filmer", "Music": "Musik", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "Videouppspelning har påbörjats", "NotificationOptionVideoPlaybackStopped": "Videouppspelning stoppades", "Photos": "Bilder", - "Playlists": "Spellistor", - "Plugin": "Tillägg", "PluginInstalledWithName": "{0} installerades", "PluginUninstalledWithName": "{0} avinstallerades", "PluginUpdatedWithName": "{0} uppdaterades", - "ProviderValue": "Leverantör: {0}", "ScheduledTaskFailedWithName": "{0} misslyckades", - "ScheduledTaskStartedWithName": "{0} startades", - "ServerNameNeedsToBeRestarted": "{0} behöver startas om", "Shows": "Serier", - "Songs": "Låtar", "StartupEmbyServerIsLoading": "Jellyfin Server arbetar. Pröva igen snart.", "SubtitleDownloadFailureFromForItem": "Undertexter kunde inte laddas ner från {0} till {1}", - "Sync": "Synk", - "System": "System", "TvShows": "Tv-serier", - "User": "Användare", "UserCreatedWithName": "Användaren {0} har skapats", "UserDeletedWithName": "Användaren {0} har tagits bort", "UserDownloadingItemWithValues": "{0} laddar ner {1}", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "{0} har kopplat ned från {1}", "UserOnlineFromDevice": "{0} är uppkopplad från {1}", "UserPasswordChangedWithName": "Lösenordet för {0} har ändrats", - "UserPolicyUpdatedWithName": "Användarpolicyn har uppdaterats för {0}", "UserStartedPlayingItemWithValues": "{0} spelar {1} på {2}", "UserStoppedPlayingItemWithValues": "{0} har stoppat uppspelningen av {1} på {2}", - "ValueHasBeenAddedToLibrary": "{0} har lagts till i ditt mediebibliotek", - "ValueSpecialEpisodeName": "Specialavsnitt - {0}", "VersionNumber": "Version {0}", "TaskDownloadMissingSubtitlesDescription": "Söker på internet efter saknade undertexter baserat på metadata-konfiguration.", "TaskDownloadMissingSubtitles": "Ladda ner saknade undertexter", @@ -136,5 +107,6 @@ "TaskMoveTrickplayImagesDescription": "Flyttar befintliga trickplay-filer enligt bibliotekets inställningar.", "CleanupUserDataTaskDescription": "Tar bort all användardata (såsom vad du sett, favoriter med mera) för media som inte funnits på enheten på minst 90 dagar.", "CleanupUserDataTask": "Uppgift för rensning av användardata", - "Original": "Original" + "Original": "Original", + "LyricDownloadFailureFromForItem": "Misslyckades att ladda ner låttexter från {0} för {1}" } diff --git a/Emby.Server.Implementations/Localization/Core/sw.json b/Emby.Server.Implementations/Localization/Core/sw.json index 0967ef424b..c117a0eae2 100644 --- a/Emby.Server.Implementations/Localization/Core/sw.json +++ b/Emby.Server.Implementations/Localization/Core/sw.json @@ -1 +1,5 @@ -{} +{ + "Artists": "Wasanii", + "Books": "Vitabu", + "Collections": "Mikusanyiko" +} diff --git a/Emby.Server.Implementations/Localization/Core/ta.json b/Emby.Server.Implementations/Localization/Core/ta.json index b68af92033..f613b973db 100644 --- a/Emby.Server.Implementations/Localization/Core/ta.json +++ b/Emby.Server.Implementations/Localization/Core/ta.json @@ -1,13 +1,11 @@ { "VersionNumber": "பதிப்பு {0}", - "ValueSpecialEpisodeName": "சிறப்பு - {0}", "TasksMaintenanceCategory": "பராமரிப்பு", "TaskCleanCache": "தற்காலிக சேமிப்பு கோப்பகத்தை சுத்தம் செய்யவும்", "TaskRefreshChapterImages": "அத்தியாயப் படங்களை பிரித்தெடுக்கவும்", "TaskRefreshPeople": "மக்களைப் புதுப்பிக்கவும்", "TaskCleanTranscode": "டிரான்ஸ்கோட் கோப்பகத்தை சுத்தம் செய்யவும்", "TaskRefreshChannelsDescription": "இணையச் சேனல் தகவல்களைப் புதுப்பிக்கிறது.", - "System": "ஒருங்கியம்", "NotificationOptionTaskFailed": "திட்டமிடப்பட்ட பணி தோல்வியடைந்தது", "NotificationOptionPluginUpdateInstalled": "உட்செருகி புதுப்பிக்கப்பட்டது", "NotificationOptionPluginUninstalled": "உட்செருகி நீக்கப்பட்டது", @@ -15,17 +13,10 @@ "NotificationOptionPluginError": "உட்செருகி செயலிழந்தது", "NotificationOptionCameraImageUploaded": "புகைப்படம் பதிவேற்றப்பட்டது", "MixedContent": "கலப்பு உள்ளடக்கங்கள்", - "MessageServerConfigurationUpdated": "சேவையக அமைப்புகள் புதுப்பிக்கப்பட்டன", - "MessageApplicationUpdatedTo": "ஜெல்லிஃபின் சேவையகம் {0} இற்கு புதுப்பிக்கப்பட்டது", - "MessageApplicationUpdated": "ஜெல்லிஃபின் சேவையகம் புதுப்பிக்கப்பட்டது", "Inherit": "மரபுரிமையாகப் பெறு", - "HeaderRecordingGroups": "பதிவு குழுக்கள்", "Folders": "கோப்புறைகள்", "FailedLoginAttemptWithUserName": "{0} இலிருந்து உள்நுழைவு முயற்சி தோல்வியடைந்தது", - "DeviceOnlineWithName": "{0} இணைக்கப்பட்டது", - "DeviceOfflineWithName": "{0} துண்டிக்கப்பட்டது", "Collections": "தொகுப்புகள்", - "CameraImageUploadedFrom": "{0} இல் இருந்து புதிய புகைப்படம் பதிவேற்றப்பட்டது", "AppDeviceValues": "செயலி: {0}, சாதனம்: {1}", "TaskDownloadMissingSubtitles": "விடுபட்டுபோன வசன வரிகளைப் பதிவிறக்கு", "TaskRefreshChannels": "சேனல்களை புதுப்பி", @@ -34,27 +25,18 @@ "TasksChannelsCategory": "இணைய சேனல்கள்", "TasksApplicationCategory": "செயலி", "TasksLibraryCategory": "நூலகம்", - "UserPolicyUpdatedWithName": "பயனர் கொள்கை {0} இற்கு புதுப்பிக்கப்பட்டுள்ளது", "UserPasswordChangedWithName": "{0} பயனருக்கு கடவுச்சொல் மாற்றப்பட்டுள்ளது", "UserLockedOutWithName": "பயனர் {0} முடக்கப்பட்டார்", "UserDownloadingItemWithValues": "{0} ஆல் {1} பதிவிறக்கப்படுகிறது", "UserDeletedWithName": "பயனர் {0} நீக்கப்பட்டார்", "UserCreatedWithName": "பயனர் {0} உருவாக்கப்பட்டார்", - "User": "பயனர்", "TvShows": "தொலைக்காட்சித் தொடர்கள்", - "Sync": "ஒத்திசைவு", "StartupEmbyServerIsLoading": "ஜெல்லிஃபின் சேவையகம் துவங்குகிறது. சிறிது நேரம் கழித்து முயற்சிக்கவும்.", - "Songs": "பாடல்கள்", "Shows": "நிகழ்ச்சிகள்", - "ServerNameNeedsToBeRestarted": "{0} மறுதொடக்கம் செய்யப்பட வேண்டும்", - "ScheduledTaskStartedWithName": "{0} துவங்கியது", "ScheduledTaskFailedWithName": "{0} தோல்வியடைந்தது", - "ProviderValue": "வழங்குநர்: {0}", "PluginUpdatedWithName": "{0} புதுப்பிக்கப்பட்டது", "PluginUninstalledWithName": "{0} நீக்கப்பட்டது", "PluginInstalledWithName": "{0} நிறுவப்பட்டது", - "Plugin": "உட்செருகி", - "Playlists": "தொடர் பட்டியல்கள்", "Photos": "புகைப்படங்கள்", "NotificationOptionVideoPlaybackStopped": "நிகழ்பட ஒளிபரப்பு நிறுத்தப்பட்டது", "NotificationOptionVideoPlayback": "நிகழ்பட ஒளிபரப்பு துவங்கியது", @@ -75,28 +57,18 @@ "Latest": "புதியவை", "LabelRunningTimeValue": "ஓடும் நேரம்: {0}", "LabelIpAddressValue": "ஐபி முகவரி: {0}", - "ItemRemovedWithName": "{0} நூலகத்திலிருந்து அகற்றப்பட்டது", - "ItemAddedWithName": "{0} நூலகத்தில் சேர்க்கப்பட்டது", "HeaderNextUp": "அடுத்தது", "HeaderLiveTV": "நேரடித் தொலைக்காட்சி", - "HeaderFavoriteSongs": "பிடித்த பாடல்கள்", "HeaderFavoriteShows": "பிடித்த தொடர்கள்", "HeaderFavoriteEpisodes": "பிடித்த அத்தியாயங்கள்", - "HeaderFavoriteArtists": "பிடித்த கலைஞர்கள்", - "HeaderFavoriteAlbums": "பிடித்த ஆல்பங்கள்", "HeaderContinueWatching": "தொடர்ந்து பார்", - "HeaderAlbumArtists": "கலைஞரின் ஆல்பம்", "Genres": "வகைகள்", "Favorites": "பிடித்தவை", "ChapterNameValue": "அத்தியாயம் {0}", - "Channels": "சேனல்கள்", "Books": "புத்தகங்கள்", "AuthenticationSucceededWithUserName": "{0} வெற்றிகரமாக அங்கீகரிக்கப்பட்டது", "Artists": "கலைஞர்கள்", - "Application": "செயலி", - "Albums": "ஆல்பங்கள்", "NewVersionIsAvailable": "ஜெல்லிஃபின் சேவையகத்தின் புதிய பதிப்பு பதிவிறக்கத்திற்கு கிடைக்கிறது.", - "MessageNamedServerConfigurationUpdatedWithValue": "சேவையக உள்ளமைவு பிரிவு {0} புதுப்பிக்கப்பட்டது", "TaskCleanCacheDescription": "கணினிக்கு இனி தேவைப்படாத தற்காலிக கோப்புகளை நீக்கு.", "UserOfflineFromDevice": "{0} இலிருந்து {1} துண்டிக்கப்பட்டுள்ளது", "SubtitleDownloadFailureFromForItem": "வசன வரிகள் {0} இல் இருந்து {1} க்கு பதிவிறக்கத் தவறிவிட்டன", @@ -108,7 +80,6 @@ "TaskCleanLogs": "பதிவு அடைவை சுத்தம் செய்யுங்கள்", "TaskRefreshLibraryDescription": "புதிய கோப்புகளுக்காக உங்கள் ஊடக நூலகத்தை ஆராய்ந்து மீத்தரவை புதுப்பிக்கும்.", "TaskRefreshChapterImagesDescription": "அத்தியாயங்களைக் கொண்ட வீடியோக்களுக்கான சிறு உருவங்களை உருவாக்குகிறது.", - "ValueHasBeenAddedToLibrary": "உங்கள் மீடியா நூலகத்தில் {0} சேர்க்கப்பட்டது", "UserOnlineFromDevice": "{1} இருந்து {0} ஆன்லைன்", "HomeVideos": "முகப்பு வீடியோக்கள்", "UserStoppedPlayingItemWithValues": "{0} {2} இல் {1} முடித்துவிட்டது", diff --git a/Emby.Server.Implementations/Localization/Core/te.json b/Emby.Server.Implementations/Localization/Core/te.json index ca9e345214..7ac770752e 100644 --- a/Emby.Server.Implementations/Localization/Core/te.json +++ b/Emby.Server.Implementations/Localization/Core/te.json @@ -1,51 +1,31 @@ { - "ValueSpecialEpisodeName": "ప్రత్యేక - {0}", - "Sync": "సమకాలీకరించు", - "Songs": "పాటలు", "Shows": "ప్రదర్శనలు", - "Playlists": "ప్లేజాబితాలు", "Photos": "ఫోటోలు", "MusicVideos": "మ్యూజిక్ వీడియోలు", "Music": "సంగీతం", "Movies": "సినిమాలు", "HeaderContinueWatching": "చూడటం కొనసాగించండి", - "HeaderAlbumArtists": "ఆల్బమ్ కళాకారులు", "Genres": "శైలులు", "Forced": "బలవంతంగా", "Folders": "ఫోల్డర్లు", "Favorites": "ఇష్టమైనవి", "Default": "డిఫాల్ట్", "Collections": "సేకరణలు", - "Channels": "ఛానెల్లు", "Books": "పుస్తకాలు", "Artists": "కళాకారులు", - "Albums": "ఆల్బమ్లు", "HearingImpaired": "వినికిడి లోపం", "HomeVideos": "హోమ్ వీడియోలు", "AppDeviceValues": "అప్లికేషన్ : {0}, పరికరం: {1}", - "Application": "అప్లికేషన్", "AuthenticationSucceededWithUserName": "విజయవంతంగా ఆమోదించబడింది", - "CameraImageUploadedFrom": "{0} నుండి కొత్త కెమెరా చిత్రం అప్లోడ్ చేయబడింది", "ChapterNameValue": "అధ్యాయం", - "DeviceOfflineWithName": "{0} డిస్కనెక్ట్ చేయబడింది", - "DeviceOnlineWithName": "{0} కనెక్ట్ చేయబడింది", "External": "బాహ్య", "FailedLoginAttemptWithUserName": "{0} నుండి విఫలమైన లాగిన్ ప్రయత్నం", - "HeaderFavoriteAlbums": "ఇష్టమైన ఆల్బమ్లు", - "HeaderFavoriteArtists": "ఇష్టమైన కళాకారులు", "HeaderFavoriteEpisodes": "ఇష్టమైన ఎపిసోడ్లు", "HeaderFavoriteShows": "ఇష్టమైన ప్రదర్శనలు", - "HeaderFavoriteSongs": "ఇష్టమైన పాటలు", "HeaderLiveTV": "ప్రత్యక్ష TV", "HeaderNextUp": "తదుపరి", - "HeaderRecordingGroups": "రికార్డింగ్ గుంపులు", - "MessageApplicationUpdated": "జెల్లీఫిన్ సర్వర్ అప్డేట్ చేయడం పూర్తి అయ్యింది", - "MessageApplicationUpdatedTo": "జెల్లీఫిన్ సర్వర్ {0} వెర్షన్ కి అప్డేట్ చెయ్యబడింది", - "MessageServerConfigurationUpdated": "సర్వర్ కన్ఫిగరేషన్ అప్డేట్ చేయబడింది", "NewVersionIsAvailable": "జెల్లీఫిన్ సర్వర్ యొక్క కొత్త వెర్షన్ డౌన్లోడ్ చేసుకోవడానికి అందుబాటులో ఉంది.", "NotificationOptionApplicationUpdateInstalled": "అప్లికేషన్ అప్డేట్ ఇన్స్టాల్ చేయబడింది", - "ItemAddedWithName": "{0} లైబ్రరీకి జోడించబడింది", - "ItemRemovedWithName": "లైబ్రరీ నుండి {0} తీసివేయబడింది", "LabelIpAddressValue": "ఐపీ చిరునామా: {0}", "LabelRunningTimeValue": "నడుస్తున్న సమయం: {0}", "Latest": "తాజా", diff --git a/Emby.Server.Implementations/Localization/Core/th.json b/Emby.Server.Implementations/Localization/Core/th.json index f0a62646f7..89c2c26748 100644 --- a/Emby.Server.Implementations/Localization/Core/th.json +++ b/Emby.Server.Implementations/Localization/Core/th.json @@ -1,10 +1,7 @@ { - "ProviderValue": "ผู้ให้บริการ: {0}", "PluginUpdatedWithName": "อัปเดต {0} แล้ว", "PluginUninstalledWithName": "ถอนการติดตั้ง {0} แล้ว", "PluginInstalledWithName": "ติดตั้ง {0} แล้ว", - "Plugin": "ปลั๊กอิน", - "Playlists": "เพลย์ลิสต์", "Photos": "รูปภาพ", "NotificationOptionVideoPlaybackStopped": "หยุดเล่นวิดีโอ", "NotificationOptionVideoPlayback": "เริ่มเล่นวิดีโอ", @@ -30,48 +27,28 @@ "Music": "ดนตรี", "Movies": "ภาพยนตร์", "MixedContent": "เนื้อหาผสม", - "MessageServerConfigurationUpdated": "อัปเดตการกำหนดค่าเซิร์ฟเวอร์แล้ว", - "MessageNamedServerConfigurationUpdatedWithValue": "อัปเดตการกำหนดค่าเซิร์ฟเวอร์ในส่วน {0} แล้ว", - "MessageApplicationUpdatedTo": "เซิร์ฟเวอร์ Jellyfin ได้รับการอัปเดตเป็น {0}", - "MessageApplicationUpdated": "อัพเดตเซิร์ฟเวอร์ Jellyfin แล้ว", "Latest": "ล่าสุด", "LabelRunningTimeValue": "ผ่านไปแล้ว: {0}", "LabelIpAddressValue": "ที่อยู่ IP: {0}", - "ItemRemovedWithName": "{0} ถูกลบออกจากไลบรารี", - "ItemAddedWithName": "{0} ถูกเพิ่มลงในไลบรารีแล้ว", "Inherit": "สืบทอด", "HomeVideos": "โฮมวิดีโอ", - "HeaderRecordingGroups": "กลุ่มการบันทึก", "HeaderNextUp": "ถัดไป", "HeaderLiveTV": "ทีวีสด", - "HeaderFavoriteSongs": "เพลงที่ชื่นชอบ", "HeaderFavoriteShows": "รายการที่ชื่นชอบ", "HeaderFavoriteEpisodes": "ตอนที่ชื่นชอบ", - "HeaderFavoriteArtists": "ศิลปินที่ชื่นชอบ", - "HeaderFavoriteAlbums": "อัมบั้มที่ชื่นชอบ", "HeaderContinueWatching": "ดูต่อ", - "HeaderAlbumArtists": "ศิลปินอัลบั้ม", "Genres": "ประเภท", "Folders": "โฟลเดอร์", "Favorites": "รายการโปรด", "FailedLoginAttemptWithUserName": "ความพยายามในการเข้าสู่ระบบล้มเหลวจาก {0}", - "DeviceOnlineWithName": "{0} เชื่อมต่อสำเร็จแล้ว", - "DeviceOfflineWithName": "{0} ยกเลิกการเชื่อมต่อแล้ว", "Collections": "คอลเลกชัน", "ChapterNameValue": "บทที่ {0}", - "Channels": "ช่อง", - "CameraImageUploadedFrom": "ภาพถ่ายใหม่ได้ถูกอัปโหลดมาจาก {0}", "Books": "หนังสือ", "AuthenticationSucceededWithUserName": "{0} ยืนยันตัวตนสำเร็จแล้ว", "Artists": "ศิลปิน", - "Application": "แอปพลิเคชัน", "AppDeviceValues": "แอป: {0}, อุปกรณ์: {1}", - "Albums": "อัลบั้ม", - "ScheduledTaskStartedWithName": "{0} เริ่มต้น", "ScheduledTaskFailedWithName": "{0} ล้มเหลว", - "Songs": "เพลง", "Shows": "รายการ", - "ServerNameNeedsToBeRestarted": "{0} ต้องการการรีสตาร์ท", "TaskDownloadMissingSubtitlesDescription": "ค้นหาคำบรรยายที่หายไปในอินเทอร์เน็ตตามค่ากำหนดในข้อมูลเมตา", "TaskDownloadMissingSubtitles": "ดาวน์โหลดคำบรรยายที่ขาดหายไป", "TaskRefreshChannelsDescription": "รีเฟรชข้อมูลช่องอินเทอร์เน็ต", @@ -95,11 +72,8 @@ "TasksLibraryCategory": "ไลบรารี", "TasksMaintenanceCategory": "ปิดซ่อมบำรุง", "VersionNumber": "เวอร์ชัน {0}", - "ValueSpecialEpisodeName": "พิเศษ - {0}", - "ValueHasBeenAddedToLibrary": "เพิ่ม {0} ลงในไลบรารีสื่อของคุณแล้ว", "UserStoppedPlayingItemWithValues": "{0} เล่นเสร็จแล้ว {1} บน {2}", "UserStartedPlayingItemWithValues": "{0} กำลังเล่น {1} บน {2}", - "UserPolicyUpdatedWithName": "มีการอัปเดตนโยบายผู้ใช้ของ {0}", "UserPasswordChangedWithName": "มีการเปลี่ยนรหัสผ่านของผู้ใช้ {0}", "UserOnlineFromDevice": "{0} ออนไลน์จาก {1}", "UserOfflineFromDevice": "{0} ได้ยกเลิกการเชื่อมต่อจาก {1}", @@ -107,10 +81,7 @@ "UserDownloadingItemWithValues": "{0} กำลังดาวน์โหลด {1}", "UserDeletedWithName": "ลบผู้ใช้ {0} แล้ว", "UserCreatedWithName": "สร้างผู้ใช้ {0} แล้ว", - "User": "ผู้ใช้งาน", "TvShows": "รายการทีวี", - "System": "ระบบ", - "Sync": "ซิงค์", "SubtitleDownloadFailureFromForItem": "ไม่สามารถดาวน์โหลดคำบรรยายจาก {0} สำหรับ {1} ได้", "StartupEmbyServerIsLoading": "กำลังโหลดเซิร์ฟเวอร์ Jellyfin โปรดลองอีกครั้งในอีกสักครู่", "Default": "ค่าเริ่มต้น", diff --git a/Emby.Server.Implementations/Localization/Core/tr.json b/Emby.Server.Implementations/Localization/Core/tr.json index 3789466868..0c42d4a55f 100644 --- a/Emby.Server.Implementations/Localization/Core/tr.json +++ b/Emby.Server.Implementations/Localization/Core/tr.json @@ -1,41 +1,24 @@ { - "Albums": "Albümler", "AppDeviceValues": "Uygulama: {0}, Aygıt: {1}", - "Application": "Uygulama", "Artists": "Sanatçılar", "AuthenticationSucceededWithUserName": "{0} kimliği başarıyla doğrulandı", "Books": "Kitaplar", - "CameraImageUploadedFrom": "{0} 'den yeni bir kamera resmi yüklendi", - "Channels": "Kanallar", "ChapterNameValue": "{0}. Bölüm", "Collections": "Koleksiyonlar", - "DeviceOfflineWithName": "{0} bağlantısı kesildi", - "DeviceOnlineWithName": "{0} bağlı", "FailedLoginAttemptWithUserName": "{0} kullanıcısının başarısız oturum açma girişimi", "Favorites": "Favoriler", "Folders": "Klasörler", "Genres": "Türler", - "HeaderAlbumArtists": "Albüm sanatçıları", "HeaderContinueWatching": "İzlemeye Devam Et", - "HeaderFavoriteAlbums": "Favori Albümler", - "HeaderFavoriteArtists": "Favori Sanatçılar", "HeaderFavoriteEpisodes": "Favori Bölümler", "HeaderFavoriteShows": "Favori Diziler", - "HeaderFavoriteSongs": "Favori Şarkılar", "HeaderLiveTV": "Canlı TV", "HeaderNextUp": "Sıradaki Bölümler", - "HeaderRecordingGroups": "Kayıt Grupları", "HomeVideos": "Ana Ekran Videoları", "Inherit": "Devral", - "ItemAddedWithName": "{0} kütüphaneye eklendi", - "ItemRemovedWithName": "{0} kütüphaneden silindi", "LabelIpAddressValue": "IP adresi: {0}", "LabelRunningTimeValue": "Oynatma süresi: {0}", "Latest": "En son", - "MessageApplicationUpdated": "Jellyfin Sunucusu güncellendi", - "MessageApplicationUpdatedTo": "Jellyfin Sunucusu {0} sürümüne güncellendi", - "MessageNamedServerConfigurationUpdatedWithValue": "Sunucu yapılandırma bölümü {0} güncellendi", - "MessageServerConfigurationUpdated": "Sunucu yapılandırması güncellendi", "MixedContent": "Karışık içerik", "Movies": "Filmler", "Music": "Müzik", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "Video oynatma başladı", "NotificationOptionVideoPlaybackStopped": "Video oynatma durduruldu", "Photos": "Fotoğraflar", - "Playlists": "Çalma listeleri", - "Plugin": "Eklenti", "PluginInstalledWithName": "{0} yüklendi", "PluginUninstalledWithName": "{0} kaldırıldı", "PluginUpdatedWithName": "{0} güncellendi", - "ProviderValue": "Sağlayıcı: {0}", "ScheduledTaskFailedWithName": "{0} başarısız oldu", - "ScheduledTaskStartedWithName": "{0} başladı", - "ServerNameNeedsToBeRestarted": "{0} yeniden başlatılması gerekiyor", "Shows": "Diziler", - "Songs": "Şarkılar", "StartupEmbyServerIsLoading": "Jellyfin Sunucusu yükleniyor. Lütfen kısa süre sonra tekrar deneyin.", "SubtitleDownloadFailureFromForItem": "{1} için altyazılar {0} sağlayıcısından indirilemedi", - "Sync": "Eşzamanlama", - "System": "Sistem", "TvShows": "Diziler", - "User": "Kullanıcı", "UserCreatedWithName": "{0} kullanıcısı oluşturuldu", "UserDeletedWithName": "{0} kullanıcısı silindi", "UserDownloadingItemWithValues": "{0} kullanıcısı {1} medyasını indiriyor", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "{0} kullanıcısının {1} ile bağlantısı kesildi", "UserOnlineFromDevice": "{0} kullanıcısı {1} ile çevrimiçi", "UserPasswordChangedWithName": "{0} kullanıcısının parolası değiştirildi", - "UserPolicyUpdatedWithName": "{0} için kullanıcı politikası güncellendi", "UserStartedPlayingItemWithValues": "{0}, {2} cihazında {1} izliyor", "UserStoppedPlayingItemWithValues": "{0}, {2} cihazında {1} izlemeyi bitirdi", - "ValueHasBeenAddedToLibrary": "{0} medya kütüphanenize eklendi", - "ValueSpecialEpisodeName": "Özel - {0}", "VersionNumber": "Sürüm {0}", "TaskCleanCache": "Önbellek Dizinini Temizle", "TasksChannelsCategory": "İnternet Kanalları", @@ -135,5 +106,7 @@ "TaskDownloadMissingLyricsDescription": "Şarkı sözlerini indirir", "TaskExtractMediaSegmentsDescription": "MediaSegment özelliği etkin olan eklentilerden medya segmentlerini çıkarır veya alır.", "CleanupUserDataTask": "Kullanıcı verisi temizleme görevi", - "CleanupUserDataTaskDescription": "En az 90 gün boyunca artık mevcut olmayan medyadaki tüm kullanıcı verilerini (İzleme durumu, favori durumu vb.) temizler." + "CleanupUserDataTaskDescription": "En az 90 gün boyunca artık mevcut olmayan medyadaki tüm kullanıcı verilerini (İzleme durumu, favori durumu vb.) temizler.", + "LyricDownloadFailureFromForItem": "{1} şarkı sözleri {0} adresinden indirilemedi", + "Original": "Orijinal" } diff --git a/Emby.Server.Implementations/Localization/Core/ug.json b/Emby.Server.Implementations/Localization/Core/ug.json index 0bcbffb41a..1d5adecb26 100644 --- a/Emby.Server.Implementations/Localization/Core/ug.json +++ b/Emby.Server.Implementations/Localization/Core/ug.json @@ -1,22 +1,15 @@ { "ChapterNameValue": "باب {0}", - "Channels": "قانال", - "CameraImageUploadedFrom": "{0} ئورۇندىن يېڭى سۈرەت چىقىرىلدى", "Books": "كىتاب", "AuthenticationSucceededWithUserName": "{0} تەستىقلاش مۇۋاپىقىيەتلىك بولدى", "Artists": "سەنئەتكار", - "Albums": "پىلاستىنكا", - "DeviceOnlineWithName": "{0} ئۇلاندى", - "DeviceOfflineWithName": "{0} ئۈزۈلدى", "Collections": "توپلام", - "Application": "ئەپ", "AppDeviceValues": "ئەپ: {0}، ئۈسكۈنە: {1}", "HeaderLiveTV": "تور تېلېۋىزىيەسى", "Default": "سۈكۈتتىكى", "Folders": "ھۆججەت خالتىسى", "Favorites": "ساقلىغۇچ", "LabelRunningTimeValue": "ئىجرا بولغان ۋاقتى:{0}", - "HeaderRecordingGroups": "خاتىرلەش گۇرۇپىسى", "Forced": "ئەڭ", "TaskKeyframeExtractor": "ھالقىلىق رامكا ئاجراتقۇچ", "TaskKeyframeExtractorDescription": "سىن ھۆججەتلىرىدىن رامكا ئاجرىتىپ، تېخىمۇ ئېنىق بولغان HLS قويۇلۇش تىزىملىكىنى قۇرۇلىدۇ. بۇ ۋەزىپە ئۇزۇن داۋام قىلىشى مۇمكىن.", @@ -46,35 +39,23 @@ "TasksLibraryCategory": "مېدىيا ئامبىرى", "TasksMaintenanceCategory": "ئاسراش", "VersionNumber": "نەشرى {0}", - "ValueSpecialEpisodeName": "خاسلىق - {0}", - "ValueHasBeenAddedToLibrary": "{0} مېدىيا ئامبىرىڭىزغا قوشۇلدى", "UserStoppedPlayingItemWithValues": "{0}،{1} نى {2} دە قويۇنشتىن توختىدى", "UserStartedPlayingItemWithValues": "{0}،{1} نى {2} دە قويۇۋاتىدۇ", - "UserPolicyUpdatedWithName": "ئابونتلار سىياسىتى {0} غا يېڭىلاندى", "UserPasswordChangedWithName": "ئابونت{0} ئۈچۈن پارول ئۆزگەرتىلدى", "UserOfflineFromDevice": "{0} بىلەن {1} نىڭ ئالاقىسى ئۈزۈلدى", "UserLockedOutWithName": "ئابونت {0} قۇلۇپلاندى", "UserDownloadingItemWithValues": "{0} چۈشۈرۈۋاتىدۇ {1}", "UserDeletedWithName": "{0} ئابونت ئۆچۈرۈلدى", "UserCreatedWithName": "{0} ئابونت يېڭىدىن قوشۇلدى", - "User": "ئابونت", "Undefined": "بېكىتىلمىگەن", "TvShows": "تىياتىرلار", - "System": "سىستېما", - "Sync": "ماس قەدەمدەش", "SubtitleDownloadFailureFromForItem": "{0} دىن {0} نىڭ فىلىم خېتىنى چۈشۈرگىلى بولمىدى", "StartupEmbyServerIsLoading": "Jellyfin مۇلازىمىتېرى يۈكلىنىۋاتىدۇ. سەل تۇرۇپ قايتا سىناڭ.", - "Songs": "ناخشىلار", "Shows": "پروگراممىلار", - "ServerNameNeedsToBeRestarted": "{0} قايتا قوزغىتىلىشى كېرەك", - "ScheduledTaskStartedWithName": "{0} باشلاندى", "ScheduledTaskFailedWithName": "{0} مەغلۇپ بولدى", - "ProviderValue": "تەمىنلىگۈچى: {0}", "PluginUpdatedWithName": "{0} يېڭىلاندى", "PluginUninstalledWithName": "{0} ئۆچۈرۈلدى", "PluginInstalledWithName": "{0} قاچىلاندى", - "Plugin": "قىستۇرما", - "Playlists": "قويۇش تىزىملىكى", "Photos": "رەسىملەر", "NotificationOptionVideoPlaybackStopped": "سىن قويۇلۇش توختىدى", "NotificationOptionVideoPlayback": "سىن قويۇلدى", @@ -100,24 +81,14 @@ "Music": "مۇزىكا", "Movies": "فىلىملەر", "MixedContent": "ئارىلاشما مەزمۇن", - "MessageNamedServerConfigurationUpdatedWithValue": "مۇلازىمىتېر تەڭشىكىنىڭ {0} قىسمى يېڭىلىنىپ بولدى", - "MessageServerConfigurationUpdated": "مۇلازىمىتېر يېڭىلىنىپ بولدى", - "MessageApplicationUpdated": "Jellyfin مۇلازىمىتېرى يېڭىلاندى", - "MessageApplicationUpdatedTo": "Jellyfin مۇلازىمىتېر نەشرى {0} گە يېڭىلاندى", "Latest": "ئەڭ يېڭى", "LabelIpAddressValue": "{0}: IP ئادرىسى", - "ItemRemovedWithName": "{0} ئامباردىن چىقىرىلدى", - "ItemAddedWithName": "{0} ئامبارغا قوشۇلدى", "Inherit": "داۋاملاشتۇرۇش", "HomeVideos": "ئائىلە سىنلىرى", "HeaderNextUp": "كېيىنكىسى", - "HeaderFavoriteSongs": "ئەڭ ياقتۇرىدىغان ناخشىلار", "HeaderFavoriteShows": "ئەڭ ياقتۇرىدىغان پروگراممىلار", "HeaderFavoriteEpisodes": "ئەڭ ياقتۇرىدىغان تىياتېرلار", - "HeaderFavoriteArtists": "ئەڭ ياقتۇرىدىغان سەنئەتكارلار", - "HeaderFavoriteAlbums": "ياقتۇرىدىغان پىلاستىنكىلار", "HeaderContinueWatching": "داۋاملىق كۆرۈش", - "HeaderAlbumArtists": "پىلاستىنكا سەنئەتكارلىرى", "Genres": "ئۇسلۇبلار", "FailedLoginAttemptWithUserName": "{0} كىرىش ئوڭۇشلۇق بولمىدى", "External": "سىرتقى" diff --git a/Emby.Server.Implementations/Localization/Core/uk.json b/Emby.Server.Implementations/Localization/Core/uk.json index 9246d9de20..ccb9d915d1 100644 --- a/Emby.Server.Implementations/Localization/Core/uk.json +++ b/Emby.Server.Implementations/Localization/Core/uk.json @@ -2,36 +2,22 @@ "MusicVideos": "Відеокліпи", "Music": "Музика", "Movies": "Фільми", - "MessageApplicationUpdatedTo": "Jellyfin Server оновлено до версії {0}", - "MessageApplicationUpdated": "Jellyfin Server оновлено", "Latest": "Останні", "LabelIpAddressValue": "IP-адреса: {0}", - "ItemRemovedWithName": "{0} видалено з медіатеки", - "ItemAddedWithName": "{0} додано до медіатеки", "HeaderNextUp": "Наступний", "HeaderLiveTV": "Ефірне ТБ", - "HeaderFavoriteSongs": "Обрані пісні", "HeaderFavoriteShows": "Обрані шоу", "HeaderFavoriteEpisodes": "Обрані епізоди", - "HeaderFavoriteArtists": "Обрані виконавці", - "HeaderFavoriteAlbums": "Обрані альбоми", "HeaderContinueWatching": "Продовжити перегляд", - "HeaderAlbumArtists": "Виконавці альбому", "Genres": "Жанри", "Folders": "Теки", "Favorites": "Обрані", - "DeviceOnlineWithName": "Пристрій {0} підключився", - "DeviceOfflineWithName": "Пристрій {0} відключився", "Collections": "Колекції", "ChapterNameValue": "Сцена {0}", - "Channels": "Канали", - "CameraImageUploadedFrom": "Нову фотографію завантажено з {0}", "Books": "Книги", "AuthenticationSucceededWithUserName": "{0} успішно авторизовано", "Artists": "Виконавці", - "Application": "Додаток", "AppDeviceValues": "Додаток: {0}, Пристрій: {1}", - "Albums": "Альбоми", "NotificationOptionServerRestartRequired": "Необхідно перезапустити сервер", "NotificationOptionPluginUpdateInstalled": "Встановлено оновлення плагіна", "NotificationOptionPluginUninstalled": "Плагін видалено", @@ -64,11 +50,8 @@ "TasksLibraryCategory": "Медіатека", "TasksMaintenanceCategory": "Обслуговування", "VersionNumber": "Версія {0}", - "ValueSpecialEpisodeName": "Спецепізод - {0}", - "ValueHasBeenAddedToLibrary": "{0} додано до медіатеки", "UserStoppedPlayingItemWithValues": "{0} закінчив відтворення {1} на {2}", "UserStartedPlayingItemWithValues": "{0} відтворює {1} на {2}", - "UserPolicyUpdatedWithName": "Політика користувача оновлена для {0}", "UserPasswordChangedWithName": "Пароль змінено для користувача {0}", "UserOnlineFromDevice": "{0} підключився з {1}", "UserOfflineFromDevice": "{0} відключився від {1}", @@ -76,23 +59,14 @@ "UserDownloadingItemWithValues": "{0} завантажує {1}", "UserDeletedWithName": "Користувача {0} видалено", "UserCreatedWithName": "Користувача {0} створено", - "User": "Користувач", "TvShows": "ТВ-шоу", - "System": "Система", - "Sync": "Синхронізація", "SubtitleDownloadFailureFromForItem": "Не вдалося завантажити субтитри з {0} для {1}", "StartupEmbyServerIsLoading": "Jellyfin Server завантажується. Будь ласка, спробуйте трішки пізніше.", - "Songs": "Пісні", "Shows": "Серіали", - "ServerNameNeedsToBeRestarted": "{0} потрібно перезапустити", - "ScheduledTaskStartedWithName": "{0} розпочато", "ScheduledTaskFailedWithName": "{0} незавершено, збій", - "ProviderValue": "Постачальник: {0}", "PluginUpdatedWithName": "{0} оновлено", "PluginUninstalledWithName": "{0} видалено", "PluginInstalledWithName": "{0} встановлено", - "Plugin": "Плагін", - "Playlists": "Плейлисти", "Photos": "Фотографії", "NotificationOptionVideoPlaybackStopped": "Відтворення відео зупинено", "NotificationOptionVideoPlayback": "Розпочато відтворення відео", @@ -109,10 +83,7 @@ "NameSeasonNumber": "Сезон {0}", "NameInstallFailed": "Не вдалося встановити {0}", "MixedContent": "Змішаний контент", - "MessageServerConfigurationUpdated": "Конфігурація сервера оновлена", - "MessageNamedServerConfigurationUpdatedWithValue": "Розділ конфігурації сервера {0} оновлено", "Inherit": "Успадкувати", - "HeaderRecordingGroups": "Групи запису", "Forced": "Форсовані", "TaskCleanActivityLogDescription": "Видаляє старші за встановлений термін записи з журналу активності.", "TaskCleanActivityLog": "Очистити журнал активності", @@ -135,5 +106,7 @@ "TaskMoveTrickplayImages": "Змінити місце розташування прев'ю-зображень", "TaskExtractMediaSegmentsDescription": "Витягує або отримує медіа-сегменти з плагінів з підтримкою MediaSegment.", "CleanupUserDataTask": "Завдання очищення даних користувача", - "CleanupUserDataTaskDescription": "Очищає всі дані користувача (стан перегляду, статус обраного тощо) з медіа, які перестали бути доступними щонайменше 90 днів тому." + "CleanupUserDataTaskDescription": "Очищає всі дані користувача (стан перегляду, статус обраного тощо) з медіа, які перестали бути доступними щонайменше 90 днів тому.", + "Original": "Оригінал", + "LyricDownloadFailureFromForItem": "Не вдалося завантажити текст пісні з {0} для {1}" } diff --git a/Emby.Server.Implementations/Localization/Core/ur.json b/Emby.Server.Implementations/Localization/Core/ur.json index 94d9c8541e..07d309c270 100644 --- a/Emby.Server.Implementations/Localization/Core/ur.json +++ b/Emby.Server.Implementations/Localization/Core/ur.json @@ -1,16 +1,10 @@ { "Books": "کتابیں", "AppDeviceValues": "ایپ: {0}، ڈیوائس: {1}", - "Albums": "البمز", - "Application": "ایپلی کیشن", "Artists": "فنکار", "AuthenticationSucceededWithUserName": "{0} کی کامیابی سے تصدیق ہو چکی ہے", - "CameraImageUploadedFrom": "ایک نئی کیمرے کی تصویر {0} سے اپ لوڈ کی گئی ہے", - "Channels": "چینلز", "ChapterNameValue": "باب {0}", "Collections": "مجموعے", "Default": "ڈیفالٹ", - "DeviceOfflineWithName": "{0} نے رابطہ منقطع کر دیا ہے", - "DeviceOnlineWithName": "{0} منسلک ہے", "External": "بیرونی" } diff --git a/Emby.Server.Implementations/Localization/Core/ur_PK.json b/Emby.Server.Implementations/Localization/Core/ur_PK.json index f6539adff3..b3f24a31e3 100644 --- a/Emby.Server.Implementations/Localization/Core/ur_PK.json +++ b/Emby.Server.Implementations/Localization/Core/ur_PK.json @@ -1,27 +1,17 @@ { - "HeaderFavoriteAlbums": "پسندیدہ البمز", "HeaderNextUp": "اگلا", - "HeaderFavoriteArtists": "پسندیدہ فنکار", - "HeaderAlbumArtists": "البم کے فنکار", "Movies": "فلمیں", "HeaderFavoriteEpisodes": "پسندیدہ اقساط", "Collections": "مجموعے", "Folders": "فولڈرز", "HeaderLiveTV": "براہ راست ٹی وی", - "Channels": "چینلز", "HeaderContinueWatching": "دیکھنا جاری رکھیں", - "Playlists": "پلے لسٹس", - "ValueSpecialEpisodeName": "خصوصی - {0}", "Shows": "دکھاتا ہے", "Genres": "انواع", "Artists": "فنکار", - "Sync": "مطابقت پذیری", "Photos": "تصاویر", - "Albums": "البمز", "Favorites": "پسندیدہ", - "Songs": "گانے", "Books": "کتابیں", - "HeaderFavoriteSongs": "پسندیدہ گانے", "HeaderFavoriteShows": "پسندیدہ شوز", "TaskDownloadMissingSubtitlesDescription": "میٹا ڈیٹا کی تشکیل پر مبنی ذیلی عنوانات کے غائب عنوانات انٹرنیٹ پے تلاش کرتا ہے۔", "TaskDownloadMissingSubtitles": "غائب سب ٹائٹلز ڈاؤن لوڈ کریں", @@ -46,10 +36,8 @@ "TasksLibraryCategory": "لآیبریری", "TasksMaintenanceCategory": "مرمت", "VersionNumber": "ورژن {0}", - "ValueHasBeenAddedToLibrary": "{0} آپ کی میڈیا لائبریری میں شامل کر دیا گیا ہے", "UserStoppedPlayingItemWithValues": "{0} نے {1} چلانا ختم کر دیا ھے {2} پے", "UserStartedPlayingItemWithValues": "{0} چلا رہا ہے {1} {2} پے", - "UserPolicyUpdatedWithName": "صارف {0} کی پالیسی کیلئے تازہ کاری کی گئی ہے", "UserPasswordChangedWithName": "صارف {0} کے لئے پاس ورڈ تبدیل کر دیا گیا ہے", "UserOnlineFromDevice": "{0} آن لائن ہے {1} سے", "UserOfflineFromDevice": "{0} سے منقطع ہوگیا ہے {1}", @@ -57,19 +45,13 @@ "UserDownloadingItemWithValues": "{0} ڈاؤن لوڈ کر رھا ھے {1}", "UserDeletedWithName": "صارف {0} کو ہٹا دیا گیا ہے", "UserCreatedWithName": "صارف {0} تشکیل دیا گیا ہے", - "User": "صارف", "TvShows": "ٹی وی کے پروگرام", - "System": "نظام", "SubtitleDownloadFailureFromForItem": "ذیلی عنوانات {0} سے ڈاؤن لوڈ کرنے میں ناکام {1} کے لیے", "StartupEmbyServerIsLoading": "جیلیفن سرور لوڈ ہورہا ہے۔ براہ کرم جلد ہی دوبارہ کوشش کریں۔", - "ServerNameNeedsToBeRestarted": "{0} دوبارہ چلانے کرنے کی ضرورت ہے", - "ScheduledTaskStartedWithName": "{0} شروع", "ScheduledTaskFailedWithName": "{0} ناکام", - "ProviderValue": "فراہم کرنے والا: {0}", "PluginUpdatedWithName": "{0} تازہ کاری کی گئی تھی", "PluginUninstalledWithName": "[0} ہٹا دیا گیا تھا", "PluginInstalledWithName": "{0} انسٹال کیا گیا تھا", - "Plugin": "پلگن", "NotificationOptionVideoPlaybackStopped": "ویڈیو پلے بیک رک گیا", "NotificationOptionVideoPlayback": "ویڈیو پلے بیک شروع ہوا", "NotificationOptionUserLockedOut": "صارف کو لاک آؤٹ کیا گیا", @@ -93,25 +75,14 @@ "MusicVideos": "میوزک ویڈیوز", "Music": "موسیقی", "MixedContent": "مخلوط مواد", - "MessageServerConfigurationUpdated": "سرور کو اپ ڈیٹ کر دیا گیا ہے", - "MessageNamedServerConfigurationUpdatedWithValue": "سرور ضمن {0} کو ترتیب دے دیا گیا ھے", - "MessageApplicationUpdatedTo": "جیلیفن سرور کو اپ ڈیٹ کیا ہے {0}", - "MessageApplicationUpdated": "جیلیفن سرور کو اپ ڈیٹ کر دیا گیا ہے", "Latest": "تازہ ترین", "LabelRunningTimeValue": "چلانے کی مدت", "LabelIpAddressValue": "آئ پی ایڈریس {0}", - "ItemRemovedWithName": "لائبریری سے ہٹا دیا گیا ھے", - "ItemAddedWithName": "[0} لائبریری میں شامل کیا گیا ھے", "Inherit": "وراثت", "HomeVideos": "ہوم ویڈیوز", - "HeaderRecordingGroups": "ریکارڈنگ گروپس", "FailedLoginAttemptWithUserName": "{0} سے لاگ ان کی ناکام کوشش", - "DeviceOnlineWithName": "{0} متصل ھو چکا ھے", - "DeviceOfflineWithName": "{0} منقطع ھو چکا ھے", "ChapterNameValue": "باب", "AuthenticationSucceededWithUserName": "{0} کامیابی کے ساتھ تصدیق ھوچکی ھے", - "CameraImageUploadedFrom": "ایک نئی کیمرہ تصویر اپ لوڈ کی گئی ہے {0}", - "Application": "پروگرام", "AppDeviceValues": "پروگرام:{0}, ڈیوائس:{1}", "Forced": "جَبری", "Undefined": "غير وضاحتى", diff --git a/Emby.Server.Implementations/Localization/Core/uz.json b/Emby.Server.Implementations/Localization/Core/uz.json index e44b3f5167..3215733c1a 100644 --- a/Emby.Server.Implementations/Localization/Core/uz.json +++ b/Emby.Server.Implementations/Localization/Core/uz.json @@ -1,47 +1,32 @@ { "HeaderContinueWatching": "Ko‘rishda davom etish", - "HeaderAlbumArtists": "Albom ijrochilari", "Genres": "Janrlar", "Folders": "Jildlar", "Favorites": "Sevimlilar", "Collections": "To'plamlar", - "Channels": "Kanallar", "Books": "Kitoblar", "Artists": "Ijrochilar", - "Albums": "Albomlar", "AuthenticationSucceededWithUserName": "{0} muvaffaqiyatli tasdiqlandi", "AppDeviceValues": "Ilova: {0}, Qurilma: {1}", - "Application": "Ilova", - "CameraImageUploadedFrom": "{0}dan yangi kamera rasmi yuklandi", - "DeviceOnlineWithName": "{0} ulangan", - "ItemRemovedWithName": "{0} kutbxonadan o'chirildi", "External": "Tashqi", "FailedLoginAttemptWithUserName": "Muvafaqiyatsiz kirishlar soni {0}", "Forced": "Majburiy", "ChapterNameValue": "{0}chi bo'lim", - "DeviceOfflineWithName": "{0} aloqa uzildi", "HeaderLiveTV": "Jonli TV", "HeaderNextUp": "Keyingisi", - "ItemAddedWithName": "{0} kutbxonaga qo'shildi", "LabelIpAddressValue": "IP manzil: {0}", "SubtitleDownloadFailureFromForItem": "{0} dan {1} uchun taglavhalarni yuklab boʻlmadi", "UserPasswordChangedWithName": "Foydalanuvchi {0} paroli oʻzgartirildi", - "ValueHasBeenAddedToLibrary": "{0} kutubxonaga qoʻshildi", "TaskCleanActivityLogDescription": "Belgilangan yoshdan kattaroq faoliyat jurnali yozuvlarini oʻchiradi.", "TaskAudioNormalization": "Ovozni normallashtirish", "TaskRefreshLibraryDescription": "Media kutubxonasi yangi fayllar uchun skanerlanmoqda va metama'lumotlar yangilanmoqda.", "Default": "Joriy", - "HeaderFavoriteAlbums": "Tanlangan albomlar", - "HeaderFavoriteArtists": "Tanlangan artistlar", "HeaderFavoriteEpisodes": "Tanlangan epizodlar", "HeaderFavoriteShows": "Tanlangan shoular", - "HeaderFavoriteSongs": "Tanlangan qo'shiqlar", - "HeaderRecordingGroups": "Yozuvlar guruhi", "HomeVideos": "Uy videolari", "NotificationOptionVideoPlaybackStopped": "Video ijrosi toʻxtatildi", "TvShows": "TV seriallar", "Undefined": "Belgilanmagan", - "User": "Foydalanuvchi", "UserCreatedWithName": "{0} foydalanuvchi yaratildi", "TaskCleanCacheDescription": "Tizimga kerak bo'lmagan kesh fayllari o'chiriladi.", "TaskAudioNormalizationDescription": "Ovozni normallashtirish ma'lumotlari uchun fayllarni skanerlaydi.", @@ -67,10 +52,6 @@ "NotificationOptionVideoPlayback": "Video ijrosi boshlandi", "Photos": "Surat", "Latest": "So'ngi", - "MessageApplicationUpdated": "Jellyfin Server yangilandi", - "MessageApplicationUpdatedTo": "Jellyfin Server {0} gacha yangilandi", - "MessageNamedServerConfigurationUpdatedWithValue": "Server konfiguratsiyasi ({0}-boʻlim) yangilandi", - "MessageServerConfigurationUpdated": "Server konfiguratsiyasi yangilandi", "MixedContent": "Aralashgan tarkib", "Movies": "Kinolar", "Music": "Qo'shiqlar", @@ -78,29 +59,19 @@ "NameInstallFailed": "Omadsiz ornatish {0}", "NameSeasonNumber": "{0} Fasl", "NameSeasonUnknown": "Fasl aniqlanmagan", - "Playlists": "Pleylistlar", "NewVersionIsAvailable": "Yuklab olish uchun Jellyfin Server ning yangi versiyasi mavjud", - "Plugin": "Plagin", "TaskCleanLogs": "Jurnallar katalogini tozalash", "PluginUpdatedWithName": "{0} - yangilandi", - "ProviderValue": "Yetkazib beruvchi: {0}", "ScheduledTaskFailedWithName": "{0} - omadsiz", - "ScheduledTaskStartedWithName": "{0} - ishga tushirildi", - "ServerNameNeedsToBeRestarted": "Qayta yuklash kerak {0}", "Shows": "Teleko'rsatuv", - "Songs": "Kompozitsiyalar", "StartupEmbyServerIsLoading": "Jellyfin Server yuklanmoqda. Tez orada qayta urinib koʻring.", - "Sync": "Sinxronizatsiya", - "System": "Tizim", "UserDeletedWithName": "{0} foydalanuvchisi oʻchirib tashlandi", "UserDownloadingItemWithValues": "{0} yuklanmoqda {1}", "UserLockedOutWithName": "{0} foydalanuvchisi bloklandi", "UserOfflineFromDevice": "{0} {1}dan uzildi", "UserOnlineFromDevice": "{0} {1} dan ulandi", - "UserPolicyUpdatedWithName": "{0} foydalanuvchisining siyosatlari yangilandi", "UserStartedPlayingItemWithValues": "{0} - {2} da \"{1}\" ijrosi", "UserStoppedPlayingItemWithValues": "{0} - ijro etish to‘xtatildi {1} {2}", - "ValueSpecialEpisodeName": "Maxsus qism – {0}", "VersionNumber": "Versiya {0}", "TasksMaintenanceCategory": "Xizmat ko'rsatish", "TasksLibraryCategory": "Media kutubxona", @@ -111,5 +82,7 @@ "TaskRefreshChapterImages": "Sahnadan tasvirini chiqarish", "TaskRefreshChapterImagesDescription": "Sahnalarni o'z ichiga olgan videolar uchun eskizlarni yaratadi.", "TaskRefreshLibrary": "Media kutubxonangizni skanerlash", - "TaskCleanLogsDescription": "{0} kundan eski log fayllarni o'chiradi." + "TaskCleanLogsDescription": "{0} kundan eski log fayllarni o'chiradi.", + "Original": "Original", + "LyricDownloadFailureFromForItem": "{0} dan {1} gacha qo'shiq matninin yuklab olishda xatolik ketdi" } diff --git a/Emby.Server.Implementations/Localization/Core/vi.json b/Emby.Server.Implementations/Localization/Core/vi.json index 947a2c80de..2ba665e2ff 100644 --- a/Emby.Server.Implementations/Localization/Core/vi.json +++ b/Emby.Server.Implementations/Localization/Core/vi.json @@ -3,17 +3,11 @@ "Favorites": "Yêu Thích", "Folders": "Thư Mục", "Genres": "Thể Loại", - "HeaderAlbumArtists": "Album nghệ sĩ", "HeaderContinueWatching": "Xem Tiếp", "HeaderLiveTV": "TV Trực Tiếp", "Movies": "Phim", "Photos": "Ảnh", - "Playlists": "Danh sách phát", "Shows": "Chương Trình TV", - "Songs": "Bài Hát", - "Sync": "Đồng Bộ", - "ValueSpecialEpisodeName": "Đặc Biệt - {0}", - "Albums": "Album", "Artists": "Ca Sĩ", "TaskDownloadMissingSubtitlesDescription": "Tìm kiếm phụ đề bị thiếu trên Internet dựa trên cấu hình dữ liệu mô tả.", "TaskDownloadMissingSubtitles": "Tải Xuống Phụ Đề Bị Thiếu", @@ -38,10 +32,8 @@ "TasksLibraryCategory": "Thư Viện", "TasksMaintenanceCategory": "Bảo Trì", "VersionNumber": "Phiên Bản {0}", - "ValueHasBeenAddedToLibrary": "{0} đã được thêm vào thư viện của bạn", "UserStoppedPlayingItemWithValues": "{0} đã kết thúc phát {1} trên {2}", "UserStartedPlayingItemWithValues": "{0} đang phát {1} trên {2}", - "UserPolicyUpdatedWithName": "Chính sách người dùng đã được cập nhật cho {0}", "UserPasswordChangedWithName": "Mật khẩu đã được thay đổi cho người dùng {0}", "UserOnlineFromDevice": "{0} trực tuyến từ {1}", "UserOfflineFromDevice": "{0} đã ngắt kết nối từ {1}", @@ -49,19 +41,13 @@ "UserDownloadingItemWithValues": "{0} đang tải xuống {1}", "UserDeletedWithName": "Người Dùng {0} đã được xóa", "UserCreatedWithName": "Người Dùng {0} đã được tạo", - "User": "Người Dùng", "TvShows": "Chương Trình TV", - "System": "Hệ Thống", "SubtitleDownloadFailureFromForItem": "Không thể tải xuống phụ đề từ {0} cho {1}", "StartupEmbyServerIsLoading": "Jellyfin Server đang tải. Vui lòng thử lại trong thời gian ngắn.", - "ServerNameNeedsToBeRestarted": "{0} cần được khởi động lại", - "ScheduledTaskStartedWithName": "{0} đã bắt đầu", "ScheduledTaskFailedWithName": "{0} đã thất bại", - "ProviderValue": "Provider: {0}", "PluginUpdatedWithName": "{0} đã cập nhật", "PluginUninstalledWithName": "{0} đã được gỡ bỏ", "PluginInstalledWithName": "{0} đã được cài đặt", - "Plugin": "Plugin", "NotificationOptionVideoPlaybackStopped": "Đã dừng phát lại video", "NotificationOptionVideoPlayback": "Đã bắt đầu phát lại video", "NotificationOptionUserLockedOut": "Người dùng bị khóa", @@ -85,33 +71,18 @@ "MusicVideos": "Videos Nhạc", "Music": "Nhạc", "MixedContent": "Nội dung hỗn hợp", - "MessageServerConfigurationUpdated": "Cấu hình máy chủ đã được cập nhật", - "MessageNamedServerConfigurationUpdatedWithValue": "Phần cấu hình máy chủ {0} đã được cập nhật", - "MessageApplicationUpdatedTo": "Jellyfin Server đã được cập nhật lên {0}", - "MessageApplicationUpdated": "Jellyfin Server đã được cập nhật", "Latest": "Gần Nhất", "LabelRunningTimeValue": "Thời Gian Chạy: {0}", "LabelIpAddressValue": "Địa chỉ IP: {0}", - "ItemRemovedWithName": "{0} đã xóa khỏi thư viện", - "ItemAddedWithName": "{0} được thêm vào thư viện", "Inherit": "Thừa hưởng", "HomeVideos": "Video Nhà", - "HeaderRecordingGroups": "Nhóm Ghi Video", "HeaderNextUp": "Tiếp Theo", - "HeaderFavoriteSongs": "Bài Hát Yêu Thích", "HeaderFavoriteShows": "Chương Trình Yêu Thích", "HeaderFavoriteEpisodes": "Tập Phim Yêu Thích", - "HeaderFavoriteArtists": "Nghệ Sĩ Yêu Thích", - "HeaderFavoriteAlbums": "Album Ưa Thích", "FailedLoginAttemptWithUserName": "Nỗ lực đăng nhập không thành công từ {0}", - "DeviceOnlineWithName": "{0} đã kết nối", - "DeviceOfflineWithName": "{0} đã ngắt kết nối", "ChapterNameValue": "Phân Cảnh {0}", - "Channels": "Kênh", - "CameraImageUploadedFrom": "Một hình ảnh máy ảnh mới đã được tải lên từ {0}", "Books": "Sách", "AuthenticationSucceededWithUserName": "{0} xác thực thành công", - "Application": "Ứng Dụng", "AppDeviceValues": "Ứng Dụng: {0}, Thiết Bị: {1}", "TaskCleanActivityLogDescription": "Xóa các mục nhật ký hoạt động cũ hơn độ tuổi đã cài đặt.", "TaskCleanActivityLog": "Xóa Nhật Ký Hoạt Động", @@ -135,5 +106,7 @@ "TaskMoveTrickplayImagesDescription": "Di chuyển các tập tin trickplay hiện có theo cài đặt thư viện.", "TaskExtractMediaSegments": "Quét Phân Đoạn Phương Tiện", "CleanupUserDataTask": "Tác vụ dọn dẹp dữ liệu người dùng", - "CleanupUserDataTaskDescription": "Làm sạch tất cả dữ liệu người dùng (trạng thái xem, trạng thái yêu thích, v.v.) từ phương tiện không còn có mặt trong ít nhất 90 ngày." + "CleanupUserDataTaskDescription": "Làm sạch tất cả dữ liệu người dùng (trạng thái xem, trạng thái yêu thích, v.v.) từ phương tiện không còn có mặt trong ít nhất 90 ngày.", + "Original": "Gốc", + "LyricDownloadFailureFromForItem": "Lời bài hát không tải xuống được từ {0} cho {1}" } diff --git a/Emby.Server.Implementations/Localization/Core/zh-CN.json b/Emby.Server.Implementations/Localization/Core/zh-CN.json index 6a7b7fb4e6..18418ae0bc 100644 --- a/Emby.Server.Implementations/Localization/Core/zh-CN.json +++ b/Emby.Server.Implementations/Localization/Core/zh-CN.json @@ -1,41 +1,24 @@ { - "Albums": "专辑", "AppDeviceValues": "应用:{0},设备:{1}", - "Application": "应用程序", "Artists": "艺术家", "AuthenticationSucceededWithUserName": "{0} 认证成功", "Books": "书籍", - "CameraImageUploadedFrom": "已从 {0} 上传新的相机照片", - "Channels": "频道", "ChapterNameValue": "章节 {0}", "Collections": "合集", - "DeviceOfflineWithName": "{0} 已断开连接", - "DeviceOnlineWithName": "{0} 已连接", "FailedLoginAttemptWithUserName": "来自 {0} 的登录失败", "Favorites": "收藏夹", "Folders": "文件夹", "Genres": "类型", - "HeaderAlbumArtists": "专辑艺术家", "HeaderContinueWatching": "继续观看", - "HeaderFavoriteAlbums": "收藏的专辑", - "HeaderFavoriteArtists": "收藏的艺术家", "HeaderFavoriteEpisodes": "收藏的剧集", "HeaderFavoriteShows": "收藏的节目", - "HeaderFavoriteSongs": "收藏的歌曲", "HeaderLiveTV": "电视直播", "HeaderNextUp": "接下来播放", - "HeaderRecordingGroups": "录制组", "HomeVideos": "家庭视频", "Inherit": "继承", - "ItemAddedWithName": "{0} 已添加到媒体库", - "ItemRemovedWithName": "{0} 已从媒体库移除", "LabelIpAddressValue": "IP 地址:{0}", "LabelRunningTimeValue": "运行时间:{0}", "Latest": "最新", - "MessageApplicationUpdated": "Jellyfin 服务器已更新", - "MessageApplicationUpdatedTo": "Jellyfin 服务器版本已更新到 {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "服务器配置 {0} 部分已更新", - "MessageServerConfigurationUpdated": "服务器配置已更新", "MixedContent": "混合内容", "Movies": "电影", "Music": "音乐", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "视频已开始播放", "NotificationOptionVideoPlaybackStopped": "视频播放已停止", "Photos": "照片", - "Playlists": "播放列表", - "Plugin": "插件", "PluginInstalledWithName": "{0} 已安装", "PluginUninstalledWithName": "{0} 已卸载", "PluginUpdatedWithName": "{0} 已更新", - "ProviderValue": "提供商:{0}", "ScheduledTaskFailedWithName": "{0} 已失败", - "ScheduledTaskStartedWithName": "{0} 已开始", - "ServerNameNeedsToBeRestarted": "{0} 需要重新启动", "Shows": "节目", - "Songs": "歌曲", "StartupEmbyServerIsLoading": "Jellyfin 服务器正在启动,请稍后再试。", "SubtitleDownloadFailureFromForItem": "无法从 {0} 下载 {1} 的字幕", - "Sync": "同步", - "System": "系统", "TvShows": "电视剧", - "User": "用户", "UserCreatedWithName": "已创建用户 {0}", "UserDeletedWithName": "已删除用户 {0}", "UserDownloadingItemWithValues": "{0} 正在下载 {1}", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "{0} 已从 {1} 断开", "UserOnlineFromDevice": "{0} 已在 {1} 上线", "UserPasswordChangedWithName": "用户 {0} 的密码已更改", - "UserPolicyUpdatedWithName": "用户协议已更新为 {0}", "UserStartedPlayingItemWithValues": "{0} 在 {2} 上开始播放 {1}", "UserStoppedPlayingItemWithValues": "{0} 在 {2} 上停止播放 {1}", - "ValueHasBeenAddedToLibrary": "{0} 已添加至您的媒体库中", - "ValueSpecialEpisodeName": "特典 - {0}", "VersionNumber": "版本 {0}", "TaskUpdatePluginsDescription": "为已设置为自动更新的插件下载和安装更新。", "TaskRefreshPeople": "刷新演职人员", @@ -135,5 +106,7 @@ "TaskExtractMediaSegmentsDescription": "从支持 MediaSegment 的插件中提取或获取媒体分段。", "TaskMoveTrickplayImagesDescription": "根据媒体库设置移动现有的进度条预览图文件。", "CleanupUserDataTask": "用户数据清理任务", - "CleanupUserDataTaskDescription": "清理已被删除超过90天的媒体中的所有用户数据(观看状态、收藏夹状态等)。" + "CleanupUserDataTaskDescription": "清理已被删除超过90天的媒体中的所有用户数据(观看状态、收藏夹状态等)。", + "LyricDownloadFailureFromForItem": "无法从 {0} 下载 {1} 的歌词", + "Original": "原始" } diff --git a/Emby.Server.Implementations/Localization/Core/zh-HK.json b/Emby.Server.Implementations/Localization/Core/zh-HK.json index f3ad8be2a8..b2fcbc93a2 100644 --- a/Emby.Server.Implementations/Localization/Core/zh-HK.json +++ b/Emby.Server.Implementations/Localization/Core/zh-HK.json @@ -1,41 +1,24 @@ { - "Albums": "專輯", "AppDeviceValues": "程式:{0},裝置:{1}", - "Application": "應用程式", "Artists": "藝人", "AuthenticationSucceededWithUserName": "{0} 成功通過驗證", "Books": "書籍", - "CameraImageUploadedFrom": "{0} 已經成功上載咗一張新相", - "Channels": "頻道", "ChapterNameValue": "第 {0} 章", "Collections": "系列", - "DeviceOfflineWithName": "{0} 斷開咗連線", - "DeviceOnlineWithName": "{0} 連線咗", "FailedLoginAttemptWithUserName": "來自 {0} 嘅登入嘗試失敗咗", "Favorites": "心水", "Folders": "資料夾", "Genres": "風格", - "HeaderAlbumArtists": "專輯歌手", "HeaderContinueWatching": "繼續睇返", - "HeaderFavoriteAlbums": "心水嘅專輯", - "HeaderFavoriteArtists": "心水嘅藝人", "HeaderFavoriteEpisodes": "心水嘅劇集", "HeaderFavoriteShows": "心水嘅節目", - "HeaderFavoriteSongs": "心水嘅歌曲", "HeaderLiveTV": "電視直播", "HeaderNextUp": "跟住落嚟", - "HeaderRecordingGroups": "錄製組", "HomeVideos": "家庭影片", "Inherit": "繼承", - "ItemAddedWithName": "{0} 經已加咗入媒體櫃", - "ItemRemovedWithName": "{0} 經已由媒體櫃移除咗", "LabelIpAddressValue": "IP 位址:{0}", "LabelRunningTimeValue": "運行時間:{0}", "Latest": "最新", - "MessageApplicationUpdated": "Jellyfin 經已更新咗", - "MessageApplicationUpdatedTo": "Jellyfin 已經更新到 {0} 版本", - "MessageNamedServerConfigurationUpdatedWithValue": "伺服器設定「{0}」經已更新咗", - "MessageServerConfigurationUpdated": "伺服器設定經已更新咗", "MixedContent": "混合內容", "Movies": "電影", "Music": "音樂", @@ -61,23 +44,14 @@ "NotificationOptionVideoPlayback": "開始播放影片", "NotificationOptionVideoPlaybackStopped": "停咗播放影片", "Photos": "相片", - "Playlists": "播放清單", - "Plugin": "外掛程式", "PluginInstalledWithName": "裝好咗 {0}", "PluginUninstalledWithName": "剷走咗 {0}", "PluginUpdatedWithName": "更新好咗 {0}", - "ProviderValue": "提供者:{0}", "ScheduledTaskFailedWithName": "{0} 執行失敗", - "ScheduledTaskStartedWithName": "開始執行 {0}", - "ServerNameNeedsToBeRestarted": "{0} 需要重新啟動", "Shows": "節目", - "Songs": "歌曲", "StartupEmbyServerIsLoading": "Jellyfin 伺服器載入緊,唔該稍後再試。", "SubtitleDownloadFailureFromForItem": "經 {0} 下載 {1} 嘅字幕失敗咗", - "Sync": "同步", - "System": "系統", "TvShows": "電視節目", - "User": "使用者", "UserCreatedWithName": "經已建立咗新使用者 {0}", "UserDeletedWithName": "使用者 {0} 經已被刪走", "UserDownloadingItemWithValues": "{0} 下載緊 {1}", @@ -85,11 +59,8 @@ "UserOfflineFromDevice": "{0} 經已由 {1} 斷開咗連線", "UserOnlineFromDevice": "{0} 正喺 {1} 連線", "UserPasswordChangedWithName": "使用者 {0} 嘅密碼經已更改咗", - "UserPolicyUpdatedWithName": "使用者 {0} 嘅權限經已更新咗", "UserStartedPlayingItemWithValues": "{0} 正喺 {2} 播緊 {1}", "UserStoppedPlayingItemWithValues": "{0} 已經喺 {2} 停止播放 {1}", - "ValueHasBeenAddedToLibrary": "{0} 已經成功加入咗你嘅媒體櫃", - "ValueSpecialEpisodeName": "特輯 - {0}", "VersionNumber": "版本 {0}", "TaskDownloadMissingSubtitles": "下載漏咗嘅字幕", "TaskUpdatePlugins": "更新外掛程式", @@ -106,8 +77,8 @@ "TaskCleanLogsDescription": "自動刪走超過 {0} 日嘅紀錄檔。", "TaskCleanLogs": "清理日誌資料夾", "TaskRefreshLibrary": "掃描媒體櫃", - "TaskRefreshChapterImagesDescription": "幫有章節嘅影片整返啲章節縮圖。", - "TaskRefreshChapterImages": "擷取章節圖片", + "TaskRefreshChapterImagesDescription": "幫有章節嘅影片整返啲章節預覽圖。", + "TaskRefreshChapterImages": "擷取章節圖像", "TaskCleanCacheDescription": "刪走系統已經唔再需要嘅快取檔案。", "TaskCleanCache": "清理快取(Cache)資料夾", "TasksChannelsCategory": "網路頻道", @@ -135,5 +106,7 @@ "TaskMoveTrickplayImagesDescription": "根據媒體櫃設定,將現有嘅 Trickplay(快轉預覽)檔案搬去對應位置。", "TaskMoveTrickplayImages": "搬移快轉預覽圖嘅位置", "CleanupUserDataTask": "清理使用者資料嘅任務", - "CleanupUserDataTaskDescription": "清理已消失至少 90 日嘅媒體用家數據(包括觀看狀態、心水狀態等)。" + "CleanupUserDataTaskDescription": "清理已消失至少 90 日嘅媒體用家數據(包括觀看狀態、心水狀態等)。", + "LyricDownloadFailureFromForItem": "冇辦法從 {0} 下載 {1} 嘅歌詞", + "Original": "原始" } diff --git a/Emby.Server.Implementations/Localization/Core/zh-TW.json b/Emby.Server.Implementations/Localization/Core/zh-TW.json index 1caf887094..5dace3b0b7 100644 --- a/Emby.Server.Implementations/Localization/Core/zh-TW.json +++ b/Emby.Server.Implementations/Localization/Core/zh-TW.json @@ -1,39 +1,23 @@ { - "Albums": "專輯", "AppDeviceValues": "應用程式:{0},裝置:{1}", - "Application": "應用程式", "Artists": "藝人", "AuthenticationSucceededWithUserName": "成功授權 {0}", "Books": "書籍", - "CameraImageUploadedFrom": "已從 {0} 成功上傳一張照片", - "Channels": "頻道", "ChapterNameValue": "章節 {0}", "Collections": "系列作", - "DeviceOfflineWithName": "{0} 已中斷連接", - "DeviceOnlineWithName": "{0} 已連接", "FailedLoginAttemptWithUserName": "來自 {0} 的登入失敗嘗試", "Favorites": "我的最愛", "Folders": "資料夾", "Genres": "風格", - "HeaderAlbumArtists": "專輯演出者", "HeaderContinueWatching": "繼續觀看", - "HeaderFavoriteAlbums": "最愛專輯", - "HeaderFavoriteArtists": "最愛的藝人", "HeaderFavoriteEpisodes": "最愛的劇集", "HeaderFavoriteShows": "最愛的節目", - "HeaderFavoriteSongs": "最愛的歌曲", "HeaderLiveTV": "電視直播", "HeaderNextUp": "接下來", "HomeVideos": "家庭影片", - "ItemAddedWithName": "{0} 已新增至媒體庫", - "ItemRemovedWithName": "{0} 已從媒體庫移除", "LabelIpAddressValue": "IP 位址:{0}", "LabelRunningTimeValue": "運行時間:{0}", "Latest": "最新", - "MessageApplicationUpdated": "Jellyfin 伺服器已經更新", - "MessageApplicationUpdatedTo": "Jellyfin 伺服器已經更新至 {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "伺服器設定 {0} 部分已經更新", - "MessageServerConfigurationUpdated": "伺服器設定已經更新", "MixedContent": "混合內容", "Movies": "電影", "Music": "音樂", @@ -59,22 +43,13 @@ "NotificationOptionVideoPlayback": "影片播放已開始", "NotificationOptionVideoPlaybackStopped": "影片播放已停止", "Photos": "相片", - "Playlists": "播放清單", - "Plugin": "擴充功能", "PluginInstalledWithName": "已安裝 {0}", "PluginUninstalledWithName": "已移除 {0}", "PluginUpdatedWithName": "已更新 {0}", - "ProviderValue": "提供者:{0}", "ScheduledTaskFailedWithName": "排程任務 {0} 執行失敗", - "ScheduledTaskStartedWithName": "排程任務 {0} 已開始", - "ServerNameNeedsToBeRestarted": "伺服器 {0} 需要重新啟動", "Shows": "節目", - "Songs": "歌曲", "StartupEmbyServerIsLoading": "Jellyfin 伺服器載入中,請稍後再試。", - "Sync": "同步", - "System": "系統", "TvShows": "電視節目", - "User": "使用者", "UserCreatedWithName": "已建立使用者 {0}", "UserDeletedWithName": "已刪除使用者 {0}", "UserDownloadingItemWithValues": "使用者 {0} 正在下載 {1}", @@ -82,13 +57,9 @@ "UserOfflineFromDevice": "使用者 {0} 已從 {1} 斷線", "UserOnlineFromDevice": "使用者 {0} 已從 {1} 連線", "UserPasswordChangedWithName": "使用者 {0} 的密碼已變更", - "UserPolicyUpdatedWithName": "使用者權限已更新為 {0}", "UserStartedPlayingItemWithValues": "{0} 正在 {2} 上播放 {1}", "UserStoppedPlayingItemWithValues": "{0} 已在 {2} 上停止播放 {1}", - "ValueHasBeenAddedToLibrary": "{0} 已新增至您的媒體庫", - "ValueSpecialEpisodeName": "特輯 - {0}", "VersionNumber": "版本 {0}", - "HeaderRecordingGroups": "錄製組", "Inherit": "繼承", "SubtitleDownloadFailureFromForItem": "無法從 {0} 下載 {1} 的字幕", "TaskDownloadMissingSubtitlesDescription": "透過媒體資訊從網路上搜尋遺失的字幕。", diff --git a/Emby.Server.Implementations/Localization/Core/zu.json b/Emby.Server.Implementations/Localization/Core/zu.json index aa056d4498..669ea0372d 100644 --- a/Emby.Server.Implementations/Localization/Core/zu.json +++ b/Emby.Server.Implementations/Localization/Core/zu.json @@ -2,37 +2,24 @@ "TasksApplicationCategory": "Ukusetshenziswa", "TasksLibraryCategory": "Umtapo", "TasksMaintenanceCategory": "Ukunakekela", - "User": "Umsebenzisi", "Undefined": "Akuchaziwe", - "System": "Isistimu", - "Sync": "Vumelanisa", - "Songs": "Amaculo", "Shows": "Izinhlelo", - "Plugin": "Isijobelelo", - "Playlists": "Izinhla Zokudlalayo", "Photos": "Izithombe", "Music": "Umculo", "Movies": "Amamuvi", "Latest": "lwakamuva", "Inherit": "Ngefa", "Forced": "Kuphoqiwe", - "Application": "Ukusetshenziswa", "Genres": "Izinhlobo", "Folders": "Izikhwama", "Favorites": "Izintandokazi", "Default": "Okumisiwe", "Collections": "Amaqoqo", - "Channels": "Amashaneli", "Books": "Izincwadi", "Artists": "Abadlali", - "Albums": "Ama-albhamu", - "CameraImageUploadedFrom": "Kulandelayo lwesithonjana sekhamera selithunyelwe kusuka ku {0}", - "HeaderFavoriteArtists": "Abasethi Abathandekayo", "HeaderFavoriteEpisodes": "Izilimi Ezithandekayo", "HeaderFavoriteShows": "Izisho Ezithandekayo", "External": "Kwezifungo", "FailedLoginAttemptWithUserName": "Ukushayiswa kwesithombe sokungena okungekho {0}", - "HeaderContinueWatching": "Buyela Ukubona", - "HeaderFavoriteAlbums": "Izimpahla Ezithandwayo", - "HeaderAlbumArtists": "Abasethi wenkulumo" + "HeaderContinueWatching": "Buyela Ukubona" } diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs index d8797e612b..e7dd984ec4 100644 --- a/Emby.Server.Implementations/Localization/LocalizationManager.cs +++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs @@ -3,6 +3,7 @@ using System.Collections.Concurrent; using System.Collections.Frozen; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using System.Globalization; using System.IO; using System.Linq; using System.Reflection; @@ -26,6 +27,7 @@ namespace Emby.Server.Implementations.Localization private const string RatingsPath = "Emby.Server.Implementations.Localization.Ratings."; private const string CulturesPath = "Emby.Server.Implementations.Localization.iso6392.txt"; private const string CountriesPath = "Emby.Server.Implementations.Localization.countries.json"; + private const string CoreResourcePrefix = "Emby.Server.Implementations.Localization.Core."; private static readonly Assembly _assembly = typeof(LocalizationManager).Assembly; private static readonly string[] _unratedValues = ["n/a", "unrated", "not rated", "nr"]; @@ -34,13 +36,21 @@ namespace Emby.Server.Implementations.Localization private readonly Dictionary<string, Dictionary<string, ParentalRatingScore?>> _allParentalRatings = new(StringComparer.OrdinalIgnoreCase); - private readonly ConcurrentDictionary<string, Dictionary<string, string>> _dictionaries = new(StringComparer.OrdinalIgnoreCase); + private readonly ConcurrentDictionary<string, Dictionary<string, string>> _cultureOnlyDictionaries = new(StringComparer.OrdinalIgnoreCase); private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; private readonly ConcurrentDictionary<string, CultureDto?> _cultureCache = new(StringComparer.OrdinalIgnoreCase); private List<CultureDto> _cultures = []; + private static readonly (IReadOnlyList<LocalizationOption> Options, FrozenDictionary<string, string> Bcp47ToJellyfinMap) _localizationData = BuildLocalizationData(); + private static readonly IReadOnlyList<LocalizationOption> _localizationOptions = _localizationData.Options; + + // Maps BCP-47 hyphenated culture codes (set by ASP.NET Core's RequestLocalizationMiddleware + // and used as CurrentUICulture.Name) to Jellyfin's underscore-based resource file codes. + // Built reflexively from the resource file scan so both directions stay in sync. + private static readonly FrozenDictionary<string, string> _bcp47ToJellyfinMap = _localizationData.Bcp47ToJellyfinMap; + private FrozenDictionary<string, string> _iso6392BtoT = null!; /// <summary> @@ -54,6 +64,59 @@ namespace Emby.Server.Implementations.Localization { _configurationManager = configurationManager; _logger = logger; + + _configurationManager.ConfigurationUpdated += OnConfigurationUpdated; + } + + /// <summary> + /// Gets the supported UI cultures. + /// </summary> + /// <returns>A list of <see cref="CultureInfo"/> objects covering every embedded translation.</returns> + public static IList<CultureInfo> GetSupportedUICultures() + { + var cultures = new List<CultureInfo>(); + foreach (var option in _localizationOptions) + { + // Skip novelty codes (e.g. "pr" Pirate, "jbo" Lojban) that .NET cannot resolve. + if (TryGetCultureInfo(option.Value, out var cultureInfo)) + { + cultures.Add(cultureInfo); + } + } + + return cultures; + } + + /// <summary> + /// Resolves a Jellyfin resource culture code (which may use underscores, e.g. <c>es_419</c>) + /// to a <see cref="CultureInfo"/>. Returns <see langword="false"/> for codes .NET cannot resolve. + /// </summary> + private static bool TryGetCultureInfo(string cultureCode, [NotNullWhen(true)] out CultureInfo? cultureInfo) + { + try + { + // Resource files use underscores for some variants (e.g. es_419); + // CultureInfo only accepts hyphenated BCP-47 codes. + cultureInfo = CultureInfo.GetCultureInfo(cultureCode.Replace('_', '-')); + return true; + } + catch (CultureNotFoundException) + { + cultureInfo = null; + return false; + } + } + + private static void OnConfigurationUpdated(object? sender, EventArgs e) + { + if (sender is IServerConfigurationManager configManager) + { + var uiCulture = configManager.Configuration.UICulture; + if (!string.IsNullOrEmpty(uiCulture)) + { + CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo(uiCulture); + } + } } /// <summary> @@ -255,13 +318,13 @@ namespace Emby.Server.Implementations.Localization // A lot of countries don't explicitly have a separate rating for adult content if (ratings.All(x => x.RatingScore?.Score != 1000)) { - ratings.Add(new ParentalRating("XXX", new(1000, null))); + ratings.Add(new ParentalRating("XXX", new(1000, null))); } // A lot of countries don't explicitly have a separate rating for banned content if (ratings.All(x => x.RatingScore?.Score != 1001)) { - ratings.Add(new ParentalRating("Banned", new(1001, null))); + ratings.Add(new ParentalRating("Banned", new(1001, null))); } return [.. ratings.OrderBy(r => r.RatingScore?.Score).ThenBy(r => r.RatingScore?.SubScore)]; @@ -293,6 +356,27 @@ namespace Emby.Server.Implementations.Localization { ArgumentException.ThrowIfNullOrEmpty(rating); + // Some providers may list multiple ratings separated by '/' (e.g. "SE:15 / SE:15+ / SE:Från 15 år"). + // Try each one in order and use the first that resolves. + var ratingValues = rating.Split('/', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); + + foreach (var ratingValue in ratingValues) + { + var score = GetSingleRatingScore(ratingValue, countryCode); + if (score is not null) + { + return score; + } + } + + return null; + } + + /// <summary> + /// Resolves a single rating value to a score. + /// </summary> + private ParentalRatingScore? GetSingleRatingScore(string rating, string? countryCode) + { // Handle unrated content if (_unratedValues.Contains(rating.AsSpan(), StringComparison.OrdinalIgnoreCase)) { @@ -301,7 +385,7 @@ namespace Emby.Server.Implementations.Localization // Convert ints directly // This may override some of the locale specific age ratings (but those always map to the same age) - if (int.TryParse(rating, out var ratingAge)) + if (TryParseRatingAsScore(rating, out var ratingAge)) { return new(ratingAge, null); } @@ -403,6 +487,13 @@ namespace Emby.Server.Implementations.Localization return true; } + // If it's not a recognized rating string, fall back to using the number as the score + if (TryParseRatingAsScore(ratingPart, out var numericScore)) + { + result = new ParentalRatingScore(numericScore, null); + return true; + } + _logger.LogWarning( "Rating '{Rating}' not found in the '{CountryCode}' rating system, treating as unrated", rating, @@ -417,9 +508,27 @@ namespace Emby.Server.Implementations.Localization return true; } + /// <summary> + /// Tries to parse a rating as a number, allowing an optional trailing '+' (e.g. "16" or "18+"). + /// </summary> + /// <param name="ratingValue">Rating value to parse.</param> + /// <param name="score">Parsed score.</param> + /// <returns>Returns true if parsing was successful.</returns> + private static bool TryParseRatingAsScore(ReadOnlySpan<char> ratingValue, out int score) + { + var trimmed = ratingValue.TrimEnd('+'); + return int.TryParse(trimmed, out score); + } + /// <inheritdoc /> public string GetLocalizedString(string phrase) { + return GetLocalizedString(phrase, CultureInfo.CurrentUICulture.Name); + } + + /// <inheritdoc /> + public string GetServerLocalizedString(string phrase) + { return GetLocalizedString(phrase, _configurationManager.Configuration.UICulture); } @@ -436,6 +545,12 @@ namespace Emby.Server.Implementations.Localization culture = DefaultCulture; } + // Normalize BCP-47 hyphenated codes to Jellyfin's underscore-based codes + if (_bcp47ToJellyfinMap.TryGetValue(culture, out var mapped)) + { + culture = mapped; + } + var dictionary = GetLocalizationDictionary(culture); if (dictionary.TryGetValue(phrase, out var value)) @@ -443,6 +558,15 @@ namespace Emby.Server.Implementations.Localization return value; } + if (!string.Equals(culture, DefaultCulture, StringComparison.OrdinalIgnoreCase)) + { + var fallback = GetLocalizationDictionary(DefaultCulture); + if (fallback.TryGetValue(phrase, out var fallbackValue)) + { + return fallbackValue; + } + } + return phrase; } @@ -450,26 +574,17 @@ namespace Emby.Server.Implementations.Localization { ArgumentException.ThrowIfNullOrEmpty(culture); - const string Prefix = "Core"; - - return _dictionaries.GetOrAdd( + return _cultureOnlyDictionaries.GetOrAdd( culture, - static (key, localizationManager) => localizationManager.GetDictionary(Prefix, key, DefaultCulture + ".json").GetAwaiter().GetResult(), - this); - } - - private async Task<Dictionary<string, string>> GetDictionary(string prefix, string culture, string baseFilename) - { - ArgumentException.ThrowIfNullOrEmpty(culture); - - var dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); - - var namespaceName = GetType().Namespace + "." + prefix; - - await CopyInto(dictionary, namespaceName + "." + baseFilename).ConfigureAwait(false); - await CopyInto(dictionary, namespaceName + "." + GetResourceFilename(culture)).ConfigureAwait(false); + static (key, localizationManager) => + { + var dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); + var namespaceName = localizationManager.GetType().Namespace + ".Core"; + localizationManager.CopyInto(dictionary, namespaceName + "." + GetResourceFilename(key)).GetAwaiter().GetResult(); - return dictionary; + return dictionary; + }, + this); } private async Task CopyInto(IDictionary<string, string> dictionary, string resourcePath) @@ -491,11 +606,15 @@ namespace Emby.Server.Implementations.Localization private static string GetResourceFilename(string culture) { - var parts = culture.Split('-'); + // Region codes may use a '-' (BCP-47, e.g. "pt-BR") or '_' (e.g. "es_419", "ar_SA") separator. + // Normalize the casing (lower-case language, upper-case region) while preserving the separator + // so the result matches the embedded resource file name, which is case-sensitive. + var separatorIndex = culture.IndexOfAny(['-', '_']); - if (parts.Length == 2) + if (separatorIndex > 0) { - culture = parts[0].ToLowerInvariant() + "-" + parts[1].ToUpperInvariant(); + var separator = culture[separatorIndex]; + culture = culture[..separatorIndex].ToLowerInvariant() + separator + culture[(separatorIndex + 1)..].ToUpperInvariant(); } else { @@ -508,77 +627,55 @@ namespace Emby.Server.Implementations.Localization /// <inheritdoc /> public IEnumerable<LocalizationOption> GetLocalizationOptions() { - yield return new LocalizationOption("Afrikaans", "af"); - yield return new LocalizationOption("العربية", "ar"); - yield return new LocalizationOption("Беларуская", "be"); - yield return new LocalizationOption("Български", "bg-BG"); - yield return new LocalizationOption("বাংলা (বাংলাদেশ)", "bn"); - yield return new LocalizationOption("Català", "ca"); - yield return new LocalizationOption("Čeština", "cs"); - yield return new LocalizationOption("Cymraeg", "cy"); - yield return new LocalizationOption("Dansk", "da"); - yield return new LocalizationOption("Deutsch", "de"); - yield return new LocalizationOption("English (United Kingdom)", "en-GB"); - yield return new LocalizationOption("English", "en-US"); - yield return new LocalizationOption("Ελληνικά", "el"); - yield return new LocalizationOption("Esperanto", "eo"); - yield return new LocalizationOption("Español", "es"); - yield return new LocalizationOption("Español americano", "es_419"); - yield return new LocalizationOption("Español (Argentina)", "es-AR"); - yield return new LocalizationOption("Español (Dominicana)", "es_DO"); - yield return new LocalizationOption("Español (México)", "es-MX"); - yield return new LocalizationOption("Eesti", "et"); - yield return new LocalizationOption("Basque", "eu"); - yield return new LocalizationOption("فارسی", "fa"); - yield return new LocalizationOption("Suomi", "fi"); - yield return new LocalizationOption("Filipino", "fil"); - yield return new LocalizationOption("Français", "fr"); - yield return new LocalizationOption("Français (Canada)", "fr-CA"); - yield return new LocalizationOption("Galego", "gl"); - yield return new LocalizationOption("Schwiizerdütsch", "gsw"); - yield return new LocalizationOption("עִבְרִית", "he"); - yield return new LocalizationOption("हिन्दी", "hi"); - yield return new LocalizationOption("Hrvatski", "hr"); - yield return new LocalizationOption("Magyar", "hu"); - yield return new LocalizationOption("Bahasa Indonesia", "id"); - yield return new LocalizationOption("Íslenska", "is"); - yield return new LocalizationOption("Italiano", "it"); - yield return new LocalizationOption("日本語", "ja"); - yield return new LocalizationOption("Qazaqşa", "kk"); - yield return new LocalizationOption("한국어", "ko"); - yield return new LocalizationOption("Lietuvių", "lt"); - yield return new LocalizationOption("Latviešu", "lv"); - yield return new LocalizationOption("Македонски", "mk"); - yield return new LocalizationOption("മലയാളം", "ml"); - yield return new LocalizationOption("मराठी", "mr"); - yield return new LocalizationOption("Bahasa Melayu", "ms"); - yield return new LocalizationOption("Norsk bokmål", "nb"); - yield return new LocalizationOption("नेपाली", "ne"); - yield return new LocalizationOption("Nederlands", "nl"); - yield return new LocalizationOption("Norsk nynorsk", "nn"); - yield return new LocalizationOption("ਪੰਜਾਬੀ", "pa"); - yield return new LocalizationOption("Polski", "pl"); - yield return new LocalizationOption("Pirate", "pr"); - yield return new LocalizationOption("Português", "pt"); - yield return new LocalizationOption("Português (Brasil)", "pt-BR"); - yield return new LocalizationOption("Português (Portugal)", "pt-PT"); - yield return new LocalizationOption("Românește", "ro"); - yield return new LocalizationOption("Русский", "ru"); - yield return new LocalizationOption("Slovenčina", "sk"); - yield return new LocalizationOption("Slovenščina", "sl-SI"); - yield return new LocalizationOption("Shqip", "sq"); - yield return new LocalizationOption("Српски", "sr"); - yield return new LocalizationOption("Svenska", "sv"); - yield return new LocalizationOption("தமிழ்", "ta"); - yield return new LocalizationOption("తెలుగు", "te"); - yield return new LocalizationOption("ภาษาไทย", "th"); - yield return new LocalizationOption("Türkçe", "tr"); - yield return new LocalizationOption("Українська", "uk"); - yield return new LocalizationOption("اُردُو", "ur_PK"); - yield return new LocalizationOption("Tiếng Việt", "vi"); - yield return new LocalizationOption("汉语 (简体字)", "zh-CN"); - yield return new LocalizationOption("漢語 (繁體字)", "zh-TW"); - yield return new LocalizationOption("廣東話 (香港)", "zh-HK"); + return _localizationOptions; + } + + private static (IReadOnlyList<LocalizationOption> Options, FrozenDictionary<string, string> Bcp47ToJellyfinMap) BuildLocalizationData() + { + var options = new List<LocalizationOption>(); + var bcp47Map = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); + var prefix = CoreResourcePrefix; + + foreach (var resource in _assembly.GetManifestResourceNames()) + { + if (!resource.StartsWith(prefix, StringComparison.Ordinal) + || !resource.EndsWith(".json", StringComparison.Ordinal)) + { + continue; + } + + // Extract culture code from resource name: "...Core.de.json" -> "de", "...Core.pt-BR.json" -> "pt-BR" + var code = resource[prefix.Length..^5]; + + // Record the BCP-47 → Jellyfin mapping for any resource file using underscores. + if (code.Contains('_', StringComparison.Ordinal)) + { + bcp47Map[code.Replace('_', '-')] = code; + } + + // Skip the base language file — en-US is added explicitly below + if (code.Equals(DefaultCulture, StringComparison.OrdinalIgnoreCase)) + { + continue; + } + + var displayName = GetDisplayName(code); + options.Add(new LocalizationOption(displayName, code)); + } + + // Ensure en-US is always present + options.Add(new LocalizationOption("English", DefaultCulture)); + + options.Sort((a, b) => string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase)); + return (options, bcp47Map.ToFrozenDictionary(StringComparer.OrdinalIgnoreCase)); + } + + private static string GetDisplayName(string cultureCode) + { + // Custom/novelty codes like "pr" (Pirate) — fall back to code itself + return TryGetCultureInfo(cultureCode, out var cultureInfo) + ? cultureInfo.NativeName + : cultureCode; } /// <inheritdoc /> diff --git a/Emby.Server.Implementations/Localization/Ratings/gr.json b/Emby.Server.Implementations/Localization/Ratings/gr.json index 794bf0b313..73abab72d3 100644 --- a/Emby.Server.Implementations/Localization/Ratings/gr.json +++ b/Emby.Server.Implementations/Localization/Ratings/gr.json @@ -10,21 +10,42 @@ } }, { - "ratingStrings": ["K12"], + "ratingStrings": ["K12", "K-12", "12"], + "ratingScore": { + "score": 12, + "subScore": null + } + }, + { + "ratingStrings": ["K13", "K-13", "13"], "ratingScore": { "score": 13, "subScore": null } }, { - "ratingStrings": ["K15"], + "ratingStrings": ["K15", "K-15", "15"], "ratingScore": { "score": 15, "subScore": null } }, { - "ratingStrings": ["K18"], + "ratingStrings": ["K16", "K-16", "16"], + "ratingScore": { + "score": 16, + "subScore": null + } + }, + { + "ratingStrings": ["K17", "K-17", "17"], + "ratingScore": { + "score": 17, + "subScore": null + } + }, + { + "ratingStrings": ["K18", "K-18", "18", "18+"], "ratingScore": { "score": 18, "subScore": null diff --git a/Emby.Server.Implementations/Localization/Ratings/se.json b/Emby.Server.Implementations/Localization/Ratings/se.json index 70084995d1..818565e16b 100644 --- a/Emby.Server.Implementations/Localization/Ratings/se.json +++ b/Emby.Server.Implementations/Localization/Ratings/se.json @@ -10,7 +10,7 @@ } }, { - "ratingStrings": ["7"], + "ratingStrings": ["7", "7+", "7 År", "Från 7 år"], "ratingScore": { "score": 7, "subScore": null @@ -31,7 +31,7 @@ } }, { - "ratingStrings": ["11"], + "ratingStrings": ["11", "11+", "11 År", "Från 11 år"], "ratingScore": { "score": 11, "subScore": null @@ -45,11 +45,18 @@ } }, { - "ratingStrings": ["15"], + "ratingStrings": ["15", "15+", "15 År", "Från 15 år"], "ratingScore": { "score": 15, "subScore": null } + }, + { + "ratingStrings": ["18", "18+", "Barnförbjuden", "Bfj"], + "ratingScore": { + "score": 18, + "subScore": null + } } ] } diff --git a/Emby.Server.Implementations/Plugins/PluginManager.cs b/Emby.Server.Implementations/Plugins/PluginManager.cs index 91ccb16ef9..f699c99d85 100644 --- a/Emby.Server.Implementations/Plugins/PluginManager.cs +++ b/Emby.Server.Implementations/Plugins/PluginManager.cs @@ -564,7 +564,8 @@ namespace Emby.Server.Implementations.Plugins Id = instance.Id, Status = PluginStatus.Active, Name = instance.Name, - Version = instance.Version.ToString() + Version = instance.Version.ToString(), + ImageResourceName = (instance as IHasEmbeddedImage)?.ImageResourceName }) { Instance = instance diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/AudioNormalizationTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/AudioNormalizationTask.cs index b2dc89be28..e4939205c9 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/AudioNormalizationTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/AudioNormalizationTask.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; +using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; @@ -234,7 +235,7 @@ public partial class AudioNormalizationTask : IScheduledTask { FileName = _mediaEncoder.EncoderPath, Arguments = args, - RedirectStandardOutput = false, + StandardErrorEncoding = Encoding.UTF8, RedirectStandardError = true }, }) diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs index f81309560e..f1e1579a1d 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs @@ -92,7 +92,8 @@ public class ChapterImagesTask : IScheduledTask EnableImages = false }, SourceTypes = [SourceType.Library], - IsVirtualItem = false + IsVirtualItem = false, + IncludeOwnedItems = true }) .OfType<Video>() .ToList(); diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/MediaSegmentExtractionTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/MediaSegmentExtractionTask.cs index 51920c5b14..9cc6eb265a 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/MediaSegmentExtractionTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/MediaSegmentExtractionTask.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Threading; @@ -68,6 +68,7 @@ public class MediaSegmentExtractionTask : IScheduledTask DtoOptions = new DtoOptions(true), SourceTypes = [SourceType.Library], Recursive = true, + IncludeOwnedItems = true, Limit = pagesize }; diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/OptimizeDatabaseTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/OptimizeDatabaseTask.cs index 92d7a3907a..8d133dc074 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/OptimizeDatabaseTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/OptimizeDatabaseTask.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Jellyfin.Database.Implementations; +using MediaBrowser.Controller.Library; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Tasks; using Microsoft.Extensions.Logging; @@ -17,6 +18,7 @@ public class OptimizeDatabaseTask : IScheduledTask, IConfigurableScheduledTask private readonly ILogger<OptimizeDatabaseTask> _logger; private readonly ILocalizationManager _localization; private readonly IJellyfinDatabaseProvider _jellyfinDatabaseProvider; + private readonly ILibraryManager _libraryManager; /// <summary> /// Initializes a new instance of the <see cref="OptimizeDatabaseTask" /> class. @@ -24,14 +26,17 @@ public class OptimizeDatabaseTask : IScheduledTask, IConfigurableScheduledTask /// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param> /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param> /// <param name="jellyfinDatabaseProvider">Instance of the JellyfinDatabaseProvider that can be used for provider specific operations.</param> + /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param> public OptimizeDatabaseTask( ILogger<OptimizeDatabaseTask> logger, ILocalizationManager localization, - IJellyfinDatabaseProvider jellyfinDatabaseProvider) + IJellyfinDatabaseProvider jellyfinDatabaseProvider, + ILibraryManager libraryManager) { _logger = logger; _localization = localization; _jellyfinDatabaseProvider = jellyfinDatabaseProvider; + _libraryManager = libraryManager; } /// <inheritdoc /> @@ -68,6 +73,15 @@ public class OptimizeDatabaseTask : IScheduledTask, IConfigurableScheduledTask /// <inheritdoc /> public async Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken) { + // Vacuuming/checkpointing requires an exclusive lock on the database. Running it while a library scan is in + // progress causes both operations to contend for the database and can stall the scan, so defer optimization + // until no scan is running. The task will run again on its next trigger. + if (_libraryManager.IsScanRunning) + { + _logger.LogInformation("Skipping database optimization because a library scan is currently running."); + return; + } + _logger.LogInformation("Optimizing and vacuuming jellyfin.db..."); try diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/PeopleValidationTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/PeopleValidationTask.cs index 6e4e5c7808..dff9a473af 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/PeopleValidationTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/PeopleValidationTask.cs @@ -4,11 +4,18 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Data.Enums; using Jellyfin.Database.Implementations; +using Jellyfin.Database.Implementations.Entities; +using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Persistence; +using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Globalization; +using MediaBrowser.Model.IO; using MediaBrowser.Model.Tasks; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.ScheduledTasks.Tasks; @@ -20,6 +27,9 @@ public class PeopleValidationTask : IScheduledTask, IConfigurableScheduledTask private readonly ILibraryManager _libraryManager; private readonly ILocalizationManager _localization; private readonly IDbContextFactory<JellyfinDbContext> _dbContextFactory; + private readonly IFileSystem _fileSystem; + private readonly ILogger<PeopleValidationTask> _logger; + private readonly IItemTypeLookup _itemTypeLookup; /// <summary> /// Initializes a new instance of the <see cref="PeopleValidationTask" /> class. @@ -27,11 +37,23 @@ public class PeopleValidationTask : IScheduledTask, IConfigurableScheduledTask /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param> /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param> /// <param name="dbContextFactory">Instance of the <see cref="IDbContextFactory{TContext}"/> interface.</param> - public PeopleValidationTask(ILibraryManager libraryManager, ILocalizationManager localization, IDbContextFactory<JellyfinDbContext> dbContextFactory) + /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param> + /// <param name="logger">Instance of the <see cref="ILogger{PeopleValidationTask}"/> interface.</param> + /// <param name="itemTypeLookup">Instance of the <see cref="IItemTypeLookup"/> interface.</param> + public PeopleValidationTask( + ILibraryManager libraryManager, + ILocalizationManager localization, + IDbContextFactory<JellyfinDbContext> dbContextFactory, + IFileSystem fileSystem, + ILogger<PeopleValidationTask> logger, + IItemTypeLookup itemTypeLookup) { _libraryManager = libraryManager; _localization = localization; _dbContextFactory = dbContextFactory; + _fileSystem = fileSystem; + _logger = logger; + _itemTypeLookup = itemTypeLookup; } /// <inheritdoc /> @@ -71,13 +93,19 @@ public class PeopleValidationTask : IScheduledTask, IConfigurableScheduledTask /// <inheritdoc /> public async Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken) { - IProgress<double> subProgress = new Progress<double>((val) => progress.Report(val / 2)); - await _libraryManager.ValidatePeopleAsync(subProgress, cancellationToken).ConfigureAwait(false); + // People validation performs heavy database writes that contend with an active library scan. + // Defer it until the scan has finished; the task will run again on its next trigger. + if (_libraryManager.IsScanRunning) + { + _logger.LogInformation("Skipping people validation because a library scan is currently running."); + return; + } - subProgress = new Progress<double>((val) => progress.Report((val / 2) + 50)); + // Phase 1: Deduplicate and remove orphaned people (0-33%) var context = await _dbContextFactory.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); await using (context.ConfigureAwait(false)) { + IProgress<double> subProgress = new Progress<double>((val) => progress.Report(val / 3)); var dupQuery = context.Peoples .GroupBy(e => new { e.Name, e.PersonType }) .Where(e => e.Count() > 1) @@ -123,7 +151,113 @@ public class PeopleValidationTask : IScheduledTask, IConfigurableScheduledTask ArrayPool<Guid[]>.Shared.Return(buffer); } + var peopleToDelete = await context.Peoples + .Where(p => !context.PeopleBaseItemMap.Any(m => m.PeopleId.Equals(p.Id))) + .ExecuteDeleteAsync(cancellationToken) + .ConfigureAwait(false); + _logger.LogInformation("Removed {Count} orphaned people.", peopleToDelete); + subProgress.Report(100); } + + // Phase 2: Validate people (33-66%). Runs after orphaned PeopleBaseItemMap entries are + // cleaned up above, so dead people are removed in a single pass instead of requiring a second run. + IProgress<double> validateProgress = new Progress<double>((val) => progress.Report((val / 3) + 33)); + await _libraryManager.ValidatePeopleAsync(validateProgress, cancellationToken).ConfigureAwait(false); + + // Phase 3: Refresh images for people missing them (66-100%) + IProgress<double> refreshProgress = new Progress<double>((val) => progress.Report((val / 3) + 66)); + await RefreshPeopleImagesAsync(refreshProgress, cancellationToken).ConfigureAwait(false); + + progress.Report(100); + } + + private async Task RefreshPeopleImagesAsync(IProgress<double> progress, CancellationToken cancellationToken) + { + var thirtyDaysAgo = DateTime.UtcNow.AddDays(-30); + var personTypeName = _itemTypeLookup.BaseItemKindNames[BaseItemKind.Person]; + + var context = await _dbContextFactory.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); + await using (context.ConfigureAwait(false)) + { + const int PartitionSize = 100; + + var numPeople = await context.BaseItems + .AsNoTracking() + .Where(b => b.Type == personTypeName) + .Where(b => b.DateLastRefreshed == null || b.DateLastRefreshed < thirtyDaysAgo) + .Where(b => + !b.Images!.Any(i => i.ImageType == ImageInfoImageType.Primary) || + string.IsNullOrEmpty(b.Overview)) + .CountAsync(cancellationToken) + .ConfigureAwait(false); + + _logger.LogDebug("Found {Count} people needing image/overview refresh", numPeople); + + if (numPeople == 0) + { + progress.Report(100); + return; + } + + var numComplete = 0; + var numRefreshed = 0; + + await foreach (var entry in context.BaseItems + .AsNoTracking() + .Where(b => b.Type == personTypeName) + .Where(b => b.DateLastRefreshed == null || b.DateLastRefreshed < thirtyDaysAgo) + .Where(b => + !b.Images!.Any(i => i.ImageType == ImageInfoImageType.Primary) || + string.IsNullOrEmpty(b.Overview)) + .OrderBy(b => b.Id) + .WithPartitionProgress(partition => _logger.LogDebug("Processing people partition {Partition}", partition)) + .PartitionEagerAsync(PartitionSize, cancellationToken) + .WithCancellation(cancellationToken) + .ConfigureAwait(false)) + { + if (await RefreshPersonAsync(entry.Id, cancellationToken).ConfigureAwait(false)) + { + numRefreshed++; + } + + numComplete++; + progress.Report(100.0 * numComplete / numPeople); + } + + _logger.LogInformation("Refreshed metadata for {Count} people missing images or overview", numRefreshed); + } + } + + private async Task<bool> RefreshPersonAsync(Guid personId, CancellationToken cancellationToken) + { + try + { + if (_libraryManager.GetItemById(personId) is not Person item) + { + return false; + } + + var hasImage = item.HasImage(MediaBrowser.Model.Entities.ImageType.Primary); + var hasOverview = !string.IsNullOrEmpty(item.Overview); + + var options = new MetadataRefreshOptions(new DirectoryService(_fileSystem)) + { + ImageRefreshMode = hasImage ? MetadataRefreshMode.ValidationOnly : MetadataRefreshMode.Default, + MetadataRefreshMode = hasOverview ? MetadataRefreshMode.ValidationOnly : MetadataRefreshMode.Default + }; + + await item.RefreshMetadata(options, cancellationToken).ConfigureAwait(false); + return true; + } + catch (OperationCanceledException) + { + throw; + } + catch (Exception ex) + { + _logger.LogError(ex, "Error refreshing images for person {PersonId}", personId); + return false; + } } } diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index 1782b53e10..828bdd6859 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -271,9 +271,9 @@ namespace Emby.Server.Implementations.Session user.LastActivityDate = activityDate; await _userManager.UpdateUserAsync(user).ConfigureAwait(false); } - catch (DbUpdateConcurrencyException e) + catch (DbUpdateConcurrencyException) { - _logger.LogDebug(e, "Error updating user's last activity date."); + _logger.LogDebug("Error updating user's last activity date due to concurrency conflict. This is an expected event."); } } } @@ -343,6 +343,10 @@ namespace Emby.Server.Implementations.Session _activeLiveStreamSessions.TryRemove(liveStreamId, out _); } } + else + { + liveStreamNeedsToBeClosed = true; + } if (liveStreamNeedsToBeClosed) { @@ -386,7 +390,7 @@ namespace Emby.Server.Implementations.Session { if (session is null) { - return; + return; } if (string.IsNullOrEmpty(info.MediaSourceId)) @@ -453,18 +457,6 @@ namespace Emby.Server.Implementations.Session session.PlayState.RepeatMode = info.RepeatMode; session.PlayState.PlaybackOrder = info.PlaybackOrder; session.PlaylistItemId = info.PlaylistItemId; - - var nowPlayingQueue = info.NowPlayingQueue; - - if (nowPlayingQueue?.Length > 0 && !nowPlayingQueue.SequenceEqual(session.NowPlayingQueue)) - { - session.NowPlayingQueue = nowPlayingQueue; - - var itemIds = Array.ConvertAll(nowPlayingQueue, queue => queue.Id); - session.NowPlayingQueueFullItems = _dtoService.GetBaseItemDtos( - _libraryManager.GetItemList(new InternalItemsQuery { ItemIds = itemIds }), - new DtoOptions(true)); - } } /// <summary> @@ -738,6 +730,31 @@ namespace Emby.Server.Implementations.Session } /// <summary> + /// Resolves the item whose user data (playback position, played status) should be updated + /// for a playback report. When an alternate version is played the client reports the displayed + /// item as <c>ItemId</c> and the played version as <c>MediaSourceId</c>. + /// </summary> + /// <param name="libraryItem">The now playing (displayed) item.</param> + /// <param name="mediaSourceId">The reported media source id.</param> + /// <returns>The item to track progress against.</returns> + private BaseItem GetProgressItem(BaseItem libraryItem, string mediaSourceId) + { + if (libraryItem is Video libraryVideo + && !string.IsNullOrEmpty(mediaSourceId) + && Guid.TryParse(mediaSourceId, out var mediaSourceItemId) + && !mediaSourceItemId.Equals(libraryVideo.Id)) + { + var versionItem = libraryVideo.GetAlternateVersion(mediaSourceItemId); + if (versionItem is not null) + { + return versionItem; + } + } + + return libraryItem; + } + + /// <summary> /// Used to report that playback has started for an item. /// </summary> /// <param name="info">The info.</param> @@ -768,9 +785,10 @@ namespace Emby.Server.Implementations.Session if (libraryItem is not null) { + var progressItem = GetProgressItem(libraryItem, info.MediaSourceId); foreach (var user in users) { - OnPlaybackStart(user, libraryItem); + OnPlaybackStart(user, progressItem); } } @@ -902,9 +920,10 @@ namespace Emby.Server.Implementations.Session // only update saved user data on actual check-ins, not automated ones if (libraryItem is not null && !isAutomated) { + var progressItem = GetProgressItem(libraryItem, info.MediaSourceId); foreach (var user in users) { - OnPlaybackProgress(user, libraryItem, info); + OnPlaybackProgress(user, progressItem, info); } } @@ -964,6 +983,20 @@ namespace Emby.Server.Implementations.Session if (changed) { _userDataManager.SaveUserData(user, item, data, UserDataSaveReason.PlaybackProgress, CancellationToken.None); + + // A completed version marks every alternate version played and clears their resume points, so the + // whole movie leaves Continue Watching and reads as watched everywhere. (Per-version resume positions + // only persist while nothing has been completed yet.) + if (data.Played == true && item is Video playedVideo) + { + playedVideo.PropagatePlayedState(user, true); + } + } + + if ((!user.RememberAudioSelections && info.AudioStreamIndex.HasValue) + || (!user.RememberSubtitleSelections && info.SubtitleStreamIndex.HasValue)) + { + _userDataManager.ResetPlaybackStreamSelections(user, item); } } @@ -1095,9 +1128,10 @@ namespace Emby.Server.Implementations.Session if (libraryItem is not null) { + var progressItem = GetProgressItem(libraryItem, info.MediaSourceId); foreach (var user in users) { - playedToCompletion = OnPlaybackStopped(user, libraryItem, info.PositionTicks, info.Failed); + playedToCompletion = OnPlaybackStopped(user, progressItem, info.PositionTicks, info.Failed); } } @@ -1150,6 +1184,14 @@ namespace Emby.Server.Implementations.Session _userDataManager.SaveUserData(user, item, data, UserDataSaveReason.PlaybackFinished, CancellationToken.None); + // A completed version marks every alternate version played and clears their resume points, so the + // whole movie leaves Continue Watching and reads as watched everywhere. (Per-version resume positions + // only persist while nothing has been completed yet.) + if (data.Played == true && item is Video playedVideo) + { + playedVideo.PropagatePlayedState(user, true); + } + return playedToCompletion; } @@ -1217,7 +1259,6 @@ namespace Emby.Server.Implementations.Session SupportsMediaControl = sessionInfo.SupportsMediaControl, SupportsRemoteControl = sessionInfo.SupportsRemoteControl, NowPlayingQueue = sessionInfo.NowPlayingQueue, - NowPlayingQueueFullItems = sessionInfo.NowPlayingQueueFullItems, HasCustomDeviceName = sessionInfo.HasCustomDeviceName, PlaylistItemId = sessionInfo.PlaylistItemId, ServerId = sessionInfo.ServerId, diff --git a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs index 6a26e92e14..2582ed9df0 100644 --- a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs +++ b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs @@ -246,8 +246,21 @@ namespace Emby.Server.Implementations.Session _logger.LogInformation("Lost {0} WebSockets.", lost.Count); foreach (var webSocket in lost) { - // TODO: handle session relative to the lost webSocket RemoveWebSocket(webSocket); + + // The connection stopped answering keep-alives, so a close frame will + // never arrive and the pending receive loop would hang forever, keeping + // the session (and e.g. its SyncPlay group membership) alive. Disposing + // the connection aborts the receive loop, which raises Closed and lets + // the session end normally. + try + { + webSocket.Dispose(); + } + catch (Exception exception) + { + _logger.LogWarning(exception, "Error disposing lost WebSocket from {RemoteEndPoint}.", webSocket.RemoteEndPoint); + } } } } diff --git a/Emby.Server.Implementations/SyncPlay/Group.cs b/Emby.Server.Implementations/SyncPlay/Group.cs index c2e834ad58..38a0018a70 100644 --- a/Emby.Server.Implementations/SyncPlay/Group.cs +++ b/Emby.Server.Implementations/SyncPlay/Group.cs @@ -206,7 +206,8 @@ namespace Emby.Server.Implementations.SyncPlay foreach (var itemId in queue) { var item = _libraryManager.GetItemById(itemId); - if (!item.IsVisibleStandalone(user)) + + if (item is null || !item.IsVisibleStandalone(user)) { return false; } diff --git a/Emby.Server.Implementations/SystemManager.cs b/Emby.Server.Implementations/SystemManager.cs index d140426ddf..11a94648f8 100644 --- a/Emby.Server.Implementations/SystemManager.cs +++ b/Emby.Server.Implementations/SystemManager.cs @@ -89,11 +89,11 @@ public class SystemManager : ISystemManager .GetVirtualFolders() .Where(e => !string.IsNullOrWhiteSpace(e.ItemId)) // this should not be null but for some users it is. .Select(e => new LibraryStorageInfo() - { - Id = Guid.Parse(e.ItemId), - Name = e.Name, - Folders = e.Locations.Select(f => StorageHelper.GetFreeSpaceOf(f)).ToArray() - }); + { + Id = Guid.Parse(e.ItemId), + Name = e.Name, + Folders = e.Locations.Select(f => StorageHelper.GetFreeSpaceOf(f)).ToArray() + }); return new SystemStorageInfo() { diff --git a/Emby.Server.Implementations/TV/TVSeriesManager.cs b/Emby.Server.Implementations/TV/TVSeriesManager.cs index 535dc01a31..459ad1a17e 100644 --- a/Emby.Server.Implementations/TV/TVSeriesManager.cs +++ b/Emby.Server.Implementations/TV/TVSeriesManager.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using Jellyfin.Data; using Jellyfin.Data.Enums; @@ -136,11 +137,15 @@ namespace Emby.Server.Implementations.TV if (nextEpisode is not null) { + // The last played date and the version that was actually played live on the version item's user data + // The played state propagated to the sibling versions carries no date + var (playedVersion, lastPlayedDate) = GetMostRecentlyPlayedVersion(result.LastWatched, user); + nextEpisode = GetPreferredVersion(nextEpisode, result.LastWatched, playedVersion); + DateTime lastWatchedDate = DateTime.MinValue; if (result.LastWatched is not null) { - var userData = _userDataManager.GetUserData(user, result.LastWatched); - lastWatchedDate = userData?.LastPlayedDate ?? DateTime.MinValue.AddDays(1); + lastWatchedDate = lastPlayedDate ?? DateTime.MinValue.AddDays(1); } nextUpList.Add((lastWatchedDate, nextEpisode)); @@ -152,11 +157,13 @@ namespace Emby.Server.Implementations.TV if (nextPlayedEpisode is not null) { + var (playedVersion, lastPlayedDate) = GetMostRecentlyPlayedVersion(result.LastWatchedForRewatching, user); + nextPlayedEpisode = GetPreferredVersion(nextPlayedEpisode, result.LastWatchedForRewatching, playedVersion); + DateTime rewatchLastWatchedDate = DateTime.MinValue; if (result.LastWatchedForRewatching is not null) { - var userData = _userDataManager.GetUserData(user, result.LastWatchedForRewatching); - rewatchLastWatchedDate = userData?.LastPlayedDate ?? DateTime.MinValue.AddDays(1); + rewatchLastWatchedDate = lastPlayedDate ?? DateTime.MinValue.AddDays(1); } nextUpList.Add((rewatchLastWatchedDate, nextPlayedEpisode)); @@ -219,10 +226,13 @@ namespace Emby.Server.Implementations.TV if (nextEpisode is not null && !includeResumable) { - var userData = _userDataManager.GetUserData(user, nextEpisode); - if (userData?.PlaybackPositionTicks > 0) + // The resume progress may live on an alternate version + foreach (var version in nextEpisode.GetAllVersions()) { - return null; + if (_userDataManager.GetUserData(user, version)?.PlaybackPositionTicks > 0) + { + return null; + } } } @@ -237,6 +247,74 @@ namespace Emby.Server.Implementations.TV return DetermineNextEpisode(result, user, includeSpecials, includeResumable: false, includePlayed: true); } + /// <summary> + /// Gets the version of the last watched episode that was actually played, together with its last played date. + /// The version that was played carries the most recent LastPlayedDate. + /// dates. + /// </summary> + /// <param name="lastWatched">The last watched episode (any version).</param> + /// <param name="user">The user.</param> + /// <returns>The played version and its last played date.</returns> + private (Video? PlayedVersion, DateTime? LastPlayedDate) GetMostRecentlyPlayedVersion(BaseItem? lastWatched, User user) + { + if (lastWatched is not Video lastWatchedVideo) + { + return (null, null); + } + + var versions = lastWatchedVideo.GetAllVersions(); + var userDataByVersion = _userDataManager.GetUserDataBatch(versions, user); + + var playedVersion = VersionPlaybackSelector.SelectMostRecentlyPlayed( + versions, + version => userDataByVersion.GetValueOrDefault(version.Id), + data => data.LastPlayedDate.HasValue); + + return (playedVersion, playedVersion is null ? null : userDataByVersion[playedVersion.Id].LastPlayedDate); + } + + /// <summary> + /// When the last watched episode was played as an alternate version, prefer the next episode's version with the matching name, + /// so Next Up continues in the version the user has been watching instead of falling back to the primary. + /// </summary> + /// <param name="nextEpisode">The determined next episode (a primary).</param> + /// <param name="lastWatched">The last watched episode.</param> + /// <param name="playedVersion">The version of the last watched episode that was played.</param> + /// <returns>The matching version of the next episode, or the episode itself.</returns> + private Episode GetPreferredVersion(Episode nextEpisode, BaseItem? lastWatched, Video? playedVersion) + { + // No version preference, or the primary was played + if (lastWatched is not Video lastWatchedVideo + || playedVersion is null + || !playedVersion.PrimaryVersionId.HasValue) + { + return nextEpisode; + } + + // Match by version name + var playedVersionId = playedVersion.Id.ToString("N", CultureInfo.InvariantCulture); + var playedVersionName = lastWatchedVideo.GetMediaSources(false) + .FirstOrDefault(source => string.Equals(source.Id, playedVersionId, StringComparison.OrdinalIgnoreCase))?.Name; + + if (string.IsNullOrEmpty(playedVersionName)) + { + return nextEpisode; + } + + var matchingSource = nextEpisode.GetMediaSources(false) + .FirstOrDefault(source => string.Equals(source.Name, playedVersionName, StringComparison.OrdinalIgnoreCase)); + + if (matchingSource is not null + && Guid.TryParse(matchingSource.Id, out var matchingId) + && !matchingId.Equals(nextEpisode.Id) + && _libraryManager.GetItemById<Episode>(matchingId) is { } matchingVersion) + { + return matchingVersion; + } + + return nextEpisode; + } + private static string GetUniqueSeriesKey(Series series) { return series.GetPresentationUniqueKey(); diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index 67b77a112d..6a60f7f5f6 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -1,4 +1,5 @@ using System; +using System.Buffers; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; @@ -32,6 +33,8 @@ namespace Emby.Server.Implementations.Updates /// </summary> public class InstallationManager : IInstallationManager { + private static readonly SearchValues<char> InvalidPackageNameChars = SearchValues.Create([.. Path.GetInvalidFileNameChars(), '/', '\\']); + /// <summary> /// The logger. /// </summary> @@ -521,48 +524,68 @@ namespace Emby.Server.Implementations.Updates return; } + if (!IsValidPackageDirectoryName(package.Name)) + { + _logger.LogError("Refusing to install package with invalid name {PackageName}.", package.Name); + throw new InvalidDataException($"Plugin package name '{package.Name}' is not a valid directory name."); + } + // Always override the passed-in target (which is a file) and figure it out again string targetDir = Path.Combine(_appPaths.PluginsPath, package.Name); - using var response = await _httpClientFactory.CreateClient(NamedClient.Default) - .GetAsync(new Uri(package.SourceUrl), cancellationToken).ConfigureAwait(false); - response.EnsureSuccessStatusCode(); - await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - - // CA5351: Do Not Use Broken Cryptographic Algorithms -#pragma warning disable CA5351 - cancellationToken.ThrowIfCancellationRequested(); - - var hash = Convert.ToHexString(await MD5.HashDataAsync(stream, cancellationToken).ConfigureAwait(false)); - if (!string.Equals(package.Checksum, hash, StringComparison.OrdinalIgnoreCase)) + var pluginsRoot = Path.TrimEndingDirectorySeparator(Path.GetFullPath(_appPaths.PluginsPath)); + var resolvedTarget = Path.GetFullPath(targetDir); + if (!resolvedTarget.StartsWith(pluginsRoot + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase)) { _logger.LogError( - "The checksums didn't match while installing {Package}, expected: {Expected}, got: {Received}", + "Refusing to install package {PackageName}: resolved target {Resolved} is outside plugins directory {Root}.", package.Name, - package.Checksum, - hash); - throw new InvalidDataException("The checksum of the received data doesn't match."); + resolvedTarget, + pluginsRoot); + throw new InvalidDataException($"Plugin package name '{package.Name}' resolves outside the plugins directory."); } - // Version folder as they cannot be overwritten in Windows. - targetDir += "_" + package.Version; - - if (Directory.Exists(targetDir)) + using var response = await _httpClientFactory.CreateClient(NamedClient.Default) + .GetAsync(new Uri(package.SourceUrl), cancellationToken).ConfigureAwait(false); + response.EnsureSuccessStatusCode(); + Stream stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); + await using (stream.ConfigureAwait(false)) { - try + // CA5351: Do Not Use Broken Cryptographic Algorithms +#pragma warning disable CA5351 + cancellationToken.ThrowIfCancellationRequested(); + + var hash = Convert.ToHexString(await MD5.HashDataAsync(stream, cancellationToken).ConfigureAwait(false)); + if (!string.Equals(package.Checksum, hash, StringComparison.OrdinalIgnoreCase)) { - Directory.Delete(targetDir, true); + _logger.LogError( + "The checksums didn't match while installing {Package}, expected: {Expected}, got: {Received}", + package.Name, + package.Checksum, + hash); + throw new InvalidDataException("The checksum of the received data doesn't match."); } + + // Version folder as they cannot be overwritten in Windows. + targetDir += "_" + package.Version; + + if (Directory.Exists(targetDir)) + { + try + { + Directory.Delete(targetDir, true); + } #pragma warning disable CA1031 // Do not catch general exception types - catch + catch #pragma warning restore CA1031 // Do not catch general exception types - { - // Ignore any exceptions. + { + // Ignore any exceptions. + } } - } - stream.Position = 0; - await ZipFile.ExtractToDirectoryAsync(stream, targetDir, true, cancellationToken); + stream.Position = 0; + await ZipFile.ExtractToDirectoryAsync(stream, targetDir, true, cancellationToken).ConfigureAwait(false); + } // Ensure we create one or populate existing ones with missing data. await _pluginManager.PopulateManifest(package.PackageInfo, package.Version, targetDir, status).ConfigureAwait(false); @@ -570,6 +593,26 @@ namespace Emby.Server.Implementations.Updates _pluginManager.ImportPluginFrom(targetDir); } + private static bool IsValidPackageDirectoryName(string? name) + { + if (string.IsNullOrWhiteSpace(name)) + { + return false; + } + + if (name.Equals(".", StringComparison.Ordinal) || name.Equals("..", StringComparison.Ordinal)) + { + return false; + } + + if (name.IndexOfAny(InvalidPackageNameChars) >= 0) + { + return false; + } + + return true; + } + private async Task<bool> InstallPackageInternal(InstallationInfo package, CancellationToken cancellationToken) { LocalPlugin? plugin = _pluginManager.Plugins.FirstOrDefault(p => p.Id.Equals(package.Id) && p.Version.Equals(package.Version)) |
