1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00

Merge remote-tracking branch 'upstream/master' into scrollbar-placeholder

This commit is contained in:
ferferga 2020-05-17 00:18:14 +02:00
commit 8cbec3fe22
36 changed files with 843 additions and 662 deletions

5
.gitignore vendored
View file

@ -8,4 +8,7 @@ node_modules
# ide # ide
.idea .idea
.vscode .vscode
#log
yarn-error.log

View file

@ -102,6 +102,10 @@
"src/scripts/filesystem.js", "src/scripts/filesystem.js",
"src/scripts/imagehelper.js", "src/scripts/imagehelper.js",
"src/scripts/inputManager.js", "src/scripts/inputManager.js",
"src/components/deletehelper.js",
"src/components/actionsheet/actionsheet.js",
"src/components/playmenu.js",
"src/components/indicators/indicators.js",
"src/scripts/keyboardnavigation.js", "src/scripts/keyboardnavigation.js",
"src/scripts/settings/appSettings.js", "src/scripts/settings/appSettings.js",
"src/scripts/settings/userSettings.js", "src/scripts/settings/userSettings.js",

View file

@ -1,360 +1,343 @@
define(['dialogHelper', 'layoutManager', 'globalize', 'browser', 'dom', 'emby-button', 'css!./actionsheet', 'material-icons', 'scrollStyles', 'listViewStyle'], function (dialogHelper, layoutManager, globalize, browser, dom) { import dialogHelper from 'dialogHelper';
'use strict'; import layoutManager from 'layoutManager';
import globalize from 'globalize';
import dom from 'dom';
import 'emby-button';
import 'css!./actionsheet';
import 'material-icons';
import 'scrollStyles';
import 'listViewStyle';
function getOffsets(elems) { function getOffsets(elems) {
var doc = document; let results = [];
var results = [];
if (!doc) {
return results;
}
var box;
var elem;
for (var i = 0, length = elems.length; i < length; i++) {
elem = elems[i];
// Support: BlackBerry 5, iOS 3 (original iPhone)
// If we don't have gBCR, just use 0,0 rather than error
if (elem.getBoundingClientRect) {
box = elem.getBoundingClientRect();
} else {
box = { top: 0, left: 0 };
}
results[i] = {
top: box.top,
left: box.left,
width: box.width,
height: box.height
};
}
if (!document) {
return results; return results;
} }
function getPosition(options, dlg) { let box;
for (let elem of elems) {
var windowSize = dom.getWindowSize(); // Support: BlackBerry 5, iOS 3 (original iPhone)
var windowHeight = windowSize.innerHeight; // If we don't have gBCR, just use 0,0 rather than error
var windowWidth = windowSize.innerWidth; if (elem.getBoundingClientRect) {
box = elem.getBoundingClientRect();
var pos = getOffsets([options.positionTo])[0]; } else {
box = { top: 0, left: 0 };
if (options.positionY !== 'top') {
pos.top += (pos.height || 0) / 2;
} }
pos.left += (pos.width || 0) / 2; results.push({
top: box.top,
var height = dlg.offsetHeight || 300; left: box.left,
var width = dlg.offsetWidth || 160; width: box.width,
height: box.height
// Account for popup size
pos.top -= height / 2;
pos.left -= width / 2;
// Avoid showing too close to the bottom
var overflowX = pos.left + width - windowWidth;
var overflowY = pos.top + height - windowHeight;
if (overflowX > 0) {
pos.left -= (overflowX + 20);
}
if (overflowY > 0) {
pos.top -= (overflowY + 20);
}
pos.top += (options.offsetTop || 0);
pos.left += (options.offsetLeft || 0);
// Do some boundary checking
pos.top = Math.max(pos.top, 10);
pos.left = Math.max(pos.left, 10);
return pos;
}
function centerFocus(elem, horiz, on) {
require(['scrollHelper'], function (scrollHelper) {
var fn = on ? 'on' : 'off';
scrollHelper.centerFocus[fn](elem, horiz);
}); });
} }
function show(options) { return results;
}
// items function getPosition(options, dlg) {
// positionTo
// showCancel
// title
var dialogOptions = {
removeOnClose: true,
enableHistory: options.enableHistory,
scrollY: false
};
var backButton = false; const windowSize = dom.getWindowSize();
var isFullscreen; const windowHeight = windowSize.innerHeight;
const windowWidth = windowSize.innerWidth;
if (layoutManager.tv) { let pos = getOffsets([options.positionTo])[0];
dialogOptions.size = 'fullscreen';
isFullscreen = true;
backButton = true;
dialogOptions.autoFocus = true;
} else {
dialogOptions.modal = false; if (options.positionY !== 'top') {
dialogOptions.entryAnimation = options.entryAnimation; pos.top += (pos.height || 0) / 2;
dialogOptions.exitAnimation = options.exitAnimation; }
dialogOptions.entryAnimationDuration = options.entryAnimationDuration || 140;
dialogOptions.exitAnimationDuration = options.exitAnimationDuration || 100; pos.left += (pos.width || 0) / 2;
dialogOptions.autoFocus = false;
const height = dlg.offsetHeight || 300;
const width = dlg.offsetWidth || 160;
// Account for popup size
pos.top -= height / 2;
pos.left -= width / 2;
// Avoid showing too close to the bottom
const overflowX = pos.left + width - windowWidth;
const overflowY = pos.top + height - windowHeight;
if (overflowX > 0) {
pos.left -= (overflowX + 20);
}
if (overflowY > 0) {
pos.top -= (overflowY + 20);
}
pos.top += (options.offsetTop || 0);
pos.left += (options.offsetLeft || 0);
// Do some boundary checking
pos.top = Math.max(pos.top, 10);
pos.left = Math.max(pos.left, 10);
return pos;
}
function centerFocus(elem, horiz, on) {
require(['scrollHelper'], function (scrollHelper) {
const fn = on ? 'on' : 'off';
scrollHelper.centerFocus[fn](elem, horiz);
});
}
export function show(options) {
// items
// positionTo
// showCancel
// title
let dialogOptions = {
removeOnClose: true,
enableHistory: options.enableHistory,
scrollY: false
};
let isFullscreen;
if (layoutManager.tv) {
dialogOptions.size = 'fullscreen';
isFullscreen = true;
dialogOptions.autoFocus = true;
} else {
dialogOptions.modal = false;
dialogOptions.entryAnimation = options.entryAnimation;
dialogOptions.exitAnimation = options.exitAnimation;
dialogOptions.entryAnimationDuration = options.entryAnimationDuration || 140;
dialogOptions.exitAnimationDuration = options.exitAnimationDuration || 100;
dialogOptions.autoFocus = false;
}
let dlg = dialogHelper.createDialog(dialogOptions);
if (isFullscreen) {
dlg.classList.add('actionsheet-fullscreen');
} else {
dlg.classList.add('actionsheet-not-fullscreen');
}
dlg.classList.add('actionSheet');
if (options.dialogClass) {
dlg.classList.add(options.dialogClass);
}
let html = '';
const scrollClassName = layoutManager.tv ? 'scrollY smoothScrollY hiddenScrollY' : 'scrollY';
let style = '';
// Admittedly a hack but right now the scrollbar is being factored into the width which is causing truncation
if (options.items.length > 20) {
const minWidth = dom.getWindowSize().innerWidth >= 300 ? 240 : 200;
style += 'min-width:' + minWidth + 'px;';
}
let renderIcon = false;
let icons = [];
let itemIcon;
for (let item of options.items) {
itemIcon = item.icon || (item.selected ? 'check' : null);
if (itemIcon) {
renderIcon = true;
}
icons.push(itemIcon || '');
}
if (layoutManager.tv) {
html += '<button is="paper-icon-button-light" class="btnCloseActionSheet hide-mouse-idle-tv" tabindex="-1"><span class="material-icons arrow_back"></span></button>';
}
// If any items have an icon, give them all an icon just to make sure they're all lined up evenly
const center = options.title && (!renderIcon /*|| itemsWithIcons.length != options.items.length*/);
if (center || layoutManager.tv) {
html += '<div class="actionSheetContent actionSheetContent-centered">';
} else {
html += '<div class="actionSheetContent">';
}
if (options.title) {
html += '<h1 class="actionSheetTitle">' + options.title + '</h1>';
}
if (options.text) {
html += '<p class="actionSheetText">' + options.text + '</p>';
}
let scrollerClassName = 'actionSheetScroller';
if (layoutManager.tv) {
scrollerClassName += ' actionSheetScroller-tv focuscontainer-x focuscontainer-y';
}
html += '<div class="' + scrollerClassName + ' ' + scrollClassName + '" style="' + style + '">';
let menuItemClass = 'listItem listItem-button actionSheetMenuItem';
if (options.border || options.shaded) {
menuItemClass += ' listItem-border';
}
if (options.menuItemClass) {
menuItemClass += ' ' + options.menuItemClass;
}
if (layoutManager.tv) {
menuItemClass += ' listItem-focusscale';
}
if (layoutManager.mobile) {
menuItemClass += ' actionsheet-xlargeFont';
}
for (let [i, item] of options.items.entries()) {
if (item.divider) {
html += '<div class="actionsheetDivider"></div>';
continue;
} }
var dlg = dialogHelper.createDialog(dialogOptions); const autoFocus = item.selected && layoutManager.tv ? ' autoFocus' : '';
if (isFullscreen) { // Check for null in case int 0 was passed in
dlg.classList.add('actionsheet-fullscreen'); const optionId = item.id == null || item.id === '' ? item.value : item.id;
} else { html += '<button' + autoFocus + ' is="emby-button" type="button" class="' + menuItemClass + '" data-id="' + optionId + '">';
dlg.classList.add('actionsheet-not-fullscreen');
itemIcon = icons[i];
if (itemIcon) {
html += '<span class="actionsheetMenuItemIcon listItemIcon listItemIcon-transparent material-icons ' + itemIcon + '"></span>';
} else if (renderIcon && !center) {
html += '<span class="actionsheetMenuItemIcon listItemIcon listItemIcon-transparent material-icons check" style="visibility:hidden;"></span>';
} }
dlg.classList.add('actionSheet'); html += '<div class="listItemBody actionsheetListItemBody">';
if (options.dialogClass) { html += '<div class="listItemBodyText actionSheetItemText">';
dlg.classList.add(options.dialogClass); html += (item.name || item.textContent || item.innerText);
}
var html = '';
var scrollClassName = layoutManager.tv ? 'scrollY smoothScrollY hiddenScrollY' : 'scrollY';
var style = '';
// Admittedly a hack but right now the scrollbar is being factored into the width which is causing truncation
if (options.items.length > 20) {
var minWidth = dom.getWindowSize().innerWidth >= 300 ? 240 : 200;
style += 'min-width:' + minWidth + 'px;';
}
var i;
var length;
var option;
var renderIcon = false;
var icons = [];
var itemIcon;
for (i = 0, length = options.items.length; i < length; i++) {
option = options.items[i];
itemIcon = option.icon || (option.selected ? 'check' : null);
if (itemIcon) {
renderIcon = true;
}
icons.push(itemIcon || '');
}
if (layoutManager.tv) {
html += '<button is="paper-icon-button-light" class="btnCloseActionSheet hide-mouse-idle-tv" tabindex="-1"><span class="material-icons arrow_back"></span></button>';
}
// If any items have an icon, give them all an icon just to make sure they're all lined up evenly
var center = options.title && (!renderIcon /*|| itemsWithIcons.length != options.items.length*/);
if (center || layoutManager.tv) {
html += '<div class="actionSheetContent actionSheetContent-centered">';
} else {
html += '<div class="actionSheetContent">';
}
if (options.title) {
html += '<h1 class="actionSheetTitle">';
html += options.title;
html += '</h1>';
}
if (options.text) {
html += '<p class="actionSheetText">';
html += options.text;
html += '</p>';
}
var scrollerClassName = 'actionSheetScroller';
if (layoutManager.tv) {
scrollerClassName += ' actionSheetScroller-tv focuscontainer-x focuscontainer-y';
}
html += '<div class="' + scrollerClassName + ' ' + scrollClassName + '" style="' + style + '">';
var menuItemClass = 'listItem listItem-button actionSheetMenuItem';
if (options.border || options.shaded) {
menuItemClass += ' listItem-border';
}
if (options.menuItemClass) {
menuItemClass += ' ' + options.menuItemClass;
}
if (layoutManager.tv) {
menuItemClass += ' listItem-focusscale';
}
if (layoutManager.mobile) {
menuItemClass += ' actionsheet-xlargeFont';
}
for (i = 0, length = options.items.length; i < length; i++) {
option = options.items[i];
if (option.divider) {
html += '<div class="actionsheetDivider"></div>';
continue;
}
var autoFocus = option.selected && layoutManager.tv ? ' autoFocus' : '';
// Check for null in case int 0 was passed in
var optionId = option.id == null || option.id === '' ? option.value : option.id;
html += '<button' + autoFocus + ' is="emby-button" type="button" class="' + menuItemClass + '" data-id="' + optionId + '">';
itemIcon = icons[i];
if (itemIcon) {
html += '<span class="actionsheetMenuItemIcon listItemIcon listItemIcon-transparent material-icons ' + itemIcon + '"></span>';
} else if (renderIcon && !center) {
html += '<span class="actionsheetMenuItemIcon listItemIcon listItemIcon-transparent material-icons check" style="visibility:hidden;"></span>';
}
html += '<div class="listItemBody actionsheetListItemBody">';
html += '<div class="listItemBodyText actionSheetItemText">';
html += (option.name || option.textContent || option.innerText);
html += '</div>';
if (option.secondaryText) {
html += '<div class="listItemBodyText secondary">';
html += option.secondaryText;
html += '</div>';
}
html += '</div>';
if (option.asideText) {
html += '<div class="listItemAside actionSheetItemAsideText">';
html += option.asideText;
html += '</div>';
}
html += '</button>';
}
if (options.showCancel) {
html += '<div class="buttons">';
html += '<button is="emby-button" type="button" class="btnCloseActionSheet">' + globalize.translate('ButtonCancel') + '</button>';
html += '</div>';
}
html += '</div>'; html += '</div>';
dlg.innerHTML = html; if (item.secondaryText) {
html += '<div class="listItemBodyText secondary">' + item.secondaryText + '</div>';
if (layoutManager.tv) {
centerFocus(dlg.querySelector('.actionSheetScroller'), false, true);
} }
var btnCloseActionSheet = dlg.querySelector('.btnCloseActionSheet'); html += '</div>';
if (btnCloseActionSheet) {
dlg.querySelector('.btnCloseActionSheet').addEventListener('click', function () { if (item.asideText) {
dialogHelper.close(dlg); html += '<div class="listItemAside actionSheetItemAsideText">' + item.asideText + '</div>';
});
} }
// Seeing an issue in some non-chrome browsers where this is requiring a double click html += '</button>';
//var eventName = browser.firefox ? 'mousedown' : 'click'; }
var selectedId;
var timeout; if (options.showCancel) {
if (options.timeout) { html += '<div class="buttons">';
timeout = setTimeout(function () { html += '<button is="emby-button" type="button" class="btnCloseActionSheet">' + globalize.translate('ButtonCancel') + '</button>';
dialogHelper.close(dlg); html += '</div>';
}, options.timeout); }
} html += '</div>';
return new Promise(function (resolve, reject) { dlg.innerHTML = html;
var isResolved; if (layoutManager.tv) {
centerFocus(dlg.querySelector('.actionSheetScroller'), false, true);
}
dlg.addEventListener('click', function (e) { let btnCloseActionSheet = dlg.querySelector('.btnCloseActionSheet');
if (btnCloseActionSheet) {
btnCloseActionSheet.addEventListener('click', function () {
dialogHelper.close(dlg);
});
}
var actionSheetMenuItem = dom.parentWithClass(e.target, 'actionSheetMenuItem'); // Seeing an issue in some non-chrome browsers where this is requiring a double click
//var eventName = browser.firefox ? 'mousedown' : 'click';
let selectedId;
if (actionSheetMenuItem) { let timeout;
selectedId = actionSheetMenuItem.getAttribute('data-id'); if (options.timeout) {
timeout = setTimeout(function () {
dialogHelper.close(dlg);
}, options.timeout);
}
if (options.resolveOnClick) { return new Promise(function (resolve, reject) {
if (options.resolveOnClick.indexOf) { let isResolved;
if (options.resolveOnClick.indexOf(selectedId) !== -1) { dlg.addEventListener('click', function (e) {
resolve(selectedId); const actionSheetMenuItem = dom.parentWithClass(e.target, 'actionSheetMenuItem');
isResolved = true;
} if (actionSheetMenuItem) {
selectedId = actionSheetMenuItem.getAttribute('data-id');
if (options.resolveOnClick) {
if (options.resolveOnClick.indexOf) {
if (options.resolveOnClick.indexOf(selectedId) !== -1) {
} else {
resolve(selectedId); resolve(selectedId);
isResolved = true; isResolved = true;
} }
}
dialogHelper.close(dlg);
}
});
dlg.addEventListener('close', function () {
if (layoutManager.tv) {
centerFocus(dlg.querySelector('.actionSheetScroller'), false, false);
}
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
if (!isResolved) {
if (selectedId != null) {
if (options.callback) {
options.callback(selectedId);
}
resolve(selectedId);
} else { } else {
reject(); resolve(selectedId);
isResolved = true;
} }
} }
});
dialogHelper.open(dlg); dialogHelper.close(dlg);
}
var pos = options.positionTo && dialogOptions.size !== 'fullscreen' ? getPosition(options, dlg) : null; });
if (pos) { dlg.addEventListener('close', function () {
dlg.style.position = 'fixed';
dlg.style.margin = 0; if (layoutManager.tv) {
dlg.style.left = pos.left + 'px'; centerFocus(dlg.querySelector('.actionSheetScroller'), false, false);
dlg.style.top = pos.top + 'px'; }
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
if (!isResolved) {
if (selectedId != null) {
if (options.callback) {
options.callback(selectedId);
}
resolve(selectedId);
} else {
reject();
}
} }
}); });
}
return { dialogHelper.open(dlg);
show: show
}; const pos = options.positionTo && dialogOptions.size !== 'fullscreen' ? getPosition(options, dlg) : null;
});
if (pos) {
dlg.style.position = 'fixed';
dlg.style.margin = 0;
dlg.style.left = pos.left + 'px';
dlg.style.top = pos.top + 'px';
}
});
}
export default {
show: show
};

View file

@ -359,7 +359,6 @@ define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'g
return -1 !== supportedFeatures.indexOf(command.toLowerCase()); return -1 !== supportedFeatures.indexOf(command.toLowerCase());
}, },
preferVisualCards: browser.android || browser.chrome, preferVisualCards: browser.android || browser.chrome,
moreIcon: browser.android ? 'more_vert' : 'more_horiz',
getSyncProfile: getSyncProfile, getSyncProfile: getSyncProfile,
getDefaultLayout: function () { getDefaultLayout: function () {
if (window.NativeShell) { if (window.NativeShell) {

View file

@ -869,7 +869,7 @@ import 'programStyles';
if (isOuterFooter && options.cardLayout && layoutManager.mobile) { if (isOuterFooter && options.cardLayout && layoutManager.mobile) {
if (options.cardFooterAside !== 'none') { if (options.cardFooterAside !== 'none') {
html += '<button is="paper-icon-button-light" class="itemAction btnCardOptions cardText-secondary" data-action="menu"><span class="material-icons more_horiz"></span></button>'; html += '<button is="paper-icon-button-light" class="itemAction btnCardOptions cardText-secondary" data-action="menu"><span class="material-icons more_vert"></span></button>';
} }
} }
@ -1426,7 +1426,7 @@ import 'programStyles';
} }
if (options.overlayMoreButton) { if (options.overlayMoreButton) {
overlayButtons += '<button is="paper-icon-button-light" class="' + btnCssClass + '" data-action="menu"><span class="material-icons cardOverlayButtonIcon more_horiz"></span></button>'; overlayButtons += '<button is="paper-icon-button-light" class="' + btnCssClass + '" data-action="menu"><span class="material-icons cardOverlayButtonIcon more_vert"></span></button>';
} }
} }
@ -1580,7 +1580,7 @@ import 'programStyles';
html += '<button is="emby-ratingbutton" type="button" data-action="none" class="' + btnCssClass + '" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-itemtype="' + item.Type + '" data-likes="' + likes + '" data-isfavorite="' + (userData.IsFavorite) + '"><span class="material-icons cardOverlayButtonIcon cardOverlayButtonIcon-hover favorite"></span></button>'; html += '<button is="emby-ratingbutton" type="button" data-action="none" class="' + btnCssClass + '" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-itemtype="' + item.Type + '" data-likes="' + likes + '" data-isfavorite="' + (userData.IsFavorite) + '"><span class="material-icons cardOverlayButtonIcon cardOverlayButtonIcon-hover favorite"></span></button>';
} }
html += '<button is="paper-icon-button-light" class="' + btnCssClass + '" data-action="menu"><span class="material-icons cardOverlayButtonIcon cardOverlayButtonIcon-hover more_horiz"></span></button>'; html += '<button is="paper-icon-button-light" class="' + btnCssClass + '" data-action="menu"><span class="material-icons cardOverlayButtonIcon cardOverlayButtonIcon-hover more_vert"></span></button>';
html += '</div>'; html += '</div>';
html += '</div>'; html += '</div>';

View file

@ -1,57 +1,54 @@
define(['connectionManager', 'confirm', 'appRouter', 'globalize'], function (connectionManager, confirm, appRouter, globalize) { import connectionManager from 'connectionManager';
'use strict'; import confirm from 'confirm';
import appRouter from 'appRouter';
import globalize from 'globalize';
function alertText(options) { function alertText(options) {
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
require(['alert'], function (alert) { require(['alert'], function (alert) {
alert(options).then(resolve, resolve); alert(options).then(resolve, resolve);
});
}); });
} });
}
function deleteItem(options) { export function deleteItem(options) {
var item = options.item; const item = options.item;
var itemId = item.Id; const parentId = item.SeasonId || item.SeriesId || item.ParentId;
var parentId = item.SeasonId || item.SeriesId || item.ParentId;
var serverId = item.ServerId;
var msg = globalize.translate('ConfirmDeleteItem'); let apiClient = connectionManager.getApiClient(item.ServerId);
var title = globalize.translate('HeaderDeleteItem');
var apiClient = connectionManager.getApiClient(item.ServerId);
return confirm({ return confirm({
title: title, title: globalize.translate('HeaderDeleteItem'),
text: msg, text: globalize.translate('ConfirmDeleteItem'),
confirmText: globalize.translate('Delete'), confirmText: globalize.translate('Delete'),
primary: 'delete' primary: 'delete'
}).then(function () { }).then(function () {
return apiClient.deleteItem(itemId).then(function () { return apiClient.deleteItem(item.Id).then(function () {
if (options.navigate) { if (options.navigate) {
if (parentId) { if (parentId) {
appRouter.showItem(parentId, serverId); appRouter.showItem(parentId, item.ServerId);
} else { } else {
appRouter.goHome(); appRouter.goHome();
}
} }
}, function (err) { }
}, function (err) {
var result = function () { let result = function () {
return Promise.reject(err); return Promise.reject(err);
}; };
return alertText(globalize.translate('ErrorDeletingItem')).then(result, result); return alertText(globalize.translate('ErrorDeletingItem')).then(result, result);
});
}); });
} });
}
return { export default {
deleteItem: deleteItem deleteItem: deleteItem
}; };
});

View file

@ -10,7 +10,7 @@
<div class="guide-headerTimeslots"> <div class="guide-headerTimeslots">
<div class="guide-channelTimeslotHeader"> <div class="guide-channelTimeslotHeader">
<button is="paper-icon-button-light" type="button" class="btnGuideViewSettings" title="${ButtonMore}"> <button is="paper-icon-button-light" type="button" class="btnGuideViewSettings" title="${ButtonMore}">
<span class="material-icons btnGuideViewSettingsIcon more_horiz" aria-hidden="true"></span> <span class="material-icons btnGuideViewSettingsIcon more_vert" aria-hidden="true"></span>
</button> </button>
</div> </div>
<div class="timeslotHeaders scrollX guideScroller"></div> <div class="timeslotHeaders scrollX guideScroller"></div>

View file

@ -136,7 +136,10 @@ define(['events', 'browser', 'require', 'apphost', 'appSettings', 'htmlMediaHelp
requireHlsPlayer(function () { requireHlsPlayer(function () {
var hls = new Hls({ var hls = new Hls({
manifestLoadingTimeOut: 20000 manifestLoadingTimeOut: 20000,
xhrSetup: function(xhr, url) {
xhr.withCredentials = true;
}
//appendErrorMaxRetry: 6, //appendErrorMaxRetry: 6,
//debug: true //debug: true
}); });
@ -155,6 +158,9 @@ define(['events', 'browser', 'require', 'apphost', 'appSettings', 'htmlMediaHelp
elem.autoplay = true; elem.autoplay = true;
// Safari will not send cookies without this
elem.crossOrigin = 'use-credentials';
return htmlMediaHelper.applySrc(elem, val, options).then(function () { return htmlMediaHelper.applySrc(elem, val, options).then(function () {
self._currentSrc = val; self._currentSrc = val;

View file

@ -338,7 +338,10 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
requireHlsPlayer(function () { requireHlsPlayer(function () {
var hls = new Hls({ var hls = new Hls({
manifestLoadingTimeOut: 20000 manifestLoadingTimeOut: 20000,
xhrSetup: function(xhr, xhr_url) {
xhr.withCredentials = true;
}
//appendErrorMaxRetry: 6, //appendErrorMaxRetry: 6,
//debug: true //debug: true
}); });
@ -559,6 +562,9 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
elem.autoplay = true; elem.autoplay = true;
// Safari will not send cookies without this
elem.crossOrigin = 'use-credentials';
return htmlMediaHelper.applySrc(elem, val, options).then(function () { return htmlMediaHelper.applySrc(elem, val, options).then(function () {
self._currentSrc = val; self._currentSrc = val;

View file

@ -1,198 +1,183 @@
define(['datetime', 'itemHelper', 'emby-progressbar', 'css!./indicators.css', 'material-icons'], function (datetime, itemHelper) { import datetime from 'datetime';
'use strict'; import itemHelper from 'itemHelper';
import 'emby-progressbar';
import 'css!./indicators.css';
import 'material-icons';
function enableProgressIndicator(item) { export function enableProgressIndicator(item) {
if (item.MediaType === 'Video') { if (item.MediaType === 'Video' && item.Type !== 'TvChannel') {
if (item.Type !== 'TvChannel') { return true;
return true;
}
}
if (item.Type === 'AudioBook' || item.Type === 'AudioPodcast') {
return true;
}
return false;
} }
function getProgressHtml(pct, options) { if (item.Type === 'AudioBook' || item.Type === 'AudioPodcast') {
var containerClass = 'itemProgressBar'; return true;
if (options) {
if (options.containerClass) {
containerClass += ' ' + options.containerClass;
}
}
return '<div class="' + containerClass + '"><div class="itemProgressBarForeground" style="width:' + pct + '%;"></div></div>';
} }
function getAutoTimeProgressHtml(pct, options, isRecording, start, end) { return false;
var containerClass = 'itemProgressBar'; }
if (options) {
if (options.containerClass) {
containerClass += ' ' + options.containerClass;
}
}
var foregroundClass = 'itemProgressBarForeground'; export function getProgressHtml(pct, options) {
if (isRecording) { let containerClass = 'itemProgressBar';
foregroundClass += ' itemProgressBarForeground-recording'; if (options && options.containerClass) {
} containerClass += ' ' + options.containerClass;
return '<div is="emby-progressbar" data-automode="time" data-starttime="' + start + '" data-endtime="' + end + '" class="' + containerClass + '"><div class="' + foregroundClass + '" style="width:' + pct + '%;"></div></div>';
} }
function getProgressBarHtml(item, options) { return '<div class="' + containerClass + '"><div class="itemProgressBarForeground" style="width:' + pct + '%;"></div></div>';
var pct; }
if (enableProgressIndicator(item) && item.Type !== 'Recording') {
var userData = options ? (options.userData || item.UserData) : item.UserData; function getAutoTimeProgressHtml(pct, options, isRecording, start, end) {
if (userData) { let containerClass = 'itemProgressBar';
pct = userData.PlayedPercentage; if (options && options.containerClass) {
if (pct && pct < 100) { containerClass += ' ' + options.containerClass;
return getProgressHtml(pct, options); }
}
let foregroundClass = 'itemProgressBarForeground';
if (isRecording) {
foregroundClass += ' itemProgressBarForeground-recording';
}
return '<div is="emby-progressbar" data-automode="time" data-starttime="' + start + '" data-endtime="' + end + '" class="' + containerClass + '"><div class="' + foregroundClass + '" style="width:' + pct + '%;"></div></div>';
}
export function getProgressBarHtml(item, options) {
let pct;
if (enableProgressIndicator(item) && item.Type !== 'Recording') {
const userData = options && options.userData ? options.userData : item.UserData;
if (userData) {
pct = userData.PlayedPercentage;
if (pct && pct < 100) {
return getProgressHtml(pct, options);
} }
} }
}
if ((item.Type === 'Program' || item.Type === 'Timer' || item.Type === 'Recording') && item.StartDate && item.EndDate) { if ((item.Type === 'Program' || item.Type === 'Timer' || item.Type === 'Recording') && item.StartDate && item.EndDate) {
var startDate = 0; let startDate = 0;
var endDate = 1; let endDate = 1;
try {
startDate = datetime.parseISO8601Date(item.StartDate).getTime();
endDate = datetime.parseISO8601Date(item.EndDate).getTime();
} catch (err) {
console.error(err);
}
const now = new Date().getTime();
const total = endDate - startDate;
pct = 100 * ((now - startDate) / total);
if (pct > 0 && pct < 100) {
const isRecording = item.Type === 'Timer' || item.Type === 'Recording' || item.TimerId;
return getAutoTimeProgressHtml(pct, options, isRecording, startDate, endDate);
}
}
return '';
}
export function enablePlayedIndicator(item) {
return itemHelper.canMarkPlayed(item);
}
export function getPlayedIndicatorHtml(item) {
if (enablePlayedIndicator(item)) {
let userData = item.UserData || {};
if (userData.UnplayedItemCount) {
return '<div class="countIndicator indicator">' + userData.UnplayedItemCount + '</div>';
}
if (userData.PlayedPercentage && userData.PlayedPercentage >= 100 || (userData.Played)) {
return '<div class="playedIndicator indicator"><span class="material-icons indicatorIcon check"></span></div>';
}
}
return '';
}
export function getChildCountIndicatorHtml(item, options) {
const minCount = options && options.minCount ? options.minCount : 0;
if (item.ChildCount && item.ChildCount > minCount) {
return '<div class="countIndicator indicator">' + item.ChildCount + '</div>';
}
return '';
}
export function getTimerIndicator(item) {
let status;
if (item.Type === 'SeriesTimer') {
return '<span class="material-icons timerIndicator indicatorIcon fiber_smart_record"></span>';
} else if (item.TimerId || item.SeriesTimerId) {
status = item.Status || 'Cancelled';
} else if (item.Type === 'Timer') {
status = item.Status;
} else {
return '';
}
if (item.SeriesTimerId) {
if (status !== 'Cancelled') {
return '<span class="material-icons timerIndicator indicatorIcon fiber_smart_record"></span>';
}
return '<span class="material-icons timerIndicator timerIndicator-inactive indicatorIcon fiber_smart_record"></span>';
}
return '<span class="material-icons timerIndicator indicatorIcon fiber_manual_record"></span>';
}
export function getSyncIndicator(item) {
if (item.SyncPercent === 100) {
return '<div class="syncIndicator indicator fullSyncIndicator"><span class="material-icons indicatorIcon file_download"></span></div>';
} else if (item.SyncPercent != null) {
return '<div class="syncIndicator indicator emptySyncIndicator"><span class="material-icons indicatorIcon file_download"></span></div>';
}
return '';
}
export function getTypeIndicator(item) {
const iconT = {
'Video' : 'videocam',
'Folder' : 'folder',
'PhotoAlbum' : 'photo_album',
'Photo' : 'photo'
};
const icon = iconT[item.Type];
return icon ? '<div class="indicator videoIndicator"><span class="material-icons indicatorIcon '+ icon +'"></span></div>' : '';
}
export function getMissingIndicator(item) {
if (item.Type === 'Episode' && item.LocationType === 'Virtual') {
if (item.PremiereDate) {
try { try {
startDate = datetime.parseISO8601Date(item.StartDate).getTime(); const premiereDate = datetime.parseISO8601Date(item.PremiereDate).getTime();
endDate = datetime.parseISO8601Date(item.EndDate).getTime(); if (premiereDate > new Date().getTime()) {
return '<div class="unairedIndicator">Unaired</div>';
}
} catch (err) { } catch (err) {
console.error(err); console.error(err);
} }
var now = new Date().getTime();
var total = endDate - startDate;
pct = 100 * ((now - startDate) / total);
if (pct > 0 && pct < 100) {
var isRecording = item.Type === 'Timer' || item.Type === 'Recording' || item.TimerId;
return getAutoTimeProgressHtml(pct, options, isRecording, startDate, endDate);
}
} }
return '<div class="missingIndicator">Missing</div>';
return '';
} }
function enablePlayedIndicator(item) { return '';
return itemHelper.canMarkPlayed(item); }
}
function getPlayedIndicator(item) { export default {
if (enablePlayedIndicator(item)) { getProgressHtml: getProgressHtml,
var userData = item.UserData || {}; getProgressBarHtml: getProgressBarHtml,
if (userData.UnplayedItemCount) { getPlayedIndicatorHtml: getPlayedIndicatorHtml,
return '<div class="countIndicator indicator">' + userData.UnplayedItemCount + '</div>'; getChildCountIndicatorHtml: getChildCountIndicatorHtml,
} enableProgressIndicator: enableProgressIndicator,
getTimerIndicator: getTimerIndicator,
if (userData.PlayedPercentage && userData.PlayedPercentage >= 100 || (userData.Played)) { enablePlayedIndicator: enablePlayedIndicator,
return '<div class="playedIndicator indicator"><span class="material-icons indicatorIcon check"></span></div>'; getSyncIndicator: getSyncIndicator,
} getTypeIndicator: getTypeIndicator,
} getMissingIndicator: getMissingIndicator
};
return '';
}
function getCountIndicatorHtml(count) {
return '<div class="countIndicator indicator">' + count + '</div>';
}
function getChildCountIndicatorHtml(item, options) {
var minCount = 0;
if (options) {
minCount = options.minCount || minCount;
}
if (item.ChildCount && item.ChildCount > minCount) {
return getCountIndicatorHtml(item.ChildCount);
}
return '';
}
function getTimerIndicator(item) {
var status;
if (item.Type === 'SeriesTimer') {
return '<span class="material-icons timerIndicator indicatorIcon fiber_smart_record"></span>';
} else if (item.TimerId || item.SeriesTimerId) {
status = item.Status || 'Cancelled';
} else if (item.Type === 'Timer') {
status = item.Status;
} else {
return '';
}
if (item.SeriesTimerId) {
if (status !== 'Cancelled') {
return '<span class="material-icons timerIndicator indicatorIcon fiber_smart_record"></span>';
}
return '<span class="material-icons timerIndicator timerIndicator-inactive indicatorIcon fiber_smart_record"></span>';
}
return '<span class="material-icons timerIndicator indicatorIcon fiber_manual_record"></span>';
}
function getSyncIndicator(item) {
if (item.SyncPercent === 100) {
return '<div class="syncIndicator indicator fullSyncIndicator"><span class="material-icons indicatorIcon file_download"></span></div>';
} else if (item.SyncPercent != null) {
return '<div class="syncIndicator indicator emptySyncIndicator"><span class="material-icons indicatorIcon file_download"></span></div>';
}
return '';
}
function getTypeIndicator(item) {
if (item.Type === 'Video') {
return '<div class="indicator videoIndicator"><span class="material-icons indicatorIcon videocam"></span></div>';
}
if (item.Type === 'Folder') {
return '<div class="indicator videoIndicator"><span class="material-icons indicatorIcon folder"></span></div>';
}
if (item.Type === 'PhotoAlbum') {
return '<div class="indicator videoIndicator"><span class="material-icons indicatorIcon photo_album"></span></div>';
}
if (item.Type === 'Photo') {
return '<div class="indicator videoIndicator"><span class="material-icons indicatorIcon photo"></span></div>';
}
return '';
}
function getMissingIndicator(item) {
if (item.Type === 'Episode' && item.LocationType === 'Virtual') {
if (item.PremiereDate) {
try {
var premiereDate = datetime.parseISO8601Date(item.PremiereDate).getTime();
if (premiereDate > new Date().getTime()) {
return '<div class="unairedIndicator">Unaired</div>';
}
} catch (err) {
console.error(err);
}
}
return '<div class="missingIndicator">Missing</div>';
}
return '';
}
return {
getProgressHtml: getProgressHtml,
getProgressBarHtml: getProgressBarHtml,
getPlayedIndicatorHtml: getPlayedIndicator,
getChildCountIndicatorHtml: getChildCountIndicatorHtml,
enableProgressIndicator: enableProgressIndicator,
getTimerIndicator: getTimerIndicator,
enablePlayedIndicator: enablePlayedIndicator,
getSyncIndicator: getSyncIndicator,
getTypeIndicator: getTypeIndicator,
getMissingIndicator: getMissingIndicator
};
});

View file

@ -426,7 +426,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
html += '<div class="' + cssClass + '">'; html += '<div class="' + cssClass + '">';
const moreIcon = 'more_horiz'; const moreIcon = 'more_vert';
html += getTextLinesHtml(textlines, isLargeStyle); html += getTextLinesHtml(textlines, isLargeStyle);

View file

@ -490,26 +490,26 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
if (i.IsInterlaced) { if (i.IsInterlaced) {
return '1440i'; return '1440i';
} }
return '1440P'; return '1440p';
} }
if (width >= 1800 || height >= 1000) { if (width >= 1800 || height >= 1000) {
if (i.IsInterlaced) { if (i.IsInterlaced) {
return '1080i'; return '1080i';
} }
return '1080P'; return '1080p';
} }
if (width >= 1200 || height >= 700) { if (width >= 1200 || height >= 700) {
if (i.IsInterlaced) { if (i.IsInterlaced) {
return '720i'; return '720i';
} }
return '720P'; return '720p';
} }
if (width >= 700 || height >= 400) { if (width >= 700 || height >= 400) {
if (i.IsInterlaced) { if (i.IsInterlaced) {
return '480i'; return '480i';
} }
return '480P'; return '480p';
} }
} }

View file

@ -9,7 +9,7 @@
<span>${Save}</span> <span>${Save}</span>
</button> </button>
<button is="paper-icon-button-light" class="btnMore autoSize" tabindex="-1"> <button is="paper-icon-button-light" class="btnMore autoSize" tabindex="-1">
<span class="material-icons more_horiz"></span> <span class="material-icons more_vert"></span>
</button> </button>
</div> </div>
</div> </div>

View file

@ -129,7 +129,7 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
html += '<button is="paper-icon-button-light" class="btnCloseSelectionPanel autoSize"><span class="material-icons close"></span></button>'; html += '<button is="paper-icon-button-light" class="btnCloseSelectionPanel autoSize"><span class="material-icons close"></span></button>';
html += '<h1 class="itemSelectionCount"></h1>'; html += '<h1 class="itemSelectionCount"></h1>';
const moreIcon = 'more_horiz'; const moreIcon = 'more_vert';
html += '<button is="paper-icon-button-light" class="btnSelectionPanelOptions autoSize" style="margin-left:auto;"><span class="material-icons ' + moreIcon + '"></span></button>'; html += '<button is="paper-icon-button-light" class="btnSelectionPanelOptions autoSize" style="margin-left:auto;"><span class="material-icons ' + moreIcon + '"></span></button>';
selectionCommandsPanel.innerHTML = html; selectionCommandsPanel.innerHTML = html;

View file

@ -1,75 +1,71 @@
define(['actionsheet', 'datetime', 'playbackManager', 'globalize', 'appSettings'], function (actionsheet, datetime, playbackManager, globalize, appSettings) { import actionsheet from 'actionsheet';
'use strict'; import datetime from 'datetime';
import playbackManager from 'playbackManager';
import globalize from 'globalize';
function show(options) { export function show(options) {
var item = options.item; var item = options.item;
var itemType = item.Type; var resumePositionTicks = item.UserData ? item.UserData.PlaybackPositionTicks : null;
var isFolder = item.IsFolder;
var itemId = item.Id;
var channelId = item.ChannelId;
var serverId = item.ServerId;
var resumePositionTicks = item.UserData ? item.UserData.PlaybackPositionTicks : null;
var playableItemId = itemType === 'Program' ? channelId : itemId; var playableItemId = item.Type === 'Program' ? item.ChannelId : item.Id;
if (!resumePositionTicks || isFolder) { if (!resumePositionTicks || item.IsFolder) {
playbackManager.play({ playbackManager.play({
ids: [playableItemId], ids: [playableItemId],
serverId: serverId serverId: item.ServerId
});
return;
}
var menuItems = [];
menuItems.push({
name: globalize.translate('ResumeAt', datetime.getDisplayRunningTime(resumePositionTicks)),
id: 'resume'
});
menuItems.push({
name: globalize.translate('PlayFromBeginning'),
id: 'play'
});
actionsheet.show({
items: menuItems,
positionTo: options.positionTo
}).then(function (id) {
switch (id) {
case 'play':
playbackManager.play({
ids: [playableItemId],
serverId: serverId
});
break;
case 'resume':
playbackManager.play({
ids: [playableItemId],
startPositionTicks: resumePositionTicks,
serverId: serverId
});
break;
case 'queue':
playbackManager.queue({
items: [item]
});
break;
case 'shuffle':
playbackManager.shuffle(item);
break;
default:
break;
}
}); });
return;
} }
return { var menuItems = [];
show: show
}; menuItems.push({
}); name: globalize.translate('ResumeAt', datetime.getDisplayRunningTime(resumePositionTicks)),
id: 'resume'
});
menuItems.push({
name: globalize.translate('PlayFromBeginning'),
id: 'play'
});
actionsheet.show({
items: menuItems,
positionTo: options.positionTo
}).then(function (id) {
switch (id) {
case 'play':
playbackManager.play({
ids: [playableItemId],
serverId: item.ServerId
});
break;
case 'resume':
playbackManager.play({
ids: [playableItemId],
startPositionTicks: resumePositionTicks,
serverId: item.ServerId
});
break;
case 'queue':
playbackManager.queue({
items: [item]
});
break;
case 'shuffle':
playbackManager.shuffle(item);
break;
default:
break;
}
});
}
export default {
show: show
};

View file

@ -89,7 +89,7 @@ define(['loading', 'dom', 'libraryMenu', 'globalize', 'scripts/imagehelper', 'da
if (canEdit || canDelete(device.Id)) { if (canEdit || canDelete(device.Id)) {
deviceHtml += '<div style="text-align:right; float:right;padding-top:5px;">'; deviceHtml += '<div style="text-align:right; float:right;padding-top:5px;">';
deviceHtml += '<button type="button" is="paper-icon-button-light" data-id="' + device.Id + '" title="' + globalize.translate('Menu') + '" class="btnDeviceMenu"><span class="material-icons more_horiz"></span></button>'; deviceHtml += '<button type="button" is="paper-icon-button-light" data-id="' + device.Id + '" title="' + globalize.translate('Menu') + '" class="btnDeviceMenu"><span class="material-icons more_vert"></span></button>';
deviceHtml += '</div>'; deviceHtml += '</div>';
} }

View file

@ -298,7 +298,7 @@ define(['jQuery', 'apphost', 'scripts/taskbutton', 'loading', 'libraryMenu', 'gl
if (virtualFolder.showMenu !== false) { if (virtualFolder.showMenu !== false) {
html += '<div style="text-align:right; float:right;padding-top:5px;">'; html += '<div style="text-align:right; float:right;padding-top:5px;">';
html += '<button type="button" is="paper-icon-button-light" class="btnCardMenu autoSize"><span class="material-icons more_horiz"></span></button>'; html += '<button type="button" is="paper-icon-button-light" class="btnCardMenu autoSize"><span class="material-icons more_vert"></span></button>';
html += '</div>'; html += '</div>';
} }

View file

@ -47,7 +47,7 @@ define(['loading', 'libraryMenu', 'dom', 'globalize', 'cardStyle', 'emby-button'
html += '</div>'; html += '</div>';
html += '<div class="cardFooter">'; html += '<div class="cardFooter">';
html += '<div style="text-align:right; float:right;padding-top:5px;">'; html += '<div style="text-align:right; float:right;padding-top:5px;">';
html += '<button type="button" is="paper-icon-button-light" class="btnCardMenu autoSize"><span class="material-icons more_horiz"></span></button>'; html += '<button type="button" is="paper-icon-button-light" class="btnCardMenu autoSize"><span class="material-icons more_vert"></span></button>';
html += '</div>'; html += '</div>';
html += "<div class='cardText'>"; html += "<div class='cardText'>";
html += configPage.DisplayName || plugin.Name; html += configPage.DisplayName || plugin.Name;

View file

@ -30,7 +30,7 @@ define(['jQuery', 'globalize', 'scripts/taskbutton', 'dom', 'libraryMenu', 'layo
html += '</div>'; html += '</div>';
html += '</div>'; html += '</div>';
html += '<div class="cardFooter visualCardBox-cardFooter">'; html += '<div class="cardFooter visualCardBox-cardFooter">';
html += '<button is="paper-icon-button-light" class="itemAction btnCardOptions autoSize" data-action="menu"><span class="material-icons more_horiz"></span></button>'; html += '<button is="paper-icon-button-light" class="itemAction btnCardOptions autoSize" data-action="menu"><span class="material-icons more_vert"></span></button>';
html += '<div class="cardText">' + (device.FriendlyName || getTunerName(device.Type)) + '</div>'; html += '<div class="cardText">' + (device.FriendlyName || getTunerName(device.Type)) + '</div>';
html += '<div class="cardText cardText-secondary">'; html += '<div class="cardText cardText-secondary">';
html += device.Url || '&nbsp;'; html += device.Url || '&nbsp;';
@ -112,7 +112,7 @@ define(['jQuery', 'globalize', 'scripts/taskbutton', 'dom', 'libraryMenu', 'layo
html += '</div>'; html += '</div>';
html += '</a>'; html += '</a>';
html += '</div>'; html += '</div>';
html += '<button type="button" is="paper-icon-button-light" class="btnOptions" data-id="' + provider.Id + '"><span class="material-icons listItemAside more_horiz"></span></button>'; html += '<button type="button" is="paper-icon-button-light" class="btnOptions" data-id="' + provider.Id + '"><span class="material-icons listItemAside more_vert"></span></button>';
html += '</div>'; html += '</div>';
} }

View file

@ -1112,6 +1112,14 @@ define(['playbackManager', 'dom', 'inputManager', 'datetime', 'itemHelper', 'med
playbackManager.playPause(currentPlayer); playbackManager.playPause(currentPlayer);
showOsd(); showOsd();
break; break;
case 'ArrowUp':
case 'Up':
playbackManager.volumeUp(currentPlayer);
break;
case 'ArrowDown':
case 'Down':
playbackManager.volumeDown(currentPlayer);
break;
case 'l': case 'l':
case 'ArrowRight': case 'ArrowRight':
case 'Right': case 'Right':
@ -1134,6 +1142,18 @@ define(['playbackManager', 'dom', 'inputManager', 'datetime', 'itemHelper', 'med
playbackManager.toggleMute(currentPlayer); playbackManager.toggleMute(currentPlayer);
showOsd(); showOsd();
break; break;
case 'p':
case 'P':
if (e.shiftKey) {
playbackManager.previousTrack(currentPlayer);
}
break;
case 'n':
case 'N':
if (e.shiftKey) {
playbackManager.nextTrack(currentPlayer);
}
break;
case 'NavigationLeft': case 'NavigationLeft':
case 'GamepadDPadLeft': case 'GamepadDPadLeft':
case 'GamepadLeftThumbstickLeft': case 'GamepadLeftThumbstickLeft':
@ -1151,6 +1171,26 @@ define(['playbackManager', 'dom', 'inputManager', 'datetime', 'itemHelper', 'med
playbackManager.fastForward(currentPlayer); playbackManager.fastForward(currentPlayer);
showOsd(); showOsd();
} }
break;
case 'Home':
playbackManager.seekPercent(0, currentPlayer);
break;
case 'End':
playbackManager.seekPercent(100, currentPlayer);
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
var percent = parseInt(key, 10) * 10;
playbackManager.seekPercent(percent, currentPlayer);
break;
} }
} }

View file

@ -115,7 +115,7 @@ define(['loading', 'dom', 'globalize', 'date-fns', 'dfnshelper', 'paper-icon-but
html += '<div class="flex-grow" style="overflow:hidden;text-overflow:ellipsis;">'; html += '<div class="flex-grow" style="overflow:hidden;text-overflow:ellipsis;">';
html += user.Name; html += user.Name;
html += '</div>'; html += '</div>';
html += '<button type="button" is="paper-icon-button-light" class="btnUserMenu flex-shrink-zero"><span class="material-icons more_horiz"></span></button>'; html += '<button type="button" is="paper-icon-button-light" class="btnUserMenu flex-shrink-zero"><span class="material-icons more_vert"></span></button>';
html += '</div>'; html += '</div>';
html += '<div class="cardText cardText-secondary">'; html += '<div class="cardText cardText-secondary">';
var lastSeen = getLastSeenText(user.LastActivityDate); var lastSeen = getLastSeenText(user.LastActivityDate);
@ -189,7 +189,7 @@ define(['loading', 'dom', 'globalize', 'date-fns', 'dfnshelper', 'paper-icon-but
html += '</div>'; html += '</div>';
html += '<div class="cardFooter visualCardBox-cardFooter">'; html += '<div class="cardFooter visualCardBox-cardFooter">';
html += '<div class="cardText" style="text-align:right; float:right;padding:0;">'; html += '<div class="cardText" style="text-align:right; float:right;padding:0;">';
html += '<button type="button" is="paper-icon-button-light" class="btnUserMenu"><span class="material-icons more_horiz"></span></button>'; html += '<button type="button" is="paper-icon-button-light" class="btnUserMenu"><span class="material-icons more_vert"></span></button>';
html += '</div>'; html += '</div>';
html += '<div class="cardText" style="padding-top:10px;padding-bottom:10px;">'; html += '<div class="cardText" style="padding-top:10px;padding-bottom:10px;">';
html += user.UserName; html += user.UserName;

View file

@ -101,7 +101,7 @@
<button is="emby-button" type="button" class="button-flat btnMoreCommands hide detailButton"> <button is="emby-button" type="button" class="button-flat btnMoreCommands hide detailButton">
<div class="detailButton-content"> <div class="detailButton-content">
<span class="material-icons detailButton-icon more_horiz"></span> <span class="material-icons detailButton-icon more_vert"></span>
<div class="detailButton-text">${ButtonMore}</div> <div class="detailButton-text">${ButtonMore}</div>
</div> </div>
</button> </button>

View file

@ -42,10 +42,10 @@
<span class="material-icons filter_list"></span> <span class="material-icons filter_list"></span>
</button> </button>
<button is="emby-button" class="btnViewSettings button-flat listTextButton-autohide"> <button is="emby-button" class="btnViewSettings button-flat listTextButton-autohide">
<span class="material-icons more_horiz"></span> <span class="material-icons more_vert"></span>
</button> </button>
<button is="paper-icon-button-light" class="btnViewSettings listIconButton-autohide"> <button is="paper-icon-button-light" class="btnViewSettings listIconButton-autohide">
<span class="material-icons more_horiz"></span> <span class="material-icons more_vert"></span>
</button> </button>
</div> </div>
<div is="emby-itemscontainer" class="vertical-wrap itemsContainer centered" style="padding: 0 0 10vh 0;"> <div is="emby-itemscontainer" class="vertical-wrap itemsContainer centered" style="padding: 0 0 10vh 0;">

View file

@ -962,7 +962,7 @@
"AllowMediaConversion": "السماح بتحويل الوسائظ", "AllowMediaConversion": "السماح بتحويل الوسائظ",
"AllLanguages": "كل اللغات", "AllLanguages": "كل اللغات",
"AllEpisodes": "كل الحلقات", "AllEpisodes": "كل الحلقات",
"AllComplexFormats": "جميع التنسيقات المعقدة (ASS ، SSA ، VOBSUB ، PGS ، SUB / IDX ، إلخ.)", "AllComplexFormats": "جميع التنسيقات المعقدة (ASS ، SSA ، VOBSUB ، PGS ، SUB / IDX ، ...)",
"AllChannels": "كل القنوات", "AllChannels": "كل القنوات",
"Albums": "ألبومات", "Albums": "ألبومات",
"Aired": "عرضت", "Aired": "عرضت",

View file

@ -55,7 +55,7 @@
"BirthLocation": "Geburtsort", "BirthLocation": "Geburtsort",
"BirthPlaceValue": "Geburtsort: {0}", "BirthPlaceValue": "Geburtsort: {0}",
"BobAndWeaveWithHelp": "Bob & Weave (höhere Qualität, aber langsamer)", "BobAndWeaveWithHelp": "Bob & Weave (höhere Qualität, aber langsamer)",
"BookLibraryHelp": "Hörbücher und E-Books werden unterstützt. Schaue in den {0}Book Naming Guide {1}.", "BookLibraryHelp": "Hörbücher und E-Books werden unterstützt. Schaue in den {0} Book Naming Guide {1}.",
"Books": "Bücher", "Books": "Bücher",
"BoxRear": "Box (Rückseite)", "BoxRear": "Box (Rückseite)",
"Browse": "Blättern", "Browse": "Blättern",

View file

@ -55,7 +55,7 @@
"BirthLocation": "Birth location", "BirthLocation": "Birth location",
"BirthPlaceValue": "Birth place: {0}", "BirthPlaceValue": "Birth place: {0}",
"Blacklist": "Blacklist", "Blacklist": "Blacklist",
"BookLibraryHelp": "Audio and text books are supported. Review the {0}book naming guide{1}.", "BookLibraryHelp": "Audio and text books are supported. Review the {0} book naming guide {1}.",
"Books": "Books", "Books": "Books",
"Box": "Box", "Box": "Box",
"BoxSet": "Box Set", "BoxSet": "Box Set",

View file

@ -61,7 +61,7 @@
"Alerts": "Alertas", "Alerts": "Alertas",
"All": "Todo", "All": "Todo",
"AllChannels": "Todos los canales", "AllChannels": "Todos los canales",
"AllComplexFormats": "Todos los formatos complejos (ASS, SSA, VOBSUB, PGS, SUB, IDX)", "AllComplexFormats": "Todos los formatos complejos (ASS, SSA, VOBSUB, PGS, SUB, IDX, ...)",
"AllEpisodes": "Todos los capítulos", "AllEpisodes": "Todos los capítulos",
"AllLanguages": "Todos los idiomas", "AllLanguages": "Todos los idiomas",
"AllLibraries": "Todas las bibliotecas", "AllLibraries": "Todas las bibliotecas",
@ -500,5 +500,45 @@
"HeaderDeleteItem": "Eliminar ítem", "HeaderDeleteItem": "Eliminar ítem",
"HeaderDeleteDevice": "Eliminar dispositivo", "HeaderDeleteDevice": "Eliminar dispositivo",
"HeaderDefaultRecordingSettings": "Ajustes de grabación por defecto", "HeaderDefaultRecordingSettings": "Ajustes de grabación por defecto",
"UnsupportedPlayback": "Jellyfin no puede descifrar contenido protegido por DRM pero a pesar de esto lo intentará con todo el contenido, incluyendo títulos protegidos. Algunos archivos pueden aparecer completamente en negro por estar cifrados o por otras características no soportadas, como títulos interactivos." "UnsupportedPlayback": "Jellyfin no puede descifrar contenido protegido por DRM pero a pesar de esto lo intentará con todo el contenido, incluyendo títulos protegidos. Algunos archivos pueden aparecer completamente en negro por estar cifrados o por otras características no soportadas, como títulos interactivos.",
"HeaderMediaFolders": "Carpetas de medios",
"HeaderMedia": "Medios",
"HeaderLoginFailure": "Error al iniciar sesión",
"HeaderLiveTvTunerSetup": "Configuración del sintonizador de TV en vivo",
"HeaderLiveTv": "TV en vivo",
"HeaderLibrarySettings": "Configuraciones de biblioteca",
"HeaderLibraryOrder": "Orden de biblioteca",
"HeaderLibraryFolders": "Carpetas de biblioteca",
"HeaderLibraryAccess": "Acceso a la biblioteca",
"HeaderLibraries": "Bibliotecas",
"HeaderLatestRecordings": "Grabaciones recientes",
"HeaderLatestMusic": "Música reciente",
"HeaderLatestMovies": "Películas recientes",
"HeaderLatestMedia": "Medios recientes",
"HeaderKeepSeries": "Mantener serie",
"HeaderKeepRecording": "Mantener grabación",
"HeaderItems": "Artículos",
"HeaderInstantMix": "Mezcla instantánea",
"HeaderInstall": "Instalar",
"HeaderImageSettings": "Configuraciones de imagen",
"HeaderImageOptions": "Opciones de imagen",
"HeaderIdentifyItemHelp": "Ingrese uno o más criterios de búsqueda. Eliminar criterios para aumentar los resultados de búsqueda.",
"HeaderIdentificationHeader": "Encabezado de identificación",
"HeaderIdentificationCriteriaHelp": "Ingrese al menos un criterio de identificación.",
"HeaderIdentification": "Identificación",
"HeaderHttpHeaders": "Encabezados HTTP",
"HeaderHome": "Inicio",
"HeaderGuideProviders": "Proveedores de datos de guías de TV",
"HeaderGenres": "Géneros",
"HeaderFrequentlyPlayed": "Reproducido con frecuencia",
"HeaderForgotPassword": "Olvidé la contraseña",
"HeaderForKids": "Para niños",
"HeaderFilters": "Filtros",
"HeaderFetcherSettings": "Configuración del recuperador",
"HeaderFetchImages": "Obtener imágenes:",
"HeaderFeatures": "Caracteristicas",
"HeaderFeatureAccess": "Acceso a características",
"HeaderFavoritePlaylists": "Listas de reproducción favoritas",
"ButtonTogglePlaylist": "Lista de reproducción",
"ButtonToggleContextMenu": "Más"
} }

View file

@ -193,5 +193,10 @@
"AllowFfmpegThrottling": "Restreindre la vitesse de transcodage", "AllowFfmpegThrottling": "Restreindre la vitesse de transcodage",
"AlbumArtist": "Artiste de l'Album", "AlbumArtist": "Artiste de l'Album",
"Album": "Album", "Album": "Album",
"AuthProviderHelp": "Sélectionner un fournisseur d'authentification pour authentifier le mot de passe de cet utilisateur." "AuthProviderHelp": "Sélectionner un fournisseur d'authentification pour authentifier le mot de passe de cet utilisateur.",
"HeaderFavoriteSongs": "Chansons favorites",
"HeaderFavoriteShows": "Séries favorites",
"HeaderFavoriteEpisodes": "Épisodes favoris",
"HeaderFavoriteArtists": "Artistes favoris",
"HeaderFavoriteAlbums": "Albums favoris"
} }

View file

@ -40,7 +40,7 @@
"BirthDateValue": "Nato il: {0}", "BirthDateValue": "Nato il: {0}",
"BirthLocation": "Luogo di nascita", "BirthLocation": "Luogo di nascita",
"BirthPlaceValue": "nato a: {0}", "BirthPlaceValue": "nato a: {0}",
"BookLibraryHelp": "Libri e audiolibri sono supportati. Rivedere {0}la guida ai nomi dei libri di Jellyfin{1}.", "BookLibraryHelp": "Libri e audiolibri sono supportati. Rivedi la guida {0} ai nomi dei libri {1} di Jellyfin.",
"Books": "Libri", "Books": "Libri",
"BoxRear": "Box (retro)", "BoxRear": "Box (retro)",
"Browse": "Esplora", "Browse": "Esplora",

View file

@ -239,7 +239,7 @@
"Kids": "Bērni", "Kids": "Bērni",
"Items": "Vienumi", "Items": "Vienumi",
"ItemCount": "{0} vienumi", "ItemCount": "{0} vienumi",
"InstallingPackage": "Instalē {0}", "InstallingPackage": "Instalē {0} (versija {1})",
"Images": "Attēli", "Images": "Attēli",
"Identify": "Identificēt", "Identify": "Identificēt",
"Horizontal": "Horizontāls", "Horizontal": "Horizontāls",
@ -455,7 +455,7 @@
"DrmChannelsNotImported": "Kanāli ar DRM netiks importēti.", "DrmChannelsNotImported": "Kanāli ar DRM netiks importēti.",
"DownloadsValue": "{0} lejupielādes", "DownloadsValue": "{0} lejupielādes",
"Download": "Lejupielādēt", "Download": "Lejupielādēt",
"DisplayModeHelp": "Izvēlies ekrāna veidu, uz kura tu izmanto Jellyfin.", "DisplayModeHelp": "Izvēlies izkārtojuma veidu, kuru tu gribi priekš šī interfeisa.",
"DoNotRecord": "Neierakstīt", "DoNotRecord": "Neierakstīt",
"DisplayInOtherHomeScreenSections": "Rādīt mājas ekrāna sadaļās kā jaunākā multvide un turpini skatīties", "DisplayInOtherHomeScreenSections": "Rādīt mājas ekrāna sadaļās kā jaunākā multvide un turpini skatīties",
"DisplayInMyMedia": "Rādīt mājas ekrānā", "DisplayInMyMedia": "Rādīt mājas ekrānā",
@ -605,8 +605,8 @@
"Art": "Māksla", "Art": "Māksla",
"AroundTime": "Ap {0}", "AroundTime": "Ap {0}",
"Anytime": "Jebkad", "Anytime": "Jebkad",
"AnyLanguage": "Jebkura valoda", "AnyLanguage": "Jebkura Valoda",
"AlwaysPlaySubtitles": "Vienmēr rādīt subtitrus", "AlwaysPlaySubtitles": "Vienmēr Rādīt",
"AllowedRemoteAddressesHelp": "Ar komatiem atdalīts IP adrešu vai IP/tīkla masku saraksts, kas norāda uz tīkliem, kas var pieslēgties attālināti. Ja atstāts tukšs, visas attālinātās adreses tiks atļautas.", "AllowedRemoteAddressesHelp": "Ar komatiem atdalīts IP adrešu vai IP/tīkla masku saraksts, kas norāda uz tīkliem, kas var pieslēgties attālināti. Ja atstāts tukšs, visas attālinātās adreses tiks atļautas.",
"AllowRemoteAccessHelp": "Ja atķeksēts, visi attālinātie savienojumi tiks bloķēti.", "AllowRemoteAccessHelp": "Ja atķeksēts, visi attālinātie savienojumi tiks bloķēti.",
"AllowRemoteAccess": "Atļaut attālinātus savienojumus šim Jellyfin Serverim.", "AllowRemoteAccess": "Atļaut attālinātus savienojumus šim Jellyfin Serverim.",
@ -615,7 +615,7 @@
"AllLibraries": "Visas bibliotēkas", "AllLibraries": "Visas bibliotēkas",
"AllLanguages": "Visas valodas", "AllLanguages": "Visas valodas",
"AllEpisodes": "Visas epizodes", "AllEpisodes": "Visas epizodes",
"AllComplexFormats": "Visi sarezģītie formāti (ASS, SSA, VOBSUB, PGS, SUB/IDX, utt.)", "AllComplexFormats": "Visi Sarežģītie formāti (ASS, SSA, VOBSUB, PGS, SUB, IDX, …)",
"AllChannels": "Visi kanāli", "AllChannels": "Visi kanāli",
"All": "Viss", "All": "Viss",
"Alerts": "Paziņojumi", "Alerts": "Paziņojumi",
@ -951,8 +951,8 @@
"HeaderCustomDlnaProfiles": "Pielāgoti Profili", "HeaderCustomDlnaProfiles": "Pielāgoti Profili",
"HeaderConfirmProfileDeletion": "Apstiprināt Profila Dzēšanu", "HeaderConfirmProfileDeletion": "Apstiprināt Profila Dzēšanu",
"HeaderChapterImages": "Nodaļu Attēli", "HeaderChapterImages": "Nodaļu Attēli",
"HeaderCastCrew": "Lomas/Apkalpe", "HeaderCastCrew": "Lomas & Apkalpe",
"HeaderCastAndCrew": "Lomas/Apkalpe", "HeaderCastAndCrew": "Lomas un Apkalpe",
"HeaderAppearsOn": "Redzams", "HeaderAppearsOn": "Redzams",
"FFmpegSavePathNotFound": "Mēs nespējām atrast FFmpeg norādītajā ceļā. FFprobe arī ir vajadzīgs, un tam ir jāatrodas tajā pašā mapē. Šīs komponentes parasti tiek apvienotas vienā un tajā pašā lejupielādē. Lūdzu pārbaudiet ceļu un mēģiniet vēlreiz.", "FFmpegSavePathNotFound": "Mēs nespējām atrast FFmpeg norādītajā ceļā. FFprobe arī ir vajadzīgs, un tam ir jāatrodas tajā pašā mapē. Šīs komponentes parasti tiek apvienotas vienā un tajā pašā lejupielādē. Lūdzu pārbaudiet ceļu un mēģiniet vēlreiz.",
"HeaderAdditionalParts": "Papildus Ceļi", "HeaderAdditionalParts": "Papildus Ceļi",
@ -1001,7 +1001,7 @@
"ButtonArrowLeft": "Kreisi", "ButtonArrowLeft": "Kreisi",
"ButtonArrowDown": "Lejup", "ButtonArrowDown": "Lejup",
"ButtonAddScheduledTaskTrigger": "Pievienot Trigeru", "ButtonAddScheduledTaskTrigger": "Pievienot Trigeru",
"BookLibraryHelp": "Audio un teksta grāmatas tiek atbalstītas. Pārskati {0}grāmatu nosaukumu instrukciju{1}.", "BookLibraryHelp": "Audio un teksta grāmatas tiek atbalstītas. Pārskati {0} grāmatu nosaukumu instrukciju {1}.",
"Blacklist": "Melnais saraksts", "Blacklist": "Melnais saraksts",
"AuthProviderHelp": "Izvēlies Autentifikācijas Nodrošinājumu, kas tiks izmantots lai autentificētu šī lietotāja paroli.", "AuthProviderHelp": "Izvēlies Autentifikācijas Nodrošinājumu, kas tiks izmantots lai autentificētu šī lietotāja paroli.",
"AspectRatio": "Attēla Proporcijas", "AspectRatio": "Attēla Proporcijas",
@ -1081,5 +1081,58 @@
"OptionAllowBrowsingLiveTv": "Atļaut Tiešraides TV piekļuvi", "OptionAllowBrowsingLiveTv": "Atļaut Tiešraides TV piekļuvi",
"MediaInfoForced": "Piespiests", "MediaInfoForced": "Piespiests",
"LabelPublicHttpPortHelp": "Publiskai porta numurs, kas tiks kartēts uz vietējo HTTP portu.", "LabelPublicHttpPortHelp": "Publiskai porta numurs, kas tiks kartēts uz vietējo HTTP portu.",
"LabelOptionalNetworkPath": "(Neobligāts) Koplietota tīkla mape:" "LabelOptionalNetworkPath": "(Neobligāts) Koplietota tīkla mape:",
"LabelLibraryPageSizeHelp": "Uzstāda vienumu daudzumu, ko rādīt bibliotēkas lapā. Uzstādi uz 0 lai atspējotu lapošanu.",
"LabelLibraryPageSize": "Bibliotēkas lapu lielums:",
"LabelKodiMetadataUserHelp": "Saglabāt skatīšanās datus uz NFO datnēm, lai tos varētu izmantot citas lietotnes.",
"LabelKodiMetadataDateFormatHelp": "Visi datumi iekš NFO datnēm tiks parsēti ar šo formātu.",
"LabelInNetworkSignInWithEasyPasswordHelp": "Izmanto vieglo pin kodu lai piekļūtu klientiem savā vietējā tīklā. Tava parastā parole būs vajadzīga ārpus mājām. Ja pin kods ir atstāts tukšs, tev nevajadzēs paroli savā vietējā mājas tīklā.",
"LabelInNetworkSignInWithEasyPassword": "Iespējot iekštīkla piekļuvi ar manu vieglo pin kodu",
"LabelImportOnlyFavoriteChannels": "Ierobežot uz kanāliem, kas atzīmēti kā favorīti",
"LabelGroupMoviesIntoCollectionsHelp": "Kad tiks rādīti filmu saraksti, filmas kas pieder pie kolekcijas tiks attēlotas kā viens grupēts vienums.",
"LabelServerNameHelp": "Šis vārds tiks izmantots lai identificētu tavu serveri un noklusējumā ir servera datora vārds.",
"LabelExtractChaptersDuringLibraryScan": "Izvilkt sadaļu attēlus bibliotēkas skenēšanas laikā",
"LabelBaseUrlHelp": "Šeit tu vari pievienot pielāgotas apakš-mapes lai piekļūtu serverim no unikālāka URL.",
"LabelBaseUrl": "Pamata URL:",
"LabelEnableSingleImageInDidlLimitHelp": "Dažas ierīces pareizi neatskaņos ja vairāki attēli ir iegulti iekš Didl.",
"LabelEnableSingleImageInDidlLimit": "Ierobežot uz vienu iegulto attēlu",
"LabelEnableDlnaClientDiscoveryIntervalHelp": "Nosaka laiku sekundēs starp Jellyfin veiktajiem SSDP meklējumiem.",
"LabelEmbedAlbumArtDidlHelp": "Dažas ierīces labprātāk izmanto šo metodi lai saņemtu albumu vākus. Citas var neatskaņot ar šo opciju ieslēgtu.",
"LabelDroppedFrames": "Nomestie kadri:",
"LabelDownMixAudioScaleHelp": "Pastiprināt audio lejupmiksēšanas laikā. Vērtība viens paturēs oriģinālo skaļumu.",
"LabelDownMixAudioScale": "Audio pastiprinājums lejupmiksējot:",
"LabelDisplayMissingEpisodesWithinSeasons": "Rādīt trūkstošās epizodes sezonās",
"LabelDateAddedBehaviorHelp": "Ja atrodas metadatu vērtība, tā vienmēr tiks izmantota pirms jebkuras no šīm opcijām.",
"LabelDashboardTheme": "Servera vadības paneļa tēma:",
"LabelCustomDeviceDisplayNameHelp": "Ievadi pielāgotu displeja vārdu vai atstāj tukšu lai izmantotu ierīces noteikto.",
"LabelCachePathHelp": "Nosaki pielāgotu atrašanās vietu priekš keša datnēm kā attēliem. Atstāj tukšu lai izmantotu servera noklusējumu.",
"LabelAllowedRemoteAddressesMode": "Attālās IP adreses filtra režīms:",
"LabelAllowedRemoteAddresses": "Attālās IP adreses filtrs:",
"LabelAlbumArtPN": "Albumu vāku PN:",
"LabelAirsBeforeSeason": "Tiešraidē pirms sezonas:",
"LabelAirsBeforeEpisode": "Tiešraidē pirms epizodes:",
"LabelAirsAfterSeason": "Tiešraidē pēc sezonas:",
"HeaderSubtitleProfilesHelp": "Subtitru profili apraksta ierīces atbalstītos subtitru formātus.",
"HeaderPendingInvitations": "Gaidošie Uzaicinājumi",
"HeaderKeepSeries": "Paturēt Sēriju",
"HeaderFavoritePlaylists": "Atskaņošanas Sarakstu Favorīti",
"ApiKeysCaption": "Saraksts ar pašlaik iespējotajām API atslēgām",
"EncoderPresetHelp": "Izvēlies ātrāku vērtību lai uzlabotu veiktspēju, vai lēnāku vērtību lai uzlabotu kvalitāti.",
"FetchingData": "Iegūst papildu datus",
"ErrorDeletingItem": "Notika kļūda dzēšot vienumu no Jellyfin Servera. Lūdzu pārliecinies vai Jellyfin Server ir rakstoša piekļuve pie satura mapes un mēģini vēlreiz.",
"ErrorAddingTunerDevice": "Kļūda pievienojot tūnera ierīci. Lūdzu pārliecinies ka tā ir pieejama un mēģini vēlreiz.",
"ErrorAddingMediaPathToVirtualFolder": "Notika kļūda pievienojot satura ceļu. Lūdzu pārliecinies ka ceļš ir derīgs un ka Jellyfin Servera procesam ir piekļuve tai vietai.",
"Episode": "Epizode",
"DeviceAccessHelp": "Tas attiecas tikai uz ierīcēm, kas var tikt unikāli identificētas un neaizliegs piekļuvi no pārlūka. Filtrējot lietotāju ierīču piekļuvi neatļaus tiem izmantot jaunas ierīces, līdz tās nav tikušas šeit atļautas.",
"DeinterlaceMethodHelp": "Izvēlies rindpārlēces sakļaušanas (deinterlacing) metodi kad tiek trans-kodēts rindpārlēces izvērsts (interlaced) saturs.",
"CustomDlnaProfilesHelp": "Izveido pielāgotu profilu priekš jaunas ierīces, vai pārraksti sistēmas profilu.",
"ColorTransfer": "Krāsu pārsūtīšana",
"ClientSettings": "Klientu Iestatījumi",
"ButtonTogglePlaylist": "Atskaņošanas Saraksts",
"ButtonToggleContextMenu": "Vairāk",
"BurnSubtitlesHelp": "Nosaka, vai serverim ir jāiededzina subtitri video trans-kodēšanas laikā. To nedarot tiks stipri palielināta veiktspēja. Izvēlies Auto lai iededzinātu uz attēliem bāzētus formātus (VOBSUB, PGS, SUB, IDX, …) un noteiktus ASS vai SSA subtitrus.",
"Artist": "Izpildītājs",
"AllowOnTheFlySubtitleExtractionHelp": "Iegultie subtitri var tikt izvilkto no video un nogādāti klientiem kā parasts teksts, lai nevajadzētu veikt lieku video trans kodēšanu. Uz dažām sistēmām tas var aizņemt ilgu laiku un likt video atskaņošanai uzkārties izvilkšanas procesa laikā. Atspējo šo lai iegultos subtitrus iededzinātu video trans kodēšanas veidā, kad tos noklusēti neatbalsta klienta ierīce.",
"AlbumArtist": "Albuma Izpildītājs",
"Album": "Albums"
} }

View file

@ -1021,7 +1021,7 @@
"OptionMissingEpisode": "Episódios em Falta", "OptionMissingEpisode": "Episódios em Falta",
"OptionMonday": "Segunda-feira", "OptionMonday": "Segunda-feira",
"OptionNameSort": "Nome", "OptionNameSort": "Nome",
"OptionNew": "Novo...", "OptionNew": "Novo",
"OptionNone": "Nenhum", "OptionNone": "Nenhum",
"OptionOnAppStartup": "Ao iniciar a aplicação", "OptionOnAppStartup": "Ao iniciar a aplicação",
"OptionOnInterval": "Em um intervalo", "OptionOnInterval": "Em um intervalo",
@ -1506,5 +1506,6 @@
"ButtonToggleContextMenu": "Mais", "ButtonToggleContextMenu": "Mais",
"Filter": "Filtro", "Filter": "Filtro",
"New": "Novo", "New": "Novo",
"HeaderFavoritePlaylists": "Playlists Favoritas" "HeaderFavoritePlaylists": "Playlists Favoritas",
"ApiKeysCaption": "Lista de chaves API ativadas no momento"
} }

View file

@ -249,7 +249,7 @@
"ButtonStop": "Stop", "ButtonStop": "Stop",
"ButtonSubmit": "Trimite", "ButtonSubmit": "Trimite",
"Collections": "Colecții", "Collections": "Colecții",
"AllowRemoteAccess": "Permite conexiuni externe către serverul Jellyfin.", "AllowRemoteAccess": "Permite conexiuni externe către acest server Jellyfin.",
"AllowRemoteAccessHelp": "Dacă este nebifat, toate conexiunile externe vor fi blocate.", "AllowRemoteAccessHelp": "Dacă este nebifat, toate conexiunile externe vor fi blocate.",
"AlwaysPlaySubtitles": "Întotdeauna arată", "AlwaysPlaySubtitles": "Întotdeauna arată",
"AnyLanguage": "Orice Limbă", "AnyLanguage": "Orice Limbă",
@ -288,7 +288,7 @@
"Director": "Regizor", "Director": "Regizor",
"AllowOnTheFlySubtitleExtractionHelp": "Subtitrările încorporate pot fi extrase din video și transmise către client în mod text pentru a preveni transcodarea videoului. Pe unele sisteme acest lucru poate dura mult timp și poate cauza oprirea redării video în timpul procesului de extragere. Dezactivează opțiunea pentru a avea subtitrările încorporate incluse în videoul transcodat atunci când nu sunt nativ suportate de către dispozitivul client.", "AllowOnTheFlySubtitleExtractionHelp": "Subtitrările încorporate pot fi extrase din video și transmise către client în mod text pentru a preveni transcodarea videoului. Pe unele sisteme acest lucru poate dura mult timp și poate cauza oprirea redării video în timpul procesului de extragere. Dezactivează opțiunea pentru a avea subtitrările încorporate incluse în videoul transcodat atunci când nu sunt nativ suportate de către dispozitivul client.",
"BirthLocation": "Locul nașterii", "BirthLocation": "Locul nașterii",
"BurnSubtitlesHelp": "Determină dacă serverul ar trebui să includă subtitrări când face transcodarea video. Evitând acest lucru va îmbunătăți performanța serverului. Selectează Auto pentru includerea formaturilor bazate pe imagini (VOBSUB, PGS, SUB, IDX) și anumitor subtitrări ASS sau SSA.", "BurnSubtitlesHelp": "Determină dacă serverul ar trebui să includă subtitrări când face transcodarea video. Evitând acest lucru va îmbunătăți performanța serverului. Selectează Auto pentru includerea formaturilor bazate pe imagini (VOBSUB, PGS, SUB, IDX, ...) și anumitor subtitrări ASS sau SSA.",
"ButtonPreviousTrack": "Calea anterioară", "ButtonPreviousTrack": "Calea anterioară",
"ButtonRevoke": "Revocă", "ButtonRevoke": "Revocă",
"ButtonSettings": "Setări", "ButtonSettings": "Setări",
@ -304,14 +304,14 @@
"Delete": "Șterge", "Delete": "Șterge",
"DeleteImage": "Șterge Imaginea", "DeleteImage": "Șterge Imaginea",
"DeleteUserConfirmation": "Sigur doriți să ștergeți acest utilizator?", "DeleteUserConfirmation": "Sigur doriți să ștergeți acest utilizator?",
"Depressed": "Depresat", "Depressed": "Deprimat",
"Descending": "Descendent", "Descending": "Descendent",
"DetectingDevices": "Detectez dispozitive", "DetectingDevices": "Detectez dispozitive",
"DirectPlaying": "Redare directă", "DirectPlaying": "Redare directă",
"DirectStreamHelp2": "Transmiterea directă a unui fișier utilizează foarte puțină putere de procesare fără pierderi în calitatea video.", "DirectStreamHelp2": "Transmiterea directă a unui fișier utilizează foarte puțină putere de procesare fără pierderi în calitatea video.",
"DirectStreaming": "Transmitere directă", "DirectStreaming": "Transmitere directă",
"Artists": "Artiști", "Artists": "Artiști",
"BookLibraryHelp": "Cărți audio și text sunt suportate. Verifică {0}ghidul numirii cărților{1}.", "BookLibraryHelp": "Cărți audio și text sunt suportate. Verifică {0} ghidul numirii cărților{1}.",
"ButtonAddImage": "Adaugă Imagine", "ButtonAddImage": "Adaugă Imagine",
"ButtonArrowUp": "Sus", "ButtonArrowUp": "Sus",
"ButtonAudioTracks": "Cale Audio", "ButtonAudioTracks": "Cale Audio",
@ -511,7 +511,7 @@
"GuestStar": "Vedeta invitata", "GuestStar": "Vedeta invitata",
"GuideProviderSelectListings": "Selectați Listări", "GuideProviderSelectListings": "Selectați Listări",
"EncoderPresetHelp": "Alegeți o valoare mai rapidă pentru a îmbunătăți performanța sau o valoare mai lentă pentru a îmbunătăți calitatea.", "EncoderPresetHelp": "Alegeți o valoare mai rapidă pentru a îmbunătăți performanța sau o valoare mai lentă pentru a îmbunătăți calitatea.",
"HardwareAccelerationWarning": "Activarea accelerării hardware poate provoca instabilitate în anumite medii. Asigurați-vă că sistemul de operare și driverele video sunt complet actualizate. Dacă întâmpinați dificultăți pentru a reda video după activarea acestei opțiuni, va trebui să schimbați setarea la Nimic.", "HardwareAccelerationWarning": "Activarea accelerării hardware poate provoca instabilitate în anumite medii. Asigurați-vă că sistemul de operare și driverele video sunt complet actualizate. Dacă întâmpinați dificultăți pentru a reda video după activarea acestei opțiuni, va trebui să schimbați setarea la inapoi la Nimic.",
"HeaderAccessSchedule": "Program de Acces", "HeaderAccessSchedule": "Program de Acces",
"HeaderAccessScheduleHelp": "Creați un program de acces pentru a limita accesul la anumite ore.", "HeaderAccessScheduleHelp": "Creați un program de acces pentru a limita accesul la anumite ore.",
"HeaderActiveDevices": "Dispozitive active", "HeaderActiveDevices": "Dispozitive active",
@ -1334,7 +1334,7 @@
"OptionOnInterval": "La un interval", "OptionOnInterval": "La un interval",
"OptionOnAppStartup": "La pornirea aplicației", "OptionOnAppStartup": "La pornirea aplicației",
"OptionNone": "Nici unul", "OptionNone": "Nici unul",
"OptionNew": "Nou...", "OptionNew": "Nou",
"OptionMissingEpisode": "Episoade lipsă", "OptionMissingEpisode": "Episoade lipsă",
"OptionMax": "Max", "OptionMax": "Max",
"OptionLoginAttemptsBeforeLockoutHelp": "O valoare zero înseamnă că va moșteni valoarea implicită de trei încercări pentru utilizatorii normali și cinci pentru administratori. Setarea acestei opțiuni la -1 va dezactiva funcția.", "OptionLoginAttemptsBeforeLockoutHelp": "O valoare zero înseamnă că va moșteni valoarea implicită de trei încercări pentru utilizatorii normali și cinci pentru administratori. Setarea acestei opțiuni la -1 va dezactiva funcția.",
@ -1359,9 +1359,9 @@
"OptionEnableExternalContentInSuggestions": "Activați conținut extern în sugestii", "OptionEnableExternalContentInSuggestions": "Activați conținut extern în sugestii",
"OptionEmbedSubtitles": "Inclus în container", "OptionEmbedSubtitles": "Inclus în container",
"OptionDownloadLogoImage": "Siglă", "OptionDownloadLogoImage": "Siglă",
"OptionDownloadImagesInAdvanceHelp": "În mod implicit, majoritatea imaginilor sunt descărcate numai la cererea unei aplicații din Jellyfin. Activați această opțiune pentru a descărca în prealabil toate imaginile, în timp ce fișierele media noi sunt importate. Acest lucru poate provoca scanări ale bibliotecii semnificativ mai lungi.", "OptionDownloadImagesInAdvanceHelp": "În mod implicit, majoritatea imaginilor sunt descărcate numai la cererea unei aplicații din Jellyfin. Activați această opțiune pentru a descărca în prealabil toate imaginile, pe măsură ce fișierele media sunt importate. Acest lucru poate provoca scanări ale bibliotecii semnificativ mai lungi.",
"OptionDownloadImagesInAdvance": "Descărcați imaginile în avans", "OptionDownloadImagesInAdvance": "Descărcați imaginile în avans",
"OptionDownloadDiscImage": "Placă", "OptionDownloadDiscImage": "Disc",
"OptionDisplayFolderViewHelp": "Afișați dosarele alături de celelalte biblioteci media. Acest lucru poate fi util dacă doriți să aveți o vizualizare direct în dosar.", "OptionDisplayFolderViewHelp": "Afișați dosarele alături de celelalte biblioteci media. Acest lucru poate fi util dacă doriți să aveți o vizualizare direct în dosar.",
"OptionDisplayFolderView": "Afișați o vizualizare de dosar pentru a afișa dosarele media simple", "OptionDisplayFolderView": "Afișați o vizualizare de dosar pentru a afișa dosarele media simple",
"OptionDateAddedImportTime": "Utilizați data scanării în bibliotecă", "OptionDateAddedImportTime": "Utilizați data scanării în bibliotecă",
@ -1465,8 +1465,8 @@
"NoCreatedLibraries": "Se pare că nu ați creat încă biblioteci. {0} Doriți să creați una acum? {1}", "NoCreatedLibraries": "Se pare că nu ați creat încă biblioteci. {0} Doriți să creați una acum? {1}",
"AskAdminToCreateLibrary": "Cereți unui administrator să creeze o bibliotecă.", "AskAdminToCreateLibrary": "Cereți unui administrator să creeze o bibliotecă.",
"PlaybackErrorNoCompatibleStream": "Clientul nu este compatibil cu formatul media, iar serverul nu trimite un format media compatibil.", "PlaybackErrorNoCompatibleStream": "Clientul nu este compatibil cu formatul media, iar serverul nu trimite un format media compatibil.",
"AllowFfmpegThrottlingHelp": "Când un transcod sau un remux se află destul de departe înainte de poziția actuală de redare, întrerupeți procesul, astfel încât să consume mai puține resurse. Acest lucru este cel mai util când priviți fără a derula des. Dezactivați acestă opțiune dacă întâmpinați probleme de redare.", "AllowFfmpegThrottlingHelp": "Când un transcod sau un remux se află destul de departe înainte de poziția actuală de redare, întrerupeți procesul, astfel încât să consume mai puține resurse. Acest lucru este util atunci când priviți fără a derula des. Dezactivați acestă opțiune dacă întâmpinați probleme de redare.",
"AllowFfmpegThrottling": "Accelerare Transcod-uri", "AllowFfmpegThrottling": "Limitare Transcod-uri",
"Track": "Cale", "Track": "Cale",
"Season": "Sezon", "Season": "Sezon",
"ReleaseGroup": "Gruparea lansării", "ReleaseGroup": "Gruparea lansării",
@ -1493,7 +1493,7 @@
"ListPaging": "{0}-{1} din {2}", "ListPaging": "{0}-{1} din {2}",
"WriteAccessRequired": "Jellyfin Server necesită acces de scriere la acest folder. Vă rugăm să vă asigurați accesul la scriere și încercați din nou.", "WriteAccessRequired": "Jellyfin Server necesită acces de scriere la acest folder. Vă rugăm să vă asigurați accesul la scriere și încercați din nou.",
"PathNotFound": "Calea nu a fost găsită. Vă rugăm să vă asigurați de validitatea căii și încercați din nou.", "PathNotFound": "Calea nu a fost găsită. Vă rugăm să vă asigurați de validitatea căii și încercați din nou.",
"YadifBob": "YADIF Bob", "YadifBob": "Gigi Bob",
"Yadif": "YADIF", "Yadif": "YADIF",
"LabelDeinterlaceMethod": "Metoda de intercalare:", "LabelDeinterlaceMethod": "Metoda de intercalare:",
"DeinterlaceMethodHelp": "Selectați metoda de intercalat pe care să o utilizați la transcodarea conținutului intercalat.", "DeinterlaceMethodHelp": "Selectați metoda de intercalat pe care să o utilizați la transcodarea conținutului intercalat.",
@ -1505,5 +1505,6 @@
"ButtonToggleContextMenu": "Mai mult", "ButtonToggleContextMenu": "Mai mult",
"Filter": "Filtru", "Filter": "Filtru",
"New": "Nou", "New": "Nou",
"HeaderFavoritePlaylists": "Listă Favorită" "HeaderFavoritePlaylists": "Listă Favorită",
"ApiKeysCaption": "Lista cheilor API active"
} }

View file

@ -25,7 +25,7 @@
"BirthDateValue": "Narodený/á: {0}", "BirthDateValue": "Narodený/á: {0}",
"BirthLocation": "Miesto narodenia", "BirthLocation": "Miesto narodenia",
"BirthPlaceValue": "Miesto narodenia: {0}", "BirthPlaceValue": "Miesto narodenia: {0}",
"BookLibraryHelp": "Audioknihy a učebnice sú podporované. Prečítajte si {0}pravidlá pre názvy kníh v Jellyfine{1}.", "BookLibraryHelp": "Audioknihy a učebnice sú podporované. Prečítajte si {0} pravidlá pre názvy kníh v Jellyfine {1}.",
"Books": "Knihy", "Books": "Knihy",
"ButtonAdd": "Pridať", "ButtonAdd": "Pridať",
"ButtonAddMediaLibrary": "Pridať knižnicu médií", "ButtonAddMediaLibrary": "Pridať knižnicu médií",

View file

@ -93,17 +93,17 @@
"ValueSeriesCount": "{0} серій", "ValueSeriesCount": "{0} серій",
"ValueSongCount": "{0} пісень", "ValueSongCount": "{0} пісень",
"AddToPlaylist": "Додати до списку відтворення", "AddToPlaylist": "Додати до списку відтворення",
"AccessRestrictedTryAgainLater": "На даний момент доступ заборонений. Будь ласка спробуйте пізніше.", "AccessRestrictedTryAgainLater": "На цей момент доступ заборонений. Повторіть спробу пізніше.",
"Actor": "Виконавець", "Actor": "Виконавець",
"AllLanguages": "Всі мови", "AllLanguages": "Усі мови",
"AllLibraries": "Всі бібліотеки", "AllLibraries": "Усі бібліотеки",
"AddToCollection": "Додати до колекції", "AddToCollection": "Додати до колекції",
"AddToPlayQueue": "Додати до черги відтворення", "AddToPlayQueue": "Додати до черги відтворення",
"All": "Всі", "All": "Всі",
"AllChannels": "Всі канали", "AllChannels": "Всі канали",
"AllEpisodes": "Всі епізоди", "AllEpisodes": "Всі епізоди",
"AllowRemoteAccess": "Дозволити віддалене підключення до цього сервера Jellyfin.", "AllowRemoteAccess": "Дозволити віддалене підключення до цього сервера Jellyfin.",
"AlwaysPlaySubtitles": "Завжди відтворювати субтитри", "AlwaysPlaySubtitles": "Завжди вмикати субтитри",
"AnyLanguage": "Будь-яка мова", "AnyLanguage": "Будь-яка мова",
"Anytime": "Завжди", "Anytime": "Завжди",
"Add": "Додати", "Add": "Додати",
@ -136,5 +136,28 @@
"Alerts": "Термінові сповіщення", "Alerts": "Термінові сповіщення",
"AlbumArtist": "Виконавець альбому", "AlbumArtist": "Виконавець альбому",
"Album": "Альбом", "Album": "Альбом",
"AdditionalNotificationServices": "Пошук у каталозі плагінів для встановлення додаткових сервісів сповіщень." "AdditionalNotificationServices": "Пошук у каталозі плагінів для встановлення додаткових сервісів сповіщень.",
"ShowYear": "Відобразити рік",
"ShowTitle": "Відобразити назву",
"Raised": "Піднятий",
"OptionResElement": "кожний елемент",
"DropShadow": "Тінь",
"Blacklist": "Чорний список",
"BirthLocation": "Місце народження",
"Banner": "Обкладинка",
"AutoBasedOnLanguageSetting": "Автоматично (на основі поточної мови)",
"Auto": "Автоматично",
"AuthProviderHelp": "Оберіть сервіс аутентифікації, який буде використаний з поточним паролем користувача.",
"Audio": "Аудіо",
"AttributeNew": "Новий",
"AspectRatio": "Відношення сторін",
"AskAdminToCreateLibrary": "Попросіть адміністратора створити бібліотеку.",
"Ascending": "У порядку зростання",
"AsManyAsPossible": "Настільки багато наскільки можливо",
"Artist": "Виконавець",
"Art": "Мистецтво",
"AllowOnTheFlySubtitleExtractionHelp": "Вбудовані субтитри можуть бути експортовані з відео і надіслані, по черзі, клієнтам у вигляді тексту. Це допоможе уникнути перекодування відео. На деяких системах, перекодування може зайняти тривалий час і зупинити відтворення відео, для того щоб забезпечити експортування. Вимкнення цієї функції дозволить вбудованим субтитрам бути інтегрованим у відео, під час перекодування, якщо вбудовані субтитри не підтримуються на стороні клієнта.",
"AllowOnTheFlySubtitleExtraction": "Дозволити експортування субтитрів «на льоту»",
"AllowHWTranscodingHelp": "Дозволити клієнту перекодування на «на льоту». Це дозволить відмикати перекодування, якщо вона вимагається сервером.",
"AllComplexFormats": "Усі складні формати (ASS, SSA, VOBSUB, PGS, SUB, IDX, …)"
} }

View file

@ -167,11 +167,11 @@
"ButtonAddScheduledTaskTrigger": "Thêm kích hoạt", "ButtonAddScheduledTaskTrigger": "Thêm kích hoạt",
"ButtonAddMediaLibrary": "Thêm thư viện Media", "ButtonAddMediaLibrary": "Thêm thư viện Media",
"ButtonAddImage": "Thêm hình ảnh", "ButtonAddImage": "Thêm hình ảnh",
"BurnSubtitlesHelp": "Xác định xem máy chủ có nên ghi phụ đề khi chuyển đổi video hay không. Tránh thực hiện việc này sẽ cải thiện hiệu suất máy chủ đáng kể. Chọn Tự động để ghi các phụ đề có định dạng dựa trên hình ảnh (VOBSUB, PGS, SUB, IDX) và một vài phụ đề ASS/SSA nhất định.", "BurnSubtitlesHelp": "Xác định xem máy chủ có nên ghi phụ đề khi chuyển đổi video hay không. Tránh thực hiện việc này sẽ cải thiện hiệu suất máy chủ đáng kể. Chọn Tự động để ghi các phụ đề có định dạng dựa trên hình ảnh (VOBSUB, PGS, SUB, IDX, ...) và một vài phụ đề ASS/SSA nhất định.",
"Browse": "Duyệt", "Browse": "Duyệt",
"BoxRear": "Hộp (mặt sau)", "BoxRear": "Hộp (mặt sau)",
"Books": "Sách", "Books": "Sách",
"BookLibraryHelp": "Âm thanh và sách văn bản được hỗ trợ. Xem lại {0}hướng dẫn đặt tên sách{1}.", "BookLibraryHelp": "Âm thanh và sách văn bản được hỗ trợ. Xem lại {0} hướng dẫn đặt tên sách {1}.",
"Blacklist": "Danh sách đen", "Blacklist": "Danh sách đen",
"BirthPlaceValue": "Nơi sinh: {0}", "BirthPlaceValue": "Nơi sinh: {0}",
"BirthLocation": "Nơi sinh", "BirthLocation": "Nơi sinh",
@ -196,7 +196,7 @@
"AllowedRemoteAddressesHelp": "Danh sách địa chỉ IP được phân tách bằng dấu phẩy hoặc các mục IP/netmask cho các mạng sẽ được phép kết nối từ xa. Nếu để trống, tất cả các địa chỉ sẽ được cho phép.", "AllowedRemoteAddressesHelp": "Danh sách địa chỉ IP được phân tách bằng dấu phẩy hoặc các mục IP/netmask cho các mạng sẽ được phép kết nối từ xa. Nếu để trống, tất cả các địa chỉ sẽ được cho phép.",
"AllowRemoteAccessHelp": "Nếu không được chọn, tất cả các kết nối từ xa sẽ bị chặn.", "AllowRemoteAccessHelp": "Nếu không được chọn, tất cả các kết nối từ xa sẽ bị chặn.",
"AllowRemoteAccess": "Cho phép kết nối từ xa đến Máy chủ Jellyfin.", "AllowRemoteAccess": "Cho phép kết nối từ xa đến Máy chủ Jellyfin.",
"AllowOnTheFlySubtitleExtractionHelp": "Phụ đề nhúng có thể được trích xuất từ video và dùng như văn bản thuần túy để giúp ngăn chặn chuyển mã video. Trên một số hệ thống, việc này có thể mất nhiều thời gian và khiến quá trình phát video bị đình trệ trong quá trình trích xuất. Vô hiệu hóa điều này để có phụ đề nhúng được ghi trong chuyển mã video khi chúng không được thiết bị khách hỗ trợ.", "AllowOnTheFlySubtitleExtractionHelp": "Phụ đề nhúng có thể được trích xuất từ video và dùng như văn bản thuần túy để giúp ngăn chặn chuyển mã video. Trên một số hệ thống, việc này có thể mất nhiều thời gian và khiến quá trình phát video bị đình trệ trong quá trình trích xuất. Vô hiệu hóa điều này để có phụ đề nhúng được ghi trong video khi chuyển mã trong trường hợp chúng không được hỗ trợ trên thiết bị phát.",
"AllowOnTheFlySubtitleExtraction": "Cho phép trích xuất phụ đề trực tiếp", "AllowOnTheFlySubtitleExtraction": "Cho phép trích xuất phụ đề trực tiếp",
"AllowMediaConversionHelp": "Cấp hoặc từ chối truy cập vào tính năng chuyển đổi media.", "AllowMediaConversionHelp": "Cấp hoặc từ chối truy cập vào tính năng chuyển đổi media.",
"AllowMediaConversion": "Cho phép chuyển đổi media", "AllowMediaConversion": "Cho phép chuyển đổi media",
@ -204,7 +204,7 @@
"AllLibraries": "Tất cả các thư viện", "AllLibraries": "Tất cả các thư viện",
"AllLanguages": "Tất cả các ngôn ngữ", "AllLanguages": "Tất cả các ngôn ngữ",
"AllEpisodes": "Tất cả các tập phim", "AllEpisodes": "Tất cả các tập phim",
"AllComplexFormats": "Tất cả các định dạng phức tạp (ASS, SSA, VOBSUB, PGS, SUB, IDX)", "AllComplexFormats": "Tất cả các định dạng phức tạp (ASS, SSA, VOBSUB, PGS, SUB, IDX, ...)",
"AllChannels": "Tất cả các kênh", "AllChannels": "Tất cả các kênh",
"Alerts": "Cảnh Báo", "Alerts": "Cảnh Báo",
"Albums": "Albums", "Albums": "Albums",
@ -672,5 +672,39 @@
"HeaderTuners": "Bộ Điều Khiển Thu Phát Sóng", "HeaderTuners": "Bộ Điều Khiển Thu Phát Sóng",
"HeaderTunerDevices": "Thiết Bị Bắt Sóng", "HeaderTunerDevices": "Thiết Bị Bắt Sóng",
"HeaderTranscodingProfileHelp": "Thêm hồ sơ chuyển mã để chỉ ra những định dạng nên dùng khi cần chuyển mã.", "HeaderTranscodingProfileHelp": "Thêm hồ sơ chuyển mã để chỉ ra những định dạng nên dùng khi cần chuyển mã.",
"HeaderTranscodingProfile": "Hồ Sơ Chuyển Mã" "HeaderTranscodingProfile": "Hồ Sơ Chuyển Mã",
"LabelEnableAutomaticPortMap": "Kích hoạt tính năng tự động kết nối các port",
"LabelEmbedAlbumArtDidlHelp": "Một vài thiết bị ưu tiên phương pháp này để tải bìa album. Một số thiết bị khác có thể không phát được nếu tuỳ chọn này được kích hoạt.",
"LabelEmbedAlbumArtDidl": "Bìa album trong Didl",
"LabelEasyPinCode": "Mã PIN đơn giản:",
"LabelDynamicExternalId": "{0} Id:",
"LabelDropShadow": "Đổ bóng:",
"LabelDroppedFrames": "Những khung hình bị loại bỏ:",
"LabelDropImageHere": "Kéo thả hình ảnh vào đây, hoặc click để lựa chọn hình ảnh.",
"LabelDownloadLanguages": "Ngôn ngữ tải xuống:",
"LabelDownMixAudioScaleHelp": "Tăng cường âm lượng khi trộn âm thanh. Giá trị bằng 1 sẽ giữ nguyên âm lượng gốc.",
"LabelDownMixAudioScale": "Tăng cường âm lượng khi trộn âm thanh:",
"LabelDisplaySpecialsWithinSeasons": "Hiển thị những tập đặc biệt trong phần mà nó được phát sóng",
"LabelDisplayOrder": "Thứ tự hiển thị:",
"LabelDisplayName": "Tên hiển thị:",
"LabelDisplayMode": "Chế độ hiển thị:",
"LabelDisplayMissingEpisodesWithinSeasons": "Hiển thị những tập bị thiếu",
"LabelDisplayLanguageHelp": "Dự án chuyển ngữ Jellyfin là một dự án diễn ra ra liên tục.",
"LabelDisplayLanguage": "Ngôn ngữ hiển thị:",
"LabelDiscNumber": "Đĩa số:",
"LabelDidlMode": "Chế độ DIDL:",
"LabelDeviceDescription": "Mô tả thiết bị",
"LabelDeinterlaceMethod": "Phương pháp khử xen kẽ:",
"LabelDefaultUserHelp": "Xác định thư viện được hiển thị trên những thiết bị đã kết nối. Tuỳ chọn này có thể được ghi đè trên hồ sơ của từng thiết bị.",
"LabelDefaultUser": "Người dùng mặc định:",
"LabelDefaultScreen": "Màn hình mặc định:",
"LabelDeathDate": "Ngày mất:",
"LabelDateTimeLocale": "Ngày giờ địa phương:",
"LabelDateAddedBehaviorHelp": "Nếu có giá trị dữ liệu bổ trợ, nó sẽ luôn được sử dụng trước một trong các tùy chọn này.",
"LabelDateAddedBehavior": "Ngày thêm hành vi cho nội dung mới:",
"LabelDateAdded": "Ngày thêm vào:",
"LabelDashboardTheme": "Chủ đề bảng điều khiển máy chủ:",
"LabelCustomRating": "Đánh giá tuỳ chọn:",
"HeaderFavoritePlaylists": "Danh Sách Phát Yêu Thích",
"ApiKeysCaption": "Danh sách các mã API đang hoạt động"
} }

View file

@ -212,7 +212,7 @@
"OptionMissingEpisode": "缺少了的單元", "OptionMissingEpisode": "缺少了的單元",
"OptionMonday": "星期一", "OptionMonday": "星期一",
"OptionNameSort": "名字", "OptionNameSort": "名字",
"OptionNew": "新增...", "OptionNew": "新增",
"OptionOnAppStartup": "在伺服器啟動", "OptionOnAppStartup": "在伺服器啟動",
"OptionOnInterval": "每時段", "OptionOnInterval": "每時段",
"OptionParentalRating": "家長評級", "OptionParentalRating": "家長評級",
@ -1678,5 +1678,10 @@
"DeinterlaceMethodHelp": "選擇對隔行掃描內容進行轉碼時所用的反交錯方法。", "DeinterlaceMethodHelp": "選擇對隔行掃描內容進行轉碼時所用的反交錯方法。",
"BoxSet": "套裝", "BoxSet": "套裝",
"UnsupportedPlayback": "Jellyfin 無法解密受 DRM 保護的內容,但仍然會嘗試播放所有內容。某些檔案由於被加密或包含如互動標題等不受支援的內容,在播放時可能會沒有畫面。", "UnsupportedPlayback": "Jellyfin 無法解密受 DRM 保護的內容,但仍然會嘗試播放所有內容。某些檔案由於被加密或包含如互動標題等不受支援的內容,在播放時可能會沒有畫面。",
"MessageUnauthorizedUser": "您目前無權存取伺服器,請與您的伺服器管理員聯繫以獲取更多訊息。" "MessageUnauthorizedUser": "您目前無權存取伺服器,請與您的伺服器管理員聯繫以獲取更多訊息。",
"Filter": "篩選器",
"New": "新增",
"ApiKeysCaption": "目前已啟用的API金鑰列表",
"ButtonTogglePlaylist": "播放清單",
"ButtonToggleContextMenu": "更多"
} }