aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations
diff options
context:
space:
mode:
Diffstat (limited to 'Emby.Server.Implementations')
-rw-r--r--Emby.Server.Implementations/ApplicationHost.cs5
-rw-r--r--Emby.Server.Implementations/Dto/DtoService.cs84
-rw-r--r--Emby.Server.Implementations/Library/LibraryManager.cs174
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/ExtraResolver.cs6
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs14
-rw-r--r--Emby.Server.Implementations/Library/Search/SearchManager.cs49
-rw-r--r--Emby.Server.Implementations/Library/Search/SearchQueryAccessFilter.cs38
-rw-r--r--Emby.Server.Implementations/Library/Search/SqlSearchProvider.cs8
-rw-r--r--Emby.Server.Implementations/Library/SimilarItems/SimilarItemsManager.cs3
-rw-r--r--Emby.Server.Implementations/Library/Validators/CollectionPosterVerifyPostScanTask.cs64
-rw-r--r--Emby.Server.Implementations/Localization/Core/ar.json17
-rw-r--r--Emby.Server.Implementations/Localization/Core/ca.json15
-rw-r--r--Emby.Server.Implementations/Localization/Core/cs.json15
-rw-r--r--Emby.Server.Implementations/Localization/Core/da.json21
-rw-r--r--Emby.Server.Implementations/Localization/Core/de.json17
-rw-r--r--Emby.Server.Implementations/Localization/Core/en-US.json13
-rw-r--r--Emby.Server.Implementations/Localization/Core/eo.json6
-rw-r--r--Emby.Server.Implementations/Localization/Core/es-AR.json15
-rw-r--r--Emby.Server.Implementations/Localization/Core/es-MX.json17
-rw-r--r--Emby.Server.Implementations/Localization/Core/es.json15
-rw-r--r--Emby.Server.Implementations/Localization/Core/es_419.json15
-rw-r--r--Emby.Server.Implementations/Localization/Core/et.json15
-rw-r--r--Emby.Server.Implementations/Localization/Core/eu.json15
-rw-r--r--Emby.Server.Implementations/Localization/Core/fi.json7
-rw-r--r--Emby.Server.Implementations/Localization/Core/fo.json65
-rw-r--r--Emby.Server.Implementations/Localization/Core/fr-CA.json15
-rw-r--r--Emby.Server.Implementations/Localization/Core/fr.json15
-rw-r--r--Emby.Server.Implementations/Localization/Core/gl.json16
-rw-r--r--Emby.Server.Implementations/Localization/Core/he.json9
-rw-r--r--Emby.Server.Implementations/Localization/Core/hu.json15
-rw-r--r--Emby.Server.Implementations/Localization/Core/hy.json7
-rw-r--r--Emby.Server.Implementations/Localization/Core/is.json15
-rw-r--r--Emby.Server.Implementations/Localization/Core/it.json15
-rw-r--r--Emby.Server.Implementations/Localization/Core/ko.json5
-rw-r--r--Emby.Server.Implementations/Localization/Core/lb.json6
-rw-r--r--Emby.Server.Implementations/Localization/Core/lt-LT.json53
-rw-r--r--Emby.Server.Implementations/Localization/Core/ms.json8
-rw-r--r--Emby.Server.Implementations/Localization/Core/nl.json15
-rw-r--r--Emby.Server.Implementations/Localization/Core/oc.json26
-rw-r--r--Emby.Server.Implementations/Localization/Core/pl.json15
-rw-r--r--Emby.Server.Implementations/Localization/Core/pt-BR.json14
-rw-r--r--Emby.Server.Implementations/Localization/Core/pt-PT.json123
-rw-r--r--Emby.Server.Implementations/Localization/Core/pt.json143
-rw-r--r--Emby.Server.Implementations/Localization/Core/ro.json5
-rw-r--r--Emby.Server.Implementations/Localization/Core/ru.json15
-rw-r--r--Emby.Server.Implementations/Localization/Core/sk.json17
-rw-r--r--Emby.Server.Implementations/Localization/Core/sq.json15
-rw-r--r--Emby.Server.Implementations/Localization/Core/sr.json15
-rw-r--r--Emby.Server.Implementations/Localization/Core/sv.json15
-rw-r--r--Emby.Server.Implementations/Localization/Core/ta.json17
-rw-r--r--Emby.Server.Implementations/Localization/Core/th.json4
-rw-r--r--Emby.Server.Implementations/Localization/Core/tr.json17
-rw-r--r--Emby.Server.Implementations/Localization/Core/uk.json15
-rw-r--r--Emby.Server.Implementations/Localization/Core/vi.json27
-rw-r--r--Emby.Server.Implementations/Localization/Core/zh-CN.json15
-rw-r--r--Emby.Server.Implementations/Localization/Core/zh-HK.json19
-rw-r--r--Emby.Server.Implementations/Localization/Core/zh-TW.json15
-rw-r--r--Emby.Server.Implementations/Playlists/PlaylistManager.cs15
-rw-r--r--Emby.Server.Implementations/Plugins/PluginManager.cs32
-rw-r--r--Emby.Server.Implementations/Session/SessionManager.cs2
-rw-r--r--Emby.Server.Implementations/Session/SessionWebSocketListener.cs2
-rw-r--r--Emby.Server.Implementations/Updates/InstallationManager.cs5
62 files changed, 1200 insertions, 295 deletions
diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs
index 0c1c7d3f5b..1a54565863 100644
--- a/Emby.Server.Implementations/ApplicationHost.cs
+++ b/Emby.Server.Implementations/ApplicationHost.cs
@@ -987,8 +987,9 @@ namespace Emby.Server.Implementations
/// <inheritdoc/>
public string GetLocalApiUrl(string hostname, string scheme = null, int? port = null)
{
- // If the smartAPI doesn't start with http then treat it as a host or ip.
- if (hostname.StartsWith("http", StringComparison.OrdinalIgnoreCase))
+ // If the smartAPI isn't already a complete URL then treat it as a host or ip.
+ if (hostname.StartsWith("http://", StringComparison.OrdinalIgnoreCase)
+ || hostname.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
{
return hostname.TrimEnd('/');
}
diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs
index 71c3b24907..6fa057702c 100644
--- a/Emby.Server.Implementations/Dto/DtoService.cs
+++ b/Emby.Server.Implementations/Dto/DtoService.cs
@@ -242,6 +242,29 @@ namespace Emby.Server.Implementations.Dto
artistsBatch = _libraryManager.GetArtists(artistNames.ToArray());
}
+ // Batch-fetch people across all items to avoid one GetPeople query per item.
+ IReadOnlyDictionary<Guid, IReadOnlyList<PersonInfo>>? peopleBatch = null;
+ if (options.ContainsField(ItemFields.People))
+ {
+ var peopleItemIds = accessibleItems.Where(i => i.SupportsPeople).Select(i => i.Id).ToList();
+ if (peopleItemIds.Count > 0)
+ {
+ peopleBatch = _libraryManager.GetPeopleByItems(peopleItemIds);
+ }
+ }
+
+ // Batch-detect which videos own alternate versions to avoid the per-item alternate-version
+ // queries in MediaSourceCount. Videos absent from this set have a single media source.
+ IReadOnlySet<Guid>? alternateVersionItemIds = null;
+ if (options.ContainsField(ItemFields.MediaSourceCount))
+ {
+ var versionItemIds = accessibleItems.OfType<Video>().Select(i => i.Id).ToList();
+ if (versionItemIds.Count > 0)
+ {
+ alternateVersionItemIds = _libraryManager.GetItemIdsWithAlternateVersions(versionItemIds);
+ }
+ }
+
for (int index = 0; index < accessibleItems.Count; index++)
{
var item = accessibleItems[index];
@@ -255,7 +278,9 @@ namespace Emby.Server.Implementations.Dto
childCountBatch,
playedCountBatch,
artistsBatch,
- resumeDataBatch?.GetValueOrDefault(item.Id));
+ resumeDataBatch?.GetValueOrDefault(item.Id),
+ peopleBatch,
+ alternateVersionItemIds);
if (item is LiveTvChannel tvChannel)
{
@@ -317,7 +342,9 @@ namespace Emby.Server.Implementations.Dto
Dictionary<Guid, int>? childCountBatch = null,
Dictionary<Guid, (int Played, int Total)>? playedCountBatch = null,
IReadOnlyDictionary<string, MusicArtist[]>? artistsBatch = null,
- VersionResumeData? resumeData = null)
+ VersionResumeData? resumeData = null,
+ IReadOnlyDictionary<Guid, IReadOnlyList<PersonInfo>>? peopleBatch = null,
+ IReadOnlySet<Guid>? alternateVersionItemIds = null)
{
var dto = new BaseItemDto
{
@@ -331,7 +358,15 @@ namespace Emby.Server.Implementations.Dto
if (options.ContainsField(ItemFields.People))
{
- AttachPeople(dto, item, user);
+ IReadOnlyList<PersonInfo>? prefetchedPeople = null;
+ if (peopleBatch is not null)
+ {
+ // The batch omits items with no people, so a miss means "no people",
+ // not "not fetched". Use an empty list to skip the per-item query.
+ prefetchedPeople = peopleBatch.GetValueOrDefault(item.Id) ?? [];
+ }
+
+ AttachPeople(dto, item, user, prefetchedPeople);
}
if (options.ContainsField(ItemFields.PrimaryImageAspectRatio))
@@ -378,7 +413,7 @@ namespace Emby.Server.Implementations.Dto
AttachStudios(dto, item);
}
- AttachBasicFields(dto, item, owner, options, artistsBatch, user);
+ AttachBasicFields(dto, item, owner, options, artistsBatch, user, alternateVersionItemIds);
if (options.ContainsField(ItemFields.CanDelete))
{
@@ -742,12 +777,18 @@ namespace Emby.Server.Implementations.Dto
/// <param name="dto">The dto.</param>
/// <param name="item">The item.</param>
/// <param name="user">The requesting user.</param>
- private void AttachPeople(BaseItemDto dto, BaseItem item, User? user = null)
+ /// <param name="prefetchedPeople">People fetched in batch by the caller; when null the people are queried per item.</param>
+ private void AttachPeople(BaseItemDto dto, BaseItem item, User? user = null, IReadOnlyList<PersonInfo>? prefetchedPeople = null)
{
+ // When rendering a page of items the caller batch-fetches people for every item up
+ // front and passes them in, avoiding one GetPeople query per item. Fall back to the
+ // per-item query for the single item path where no batch is available.
+ var source = prefetchedPeople ?? _libraryManager.GetPeople(item);
+
// Ordering by person type to ensure actors and artists are at the front.
// This is taking advantage of the fact that they both begin with A
// This should be improved in the future
- var people = _libraryManager.GetPeople(item).OrderBy(i => i.SortOrder ?? int.MaxValue)
+ var people = source.OrderBy(i => i.SortOrder ?? int.MaxValue)
.ThenBy(i =>
{
if (i.IsType(PersonKind.Actor))
@@ -957,7 +998,8 @@ namespace Emby.Server.Implementations.Dto
/// <param name="options">The options.</param>
/// <param name="artistsBatch">Optional pre-fetched artist lookup shared across a batch of items.</param>
/// <param name="user">The user, for per-user values such as the accessible media source count.</param>
- private void AttachBasicFields(BaseItemDto dto, BaseItem item, BaseItem? owner, DtoOptions options, IReadOnlyDictionary<string, MusicArtist[]>? artistsBatch = null, User? user = null)
+ /// <param name="alternateVersionItemIds">Optional pre-fetched set of item IDs that own alternate versions, shared across a batch of items.</param>
+ private void AttachBasicFields(BaseItemDto dto, BaseItem item, BaseItem? owner, DtoOptions options, IReadOnlyDictionary<string, MusicArtist[]>? artistsBatch = null, User? user = null, IReadOnlySet<Guid>? alternateVersionItemIds = null)
{
if (options.ContainsField(ItemFields.DateCreated))
{
@@ -1271,15 +1313,27 @@ namespace Emby.Server.Implementations.Dto
if (options.ContainsField(ItemFields.MediaSourceCount))
{
- // Match the per-user filtering of the media sources: versions the user cannot
- // access are not selectable, so they must not count towards the badge either.
- var mediaSourceCount = user is null
- || (!video.PrimaryVersionId.HasValue && video.LinkedAlternateVersions.Length == 0 && !video.HasLocalAlternateVersions)
- ? video.MediaSourceCount
- : video.GetAllVersions().Count(v => v.Id.Equals(video.Id) || v.IsVisibleStandalone(user));
- if (mediaSourceCount != 1)
+ // A video with no primary version and no alternate versions always has a single
+ // media source. Only compute the count for videos that might have more: a primary
+ // version, or membership in the batch's set of items that own alternate versions.
+ // Without the batch we can't rule it out, so fall back to computing (the single-item
+ // path). Everything else is the common case and keeps the default count of one.
+ var mayHaveAlternateVersions = alternateVersionItemIds is null
+ || video.PrimaryVersionId.HasValue
+ || alternateVersionItemIds.Contains(video.Id);
+
+ if (mayHaveAlternateVersions)
{
- dto.MediaSourceCount = mediaSourceCount;
+ // Match the per-user filtering of the media sources: versions the user cannot
+ // access are not selectable, so they must not count towards the badge either.
+ var mediaSourceCount = user is null
+ || (!video.PrimaryVersionId.HasValue && video.LinkedAlternateVersions.Length == 0 && !video.HasLocalAlternateVersions)
+ ? video.MediaSourceCount
+ : video.GetAllVersions().Count(v => v.Id.Equals(video.Id) || v.IsVisibleStandalone(user));
+ if (mediaSourceCount != 1)
+ {
+ dto.MediaSourceCount = mediaSourceCount;
+ }
}
}
diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs
index 983ecced02..6a39b2177d 100644
--- a/Emby.Server.Implementations/Library/LibraryManager.cs
+++ b/Emby.Server.Implementations/Library/LibraryManager.cs
@@ -45,6 +45,7 @@ using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Library;
using MediaBrowser.Model.Querying;
@@ -86,6 +87,7 @@ namespace Emby.Server.Implementations.Library
private readonly IPeopleRepository _peopleRepository;
private readonly ExtraResolver _extraResolver;
private readonly IPathManager _pathManager;
+ private readonly ILocalizationManager _localization;
private readonly FastConcurrentLru<Guid, BaseItem> _cache;
private readonly DotIgnoreIgnoreRule _dotIgnoreIgnoreRule;
private readonly IMediaStreamRepository _mediaStreamRepository;
@@ -132,6 +134,7 @@ namespace Emby.Server.Implementations.Library
/// <param name="peopleRepository">The people repository.</param>
/// <param name="pathManager">The path manager.</param>
/// <param name="dotIgnoreIgnoreRule">The .ignore rule handler.</param>
+ /// <param name="localization">The localization manager.</param>
/// <param name="mediaStreamRepository">The media stream repository.</param>
/// <param name="externalDataManagerFactory">The external data manager (lazy, to break the DI cycle through ChapterManager).</param>
public LibraryManager(
@@ -157,6 +160,7 @@ namespace Emby.Server.Implementations.Library
IPeopleRepository peopleRepository,
IPathManager pathManager,
DotIgnoreIgnoreRule dotIgnoreIgnoreRule,
+ ILocalizationManager localization,
IMediaStreamRepository mediaStreamRepository,
Lazy<IExternalDataManager> externalDataManagerFactory)
{
@@ -184,6 +188,7 @@ namespace Emby.Server.Implementations.Library
_peopleRepository = peopleRepository;
_pathManager = pathManager;
_dotIgnoreIgnoreRule = dotIgnoreIgnoreRule;
+ _localization = localization;
_extraResolver = new ExtraResolver(loggerFactory.CreateLogger<ExtraResolver>(), namingOptions, directoryService);
_configurationManager.ConfigurationUpdated += ConfigurationUpdated;
@@ -407,6 +412,13 @@ namespace Emby.Server.Implementations.Library
}
_persistenceService.DeleteItem([.. pathMaps.Select(f => f.Item.Id)]);
+
+ // Evict the deleted items from the cache and announce each removal.
+ foreach (var (item, _, _) in pathMaps)
+ {
+ _cache.TryRemove(item.Id, out _);
+ ReportItemRemoved(item, item.GetOwner() ?? item.GetParent());
+ }
}
public void DeleteItem(BaseItem item, DeleteOptions options, BaseItem parent, bool notifyParentItem)
@@ -606,6 +618,12 @@ namespace Emby.Server.Implementations.Library
folder.UserData = null;
}
+ // Announce the descendants before the item itself.
+ foreach (var child in children)
+ {
+ ReportItemRemoved(child, item);
+ }
+
ReportItemRemoved(item, parent);
}
@@ -2230,6 +2248,12 @@ namespace Emby.Server.Implementations.Library
}
/// <inheritdoc />
+ public IReadOnlySet<Guid> GetItemIdsWithAlternateVersions(IReadOnlyList<Guid> itemIds)
+ {
+ return _linkedChildrenService.GetItemIdsWithAlternateVersions(itemIds);
+ }
+
+ /// <inheritdoc />
public void UpsertLinkedChild(Guid parentId, Guid childId, MediaBrowser.Controller.Entities.LinkedChildType childType)
{
_linkedChildrenService.UpsertLinkedChild(parentId, childId, childType);
@@ -2371,6 +2395,7 @@ namespace Emby.Server.Implementations.Library
{
altVideo.OwnerId = video.Id;
altVideo.SetPrimaryVersionId(video.Id);
+ altVideo.IsInMixedFolder = video.IsInMixedFolder;
// ResolveAlternateVersion only sees the alternate's primary file.
// If the alternate is itself a stack (e.g. 1080p part1 + part2),
// detect its parts from sibling files so its AdditionalParts persist.
@@ -2556,6 +2581,8 @@ namespace Emby.Server.Implementations.Library
item.DateLastSaved = DateTime.UtcNow;
}
+ ForgetDroppedLocalAlternateVersions(items);
+
// Resolve and add any local alternate version items that don't exist yet
// This ensures they exist in the database when LinkedChildren are processed
var allItems = new List<BaseItem>(items);
@@ -2584,6 +2611,7 @@ namespace Emby.Server.Implementations.Library
{
altVideo.OwnerId = video.Id;
altVideo.SetPrimaryVersionId(video.Id);
+ altVideo.IsInMixedFolder = video.IsInMixedFolder;
// ResolveAlternateVersion only sees the alternate's primary file.
// If the alternate is itself a stack (e.g. 1080p part1 + part2),
// detect its parts from sibling files so its AdditionalParts persist.
@@ -2644,6 +2672,30 @@ namespace Emby.Server.Implementations.Library
public Task UpdateItemAsync(BaseItem item, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken)
=> UpdateItemsAsync([item], parent, updateReason, cancellationToken);
+ /// <summary>
+ /// Forgets the cached local alternate versions of the supplied items that they no longer list.
+ /// </summary>
+ /// <param name="items">The items about to be saved.</param>
+ private void ForgetDroppedLocalAlternateVersions(IReadOnlyList<BaseItem> items)
+ {
+ foreach (var video in items.OfType<Video>())
+ {
+ var videoType = video.GetType();
+ var keptIds = video.LocalAlternateVersions
+ .Where(path => !string.IsNullOrEmpty(path))
+ .Select(path => GetNewItemId(path, videoType))
+ .ToHashSet();
+
+ foreach (var versionId in GetLocalAlternateVersionIds(video))
+ {
+ if (!keptIds.Contains(versionId))
+ {
+ _cache.TryRemove(versionId, out _);
+ }
+ }
+ }
+ }
+
/// <inheritdoc />
public async Task ReattachUserDataAsync(BaseItem item, CancellationToken cancellationToken)
{
@@ -3280,9 +3332,11 @@ namespace Emby.Server.Implementations.Library
var ownerVideoInfo = VideoResolver.Resolve(owner.Path, isFolder, _namingOptions, libraryRoot: owner.ContainingFolderPath);
if (ownerVideoInfo is null)
{
- yield break;
+ return [];
}
+ var candidates = new List<ExtraCandidate>();
+
var count = filtered.Count;
for (var i = 0; i < count; i++)
{
@@ -3296,35 +3350,50 @@ namespace Emby.Server.Implementations.Library
foreach (var file in filesInSubFolderList)
{
- if (!_extraResolver.TryGetExtraTypeForOwner(file.FullName, ownerVideoInfo, out var extraType))
+ if (!_extraResolver.TryGetExtraTypeForOwner(file.FullName, ownerVideoInfo, out var extraType, out var extraRule))
{
continue;
}
- var extra = GetExtra(file, extraType.Value, subFolderIsMixedFolder);
- if (extra is not null)
- {
- yield return extra;
- }
+ AddCandidate(file, extraType.Value, extraRule, subFolderIsMixedFolder);
}
}
- else if (!current.IsDirectory && _extraResolver.TryGetExtraTypeForOwner(current.FullName, ownerVideoInfo, out var extraType))
+ else if (!current.IsDirectory && _extraResolver.TryGetExtraTypeForOwner(current.FullName, ownerVideoInfo, out var extraType, out var extraRule))
{
- var extra = GetExtra(current, extraType.Value, false);
- if (extra is not null)
- {
- yield return extra;
- }
+ AddCandidate(current, extraType.Value, extraRule, false);
+ }
+ }
+
+ var extras = new List<BaseItem>();
+ var typeCounters = new Dictionary<ExtraType, int>();
+
+ // Order by path so that the numbering handed out below does not depend on the
+ // order the file system happened to list the folder in
+ foreach (var candidate in candidates.OrderBy(c => c.Extra.Path, StringComparer.Ordinal))
+ {
+ var extra = PrepareExtra(candidate);
+ if (extra is not null)
+ {
+ extras.Add(extra);
}
}
- BaseItem? GetExtra(FileSystemMetadata file, ExtraType extraType, bool isInMixedFolder)
+ return extras;
+
+ void AddCandidate(FileSystemMetadata file, ExtraType extraType, ExtraRule extraRule, bool isInMixedFolder)
{
var extra = ResolvePath(_fileSystem.GetFileInfo(file.FullName), directoryService, _extraResolver.GetResolversForExtraType(extraType));
- if (extra is not Video && extra is not Audio)
+ if (extra is Video or Audio)
{
- return null;
+ candidates.Add(new ExtraCandidate(extra, extraType, extraRule, isInMixedFolder));
}
+ }
+
+ BaseItem? PrepareExtra(ExtraCandidate candidate)
+ {
+ var resolved = candidate.Extra;
+ var extra = resolved;
+ var name = GetExtraName(candidate, ownerVideoInfo, typeCounters);
// Try to retrieve it from the db. If we don't find it, use the resolved version
var itemById = GetItemById(extra.Id);
@@ -3333,10 +3402,18 @@ namespace Emby.Server.Implementations.Library
extra = itemById;
}
+ // An extra is named after its file, so the file is the source of truth. Items created
+ // by older versions, or renamed by a metadata provider, are corrected here;
+ // RefreshExtras persists the change.
+ if (!string.IsNullOrEmpty(name) && extra.LockedFields?.Contains(MetadataField.Name) != true)
+ {
+ extra.Name = name;
+ }
+
// Only update extra type if it is more specific then the currently known extra type
- if (extra.ExtraType is null or ExtraType.Unknown || extraType != ExtraType.Unknown)
+ if (extra.ExtraType is null or ExtraType.Unknown || candidate.ExtraType != ExtraType.Unknown)
{
- extra.ExtraType = extraType;
+ extra.ExtraType = candidate.ExtraType;
}
// Only return items that are actual extras (have ExtraType set)
@@ -3344,7 +3421,7 @@ namespace Emby.Server.Implementations.Library
// so that RefreshExtras can detect when they need updating and set ForceSave.
if (extra.ExtraType is not null)
{
- extra.IsInMixedFolder = isInMixedFolder;
+ extra.IsInMixedFolder = candidate.IsInMixedFolder;
return extra;
}
@@ -3352,6 +3429,57 @@ namespace Emby.Server.Implementations.Library
}
}
+ /// <summary>
+ /// Gets the name to give an extra.
+ /// </summary>
+ /// <param name="candidate">The resolved extra.</param>
+ /// <param name="ownerVideoInfo">The naming info of the owner.</param>
+ /// <param name="typeCounters">Number of extras named after their type so far, per type.</param>
+ /// <returns>The name.</returns>
+ private string GetExtraName(ExtraCandidate candidate, VideoFileInfo ownerVideoInfo, Dictionary<ExtraType, int> typeCounters)
+ {
+ var isNamedAfterOwner = candidate.ExtraRule.RuleType switch
+ {
+ ExtraRuleType.Filename => true,
+ ExtraRuleType.Suffix => string.Equals(candidate.Extra.Name, ownerVideoInfo.Name, StringComparison.OrdinalIgnoreCase),
+ _ => false
+ };
+
+ if (!isNamedAfterOwner)
+ {
+ return candidate.Extra.Name;
+ }
+
+ typeCounters.TryGetValue(candidate.ExtraType, out var seen);
+ typeCounters[candidate.ExtraType] = seen + 1;
+
+ var typeName = _localization.GetServerLocalizedString(GetExtraTypeNameKey(candidate.ExtraType));
+
+ return seen == 0
+ ? typeName
+ : string.Format(
+ CultureInfo.InvariantCulture,
+ _localization.GetServerLocalizedString("NameExtraNumbered"),
+ typeName,
+ seen + 1);
+ }
+
+ private static string GetExtraTypeNameKey(ExtraType extraType) => extraType switch
+ {
+ ExtraType.Clip => "NameExtraClip",
+ ExtraType.Trailer => "NameExtraTrailer",
+ ExtraType.BehindTheScenes => "NameExtraBehindTheScenes",
+ ExtraType.DeletedScene => "NameExtraDeletedScene",
+ ExtraType.Interview => "NameExtraInterview",
+ ExtraType.Scene => "NameExtraScene",
+ ExtraType.Sample => "NameExtraSample",
+ ExtraType.ThemeSong => "NameExtraThemeSong",
+ ExtraType.ThemeVideo => "NameExtraThemeVideo",
+ ExtraType.Featurette => "NameExtraFeaturette",
+ ExtraType.Short => "NameExtraShort",
+ _ => "NameExtraUnknown"
+ };
+
public string GetPathAfterNetworkSubstitution(string path, BaseItem? ownerItem)
{
foreach (var map in _configurationManager.Configuration.PathSubstitutions)
@@ -3428,6 +3556,12 @@ namespace Emby.Server.Implementations.Library
return _peopleRepository.GetPeopleNamesByItems(itemIds, personTypes);
}
+ /// <inheritdoc/>
+ public IReadOnlyDictionary<Guid, IReadOnlyList<PersonInfo>> GetPeopleByItems(IReadOnlyList<Guid> itemIds)
+ {
+ return _peopleRepository.GetPeopleByItems(itemIds);
+ }
+
public void UpdatePeople(BaseItem item, List<PersonInfo> people)
{
UpdatePeopleAsync(item, people, CancellationToken.None).GetAwaiter().GetResult();
@@ -3902,5 +4036,7 @@ namespace Emby.Server.Implementations.Library
SetTopParentOrAncestorIds(query);
return _itemRepository.GetMediaStreamLanguages(query, mediaStreamType);
}
+
+ private sealed record ExtraCandidate(BaseItem Extra, ExtraType ExtraType, ExtraRule ExtraRule, bool IsInMixedFolder);
}
}
diff --git a/Emby.Server.Implementations/Library/Resolvers/ExtraResolver.cs b/Emby.Server.Implementations/Library/Resolvers/ExtraResolver.cs
index 6ba4a7bce6..a0f75e4ddb 100644
--- a/Emby.Server.Implementations/Library/Resolvers/ExtraResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/ExtraResolver.cs
@@ -54,12 +54,13 @@ namespace Emby.Server.Implementations.Library.Resolvers
_ => _videoResolvers
};
- public bool TryGetExtraTypeForOwner(string path, VideoFileInfo ownerVideoFileInfo, [NotNullWhen(true)] out ExtraType? extraType, string? libraryRoot = "")
+ public bool TryGetExtraTypeForOwner(string path, VideoFileInfo ownerVideoFileInfo, [NotNullWhen(true)] out ExtraType? extraType, [NotNullWhen(true)] out ExtraRule? extraRule, string? libraryRoot = "")
{
var extraResult = GetExtraInfo(path, _namingOptions, libraryRoot);
- if (extraResult.ExtraType is null)
+ if (extraResult.ExtraType is null || extraResult.Rule is null)
{
extraType = null;
+ extraRule = null;
return false;
}
@@ -88,6 +89,7 @@ namespace Emby.Server.Implementations.Library.Resolvers
}
extraType = extraResult.ExtraType;
+ extraRule = extraResult.Rule;
return isValid;
}
diff --git a/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs
index 74c1f69616..d6513fc79c 100644
--- a/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs
@@ -4,6 +4,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using Emby.Server.Implementations.Playlists;
using Jellyfin.Data.Enums;
using Jellyfin.Extensions;
using MediaBrowser.Controller.Library;
@@ -46,6 +47,19 @@ namespace Emby.Server.Implementations.Library.Resolvers
};
}
+ // Anything directly inside the internal playlists folder is a playlist, even when its
+ // playlist.xml is missing: failing to resolve here makes the library scan treat the
+ // playlist as deleted from disk and remove it, taking its items with it.
+ if (args.Parent is PlaylistsFolder)
+ {
+ return new Playlist
+ {
+ Path = args.Path,
+ Name = filename,
+ OpenAccess = true
+ };
+ }
+
// It's a directory-based playlist if the directory contains a playlist file
IEnumerable<string> filePaths;
try
diff --git a/Emby.Server.Implementations/Library/Search/SearchManager.cs b/Emby.Server.Implementations/Library/Search/SearchManager.cs
index a5be3f07bd..0e180753a6 100644
--- a/Emby.Server.Implementations/Library/Search/SearchManager.cs
+++ b/Emby.Server.Implementations/Library/Search/SearchManager.cs
@@ -92,49 +92,46 @@ public class SearchManager : ISearchManager
await Task.WhenAll(externalTask, internalTask).ConfigureAwait(false);
var externalResults = await externalTask.ConfigureAwait(false);
- var fromExternal = externalResults.Count > 0;
- IReadOnlyList<SearchResult> results;
- if (fromExternal)
- {
- results = externalResults;
- }
- else
- {
- results = await internalTask.ConfigureAwait(false);
- if (_internalProviders.Length > 0)
- {
- _logger.LogDebug("No results from external providers, using internal provider results");
- }
- }
// Internal providers apply user-access filtering inline in their queries. External
// providers don't know about user permissions, so they may return IDs from hidden
- // libraries or items the user is otherwise blocked from. Run the post-filter only
- // when results came from externals to close that gap. The Items controller's second
- // roundtrip via folder.GetItems applies most of these again, but it does not restrict
- // by TopParentIds when ItemIds is set.
- if (fromExternal && results.Count > 0 && query.UserId.HasValue && !query.UserId.Value.IsEmpty())
+ // libraries or items the user is otherwise blocked from. Filter them here to close
+ // that gap. The Items controller's second roundtrip via folder.GetItems applies most
+ // of these again, but it does not restrict by TopParentIds when ItemIds is set.
+ if (externalResults.Count > 0 && query.UserId.HasValue && !query.UserId.Value.IsEmpty())
{
var user = _userManager.GetUserById(query.UserId.Value);
if (user is not null)
{
- results = await FilterByUserAccessAsync(results, user, cancellationToken).ConfigureAwait(false);
+ externalResults = await FilterByUserAccessAsync(externalResults, user, query, cancellationToken).ConfigureAwait(false);
}
}
- return results;
+ if (externalResults.Count > 0)
+ {
+ return externalResults;
+ }
+
+ var internalResults = await internalTask.ConfigureAwait(false);
+ if (_internalProviders.Length > 0)
+ {
+ _logger.LogDebug("No results from external providers, using internal provider results");
+ }
+
+ return internalResults;
}
private async Task<IReadOnlyList<SearchResult>> FilterByUserAccessAsync(
IReadOnlyList<SearchResult> candidates,
User user,
+ SearchProviderQuery query,
CancellationToken cancellationToken)
{
- // SetUser populates parental rating + blocked/allowed tags. ConfigureUserAccess populates
- // TopParentIds for the user's accessible libraries — we call it before assigning ItemIds
- // because LibraryManager.AddUserToQuery skips TopParentIds when ItemIds is non-empty.
- var accessFilter = new InternalItemsQuery(user);
- _libraryManager.ConfigureUserAccess(accessFilter, user);
+ // SetUser populates parental rating + blocked/allowed tags, Build populates TopParentIds
+ // for the user's accessible libraries. The candidate ids are applied to the query below
+ // rather than to the filter because LibraryManager.AddUserToQuery skips TopParentIds when
+ // ItemIds is non-empty.
+ var accessFilter = SearchQueryAccessFilter.Build(user, query, _libraryManager);
Guid[] candidateIds = [.. candidates.Select(c => c.ItemId)];
diff --git a/Emby.Server.Implementations/Library/Search/SearchQueryAccessFilter.cs b/Emby.Server.Implementations/Library/Search/SearchQueryAccessFilter.cs
new file mode 100644
index 0000000000..6e3f01de13
--- /dev/null
+++ b/Emby.Server.Implementations/Library/Search/SearchQueryAccessFilter.cs
@@ -0,0 +1,38 @@
+using Jellyfin.Database.Implementations.Entities;
+using Jellyfin.Extensions;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
+
+namespace Emby.Server.Implementations.Library.Search;
+
+/// <summary>
+/// Builds the access filter that decides which items a search may return for a user.
+/// </summary>
+internal static class SearchQueryAccessFilter
+{
+ /// <summary>
+ /// Builds an access filter carrying the search's library access and type filters.
+ /// </summary>
+ /// <param name="user">The user the search runs for.</param>
+ /// <param name="query">The search query.</param>
+ /// <param name="libraryManager">The library manager.</param>
+ /// <returns>The access filter.</returns>
+ public static InternalItemsQuery Build(User user, SearchProviderQuery query, ILibraryManager libraryManager)
+ {
+ // The type filters have to travel with the access filter: a by-name item belongs to no
+ // library, so it carries no TopParentId to match, and the library filter only knows to
+ // exempt it when the query says those types are wanted. A search scoped to a parent gets
+ // no exemption because a by-name item has no parent to descend from either.
+ var accessFilter = new InternalItemsQuery(user)
+ {
+ IncludeItemTypes = query.IncludeItemTypes,
+ ExcludeItemTypes = query.ExcludeItemTypes,
+ IncludeItemsByName = !query.ParentId.HasValue || query.ParentId.Value.IsEmpty()
+ };
+
+ // ConfigureUserAccess populates TopParentIds for the libraries the user may open.
+ libraryManager.ConfigureUserAccess(accessFilter, user);
+
+ return accessFilter;
+ }
+}
diff --git a/Emby.Server.Implementations/Library/Search/SqlSearchProvider.cs b/Emby.Server.Implementations/Library/Search/SqlSearchProvider.cs
index bc766f1c8c..c4d3b249d5 100644
--- a/Emby.Server.Implementations/Library/Search/SqlSearchProvider.cs
+++ b/Emby.Server.Implementations/Library/Search/SqlSearchProvider.cs
@@ -114,7 +114,7 @@ public class SqlSearchProvider : IInternalSearchProvider
dbQuery = ApplyTypeFilter(dbQuery, query.IncludeItemTypes, query.ExcludeItemTypes);
dbQuery = ApplyMediaTypeFilter(dbQuery, query.MediaTypes);
dbQuery = ApplyParentFilter(dbQuery, query.ParentId);
- dbQuery = ApplyUserAccessFilter(dbContext, dbQuery, query.UserId);
+ dbQuery = ApplyUserAccessFilter(dbContext, dbQuery, query);
// Compute the score in SQL: the ternary translates to a CASE WHEN. CleanName is
// the pre-normalized (lowercase, diacritic-stripped) form, so we score against it
@@ -196,8 +196,9 @@ public class SqlSearchProvider : IInternalSearchProvider
private IQueryable<BaseItemEntity> ApplyUserAccessFilter(
JellyfinDbContext dbContext,
IQueryable<BaseItemEntity> query,
- Guid? userId)
+ SearchProviderQuery searchQuery)
{
+ var userId = searchQuery.UserId;
if (!userId.HasValue || userId.Value.IsEmpty())
{
return query;
@@ -209,8 +210,7 @@ public class SqlSearchProvider : IInternalSearchProvider
return query;
}
- var accessFilter = new InternalItemsQuery(user);
- _libraryManager.ConfigureUserAccess(accessFilter, user);
+ var accessFilter = SearchQueryAccessFilter.Build(user, searchQuery, _libraryManager);
return _queryHelpers.ApplyAccessFiltering(dbContext, query, accessFilter);
}
diff --git a/Emby.Server.Implementations/Library/SimilarItems/SimilarItemsManager.cs b/Emby.Server.Implementations/Library/SimilarItems/SimilarItemsManager.cs
index d923cff07e..4e482c174a 100644
--- a/Emby.Server.Implementations/Library/SimilarItems/SimilarItemsManager.cs
+++ b/Emby.Server.Implementations/Library/SimilarItems/SimilarItemsManager.cs
@@ -183,6 +183,7 @@ public class SimilarItemsManager : ISimilarItemsManager
// Collect references in batches and resolve against local library.
// Stop fetching once we have enough resolved local items.
const int BatchSize = 20;
+ const int MaxRemoteReferenceFetchLimit = 500;
var remaining = requestedLimit - allResults.Count;
var collectedReferences = new List<SimilarItemReference>();
var pendingBatch = new List<SimilarItemReference>();
@@ -199,7 +200,7 @@ public class SimilarItemsManager : ISimilarItemsManager
remaining -= resolvedItems.Count;
pendingBatch.Clear();
- if (remaining <= 0)
+ if (remaining <= 0 || collectedReferences.Count >= MaxRemoteReferenceFetchLimit)
{
break;
}
diff --git a/Emby.Server.Implementations/Library/Validators/CollectionPosterVerifyPostScanTask.cs b/Emby.Server.Implementations/Library/Validators/CollectionPosterVerifyPostScanTask.cs
new file mode 100644
index 0000000000..2cfa446862
--- /dev/null
+++ b/Emby.Server.Implementations/Library/Validators/CollectionPosterVerifyPostScanTask.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Model.Entities;
+using Microsoft.Extensions.Logging;
+
+namespace Emby.Server.Implementations.Library.Validators;
+
+/// <summary>
+/// Ensures top-level library folders have a primary poster after scans.
+/// Poster extraction is attempted before library scanning. When a library is
+/// empty at that point, no poster can be extracted. This post-scan task reruns
+/// metadata extraction for top-level folders that are still missing images.
+/// </summary>
+public class CollectionPosterVerifyPostScanTask : ILibraryPostScanTask
+{
+ private readonly ILibraryManager _libraryManager;
+ private readonly ILogger<CollectionPosterVerifyPostScanTask> _logger;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CollectionPosterVerifyPostScanTask" /> class.
+ /// </summary>
+ /// <param name="libraryManager">The library manager.</param>
+ /// <param name="logger">The logger.</param>
+ public CollectionPosterVerifyPostScanTask(
+ ILibraryManager libraryManager,
+ ILogger<CollectionPosterVerifyPostScanTask> logger)
+ {
+ _libraryManager = libraryManager;
+ _logger = logger;
+ }
+
+ /// <summary>
+ /// Runs the specified progress.
+ /// </summary>
+ /// <param name="progress">The progress.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task.</returns>
+ public async Task Run(IProgress<double> progress, CancellationToken cancellationToken)
+ {
+ var libraries = _libraryManager.GetUserRootFolder().Children.OfType<CollectionFolder>().ToList();
+ var totalLibraries = libraries.Count;
+ var processedLibraries = 0;
+
+ foreach (var library in libraries)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ if (!library.HasImage(ImageType.Primary))
+ {
+ _logger.LogDebug("Library {LibraryName} is missing a primary image. Refreshing metadata.", library.Name);
+ await library.RefreshMetadata(cancellationToken).ConfigureAwait(false);
+ }
+
+ processedLibraries++;
+ progress.Report((double)processedLibraries / totalLibraries * 100);
+ }
+
+ progress.Report(100);
+ }
+}
diff --git a/Emby.Server.Implementations/Localization/Core/ar.json b/Emby.Server.Implementations/Localization/Core/ar.json
index 17af935562..2dc4f5652b 100644
--- a/Emby.Server.Implementations/Localization/Core/ar.json
+++ b/Emby.Server.Implementations/Localization/Core/ar.json
@@ -100,7 +100,7 @@
"TaskAudioNormalization": "تطبيع الصوت",
"TaskAudioNormalizationDescription": "يفحص الملفات لجمع بيانات تطبيع الصوت.",
"TaskDownloadMissingLyrics": "تنزيل الكلمات المفقودة",
- "TaskDownloadMissingLyricsDescription": "ينزّل الكلمات للأغاني.",
+ "TaskDownloadMissingLyricsDescription": "تحميل كلمات الأغاني",
"TaskExtractMediaSegments": "فحص مقاطع المحتوى",
"TaskExtractMediaSegmentsDescription": "يستخرج أو يحصل على مقاطع المحتوى من الملحقات المفعّلة لمقاطع المحتوى (MediaSegment).",
"TaskMoveTrickplayImages": "نقل موقع صور معاينات التنقل",
@@ -108,5 +108,18 @@
"CleanupUserDataTask": "مهمة تنظيف بيانات المستخدم",
"CleanupUserDataTaskDescription": "ينظف جميع بيانات المستخدم (مثل حالة المشاهدة وحالة المفضلة وغيرها) للمحتوى الذي لم يعد موجوداً لمدة 90 يوماً على الأقل.",
"Original": "فريد",
- "LyricDownloadFailureFromForItem": "فشل تحميل الكلمات من {0} إلى {1}"
+ "LyricDownloadFailureFromForItem": "فشل تحميل الكلمات من {0} إلى {1}",
+ "NameExtraBehindTheScenes": "خلف المشاهد",
+ "NameExtraClip": "مقطع",
+ "NameExtraDeletedScene": "المشهد المحذوف",
+ "NameExtraInterview": "مقابلة",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraSample": "عيّنة",
+ "NameExtraScene": "مشهد",
+ "NameExtraShort": "قصير",
+ "NameExtraThemeSong": "الاغنية السمة",
+ "NameExtraThemeVideo": "الفيديو السمة",
+ "NameExtraFeaturette": "فيلم قصير إضافي",
+ "NameExtraTrailer": "إعلان ترويجي",
+ "NameExtraUnknown": "إضافي"
}
diff --git a/Emby.Server.Implementations/Localization/Core/ca.json b/Emby.Server.Implementations/Localization/Core/ca.json
index 6c81726ee6..12076d6c15 100644
--- a/Emby.Server.Implementations/Localization/Core/ca.json
+++ b/Emby.Server.Implementations/Localization/Core/ca.json
@@ -108,5 +108,18 @@
"CleanupUserDataTaskDescription": "Neteja totes les dades d'usuari (estat de la visualització, estat dels preferits, etc.) del contingut multimèdia que no ha estat present durant almenys 90 dies.",
"CleanupUserDataTask": "Tasca de neteja de dades d'usuari",
"Original": "Original",
- "LyricDownloadFailureFromForItem": "No s'han pogut descarregar les lletres des de {0} per a {1}"
+ "LyricDownloadFailureFromForItem": "No s'han pogut descarregar les lletres des de {0} per a {1}",
+ "NameExtraBehindTheScenes": "Rere les càmeres",
+ "NameExtraClip": "Tall",
+ "NameExtraDeletedScene": "Escena eliminada",
+ "NameExtraFeaturette": "Migmetratge",
+ "NameExtraInterview": "Entrevista",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraSample": "Mostra",
+ "NameExtraScene": "Escena",
+ "NameExtraShort": "Curt",
+ "NameExtraThemeSong": "Tema musical",
+ "NameExtraThemeVideo": "Vídeo temàtic",
+ "NameExtraTrailer": "Tràiler",
+ "NameExtraUnknown": "Extra"
}
diff --git a/Emby.Server.Implementations/Localization/Core/cs.json b/Emby.Server.Implementations/Localization/Core/cs.json
index 28f0e2df97..033002d2b2 100644
--- a/Emby.Server.Implementations/Localization/Core/cs.json
+++ b/Emby.Server.Implementations/Localization/Core/cs.json
@@ -108,5 +108,18 @@
"CleanupUserDataTaskDescription": "Odstraní všechna uživatelská data (stav zhlédnutí, oblíbené atd.) z médií, které již neexistují více než 90 dní.",
"CleanupUserDataTask": "Pročistit uživatelská data",
"Original": "Originál",
- "LyricDownloadFailureFromForItem": "Nepodařilo se stáhnout texty pro {1} ze služby {0}"
+ "LyricDownloadFailureFromForItem": "Nepodařilo se stáhnout texty pro {1} ze služby {0}",
+ "NameExtraBehindTheScenes": "Zákulisí",
+ "NameExtraClip": "Klip",
+ "NameExtraDeletedScene": "Vymazaná scéna",
+ "NameExtraFeaturette": "Featurette",
+ "NameExtraInterview": "Rozhovor",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraSample": "Ukázka",
+ "NameExtraScene": "Scéna",
+ "NameExtraShort": "Krátké",
+ "NameExtraThemeSong": "Úvodní píseň",
+ "NameExtraThemeVideo": "Úvodní video",
+ "NameExtraTrailer": "Upoutávka",
+ "NameExtraUnknown": "Extra"
}
diff --git a/Emby.Server.Implementations/Localization/Core/da.json b/Emby.Server.Implementations/Localization/Core/da.json
index de56b6fd66..6e5532ead9 100644
--- a/Emby.Server.Implementations/Localization/Core/da.json
+++ b/Emby.Server.Implementations/Localization/Core/da.json
@@ -51,7 +51,7 @@
"Shows": "Serier",
"StartupEmbyServerIsLoading": "Jellyfin er i gang med at starte. Prøv igen om et øjeblik.",
"SubtitleDownloadFailureFromForItem": "Undertekster kunne ikke hentes fra {0} til {1}",
- "TvShows": "TV-serier",
+ "TvShows": "Serier",
"UserCreatedWithName": "Bruger {0} er blevet oprettet",
"UserDeletedWithName": "Brugeren {0} er nu slettet",
"UserDownloadingItemWithValues": "{0} henter {1}",
@@ -80,8 +80,8 @@
"TaskRefreshChapterImagesDescription": "Laver miniaturebilleder for videoer, der har kapitler.",
"TaskRefreshChannelsDescription": "Opdaterer information for internetkanaler.",
"TaskRefreshChannels": "Opdatér kanaler",
- "TaskCleanTranscodeDescription": "Fjerner omkodningsfiler, som er mere end 1 dag gamle.",
- "TaskCleanTranscode": "Tøm omkodningsmappen",
+ "TaskCleanTranscodeDescription": "Fjerner transkodningsfiler, som er mere end 1 dag gamle.",
+ "TaskCleanTranscode": "Tøm transkodningsmappen",
"TaskRefreshPeople": "Opdatér personer",
"TaskRefreshPeopleDescription": "Opdaterer metadata for skuespillere og instruktører i dit mediebibliotek.",
"TaskCleanActivityLogDescription": "Sletter linjer i aktivitetsloggen ældre end den konfigurerede alder.",
@@ -108,5 +108,18 @@
"CleanupUserDataTask": "Brugerdata oprydningsopgave",
"CleanupUserDataTaskDescription": "Rydder alle brugerdata (eks. visning- og favoritstatus) fra medier, der har været utilgængelige i mindst 90 dage.",
"LyricDownloadFailureFromForItem": "Sangtekster kunne ikke downloades fra {0} til {1}",
- "Original": "Original"
+ "Original": "Original",
+ "NameExtraBehindTheScenes": "Bag scenerne",
+ "NameExtraClip": "Klip",
+ "NameExtraDeletedScene": "Slettet scene",
+ "NameExtraFeaturette": "Featurette",
+ "NameExtraInterview": "Interview",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraSample": "Smagsprøve",
+ "NameExtraScene": "Scene",
+ "NameExtraShort": "Kort",
+ "NameExtraThemeSong": "Temasang",
+ "NameExtraThemeVideo": "Temavideo",
+ "NameExtraTrailer": "Trailer",
+ "NameExtraUnknown": "Ekstra"
}
diff --git a/Emby.Server.Implementations/Localization/Core/de.json b/Emby.Server.Implementations/Localization/Core/de.json
index 8ac5fdf6fc..ce5a4c0a6c 100644
--- a/Emby.Server.Implementations/Localization/Core/de.json
+++ b/Emby.Server.Implementations/Localization/Core/de.json
@@ -1,6 +1,6 @@
{
"AppDeviceValues": "App: {0}, Gerät: {1}",
- "Artists": "Interpreten",
+ "Artists": "Künstler",
"AuthenticationSucceededWithUserName": "{0} erfolgreich authentifiziert",
"Books": "Bücher",
"ChapterNameValue": "Kapitel {0}",
@@ -108,5 +108,18 @@
"CleanupUserDataTask": "Aufgabe zur Bereinigung von Benutzerdaten",
"CleanupUserDataTaskDescription": "Löscht alle Benutzerdaten (Abspielstatus, Favoritenstatus, usw.) von Medien, die seit mindestens 90 Tagen nicht mehr vorhanden sind.",
"Original": "Original",
- "LyricDownloadFailureFromForItem": "Fehler beim Download der Songtexte von {0} für {1}"
+ "LyricDownloadFailureFromForItem": "Fehler beim Download der Songtexte von {0} für {1}",
+ "NameExtraBehindTheScenes": "Behind The Scenes",
+ "NameExtraDeletedScene": "Entfernte Szene",
+ "NameExtraInterview": "Interview",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraSample": "Ausschnitt",
+ "NameExtraScene": "Szene",
+ "NameExtraShort": "Kurzfilm",
+ "NameExtraThemeSong": "Titellied",
+ "NameExtraThemeVideo": "Titelvideo",
+ "NameExtraTrailer": "Trailer",
+ "NameExtraUnknown": "Extra",
+ "NameExtraClip": "Clip",
+ "NameExtraFeaturette": "Hinter den Kulissen"
}
diff --git a/Emby.Server.Implementations/Localization/Core/en-US.json b/Emby.Server.Implementations/Localization/Core/en-US.json
index 856941c61a..578c85da9d 100644
--- a/Emby.Server.Implementations/Localization/Core/en-US.json
+++ b/Emby.Server.Implementations/Localization/Core/en-US.json
@@ -28,6 +28,19 @@
"Movies": "Movies",
"Music": "Music",
"MusicVideos": "Music Videos",
+ "NameExtraBehindTheScenes": "Behind The Scenes",
+ "NameExtraClip": "Clip",
+ "NameExtraDeletedScene": "Deleted Scene",
+ "NameExtraFeaturette": "Featurette",
+ "NameExtraInterview": "Interview",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraSample": "Sample",
+ "NameExtraScene": "Scene",
+ "NameExtraShort": "Short",
+ "NameExtraThemeSong": "Theme Song",
+ "NameExtraThemeVideo": "Theme Video",
+ "NameExtraTrailer": "Trailer",
+ "NameExtraUnknown": "Extra",
"NameInstallFailed": "{0} installation failed",
"NameSeasonNumber": "Season {0}",
"NameSeasonUnknown": "Season Unknown",
diff --git a/Emby.Server.Implementations/Localization/Core/eo.json b/Emby.Server.Implementations/Localization/Core/eo.json
index 133a2755a8..e59f089459 100644
--- a/Emby.Server.Implementations/Localization/Core/eo.json
+++ b/Emby.Server.Implementations/Localization/Core/eo.json
@@ -97,5 +97,9 @@
"TaskAudioNormalizationDescription": "Skanas dosierojn por sonnivelaj normaligaj datumoj.",
"TaskRefreshTrickplayImages": "Generi la bildojn por TrickPlay (Antaŭrigardo rapida antaŭen)",
"TaskAudioNormalization": "Normaligo Sonnivela",
- "HearingImpaired": "Surda"
+ "HearingImpaired": "Surda",
+ "NameExtraDeletedScene": "Forigita sceno",
+ "NameExtraScene": "Sceno",
+ "NameExtraThemeSong": "Tema Kanto",
+ "Original": "Originala"
}
diff --git a/Emby.Server.Implementations/Localization/Core/es-AR.json b/Emby.Server.Implementations/Localization/Core/es-AR.json
index bccfdd4c19..a30abb9d4e 100644
--- a/Emby.Server.Implementations/Localization/Core/es-AR.json
+++ b/Emby.Server.Implementations/Localization/Core/es-AR.json
@@ -108,5 +108,18 @@
"CleanupUserDataTaskDescription": "Limpia todos los datos del usuario (estado de visualización, estado de los favoritos, etc.) que no están presentes en la biblioteca por al menos 90 días.",
"CleanupUserDataTask": "Tarea de limpieza de datos de usuarios",
"LyricDownloadFailureFromForItem": "No se pudo descargar la letra desde {0} para {1}",
- "Original": "Original"
+ "Original": "Original",
+ "NameExtraBehindTheScenes": "Detrás de cámaras",
+ "NameExtraClip": "Clip",
+ "NameExtraDeletedScene": "Escena eliminada",
+ "NameExtraFeaturette": "Minidocumental",
+ "NameExtraInterview": "Entrevista",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraSample": "Muestra",
+ "NameExtraScene": "Escena",
+ "NameExtraShort": "Cortometraje",
+ "NameExtraThemeSong": "Música de presentación",
+ "NameExtraThemeVideo": "Video de presentación",
+ "NameExtraTrailer": "Tráiler",
+ "NameExtraUnknown": "Extra"
}
diff --git a/Emby.Server.Implementations/Localization/Core/es-MX.json b/Emby.Server.Implementations/Localization/Core/es-MX.json
index ac489b9e77..f4cf45cb12 100644
--- a/Emby.Server.Implementations/Localization/Core/es-MX.json
+++ b/Emby.Server.Implementations/Localization/Core/es-MX.json
@@ -106,5 +106,20 @@
"TaskMoveTrickplayImages": "Migrar la ubicación de la imagen de Trickplay",
"TaskMoveTrickplayImagesDescription": "Mueve archivos de trickplay existentes según la configuración de la biblioteca.",
"CleanupUserDataTask": "Tarea de limpieza de los datos del usuario",
- "CleanupUserDataTaskDescription": "Limpia toda la información de usuario (Estado de última vez visto, favoritos, etc) del archivo media que no está presente por los últimos 90 días."
+ "CleanupUserDataTaskDescription": "Limpia toda la información de usuario (Estado de última vez visto, favoritos, etc) del archivo media que no está presente por los últimos 90 días.",
+ "LyricDownloadFailureFromForItem": "No se pudo descargar la letra desde {0} para {1}",
+ "NameExtraBehindTheScenes": "Detrás de cámaras",
+ "NameExtraClip": "Clip",
+ "NameExtraDeletedScene": "Escena eliminada",
+ "NameExtraFeaturette": "Minidocumental",
+ "NameExtraInterview": "Entrevista",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraSample": "Muestra",
+ "NameExtraScene": "Escena",
+ "NameExtraShort": "Cortometraje",
+ "NameExtraThemeSong": "Música de presentación",
+ "NameExtraThemeVideo": "Video de presentación",
+ "NameExtraTrailer": "Tráiler",
+ "NameExtraUnknown": "Extra",
+ "Original": "Original"
}
diff --git a/Emby.Server.Implementations/Localization/Core/es.json b/Emby.Server.Implementations/Localization/Core/es.json
index 563dce8fe6..9e82e0601b 100644
--- a/Emby.Server.Implementations/Localization/Core/es.json
+++ b/Emby.Server.Implementations/Localization/Core/es.json
@@ -108,5 +108,18 @@
"CleanupUserDataTask": "Tarea de limpieza de datos del usuario",
"CleanupUserDataTaskDescription": "Limpia todos los datos del usuario (estado de visualización, favoritos, etc.) de los medios que ya no están disponibles desde hace al menos 90 días.",
"Original": "Original",
- "LyricDownloadFailureFromForItem": "No se pudieron descargar las letras desde {0} para {1}"
+ "LyricDownloadFailureFromForItem": "No se pudieron descargar las letras desde {0} para {1}",
+ "NameExtraBehindTheScenes": "Detrás de Cámaras",
+ "NameExtraClip": "Clip",
+ "NameExtraDeletedScene": "Escena eliminada",
+ "NameExtraFeaturette": "Reportaje especial",
+ "NameExtraInterview": "Entrevista",
+ "NameExtraSample": "Muestra",
+ "NameExtraScene": "Escena",
+ "NameExtraShort": "Cortometraje",
+ "NameExtraThemeSong": "Tema principal",
+ "NameExtraThemeVideo": "Vídeo del tema principal",
+ "NameExtraTrailer": "Tráiler",
+ "NameExtraUnknown": "Extra",
+ "NameExtraNumbered": "{0} {1}"
}
diff --git a/Emby.Server.Implementations/Localization/Core/es_419.json b/Emby.Server.Implementations/Localization/Core/es_419.json
index 4404354a88..274c60c7bc 100644
--- a/Emby.Server.Implementations/Localization/Core/es_419.json
+++ b/Emby.Server.Implementations/Localization/Core/es_419.json
@@ -108,5 +108,18 @@
"CleanupUserDataTask": "Tarea de limpieza de datos de usuario",
"CleanupUserDataTaskDescription": "Limpia todos los datos de usuario (estado de visualización, favoritos, etc.) que no están presentes en la biblioteca por al menos 90 días.",
"LyricDownloadFailureFromForItem": "No se pudo descargar las letras de {0} para {1}",
- "Original": "Original"
+ "Original": "Original",
+ "NameExtraUnknown": "Extra",
+ "NameExtraBehindTheScenes": "Detrás de cámaras",
+ "NameExtraClip": "Clip",
+ "NameExtraDeletedScene": "Escena eliminada",
+ "NameExtraFeaturette": "Minidocumental",
+ "NameExtraInterview": "Entrevista",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraSample": "Muestra",
+ "NameExtraScene": "Escena",
+ "NameExtraShort": "Cortometraje",
+ "NameExtraThemeSong": "Música de presentación",
+ "NameExtraThemeVideo": "Video de presentación",
+ "NameExtraTrailer": "Tráiler"
}
diff --git a/Emby.Server.Implementations/Localization/Core/et.json b/Emby.Server.Implementations/Localization/Core/et.json
index e6bf1f25b5..a7afcf5b77 100644
--- a/Emby.Server.Implementations/Localization/Core/et.json
+++ b/Emby.Server.Implementations/Localization/Core/et.json
@@ -108,5 +108,18 @@
"CleanupUserDataTask": "Puhasta kasutajaandmed",
"CleanupUserDataTaskDescription": "Puhastab kõik kasutajaandmed (vaatamise olek, lemmikute olek jne) meediast, mida pole enam vähemalt 90 päeva saadaval olnud.",
"LyricDownloadFailureFromForItem": "Laulusõnade hankimine teenusest {0} loole {1} nurjus",
- "Original": "Algne"
+ "Original": "Algne",
+ "NameExtraBehindTheScenes": "Kulisside taga",
+ "NameExtraDeletedScene": "Väljajäetud stseen",
+ "NameExtraFeaturette": "Lisalõik",
+ "NameExtraInterview": "Intervjuu",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraSample": "Näidis",
+ "NameExtraScene": "Stseen",
+ "NameExtraShort": "Lühifilm",
+ "NameExtraThemeSong": "Tunnusmeloodia",
+ "NameExtraThemeVideo": "Tunnusvideo",
+ "NameExtraTrailer": "Treiler",
+ "NameExtraUnknown": "Lisamaterjal",
+ "NameExtraClip": "Videoklipp"
}
diff --git a/Emby.Server.Implementations/Localization/Core/eu.json b/Emby.Server.Implementations/Localization/Core/eu.json
index 71c351adcd..df6855d6e3 100644
--- a/Emby.Server.Implementations/Localization/Core/eu.json
+++ b/Emby.Server.Implementations/Localization/Core/eu.json
@@ -108,5 +108,18 @@
"CleanupUserDataTaskDescription": "Gutxienez 90 egunez dagoeneko existitzen ez den multimediatik erabiltzaile-datu guztiak (ikusteko egoera, gogokoen egoera, etab.) garbitzen ditu.",
"CleanupUserDataTask": "Erabiltzaileen datuak garbitzeko zeregina",
"LyricDownloadFailureFromForItem": "Ezin izan dira {1}-ren letrak deskargatu {0}-tik",
- "Original": "Jatorrizkoa"
+ "Original": "Jatorrizkoa",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraSample": "Lagina",
+ "NameExtraScene": "Eszena",
+ "NameExtraShort": "Laburra",
+ "NameExtraThemeSong": "Gai-abestia",
+ "NameExtraThemeVideo": "Gai-bideoa",
+ "NameExtraBehindTheScenes": "Eszenen atzean",
+ "NameExtraClip": "Klipa",
+ "NameExtraDeletedScene": "Ezabatutako eszena",
+ "NameExtraFeaturette": "Erreportajea",
+ "NameExtraInterview": "Elkarrizketa",
+ "NameExtraTrailer": "Trailerra",
+ "NameExtraUnknown": "Extra"
}
diff --git a/Emby.Server.Implementations/Localization/Core/fi.json b/Emby.Server.Implementations/Localization/Core/fi.json
index d080eb0236..36a248a1d1 100644
--- a/Emby.Server.Implementations/Localization/Core/fi.json
+++ b/Emby.Server.Implementations/Localization/Core/fi.json
@@ -108,5 +108,10 @@
"CleanupUserDataTask": "Käyttäjätietojen puhdistustehtävä",
"CleanupUserDataTaskDescription": "Puhdistaa kaikki käyttäjätiedot (katselutila, suosikit ym.) medioista, joita ei ole ollut saatavilla yli 90 päivään.",
"LyricDownloadFailureFromForItem": "Sanoitusten lataus kohteesta {0} kappaleelle {1} epäonnistui",
- "Original": "Alkuperäinen"
+ "Original": "Alkuperäinen",
+ "NameExtraBehindTheScenes": "Kulissien Takana",
+ "NameExtraClip": "Klippi",
+ "NameExtraDeletedScene": "Poistettu Kohtaus",
+ "NameExtraFeaturette": "Lyhytelokuva",
+ "NameExtraInterview": "Haastattelu"
}
diff --git a/Emby.Server.Implementations/Localization/Core/fo.json b/Emby.Server.Implementations/Localization/Core/fo.json
index e079ada064..d1e9065d97 100644
--- a/Emby.Server.Implementations/Localization/Core/fo.json
+++ b/Emby.Server.Implementations/Localization/Core/fo.json
@@ -1,6 +1,6 @@
{
"Artists": "Tónlistafólk",
- "Collections": "Søvn",
+ "Collections": "Samlingar",
"Default": "Forsett",
"External": "Ytri",
"Genres": "Greinar",
@@ -50,5 +50,66 @@
"MixedContent": "Blandað innihald",
"Music": "Tónleikur",
"UserStartedPlayingItemWithValues": "{0} spælur {1} á {2}",
- "HeaderContinueWatching": "Hald áfram at hyggja"
+ "HeaderContinueWatching": "Hald áfram at hyggja",
+ "MusicVideos": "Sjónbandaløg",
+ "TaskUpdatePluginsDescription": "Niðurtekur og innleggur dagføringar til ískoytisforrit ið eru stillaði til at dagførast sjálvvirkandi.",
+ "TaskCleanTranscodeDescription": "Strikar umkotaðar fílar ið eru eldri enn 1 dag.",
+ "TaskOptimizeDatabase": "Albøt dátugrunn",
+ "NameSeasonNumber": "Umfar {0}",
+ "NameSeasonUnknown": "Ókent umfar",
+ "ScheduledTaskFailedWithName": "{0} miseydnaðist",
+ "Undefined": "Óskilmarkað",
+ "TasksMaintenanceCategory": "Viðlíkahald",
+ "TaskCleanLogs": "Reinsa gerðalistaskjáttu",
+ "UserOnlineFromDevice": "{0} er íbundin frá {1}",
+ "HeaderNextUp": "Næst á skránni",
+ "NotificationOptionPluginError": "Brek í ískoytisforriti",
+ "NotificationOptionInstallationFailed": "Innleggingarbrek",
+ "NotificationOptionServerRestartRequired": "Tørvur er á ambætaraendurbyrjan",
+ "TasksApplicationCategory": "Nýtsluskipan",
+ "NotificationOptionApplicationUpdateAvailable": "Skipanardagføring er tøk",
+ "NotificationOptionApplicationUpdateInstalled": "Skipanardagføring varð innløgd",
+ "UserStoppedPlayingItemWithValues": "{0} er liðugur at spæla {1} á {2}",
+ "HomeVideos": "Heimaupptøkur",
+ "StartupEmbyServerIsLoading": "Jellyfin-ambætarin er undir byrjanarinnlesing. Vinaliga royn aftur um eitt bil.",
+ "UserOfflineFromDevice": "{0} breyt av á {1}",
+ "UserPasswordChangedWithName": "Loyniorðið hjá brúkaranum {0} er broytt",
+ "TasksChannelsCategory": "Alnetsrásir",
+ "TaskCleanActivityLog": "Reinsa virksemisskrá",
+ "TaskCleanActivityLogDescription": "Strikar skrásetingar eldri enn ásetta aldur.",
+ "TaskCleanCache": "Reinsa kovaskjáttu",
+ "TaskCleanCacheDescription": "Strikar kovafílar ið kervið ikki hevur tørv á longur.",
+ "TaskCleanTranscode": "Reinsa umkotuskjáttu",
+ "TaskDownloadMissingLyrics": "Niðurtak vantandi sangtekstir",
+ "TaskDownloadMissingSubtitles": "Niðurtak vantandi undirtekstir",
+ "CleanupUserDataTaskDescription": "Strikar allar brúkaradátur, so sum spælistøðu, yndislistastøðu o.s.fr., fyri miðlar ið ikki hava verið tøkir í í minsta lagi 90 dagar.",
+ "CleanupUserDataTask": "Koyrsla ið reinsar brúkaradátur",
+ "TaskRefreshPeople": "Dagfør persónsupplýsingar",
+ "TaskRefreshPeopleDescription": "Dagførur metadátur um leikarar og leikstjórar í tínum margmiðlasavni.",
+ "TaskRefreshChannelsDescription": "Dagførur upplýsingar um alnetsrásir.",
+ "TaskDownloadMissingSubtitlesDescription": "Leitar á alnótini eftir vantandi undirtekstum grundað á metadátauppsetan.",
+ "NotificationOptionTaskFailed": "Brek undir fyriskipaðari koyrslu",
+ "TaskRefreshLibraryDescription": "Skannar títt miðlasavn fyri nýggjum fílum og dagførur metadátur.",
+ "TaskKeyframeExtractor": "Lyklamyndaúttøka",
+ "TaskKeyframeExtractorDescription": "Úttekur lyklamyndir frá kykmynda-fílum til tess at byggja nágreiniligari HLS-spælilistar. Koyrslan kann taka langa tíð.",
+ "TaskOptimizeDatabaseDescription": "Trýstur dátugrunninin saman og loysur tóma goymslu. Koyrslan kann bøta um avrikið, eftir skanning ella aðrar broytingar í savninum ið elva til dátugrunnsbroytingar.",
+ "TaskRefreshChapterImagesDescription": "Ger smámyndir fyri kykmyndir ið hava kapitlar.",
+ "TaskRefreshChapterImages": "Kapitlamyndaúttøkur",
+ "NotificationOptionVideoPlayback": "Kykmyndaspæl byrjað",
+ "NotificationOptionVideoPlaybackStopped": "Kykmyndaspæl steðgað",
+ "NotificationOptionAudioPlayback": "Ljóðspæl byrjað",
+ "NotificationOptionAudioPlaybackStopped": "Ljóðspæl steðgað",
+ "TaskExtractMediaSegments": "Leita eftir margmiðlabrotum",
+ "TaskExtractMediaSegmentsDescription": "Framleiður upplýsingar um brot í margmiðlum, við hjálp frá MediaSegment-virktum ískoytisforritum.",
+ "NotificationOptionCameraImageUploaded": "Ljósmynd uppsend",
+ "NameExtraShort": "Stuttfilmur",
+ "NameExtraThemeSong": "Eyðkennislag",
+ "NameExtraTrailer": "Forfilmur",
+ "NameExtraInterview": "Samrøða",
+ "NameExtraBehindTheScenes": "Aftanfyri leiktjøldini",
+ "NameExtraClip": "Klipp",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraFeaturette": "Stuttur heimildarfilmur",
+ "TaskAudioNormalization": "Ljóðjavnan",
+ "TaskAudioNormalizationDescription": "Kannar fílur fyri dátum til ljóðjavnan."
}
diff --git a/Emby.Server.Implementations/Localization/Core/fr-CA.json b/Emby.Server.Implementations/Localization/Core/fr-CA.json
index e05cce47b0..393af79ab8 100644
--- a/Emby.Server.Implementations/Localization/Core/fr-CA.json
+++ b/Emby.Server.Implementations/Localization/Core/fr-CA.json
@@ -108,5 +108,18 @@
"CleanupUserDataTaskDescription": "Nettoie toutes les données utilisateur (état de la montre, statut favori, etc.) des supports qui ne sont plus présents depuis au moins 90 jours.",
"CleanupUserDataTask": "Tâche de nettoyage des données utilisateur",
"LyricDownloadFailureFromForItem": "Le téléchargement des paroles a échoué de {0} pour {1}",
- "Original": "Original"
+ "Original": "Original",
+ "NameExtraBehindTheScenes": "Dans Les Coulisses",
+ "NameExtraClip": "Clip",
+ "NameExtraDeletedScene": "Scène supprimée",
+ "NameExtraFeaturette": "Court-métrage",
+ "NameExtraInterview": "Entrevue",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraSample": "Échantillon",
+ "NameExtraScene": "Scène",
+ "NameExtraShort": "Court-métrage",
+ "NameExtraThemeSong": "Chanson thème",
+ "NameExtraThemeVideo": "Générique",
+ "NameExtraTrailer": "Bande-annonce",
+ "NameExtraUnknown": "Extra"
}
diff --git a/Emby.Server.Implementations/Localization/Core/fr.json b/Emby.Server.Implementations/Localization/Core/fr.json
index ceba1dcb41..858fd9eff6 100644
--- a/Emby.Server.Implementations/Localization/Core/fr.json
+++ b/Emby.Server.Implementations/Localization/Core/fr.json
@@ -108,5 +108,18 @@
"CleanupUserDataTaskDescription": "Nettoie toutes les données utilisateur (état de la montre, statut favori, etc.) des supports qui ne sont plus présents depuis au moins 90 jours.",
"CleanupUserDataTask": "Tâche de nettoyage des données utilisateur",
"LyricDownloadFailureFromForItem": "Le téléchargement des paroles à échoué de {0} pour {1}",
- "Original": "Original"
+ "Original": "Original",
+ "NameExtraBehindTheScenes": "Dans Les Coulisses",
+ "NameExtraClip": "Clip",
+ "NameExtraDeletedScene": "Scène supprimée",
+ "NameExtraFeaturette": "Court-métrage",
+ "NameExtraInterview": "Entrevue",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraSample": "Échantillon",
+ "NameExtraScene": "Scène",
+ "NameExtraShort": "Court-métrage",
+ "NameExtraThemeSong": "Thème musical",
+ "NameExtraThemeVideo": "Générique",
+ "NameExtraTrailer": "Bande-annonce",
+ "NameExtraUnknown": "Extra"
}
diff --git a/Emby.Server.Implementations/Localization/Core/gl.json b/Emby.Server.Implementations/Localization/Core/gl.json
index a68db0076a..9eb9786b8a 100644
--- a/Emby.Server.Implementations/Localization/Core/gl.json
+++ b/Emby.Server.Implementations/Localization/Core/gl.json
@@ -107,5 +107,19 @@
"TaskAudioNormalizationDescription": "Escanea ficheiros á procura de datos de normalización de volume.",
"CleanupUserDataTask": "Tarefa de limpeza de datos dos usuarios",
"CleanupUserDataTaskDescription": "Limpa todos os datos do usuario (estado de visualización, de favorito etc.) dos medios ausentes polo menos 90 días.",
- "Original": "Orixinal"
+ "Original": "Orixinal",
+ "LyricDownloadFailureFromForItem": "Non se puideron descargar as letras desde {0} para {1}",
+ "NameExtraBehindTheScenes": "Detrás das Cámaras",
+ "NameExtraClip": "Clip",
+ "NameExtraDeletedScene": "Escena Eliminada",
+ "NameExtraFeaturette": "Reportaxe especial",
+ "NameExtraInterview": "Entrevista",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraSample": "Mostra",
+ "NameExtraScene": "Escena",
+ "NameExtraShort": "Curtametraxe",
+ "NameExtraThemeSong": "Canción principal",
+ "NameExtraThemeVideo": "Vídeo da canción principal",
+ "NameExtraTrailer": "Tráiler",
+ "NameExtraUnknown": "Extra"
}
diff --git a/Emby.Server.Implementations/Localization/Core/he.json b/Emby.Server.Implementations/Localization/Core/he.json
index 48056b0bb8..0ca7c6aa08 100644
--- a/Emby.Server.Implementations/Localization/Core/he.json
+++ b/Emby.Server.Implementations/Localization/Core/he.json
@@ -108,5 +108,12 @@
"CleanupUserDataTaskDescription": "ניקוי כל המידע של המשתמש (מצב צפייה, מועדפים וכו) ממדיה שאינה קיימת מעל 90 יום.",
"CleanupUserDataTask": "משימת ניקוי מידע משתמש",
"LyricDownloadFailureFromForItem": "הורדת המילים מ-{0} עבור {1} נכשלה",
- "Original": "מקור"
+ "Original": "מקור",
+ "NameExtraBehindTheScenes": "מאחורי הקלעים",
+ "NameExtraClip": "קליפ",
+ "NameExtraDeletedScene": "סצנה שנמחקה",
+ "NameExtraFeaturette": "סרט קצר",
+ "NameExtraInterview": "ריאיון",
+ "NameExtraSample": "דגימה",
+ "NameExtraScene": "סצנה"
}
diff --git a/Emby.Server.Implementations/Localization/Core/hu.json b/Emby.Server.Implementations/Localization/Core/hu.json
index 1995d7a4cf..4a327e7b02 100644
--- a/Emby.Server.Implementations/Localization/Core/hu.json
+++ b/Emby.Server.Implementations/Localization/Core/hu.json
@@ -108,5 +108,18 @@
"CleanupUserDataTaskDescription": "Legalább 90 napja nem elérhető médiákhoz kapcsolódó összes felhasználói adat (pl. megtekintési állapot, kedvencek) törlése.",
"CleanupUserDataTask": "Felhasználói adatok tisztítása feladat",
"Original": "Eredeti",
- "LyricDownloadFailureFromForItem": "Dalszöveg letöltése {0}-tól {1}-hez sikertelen"
+ "LyricDownloadFailureFromForItem": "Dalszöveg letöltése {0}-tól {1}-hez sikertelen",
+ "NameExtraBehindTheScenes": "Színfalak mögött",
+ "NameExtraClip": "Klip",
+ "NameExtraDeletedScene": "Törölt jelenet",
+ "NameExtraFeaturette": "Kísérő film",
+ "NameExtraInterview": "Interjú",
+ "NameExtraSample": "Minta",
+ "NameExtraScene": "Jelenet",
+ "NameExtraShort": "Rövidfilm",
+ "NameExtraThemeSong": "Főcímdal",
+ "NameExtraThemeVideo": "Főcímvideó",
+ "NameExtraTrailer": "Előzetes",
+ "NameExtraUnknown": "Extra",
+ "NameExtraNumbered": "{0} {1}"
}
diff --git a/Emby.Server.Implementations/Localization/Core/hy.json b/Emby.Server.Implementations/Localization/Core/hy.json
index b79b540bf4..80be71ed70 100644
--- a/Emby.Server.Implementations/Localization/Core/hy.json
+++ b/Emby.Server.Implementations/Localization/Core/hy.json
@@ -24,5 +24,10 @@
"TaskDownloadMissingSubtitles": "Ներբեռնել պակասող ենթագրերը",
"AppDeviceValues": "Հավելված` {0}, Սարք `{1}",
"ChapterNameValue": "Գլուխ {0}",
- "Collections": "Հավաքածուներ"
+ "Collections": "Հավաքածուներ",
+ "Artists": "Երաժիշտներ",
+ "Default": "Լռելյայն",
+ "Favorites": "Ընտրյալ",
+ "Forced": "Ստիպուած",
+ "Genres": "Ոճ"
}
diff --git a/Emby.Server.Implementations/Localization/Core/is.json b/Emby.Server.Implementations/Localization/Core/is.json
index b889a073a2..a25857e510 100644
--- a/Emby.Server.Implementations/Localization/Core/is.json
+++ b/Emby.Server.Implementations/Localization/Core/is.json
@@ -108,5 +108,18 @@
"Original": "Upprunaleg",
"TaskExtractMediaSegmentsDescription": "Sækir myndbúta úr viðbótum þar sem MediaSegment er virkt.",
"TaskMoveTrickplayImages": "Flytja geymslustað fyrir Trickplay-myndir",
- "TaskMoveTrickplayImagesDescription": "Flytur fyrirliggjandi Trickplay-skrár í samræmi við stillingar safnsins."
+ "TaskMoveTrickplayImagesDescription": "Flytur fyrirliggjandi Trickplay-skrár í samræmi við stillingar safnsins.",
+ "NameExtraBehindTheScenes": "Bak við tjöldin",
+ "NameExtraClip": "Brot",
+ "NameExtraDeletedScene": "Eydd atriði",
+ "NameExtraFeaturette": "Stutt heimildarmynd",
+ "NameExtraInterview": "Viðtal",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraSample": "Sýnishorn",
+ "NameExtraScene": "Sena",
+ "NameExtraShort": "Stuttmynd",
+ "NameExtraThemeSong": "Þema lag",
+ "NameExtraThemeVideo": "Þema myndband",
+ "NameExtraTrailer": "Stikla",
+ "NameExtraUnknown": "Aukaefni"
}
diff --git a/Emby.Server.Implementations/Localization/Core/it.json b/Emby.Server.Implementations/Localization/Core/it.json
index f13944e6be..41097ed92e 100644
--- a/Emby.Server.Implementations/Localization/Core/it.json
+++ b/Emby.Server.Implementations/Localization/Core/it.json
@@ -108,5 +108,18 @@
"CleanupUserDataTask": "Task di pulizia dei dati utente",
"CleanupUserDataTaskDescription": "Pulisce tutti i dati utente (stato di visione, status preferiti, ecc.) dai contenuti non più presenti da almeno 90 giorni.",
"Original": "Originale",
- "LyricDownloadFailureFromForItem": "Scaricamento dei testi non riuscito da {0} per {1}"
+ "LyricDownloadFailureFromForItem": "Scaricamento dei testi non riuscito da {0} per {1}",
+ "NameExtraBehindTheScenes": "Dietro le scene",
+ "NameExtraClip": "Filmato",
+ "NameExtraDeletedScene": "Scena eliminata",
+ "NameExtraInterview": "Intervista",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraScene": "Scena",
+ "NameExtraSample": "Campione",
+ "NameExtraShort": "Corto",
+ "NameExtraThemeSong": "Sigla musicale",
+ "NameExtraTrailer": "Trailer",
+ "NameExtraFeaturette": "Caratteristica",
+ "NameExtraThemeVideo": "Video tematico",
+ "NameExtraUnknown": "Extra"
}
diff --git a/Emby.Server.Implementations/Localization/Core/ko.json b/Emby.Server.Implementations/Localization/Core/ko.json
index a210125d34..1f16a90842 100644
--- a/Emby.Server.Implementations/Localization/Core/ko.json
+++ b/Emby.Server.Implementations/Localization/Core/ko.json
@@ -108,5 +108,8 @@
"CleanupUserDataTask": "사용자 데이터 정리 작업",
"CleanupUserDataTaskDescription": "최소 90일 이상 존재하지 않는 미디어에 대한 사용자 데이터(시청 상태, 즐겨찾기 등)를 정리합니다.",
"LyricDownloadFailureFromForItem": "{1}에 대한 가사를 {0}에서 다운로드하지 못했습니다",
- "Original": "원본"
+ "Original": "원본",
+ "NameExtraClip": "클립",
+ "NameExtraDeletedScene": "삭제된 장면",
+ "NameExtraInterview": "인터뷰"
}
diff --git a/Emby.Server.Implementations/Localization/Core/lb.json b/Emby.Server.Implementations/Localization/Core/lb.json
index e94709b083..917f26a49c 100644
--- a/Emby.Server.Implementations/Localization/Core/lb.json
+++ b/Emby.Server.Implementations/Localization/Core/lb.json
@@ -104,5 +104,9 @@
"TaskKeyframeExtractorDescription": "Extrahéiert Schlësselbiller aus Videodateien, fir méi präzis HLS-Playlisten ze erstellen. Dës Aufgab kann eng längere Zäit daueren.",
"TaskRefreshChannelsDescription": "Aktualiséiert Informatiounen iwwer Internetkanäl.",
"TaskExtractMediaSegmentsDescription": "Extrahéiert oder kritt Mediesegmenter aus Plugins, déi MediaSegment ënnerstëtzen.",
- "TaskOptimizeDatabaseDescription": "Kompriméiert d’Datebank a schneit de fräie Speicherplatz zou. Dës Aufgab no engem Bibliothéik-Scan oder anere Ännerungen, déi Datebankmodifikatioune mat sech bréngen, auszeféieren, kann d’Performance verbesseren."
+ "TaskOptimizeDatabaseDescription": "Kompriméiert d’Datebank a schneit de fräie Speicherplatz zou. Dës Aufgab no engem Bibliothéik-Scan oder anere Ännerungen, déi Datebankmodifikatioune mat sech bréngen, auszeféieren, kann d’Performance verbesseren.",
+ "LyricDownloadFailureFromForItem": "Feeler beim Download vun de Songtexter vun {0} fir {1}",
+ "Original": "Original",
+ "CleanupUserDataTask": "Aufgab fir Berengege vu Benotzerdaten",
+ "CleanupUserDataTaskDescription": "Läscht all Benotzerdaten (Ofspillstatus, Favoritestatus, asw.) vu Medien, déi zënter mindestens 90 Deeg net méi besteeënd sinn."
}
diff --git a/Emby.Server.Implementations/Localization/Core/lt-LT.json b/Emby.Server.Implementations/Localization/Core/lt-LT.json
index ed26004a43..b0fb6c52ba 100644
--- a/Emby.Server.Implementations/Localization/Core/lt-LT.json
+++ b/Emby.Server.Implementations/Localization/Core/lt-LT.json
@@ -3,15 +3,15 @@
"Artists": "Atlikėjai",
"AuthenticationSucceededWithUserName": "{0} sėkmingai autentifikuota",
"Books": "Knygos",
- "ChapterNameValue": "Scena{0}",
- "Collections": "Rinkiniai",
+ "ChapterNameValue": "Skyrius{0}",
+ "Collections": "Kolekcijos",
"FailedLoginAttemptWithUserName": "Nesėkmingas {0} bandymas prisijungti",
"Favorites": "Mėgstami",
- "Folders": "Katalogai",
+ "Folders": "Aplankai",
"Genres": "Žanrai",
"HeaderContinueWatching": "Žiūrėti toliau",
- "HeaderFavoriteEpisodes": "Mėgstamiausios serijos",
- "HeaderFavoriteShows": "Mėgstamiausios TV Laidos",
+ "HeaderFavoriteEpisodes": "Mėgstami Epizodai",
+ "HeaderFavoriteShows": "Mėgstamos TV Laidos",
"HeaderLiveTV": "Tiesioginė TV",
"HeaderNextUp": "Toliau",
"HomeVideos": "Namų vaizdo įrašai",
@@ -26,14 +26,14 @@
"NameInstallFailed": "{0} diegimo klaida",
"NameSeasonNumber": "Sezonas {0}",
"NameSeasonUnknown": "Sezonas neatpažintas",
- "NewVersionIsAvailable": "Nauja \"Jellyfin Server\" versija yra prieinama atsisiuntimui.",
+ "NewVersionIsAvailable": "Nauja Jellyfin Server versija yra prieinama atsisiuntimui.",
"NotificationOptionApplicationUpdateAvailable": "Galimi programos atnaujinimai",
"NotificationOptionApplicationUpdateInstalled": "Programos atnaujinimai įdiegti",
"NotificationOptionAudioPlayback": "Garso atkūrimas pradėtas",
"NotificationOptionAudioPlaybackStopped": "Garso atkūrimas sustabdytas",
- "NotificationOptionCameraImageUploaded": "Kameros vaizdai įkelti",
+ "NotificationOptionCameraImageUploaded": "Kameros atvaizdai įkelti",
"NotificationOptionInstallationFailed": "Diegimo klaida",
- "NotificationOptionNewLibraryContent": "Naujas turinys įkeltas",
+ "NotificationOptionNewLibraryContent": "Pridėtas naujas turinys",
"NotificationOptionPluginError": "Įskiepio klaida",
"NotificationOptionPluginInstalled": "Įskiepis įdiegtas",
"NotificationOptionPluginUninstalled": "Įskiepis išdiegtas",
@@ -51,7 +51,7 @@
"Shows": "Laidos",
"StartupEmbyServerIsLoading": "Jellyfin Server kraunasi. Netrukus pabandykite dar kartą.",
"SubtitleDownloadFailureFromForItem": "{1} subtitrai buvo nesėkmingai parsiųsti iš {0}",
- "TvShows": "TV laidos",
+ "TvShows": "TV Laidos",
"UserCreatedWithName": "Buvo sukurtas {0} naudotojas",
"UserDeletedWithName": "Naudotojas {0} ištrintas",
"UserDownloadingItemWithValues": "{0} siunčiasi {1}",
@@ -59,14 +59,14 @@
"UserOfflineFromDevice": "{0} buvo atjungtas nuo {1}",
"UserOnlineFromDevice": "{0} prisijungęs iš {1}",
"UserPasswordChangedWithName": "Slaptažodis pakeistas naudotojui {0}",
- "UserStartedPlayingItemWithValues": "{0} leidžia {1} į {2}",
- "UserStoppedPlayingItemWithValues": "{0} baigė leisti {1} į {2}",
+ "UserStartedPlayingItemWithValues": "{0} atkuriama {1} į {2}",
+ "UserStoppedPlayingItemWithValues": "{0} baigė atkūrimą {1} į {2}",
"VersionNumber": "Versija {0}",
"TaskUpdatePluginsDescription": "Atsisiunčia ir įdiegia įskiepių, kurie sukonfigūruoti atnaujinti automatiškai, naujinius.",
"TaskUpdatePlugins": "Atnaujinti įskieius",
"TaskDownloadMissingSubtitlesDescription": "Ieško trūkstamų subtitrų internete remiantis metaduomenų konfigūracija.",
- "TaskCleanTranscodeDescription": "Ištrina dienos senumo perkodavimo failus.",
- "TaskCleanTranscode": "Išvalyti perkodavimo katalogą",
+ "TaskCleanTranscodeDescription": "Ištrina dienos senumo transkodavimo failus.",
+ "TaskCleanTranscode": "Išvalyti transkodavimo katalogą",
"TaskRefreshLibraryDescription": "Skenuoja medijos biblioteką, ieškodamas naujų failų, ir atnaujina metaduomenis.",
"TaskRefreshLibrary": "Skenuoti medijos biblioteką",
"TaskDownloadMissingSubtitles": "Atsisiųsti trūkstamus subtitrus",
@@ -76,8 +76,8 @@
"TaskRefreshPeople": "Atnaujinti žmones",
"TaskCleanLogsDescription": "Ištrina žurnalo failus kurie yra senesni nei {0} dienos.",
"TaskCleanLogs": "Išvalyti žurnalą",
- "TaskRefreshChapterImagesDescription": "Sukuria vaizdo įrašų, kuriuose yra skyrių, miniatiūras.",
- "TaskRefreshChapterImages": "Ištraukti skyrių vaizdus",
+ "TaskRefreshChapterImagesDescription": "Sukuria miniatiūras vaizdo įrašams, kuriuose yra skyriai.",
+ "TaskRefreshChapterImages": "Ištraukti skyrių atvaizdus",
"TaskCleanCache": "Išvalyti talpyklą",
"TaskCleanCacheDescription": "Ištrina talpyklos failus, kurių daugiau nereikia sistemai.",
"TasksChannelsCategory": "Internetiniai kanalai",
@@ -96,15 +96,30 @@
"External": "Išorinis",
"HearingImpaired": "Su klausos sutrikimais",
"TaskRefreshTrickplayImages": "Generuoti Trickplay atvaizdus",
- "TaskRefreshTrickplayImagesDescription": "Sukuria trickplay peržiūras vaizdo įrašams įgalintose bibliotekose.",
+ "TaskRefreshTrickplayImagesDescription": "Sukuria vaizdo įrašų, esančių įgalintose bibliotekose, Trickplay peržiūras.",
"TaskAudioNormalization": "Garso normalizavimas",
"TaskAudioNormalizationDescription": "Skenuoja failus, ieškant garso normalizavimo duomenų.",
"TaskExtractMediaSegments": "Medijos segmentų nuskaitymas",
"TaskDownloadMissingLyrics": "Parsisiųsti trūkstamus dainų tekstus",
"TaskExtractMediaSegmentsDescription": "Ištraukia arba gauna medijos segmentus iš MediaSegment ijungtų įskiepių.",
- "TaskMoveTrickplayImages": "Pakeisti Trickplay vaizdų vietą",
- "TaskMoveTrickplayImagesDescription": "Perkelia egzistuojančius trickplay failus pagal bibliotekos nustatymus.",
+ "TaskMoveTrickplayImages": "Pakeisti Trickplay atvaizdų vietą",
+ "TaskMoveTrickplayImagesDescription": "Perkelia egzistuojančius Trickplay failus pagal bibliotekos nustatymus.",
"TaskDownloadMissingLyricsDescription": "Parsisiųsti dainų žodžius",
"CleanupUserDataTask": "Naudotojo duomenų valymo užduotis",
- "CleanupUserDataTaskDescription": "Iš medijos, kurios nebėra bent 90 dienų, išvalo visus naudotojo duomenis (žiūrėjimo būseną, mėgstamiausią būseną ir t. t.)."
+ "CleanupUserDataTaskDescription": "Iš medijos, kurios nebėra bent 90 dienų, išvalo visus naudotojo duomenis (žiūrėjimo būseną, mėgstamą būseną ir t. t.).",
+ "LyricDownloadFailureFromForItem": "Nepavyko atsisiųsti dainos žodžių iš {0}, skirto {1}",
+ "NameExtraBehindTheScenes": "Užkulisiuose",
+ "NameExtraClip": "Klipas",
+ "NameExtraDeletedScene": "Ištrinta scena",
+ "NameExtraInterview": "Interviu",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraSample": "Pavyzdys",
+ "NameExtraScene": "Scena",
+ "NameExtraThemeSong": "Teminė daina",
+ "NameExtraThemeVideo": "Teminis vaizdo įrašas",
+ "NameExtraTrailer": "Anonsas",
+ "NameExtraUnknown": "Papildomas",
+ "Original": "Originalus",
+ "NameExtraFeaturette": "Trumpametražis filmas",
+ "NameExtraShort": "Trumpas filmukas"
}
diff --git a/Emby.Server.Implementations/Localization/Core/ms.json b/Emby.Server.Implementations/Localization/Core/ms.json
index 9fc61fadd5..bb4469ad9c 100644
--- a/Emby.Server.Implementations/Localization/Core/ms.json
+++ b/Emby.Server.Implementations/Localization/Core/ms.json
@@ -106,5 +106,11 @@
"TaskAudioNormalization": "Normalisasi Audio",
"TaskAudioNormalizationDescription": "Mengimbas fail-fail untuk data normalisasi audio.",
"CleanupUserDataTaskDescription": "Membersihkan semua data pengguna (keadaan tontonan, status kegemaran, dan sebagainya) daripada media yang tidak lagi wujud sekurang-kurangnya selama 90 hari.",
- "CleanupUserDataTask": "Tugas pembersihan data pengguna"
+ "CleanupUserDataTask": "Tugas pembersihan data pengguna",
+ "LyricDownloadFailureFromForItem": "Lirik gagal dimuat turun dari {0} untuk {1}",
+ "NameExtraBehindTheScenes": "Di Sebalik Takbir",
+ "NameExtraClip": "Klip",
+ "NameExtraInterview": "Temu bual",
+ "NameExtraThemeSong": "Lagu Tema",
+ "NameExtraThemeVideo": "Video Tema"
}
diff --git a/Emby.Server.Implementations/Localization/Core/nl.json b/Emby.Server.Implementations/Localization/Core/nl.json
index 9aea3adc22..28ac66e70d 100644
--- a/Emby.Server.Implementations/Localization/Core/nl.json
+++ b/Emby.Server.Implementations/Localization/Core/nl.json
@@ -108,5 +108,18 @@
"CleanupUserDataTask": "Opruimtaak gebruikersdata",
"Genres": "Genres",
"Original": "Oorspronkelijk",
- "LyricDownloadFailureFromForItem": "Downloaden van liedteksten voor {1} van {0} mislukt"
+ "LyricDownloadFailureFromForItem": "Downloaden van liedteksten voor {1} van {0} mislukt",
+ "NameExtraBehindTheScenes": "Achter de schermen",
+ "NameExtraClip": "Clip",
+ "NameExtraDeletedScene": "Geschrapte scène",
+ "NameExtraFeaturette": "Featurette",
+ "NameExtraInterview": "Vraaggesprek",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraSample": "Voorbeeldfragment",
+ "NameExtraScene": "Scène",
+ "NameExtraShort": "Korte film",
+ "NameExtraThemeSong": "Themamuziek",
+ "NameExtraThemeVideo": "Themavideo",
+ "NameExtraTrailer": "Trailer",
+ "NameExtraUnknown": "Extra inhoud"
}
diff --git a/Emby.Server.Implementations/Localization/Core/oc.json b/Emby.Server.Implementations/Localization/Core/oc.json
index cad5640763..4f573b3c58 100644
--- a/Emby.Server.Implementations/Localization/Core/oc.json
+++ b/Emby.Server.Implementations/Localization/Core/oc.json
@@ -1,3 +1,27 @@
{
- "AppDeviceValues": "Aplicacion: {0}, Periferic: {1}"
+ "AppDeviceValues": "Aplicacion: {0}, Periferic: {1}",
+ "Books": "Libres",
+ "Artists": "Artistas",
+ "Collections": "Collecciones",
+ "ChapterNameValue": "Capitol {0}",
+ "External": "Extèrn",
+ "Folders": "Dorsièrs",
+ "Favorites": "Favorits",
+ "HeaderContinueWatching": "Contunhar de regardar",
+ "HeaderFavoriteEpisodes": "Episòdis Favorits",
+ "AuthenticationSucceededWithUserName": "{0} autentificat amb succès",
+ "HeaderFavoriteShows": "Serias Favoritas",
+ "HeaderLiveTV": "TV en dirècte",
+ "HeaderNextUp": "Seguent",
+ "HearingImpaired": "Amb de deficiéncias auditivas",
+ "Movies": "Filmes",
+ "Music": "Musica",
+ "Latest": "Darrièr",
+ "Forced": "Forçat",
+ "Default": "Defaut",
+ "Genres": "Genres",
+ "HomeVideos": "Vidèos d'Acuèlh",
+ "Inherit": "Eiretar",
+ "LabelIpAddressValue": "Adreça IP: {0}",
+ "LabelRunningTimeValue": "Temps d'execucion : {0}"
}
diff --git a/Emby.Server.Implementations/Localization/Core/pl.json b/Emby.Server.Implementations/Localization/Core/pl.json
index c4657bdd6e..71909fd73a 100644
--- a/Emby.Server.Implementations/Localization/Core/pl.json
+++ b/Emby.Server.Implementations/Localization/Core/pl.json
@@ -108,5 +108,18 @@
"CleanupUserDataTaskDescription": "Usuwa wszystkie dane użytkownika (stan oglądanych, status ulubionych itp.) z mediów, które nie są dostępne od co najmniej 90 dni.",
"CleanupUserDataTask": "Zadanie czyszczenia danych użytkownika",
"Original": "Oryginalny",
- "LyricDownloadFailureFromForItem": "Błąd podczas pobierania tekstu piosenki z {0} dla {1}"
+ "LyricDownloadFailureFromForItem": "Błąd podczas pobierania tekstu piosenki z {0} dla {1}",
+ "NameExtraBehindTheScenes": "Za kulisami",
+ "NameExtraClip": "Urywek",
+ "NameExtraDeletedScene": "Usunięta scena",
+ "NameExtraFeaturette": "Film średniometrażowy",
+ "NameExtraInterview": "Wywiad",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraSample": "Fragment",
+ "NameExtraScene": "Scena",
+ "NameExtraShort": "Film krótkometrażowy",
+ "NameExtraThemeSong": "Czołówka",
+ "NameExtraThemeVideo": "Wideo wprowadzające",
+ "NameExtraTrailer": "Zwiastun",
+ "NameExtraUnknown": "Dodatek"
}
diff --git a/Emby.Server.Implementations/Localization/Core/pt-BR.json b/Emby.Server.Implementations/Localization/Core/pt-BR.json
index 1db500adf3..031c6e17c4 100644
--- a/Emby.Server.Implementations/Localization/Core/pt-BR.json
+++ b/Emby.Server.Implementations/Localization/Core/pt-BR.json
@@ -108,5 +108,17 @@
"CleanupUserDataTask": "Tarefa de limpeza de dados do usuário",
"CleanupUserDataTaskDescription": "Limpa todos os dados do usuário (estado de visualização, status de favorito, etc.) de mídias que não estão presentes por pelo menos 90 dias.",
"LyricDownloadFailureFromForItem": "Download das Letras falharam em {0} para o item {1}",
- "Original": "Original"
+ "Original": "Original",
+ "NameExtraBehindTheScenes": "Nos Bastidores",
+ "NameExtraClip": "Clipe",
+ "NameExtraDeletedScene": "cena Extra",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraSample": "Trecho",
+ "NameExtraScene": "Cena",
+ "NameExtraShort": "Curta-metragem",
+ "NameExtraThemeSong": "Música Tema",
+ "NameExtraThemeVideo": "Vídeo de Abertura",
+ "NameExtraTrailer": "Trailer",
+ "NameExtraUnknown": "Extra",
+ "NameExtraFeaturette": "Nos Bastidores"
}
diff --git a/Emby.Server.Implementations/Localization/Core/pt-PT.json b/Emby.Server.Implementations/Localization/Core/pt-PT.json
index ce7f6d120e..e71475afd8 100644
--- a/Emby.Server.Implementations/Localization/Core/pt-PT.json
+++ b/Emby.Server.Implementations/Localization/Core/pt-PT.json
@@ -5,108 +5,121 @@
"Books": "Livros",
"ChapterNameValue": "Capítulo {0}",
"Collections": "Coleções",
- "FailedLoginAttemptWithUserName": "Tentativa de login falhada a partir de {0}",
+ "FailedLoginAttemptWithUserName": "Tentativa falhada de início de sessão do utilizador {0}",
"Favorites": "Favoritos",
"Folders": "Pastas",
"Genres": "Géneros",
"HeaderContinueWatching": "Continuar a ver",
- "HeaderFavoriteEpisodes": "Episódios Favoritos",
- "HeaderFavoriteShows": "Séries Favoritas",
- "HeaderLiveTV": "TV em Direto",
- "HeaderNextUp": "A Seguir",
- "HomeVideos": "Vídeos Caseiros",
+ "HeaderFavoriteEpisodes": "Episódios favoritos",
+ "HeaderFavoriteShows": "Séries favoritas",
+ "HeaderLiveTV": "TV em direto",
+ "HeaderNextUp": "A seguir",
+ "HomeVideos": "Vídeos caseiros",
"Inherit": "Herdar",
"LabelIpAddressValue": "Endereço IP: {0}",
"LabelRunningTimeValue": "Duração: {0}",
- "Latest": "Mais Recente",
- "MixedContent": "Conteúdo Misto",
+ "Latest": "Mais recente",
+ "MixedContent": "Conteúdo misto",
"Movies": "Filmes",
"Music": "Música",
"MusicVideos": "Videoclipes",
- "NameInstallFailed": "{0} falha na instalação",
+ "NameInstallFailed": "Falha na instalação de {0}",
"NameSeasonNumber": "Temporada {0}",
- "NameSeasonUnknown": "Temporada Desconhecida",
+ "NameSeasonUnknown": "Temporada desconhecida",
"NewVersionIsAvailable": "Está disponível para transferência uma nova versão do servidor Jellyfin.",
"NotificationOptionApplicationUpdateAvailable": "Atualização de aplicação disponível",
"NotificationOptionApplicationUpdateInstalled": "Atualização de aplicação instalada",
- "NotificationOptionAudioPlayback": "Reprodução Iniciada",
- "NotificationOptionAudioPlaybackStopped": "Reprodução Parada",
+ "NotificationOptionAudioPlayback": "Reprodução de áudio iniciada",
+ "NotificationOptionAudioPlaybackStopped": "Reprodução de áudio interrompida",
"NotificationOptionCameraImageUploaded": "Imagem da câmara enviada",
"NotificationOptionInstallationFailed": "Falha na instalação",
"NotificationOptionNewLibraryContent": "Novo conteúdo adicionado",
- "NotificationOptionPluginError": "Falha na extensão",
- "NotificationOptionPluginInstalled": "Extensão instalada",
- "NotificationOptionPluginUninstalled": "Extensão desinstalada",
- "NotificationOptionPluginUpdateInstalled": "Extensão atualizada",
+ "NotificationOptionPluginError": "Falha no plugin",
+ "NotificationOptionPluginInstalled": "Plugin instalado",
+ "NotificationOptionPluginUninstalled": "Plugin desinstalado",
+ "NotificationOptionPluginUpdateInstalled": "Atualização de plugin instalada",
"NotificationOptionServerRestartRequired": "Necessário reiniciar o servidor",
"NotificationOptionTaskFailed": "Falha em tarefa agendada",
"NotificationOptionUserLockedOut": "Utilizador bloqueado",
- "NotificationOptionVideoPlayback": "Reprodução do vídeo iniciada",
- "NotificationOptionVideoPlaybackStopped": "Reprodução do vídeo parada",
+ "NotificationOptionVideoPlayback": "Reprodução de vídeo iniciada",
+ "NotificationOptionVideoPlaybackStopped": "Reprodução de vídeo interrompida",
"Photos": "Fotografias",
"PluginInstalledWithName": "{0} foi instalado",
"PluginUninstalledWithName": "{0} foi desinstalado",
"PluginUpdatedWithName": "{0} foi atualizado",
"ScheduledTaskFailedWithName": "{0} falhou",
"Shows": "Séries",
- "StartupEmbyServerIsLoading": "O servidor Jellyfin está a iniciar. Tente novamente mais tarde.",
- "SubtitleDownloadFailureFromForItem": "Falha na transferência de legendas a partir de {0} para {1}",
- "TvShows": "Séries",
+ "StartupEmbyServerIsLoading": "O servidor Jellyfin está a iniciar. Tenta novamente dentro de instantes.",
+ "SubtitleDownloadFailureFromForItem": "Falha ao transferir legendas de {0} para {1}",
+ "TvShows": "Séries de TV",
"UserCreatedWithName": "Utilizador {0} criado",
- "UserDeletedWithName": "Utilizador {0} apagado",
+ "UserDeletedWithName": "Utilizador {0} eliminado",
"UserDownloadingItemWithValues": "{0} está a transferir {1}",
"UserLockedOutWithName": "Utilizador {0} bloqueado",
- "UserOfflineFromDevice": "{0} desligou-se a partir de {1}",
- "UserOnlineFromDevice": "{0} ligou-se a partir de {1}",
+ "UserOfflineFromDevice": "{0} desligou-se de {1}",
+ "UserOnlineFromDevice": "{0} está online em {1}",
"UserPasswordChangedWithName": "Palavra-passe alterada para o utilizador {0}",
"UserStartedPlayingItemWithValues": "{0} está a reproduzir {1} em {2}",
"UserStoppedPlayingItemWithValues": "{0} terminou a reprodução de {1} em {2}",
"VersionNumber": "Versão {0}",
- "TaskDownloadMissingSubtitlesDescription": "Procurar na internet por legendas em falta baseado na configuração de metadados.",
+ "TaskDownloadMissingSubtitlesDescription": "Procura na Internet legendas em falta com base na configuração dos metadados.",
"TaskDownloadMissingSubtitles": "Transferir legendas em falta",
- "TaskRefreshChannelsDescription": "Atualizar informação sobre canais da Internet.",
- "TaskRefreshChannels": "Atualizar Canais",
- "TaskCleanTranscodeDescription": "Apagar ficheiros de transcode com mais de um dia.",
- "TaskCleanTranscode": "Limpar a Diretoria de Transcode",
- "TaskUpdatePluginsDescription": "Faz o download e instala updates para os plugins que estão configurados para atualizar automaticamente.",
- "TaskUpdatePlugins": "Atualizar Plugins",
- "TaskRefreshPeopleDescription": "Atualizar metadados para elenco e equipa técnica da tua mediateca.",
- "TaskRefreshPeople": "Atualizar Pessoas",
- "TaskCleanLogsDescription": "Apagar ficheiros de log que têm mais de {0} dias.",
- "TaskCleanLogs": "Limpar a Diretoria de Logs",
- "TaskRefreshLibraryDescription": "Analisar a mediateca para novos ficheiros e atualizar os metadados.",
- "TaskRefreshLibrary": "Analisar mediateca",
- "TaskRefreshChapterImagesDescription": "Criar thumbnails para os vídeos que têm capítulos.",
- "TaskRefreshChapterImages": "Extrair Imagens dos Capítulos",
- "TaskCleanCacheDescription": "Apagar ficheiros em cache que já não são necessários.",
- "TaskCleanCache": "Limpar Cache",
+ "TaskRefreshChannelsDescription": "Atualiza as informações dos canais da Internet.",
+ "TaskRefreshChannels": "Atualizar canais",
+ "TaskCleanTranscodeDescription": "Elimina ficheiros de transcodificação com mais de um dia.",
+ "TaskCleanTranscode": "Limpar pasta de transcodificação",
+ "TaskUpdatePluginsDescription": "Transfere e instala atualizações dos plugins configurados para atualização automática.",
+ "TaskUpdatePlugins": "Atualizar plugins",
+ "TaskRefreshPeopleDescription": "Atualiza os metadados de atores e realizadores na tua biblioteca multimédia.",
+ "TaskRefreshPeople": "Atualizar pessoas",
+ "TaskCleanLogsDescription": "Elimina ficheiros de registo com mais de {0} dias.",
+ "TaskCleanLogs": "Limpar pasta de registos",
+ "TaskRefreshLibraryDescription": "Analisa a biblioteca multimédia à procura de novos ficheiros e atualiza os metadados.",
+ "TaskRefreshLibrary": "Analisar biblioteca multimédia",
+ "TaskRefreshChapterImagesDescription": "Cria miniaturas para vídeos que têm capítulos.",
+ "TaskRefreshChapterImages": "Extrair imagens dos capítulos",
+ "TaskCleanCacheDescription": "Elimina ficheiros de cache que já não são necessários ao sistema.",
+ "TaskCleanCache": "Limpar pasta de cache",
"TasksChannelsCategory": "Canais da Internet",
"TasksApplicationCategory": "Aplicação",
- "TasksLibraryCategory": "Mediateca",
+ "TasksLibraryCategory": "Biblioteca",
"TasksMaintenanceCategory": "Manutenção",
- "TaskCleanActivityLogDescription": "Apaga as entradas do registo de atividade anteriores à data configurada.",
+ "TaskCleanActivityLogDescription": "Elimina as entradas do registo de atividade mais antigas do que o período configurado.",
"TaskCleanActivityLog": "Limpar registo de atividade",
"Undefined": "Indefinido",
"Forced": "Forçado",
"Default": "Predefinição",
- "TaskOptimizeDatabaseDescription": "Otimiza e liberta espaço livre na base de dados. A execução desta tarefa depois de analisar a mediateca ou efetuar outras alterações que impliquem modificações na base de dados pode melhorar o desempenho.",
+ "TaskOptimizeDatabaseDescription": "Compacta a base de dados e liberta espaço não utilizado. A execução desta tarefa depois de analisar a biblioteca ou de outras alterações que modifiquem a base de dados pode melhorar o desempenho.",
"TaskOptimizeDatabase": "Otimizar base de dados",
- "TaskKeyframeExtractorDescription": "Extrai quadros-chave de ficheiros de video para criar listas de reprodução HLS mais precisas. Esta tarefa pode demorar algum tempo.",
- "TaskKeyframeExtractor": "Extrator de Quadros-chave",
+ "TaskKeyframeExtractorDescription": "Extrai fotogramas-chave de ficheiros de vídeo para criar playlists HLS mais precisas. Esta tarefa pode demorar algum tempo.",
+ "TaskKeyframeExtractor": "Extrator de fotogramas-chave",
"External": "Externo",
- "HearingImpaired": "Surdo",
+ "HearingImpaired": "Deficiência auditiva",
"TaskRefreshTrickplayImages": "Gerar imagens de trickplay",
"TaskRefreshTrickplayImagesDescription": "Cria pré-visualizações de trickplay para vídeos nas bibliotecas ativadas.",
"TaskAudioNormalizationDescription": "Analisa os ficheiros para obter dados de normalização de áudio.",
"TaskAudioNormalization": "Normalização de áudio",
- "TaskExtractMediaSegments": "Analisar segmentos de multimédia",
- "TaskDownloadMissingLyrics": "Transferir letra em falta",
- "TaskMoveTrickplayImages": "Migrar a localização da imagem do Trickplay",
- "TaskDownloadMissingLyricsDescription": "Transferir letra para músicas",
- "TaskExtractMediaSegmentsDescription": "Extrai ou obtém segmentos de multimédia a partir de plugins com suporte para MediaSegment.",
- "TaskMoveTrickplayImagesDescription": "Move os ficheiros trickplay existentes de acordo com as definições da mediateca.",
- "CleanupUserDataTaskDescription": "Apaga todos os dados de utilizador (estados de reprodução, favoritos, etc) de arquivos média não presentes há 90 dias ou mais.",
+ "TaskExtractMediaSegments": "Analisar segmentos multimédia",
+ "TaskDownloadMissingLyrics": "Transferir letras em falta",
+ "TaskMoveTrickplayImages": "Migrar localização das imagens de trickplay",
+ "TaskDownloadMissingLyricsDescription": "Transfere letras de músicas",
+ "TaskExtractMediaSegmentsDescription": "Extrai ou obtém segmentos multimédia de plugins com MediaSegment ativado.",
+ "TaskMoveTrickplayImagesDescription": "Move os ficheiros de trickplay existentes de acordo com as definições da biblioteca.",
+ "CleanupUserDataTaskDescription": "Remove todos os dados de utilizador (estado de reprodução, estado de favorito, etc.) de conteúdos multimédia que já não estejam presentes há pelo menos 90 dias.",
"CleanupUserDataTask": "Limpeza de dados de utilizador",
"Original": "Original",
- "LyricDownloadFailureFromForItem": "Erro ao descarregar letras de {0} para {1}"
+ "LyricDownloadFailureFromForItem": "Falha ao transferir letras de {0} para {1}",
+ "NameExtraDeletedScene": "Cena eliminada",
+ "NameExtraInterview": "Entrevista",
+ "NameExtraUnknown": "Extra",
+ "NameExtraBehindTheScenes": "Bastidores",
+ "NameExtraSample": "Amostra",
+ "NameExtraScene": "Cena",
+ "NameExtraClip": "Excerto",
+ "NameExtraFeaturette": "Minidocumentário",
+ "NameExtraThemeSong": "Tema musical",
+ "NameExtraThemeVideo": "Vídeo temático",
+ "NameExtraShort": "Curta-metragem",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraTrailer": "Trailer"
}
diff --git a/Emby.Server.Implementations/Localization/Core/pt.json b/Emby.Server.Implementations/Localization/Core/pt.json
index ce338acf34..8299a25992 100644
--- a/Emby.Server.Implementations/Localization/Core/pt.json
+++ b/Emby.Server.Implementations/Localization/Core/pt.json
@@ -1,112 +1,125 @@
{
- "HeaderLiveTV": "TV Em Direto",
+ "HeaderLiveTV": "TV em direto",
"Collections": "Coleções",
"Books": "Livros",
"Artists": "Artistas",
- "HeaderNextUp": "A Seguir",
- "HeaderFavoriteEpisodes": "Episódios Favoritos",
- "HeaderFavoriteShows": "Séries Favoritas",
+ "HeaderNextUp": "A seguir",
+ "HeaderFavoriteEpisodes": "Episódios favoritos",
+ "HeaderFavoriteShows": "Séries favoritas",
"HeaderContinueWatching": "Continuar a ver",
"Genres": "Géneros",
"Folders": "Pastas",
"Favorites": "Favoritos",
- "UserDownloadingItemWithValues": "{0} está sendo baixado {1}",
+ "UserDownloadingItemWithValues": "{0} está a transferir {1}",
"VersionNumber": "Versão {0}",
"UserStoppedPlayingItemWithValues": "{0} terminou a reprodução de {1} em {2}",
- "UserStartedPlayingItemWithValues": "{0} está reproduzindo {1} em {2}",
- "UserPasswordChangedWithName": "A senha do usuário {0} foi alterada",
- "UserOnlineFromDevice": "{0} está online a partir de {1}",
- "UserOfflineFromDevice": "{0} desconectou-se a partir de {1}",
- "UserLockedOutWithName": "O usuário {0} foi bloqueado",
- "UserDeletedWithName": "O usuário {0} foi removido",
- "UserCreatedWithName": "O usuário {0} foi criado",
- "TvShows": "Séries",
- "SubtitleDownloadFailureFromForItem": "Falha na transferência de legendas de {0} para {1}",
- "StartupEmbyServerIsLoading": "O servidor Jellyfin está iniciando. Tente novamente dentro de momentos.",
+ "UserStartedPlayingItemWithValues": "{0} está a reproduzir {1} em {2}",
+ "UserPasswordChangedWithName": "Palavra-passe alterada para o utilizador {0}",
+ "UserOnlineFromDevice": "{0} está online em {1}",
+ "UserOfflineFromDevice": "{0} desligou-se de {1}",
+ "UserLockedOutWithName": "Utilizador {0} bloqueado",
+ "UserDeletedWithName": "Utilizador {0} eliminado",
+ "UserCreatedWithName": "Utilizador {0} criado",
+ "TvShows": "Séries de TV",
+ "SubtitleDownloadFailureFromForItem": "Falha ao transferir legendas de {0} para {1}",
+ "StartupEmbyServerIsLoading": "O servidor Jellyfin está a iniciar. Tenta novamente dentro de instantes.",
"ScheduledTaskFailedWithName": "{0} falhou",
"PluginUpdatedWithName": "{0} foi atualizado",
"PluginUninstalledWithName": "{0} foi desinstalado",
"PluginInstalledWithName": "{0} foi instalado",
- "NotificationOptionVideoPlaybackStopped": "Reprodução de vídeo parada",
+ "NotificationOptionVideoPlaybackStopped": "Reprodução de vídeo interrompida",
"NotificationOptionVideoPlayback": "Reprodução de vídeo iniciada",
- "NotificationOptionUserLockedOut": "Usuário bloqueado",
- "NotificationOptionTaskFailed": "Falha na tarefa agendada",
- "NotificationOptionServerRestartRequired": "É necessário reiniciar o servidor",
- "NotificationOptionPluginUpdateInstalled": "Plugin atualizado",
+ "NotificationOptionUserLockedOut": "Utilizador bloqueado",
+ "NotificationOptionTaskFailed": "Falha em tarefa agendada",
+ "NotificationOptionServerRestartRequired": "Necessário reiniciar o servidor",
+ "NotificationOptionPluginUpdateInstalled": "Atualização de plugin instalada",
"NotificationOptionPluginUninstalled": "Plugin desinstalado",
"NotificationOptionPluginInstalled": "Plugin instalado",
"NotificationOptionPluginError": "Falha no plugin",
"NotificationOptionNewLibraryContent": "Novo conteúdo adicionado",
- "NotificationOptionInstallationFailed": "Falha de instalação",
- "NotificationOptionCameraImageUploaded": "Imagem de câmera enviada",
- "NotificationOptionAudioPlaybackStopped": "Reprodução Parada",
- "NotificationOptionAudioPlayback": "Reprodução Iniciada",
- "NotificationOptionApplicationUpdateInstalled": "A atualização do aplicativo foi instalada",
- "NotificationOptionApplicationUpdateAvailable": "Uma atualização do aplicativo está disponível",
- "NewVersionIsAvailable": "Uma nova versão do servidor Jellyfin está disponível para download.",
- "NameSeasonUnknown": "Temporada Desconhecida",
+ "NotificationOptionInstallationFailed": "Falha na instalação",
+ "NotificationOptionCameraImageUploaded": "Imagem da câmara enviada",
+ "NotificationOptionAudioPlaybackStopped": "Reprodução de áudio interrompida",
+ "NotificationOptionAudioPlayback": "Reprodução de áudio iniciada",
+ "NotificationOptionApplicationUpdateInstalled": "Atualização de aplicação instalada",
+ "NotificationOptionApplicationUpdateAvailable": "Atualização de aplicação disponível",
+ "NewVersionIsAvailable": "Está disponível para transferência uma nova versão do servidor Jellyfin.",
+ "NameSeasonUnknown": "Temporada desconhecida",
"NameSeasonNumber": "Temporada {0}",
"NameInstallFailed": "Falha na instalação de {0}",
"MusicVideos": "Videoclipes",
"Music": "Música",
- "MixedContent": "Conteúdo diverso",
- "Latest": "Mais Recente",
+ "MixedContent": "Conteúdo misto",
+ "Latest": "Mais recente",
"LabelRunningTimeValue": "Duração: {0}",
- "LabelIpAddressValue": "Endereço de IP: {0}",
+ "LabelIpAddressValue": "Endereço IP: {0}",
"Inherit": "Herdar",
- "HomeVideos": "Vídeos Caseiros",
+ "HomeVideos": "Vídeos caseiros",
"Shows": "Séries",
"Photos": "Fotografias",
"Movies": "Filmes",
- "FailedLoginAttemptWithUserName": "Tentativa de início de sessão falhada a partir de {0}",
+ "FailedLoginAttemptWithUserName": "Tentativa falhada de início de sessão do utilizador {0}",
"ChapterNameValue": "Capítulo {0}",
"AuthenticationSucceededWithUserName": "{0} autenticado com sucesso",
"AppDeviceValues": "Aplicação: {0}, Dispositivo: {1}",
- "TaskCleanCache": "Limpar Diretório de Cache",
+ "TaskCleanCache": "Limpar pasta de cache",
"TasksApplicationCategory": "Aplicação",
- "TasksLibraryCategory": "Mediateca",
+ "TasksLibraryCategory": "Biblioteca",
"TasksMaintenanceCategory": "Manutenção",
- "TaskRefreshChannels": "Atualizar Canais",
- "TaskUpdatePlugins": "Atualizar Plugins",
- "TaskCleanLogsDescription": "Deletar arquivos de log que existe a mais de {0} dias.",
- "TaskCleanLogs": "Limpar diretório de logs",
- "TaskRefreshLibrary": "Analisar mediateca",
+ "TaskRefreshChannels": "Atualizar canais",
+ "TaskUpdatePlugins": "Atualizar plugins",
+ "TaskCleanLogsDescription": "Elimina ficheiros de registo com mais de {0} dias.",
+ "TaskCleanLogs": "Limpar pasta de registos",
+ "TaskRefreshLibrary": "Analisar biblioteca multimédia",
"TaskRefreshChapterImagesDescription": "Cria miniaturas para vídeos que têm capítulos.",
- "TaskCleanCacheDescription": "Apaga ficheiros em cache que já não são usados pelo sistema.",
- "TasksChannelsCategory": "Canais de Internet",
- "TaskRefreshChapterImages": "Extrair Imagens do Capítulo",
- "TaskDownloadMissingSubtitlesDescription": "Pesquisa na Internet as legendas em falta com base na configuração de metadados.",
+ "TaskCleanCacheDescription": "Elimina ficheiros de cache que já não são necessários ao sistema.",
+ "TasksChannelsCategory": "Canais da Internet",
+ "TaskRefreshChapterImages": "Extrair imagens dos capítulos",
+ "TaskDownloadMissingSubtitlesDescription": "Procura na Internet legendas em falta com base na configuração dos metadados.",
"TaskDownloadMissingSubtitles": "Transferir legendas em falta",
- "TaskRefreshChannelsDescription": "Atualiza as informações do canal da Internet.",
- "TaskCleanTranscodeDescription": "Apagar os ficheiros com mais de um dia, de Transcode.",
- "TaskCleanTranscode": "Limpar o diretório de Transcode",
- "TaskUpdatePluginsDescription": "Baixa e instala as atualizações para plug-ins configurados para atualização automática.",
- "TaskRefreshPeopleDescription": "Atualizar metadados para elenco e equipa técnica da tua mediateca.",
+ "TaskRefreshChannelsDescription": "Atualiza as informações dos canais da Internet.",
+ "TaskCleanTranscodeDescription": "Elimina ficheiros de transcodificação com mais de um dia.",
+ "TaskCleanTranscode": "Limpar pasta de transcodificação",
+ "TaskUpdatePluginsDescription": "Transfere e instala atualizações dos plugins configurados para atualização automática.",
+ "TaskRefreshPeopleDescription": "Atualiza os metadados de atores e realizadores na tua biblioteca multimédia.",
"TaskRefreshPeople": "Atualizar pessoas",
- "TaskRefreshLibraryDescription": "Analisar a mediateca para novos ficheiros e atualizar os metadados.",
- "TaskCleanActivityLog": "Limpar registro de atividade",
+ "TaskRefreshLibraryDescription": "Analisa a biblioteca multimédia à procura de novos ficheiros e atualiza os metadados.",
+ "TaskCleanActivityLog": "Limpar registo de atividade",
"Undefined": "Indefinido",
"Forced": "Forçado",
"Default": "Predefinição",
- "TaskCleanActivityLogDescription": "Apaga itens no registro com idade acima do que é configurado.",
+ "TaskCleanActivityLogDescription": "Elimina as entradas do registo de atividade mais antigas do que o período configurado.",
"TaskOptimizeDatabase": "Otimizar base de dados",
- "TaskOptimizeDatabaseDescription": "Otimiza e liberta espaço livre na base de dados. A execução desta tarefa depois de analisar a mediateca ou efetuar outras alterações que impliquem modificações na base de dados pode melhorar o desempenho.",
+ "TaskOptimizeDatabaseDescription": "Compacta a base de dados e liberta espaço não utilizado. A execução desta tarefa depois de analisar a biblioteca ou de outras alterações que modifiquem a base de dados pode melhorar o desempenho.",
"External": "Externo",
- "HearingImpaired": "Problemas auditivos",
- "TaskKeyframeExtractor": "Extrator de quadro-chave",
- "TaskKeyframeExtractorDescription": "Retira frames chave do video para criar listas HLS precisas. Esta tarefa pode correr durante algum tempo.",
+ "HearingImpaired": "Deficiência auditiva",
+ "TaskKeyframeExtractor": "Extrator de fotogramas-chave",
+ "TaskKeyframeExtractorDescription": "Extrai fotogramas-chave de ficheiros de vídeo para criar playlists HLS mais precisas. Esta tarefa pode demorar algum tempo.",
"TaskRefreshTrickplayImages": "Gerar imagens de trickplay",
"TaskRefreshTrickplayImagesDescription": "Cria pré-visualizações de trickplay para vídeos nas bibliotecas ativadas.",
"TaskAudioNormalizationDescription": "Analisa os ficheiros para obter dados de normalização de áudio.",
"TaskAudioNormalization": "Normalização de áudio",
- "TaskDownloadMissingLyrics": "Transferir letra em falta",
- "TaskDownloadMissingLyricsDescription": "Transferir letra para músicas",
- "TaskMoveTrickplayImagesDescription": "Move os ficheiros trickplay existentes de acordo com as definições da mediateca.",
- "TaskExtractMediaSegments": "Analisar segmentos de multimédia",
- "TaskExtractMediaSegmentsDescription": "Extrai ou obtém segmentos de multimédia a partir de plugins com suporte para MediaSegment.",
- "TaskMoveTrickplayImages": "Migrar a localização da imagem do Trickplay",
- "CleanupUserDataTask": "Task de limpeza de dados do usuário",
- "CleanupUserDataTaskDescription": "Remove todos os dados do usuário (progresso, favoritos etc) de mídias que não estão presentes há pelo menos 90 dias.",
+ "TaskDownloadMissingLyrics": "Transferir letras em falta",
+ "TaskDownloadMissingLyricsDescription": "Transfere letras de músicas",
+ "TaskMoveTrickplayImagesDescription": "Move os ficheiros de trickplay existentes de acordo com as definições da biblioteca.",
+ "TaskExtractMediaSegments": "Analisar segmentos multimédia",
+ "TaskExtractMediaSegmentsDescription": "Extrai ou obtém segmentos multimédia de plugins com MediaSegment ativado.",
+ "TaskMoveTrickplayImages": "Migrar localização das imagens de trickplay",
+ "CleanupUserDataTask": "Limpeza de dados de utilizador",
+ "CleanupUserDataTaskDescription": "Remove todos os dados de utilizador (estado de reprodução, estado de favorito, etc.) de conteúdos multimédia que já não estejam presentes há pelo menos 90 dias.",
"Original": "Original",
- "LyricDownloadFailureFromForItem": "Erro ao descarregar letras de {0} para {1}"
+ "LyricDownloadFailureFromForItem": "Falha ao transferir letras de {0} para {1}",
+ "NameExtraBehindTheScenes": "Bastidores",
+ "NameExtraClip": "Excerto",
+ "NameExtraDeletedScene": "Cena eliminada",
+ "NameExtraFeaturette": "Minidocumentário",
+ "NameExtraInterview": "Entrevista",
+ "NameExtraSample": "Amostra",
+ "NameExtraShort": "Curta-metragem",
+ "NameExtraThemeSong": "Tema musical",
+ "NameExtraThemeVideo": "Vídeo temático",
+ "NameExtraScene": "Cena",
+ "NameExtraUnknown": "Extra",
+ "NameExtraTrailer": "Trailer",
+ "NameExtraNumbered": "{0} {1}"
}
diff --git a/Emby.Server.Implementations/Localization/Core/ro.json b/Emby.Server.Implementations/Localization/Core/ro.json
index ea83b88951..358c19881f 100644
--- a/Emby.Server.Implementations/Localization/Core/ro.json
+++ b/Emby.Server.Implementations/Localization/Core/ro.json
@@ -108,5 +108,8 @@
"CleanupUserDataTask": "Sarcina de curatare a datelor utilizatorului",
"CleanupUserDataTaskDescription": "Sterge toate datele utilizatorului (starea vizionarii, starea favoritelor etc.) de pe suporturile media care nu mai sunt prezente timp de cel puțin 90 de zile.",
"LyricDownloadFailureFromForItem": "Versurile nu au putut fi descărcate din {0} pentru {1}",
- "Original": "Original"
+ "Original": "Original",
+ "NameExtraBehindTheScenes": "În culise",
+ "NameExtraClip": "Clip",
+ "NameExtraDeletedScene": "Scenă ștearsă"
}
diff --git a/Emby.Server.Implementations/Localization/Core/ru.json b/Emby.Server.Implementations/Localization/Core/ru.json
index 40d5e3985d..c13fd3ebdc 100644
--- a/Emby.Server.Implementations/Localization/Core/ru.json
+++ b/Emby.Server.Implementations/Localization/Core/ru.json
@@ -108,5 +108,18 @@
"CleanupUserDataTask": "Задача очистки пользовательских данных",
"CleanupUserDataTaskDescription": "Очищает все пользовательские данные (состояние просмотра, статус избранного и т.д.) с медиа, отсутствующих по меньшей мере в течение 90 дней.",
"Original": "Оригинальный",
- "LyricDownloadFailureFromForItem": "Не получилось скачать текст песни с {0} для {1}"
+ "LyricDownloadFailureFromForItem": "Не получилось скачать текст песни с {0} для {1}",
+ "NameExtraBehindTheScenes": "За кадром",
+ "NameExtraClip": "Отрывок",
+ "NameExtraDeletedScene": "Удалённая сцена",
+ "NameExtraFeaturette": "Короткометражка",
+ "NameExtraInterview": "Интервью",
+ "NameExtraSample": "Образец",
+ "NameExtraScene": "Сцена",
+ "NameExtraThemeSong": "Заглавная песня",
+ "NameExtraThemeVideo": "Заглавное видео",
+ "NameExtraTrailer": "Трейлер",
+ "NameExtraUnknown": "Дополнительный материал",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraShort": "Короткометражка"
}
diff --git a/Emby.Server.Implementations/Localization/Core/sk.json b/Emby.Server.Implementations/Localization/Core/sk.json
index 7ae8857e5d..9573eeefe4 100644
--- a/Emby.Server.Implementations/Localization/Core/sk.json
+++ b/Emby.Server.Implementations/Localization/Core/sk.json
@@ -91,7 +91,7 @@
"Default": "Predvolené",
"TaskOptimizeDatabaseDescription": "Zmenší databázu a odstráni prázdne miesto. Spustenie tejto úlohy po skenovaní knižnice alebo po iných zmenách zahŕňajúcich úpravy databáze môže zlepšiť výkon.",
"TaskOptimizeDatabase": "Optimalizovať databázu",
- "TaskKeyframeExtractorDescription": "Extrahuje kľúčové snímky z video súborov na vytvorenie presnejších HLS playlistov. Táto úloha môže trvať dlhšiu dobu.",
+ "TaskKeyframeExtractorDescription": "Extrahuje kľúčové snímky z video súborov na vytvorenie presnejších HLS zoznamov prehrávania. Táto úloha môže trvať dlhšiu dobu.",
"TaskKeyframeExtractor": "Extraktor kľúčových snímkov",
"External": "Externé",
"HearingImpaired": "Sluchovo postihnutí",
@@ -108,5 +108,18 @@
"CleanupUserDataTask": "Prečistiť používateľské dáta",
"CleanupUserDataTaskDescription": "Vyčistí všetky dáta používateľa (stav sledovania, stav obľúbených atď.) z médií, ktoré už neexistujú aspoň 90 dní.",
"LyricDownloadFailureFromForItem": "Text piesne sa nepodarilo stiahnuť z {0} pre {1}",
- "Original": "Originál"
+ "Original": "Originál",
+ "NameExtraBehindTheScenes": "Zo zákulisia",
+ "NameExtraClip": "Klip",
+ "NameExtraDeletedScene": "Vystrihnutá scéna",
+ "NameExtraFeaturette": "Bonus",
+ "NameExtraInterview": "Rozhovor",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraSample": "Ukážka",
+ "NameExtraScene": "Scéna",
+ "NameExtraShort": "Krátky film",
+ "NameExtraThemeSong": "Úvodná pieseň",
+ "NameExtraThemeVideo": "Úvodné video",
+ "NameExtraTrailer": "Trailer",
+ "NameExtraUnknown": "Extra"
}
diff --git a/Emby.Server.Implementations/Localization/Core/sq.json b/Emby.Server.Implementations/Localization/Core/sq.json
index e13f7b09e1..11b25e9795 100644
--- a/Emby.Server.Implementations/Localization/Core/sq.json
+++ b/Emby.Server.Implementations/Localization/Core/sq.json
@@ -108,5 +108,18 @@
"CleanupUserDataTaskDescription": "Pastron të gjitha të dhënat e përdorueseve (gjendja e shikimit, statusi i të preferuarave etj.) nga mediat që nuk janë më të pranishme për të paktën 90 ditë.",
"CleanupUserDataTask": "Veprim për pastrimin të dhënave të përdorueseve",
"LyricDownloadFailureFromForItem": "Teksti i këngës nuk arriti të shkarkohej nga {0} për {1}",
- "Original": "Origjinal"
+ "Original": "Origjinal",
+ "NameExtraBehindTheScenes": "Pamje nga prapaskenat",
+ "NameExtraClip": "Pjesë",
+ "NameExtraDeletedScene": "Skenë e fshirë",
+ "NameExtraFeaturette": "Film i shkurtër",
+ "NameExtraInterview": "Intervistë",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraSample": "Shembull",
+ "NameExtraScene": "Skenë",
+ "NameExtraShort": "Film i shkurtër",
+ "NameExtraThemeSong": "Kënga e temës",
+ "NameExtraThemeVideo": "Videoja e temës",
+ "NameExtraTrailer": "Parapamje",
+ "NameExtraUnknown": "Shtesë"
}
diff --git a/Emby.Server.Implementations/Localization/Core/sr.json b/Emby.Server.Implementations/Localization/Core/sr.json
index 92f309c80c..de0e425098 100644
--- a/Emby.Server.Implementations/Localization/Core/sr.json
+++ b/Emby.Server.Implementations/Localization/Core/sr.json
@@ -108,5 +108,18 @@
"TaskMoveTrickplayImages": "Промени локацију сличица за визуелно премотавање",
"TaskDownloadMissingLyricsDescription": "Преузми стихове песама",
"LyricDownloadFailureFromForItem": "Није успело преузимање стихова са {0} за {1}",
- "Original": "Изворно"
+ "Original": "Изворно",
+ "NameExtraBehindTheScenes": "Иза кулиса",
+ "NameExtraClip": "Исечак",
+ "NameExtraDeletedScene": "Обрисана сцена",
+ "NameExtraFeaturette": "Кратки прилог",
+ "NameExtraInterview": "Интервју",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraSample": "Узорак",
+ "NameExtraScene": "Сцена",
+ "NameExtraShort": "Кратки филм",
+ "NameExtraThemeSong": "Музичка тема",
+ "NameExtraThemeVideo": "Спот музичке теме",
+ "NameExtraTrailer": "Реклама",
+ "NameExtraUnknown": "Додатак"
}
diff --git a/Emby.Server.Implementations/Localization/Core/sv.json b/Emby.Server.Implementations/Localization/Core/sv.json
index 7384967122..7d741bca36 100644
--- a/Emby.Server.Implementations/Localization/Core/sv.json
+++ b/Emby.Server.Implementations/Localization/Core/sv.json
@@ -108,5 +108,18 @@
"CleanupUserDataTaskDescription": "Tar bort all användardata (såsom vad du sett, favoriter med mera) för media som inte funnits på enheten på minst 90 dagar.",
"CleanupUserDataTask": "Uppgift för rensning av användardata",
"Original": "Original",
- "LyricDownloadFailureFromForItem": "Misslyckades att ladda ner låttexter från {0} för {1}"
+ "LyricDownloadFailureFromForItem": "Misslyckades att ladda ner låttexter från {0} för {1}",
+ "NameExtraBehindTheScenes": "Bakom kulisserna",
+ "NameExtraDeletedScene": "Borttagen scen",
+ "NameExtraInterview": "Intervju",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraScene": "Scen",
+ "NameExtraShort": "Kortfilm",
+ "NameExtraThemeSong": "Signaturmelodi",
+ "NameExtraTrailer": "Trailer",
+ "NameExtraClip": "Klipp",
+ "NameExtraFeaturette": "Kortfilm",
+ "NameExtraSample": "Prov",
+ "NameExtraThemeVideo": "Signaturvideo",
+ "NameExtraUnknown": "Extra"
}
diff --git a/Emby.Server.Implementations/Localization/Core/ta.json b/Emby.Server.Implementations/Localization/Core/ta.json
index f613b973db..256f349926 100644
--- a/Emby.Server.Implementations/Localization/Core/ta.json
+++ b/Emby.Server.Implementations/Localization/Core/ta.json
@@ -106,5 +106,20 @@
"TaskExtractMediaSegments": "மீடியா பிரிவு ஸ்கேன்",
"TaskExtractMediaSegmentsDescription": "மீடியாசெக்மென்ட் இயக்கப்பட்ட செருகுநிரல்களிலிருந்து மீடியா பிரிவுகளைப் பிரித்தெடுக்கிறது அல்லது பெறுகிறது.",
"CleanupUserDataTaskDescription": "குறைந்தது 90 நாட்களுக்கு இல்லாத மீடியாவிலிருந்து அனைத்து பயனர் தரவையும் (கண்காணிப்பு நிலை, பிடித்த நிலை போன்றவை) சுத்தம் செய்கிறது.",
- "CleanupUserDataTask": "பயனர் தரவை சுத்தம் செய்யும் பணி"
+ "CleanupUserDataTask": "பயனர் தரவை சுத்தம் செய்யும் பணி",
+ "LyricDownloadFailureFromForItem": "{0} இலிருந்து {1} க்கு பாடல் வரிகளைப் பதிவிறக்க முடியவில்லை",
+ "NameExtraBehindTheScenes": "திரைக்குப் பின்னால்",
+ "NameExtraClip": "துண்டுக்காட்சி",
+ "NameExtraDeletedScene": "நீக்கப்பட்ட காட்சிகள்",
+ "NameExtraFeaturette": "திரைப்பின்னணித் தொகுப்பு",
+ "NameExtraInterview": "நேர்காணல்",
+ "NameExtraSample": "மாதிரி",
+ "NameExtraScene": "காட்சி",
+ "NameExtraShort": "குறுகிய",
+ "NameExtraThemeSong": "மையப் பாடல்",
+ "NameExtraThemeVideo": "மையக் காணொளி",
+ "NameExtraTrailer": "முன்னோட்டம்",
+ "NameExtraUnknown": "கூடுதல்",
+ "Original": "அசல்",
+ "NameExtraNumbered": "{0} {1}"
}
diff --git a/Emby.Server.Implementations/Localization/Core/th.json b/Emby.Server.Implementations/Localization/Core/th.json
index 89c2c26748..716e3ae55d 100644
--- a/Emby.Server.Implementations/Localization/Core/th.json
+++ b/Emby.Server.Implementations/Localization/Core/th.json
@@ -106,5 +106,7 @@
"TaskExtractMediaSegmentsDescription": "แยกหรือดึงส่วนของสื่อจากปลั๊กอินที่เปิดใช้งาน MediaSegment",
"TaskMoveTrickplayImages": "ย้ายตำแหน่งเก็บภาพตัวอย่าง Trickplay",
"CleanupUserDataTask": "ส่วนงานล้างข้อมูลผู้ใช้",
- "CleanupUserDataTaskDescription": "ล้างข้อมูลผู้ใช้ทั้งหมด (สถานะการรับชม สถานะรายการโปรด ฯลฯ) จากสื่อที่ไม่ได้ใช้งานแล้วอย่างน้อย 90 วัน"
+ "CleanupUserDataTaskDescription": "ล้างข้อมูลผู้ใช้ทั้งหมด (สถานะการรับชม สถานะรายการโปรด ฯลฯ) จากสื่อที่ไม่ได้ใช้งานแล้วอย่างน้อย 90 วัน",
+ "LyricDownloadFailureFromForItem": "ไม่สามารถดาวน์โหลดเนื้อเพลงจาก {0} สำหรับ {1}",
+ "Original": "ต้นฉบับ"
}
diff --git a/Emby.Server.Implementations/Localization/Core/tr.json b/Emby.Server.Implementations/Localization/Core/tr.json
index 0c42d4a55f..67f4ecc4d5 100644
--- a/Emby.Server.Implementations/Localization/Core/tr.json
+++ b/Emby.Server.Implementations/Localization/Core/tr.json
@@ -1,5 +1,5 @@
{
- "AppDeviceValues": "Uygulama: {0}, Aygıt: {1}",
+ "AppDeviceValues": "Uygulama: {0}, Cihaz: {1}",
"Artists": "Sanatçılar",
"AuthenticationSucceededWithUserName": "{0} kimliği başarıyla doğrulandı",
"Books": "Kitaplar",
@@ -108,5 +108,18 @@
"CleanupUserDataTask": "Kullanıcı verisi temizleme görevi",
"CleanupUserDataTaskDescription": "En az 90 gün boyunca artık mevcut olmayan medyadaki tüm kullanıcı verilerini (İzleme durumu, favori durumu vb.) temizler.",
"LyricDownloadFailureFromForItem": "{1} şarkı sözleri {0} adresinden indirilemedi",
- "Original": "Orijinal"
+ "Original": "Orijinal",
+ "NameExtraBehindTheScenes": "Kamera Arkası",
+ "NameExtraClip": "Klip",
+ "NameExtraDeletedScene": "Silinmiş Sahne",
+ "NameExtraFeaturette": "Kısa film",
+ "NameExtraInterview": "Röportaj",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraSample": "Örnek",
+ "NameExtraScene": "Sahne",
+ "NameExtraShort": "Kısa",
+ "NameExtraThemeSong": "Tanıtım Müziği",
+ "NameExtraThemeVideo": "Tanıtım Videosu",
+ "NameExtraTrailer": "Fragman",
+ "NameExtraUnknown": "Fazladan"
}
diff --git a/Emby.Server.Implementations/Localization/Core/uk.json b/Emby.Server.Implementations/Localization/Core/uk.json
index ccb9d915d1..856740545c 100644
--- a/Emby.Server.Implementations/Localization/Core/uk.json
+++ b/Emby.Server.Implementations/Localization/Core/uk.json
@@ -108,5 +108,18 @@
"CleanupUserDataTask": "Завдання очищення даних користувача",
"CleanupUserDataTaskDescription": "Очищає всі дані користувача (стан перегляду, статус обраного тощо) з медіа, які перестали бути доступними щонайменше 90 днів тому.",
"Original": "Оригінал",
- "LyricDownloadFailureFromForItem": "Не вдалося завантажити текст пісні з {0} для {1}"
+ "LyricDownloadFailureFromForItem": "Не вдалося завантажити текст пісні з {0} для {1}",
+ "NameExtraBehindTheScenes": "За лаштунками",
+ "NameExtraClip": "Кліп",
+ "NameExtraDeletedScene": "Видалена сцена",
+ "NameExtraFeaturette": "Фічуретка",
+ "NameExtraInterview": "Інтерв’ю",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraSample": "Приклад",
+ "NameExtraScene": "Сцена",
+ "NameExtraShort": "Коротко",
+ "NameExtraThemeSong": "Тематична пісня",
+ "NameExtraThemeVideo": "Тематичне вiдео",
+ "NameExtraTrailer": "Трейлер",
+ "NameExtraUnknown": "Додатково"
}
diff --git a/Emby.Server.Implementations/Localization/Core/vi.json b/Emby.Server.Implementations/Localization/Core/vi.json
index 2ba665e2ff..77619b24d0 100644
--- a/Emby.Server.Implementations/Localization/Core/vi.json
+++ b/Emby.Server.Implementations/Localization/Core/vi.json
@@ -32,7 +32,7 @@
"TasksLibraryCategory": "Thư Viện",
"TasksMaintenanceCategory": "Bảo Trì",
"VersionNumber": "Phiên Bản {0}",
- "UserStoppedPlayingItemWithValues": "{0} đã kết thúc phát {1} trên {2}",
+ "UserStoppedPlayingItemWithValues": "{0} đã phát xong {1} trên {2}",
"UserStartedPlayingItemWithValues": "{0} đang phát {1} trên {2}",
"UserPasswordChangedWithName": "Mật khẩu đã được thay đổi cho người dùng {0}",
"UserOnlineFromDevice": "{0} trực tuyến từ {1}",
@@ -79,7 +79,7 @@
"HeaderNextUp": "Tiếp Theo",
"HeaderFavoriteShows": "Chương Trình Yêu Thích",
"HeaderFavoriteEpisodes": "Tập Phim Yêu Thích",
- "FailedLoginAttemptWithUserName": "Nỗ lực đăng nhập không thành công từ {0}",
+ "FailedLoginAttemptWithUserName": "Cố gắng đăng nhập thất bại từ {0}",
"ChapterNameValue": "Phân Cảnh {0}",
"Books": "Sách",
"AuthenticationSucceededWithUserName": "{0} xác thực thành công",
@@ -95,18 +95,31 @@
"TaskKeyframeExtractorDescription": "Trích xuất khung hình chính từ các tệp video để tạo danh sách phát HLS chính xác hơn. Tác vụ này có thể chạy trong một thời gian dài.",
"External": "Bên ngoài",
"HearingImpaired": "Khiếm Thính",
- "TaskRefreshTrickplayImages": "Tạo Ảnh Xem Trước Trickplay",
- "TaskRefreshTrickplayImagesDescription": "Tạo bản xem trước trịckplay cho video trong thư viện đã bật.",
+ "TaskRefreshTrickplayImages": "Tạo Ảnh Tua Nhanh (Trickplay)",
+ "TaskRefreshTrickplayImagesDescription": "Tạo ảnh tua nhanh (trịckplay) xem thử cho các video trong các thư viện được kích hoạt.",
"TaskAudioNormalization": "Chuẩn Hóa Âm Thanh",
"TaskAudioNormalizationDescription": "Quét tập tin để tìm dữ liệu chuẩn hóa âm thanh.",
"TaskDownloadMissingLyricsDescription": "Tải xuống lời cho bài hát",
"TaskDownloadMissingLyrics": "Tải xuống lời bị thiếu",
"TaskExtractMediaSegmentsDescription": "Trích xuất hoặc lấy các phân đoạn phương tiện từ các plugin hỗ trợ MediaSegment.",
- "TaskMoveTrickplayImages": "Di chuyển vị trí hình ảnh Trickplay",
- "TaskMoveTrickplayImagesDescription": "Di chuyển các tập tin trickplay hiện có theo cài đặt thư viện.",
+ "TaskMoveTrickplayImages": "Di Chuyển Vị Trí Ảnh Tua Nhanh (Trickplay)",
+ "TaskMoveTrickplayImagesDescription": "Di chuyển các tệp ảnh tua nhanh (trickplay) hiện có theo cài đặt thư viện.",
"TaskExtractMediaSegments": "Quét Phân Đoạn Phương Tiện",
"CleanupUserDataTask": "Tác vụ dọn dẹp dữ liệu người dùng",
"CleanupUserDataTaskDescription": "Làm sạch tất cả dữ liệu người dùng (trạng thái xem, trạng thái yêu thích, v.v.) từ phương tiện không còn có mặt trong ít nhất 90 ngày.",
"Original": "Gốc",
- "LyricDownloadFailureFromForItem": "Lời bài hát không tải xuống được từ {0} cho {1}"
+ "LyricDownloadFailureFromForItem": "Lời bài hát không tải xuống được từ {0} cho {1}",
+ "NameExtraBehindTheScenes": "Hậu Trường",
+ "NameExtraDeletedScene": "Cảnh Bị Xóa",
+ "NameExtraInterview": "Phỏng vấn",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraSample": "Mẫu",
+ "NameExtraScene": "Cảnh",
+ "NameExtraShort": "Ngắn",
+ "NameExtraThemeSong": "Bài Hát Chủ Đề",
+ "NameExtraThemeVideo": "Video Chủ Đề",
+ "NameExtraFeaturette": "Nội dung phụ",
+ "NameExtraClip": "Clip ngắn",
+ "NameExtraTrailer": "Đoạn giới thiệu",
+ "NameExtraUnknown": "Nội dung bổ sung"
}
diff --git a/Emby.Server.Implementations/Localization/Core/zh-CN.json b/Emby.Server.Implementations/Localization/Core/zh-CN.json
index 18418ae0bc..9590d9c1c9 100644
--- a/Emby.Server.Implementations/Localization/Core/zh-CN.json
+++ b/Emby.Server.Implementations/Localization/Core/zh-CN.json
@@ -108,5 +108,18 @@
"CleanupUserDataTask": "用户数据清理任务",
"CleanupUserDataTaskDescription": "清理已被删除超过90天的媒体中的所有用户数据(观看状态、收藏夹状态等)。",
"LyricDownloadFailureFromForItem": "无法从 {0} 下载 {1} 的歌词",
- "Original": "原始"
+ "Original": "原始",
+ "NameExtraBehindTheScenes": "幕后花絮",
+ "NameExtraClip": "片段",
+ "NameExtraDeletedScene": "删减场景",
+ "NameExtraFeaturette": "花絮",
+ "NameExtraInterview": "采访",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraSample": "试看",
+ "NameExtraScene": "精选片段",
+ "NameExtraShort": "短篇",
+ "NameExtraThemeSong": "主题曲",
+ "NameExtraThemeVideo": "主题视频",
+ "NameExtraTrailer": "预告片",
+ "NameExtraUnknown": "额外内容"
}
diff --git a/Emby.Server.Implementations/Localization/Core/zh-HK.json b/Emby.Server.Implementations/Localization/Core/zh-HK.json
index b2fcbc93a2..9557742d39 100644
--- a/Emby.Server.Implementations/Localization/Core/zh-HK.json
+++ b/Emby.Server.Implementations/Localization/Core/zh-HK.json
@@ -10,8 +10,8 @@
"Folders": "資料夾",
"Genres": "風格",
"HeaderContinueWatching": "繼續睇返",
- "HeaderFavoriteEpisodes": "心水嘅劇集",
- "HeaderFavoriteShows": "心水嘅節目",
+ "HeaderFavoriteEpisodes": "心水劇集",
+ "HeaderFavoriteShows": "心水節目",
"HeaderLiveTV": "電視直播",
"HeaderNextUp": "跟住落嚟",
"HomeVideos": "家庭影片",
@@ -108,5 +108,18 @@
"CleanupUserDataTask": "清理使用者資料嘅任務",
"CleanupUserDataTaskDescription": "清理已消失至少 90 日嘅媒體用家數據(包括觀看狀態、心水狀態等)。",
"LyricDownloadFailureFromForItem": "冇辦法從 {0} 下載 {1} 嘅歌詞",
- "Original": "原始"
+ "Original": "原始",
+ "NameExtraBehindTheScenes": "幕後花絮",
+ "NameExtraClip": "片段",
+ "NameExtraDeletedScene": "刪減場景",
+ "NameExtraFeaturette": "花絮",
+ "NameExtraInterview": "采訪",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraSample": "試看",
+ "NameExtraScene": "精選片段",
+ "NameExtraShort": "短篇",
+ "NameExtraThemeSong": "主題曲",
+ "NameExtraThemeVideo": "主題影片",
+ "NameExtraTrailer": "預告片",
+ "NameExtraUnknown": "額外內容"
}
diff --git a/Emby.Server.Implementations/Localization/Core/zh-TW.json b/Emby.Server.Implementations/Localization/Core/zh-TW.json
index 4e0dff87b9..bcc5b0b44f 100644
--- a/Emby.Server.Implementations/Localization/Core/zh-TW.json
+++ b/Emby.Server.Implementations/Localization/Core/zh-TW.json
@@ -108,5 +108,18 @@
"CleanupUserDataTask": "用戶資料清理工作",
"CleanupUserDataTaskDescription": "從用戶資料中清除已被刪除超過 90 天的媒體的相關資料。",
"Original": "原作",
- "LyricDownloadFailureFromForItem": "無法從 {0} 下載 {1} 的歌詞"
+ "LyricDownloadFailureFromForItem": "無法從 {0} 下載 {1} 的歌詞",
+ "NameExtraBehindTheScenes": "幕後花絮",
+ "NameExtraClip": "片段",
+ "NameExtraDeletedScene": "刪減場景",
+ "NameExtraFeaturette": "花絮",
+ "NameExtraInterview": "采訪",
+ "NameExtraNumbered": "{0} {1}",
+ "NameExtraSample": "試看",
+ "NameExtraScene": "精選片段",
+ "NameExtraShort": "短篇",
+ "NameExtraThemeSong": "主題曲",
+ "NameExtraThemeVideo": "主題影片",
+ "NameExtraTrailer": "預告片",
+ "NameExtraUnknown": "額外內容"
}
diff --git a/Emby.Server.Implementations/Playlists/PlaylistManager.cs b/Emby.Server.Implementations/Playlists/PlaylistManager.cs
index 409414139c..308faed8cc 100644
--- a/Emby.Server.Implementations/Playlists/PlaylistManager.cs
+++ b/Emby.Server.Implementations/Playlists/PlaylistManager.cs
@@ -219,28 +219,15 @@ namespace Emby.Server.Implementations.Playlists
var playlist = _libraryManager.GetItemById(playlistId) as Playlist
?? throw new ArgumentException("No Playlist exists with Id " + playlistId);
- // Retrieve all the items to be added to the playlist
+ // Retrieve all the items to be added to the playlist.
var newItems = GetPlaylistItems(newItemIds, user, options)
.Where(i => i.SupportsAddingToPlaylist);
- // Filter out duplicate items
- var existingIds = playlist.LinkedChildren.Select(c => c.ItemId).ToHashSet();
- newItems = newItems
- .Where(i => !existingIds.Contains(i.Id))
- .Distinct();
-
// Create a list of the new linked children to add to the playlist
var childrenToAdd = newItems
.Select(LinkedChild.Create)
.ToList();
- // Log duplicates that have been ignored, if any
- int numDuplicates = newItemIds.Count - childrenToAdd.Count;
- if (numDuplicates > 0)
- {
- _logger.LogWarning("Ignored adding {DuplicateCount} duplicate items to playlist {PlaylistName}.", numDuplicates, playlist.Name);
- }
-
// Do nothing else if there are no items to add to the playlist
if (childrenToAdd.Count == 0)
{
diff --git a/Emby.Server.Implementations/Plugins/PluginManager.cs b/Emby.Server.Implementations/Plugins/PluginManager.cs
index f699c99d85..8d29d6a512 100644
--- a/Emby.Server.Implementations/Plugins/PluginManager.cs
+++ b/Emby.Server.Implementations/Plugins/PluginManager.cs
@@ -255,6 +255,14 @@ namespace Emby.Server.Implementations.Plugins
}
_plugins.Add(plugin);
+
+ // Updating a disabled plugin must not enable it again.
+ if (plugin.Manifest.Status == PluginStatus.Disabled)
+ {
+ ProcessAlternative(plugin);
+ return;
+ }
+
EnablePlugin(plugin);
}
@@ -632,9 +640,10 @@ namespace Emby.Server.Implementations.Plugins
return;
}
- var predecessor = _plugins.OrderByDescending(p => p.Version)
- .FirstOrDefault(p => p.Id.Equals(plugin.Id) && p.IsEnabledAndSupported && p.Version != plugin.Version);
- if (predecessor is not null)
+ var successor = _plugins.FirstOrDefault(p => p.Id.Equals(plugin.Id)
+ && p.Version > plugin.Version
+ && (p.IsEnabledAndSupported || p.Manifest.Status == PluginStatus.Disabled));
+ if (successor is not null)
{
return;
}
@@ -763,6 +772,8 @@ namespace Emby.Server.Implementations.Plugins
var entry = versions[x];
if (!string.Equals(lastName, entry.Name, StringComparison.OrdinalIgnoreCase))
{
+ lastName = string.Empty;
+
if (!TryGetPluginDlls(entry, out var allowedDlls))
{
_logger.LogError("One or more assembly paths was invalid. Marking plugin {Plugin} as \"Malfunctioned\".", entry.Name);
@@ -772,15 +783,18 @@ namespace Emby.Server.Implementations.Plugins
entry.DllFiles = allowedDlls;
+ // Only clean up older versions when this version will actually be loaded.
if (entry.IsEnabledAndSupported)
{
lastName = entry.Name;
- continue;
}
+
+ continue;
}
if (string.IsNullOrEmpty(lastName))
{
+ // Unnamed plugin, so there is nothing to match older versions against.
continue;
}
@@ -891,9 +905,9 @@ namespace Emby.Server.Implementations.Plugins
if (previousVersion is null)
{
- // This value is memory only - so that the web will show restart required.
- plugin.Manifest.Status = PluginStatus.Restart;
- plugin.Manifest.AutoUpdate = false;
+ // Memory only, so that the web will show restart required. The manifest must keep
+ // holding the persisted state, or a later save would write the wrong state to disk.
+ plugin.RestartRequired = true;
return;
}
@@ -906,9 +920,7 @@ namespace Emby.Server.Implementations.Plugins
_logger.LogError("Unable to supercede version {Version} of {Name}", previousVersion.Version, previousVersion.Name);
}
- // This value is memory only - so that the web will show restart required.
- plugin.Manifest.Status = PluginStatus.Restart;
- plugin.Manifest.AutoUpdate = false;
+ plugin.RestartRequired = true;
}
}
}
diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs
index 5d62332552..f4aa0ad03a 100644
--- a/Emby.Server.Implementations/Session/SessionManager.cs
+++ b/Emby.Server.Implementations/Session/SessionManager.cs
@@ -655,7 +655,7 @@ namespace Emby.Server.Implementations.Session
ItemId = session.NowPlayingItem is null ? Guid.Empty : session.NowPlayingItem.Id,
SessionId = session.Id,
MediaSourceId = session.PlayState?.MediaSourceId,
- PositionTicks = session.PlayState?.PositionTicks
+ PositionTicks = session.LastPlaybackCheckInPositionTicks
}).ConfigureAwait(false);
}
catch (Exception ex)
diff --git a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs
index 2582ed9df0..e81edc82c6 100644
--- a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs
+++ b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs
@@ -223,7 +223,7 @@ namespace Emby.Server.Implementations.Session
if (inactive.Count > 0)
{
- _logger.LogInformation("Sending ForceKeepAlive message to {0} inactive WebSockets.", inactive.Count);
+ _logger.LogDebug("Sending ForceKeepAlive message to {0} inactive WebSockets.", inactive.Count);
}
foreach (var webSocket in inactive)
diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs
index 6a60f7f5f6..174234b96b 100644
--- a/Emby.Server.Implementations/Updates/InstallationManager.cs
+++ b/Emby.Server.Implementations/Updates/InstallationManager.cs
@@ -500,8 +500,9 @@ namespace Emby.Server.Implementations.Updates
var plugins = _pluginManager.Plugins;
foreach (var plugin in plugins)
{
- // Don't auto update when plugin marked not to, or when it's disabled.
- if (plugin.Manifest?.AutoUpdate == false || plugin.Manifest?.Status == PluginStatus.Disabled)
+ // Don't auto update when plugin marked not to, or when it's disabled or pending removal.
+ if (plugin.Manifest?.AutoUpdate == false
+ || plugin.Manifest?.Status is PluginStatus.Disabled or PluginStatus.Deleted)
{
continue;
}