diff --git a/.eslintrc.js b/.eslintrc.js
index 6fd4392e60..7de812ea6e 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -1,3 +1,5 @@
+const restrictedGlobals = require('confusing-browser-globals');
+
module.exports = {
root: true,
plugins: [
@@ -39,6 +41,7 @@ module.exports = {
'no-floating-decimal': ['error'],
'no-multi-spaces': ['error'],
'no-multiple-empty-lines': ['error', { 'max': 1 }],
+ 'no-restricted-globals': ['error'].concat(restrictedGlobals),
'no-trailing-spaces': ['error'],
'@babel/no-unused-expressions': ['error', { 'allowShortCircuit': true, 'allowTernary': true, 'allowTaggedTemplates': true }],
//'no-unused-vars': ['error', { 'vars': 'all', 'args': 'none', 'ignoreRestSiblings': true }],
diff --git a/package.json b/package.json
index 654845113c..d6e8c1941f 100644
--- a/package.json
+++ b/package.json
@@ -16,8 +16,9 @@
"autoprefixer": "^9.8.6",
"babel-loader": "^8.0.6",
"browser-sync": "^2.26.12",
+ "confusing-browser-globals": "^1.0.9",
"copy-webpack-plugin": "^5.1.1",
- "css-loader": "^4.2.1",
+ "css-loader": "^4.2.2",
"cssnano": "^4.1.10",
"del": "^5.1.0",
"eslint": "^7.7.0",
diff --git a/src/components/appRouter.js b/src/components/appRouter.js
index 28826c55cc..f986e71357 100644
--- a/src/components/appRouter.js
+++ b/src/components/appRouter.js
@@ -41,7 +41,7 @@ class AppRouter {
}
});
- this.baseRoute = self.location.href.split('?')[0].replace(this.getRequestFile(), '');
+ this.baseRoute = window.location.href.split('?')[0].replace(this.getRequestFile(), '');
// support hashbang
this.baseRoute = this.baseRoute.split('#')[0];
if (this.baseRoute.endsWith('/') && !this.baseRoute.endsWith('://')) {
@@ -55,7 +55,7 @@ class AppRouter {
* @private
*/
setBaseRoute() {
- let baseRoute = self.location.pathname.replace(this.getRequestFile(), '');
+ let baseRoute = window.location.pathname.replace(this.getRequestFile(), '');
if (baseRoute.lastIndexOf('/') === baseRoute.length - 1) {
baseRoute = baseRoute.substring(0, baseRoute.length - 1);
}
@@ -182,7 +182,7 @@ class AppRouter {
return false;
}
- return history.length > 1;
+ return window.history.length > 1;
}
current() {
@@ -258,7 +258,7 @@ class AppRouter {
pushState(state, title, url) {
state.navigate = false;
- history.pushState(state, title, url);
+ window.history.pushState(state, title, url);
}
enableNativeHistory() {
@@ -594,7 +594,7 @@ class AppRouter {
}
getRequestFile() {
- let path = self.location.pathname || '';
+ let path = window.location.pathname || '';
const index = path.lastIndexOf('/');
if (index !== -1) {
diff --git a/src/components/apphost.js b/src/components/apphost.js
index c3e9342827..33ca5a0b79 100644
--- a/src/components/apphost.js
+++ b/src/components/apphost.js
@@ -55,7 +55,7 @@ function replaceAll(originalString, strReplace, strWith) {
function generateDeviceId() {
const keys = [];
- if (keys.push(navigator.userAgent), keys.push(new Date().getTime()), self.btoa) {
+ if (keys.push(navigator.userAgent), keys.push(new Date().getTime()), window.btoa) {
const result = replaceAll(btoa(keys.join('|')), '=', '1');
return Promise.resolve(result);
}
@@ -404,9 +404,9 @@ document.addEventListener(visibilityChange, function () {
}
}, false);
-if (self.addEventListener) {
- self.addEventListener('focus', onAppVisible);
- self.addEventListener('blur', onAppHidden);
+if (window.addEventListener) {
+ window.addEventListener('focus', onAppVisible);
+ window.addEventListener('blur', onAppHidden);
}
export default appHost;
diff --git a/src/components/confirm/confirm.js b/src/components/confirm/confirm.js
index 0670816a53..eca612ccb8 100644
--- a/src/components/confirm/confirm.js
+++ b/src/components/confirm/confirm.js
@@ -19,7 +19,7 @@ export default (() => {
}
const text = replaceAll(options.text || '', '
', '\n');
- const result = confirm(text);
+ const result = window.confirm(text);
if (result) {
return Promise.resolve();
diff --git a/src/components/dialogHelper/dialogHelper.js b/src/components/dialogHelper/dialogHelper.js
index b9256714fd..e1a267fed2 100644
--- a/src/components/dialogHelper/dialogHelper.js
+++ b/src/components/dialogHelper/dialogHelper.js
@@ -85,9 +85,9 @@ import 'scrollStyles';
}
if (!self.closedByBack && isHistoryEnabled(dlg)) {
- const state = history.state || {};
+ const state = window.history.state || {};
if (state.dialogId === hash) {
- history.back();
+ window.history.back();
}
}
@@ -213,7 +213,7 @@ import 'scrollStyles';
export function close(dlg) {
if (isOpened(dlg)) {
if (isHistoryEnabled(dlg)) {
- history.back();
+ window.history.back();
} else {
closeDialog(dlg);
}
diff --git a/src/components/playback/playbackorientation.js b/src/components/playback/playbackorientation.js
index 1aa939da04..b73377bade 100644
--- a/src/components/playback/playbackorientation.js
+++ b/src/components/playback/playbackorientation.js
@@ -18,7 +18,7 @@ events.on(playbackManager, 'playbackstart', function (e, player, state) {
if (isLocalVideo && layoutManager.mobile) {
/* eslint-disable-next-line compat/compat */
- var lockOrientation = screen.lockOrientation || screen.mozLockOrientation || screen.msLockOrientation || (screen.orientation && screen.orientation.lock);
+ var lockOrientation = window.screen.lockOrientation || window.screen.mozLockOrientation || window.screen.msLockOrientation || (window.screen.orientation && window.screen.orientation.lock);
if (lockOrientation) {
try {
@@ -39,7 +39,7 @@ events.on(playbackManager, 'playbackstart', function (e, player, state) {
events.on(playbackManager, 'playbackstop', function (e, playbackStopInfo) {
if (orientationLocked && !playbackStopInfo.nextMediaType) {
/* eslint-disable-next-line compat/compat */
- var unlockOrientation = screen.unlockOrientation || screen.mozUnlockOrientation || screen.msUnlockOrientation || (screen.orientation && screen.orientation.unlock);
+ var unlockOrientation = window.screen.unlockOrientation || window.screen.mozUnlockOrientation || window.screen.msUnlockOrientation || (window.screen.orientation && window.screen.orientation.unlock);
if (unlockOrientation) {
try {
diff --git a/src/components/require/requiretext.js b/src/components/require/requiretext.js
index 8c68daed92..28ddeb21c8 100644
--- a/src/components/require/requiretext.js
+++ b/src/components/require/requiretext.js
@@ -2,7 +2,7 @@ define(function () {
'use strict';
// hack to work around the server's auto-redirection feature
- var addRedirectPrevention = self.dashboardVersion != null && self.Dashboard && !self.AppInfo.isNativeApp;
+ var addRedirectPrevention = window.dashboardVersion != null && window.Dashboard && !window.AppInfo.isNativeApp;
return {
diff --git a/src/components/serviceworker/notifications.js b/src/components/serviceworker/notifications.js
index 5f96d01a4d..339d521bbc 100644
--- a/src/components/serviceworker/notifications.js
+++ b/src/components/serviceworker/notifications.js
@@ -26,7 +26,7 @@
});
}
- self.addEventListener('notificationclick', function (event) {
+ window.addEventListener('notificationclick', function (event) {
var notification = event.notification;
notification.close();
diff --git a/src/controllers/itemDetails/index.js b/src/controllers/itemDetails/index.js
index f44b82c411..5cb027881b 100644
--- a/src/controllers/itemDetails/index.js
+++ b/src/controllers/itemDetails/index.js
@@ -1067,7 +1067,7 @@ import 'emby-select';
}
function enableScrollX() {
- return browser.mobile && screen.availWidth <= 1000;
+ return browser.mobile && window.screen.availWidth <= 1000;
}
function getPortraitShape(scrollX) {
diff --git a/src/controllers/music/musicalbums.js b/src/controllers/music/musicalbums.js
index 7e42d34019..7947aa1376 100644
--- a/src/controllers/music/musicalbums.js
+++ b/src/controllers/music/musicalbums.js
@@ -69,8 +69,8 @@ import 'emby-itemscontainer';
return savedQueryKey;
}
- function onViewStyleChange() {
- const viewStyle = self.getCurrentViewStyle();
+ const onViewStyleChange = () => {
+ const viewStyle = this.getCurrentViewStyle();
const itemsContainer = tabContent.querySelector('.itemsContainer');
if (viewStyle == 'List') {
@@ -82,13 +82,13 @@ import 'emby-itemscontainer';
}
itemsContainer.innerHTML = '';
- }
+ };
- function reloadItems(page) {
+ const reloadItems = (page) => {
loading.show();
isLoading = true;
const query = getQuery();
- ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function (result) {
+ ApiClient.getItems(ApiClient.getCurrentUserId(), query).then((result) => {
function onNextPageClick() {
if (isLoading) {
return;
@@ -124,7 +124,7 @@ import 'emby-itemscontainer';
sortButton: false,
filterButton: false
});
- const viewStyle = self.getCurrentViewStyle();
+ const viewStyle = this.getCurrentViewStyle();
if (viewStyle == 'List') {
html = listView.getListViewHtml({
items: result.Items,
@@ -182,19 +182,18 @@ import 'emby-itemscontainer';
autoFocuser.autoFocus(tabContent);
});
});
- }
+ };
- function updateFilterControls(tabContent) {
+ const updateFilterControls = (tabContent) => {
const query = getQuery();
- self.alphaPicker.value(query.NameStartsWithOrGreater);
- }
+ this.alphaPicker.value(query.NameStartsWithOrGreater);
+ };
let savedQueryKey;
let pageData;
- const self = this;
let isLoading = false;
- self.showFilterMenu = function () {
+ this.showFilterMenu = function () {
import('components/filterdialog/filterdialog').then(({default: filterDialogFactory}) => {
const filterDialog = new filterDialogFactory({
query: getQuery(),
@@ -209,11 +208,11 @@ import 'emby-itemscontainer';
});
};
- self.getCurrentViewStyle = function () {
+ this.getCurrentViewStyle = function () {
return getPageData().view;
};
- function initPage(tabContent) {
+ const initPage = (tabContent) => {
const alphaPickerElement = tabContent.querySelector('.alphaPicker');
const itemsContainer = tabContent.querySelector('.itemsContainer');
@@ -224,7 +223,7 @@ import 'emby-itemscontainer';
query.StartIndex = 0;
reloadItems(tabContent);
});
- self.alphaPicker = new AlphaPicker({
+ this.alphaPicker = new AlphaPicker({
element: alphaPickerElement,
valueChangeEvent: 'click'
});
@@ -233,10 +232,10 @@ import 'emby-itemscontainer';
alphaPickerElement.classList.add('alphaPicker-fixed-right');
itemsContainer.classList.add('padded-right-withalphapicker');
- tabContent.querySelector('.btnFilter').addEventListener('click', function () {
- self.showFilterMenu();
+ tabContent.querySelector('.btnFilter').addEventListener('click', () => {
+ this.showFilterMenu();
});
- tabContent.querySelector('.btnSort').addEventListener('click', function (e) {
+ tabContent.querySelector('.btnSort').addEventListener('click', (e) => {
libraryBrowser.showSortMenu({
items: [{
name: globalize.translate('Name'),
@@ -269,8 +268,8 @@ import 'emby-itemscontainer';
});
});
const btnSelectView = tabContent.querySelector('.btnSelectView');
- btnSelectView.addEventListener('click', function (e) {
- libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), 'List,Poster,PosterCard'.split(','));
+ btnSelectView.addEventListener('click', (e) => {
+ libraryBrowser.showLayoutMenu(e.target, this.getCurrentViewStyle(), 'List,Poster,PosterCard'.split(','));
});
btnSelectView.addEventListener('layoutchange', function (e) {
const viewStyle = e.detail.viewStyle;
@@ -282,17 +281,17 @@ import 'emby-itemscontainer';
});
tabContent.querySelector('.btnPlayAll').addEventListener('click', playAll);
tabContent.querySelector('.btnShuffle').addEventListener('click', shuffle);
- }
+ };
initPage(tabContent);
onViewStyleChange();
- self.renderTab = function () {
+ this.renderTab = function () {
reloadItems(tabContent);
updateFilterControls(tabContent);
};
- self.destroy = function () {};
+ this.destroy = function () {};
}
/* eslint-enable indent */
diff --git a/src/controllers/music/musicartists.js b/src/controllers/music/musicartists.js
index 23e0bbd459..32e0a22a07 100644
--- a/src/controllers/music/musicartists.js
+++ b/src/controllers/music/musicartists.js
@@ -45,16 +45,16 @@ import 'emby-itemscontainer';
return getPageData(context).query;
}
- function getSavedQueryKey(context) {
+ const getSavedQueryKey = (context) => {
if (!context.savedQueryKey) {
- context.savedQueryKey = libraryBrowser.getSavedQueryKey(self.mode);
+ context.savedQueryKey = libraryBrowser.getSavedQueryKey(this.mode);
}
return context.savedQueryKey;
- }
+ };
- function onViewStyleChange() {
- const viewStyle = self.getCurrentViewStyle();
+ const onViewStyleChange = () => {
+ const viewStyle = this.getCurrentViewStyle();
const itemsContainer = tabContent.querySelector('.itemsContainer');
if (viewStyle == 'List') {
@@ -66,16 +66,16 @@ import 'emby-itemscontainer';
}
itemsContainer.innerHTML = '';
- }
+ };
- function reloadItems(page) {
+ const reloadItems = (page) => {
loading.show();
isLoading = true;
const query = getQuery(page);
- const promise = self.mode == 'albumartists' ?
+ const promise = this.mode == 'albumartists' ?
ApiClient.getAlbumArtists(ApiClient.getCurrentUserId(), query) :
ApiClient.getArtists(ApiClient.getCurrentUserId(), query);
- promise.then(function (result) {
+ promise.then((result) => {
function onNextPageClick() {
if (isLoading) {
return;
@@ -111,7 +111,7 @@ import 'emby-itemscontainer';
sortButton: false,
filterButton: false
});
- const viewStyle = self.getCurrentViewStyle();
+ const viewStyle = this.getCurrentViewStyle();
if (viewStyle == 'List') {
html = listView.getListViewHtml({
items: result.Items,
@@ -165,22 +165,21 @@ import 'emby-itemscontainer';
autoFocuser.autoFocus(tabContent);
});
});
- }
+ };
- function updateFilterControls(tabContent) {
+ const updateFilterControls = (tabContent) => {
const query = getQuery(tabContent);
- self.alphaPicker.value(query.NameStartsWithOrGreater);
- }
+ this.alphaPicker.value(query.NameStartsWithOrGreater);
+ };
- const self = this;
const data = {};
let isLoading = false;
- self.showFilterMenu = function () {
+ this.showFilterMenu = function () {
import('components/filterdialog/filterdialog').then(({default: filterDialogFactory}) => {
const filterDialog = new filterDialogFactory({
query: getQuery(tabContent),
- mode: self.mode,
+ mode: this.mode,
serverId: ApiClient.serverId()
});
events.on(filterDialog, 'filterchange', function () {
@@ -191,11 +190,11 @@ import 'emby-itemscontainer';
});
};
- self.getCurrentViewStyle = function () {
+ this.getCurrentViewStyle = function () {
return getPageData(tabContent).view;
};
- function initPage(tabContent) {
+ const initPage = (tabContent) => {
const alphaPickerElement = tabContent.querySelector('.alphaPicker');
const itemsContainer = tabContent.querySelector('.itemsContainer');
@@ -206,7 +205,7 @@ import 'emby-itemscontainer';
query.StartIndex = 0;
reloadItems(tabContent);
});
- self.alphaPicker = new AlphaPicker({
+ this.alphaPicker = new AlphaPicker({
element: alphaPickerElement,
valueChangeEvent: 'click'
});
@@ -215,12 +214,12 @@ import 'emby-itemscontainer';
alphaPickerElement.classList.add('alphaPicker-fixed-right');
itemsContainer.classList.add('padded-right-withalphapicker');
- tabContent.querySelector('.btnFilter').addEventListener('click', function () {
- self.showFilterMenu();
+ tabContent.querySelector('.btnFilter').addEventListener('click', () => {
+ this.showFilterMenu();
});
const btnSelectView = tabContent.querySelector('.btnSelectView');
btnSelectView.addEventListener('click', function (e) {
- libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), 'List,Poster,PosterCard'.split(','));
+ libraryBrowser.showLayoutMenu(e.target, this.getCurrentViewStyle(), 'List,Poster,PosterCard'.split(','));
});
btnSelectView.addEventListener('layoutchange', function (e) {
const viewStyle = e.detail.viewStyle;
@@ -230,17 +229,17 @@ import 'emby-itemscontainer';
onViewStyleChange();
reloadItems(tabContent);
});
- }
+ };
initPage(tabContent);
onViewStyleChange();
- self.renderTab = function () {
+ this.renderTab = function () {
reloadItems(tabContent);
updateFilterControls(tabContent);
};
- self.destroy = function () {};
+ this.destroy = function () {};
}
/* eslint-enable indent */
diff --git a/src/controllers/music/musicgenres.js b/src/controllers/music/musicgenres.js
index 29e0d888e4..2cd9e2114b 100644
--- a/src/controllers/music/musicgenres.js
+++ b/src/controllers/music/musicgenres.js
@@ -42,11 +42,11 @@ import loading from 'loading';
return ApiClient.getGenres(ApiClient.getCurrentUserId(), query);
}
- function reloadItems(context, promise) {
+ const reloadItems = (context, promise) => {
const query = getQuery();
- promise.then(function (result) {
+ promise.then((result) => {
let html = '';
- const viewStyle = self.getCurrentViewStyle();
+ const viewStyle = this.getCurrentViewStyle();
if (viewStyle == 'Thumb') {
html = cardBuilder.getCardsHtml({
@@ -96,38 +96,37 @@ import loading from 'loading';
autoFocuser.autoFocus(context);
});
});
- }
+ };
function fullyReload() {
- self.preRender();
- self.renderTab();
+ this.preRender();
+ this.renderTab();
}
- const self = this;
const data = {};
- self.getViewStyles = function () {
+ this.getViewStyles = function () {
return 'Poster,PosterCard,Thumb,ThumbCard'.split(',');
};
- self.getCurrentViewStyle = function () {
+ this.getCurrentViewStyle = function () {
return getPageData().view;
};
- self.setCurrentViewStyle = function (viewStyle) {
+ this.setCurrentViewStyle = function (viewStyle) {
getPageData().view = viewStyle;
libraryBrowser.saveViewSetting(getSavedQueryKey(), viewStyle);
fullyReload();
};
- self.enableViewSelection = true;
+ this.enableViewSelection = true;
let promise;
- self.preRender = function () {
+ this.preRender = function () {
promise = getPromise();
};
- self.renderTab = function () {
+ this.renderTab = function () {
reloadItems(tabContent, promise);
};
}
diff --git a/src/controllers/music/musicplaylists.js b/src/controllers/music/musicplaylists.js
index befeafcf4c..67e6a959eb 100644
--- a/src/controllers/music/musicplaylists.js
+++ b/src/controllers/music/musicplaylists.js
@@ -69,20 +69,19 @@ import loading from 'loading';
});
}
- const self = this;
const data = {};
- self.getCurrentViewStyle = function () {
+ this.getCurrentViewStyle = function () {
return getPageData().view;
};
let promise;
- self.preRender = function () {
+ this.preRender = function () {
promise = getPromise();
};
- self.renderTab = function () {
+ this.renderTab = function () {
reloadItems(tabContent, promise);
};
}
diff --git a/src/controllers/music/musicrecommended.js b/src/controllers/music/musicrecommended.js
index 5661bf8422..a93bfea4e3 100644
--- a/src/controllers/music/musicrecommended.js
+++ b/src/controllers/music/musicrecommended.js
@@ -263,7 +263,7 @@ import 'flexStyles';
mainTabsManager.setTabs(view, currentTabIndex, getTabs, getTabContainers, onBeforeTabChange, onTabChange);
}
- function getTabController(page, index, callback) {
+ const getTabController = (page, index, callback) => {
let depends;
switch (index) {
@@ -298,7 +298,7 @@ import 'flexStyles';
if (index == 0) {
tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']");
- self.tabContent = tabContent;
+ this.tabContent = tabContent;
}
let controller = tabControllers[index];
@@ -307,7 +307,7 @@ import 'flexStyles';
tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']");
if (index === 0) {
- controller = self;
+ controller = this;
} else if (index === 7) {
controller = new controllerFactory(view, tabContent, {
collectionType: 'music',
@@ -331,7 +331,7 @@ import 'flexStyles';
callback(controller);
});
- }
+ };
function preLoadTab(page, index) {
getTabController(page, index, function (controller) {
@@ -359,10 +359,9 @@ import 'flexStyles';
}
}
- var self = this;
- var currentTabIndex = parseInt(params.tab || getDefaultTabIndex(params.topParentId));
+ let currentTabIndex = parseInt(params.tab || getDefaultTabIndex(params.topParentId));
- self.initTab = function () {
+ this.initTab = function () {
const tabContent = view.querySelector(".pageTabContent[data-index='0']");
const containers = tabContent.querySelectorAll('.itemsContainer');
@@ -371,7 +370,7 @@ import 'flexStyles';
}
};
- self.renderTab = function () {
+ this.renderTab = function () {
reload();
};
diff --git a/src/scripts/apploader.js b/src/scripts/apploader.js
index e98c82e693..f5f6850c40 100644
--- a/src/scripts/apploader.js
+++ b/src/scripts/apploader.js
@@ -5,8 +5,8 @@
}
const script = document.createElement('script');
- if (self.dashboardVersion) {
- src += `?v=${self.dashboardVersion}`;
+ if (window.dashboardVersion) {
+ src += `?v=${window.dashboardVersion}`;
}
script.src = src;
script.setAttribute('async', '');
@@ -35,10 +35,10 @@
// Promise() being missing on some legacy browser, and a funky one
// is Promise() present but buggy on WebOS 2
window.Promise = undefined;
- self.Promise = undefined;
+ window.Promise = undefined;
}
- if (!self.Promise) {
+ if (!window.Promise) {
// Load Promise polyfill if they are not natively supported
injectScriptElement(
'./libraries/npo.js',
diff --git a/src/scripts/browser.js b/src/scripts/browser.js
index b10587cb09..618d930ec8 100644
--- a/src/scripts/browser.js
+++ b/src/scripts/browser.js
@@ -210,7 +210,7 @@ if (userAgent.toLowerCase().indexOf('xbox') !== -1) {
browser.tv = true;
}
browser.animate = typeof document !== 'undefined' && document.documentElement.animate != null;
-browser.tizen = userAgent.toLowerCase().indexOf('tizen') !== -1 || self.tizen != null;
+browser.tizen = userAgent.toLowerCase().indexOf('tizen') !== -1 || window.tizen != null;
browser.web0s = userAgent.toLowerCase().indexOf('Web0S'.toLowerCase()) !== -1;
browser.edgeUwp = browser.edge && (userAgent.toLowerCase().indexOf('msapphost') !== -1 || userAgent.toLowerCase().indexOf('webview') !== -1);
diff --git a/src/scripts/browserDeviceProfile.js b/src/scripts/browserDeviceProfile.js
index 5befcb1df5..67c75da901 100644
--- a/src/scripts/browserDeviceProfile.js
+++ b/src/scripts/browserDeviceProfile.js
@@ -315,10 +315,12 @@ define(['browser'], function (browser) {
// Not sure how to test for this
var supportsMp2VideoAudio = browser.edgeUwp || browser.tizen || browser.web0s;
+ /* eslint-disable compat/compat */
var maxVideoWidth = browser.xboxOne ?
- (self.screen ? self.screen.width : null) :
+ (window.screen ? window.screen.width : null) :
null;
+ /* eslint-enable compat/compat */
if (options.maxVideoWidth) {
maxVideoWidth = options.maxVideoWidth;
}
diff --git a/src/scripts/clientUtils.js b/src/scripts/clientUtils.js
index 1bad8bc81c..70d42d0782 100644
--- a/src/scripts/clientUtils.js
+++ b/src/scripts/clientUtils.js
@@ -154,7 +154,7 @@ export function capabilities(appHost) {
let capabilities = {
PlayableMediaTypes: ['Audio', 'Video'],
SupportedCommands: ['MoveUp', 'MoveDown', 'MoveLeft', 'MoveRight', 'PageUp', 'PageDown', 'PreviousLetter', 'NextLetter', 'ToggleOsd', 'ToggleContextMenu', 'Select', 'Back', 'SendKey', 'SendString', 'GoHome', 'GoToSettings', 'VolumeUp', 'VolumeDown', 'Mute', 'Unmute', 'ToggleMute', 'SetVolume', 'SetAudioStreamIndex', 'SetSubtitleStreamIndex', 'DisplayContent', 'GoToSearch', 'DisplayMessage', 'SetRepeatMode', 'SetShuffleQueue', 'ChannelUp', 'ChannelDown', 'PlayMediaSource', 'PlayTrailers'],
- SupportsPersistentIdentifier: self.appMode === 'cordova' || self.appMode === 'android',
+ SupportsPersistentIdentifier: window.appMode === 'cordova' || window.appMode === 'android',
SupportsMediaControl: true
};
return Object.assign(capabilities, appHost.getPushTokenInfo());
diff --git a/src/scripts/libraryMenu.js b/src/scripts/libraryMenu.js
index e6b96e7447..dd8ddac983 100644
--- a/src/scripts/libraryMenu.js
+++ b/src/scripts/libraryMenu.js
@@ -799,7 +799,7 @@ import 'flexStyles';
}
function getNavDrawerOptions() {
- let drawerWidth = screen.availWidth - 50;
+ let drawerWidth = window.screen.availWidth - 50;
drawerWidth = Math.max(drawerWidth, 240);
drawerWidth = Math.min(drawerWidth, 320);
return {
diff --git a/src/scripts/multiDownload.js b/src/scripts/multiDownload.js
index b4ad95a975..d1c717af0e 100644
--- a/src/scripts/multiDownload.js
+++ b/src/scripts/multiDownload.js
@@ -31,7 +31,7 @@ function sameDomain(url) {
var a = document.createElement('a');
a.href = url;
- return location.hostname === a.hostname && location.protocol === a.protocol;
+ return window.location.hostname === a.hostname && window.location.protocol === a.protocol;
}
function download(url) {
@@ -62,4 +62,3 @@ export default function (urls) {
download(url);
});
}
-
diff --git a/src/scripts/site.js b/src/scripts/site.js
index 48a5044f5e..0e1e44251c 100644
--- a/src/scripts/site.js
+++ b/src/scripts/site.js
@@ -187,9 +187,9 @@ function initClient() {
}
function defineResizeObserver() {
- if (self.ResizeObserver) {
+ if (window.ResizeObserver) {
define('ResizeObserver', [], function () {
- return self.ResizeObserver;
+ return window.ResizeObserver;
});
} else {
define('ResizeObserver', ['resize-observer-polyfill'], returnFirstDependency);
@@ -248,8 +248,8 @@ function initClient() {
}
function onGlobalizeInit(browser, globalize) {
- if (self.appMode === 'android') {
- if (self.location.href.toString().toLowerCase().indexOf('start=backgroundsync') !== -1) {
+ if (window.appMode === 'android') {
+ if (window.location.href.toString().toLowerCase().indexOf('start=backgroundsync') !== -1) {
return onAppReady(browser);
}
}
@@ -384,11 +384,15 @@ function initClient() {
return response.text();
})
.then(function(css) {
- // Inject the branding css as a dom element in body so it will take
- // precedence over other stylesheets
- var style = document.createElement('style');
- style.appendChild(document.createTextNode(css));
- document.body.appendChild(style);
+ let style = document.querySelector('#cssBranding');
+ if (!style) {
+ // Inject the branding css as a dom element in body so it will take
+ // precedence over other stylesheets
+ style = document.createElement('style');
+ style.id = 'cssBranding';
+ document.body.appendChild(style);
+ }
+ style.textContent = css;
})
.catch(function(err) {
console.warn('Error applying custom css', err);
@@ -400,7 +404,7 @@ function initClient() {
function registerServiceWorker() {
/* eslint-disable compat/compat */
- if (navigator.serviceWorker && self.appMode !== 'cordova' && self.appMode !== 'android') {
+ if (navigator.serviceWorker && window.appMode !== 'cordova' && window.appMode !== 'android') {
try {
navigator.serviceWorker.register('serviceworker.js');
} catch (err) {
@@ -437,7 +441,7 @@ function initClient() {
define('castSenderApiLoader', [componentsPath + '/castSenderApi'], returnFirstDependency);
- if (self.appMode === 'cordova' || self.appMode === 'android' || self.appMode === 'standalone') {
+ if (window.appMode === 'cordova' || window.appMode === 'android' || window.appMode === 'standalone') {
AppInfo.isNativeApp = true;
}
diff --git a/src/scripts/themeManager.js b/src/scripts/themeManager.js
index d61e9ef67e..03ca621749 100644
--- a/src/scripts/themeManager.js
+++ b/src/scripts/themeManager.js
@@ -1,13 +1,12 @@
import * as webSettings from 'webSettings';
-var themeStyleElement;
+var themeStyleElement = document.querySelector('#cssTheme');
var currentThemeId;
function unloadTheme() {
var elem = themeStyleElement;
if (elem) {
- elem.parentNode.removeChild(elem);
- themeStyleElement = null;
+ elem.removeAttribute('href');
currentThemeId = null;
}
}
@@ -45,15 +44,26 @@ function setTheme(id) {
var linkUrl = info.stylesheetPath;
unloadTheme();
- var link = document.createElement('link');
- link.setAttribute('rel', 'stylesheet');
- link.setAttribute('type', 'text/css');
- link.onload = function () {
+ let link = themeStyleElement;
+
+ if (!link) {
+ // Inject the theme css as a dom element in body so it will take
+ // precedence over other stylesheets
+ link = document.createElement('link');
+ link.id = 'cssTheme';
+ link.setAttribute('rel', 'stylesheet');
+ link.setAttribute('type', 'text/css');
+ document.body.appendChild(link);
+ }
+
+ const onLoad = function (e) {
+ e.target.removeEventListener('load', onLoad);
resolve();
};
+ link.addEventListener('load', onLoad);
+
link.setAttribute('href', linkUrl);
- document.head.appendChild(link);
themeStyleElement = link;
currentThemeId = info.themeId;
});
diff --git a/src/strings/bg-bg.json b/src/strings/bg-bg.json
index 582eb38fa8..3c3850178e 100644
--- a/src/strings/bg-bg.json
+++ b/src/strings/bg-bg.json
@@ -182,7 +182,7 @@
"HeaderPreferredMetadataLanguage": "Предпочитан език на метаданните",
"HeaderProfile": "Профил",
"HeaderProfileInformation": "Профил",
- "HeaderProfileServerSettingsHelp": "Тези величини определят как Jellyfin сървърът ще се представя на устройствата.",
+ "HeaderProfileServerSettingsHelp": "Тези величини определят как Джелифин сървърът ще се представя на устройствата.",
"HeaderRecentlyPlayed": "Скоро пускани",
"HeaderRemoteControl": "Отдалечен контрол",
"HeaderRemoveMediaFolder": "Премахване на медийна папка",
@@ -220,7 +220,7 @@
"Horizontal": "Водоравно",
"Identify": "Разпознаване",
"Images": "Изображения",
- "ImportMissingEpisodesHelp": "Ако е активирано, информация за липсващи епизоди ще бъде добавена в базата данни на Jellyfin и ще бъде показвана заедно със сезони и серии. Това може да доведе до значително по-дълго сканиране на библиотеката.",
+ "ImportMissingEpisodesHelp": "Ако е активирано, информация за липсващи епизоди ще бъде добавена в базата данни на Джелифин и ще бъде показвана заедно със сезони и серии. Това може да доведе до значително по-дълго сканиране на библиотеката.",
"InstallingPackage": "Инсталиране на {0} на версия {1})",
"InstantMix": "Пускане на подобни",
"Label3DFormat": "Триизмерен формат:",
@@ -254,7 +254,7 @@
"LabelDay": "Ден:",
"LabelDeviceDescription": "Описание на устройството",
"LabelDisplayLanguage": "Език на показване:",
- "LabelDisplayLanguageHelp": "Превеждането на Емби е текущ проект.",
+ "LabelDisplayLanguageHelp": "Превеждането на Джелифин е текущ проект.",
"LabelDisplayMode": "Режим на показване:",
"LabelDisplayName": "Показвано име:",
"LabelDisplayOrder": "Ред на показване:",
@@ -267,7 +267,7 @@
"LabelEmbedAlbumArtDidl": "Вградждане на албумно изкуство в Didl",
"LabelEnableAutomaticPortMap": "Автоматично съответстване на портовете",
"LabelEnableDlnaClientDiscoveryInterval": "Интервал за откриване на клиенти (секунди)",
- "LabelEnableDlnaClientDiscoveryIntervalHelp": "Определя времетраенето в секунди между SSDP търсения направени от Jellyfin.",
+ "LabelEnableDlnaClientDiscoveryIntervalHelp": "Определя времетраенето в секунди между SSDP търсения направени от Джелифин.",
"LabelEnableDlnaDebugLogging": "Включване на журналите за грешки на ДЛНА",
"LabelEnableDlnaPlayTo": "Включване на функцията \"възпроизвеждане с ДЛНА\"",
"LabelEnableDlnaPlayToHelp": "Засичане на устройства в мрежата ви и предлагане на възможност за дистанционно управление.",
@@ -546,8 +546,8 @@
"SearchForSubtitles": "Търсене на субтитри",
"SendMessage": "Изпращане на съобщение",
"SeriesYearToPresent": "{0} - Настояще",
- "ServerNameIsRestarting": "Сървърно издание Емби - {0} се пуска повторно.",
- "ServerNameIsShuttingDown": "Сървърно издание Емби - {0} се изключва.",
+ "ServerNameIsRestarting": "Сървърът - {0} се пуска повторно.",
+ "ServerNameIsShuttingDown": "Сървърът във - {0} се изключва.",
"ServerRestartNeededAfterPluginInstall": "След инсталирането на приставка, сървърът ще трябва да бъде пуснат наново.",
"ServerUpdateNeeded": "Сървърът трябва да бъде обновен. Моля, посетете {0}, за да свалите последната версия.",
"Settings": "Настройки",
@@ -635,7 +635,7 @@
"ViewAlbum": "Преглед на албума",
"Watched": "Изгледано",
"Wednesday": "Сряда",
- "WelcomeToProject": "Добре дошли в Емби!",
+ "WelcomeToProject": "Добре дошли в Джелифин!",
"WizardCompleted": "Това е всичко, от което се нуждаем за момента. Джелифин започва да събира данни за библиотеката ви. Разгледайте някои от нашите приложения, после натиснете Готово, за да видите таблото на сървъра.",
"Writer": "Писател",
"AllowMediaConversion": "Разрешаване на медийни преобразувания",
@@ -693,7 +693,7 @@
"ButtonAddImage": "Добавяне на изображение",
"MessageBrowsePluginCatalog": "За да видите наличните добавки, прегледайте каталога с добавките.",
"Box": "Кутия",
- "AlwaysPlaySubtitlesHelp": "Поднадписите, съвпадащи с езика от настройките, ще се зареждат, независимо от езика на аудио то.",
+ "AlwaysPlaySubtitlesHelp": "Субтитрите, съвпадащи с езика от настройките, ще се зареждат, независимо от езика на аудиото.",
"BookLibraryHelp": "Поддържат се аудио книги такива съдържащи текст. Проверете ръководството за наименуване {1} на книги {0}.",
"Blacklist": "Списък с блокирани",
"BirthLocation": "Месторождение",
@@ -708,7 +708,7 @@
"AnyLanguage": "Който и да е език",
"AlwaysPlaySubtitles": "Постоянно изпълнение",
"AllowRemoteAccessHelp": "Ако не е маркирано, всеки отдалечен достъп ще бъде блокиран.",
- "AllowRemoteAccess": "Позволяване на отдалечен достъп до този Jellyfin сървър.",
+ "AllowRemoteAccess": "Позволяване на отдалечен достъп до този Джелифин сървър.",
"AllowFfmpegThrottling": "Подтискане на прекодирането",
"AllowMediaConversionHelp": "Даване или отнемане на права за функциите за конвертиране на медия.",
"AlbumArtist": "Изпълнител",
@@ -724,7 +724,7 @@
"ButtonEditOtherUserPreferences": "Редакция на потребителския профил, изображение и лични предпочитания.",
"BoxRear": "Комплект (стар)",
"BoxSet": "Комплект",
- "AuthProviderHelp": "Избор на доставчик на услуга за Автентификация, която ще се използва за автентификация на потребителската парола.",
+ "AuthProviderHelp": "Избор на доставчик на услуга за автентификация, която ще се използва за автентификация на потребителската парола.",
"AllowedRemoteAddressesHelp": "Списък с IP адреси или IP/маска записи, разделени със запетая, които ще имат отдалечен достъп. Ако полето не е попълнено всички адреси ще имат отдалечен достъп.",
"BurnSubtitlesHelp": "Определя дали сървърът трябва да записва субтитри във видеофайлове при прекодиране. Избягването на това значително ще подобри производителността. Изберете Auto, за да запишете формати, базирани на изображения (VOBSUB, PGS, SUB, IDX) и някои ASS или SSA субтитри.",
"AllowFfmpegThrottlingHelp": "Когато прекодирането или запазването на видео стигне достатъчно далеч напред от текущата позиция за възпроизвеждане, поставете на пауза процеса, така ще се изразходват по-малко ресурси. Това е най-полезно, когато се гледа, без да се търси често из видеото. Изключете това, ако имате проблеми с възпроизвеждането.",
@@ -737,10 +737,10 @@
"CopyStreamURL": "Копиране URL на стрийма",
"CopyStreamURLSuccess": "URL се копира успешно.",
"Connect": "Свързване",
- "ConfirmEndPlayerSession": "Искате ли да изключите Jellyfin на {0}?",
+ "ConfirmEndPlayerSession": "Искате ли да изключите Джелифин на {0}?",
"ConfirmDeletion": "Потвърждаване на изтриването",
"ConfirmDeleteItem": "Изтриването на елемента ще го премахне едновременно от файловата система и библиотеката. Сигурни ли сте, че искате да продължите?",
- "ConfigureDateAdded": "Конфигурацията на добавянето на датата се определя в панела на Jellyfin сървъра в секцията за настройка на библиотека",
+ "ConfigureDateAdded": "Конфигурацията на добавянето на датата се определя в панела на Джелифин сървъра в секцията за настройка на библиотека",
"ConfirmDeleteItems": "Изтриването на елементите ще ги премахне едновременно от файловата система и библиотеката. Сигурни ли сте, че искате да продължите?",
"ColorTransfer": "Предаване на цвета",
"ColorPrimaries": "Основни цветове",
diff --git a/src/strings/es_419.json b/src/strings/es_419.json
index 8b0f629cf3..131b7d9df2 100644
--- a/src/strings/es_419.json
+++ b/src/strings/es_419.json
@@ -1394,5 +1394,6 @@
"LabelSubtitleVerticalPosition": "Posición vertical:",
"PreviousTrack": "Saltar al anterior",
"MessageGetInstalledPluginsError": "Ocurrió un error buscando la lista de complementos instalados.",
- "MessagePluginInstallError": "Ocurrió un error instalando el complemento."
+ "MessagePluginInstallError": "Ocurrió un error instalando el complemento.",
+ "PlaybackRate": "Tasa de reproducción"
}
diff --git a/src/strings/fr-ca.json b/src/strings/fr-ca.json
index 8ac6d94679..455c068762 100644
--- a/src/strings/fr-ca.json
+++ b/src/strings/fr-ca.json
@@ -11,7 +11,7 @@
"Disconnect": "Se déconnecter",
"Download": "Télécharger",
"Edit": "Modifier",
- "EnableDisplayMirroring": "Activer l'affichage mirroir",
+ "EnableDisplayMirroring": "Duplication d'écran",
"EndsAtValue": "Se termine à {0}",
"File": "Fichier",
"FolderTypeTvShows": "Séries TV",
@@ -39,7 +39,7 @@
"NewCollectionHelp": "Les collections vous permettent de créer des regroupements personnalisés de films et d'autres contenus de la bibliothèque.",
"NewCollectionNameExample": "Exemple: Collection Star Wars",
"NoSubtitleSearchResultsFound": "Aucun résultat trouvé.",
- "OptionNew": "Nouveau...",
+ "OptionNew": "Nouveau…",
"OriginalAirDateValue": "Date de diffusion originale: {0}",
"ParentalRating": "Classement parentale",
"Premiere": "Première",
@@ -56,7 +56,7 @@
"SearchForSubtitles": "Rechercher des sous-titres",
"SeriesCancelled": "Série annulée.",
"SeriesRecordingScheduled": "Enregistrement en série programmé.",
- "ServerUpdateNeeded": "Ce serveur Jellyfin doit être mis à jour. Pour télécharger la dernière version, veuillez visiter {0}",
+ "ServerUpdateNeeded": "Ce serveur doit être mis à jour. Pour télécharger la dernière version, veuillez visiter {0}",
"Share": "Partager",
"Subtitles": "Sous-titres",
"Sunday": "Dimanche",
@@ -167,7 +167,7 @@
"DatePlayed": "Date écoutée",
"DateAdded": "Date d'ajout",
"CriticRating": "Évaluation critique",
- "CopyStreamURLSuccess": "L'URL a été copié avec succès.",
+ "CopyStreamURLSuccess": "URL copié avec succès.",
"CopyStreamURL": "Copier l'URL du stream",
"ContinueWatching": "Continuer à visionner",
"Connect": "Connexion",
@@ -210,5 +210,21 @@
"ChangingMetadataImageSettingsNewContent": "Les modifications aux paramètres de téléchargement de métadonnées et d'illustrations seront appliquées seulement au nouveau contenu de votre médiathèque. Vous devrez actualiser les métadonnées manuellement pour que les changements soient appliqués à l'ensemble de votre contenu.",
"ButtonTrailer": "Bande-annonce",
"ButtonSplit": "Couper",
- "ButtonSelectView": "Sélectionner l'affichage"
+ "ButtonSelectView": "Sélectionner l'affichage",
+ "LabelSubtitleVerticalPosition": "Position verticale :",
+ "ClearQueue": "Effacer la file d'attente",
+ "DashboardServerName": "Serveur : {0}",
+ "DashboardVersionNumber": "Version : {0}",
+ "LabelVersionInstalled": "{0} installée",
+ "LabelVersion": "Version :",
+ "LabelValue": "Valeur :",
+ "LabelVideo": "Vidéo",
+ "DashboardArchitecture": "Architecture : {0}",
+ "DashboardOperatingSystem": "Système d'exploitation : {0}",
+ "ConfigureDateAdded": "Configure la façon dont la date d'ajout est déterminée dans le tableau de board dans les paramètres de la médiathèque",
+ "Composer": "Compositeur(trice)",
+ "CommunityRating": "Évaluation de la communauté",
+ "ColorTransfer": "Transfert de couleur",
+ "ColorSpace": "Espace colorimétrique",
+ "ColorPrimaries": "Primaires colorimétriques"
}
diff --git a/src/strings/hu.json b/src/strings/hu.json
index ef20c6a8a5..5a4f116b69 100644
--- a/src/strings/hu.json
+++ b/src/strings/hu.json
@@ -615,7 +615,7 @@
"HeaderImageOptions": "Képbeállítások",
"HeaderInstantMix": "Azonnali keverés",
"HeaderKeepRecording": "Felvétel készítése",
- "HeaderKodiMetadataHelp": "Az Nfo metaadatok engedélyezéséhez vagy letiltásához szerkeszd a könyvtárat és keresd meg a metaadat letöltő részt.",
+ "HeaderKodiMetadataHelp": "Az NFO metaadatok engedélyezéséhez vagy letiltásához szerkeszd a könyvtárat és keresd meg a metaadat letöltő részt.",
"HeaderLatestMusic": "Legújabb Zene",
"HeaderLatestRecordings": "Legújabb Felvételek",
"HeaderLoginFailure": "Bejelentkezési hiba",
@@ -1363,7 +1363,7 @@
"LabelSyncPlayTimeOffset": "Időeltolás a szerverhez képest:",
"EnableDetailsBannerHelp": "Megjelenít egy banner képet a részletes információoldal tetején.",
"EnableDetailsBanner": "Banner a részletes oldalon",
- "EnableBlurHashHelp": "A még betöltés alatt álló képek helyén egy elmosódott helyettesítő képet jelenít meg",
+ "EnableBlurHashHelp": "A még betöltés alatt álló képek helyén egy elmosódott helyettesítő képet jelenít meg.",
"EnableBlurHash": "Elmosódott helyettesítőképek engedélyezése",
"ShowMore": "Továbbiak megtekintése",
"ShowLess": "Kevesebb mutatása",
diff --git a/src/strings/it.json b/src/strings/it.json
index 727416a39a..6c08abe02e 100644
--- a/src/strings/it.json
+++ b/src/strings/it.json
@@ -1393,5 +1393,7 @@
"LabelSubtitleVerticalPosition": "Posizione verticale:",
"PreviousTrack": "Traccia precedente",
"MessageGetInstalledPluginsError": "Errore durante la generazione della lista dei plugin installati.",
- "MessagePluginInstallError": "Errore durante l'installazione del plugin."
+ "MessagePluginInstallError": "Errore durante l'installazione del plugin.",
+ "SubtitleVerticalPositionHelp": "Numero di riga in cui viene visualizzato il testo. I numeri positivi indicano dall'alto verso il basso. I numeri negativi indicano dal basso verso l'alto.",
+ "PlaybackRate": "Velocità di riproduzione"
}
diff --git a/src/strings/ro.json b/src/strings/ro.json
index 7feff235c1..9122d943bf 100644
--- a/src/strings/ro.json
+++ b/src/strings/ro.json
@@ -225,7 +225,7 @@
"Delete": "Șterge",
"DeleteImage": "Șterge Imaginea",
"DeleteUserConfirmation": "Sigur doriți să ștergeți acest utilizator?",
- "Depressed": "Deprimat",
+ "Depressed": "Presat",
"Descending": "Descendent",
"DetectingDevices": "Detectez dispozitive",
"DirectPlaying": "Redare directă",
@@ -400,7 +400,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 inapoi la Nimic.",
+ "HardwareAccelerationWarning": "Activarea accelerării hardware poate provoca instabilitate în anumite medii. Asigurați-vă că sistemul de operare și driverele video sunt actualizate. Dacă întâmpinați dificultăți pentru a reda video după activarea acestei opțiuni, va trebui să schimbați setarea înapoi la Fără.",
"HeaderAccessSchedule": "Program de Acces",
"HeaderAccessScheduleHelp": "Creați un program de acces pentru a limita accesul la anumite ore.",
"HeaderActiveDevices": "Dispozitive active",
@@ -715,7 +715,7 @@
"LabelEnableDlnaClientDiscoveryInterval": "Interval de descoperire a clientului",
"LabelEnableBlastAliveMessagesHelp": "Activați acest lucru dacă serverul nu este detectat în mod fiabil de alte dispozitive UPnP din rețeaua dvs.",
"LabelEnableBlastAliveMessages": "Trimitere mesaje de disponibilitate",
- "LabelEnableAutomaticPortMapHelp": "Încercați să mapați automat portul public către portul local prin UPnP. Este posibil să nu funcționeze cu unele modele de router. Modificările nu se vor aplica decât după repornirea serverului.",
+ "LabelEnableAutomaticPortMapHelp": "Încercați să mapați automat portul public către portul local prin UPnP. Este posibil să nu funcționeze cu unele modele de router. Schimbările nu vor fi aplicate decât după un restart al serverului.",
"LabelEnableAutomaticPortMap": "Activați maparea automată a porturilor",
"LabelEmbedAlbumArtDidlHelp": "Unele dispozitive preferă această metodă pentru obținerea artei albumelor. Alții pot să nu redea cu această opțiune activată.",
"LabelEmbedAlbumArtDidl": "Încorporați arta albumului în Didl",
@@ -1190,9 +1190,9 @@
"OptionEnableForAllTuners": "Activare pentru toate dispozitivele tuner",
"OptionEnableExternalContentInSuggestionsHelp": "Permiteți trailerelor din internet și programelor TV în direct să fie incluse în conținutul sugerat.",
"OptionEnableExternalContentInSuggestions": "Activați conținut extern în sugestii",
- "OptionEmbedSubtitles": "Inclus în container",
+ "OptionEmbedSubtitles": "Încorporați în container",
"OptionDownloadImagesInAdvanceHelp": "În mod implicit, majoritatea imaginilor sunt descărcate numai la cererea unei aplicații Jellyfin. Activați această opțiune pentru a descărca în avans toate imaginile, pe măsură ce fișiere media noi sunt importate. Acest lucru poate duce la mărirea semnificativă a timpilor de scanare a bibliotecii.",
- "OptionDownloadImagesInAdvance": "Descărcați imaginile în avans",
+ "OptionDownloadImagesInAdvance": "Descărcă imaginile în avans",
"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ă",
@@ -1282,7 +1282,7 @@
"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 util atunci când priviți fără a derula des. Dezactivați acestă opțiune dacă întâmpinați probleme de redare.",
+ "AllowFfmpegThrottlingHelp": "Când o transcodare sau un remux se află departe de poziția actuală de redare, întrerupeți procesul, astfel încât acesta să consume mai puține resurse. Acest lucru este cel mai util când priviți fără a căuta prin film des. Dezactivați acest lucru dacă întâmpinați probleme de redare.",
"AllowFfmpegThrottling": "Limitare Transcod-uri",
"Track": "Cale",
"Season": "Sezon",
@@ -1363,7 +1363,7 @@
"HeaderSyncPlaySelectGroup": "Alăturați-vă unui grup",
"EnableDetailsBannerHelp": "Afișați o imagine de bandou în partea de sus a paginii cu detalii ale articolului.",
"EnableDetailsBanner": "Detalii Bandou",
- "EnableBlurHashHelp": "Imaginile care sunt în curs de încărcare vor fi afișate cu un marcaj întinat",
+ "EnableBlurHashHelp": "Imaginile care sunt în curs de încărcare vor fi afișate cu un marcaj întinat.",
"EnableBlurHash": "Activați marcatoarele întinate pentru imagini",
"ShowMore": "Arată mai mult",
"ShowLess": "Arată mai puțin",
@@ -1394,5 +1394,6 @@
"LabelSubtitleVerticalPosition": "Poziție verticală:",
"PreviousTrack": "Sari anterior",
"MessageGetInstalledPluginsError": "A apărut o eroare la obținerea listei de plugin-uri instalate în prezent.",
- "MessagePluginInstallError": "A apărut o eroare la instalarea pluginului."
+ "MessagePluginInstallError": "A apărut o eroare la instalarea pluginului.",
+ "PlaybackRate": "Rata de redare"
}
diff --git a/yarn.lock b/yarn.lock
index 5f962daee2..5e93eef199 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2751,6 +2751,11 @@ config-chain@^1.1.11:
ini "^1.3.4"
proto-list "~1.2.1"
+confusing-browser-globals@^1.0.9:
+ version "1.0.9"
+ resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.9.tgz#72bc13b483c0276801681871d4898516f8f54fdd"
+ integrity sha512-KbS1Y0jMtyPgIxjO7ZzMAuUpAKMt1SzCL9fsrKsX6b0zJPTaT0SiSPmewwVZg9UAO83HVIlEhZF84LIjZ0lmAw==
+
connect-history-api-fallback@^1:
version "1.6.0"
resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc"
@@ -3010,16 +3015,15 @@ css-has-pseudo@^0.10.0:
postcss "^7.0.6"
postcss-selector-parser "^5.0.0-rc.4"
-css-loader@^4.2.1:
- version "4.2.1"
- resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-4.2.1.tgz#9f48fd7eae1219d629a3f085ba9a9102ca1141a7"
- integrity sha512-MoqmF1if7Z0pZIEXA4ZF9PgtCXxWbfzfJM+3p+OYfhcrwcqhaCRb74DSnfzRl7e024xEiCRn5hCvfUbTf2sgFA==
+css-loader@^4.2.2:
+ version "4.2.2"
+ resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-4.2.2.tgz#b668b3488d566dc22ebcf9425c5f254a05808c89"
+ integrity sha512-omVGsTkZPVwVRpckeUnLshPp12KsmMSLqYxs12+RzM9jRR5Y+Idn/tBffjXRvOE+qW7if24cuceFJqYR5FmGBg==
dependencies:
camelcase "^6.0.0"
cssesc "^3.0.0"
icss-utils "^4.1.1"
loader-utils "^2.0.0"
- normalize-path "^3.0.0"
postcss "^7.0.32"
postcss-modules-extract-imports "^2.0.0"
postcss-modules-local-by-default "^3.0.3"