Selaa lähdekoodia

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

Bond-009 6 vuotta sitten
vanhempi
sitoutus
a35ea49c99
35 muutettua tiedostoa jossa 586 lisäystä ja 419 poistoa
  1. 1 0
      CONTRIBUTORS.md
  2. 7 6
      Dockerfile
  3. 22 10
      Dockerfile.arm
  4. 18 14
      Dockerfile.arm64
  5. 5 5
      Emby.Dlna/PlayTo/PlayToManager.cs
  6. 1 1
      Emby.Server.Implementations/ApplicationHost.cs
  7. 9 29
      Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs
  8. 23 77
      Emby.Server.Implementations/HttpServer/HttpResultFactory.cs
  9. 25 25
      Emby.Server.Implementations/Localization/Core/da.json
  10. 27 27
      Emby.Server.Implementations/Localization/Core/de.json
  11. 1 1
      Emby.Server.Implementations/Localization/Core/en-GB.json
  12. 1 1
      Emby.Server.Implementations/Localization/Core/en-US.json
  13. 23 23
      Emby.Server.Implementations/Localization/Core/es.json
  14. 1 1
      Emby.Server.Implementations/Localization/Core/fr.json
  15. 35 35
      Emby.Server.Implementations/Localization/Core/hu.json
  16. 4 4
      Emby.Server.Implementations/Localization/Core/it.json
  17. 94 94
      Emby.Server.Implementations/Localization/Core/kk.json
  18. 3 3
      Emby.Server.Implementations/Localization/Core/ms.json
  19. 18 18
      Emby.Server.Implementations/Localization/Core/nl.json
  20. 5 5
      Emby.Server.Implementations/Localization/Core/ru.json
  21. 15 25
      Emby.Server.Implementations/Updates/InstallationManager.cs
  22. 0 2
      MediaBrowser.Api/Playback/BaseStreamingService.cs
  23. 4 1
      MediaBrowser.Api/Playback/Progressive/AudioService.cs
  24. 3 0
      MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
  25. 4 1
      MediaBrowser.Api/Playback/Progressive/VideoService.cs
  26. 5 1
      MediaBrowser.Api/Playback/UniversalAudioService.cs
  27. 0 2
      MediaBrowser.Controller/Net/StaticResultOptions.cs
  28. 1 1
      MediaBrowser.Model/Dlna/StreamBuilder.cs
  29. 1 1
      MediaBrowser.WebDashboard/jellyfin-web
  30. 2 2
      SharedVersion.cs
  31. 108 0
      deployment/debian-package-x64/pkg-src/changelog
  32. 6 1
      deployment/debian-package-x64/pkg-src/control
  33. 106 2
      deployment/fedora-package-x64/pkg-src/jellyfin.spec
  34. 2 1
      deployment/win-x64/package.sh
  35. 6 0
      hooks/pre_build

+ 1 - 0
CONTRIBUTORS.md

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

+ 7 - 6
Dockerfile

@@ -3,9 +3,8 @@ ARG DOTNET_VERSION=2
 FROM microsoft/dotnet:${DOTNET_VERSION}-sdk as builder
 WORKDIR /repo
 COPY . .
-RUN export DOTNET_CLI_TELEMETRY_OPTOUT=1 \
- && dotnet clean \
- && dotnet publish \
+ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
+RUN dotnet publish \
     --configuration release \
     --output /jellyfin \
     Jellyfin.Server
@@ -18,9 +17,11 @@ RUN apt-get update \
    libfontconfig1 \
  && apt-get clean autoclean \
  && 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=builder /jellyfin /jellyfin
 EXPOSE 8096
-VOLUME /config /media
-ENTRYPOINT dotnet /jellyfin/jellyfin.dll --datadir /config
+VOLUME /cache /config /media
+ENTRYPOINT dotnet /jellyfin/jellyfin.dll --datadir /config --cachedir /cache

+ 22 - 10
Dockerfile.arm

@@ -1,24 +1,36 @@
+# Requires binfm_misc registration
+# https://github.com/multiarch/qemu-user-static#binfmt_misc-register
 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
 COPY . .
-#TODO Remove or update the sed line when we update dotnet version.
-RUN export DOTNET_CLI_TELEMETRY_OPTOUT=1 \
- && find . -type f -exec sed -i 's/netcoreapp2.1/netcoreapp3.0/g' {} \; \
- && dotnet clean -maxcpucount:1 \
- && dotnet publish \
-    -maxcpucount:1 \
+ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
+# TODO Remove or update the sed line when we update dotnet version.
+RUN find . -type f -exec sed -i 's/netcoreapp2.1/netcoreapp3.0/g' {} \;
+# Discard objs - may cause failures if exists
+RUN find . -type d -name obj | xargs -r rm -r
+# Build
+RUN dotnet publish \
+    -r linux-arm \
     --configuration release \
     --output /jellyfin \
     Jellyfin.Server
 
 
 FROM microsoft/dotnet:${DOTNET_VERSION}-runtime-stretch-slim-arm32v7
+COPY --from=qemu_extract qemu-arm-static /usr/bin
 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
 EXPOSE 8096
-VOLUME /config /media
-ENTRYPOINT dotnet /jellyfin/jellyfin.dll --datadir /config
+VOLUME /cache /config /media
+ENTRYPOINT dotnet /jellyfin/jellyfin.dll --datadir /config --cachedir /cache

+ 18 - 14
Dockerfile.arm64

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

+ 5 - 5
Emby.Dlna/PlayTo/PlayToManager.cs

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

+ 1 - 1
Emby.Server.Implementations/ApplicationHost.cs

@@ -665,7 +665,7 @@ namespace Emby.Server.Implementations
             SocketFactory = new 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);
 
             ZipClient = new ZipClient(FileSystemManager);

+ 9 - 29
Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs

@@ -66,11 +66,6 @@ namespace Emby.Server.Implementations.HttpClientManager
 
             // http://stackoverflow.com/questions/566437/http-post-returns-the-error-417-expectation-failed-c
             ServicePointManager.Expect100Continue = false;
-
-#if NET46
-// Trakt requests sometimes fail without this
-            ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls;
-#endif
         }
 
         /// <summary>
@@ -106,23 +101,6 @@ namespace Emby.Server.Implementations.HttpClientManager
             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)
         {
             string url = options.Url;
@@ -135,7 +113,7 @@ namespace Emby.Server.Implementations.HttpClientManager
                 url = url.Replace(userInfo + "@", string.Empty);
             }
 
-            var request = CreateWebRequest(url);
+            var request = WebRequest.Create(url);
 
             if (request is HttpWebRequest httpWebRequest)
             {
@@ -627,14 +605,16 @@ namespace Emby.Server.Implementations.HttpClientManager
 
                 var exception = new HttpException(webException.Message, webException);
 
-                var response = webException.Response as HttpWebResponse;
-                if (response != null)
+                using (var response = webException.Response as HttpWebResponse)
                 {
-                    exception.StatusCode = response.StatusCode;
-
-                    if ((int)response.StatusCode == 429)
+                    if (response != null)
                     {
-                        client.LastTimeout = DateTime.UtcNow;
+                        exception.StatusCode = response.StatusCode;
+
+                        if ((int)response.StatusCode == 429)
+                        {
+                            client.LastTimeout = DateTime.UtcNow;
+                        }
                     }
                 }
 

+ 23 - 77
Emby.Server.Implementations/HttpServer/HttpResultFactory.cs

@@ -422,18 +422,20 @@ namespace Emby.Server.Implementations.HttpServer
         /// <summary>
         /// Pres the process optimized result.
         /// </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;
+            AddCachingHeaders(responseHeaders, options.CacheDuration, noCache, options.DateLastModified);
 
             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);
-                    AddExpiresHeader(responseHeaders, cacheKeyString, cacheDuration);
+                    AddAgeHeader(responseHeaders, options.DateLastModified);
 
-                    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);
 
@@ -441,8 +443,6 @@ namespace Emby.Server.Implementations.HttpServer
                 }
             }
 
-            AddCachingHeaders(responseHeaders, cacheKeyString, cacheDuration);
-
             return null;
         }
 
@@ -487,9 +487,6 @@ namespace Emby.Server.Implementations.HttpServer
                 options.DateLastModified = _fileSystem.GetLastWriteTimeUtc(path);
             }
 
-            var cacheKey = path + options.DateLastModified.Value.Ticks;
-
-            options.CacheKey = cacheKey.GetMD5();
             options.ContentFactory = () => Task.FromResult(GetFileStream(path, fileShare));
 
             options.ResponseHeaders = options.ResponseHeaders ?? new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
@@ -520,7 +517,6 @@ namespace Emby.Server.Implementations.HttpServer
             return GetStaticResult(requestContext, new StaticResultOptions
             {
                 CacheDuration = cacheDuration,
-                CacheKey = cacheKey,
                 ContentFactory = factoryFn,
                 ContentType = contentType,
                 DateLastModified = lastDateModified,
@@ -534,14 +530,10 @@ namespace Emby.Server.Implementations.HttpServer
             options.ResponseHeaders = options.ResponseHeaders ?? new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
 
             var contentType = options.ContentType;
-            var etag = requestContext.Headers.Get("If-None-Match");
-            var cacheKey = etag != null ? new Guid(etag.Trim('\"')) : Guid.Empty;
-            if (!cacheKey.Equals(Guid.Empty))
+            if (!string.IsNullOrEmpty(requestContext.Headers.Get("If-Modified-Since")))
             {
-                var key = cacheKey.ToString("N");
-
                 // 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)
                 {
@@ -553,6 +545,8 @@ namespace Emby.Server.Implementations.HttpServer
             var isHeadRequest = options.IsHeadRequest || string.Equals(requestContext.Verb, "HEAD", StringComparison.OrdinalIgnoreCase);
             var factoryFn = options.ContentFactory;
             var responseHeaders = options.ResponseHeaders;
+            AddCachingHeaders(responseHeaders, options.CacheDuration, false, options.DateLastModified);
+            AddAgeHeader(responseHeaders, options.DateLastModified);
 
             var rangeHeader = requestContext.Headers.Get("Range");
 
@@ -566,21 +560,10 @@ namespace Emby.Server.Implementations.HttpServer
                 };
 
                 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;
             }
 
             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;
             if (!totalContentLength.HasValue)
@@ -603,7 +586,6 @@ namespace Emby.Server.Implementations.HttpServer
                 };
 
                 AddResponseHeaders(hasHeaders, options.ResponseHeaders);
-                hasHeaders.Headers["ETag"] = newEtag;
                 return hasHeaders;
             }
             else
@@ -628,7 +610,6 @@ namespace Emby.Server.Implementations.HttpServer
                 };
 
                 AddResponseHeaders(hasHeaders, options.ResponseHeaders);
-                hasHeaders.Headers["ETag"] = newEtag;
                 return hasHeaders;
             }
         }
@@ -641,37 +622,28 @@ namespace Emby.Server.Implementations.HttpServer
         /// <summary>
         /// Adds the caching responseHeaders.
         /// </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";
-            }
-            else
+            if (noCache)
             {
                 responseHeaders["Cache-Control"] = "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)
             {
-                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);
             }
         }
-        /// <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>
         /// Determines whether [is not modified] [the specified if modified since].

+ 25 - 25
Emby.Server.Implementations/Localization/Core/da.json

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

+ 27 - 27
Emby.Server.Implementations/Localization/Core/de.json

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

+ 1 - 1
Emby.Server.Implementations/Localization/Core/en-GB.json

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

+ 1 - 1
Emby.Server.Implementations/Localization/Core/en-US.json

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

+ 23 - 23
Emby.Server.Implementations/Localization/Core/es.json

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

+ 1 - 1
Emby.Server.Implementations/Localization/Core/fr.json

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

+ 35 - 35
Emby.Server.Implementations/Localization/Core/hu.json

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

+ 4 - 4
Emby.Server.Implementations/Localization/Core/it.json

@@ -5,13 +5,13 @@
     "Artists": "Artisti",
     "AuthenticationSucceededWithUserName": "{0} autenticato con successo",
     "Books": "Libri",
-    "CameraImageUploadedFrom": "A new camera image has been uploaded from {0}",
+    "CameraImageUploadedFrom": "È stata caricata una nuova immagine della fotocamera {0}",
     "Channels": "Canali",
     "ChapterNameValue": "Capitolo {0}",
     "Collections": "Collezioni",
     "DeviceOfflineWithName": "{0} è stato disconnesso",
     "DeviceOnlineWithName": "{0} è connesso",
-    "FailedLoginAttemptWithUserName": "Tentativo di accesso fallito da  {0}",
+    "FailedLoginAttemptWithUserName": "Tentativo di accesso fallito da {0}",
     "Favorites": "Preferiti",
     "Folders": "Cartelle",
     "Genres": "Generi",
@@ -19,9 +19,9 @@
     "HeaderCameraUploads": "Caricamenti Fotocamera",
     "HeaderContinueWatching": "Continua a guardare",
     "HeaderFavoriteAlbums": "Album preferiti",
-    "HeaderFavoriteArtists": "Artisti preferiti",
+    "HeaderFavoriteArtists": "Artisti Preferiti",
     "HeaderFavoriteEpisodes": "Episodi Preferiti",
-    "HeaderFavoriteShows": "Show preferiti",
+    "HeaderFavoriteShows": "Serie TV Preferite",
     "HeaderFavoriteSongs": "Brani Preferiti",
     "HeaderLiveTV": "Diretta TV",
     "HeaderNextUp": "Prossimo",

+ 94 - 94
Emby.Server.Implementations/Localization/Core/kk.json

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

+ 3 - 3
Emby.Server.Implementations/Localization/Core/ms.json

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

+ 18 - 18
Emby.Server.Implementations/Localization/Core/nl.json

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

+ 5 - 5
Emby.Server.Implementations/Localization/Core/ru.json

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

+ 15 - 25
Emby.Server.Implementations/Updates/InstallationManager.cs

@@ -116,6 +116,7 @@ namespace Emby.Server.Implementations.Updates
         private readonly IApplicationHost _applicationHost;
 
         private readonly ICryptoProvider _cryptographyProvider;
+        private readonly IZipClient _zipClient;
 
         // netframework or netcore
         private readonly string _packageRuntime;
@@ -129,6 +130,7 @@ namespace Emby.Server.Implementations.Updates
             IServerConfigurationManager config,
             IFileSystem fileSystem,
             ICryptoProvider cryptographyProvider,
+            IZipClient zipClient,
             string packageRuntime)
         {
             if (loggerFactory == null)
@@ -146,6 +148,7 @@ namespace Emby.Server.Implementations.Updates
             _config = config;
             _fileSystem = fileSystem;
             _cryptographyProvider = cryptographyProvider;
+            _zipClient = zipClient;
             _packageRuntime = packageRuntime;
             _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)
         {
-            // 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 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)
             {
-                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
@@ -547,36 +554,19 @@ namespace Emby.Server.Implementations.Updates
 
             cancellationToken.ThrowIfCancellationRequested();
 
-            // Validate with a checksum
-            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();
+            // TODO: Validate with a checksum, *properly*
 
             // Success - move it to the real target
             try
             {
-                Directory.CreateDirectory(Path.GetDirectoryName(target));
-                File.Copy(tempFile, target, true);
-                //If it is an archive - write out a version file so we know what it is
-                if (isArchive)
+                using (var stream = File.OpenRead(tempFile))
                 {
-                    File.WriteAllText(target + ".ver", package.versionStr);
+                    _zipClient.ExtractAllFromZip(stream, target, true);
                 }
             }
             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;
             }
 

+ 0 - 2
MediaBrowser.Api/Playback/BaseStreamingService.cs

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

+ 4 - 1
MediaBrowser.Api/Playback/Progressive/AudioService.cs

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

+ 3 - 0
MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs

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

+ 4 - 1
MediaBrowser.Api/Playback/Progressive/VideoService.cs

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

+ 5 - 1
MediaBrowser.Api/Playback/UniversalAudioService.cs

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

+ 0 - 2
MediaBrowser.Controller/Net/StaticResultOptions.cs

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

+ 1 - 1
MediaBrowser.Model/Dlna/StreamBuilder.cs

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

+ 1 - 1
MediaBrowser.WebDashboard/jellyfin-web

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

+ 2 - 2
SharedVersion.cs

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

+ 108 - 0
deployment/debian-package-x64/pkg-src/changelog

@@ -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:

+ 6 - 1
deployment/debian-package-x64/pkg-src/control

@@ -18,6 +18,11 @@ Replaces: 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
 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.
  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.

+ 106 - 2
deployment/fedora-package-x64/pkg-src/jellyfin.spec

@@ -7,8 +7,8 @@
 %endif
 
 Name:           jellyfin
-Version:        10.1.0
-Release:        1%{?dist}
+Version:        10.2.0
+Release:        2%{?dist}
 Summary:        The Free Software Media Browser
 License:        GPLv2
 URL:            https://jellyfin.media
@@ -140,6 +140,110 @@ fi
 %systemd_postun_with_restart jellyfin.service
 
 %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>
 - jellyfin:
 - PR335 Build scripts and build system consolidation.

+ 2 - 1
deployment/win-x64/package.sh

@@ -1,4 +1,5 @@
 #!/usr/bin/env bash
+set -x
 package_win64() (
     local NSSM_VERSION="nssm-2.24-101-g897c7ad"
     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 ${FFMPEG_URL} -O ${TEMP_DIR}/ffmpeg.zip
         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
         cp ${TEMP_DIR}/${FFMPEG_VERSION}/bin/ffmpeg.exe ${OUTPUT_DIR}/ffmpeg.exe
         cp ${TEMP_DIR}/${FFMPEG_VERSION}/bin/ffprobe.exe ${OUTPUT_DIR}/ffprobe.exe

+ 6 - 0
hooks/pre_build

@@ -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