mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-04-26 12:05:04 +01:00
Merge branch 'master' into network-rewrite
This commit is contained in:
@@ -365,11 +365,7 @@ namespace Emby.Server.Implementations.AppBase
|
||||
validatingStore.Validate(currentConfiguration, configuration);
|
||||
}
|
||||
|
||||
NamedConfigurationUpdating?.Invoke(this, new ConfigurationUpdateEventArgs
|
||||
{
|
||||
Key = key,
|
||||
NewConfiguration = configuration
|
||||
});
|
||||
NamedConfigurationUpdating?.Invoke(this, new ConfigurationUpdateEventArgs(key, configuration));
|
||||
|
||||
_configurations.AddOrUpdate(key, configuration, (_, _) => configuration);
|
||||
|
||||
@@ -391,11 +387,7 @@ namespace Emby.Server.Implementations.AppBase
|
||||
/// <param name="configuration">The old configuration.</param>
|
||||
protected virtual void OnNamedConfigurationUpdated(string key, object configuration)
|
||||
{
|
||||
NamedConfigurationUpdated?.Invoke(this, new ConfigurationUpdateEventArgs
|
||||
{
|
||||
Key = key,
|
||||
NewConfiguration = configuration
|
||||
});
|
||||
NamedConfigurationUpdated?.Invoke(this, new ConfigurationUpdateEventArgs(key, configuration));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -83,6 +83,7 @@ using MediaBrowser.Controller.SyncPlay;
|
||||
using MediaBrowser.Controller.TV;
|
||||
using MediaBrowser.LocalMetadata.Savers;
|
||||
using MediaBrowser.MediaEncoding.BdInfo;
|
||||
using MediaBrowser.MediaEncoding.Subtitles;
|
||||
using MediaBrowser.Model.Cryptography;
|
||||
using MediaBrowser.Model.Dlna;
|
||||
using MediaBrowser.Model.Globalization;
|
||||
@@ -111,7 +112,7 @@ namespace Emby.Server.Implementations
|
||||
/// <summary>
|
||||
/// Class CompositionRoot.
|
||||
/// </summary>
|
||||
public abstract class ApplicationHost : IServerApplicationHost, IDisposable
|
||||
public abstract class ApplicationHost : IServerApplicationHost, IAsyncDisposable, IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// The environment variable prefixes to log at server startup.
|
||||
@@ -634,7 +635,8 @@ namespace Emby.Server.Implementations
|
||||
serviceCollection.AddSingleton<IAuthService, AuthService>();
|
||||
serviceCollection.AddSingleton<IQuickConnect, QuickConnectManager>();
|
||||
|
||||
serviceCollection.AddSingleton<ISubtitleEncoder, MediaBrowser.MediaEncoding.Subtitles.SubtitleEncoder>();
|
||||
serviceCollection.AddSingleton<ISubtitleParser, SubtitleEditParser>();
|
||||
serviceCollection.AddSingleton<ISubtitleEncoder, SubtitleEncoder>();
|
||||
|
||||
serviceCollection.AddSingleton<IAttachmentExtractor, MediaBrowser.MediaEncoding.Attachments.AttachmentExtractor>();
|
||||
|
||||
@@ -1233,5 +1235,49 @@ namespace Emby.Server.Implementations
|
||||
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
await DisposeAsyncCore().ConfigureAwait(false);
|
||||
Dispose(false);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to perform asynchronous cleanup of managed resources or for cascading calls to <see cref="DisposeAsync"/>.
|
||||
/// </summary>
|
||||
/// <returns>A ValueTask.</returns>
|
||||
protected virtual async ValueTask DisposeAsyncCore()
|
||||
{
|
||||
var type = GetType();
|
||||
|
||||
Logger.LogInformation("Disposing {Type}", type.Name);
|
||||
|
||||
foreach (var (part, _) in _disposableParts)
|
||||
{
|
||||
var partType = part.GetType();
|
||||
if (partType == type)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Logger.LogInformation("Disposing {Type}", partType.Name);
|
||||
|
||||
try
|
||||
{
|
||||
part.Dispose();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Error disposing {Type}", partType.Name);
|
||||
}
|
||||
}
|
||||
|
||||
// used for closing websockets
|
||||
foreach (var session in _sessionManager.Sessions)
|
||||
{
|
||||
await session.DisposeAsync().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4934,6 +4934,7 @@ SELECT key FROM UserDatas WHERE isFavorite=@IsFavorite AND userId=@UserId)
|
||||
AND Type = @InternalPersonType)");
|
||||
statement?.TryBind("@IsFavorite", query.IsFavorite.Value);
|
||||
statement?.TryBind("@InternalPersonType", typeof(Person).FullName);
|
||||
statement?.TryBind("@UserId", query.User.InternalId);
|
||||
}
|
||||
|
||||
if (!query.ItemId.Equals(default))
|
||||
@@ -4988,11 +4989,6 @@ AND Type = @InternalPersonType)");
|
||||
statement?.TryBind("@NameContains", "%" + query.NameContains + "%");
|
||||
}
|
||||
|
||||
if (query.User != null)
|
||||
{
|
||||
statement?.TryBind("@UserId", query.User.InternalId);
|
||||
}
|
||||
|
||||
return whereClauses;
|
||||
}
|
||||
|
||||
|
||||
@@ -182,7 +182,7 @@ namespace Emby.Server.Implementations.Dto
|
||||
|
||||
if (options.ContainsField(ItemFields.People))
|
||||
{
|
||||
AttachPeople(dto, item);
|
||||
AttachPeople(dto, item, user);
|
||||
}
|
||||
|
||||
if (options.ContainsField(ItemFields.PrimaryImageAspectRatio))
|
||||
@@ -503,7 +503,8 @@ namespace Emby.Server.Implementations.Dto
|
||||
/// </summary>
|
||||
/// <param name="dto">The dto.</param>
|
||||
/// <param name="item">The item.</param>
|
||||
private void AttachPeople(BaseItemDto dto, BaseItem item)
|
||||
/// <param name="user">The requesting user.</param>
|
||||
private void AttachPeople(BaseItemDto dto, BaseItem item, User user = null)
|
||||
{
|
||||
// Ordering by person type to ensure actors and artists are at the front.
|
||||
// This is taking advantage of the fact that they both begin with A
|
||||
@@ -560,6 +561,9 @@ namespace Emby.Server.Implementations.Dto
|
||||
return null;
|
||||
}
|
||||
}).Where(i => i != null)
|
||||
.Where(i => user == null ?
|
||||
true :
|
||||
i.IsVisible(user))
|
||||
.GroupBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
|
||||
.Select(x => x.First())
|
||||
.ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
@@ -29,10 +29,10 @@
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="6.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.6" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.9" />
|
||||
<PackageReference Include="Mono.Nat" Version="3.0.3" />
|
||||
<PackageReference Include="prometheus-net.DotNetRuntime" Version="4.2.4" />
|
||||
<PackageReference Include="sharpcompress" Version="0.32.1" />
|
||||
<PackageReference Include="sharpcompress" Version="0.32.2" />
|
||||
<PackageReference Include="SQLitePCL.pretty.netstandard" Version="3.1.0" />
|
||||
<PackageReference Include="DotNet.Glob" Version="3.1.3" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Jellyfin.Data.Entities;
|
||||
using MediaBrowser.Common.Extensions;
|
||||
|
||||
@@ -11,7 +11,6 @@ using Jellyfin.Extensions.Json;
|
||||
using MediaBrowser.Controller.Net;
|
||||
using MediaBrowser.Model.Net;
|
||||
using MediaBrowser.Model.Session;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Emby.Server.Implementations.HttpServer
|
||||
@@ -19,7 +18,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
/// <summary>
|
||||
/// Class WebSocketConnection.
|
||||
/// </summary>
|
||||
public class WebSocketConnection : IWebSocketConnection, IDisposable
|
||||
public class WebSocketConnection : IWebSocketConnection
|
||||
{
|
||||
/// <summary>
|
||||
/// The logger.
|
||||
@@ -36,6 +35,8 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
/// </summary>
|
||||
private readonly WebSocket _socket;
|
||||
|
||||
private bool _disposed = false;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WebSocketConnection" /> class.
|
||||
/// </summary>
|
||||
@@ -244,10 +245,39 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
/// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
|
||||
protected virtual void Dispose(bool dispose)
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (dispose)
|
||||
{
|
||||
_socket.Dispose();
|
||||
}
|
||||
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
await DisposeAsyncCore().ConfigureAwait(false);
|
||||
Dispose(false);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to perform asynchronous cleanup of managed resources or for cascading calls to <see cref="DisposeAsync"/>.
|
||||
/// </summary>
|
||||
/// <returns>A ValueTask.</returns>
|
||||
protected virtual async ValueTask DisposeAsyncCore()
|
||||
{
|
||||
if (_socket.State == WebSocketState.Open)
|
||||
{
|
||||
await _socket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "System Shutdown", CancellationToken.None).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
_socket.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,6 @@ using MediaBrowser.Model.Library;
|
||||
using MediaBrowser.Model.Querying;
|
||||
using MediaBrowser.Model.Tasks;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Episode = MediaBrowser.Controller.Entities.TV.Episode;
|
||||
using EpisodeInfo = Emby.Naming.TV.EpisodeInfo;
|
||||
@@ -2453,6 +2452,12 @@ namespace Emby.Server.Implementations.Library
|
||||
return RootFolder;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void QueueLibraryScan()
|
||||
{
|
||||
_taskManager.QueueScheduledTask<RefreshMediaLibraryTask>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public int? GetSeasonNumberFromPath(string path)
|
||||
=> SeasonPathParser.Parse(path, true, true).SeasonNumber;
|
||||
@@ -2523,7 +2528,7 @@ namespace Emby.Server.Implementations.Library
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error reading the episode informations with ffprobe. Episode: {EpisodeInfo}", episodeInfo.Path);
|
||||
_logger.LogError(ex, "Error reading the episode information with ffprobe. Episode: {EpisodeInfo}", episodeInfo.Path);
|
||||
}
|
||||
|
||||
var changed = false;
|
||||
@@ -2760,7 +2765,8 @@ namespace Emby.Server.Implementations.Library
|
||||
|
||||
public List<Person> GetPeopleItems(InternalPeopleQuery query)
|
||||
{
|
||||
return _itemRepository.GetPeopleNames(query).Select(i =>
|
||||
return _itemRepository.GetPeopleNames(query)
|
||||
.Select(i =>
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -2771,7 +2777,12 @@ namespace Emby.Server.Implementations.Library
|
||||
_logger.LogError(ex, "Error getting person");
|
||||
return null;
|
||||
}
|
||||
}).Where(i => i != null).ToList();
|
||||
})
|
||||
.Where(i => i != null)
|
||||
.Where(i => query.User == null ?
|
||||
true :
|
||||
i.IsVisible(query.User))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public List<string> GetPeopleNames(InternalPeopleQuery query)
|
||||
|
||||
@@ -387,7 +387,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
|
||||
|
||||
if (!string.IsNullOrEmpty(item.Path))
|
||||
{
|
||||
// check for imdb id - we use full media path, as we can assume, that this will match in any use case (wither id in parent dir or in file name)
|
||||
// check for imdb id - we use full media path, as we can assume, that this will match in any use case (either id in parent dir or in file name)
|
||||
var imdbid = item.Path.AsSpan().GetAttributeValue("imdbid");
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(imdbid))
|
||||
@@ -464,7 +464,9 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
|
||||
var result = ResolveVideos<T>(parent, fileSystemEntries, SupportsMultiVersion, collectionType, parseName) ??
|
||||
new MultiItemResolverResult();
|
||||
|
||||
if (result.Items.Count == 1)
|
||||
var isPhotosCollection = string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(collectionType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase);
|
||||
if (!isPhotosCollection && result.Items.Count == 1)
|
||||
{
|
||||
var videoPath = result.Items[0].Path;
|
||||
var hasPhotos = photos.Any(i => !PhotoResolver.IsOwnedByResolvedMedia(videoPath, i.Name));
|
||||
|
||||
@@ -995,7 +995,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception("Tuner not found.");
|
||||
throw new ResourceNotFoundException("Tuner not found.");
|
||||
}
|
||||
|
||||
public async Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(string channelId, CancellationToken cancellationToken)
|
||||
|
||||
@@ -13,6 +13,7 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Jellyfin.Extensions;
|
||||
using Jellyfin.Extensions.Json;
|
||||
using MediaBrowser.Common;
|
||||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
@@ -297,7 +298,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||
else
|
||||
{
|
||||
_taskCompletionSource.TrySetException(
|
||||
new Exception(
|
||||
new FfmpegException(
|
||||
string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"Recording for {0} failed. Exit code {1}",
|
||||
|
||||
@@ -20,6 +20,7 @@ using Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos;
|
||||
using Jellyfin.Extensions;
|
||||
using Jellyfin.Extensions.Json;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Controller.Authentication;
|
||||
using MediaBrowser.Controller.LiveTv;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Entities;
|
||||
@@ -591,13 +592,10 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
if (ex.StatusCode.HasValue)
|
||||
if (ex.StatusCode.HasValue && ex.StatusCode.Value == HttpStatusCode.BadRequest)
|
||||
{
|
||||
if ((int)ex.StatusCode.Value == 400)
|
||||
{
|
||||
_tokens.Clear();
|
||||
_lastErrorResponse = DateTime.UtcNow;
|
||||
}
|
||||
_tokens.Clear();
|
||||
_lastErrorResponse = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
throw;
|
||||
@@ -662,7 +660,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
||||
return root.Token;
|
||||
}
|
||||
|
||||
throw new Exception("Could not authenticate with Schedules Direct Error: " + root.Message);
|
||||
throw new AuthenticationException("Could not authenticate with Schedules Direct Error: " + root.Message);
|
||||
}
|
||||
|
||||
private async Task AddLineupToAccount(ListingsProviderInfo info, CancellationToken cancellationToken)
|
||||
@@ -697,7 +695,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
||||
|
||||
if (string.IsNullOrEmpty(token))
|
||||
{
|
||||
throw new Exception("token required");
|
||||
throw new ArgumentException("token required");
|
||||
}
|
||||
|
||||
_logger.LogInformation("Headends on account ");
|
||||
@@ -768,14 +766,14 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
||||
var listingsId = info.ListingsId;
|
||||
if (string.IsNullOrEmpty(listingsId))
|
||||
{
|
||||
throw new Exception("ListingsId required");
|
||||
throw new ArgumentException("ListingsId required");
|
||||
}
|
||||
|
||||
var token = await GetToken(info, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (string.IsNullOrEmpty(token))
|
||||
{
|
||||
throw new Exception("token required");
|
||||
throw new ArgumentException("token required");
|
||||
}
|
||||
|
||||
using var options = new HttpRequestMessage(HttpMethod.Get, ApiUrl + "/lineups/" + listingsId);
|
||||
|
||||
@@ -196,7 +196,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
IsInfiniteStream = true,
|
||||
IsRemote = isRemote,
|
||||
|
||||
IgnoreDts = true,
|
||||
IgnoreDts = info.IgnoreDts,
|
||||
SupportsDirectPlay = supportsDirectPlay,
|
||||
SupportsDirectStream = supportsDirectStream,
|
||||
|
||||
|
||||
@@ -199,7 +199,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
if (string.IsNullOrWhiteSpace(numberString))
|
||||
{
|
||||
// Using this as a fallback now as this leads to Problems with channels like "5 USA"
|
||||
// where 5 isn't ment to be the channel number
|
||||
// where 5 isn't meant to be the channel number
|
||||
// Check for channel number with the format from SatIp
|
||||
// #EXTINF:0,84. VOX Schweiz
|
||||
// #EXTINF:0,84.0 - VOX Schweiz
|
||||
|
||||
@@ -92,22 +92,22 @@
|
||||
"ValueHasBeenAddedToLibrary": "تمت اضافت {0} إلى مكتبة الوسائط",
|
||||
"ValueSpecialEpisodeName": "حلقه خاصه - {0}",
|
||||
"VersionNumber": "النسخة {0}",
|
||||
"TaskCleanCacheDescription": "يحذف ملفات ذاكرة التخزين المؤقت التي لم يعد النظام بحاجة إليها.",
|
||||
"TaskCleanCache": "احذف مجلد ذاكرة التخزين المؤقت",
|
||||
"TaskCleanCacheDescription": "يحذف الملفات المؤقتة التي لم يعد النظام بحاجة إليها.",
|
||||
"TaskCleanCache": "احذف ما بمجلد الملفات المؤقتة",
|
||||
"TasksChannelsCategory": "قنوات الإنترنت",
|
||||
"TasksLibraryCategory": "مكتبة",
|
||||
"TasksMaintenanceCategory": "صيانة",
|
||||
"TaskRefreshLibraryDescription": "يقوم بفصح مكتبة الوسائط الخاصة بك بحثًا عن ملفات جديدة وتحديث البيانات الوصفية.",
|
||||
"TaskRefreshLibraryDescription": "يفصح مكتبة الوسائط الخاصة بك بحثًا عن ملفات جديدة، ومن ثم يتحدث البيانات الوصفية.",
|
||||
"TaskRefreshLibrary": "افحص مكتبة الوسائط",
|
||||
"TaskRefreshChapterImagesDescription": "يقوم بانشاء صور مصغرة لمقاطع الفيديو التي تحتوي على فصول.",
|
||||
"TaskRefreshChapterImagesDescription": "يُنشئ صور مصغرة لمقاطع الفيديو التي تحتوي على فصول.",
|
||||
"TaskRefreshChapterImages": "استخراج صور الفصل",
|
||||
"TasksApplicationCategory": "تطبيق",
|
||||
"TaskDownloadMissingSubtitlesDescription": "يقوم بالبحث في الإنترنت على الترجمات المفقودة إستنادا على البيانات الوصفية.",
|
||||
"TaskDownloadMissingSubtitles": "تحميل الترجمات المفقودة",
|
||||
"TaskRefreshChannelsDescription": "يقوم بتحديث معلومات قنوات الإنترنت.",
|
||||
"TaskDownloadMissingSubtitlesDescription": "يبحث في الإنترنت على الترجمات الناقصة استنادا على البيانات الوصفية.",
|
||||
"TaskDownloadMissingSubtitles": "تحميل الترجمات الناقصة",
|
||||
"TaskRefreshChannelsDescription": "يحدث معلومات قنوات الإنترنت.",
|
||||
"TaskRefreshChannels": "إعادة تحديث القنوات",
|
||||
"TaskCleanTranscodeDescription": "يقوم بحذف ملفات الترميز الأقدم من يوم واحد.",
|
||||
"TaskCleanTranscode": "حذف سجلات الترميز",
|
||||
"TaskCleanTranscodeDescription": "يحذف ملفات الترميز الأقدم من يوم واحد.",
|
||||
"TaskCleanTranscode": "حذف ما بمجلد الترميز",
|
||||
"TaskUpdatePluginsDescription": "تحميل وتثبيت الإضافات التي تم تفعيل التحديث التلقائي لها.",
|
||||
"TaskUpdatePlugins": "تحديث الإضافات",
|
||||
"TaskRefreshPeopleDescription": "يقوم بتحديث البيانات الوصفية للممثلين والمخرجين في مكتبة الوسائط الخاصة بك.",
|
||||
@@ -116,12 +116,12 @@
|
||||
"TaskCleanLogs": "حذف مسار السجل",
|
||||
"TaskCleanActivityLogDescription": "يحذف سجل الأنشطة الأقدم من الوقت الذي تم تحديده.",
|
||||
"TaskCleanActivityLog": "حذف سجل الأنشطة",
|
||||
"Default": "إفتراضي",
|
||||
"Default": "افتراضي",
|
||||
"Undefined": "غير معرف",
|
||||
"Forced": "ملحقة",
|
||||
"TaskOptimizeDatabaseDescription": "يضغط قاعدة البيانات ويقتطع المساحة الحرة. تشغيل هذه المهمة بعد فحص المكتبة أو إجراء تغييرات أخرى تتضمن تعديلات في قاعدة البيانات قد تؤدي إلى تحسين الأداء.",
|
||||
"TaskOptimizeDatabase": "تحسين قاعدة البيانات",
|
||||
"TaskKeyframeExtractorDescription": "يقوم باستخراج الإطارات الرئيسيه من ملفات الفيديو لكي ينشئ قوائم تشغيل بث HTTP المباشر. هذه المهمه قد تستمر لاوقات طويلة.",
|
||||
"TaskKeyframeExtractorDescription": "يستخرج الإطارات الرئيسية من ملفات الفيديو لكي ينشئ قوائم تشغيل بث HTTP المباشر. قد تستمر هذه العملية لوقت طويل.",
|
||||
"TaskKeyframeExtractor": "مستخرج الإطار الرئيسي",
|
||||
"External": "خارجي"
|
||||
}
|
||||
|
||||
@@ -119,5 +119,6 @@
|
||||
"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}"
|
||||
"UserOnlineFromDevice": "{0} on ühendatud seadmest {1}",
|
||||
"External": "Väline"
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"Artists": "Artistes",
|
||||
"AuthenticationSucceededWithUserName": "{0} authentifié avec succès",
|
||||
"Books": "Livres",
|
||||
"CameraImageUploadedFrom": "Une photo a été chargée depuis {0}",
|
||||
"CameraImageUploadedFrom": "Une photo a été téléversée depuis {0}",
|
||||
"Channels": "Chaînes",
|
||||
"ChapterNameValue": "Chapitre {0}",
|
||||
"Collections": "Collections",
|
||||
@@ -42,13 +42,13 @@
|
||||
"MusicVideos": "Clips musicaux",
|
||||
"NameInstallFailed": "{0} échec de l'installation",
|
||||
"NameSeasonNumber": "Saison {0}",
|
||||
"NameSeasonUnknown": "Saison Inconnue",
|
||||
"NameSeasonUnknown": "Saison inconnue",
|
||||
"NewVersionIsAvailable": "Une nouvelle version de Jellyfin Serveur est disponible au téléchargement.",
|
||||
"NotificationOptionApplicationUpdateAvailable": "Mise à jour de l'application disponible",
|
||||
"NotificationOptionApplicationUpdateInstalled": "Mise à jour de l'application installée",
|
||||
"NotificationOptionAudioPlayback": "Lecture audio démarrée",
|
||||
"NotificationOptionAudioPlaybackStopped": "Lecture audio arrêtée",
|
||||
"NotificationOptionCameraImageUploaded": "L'image de l'appareil photo a été transférée",
|
||||
"NotificationOptionCameraImageUploaded": "L'image de l'appareil photo a été téléversée",
|
||||
"NotificationOptionInstallationFailed": "Échec de l'installation",
|
||||
"NotificationOptionNewLibraryContent": "Nouveau contenu ajouté",
|
||||
"NotificationOptionPluginError": "Erreur d'extension",
|
||||
@@ -93,33 +93,33 @@
|
||||
"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.",
|
||||
"TaskDownloadMissingSubtitlesDescription": "Recherche les sous-titres manquants sur Internet en se basant sur la configuration des métadonnées.",
|
||||
"TaskDownloadMissingSubtitles": "Télécharger les sous-titres manquants",
|
||||
"TaskRefreshChannelsDescription": "Rafraîchit les informations des chaînes en ligne.",
|
||||
"TaskRefreshChannels": "Rafraîchir les chaînes",
|
||||
"TaskRefreshChannelsDescription": "Actualise les informations des chaînes en ligne.",
|
||||
"TaskRefreshChannels": "Actualiser les chaînes",
|
||||
"TaskCleanTranscodeDescription": "Supprime les fichiers transcodés de plus d'un jour.",
|
||||
"TaskCleanTranscode": "Nettoyer les dossier des transcodages",
|
||||
"TaskCleanTranscode": "Nettoyer le dossier des transcodages",
|
||||
"TaskUpdatePluginsDescription": "Télécharge et installe les mises à jours des extensions configurées pour être mises à jour automatiquement.",
|
||||
"TaskUpdatePlugins": "Mettre à jour les extensions",
|
||||
"TaskRefreshPeopleDescription": "Met à jour les métadonnées pour les acteurs et réalisateurs dans votre bibliothèque.",
|
||||
"TaskRefreshPeople": "Rafraîchir les acteurs",
|
||||
"TaskRefreshPeopleDescription": "Met à jour les métadonnées pour les acteurs et réalisateurs dans votre médiathèque.",
|
||||
"TaskRefreshPeople": "Actualiser les acteurs",
|
||||
"TaskCleanLogsDescription": "Supprime les journaux de plus de {0} jours.",
|
||||
"TaskCleanLogs": "Nettoyer le répertoire des journaux",
|
||||
"TaskRefreshLibraryDescription": "Scanne votre médiathèque pour trouver les nouveaux fichiers et rafraîchit les métadonnées.",
|
||||
"TaskRefreshLibraryDescription": "Scanne votre médiathèque pour trouver les nouveaux fichiers et actualise les métadonnées.",
|
||||
"TaskRefreshLibrary": "Scanner la médiathèque",
|
||||
"TaskRefreshChapterImagesDescription": "Crée des vignettes pour les vidéos ayant des chapitres.",
|
||||
"TaskRefreshChapterImages": "Extraire les images de chapitre",
|
||||
"TaskCleanCacheDescription": "Supprime les fichiers de cache dont le système n'a plus besoin.",
|
||||
"TaskCleanCache": "Vider le répertoire cache",
|
||||
"TasksApplicationCategory": "Application",
|
||||
"TasksLibraryCategory": "Bibliothèque",
|
||||
"TasksLibraryCategory": "Médiathèque",
|
||||
"TasksMaintenanceCategory": "Maintenance",
|
||||
"TaskCleanActivityLogDescription": "Supprime les entrées du journal d'activité antérieures à l'âge configuré.",
|
||||
"TaskCleanActivityLog": "Nettoyer le journal d'activité",
|
||||
"Undefined": "Non défini",
|
||||
"Forced": "Forcé",
|
||||
"Default": "Par défaut",
|
||||
"TaskOptimizeDatabaseDescription": "Réduit les espaces vides ou inutiles et compacte la base de données. Utiliser cette fonction après une mise à jour de la bibliothèque ou toute autre modification de la base de données peut améliorer les performances du serveur.",
|
||||
"TaskOptimizeDatabaseDescription": "Réduit les espaces vides ou inutiles et compacte la base de données. Utiliser cette fonction après une mise à jour de la médiathèque ou toute autre modification de la base de données peut améliorer les performances du serveur.",
|
||||
"TaskOptimizeDatabase": "Optimiser la base de données",
|
||||
"TaskKeyframeExtractorDescription": "Extrait les images clés des fichiers vidéo pour créer des listes de lecture HLS plus précises. Cette tâche peut durer très longtemps.",
|
||||
"TaskKeyframeExtractor": "Extracteur d'image clé",
|
||||
|
||||
@@ -122,5 +122,6 @@
|
||||
"TaskOptimizeDatabase": "Optimiziraj bazu podataka",
|
||||
"External": "Vanjski",
|
||||
"TaskKeyframeExtractorDescription": "Izvlačenje ključnih okvira iz videozapisa za stvaranje objektivnije HLS liste za reprodukciju. Pokretanje ovog zadatka može potrajati.",
|
||||
"TaskKeyframeExtractor": "Izvoditelj ključnog okvira"
|
||||
"TaskKeyframeExtractor": "Izvoditelj ključnog okvira",
|
||||
"TaskOptimizeDatabaseDescription": "Sažima bazu podataka i uklanja prazan prostor. Pokretanje ovog zadatka, može poboljšati performanse nakon provođenja indeksiranja biblioteke ili provođenja drugih promjena koje utječu na bazu podataka."
|
||||
}
|
||||
|
||||
@@ -120,5 +120,8 @@
|
||||
"Forced": "강제하기",
|
||||
"Default": "기본 설정",
|
||||
"TaskOptimizeDatabaseDescription": "데이터베이스를 압축하고 사용 가능한 공간을 늘립니다. 라이브러리를 검색한 후 이 작업을 실행하거나 데이터베이스 수정같은 비슷한 작업을 수행하면 성능이 향상될 수 있습니다.",
|
||||
"TaskOptimizeDatabase": "데이터베이스 최적화"
|
||||
"TaskOptimizeDatabase": "데이터베이스 최적화",
|
||||
"TaskKeyframeExtractorDescription": "비디오 파일에서 키프레임을 추출하여 더 정확한 HLS 재생 목록을 만듭니다. 이 작업은 오랫동안 진행될 수 있습니다.",
|
||||
"TaskKeyframeExtractor": "키프레임 추출",
|
||||
"External": "외부"
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
"MixedContent": "Mixed content",
|
||||
"Movies": "Filmai",
|
||||
"Music": "Muzika",
|
||||
"MusicVideos": "Muzikiniai klipai",
|
||||
"MusicVideos": "Muzikiniai vaizdo įrašai",
|
||||
"NameInstallFailed": "{0} diegimo klaida",
|
||||
"NameSeasonNumber": "Sezonas {0}",
|
||||
"NameSeasonUnknown": "Sezonas neatpažintas",
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
"CameraImageUploadedFrom": "Jauns kameras attēls ir ticis augšupielādēts no {0}",
|
||||
"Books": "Grāmatas",
|
||||
"Artists": "Izpildītāji",
|
||||
"Albums": "Albumi",
|
||||
"Albums": "Albūmi",
|
||||
"ProviderValue": "Provider: {0}",
|
||||
"HeaderFavoriteSongs": "Dziesmu Favorīti",
|
||||
"HeaderFavoriteShows": "Raidījumu Favorīti",
|
||||
@@ -117,7 +117,8 @@
|
||||
"TaskCleanActivityLogDescription": "Nodzēš darbību žurnāla ierakstus, kuri ir vecāki par doto vecumu.",
|
||||
"TaskCleanActivityLog": "Notīrīt Darbību Žurnālu",
|
||||
"Undefined": "Nenoteikts",
|
||||
"Default": "Noklusējums",
|
||||
"Default": "Noklusējuma",
|
||||
"TaskOptimizeDatabaseDescription": "Saspiež datubāzi un atbrīvo atmiņu. Uzdevum palaišana pēc bibliotēku skenēšanas vai citām, ar datubāzi saistītām, izmaiņām iespējams uzlabos ātrdarbību.",
|
||||
"TaskOptimizeDatabase": "Optimizēt datubāzi"
|
||||
"TaskOptimizeDatabase": "Optimizēt datubāzi",
|
||||
"External": "Ārējais"
|
||||
}
|
||||
|
||||
@@ -64,9 +64,9 @@
|
||||
"CameraImageUploadedFrom": "Нова слика од камера беше поставена од {0}",
|
||||
"Books": "Книги",
|
||||
"AuthenticationSucceededWithUserName": "{0} успешно поврзан",
|
||||
"Artists": "Изведувач",
|
||||
"Artists": "Изведувачи",
|
||||
"Application": "Апликација",
|
||||
"AppDeviceValues": "Аплиакција: {0}, Уред: {1}",
|
||||
"AppDeviceValues": "Апликација: {0}, Уред: {1}",
|
||||
"Albums": "Албуми",
|
||||
"VersionNumber": "Верзија {0}",
|
||||
"ValueSpecialEpisodeName": "Специјално - {0}",
|
||||
@@ -100,5 +100,27 @@
|
||||
"TasksMaintenanceCategory": "Одржување",
|
||||
"Undefined": "Недефинирано",
|
||||
"Forced": "Принудно",
|
||||
"Default": "Зададено"
|
||||
"Default": "Зададено",
|
||||
"TaskKeyframeExtractorDescription": "Извлекува клучни рамки од видео фајлови за да се направат попрецизни HLS плејлисти. Оваа задача може да работи многу долго време.",
|
||||
"TaskKeyframeExtractor": "Извлекувач на клучни рамки",
|
||||
"TaskOptimizeDatabaseDescription": "Компактира датабазата и смалува празното место. Извршувањето на оваа задача по скенирање на библиотеката или правење други промени што прават модификации на датабазата може да подобри перформансите.",
|
||||
"TaskOptimizeDatabase": "Оптимизирај датабаза",
|
||||
"TaskDownloadMissingSubtitlesDescription": "Пребарува интернет за преводи што недостиваат според метадата конфигурација.",
|
||||
"TaskDownloadMissingSubtitles": "Симни преводи што недостигаат",
|
||||
"TaskRefreshChannelsDescription": "Ажурирај информации за интернет канали.",
|
||||
"TaskRefreshChannels": "Ажурирај Канали",
|
||||
"TaskCleanTranscodeDescription": "Избриши транскодирани фајлови постари од еден ден.",
|
||||
"TaskCleanTranscode": "Исчисти Директориум за Транскодирање",
|
||||
"TaskUpdatePluginsDescription": "Симни и инсталирај ажурирања за плагини што се конфигурирани за автоматско ажурирање.",
|
||||
"TaskUpdatePlugins": "Ажурирај Плагини",
|
||||
"TaskRefreshPeopleDescription": "Ажурирај метадата за акери и директори во вашата медиска библиотека.",
|
||||
"TaskRefreshPeople": "Ажурирајте ги Луѓето",
|
||||
"TaskCleanLogsDescription": "Избриши лог фајлови постари од {0} денови.",
|
||||
"TaskCleanLogs": "Избриши Директориум на Логови",
|
||||
"TaskRefreshLibraryDescription": "Скенирајте ја вашата медиска библиотека за нови фајлови и ажурирај метадата.",
|
||||
"TaskRefreshLibrary": "Скенирај Медиумска Библиотека",
|
||||
"TaskRefreshChapterImagesDescription": "Создава тамбнеил за видеата шти имаат поглавја.",
|
||||
"TaskCleanActivityLogDescription": "Избришува логови на активности постари од определеното време.",
|
||||
"TaskCleanActivityLog": "Избриши Лог на Активности",
|
||||
"External": "Надворешен"
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"NotificationOptionVideoPlayback": "Ulangmain video bermula",
|
||||
"NotificationOptionVideoPlaybackStopped": "Ulangmain video dihentikan",
|
||||
"Photos": "Gambar-gambar",
|
||||
"Playlists": "Senarai main",
|
||||
"Playlists": "Senarai ulangmain",
|
||||
"Plugin": "Plugin",
|
||||
"PluginInstalledWithName": "{0} telah dipasang",
|
||||
"PluginUninstalledWithName": "{0} telah dinyahpasang",
|
||||
|
||||
@@ -6,97 +6,97 @@
|
||||
"Artists": "အနုပညာရှင်များ",
|
||||
"Albums": "သီချင်းအခွေများ",
|
||||
"TaskOptimizeDatabaseDescription": "ဒေတာဘေ့စ်ကို ကျစ်လစ်စေပြီး နေရာလွတ်များကို ဖြတ်တောက်ပေးသည်။ စာကြည့်တိုက်ကို စကင်န်ဖတ်ပြီးနောက် ဤလုပ်ငန်းကို လုပ်ဆောင်ခြင်း သို့မဟုတ် ဒေတာဘေ့စ်မွမ်းမံမှုများ စွမ်းဆောင်ရည်ကို မြှင့်တင်ပေးနိုင်သည်ဟု ရည်ညွှန်းသော အခြားပြောင်းလဲမှုများကို လုပ်ဆောင်ခြင်း။.",
|
||||
"TaskOptimizeDatabase": "ဒေတာဘေ့စ်ကို အကောင်းဆုံးဖြစ်အောင်လုပ်ပါ။",
|
||||
"TaskOptimizeDatabase": "ဒေတာဘေ့စ်ကို အကောင်းဆုံးဖြစ်အောင်လုပ်ပါ",
|
||||
"TaskDownloadMissingSubtitlesDescription": "မက်တာဒေတာ ဖွဲ့စည်းမှုပုံစံအပေါ် အခြေခံ၍ ပျောက်ဆုံးနေသော စာတန်းထိုးများအတွက် အင်တာနက်ကို ရှာဖွေသည်။",
|
||||
"TaskDownloadMissingSubtitles": "ပျောက်ဆုံးနေသော စာတန်းထိုးများကို ဒေါင်းလုဒ်လုပ်ပါ။",
|
||||
"TaskDownloadMissingSubtitles": "ပျောက်ဆုံးနေသော စာတန်းထိုးများကို ဒေါင်းလုဒ်လုပ်ပါ",
|
||||
"TaskRefreshChannelsDescription": "အင်တာနက်ချန်နယ်အချက်အလက်ကို ပြန်လည်စတင်သည်။",
|
||||
"TaskRefreshChannels": "ချန်နယ်များကို ပြန်လည်စတင်ပါ။",
|
||||
"TaskRefreshChannels": "ချန်နယ်များကို ပြန်လည်စတင်ပါ",
|
||||
"TaskCleanTranscodeDescription": "သက်တမ်း တစ်ရက်ထက်ပိုသော အသွင်ပြောင်းကုဒ်ဖိုင်များကို ဖျက်ပါ။",
|
||||
"TaskCleanTranscode": "Transcode လမ်းညွှန်ကို သန့်ရှင်းပါ။",
|
||||
"TaskCleanTranscode": "Transcode လမ်းညွှန်ကို သန့်ရှင်းပါ",
|
||||
"TaskUpdatePluginsDescription": "အလိုအလျောက် အပ်ဒိတ်လုပ်ရန် စီစဉ်ထားသော ပလပ်အင်များအတွက် အပ်ဒိတ်များကို ဒေါင်းလုဒ်လုပ်ပြီး ထည့်သွင်းပါ။",
|
||||
"TaskUpdatePlugins": "ပလပ်အင်များကို အပ်ဒိတ်လုပ်ပါ။",
|
||||
"TaskUpdatePlugins": "ပလပ်အင်များကို အပ်ဒိတ်လုပ်ပါ",
|
||||
"TaskRefreshPeopleDescription": "သင့်မီဒီယာစာကြည့်တိုက်ရှိ သရုပ်ဆောင်များနှင့် ဒါရိုက်တာများအတွက် မက်တာဒေတာကို အပ်ဒိတ်လုပ်ပါ။",
|
||||
"TaskRefreshPeople": "လူများကို ပြန်လည်ဆန်းသစ်ပါ။",
|
||||
"TaskRefreshPeople": "လူများကို ပြန်လည်ဆန်းသစ်ပါ",
|
||||
"TaskCleanLogsDescription": "{0} ရက်ထက်ပိုသော မှတ်တမ်းဖိုင်များကို ဖျက်သည်။",
|
||||
"TaskCleanLogs": "မှတ်တမ်းလမ်းညွှန်ကို သန့်ရှင်းပါ။",
|
||||
"TaskCleanLogs": "မှတ်တမ်းလမ်းညွှန်ကို သန့်ရှင်းပါ",
|
||||
"TaskRefreshLibraryDescription": "သင့်မီဒီယာဒစ်ဂျစ်တိုက်ကို ဖိုင်အသစ်များရှိမရှိ စကင်န်ဖတ်ပြီး ဖိုင်ရဲ့အကြောင်းအရာများ ကို ပြန်ပြုပြင်မွမ်းမံပါ။",
|
||||
"TaskRefreshLibrary": "မီဒီယာစာကြည့်တိုက်ကို စကင်န်ဖတ်ပါ။",
|
||||
"TaskRefreshLibrary": "မီဒီယာစာကြည့်တိုက်ကို စကင်န်ဖတ်ပါ",
|
||||
"TaskRefreshChapterImagesDescription": "အခန်းများပါရှိသော ဗီဒီယိုများအတွက် ပုံသေးများကို ဖန်တီးပါ။",
|
||||
"TaskRefreshChapterImages": "အခန်းတစ်ခုစီ ပုံများကို ထုတ်ယူပါ။",
|
||||
"TaskRefreshChapterImages": "အခန်းတစ်ခုစီ ပုံများကို ထုတ်ယူပါ",
|
||||
"TaskCleanCacheDescription": "စနစ်မှ မလိုအပ်တော့သော ကက်ရှ်ဖိုင်များကို ဖျက်ပါ။.",
|
||||
"TaskCleanCache": "Cache Directory ကို ရှင်းပါ။",
|
||||
"TaskCleanCache": "Cache Directory ကို ရှင်းပါ",
|
||||
"TaskCleanActivityLogDescription": "စီစဉ်သတ်မှတ်ထားသော အသက်ထက် ပိုကြီးသော လုပ်ဆောင်ချက်မှတ်တမ်းများကို ဖျက်ပါ။",
|
||||
"TaskCleanActivityLog": "လုပ်ဆောင်ချက်မှတ်တမ်းကို ရှင်းလင်းပါ။",
|
||||
"TaskCleanActivityLog": "လုပ်ဆောင်ချက်မှတ်တမ်းကို ရှင်းလင်းပါ",
|
||||
"TasksChannelsCategory": "အင်တာနက် ချန်နယ်လိုင်းများ",
|
||||
"TasksApplicationCategory": "အပလီကေးရှင်း",
|
||||
"TasksLibraryCategory": "မီဒီယာတိုက်",
|
||||
"TasksMaintenanceCategory": "ပြုပြင် ထိန်းသိမ်းခြင်း",
|
||||
"VersionNumber": "ဗားရှင်း {0}",
|
||||
"ValueSpecialEpisodeName": "အထူး- {0}",
|
||||
"ValueHasBeenAddedToLibrary": "{0} ကို သင့်မီဒီယာဒစ်ဂျစ်တိုက်သို့ ပေါင်းထည့်လိုက်ပါပြီ။",
|
||||
"ValueHasBeenAddedToLibrary": "{0} ကို သင့်မီဒီယာဒစ်ဂျစ်တိုက်သို့ ပေါင်းထည့်လိုက်ပါပြီ",
|
||||
"UserStoppedPlayingItemWithValues": "{0} သည် {1} ကို {2} တွင် ဖွင့်ပြီးပါပြီ",
|
||||
"UserStartedPlayingItemWithValues": "{0} သည် {1} ကို {2} တွင် ပြသနေသည်",
|
||||
"UserPolicyUpdatedWithName": "{0} အတွက် အသုံးပြုသူမူဝါဒကို အပ်ဒိတ်လုပ်ပြီးပါပြီ",
|
||||
"UserPasswordChangedWithName": "အသုံးပြုသူ {0} အတွက် စကားဝှက်ကို ပြောင်းထားသည်",
|
||||
"UserOnlineFromDevice": "{0} သည် {1} မှ အွန်လိုင်းဖြစ်သည်",
|
||||
"UserOfflineFromDevice": "{0} သည် {1} မှ ချိတ်ဆက်မှုပြတ်တောက်သွားသည်",
|
||||
"UserLockedOutWithName": "အသုံးပြုသူ {0} အား လော့ခ်ချထားသည်။",
|
||||
"UserLockedOutWithName": "အသုံးပြုသူ {0} အား လော့ခ်ချထားသည်",
|
||||
"UserDownloadingItemWithValues": "{0} သည် {1} ကို ဒေါင်းလုဒ်လုပ်နေသည်",
|
||||
"UserDeletedWithName": "အသုံးပြုသူ {0} ကို ဖျက်လိုက်ပါပြီ။",
|
||||
"UserCreatedWithName": "အသုံးပြုသူ {0} ကို ဖန်တီးပြီးပါပြီ။",
|
||||
"UserDeletedWithName": "အသုံးပြုသူ {0} ကို ဖျက်လိုက်ပါပြီ",
|
||||
"UserCreatedWithName": "အသုံးပြုသူ {0} ကို ဖန်တီးပြီးပါပြီ",
|
||||
"User": "အသုံးပြုသူ",
|
||||
"Undefined": "သတ်မှတ်မထားသော",
|
||||
"TvShows": "တီဗီ ဇာတ်လမ်းတွဲများ",
|
||||
"System": "စနစ်",
|
||||
"Sync": "ထပ်တူကျသည်။",
|
||||
"SubtitleDownloadFailureFromForItem": "{1} အတွက် {0} မှ စာတန်းထိုးများ ဒေါင်းလုဒ်လုပ်ခြင်း မအောင်မြင်ပါ။",
|
||||
"SubtitleDownloadFailureFromForItem": "{1} အတွက် {0} မှ စာတန်းထိုးများ ဒေါင်းလုဒ်လုပ်ခြင်း မအောင်မြင်ပါ",
|
||||
"StartupEmbyServerIsLoading": "Jellyfin ဆာဗာကို အသင့်ပြင်နေပါသည်။ ခဏနေ ထပ်စမ်းကြည့်ပါ။",
|
||||
"Songs": "သီချင်းများ",
|
||||
"Shows": "ဇာတ်လမ်းတွဲများ",
|
||||
"ServerNameNeedsToBeRestarted": "{0} ကို ပြန်လည်စတင်ရန် လိုအပ်သည်။",
|
||||
"ScheduledTaskStartedWithName": "{0} စတင်ခဲ့သည်။",
|
||||
"ScheduledTaskFailedWithName": "{0} မအောင်မြင်ပါ။",
|
||||
"ServerNameNeedsToBeRestarted": "{0} ကို ပြန်လည်စတင်ရန် လိုအပ်သည်",
|
||||
"ScheduledTaskStartedWithName": "{0} စတင်ခဲ့သည်",
|
||||
"ScheduledTaskFailedWithName": "{0} မအောင်မြင်ပါ",
|
||||
"ProviderValue": "ဝန်ဆောင်မှုပေးသူ- {0}",
|
||||
"PluginUpdatedWithName": "ပလပ်ခ်အင် {0} ကို အပ်ဒိတ်လုပ်ထားသည်။",
|
||||
"PluginUninstalledWithName": "ပလပ်ခ်အင် {0} ကို ဖြုတ်လိုက်ပါပြီ။",
|
||||
"PluginInstalledWithName": "ပလပ်ခ်အင် {0} ကို ထည့်သွင်းခဲ့သည်။",
|
||||
"PluginUpdatedWithName": "ပလပ်ခ်အင် {0} ကို အပ်ဒိတ်လုပ်ထားသည်",
|
||||
"PluginUninstalledWithName": "ပလပ်ခ်အင် {0} ကို ဖြုတ်လိုက်ပါပြီ",
|
||||
"PluginInstalledWithName": "ပလပ်ခ်အင် {0} ကို ထည့်သွင်းခဲ့သည်",
|
||||
"Plugin": "ပလပ်အင်",
|
||||
"Playlists": "အစီအစဉ်များ",
|
||||
"Photos": "ဓာတ်ပုံများ",
|
||||
"NotificationOptionVideoPlaybackStopped": "ဗီဒီယိုဖွင့်ခြင်း ရပ်သွားသည်။",
|
||||
"NotificationOptionVideoPlayback": "ဗီဒီယိုဖွင့်ခြင်း စတင်ပါပြီ။",
|
||||
"NotificationOptionUserLockedOut": "အသုံးပြုသူ ဝင်ရန် တားမြစ်ခံရသည်။",
|
||||
"NotificationOptionVideoPlaybackStopped": "ဗီဒီယိုဖွင့်ခြင်း ရပ်သွားသည်",
|
||||
"NotificationOptionVideoPlayback": "ဗီဒီယိုဖွင့်ခြင်း စတင်ပါပြီ",
|
||||
"NotificationOptionUserLockedOut": "အသုံးပြုသူ ဝင်ရန် တားမြစ်ခံရသည်",
|
||||
"NotificationOptionTaskFailed": "စီစဉ်ထားသော အလုပ်ပျက်ကွက်",
|
||||
"NotificationOptionServerRestartRequired": "ဆာဗာ ပြန်လည်စတင်ရန် လိုအပ်သည်။",
|
||||
"NotificationOptionPluginUpdateInstalled": "ပလပ်အင် အပ်ဒိတ် ထည့်သွင်းပြီးပါပြီ။",
|
||||
"NotificationOptionPluginUninstalled": "ပလပ်အင်ကို ဖြုတ်လိုက်ပါပြီ။",
|
||||
"NotificationOptionPluginInstalled": "ပလပ်အင် ထည့်သွင်းထားသည်။",
|
||||
"NotificationOptionPluginError": "ပလပ်အင် ချို့ယွင်းခြင်း။",
|
||||
"NotificationOptionNewLibraryContent": "အသစ်များ ထပ်ထည့်ထားပါတယ်။",
|
||||
"NotificationOptionInstallationFailed": "ထည့်သွင်းမှု မအောင်မြင်ပါ။",
|
||||
"NotificationOptionCameraImageUploaded": "ကင်မရာမှ ဓာတ်ပုံ အပ်လုဒ် ပြီးပါပြီ။",
|
||||
"NotificationOptionAudioPlaybackStopped": "အသံဖိုင်ဖွင့်ခြင်း ရပ်သွားသည်။",
|
||||
"NotificationOptionAudioPlayback": "အသံဖွင့်ခြင်း စတင်ပါပြီ။",
|
||||
"NotificationOptionApplicationUpdateInstalled": "အပလီကေးရှင်း အပ်ဒိတ်ကို ထည့်သွင်းထားသည်။",
|
||||
"NotificationOptionApplicationUpdateAvailable": "အပလီကေးရှင်း အပ်ဒိတ် ရနိုင်ပါပြီ။",
|
||||
"NotificationOptionServerRestartRequired": "ဆာဗာ ပြန်လည်စတင်ရန် လိုအပ်သည်",
|
||||
"NotificationOptionPluginUpdateInstalled": "ပလပ်အင် အပ်ဒိတ် ထည့်သွင်းပြီးပါပြီ",
|
||||
"NotificationOptionPluginUninstalled": "ပလပ်အင်ကို ဖြုတ်လိုက်ပါပြီ",
|
||||
"NotificationOptionPluginInstalled": "ပလပ်အင် ထည့်သွင်းထားသည်",
|
||||
"NotificationOptionPluginError": "ပလပ်အင် ချို့ယွင်းခြင်း",
|
||||
"NotificationOptionNewLibraryContent": "အသစ်များ ထပ်ထည့်ထားပါတယ်",
|
||||
"NotificationOptionInstallationFailed": "ထည့်သွင်းမှု မအောင်မြင်ပါ",
|
||||
"NotificationOptionCameraImageUploaded": "ကင်မရာမှ ဓာတ်ပုံ အပ်လုဒ် ပြီးပါပြီ",
|
||||
"NotificationOptionAudioPlaybackStopped": "အသံဖိုင်ဖွင့်ခြင်း ရပ်သွားသည်",
|
||||
"NotificationOptionAudioPlayback": "အသံဖွင့်ခြင်း စတင်ပါပြီ",
|
||||
"NotificationOptionApplicationUpdateInstalled": "အပလီကေးရှင်း အပ်ဒိတ်ကို ထည့်သွင်းထားသည်",
|
||||
"NotificationOptionApplicationUpdateAvailable": "အပလီကေးရှင်း အပ်ဒိတ် ရနိုင်ပါပြီ",
|
||||
"NewVersionIsAvailable": "Jellyfin Server ၏ ဗားရှင်းအသစ်ကို ဒေါင်းလုဒ်လုပ်နိုင်ပါပြီ။",
|
||||
"NameSeasonUnknown": "ဇာတ်လမ်းတွဲ အပိုင်းမသိ",
|
||||
"NameSeasonNumber": "ဇာတ်လမ်းတွဲ အပိုင်း {0}",
|
||||
"NameInstallFailed": "{0} ထည့်သွင်းမှု မအောင်မြင်ပါ။",
|
||||
"NameInstallFailed": "{0} ထည့်သွင်းမှု မအောင်မြင်ပါ",
|
||||
"MusicVideos": "ဂီတဗီဒီယိုများ",
|
||||
"Music": "တေးဂီတ",
|
||||
"Movies": "ရုပ်ရှင်များ",
|
||||
"MixedContent": "ရောနှောပါဝင်မှု",
|
||||
"MessageServerConfigurationUpdated": "ဆာဗာဖွဲ့စည်းပုံကို အပ်ဒိတ်လုပ်ပြီးပါပြီ။",
|
||||
"MessageNamedServerConfigurationUpdatedWithValue": "ဆာဗာဖွဲ့စည်းပုံကဏ္ဍ {0} ကို အပ်ဒိတ်လုပ်ပြီးပါပြီ။",
|
||||
"MessageServerConfigurationUpdated": "ဆာဗာဖွဲ့စည်းပုံကို အပ်ဒိတ်လုပ်ပြီးပါပြီ",
|
||||
"MessageNamedServerConfigurationUpdatedWithValue": "ဆာဗာဖွဲ့စည်းပုံကဏ္ဍ {0} ကို အပ်ဒိတ်လုပ်ပြီးပါပြီ",
|
||||
"MessageApplicationUpdatedTo": "Jellyfin ဆာဗာကို {0} သို့ အပ်ဒိတ်လုပ်ထားသည်",
|
||||
"MessageApplicationUpdated": "Jellyfin ဆာဗာကို အပ်ဒိတ်လုပ်ပြီးပါပြီ။",
|
||||
"MessageApplicationUpdated": "Jellyfin ဆာဗာကို အပ်ဒိတ်လုပ်ပြီးပါပြီ",
|
||||
"Latest": "နောက်ဆုံး",
|
||||
"LabelRunningTimeValue": "ကြာချိန် - {0}",
|
||||
"LabelIpAddressValue": "IP လိပ်စာ- {0}",
|
||||
"ItemRemovedWithName": "{0} ကို ဒစ်ဂျစ်တိုက်မှ ဖယ်ရှားခဲ့သည်။",
|
||||
"ItemAddedWithName": "{0} ကို စာကြည့်တိုက်သို့ ထည့်ထားသည်။",
|
||||
"Inherit": "ဆက်ခံ၍ လုပ်ဆောင်သည်။",
|
||||
"ItemRemovedWithName": "{0} ကို ဒစ်ဂျစ်တိုက်မှ ဖယ်ရှားခဲ့သည်",
|
||||
"ItemAddedWithName": "{0} ကို စာကြည့်တိုက်သို့ ထည့်ထားသည်",
|
||||
"Inherit": "ဆက်ခံ၍ လုပ်ဆောင်သည်",
|
||||
"HomeVideos": "ကိုယ်တိုင်ရိုက် ဗီဒီယိုများ",
|
||||
"HeaderRecordingGroups": "အသံဖမ်းအဖွဲ့များ",
|
||||
"HeaderNextUp": "နောက်ထပ်",
|
||||
@@ -106,18 +106,18 @@
|
||||
"HeaderFavoriteEpisodes": "အကြိုက်ဆုံး ဇာတ်လမ်းအပိုင်းများ",
|
||||
"HeaderFavoriteArtists": "အကြိုက်ဆုံးအနုပညာရှင်များ",
|
||||
"HeaderFavoriteAlbums": "အကြိုက်ဆုံး အယ်လ်ဘမ်များ",
|
||||
"HeaderContinueWatching": "ဆက်လက်ကြည့်ရှုပါ။",
|
||||
"HeaderContinueWatching": "ဆက်လက်ကြည့်ရှုပါ",
|
||||
"HeaderAlbumArtists": "အယ်လ်ဘမ်အနုပညာရှင်များ",
|
||||
"Genres": "အမျိုးအစားများ",
|
||||
"Forced": "အတင်းအကြပ်",
|
||||
"Folders": "ဖိုလ်ဒါများ",
|
||||
"Favorites": "အကြိုက်ဆုံးများ",
|
||||
"FailedLoginAttemptWithUserName": "{0} မှ အကောင့်ဝင်ရန် မအောင်မြင်ပါ",
|
||||
"DeviceOnlineWithName": "{0} ကို ချိတ်ဆက်ထားသည်။",
|
||||
"DeviceOfflineWithName": "{0} နှင့် အဆက်ပြတ်သွားပါပြီ။",
|
||||
"DeviceOnlineWithName": "{0} ကို ချိတ်ဆက်ထားသည်",
|
||||
"DeviceOfflineWithName": "{0} နှင့် အဆက်ပြတ်သွားပါပြီ",
|
||||
"ChapterNameValue": "အခန်း {0}",
|
||||
"CameraImageUploadedFrom": "ကင်မရာပုံအသစ်ကို {0} မှ ထည့်သွင်းလိုက်သည်။",
|
||||
"AuthenticationSucceededWithUserName": "{0} စစ်မှန်ကြောင်း အောင်မြင်စွာ အတည်ပြုပြီးပါပြီ။",
|
||||
"CameraImageUploadedFrom": "ကင်မရာပုံအသစ်ကို {0} မှ ထည့်သွင်းလိုက်သည်",
|
||||
"AuthenticationSucceededWithUserName": "{0} အောင်မြင်စွာ စစ်မှန်ကြောင်း အတည်ပြုပြီးပါပြီ",
|
||||
"Application": "အပလီကေးရှင်း",
|
||||
"AppDeviceValues": "အက်ပ်- {0}၊ စက်- {1}",
|
||||
"External": "ပြင်ပ"
|
||||
|
||||
@@ -8,15 +8,15 @@
|
||||
"CameraImageUploadedFrom": "Uma nova imagem de câmara foi enviada a partir de {0}",
|
||||
"Channels": "Canais",
|
||||
"ChapterNameValue": "Capítulo {0}",
|
||||
"Collections": "Coleções",
|
||||
"Collections": "Colecçõ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",
|
||||
"HeaderAlbumArtists": "Artistas do álbum",
|
||||
"HeaderContinueWatching": "Continuar a ver",
|
||||
"HeaderFavoriteAlbums": "Álbuns Favoritos",
|
||||
"HeaderFavoriteArtists": "Artistas Favoritos",
|
||||
"HeaderFavoriteEpisodes": "Episódios Favoritos",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"HeaderLiveTV": "TV Ao Vivo",
|
||||
"HeaderLiveTV": "TV Em Direto",
|
||||
"Collections": "Coleções",
|
||||
"Books": "Livros",
|
||||
"Artists": "Artistas",
|
||||
@@ -10,9 +10,9 @@
|
||||
"HeaderFavoriteAlbums": "Álbuns Favoritos",
|
||||
"HeaderFavoriteEpisodes": "Episódios Favoritos",
|
||||
"HeaderFavoriteShows": "Séries Favoritas",
|
||||
"HeaderContinueWatching": "Continuar assistindo",
|
||||
"HeaderContinueWatching": "Continuar a ver",
|
||||
"HeaderAlbumArtists": "Artistas do Álbum",
|
||||
"Genres": "Gêneros",
|
||||
"Genres": "Géneros",
|
||||
"Folders": "Diretórios",
|
||||
"Favorites": "Favoritos",
|
||||
"Channels": "Canais",
|
||||
@@ -74,7 +74,7 @@
|
||||
"ItemRemovedWithName": "{0} foi removido da biblioteca",
|
||||
"ItemAddedWithName": "{0} foi adicionado à biblioteca",
|
||||
"Inherit": "Herdar",
|
||||
"HomeVideos": "Vídeos principais",
|
||||
"HomeVideos": "Vídeos Caseiros",
|
||||
"HeaderRecordingGroups": "Grupos de Gravação",
|
||||
"ValueSpecialEpisodeName": "Episódio Especial - {0}",
|
||||
"Sync": "Sincronização",
|
||||
@@ -83,14 +83,14 @@
|
||||
"Playlists": "Listas de Reprodução",
|
||||
"Photos": "Fotografias",
|
||||
"Movies": "Filmes",
|
||||
"FailedLoginAttemptWithUserName": "Tentativa falha de login a partir de {0}",
|
||||
"DeviceOnlineWithName": "{0} está conectado",
|
||||
"DeviceOfflineWithName": "{0} desconectou-se",
|
||||
"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": "Aplicativo",
|
||||
"AppDeviceValues": "Aplicativo {0}, Dispositivo: {1}",
|
||||
"Application": "Aplicação",
|
||||
"AppDeviceValues": "Aplicação: {0}, Dispositivo: {1}",
|
||||
"TaskCleanCache": "Limpar Diretório de Cache",
|
||||
"TasksApplicationCategory": "Aplicativo",
|
||||
"TasksLibraryCategory": "Biblioteca",
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
"UserStartedPlayingItemWithValues": "{0} predvaja {1} na {2}",
|
||||
"UserStoppedPlayingItemWithValues": "{0} je nehal predvajati {1} na {2}",
|
||||
"ValueHasBeenAddedToLibrary": "{0} je bil dodan vaši knjižnici",
|
||||
"ValueSpecialEpisodeName": "Bonus - {0}",
|
||||
"ValueSpecialEpisodeName": "Posebna epizoda - {0}",
|
||||
"VersionNumber": "Različica {0}",
|
||||
"TaskDownloadMissingSubtitles": "Prenesi manjkajoče podnapise",
|
||||
"TaskRefreshChannelsDescription": "Osveži podatke spletnih kanalov.",
|
||||
@@ -122,5 +122,6 @@
|
||||
"TaskOptimizeDatabaseDescription": "Stisne bazo podatkov in uredi prazen prostor. Zagon tega opravila po iskanju predstavnosti ali drugih spremembah ki vplivajo na bazo podatkov lahko izboljša hitrost delovanja.",
|
||||
"TaskOptimizeDatabase": "Optimiziraj bazo podatkov",
|
||||
"TaskKeyframeExtractor": "Ekstraktor ključnih sličic",
|
||||
"External": "Zunanje"
|
||||
"External": "Zunanji",
|
||||
"TaskKeyframeExtractorDescription": "Iz video datoteke Izvleče ključne sličice, da ustvari bolj natančne sezname predvajanja HLS. Proces lahko traja dolgo časa."
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
"Channels": "Канали",
|
||||
"CameraImageUploadedFrom": "Нова фотографија је учитана са {0}",
|
||||
"Books": "Књиге",
|
||||
"AuthenticationSucceededWithUserName": "{0} Успешна аутентикација",
|
||||
"AuthenticationSucceededWithUserName": "{0} Успешна аутентификација",
|
||||
"Artists": "Извођачи",
|
||||
"Application": "Апликација",
|
||||
"AppDeviceValues": "Апликација: {0}, Уређај: {1}",
|
||||
@@ -118,7 +118,9 @@
|
||||
"Undefined": "Недефинисано",
|
||||
"Forced": "Принудно",
|
||||
"Default": "Подразумевано",
|
||||
"TaskOptimizeDatabase": "Оптимизуј датабазу",
|
||||
"TaskOptimizeDatabase": "Оптимизуј банку података",
|
||||
"TaskOptimizeDatabaseDescription": "Сажима базу података и скраћује слободан простор. Покретање овог задатка након скенирања библиотеке или других промена које подразумевају измене базе података које могу побољшати перформансе.",
|
||||
"External": "Спољно"
|
||||
"External": "Спољно",
|
||||
"TaskKeyframeExtractorDescription": "Екстрактује кљулне сличице из видео датотека да би креирао више преицзну HLS плеј-листу. Овај задатак може да потраје дуже време.",
|
||||
"TaskKeyframeExtractor": "Екстрактор кључних сличица"
|
||||
}
|
||||
|
||||
@@ -3,7 +3,16 @@
|
||||
"Channels": "قانال",
|
||||
"CameraImageUploadedFrom": "{0} ئورۇندىن يېڭى سۈرەت چىقىرىلدى",
|
||||
"Books": "كىتاب",
|
||||
"AuthenticationSucceededWithUserName": "تىزىملىتىش مۇۋەپپەقىيەتلىك بول",
|
||||
"AuthenticationSucceededWithUserName": "{0} تەستىقلاش مۇۋاپىقىيەتلىك بولدى",
|
||||
"Artists": "سەنئەتكار",
|
||||
"Albums": "پىلاستىنكا"
|
||||
"Albums": "پىلاستىنكا",
|
||||
"DeviceOnlineWithName": "{0} ئۇلاندى",
|
||||
"DeviceOfflineWithName": "{0} ئۈزۈلدى",
|
||||
"Collections": "توپلام",
|
||||
"Application": "ئەپ",
|
||||
"AppDeviceValues": "ئەپ: {0}، ئۈسكۈنە: {1}",
|
||||
"HeaderLiveTV": "تور تېلېۋىزىيەسى",
|
||||
"Default": "سۈكۈتتىكى",
|
||||
"Folders": "ھۆججەت خالتىسى",
|
||||
"Favorites": "ساقلىغۇچ"
|
||||
}
|
||||
|
||||
@@ -120,5 +120,8 @@
|
||||
"Default": "預設",
|
||||
"TaskOptimizeDatabaseDescription": "壓縮數據庫並截斷可用空間。在掃描媒體庫或執行其他數據庫的修改後運行此任務可能會提高性能。",
|
||||
"TaskOptimizeDatabase": "最佳化數據庫",
|
||||
"TaskCleanActivityLogDescription": "刪除早於設定時間的日誌記錄。"
|
||||
"TaskCleanActivityLogDescription": "刪除早於設定時間的日誌記錄。",
|
||||
"TaskKeyframeExtractorDescription": "提取關鍵格以創建更準確的HLS播放列表。次指示可能用時很長。",
|
||||
"TaskKeyframeExtractor": "關鍵幀提取器",
|
||||
"External": "外部"
|
||||
}
|
||||
|
||||
10
Emby.Server.Implementations/Localization/Ratings/fi.csv
Normal file
10
Emby.Server.Implementations/Localization/Ratings/fi.csv
Normal file
@@ -0,0 +1,10 @@
|
||||
FI-S,1
|
||||
FI-T,1
|
||||
FI-7,4
|
||||
FI-12,5
|
||||
FI-16,8
|
||||
FI-18,9
|
||||
FI-K7,4
|
||||
FI-K12,5
|
||||
FI-K16,8
|
||||
FI-K18,9
|
||||
|
6
Emby.Server.Implementations/Localization/Ratings/no.csv
Normal file
6
Emby.Server.Implementations/Localization/Ratings/no.csv
Normal file
@@ -0,0 +1,6 @@
|
||||
NO-A,1
|
||||
NO-6,3
|
||||
NO-9,4
|
||||
NO-12,5
|
||||
NO-15,8
|
||||
NO-18,9
|
||||
|
5
Emby.Server.Implementations/Localization/Ratings/se.csv
Normal file
5
Emby.Server.Implementations/Localization/Ratings/se.csv
Normal file
@@ -0,0 +1,5 @@
|
||||
SE-Btl,1
|
||||
SE-Barntillåten,1
|
||||
SE-7,3
|
||||
SE-11,5
|
||||
SE-15,8
|
||||
|
@@ -96,7 +96,7 @@ namespace Emby.Server.Implementations.Net
|
||||
}
|
||||
else
|
||||
{
|
||||
tcs.TrySetException(new Exception("SocketError: " + e.SocketError));
|
||||
tcs.TrySetException(new SocketException((int)e.SocketError));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -114,7 +114,7 @@ namespace Emby.Server.Implementations.Net
|
||||
}
|
||||
else
|
||||
{
|
||||
tcs.TrySetException(new Exception("SocketError: " + e.SocketError));
|
||||
tcs.TrySetException(new SocketException((int)e.SocketError));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1242,7 +1242,7 @@ namespace Emby.Server.Implementations.Session
|
||||
|
||||
if (item == null)
|
||||
{
|
||||
_logger.LogError("A non-existant item Id {0} was passed into TranslateItemForPlayback", id);
|
||||
_logger.LogError("A non-existent item Id {0} was passed into TranslateItemForPlayback", id);
|
||||
return Array.Empty<BaseItem>();
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ using System.Linq;
|
||||
using System.Net.WebSockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Controller.Net;
|
||||
using MediaBrowser.Controller.Session;
|
||||
using MediaBrowser.Model.Net;
|
||||
@@ -37,7 +36,7 @@ namespace Emby.Server.Implementations.Session
|
||||
private const float ForceKeepAliveFactor = 0.75f;
|
||||
|
||||
/// <summary>
|
||||
/// Lock used for accesing the KeepAlive cancellation token.
|
||||
/// Lock used for accessing the KeepAlive cancellation token.
|
||||
/// </summary>
|
||||
private readonly object _keepAliveLock = new object();
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Emby.Server.Implementations.Session
|
||||
{
|
||||
public sealed class WebSocketController : ISessionController, IDisposable
|
||||
public sealed class WebSocketController : ISessionController, IAsyncDisposable, IDisposable
|
||||
{
|
||||
private readonly ILogger<WebSocketController> _logger;
|
||||
private readonly ISessionManager _sessionManager;
|
||||
@@ -99,6 +99,23 @@ namespace Emby.Server.Implementations.Session
|
||||
foreach (var socket in _sockets)
|
||||
{
|
||||
socket.Closed -= OnConnectionClosed;
|
||||
socket.Dispose();
|
||||
}
|
||||
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var socket in _sockets)
|
||||
{
|
||||
socket.Closed -= OnConnectionClosed;
|
||||
await socket.DisposeAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
_disposed = true;
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Jellyfin.Extensions;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Sorting;
|
||||
|
||||
@@ -43,9 +43,9 @@ namespace Emby.Server.Implementations.TV
|
||||
}
|
||||
|
||||
string presentationUniqueKey = null;
|
||||
if (!string.IsNullOrEmpty(query.SeriesId))
|
||||
if (query.SeriesId.HasValue && !query.SeriesId.Value.Equals(default))
|
||||
{
|
||||
if (_libraryManager.GetItemById(query.SeriesId) is Series series)
|
||||
if (_libraryManager.GetItemById(query.SeriesId.Value) is Series series)
|
||||
{
|
||||
presentationUniqueKey = GetUniqueSeriesKey(series);
|
||||
}
|
||||
@@ -93,9 +93,9 @@ namespace Emby.Server.Implementations.TV
|
||||
|
||||
string presentationUniqueKey = null;
|
||||
int? limit = null;
|
||||
if (!string.IsNullOrEmpty(request.SeriesId))
|
||||
if (request.SeriesId.HasValue && !request.SeriesId.Value.Equals(default))
|
||||
{
|
||||
if (_libraryManager.GetItemById(request.SeriesId) is Series series)
|
||||
if (_libraryManager.GetItemById(request.SeriesId.Value) is Series series)
|
||||
{
|
||||
presentationUniqueKey = GetUniqueSeriesKey(series);
|
||||
limit = 1;
|
||||
@@ -135,25 +135,20 @@ namespace Emby.Server.Implementations.TV
|
||||
return GetResult(episodes, request);
|
||||
}
|
||||
|
||||
public IEnumerable<Episode> GetNextUpEpisodes(NextUpQuery request, User user, IReadOnlyList<string> seriesKeys, DtoOptions dtoOptions)
|
||||
private IEnumerable<Episode> GetNextUpEpisodes(NextUpQuery request, User user, IReadOnlyList<string> seriesKeys, DtoOptions dtoOptions)
|
||||
{
|
||||
// Avoid implicitly captured closure
|
||||
var currentUser = user;
|
||||
|
||||
var allNextUp = seriesKeys
|
||||
.Select(i => GetNextUp(i, currentUser, dtoOptions, false));
|
||||
var allNextUp = seriesKeys.Select(i => GetNextUp(i, user, dtoOptions, false));
|
||||
|
||||
if (request.EnableRewatching)
|
||||
{
|
||||
allNextUp = allNextUp.Concat(
|
||||
seriesKeys.Select(i => GetNextUp(i, currentUser, dtoOptions, true))
|
||||
)
|
||||
.OrderByDescending(i => i.Item1);
|
||||
seriesKeys.Select(i => GetNextUp(i, user, dtoOptions, true)))
|
||||
.OrderByDescending(i => i.LastWatchedDate);
|
||||
}
|
||||
|
||||
// If viewing all next up for all series, remove first episodes
|
||||
// But if that returns empty, keep those first episodes (avoid completely empty view)
|
||||
var alwaysEnableFirstEpisode = !string.IsNullOrEmpty(request.SeriesId);
|
||||
var alwaysEnableFirstEpisode = request.SeriesId.HasValue && !request.SeriesId.Value.Equals(default);
|
||||
var anyFound = false;
|
||||
|
||||
return allNextUp
|
||||
@@ -161,23 +156,18 @@ namespace Emby.Server.Implementations.TV
|
||||
{
|
||||
if (request.DisableFirstEpisode)
|
||||
{
|
||||
return i.Item1 != DateTime.MinValue;
|
||||
return i.LastWatchedDate != DateTime.MinValue;
|
||||
}
|
||||
|
||||
if (alwaysEnableFirstEpisode || (i.Item1 != DateTime.MinValue && i.Item1.Date >= request.NextUpDateCutoff))
|
||||
if (alwaysEnableFirstEpisode || (i.LastWatchedDate != DateTime.MinValue && i.LastWatchedDate.Date >= request.NextUpDateCutoff))
|
||||
{
|
||||
anyFound = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!anyFound && i.Item1 == DateTime.MinValue)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return !anyFound && i.LastWatchedDate == DateTime.MinValue;
|
||||
})
|
||||
.Select(i => i.Item2())
|
||||
.Select(i => i.GetEpisodeFunction())
|
||||
.Where(i => i != null);
|
||||
}
|
||||
|
||||
@@ -195,14 +185,14 @@ namespace Emby.Server.Implementations.TV
|
||||
/// Gets the next up.
|
||||
/// </summary>
|
||||
/// <returns>Task{Episode}.</returns>
|
||||
private Tuple<DateTime, Func<Episode>> GetNextUp(string seriesKey, User user, DtoOptions dtoOptions, bool rewatching)
|
||||
private (DateTime LastWatchedDate, Func<Episode> GetEpisodeFunction) GetNextUp(string seriesKey, User user, DtoOptions dtoOptions, bool rewatching)
|
||||
{
|
||||
var lastQuery = new InternalItemsQuery(user)
|
||||
{
|
||||
AncestorWithPresentationUniqueKey = null,
|
||||
SeriesPresentationUniqueKey = seriesKey,
|
||||
IncludeItemTypes = new[] { BaseItemKind.Episode },
|
||||
OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Descending) },
|
||||
OrderBy = new[] { (ItemSortBy.ParentIndexNumber, SortOrder.Descending), (ItemSortBy.IndexNumber, SortOrder.Descending) },
|
||||
IsPlayed = true,
|
||||
Limit = 1,
|
||||
ParentIndexNumberNotEquals = 0,
|
||||
@@ -216,24 +206,23 @@ namespace Emby.Server.Implementations.TV
|
||||
if (rewatching)
|
||||
{
|
||||
// find last watched by date played, not by newest episode watched
|
||||
lastQuery.OrderBy = new[] { (ItemSortBy.DatePlayed, SortOrder.Descending) };
|
||||
lastQuery.OrderBy = new[] { (ItemSortBy.DatePlayed, SortOrder.Descending), (ItemSortBy.ParentIndexNumber, SortOrder.Descending), (ItemSortBy.IndexNumber, SortOrder.Descending) };
|
||||
}
|
||||
|
||||
var lastWatchedEpisode = _libraryManager.GetItemList(lastQuery).Cast<Episode>().FirstOrDefault();
|
||||
|
||||
Func<Episode> getEpisode = () =>
|
||||
Episode GetEpisode()
|
||||
{
|
||||
var nextQuery = new InternalItemsQuery(user)
|
||||
{
|
||||
AncestorWithPresentationUniqueKey = null,
|
||||
SeriesPresentationUniqueKey = seriesKey,
|
||||
IncludeItemTypes = new[] { BaseItemKind.Episode },
|
||||
OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Ascending) },
|
||||
OrderBy = new[] { (ItemSortBy.ParentIndexNumber, SortOrder.Ascending), (ItemSortBy.IndexNumber, SortOrder.Ascending) },
|
||||
Limit = 1,
|
||||
IsPlayed = rewatching,
|
||||
IsVirtualItem = false,
|
||||
ParentIndexNumberNotEquals = 0,
|
||||
MinSortName = lastWatchedEpisode?.SortName,
|
||||
DtoOptions = dtoOptions
|
||||
};
|
||||
|
||||
@@ -297,7 +286,7 @@ namespace Emby.Server.Implementations.TV
|
||||
}
|
||||
|
||||
return nextEpisode;
|
||||
};
|
||||
}
|
||||
|
||||
if (lastWatchedEpisode != null)
|
||||
{
|
||||
@@ -305,11 +294,11 @@ namespace Emby.Server.Implementations.TV
|
||||
|
||||
var lastWatchedDate = userData.LastPlayedDate ?? DateTime.MinValue.AddDays(1);
|
||||
|
||||
return new Tuple<DateTime, Func<Episode>>(lastWatchedDate, getEpisode);
|
||||
return (lastWatchedDate, GetEpisode);
|
||||
}
|
||||
|
||||
// Return the first episode
|
||||
return new Tuple<DateTime, Func<Episode>>(DateTime.MinValue, getEpisode);
|
||||
return (DateTime.MinValue, GetEpisode);
|
||||
}
|
||||
|
||||
private static QueryResult<BaseItem> GetResult(IEnumerable<BaseItem> items, NextUpQuery query)
|
||||
|
||||
Reference in New Issue
Block a user