diff --git a/.gitignore b/.gitignore index 4adf9558b..9bccd32fb 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,7 @@ node_modules # ide .idea -.vscode \ No newline at end of file +.vscode + +#log +yarn-error.log diff --git a/package.json b/package.json index ffbbc0295..1e7ebfd0c 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "webpack": "^4.41.5", "webpack-cli": "^3.3.10", "webpack-concat-plugin": "^3.0.0", - "webpack-dev-server": "^3.10.3", + "webpack-dev-server": "^3.11.0", "webpack-merge": "^4.2.2", "webpack-stream": "^5.2.1" }, @@ -57,7 +57,7 @@ "alameda": "^1.4.0", "classlist.js": "https://github.com/eligrey/classList.js/archive/1.2.20180112.tar.gz", "core-js": "^3.6.5", - "date-fns": "^2.12.0", + "date-fns": "^2.13.0", "document-register-element": "^1.14.3", "fast-text-encoding": "^1.0.1", "flv.js": "^1.5.0", @@ -67,7 +67,7 @@ "intersection-observer": "^0.10.0", "jellyfin-apiclient": "^1.1.1", "jellyfin-noto": "https://github.com/jellyfin/jellyfin-noto", - "jquery": "^3.5.0", + "jquery": "^3.5.1", "jstree": "^3.3.7", "libass-wasm": "https://github.com/jellyfin/JavascriptSubtitlesOctopus#4.0.0-jf-smarttv", "material-design-icons-iconfont": "^5.0.1", @@ -76,7 +76,7 @@ "query-string": "^6.11.1", "resize-observer-polyfill": "^1.5.1", "screenfull": "^5.0.2", - "shaka-player": "^2.5.10", + "shaka-player": "^2.5.11", "sortablejs": "^1.10.2", "swiper": "^5.3.7", "webcomponents.js": "^0.7.24", @@ -102,6 +102,10 @@ "src/scripts/filesystem.js", "src/scripts/imagehelper.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/settings/appSettings.js", "src/scripts/settings/userSettings.js", diff --git a/postcss.config.js b/postcss.config.js index 0e19ca6e1..bd1651fa1 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -5,8 +5,10 @@ const cssnano = require('cssnano'); const config = () => ({ plugins: [ + // Explicitly specify browserslist to override ones from node_modules + // For example, Swiper has it in its package.json postcssPresetEnv({browsers: packageConfig.browserslist}), - autoprefixer(), + autoprefixer({overrideBrowserslist: packageConfig.browserslist}), cssnano() ] }); diff --git a/src/addplugin.html b/src/addplugin.html index 30e42a2c5..81c671d5b 100644 --- a/src/addplugin.html +++ b/src/addplugin.html @@ -5,7 +5,7 @@

- ${Help} + ${Help}

diff --git a/src/addserver.html b/src/addserver.html index 763f56851..02850fffb 100644 --- a/src/addserver.html +++ b/src/addserver.html @@ -3,7 +3,7 @@

${HeaderConnectToServer}

- +
${LabelServerHostHelp}

diff --git a/src/apikeys.html b/src/apikeys.html index 7ca490724..3cb7cd6de 100644 --- a/src/apikeys.html +++ b/src/apikeys.html @@ -4,18 +4,19 @@

${HeaderApiKeys}

${HeaderApiKeysHelp}


+ - - - - + + + + diff --git a/src/assets/css/site.css b/src/assets/css/site.css index e59b639f4..627145abc 100644 --- a/src/assets/css/site.css +++ b/src/assets/css/site.css @@ -5,6 +5,17 @@ html { height: 100%; } +.clipForScreenReader { + clip: rect(1px, 1px, 1px, 1px); + clip-path: inset(50%); + height: 1px; + width: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; +} + .material-icons { /* Fix font ligatures on older WebOS versions */ -webkit-font-feature-settings: "liga"; diff --git a/src/components/accessschedule/accessschedule.template.html b/src/components/accessschedule/accessschedule.template.html index 906d20869..493150ae5 100644 --- a/src/components/accessschedule/accessschedule.template.html +++ b/src/components/accessschedule/accessschedule.template.html @@ -1,6 +1,6 @@
-

${HeaderAccessSchedule} diff --git a/src/components/actionsheet/actionsheet.js b/src/components/actionsheet/actionsheet.js index e08fbf4a2..18239f8de 100644 --- a/src/components/actionsheet/actionsheet.js +++ b/src/components/actionsheet/actionsheet.js @@ -1,360 +1,343 @@ -define(['dialogHelper', 'layoutManager', 'globalize', 'browser', 'dom', 'emby-button', 'css!./actionsheet', 'material-icons', 'scrollStyles', 'listViewStyle'], function (dialogHelper, layoutManager, globalize, browser, dom) { - 'use strict'; +import dialogHelper from 'dialogHelper'; +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; - 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 - }; - } + let results = []; + if (!document) { return results; } - function getPosition(options, dlg) { - - var windowSize = dom.getWindowSize(); - var windowHeight = windowSize.innerHeight; - var windowWidth = windowSize.innerWidth; - - var pos = getOffsets([options.positionTo])[0]; - - if (options.positionY !== 'top') { - pos.top += (pos.height || 0) / 2; + let box; + for (let elem of elems) { + // 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 }; } - pos.left += (pos.width || 0) / 2; - - var height = dlg.offsetHeight || 300; - var width = dlg.offsetWidth || 160; - - // 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); + results.push({ + top: box.top, + left: box.left, + width: box.width, + height: box.height }); } - function show(options) { + return results; +} - // items - // positionTo - // showCancel - // title - var dialogOptions = { - removeOnClose: true, - enableHistory: options.enableHistory, - scrollY: false - }; +function getPosition(options, dlg) { - var backButton = false; - var isFullscreen; + const windowSize = dom.getWindowSize(); + const windowHeight = windowSize.innerHeight; + const windowWidth = windowSize.innerWidth; - if (layoutManager.tv) { - dialogOptions.size = 'fullscreen'; - isFullscreen = true; - backButton = true; - dialogOptions.autoFocus = true; - } else { + let pos = getOffsets([options.positionTo])[0]; - dialogOptions.modal = false; - dialogOptions.entryAnimation = options.entryAnimation; - dialogOptions.exitAnimation = options.exitAnimation; - dialogOptions.entryAnimationDuration = options.entryAnimationDuration || 140; - dialogOptions.exitAnimationDuration = options.exitAnimationDuration || 100; - dialogOptions.autoFocus = false; + if (options.positionY !== 'top') { + pos.top += (pos.height || 0) / 2; + } + + pos.left += (pos.width || 0) / 2; + + 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 += ''; + } + + // 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 += '
'; + } else { + html += '
'; + } + + if (options.title) { + + html += '

' + options.title + '

'; + } + if (options.text) { + html += '

' + options.text + '

'; + } + + let scrollerClassName = 'actionSheetScroller'; + if (layoutManager.tv) { + scrollerClassName += ' actionSheetScroller-tv focuscontainer-x focuscontainer-y'; + } + html += '
'; + + 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 += '
'; + continue; } - var dlg = dialogHelper.createDialog(dialogOptions); + const autoFocus = item.selected && layoutManager.tv ? ' autoFocus' : ''; - if (isFullscreen) { - dlg.classList.add('actionsheet-fullscreen'); - } else { - dlg.classList.add('actionsheet-not-fullscreen'); + // Check for null in case int 0 was passed in + const optionId = item.id == null || item.id === '' ? item.value : item.id; + html += ''; + + itemIcon = icons[i]; + + if (itemIcon) { + html += ''; + } else if (renderIcon && !center) { + html += ''; } - dlg.classList.add('actionSheet'); + html += '
'; - if (options.dialogClass) { - dlg.classList.add(options.dialogClass); - } - - 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 += ''; - } - - // 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 += '
'; - } else { - html += '
'; - } - - if (options.title) { - - html += '

'; - html += options.title; - html += '

'; - } - if (options.text) { - html += '

'; - html += options.text; - html += '

'; - } - - var scrollerClassName = 'actionSheetScroller'; - if (layoutManager.tv) { - scrollerClassName += ' actionSheetScroller-tv focuscontainer-x focuscontainer-y'; - } - html += '
'; - - 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 += '
'; - 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 += ''; - - itemIcon = icons[i]; - - if (itemIcon) { - - html += ''; - } else if (renderIcon && !center) { - html += ''; - } - - html += '
'; - - html += '
'; - html += (option.name || option.textContent || option.innerText); - html += '
'; - - if (option.secondaryText) { - html += '
'; - html += option.secondaryText; - html += '
'; - } - - html += '
'; - - if (option.asideText) { - html += '
'; - html += option.asideText; - html += '
'; - } - - html += ''; - } - - if (options.showCancel) { - html += '
'; - html += ''; - html += '
'; - } + html += '
'; + html += (item.name || item.textContent || item.innerText); html += '
'; - dlg.innerHTML = html; - - if (layoutManager.tv) { - centerFocus(dlg.querySelector('.actionSheetScroller'), false, true); + if (item.secondaryText) { + html += '
' + item.secondaryText + '
'; } - var btnCloseActionSheet = dlg.querySelector('.btnCloseActionSheet'); - if (btnCloseActionSheet) { - dlg.querySelector('.btnCloseActionSheet').addEventListener('click', function () { - dialogHelper.close(dlg); - }); + html += '
'; + + if (item.asideText) { + html += '
' + item.asideText + '
'; } - // Seeing an issue in some non-chrome browsers where this is requiring a double click - //var eventName = browser.firefox ? 'mousedown' : 'click'; - var selectedId; + html += ''; + } - var timeout; - if (options.timeout) { - timeout = setTimeout(function () { - dialogHelper.close(dlg); - }, options.timeout); - } + if (options.showCancel) { + html += '
'; + html += ''; + html += '
'; + } + html += '
'; - 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) { - selectedId = actionSheetMenuItem.getAttribute('data-id'); + let timeout; + 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); - isResolved = true; - } + const actionSheetMenuItem = dom.parentWithClass(e.target, 'actionSheetMenuItem'); + + if (actionSheetMenuItem) { + selectedId = actionSheetMenuItem.getAttribute('data-id'); + + if (options.resolveOnClick) { + + if (options.resolveOnClick.indexOf) { + + if (options.resolveOnClick.indexOf(selectedId) !== -1) { - } else { resolve(selectedId); 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 { - 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.style.position = 'fixed'; - dlg.style.margin = 0; - dlg.style.left = pos.left + 'px'; - dlg.style.top = pos.top + 'px'; + 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 { + reject(); + } } }); - } - return { - show: show - }; -}); + dialogHelper.open(dlg); + + 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 +}; diff --git a/src/components/apphost.js b/src/components/apphost.js index 75e8ba17f..7b044d5d3 100644 --- a/src/components/apphost.js +++ b/src/components/apphost.js @@ -359,7 +359,6 @@ define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'g return -1 !== supportedFeatures.indexOf(command.toLowerCase()); }, preferVisualCards: browser.android || browser.chrome, - moreIcon: browser.android ? 'more_vert' : 'more_horiz', getSyncProfile: getSyncProfile, getDefaultLayout: function () { if (window.NativeShell) { diff --git a/src/components/cardbuilder/cardBuilder.js b/src/components/cardbuilder/cardBuilder.js index 43ca28f01..d4d4d7f73 100644 --- a/src/components/cardbuilder/cardBuilder.js +++ b/src/components/cardbuilder/cardBuilder.js @@ -869,7 +869,7 @@ import 'programStyles'; if (isOuterFooter && options.cardLayout && layoutManager.mobile) { if (options.cardFooterAside !== 'none') { - html += ''; + html += ''; } } @@ -1426,7 +1426,7 @@ import 'programStyles'; } if (options.overlayMoreButton) { - overlayButtons += ''; + overlayButtons += ''; } } @@ -1580,7 +1580,7 @@ import 'programStyles'; html += ''; } - html += ''; + html += ''; html += '
'; html += '
'; diff --git a/src/components/deletehelper.js b/src/components/deletehelper.js index 2212fd443..e13eb9c4a 100644 --- a/src/components/deletehelper.js +++ b/src/components/deletehelper.js @@ -1,57 +1,54 @@ -define(['connectionManager', 'confirm', 'appRouter', 'globalize'], function (connectionManager, confirm, appRouter, globalize) { - 'use strict'; +import connectionManager from 'connectionManager'; +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) { - alert(options).then(resolve, resolve); - }); + require(['alert'], function (alert) { + alert(options).then(resolve, resolve); }); - } + }); +} - function deleteItem(options) { +export function deleteItem(options) { - var item = options.item; - var itemId = item.Id; - var parentId = item.SeasonId || item.SeriesId || item.ParentId; - var serverId = item.ServerId; + const item = options.item; + const parentId = item.SeasonId || item.SeriesId || item.ParentId; - var msg = globalize.translate('ConfirmDeleteItem'); - var title = globalize.translate('HeaderDeleteItem'); - var apiClient = connectionManager.getApiClient(item.ServerId); + let apiClient = connectionManager.getApiClient(item.ServerId); - return confirm({ + return confirm({ - title: title, - text: msg, - confirmText: globalize.translate('Delete'), - primary: 'delete' + title: globalize.translate('HeaderDeleteItem'), + text: globalize.translate('ConfirmDeleteItem'), + confirmText: globalize.translate('Delete'), + primary: 'delete' - }).then(function () { + }).then(function () { - return apiClient.deleteItem(itemId).then(function () { + return apiClient.deleteItem(item.Id).then(function () { - if (options.navigate) { - if (parentId) { - appRouter.showItem(parentId, serverId); - } else { - appRouter.goHome(); - } + if (options.navigate) { + if (parentId) { + appRouter.showItem(parentId, item.ServerId); + } else { + appRouter.goHome(); } - }, function (err) { + } + }, function (err) { - var result = function () { - return Promise.reject(err); - }; + let result = function () { + return Promise.reject(err); + }; - return alertText(globalize.translate('ErrorDeletingItem')).then(result, result); - }); + return alertText(globalize.translate('ErrorDeletingItem')).then(result, result); }); - } + }); +} - return { - deleteItem: deleteItem - }; -}); +export default { + deleteItem: deleteItem +}; diff --git a/src/components/displaysettings/displaysettings.template.html b/src/components/displaysettings/displaysettings.template.html index 62cb493e8..b8ab1a9ba 100644 --- a/src/components/displaysettings/displaysettings.template.html +++ b/src/components/displaysettings/displaysettings.template.html @@ -56,7 +56,7 @@
diff --git a/src/components/guide/guide-settings.template.html b/src/components/guide/guide-settings.template.html index 6888ca80d..edb2ffa8d 100644 --- a/src/components/guide/guide-settings.template.html +++ b/src/components/guide/guide-settings.template.html @@ -1,5 +1,7 @@
- +

${Settings}

diff --git a/src/components/guide/tvguide.template.html b/src/components/guide/tvguide.template.html index bd4c9cc3c..730de5590 100644 --- a/src/components/guide/tvguide.template.html +++ b/src/components/guide/tvguide.template.html @@ -9,8 +9,8 @@
-
@@ -29,10 +29,10 @@
- -
diff --git a/src/components/htmlMediaHelper.js b/src/components/htmlMediaHelper.js index fb84bc19f..3f17eeb33 100644 --- a/src/components/htmlMediaHelper.js +++ b/src/components/htmlMediaHelper.js @@ -194,7 +194,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve } }; events.map(function (name) { - element.addEventListener(name, onMediaChange); + return element.addEventListener(name, onMediaChange); }); } } diff --git a/src/components/htmlaudioplayer/plugin.js b/src/components/htmlaudioplayer/plugin.js index c3a5484ac..000af6f22 100644 --- a/src/components/htmlaudioplayer/plugin.js +++ b/src/components/htmlaudioplayer/plugin.js @@ -136,7 +136,10 @@ define(['events', 'browser', 'require', 'apphost', 'appSettings', 'htmlMediaHelp requireHlsPlayer(function () { var hls = new Hls({ - manifestLoadingTimeOut: 20000 + manifestLoadingTimeOut: 20000, + xhrSetup: function(xhr, url) { + xhr.withCredentials = true; + } //appendErrorMaxRetry: 6, //debug: true }); @@ -155,6 +158,9 @@ define(['events', 'browser', 'require', 'apphost', 'appSettings', 'htmlMediaHelp elem.autoplay = true; + // Safari will not send cookies without this + elem.crossOrigin = 'use-credentials'; + return htmlMediaHelper.applySrc(elem, val, options).then(function () { self._currentSrc = val; diff --git a/src/components/htmlvideoplayer/plugin.js b/src/components/htmlvideoplayer/plugin.js index f87fd1946..65b1c3c29 100644 --- a/src/components/htmlvideoplayer/plugin.js +++ b/src/components/htmlvideoplayer/plugin.js @@ -106,10 +106,16 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa }); } + function hidePrePlaybackPage() { + let animatedPage = document.querySelector('.page:not(.hide)'); + animatedPage.classList.add('hide'); + } + function zoomIn(elem) { return new Promise(function (resolve, reject) { var duration = 240; elem.style.animation = 'htmlvideoplayer-zoomin ' + duration + 'ms ease-in normal'; + hidePrePlaybackPage(); dom.addEventListener(elem, dom.whichAnimationEvent(), resolve, { once: true }); @@ -290,7 +296,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa return createMediaElement(options).then(function (elem) { - return updateVideoUrl(options, options.mediaSource).then(function () { + return updateVideoUrl(options).then(function () { return setCurrentSrc(elem, options); }); }); @@ -330,7 +336,10 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa requireHlsPlayer(function () { var hls = new Hls({ - manifestLoadingTimeOut: 20000 + manifestLoadingTimeOut: 20000, + xhrSetup: function(xhr, xhr_url) { + xhr.withCredentials = true; + } //appendErrorMaxRetry: 6, //debug: true }); @@ -551,6 +560,9 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa elem.autoplay = true; + // Safari will not send cookies without this + elem.crossOrigin = 'use-credentials'; + return htmlMediaHelper.applySrc(elem, val, options).then(function () { self._currentSrc = val; @@ -836,7 +848,6 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa function onNavigatedToOsd() { var dlg = videoDialog; if (dlg) { - dlg.classList.remove('videoPlayerContainer-withBackdrop'); dlg.classList.remove('videoPlayerContainer-onTop'); onStartedAndNavigatedToOsd(); @@ -873,7 +884,6 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa } else { appRouter.setTransparency('backdrop'); - videoDialog.classList.remove('videoPlayerContainer-withBackdrop'); videoDialog.classList.remove('videoPlayerContainer-onTop'); onStartedAndNavigatedToOsd(); @@ -1290,12 +1300,6 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa function createMediaElement(options) { - if (browser.tv || browser.iOS || browser.mobile) { - // too slow - // also on iOS, the backdrop image doesn't look right - // on android mobile, it works, but can be slow to have the video surface fully cover the backdrop - options.backdropUrl = null; - } return new Promise(function (resolve, reject) { var dlg = document.querySelector('.videoPlayerContainer'); @@ -1310,11 +1314,6 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa dlg.classList.add('videoPlayerContainer'); - if (options.backdropUrl) { - dlg.classList.add('videoPlayerContainer-withBackdrop'); - dlg.style.backgroundImage = "url('" + options.backdropUrl + "')"; - } - if (options.fullscreen) { dlg.classList.add('videoPlayerContainer-onTop'); } @@ -1348,6 +1347,9 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa videoElement.addEventListener('play', onPlay); videoElement.addEventListener('click', onClick); videoElement.addEventListener('dblclick', onDblClick); + if (options.backdropUrl) { + videoElement.poster = options.backdropUrl; + } document.body.insertBefore(dlg, document.body.firstChild); videoDialog = dlg; @@ -1367,15 +1369,11 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa resolve(videoElement); }); } else { + hidePrePlaybackPage(); resolve(videoElement); } }); } else { - if (options.backdropUrl) { - dlg.classList.add('videoPlayerContainer-withBackdrop'); - dlg.style.backgroundImage = "url('" + options.backdropUrl + "')"; - } - resolve(dlg.querySelector('video')); } }); diff --git a/src/components/htmlvideoplayer/style.css b/src/components/htmlvideoplayer/style.css index 5ecf4af66..b83a7816f 100644 --- a/src/components/htmlvideoplayer/style.css +++ b/src/components/htmlvideoplayer/style.css @@ -6,20 +6,9 @@ right: 0; display: flex; align-items: center; -} - -.videoPlayerContainer:not(.videoPlayerContainer-withBackdrop) { background: #000 !important; } -.videoPlayerContainer-withBackdrop { - background-repeat: no-repeat; - background-position: center center; - background-size: cover; - background-attachment: fixed; - background-color: #000; -} - .videoPlayerContainer-onTop { z-index: 1000; } diff --git a/src/components/indicators/indicators.js b/src/components/indicators/indicators.js index b4391fd4a..7bc8ddd4e 100644 --- a/src/components/indicators/indicators.js +++ b/src/components/indicators/indicators.js @@ -1,198 +1,183 @@ -define(['datetime', 'itemHelper', 'emby-progressbar', 'css!./indicators.css', 'material-icons'], function (datetime, itemHelper) { - 'use strict'; +import datetime from 'datetime'; +import itemHelper from 'itemHelper'; +import 'emby-progressbar'; +import 'css!./indicators.css'; +import 'material-icons'; - function enableProgressIndicator(item) { - if (item.MediaType === 'Video') { - if (item.Type !== 'TvChannel') { - return true; - } - } - - if (item.Type === 'AudioBook' || item.Type === 'AudioPodcast') { - return true; - } - - return false; +export function enableProgressIndicator(item) { + if (item.MediaType === 'Video' && item.Type !== 'TvChannel') { + return true; } - function getProgressHtml(pct, options) { - var containerClass = 'itemProgressBar'; - if (options) { - if (options.containerClass) { - containerClass += ' ' + options.containerClass; - } - } - - return '
'; + if (item.Type === 'AudioBook' || item.Type === 'AudioPodcast') { + return true; } - function getAutoTimeProgressHtml(pct, options, isRecording, start, end) { - var containerClass = 'itemProgressBar'; - if (options) { - if (options.containerClass) { - containerClass += ' ' + options.containerClass; - } - } + return false; +} - var foregroundClass = 'itemProgressBarForeground'; - if (isRecording) { - foregroundClass += ' itemProgressBarForeground-recording'; - } - - return '
'; +export function getProgressHtml(pct, options) { + let containerClass = 'itemProgressBar'; + if (options && options.containerClass) { + containerClass += ' ' + options.containerClass; } - function getProgressBarHtml(item, options) { - var pct; - if (enableProgressIndicator(item) && item.Type !== 'Recording') { - var userData = options ? (options.userData || item.UserData) : item.UserData; - if (userData) { - pct = userData.PlayedPercentage; - if (pct && pct < 100) { - return getProgressHtml(pct, options); - } + return '
'; +} + +function getAutoTimeProgressHtml(pct, options, isRecording, start, end) { + let containerClass = 'itemProgressBar'; + if (options && options.containerClass) { + containerClass += ' ' + options.containerClass; + } + + let foregroundClass = 'itemProgressBarForeground'; + if (isRecording) { + foregroundClass += ' itemProgressBarForeground-recording'; + } + + return '
'; +} + +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) { - var startDate = 0; - var endDate = 1; + if ((item.Type === 'Program' || item.Type === 'Timer' || item.Type === 'Recording') && item.StartDate && item.EndDate) { + let startDate = 0; + 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 '
' + userData.UnplayedItemCount + '
'; + } + + if (userData.PlayedPercentage && userData.PlayedPercentage >= 100 || (userData.Played)) { + return '
'; + } + } + + return ''; +} + +export function getChildCountIndicatorHtml(item, options) { + const minCount = options && options.minCount ? options.minCount : 0; + + if (item.ChildCount && item.ChildCount > minCount) { + return '
' + item.ChildCount + '
'; + } + + return ''; +} + +export function getTimerIndicator(item) { + let status; + + if (item.Type === 'SeriesTimer') { + return ''; + } 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 ''; + } + + return ''; + } + + return ''; +} + +export function getSyncIndicator(item) { + if (item.SyncPercent === 100) { + return '
'; + } else if (item.SyncPercent != null) { + return '
'; + } + + return ''; +} + +export function getTypeIndicator(item) { + const iconT = { + 'Video' : 'videocam', + 'Folder' : 'folder', + 'PhotoAlbum' : 'photo_album', + 'Photo' : 'photo' + }; + + const icon = iconT[item.Type]; + return icon ? '
' : ''; +} + +export function getMissingIndicator(item) { + if (item.Type === 'Episode' && item.LocationType === 'Virtual') { + if (item.PremiereDate) { try { - startDate = datetime.parseISO8601Date(item.StartDate).getTime(); - endDate = datetime.parseISO8601Date(item.EndDate).getTime(); + const premiereDate = datetime.parseISO8601Date(item.PremiereDate).getTime(); + if (premiereDate > new Date().getTime()) { + return '
Unaired
'; + } } catch (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 ''; + return '
Missing
'; } - function enablePlayedIndicator(item) { - return itemHelper.canMarkPlayed(item); - } + return ''; +} - function getPlayedIndicator(item) { - if (enablePlayedIndicator(item)) { - var userData = item.UserData || {}; - if (userData.UnplayedItemCount) { - return '
' + userData.UnplayedItemCount + '
'; - } - - if (userData.PlayedPercentage && userData.PlayedPercentage >= 100 || (userData.Played)) { - return '
'; - } - } - - return ''; - } - - function getCountIndicatorHtml(count) { - return '
' + count + '
'; - } - - 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 ''; - } 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 ''; - } - - return ''; - } - - return ''; - } - - function getSyncIndicator(item) { - if (item.SyncPercent === 100) { - return '
'; - } else if (item.SyncPercent != null) { - return '
'; - } - - return ''; - } - - function getTypeIndicator(item) { - if (item.Type === 'Video') { - return '
'; - } - if (item.Type === 'Folder') { - return '
'; - } - if (item.Type === 'PhotoAlbum') { - return '
'; - } - if (item.Type === 'Photo') { - return '
'; - } - - 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 '
Unaired
'; - } - } catch (err) { - console.error(err); - } - } - return '
Missing
'; - } - - return ''; - } - - return { - getProgressHtml: getProgressHtml, - getProgressBarHtml: getProgressBarHtml, - getPlayedIndicatorHtml: getPlayedIndicator, - getChildCountIndicatorHtml: getChildCountIndicatorHtml, - enableProgressIndicator: enableProgressIndicator, - getTimerIndicator: getTimerIndicator, - enablePlayedIndicator: enablePlayedIndicator, - getSyncIndicator: getSyncIndicator, - getTypeIndicator: getTypeIndicator, - getMissingIndicator: getMissingIndicator - }; -}); +export default { + getProgressHtml: getProgressHtml, + getProgressBarHtml: getProgressBarHtml, + getPlayedIndicatorHtml: getPlayedIndicatorHtml, + getChildCountIndicatorHtml: getChildCountIndicatorHtml, + enableProgressIndicator: enableProgressIndicator, + getTimerIndicator: getTimerIndicator, + enablePlayedIndicator: enablePlayedIndicator, + getSyncIndicator: getSyncIndicator, + getTypeIndicator: getTypeIndicator, + getMissingIndicator: getMissingIndicator +}; diff --git a/src/components/libraryoptionseditor/libraryoptionseditor.js b/src/components/libraryoptionseditor/libraryoptionseditor.js index 6fc93b3bd..fec465640 100644 --- a/src/components/libraryoptionseditor/libraryoptionseditor.js +++ b/src/components/libraryoptionseditor/libraryoptionseditor.js @@ -109,8 +109,8 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct html += '
'; html += '

' + globalize.translate('LabelTypeMetadataDownloaders', globalize.translate(availableTypeOptions.Type)) + '

'; html += '
'; - for (var i = 0; i < plugins.length; i++) { - var plugin = plugins[i]; + + plugins.forEach((plugin, index) => { html += '
'; var isChecked = libraryOptionsForType.MetadataFetchers ? -1 !== libraryOptionsForType.MetadataFetchers.indexOf(plugin.Name) : plugin.DefaultEnabled; var checkedHtml = isChecked ? ' checked="checked"' : ''; @@ -120,8 +120,9 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct html += plugin.Name; html += '

'; html += '
'; - i > 0 ? html += '' : plugins.length > 1 && (html += ''), html += ''; - } + index > 0 ? html += '' : plugins.length > 1 && (html += ''), html += ''; + }); + html += ''; html += '
' + globalize.translate('LabelMetadataDownloadersHelp') + '
'; html += ''; @@ -292,11 +293,15 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct function showImageOptionsForType(type) { require(['imageoptionseditor'], function(ImageOptionsEditor) { var typeOptions = getTypeOptions(currentLibraryOptions, type); - typeOptions || (typeOptions = { - Type: type - }, currentLibraryOptions.TypeOptions.push(typeOptions)); + if (!typeOptions) { + typeOptions = { + Type: type + }; + currentLibraryOptions.TypeOptions.push(typeOptions); + } var availableOptions = getTypeOptions(currentAvailableOptions || {}, type); - (new ImageOptionsEditor).show(type, typeOptions, availableOptions); + var imageOptionsEditor = new ImageOptionsEditor(); + imageOptionsEditor.show(type, typeOptions, availableOptions); }); } @@ -315,10 +320,16 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct var list = dom.parentWithClass(li, 'paperList'); if (btnSortable.classList.contains('btnSortableMoveDown')) { var next = li.nextSibling; - next && (li.parentNode.removeChild(li), next.parentNode.insertBefore(li, next.nextSibling)); + if (next) { + li.parentNode.removeChild(li); + next.parentNode.insertBefore(li, next.nextSibling); + } } else { var prev = li.previousSibling; - prev && (li.parentNode.removeChild(li), prev.parentNode.insertBefore(li, prev)); + if (prev) { + li.parentNode.removeChild(li); + prev.parentNode.insertBefore(li, prev); + } } Array.prototype.forEach.call(list.querySelectorAll('.sortableOption'), adjustSortableListElement); } diff --git a/src/components/listview/listview.js b/src/components/listview/listview.js index 0743b3528..587355b35 100644 --- a/src/components/listview/listview.js +++ b/src/components/listview/listview.js @@ -426,7 +426,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan html += '
'; - const moreIcon = 'more_horiz'; + const moreIcon = 'more_vert'; html += getTextLinesHtml(textlines, isLargeStyle); diff --git a/src/components/mediainfo/mediainfo.js b/src/components/mediainfo/mediainfo.js index 0c9a87e80..c569a7c78 100644 --- a/src/components/mediainfo/mediainfo.js +++ b/src/components/mediainfo/mediainfo.js @@ -490,26 +490,26 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater if (i.IsInterlaced) { return '1440i'; } - return '1440P'; + return '1440p'; } if (width >= 1800 || height >= 1000) { if (i.IsInterlaced) { return '1080i'; } - return '1080P'; + return '1080p'; } if (width >= 1200 || height >= 700) { if (i.IsInterlaced) { return '720i'; } - return '720P'; + return '720p'; } if (width >= 700 || height >= 400) { if (i.IsInterlaced) { return '480i'; } - return '480P'; + return '480p'; } } diff --git a/src/components/metadataeditor/metadataeditor.js b/src/components/metadataeditor/metadataeditor.js index 41d400062..b1905ea73 100644 --- a/src/components/metadataeditor/metadataeditor.js +++ b/src/components/metadataeditor/metadataeditor.js @@ -750,11 +750,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi return a.Name; }).join(';'); - if (item.Type === 'Series') { - context.querySelector('#selectDisplayOrder').value = item.DisplayOrder || ''; - } else { - context.querySelector('#selectDisplayOrder').value = item.DisplayOrder || ''; - } + context.querySelector('#selectDisplayOrder').value = item.DisplayOrder || ''; context.querySelector('#txtArtist').value = (item.ArtistItems || []).map(function (a) { return a.Name; diff --git a/src/components/multiselect/multiselect.js b/src/components/multiselect/multiselect.js index 70a0924bc..6a22e5509 100644 --- a/src/components/multiselect/multiselect.js +++ b/src/components/multiselect/multiselect.js @@ -129,7 +129,7 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo html += ''; html += '

'; - const moreIcon = 'more_horiz'; + const moreIcon = 'more_vert'; html += ''; selectionCommandsPanel.innerHTML = html; diff --git a/src/components/playback/playbackmanager.js b/src/components/playback/playbackmanager.js index ee85f9acb..dea419c8c 100644 --- a/src/components/playback/playbackmanager.js +++ b/src/components/playback/playbackmanager.js @@ -309,13 +309,11 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla if (codecProfile.Type === 'Audio') { (codecProfile.Conditions || []).map(function (condition) { if (condition.Condition === 'LessThanEqual' && condition.Property === 'AudioBitDepth') { - maxAudioBitDepth = condition.Value; - } - if (condition.Condition === 'LessThanEqual' && condition.Property === 'AudioSampleRate') { - maxAudioSampleRate = condition.Value; - } - if (condition.Condition === 'LessThanEqual' && condition.Property === 'AudioBitrate') { - maxAudioBitrate = condition.Value; + return maxAudioBitDepth = condition.Value; + } else if (condition.Condition === 'LessThanEqual' && condition.Property === 'AudioSampleRate') { + return maxAudioSampleRate = condition.Value; + } else if (condition.Condition === 'LessThanEqual' && condition.Property === 'AudioBitrate') { + return maxAudioBitrate = condition.Value; } }); } diff --git a/src/components/playmenu.js b/src/components/playmenu.js index a410da698..50c2a7b31 100644 --- a/src/components/playmenu.js +++ b/src/components/playmenu.js @@ -1,75 +1,71 @@ -define(['actionsheet', 'datetime', 'playbackManager', 'globalize', 'appSettings'], function (actionsheet, datetime, playbackManager, globalize, appSettings) { - 'use strict'; +import actionsheet from 'actionsheet'; +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 isFolder = item.IsFolder; - var itemId = item.Id; - var channelId = item.ChannelId; - var serverId = item.ServerId; - var resumePositionTicks = item.UserData ? item.UserData.PlaybackPositionTicks : null; + 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) { - playbackManager.play({ - ids: [playableItemId], - serverId: 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; - } + if (!resumePositionTicks || item.IsFolder) { + playbackManager.play({ + ids: [playableItemId], + serverId: item.ServerId }); + return; } - return { - show: show - }; -}); + 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: 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 +}; diff --git a/src/components/subtitleeditor/subtitleeditor.js b/src/components/subtitleeditor/subtitleeditor.js index 8ce1fd580..e9bcc0bfc 100644 --- a/src/components/subtitleeditor/subtitleeditor.js +++ b/src/components/subtitleeditor/subtitleeditor.js @@ -232,11 +232,7 @@ define(['dialogHelper', 'require', 'layoutManager', 'globalize', 'userSettings', html += '
'; } html += '

' + provider + '

'; - if (layoutManager.tv) { - html += '
'; - } else { - html += '
'; - } + html += '
'; lastProvider = provider; } diff --git a/src/components/subtitleeditor/subtitleeditor.template.html b/src/components/subtitleeditor/subtitleeditor.template.html index 01066ecc6..7471972f5 100644 --- a/src/components/subtitleeditor/subtitleeditor.template.html +++ b/src/components/subtitleeditor/subtitleeditor.template.html @@ -2,8 +2,7 @@

${Subtitles}

- ${Help} - + ${Help}
diff --git a/src/components/tvproviders/schedulesdirect.template.html b/src/components/tvproviders/schedulesdirect.template.html index 3cfba06fe..abe19b50f 100644 --- a/src/components/tvproviders/schedulesdirect.template.html +++ b/src/components/tvproviders/schedulesdirect.template.html @@ -1,7 +1,7 @@

Schedules Direct

- ${Help} + ${Help}

diff --git a/src/components/tvproviders/xmltv.template.html b/src/components/tvproviders/xmltv.template.html index e8dc43416..72c29904b 100644 --- a/src/components/tvproviders/xmltv.template.html +++ b/src/components/tvproviders/xmltv.template.html @@ -1,7 +1,7 @@

Xml TV

- ${Help} + ${Help}
diff --git a/src/components/upnextdialog/upnextdialog.css b/src/components/upnextdialog/upnextdialog.css index 15f91b29d..05e3b10f5 100644 --- a/src/components/upnextdialog/upnextdialog.css +++ b/src/components/upnextdialog/upnextdialog.css @@ -63,8 +63,8 @@ height: auto; width: 100%; box-shadow: 0 0.0725em 0.29em 0 rgba(0, 0, 0, 0.37); - border: 0; user-drag: none; + border: 0; user-select: none; -moz-user-select: none; -webkit-user-drag: none; diff --git a/src/config.example.json b/src/config.template.json similarity index 100% rename from src/config.example.json rename to src/config.template.json diff --git a/src/controllers/dashboard/devices/devices.js b/src/controllers/dashboard/devices/devices.js index da65ef621..0dea81c75 100644 --- a/src/controllers/dashboard/devices/devices.js +++ b/src/controllers/dashboard/devices/devices.js @@ -89,7 +89,7 @@ define(['loading', 'dom', 'libraryMenu', 'globalize', 'scripts/imagehelper', 'da if (canEdit || canDelete(device.Id)) { deviceHtml += '
'; - deviceHtml += ''; + deviceHtml += ''; deviceHtml += '
'; } diff --git a/src/controllers/dashboard/medialibrarypage.js b/src/controllers/dashboard/medialibrarypage.js index 0788fa4ca..06eba37cb 100644 --- a/src/controllers/dashboard/medialibrarypage.js +++ b/src/controllers/dashboard/medialibrarypage.js @@ -298,7 +298,7 @@ define(['jQuery', 'apphost', 'scripts/taskbutton', 'loading', 'libraryMenu', 'gl if (virtualFolder.showMenu !== false) { html += '
'; - html += ''; + html += ''; html += '
'; } diff --git a/src/controllers/dashboard/plugins/installed.js b/src/controllers/dashboard/plugins/installed.js index 427ce7d94..5ca739f71 100644 --- a/src/controllers/dashboard/plugins/installed.js +++ b/src/controllers/dashboard/plugins/installed.js @@ -47,7 +47,7 @@ define(['loading', 'libraryMenu', 'dom', 'globalize', 'cardStyle', 'emby-button' html += '
'; html += '
'; html += '
'; - html += ''; + html += ''; html += '
'; html += "
"; html += configPage.DisplayName || plugin.Name; diff --git a/src/controllers/list.js b/src/controllers/list.js index cef6ceda6..edd446900 100644 --- a/src/controllers/list.js +++ b/src/controllers/list.js @@ -1016,7 +1016,6 @@ define(['globalize', 'listView', 'layoutManager', 'userSettings', 'focusManager' if ('Programs' === params.type) { filters.push('Genres'); } else { - params.type; filters.push('IsUnplayed'); filters.push('IsPlayed'); diff --git a/src/controllers/livetvstatus.js b/src/controllers/livetvstatus.js index 053e5d3d4..737d49496 100644 --- a/src/controllers/livetvstatus.js +++ b/src/controllers/livetvstatus.js @@ -30,7 +30,7 @@ define(['jQuery', 'globalize', 'scripts/taskbutton', 'dom', 'libraryMenu', 'layo html += '
'; html += '
'; html += '
'; - html += ''; + html += ''; html += '
' + (device.FriendlyName || getTunerName(device.Type)) + '
'; html += '
'; html += device.Url || ' '; @@ -112,7 +112,7 @@ define(['jQuery', 'globalize', 'scripts/taskbutton', 'dom', 'libraryMenu', 'layo html += '
'; html += ''; html += '
'; - html += ''; + html += ''; html += '
'; } diff --git a/src/controllers/livetvtuner.js b/src/controllers/livetvtuner.js index e8a03e7f2..d7a4d92db 100644 --- a/src/controllers/livetvtuner.js +++ b/src/controllers/livetvtuner.js @@ -82,7 +82,6 @@ define(['globalize', 'loading', 'libraryMenu', 'dom', 'emby-input', 'emby-button info.Id = id; } - info.Id; ApiClient.ajax({ type: 'POST', url: ApiClient.getUrl('LiveTv/TunerHosts'), diff --git a/src/controllers/playback/videoosd.js b/src/controllers/playback/videoosd.js index e9923d779..831aea557 100644 --- a/src/controllers/playback/videoosd.js +++ b/src/controllers/playback/videoosd.js @@ -1112,6 +1112,14 @@ define(['playbackManager', 'dom', 'inputManager', 'datetime', 'itemHelper', 'med playbackManager.playPause(currentPlayer); showOsd(); break; + case 'ArrowUp': + case 'Up': + playbackManager.volumeUp(currentPlayer); + break; + case 'ArrowDown': + case 'Down': + playbackManager.volumeDown(currentPlayer); + break; case 'l': case 'ArrowRight': case 'Right': @@ -1134,6 +1142,18 @@ define(['playbackManager', 'dom', 'inputManager', 'datetime', 'itemHelper', 'med playbackManager.toggleMute(currentPlayer); showOsd(); 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 'GamepadDPadLeft': case 'GamepadLeftThumbstickLeft': @@ -1151,6 +1171,26 @@ define(['playbackManager', 'dom', 'inputManager', 'datetime', 'itemHelper', 'med playbackManager.fastForward(currentPlayer); 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; } } diff --git a/src/controllers/usernew.js b/src/controllers/usernew.js index e59143a9d..5646b239d 100644 --- a/src/controllers/usernew.js +++ b/src/controllers/usernew.js @@ -8,12 +8,12 @@ define(['jQuery', 'loading', 'globalize', 'fnchecked', 'emby-checkbox'], functio for (var i = 0; i < mediaFolders.length; i++) { var folder = mediaFolders[i]; - html += ''; + html += ''; } html += '
'; $('.folderAccess', page).html(html).trigger('create'); - $('#chkEnableAllFolders', page).checked(true).trigger('change'); + $('#chkEnableAllFolders', page).checked(false).trigger('change'); } function loadChannels(page, channels) { @@ -23,7 +23,7 @@ define(['jQuery', 'loading', 'globalize', 'fnchecked', 'emby-checkbox'], functio for (var i = 0; i < channels.length; i++) { var folder = channels[i]; - html += ''; + html += ''; } html += '
'; @@ -35,7 +35,7 @@ define(['jQuery', 'loading', 'globalize', 'fnchecked', 'emby-checkbox'], functio $('.channelAccessContainer', page).hide(); } - $('#chkEnableAllChannels', page).checked(true).trigger('change'); + $('#chkEnableAllChannels', page).checked(false).trigger('change'); } function loadUser(page) { diff --git a/src/controllers/userprofilespage.js b/src/controllers/userprofilespage.js index 528166e84..c691c665f 100644 --- a/src/controllers/userprofilespage.js +++ b/src/controllers/userprofilespage.js @@ -115,7 +115,7 @@ define(['loading', 'dom', 'globalize', 'date-fns', 'dfnshelper', 'paper-icon-but html += '
'; html += user.Name; html += '
'; - html += ''; + html += ''; html += ''; html += '
'; var lastSeen = getLastSeenText(user.LastActivityDate); @@ -189,7 +189,7 @@ define(['loading', 'dom', 'globalize', 'date-fns', 'dfnshelper', 'paper-icon-but html += '
'; html += '
'; html += '
'; - html += ''; + html += ''; html += '
'; html += '
'; html += user.UserName; diff --git a/src/dashboard.html b/src/dashboard.html index 8be9f54eb..9063f5596 100644 --- a/src/dashboard.html +++ b/src/dashboard.html @@ -112,7 +112,7 @@
diff --git a/src/dashboardgeneral.html b/src/dashboardgeneral.html index 59c8e623d..03bfa9af8 100644 --- a/src/dashboardgeneral.html +++ b/src/dashboardgeneral.html @@ -5,7 +5,7 @@

${TabSettings}

- ${Help} + ${Help}
@@ -19,7 +19,7 @@
${LabelPreferredDisplayLanguageHelp}
- ${LabelReadHowYouCanContribute} + ${LabelReadHowYouCanContribute}
diff --git a/src/device.html b/src/device.html index 11fc9671b..093b31120 100644 --- a/src/device.html +++ b/src/device.html @@ -5,7 +5,7 @@
diff --git a/src/devices.html b/src/devices.html index 4e6552f05..55f51d7e2 100644 --- a/src/devices.html +++ b/src/devices.html @@ -4,7 +4,7 @@

${TabDevices}

- ${Help} + ${Help}
diff --git a/src/dlnaprofile.html b/src/dlnaprofile.html index edaee0e6f..e960d97a0 100644 --- a/src/dlnaprofile.html +++ b/src/dlnaprofile.html @@ -5,7 +5,7 @@

${HeaderProfileInformation}

- ${Help} + ${Help}
diff --git a/src/dlnasettings.html b/src/dlnasettings.html index 8068acf5a..703dd66a9 100644 --- a/src/dlnasettings.html +++ b/src/dlnasettings.html @@ -8,7 +8,7 @@

${TabSettings}

- ${Help} + ${Help}
diff --git a/src/elements/emby-slider/emby-slider.css b/src/elements/emby-slider/emby-slider.css index f59c2a3cd..7661895f1 100644 --- a/src/elements/emby-slider/emby-slider.css +++ b/src/elements/emby-slider/emby-slider.css @@ -87,10 +87,6 @@ transform: scale(1.3); } -.slider-no-webkit-thumb::-webkit-slider-thumb { - opacity: 0 !important; -} - .mdl-slider::-moz-range-thumb { -moz-appearance: none; width: 1.08em; diff --git a/src/elements/emby-slider/emby-slider.js b/src/elements/emby-slider/emby-slider.js index 03d64719e..e37455dfe 100644 --- a/src/elements/emby-slider/emby-slider.js +++ b/src/elements/emby-slider/emby-slider.js @@ -148,9 +148,6 @@ define(['browser', 'dom', 'layoutManager', 'keyboardnavigation', 'css!./emby-sli this.classList.add('mdl-slider'); this.classList.add('mdl-js-slider'); - if (browser.noFlex) { - this.classList.add('slider-no-webkit-thumb'); - } if (browser.edge || browser.msie) { this.classList.add('slider-browser-edge'); } diff --git a/src/encodingsettings.html b/src/encodingsettings.html index 27cfe404c..8971957b7 100644 --- a/src/encodingsettings.html +++ b/src/encodingsettings.html @@ -5,7 +5,7 @@

${TabTranscoding}

- ${Help} + ${Help}
@@ -21,7 +21,7 @@
diff --git a/src/itemdetails.html b/src/itemdetails.html index 37f1432e2..4d5cab026 100644 --- a/src/itemdetails.html +++ b/src/itemdetails.html @@ -101,7 +101,7 @@ diff --git a/src/libraries/navdrawer/navdrawer.js b/src/libraries/navdrawer/navdrawer.js index 9c15fbc18..d9c246b40 100644 --- a/src/libraries/navdrawer/navdrawer.js +++ b/src/libraries/navdrawer/navdrawer.js @@ -260,7 +260,6 @@ define(["browser", "dom", "css!./navdrawer", "scrollStyles"], function (browser, TouchMenuLA.prototype.showMask = function () { mask.classList.remove("hide"); - mask.offsetWidth; mask.classList.add("backdrop"); }; diff --git a/src/library.html b/src/library.html index 398613f9e..1bca60724 100644 --- a/src/library.html +++ b/src/library.html @@ -6,7 +6,7 @@ ${ButtonScanAllLibraries} - ${Help} + ${Help}
diff --git a/src/list.html b/src/list.html index efac2d891..464cd1553 100644 --- a/src/list.html +++ b/src/list.html @@ -42,10 +42,10 @@
diff --git a/src/livetvsettings.html b/src/livetvsettings.html index bffd6ae4b..a3a43c792 100644 --- a/src/livetvsettings.html +++ b/src/livetvsettings.html @@ -4,7 +4,7 @@

DVR

- ${Help} + ${Help}
diff --git a/src/livetvstatus.html b/src/livetvstatus.html index cc5f8ae0b..3aa27637d 100644 --- a/src/livetvstatus.html +++ b/src/livetvstatus.html @@ -10,7 +10,7 @@ - ${Help} + ${Help}
diff --git a/src/livetvtuner.html b/src/livetvtuner.html index 816d30f34..f45a3a1d0 100644 --- a/src/livetvtuner.html +++ b/src/livetvtuner.html @@ -5,7 +5,7 @@

${HeaderLiveTvTunerSetup}

- ${Help} + ${Help}
diff --git a/src/networking.html b/src/networking.html index 2cb354e7d..cc824eaab 100644 --- a/src/networking.html +++ b/src/networking.html @@ -5,7 +5,7 @@

${TabNetworking}

- ${Help} + ${Help}
diff --git a/src/notificationsetting.html b/src/notificationsetting.html index f982aa29c..67b35981f 100644 --- a/src/notificationsetting.html +++ b/src/notificationsetting.html @@ -8,7 +8,7 @@ diff --git a/src/scheduledtask.html b/src/scheduledtask.html index 6789e5990..c7e82594c 100644 --- a/src/scheduledtask.html +++ b/src/scheduledtask.html @@ -4,7 +4,7 @@ diff --git a/src/scripts/browser.js b/src/scripts/browser.js index 276f580df..b1912862b 100644 --- a/src/scripts/browser.js +++ b/src/scripts/browser.js @@ -53,45 +53,6 @@ define([], function () { return false; } - function isStyleSupported(prop, value) { - - if (typeof window === 'undefined') { - return false; - } - - // If no value is supplied, use "inherit" - value = arguments.length === 2 ? value : 'inherit'; - // Try the native standard method first - if ('CSS' in window && 'supports' in window.CSS) { - return window.CSS.supports(prop, value); - } - // Check Opera's native method - if ('supportsCSS' in window) { - return window.supportsCSS(prop, value); - } - - // need try/catch because it's failing on tizen - - try { - // Convert to camel-case for DOM interactions - var camel = prop.replace(/-([a-z]|[0-9])/ig, function (all, letter) { - return (letter + '').toUpperCase(); - }); - // Create test element - var el = document.createElement('div'); - // Check if the property is supported - var support = (camel in el.style); - // Assign the property and value to invoke - // the CSS interpreter - el.style.cssText = prop + ':' + value; - // Ensure both the property and value are - // supported and return - return support && (el.style[camel] !== ''); - } catch (err) { - return false; - } - } - function hasKeyboard(browser) { if (browser.touch) { @@ -283,10 +244,6 @@ define([], function () { browser.tv = isTv(); browser.operaTv = browser.tv && userAgent.toLowerCase().indexOf('opr/') !== -1; - if (!isStyleSupported('display', 'flex')) { - browser.noFlex = true; - } - if (browser.mobile || browser.tv) { browser.slow = true; } diff --git a/src/scripts/routes.js b/src/scripts/routes.js index 31530705c..a5ed0a00a 100644 --- a/src/scripts/routes.js +++ b/src/scripts/routes.js @@ -38,6 +38,14 @@ define([ controller: 'auth/selectserver', type: 'selectserver' }); + defineRoute({ + path: '/login.html', + autoFocus: false, + anonymous: true, + startup: true, + controller: 'auth/login', + type: 'login' + }); defineRoute({ path: '/forgotpassword.html', anonymous: true, @@ -52,12 +60,6 @@ define([ controller: 'auth/forgotpasswordpin' }); - defineRoute({ - path: '/addplugin.html', - autoFocus: false, - roles: 'admin', - controller: 'dashboard/plugins/add' - }); defineRoute({ path: '/mypreferencesmenu.html', autoFocus: false, @@ -137,6 +139,24 @@ define([ roles: 'admin', controller: 'dashboard/dlna/dlnaprofiles' }); + defineRoute({ + path: '/addplugin.html', + autoFocus: false, + roles: 'admin', + controller: 'dashboard/plugins/add' + }); + defineRoute({ + path: '/library.html', + autoFocus: false, + roles: 'admin', + controller: 'dashboard/medialibrarypage' + }); + defineRoute({ + path: '/librarydisplay.html', + autoFocus: false, + roles: 'admin', + controller: 'dashboard/librarydisplay' + }); defineRoute({ path: '/dlnasettings.html', autoFocus: false, @@ -154,6 +174,7 @@ define([ roles: 'admin', controller: 'dashboard/encodingsettings' }); + defineRoute({ path: '/home.html', autoFocus: false, @@ -161,6 +182,10 @@ define([ transition: 'fade', type: 'home' }); + defineRoute({ + path: '/search.html', + controller: 'searchpage' + }); defineRoute({ path: '/list.html', autoFocus: false, @@ -173,18 +198,6 @@ define([ autoFocus: false, transition: 'fade' }); - defineRoute({ - path: '/library.html', - autoFocus: false, - roles: 'admin', - controller: 'dashboard/medialibrarypage' - }); - defineRoute({ - path: '/librarydisplay.html', - autoFocus: false, - roles: 'admin', - controller: 'dashboard/librarydisplay' - }); defineRoute({ path: '/livetv.html', controller: 'livetv/livetvsuggested', @@ -219,14 +232,6 @@ define([ roles: 'admin', controller: 'dashboard/logs' }); - defineRoute({ - path: '/login.html', - autoFocus: false, - anonymous: true, - startup: true, - controller: 'auth/login', - type: 'login' - }); defineRoute({ path: '/metadataimages.html', autoFocus: false, @@ -293,10 +298,6 @@ define([ roles: 'admin', controller: 'dashboard/scheduledtasks/scheduledtasks' }); - defineRoute({ - path: '/search.html', - controller: 'searchpage' - }); defineRoute({ path: '/serveractivity.html', autoFocus: false, @@ -321,6 +322,7 @@ define([ controller: 'shows/tvrecommended', transition: 'fade' }); + defineRoute({ path: '/useredit.html', autoFocus: false, @@ -373,7 +375,7 @@ define([ path: '/wizardlibrary.html', autoFocus: false, anonymous: true, - controller: 'medialibrarypage' + controller: 'dashboard/medialibrarypage' }); defineRoute({ path: '/wizardsettings.html', diff --git a/src/scripts/settings/webSettings.js b/src/scripts/settings/webSettings.js index 92093dfbe..d999724af 100644 --- a/src/scripts/settings/webSettings.js +++ b/src/scripts/settings/webSettings.js @@ -2,7 +2,17 @@ let data; function getConfig() { if (data) return Promise.resolve(data); - return fetch('/config.json?nocache=' + new Date().getUTCMilliseconds()).then(function (response) { + return fetch('/config.json?nocache=' + new Date().getUTCMilliseconds()).then(response => { + data = response.json(); + return data; + }).catch(error => { + console.warn('web config file is missing so the template will be used'); + return getDefaultConfig(); + }); +} + +function getDefaultConfig() { + return fetch('/config.template.json').then(function (response) { data = response.json(); return data; }); diff --git a/src/strings/ar.json b/src/strings/ar.json index 50b93a830..f6f64c5d4 100644 --- a/src/strings/ar.json +++ b/src/strings/ar.json @@ -962,7 +962,7 @@ "AllowMediaConversion": "السماح بتحويل الوسائظ", "AllLanguages": "كل اللغات", "AllEpisodes": "كل الحلقات", - "AllComplexFormats": "جميع التنسيقات المعقدة (ASS ، SSA ، VOBSUB ، PGS ، SUB / IDX ، إلخ.)", + "AllComplexFormats": "جميع التنسيقات المعقدة (ASS ، SSA ، VOBSUB ، PGS ، SUB / IDX ، ...)", "AllChannels": "كل القنوات", "Albums": "ألبومات", "Aired": "عرضت", diff --git a/src/strings/de.json b/src/strings/de.json index 07cca966f..1f70b418f 100644 --- a/src/strings/de.json +++ b/src/strings/de.json @@ -17,7 +17,7 @@ "Albums": "Alben", "All": "Alle", "AllChannels": "Alle Kanäle", - "AllComplexFormats": "Alle komplexen Formate (ASS, SSA, VOBSUB, PGS, SUB/IDX)", + "AllComplexFormats": "Alle komplexen Formate (ASS, SSA, VOBSUB, PGS, SUB/IDX, ...)", "AllEpisodes": "Alle Folgen", "AllLanguages": "Alle Sprachen", "AllLibraries": "Alle Bibliotheken", @@ -55,12 +55,12 @@ "BirthLocation": "Geburtsort", "BirthPlaceValue": "Geburtsort: {0}", "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", "BoxRear": "Box (Rückseite)", "Browse": "Blättern", "BrowsePluginCatalogMessage": "Durchsuche unsere Bibliothek, um alle verfügbaren Plugins anzuzeigen.", - "BurnSubtitlesHelp": "Legt fest, ob der Server die Untertitel während der Videotranskodierung einbrennen soll. Deaktivieren verbessert die Serverperformance immens. Wähle Auto, um bildbasierte Formate (z.B. VOBSUB, PGS, SUB, IDX) sowie bestimmte ASS- oder SSA-Untertitel einbrennen zu lassen.", + "BurnSubtitlesHelp": "Legt fest, ob der Server die Untertitel während der Videotranskodierung einbrennen soll. Deaktivieren verbessert die Serverperformance immens. Wähle Auto, um bildbasierte Formate (z.B. VOBSUB, PGS, SUB, IDX, ...) sowie bestimmte ASS- oder SSA-Untertitel einbrennen zu lassen.", "ButtonAdd": "Hinzufügen", "ButtonAddMediaLibrary": "Füge Medienbibliothek hinzu", "ButtonAddScheduledTaskTrigger": "Auslöser hinzufügen", @@ -1000,7 +1000,7 @@ "OptionLikes": "Mag ich", "OptionMissingEpisode": "Fehlende Episoden", "OptionMonday": "Montag", - "OptionNew": "Neu...", + "OptionNew": "Neu…", "OptionNone": "Keines", "OptionOnAppStartup": "Bei Anwendungsstart", "OptionOnInterval": "Nach einem Intervall", @@ -1528,5 +1528,6 @@ "MessageUnauthorizedUser": "Sie sind im Moment nicht berechtigt, auf den Server zuzugreifen. Bitte kontaktieren Sie Ihren Server-Administrator für weitere Informationen.", "HeaderFavoritePlaylists": "Lieblings-Wiedergabeliste", "ButtonTogglePlaylist": "Wiedergabeliste", - "ButtonToggleContextMenu": "Mehr" + "ButtonToggleContextMenu": "Mehr", + "ApiKeysCaption": "Liste der aktuell aktivierten API-Schlüssel" } diff --git a/src/strings/en-us.json b/src/strings/en-us.json index ee47d676a..077f430f1 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -17,7 +17,7 @@ "Alerts": "Alerts", "All": "All", "AllChannels": "All channels", - "AllComplexFormats": "All Complex Formats (ASS, SSA, VOBSUB, PGS, SUB, IDX)", + "AllComplexFormats": "All Complex Formats (ASS, SSA, VOBSUB, PGS, SUB, IDX, …)", "AllEpisodes": "All episodes", "AllLanguages": "All languages", "AllLibraries": "All libraries", @@ -25,7 +25,7 @@ "AllowMediaConversion": "Allow media conversion", "AllowMediaConversionHelp": "Grant or deny access to the convert media feature.", "AllowOnTheFlySubtitleExtraction": "Allow subtitle extraction on the fly", - "AllowOnTheFlySubtitleExtractionHelp": "Embedded subtitles can be extracted from videos and delivered to clients in plain text in order to help prevent video transcoding. On some systems this can take a long time and cause video playback to stall during the extraction process. Disable this to have embedded subtitles burned in with video transcoding when they are not natively supported by the client device.", + "AllowOnTheFlySubtitleExtractionHelp": "Embedded subtitles can be extracted from videos and delivered to clients in plain text, in order to help prevent video transcoding. On some systems this can take a long time and cause video playback to stall during the extraction process. Disable this to have embedded subtitles burned in with video transcoding when they are not natively supported by the client device.", "AllowFfmpegThrottling": "Throttle Transcodes", "AllowFfmpegThrottlingHelp": "When a transcode or remux gets far enough ahead from the current playback position, pause the process so it will consume less resources. This is most useful when watching without seeking often. Turn this off if you experience playback issues.", "AllowRemoteAccess": "Allow remote connections to this Jellyfin Server.", @@ -55,14 +55,14 @@ "BirthLocation": "Birth location", "BirthPlaceValue": "Birth place: {0}", "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", "Box": "Box", "BoxSet": "Box Set", "BoxRear": "Box (rear)", "Browse": "Browse", "BrowsePluginCatalogMessage": "Browse our plugin catalog to view available plugins.", - "BurnSubtitlesHelp": "Determines if the server should burn in subtitles when transcoding videos. Avoiding this will greatly improve performance. Select Auto to burn image based formats (VOBSUB, PGS, SUB, IDX) and certain ASS or SSA subtitles.", + "BurnSubtitlesHelp": "Determines if the server should burn in subtitles when transcoding videos. Avoiding this will greatly improve performance. Select Auto to burn image based formats (VOBSUB, PGS, SUB, IDX, …) and certain ASS or SSA subtitles.", "ButtonAdd": "Add", "ButtonAddImage": "Add Image", "ButtonAddMediaLibrary": "Add Media Library", @@ -311,6 +311,7 @@ "HeaderApiKey": "API Key", "HeaderApiKeys": "API Keys", "HeaderApiKeysHelp": "External applications are required to have an API key in order to communicate with Jellyfin Server. Keys are issued by logging in with a Jellyfin account, or by manually granting the application a key.", + "ApiKeysCaption": "List of the currently enabled API keys", "HeaderApp": "App", "HeaderAppearsOn": "Appears On", "HeaderAudioBooks": "Audio Books", @@ -1166,7 +1167,7 @@ "OptionMissingEpisode": "Missing Episodes", "OptionMonday": "Monday", "OptionNameSort": "Name", - "OptionNew": "New...", + "OptionNew": "New…", "OptionNone": "None", "OptionOnAppStartup": "On application startup", "OptionOnInterval": "On an interval", diff --git a/src/strings/eo.json b/src/strings/eo.json new file mode 100644 index 000000000..3151c9e43 --- /dev/null +++ b/src/strings/eo.json @@ -0,0 +1,5 @@ +{ + "AddToCollection": "Aldoni al kolekto", + "Actor": "Aktoro", + "Absolute": "Absoluto" +} diff --git a/src/strings/es-ar.json b/src/strings/es-ar.json index 69c571a57..2ea87c424 100644 --- a/src/strings/es-ar.json +++ b/src/strings/es-ar.json @@ -61,7 +61,7 @@ "Alerts": "Alertas", "All": "Todo", "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", "AllLanguages": "Todos los idiomas", "AllLibraries": "Todas las bibliotecas", @@ -500,5 +500,45 @@ "HeaderDeleteItem": "Eliminar ítem", "HeaderDeleteDevice": "Eliminar dispositivo", "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" } diff --git a/src/strings/es.json b/src/strings/es.json index 9a0997628..1ce442579 100644 --- a/src/strings/es.json +++ b/src/strings/es.json @@ -957,7 +957,7 @@ "OptionMissingEpisode": "Episodios que faltan", "OptionMonday": "Lunes", "OptionNameSort": "Nombre", - "OptionNew": "Nuevo...", + "OptionNew": "Nuevo…", "OptionNone": "Nada", "OptionOnAppStartup": "Al iniciar la aplicación", "OptionOnInterval": "En un intervalo", @@ -1513,5 +1513,6 @@ "ButtonToggleContextMenu": "Más", "Filter": "Filtro", "New": "Nuevo", - "HeaderFavoritePlaylists": "Lista reproducción favorita" + "HeaderFavoritePlaylists": "Lista reproducción favorita", + "ApiKeysCaption": "Lista de las claves API actuales" } diff --git a/src/strings/gsw.json b/src/strings/gsw.json index 452028eb4..2c5210969 100644 --- a/src/strings/gsw.json +++ b/src/strings/gsw.json @@ -7,7 +7,7 @@ "ButtonQuickStartGuide": "Schnellstart Instruktione", "ButtonResetPassword": "Passwort zrug setze", "ButtonSave": "Speichere", - "ButtonSignOut": "Sign out", + "ButtonSignOut": "Uslogge", "ButtonSort": "Sortiere", "ChannelAccessHelp": "Wähl en Kanal us, um de mit dem User z'teile. Administratore werded immer d'Möglichkeit ha alli Kanäl mitm Metadate Manager z'bearbeite.", "Continuing": "Fortlaufend", diff --git a/src/strings/he.json b/src/strings/he.json index 8d507070a..a3e4bc932 100644 --- a/src/strings/he.json +++ b/src/strings/he.json @@ -770,5 +770,7 @@ "Raised": "מורם", "LabelSpecialSeasonsDisplayName": "שם תצוגת \"עונה מיוחדת\":", "LabelSource": "מקור:", - "LabelSoundEffects": "אפקטי סאונד:" + "LabelSoundEffects": "אפקטי סאונד:", + "ButtonTogglePlaylist": "רשימת ניגון", + "ButtonToggleContextMenu": "עוד" } diff --git a/src/strings/hu.json b/src/strings/hu.json index 065460a64..61d4dfbf0 100644 --- a/src/strings/hu.json +++ b/src/strings/hu.json @@ -424,7 +424,7 @@ "OptionMissingEpisode": "Hiányzó Epizódok", "OptionMonday": "Hétfő", "OptionNameSort": "Név", - "OptionNew": "Új...", + "OptionNew": "Új…", "OptionParentalRating": "Korhatár besorolás", "OptionPlayCount": "Lejátszások száma", "OptionPlayed": "Megnézett", @@ -584,7 +584,7 @@ "Aired": "Adásban", "Albums": "Albumok", "AllChannels": "Minden csatorna", - "AllComplexFormats": "Minden összetett formátum (ASS, SSA, VOBSUB, PGS, SUB, IDX)", + "AllComplexFormats": "Minden összetett formátum (ASS, SSA, VOBSUB, PGS, SUB, IDX, ...)", "AllowMediaConversion": "Média konvertálás engedélyezése", "AllowMediaConversionHelp": "Add meg vagy tiltsd le a média konvertálás funkcióhoz való hozzáférést.", "AllowRemoteAccess": "Engedélyezze a távoli kapcsolatokat a Jellyfin szerverhez.", @@ -1511,5 +1511,6 @@ "ButtonToggleContextMenu": "Továbbiak", "Filter": "Szűrés", "New": "Új", - "HeaderFavoritePlaylists": "Kedvenc lejátszási listák" + "HeaderFavoritePlaylists": "Kedvenc lejátszási listák", + "ApiKeysCaption": "A jelenleg engedélyezett API kulcsok listája" } diff --git a/src/strings/it.json b/src/strings/it.json index 3adbeb203..3d09244c3 100644 --- a/src/strings/it.json +++ b/src/strings/it.json @@ -14,13 +14,13 @@ "Albums": "Album", "All": "Tutto", "AllChannels": "Tutti i canali", - "AllComplexFormats": "Tutti i formati complessi (ASS, SSA, VOBSUB, PGS, SUB, IDX)", + "AllComplexFormats": "Tutti i formati complessi (ASS, SSA, VOBSUB, PGS, SUB, IDX, ...)", "AllEpisodes": "Tutti gli episodi", "AllLanguages": "Tutte le lingue", "AllLibraries": "Tutte le librerie", "AllowHWTranscodingHelp": "Abilita il sintonizzatore per codificare i flussi al volo. Ciò potrebbe contribuire a ridurre la transcodifica richiesta dal server.", "AllowOnTheFlySubtitleExtraction": "Consenti l'estrazione sottotitoli al volo", - "AllowOnTheFlySubtitleExtractionHelp": "I sottotitoli incorporati possono essere estratti dai video e consegnati ad applicazioni in testo semplice per evitare la transcodifica dei video. In alcuni sistemi questo può richiedere molto tempo e causare un rallentamento della riproduzione video durante il processo di estrazione. Disattivare questa opzione per avere i sottotitoli incorporati con la transcodifica video quando non sono supportati nativamente dal dispositivo client.", + "AllowOnTheFlySubtitleExtractionHelp": "I sottotitoli incorporati possono essere estratti dai video e consegnati ai client in testo semplice per evitare la transcodifica dei video. In alcuni sistemi questo può richiedere molto tempo e causare un rallentamento della riproduzione video durante il processo di estrazione. Disattivare questa opzione per avere i sottotitoli incorporati con la transcodifica video quando non sono supportati nativamente dal dispositivo client.", "AllowRemoteAccess": "Abilita connessioni remote a questo Server Jellyfin.", "AllowRemoteAccessHelp": "Se deselezionato, tutte le connessioni remote saranno bloccate.", "AllowedRemoteAddressesHelp": "Elenco separato da virgola di indirizzi IP o voci IP / maschera di rete per reti che potranno connettersi da remoto. Se lasciato vuoto, saranno consentiti tutti gli indirizzi remoti.", @@ -40,12 +40,12 @@ "BirthDateValue": "Nato il: {0}", "BirthLocation": "Luogo di nascita", "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", "BoxRear": "Box (retro)", "Browse": "Esplora", "BrowsePluginCatalogMessage": "Sfoglia il catalogo dei Plugins.", - "BurnSubtitlesHelp": "Determina se il server deve imprimere i sottotitoli quando i video vengono convertiti. Evitare ciò migliorerà di molto le prestazioni. Selezionare Auto per imprimere formati basati sull'immagine (VOBSUB, PGS, SUB, IDX) e alcuni sottotitoli ASS o SSA.", + "BurnSubtitlesHelp": "Determina se il server deve imprimere i sottotitoli quando i video vengono convertiti. Evitare ciò migliorerà di molto le prestazioni. Selezionare Auto per imprimere formati basati sull'immagine (VOBSUB, PGS, SUB, IDX, ...) e alcuni sottotitoli ASS o SSA.", "ButtonAdd": "Aggiungi", "ButtonAddMediaLibrary": "Aggiungi raccolta multimediale", "ButtonAddScheduledTaskTrigger": "Aggiungi operazione", @@ -995,7 +995,7 @@ "OptionMissingEpisode": "Episodi mancanti", "OptionMonday": "Lunedì", "OptionNameSort": "Nome", - "OptionNew": "Nuovo...", + "OptionNew": "Nuovo…", "OptionNone": "Nessuno", "OptionOnAppStartup": "All'avvio", "OptionOnInterval": "Su intervallo", @@ -1504,5 +1504,8 @@ "MessageUnauthorizedUser": "Non sei autorizzato ad accedere in questo momento al server. Contatta l'amministratore per ulteriori dettagli.", "ButtonTogglePlaylist": "Playlist", "ButtonToggleContextMenu": "Altro", - "HeaderFavoritePlaylists": "Playlist Favorite" + "HeaderFavoritePlaylists": "Playlist Favorite", + "Filter": "Filtro", + "New": "Nuovo", + "ApiKeysCaption": "Elenco chiavi API abilitate" } diff --git a/src/strings/ko.json b/src/strings/ko.json index 138a2ee49..33c44334a 100644 --- a/src/strings/ko.json +++ b/src/strings/ko.json @@ -1325,7 +1325,7 @@ "MediaInfoPixelFormat": "픽셀 형식", "MapChannels": "채널 매핑", "LaunchWebAppOnStartupHelp": "서버가 처음 시작되면 웹 브라우저에서 웹 클라이언트를 실행하십시오. 서버 재시작의 경우에는 적용되지 않습니다.", - "Large": "큰", + "Large": "크게", "LanNetworksHelp": "대역폭을 강제로 제한할 때 로컬 네트워크로 간주되는 쉼표로 구분된 IP 주소 및 IP/서브넷 마스크 목록입니다. 지정될 경우 모든 다른 IP 주소는 외부 네트워크로 간주되며 외부 대역폭 제한이 적용됩니다. 공백일 경우 서버의 서브넷만이 로컬 네트워크로 간주됩니다.", "LabelffmpegPathHelp": "ffmpeg 실행 파일 혹은 ffmpeg를 포함하는 폴더 경로입니다.", "LabelXDlnaDocHelp": "urn:schemas-dlna-org:device-1-0 네임스페이스에 포함된 X_DLNADOC 요소의 내용을 결정합니다.", @@ -1430,5 +1430,8 @@ "MessageUnauthorizedUser": "현재 서버에 접속할 권한이 없습니다. 자세한 정보는 서버 관리자에게 문의하십시오.", "HeaderFavoritePlaylists": "즐겨찾는 플레이리스트", "ButtonTogglePlaylist": "플레이리스트", - "ButtonToggleContextMenu": "더보기" + "ButtonToggleContextMenu": "더보기", + "Rate": "평", + "PerfectMatch": "정확히 일치", + "OtherArtist": "다른 아티스트" } diff --git a/src/strings/lv.json b/src/strings/lv.json index 8c19b23ad..8aa0fd525 100644 --- a/src/strings/lv.json +++ b/src/strings/lv.json @@ -239,7 +239,7 @@ "Kids": "Bērni", "Items": "Vienumi", "ItemCount": "{0} vienumi", - "InstallingPackage": "Instalē {0}", + "InstallingPackage": "Instalē {0} (versija {1})", "Images": "Attēli", "Identify": "Identificēt", "Horizontal": "Horizontāls", @@ -455,7 +455,7 @@ "DrmChannelsNotImported": "Kanāli ar DRM netiks importēti.", "DownloadsValue": "{0} lejupielādes", "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", "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ā", @@ -605,8 +605,8 @@ "Art": "Māksla", "AroundTime": "Ap {0}", "Anytime": "Jebkad", - "AnyLanguage": "Jebkura valoda", - "AlwaysPlaySubtitles": "Vienmēr rādīt subtitrus", + "AnyLanguage": "Jebkura Valoda", + "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.", "AllowRemoteAccessHelp": "Ja atķeksēts, visi attālinātie savienojumi tiks bloķēti.", "AllowRemoteAccess": "Atļaut attālinātus savienojumus šim Jellyfin Serverim.", @@ -615,7 +615,7 @@ "AllLibraries": "Visas bibliotēkas", "AllLanguages": "Visas valodas", "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", "All": "Viss", "Alerts": "Paziņojumi", @@ -951,8 +951,8 @@ "HeaderCustomDlnaProfiles": "Pielāgoti Profili", "HeaderConfirmProfileDeletion": "Apstiprināt Profila Dzēšanu", "HeaderChapterImages": "Nodaļu Attēli", - "HeaderCastCrew": "Lomas/Apkalpe", - "HeaderCastAndCrew": "Lomas/Apkalpe", + "HeaderCastCrew": "Lomas & Apkalpe", + "HeaderCastAndCrew": "Lomas un Apkalpe", "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.", "HeaderAdditionalParts": "Papildus Ceļi", @@ -1001,7 +1001,7 @@ "ButtonArrowLeft": "Kreisi", "ButtonArrowDown": "Lejup", "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", "AuthProviderHelp": "Izvēlies Autentifikācijas Nodrošinājumu, kas tiks izmantots lai autentificētu šī lietotāja paroli.", "AspectRatio": "Attēla Proporcijas", @@ -1081,5 +1081,58 @@ "OptionAllowBrowsingLiveTv": "Atļaut Tiešraides TV piekļuvi", "MediaInfoForced": "Piespiests", "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" } diff --git a/src/strings/pl.json b/src/strings/pl.json index 431ea3feb..1cea825bf 100644 --- a/src/strings/pl.json +++ b/src/strings/pl.json @@ -54,7 +54,7 @@ "BoxRear": "Pudełko (tył)", "Browse": "Przeglądaj", "BrowsePluginCatalogMessage": "Przejrzyj nasz katalog wtyczek żeby zobaczyć dostępne wtyczki.", - "BurnSubtitlesHelp": "Określa czy serwer powinien wypalać napisy podczas konwersji wideo, w zależności od formatu napisów. Unikanie wypalania napisów poprawia wydajność serwera. Wybierz Automatycznie, w celu wypalania zarówno napisów w formatach graficznych (np. VOBSUB, PGS, SUB/IDX, itp.), jak i pewnych napisów ASS/SSA.", + "BurnSubtitlesHelp": "Określa czy serwer powinien wypalać napisy podczas konwersji wideo, w zależności od formatu napisów. Unikanie wypalania napisów znacząco poprawia wydajność serwera. Wybierz Automatycznie, w celu wypalania zarówno napisów w formatach graficznych (np. VOBSUB, PGS, SUB/IDX), jak i pewnych napisów ASS lub SSA.", "ButtonAdd": "Dodaj", "ButtonAddMediaLibrary": "Dodaj media do biblioteki", "ButtonAddScheduledTaskTrigger": "Dodaj wyzwalacz", @@ -190,7 +190,7 @@ "DisplayInOtherHomeScreenSections": "Wyświetlaj na ekranie startowym sekcje Ostatnio dodane i Kontynuuj odtwarzanie", "DisplayMissingEpisodesWithinSeasons": "Wyświetlaj w sezonach brakujące odcinki", "DisplayMissingEpisodesWithinSeasonsHelp": "Ta opcja musi zostać dodatkowo aktywowana w bibliotece seriali, w konfiguracji serwera.", - "DisplayModeHelp": "Określa typ urządzenia, na którym uruchomiono Jellyfin.", + "DisplayModeHelp": "Wybierz styl układu interfejsu.", "DoNotRecord": "Nie nagrywaj", "Down": "W dół", "Download": "Pobierz", @@ -490,7 +490,7 @@ "Images": "Obrazy", "ImportFavoriteChannelsHelp": "Jeśli aktywne, tylko kanały oznaczone jako ulubione na tunerze, będą importowane.", "ImportMissingEpisodesHelp": "W przypadku aktywacji tej opcji, informacje o brakujących odcinkach zostaną zaimportowane do bazy Jellyfin i będą wyświetlane na listach sezonów i seriali. Może to jednak znacznie wydłużyć czas skanowania biblioteki.", - "InstallingPackage": "Instalowanie {0}", + "InstallingPackage": "Instalowanie {0} (wersja {1})", "InstantMix": "Szybki remiks", "ItemCount": "{0} pozycje", "Items": "Pozycje", @@ -953,16 +953,16 @@ "NoNextUpItemsMessage": "Nie znaleziono niczego. Zacznij oglądać swoje seriale!", "NoPluginConfigurationMessage": "Ta wtyczka nie ma żadnych ustawień.", "NoSubtitleSearchResultsFound": "Brak wyników wyszukiwania.", - "NoSubtitles": "Brak napisów", + "NoSubtitles": "Brak", "NoSubtitlesHelp": "Domyślnie napisy nie będą wczytywane. Można je ciągle włączyć ręcznie podczas odtwarzania.", "None": "Brak", "Normal": "Normalny", "NumLocationsValue": "{0} foldery", "Off": "Wyłączone", "OneChannel": "Jeden kanał", - "OnlyForcedSubtitles": "Tylko wymuszone napisy", + "OnlyForcedSubtitles": "Tylko wymuszone", "OnlyForcedSubtitlesHelp": "Tylko napisy oznaczone jako wymuszone będą wczytywane.", - "OnlyImageFormats": "Tylko formaty graficzne (VOBSUB, PGS, SUB, itp.)", + "OnlyImageFormats": "Tylko Formaty Graficzne (VOBSUB, PGS, SUB)", "OptionAdminUsers": "Administratorzy", "OptionAlbumArtist": "Wykonawca albumu", "OptionAllUsers": "Wszyscy użytkownicy", @@ -1100,7 +1100,7 @@ "OptionWeekly": "Cotygodniowo", "OriginalAirDateValue": "Data pierwszej emisji: {0}", "Overview": "Opis", - "PackageInstallCancelled": "Instalacja {0} anulowana.", + "PackageInstallCancelled": "Instalacja {0} (wersja {1}) anulowana.", "PackageInstallCompleted": "Instalacja {0} zakończona.", "PackageInstallFailed": "Instalacja {0} nieudana.", "ParentalRating": "Kategoria wiekowa", @@ -1470,5 +1470,18 @@ "EnableFastImageFadeIn": "Szybkie pojawianie się obrazów", "Artist": "Artysta", "AlbumArtist": "Album artysty", - "Album": "Album" + "Album": "Album", + "Person": "Osoba", + "OtherArtist": "Inny artysta", + "Movie": "Film", + "MessageUnauthorizedUser": "Nie masz dostępu do zasobów serwera. Skontaktuj się z administratorem sieci, aby uzyskać więcej informacji.", + "LabelLibraryPageSizeHelp": "Ustaw liczbę pozycji pokazywanych na stronie biblioteki. Ustaw 0, aby wyłączyć podział na strony.", + "LabelLibraryPageSize": "Rozmiar strony biblioteki:", + "LabelDeinterlaceMethod": "Metoda usuwania przeplotu:", + "HeaderFavoritePlaylists": "Ulubione Playlisty", + "Episode": "Odcinek", + "DeinterlaceMethodHelp": "Wybierz metodę usuwania przeplotu używaną podczas transkodowania.", + "ClientSettings": "Ustawienia klienta", + "ButtonTogglePlaylist": "Playlista", + "ButtonToggleContextMenu": "Więcej" } diff --git a/src/strings/pt-br.json b/src/strings/pt-br.json index 16b6e0313..d7418749e 100644 --- a/src/strings/pt-br.json +++ b/src/strings/pt-br.json @@ -182,7 +182,7 @@ "DisplayInOtherHomeScreenSections": "Exibir nas seções da tela inicial como mídia recente e continuar assistindo", "DisplayMissingEpisodesWithinSeasons": "Exibir episódios em falta nas temporadas", "DisplayMissingEpisodesWithinSeasonsHelp": "Isto também deve ser ativado para as bibliotecas de TV na configuração do servidor.", - "DisplayModeHelp": "Seleciona o tipo de tela para executar o Jellyfin.", + "DisplayModeHelp": "Selecione o estilo de layout que deseje para a interface.", "DoNotRecord": "Não gravar", "Down": "Baixo", "DrmChannelsNotImported": "Canais com DRM não serão importados.", @@ -626,7 +626,7 @@ "LabelKodiMetadataEnablePathSubstitution": "Ativar substituição de local", "LabelKodiMetadataEnablePathSubstitutionHelp": "Ativa a substituição do local das imagens usando as configurações de substituição de local do servidor.", "LabelKodiMetadataSaveImagePaths": "Salvar o local das imagens dentro dos arquivos nfo", - "LabelKodiMetadataSaveImagePathsHelp": "Isto é recomendado se os nomes dos arquivos de imagem não estão de acordo com as recomendações do Kodi.", + "LabelKodiMetadataSaveImagePathsHelp": "Isto é recomendado se os nomes dos arquivos de imagem não estão de acordo com as exigências do Kodi.", "LabelKodiMetadataUser": "Salvar informações do que o usuário assiste aos NFO's para:", "LabelKodiMetadataUserHelp": "Salva os dados para arquivos NFO para que outras aplicações possam usar.", "LabelLanNetworks": "Redes LAN:", @@ -1021,7 +1021,7 @@ "OptionMissingEpisode": "Episódios em Falta", "OptionMonday": "Segunda-feira", "OptionNameSort": "Nome", - "OptionNew": "Novo...", + "OptionNew": "Novo…", "OptionNone": "Nenhum", "OptionOnAppStartup": "Ao iniciar a aplicação", "OptionOnInterval": "Em um intervalo", @@ -1503,5 +1503,9 @@ "UnsupportedPlayback": "O Jellyfin não pode descriptografar conteúdo protegido por DRM, porém mesmo assim fará uma tentativa para todo tipo de conteúdo, incluindo títulos protegidos. A imagem de alguns arquivos pode aparecer completamente preta devido a criptografia ou outros recursos não suportados, como títulos interativos.", "MessageUnauthorizedUser": "Você não está autorizado a acessar o servidor neste momento. Por favor, contate o administrador do servidor para mais informações.", "ButtonTogglePlaylist": "Playlist", - "ButtonToggleContextMenu": "Mais" + "ButtonToggleContextMenu": "Mais", + "Filter": "Filtro", + "New": "Novo", + "HeaderFavoritePlaylists": "Playlists Favoritas", + "ApiKeysCaption": "Lista de chaves API ativadas no momento" } diff --git a/src/strings/ro.json b/src/strings/ro.json index de53cabc6..aa6bdf4a3 100644 --- a/src/strings/ro.json +++ b/src/strings/ro.json @@ -249,7 +249,7 @@ "ButtonStop": "Stop", "ButtonSubmit": "Trimite", "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.", "AlwaysPlaySubtitles": "Întotdeauna arată", "AnyLanguage": "Orice Limbă", @@ -288,7 +288,7 @@ "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.", "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ă", "ButtonRevoke": "Revocă", "ButtonSettings": "Setări", @@ -304,14 +304,14 @@ "Delete": "Șterge", "DeleteImage": "Șterge Imaginea", "DeleteUserConfirmation": "Sigur doriți să ștergeți acest utilizator?", - "Depressed": "Depresat", + "Depressed": "Deprimat", "Descending": "Descendent", "DetectingDevices": "Detectez dispozitive", "DirectPlaying": "Redare directă", "DirectStreamHelp2": "Transmiterea directă a unui fișier utilizează foarte puțină putere de procesare fără pierderi în calitatea video.", "DirectStreaming": "Transmitere directă", "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", "ButtonArrowUp": "Sus", "ButtonAudioTracks": "Cale Audio", @@ -511,7 +511,7 @@ "GuestStar": "Vedeta invitata", "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.", - "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", "HeaderAccessScheduleHelp": "Creați un program de acces pentru a limita accesul la anumite ore.", "HeaderActiveDevices": "Dispozitive active", @@ -1334,7 +1334,7 @@ "OptionOnInterval": "La un interval", "OptionOnAppStartup": "La pornirea aplicației", "OptionNone": "Nici unul", - "OptionNew": "Nou...", + "OptionNew": "Nou…", "OptionMissingEpisode": "Episoade lipsă", "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.", @@ -1359,9 +1359,9 @@ "OptionEnableExternalContentInSuggestions": "Activați conținut extern în sugestii", "OptionEmbedSubtitles": "Inclus în container", "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", - "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.", "OptionDisplayFolderView": "Afișați o vizualizare de dosar pentru a afișa dosarele media simple", "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}", "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.", - "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.", - "AllowFfmpegThrottling": "Accelerare Transcod-uri", + "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": "Limitare Transcod-uri", "Track": "Cale", "Season": "Sezon", "ReleaseGroup": "Gruparea lansării", @@ -1493,7 +1493,7 @@ "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.", "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", "LabelDeinterlaceMethod": "Metoda de intercalare:", "DeinterlaceMethodHelp": "Selectați metoda de intercalat pe care să o utilizați la transcodarea conținutului intercalat.", @@ -1505,5 +1505,6 @@ "ButtonToggleContextMenu": "Mai mult", "Filter": "Filtru", "New": "Nou", - "HeaderFavoritePlaylists": "Listă Favorită" + "HeaderFavoritePlaylists": "Listă Favorită", + "ApiKeysCaption": "Lista cheilor API active" } diff --git a/src/strings/sk.json b/src/strings/sk.json index d56b9fc59..05d0913f6 100644 --- a/src/strings/sk.json +++ b/src/strings/sk.json @@ -5,7 +5,7 @@ "Albums": "Albumy", "All": "Všetko", "AllChannels": "Všetky kanály", - "AllComplexFormats": "Všetky komplexné formáty (ASS, SSA, VOBSUB, PGS, SUB, IDX)", + "AllComplexFormats": "Všetky komplexné formáty (ASS, SSA, VOBSUB, PGS, SUB, IDX, …)", "AllEpisodes": "Všetky epizódy", "AllLanguages": "Všetky jazyky", "AllLibraries": "Všetky knižnice", @@ -25,7 +25,7 @@ "BirthDateValue": "Narodený/á: {0}", "BirthLocation": "Miesto narodenia", "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", "ButtonAdd": "Pridať", "ButtonAddMediaLibrary": "Pridať knižnicu médií", @@ -648,7 +648,7 @@ "OptionMissingEpisode": "Chýbajúce epizódy", "OptionMonday": "Pondelok", "OptionNameSort": "Názov", - "OptionNew": "Nové...", + "OptionNew": "Nové…", "OptionNone": "Žiadne", "OptionOnAppStartup": "Pri spustení aplikácie", "OptionParentalRating": "Rodičovské hodnotenie", @@ -1180,7 +1180,7 @@ "CancelSeries": "Ukončiť seriál", "ButtonSplit": "Rozdeliť", "ButtonAddImage": "Pridať obrázok", - "BurnSubtitlesHelp": "Určuje, či má server vpáliť titulky počas transkódovania videa. Vynechanie tejto možnosti výrazne zvýši výkon. Vyberte možnosť Auto, pokiaľ chcete vpáliť do obrazu titulky v grafickom formáte (VOBSUB, PGS, SUB, IDX) a niektoré ASS alebo SSA titulky.", + "BurnSubtitlesHelp": "Určuje, či má server vpáliť titulky počas transkódovania videa. Vynechanie tejto možnosti výrazne zvýši výkon. Vyberte možnosť Auto, pokiaľ chcete vpáliť do obrazu titulky v grafickom formáte (VOBSUB, PGS, SUB, IDX, …) a niektoré ASS alebo SSA titulky.", "BrowsePluginCatalogMessage": "Prehliadnite si náš katalóg dostupných zásuvných modulov.", "Browse": "Prechádzať", "Blacklist": "Blacklist", @@ -1189,7 +1189,7 @@ "Art": "Umenie", "AlwaysPlaySubtitlesHelp": "Titulky odpovedajúce jazykovej preferencií sa načítajú bez ohľadu na jazyk zvuku.", "AllowedRemoteAddressesHelp": "Zoznam IP adries alebo IP/netmask záznamov pre siete oddelené čiarkami z ktorých sa dá vzdialene pripojiť. Pokiaľ zoznam bude prázdny, všetky adresy budú povolené.", - "AllowOnTheFlySubtitleExtractionHelp": "Vložené titulky môžu byť extrahované z videa a prenesené na klienta vo forme jednoduchého textu aby sa zabránilo transkódovaniu videa. Na niektorých systémoch táto operácia môže trvať dlhší čas a a spôsobiť sekanie videa počas počas extrahovania. Vypnutie tejto funkcie bude mať za následok, že titulky budú počas transkódovania vypálené do samotného videa pokiaľ klientské zariadenie natívne nepodporuje ich formát.", + "AllowOnTheFlySubtitleExtractionHelp": "Vložené titulky môžu byť extrahované z videa a prenesené na klienta vo forme jednoduchého textu, aby sa zabránilo transkódovaniu videa. Na niektorých systémoch táto operácia môže trvať dlhší čas a a spôsobiť sekanie videa počas počas extrahovania. Vypnutie tejto funkcie bude mať za následok, že titulky budú počas transkódovania vypálené do samotného videa pokiaľ klientské zariadenie natívne nepodporuje ich formát.", "Watched": "Pozreté", "TvLibraryHelp": "Pozrite sa na {0}sprievodcu pomenovania TV programov{1}.", "LabelLineup": "Lineup:", @@ -1507,5 +1507,6 @@ "New": "Nové", "HeaderFavoritePlaylists": "Obľúbené playlisty", "ButtonTogglePlaylist": "Playlist", - "ButtonToggleContextMenu": "Viac" + "ButtonToggleContextMenu": "Viac", + "ApiKeysCaption": "Zoznam v súčasnosti povolených API kľúčov" } diff --git a/src/strings/sv.json b/src/strings/sv.json index d93222199..443549e79 100644 --- a/src/strings/sv.json +++ b/src/strings/sv.json @@ -2,7 +2,7 @@ "AccessRestrictedTryAgainLater": "För närvarande är åtkomsten begränsad. Försök igen senare.", "Actor": "Skådespelare", "Add": "Lägg till", - "AddItemToCollectionHelp": "Lägg till objekt i samlingar genom att söka efter dem och använda deras högerklick- eller knackmeny", + "AddItemToCollectionHelp": "Lägg till objekt i samlingar genom att söka efter dem och använda deras högerklick- eller pekmeny för att lägga till dem i en samling.", "AddToCollection": "Lägg till i samling", "AddToPlayQueue": "Lägg till i spelkö", "AddToPlaylist": "Lägg till i spellista", @@ -898,7 +898,7 @@ "NumLocationsValue": "{0} mappar", "Off": "Av", "OneChannel": "En kanal", - "OnlyForcedSubtitles": "Endast tvingande undertexter", + "OnlyForcedSubtitles": "Endast påtvingad", "OnlyForcedSubtitlesHelp": "Endast undertexter markerade som tvingande kommer att laddas.", "OnlyImageFormats": "Endast bildbaserade format (VOBSUB, PGS, SUB, etc)", "OptionAdminUsers": "Administratörer", @@ -1492,5 +1492,20 @@ "Artist": "Artist", "ButtonTogglePlaylist": "Spellista", "ButtonToggleContextMenu": "Mer", - "AlbumArtist": "Albumartist" + "AlbumArtist": "Albumartist", + "LabelLibraryPageSize": "Bibliotekets sidstorlek:", + "LabelDeinterlaceMethod": "Deinterlacing-metod:", + "WeeklyAt": "{0}s vid {1}", + "LastSeen": "Senast sedd {0}", + "YadifBob": "YADIF Bob", + "Yadif": "YADIF", + "Filter": "Filter", + "New": "Ny", + "MessageUnauthorizedUser": "Du har inte behörighet att komma åt servern just nu. Kontakta din serveradministratör för mer information.", + "HeaderFavoritePlaylists": "Favoritspellista", + "OnWakeFromSleep": "Vid start från vilande läge", + "UnsupportedPlayback": "Jellyfin kan inte dekryptera inehåll skyddat av DRM men allt inehåll kommer ändå försökas, även skyddade titlar. Vissa filer kan se helt svart ut på grund av kryptering eller andra funktioner som inte stöds, till exempel interaktiva titlar.", + "LabelLibraryPageSizeHelp": "Sätter en begränsad sidstorlek i bibliotek. Sätt 0 för att avaktivera begränsad sidstorlek.", + "ApiKeysCaption": "Lista av aktiva API-nycklar", + "DeinterlaceMethodHelp": "Välj metod för borttagning av inflätning vid konvertering av inflätat inehåll." } diff --git a/src/strings/uk.json b/src/strings/uk.json index 1c4c49774..5a859a4ae 100644 --- a/src/strings/uk.json +++ b/src/strings/uk.json @@ -93,17 +93,17 @@ "ValueSeriesCount": "{0} серій", "ValueSongCount": "{0} пісень", "AddToPlaylist": "Додати до списку відтворення", - "AccessRestrictedTryAgainLater": "На даний момент доступ заборонений. Будь ласка спробуйте пізніше.", + "AccessRestrictedTryAgainLater": "На цей момент доступ заборонений. Повторіть спробу пізніше.", "Actor": "Виконавець", - "AllLanguages": "Всі мови", - "AllLibraries": "Всі бібліотеки", + "AllLanguages": "Усі мови", + "AllLibraries": "Усі бібліотеки", "AddToCollection": "Додати до колекції", "AddToPlayQueue": "Додати до черги відтворення", "All": "Всі", "AllChannels": "Всі канали", "AllEpisodes": "Всі епізоди", "AllowRemoteAccess": "Дозволити віддалене підключення до цього сервера Jellyfin.", - "AlwaysPlaySubtitles": "Завжди відтворювати субтитри", + "AlwaysPlaySubtitles": "Завжди вмикати субтитри", "AnyLanguage": "Будь-яка мова", "Anytime": "Завжди", "Add": "Додати", @@ -136,5 +136,28 @@ "Alerts": "Термінові сповіщення", "AlbumArtist": "Виконавець альбому", "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, …)" } diff --git a/src/strings/vi.json b/src/strings/vi.json index 65fcd88ef..9ff05dcb6 100644 --- a/src/strings/vi.json +++ b/src/strings/vi.json @@ -167,11 +167,11 @@ "ButtonAddScheduledTaskTrigger": "Thêm kích hoạt", "ButtonAddMediaLibrary": "Thêm thư viện Media", "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", "BoxRear": "Hộp (mặt sau)", "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", "BirthPlaceValue": "Nơi sinh: {0}", "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.", "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.", - "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", "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", @@ -204,7 +204,7 @@ "AllLibraries": "Tất cả các thư viện", "AllLanguages": "Tất cả các ngôn ngữ", "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", "Alerts": "Cảnh Báo", "Albums": "Albums", @@ -564,5 +564,147 @@ "HeaderSortOrder": "Thứ tự Sắp xếp", "HeaderSortBy": "Sắp xếp theo", "HeaderStartNow": "Bắt đầu", - "HeaderSetupLibrary": "Thiết lập thư viện nội dung của bạn" + "HeaderSetupLibrary": "Thiết lập thư viện nội dung của bạn", + "HeaderTracks": "Bài Hát", + "HeaderThisUserIsCurrentlyDisabled": "Người dùng này hiện tại đang bị khoá", + "HeaderTaskTriggers": "Kích Hoạt Tác Vụ", + "HeaderTags": "Nhãn", + "HeaderSubtitleProfilesHelp": "Hồ sơ phụ đề chỉ ra những định dạng phụ đề được hỗ trợ bởi thiết bị phát.", + "HeaderSubtitleProfiles": "Hồ Sơ Phụ Đề", + "HeaderSubtitleProfile": "Hồ Sơ Phụ Đề", + "HeaderSubtitleDownloads": "Tải Phụ Đề", + "HeaderSubtitleAppearance": "Giao Diện Phụ Đề", + "HeaderStopRecording": "Ngừng Ghi Hình/Ghi Âm", + "HeaderSpecialFeatures": "Những Phần Đặc Biệt Nổi Bật", + "HeaderSpecialEpisodeInfo": "Thông Tin Tập Đặc Biệt", + "HeaderShutdown": "Tắt Máy Chủ", + "LabelCustomDeviceDisplayNameHelp": "Cung cấp một tên hiển thị riêng hoặc bỏ trống để sử dụng tên có sẵn của thiết bị.", + "LabelCustomDeviceDisplayName": "Tên hiển thị:", + "LabelCustomCssHelp": "Áp dụng tuỳ chỉnh riêng của bạn vào giao diện trang web.", + "LabelCustomCss": "CSS tuỳ chọn:", + "LabelCustomCertificatePathHelp": "Đường dẫn đến tập tin PKCS #12 chứa chứng chỉ (certificate) và khoá riêng (private key) để bật tính năng TLS trên một tên miền tuỳ chọn.", + "LabelCustomCertificatePath": "Đường dẫn đến chứng chỉ SSL:", + "LabelCriticRating": "Đánh giá phê bình:", + "LabelCorruptedFrames": "Những khung hình bị lỗi:", + "LabelContentType": "Loại nội dung:", + "LabelCommunityRating": "Đánh giá của cộng đồng:", + "LabelCollection": "Bộ Sưu Tập:", + "LabelChannels": "Kênh:", + "LabelCertificatePasswordHelp": "Nếu chứng chỉ của bạn cần mật khẩu, hãy nhập nó ở đây.", + "LabelCertificatePassword": "Mật khẩu chứng chỉ:", + "LabelCancelled": "Đã Huỷ", + "LabelCachePathHelp": "Chọn một đường dẫn cho những tập tin lưu tạm như là hình ảnh. Bỏ trống để sử dụng cài đặt mặc định của máy chủ.", + "LabelCachePath": "Đường dẫn cache:", + "LabelCache": "Cache:", + "LabelBurnSubtitles": "Nhúng phụ đề:", + "LabelBlockContentWithTags": "Chặn những mục có nhãn:", + "LabelBlastMessageIntervalHelp": "Xác định thời gian tồn tại giữa các tin nhắn (tính bằng giây).", + "LabelBlastMessageInterval": "Thời gian tồn tại của tin nhắn (giây)", + "LabelBitrate": "Bitrate:", + "LabelBirthYear": "Năm sinh:", + "LabelBirthDate": "Ngày sinh:", + "LabelBindToLocalNetworkAddressHelp": "Không bắt buộc. Cài đặt đè địa chỉ IP nội bộ để kết nối đến máy chủ HTTP. Nếu bỏ trống, máy chủ sẽ cài đặt vào toàn bộ những địa chỉ nội bộ có sẵn. Nếu thay đổi tuỳ chọn này, cần phải khởi động lại máy chủ Jellyfin để có tác dụng.", + "LabelBindToLocalNetworkAddress": "Cài đặt vào địa chỉ nội bộ:", + "LabelAutomaticallyRefreshInternetMetadataEvery": "Tự động cập nhật dữ liệu bổ trợ từ Internet:", + "LabelAuthProvider": "Nhà Cung Cấp Xác Thực:", + "LabelAudioSampleRate": "Sample rate âm thanh:", + "LabelAudioCodec": "Bộ giải mã âm thanh:", + "LabelAudioChannels": "Các kênh âm thanh:", + "LabelAudioBitrate": "Bitrate của âm thanh:", + "LabelAudioBitDepth": "Chiều sâu của âm thanh:", + "LabelAudio": "Âm Thanh", + "LabelArtistsHelp": "Sử dụng dấu ; để tách rời nhiều nghệ", + "LabelArtists": "Nghệ sĩ:", + "LabelAppNameExample": "Ví dụ: Sickbeard, Sonarr", + "LabelAppName": "Tên ứng dụng", + "LabelAllowedRemoteAddressesMode": "Chế độ bộ lọc địa chỉ IP từ xa:", + "LabelAllowedRemoteAddresses": "Bộ lọc địa chỉ IP từ xa:", + "LabelAllowServerAutoRestartHelp": "Máy chủ chỉ khởi động lại trong thời gian rỗi khi không có người dùng đang sử dụng.", + "LabelAllowHWTranscoding": "Cho phép chuyển mã bằng phần cứng", + "LabelAll": "Tất Cả", + "LabelAlbumArtists": "Nghệ sĩ album:", + "LabelAlbumArtPN": "Bìa album PN:", + "LabelAlbumArtMaxWidthHelp": "Độ phân giải cao nhất của bìa album thông qua upnp:albumArtURI.", + "LabelAlbumArtMaxWidth": "Chiều ngang lớn nhất của bìa album:", + "LabelAlbumArtMaxHeightHelp": "Độ phân giải cao nhất của bìa album thông qua upnp:albumArtURI.", + "LabelAlbumArtMaxHeight": "Chiều cao lớn nhất của bìa album:", + "LabelAlbumArtHelp": "PN được sử dụng cho bìa album, trong dlna:profileID thuộc tính upnp:albumArtURI. Một vài thiết bị phát cần một giá trị đặc biệt, không ảnh hưởng đến kích thước của hình ảnh.", + "LabelAlbum": "Album:", + "LabelAirsBeforeSeason": "Phát sóng trước mùa:", + "LabelAirsBeforeEpisode": "Phát sóng trước tập:", + "LabelAirsAfterSeason": "Phát sóng sau mùa:", + "LabelAirTime": "Thời gian phát sóng:", + "LabelAirDays": "Ngày phát sóng:", + "LabelAccessStart": "Thời gian bắt đầu:", + "LabelAccessEnd": "Thời gian kết thúc:", + "LabelAccessDay": "Ngày trong tuần:", + "LabelAbortedByServerShutdown": "(Đã huỷ bởi máy chủ ngừng hoạt động)", + "Label3DFormat": "Định dạng 3D:", + "Kids": "Trẻ Em", + "Items": "Mục", + "ItemCount": "{0} mục", + "InstantMix": "Trộn Lẫn Nhanh", + "InstallingPackage": "Đang cài đặt {0} (phiên bản {1})", + "ImportMissingEpisodesHelp": "Nếu bật tuỳ chọn này, thông tin bị thiếu trong các tập phim sẽ được nhập vào cơ sở dữ liệu của máy chủ Jellyfin và hiển thị trong các phần và series. Điều này có thể làm việc quét thư viện lâu hơn rất nhiều.", + "ImportFavoriteChannelsHelp": "Nếu bật tuỳ chọn này, chỉ những kênh yêu thích trong thiết bị bắt sóng sẽ được nhập vào.", + "Images": "Hình Ảnh", + "Identify": "Nhận Dạng", + "HttpsRequiresCert": "Để bật kết nối bảo mật, bạn cần phải cung cấp một Chứng Chỉ SSL đáng tin cậy, ví dụ như \"Let's Encrypt\". Hãy cung cấp Chứng Chỉ SSL hoặc là tắt tính năng kết nối bảo mật.", + "Horizontal": "Nằm Ngang", + "Home": "Trang Chủ", + "HideWatchedContentFromLatestMedia": "Ẩn những nội dung đã xem khỏi phần nội dung mới nhất", + "Hide": "Ẩn", + "Help": "Trợ Giúp", + "HeadersFolders": "Thư Mục", + "HeaderYears": "Năm", + "HeaderXmlSettings": "Cài Đặt XML", + "HeaderXmlDocumentAttributes": "Những Thuộc Tính Tài Liệu XML", + "HeaderXmlDocumentAttribute": "Thuộc Tính Tài Liệu XML", + "HeaderVideos": "Videos", + "HeaderVideoTypes": "Kiểu Video", + "HeaderVideoType": "Kiểu Video", + "HeaderVideoQuality": "Chất Lượng Video", + "HeaderUser": "Người Dùng", + "HeaderUploadImage": "Tải Lên Hình Ảnh", + "HeaderUpcomingOnTV": "Sắp Phát Sóng Trên TV", + "HeaderTypeText": "Nhập nội dung", + "HeaderTypeImageFetchers": "{0} Trình Tải Hình Ảnh", + "HeaderTuners": "Bộ Điều Khiển Thu Phá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ã.", + "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" } diff --git a/src/strings/zh-tw.json b/src/strings/zh-tw.json index f5020837f..4c7645226 100644 --- a/src/strings/zh-tw.json +++ b/src/strings/zh-tw.json @@ -212,7 +212,7 @@ "OptionMissingEpisode": "缺少了的單元", "OptionMonday": "星期一", "OptionNameSort": "名字", - "OptionNew": "新增...", + "OptionNew": "新增…", "OptionOnAppStartup": "在伺服器啟動", "OptionOnInterval": "每時段", "OptionParentalRating": "家長評級", @@ -1678,5 +1678,10 @@ "DeinterlaceMethodHelp": "選擇對隔行掃描內容進行轉碼時所用的反交錯方法。", "BoxSet": "套裝", "UnsupportedPlayback": "Jellyfin 無法解密受 DRM 保護的內容,但仍然會嘗試播放所有內容。某些檔案由於被加密或包含如互動標題等不受支援的內容,在播放時可能會沒有畫面。", - "MessageUnauthorizedUser": "您目前無權存取伺服器,請與您的伺服器管理員聯繫以獲取更多訊息。" + "MessageUnauthorizedUser": "您目前無權存取伺服器,請與您的伺服器管理員聯繫以獲取更多訊息。", + "Filter": "篩選器", + "New": "新增", + "ApiKeysCaption": "目前已啟用的API金鑰列表", + "ButtonTogglePlaylist": "播放清單", + "ButtonToggleContextMenu": "更多" } diff --git a/src/useredit.html b/src/useredit.html index 0de3069dc..253387b4a 100644 --- a/src/useredit.html +++ b/src/useredit.html @@ -6,7 +6,7 @@ diff --git a/src/userlibraryaccess.html b/src/userlibraryaccess.html index 4653fd07e..8a6177585 100644 --- a/src/userlibraryaccess.html +++ b/src/userlibraryaccess.html @@ -6,7 +6,7 @@ diff --git a/src/usernew.html b/src/usernew.html index bca1e72fe..fac036aa8 100644 --- a/src/usernew.html +++ b/src/usernew.html @@ -5,7 +5,7 @@

${HeaderAddUser}

- ${Help} + ${Help}
diff --git a/src/userparentalcontrol.html b/src/userparentalcontrol.html index f320c361f..2c13ec801 100644 --- a/src/userparentalcontrol.html +++ b/src/userparentalcontrol.html @@ -4,7 +4,7 @@ diff --git a/src/userpassword.html b/src/userpassword.html index f38e39599..119a0212d 100644 --- a/src/userpassword.html +++ b/src/userpassword.html @@ -4,7 +4,7 @@ diff --git a/src/userprofiles.html b/src/userprofiles.html index 1eaa1006d..98237645d 100644 --- a/src/userprofiles.html +++ b/src/userprofiles.html @@ -8,7 +8,7 @@ - ${Help} + ${Help}
diff --git a/src/wizardlibrary.html b/src/wizardlibrary.html index b8a4fab9d..3a5ca5069 100644 --- a/src/wizardlibrary.html +++ b/src/wizardlibrary.html @@ -3,7 +3,7 @@

${HeaderSetupLibrary}

- +

diff --git a/src/wizardstart.html b/src/wizardstart.html index c640b8eff..05e282bee 100644 --- a/src/wizardstart.html +++ b/src/wizardstart.html @@ -4,7 +4,7 @@

${WelcomeToProject}

- + ${ButtonQuickStartGuide}
diff --git a/webpack.dev.js b/webpack.dev.js index 76a1a7a75..716cfb2d0 100644 --- a/webpack.dev.js +++ b/webpack.dev.js @@ -2,7 +2,6 @@ const path = require('path'); const common = require('./webpack.common'); const merge = require('webpack-merge'); const packageConfig = require('./package.json'); -const postcssConfig = require('./postcss.config.js'); module.exports = merge(common, { mode: 'development', @@ -31,7 +30,11 @@ module.exports = merge(common, { 'css-loader', { loader: 'postcss-loader', - options: postcssConfig() + options: { + config: { + path: __dirname + } + } } ] }, diff --git a/webpack.prod.js b/webpack.prod.js index f5c7accd0..eb39f82cd 100644 --- a/webpack.prod.js +++ b/webpack.prod.js @@ -1,7 +1,6 @@ const common = require('./webpack.common'); const merge = require('webpack-merge'); const packageConfig = require('./package.json'); -const postcssConfig = require('./postcss.config.js'); module.exports = merge(common, { mode: 'production', @@ -24,7 +23,11 @@ module.exports = merge(common, { 'css-loader', { loader: 'postcss-loader', - options: postcssConfig() + options: { + config: { + path: __dirname + } + } } ] }, diff --git a/yarn.lock b/yarn.lock index e384265ff..28182ae1d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2436,15 +2436,6 @@ cliui@^3.2.0: strip-ansi "^3.0.1" wrap-ansi "^2.0.0" -cliui@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" - integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ== - dependencies: - string-width "^2.1.1" - strip-ansi "^4.0.0" - wrap-ansi "^2.0.0" - cliui@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" @@ -3174,10 +3165,10 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" -date-fns@^2.12.0: - version "2.12.0" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.12.0.tgz#01754c8a2f3368fc1119cf4625c3dad8c1845ee6" - integrity sha512-qJgn99xxKnFgB1qL4jpxU7Q2t0LOn1p8KMIveef3UZD7kqjT3tpFNNdXJelEHhE+rUgffriXriw/sOSU+cS1Hw== +date-fns@^2.13.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.13.0.tgz#d7b8a0a2d392e8d88a8024d0a46b980bbfdbd708" + integrity sha512-xm0c61mevGF7f0XpCGtDTGpzEFC/1fpLXHbmFpxZZQJuvByIK2ozm6cSYuU+nxFYOPh2EuCfzUwlTEFwKG+h5w== dateformat@^2.0.0: version "2.2.0" @@ -5642,7 +5633,7 @@ html-comment-regex@^1.1.0, html-comment-regex@^1.1.2: resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.2.tgz#97d4688aeb5c81886a364faa0cad1dda14d433a7" integrity sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ== -html-entities@^1.2.1: +html-entities@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.3.1.tgz#fb9a1a4b5b14c5daba82d3e34c6ae4fe701a0e44" integrity sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA== @@ -6572,10 +6563,10 @@ jellyfin-apiclient@^1.1.1: version "1.0.3" resolved "https://github.com/jellyfin/jellyfin-noto#b784602db063734c721a46563ae5d6577ec2b35d" -jquery@>=1.9.1, jquery@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.5.0.tgz#9980b97d9e4194611c36530e7dc46a58d7340fc9" - integrity sha512-Xb7SVYMvygPxbFMpTFQiHh1J7HClEaThguL15N/Gg37Lri/qKyhRGZYzHRyLH8Stq3Aow0LsHO2O2ci86fCrNQ== +jquery@>=1.9.1, jquery@^3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.5.1.tgz#d7b4d08e1bfdb86ad2f1a3d039ea17304717abb5" + integrity sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg== js-base64@^2.1.8, js-base64@^2.1.9: version "2.5.2" @@ -6807,10 +6798,6 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" -"libass-wasm@https://github.com/jellyfin/JavascriptSubtitlesOctopus#4.0.0-jf-cordova": - version "4.0.0" - resolved "https://github.com/jellyfin/JavascriptSubtitlesOctopus#b38056588bfaebc18a8353cb1757de0a815ac879" - "libass-wasm@https://github.com/jellyfin/JavascriptSubtitlesOctopus#4.0.0-jf-smarttv": version "4.0.0" resolved "https://github.com/jellyfin/JavascriptSubtitlesOctopus#58e9a3f1a7f7883556ee002545f445a430120639" @@ -7113,7 +7100,7 @@ logalot@^2.0.0, logalot@^2.1.0: figures "^1.3.5" squeak "^1.0.0" -loglevel@^1.6.6: +loglevel@^1.6.8: version "1.6.8" resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.8.tgz#8a25fb75d092230ecd4457270d80b54e28011171" integrity sha512-bsU7+gc9AJ2SqpzxwU3+1fedl8zAntbtC5XYlt3s2j1hJcn2PsXSmgN8TaLG/J1/2mod4+cE/3vNL70/c1RNCA== @@ -8182,7 +8169,7 @@ os-locale@^1.4.0: dependencies: lcid "^1.0.0" -os-locale@^3.0.0, os-locale@^3.1.0: +os-locale@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q== @@ -8702,7 +8689,7 @@ plur@^3.0.1: dependencies: irregular-plurals "^2.0.0" -portfinder@^1.0.25: +portfinder@^1.0.26: version "1.0.26" resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.26.tgz#475658d56ca30bed72ac7f1378ed350bd1b64e70" integrity sha512-Xi7mKxJHHMI3rIUrnm/jjUgwhbYMkp/XKEcZX3aG4BrumLpq3nmoQMX+ClYnDZnZ/New7IatC1no5RX0zo1vXQ== @@ -10595,10 +10582,10 @@ sha.js@^2.4.0, sha.js@^2.4.8: inherits "^2.0.1" safe-buffer "^5.0.1" -shaka-player@^2.5.10: - version "2.5.10" - resolved "https://registry.yarnpkg.com/shaka-player/-/shaka-player-2.5.10.tgz#6f4e72e2433002d11824a223b02edd5004e30e2b" - integrity sha512-kS9TQL6bWODo4XNnozERZWsEiWlLZ6huspPx4ZjmMjeOBL9gwqlULLfLyO+5gA3CYV/dk9LaAi1WAEaLWckGpA== +shaka-player@^2.5.11: + version "2.5.11" + resolved "https://registry.yarnpkg.com/shaka-player/-/shaka-player-2.5.11.tgz#af550a0ee3aadf7be4e64e1a4d615c8d728e0b0f" + integrity sha512-SiZd/vCUPeKXNPnfWcBdraskdUYLtm+DITWceCZvRP4eoxxQuRI0MekVJTGqu5d7B2yW9TdQh5ojyRAjbQPFGA== dependencies: eme-encryption-scheme-polyfill "^2.0.1" @@ -10767,13 +10754,14 @@ sockjs-client@1.4.0: json3 "^3.3.2" url-parse "^1.4.3" -sockjs@0.3.19: - version "0.3.19" - resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.19.tgz#d976bbe800af7bd20ae08598d582393508993c0d" - integrity sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw== +sockjs@0.3.20: + version "0.3.20" + resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.20.tgz#b26a283ec562ef8b2687b44033a4eeceac75d855" + integrity sha512-SpmVOVpdq0DJc0qArhF3E5xsxvaiqGNb73XfgBpK1y3UD5gs8DSo8aCTsuT5pX8rssdc2NDIzANwP9eCAiSdTA== dependencies: faye-websocket "^0.10.0" - uuid "^3.0.1" + uuid "^3.4.0" + websocket-driver "0.6.5" sort-keys-length@^1.0.0: version "1.0.1" @@ -10890,7 +10878,7 @@ spdy-transport@^3.0.0: readable-stream "^3.0.6" wbuf "^1.7.3" -spdy@^4.0.1: +spdy@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b" integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA== @@ -11088,7 +11076,7 @@ string-width@^1.0.1, string-width@^1.0.2: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1: +"string-width@^1.0.2 || 2": version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== @@ -12302,7 +12290,7 @@ utils-merge@1.0.1: resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= -uuid@^3.0.1, uuid@^3.3.2: +uuid@^3.0.1, uuid@^3.3.2, uuid@^3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== @@ -12539,10 +12527,10 @@ webpack-dev-middleware@^3.7.2: range-parser "^1.2.1" webpack-log "^2.0.0" -webpack-dev-server@^3.10.3: - version "3.10.3" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.10.3.tgz#f35945036813e57ef582c2420ef7b470e14d3af0" - integrity sha512-e4nWev8YzEVNdOMcNzNeCN947sWJNd43E5XvsJzbAL08kGc2frm1tQ32hTJslRS+H65LCb/AaUCYU7fjHCpDeQ== +webpack-dev-server@^3.11.0: + version "3.11.0" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.11.0.tgz#8f154a3bce1bcfd1cc618ef4e703278855e7ff8c" + integrity sha512-PUxZ+oSTxogFQgkTtFndEtJIPNmml7ExwufBZ9L2/Xyyd5PnOL5UreWe5ZT7IU25DSdykL9p1MLQzmLh2ljSeg== dependencies: ansi-html "0.0.7" bonjour "^3.5.0" @@ -12552,31 +12540,31 @@ webpack-dev-server@^3.10.3: debug "^4.1.1" del "^4.1.1" express "^4.17.1" - html-entities "^1.2.1" + html-entities "^1.3.1" http-proxy-middleware "0.19.1" import-local "^2.0.0" internal-ip "^4.3.0" ip "^1.1.5" is-absolute-url "^3.0.3" killable "^1.0.1" - loglevel "^1.6.6" + loglevel "^1.6.8" opn "^5.5.0" p-retry "^3.0.1" - portfinder "^1.0.25" + portfinder "^1.0.26" schema-utils "^1.0.0" selfsigned "^1.10.7" semver "^6.3.0" serve-index "^1.9.1" - sockjs "0.3.19" + sockjs "0.3.20" sockjs-client "1.4.0" - spdy "^4.0.1" + spdy "^4.0.2" strip-ansi "^3.0.1" supports-color "^6.1.0" url "^0.11.0" webpack-dev-middleware "^3.7.2" webpack-log "^2.0.0" ws "^6.2.1" - yargs "12.0.5" + yargs "^13.3.2" webpack-log@^2.0.0: version "2.0.0" @@ -12645,6 +12633,13 @@ webpack@^4.26.1, webpack@^4.41.5: watchpack "^1.6.1" webpack-sources "^1.4.1" +websocket-driver@0.6.5: + version "0.6.5" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.6.5.tgz#5cb2556ceb85f4373c6d8238aa691c8454e13a36" + integrity sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY= + dependencies: + websocket-extensions ">=0.1.1" + websocket-driver@>=0.5.1: version "0.7.3" resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.3.tgz#a2d4e0d4f4f116f1e6297eba58b05d430100e9f9" @@ -12797,7 +12792,7 @@ y18n@^3.2.1: resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= -"y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0: +y18n@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== @@ -12826,14 +12821,6 @@ yargs-parser@^10.0.0: dependencies: camelcase "^4.1.0" -yargs-parser@^11.1.1: - version "11.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4" - integrity sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - yargs-parser@^13.1.0, yargs-parser@^13.1.2: version "13.1.2" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" @@ -12864,24 +12851,6 @@ yargs-parser@^5.0.0: dependencies: camelcase "^3.0.0" -yargs@12.0.5: - version "12.0.5" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13" - integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw== - dependencies: - cliui "^4.0.0" - decamelize "^1.2.0" - find-up "^3.0.0" - get-caller-file "^1.0.1" - os-locale "^3.0.0" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^2.0.0" - which-module "^2.0.0" - y18n "^3.2.1 || ^4.0.0" - yargs-parser "^11.1.1" - yargs@13.2.4: version "13.2.4" resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.4.tgz#0b562b794016eb9651b98bd37acf364aa5d6dc83"
${ApiKeysCaption}
${HeaderApiKey}${HeaderApp}${HeaderDateIssued}${HeaderApiKey}${HeaderApp}${HeaderDateIssued}