Merge remote-tracking branch 'upstream/release-10.2.z' into newmaser

pull/925/head
Bond-009 5 years ago
commit a35ea49c99

@ -18,6 +18,7 @@
- [dkanada](https://github.com/dkanada) - [dkanada](https://github.com/dkanada)
- [LogicalPhallacy](https://github.com/LogicalPhallacy/) - [LogicalPhallacy](https://github.com/LogicalPhallacy/)
- [RazeLighter777](https://github.com/RazeLighter777) - [RazeLighter777](https://github.com/RazeLighter777)
- [WillWill56](https://github.com/WillWill56)
# Emby Contributors # Emby Contributors

@ -3,9 +3,8 @@ ARG DOTNET_VERSION=2
FROM microsoft/dotnet:${DOTNET_VERSION}-sdk as builder FROM microsoft/dotnet:${DOTNET_VERSION}-sdk as builder
WORKDIR /repo WORKDIR /repo
COPY . . COPY . .
RUN export DOTNET_CLI_TELEMETRY_OPTOUT=1 \ ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
&& dotnet clean \ RUN dotnet publish \
&& dotnet publish \
--configuration release \ --configuration release \
--output /jellyfin \ --output /jellyfin \
Jellyfin.Server Jellyfin.Server
@ -18,9 +17,11 @@ RUN apt-get update \
libfontconfig1 \ libfontconfig1 \
&& apt-get clean autoclean \ && apt-get clean autoclean \
&& apt-get autoremove \ && apt-get autoremove \
&& rm -rf /var/lib/{apt,dpkg,cache,log} && rm -rf /var/lib/{apt,dpkg,cache,log} \
&& mkdir -p /cache /config /media \
&& chmod 777 /cache /config /media
COPY --from=ffmpeg / / COPY --from=ffmpeg / /
COPY --from=builder /jellyfin /jellyfin COPY --from=builder /jellyfin /jellyfin
EXPOSE 8096 EXPOSE 8096
VOLUME /config /media VOLUME /cache /config /media
ENTRYPOINT dotnet /jellyfin/jellyfin.dll --datadir /config ENTRYPOINT dotnet /jellyfin/jellyfin.dll --datadir /config --cachedir /cache

@ -1,24 +1,36 @@
# Requires binfm_misc registration
# https://github.com/multiarch/qemu-user-static#binfmt_misc-register
ARG DOTNET_VERSION=3.0 ARG DOTNET_VERSION=3.0
FROM microsoft/dotnet:${DOTNET_VERSION}-sdk-stretch-arm32v7 as builder FROM multiarch/qemu-user-static:x86_64-arm as qemu
FROM alpine as qemu_extract
COPY --from=qemu /usr/bin qemu-arm-static.tar.gz
RUN tar -xzvf qemu-arm-static.tar.gz
FROM microsoft/dotnet:${DOTNET_VERSION}-sdk-stretch as builder
WORKDIR /repo WORKDIR /repo
COPY . . COPY . .
ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
# TODO Remove or update the sed line when we update dotnet version. # TODO Remove or update the sed line when we update dotnet version.
RUN export DOTNET_CLI_TELEMETRY_OPTOUT=1 \ RUN find . -type f -exec sed -i 's/netcoreapp2.1/netcoreapp3.0/g' {} \;
&& find . -type f -exec sed -i 's/netcoreapp2.1/netcoreapp3.0/g' {} \; \ # Discard objs - may cause failures if exists
&& dotnet clean -maxcpucount:1 \ RUN find . -type d -name obj | xargs -r rm -r
&& dotnet publish \ # Build
-maxcpucount:1 \ RUN dotnet publish \
-r linux-arm \
--configuration release \ --configuration release \
--output /jellyfin \ --output /jellyfin \
Jellyfin.Server Jellyfin.Server
FROM microsoft/dotnet:${DOTNET_VERSION}-runtime-stretch-slim-arm32v7 FROM microsoft/dotnet:${DOTNET_VERSION}-runtime-stretch-slim-arm32v7
COPY --from=qemu_extract qemu-arm-static /usr/bin
RUN apt-get update \ RUN apt-get update \
&& apt-get install -y ffmpeg && apt-get install --no-install-recommends --no-install-suggests -y ffmpeg \
&& mkdir -p /cache /config /media \
&& chmod 777 /cache /config /media
COPY --from=builder /jellyfin /jellyfin COPY --from=builder /jellyfin /jellyfin
EXPOSE 8096 EXPOSE 8096
VOLUME /config /media VOLUME /cache /config /media
ENTRYPOINT dotnet /jellyfin/jellyfin.dll --datadir /config ENTRYPOINT dotnet /jellyfin/jellyfin.dll --datadir /config --cachedir /cache

@ -1,33 +1,37 @@
# Requires binfm_misc registration for aarch64 # Requires binfm_misc registration
# https://github.com/multiarch/qemu-user-static#binfmt_misc-register # https://github.com/multiarch/qemu-user-static#binfmt_misc-register
ARG DOTNET_VERSION=3.0 ARG DOTNET_VERSION=3.0
FROM multiarch/qemu-user-static:x86_64-aarch64 as qemu FROM multiarch/qemu-user-static:x86_64-aarch64 as qemu
FROM alpine as qemu_extract FROM alpine as qemu_extract
COPY --from=qemu /usr/bin qemu_user_static.tgz COPY --from=qemu /usr/bin qemu-aarch64-static.tar.gz
RUN tar -xzvf qemu_user_static.tgz RUN tar -xzvf qemu-aarch64-static.tar.gz
FROM microsoft/dotnet:${DOTNET_VERSION}-sdk-stretch-arm64v8 as builder FROM microsoft/dotnet:${DOTNET_VERSION}-sdk-stretch as builder
COPY --from=qemu_extract qemu-* /usr/bin
WORKDIR /repo WORKDIR /repo
COPY . . COPY . .
ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
# TODO Remove or update the sed line when we update dotnet version. # TODO Remove or update the sed line when we update dotnet version.
RUN export DOTNET_CLI_TELEMETRY_OPTOUT=1 \ RUN find . -type f -exec sed -i 's/netcoreapp2.1/netcoreapp3.0/g' {} \;
&& find . -type f -exec sed -i 's/netcoreapp2.1/netcoreapp3.0/g' {} \; \ # Discard objs - may cause failures if exists
&& dotnet clean \ RUN find . -type d -name obj | xargs -r rm -r
&& dotnet publish \ # Build
RUN dotnet publish \
-r linux-arm64 \
--configuration release \ --configuration release \
--output /jellyfin \ --output /jellyfin \
Jellyfin.Server Jellyfin.Server
FROM microsoft/dotnet:${DOTNET_VERSION}-runtime-stretch-slim-arm64v8 FROM microsoft/dotnet:${DOTNET_VERSION}-runtime-stretch-slim-arm64v8
COPY --from=qemu_extract qemu-aarch64-static /usr/bin
RUN apt-get update \ RUN apt-get update \
&& apt-get install -y ffmpeg && apt-get install --no-install-recommends --no-install-suggests -y ffmpeg \
COPY --from=qemu_extract qemu-* /usr/bin && mkdir -p /cache /config /media \
&& chmod 777 /cache /config /media
COPY --from=builder /jellyfin /jellyfin COPY --from=builder /jellyfin /jellyfin
EXPOSE 8096 EXPOSE 8096
VOLUME /config /media VOLUME /cache /config /media
ENTRYPOINT dotnet /jellyfin/jellyfin.dll --datadir /config ENTRYPOINT dotnet /jellyfin/jellyfin.dll --datadir /config --cachedir /cache

@ -89,11 +89,6 @@ namespace Emby.Dlna.PlayTo
return; return;
} }
if (_sessionManager.Sessions.Any(i => usn.IndexOf(i.DeviceId, StringComparison.OrdinalIgnoreCase) != -1))
{
return;
}
var cancellationToken = _disposeCancellationTokenSource.Token; var cancellationToken = _disposeCancellationTokenSource.Token;
await _sessionLock.WaitAsync(cancellationToken).ConfigureAwait(false); await _sessionLock.WaitAsync(cancellationToken).ConfigureAwait(false);
@ -105,6 +100,11 @@ namespace Emby.Dlna.PlayTo
return; return;
} }
if (_sessionManager.Sessions.Any(i => usn.IndexOf(i.DeviceId, StringComparison.OrdinalIgnoreCase) != -1))
{
return;
}
await AddDevice(info, location, cancellationToken).ConfigureAwait(false); await AddDevice(info, location, cancellationToken).ConfigureAwait(false);
} }
catch (OperationCanceledException) catch (OperationCanceledException)

@ -665,7 +665,7 @@ namespace Emby.Server.Implementations
SocketFactory = new SocketFactory(); SocketFactory = new SocketFactory();
serviceCollection.AddSingleton(SocketFactory); serviceCollection.AddSingleton(SocketFactory);
InstallationManager = new InstallationManager(LoggerFactory, this, ApplicationPaths, HttpClient, JsonSerializer, ServerConfigurationManager, FileSystemManager, CryptographyProvider, PackageRuntime); InstallationManager = new InstallationManager(LoggerFactory, this, ApplicationPaths, HttpClient, JsonSerializer, ServerConfigurationManager, FileSystemManager, CryptographyProvider, ZipClient, PackageRuntime);
serviceCollection.AddSingleton(InstallationManager); serviceCollection.AddSingleton(InstallationManager);
ZipClient = new ZipClient(FileSystemManager); ZipClient = new ZipClient(FileSystemManager);

@ -66,11 +66,6 @@ namespace Emby.Server.Implementations.HttpClientManager
// http://stackoverflow.com/questions/566437/http-post-returns-the-error-417-expectation-failed-c // http://stackoverflow.com/questions/566437/http-post-returns-the-error-417-expectation-failed-c
ServicePointManager.Expect100Continue = false; ServicePointManager.Expect100Continue = false;
#if NET46
// Trakt requests sometimes fail without this
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls;
#endif
} }
/// <summary> /// <summary>
@ -106,23 +101,6 @@ namespace Emby.Server.Implementations.HttpClientManager
return client; return client;
} }
private static WebRequest CreateWebRequest(string url)
{
try
{
return WebRequest.Create(url);
}
catch (NotSupportedException)
{
//Webrequest creation does fail on MONO randomly when using WebRequest.Create
//the issue occurs in the GetCreator method here: http://www.oschina.net/code/explore/mono-2.8.1/mcs/class/System/System.Net/WebRequest.cs
var type = Type.GetType("System.Net.HttpRequestCreator, System, Version=4.0.0.0,Culture=neutral, PublicKeyToken=b77a5c561934e089");
var creator = Activator.CreateInstance(type, nonPublic: true) as IWebRequestCreate;
return creator.Create(new Uri(url)) as HttpWebRequest;
}
}
private WebRequest GetRequest(HttpRequestOptions options, string method) private WebRequest GetRequest(HttpRequestOptions options, string method)
{ {
string url = options.Url; string url = options.Url;
@ -135,7 +113,7 @@ namespace Emby.Server.Implementations.HttpClientManager
url = url.Replace(userInfo + "@", string.Empty); url = url.Replace(userInfo + "@", string.Empty);
} }
var request = CreateWebRequest(url); var request = WebRequest.Create(url);
if (request is HttpWebRequest httpWebRequest) if (request is HttpWebRequest httpWebRequest)
{ {
@ -627,7 +605,8 @@ namespace Emby.Server.Implementations.HttpClientManager
var exception = new HttpException(webException.Message, webException); var exception = new HttpException(webException.Message, webException);
var response = webException.Response as HttpWebResponse; using (var response = webException.Response as HttpWebResponse)
{
if (response != null) if (response != null)
{ {
exception.StatusCode = response.StatusCode; exception.StatusCode = response.StatusCode;
@ -637,6 +616,7 @@ namespace Emby.Server.Implementations.HttpClientManager
client.LastTimeout = DateTime.UtcNow; client.LastTimeout = DateTime.UtcNow;
} }
} }
}
if (!exception.StatusCode.HasValue) if (!exception.StatusCode.HasValue)
{ {

@ -422,18 +422,20 @@ namespace Emby.Server.Implementations.HttpServer
/// <summary> /// <summary>
/// Pres the process optimized result. /// Pres the process optimized result.
/// </summary> /// </summary>
private object GetCachedResult(IRequest requestContext, IDictionary<string, string> responseHeaders, Guid cacheKey, string cacheKeyString, DateTime? lastDateModified, TimeSpan? cacheDuration, string contentType) private object GetCachedResult(IRequest requestContext, IDictionary<string, string> responseHeaders, StaticResultOptions options)
{ {
bool noCache = (requestContext.Headers.Get("Cache-Control") ?? string.Empty).IndexOf("no-cache", StringComparison.OrdinalIgnoreCase) != -1; bool noCache = (requestContext.Headers.Get("Cache-Control") ?? string.Empty).IndexOf("no-cache", StringComparison.OrdinalIgnoreCase) != -1;
AddCachingHeaders(responseHeaders, options.CacheDuration, noCache, options.DateLastModified);
if (!noCache) if (!noCache)
{ {
if (IsNotModified(requestContext, cacheKey)) DateTime.TryParse(requestContext.Headers.Get("If-Modified-Since"), out var ifModifiedSinceHeader);
if (IsNotModified(ifModifiedSinceHeader, options.CacheDuration, options.DateLastModified))
{ {
AddAgeHeader(responseHeaders, lastDateModified); AddAgeHeader(responseHeaders, options.DateLastModified);
AddExpiresHeader(responseHeaders, cacheKeyString, cacheDuration);
var result = new HttpResult(Array.Empty<byte>(), contentType ?? "text/html", HttpStatusCode.NotModified); var result = new HttpResult(Array.Empty<byte>(), options.ContentType ?? "text/html", HttpStatusCode.NotModified);
AddResponseHeaders(result, responseHeaders); AddResponseHeaders(result, responseHeaders);
@ -441,8 +443,6 @@ namespace Emby.Server.Implementations.HttpServer
} }
} }
AddCachingHeaders(responseHeaders, cacheKeyString, cacheDuration);
return null; return null;
} }
@ -487,9 +487,6 @@ namespace Emby.Server.Implementations.HttpServer
options.DateLastModified = _fileSystem.GetLastWriteTimeUtc(path); options.DateLastModified = _fileSystem.GetLastWriteTimeUtc(path);
} }
var cacheKey = path + options.DateLastModified.Value.Ticks;
options.CacheKey = cacheKey.GetMD5();
options.ContentFactory = () => Task.FromResult(GetFileStream(path, fileShare)); options.ContentFactory = () => Task.FromResult(GetFileStream(path, fileShare));
options.ResponseHeaders = options.ResponseHeaders ?? new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); options.ResponseHeaders = options.ResponseHeaders ?? new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
@ -520,7 +517,6 @@ namespace Emby.Server.Implementations.HttpServer
return GetStaticResult(requestContext, new StaticResultOptions return GetStaticResult(requestContext, new StaticResultOptions
{ {
CacheDuration = cacheDuration, CacheDuration = cacheDuration,
CacheKey = cacheKey,
ContentFactory = factoryFn, ContentFactory = factoryFn,
ContentType = contentType, ContentType = contentType,
DateLastModified = lastDateModified, DateLastModified = lastDateModified,
@ -534,14 +530,10 @@ namespace Emby.Server.Implementations.HttpServer
options.ResponseHeaders = options.ResponseHeaders ?? new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); options.ResponseHeaders = options.ResponseHeaders ?? new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
var contentType = options.ContentType; var contentType = options.ContentType;
var etag = requestContext.Headers.Get("If-None-Match"); if (!string.IsNullOrEmpty(requestContext.Headers.Get("If-Modified-Since")))
var cacheKey = etag != null ? new Guid(etag.Trim('\"')) : Guid.Empty;
if (!cacheKey.Equals(Guid.Empty))
{ {
var key = cacheKey.ToString("N");
// See if the result is already cached in the browser // See if the result is already cached in the browser
var result = GetCachedResult(requestContext, options.ResponseHeaders, cacheKey, key, options.DateLastModified, options.CacheDuration, contentType); var result = GetCachedResult(requestContext, options.ResponseHeaders, options);
if (result != null) if (result != null)
{ {
@ -553,6 +545,8 @@ namespace Emby.Server.Implementations.HttpServer
var isHeadRequest = options.IsHeadRequest || string.Equals(requestContext.Verb, "HEAD", StringComparison.OrdinalIgnoreCase); var isHeadRequest = options.IsHeadRequest || string.Equals(requestContext.Verb, "HEAD", StringComparison.OrdinalIgnoreCase);
var factoryFn = options.ContentFactory; var factoryFn = options.ContentFactory;
var responseHeaders = options.ResponseHeaders; var responseHeaders = options.ResponseHeaders;
AddCachingHeaders(responseHeaders, options.CacheDuration, false, options.DateLastModified);
AddAgeHeader(responseHeaders, options.DateLastModified);
var rangeHeader = requestContext.Headers.Get("Range"); var rangeHeader = requestContext.Headers.Get("Range");
@ -566,21 +560,10 @@ namespace Emby.Server.Implementations.HttpServer
}; };
AddResponseHeaders(hasHeaders, options.ResponseHeaders); AddResponseHeaders(hasHeaders, options.ResponseHeaders);
// Generate an ETag based on identifying information - TODO read contents from filesystem instead?
var responseId = $"{hasHeaders.ContentType}{options.Path}{hasHeaders.TotalContentLength}";
var hashedId = MD5.Create().ComputeHash(Encoding.Default.GetBytes(responseId));
hasHeaders.Headers["ETag"] = new Guid(hashedId).ToString("N");
return hasHeaders; return hasHeaders;
} }
var stream = await factoryFn().ConfigureAwait(false); var stream = await factoryFn().ConfigureAwait(false);
// Generate an etag based on stream content
var streamHash = MD5.Create().ComputeHash(stream);
var newEtag = new Guid(streamHash).ToString("N");
// reset position so the response can re-use it -- TODO is this ok?
stream.Position = 0;
var totalContentLength = options.ContentLength; var totalContentLength = options.ContentLength;
if (!totalContentLength.HasValue) if (!totalContentLength.HasValue)
@ -603,7 +586,6 @@ namespace Emby.Server.Implementations.HttpServer
}; };
AddResponseHeaders(hasHeaders, options.ResponseHeaders); AddResponseHeaders(hasHeaders, options.ResponseHeaders);
hasHeaders.Headers["ETag"] = newEtag;
return hasHeaders; return hasHeaders;
} }
else else
@ -628,7 +610,6 @@ namespace Emby.Server.Implementations.HttpServer
}; };
AddResponseHeaders(hasHeaders, options.ResponseHeaders); AddResponseHeaders(hasHeaders, options.ResponseHeaders);
hasHeaders.Headers["ETag"] = newEtag;
return hasHeaders; return hasHeaders;
} }
} }
@ -641,37 +622,28 @@ namespace Emby.Server.Implementations.HttpServer
/// <summary> /// <summary>
/// Adds the caching responseHeaders. /// Adds the caching responseHeaders.
/// </summary> /// </summary>
private void AddCachingHeaders(IDictionary<string, string> responseHeaders, string cacheKey, TimeSpan? cacheDuration) private void AddCachingHeaders(IDictionary<string, string> responseHeaders, TimeSpan? cacheDuration,
{ bool noCache, DateTime? lastModifiedDate)
if (cacheDuration.HasValue)
{
responseHeaders["Cache-Control"] = "public, max-age=" + Convert.ToInt32(cacheDuration.Value.TotalSeconds);
}
else if (!string.IsNullOrEmpty(cacheKey))
{ {
responseHeaders["Cache-Control"] = "public"; if (noCache)
}
else
{ {
responseHeaders["Cache-Control"] = "no-cache, no-store, must-revalidate"; responseHeaders["Cache-Control"] = "no-cache, no-store, must-revalidate";
responseHeaders["pragma"] = "no-cache, no-store, must-revalidate"; responseHeaders["pragma"] = "no-cache, no-store, must-revalidate";
return;
} }
AddExpiresHeader(responseHeaders, cacheKey, cacheDuration);
}
/// <summary>
/// Adds the expires header.
/// </summary>
private static void AddExpiresHeader(IDictionary<string, string> responseHeaders, string cacheKey, TimeSpan? cacheDuration)
{
if (cacheDuration.HasValue) if (cacheDuration.HasValue)
{ {
responseHeaders["Expires"] = DateTime.UtcNow.Add(cacheDuration.Value).ToString("r"); responseHeaders["Cache-Control"] = "public, max-age=" + cacheDuration.Value.TotalSeconds;
} }
else if (string.IsNullOrEmpty(cacheKey)) else
{ {
responseHeaders["Expires"] = "-1"; responseHeaders["Cache-Control"] = "public";
}
if (lastModifiedDate.HasValue)
{
responseHeaders["Last-Modified"] = lastModifiedDate.ToString();
} }
} }
@ -687,32 +659,6 @@ namespace Emby.Server.Implementations.HttpServer
responseHeaders["Age"] = Convert.ToInt64((DateTime.UtcNow - lastDateModified.Value).TotalSeconds).ToString(CultureInfo.InvariantCulture); responseHeaders["Age"] = Convert.ToInt64((DateTime.UtcNow - lastDateModified.Value).TotalSeconds).ToString(CultureInfo.InvariantCulture);
} }
} }
/// <summary>
/// Determines whether [is not modified] [the specified cache key].
/// </summary>
/// <param name="requestContext">The request context.</param>
/// <param name="cacheKey">The cache key.</param>
/// <param name="lastDateModified">The last date modified.</param>
/// <param name="cacheDuration">Duration of the cache.</param>
/// <returns><c>true</c> if [is not modified] [the specified cache key]; otherwise, <c>false</c>.</returns>
private bool IsNotModified(IRequest requestContext, Guid cacheKey)
{
var ifNoneMatchHeader = requestContext.Headers.Get("If-None-Match");
bool hasCacheKey = !cacheKey.Equals(Guid.Empty);
// Validate If-None-Match
if (hasCacheKey && !string.IsNullOrEmpty(ifNoneMatchHeader))
{
if (Guid.TryParse(ifNoneMatchHeader, out var ifNoneMatch)
&& cacheKey.Equals(ifNoneMatch))
{
return true;
}
}
return false;
}
/// <summary> /// <summary>
/// Determines whether [is not modified] [the specified if modified since]. /// Determines whether [is not modified] [the specified if modified since].

@ -2,10 +2,10 @@
"Albums": "Album", "Albums": "Album",
"AppDeviceValues": "App: {0}, Enhed: {1}", "AppDeviceValues": "App: {0}, Enhed: {1}",
"Application": "Applikation", "Application": "Applikation",
"Artists": "Kunstner", "Artists": "Kunstnere",
"AuthenticationSucceededWithUserName": "{0} bekræftet med succes", "AuthenticationSucceededWithUserName": "{0} bekræftet med succes",
"Books": "Bøger", "Books": "Bøger",
"CameraImageUploadedFrom": "A new camera image has been uploaded from {0}", "CameraImageUploadedFrom": "Et nyt kamerabillede er blevet uploadet fra {0}",
"Channels": "Kanaler", "Channels": "Kanaler",
"ChapterNameValue": "Kapitel {0}", "ChapterNameValue": "Kapitel {0}",
"Collections": "Samlinger", "Collections": "Samlinger",
@ -14,41 +14,41 @@
"FailedLoginAttemptWithUserName": "Fejlet loginforsøg fra {0}", "FailedLoginAttemptWithUserName": "Fejlet loginforsøg fra {0}",
"Favorites": "Favoritter", "Favorites": "Favoritter",
"Folders": "Mapper", "Folders": "Mapper",
"Genres": "Genre", "Genres": "Genrer",
"HeaderAlbumArtists": "Albumkunstnere", "HeaderAlbumArtists": "Albumkunstnere",
"HeaderCameraUploads": "Camera Uploads", "HeaderCameraUploads": "Kamera Uploads",
"HeaderContinueWatching": "Fortsæt Afspilning", "HeaderContinueWatching": "Fortsæt Afspilning",
"HeaderFavoriteAlbums": "Favoritalbum", "HeaderFavoriteAlbums": "Favoritalbum",
"HeaderFavoriteArtists": "Favoritkunstnere", "HeaderFavoriteArtists": "Favoritkunstnere",
"HeaderFavoriteEpisodes": "Favoritepisoder", "HeaderFavoriteEpisodes": "Favorit-afsnit",
"HeaderFavoriteShows": "Favorit serier", "HeaderFavoriteShows": "Favorit-serier",
"HeaderFavoriteSongs": "Favoritsange", "HeaderFavoriteSongs": "Favorit-sange",
"HeaderLiveTV": "Live TV", "HeaderLiveTV": "Live TV",
"HeaderNextUp": "Næste", "HeaderNextUp": "Næste",
"HeaderRecordingGroups": "Optagegrupper", "HeaderRecordingGroups": "Optagelsesgrupper",
"HomeVideos": "Hjemmevideoer", "HomeVideos": "Hjemmevideoer",
"Inherit": "Arv", "Inherit": "Nedarv",
"ItemAddedWithName": "{0} blev tilføjet til biblioteket", "ItemAddedWithName": "{0} blev tilføjet til biblioteket",
"ItemRemovedWithName": "{0} blev fjernet fra biblioteket", "ItemRemovedWithName": "{0} blev fjernet fra biblioteket",
"LabelIpAddressValue": "IP-adresse: {0}", "LabelIpAddressValue": "IP-adresse: {0}",
"LabelRunningTimeValue": "Spilletid: {0}", "LabelRunningTimeValue": "Spilletid: {0}",
"Latest": "Seneste", "Latest": "Seneste",
"MessageApplicationUpdated": "Jellyfin Server er blevet opdateret", "MessageApplicationUpdated": "Jellyfin Server er blevet opdateret",
"MessageApplicationUpdatedTo": "Jellyfin Server has been updated to {0}", "MessageApplicationUpdatedTo": "Jellyfin Server er blevet opdateret til {0}",
"MessageNamedServerConfigurationUpdatedWithValue": "Server konfigurationssektion {0} er blevet opdateret", "MessageNamedServerConfigurationUpdatedWithValue": "Serverkonfigurationsafsnit {0} er blevet opdateret",
"MessageServerConfigurationUpdated": "Serverkonfiguration er blevet opdateret", "MessageServerConfigurationUpdated": "Serverkonfigurationen er blevet opdateret",
"MixedContent": "Blandet indhold", "MixedContent": "Blandet indhold",
"Movies": "Film", "Movies": "Film",
"Music": "Musik", "Music": "Musik",
"MusicVideos": "Musikvideoer", "MusicVideos": "Musikvideoer",
"NameInstallFailed": "{0} installation failed", "NameInstallFailed": "{0} installationen mislykkedes",
"NameSeasonNumber": "Sæson {0}", "NameSeasonNumber": "Sæson {0}",
"NameSeasonUnknown": "Season Unknown", "NameSeasonUnknown": "Ukendt Sæson",
"NewVersionIsAvailable": "A new version of Jellyfin Server is available for download.", "NewVersionIsAvailable": "En ny version af Jellyfin Server er tilgængelig til download.",
"NotificationOptionApplicationUpdateAvailable": "Opdatering til applikation tilgængelig", "NotificationOptionApplicationUpdateAvailable": "Opdatering til applikation tilgængelig",
"NotificationOptionApplicationUpdateInstalled": "Opdatering til applikation installeret", "NotificationOptionApplicationUpdateInstalled": "Opdatering til applikation installeret",
"NotificationOptionAudioPlayback": "Audioafspilning påbegyndt", "NotificationOptionAudioPlayback": "Lydafspilning påbegyndt",
"NotificationOptionAudioPlaybackStopped": "Audioafspilning stoppet", "NotificationOptionAudioPlaybackStopped": "Lydafspilning stoppet",
"NotificationOptionCameraImageUploaded": "Kamerabillede uploadet", "NotificationOptionCameraImageUploaded": "Kamerabillede uploadet",
"NotificationOptionInstallationFailed": "Installationsfejl", "NotificationOptionInstallationFailed": "Installationsfejl",
"NotificationOptionNewLibraryContent": "Nyt indhold tilføjet", "NotificationOptionNewLibraryContent": "Nyt indhold tilføjet",
@ -70,16 +70,16 @@
"ProviderValue": "Udbyder: {0}", "ProviderValue": "Udbyder: {0}",
"ScheduledTaskFailedWithName": "{0} fejlet", "ScheduledTaskFailedWithName": "{0} fejlet",
"ScheduledTaskStartedWithName": "{0} påbegyndt", "ScheduledTaskStartedWithName": "{0} påbegyndt",
"ServerNameNeedsToBeRestarted": "{0} needs to be restarted", "ServerNameNeedsToBeRestarted": "{0} skal genstartes",
"Shows": "Shows", "Shows": "Serier",
"Songs": "Sange", "Songs": "Sange",
"StartupEmbyServerIsLoading": "Jellyfin Server indlæser. Prøv venligst igen om kort tid.", "StartupEmbyServerIsLoading": "Jellyfin Server er i gang med at starte op. Prøv venligst igen om lidt.",
"SubtitleDownloadFailureForItem": "Fejlet i download af undertekster for {0}", "SubtitleDownloadFailureForItem": "Fejlet i download af undertekster for {0}",
"SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}", "SubtitleDownloadFailureFromForItem": "Undertekster kunne ikke downloades fra {0} til {1}",
"SubtitlesDownloadedForItem": "Undertekster downloadet for {0}", "SubtitlesDownloadedForItem": "Undertekster downloadet for {0}",
"Sync": "Synk", "Sync": "Synk",
"System": "System", "System": "System",
"TvShows": "TV Shows", "TvShows": "TV serier",
"User": "Bruger", "User": "Bruger",
"UserCreatedWithName": "Bruger {0} er blevet oprettet", "UserCreatedWithName": "Bruger {0} er blevet oprettet",
"UserDeletedWithName": "Brugeren {0} er blevet slettet", "UserDeletedWithName": "Brugeren {0} er blevet slettet",
@ -88,10 +88,10 @@
"UserOfflineFromDevice": "{0} har afbrudt fra {1}", "UserOfflineFromDevice": "{0} har afbrudt fra {1}",
"UserOnlineFromDevice": "{0} er online fra {1}", "UserOnlineFromDevice": "{0} er online fra {1}",
"UserPasswordChangedWithName": "Adgangskode er ændret for bruger {0}", "UserPasswordChangedWithName": "Adgangskode er ændret for bruger {0}",
"UserPolicyUpdatedWithName": "User policy has been updated for {0}", "UserPolicyUpdatedWithName": "Brugerpolitik er blevet opdateret for {0}",
"UserStartedPlayingItemWithValues": "{0} har påbegyndt afspilning af {1}", "UserStartedPlayingItemWithValues": "{0} har påbegyndt afspilning af {1}",
"UserStoppedPlayingItemWithValues": "{0} har afsluttet afspilning af {1}", "UserStoppedPlayingItemWithValues": "{0} har afsluttet afspilning af {1} på {2}",
"ValueHasBeenAddedToLibrary": "{0} has been added to your media library", "ValueHasBeenAddedToLibrary": "{0} er blevet tilføjet til dit mediebibliotek",
"ValueSpecialEpisodeName": "Special - {0}", "ValueSpecialEpisodeName": "Special - {0}",
"VersionNumber": "Version {0}" "VersionNumber": "Version {0}"
} }

@ -3,61 +3,61 @@
"AppDeviceValues": "App: {0}, Gerät: {1}", "AppDeviceValues": "App: {0}, Gerät: {1}",
"Application": "Anwendung", "Application": "Anwendung",
"Artists": "Interpreten", "Artists": "Interpreten",
"AuthenticationSucceededWithUserName": "{0} erfolgreich authentifiziert", "AuthenticationSucceededWithUserName": "{0} hat sich angemeldet",
"Books": "Bücher", "Books": "Bücher",
"CameraImageUploadedFrom": "Ein neues Bild wurde hochgeladen von {0}", "CameraImageUploadedFrom": "Ein neues Foto wurde hochgeladen von {0}",
"Channels": "Kanäle", "Channels": "Kanäle",
"ChapterNameValue": "Kapitel {0}", "ChapterNameValue": "Kapitel {0}",
"Collections": "Sammlungen", "Collections": "Sammlungen",
"DeviceOfflineWithName": "{0} wurde getrennt", "DeviceOfflineWithName": "{0} wurde getrennt",
"DeviceOnlineWithName": "{0} ist verbunden", "DeviceOnlineWithName": "{0} hat sich verbunden",
"FailedLoginAttemptWithUserName": "Fehlgeschlagener Anmeldeversuch von {0}", "FailedLoginAttemptWithUserName": "Fehlgeschlagener Anmeldeversuch von {0}",
"Favorites": "Favoriten", "Favorites": "Favoriten",
"Folders": "Verzeichnisse", "Folders": "Verzeichnisse",
"Genres": "Genres", "Genres": "Genres",
"HeaderAlbumArtists": "Album-Künstler", "HeaderAlbumArtists": "Album-Interpreten",
"HeaderCameraUploads": "Kamera Uploads", "HeaderCameraUploads": "Kamera-Uploads",
"HeaderContinueWatching": "Weiterschauen", "HeaderContinueWatching": "Weiterschauen",
"HeaderFavoriteAlbums": "Lieblingsalben", "HeaderFavoriteAlbums": "Lieblingsalben",
"HeaderFavoriteArtists": "Interpreten Favoriten", "HeaderFavoriteArtists": "Lieblings-Interpreten",
"HeaderFavoriteEpisodes": "Lieblingsepisoden", "HeaderFavoriteEpisodes": "Lieblingsepisoden",
"HeaderFavoriteShows": "Lieblingsserien", "HeaderFavoriteShows": "Lieblingsserien",
"HeaderFavoriteSongs": "Lieder Favoriten", "HeaderFavoriteSongs": "Lieblingslieder",
"HeaderLiveTV": "Live TV", "HeaderLiveTV": "Live-TV",
"HeaderNextUp": "Als Nächstes", "HeaderNextUp": "Als Nächstes",
"HeaderRecordingGroups": "Aufnahme-Gruppen", "HeaderRecordingGroups": "Aufnahme-Gruppen",
"HomeVideos": "Heimvideos", "HomeVideos": "Heimvideos",
"Inherit": "Übernehmen", "Inherit": "Übernehmen",
"ItemAddedWithName": "{0} wurde der Bibliothek hinzugefügt", "ItemAddedWithName": "{0} wurde der Bibliothek hinzugefügt",
"ItemRemovedWithName": "{0} wurde aus der Bibliothek entfernt", "ItemRemovedWithName": "{0} wurde aus der Bibliothek entfernt",
"LabelIpAddressValue": "IP Adresse: {0}", "LabelIpAddressValue": "IP-Adresse: {0}",
"LabelRunningTimeValue": "Laufzeit: {0}", "LabelRunningTimeValue": "Laufzeit: {0}",
"Latest": "Neueste", "Latest": "Neueste",
"MessageApplicationUpdated": "Jellyfin Server wurde auf den neusten Stand gebracht.", "MessageApplicationUpdated": "Jellyfin-Server wurde aktualisiert",
"MessageApplicationUpdatedTo": "Jellyfin Server wurde auf Version {0} aktualisiert", "MessageApplicationUpdatedTo": "Jellyfin-Server wurde auf Version {0} aktualisiert",
"MessageNamedServerConfigurationUpdatedWithValue": "Der Server Einstellungsbereich {0} wurde aktualisiert", "MessageNamedServerConfigurationUpdatedWithValue": "Der Server Einstellungsbereich {0} wurde aktualisiert",
"MessageServerConfigurationUpdated": "Server Einstellungen wurden aktualisiert", "MessageServerConfigurationUpdated": "Servereinstellungen wurden aktualisiert",
"MixedContent": "Gemischte Inhalte", "MixedContent": "Gemischte Inhalte",
"Movies": "Filme", "Movies": "Filme",
"Music": "Musik", "Music": "Musik",
"MusicVideos": "Musikvideos", "MusicVideos": "Musikvideos",
"NameInstallFailed": "{0} Installation fehlgeschlagen", "NameInstallFailed": "Installation von {0} fehlgeschlagen",
"NameSeasonNumber": "Staffel {0}", "NameSeasonNumber": "Staffel {0}",
"NameSeasonUnknown": "Staffel unbekannt", "NameSeasonUnknown": "Staffel unbekannt",
"NewVersionIsAvailable": "Eine neue Version von Jellyfin Server steht zum Download bereit.", "NewVersionIsAvailable": "Eine neue Version von Jellyfin-Server steht zum Download bereit.",
"NotificationOptionApplicationUpdateAvailable": "Anwendungsaktualisierung verfügbar", "NotificationOptionApplicationUpdateAvailable": "Anwendungsaktualisierung verfügbar",
"NotificationOptionApplicationUpdateInstalled": "Anwendungsaktualisierung installiert", "NotificationOptionApplicationUpdateInstalled": "Anwendungsaktualisierung installiert",
"NotificationOptionAudioPlayback": "Audiowiedergabe gestartet", "NotificationOptionAudioPlayback": "Audiowiedergabe gestartet",
"NotificationOptionAudioPlaybackStopped": "Audiowiedergabe gestoppt", "NotificationOptionAudioPlaybackStopped": "Audiowiedergabe gestoppt",
"NotificationOptionCameraImageUploaded": "Kamera Bild hochgeladen", "NotificationOptionCameraImageUploaded": "Foto hochgeladen",
"NotificationOptionInstallationFailed": "Installationsfehler", "NotificationOptionInstallationFailed": "Installationsfehler",
"NotificationOptionNewLibraryContent": "Neuer Inhalt hinzugefügt", "NotificationOptionNewLibraryContent": "Neuer Inhalt hinzugefügt",
"NotificationOptionPluginError": "Plugin Fehler", "NotificationOptionPluginError": "Plugin-Fehler",
"NotificationOptionPluginInstalled": "Plugin installiert", "NotificationOptionPluginInstalled": "Plugin installiert",
"NotificationOptionPluginUninstalled": "Plugin deinstalliert", "NotificationOptionPluginUninstalled": "Plugin deinstalliert",
"NotificationOptionPluginUpdateInstalled": "Pluginaktualisierung installiert", "NotificationOptionPluginUpdateInstalled": "Pluginaktualisierung installiert",
"NotificationOptionServerRestartRequired": "Serverneustart notwendig", "NotificationOptionServerRestartRequired": "Serverneustart notwendig",
"NotificationOptionTaskFailed": "Geplante Aufgaben fehlgeschlagen", "NotificationOptionTaskFailed": "Geplante Aufgabe fehlgeschlagen",
"NotificationOptionUserLockedOut": "Benutzer ausgeschlossen", "NotificationOptionUserLockedOut": "Benutzer ausgeschlossen",
"NotificationOptionVideoPlayback": "Videowiedergabe gestartet", "NotificationOptionVideoPlayback": "Videowiedergabe gestartet",
"NotificationOptionVideoPlaybackStopped": "Videowiedergabe gestoppt", "NotificationOptionVideoPlaybackStopped": "Videowiedergabe gestoppt",
@ -68,18 +68,18 @@
"PluginUninstalledWithName": "{0} wurde deinstalliert", "PluginUninstalledWithName": "{0} wurde deinstalliert",
"PluginUpdatedWithName": "{0} wurde aktualisiert", "PluginUpdatedWithName": "{0} wurde aktualisiert",
"ProviderValue": "Anbieter: {0}", "ProviderValue": "Anbieter: {0}",
"ScheduledTaskFailedWithName": "{0} fehlgeschlagen", "ScheduledTaskFailedWithName": "{0} ist fehlgeschlagen",
"ScheduledTaskStartedWithName": "{0} gestartet", "ScheduledTaskStartedWithName": "{0} wurde gestartet",
"ServerNameNeedsToBeRestarted": "{0} muss neu gestartet werden", "ServerNameNeedsToBeRestarted": "{0} muss neu gestartet werden",
"Shows": "Serien", "Shows": "Serien",
"Songs": "Songs", "Songs": "Songs",
"StartupEmbyServerIsLoading": "Jellyfin Server startet, bitte versuche es gleich noch einmal.", "StartupEmbyServerIsLoading": "Jellyfin-Server startet, bitte versuche es gleich noch einmal.",
"SubtitleDownloadFailureForItem": "Download der Untertitel fehlgeschlagen für {0}", "SubtitleDownloadFailureForItem": "Download der Untertitel fehlgeschlagen für {0}",
"SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}", "SubtitleDownloadFailureFromForItem": "Untertitel von {0} für {1} konnten nicht heruntergeladen werden",
"SubtitlesDownloadedForItem": "Untertitel heruntergeladen für {0}", "SubtitlesDownloadedForItem": "Untertitel heruntergeladen für {0}",
"Sync": "Synchronisation", "Sync": "Synchronisation",
"System": "System", "System": "System",
"TvShows": "TV Sendungen", "TvShows": "TV-Sendungen",
"User": "Benutzer", "User": "Benutzer",
"UserCreatedWithName": "Benutzer {0} wurde erstellt", "UserCreatedWithName": "Benutzer {0} wurde erstellt",
"UserDeletedWithName": "Benutzer {0} wurde gelöscht", "UserDeletedWithName": "Benutzer {0} wurde gelöscht",
@ -88,10 +88,10 @@
"UserOfflineFromDevice": "{0} wurde getrennt von {1}", "UserOfflineFromDevice": "{0} wurde getrennt von {1}",
"UserOnlineFromDevice": "{0} ist online von {1}", "UserOnlineFromDevice": "{0} ist online von {1}",
"UserPasswordChangedWithName": "Das Passwort für Benutzer {0} wurde geändert", "UserPasswordChangedWithName": "Das Passwort für Benutzer {0} wurde geändert",
"UserPolicyUpdatedWithName": "Benutzerrichtlinie wurde für {0} aktualisiert", "UserPolicyUpdatedWithName": "Benutzerrichtlinie von {0} wurde aktualisiert",
"UserStartedPlayingItemWithValues": "{0} hat die Wiedergabe von {1} gestartet", "UserStartedPlayingItemWithValues": "{0} hat die Wiedergabe von {1} auf {2} gestartet",
"UserStoppedPlayingItemWithValues": "{0} hat die Wiedergabe von {1} beendet", "UserStoppedPlayingItemWithValues": "{0} hat die Wiedergabe von {1} auf {2} beendet",
"ValueHasBeenAddedToLibrary": "{0} wurde ihrer Bibliothek hinzugefügt", "ValueHasBeenAddedToLibrary": "{0} wurde deiner Bibliothek hinzugefügt",
"ValueSpecialEpisodeName": "Special - {0}", "ValueSpecialEpisodeName": "Extra - {0}",
"VersionNumber": "Version {0}" "VersionNumber": "Version {0}"
} }

@ -90,7 +90,7 @@
"UserPasswordChangedWithName": "Password has been changed for user {0}", "UserPasswordChangedWithName": "Password has been changed for user {0}",
"UserPolicyUpdatedWithName": "User policy has been updated for {0}", "UserPolicyUpdatedWithName": "User policy has been updated for {0}",
"UserStartedPlayingItemWithValues": "{0} has started playing {1}", "UserStartedPlayingItemWithValues": "{0} has started playing {1}",
"UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", "UserStoppedPlayingItemWithValues": "{0} has finished playing {1} on {2}",
"ValueHasBeenAddedToLibrary": "{0} has been added to your media library", "ValueHasBeenAddedToLibrary": "{0} has been added to your media library",
"ValueSpecialEpisodeName": "Special - {0}", "ValueSpecialEpisodeName": "Special - {0}",
"VersionNumber": "Version {0}" "VersionNumber": "Version {0}"

@ -30,7 +30,7 @@
"Inherit": "Inherit", "Inherit": "Inherit",
"ItemAddedWithName": "{0} was added to the library", "ItemAddedWithName": "{0} was added to the library",
"ItemRemovedWithName": "{0} was removed from the library", "ItemRemovedWithName": "{0} was removed from the library",
"LabelIpAddressValue": "Ip address: {0}", "LabelIpAddressValue": "IP address: {0}",
"LabelRunningTimeValue": "Running time: {0}", "LabelRunningTimeValue": "Running time: {0}",
"Latest": "Latest", "Latest": "Latest",
"MessageApplicationUpdated": "Jellyfin Server has been updated", "MessageApplicationUpdated": "Jellyfin Server has been updated",

@ -5,46 +5,46 @@
"Artists": "Artistas", "Artists": "Artistas",
"AuthenticationSucceededWithUserName": "{0} autenticado correctamente", "AuthenticationSucceededWithUserName": "{0} autenticado correctamente",
"Books": "Libros", "Books": "Libros",
"CameraImageUploadedFrom": "A new camera image has been uploaded from {0}", "CameraImageUploadedFrom": "Se ha subido una nueva imagen de cámara desde {0}",
"Channels": "Canales", "Channels": "Canales",
"ChapterNameValue": "Capítulo {0}", "ChapterNameValue": "Capítulo {0}",
"Collections": "Colecciones", "Collections": "Colecciones",
"DeviceOfflineWithName": "{0} se ha desconectado", "DeviceOfflineWithName": "{0} se ha desconectado",
"DeviceOnlineWithName": "{0} está conectado", "DeviceOnlineWithName": "{0} está conectado",
"FailedLoginAttemptWithUserName": "Error al intentar iniciar sesión a partir de {0}", "FailedLoginAttemptWithUserName": "Error al intentar iniciar sesión desde {0}",
"Favorites": "Favoritos", "Favorites": "Favoritos",
"Folders": "Carpetas", "Folders": "Carpetas",
"Genres": "Géneros", "Genres": "Géneros",
"HeaderAlbumArtists": "Artistas del Álbum", "HeaderAlbumArtists": "Artistas del álbum",
"HeaderCameraUploads": "Camera Uploads", "HeaderCameraUploads": "Subidas desde cámara",
"HeaderContinueWatching": "Continuar viendo", "HeaderContinueWatching": "Continuar viendo",
"HeaderFavoriteAlbums": "Álbumes favoritos", "HeaderFavoriteAlbums": "Álbumes favoritos",
"HeaderFavoriteArtists": "Artistas favoritos", "HeaderFavoriteArtists": "Artistas favoritos",
"HeaderFavoriteEpisodes": "Episodios favoritos", "HeaderFavoriteEpisodes": "Episodios favoritos",
"HeaderFavoriteShows": "Programas favoritos", "HeaderFavoriteShows": "Programas favoritos",
"HeaderFavoriteSongs": "Canciones favoritas", "HeaderFavoriteSongs": "Canciones favoritas",
"HeaderLiveTV": "TV en vivo", "HeaderLiveTV": "TV en directo",
"HeaderNextUp": "Siguiendo", "HeaderNextUp": "Siguiendo",
"HeaderRecordingGroups": "Grupos de grabación", "HeaderRecordingGroups": "Grupos de grabación",
"HomeVideos": "Vídeos de inicio", "HomeVideos": "Vídeos caseros",
"Inherit": "Heredar", "Inherit": "Heredar",
"ItemAddedWithName": "{0} se ha añadido a la biblioteca", "ItemAddedWithName": "{0} se ha añadido a la biblioteca",
"ItemRemovedWithName": "{0} se elimina de la biblioteca", "ItemRemovedWithName": "{0} ha sido eliminado de la biblioteca",
"LabelIpAddressValue": "Dirección IP: {0}", "LabelIpAddressValue": "Dirección IP: {0}",
"LabelRunningTimeValue": "Tiempo de funcionamiento: {0}", "LabelRunningTimeValue": "Tiempo de funcionamiento: {0}",
"Latest": "Últimos", "Latest": "Últimos",
"MessageApplicationUpdated": "Se ha actualizado el servidor Jellyfin", "MessageApplicationUpdated": "Se ha actualizado el servidor Jellyfin",
"MessageApplicationUpdatedTo": "Jellyfin Server has been updated to {0}", "MessageApplicationUpdatedTo": "Se ha actualizado el servidor Jellyfin a la versión {0}",
"MessageNamedServerConfigurationUpdatedWithValue": "La sección de configuración del servidor {0} ha sido actualizado", "MessageNamedServerConfigurationUpdatedWithValue": "La sección {0} de configuración del servidor ha sido actualizada",
"MessageServerConfigurationUpdated": "Se ha actualizado la configuración del servidor", "MessageServerConfigurationUpdated": "Se ha actualizado la configuración del servidor",
"MixedContent": "Contenido mixto", "MixedContent": "Contenido mixto",
"Movies": "Peliculas", "Movies": "Películas",
"Music": "Música", "Music": "Música",
"MusicVideos": "Videos musicales", "MusicVideos": "Vídeos musicales",
"NameInstallFailed": "{0} installation failed", "NameInstallFailed": "{0} error de instalación",
"NameSeasonNumber": "Temporada {0}", "NameSeasonNumber": "Temporada {0}",
"NameSeasonUnknown": "Season Unknown", "NameSeasonUnknown": "Temporada desconocida",
"NewVersionIsAvailable": "A new version of Jellyfin Server is available for download.", "NewVersionIsAvailable": "Disponible una nueva versión de Jellyfin para descargar.",
"NotificationOptionApplicationUpdateAvailable": "Actualización de la aplicación disponible", "NotificationOptionApplicationUpdateAvailable": "Actualización de la aplicación disponible",
"NotificationOptionApplicationUpdateInstalled": "Actualización de la aplicación instalada", "NotificationOptionApplicationUpdateInstalled": "Actualización de la aplicación instalada",
"NotificationOptionAudioPlayback": "Se inició la reproducción de audio", "NotificationOptionAudioPlayback": "Se inició la reproducción de audio",
@ -56,13 +56,13 @@
"NotificationOptionPluginInstalled": "Plugin instalado", "NotificationOptionPluginInstalled": "Plugin instalado",
"NotificationOptionPluginUninstalled": "Plugin desinstalado", "NotificationOptionPluginUninstalled": "Plugin desinstalado",
"NotificationOptionPluginUpdateInstalled": "Actualización del complemento instalada", "NotificationOptionPluginUpdateInstalled": "Actualización del complemento instalada",
"NotificationOptionServerRestartRequired": "Requiere reinicio del servidor", "NotificationOptionServerRestartRequired": "Se requiere reinicio del servidor",
"NotificationOptionTaskFailed": "Error de tarea programada", "NotificationOptionTaskFailed": "Error de tarea programada",
"NotificationOptionUserLockedOut": "Usuario bloqueado", "NotificationOptionUserLockedOut": "Usuario bloqueado",
"NotificationOptionVideoPlayback": "Se inició la reproducción de vídeo", "NotificationOptionVideoPlayback": "Se inició la reproducción de vídeo",
"NotificationOptionVideoPlaybackStopped": "Reproducción de vídeo detenida", "NotificationOptionVideoPlaybackStopped": "Reproducción de vídeo detenida",
"Photos": "Fotos", "Photos": "Fotos",
"Playlists": "Listas reproducción", "Playlists": "Listas de reproducción",
"Plugin": "Plugin", "Plugin": "Plugin",
"PluginInstalledWithName": "{0} se ha instalado", "PluginInstalledWithName": "{0} se ha instalado",
"PluginUninstalledWithName": "{0} se ha desinstalado", "PluginUninstalledWithName": "{0} se ha desinstalado",
@ -70,16 +70,16 @@
"ProviderValue": "Proveedor: {0}", "ProviderValue": "Proveedor: {0}",
"ScheduledTaskFailedWithName": "{0} falló", "ScheduledTaskFailedWithName": "{0} falló",
"ScheduledTaskStartedWithName": "{0} iniciada", "ScheduledTaskStartedWithName": "{0} iniciada",
"ServerNameNeedsToBeRestarted": "{0} needs to be restarted", "ServerNameNeedsToBeRestarted": "{0} necesita ser reiniciado",
"Shows": "Series", "Shows": "Series",
"Songs": "Canciones", "Songs": "Canciones",
"StartupEmbyServerIsLoading": "Jellyfin Server se está cargando. Vuelve a intentarlo en breve.", "StartupEmbyServerIsLoading": "Jellyfin Server se está cargando. Vuelve a intentarlo en breve.",
"SubtitleDownloadFailureForItem": "Error al descargar subtítulos para {0}", "SubtitleDownloadFailureForItem": "Error al descargar subtítulos para {0}",
"SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}", "SubtitleDownloadFailureFromForItem": "Fallo de descarga de subtítulos desde {0} para {1}",
"SubtitlesDownloadedForItem": "Descargar subtítulos para {0}", "SubtitlesDownloadedForItem": "Descargar subtítulos para {0}",
"Sync": "Sincronizar", "Sync": "Sincronizar",
"System": "Sistema", "System": "Sistema",
"TvShows": "Series TV", "TvShows": "Series de TV",
"User": "Usuario", "User": "Usuario",
"UserCreatedWithName": "El usuario {0} ha sido creado", "UserCreatedWithName": "El usuario {0} ha sido creado",
"UserDeletedWithName": "El usuario {0} ha sido borrado", "UserDeletedWithName": "El usuario {0} ha sido borrado",
@ -88,10 +88,10 @@
"UserOfflineFromDevice": "{0} se ha desconectado de {1}", "UserOfflineFromDevice": "{0} se ha desconectado de {1}",
"UserOnlineFromDevice": "{0} está en línea desde {1}", "UserOnlineFromDevice": "{0} está en línea desde {1}",
"UserPasswordChangedWithName": "Se ha cambiado la contraseña para el usuario {0}", "UserPasswordChangedWithName": "Se ha cambiado la contraseña para el usuario {0}",
"UserPolicyUpdatedWithName": "User policy has been updated for {0}", "UserPolicyUpdatedWithName": "Actualizada política de usuario para {0}",
"UserStartedPlayingItemWithValues": "{0} ha comenzado reproducir {1}", "UserStartedPlayingItemWithValues": "{0} está reproduciendo {1} en {2}",
"UserStoppedPlayingItemWithValues": "{0} ha parado de reproducir {1}", "UserStoppedPlayingItemWithValues": "{0} ha terminado de reproducir {1} en {2}",
"ValueHasBeenAddedToLibrary": "{0} has been added to your media library", "ValueHasBeenAddedToLibrary": "{0} ha sido añadido a tu biblioteca multimedia",
"ValueSpecialEpisodeName": "Especial - {0}", "ValueSpecialEpisodeName": "Especial - {0}",
"VersionNumber": "Versión {0}" "VersionNumber": "Versión {0}"
} }

@ -36,7 +36,7 @@
"MessageApplicationUpdated": "Le serveur Jellyfin a été mis à jour", "MessageApplicationUpdated": "Le serveur Jellyfin a été mis à jour",
"MessageApplicationUpdatedTo": "Jellyfin Serveur a été mis à jour en version {0}", "MessageApplicationUpdatedTo": "Jellyfin Serveur a été mis à jour en version {0}",
"MessageNamedServerConfigurationUpdatedWithValue": "La configuration de la section {0} du serveur a été mise à jour", "MessageNamedServerConfigurationUpdatedWithValue": "La configuration de la section {0} du serveur a été mise à jour",
"MessageServerConfigurationUpdated": "La configuration du serveur a été mise à jour.", "MessageServerConfigurationUpdated": "La configuration du serveur a été mise à jour",
"MixedContent": "Contenu mixte", "MixedContent": "Contenu mixte",
"Movies": "Films", "Movies": "Films",
"Music": "Musique", "Music": "Musique",

@ -5,47 +5,47 @@
"Artists": "Előadók", "Artists": "Előadók",
"AuthenticationSucceededWithUserName": "{0} sikeresen azonosítva", "AuthenticationSucceededWithUserName": "{0} sikeresen azonosítva",
"Books": "Könyvek", "Books": "Könyvek",
"CameraImageUploadedFrom": "A new camera image has been uploaded from {0}", "CameraImageUploadedFrom": "Új kamerakép került feltöltésre {0}",
"Channels": "Csatornák", "Channels": "Csatornák",
"ChapterNameValue": "Jelenet {0}", "ChapterNameValue": "Jelenet {0}",
"Collections": "Gyűjtemények", "Collections": "Gyűjtemények",
"DeviceOfflineWithName": "{0} kijelentkezett", "DeviceOfflineWithName": "{0} kijelentkezett",
"DeviceOnlineWithName": "{0} belépett", "DeviceOnlineWithName": "{0} belépett",
"FailedLoginAttemptWithUserName": "Failed login attempt from {0}", "FailedLoginAttemptWithUserName": "Sikertelen bejelentkezési kísérlet {0}",
"Favorites": "Kedvencek", "Favorites": "Kedvencek",
"Folders": "Könyvtárak", "Folders": "Könyvtárak",
"Genres": "Műfajok", "Genres": "Műfajok",
"HeaderAlbumArtists": "Album Előadók", "HeaderAlbumArtists": "Album Előadók",
"HeaderCameraUploads": "Camera Uploads", "HeaderCameraUploads": "Kamera feltöltések",
"HeaderContinueWatching": "Vetítés(ek) folytatása", "HeaderContinueWatching": "Folyamatban lévő filmek",
"HeaderFavoriteAlbums": "Kedvenc Albumok", "HeaderFavoriteAlbums": "Kedvenc Albumok",
"HeaderFavoriteArtists": "Kedvenc Művészek", "HeaderFavoriteArtists": "Kedvenc Művészek",
"HeaderFavoriteEpisodes": "Kedvenc Epizódok", "HeaderFavoriteEpisodes": "Kedvenc Epizódok",
"HeaderFavoriteShows": "Kedvenc Műsorok", "HeaderFavoriteShows": "Kedvenc Műsorok",
"HeaderFavoriteSongs": "Kedvenc Dalok", "HeaderFavoriteSongs": "Kedvenc Dalok",
"HeaderLiveTV": "Live TV", "HeaderLiveTV": "Élő TV",
"HeaderNextUp": "Következik", "HeaderNextUp": "Következik",
"HeaderRecordingGroups": "Recording Groups", "HeaderRecordingGroups": "Felvételi csoportok",
"HomeVideos": "Házi videók", "HomeVideos": "Házi videók",
"Inherit": "Inherit", "Inherit": "Inherit",
"ItemAddedWithName": "{0} was added to the library", "ItemAddedWithName": "{0} hozzáadva a könyvtárhoz",
"ItemRemovedWithName": "{0} was removed from the library", "ItemRemovedWithName": "{0} eltávolítva a könyvtárból",
"LabelIpAddressValue": "Ip cím: {0}", "LabelIpAddressValue": "IP cím: {0}",
"LabelRunningTimeValue": "Running time: {0}", "LabelRunningTimeValue": "Futási idő: {0}",
"Latest": "Legújabb", "Latest": "Legújabb",
"MessageApplicationUpdated": "Jellyfin Szerver frissítve", "MessageApplicationUpdated": "Jellyfin Szerver frissítve",
"MessageApplicationUpdatedTo": "Jellyfin Server has been updated to {0}", "MessageApplicationUpdatedTo": "Jellyfin Szerver frissítve lett a következőre {0}",
"MessageNamedServerConfigurationUpdatedWithValue": "Szerver konfigurációs rész {0} frissítve", "MessageNamedServerConfigurationUpdatedWithValue": "Szerver konfigurációs rész {0} frissítve",
"MessageServerConfigurationUpdated": "Szerver konfiguráció frissítve", "MessageServerConfigurationUpdated": "Szerver konfiguráció frissítve",
"MixedContent": "Vegyes tartalom", "MixedContent": "Vegyes tartalom",
"Movies": "Filmek", "Movies": "Filmek",
"Music": "Zene", "Music": "Zene",
"MusicVideos": "Zenei Videók", "MusicVideos": "Zenei Videók",
"NameInstallFailed": "{0} installation failed", "NameInstallFailed": "{0} sikertelen telepítés",
"NameSeasonNumber": "Season {0}", "NameSeasonNumber": "Évad {0}",
"NameSeasonUnknown": "Season Unknown", "NameSeasonUnknown": "Ismeretlen évad",
"NewVersionIsAvailable": "A new version of Jellyfin Server is available for download.", "NewVersionIsAvailable": "Letölthető a Jellyfin Szerver új verziója.",
"NotificationOptionApplicationUpdateAvailable": "Program frissítés elérhető", "NotificationOptionApplicationUpdateAvailable": "Új programfrissítés érhető el",
"NotificationOptionApplicationUpdateInstalled": "Programfrissítés telepítve", "NotificationOptionApplicationUpdateInstalled": "Programfrissítés telepítve",
"NotificationOptionAudioPlayback": "Audió lejátszás elkezdve", "NotificationOptionAudioPlayback": "Audió lejátszás elkezdve",
"NotificationOptionAudioPlaybackStopped": "Audió lejátszás befejezve", "NotificationOptionAudioPlaybackStopped": "Audió lejátszás befejezve",
@ -57,7 +57,7 @@
"NotificationOptionPluginUninstalled": "Bővítmény eltávolítva", "NotificationOptionPluginUninstalled": "Bővítmény eltávolítva",
"NotificationOptionPluginUpdateInstalled": "Bővítmény frissítés telepítve", "NotificationOptionPluginUpdateInstalled": "Bővítmény frissítés telepítve",
"NotificationOptionServerRestartRequired": "Szerver újraindítás szükséges", "NotificationOptionServerRestartRequired": "Szerver újraindítás szükséges",
"NotificationOptionTaskFailed": "Scheduled task failure", "NotificationOptionTaskFailed": "Ütemezett feladat hiba",
"NotificationOptionUserLockedOut": "Felhasználó tiltva", "NotificationOptionUserLockedOut": "Felhasználó tiltva",
"NotificationOptionVideoPlayback": "Videó lejátszás elkezdve", "NotificationOptionVideoPlayback": "Videó lejátszás elkezdve",
"NotificationOptionVideoPlaybackStopped": "Videó lejátszás befejezve", "NotificationOptionVideoPlaybackStopped": "Videó lejátszás befejezve",
@ -68,30 +68,30 @@
"PluginUninstalledWithName": "{0} eltávolítva", "PluginUninstalledWithName": "{0} eltávolítva",
"PluginUpdatedWithName": "{0} frissítve", "PluginUpdatedWithName": "{0} frissítve",
"ProviderValue": "Provider: {0}", "ProviderValue": "Provider: {0}",
"ScheduledTaskFailedWithName": "{0} failed", "ScheduledTaskFailedWithName": "{0} hiba",
"ScheduledTaskStartedWithName": "{0} started", "ScheduledTaskStartedWithName": "{0} elkezdve",
"ServerNameNeedsToBeRestarted": "{0} needs to be restarted", "ServerNameNeedsToBeRestarted": "{0}-t újra kell indítani",
"Shows": "Műsorok", "Shows": "Műsorok",
"Songs": "Dalok", "Songs": "Dalok",
"StartupEmbyServerIsLoading": "Jellyfin Szerver betöltődik. Kérjük, próbáld meg újra később.", "StartupEmbyServerIsLoading": "A Jellyfin Szerver betöltődik. Kérlek próbáld újra később.",
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
"SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}", "SubtitleDownloadFailureFromForItem": "Nem sikerült a felirat letöltése innen: {0} ehhez: {1}",
"SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", "SubtitlesDownloadedForItem": "Letöltött feliratok a következőhöz {0}",
"Sync": "Szinkronizál", "Sync": "Szinkronizál",
"System": "Rendszer", "System": "Rendszer",
"TvShows": "TV Műsorok", "TvShows": "TV Műsorok",
"User": "Felhasználó", "User": "Felhasználó",
"UserCreatedWithName": "User {0} has been created", "UserCreatedWithName": "{0} felhasználó létrehozva",
"UserDeletedWithName": "User {0} has been deleted", "UserDeletedWithName": "{0} felhasználó törölve",
"UserDownloadingItemWithValues": "{0} letölti {1}", "UserDownloadingItemWithValues": "{0} letölti {1}",
"UserLockedOutWithName": "User {0} has been locked out", "UserLockedOutWithName": "{0} felhasználó zárolva van",
"UserOfflineFromDevice": "{0} kijelentkezett innen {1}", "UserOfflineFromDevice": "{0} kijelentkezett innen: {1}",
"UserOnlineFromDevice": "{0} is online from {1}", "UserOnlineFromDevice": "{0} online itt: {1}",
"UserPasswordChangedWithName": "Password has been changed for user {0}", "UserPasswordChangedWithName": "Jelszó megváltozott a következő felhasználó számára: {0}",
"UserPolicyUpdatedWithName": "User policy has been updated for {0}", "UserPolicyUpdatedWithName": "A felhasználói házirend frissítve lett {0}",
"UserStartedPlayingItemWithValues": "{0} elkezdte játszani a következőt {1}", "UserStartedPlayingItemWithValues": "{0} elkezdte játszani a következőt: {1} itt: {2}",
"UserStoppedPlayingItemWithValues": "{0} befejezte a következőt {1}", "UserStoppedPlayingItemWithValues": "{0} befejezte a következőt: {1} itt: {2}",
"ValueHasBeenAddedToLibrary": "{0} has been added to your media library", "ValueHasBeenAddedToLibrary": "{0} hozzáadva a médiatárhoz",
"ValueSpecialEpisodeName": "Special - {0}", "ValueSpecialEpisodeName": "Special - {0}",
"VersionNumber": "Verzió {0}" "VersionNumber": "Verzió: {0}"
} }

@ -5,7 +5,7 @@
"Artists": "Artisti", "Artists": "Artisti",
"AuthenticationSucceededWithUserName": "{0} autenticato con successo", "AuthenticationSucceededWithUserName": "{0} autenticato con successo",
"Books": "Libri", "Books": "Libri",
"CameraImageUploadedFrom": "A new camera image has been uploaded from {0}", "CameraImageUploadedFrom": "È stata caricata una nuova immagine della fotocamera {0}",
"Channels": "Canali", "Channels": "Canali",
"ChapterNameValue": "Capitolo {0}", "ChapterNameValue": "Capitolo {0}",
"Collections": "Collezioni", "Collections": "Collezioni",
@ -19,9 +19,9 @@
"HeaderCameraUploads": "Caricamenti Fotocamera", "HeaderCameraUploads": "Caricamenti Fotocamera",
"HeaderContinueWatching": "Continua a guardare", "HeaderContinueWatching": "Continua a guardare",
"HeaderFavoriteAlbums": "Album preferiti", "HeaderFavoriteAlbums": "Album preferiti",
"HeaderFavoriteArtists": "Artisti preferiti", "HeaderFavoriteArtists": "Artisti Preferiti",
"HeaderFavoriteEpisodes": "Episodi Preferiti", "HeaderFavoriteEpisodes": "Episodi Preferiti",
"HeaderFavoriteShows": "Show preferiti", "HeaderFavoriteShows": "Serie TV Preferite",
"HeaderFavoriteSongs": "Brani Preferiti", "HeaderFavoriteSongs": "Brani Preferiti",
"HeaderLiveTV": "Diretta TV", "HeaderLiveTV": "Diretta TV",
"HeaderNextUp": "Prossimo", "HeaderNextUp": "Prossimo",

@ -1,97 +1,97 @@
{ {
"Albums": "Альбомдар", "Albums": "Álbomdar",
"AppDeviceValues": "Қолданба: {0}, Құрылғы: {1}", "AppDeviceValues": "Qoldanba: {0}, Qurylǵy: {1}",
"Application": "Қолданба", "Application": "Qoldanba",
"Artists": "Орындаушылар", "Artists": "Oryndaýshylar",
"AuthenticationSucceededWithUserName": "{0} түпнұсқалығын расталуы сәтті", "AuthenticationSucceededWithUserName": "{0} túpnusqalyǵyn rastalýy sátti",
"Books": "Кітаптар", "Books": "Kitaptar",
"CameraImageUploadedFrom": "Жаңа сурет {0} камерасынан жүктеп алынды", "CameraImageUploadedFrom": "Jańa sýret {0} kamerasynan júktep alyndy",
"Channels": "Арналар", "Channels": "Arnalar",
"ChapterNameValue": "{0}-сахна", "ChapterNameValue": "{0}-sahna",
"Collections": "Жиынтықтар", "Collections": "Jıyntyqtar",
"DeviceOfflineWithName": "{0} ажыратылған", "DeviceOfflineWithName": "{0} ajyratylǵan",
"DeviceOnlineWithName": "{0} қосылған", "DeviceOnlineWithName": "{0} qosylǵan",
"FailedLoginAttemptWithUserName": "{0} тарапынан кіру әрекеті сәтсіз", "FailedLoginAttemptWithUserName": "{0} tarapynan kirý áreketi sátsiz",
"Favorites": "Таңдаулылар", "Favorites": "Tańdaýlylar",
"Folders": "Қалталар", "Folders": "Qaltalar",
"Genres": "Жанрлар", "Genres": "Janrlar",
"HeaderAlbumArtists": "Альбом орындаушылары", "HeaderAlbumArtists": "Álbom oryndaýshylary",
"HeaderCameraUploads": "Камерадан жүктелгендер", "HeaderCameraUploads": "Kameradan júktelgender",
"HeaderContinueWatching": "Қарауды жалғастыру", "HeaderContinueWatching": "Qaraýdy jalǵastyrý",
"HeaderFavoriteAlbums": "Таңдаулы альбомдар", "HeaderFavoriteAlbums": "Tańdaýly álbomdar",
"HeaderFavoriteArtists": "Таңдаулы орындаушылар", "HeaderFavoriteArtists": "Tańdaýly oryndaýshylar",
"HeaderFavoriteEpisodes": "Таңдаулы бөлімдер", "HeaderFavoriteEpisodes": "Tańdaýly bólimder",
"HeaderFavoriteShows": "Таңдаулы көрсетімдер", "HeaderFavoriteShows": "Tańdaýly kórsetimder",
"HeaderFavoriteSongs": "Таңдаулы әуендер", "HeaderFavoriteSongs": "Tańdaýly áýender",
"HeaderLiveTV": "Эфир", "HeaderLiveTV": "Efır",
"HeaderNextUp": "Кезекті", "HeaderNextUp": "Kezekti",
"HeaderRecordingGroups": "Жазба топтары", "HeaderRecordingGroups": "Jazba toptary",
"HomeVideos": "Үйлік бейнелер", "HomeVideos": "Úılik beıneler",
"Inherit": "Мұраға иелену", "Inherit": "Muraǵa ıelený",
"ItemAddedWithName": "{0} тасығышханаға үстелінді", "ItemAddedWithName": "{0} tasyǵyshhanaǵa ústelindi",
"ItemRemovedWithName": "{0} тасығышханадан аласталды", "ItemRemovedWithName": "{0} tasyǵyshhanadan alastaldy",
"LabelIpAddressValue": "IP-мекенжайы: {0}", "LabelIpAddressValue": "IP-mekenjaıy: {0}",
"LabelRunningTimeValue": "Іске қосылу уақыты: {0}", "LabelRunningTimeValue": "Oınatý ýaqyty: {0}",
"Latest": "Ең кейінгі", "Latest": "Eń keıingi",
"MessageApplicationUpdated": "Jellyfin Server жаңартылды.", "MessageApplicationUpdated": "Jellyfin Serveri jańartyldy",
"MessageApplicationUpdatedTo": "Jellyfin Server {0} үшін жаңартылды", "MessageApplicationUpdatedTo": "Jellyfin Serveri {0} deńgeıge jańartyldy",
"MessageNamedServerConfigurationUpdatedWithValue": "Сервер теңшелімі ({0} бөлімі) жаңартылды", "MessageNamedServerConfigurationUpdatedWithValue": "Server teńsheliminiń {0} bólimi jańartyldy",
"MessageServerConfigurationUpdated": "Сервер теңшелімі жаңартылды", "MessageServerConfigurationUpdated": "Server teńshelimi jańartyldy",
"MixedContent": "Аралас мазмұн", "MixedContent": "Aralas mazmun",
"Movies": "Фильмдер", "Movies": "Fılmder",
"Music": "Музыка", "Music": "Mýzyka",
"MusicVideos": "Музыкалық бейнелер", "MusicVideos": "Mýzykalyq beıneler",
"NameInstallFailed": "{0} орнатылуы сәтсіз", "NameInstallFailed": "{0} ornatylýy sátsiz",
"NameSeasonNumber": "{0}-маусым", "NameSeasonNumber": "{0}-maýsym",
"NameSeasonUnknown": "Белгісіз маусым", "NameSeasonUnknown": "Belgisiz maýsym",
"NewVersionIsAvailable": "Жаңа Jellyfin Server нұсқасы жүктеп алуға қолжетімді.", "NewVersionIsAvailable": "Jańa Jellyfin Server nusqasy júktep alýǵa qoljetimdi.",
"NotificationOptionApplicationUpdateAvailable": "Қолданба жаңартуы қолжетімді", "NotificationOptionApplicationUpdateAvailable": "Qoldanba jańartýy qoljetimdi",
"NotificationOptionApplicationUpdateInstalled": "Қолданба жаңартуы орнатылды", "NotificationOptionApplicationUpdateInstalled": "Qoldanba jańartýy ornatyldy",
"NotificationOptionAudioPlayback": "Дыбыс ойнатуы басталды", "NotificationOptionAudioPlayback": "Dybys oınatýy bastaldy",
"NotificationOptionAudioPlaybackStopped": "Дыбыс ойнатуы тоқтатылды", "NotificationOptionAudioPlaybackStopped": "Dybys oınatýy toqtatyldy",
"NotificationOptionCameraImageUploaded": "Камерадан фотосурет кері қотарылған", "NotificationOptionCameraImageUploaded": "Kameradan fotosýret keri qotarylǵan",
"NotificationOptionInstallationFailed": "Орнату сәтсіздігі", "NotificationOptionInstallationFailed": "Ornatý sátsizdigi",
"NotificationOptionNewLibraryContent": "Жаңа мазмұн үстелген", "NotificationOptionNewLibraryContent": "Jańa mazmun ústelgen",
"NotificationOptionPluginError": "Плагин сәтсіздігі", "NotificationOptionPluginError": "Plagın sátsizdigi",
"NotificationOptionPluginInstalled": "Плагин орнатылды", "NotificationOptionPluginInstalled": "Plagın ornatyldy",
"NotificationOptionPluginUninstalled": "Плагин орнатуы болдырылмады", "NotificationOptionPluginUninstalled": "Plagın ornatýy boldyrylmady",
"NotificationOptionPluginUpdateInstalled": "Плагин жаңартуы орнатылды", "NotificationOptionPluginUpdateInstalled": "Plagın jańartýy ornatyldy",
"NotificationOptionServerRestartRequired": "Серверді қайта іске қосу қажет", "NotificationOptionServerRestartRequired": "Serverdi qaıta iske qosý qajet",
"NotificationOptionTaskFailed": "Жоспарлаған тапсырма сәтсіздігі", "NotificationOptionTaskFailed": "Josparlaǵan tapsyrma sátsizdigi",
"NotificationOptionUserLockedOut": "Пайдаланушы құрсаулы", "NotificationOptionUserLockedOut": "Paıdalanýshy qursaýly",
"NotificationOptionVideoPlayback": "Бейне ойнатуы басталды", "NotificationOptionVideoPlayback": "Beıne oınatýy bastaldy",
"NotificationOptionVideoPlaybackStopped": "Бейне ойнатуы тоқтатылды", "NotificationOptionVideoPlaybackStopped": "Beıne oınatýy toqtatyldy",
"Photos": "Фотосуреттер", "Photos": "Fotosýretter",
"Playlists": "Ойнату тізімдері", "Playlists": "Oınatý tizimderi",
"Plugin": "Плагин", "Plugin": "Plagın",
"PluginInstalledWithName": "{0} орнатылды", "PluginInstalledWithName": "{0} ornatyldy",
"PluginUninstalledWithName": "{0} жойылды", "PluginUninstalledWithName": "{0} joıyldy",
"PluginUpdatedWithName": "{0} жаңартылды", "PluginUpdatedWithName": "{0} jańartyldy",
"ProviderValue": "Жеткізуші: {0}", "ProviderValue": "Jetkizýshi: {0}",
"ScheduledTaskFailedWithName": "{0} сәтсіз", "ScheduledTaskFailedWithName": "{0} sátsiz",
"ScheduledTaskStartedWithName": "{0} іске қосылды", "ScheduledTaskStartedWithName": "{0} iske qosyldy",
"ServerNameNeedsToBeRestarted": "{0} қайта іске қосу қажет", "ServerNameNeedsToBeRestarted": "{0} qaıta iske qosý qajet",
"Shows": "Көрсетімдер", "Shows": "Kórsetimder",
"Songs": "Әуендер", "Songs": "Áýender",
"StartupEmbyServerIsLoading": "Jellyfin Server жүктелуде. Әрекетті көп ұзамай қайталаңыз.", "StartupEmbyServerIsLoading": "Jellyfin Server júktelýde. Áreketti kóp uzamaı qaıtalańyz.",
"SubtitleDownloadFailureForItem": "Субтитрлер {0} үшін жүктеліп алынуы сәтсіз", "SubtitleDownloadFailureForItem": "Субтитрлер {0} үшін жүктеліп алынуы сәтсіз",
"SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}", "SubtitleDownloadFailureFromForItem": "{1} úshin sýbtıtrlerdi {0} kózinen júktep alý sátsiz",
"SubtitlesDownloadedForItem": "{0} үшін субтитрлер жүктеліп алынды", "SubtitlesDownloadedForItem": "{0} úshin sýbtıtrler júktelip alyndy",
"Sync": "Үндестіру", "Sync": "Úndestirý",
"System": "Жүйе", "System": "ıe",
"TvShows": "ТД-көрсетімдер", "TvShows": "TD-kórsetimder",
"User": "Пайдаланушы", "User": "Paıdalanýshy",
"UserCreatedWithName": "Пайдаланушы {0} жасалған", "UserCreatedWithName": "Paıdalanýshy {0} jasalǵan",
"UserDeletedWithName": "Пайдаланушы {0} жойылған", "UserDeletedWithName": "Paıdalanýshy {0} joıylǵan",
"UserDownloadingItemWithValues": "{0} мынаны жүктеп алуда: {1}", "UserDownloadingItemWithValues": "{0} mynany júktep alýda: {1}",
"UserLockedOutWithName": "Пайдаланушы {0} құрсаулы", "UserLockedOutWithName": "Paıdalanýshy {0} qursaýly",
"UserOfflineFromDevice": "{0} - {1} тарапынан ажыратылған", "UserOfflineFromDevice": "{0} - {1} tarapynan ajyratylǵan",
"UserOnlineFromDevice": "{0} - {1} арқылы қосылған", "UserOnlineFromDevice": "{0} - {1} arqyly qosylǵan",
"UserPasswordChangedWithName": "Пайдаланушы {0} үшін құпия сөз өзгертілді", "UserPasswordChangedWithName": "Paıdalanýshy {0} úshin paról ózgertildi",
"UserPolicyUpdatedWithName": "Пайдаланушы {0} үшін саясаттары жаңартылды", "UserPolicyUpdatedWithName": "Paıdalanýshy {0} úshin saıasattary jańartyldy",
"UserStartedPlayingItemWithValues": "{0} - {1} ойнатуын {2} бастады", "UserStartedPlayingItemWithValues": "{0} - {1} oınatýyn {2} bastady",
"UserStoppedPlayingItemWithValues": "{0} - {1} ойнатуын {2} тоқтатты", "UserStoppedPlayingItemWithValues": "{0} - {1} oınatýyn {2} toqtatty",
"ValueHasBeenAddedToLibrary": "{0} (тасығышханаға үстелінді)", "ValueHasBeenAddedToLibrary": "{0} (tasyǵyshhanaǵa ústelindi)",
"ValueSpecialEpisodeName": "Арнайы - {0}", "ValueSpecialEpisodeName": "Arnaıy - {0}",
"VersionNumber": "Нұсқасы: {0}" "VersionNumber": "Nusqasy {0}"
} }

@ -1,10 +1,10 @@
{ {
"Albums": "Albums", "Albums": "Album-album",
"AppDeviceValues": "App: {0}, Device: {1}", "AppDeviceValues": "App: {0}, Device: {1}",
"Application": "Application", "Application": "Application",
"Artists": "Artists", "Artists": "Artis-artis",
"AuthenticationSucceededWithUserName": "{0} successfully authenticated", "AuthenticationSucceededWithUserName": "{0} successfully authenticated",
"Books": "Books", "Books": "Buku-buku",
"CameraImageUploadedFrom": "A new camera image has been uploaded from {0}", "CameraImageUploadedFrom": "A new camera image has been uploaded from {0}",
"Channels": "Channels", "Channels": "Channels",
"ChapterNameValue": "Chapter {0}", "ChapterNameValue": "Chapter {0}",

@ -5,28 +5,28 @@
"Artists": "Artiesten", "Artists": "Artiesten",
"AuthenticationSucceededWithUserName": "{0} is succesvol geverifieerd", "AuthenticationSucceededWithUserName": "{0} is succesvol geverifieerd",
"Books": "Boeken", "Books": "Boeken",
"CameraImageUploadedFrom": "A new camera image has been uploaded from {0}", "CameraImageUploadedFrom": "Er is een nieuwe foto toegevoegd via {0}",
"Channels": "Kanalen", "Channels": "Kanalen",
"ChapterNameValue": "Hoofdstuk {0}", "ChapterNameValue": "Hoofdstuk {0}",
"Collections": "Collecties", "Collections": "Collecties",
"DeviceOfflineWithName": "{0} is losgekoppeld", "DeviceOfflineWithName": "{0} heeft de verbinding verbroken",
"DeviceOnlineWithName": "{0} is verbonden", "DeviceOnlineWithName": "{0} is verbonden",
"FailedLoginAttemptWithUserName": "Mislukte aanmeld poging van {0}", "FailedLoginAttemptWithUserName": "Mislukte aanmeld poging van {0}",
"Favorites": "Favorieten", "Favorites": "Favorieten",
"Folders": "Mappen", "Folders": "Mappen",
"Genres": "Genres", "Genres": "Genres",
"HeaderAlbumArtists": "Albumartiesten", "HeaderAlbumArtists": "Albumartiesten",
"HeaderCameraUploads": "Camera uploads", "HeaderCameraUploads": "Camera-uploads",
"HeaderContinueWatching": "Kijken hervatten", "HeaderContinueWatching": "Kijken hervatten",
"HeaderFavoriteAlbums": "Favoriete albums", "HeaderFavoriteAlbums": "Favoriete albums",
"HeaderFavoriteArtists": "Favoriete artiesten", "HeaderFavoriteArtists": "Favoriete artiesten",
"HeaderFavoriteEpisodes": "Favoriete afleveringen", "HeaderFavoriteEpisodes": "Favoriete afleveringen",
"HeaderFavoriteShows": "Favoriete shows", "HeaderFavoriteShows": "Favoriete shows",
"HeaderFavoriteSongs": "Favoriete titels", "HeaderFavoriteSongs": "Favoriete nummers",
"HeaderLiveTV": "Live TV", "HeaderLiveTV": "Live TV",
"HeaderNextUp": "Volgende", "HeaderNextUp": "Volgende",
"HeaderRecordingGroups": "Opnamegroepen", "HeaderRecordingGroups": "Opnamegroepen",
"HomeVideos": "Thuis video's", "HomeVideos": "Start video's",
"Inherit": "Overerven", "Inherit": "Overerven",
"ItemAddedWithName": "{0} is toegevoegd aan de bibliotheek", "ItemAddedWithName": "{0} is toegevoegd aan de bibliotheek",
"ItemRemovedWithName": "{0} is verwijderd uit de bibliotheek", "ItemRemovedWithName": "{0} is verwijderd uit de bibliotheek",
@ -34,22 +34,22 @@
"LabelRunningTimeValue": "Looptijd: {0}", "LabelRunningTimeValue": "Looptijd: {0}",
"Latest": "Nieuwste", "Latest": "Nieuwste",
"MessageApplicationUpdated": "Jellyfin Server is bijgewerkt", "MessageApplicationUpdated": "Jellyfin Server is bijgewerkt",
"MessageApplicationUpdatedTo": "Jellyfin Server has been updated to {0}", "MessageApplicationUpdatedTo": "Jellyfin Server is bijgewerkt naar {0}",
"MessageNamedServerConfigurationUpdatedWithValue": "Sectie {0} van de server configuratie is bijgewerkt", "MessageNamedServerConfigurationUpdatedWithValue": "Sectie {0} van de server configuratie is bijgewerkt",
"MessageServerConfigurationUpdated": "Server configuratie is bijgewerkt", "MessageServerConfigurationUpdated": "Server configuratie is bijgewerkt",
"MixedContent": "Gemengde inhoud", "MixedContent": "Gemengde inhoud",
"Movies": "Films", "Movies": "Films",
"Music": "Muziek", "Music": "Muziek",
"MusicVideos": "Muziekvideo's", "MusicVideos": "Muziekvideo's",
"NameInstallFailed": "{0} installation failed", "NameInstallFailed": "{0} installatie mislukt",
"NameSeasonNumber": "Seizoen {0}", "NameSeasonNumber": "Seizoen {0}",
"NameSeasonUnknown": "Seizoen onbekend", "NameSeasonUnknown": "Seizoen onbekend",
"NewVersionIsAvailable": "A new version of Jellyfin Server is available for download.", "NewVersionIsAvailable": "Een nieuwe versie van Jellyfin Server is beschikbaar om te downloaden.",
"NotificationOptionApplicationUpdateAvailable": "Programma-update beschikbaar", "NotificationOptionApplicationUpdateAvailable": "Programma-update beschikbaar",
"NotificationOptionApplicationUpdateInstalled": "Programma-update geïnstalleerd", "NotificationOptionApplicationUpdateInstalled": "Programma-update geïnstalleerd",
"NotificationOptionAudioPlayback": "Geluid gestart", "NotificationOptionAudioPlayback": "Muziek gestart",
"NotificationOptionAudioPlaybackStopped": "Geluid gestopt", "NotificationOptionAudioPlaybackStopped": "Muziek gestopt",
"NotificationOptionCameraImageUploaded": "Camera afbeelding geüpload", "NotificationOptionCameraImageUploaded": "Camera-afbeelding geüpload",
"NotificationOptionInstallationFailed": "Installatie mislukt", "NotificationOptionInstallationFailed": "Installatie mislukt",
"NotificationOptionNewLibraryContent": "Nieuwe content toegevoegd", "NotificationOptionNewLibraryContent": "Nieuwe content toegevoegd",
"NotificationOptionPluginError": "Plug-in fout", "NotificationOptionPluginError": "Plug-in fout",
@ -70,12 +70,12 @@
"ProviderValue": "Aanbieder: {0}", "ProviderValue": "Aanbieder: {0}",
"ScheduledTaskFailedWithName": "{0} is mislukt", "ScheduledTaskFailedWithName": "{0} is mislukt",
"ScheduledTaskStartedWithName": "{0} is gestart", "ScheduledTaskStartedWithName": "{0} is gestart",
"ServerNameNeedsToBeRestarted": "{0} needs to be restarted", "ServerNameNeedsToBeRestarted": "{0} moet herstart worden",
"Shows": "Series", "Shows": "Series",
"Songs": "Titels", "Songs": "Nummers",
"StartupEmbyServerIsLoading": "Jellyfin Server is aan het laden, probeer het later opnieuw.", "StartupEmbyServerIsLoading": "Jellyfin Server is aan het laden, probeer het later opnieuw.",
"SubtitleDownloadFailureForItem": "Downloaden van ondertiteling voor {0} is mislukt", "SubtitleDownloadFailureForItem": "Downloaden van ondertiteling voor {0} is mislukt",
"SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}", "SubtitleDownloadFailureFromForItem": "Ondertitels konden niet gedownload worden van {0} voor {1}",
"SubtitlesDownloadedForItem": "Ondertiteling voor {0} is gedownload", "SubtitlesDownloadedForItem": "Ondertiteling voor {0} is gedownload",
"Sync": "Synchronisatie", "Sync": "Synchronisatie",
"System": "Systeem", "System": "Systeem",
@ -89,9 +89,9 @@
"UserOnlineFromDevice": "{0} heeft verbinding met {1}", "UserOnlineFromDevice": "{0} heeft verbinding met {1}",
"UserPasswordChangedWithName": "Wachtwoord voor {0} is gewijzigd", "UserPasswordChangedWithName": "Wachtwoord voor {0} is gewijzigd",
"UserPolicyUpdatedWithName": "Gebruikersbeleid gewijzigd voor {0}", "UserPolicyUpdatedWithName": "Gebruikersbeleid gewijzigd voor {0}",
"UserStartedPlayingItemWithValues": "{0} heeft afspelen van {1} gestart", "UserStartedPlayingItemWithValues": "{0} heeft afspelen van {1} gestart op {2}",
"UserStoppedPlayingItemWithValues": "{0} heeft afspelen van {1} gestopt", "UserStoppedPlayingItemWithValues": "{0} heeft afspelen van {1} gestopt op {2}",
"ValueHasBeenAddedToLibrary": "{0} has been added to your media library", "ValueHasBeenAddedToLibrary": "{0} is toegevoegd aan je mediabibliotheek",
"ValueSpecialEpisodeName": "Speciaal - {0}", "ValueSpecialEpisodeName": "Speciaal - {0}",
"VersionNumber": "Versie {0}" "VersionNumber": "Versie {0}"
} }

@ -5,7 +5,7 @@
"Artists": "Исполнители", "Artists": "Исполнители",
"AuthenticationSucceededWithUserName": "{0} - авторизация успешна", "AuthenticationSucceededWithUserName": "{0} - авторизация успешна",
"Books": "Литература", "Books": "Литература",
"CameraImageUploadedFrom": "Новое фото было выложено с {0}", "CameraImageUploadedFrom": "Новое фото было выложено с камеры {0}",
"Channels": "Каналы", "Channels": "Каналы",
"ChapterNameValue": "Сцена {0}", "ChapterNameValue": "Сцена {0}",
"Collections": "Коллекции", "Collections": "Коллекции",
@ -31,20 +31,20 @@
"ItemAddedWithName": "{0} - добавлено в медиатеку", "ItemAddedWithName": "{0} - добавлено в медиатеку",
"ItemRemovedWithName": "{0} - изъято из медиатеки", "ItemRemovedWithName": "{0} - изъято из медиатеки",
"LabelIpAddressValue": "IP-адрес: {0}", "LabelIpAddressValue": "IP-адрес: {0}",
"LabelRunningTimeValue": "Время выполнения: {0}", "LabelRunningTimeValue": "Длительность: {0}",
"Latest": "Новейшее", "Latest": "Новейшее",
"MessageApplicationUpdated": "Jellyfin Server был обновлён", "MessageApplicationUpdated": "Jellyfin Server был обновлён",
"MessageApplicationUpdatedTo": "Jellyfin Server был обновлён до {0}", "MessageApplicationUpdatedTo": "Jellyfin Server был обновлён до {0}",
"MessageNamedServerConfigurationUpdatedWithValue": "Конфиг-ия сервера (раздел {0}) была обновлена", "MessageNamedServerConfigurationUpdatedWithValue": "Конфиг-ия сервера (раздел {0}) была обновлена",
"MessageServerConfigurationUpdated": "Конфиг-ия сервера была обновлена", "MessageServerConfigurationUpdated": "Конфиг-ия сервера была обновлена",
"MixedContent": "Смешанное содержание", "MixedContent": "Смешанное содержимое",
"Movies": "Кино", "Movies": "Кино",
"Music": "Музыка", "Music": "Музыка",
"MusicVideos": "Муз. видео", "MusicVideos": "Муз. видео",
"NameInstallFailed": "Установка {0} неудачна", "NameInstallFailed": "Установка {0} неудачна",
"NameSeasonNumber": "Сезон {0}", "NameSeasonNumber": "Сезон {0}",
"NameSeasonUnknown": "Сезон неопознан", "NameSeasonUnknown": "Сезон неопознан",
"NewVersionIsAvailable": "Имеется новая версия Jellyfin Server", "NewVersionIsAvailable": "Новая версия Jellyfin Server доступна для загрузки.",
"NotificationOptionApplicationUpdateAvailable": "Имеется обновление приложения", "NotificationOptionApplicationUpdateAvailable": "Имеется обновление приложения",
"NotificationOptionApplicationUpdateInstalled": "Обновление приложения установлено", "NotificationOptionApplicationUpdateInstalled": "Обновление приложения установлено",
"NotificationOptionAudioPlayback": "Воспр-ие аудио зап-но", "NotificationOptionAudioPlayback": "Воспр-ие аудио зап-но",
@ -75,7 +75,7 @@
"Songs": "Композиции", "Songs": "Композиции",
"StartupEmbyServerIsLoading": "Jellyfin Server загружается. Повторите попытку в ближайшее время.", "StartupEmbyServerIsLoading": "Jellyfin Server загружается. Повторите попытку в ближайшее время.",
"SubtitleDownloadFailureForItem": "Субтитры к {0} не удалось загрузить", "SubtitleDownloadFailureForItem": "Субтитры к {0} не удалось загрузить",
"SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}", "SubtitleDownloadFailureFromForItem": "Субтитры к {1} не удалось загрузить с {0}",
"SubtitlesDownloadedForItem": "Субтитры к {0} загружены", "SubtitlesDownloadedForItem": "Субтитры к {0} загружены",
"Sync": "Синхро", "Sync": "Синхро",
"System": "Система", "System": "Система",

@ -116,6 +116,7 @@ namespace Emby.Server.Implementations.Updates
private readonly IApplicationHost _applicationHost; private readonly IApplicationHost _applicationHost;
private readonly ICryptoProvider _cryptographyProvider; private readonly ICryptoProvider _cryptographyProvider;
private readonly IZipClient _zipClient;
// netframework or netcore // netframework or netcore
private readonly string _packageRuntime; private readonly string _packageRuntime;
@ -129,6 +130,7 @@ namespace Emby.Server.Implementations.Updates
IServerConfigurationManager config, IServerConfigurationManager config,
IFileSystem fileSystem, IFileSystem fileSystem,
ICryptoProvider cryptographyProvider, ICryptoProvider cryptographyProvider,
IZipClient zipClient,
string packageRuntime) string packageRuntime)
{ {
if (loggerFactory == null) if (loggerFactory == null)
@ -146,6 +148,7 @@ namespace Emby.Server.Implementations.Updates
_config = config; _config = config;
_fileSystem = fileSystem; _fileSystem = fileSystem;
_cryptographyProvider = cryptographyProvider; _cryptographyProvider = cryptographyProvider;
_zipClient = zipClient;
_packageRuntime = packageRuntime; _packageRuntime = packageRuntime;
_logger = loggerFactory.CreateLogger(nameof(InstallationManager)); _logger = loggerFactory.CreateLogger(nameof(InstallationManager));
} }
@ -526,14 +529,18 @@ namespace Emby.Server.Implementations.Updates
private async Task PerformPackageInstallation(IProgress<double> progress, string target, PackageVersionInfo package, CancellationToken cancellationToken) private async Task PerformPackageInstallation(IProgress<double> progress, string target, PackageVersionInfo package, CancellationToken cancellationToken)
{ {
// Target based on if it is an archive or single assembly
// zip archives are assumed to contain directory structures relative to our ProgramDataPath
var extension = Path.GetExtension(package.targetFilename); var extension = Path.GetExtension(package.targetFilename);
var isArchive = string.Equals(extension, ".zip", StringComparison.OrdinalIgnoreCase) || string.Equals(extension, ".rar", StringComparison.OrdinalIgnoreCase) || string.Equals(extension, ".7z", StringComparison.OrdinalIgnoreCase); var isArchive = string.Equals(extension, ".zip", StringComparison.OrdinalIgnoreCase);
if (!isArchive)
{
_logger.LogError("Only zip packages are supported. {Filename} is not a zip archive.", package.targetFilename);
return;
}
if (target == null) if (target == null)
{ {
target = Path.Combine(isArchive ? _appPaths.TempUpdatePath : _appPaths.PluginsPath, package.targetFilename); target = Path.Combine(_appPaths.PluginsPath, Path.GetFileNameWithoutExtension(package.targetFilename));
} }
// Download to temporary file so that, if interrupted, it won't destroy the existing installation // Download to temporary file so that, if interrupted, it won't destroy the existing installation
@ -547,36 +554,19 @@ namespace Emby.Server.Implementations.Updates
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
// Validate with a checksum // TODO: Validate with a checksum, *properly*
var packageChecksum = string.IsNullOrWhiteSpace(package.checksum) ? Guid.Empty : new Guid(package.checksum);
if (!packageChecksum.Equals(Guid.Empty)) // support for legacy uploads for now
{
using (var stream = File.OpenRead(tempFile))
{
var check = Guid.Parse(BitConverter.ToString(_cryptographyProvider.ComputeMD5(stream)).Replace("-", string.Empty));
if (check != packageChecksum)
{
throw new Exception(string.Format("Download validation failed for {0}. Probably corrupted during transfer.", package.name));
}
}
}
cancellationToken.ThrowIfCancellationRequested();
// Success - move it to the real target // Success - move it to the real target
try try
{ {
Directory.CreateDirectory(Path.GetDirectoryName(target)); using (var stream = File.OpenRead(tempFile))
File.Copy(tempFile, target, true);
//If it is an archive - write out a version file so we know what it is
if (isArchive)
{ {
File.WriteAllText(target + ".ver", package.versionStr); _zipClient.ExtractAllFromZip(stream, target, true);
} }
} }
catch (IOException ex) catch (IOException ex)
{ {
_logger.LogError(ex, "Error attempting to move file from {TempFile} to {TargetFile}", tempFile, target); _logger.LogError(ex, "Error attempting to extract {TempFile} to {TargetFile}", tempFile, target);
throw; throw;
} }

@ -8,7 +8,6 @@ using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller; using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Devices;
@ -71,7 +70,6 @@ namespace MediaBrowser.Api.Playback
protected IMediaSourceManager MediaSourceManager { get; private set; } protected IMediaSourceManager MediaSourceManager { get; private set; }
protected IJsonSerializer JsonSerializer { get; private set; } protected IJsonSerializer JsonSerializer { get; private set; }
public static IHttpClient HttpClient;
protected IAuthorizationContext AuthorizationContext { get; private set; } protected IAuthorizationContext AuthorizationContext { get; private set; }
protected EncodingHelper EncodingHelper { get; set; } protected EncodingHelper EncodingHelper { get; set; }

@ -1,4 +1,5 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Dlna;
@ -33,6 +34,7 @@ namespace MediaBrowser.Api.Playback.Progressive
public class AudioService : BaseProgressiveStreamingService public class AudioService : BaseProgressiveStreamingService
{ {
public AudioService( public AudioService(
IHttpClient httpClient,
IServerConfigurationManager serverConfig, IServerConfigurationManager serverConfig,
IUserManager userManager, IUserManager userManager,
ILibraryManager libraryManager, ILibraryManager libraryManager,
@ -46,7 +48,8 @@ namespace MediaBrowser.Api.Playback.Progressive
IJsonSerializer jsonSerializer, IJsonSerializer jsonSerializer,
IAuthorizationContext authorizationContext, IAuthorizationContext authorizationContext,
IEnvironmentInfo environmentInfo) IEnvironmentInfo environmentInfo)
: base(serverConfig, : base(httpClient,
serverConfig,
userManager, userManager,
libraryManager, libraryManager,
isoManager, isoManager,

@ -26,8 +26,10 @@ namespace MediaBrowser.Api.Playback.Progressive
public abstract class BaseProgressiveStreamingService : BaseStreamingService public abstract class BaseProgressiveStreamingService : BaseStreamingService
{ {
protected readonly IEnvironmentInfo EnvironmentInfo; protected readonly IEnvironmentInfo EnvironmentInfo;
protected IHttpClient HttpClient { get; private set; }
public BaseProgressiveStreamingService( public BaseProgressiveStreamingService(
IHttpClient httpClient,
IServerConfigurationManager serverConfig, IServerConfigurationManager serverConfig,
IUserManager userManager, IUserManager userManager,
ILibraryManager libraryManager, ILibraryManager libraryManager,
@ -55,6 +57,7 @@ namespace MediaBrowser.Api.Playback.Progressive
authorizationContext) authorizationContext)
{ {
EnvironmentInfo = environmentInfo; EnvironmentInfo = environmentInfo;
HttpClient = httpClient;
} }
/// <summary> /// <summary>

@ -1,4 +1,5 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Dlna;
@ -69,6 +70,7 @@ namespace MediaBrowser.Api.Playback.Progressive
public class VideoService : BaseProgressiveStreamingService public class VideoService : BaseProgressiveStreamingService
{ {
public VideoService( public VideoService(
IHttpClient httpClient,
IServerConfigurationManager serverConfig, IServerConfigurationManager serverConfig,
IUserManager userManager, IUserManager userManager,
ILibraryManager libraryManager, ILibraryManager libraryManager,
@ -82,7 +84,8 @@ namespace MediaBrowser.Api.Playback.Progressive
IJsonSerializer jsonSerializer, IJsonSerializer jsonSerializer,
IAuthorizationContext authorizationContext, IAuthorizationContext authorizationContext,
IEnvironmentInfo environmentInfo) IEnvironmentInfo environmentInfo)
: base(serverConfig, : base(httpClient,
serverConfig,
userManager, userManager,
libraryManager, libraryManager,
isoManager, isoManager,

@ -77,6 +77,7 @@ namespace MediaBrowser.Api.Playback
public class UniversalAudioService : BaseApiService public class UniversalAudioService : BaseApiService
{ {
public UniversalAudioService( public UniversalAudioService(
IHttpClient httpClient,
IServerConfigurationManager serverConfigurationManager, IServerConfigurationManager serverConfigurationManager,
IUserManager userManager, IUserManager userManager,
ILibraryManager libraryManager, ILibraryManager libraryManager,
@ -95,6 +96,7 @@ namespace MediaBrowser.Api.Playback
IEnvironmentInfo environmentInfo, IEnvironmentInfo environmentInfo,
ILoggerFactory loggerFactory) ILoggerFactory loggerFactory)
{ {
HttpClient = httpClient;
ServerConfigurationManager = serverConfigurationManager; ServerConfigurationManager = serverConfigurationManager;
UserManager = userManager; UserManager = userManager;
LibraryManager = libraryManager; LibraryManager = libraryManager;
@ -115,6 +117,7 @@ namespace MediaBrowser.Api.Playback
_logger = loggerFactory.CreateLogger(nameof(UniversalAudioService)); _logger = loggerFactory.CreateLogger(nameof(UniversalAudioService));
} }
protected IHttpClient HttpClient { get; private set; }
protected IServerConfigurationManager ServerConfigurationManager { get; private set; } protected IServerConfigurationManager ServerConfigurationManager { get; private set; }
protected IUserManager UserManager { get; private set; } protected IUserManager UserManager { get; private set; }
protected ILibraryManager LibraryManager { get; private set; } protected ILibraryManager LibraryManager { get; private set; }
@ -323,7 +326,8 @@ namespace MediaBrowser.Api.Playback
} }
else else
{ {
var service = new AudioService(ServerConfigurationManager, var service = new AudioService(HttpClient,
ServerConfigurationManager,
UserManager, UserManager,
LibraryManager, LibraryManager,
IsoManager, IsoManager,

@ -12,8 +12,6 @@ namespace MediaBrowser.Controller.Net
public string ContentType { get; set; } public string ContentType { get; set; }
public TimeSpan? CacheDuration { get; set; } public TimeSpan? CacheDuration { get; set; }
public DateTime? DateLastModified { get; set; } public DateTime? DateLastModified { get; set; }
public Guid CacheKey { get; set; }
public Func<Task<Stream>> ContentFactory { get; set; } public Func<Task<Stream>> ContentFactory { get; set; }
public bool IsHeadRequest { get; set; } public bool IsHeadRequest { get; set; }

@ -297,7 +297,7 @@ namespace MediaBrowser.Model.Dlna
int? inputAudioChannels = audioStream?.Channels; int? inputAudioChannels = audioStream?.Channels;
int? inputAudioBitrate = audioStream?.BitDepth; int? inputAudioBitrate = audioStream?.BitDepth;
int? inputAudioSampleRate = audioStream?.SampleRate; int? inputAudioSampleRate = audioStream?.SampleRate;
int? inputAudioBitDepth = audioStream.BitDepth; int? inputAudioBitDepth = audioStream?.BitDepth;
if (directPlayMethods.Count() > 0) if (directPlayMethods.Count() > 0)
{ {

@ -1 +1 @@
Subproject commit c7ce1ac8eccd50f1bd759b30fbe60ea797ffe86e Subproject commit b4842e325e9d7d708193b4a27060cfe4c978df5e

@ -1,4 +1,4 @@
using System.Reflection; using System.Reflection;
[assembly: AssemblyVersion("10.1.0")] [assembly: AssemblyVersion("10.2.0")]
[assembly: AssemblyFileVersion("10.1.0")] [assembly: AssemblyFileVersion("10.2.0")]

@ -1,3 +1,111 @@
jellyfin (10.2.0-2) unstable; urgency=medium
* jellyfin:
* PR452 Use EF Core for Activity database
* PR535 Clean up streambuilder
* PR655 Support trying local branches in submodule
* PR656 Do some logging in MediaInfoService
* PR657 Remove conditions that are always true/false
* PR661 Fix NullRef from progress report
* PR663 Use TagLibSharp Nuget package
* PR664 Revert "Fix segment_time_delta for ffmpeg 4.1"
* PR666 Add cross-platform build for arm64
* PR668 Return Audio objects from MusicAlbum.Tracks
* PR671 Set EnableRaisingEvents correctly
* PR672 Remove unconditional caching, modified since header and use ETags
* PR677 Fix arm32 Docker
* PR681 Fix Windows build script errors + pin ffmpeg to 4.0
* PR686 Disable some StyleCop warnings
* PR687 Fix some analyzer warnings
* PR689 Fix RPM package build for fedora
* PR702 Fix debug build on windows
* PR706 Make another docker layer reusable
* PR709 Fix always null expressions
* PR710 Fix a spelling mistake
* PR711 Remove remnants of system events
* PR713 Fix empty statement in DidlBuilder.cs
* PR716 Remove more compile time warnings
* PR721 Change image dimentions from double to int
* PR723 Minor improvements to db code
* PR724 Move Skia back into it's own project
* PR726 Clean up IFileSystem wrappers around stdlib.
* PR727 Change default aspect ratio to 2/3 from 0
* PR728 Use ffmpeg from jrottenberg/ffmpeg
* PR732 Reworked LocalizationManager to load data async
* PR733 Remove unused function
* PR734 Fix more analyzer warnings
* PR736 Start startup tasks async
* PR737 Add AssemblyInfo for Jellyfin.Drawing.Skia
* PR739 Change multi version logic for movies
* PR740 Remove code for pre-installed plugins & properly check if file exists
* PR756 Make cache dir configurable
* PR757 Fix default aspect ratio
* PR758 Add password field to initial setup
* PR764 Remove dead code, made some functions properly async
* PR769 Fix conditions where the ! was swallowed in #726
* PR774 reimplement support for plugin repository
* PR782 Remove commented file MediaBrowser.LocalMetadata.Savers.PersonXmlSaver
* PR783 Update builds to use #749 and #756
* PR788 Fix more warnings
* PR794 Remove MoreLINQ
* PR797 Fix all warnings
* PR798 Cleanup around the api endpoints
* PR800 Add CentOS and update rpm spec for the cachedir option
* PR802 Fix build error
* PR804 Handle new option parser properly
* PR805 Add weblate translation status to README
* PR807 Fix restart script in OS packages
* PR810 Fix loading of rating files
* PR812 Fix up the explicit docs links in the README
* PR819 Some small changes in Device.cs and DidlBuilder.cs
* PR822 Complete rename ImageSize -> ImageDimensions
* PR824 Improved Docker pkgbuild
* PR831 Move some arrays to generics
* PR833 Add await to GetCountries in LocalizationService
* PR834 Add donation badge and reorganize badges
* PR838 Quick style fix
* PR840 Fix more warnings
* PR841 Fix OC badge to all and add forum badge
* PR842 Use VAAPI-enabled ffmpeg
* PR852 Use SQLitePCL.pretty.netstandard on NuGet
* PR853 Fix poor handling of cache directories
* PR864: Add support for ZIP plugin archives
* PR868: Fix audio streaming via BaseProgressiveStreamingService
* PR869: Remove DLL support and require all packages/plugins to be zip archives
* PR872: Fix potential NullReferenceException
* PR890: Drop ETag and use Last-Modified header
* PR892: Add jellyfin-ffmpeg and versioning to package deps
* PR899: DLNA: Fix race condition leading to missing device names
* PR901: Properly dispose HttpWebResponse when the request failed to avoid 'too many open files'
* PR909: Fix docker arm builds
* PR910: Enhance Dockerfiles
* PR911: Checkout submodules in Docker Hub hook
* jellyfin-web:
* PR51 remove more code for sync and camera roll
* PR56 Use English for fallback translations and clean up language files
* PR58 Css slider fixes
* PR62 remove BOM markers
* PR65 Fix profile image not being shown on profile page
* PR73 Dev sync
* PR74 Add download menu option to media items
* PR75 User profile fixes
* PR76 Fix syntax error caused by deminification
* PR79 Remove unused Connect related from the frontend
* PR80 Remove games
* PR92 Added frontend support for a password field on setup
* PR94 Update british strings
* PR95 add display language option back
* PR112 Removed seasonal theme support
* PR116 Consolidate all strings into a single file per language
* PR117 Fix volume slider behavior
* PR118 Enable and fix PiP for Safari
* PR119 Make the toggle track visible on all themes
* PR121 Fix syntax error in site.js
* PR127 Change sharedcomponents module to core
* PR135 Make sure fallback culture is always available
-- Jellyfin Packaging Team <packaging@jellyfin.org> Fri, 15 Feb 2019 20:51:25 -0500
jellyfin (10.1.0-1) unstable; urgency=medium jellyfin (10.1.0-1) unstable; urgency=medium
* jellyfin: * jellyfin:

@ -18,6 +18,11 @@ Replaces: mediabrowser, emby, emby-server-beta, jellyfin-dev, emby-server
Breaks: mediabrowser, emby, emby-server-beta, jellyfin-dev, emby-server Breaks: mediabrowser, emby, emby-server-beta, jellyfin-dev, emby-server
Conflicts: mediabrowser, emby, emby-server-beta, jellyfin-dev, emby-server Conflicts: mediabrowser, emby, emby-server-beta, jellyfin-dev, emby-server
Architecture: any Architecture: any
Depends: at, libsqlite3-0, ffmpeg, libfontconfig1, libfreetype6, libssl1.0.0 | libssl1.0.2 Depends: at,
libsqlite3-0,
ffmpeg (<7:4.1) | jellyfin-ffmpeg,
libfontconfig1,
libfreetype6,
libssl1.0.0 | libssl1.0.2
Description: Jellyfin is a home media server. Description: Jellyfin is a home media server.
It is built on top of other popular open source technologies such as Service Stack, jQuery, jQuery mobile, and Mono. It features a REST-based api with built-in documentation to facilitate client development. We also have client libraries for our api to enable rapid development. It is built on top of other popular open source technologies such as Service Stack, jQuery, jQuery mobile, and Mono. It features a REST-based api with built-in documentation to facilitate client development. We also have client libraries for our api to enable rapid development.

@ -7,8 +7,8 @@
%endif %endif
Name: jellyfin Name: jellyfin
Version: 10.1.0 Version: 10.2.0
Release: 1%{?dist} Release: 2%{?dist}
Summary: The Free Software Media Browser Summary: The Free Software Media Browser
License: GPLv2 License: GPLv2
URL: https://jellyfin.media URL: https://jellyfin.media
@ -140,6 +140,110 @@ fi
%systemd_postun_with_restart jellyfin.service %systemd_postun_with_restart jellyfin.service
%changelog %changelog
* Fri Feb 15 2019 Jellyfin Packaging Team <packaging@jellyfin.org>
- jellyfin:
- PR452 Use EF Core for Activity database
- PR535 Clean up streambuilder
- PR655 Support trying local branches in submodule
- PR656 Do some logging in MediaInfoService
- PR657 Remove conditions that are always true/false
- PR661 Fix NullRef from progress report
- PR663 Use TagLibSharp Nuget package
- PR664 Revert "Fix segment_time_delta for ffmpeg 4.1"
- PR666 Add cross-platform build for arm64
- PR668 Return Audio objects from MusicAlbum.Tracks
- PR671 Set EnableRaisingEvents correctly
- PR672 Remove unconditional caching, modified since header and use ETags
- PR677 Fix arm32 Docker
- PR681 Fix Windows build script errors + pin ffmpeg to 4.0
- PR686 Disable some StyleCop warnings
- PR687 Fix some analyzer warnings
- PR689 Fix RPM package build for fedora
- PR702 Fix debug build on windows
- PR706 Make another docker layer reusable
- PR709 Fix always null expressions
- PR710 Fix a spelling mistake
- PR711 Remove remnants of system events
- PR713 Fix empty statement in DidlBuilder.cs
- PR716 Remove more compile time warnings
- PR721 Change image dimentions from double to int
- PR723 Minor improvements to db code
- PR724 Move Skia back into it's own project
- PR726 Clean up IFileSystem wrappers around stdlib.
- PR727 Change default aspect ratio to 2/3 from 0
- PR728 Use ffmpeg from jrottenberg/ffmpeg
- PR732 Reworked LocalizationManager to load data async
- PR733 Remove unused function
- PR734 Fix more analyzer warnings
- PR736 Start startup tasks async
- PR737 Add AssemblyInfo for Jellyfin.Drawing.Skia
- PR739 Change multi version logic for movies
- PR740 Remove code for pre-installed plugins & properly check if file exists
- PR756 Make cache dir configurable
- PR757 Fix default aspect ratio
- PR758 Add password field to initial setup
- PR764 Remove dead code, made some functions properly async
- PR769 Fix conditions where the ! was swallowed in #726
- PR774 reimplement support for plugin repository
- PR782 Remove commented file MediaBrowser.LocalMetadata.Savers.PersonXmlSaver
- PR783 Update builds to use #749 and #756
- PR788 Fix more warnings
- PR794 Remove MoreLINQ
- PR797 Fix all warnings
- PR798 Cleanup around the api endpoints
- PR800 Add CentOS and update rpm spec for the cachedir option
- PR802 Fix build error
- PR804 Handle new option parser properly
- PR805 Add weblate translation status to README
- PR807 Fix restart script in OS packages
- PR810 Fix loading of rating files
- PR812 Fix up the explicit docs links in the README
- PR819 Some small changes in Device.cs and DidlBuilder.cs
- PR822 Complete rename ImageSize -> ImageDimensions
- PR824 Improved Docker pkgbuild
- PR831 Move some arrays to generics
- PR833 Add await to GetCountries in LocalizationService
- PR834 Add donation badge and reorganize badges
- PR838 Quick style fix
- PR840 Fix more warnings
- PR841 Fix OC badge to all and add forum badge
- PR842 Use VAAPI-enabled ffmpeg
- PR852 Use SQLitePCL.pretty.netstandard on NuGet
- PR853 Fix poor handling of cache directories
- PR864 Add support for ZIP plugin archives
- PR868 Fix audio streaming via BaseProgressiveStreamingService
- PR869 Remove DLL support and require all packages/plugins to be zip archives
- PR872 Fix potential NullReferenceException
- PR899: DLNA: Fix race condition leading to missing device names
- PR890 Drop ETag and use Last-Modified header
- PR892: Add jellyfin-ffmpeg and versioning to package deps
- PR901: Properly dispose HttpWebResponse when the request failed to avoid 'too many open files'
- PR909: Fix docker arm builds
- PR910: Enhance Dockerfiles
- PR911: Checkout submodules in Docker Hub hook
- jellyfin-web:
- PR51 remove more code for sync and camera roll
- PR56 Use English for fallback translations and clean up language files
- PR58 Css slider fixes
- PR62 remove BOM markers
- PR65 Fix profile image not being shown on profile page
- PR73 Dev sync
- PR74 Add download menu option to media items
- PR75 User profile fixes
- PR76 Fix syntax error caused by deminification
- PR79 Remove unused Connect related from the frontend
- PR80 Remove games
- PR92 Added frontend support for a password field on setup
- PR94 Update british strings
- PR95 add display language option back
- PR112 Removed seasonal theme support
- PR116 Consolidate all strings into a single file per language
- PR117 Fix volume slider behavior
- PR118 Enable and fix PiP for Safari
- PR119 Make the toggle track visible on all themes
- PR121 Fix syntax error in site.js
- PR127 Change sharedcomponents module to core
- PR135 Make sure fallback culture is always available
* Sun Jan 20 2019 Jellyfin Packaging Team <packaging@jellyfin.org> * Sun Jan 20 2019 Jellyfin Packaging Team <packaging@jellyfin.org>
- jellyfin: - jellyfin:
- PR335 Build scripts and build system consolidation. - PR335 Build scripts and build system consolidation.

@ -1,4 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -x
package_win64() ( package_win64() (
local NSSM_VERSION="nssm-2.24-101-g897c7ad" local NSSM_VERSION="nssm-2.24-101-g897c7ad"
local NSSM_URL="https://nssm.cc/ci/${NSSM_VERSION}.zip" local NSSM_URL="https://nssm.cc/ci/${NSSM_VERSION}.zip"
@ -15,7 +16,7 @@ package_win64() (
wget ${NSSM_URL} -O ${TEMP_DIR}/nssm.zip wget ${NSSM_URL} -O ${TEMP_DIR}/nssm.zip
wget ${FFMPEG_URL} -O ${TEMP_DIR}/ffmpeg.zip wget ${FFMPEG_URL} -O ${TEMP_DIR}/ffmpeg.zip
unzip ${TEMP_DIR}/nssm.zip -d $TEMP_DIR unzip ${TEMP_DIR}/nssm.zip -d $TEMP_DIR
cp ${TEMP_DIR}/${NSSM_VERSION}}/win64/nssm.exe ${OUTPUT_DIR}/nssm.exe cp ${TEMP_DIR}/${NSSM_VERSION}/win64/nssm.exe ${OUTPUT_DIR}/nssm.exe
unzip ${TEMP_DIR}/ffmpeg.zip -d $TEMP_DIR unzip ${TEMP_DIR}/ffmpeg.zip -d $TEMP_DIR
cp ${TEMP_DIR}/${FFMPEG_VERSION}/bin/ffmpeg.exe ${OUTPUT_DIR}/ffmpeg.exe cp ${TEMP_DIR}/${FFMPEG_VERSION}/bin/ffmpeg.exe ${OUTPUT_DIR}/ffmpeg.exe
cp ${TEMP_DIR}/${FFMPEG_VERSION}/bin/ffprobe.exe ${OUTPUT_DIR}/ffprobe.exe cp ${TEMP_DIR}/${FFMPEG_VERSION}/bin/ffprobe.exe ${OUTPUT_DIR}/ffprobe.exe

@ -0,0 +1,6 @@
#!/bin/bash
git submodule update --init --recursive
# Register qemu-*-static for all supported processors except the
# current one, but also remove all registered binfmt_misc before
docker run --rm --privileged multiarch/qemu-user-static:register --reset
Loading…
Cancel
Save