aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations
diff options
context:
space:
mode:
authorBond-009 <bond.009@outlook.com>2019-02-17 10:38:44 +0100
committerBond-009 <bond.009@outlook.com>2019-02-17 10:38:44 +0100
commita35ea49c996d42c2fa26f0536b1beaab15bd3b08 (patch)
tree872afa2535e8318c0af9d4eca7e457d7d5b0e078 /Emby.Server.Implementations
parent25c2267a89af5c2e82774c638cdad0defcc894b5 (diff)
parent4b4399fba6df3368ab04e78acd2dd08873e4f07b (diff)
Merge remote-tracking branch 'upstream/release-10.2.z' into newmaser
Diffstat (limited to 'Emby.Server.Implementations')
-rw-r--r--Emby.Server.Implementations/ApplicationHost.cs2
-rw-r--r--Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs38
-rw-r--r--Emby.Server.Implementations/HttpServer/HttpResultFactory.cs100
-rw-r--r--Emby.Server.Implementations/Localization/Core/da.json50
-rw-r--r--Emby.Server.Implementations/Localization/Core/de.json54
-rw-r--r--Emby.Server.Implementations/Localization/Core/en-GB.json2
-rw-r--r--Emby.Server.Implementations/Localization/Core/en-US.json2
-rw-r--r--Emby.Server.Implementations/Localization/Core/es.json46
-rw-r--r--Emby.Server.Implementations/Localization/Core/fr.json2
-rw-r--r--Emby.Server.Implementations/Localization/Core/hu.json70
-rw-r--r--Emby.Server.Implementations/Localization/Core/it.json8
-rw-r--r--Emby.Server.Implementations/Localization/Core/kk.json188
-rw-r--r--Emby.Server.Implementations/Localization/Core/ms.json6
-rw-r--r--Emby.Server.Implementations/Localization/Core/nl.json36
-rw-r--r--Emby.Server.Implementations/Localization/Core/ru.json10
-rw-r--r--Emby.Server.Implementations/Updates/InstallationManager.cs40
16 files changed, 285 insertions, 369 deletions
diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs
index 784486d52..9d4fd95a0 100644
--- a/Emby.Server.Implementations/ApplicationHost.cs
+++ b/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);
diff --git a/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs b/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs
index 6ea1bd08e..2232b3eeb 100644
--- a/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs
+++ b/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;
+ }
}
}
diff --git a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs
index 7445fd3c2..75ca57ebb 100644
--- a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs
+++ b/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].
diff --git a/Emby.Server.Implementations/Localization/Core/da.json b/Emby.Server.Implementations/Localization/Core/da.json
index 7004d44db..9d4d74099 100644
--- a/Emby.Server.Implementations/Localization/Core/da.json
+++ b/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}"
}
diff --git a/Emby.Server.Implementations/Localization/Core/de.json b/Emby.Server.Implementations/Localization/Core/de.json
index 7bd2e90fe..6fd63a514 100644
--- a/Emby.Server.Implementations/Localization/Core/de.json
+++ b/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}"
}
diff --git a/Emby.Server.Implementations/Localization/Core/en-GB.json b/Emby.Server.Implementations/Localization/Core/en-GB.json
index 332902292..67d4068cf 100644
--- a/Emby.Server.Implementations/Localization/Core/en-GB.json
+++ b/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}"
diff --git a/Emby.Server.Implementations/Localization/Core/en-US.json b/Emby.Server.Implementations/Localization/Core/en-US.json
index f19cd532b..aa855ed21 100644
--- a/Emby.Server.Implementations/Localization/Core/en-US.json
+++ b/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",
diff --git a/Emby.Server.Implementations/Localization/Core/es.json b/Emby.Server.Implementations/Localization/Core/es.json
index 5d118d21f..1850b8f25 100644
--- a/Emby.Server.Implementations/Localization/Core/es.json
+++ b/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}"
}
diff --git a/Emby.Server.Implementations/Localization/Core/fr.json b/Emby.Server.Implementations/Localization/Core/fr.json
index aa9a1add3..52afb4e49 100644
--- a/Emby.Server.Implementations/Localization/Core/fr.json
+++ b/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",
diff --git a/Emby.Server.Implementations/Localization/Core/hu.json b/Emby.Server.Implementations/Localization/Core/hu.json
index d2d16b18f..c0f988abe 100644
--- a/Emby.Server.Implementations/Localization/Core/hu.json
+++ b/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}"
}
diff --git a/Emby.Server.Implementations/Localization/Core/it.json b/Emby.Server.Implementations/Localization/Core/it.json
index b3d9c16cf..a5f1e8f94 100644
--- a/Emby.Server.Implementations/Localization/Core/it.json
+++ b/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",
diff --git a/Emby.Server.Implementations/Localization/Core/kk.json b/Emby.Server.Implementations/Localization/Core/kk.json
index ae256f79d..658d168e9 100644
--- a/Emby.Server.Implementations/Localization/Core/kk.json
+++ b/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}"
}
diff --git a/Emby.Server.Implementations/Localization/Core/ms.json b/Emby.Server.Implementations/Localization/Core/ms.json
index c01bb0c50..c10fbe58f 100644
--- a/Emby.Server.Implementations/Localization/Core/ms.json
+++ b/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}",
diff --git a/Emby.Server.Implementations/Localization/Core/nl.json b/Emby.Server.Implementations/Localization/Core/nl.json
index 589753c44..24af1839f 100644
--- a/Emby.Server.Implementations/Localization/Core/nl.json
+++ b/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}"
}
diff --git a/Emby.Server.Implementations/Localization/Core/ru.json b/Emby.Server.Implementations/Localization/Core/ru.json
index d799fa50b..c0465def8 100644
--- a/Emby.Server.Implementations/Localization/Core/ru.json
+++ b/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": "Система",
diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs
index dc7f57f27..301802b8a 100644
--- a/Emby.Server.Implementations/Updates/InstallationManager.cs
+++ b/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;
}