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

Merge branch 'master' into jassub

This commit is contained in:
Cas 2023-03-30 13:50:25 +02:00 committed by GitHub
commit 4c7c2067f9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
116 changed files with 1269 additions and 982 deletions

View file

@ -64,7 +64,9 @@ module.exports = {
'no-var': ['error'], 'no-var': ['error'],
'no-void': ['error', { 'allowAsStatement': true }], 'no-void': ['error', { 'allowAsStatement': true }],
'no-warning-comments': ['warn', { 'terms': ['fixme', 'hack', 'xxx'] }], 'no-warning-comments': ['warn', { 'terms': ['fixme', 'hack', 'xxx'] }],
'object-curly-spacing': ['error', 'always'],
'one-var': ['error', 'never'], 'one-var': ['error', 'never'],
'operator-linebreak': ['error', 'before', { overrides: { '?': 'after', ':': 'after', '=': 'after' } }],
'padded-blocks': ['error', 'never'], 'padded-blocks': ['error', 'never'],
'prefer-const': ['error', { 'destructuring': 'all' }], 'prefer-const': ['error', { 'destructuring': 'all' }],
'quotes': ['error', 'single', { 'avoidEscape': true, 'allowTemplateLiterals': false }], 'quotes': ['error', 'single', { 'avoidEscape': true, 'allowTemplateLiterals': false }],
@ -267,7 +269,6 @@ module.exports = {
'no-useless-constructor': ['off'], 'no-useless-constructor': ['off'],
'@typescript-eslint/no-useless-constructor': ['error'], '@typescript-eslint/no-useless-constructor': ['error'],
'max-params': ['error', 7],
'sonarjs/cognitive-complexity': ['warn'] 'sonarjs/cognitive-complexity': ['warn']
} }
} }

View file

@ -19,13 +19,13 @@ jobs:
language: [ 'javascript' ] language: [ 'javascript' ]
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@168b99b3c22180941ae7dbdd5f5c9678ede476ba # v2.2.7 uses: github/codeql-action/init@04df1262e6247151b5ac09cd2c303ac36ad3f62b # v2.2.9
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
queries: +security-extended queries: +security-extended
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@168b99b3c22180941ae7dbdd5f5c9678ede476ba # v2.2.7 uses: github/codeql-action/autobuild@04df1262e6247151b5ac09cd2c303ac36ad3f62b # v2.2.9
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@168b99b3c22180941ae7dbdd5f5c9678ede476ba # v2.2.7 uses: github/codeql-action/analyze@04df1262e6247151b5ac09cd2c303ac36ad3f62b # v2.2.9

View file

@ -18,7 +18,7 @@ jobs:
comment-id: ${{ github.event.comment.id }} comment-id: ${{ github.event.comment.id }}
reactions: '+1' reactions: '+1'
- name: Checkout the latest code - name: Checkout the latest code
uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0
with: with:
token: ${{ secrets.JF_BOT_TOKEN }} token: ${{ secrets.JF_BOT_TOKEN }}
fetch-depth: 0 fetch-depth: 0

View file

@ -13,7 +13,7 @@ jobs:
steps: steps:
- name: Check out Git repository - name: Check out Git repository
uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0
- name: Setup node environment - name: Setup node environment
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0
@ -37,7 +37,7 @@ jobs:
steps: steps:
- name: Check out Git repository - name: Check out Git repository
uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0
- name: Setup node environment - name: Setup node environment
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0
@ -58,7 +58,7 @@ jobs:
steps: steps:
- name: Check out Git repository - name: Check out Git repository
uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0
- name: Setup node environment - name: Setup node environment
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0
@ -82,7 +82,7 @@ jobs:
steps: steps:
- name: Check out Git repository - name: Check out Git repository
uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0
- name: Setup node environment - name: Setup node environment
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0

View file

@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: ${{ contains(github.repository, 'jellyfin/') }} if: ${{ contains(github.repository, 'jellyfin/') }}
steps: steps:
- uses: actions/stale@6f05e4244c9a0b2ed3401882b05d701dd0a7289b # v7.0.0 - uses: actions/stale@1160a2240286f5da8ec72b1c0816ce2481aabf84 # v8.0.0
with: with:
repo-token: ${{ secrets.JF_BOT_TOKEN }} repo-token: ${{ secrets.JF_BOT_TOKEN }}
operations-per-run: 75 operations-per-run: 75
@ -37,7 +37,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: ${{ contains(github.repository, 'jellyfin/') }} if: ${{ contains(github.repository, 'jellyfin/') }}
steps: steps:
- uses: actions/stale@6f05e4244c9a0b2ed3401882b05d701dd0a7289b # v7.0.0 - uses: actions/stale@1160a2240286f5da8ec72b1c0816ce2481aabf84 # v8.0.0
with: with:
repo-token: ${{ secrets.JF_BOT_TOKEN }} repo-token: ${{ secrets.JF_BOT_TOKEN }}
operations-per-run: 75 operations-per-run: 75

View file

@ -13,7 +13,7 @@ jobs:
steps: steps:
- name: Check out Git repository - name: Check out Git repository
uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0
- name: Setup node environment - name: Setup node environment
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0

1125
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -5,8 +5,8 @@
"repository": "https://github.com/jellyfin/jellyfin-web", "repository": "https://github.com/jellyfin/jellyfin-web",
"license": "GPL-2.0-or-later", "license": "GPL-2.0-or-later",
"devDependencies": { "devDependencies": {
"@babel/core": "7.21.0", "@babel/core": "7.21.3",
"@babel/eslint-parser": "7.19.1", "@babel/eslint-parser": "7.21.3",
"@babel/eslint-plugin": "7.19.1", "@babel/eslint-plugin": "7.19.1",
"@babel/plugin-proposal-class-properties": "7.18.6", "@babel/plugin-proposal-class-properties": "7.18.6",
"@babel/plugin-proposal-private-methods": "7.18.6", "@babel/plugin-proposal-private-methods": "7.18.6",
@ -16,13 +16,13 @@
"@babel/preset-typescript": "7.21.0", "@babel/preset-typescript": "7.21.0",
"@types/escape-html": "1.0.2", "@types/escape-html": "1.0.2",
"@types/loadable__component": "5.13.4", "@types/loadable__component": "5.13.4",
"@types/lodash-es": "4.17.6", "@types/lodash-es": "4.17.7",
"@types/react": "17.0.53", "@types/react": "17.0.53",
"@types/react-dom": "17.0.19", "@types/react-dom": "17.0.19",
"@typescript-eslint/eslint-plugin": "5.54.1", "@typescript-eslint/eslint-plugin": "5.56.0",
"@typescript-eslint/parser": "5.54.1", "@typescript-eslint/parser": "5.56.0",
"@uupaa/dynamic-import-polyfill": "1.0.2", "@uupaa/dynamic-import-polyfill": "1.0.2",
"autoprefixer": "10.4.13", "autoprefixer": "10.4.14",
"babel-loader": "9.1.2", "babel-loader": "9.1.2",
"babel-plugin-dynamic-import-polyfill": "1.0.0", "babel-plugin-dynamic-import-polyfill": "1.0.0",
"clean-webpack-plugin": "4.0.0", "clean-webpack-plugin": "4.0.0",
@ -32,7 +32,7 @@
"css-loader": "6.7.3", "css-loader": "6.7.3",
"cssnano": "5.1.15", "cssnano": "5.1.15",
"es-check": "7.1.0", "es-check": "7.1.0",
"eslint": "8.35.0", "eslint": "8.36.0",
"eslint-plugin-compat": "4.1.2", "eslint-plugin-compat": "4.1.2",
"eslint-plugin-eslint-comments": "3.2.0", "eslint-plugin-eslint-comments": "3.2.0",
"eslint-plugin-import": "2.27.5", "eslint-plugin-import": "2.27.5",
@ -40,29 +40,29 @@
"eslint-plugin-promise": "6.1.1", "eslint-plugin-promise": "6.1.1",
"eslint-plugin-react": "7.32.2", "eslint-plugin-react": "7.32.2",
"eslint-plugin-react-hooks": "4.6.0", "eslint-plugin-react-hooks": "4.6.0",
"eslint-plugin-sonarjs": "0.18.0", "eslint-plugin-sonarjs": "0.19.0",
"expose-loader": "4.0.0", "expose-loader": "4.1.0",
"html-loader": "4.2.0", "html-loader": "4.2.0",
"html-webpack-plugin": "5.5.0", "html-webpack-plugin": "5.5.0",
"mini-css-extract-plugin": "2.7.3", "mini-css-extract-plugin": "2.7.5",
"postcss": "8.4.21", "postcss": "8.4.21",
"postcss-loader": "7.0.2", "postcss-loader": "7.1.0",
"postcss-preset-env": "8.0.1", "postcss-preset-env": "8.0.1",
"postcss-scss": "4.0.6", "postcss-scss": "4.0.6",
"sass": "1.58.3", "sass": "1.59.3",
"sass-loader": "13.2.0", "sass-loader": "13.2.1",
"source-map-loader": "4.0.1", "source-map-loader": "4.0.1",
"style-loader": "3.3.1", "style-loader": "3.3.2",
"stylelint": "15.2.0", "stylelint": "15.3.0",
"stylelint-config-rational-order": "0.1.2", "stylelint-config-rational-order": "0.1.2",
"stylelint-no-browser-hacks": "1.2.1", "stylelint-no-browser-hacks": "1.2.1",
"stylelint-order": "6.0.3", "stylelint-order": "6.0.3",
"stylelint-scss": "4.4.0", "stylelint-scss": "4.5.0",
"ts-loader": "9.4.2", "ts-loader": "9.4.2",
"typescript": "4.9.5", "typescript": "5.0.2",
"webpack": "5.76.0", "webpack": "5.76.3",
"webpack-cli": "5.0.1", "webpack-cli": "5.0.1",
"webpack-dev-server": "4.11.1", "webpack-dev-server": "4.13.1",
"webpack-merge": "5.8.0", "webpack-merge": "5.8.0",
"workbox-webpack-plugin": "6.5.4", "workbox-webpack-plugin": "6.5.4",
"worker-loader": "3.0.8" "worker-loader": "3.0.8"
@ -79,10 +79,10 @@
"blurhash": "2.0.5", "blurhash": "2.0.5",
"classlist.js": "https://github.com/eligrey/classList.js/archive/1.2.20180112.tar.gz", "classlist.js": "https://github.com/eligrey/classList.js/archive/1.2.20180112.tar.gz",
"classnames": "2.3.2", "classnames": "2.3.2",
"core-js": "3.29.0", "core-js": "3.29.1",
"date-fns": "2.29.3", "date-fns": "2.29.3",
"dompurify": "3.0.1", "dompurify": "3.0.1",
"epubjs": "0.4.2", "epubjs": "0.3.93",
"escape-html": "1.0.3", "escape-html": "1.0.3",
"event-target-polyfill": "github:ThaUnknown/event-target-polyfill", "event-target-polyfill": "github:ThaUnknown/event-target-polyfill",
"fast-text-encoding": "1.0.6", "fast-text-encoding": "1.0.6",
@ -93,17 +93,17 @@
"intersection-observer": "0.12.2", "intersection-observer": "0.12.2",
"jassub": "1.5.12", "jassub": "1.5.12",
"jellyfin-apiclient": "1.10.0", "jellyfin-apiclient": "1.10.0",
"jquery": "3.6.3", "jquery": "3.6.4",
"jstree": "3.3.15", "jstree": "3.3.15",
"libarchive.js": "1.3.0", "libarchive.js": "1.3.0",
"lodash-es": "4.17.21", "lodash-es": "4.17.21",
"marked": "4.2.12", "marked": "4.3.0",
"material-design-icons-iconfont": "6.7.0", "material-design-icons-iconfont": "6.7.0",
"native-promise-only": "0.8.1", "native-promise-only": "0.8.1",
"pdfjs-dist": "2.16.105", "pdfjs-dist": "2.16.105",
"react": "17.0.2", "react": "17.0.2",
"react-dom": "17.0.2", "react-dom": "17.0.2",
"react-router-dom": "6.8.2", "react-router-dom": "6.9.0",
"resize-observer-polyfill": "1.5.1", "resize-observer-polyfill": "1.5.1",
"screenfull": "6.0.2", "screenfull": "6.0.2",
"sortablejs": "1.15.0", "sortablejs": "1.15.0",

View file

@ -366,20 +366,20 @@ export const appHost = {
}; };
}, },
deviceName: function () { deviceName: function () {
return window.NativeShell?.AppHost?.deviceName return window.NativeShell?.AppHost?.deviceName ?
? window.NativeShell.AppHost.deviceName() : getDeviceName(); window.NativeShell.AppHost.deviceName() : getDeviceName();
}, },
deviceId: function () { deviceId: function () {
return window.NativeShell?.AppHost?.deviceId return window.NativeShell?.AppHost?.deviceId ?
? window.NativeShell.AppHost.deviceId() : getDeviceId(); window.NativeShell.AppHost.deviceId() : getDeviceId();
}, },
appName: function () { appName: function () {
return window.NativeShell?.AppHost?.appName return window.NativeShell?.AppHost?.appName ?
? window.NativeShell.AppHost.appName() : appName; window.NativeShell.AppHost.appName() : appName;
}, },
appVersion: function () { appVersion: function () {
return window.NativeShell?.AppHost?.appVersion return window.NativeShell?.AppHost?.appVersion ?
? window.NativeShell.AppHost.appVersion() : Package.version; window.NativeShell.AppHost.appVersion() : Package.version;
}, },
getPushTokenInfo: function () { getPushTokenInfo: function () {
return {}; return {};

View file

@ -26,8 +26,8 @@ import Events from '../utils/events.ts';
function canPlayNativeHls() { function canPlayNativeHls() {
const media = document.createElement('video'); const media = document.createElement('video');
return !!(media.canPlayType('application/x-mpegURL').replace(/no/, '') || return !!(media.canPlayType('application/x-mpegURL').replace(/no/, '')
media.canPlayType('application/vnd.apple.mpegURL').replace(/no/, '')); || media.canPlayType('application/vnd.apple.mpegURL').replace(/no/, ''));
} }
export function enableHlsJsPlayer(runTimeTicks, mediaType) { export function enableHlsJsPlayer(runTimeTicks, mediaType) {
@ -201,8 +201,8 @@ import Events from '../utils/events.ts';
.catch((e) => { .catch((e) => {
const errorName = (e.name || '').toLowerCase(); const errorName = (e.name || '').toLowerCase();
// safari uses aborterror // safari uses aborterror
if (errorName === 'notallowederror' || if (errorName === 'notallowederror'
errorName === 'aborterror') { || errorName === 'aborterror') {
// swallow this error because the user can still click the play button on the video element // swallow this error because the user can still click the play button on the video element
return Promise.resolve(); return Promise.resolve();
} }

View file

@ -25,7 +25,7 @@ import toast from '../toast/toast';
import alert from '../alert'; import alert from '../alert';
import template from './mediaLibraryCreator.template.html'; import template from './mediaLibraryCreator.template.html';
function onAddLibrary() { function onAddLibrary(e) {
if (isCreating) { if (isCreating) {
return false; return false;
} }
@ -62,7 +62,7 @@ import template from './mediaLibraryCreator.template.html';
isCreating = false; isCreating = false;
loading.hide(); loading.hide();
}); });
return false; e.preventDefault();
} }
function getCollectionTypeOptionsHtml(collectionTypeOptions) { function getCollectionTypeOptionsHtml(collectionTypeOptions) {
@ -96,7 +96,7 @@ import template from './mediaLibraryCreator.template.html';
$('.collectionTypeFieldDescription', dlg).html(folderOption?.message || ''); $('.collectionTypeFieldDescription', dlg).html(folderOption?.message || '');
}); });
page.querySelector('.btnAddFolder').addEventListener('click', onAddButtonClick); page.querySelector('.btnAddFolder').addEventListener('click', onAddButtonClick);
page.querySelector('.btnSubmit').addEventListener('click', onAddLibrary); page.querySelector('.addLibraryForm').addEventListener('submit', onAddLibrary);
page.querySelector('.folderList').addEventListener('click', onRemoveClick); page.querySelector('.folderList').addEventListener('click', onRemoveClick);
} }

View file

@ -1,3 +1,4 @@
<form class="addLibraryForm" style="max-width:100%;">
<div class="formDialogHeader"> <div class="formDialogHeader">
<button type="button" is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1" title="${ButtonBack}"><span class="material-icons arrow_back" aria-hidden="true"></span></button> <button type="button" is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1" title="${ButtonBack}"><span class="material-icons arrow_back" aria-hidden="true"></span></button>
<h3 class="formDialogHeaderTitle">${ButtonAddMediaLibrary}</h3> <h3 class="formDialogHeaderTitle">${ButtonAddMediaLibrary}</h3>
@ -31,7 +32,8 @@
</div> </div>
<div class="formDialogFooter"> <div class="formDialogFooter">
<button is="emby-button" type="button" class="raised btnSubmit button-submit block formDialogFooterItem"> <button is="emby-button" type="submit" class="raised btnSubmit button-submit block formDialogFooterItem">
<span>${ButtonOk}</span> <span>${ButtonOk}</span>
</button> </button>
</div> </div>
</form>

View file

@ -588,12 +588,12 @@ import template from './metadataEditor.template.html';
hideElement('#collapsibleSpecialEpisodeInfo', context); hideElement('#collapsibleSpecialEpisodeInfo', context);
} }
if (item.Type === 'Person' || if (item.Type === 'Person'
item.Type === 'Genre' || || item.Type === 'Genre'
item.Type === 'Studio' || || item.Type === 'Studio'
item.Type === 'MusicGenre' || || item.Type === 'MusicGenre'
item.Type === 'TvChannel' || || item.Type === 'TvChannel'
item.Type === 'Book') { || item.Type === 'Book') {
hideElement('#peopleCollapsible', context); hideElement('#peopleCollapsible', context);
} else { } else {
showElement('#peopleCollapsible', context); showElement('#peopleCollapsible', context);

View file

@ -4,7 +4,8 @@ import Events from '../../utils/events.ts';
import layoutManager from '../layoutManager'; import layoutManager from '../layoutManager';
import { playbackManager } from '../playback/playbackmanager'; import { playbackManager } from '../playback/playbackmanager';
import playMethodHelper from '../playback/playmethodhelper'; import playMethodHelper from '../playback/playmethodhelper';
import SyncPlay from '../../plugins/syncPlay/core'; import { pluginManager } from '../pluginManager';
import { PluginType } from '../../types/plugin.ts';
import './playerstats.scss'; import './playerstats.scss';
import ServerConnections from '../ServerConnections'; import ServerConnections from '../ServerConnections';
@ -325,6 +326,12 @@ import ServerConnections from '../ServerConnections';
} }
function getSyncPlayStats() { function getSyncPlayStats() {
const SyncPlay = pluginManager.firstOfType(PluginType.SyncPlay)?.instance;
if (!SyncPlay?.Manager.isSyncPlayEnabled()) {
return [];
}
const syncStats = []; const syncStats = [];
const stats = SyncPlay.Manager.getStats(); const stats = SyncPlay.Manager.getStats();
@ -422,10 +429,10 @@ import ServerConnections from '../ServerConnections';
name: globalize.translate('LabelOriginalMediaInfo') name: globalize.translate('LabelOriginalMediaInfo')
}); });
const apiClient = ServerConnections.getApiClient(playbackManager.currentItem(player).ServerId); const syncPlayStats = getSyncPlayStats();
if (SyncPlay.Manager.isSyncPlayEnabled() && apiClient.isMinServerVersion('10.6.0')) { if (syncPlayStats.length > 0) {
categories.push({ categories.push({
stats: getSyncPlayStats(), stats: syncPlayStats,
name: globalize.translate('LabelSyncPlayInfo') name: globalize.translate('LabelSyncPlayInfo')
}); });
} }

View file

@ -4,10 +4,12 @@ import dialogHelper from '../dialogHelper/dialogHelper';
import loading from '../loading/loading'; import loading from '../loading/loading';
import layoutManager from '../layoutManager'; import layoutManager from '../layoutManager';
import { playbackManager } from '../playback/playbackmanager'; import { playbackManager } from '../playback/playbackmanager';
import SyncPlay from '../../plugins/syncPlay/core'; import { pluginManager } from '../pluginManager';
import * as userSettings from '../../scripts/settings/userSettings'; import * as userSettings from '../../scripts/settings/userSettings';
import { appRouter } from '../appRouter'; import { appRouter } from '../appRouter';
import globalize from '../../scripts/globalize'; import globalize from '../../scripts/globalize';
import { PluginType } from '../../types/plugin.ts';
import '../../elements/emby-button/emby-button'; import '../../elements/emby-button/emby-button';
import '../../elements/emby-input/emby-input'; import '../../elements/emby-input/emby-input';
import '../../elements/emby-button/paper-icon-button-light'; import '../../elements/emby-button/paper-icon-button-light';
@ -117,10 +119,12 @@ import ServerConnections from '../ServerConnections';
}; };
const apiClient = ServerConnections.getApiClient(currentServerId); const apiClient = ServerConnections.getApiClient(currentServerId);
const SyncPlay = pluginManager.firstOfType(PluginType.SyncPlay)?.instance;
apiClient.getItems(apiClient.getCurrentUserId(), options).then(result => { apiClient.getItems(apiClient.getCurrentUserId(), options).then(result => {
let html = ''; let html = '';
if ((editorOptions.enableAddToPlayQueue !== false && playbackManager.isPlaying()) || SyncPlay.Manager.isSyncPlayEnabled()) { if ((editorOptions.enableAddToPlayQueue !== false && playbackManager.isPlaying()) || SyncPlay?.Manager.isSyncPlayEnabled()) {
html += `<option value="queue">${globalize.translate('AddToPlayQueue')}</option>`; html += `<option value="queue">${globalize.translate('AddToPlayQueue')}</option>`;
} }

View file

@ -119,9 +119,14 @@ class PluginManager {
} }
ofType(type) { ofType(type) {
return this.pluginsList.filter((o) => { return this.pluginsList.filter(plugin => plugin.type === type);
return o.type === type; }
});
firstOfType(type) {
// Get all plugins of the specified type
return this.ofType(type)
// Return the plugin with the "highest" (lowest numeric value) priority
.sort((p1, p2) => (p1.priority || 0) - (p2.priority || 0))[0];
} }
#mapRoute(plugin, route) { #mapRoute(plugin, route) {

View file

@ -85,8 +85,8 @@ const SearchFields: FunctionComponent<SearchFieldsProps> = ({ onSearch = () => {
dangerouslySetInnerHTML={createInputElement()} dangerouslySetInnerHTML={createInputElement()}
/> />
</div> </div>
{layoutManager.tv && !browser.tv && {layoutManager.tv && !browser.tv
<AlphaPicker onAlphaPicked={onAlphaPicked} /> && <AlphaPicker onAlphaPicked={onAlphaPicked} />
} }
</div> </div>
); );

View file

@ -94,9 +94,9 @@ function init(instance) {
subtitleSyncSlider.getBubbleHtml = function (value) { subtitleSyncSlider.getBubbleHtml = function (value) {
const newOffset = getOffsetFromPercentage(value); const newOffset = getOffsetFromPercentage(value);
return '<h1 class="sliderBubbleText">' + return '<h1 class="sliderBubbleText">'
(newOffset > 0 ? '+' : '') + parseFloat(newOffset) + 's' + + (newOffset > 0 ? '+' : '') + parseFloat(newOffset) + 's'
'</h1>'; + '</h1>';
}; };
subtitleSyncCloseButton.addEventListener('click', function () { subtitleSyncCloseButton.addEventListener('click', function () {

View file

@ -253,6 +253,13 @@
</label> </label>
<div class="fieldDescription checkboxFieldDescription">${EnableFallbackFontHelp}</div> <div class="fieldDescription checkboxFieldDescription">${EnableFallbackFontHelp}</div>
</div> </div>
<div class="checkboxContainer checkboxContainer-withDescription">
<label>
<input is="emby-checkbox" type="checkbox" id="chkEnableAudioVbr" />
<span>${LabelEnableAudioVbr}</span>
</label>
<div class="fieldDescription checkboxFieldDescription">${LabelEnableAudioVbrHelp}</div>
</div>
<div class="inputContainer"> <div class="inputContainer">
<input is="emby-input" type="number" id="txtDownMixAudioBoost" pattern="[0-9]*" required="required" min=".5" max="3" step=".1" label="${LabelDownMixAudioScale}" /> <input is="emby-input" type="number" id="txtDownMixAudioBoost" pattern="[0-9]*" required="required" min=".5" max="3" step=".1" label="${LabelDownMixAudioScale}" />
<div class="fieldDescription">${LabelDownMixAudioScaleHelp}</div> <div class="fieldDescription">${LabelDownMixAudioScaleHelp}</div>

View file

@ -22,6 +22,7 @@ import alert from '../../components/alert';
page.querySelector('#chkAllowHevcEncoding').checked = config.AllowHevcEncoding; page.querySelector('#chkAllowHevcEncoding').checked = config.AllowHevcEncoding;
$('#selectVideoDecoder', page).val(config.HardwareAccelerationType); $('#selectVideoDecoder', page).val(config.HardwareAccelerationType);
$('#selectThreadCount', page).val(config.EncodingThreadCount); $('#selectThreadCount', page).val(config.EncodingThreadCount);
page.querySelector('#chkEnableAudioVbr').checked = config.EnableAudioVbr;
$('#txtDownMixAudioBoost', page).val(config.DownMixAudioBoost); $('#txtDownMixAudioBoost', page).val(config.DownMixAudioBoost);
$('#selectStereoDownmixAlgorithm').val(config.DownMixStereoAlgorithm || 'None'); $('#selectStereoDownmixAlgorithm').val(config.DownMixStereoAlgorithm || 'None');
page.querySelector('#txtMaxMuxingQueueSize').value = config.MaxMuxingQueueSize || ''; page.querySelector('#txtMaxMuxingQueueSize').value = config.MaxMuxingQueueSize || '';
@ -78,6 +79,7 @@ import alert from '../../components/alert';
const onDecoderConfirmed = function () { const onDecoderConfirmed = function () {
loading.show(); loading.show();
ApiClient.getNamedConfiguration('encoding').then(function (config) { ApiClient.getNamedConfiguration('encoding').then(function (config) {
config.EnableAudioVbr = form.querySelector('#chkEnableAudioVbr').checked;
config.DownMixAudioBoost = $('#txtDownMixAudioBoost', form).val(); config.DownMixAudioBoost = $('#txtDownMixAudioBoost', form).val();
config.DownMixStereoAlgorithm = $('#selectStereoDownmixAlgorithm', form).val() || 'None'; config.DownMixStereoAlgorithm = $('#selectStereoDownmixAlgorithm', form).val() || 'None';
config.MaxMuxingQueueSize = form.querySelector('#txtMaxMuxingQueueSize').value; config.MaxMuxingQueueSize = form.querySelector('#txtMaxMuxingQueueSize').value;

View file

@ -1,6 +1,5 @@
import escapeHtml from 'escape-html'; import escapeHtml from 'escape-html';
import { playbackManager } from '../../../components/playback/playbackmanager'; import { playbackManager } from '../../../components/playback/playbackmanager';
import SyncPlay from '../../../plugins/syncPlay/core';
import browser from '../../../scripts/browser'; import browser from '../../../scripts/browser';
import dom from '../../../scripts/dom'; import dom from '../../../scripts/dom';
import inputManager from '../../../scripts/inputManager'; import inputManager from '../../../scripts/inputManager';
@ -25,6 +24,8 @@ import SubtitleSync from '../../../components/subtitlesync/subtitlesync';
import { appRouter } from '../../../components/appRouter'; import { appRouter } from '../../../components/appRouter';
import LibraryMenu from '../../../scripts/libraryMenu'; import LibraryMenu from '../../../scripts/libraryMenu';
import { setBackdropTransparency, TRANSPARENCY_LEVEL } from '../../../components/backdrop/backdrop'; import { setBackdropTransparency, TRANSPARENCY_LEVEL } from '../../../components/backdrop/backdrop';
import { pluginManager } from '../../../components/pluginManager';
import { PluginType } from '../../../types/plugin.ts';
/* eslint-disable indent */ /* eslint-disable indent */
const TICKS_PER_MINUTE = 600000000; const TICKS_PER_MINUTE = 600000000;
@ -896,8 +897,8 @@ import { setBackdropTransparency, TRANSPARENCY_LEVEL } from '../../../components
const state = playbackManager.getPlayerState(player); const state = playbackManager.getPlayerState(player);
// show subtitle offset feature only if player and media support it // show subtitle offset feature only if player and media support it
const showSubOffset = playbackManager.supportSubtitleOffset(player) && const showSubOffset = playbackManager.supportSubtitleOffset(player)
playbackManager.canHandleOffsetOnCurrentSubtitle(player); && playbackManager.canHandleOffsetOnCurrentSubtitle(player);
playerSettingsMenu.show({ playerSettingsMenu.show({
mediaType: 'Video', mediaType: 'Video',
@ -1774,20 +1775,20 @@ import { setBackdropTransparency, TRANSPARENCY_LEVEL } from '../../../components
}, iconVisibilityTime); }, iconVisibilityTime);
}; };
Events.on(SyncPlay.Manager, 'enabled', (event, enabled) => { const SyncPlay = pluginManager.firstOfType(PluginType.SyncPlay)?.instance;
if (enabled) { if (SyncPlay) {
// SyncPlay enabled Events.on(SyncPlay.Manager, 'enabled', (_event, enabled) => {
} else { if (!enabled) {
const syncPlayIcon = view.querySelector('#syncPlayIcon'); const syncPlayIcon = view.querySelector('#syncPlayIcon');
syncPlayIcon.style.visibility = 'hidden'; syncPlayIcon.style.visibility = 'hidden';
} }
}); });
Events.on(SyncPlay.Manager, 'notify-osd', (event, action) => { Events.on(SyncPlay.Manager, 'notify-osd', (_event, action) => {
showIcon(action); showIcon(action);
}); });
Events.on(SyncPlay.Manager, 'group-state-update', (event, state, reason) => { Events.on(SyncPlay.Manager, 'group-state-update', (_event, state, reason) => {
if (state === 'Playing' && reason === 'Unpause') { if (state === 'Playing' && reason === 'Unpause') {
showIcon('schedule-play'); showIcon('schedule-play');
} else if (state === 'Playing' && reason === 'Ready') { } else if (state === 'Playing' && reason === 'Ready') {
@ -1807,5 +1808,6 @@ import { setBackdropTransparency, TRANSPARENCY_LEVEL } from '../../../components
} }
}); });
} }
}
/* eslint-enable indent */ /* eslint-enable indent */

View file

@ -229,8 +229,8 @@ const Scroller: FC<ScrollerProps> = ({
return ( return (
<> <>
{ {
showControls && scrollState.scrollWidth > scrollState.scrollSize + 20 && showControls && scrollState.scrollWidth > scrollState.scrollSize + 20
<ScrollButtons && <ScrollButtons
scrollRef={scrollRef} scrollRef={scrollRef}
scrollerFactoryRef={scrollerFactoryRef} scrollerFactoryRef={scrollerFactoryRef}
scrollState={scrollState} scrollState={scrollState}

View file

@ -17,15 +17,31 @@ import '../../elements/emby-button/paper-icon-button-light';
import html from './template.html'; import html from './template.html';
import './style.scss'; import './style.scss';
const THEMES = {
'dark': { 'body': { 'color': '#d8dadc', 'background': '#000', 'font-size': 'medium' } },
'sepia': { 'body': { 'color': '#d8a262', 'background': '#000', 'font-size': 'medium' } },
'light': { 'body': { 'color': '#000', 'background': '#fff', 'font-size': 'medium' } }
};
const THEME_ORDER = ['dark', 'sepia', 'light'];
const FONT_SIZES = ['x-small', 'small', 'medium', 'large', 'x-large'];
export class BookPlayer { export class BookPlayer {
constructor() { constructor() {
this.name = 'Book Player'; this.name = 'Book Player';
this.type = PluginType.MediaPlayer; this.type = PluginType.MediaPlayer;
this.id = 'bookplayer'; this.id = 'bookplayer';
this.priority = 1; this.priority = 1;
if (!userSettings.theme() || userSettings.theme() === 'dark') {
this.theme = 'dark';
} else {
this.theme = 'light';
}
this.fontSize = 'medium';
this.onDialogClosed = this.onDialogClosed.bind(this); this.onDialogClosed = this.onDialogClosed.bind(this);
this.openTableOfContents = this.openTableOfContents.bind(this); this.openTableOfContents = this.openTableOfContents.bind(this);
this.rotateTheme = this.rotateTheme.bind(this);
this.increaseFontSize = this.increaseFontSize.bind(this);
this.decreaseFontSize = this.decreaseFontSize.bind(this);
this.previous = this.previous.bind(this); this.previous = this.previous.bind(this);
this.next = this.next.bind(this); this.next = this.next.bind(this);
this.onWindowKeyUp = this.onWindowKeyUp.bind(this); this.onWindowKeyUp = this.onWindowKeyUp.bind(this);
@ -164,6 +180,9 @@ export class BookPlayer {
elem.querySelector('#btnBookplayerExit').addEventListener('click', this.onDialogClosed, { once: true }); elem.querySelector('#btnBookplayerExit').addEventListener('click', this.onDialogClosed, { once: true });
elem.querySelector('#btnBookplayerToc').addEventListener('click', this.openTableOfContents); elem.querySelector('#btnBookplayerToc').addEventListener('click', this.openTableOfContents);
elem.querySelector('#btnBookplayerFullscreen').addEventListener('click', this.toggleFullscreen); elem.querySelector('#btnBookplayerFullscreen').addEventListener('click', this.toggleFullscreen);
elem.querySelector('#btnBookplayerRotateTheme').addEventListener('click', this.rotateTheme);
elem.querySelector('#btnBookplayerIncreaseFontSize').addEventListener('click', this.increaseFontSize);
elem.querySelector('#btnBookplayerDecreaseFontSize').addEventListener('click', this.decreaseFontSize);
elem.querySelector('#btnBookplayerPrev')?.addEventListener('click', this.previous); elem.querySelector('#btnBookplayerPrev')?.addEventListener('click', this.previous);
elem.querySelector('#btnBookplayerNext')?.addEventListener('click', this.next); elem.querySelector('#btnBookplayerNext')?.addEventListener('click', this.next);
} }
@ -184,6 +203,9 @@ export class BookPlayer {
elem.querySelector('#btnBookplayerExit').removeEventListener('click', this.onDialogClosed); elem.querySelector('#btnBookplayerExit').removeEventListener('click', this.onDialogClosed);
elem.querySelector('#btnBookplayerToc').removeEventListener('click', this.openTableOfContents); elem.querySelector('#btnBookplayerToc').removeEventListener('click', this.openTableOfContents);
elem.querySelector('#btnBookplayerFullscreen').removeEventListener('click', this.toggleFullscreen); elem.querySelector('#btnBookplayerFullscreen').removeEventListener('click', this.toggleFullscreen);
elem.querySelector('#btnBookplayerRotateTheme').removeEventListener('click', this.rotateTheme);
elem.querySelector('#btnBookplayerIncreaseFontSize').removeEventListener('click', this.increaseFontSize);
elem.querySelector('#btnBookplayerDecreaseFontSize').removeEventListener('click', this.decreaseFontSize);
elem.querySelector('#btnBookplayerPrev')?.removeEventListener('click', this.previous); elem.querySelector('#btnBookplayerPrev')?.removeEventListener('click', this.previous);
elem.querySelector('#btnBookplayerNext')?.removeEventListener('click', this.next); elem.querySelector('#btnBookplayerNext')?.removeEventListener('click', this.next);
} }
@ -214,6 +236,31 @@ export class BookPlayer {
} }
} }
rotateTheme() {
if (this.loaded) {
const newTheme = THEME_ORDER[(THEME_ORDER.indexOf(this.theme) + 1) % THEME_ORDER.length];
this.rendition.themes.register('default', THEMES[newTheme]);
this.rendition.themes.update('default');
this.theme = newTheme;
}
}
increaseFontSize() {
if (this.loaded && this.fontSize !== FONT_SIZES[FONT_SIZES.length - 1]) {
const newFontSize = FONT_SIZES[(FONT_SIZES.indexOf(this.fontSize) + 1)];
this.rendition.themes.fontSize(newFontSize);
this.fontSize = newFontSize;
}
}
decreaseFontSize() {
if (this.loaded && this.fontSize !== FONT_SIZES[0]) {
const newFontSize = FONT_SIZES[(FONT_SIZES.indexOf(this.fontSize) - 1)];
this.rendition.themes.fontSize(newFontSize);
this.fontSize = newFontSize;
}
}
previous(e) { previous(e) {
e?.preventDefault(); e?.preventDefault();
if (this.rendition) { if (this.rendition) {
@ -296,11 +343,8 @@ export class BookPlayer {
this.currentSrc = downloadHref; this.currentSrc = downloadHref;
this.rendition = rendition; this.rendition = rendition;
rendition.themes.register('dark', { 'body': { 'color': '#fff' } }); rendition.themes.register('default', THEMES[this.theme]);
rendition.themes.select('default');
if (userSettings.theme(undefined) === 'dark' || userSettings.theme(undefined) === null) {
rendition.themes.select('dark');
}
return rendition.display().then(() => { return rendition.display().then(() => {
const epubElem = document.querySelector('.epub-container'); const epubElem = document.querySelector('.epub-container');

View file

@ -11,6 +11,15 @@
<button is="paper-icon-button-light" id="btnBookplayerExit" class="autoSize bookplayerButton hide-mouse-idle-tv" tabindex="-1"> <button is="paper-icon-button-light" id="btnBookplayerExit" class="autoSize bookplayerButton hide-mouse-idle-tv" tabindex="-1">
<span class="material-icons bookplayerButtonIcon close" aria-hidden="true"></span> <span class="material-icons bookplayerButtonIcon close" aria-hidden="true"></span>
</button> </button>
<button is="paper-icon-button-light" id="btnBookplayerRotateTheme" class="autoSize bookplayerButton hide-mouse-idle-tv" tabindex="-1">
<span class="material-icons bookplayerButtonIcon remove_red_eye" aria-hidden="true"></span>
</button>
<button is="paper-icon-button-light" id="btnBookplayerDecreaseFontSize" class="autoSize bookplayerButton hide-mouse-idle-tv" tabindex="-1">
<span class="material-icons bookplayerButtonIcon text_decrease" aria-hidden="true"></span>
</button>
<button is="paper-icon-button-light" id="btnBookplayerIncreaseFontSize" class="autoSize bookplayerButton hide-mouse-idle-tv" tabindex="-1">
<span class="material-icons bookplayerButtonIcon text_increase" aria-hidden="true"></span>
</button>
<button is="paper-icon-button-light" id="btnBookplayerFullscreen" class="autoSize bookplayerButton hide-mouse-idle-tv" tabindex="-1"> <button is="paper-icon-button-light" id="btnBookplayerFullscreen" class="autoSize bookplayerButton hide-mouse-idle-tv" tabindex="-1">
<span class="material-icons bookplayerButtonIcon fullscreen" aria-hidden="true"></span> <span class="material-icons bookplayerButtonIcon fullscreen" aria-hidden="true"></span>
</button> </button>

View file

@ -133,9 +133,9 @@ class PlaybackCore {
*/ */
async sendBufferingRequest(isBuffering = true) { async sendBufferingRequest(isBuffering = true) {
const playerWrapper = this.manager.getPlayerWrapper(); const playerWrapper = this.manager.getPlayerWrapper();
const currentPosition = (playerWrapper.currentTimeAsync const currentPosition = (playerWrapper.currentTimeAsync ?
? await playerWrapper.currentTimeAsync() await playerWrapper.currentTimeAsync() :
: playerWrapper.currentTime()); playerWrapper.currentTime());
const currentPositionTicks = Math.round(currentPosition * Helper.TicksPerMillisecond); const currentPositionTicks = Math.round(currentPosition * Helper.TicksPerMillisecond);
const isPlaying = playerWrapper.isPlaying(); const isPlaying = playerWrapper.isPlaying();
@ -172,11 +172,11 @@ class PlaybackCore {
*/ */
async applyCommand(command) { async applyCommand(command) {
// Check if duplicate. // Check if duplicate.
if (this.lastCommand && if (this.lastCommand
this.lastCommand.When.getTime() === command.When.getTime() && && this.lastCommand.When.getTime() === command.When.getTime()
this.lastCommand.PositionTicks === command.PositionTicks && && this.lastCommand.PositionTicks === command.PositionTicks
this.lastCommand.Command === command.Command && && this.lastCommand.Command === command.Command
this.lastCommand.PlaylistItemId === command.PlaylistItemId && this.lastCommand.PlaylistItemId === command.PlaylistItemId
) { ) {
// Duplicate command found, check playback state and correct if needed. // Duplicate command found, check playback state and correct if needed.
console.debug('SyncPlay applyCommand: duplicate command received!', command); console.debug('SyncPlay applyCommand: duplicate command received!', command);
@ -192,9 +192,9 @@ class PlaybackCore {
} else { } else {
// Check if playback state matches requested command. // Check if playback state matches requested command.
const playerWrapper = this.manager.getPlayerWrapper(); const playerWrapper = this.manager.getPlayerWrapper();
const currentPositionTicks = Math.round((playerWrapper.currentTimeAsync const currentPositionTicks = Math.round((playerWrapper.currentTimeAsync ?
? await playerWrapper.currentTimeAsync() await playerWrapper.currentTimeAsync() :
: playerWrapper.currentTime()) * Helper.TicksPerMillisecond); playerWrapper.currentTime()) * Helper.TicksPerMillisecond);
const isPlaying = playerWrapper.isPlaying(); const isPlaying = playerWrapper.isPlaying();
switch (command.Command) { switch (command.Command) {
@ -279,9 +279,9 @@ class PlaybackCore {
const playAtTimeLocal = this.timeSyncCore.remoteDateToLocal(playAtTime); const playAtTimeLocal = this.timeSyncCore.remoteDateToLocal(playAtTime);
const playerWrapper = this.manager.getPlayerWrapper(); const playerWrapper = this.manager.getPlayerWrapper();
const currentPositionTicks = (playerWrapper.currentTimeAsync const currentPositionTicks = (playerWrapper.currentTimeAsync ?
? await playerWrapper.currentTimeAsync() await playerWrapper.currentTimeAsync() :
: playerWrapper.currentTime()) * Helper.TicksPerMillisecond; playerWrapper.currentTime()) * Helper.TicksPerMillisecond;
if (playAtTimeLocal > currentTime) { if (playAtTimeLocal > currentTime) {
const playTimeout = playAtTimeLocal - currentTime; const playTimeout = playAtTimeLocal - currentTime;

View file

@ -174,9 +174,9 @@ class QueueCore {
const currentTime = new Date(); const currentTime = new Date();
const now = this.manager.timeSyncCore.localDateToRemote(currentTime); const now = this.manager.timeSyncCore.localDateToRemote(currentTime);
const currentPosition = (playerWrapper.currentTimeAsync const currentPosition = (playerWrapper.currentTimeAsync ?
? await playerWrapper.currentTimeAsync() await playerWrapper.currentTimeAsync() :
: playerWrapper.currentTime()); playerWrapper.currentTime());
const currentPositionTicks = Math.round(currentPosition * Helper.TicksPerMillisecond); const currentPositionTicks = Math.round(currentPosition * Helper.TicksPerMillisecond);
const isPlaying = playerWrapper.isPlaying(); const isPlaying = playerWrapper.isPlaying();

View file

@ -12,6 +12,7 @@ class SyncPlayPlugin implements Plugin {
id: string; id: string;
type: string; type: string;
priority: number; priority: number;
instance: typeof SyncPlay;
constructor() { constructor() {
this.name = 'SyncPlay Plugin'; this.name = 'SyncPlay Plugin';
@ -21,6 +22,8 @@ class SyncPlayPlugin implements Plugin {
this.type = PluginType.SyncPlay; this.type = PluginType.SyncPlay;
this.priority = 1; this.priority = 1;
this.instance = SyncPlay;
this.init(); this.init();
} }

View file

@ -1,11 +1,12 @@
import SyncPlay from '../core';
import SyncPlaySettingsEditor from './settings/SettingsEditor'; import SyncPlaySettingsEditor from './settings/SettingsEditor';
import loading from '../../../components/loading/loading'; import loading from '../../../components/loading/loading';
import toast from '../../../components/toast/toast'; import toast from '../../../components/toast/toast';
import actionsheet from '../../../components/actionSheet/actionSheet'; import actionsheet from '../../../components/actionSheet/actionSheet';
import globalize from '../../../scripts/globalize'; import globalize from '../../../scripts/globalize';
import playbackPermissionManager from './playbackPermissionManager'; import playbackPermissionManager from './playbackPermissionManager';
import { pluginManager } from '../../../components/pluginManager';
import ServerConnections from '../../../components/ServerConnections'; import ServerConnections from '../../../components/ServerConnections';
import { PluginType } from '../../../types/plugin.ts';
import Events from '../../../utils/events.ts'; import Events from '../../../utils/events.ts';
import './groupSelectionMenu.scss'; import './groupSelectionMenu.scss';
@ -17,11 +18,25 @@ class GroupSelectionMenu {
constructor() { constructor() {
// Register to SyncPlay events. // Register to SyncPlay events.
this.syncPlayEnabled = false; this.syncPlayEnabled = false;
Events.on(SyncPlay.Manager, 'enabled', (e, enabled) => { this.SyncPlay = pluginManager.firstOfType(PluginType.SyncPlay)?.instance;
if (this.SyncPlay) {
Events.on(this.SyncPlay.Manager, 'enabled', (_event, enabled) => {
this.syncPlayEnabled = enabled; this.syncPlayEnabled = enabled;
}); });
} }
Events.on(pluginManager, 'registered', (_event0, plugin) => {
if (plugin.type === PluginType.SyncPlay) {
this.SyncPlay = plugin.instance;
Events.on(plugin.instance.Manager, 'enabled', (_event1, enabled) => {
this.syncPlayEnabled = enabled;
});
}
});
}
/** /**
* Used when user needs to join a group. * Used when user needs to join a group.
* @param {HTMLElement} button - Element where to place the menu. * @param {HTMLElement} button - Element where to place the menu.
@ -103,10 +118,11 @@ class GroupSelectionMenu {
* @param {Object} apiClient - ApiClient. * @param {Object} apiClient - ApiClient.
*/ */
showLeaveGroupSelection(button, user, apiClient) { showLeaveGroupSelection(button, user, apiClient) {
const groupInfo = SyncPlay.Manager.getGroupInfo(); const groupInfo = this.SyncPlay?.Manager.getGroupInfo();
const menuItems = []; const menuItems = [];
if (!SyncPlay.Manager.isPlaylistEmpty() && !SyncPlay.Manager.isPlaybackActive()) { if (!this.SyncPlay?.Manager.isPlaylistEmpty()
&& !this.SyncPlay?.Manager.isPlaybackActive()) {
menuItems.push({ menuItems.push({
name: globalize.translate('LabelSyncPlayResumePlayback'), name: globalize.translate('LabelSyncPlayResumePlayback'),
icon: 'play_circle_filled', icon: 'play_circle_filled',
@ -114,7 +130,7 @@ class GroupSelectionMenu {
selected: false, selected: false,
secondaryText: globalize.translate('LabelSyncPlayResumePlaybackDescription') secondaryText: globalize.translate('LabelSyncPlayResumePlaybackDescription')
}); });
} else if (SyncPlay.Manager.isPlaybackActive()) { } else if (this.SyncPlay?.Manager.isPlaybackActive()) {
menuItems.push({ menuItems.push({
name: globalize.translate('LabelSyncPlayHaltPlayback'), name: globalize.translate('LabelSyncPlayHaltPlayback'),
icon: 'pause_circle_filled', icon: 'pause_circle_filled',
@ -149,15 +165,15 @@ class GroupSelectionMenu {
border: true border: true
}; };
actionsheet.show(menuOptions).then(function (id) { actionsheet.show(menuOptions).then((id) => {
if (id == 'resume-playback') { if (id == 'resume-playback') {
SyncPlay.Manager.resumeGroupPlayback(apiClient); this.SyncPlay?.Manager.resumeGroupPlayback(apiClient);
} else if (id == 'halt-playback') { } else if (id == 'halt-playback') {
SyncPlay.Manager.haltGroupPlayback(apiClient); this.SyncPlay?.Manager.haltGroupPlayback(apiClient);
} else if (id == 'leave-group') { } else if (id == 'leave-group') {
apiClient.leaveSyncPlayGroup(); apiClient.leaveSyncPlayGroup();
} else if (id == 'settings') { } else if (id == 'settings') {
new SyncPlaySettingsEditor(apiClient, SyncPlay.Manager.getTimeSyncCore(), { groupInfo: groupInfo }) new SyncPlaySettingsEditor(apiClient, this.SyncPlay?.Manager.getTimeSyncCore(), { groupInfo: groupInfo })
.embed() .embed()
.catch(error => { .catch(error => {
if (error) { if (error) {

View file

@ -3,13 +3,14 @@
* @module components/syncPlay/settings/SettingsEditor * @module components/syncPlay/settings/SettingsEditor
*/ */
import SyncPlay from '../../core';
import { setSetting } from '../../core/Settings'; import { setSetting } from '../../core/Settings';
import dialogHelper from '../../../../components/dialogHelper/dialogHelper'; import dialogHelper from '../../../../components/dialogHelper/dialogHelper';
import layoutManager from '../../../../components/layoutManager'; import layoutManager from '../../../../components/layoutManager';
import { pluginManager } from '../../../../components/pluginManager';
import loading from '../../../../components/loading/loading'; import loading from '../../../../components/loading/loading';
import toast from '../../../../components/toast/toast'; import toast from '../../../../components/toast/toast';
import globalize from '../../../../scripts/globalize'; import globalize from '../../../../scripts/globalize';
import { PluginType } from '../../../../types/plugin.ts';
import Events from '../../../../utils/events.ts'; import Events from '../../../../utils/events.ts';
import 'material-design-icons-iconfont'; import 'material-design-icons-iconfont';
@ -36,6 +37,7 @@ class SettingsEditor {
this.apiClient = apiClient; this.apiClient = apiClient;
this.timeSyncCore = timeSyncCore; this.timeSyncCore = timeSyncCore;
this.options = options; this.options = options;
this.SyncPlay = pluginManager.firstOfType(PluginType.SyncPlay)?.instance;
} }
async embed() { async embed() {
@ -95,14 +97,14 @@ class SettingsEditor {
async initEditor() { async initEditor() {
const { context } = this; const { context } = this;
context.querySelector('#txtExtraTimeOffset').value = SyncPlay.Manager.timeSyncCore.extraTimeOffset; context.querySelector('#txtExtraTimeOffset').value = this.SyncPlay?.Manager.timeSyncCore.extraTimeOffset;
context.querySelector('#chkSyncCorrection').checked = SyncPlay.Manager.playbackCore.enableSyncCorrection; context.querySelector('#chkSyncCorrection').checked = this.SyncPlay?.Manager.playbackCore.enableSyncCorrection;
context.querySelector('#txtMinDelaySpeedToSync').value = SyncPlay.Manager.playbackCore.minDelaySpeedToSync; context.querySelector('#txtMinDelaySpeedToSync').value = this.SyncPlay?.Manager.playbackCore.minDelaySpeedToSync;
context.querySelector('#txtMaxDelaySpeedToSync').value = SyncPlay.Manager.playbackCore.maxDelaySpeedToSync; context.querySelector('#txtMaxDelaySpeedToSync').value = this.SyncPlay?.Manager.playbackCore.maxDelaySpeedToSync;
context.querySelector('#txtSpeedToSyncDuration').value = SyncPlay.Manager.playbackCore.speedToSyncDuration; context.querySelector('#txtSpeedToSyncDuration').value = this.SyncPlay?.Manager.playbackCore.speedToSyncDuration;
context.querySelector('#txtMinDelaySkipToSync').value = SyncPlay.Manager.playbackCore.minDelaySkipToSync; context.querySelector('#txtMinDelaySkipToSync').value = this.SyncPlay?.Manager.playbackCore.minDelaySkipToSync;
context.querySelector('#chkSpeedToSync').checked = SyncPlay.Manager.playbackCore.useSpeedToSync; context.querySelector('#chkSpeedToSync').checked = this.SyncPlay?.Manager.playbackCore.useSpeedToSync;
context.querySelector('#chkSkipToSync').checked = SyncPlay.Manager.playbackCore.useSkipToSync; context.querySelector('#chkSkipToSync').checked = this.SyncPlay?.Manager.playbackCore.useSkipToSync;
} }
onSubmit() { onSubmit() {
@ -139,7 +141,7 @@ class SettingsEditor {
setSetting('useSpeedToSync', useSpeedToSync); setSetting('useSpeedToSync', useSpeedToSync);
setSetting('useSkipToSync', useSkipToSync); setSetting('useSkipToSync', useSkipToSync);
Events.trigger(SyncPlay.Manager, 'settings-update'); Events.trigger(this.SyncPlay?.Manager, 'settings-update');
} }
} }

View file

@ -19,8 +19,8 @@ const Search: FunctionComponent = () => {
className='mainAnimatedPage libraryPage allLibraryPage noSecondaryNavPage' className='mainAnimatedPage libraryPage allLibraryPage noSecondaryNavPage'
> >
<SearchFields onSearch={setQuery} /> <SearchFields onSearch={setQuery} />
{!query && {!query
<SearchSuggestions && <SearchSuggestions
parentId={searchParams.get('parentId')} parentId={searchParams.get('parentId')}
/> />
} }

View file

@ -187,25 +187,25 @@ function supportsCssAnimation(allowPrefix) {
const uaMatch = function (ua) { const uaMatch = function (ua) {
ua = ua.toLowerCase(); ua = ua.toLowerCase();
const match = /(edg)[ /]([\w.]+)/.exec(ua) || const match = /(edg)[ /]([\w.]+)/.exec(ua)
/(edga)[ /]([\w.]+)/.exec(ua) || || /(edga)[ /]([\w.]+)/.exec(ua)
/(edgios)[ /]([\w.]+)/.exec(ua) || || /(edgios)[ /]([\w.]+)/.exec(ua)
/(edge)[ /]([\w.]+)/.exec(ua) || || /(edge)[ /]([\w.]+)/.exec(ua)
/(opera)[ /]([\w.]+)/.exec(ua) || || /(opera)[ /]([\w.]+)/.exec(ua)
/(opr)[ /]([\w.]+)/.exec(ua) || || /(opr)[ /]([\w.]+)/.exec(ua)
/(chrome)[ /]([\w.]+)/.exec(ua) || || /(chrome)[ /]([\w.]+)/.exec(ua)
/(safari)[ /]([\w.]+)/.exec(ua) || || /(safari)[ /]([\w.]+)/.exec(ua)
/(firefox)[ /]([\w.]+)/.exec(ua) || || /(firefox)[ /]([\w.]+)/.exec(ua)
ua.indexOf('compatible') < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || || ua.indexOf('compatible') < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua)
[]; || [];
const versionMatch = /(version)[ /]([\w.]+)/.exec(ua); const versionMatch = /(version)[ /]([\w.]+)/.exec(ua);
let platform_match = /(ipad)/.exec(ua) || let platform_match = /(ipad)/.exec(ua)
/(iphone)/.exec(ua) || || /(iphone)/.exec(ua)
/(windows)/.exec(ua) || || /(windows)/.exec(ua)
/(android)/.exec(ua) || || /(android)/.exec(ua)
[]; || [];
let browser = match[1] || ''; let browser = match[1] || '';

View file

@ -17,11 +17,11 @@ import browser from './browser';
} }
// hevc main level 4.0 // hevc main level 4.0
return !!videoTestElement.canPlayType && return !!videoTestElement.canPlayType
(videoTestElement.canPlayType('video/mp4; codecs="hvc1.1.L120"').replace(/no/, '') || && (videoTestElement.canPlayType('video/mp4; codecs="hvc1.1.L120"').replace(/no/, '')
videoTestElement.canPlayType('video/mp4; codecs="hev1.1.L120"').replace(/no/, '') || || videoTestElement.canPlayType('video/mp4; codecs="hev1.1.L120"').replace(/no/, '')
videoTestElement.canPlayType('video/mp4; codecs="hvc1.1.0.L120"').replace(/no/, '') || || videoTestElement.canPlayType('video/mp4; codecs="hvc1.1.0.L120"').replace(/no/, '')
videoTestElement.canPlayType('video/mp4; codecs="hev1.1.0.L120"').replace(/no/, '')); || videoTestElement.canPlayType('video/mp4; codecs="hev1.1.0.L120"').replace(/no/, ''));
} }
let _supportsTextTracks; let _supportsTextTracks;
@ -53,8 +53,8 @@ import browser from './browser';
} }
const media = document.createElement('video'); const media = document.createElement('video');
return !!(media.canPlayType('application/x-mpegURL').replace(/no/, '') || return !!(media.canPlayType('application/x-mpegURL').replace(/no/, '')
media.canPlayType('application/vnd.apple.mpegURL').replace(/no/, '')); || media.canPlayType('application/vnd.apple.mpegURL').replace(/no/, ''));
} }
function canPlayHlsWithMSE() { function canPlayHlsWithMSE() {
@ -96,8 +96,8 @@ import browser from './browser';
} }
if (videoTestElement.canPlayType) { if (videoTestElement.canPlayType) {
return videoTestElement.canPlayType('application/x-mpegurl; codecs="avc1.42E01E, ac-3"').replace(/no/, '') || return videoTestElement.canPlayType('application/x-mpegurl; codecs="avc1.42E01E, ac-3"').replace(/no/, '')
videoTestElement.canPlayType('application/vnd.apple.mpegURL; codecs="avc1.42E01E, ac-3"').replace(/no/, ''); || videoTestElement.canPlayType('application/vnd.apple.mpegURL; codecs="avc1.42E01E, ac-3"').replace(/no/, '');
} }
return false; return false;
@ -146,8 +146,8 @@ import browser from './browser';
return true; return true;
} }
if (videoTestElement.canPlayType('video/x-matroska').replace(/no/, '') || if (videoTestElement.canPlayType('video/x-matroska').replace(/no/, '')
videoTestElement.canPlayType('video/mkv').replace(/no/, '')) { || videoTestElement.canPlayType('video/mkv').replace(/no/, '')) {
return true; return true;
} }
@ -815,19 +815,19 @@ export function canPlaySecondaryAudio(videoTestElement) {
let maxH264Level = 42; let maxH264Level = 42;
let h264Profiles = 'high|main|baseline|constrained baseline'; let h264Profiles = 'high|main|baseline|constrained baseline';
if (browser.tizen || browser.web0s || if (browser.tizen || browser.web0s
videoTestElement.canPlayType('video/mp4; codecs="avc1.640833"').replace(/no/, '')) { || videoTestElement.canPlayType('video/mp4; codecs="avc1.640833"').replace(/no/, '')) {
maxH264Level = 51; maxH264Level = 51;
} }
// Support H264 Level 52 (Tizen 5.0) - app only // Support H264 Level 52 (Tizen 5.0) - app only
if ((browser.tizenVersion >= 5 && window.NativeShell) || if ((browser.tizenVersion >= 5 && window.NativeShell)
videoTestElement.canPlayType('video/mp4; codecs="avc1.640834"').replace(/no/, '')) { || videoTestElement.canPlayType('video/mp4; codecs="avc1.640834"').replace(/no/, '')) {
maxH264Level = 52; maxH264Level = 52;
} }
if ((browser.tizen || if ((browser.tizen
videoTestElement.canPlayType('video/mp4; codecs="avc1.6e0033"').replace(/no/, '')) || videoTestElement.canPlayType('video/mp4; codecs="avc1.6e0033"').replace(/no/, ''))
// These tests are passing in safari, but playback is failing // These tests are passing in safari, but playback is failing
&& !browser.safari && !browser.iOS && !browser.web0s && !browser.edge && !browser.mobile && !browser.safari && !browser.iOS && !browser.web0s && !browser.edge && !browser.mobile
) { ) {
@ -838,28 +838,28 @@ export function canPlaySecondaryAudio(videoTestElement) {
let hevcProfiles = 'main'; let hevcProfiles = 'main';
// hevc main level 4.1 // hevc main level 4.1
if (videoTestElement.canPlayType('video/mp4; codecs="hvc1.1.4.L123"').replace(/no/, '') || if (videoTestElement.canPlayType('video/mp4; codecs="hvc1.1.4.L123"').replace(/no/, '')
videoTestElement.canPlayType('video/mp4; codecs="hev1.1.4.L123"').replace(/no/, '')) { || videoTestElement.canPlayType('video/mp4; codecs="hev1.1.4.L123"').replace(/no/, '')) {
maxHevcLevel = 123; maxHevcLevel = 123;
} }
// hevc main10 level 4.1 // hevc main10 level 4.1
if (videoTestElement.canPlayType('video/mp4; codecs="hvc1.2.4.L123"').replace(/no/, '') || if (videoTestElement.canPlayType('video/mp4; codecs="hvc1.2.4.L123"').replace(/no/, '')
videoTestElement.canPlayType('video/mp4; codecs="hev1.2.4.L123"').replace(/no/, '')) { || videoTestElement.canPlayType('video/mp4; codecs="hev1.2.4.L123"').replace(/no/, '')) {
maxHevcLevel = 123; maxHevcLevel = 123;
hevcProfiles = 'main|main 10'; hevcProfiles = 'main|main 10';
} }
// hevc main10 level 5.1 // hevc main10 level 5.1
if (videoTestElement.canPlayType('video/mp4; codecs="hvc1.2.4.L153"').replace(/no/, '') || if (videoTestElement.canPlayType('video/mp4; codecs="hvc1.2.4.L153"').replace(/no/, '')
videoTestElement.canPlayType('video/mp4; codecs="hev1.2.4.L153"').replace(/no/, '')) { || videoTestElement.canPlayType('video/mp4; codecs="hev1.2.4.L153"').replace(/no/, '')) {
maxHevcLevel = 153; maxHevcLevel = 153;
hevcProfiles = 'main|main 10'; hevcProfiles = 'main|main 10';
} }
// hevc main10 level 6.1 // hevc main10 level 6.1
if (videoTestElement.canPlayType('video/mp4; codecs="hvc1.2.4.L183"').replace(/no/, '') || if (videoTestElement.canPlayType('video/mp4; codecs="hvc1.2.4.L183"').replace(/no/, '')
videoTestElement.canPlayType('video/mp4; codecs="hev1.2.4.L183"').replace(/no/, '')) { || videoTestElement.canPlayType('video/mp4; codecs="hev1.2.4.L183"').replace(/no/, '')) {
maxHevcLevel = 183; maxHevcLevel = 183;
hevcProfiles = 'main|main 10'; hevcProfiles = 'main|main 10';
} }

View file

@ -1,5 +1,5 @@
import { playbackManager } from '../components/playback/playbackmanager'; import { playbackManager } from '../components/playback/playbackmanager';
import SyncPlay from '../plugins/syncPlay/core'; import { pluginManager } from '../components/pluginManager';
import inputManager from '../scripts/inputManager'; import inputManager from '../scripts/inputManager';
import focusManager from '../components/focusManager'; import focusManager from '../components/focusManager';
import { appRouter } from '../components/appRouter'; import { appRouter } from '../components/appRouter';
@ -7,6 +7,7 @@ import ServerConnections from '../components/ServerConnections';
import toast from '../components/toast/toast'; import toast from '../components/toast/toast';
import alert from '../components/alert'; import alert from '../components/alert';
import Events from '../utils/events.ts'; import Events from '../utils/events.ts';
import { PluginType } from '../types/plugin.ts';
const serverNotifications = {}; const serverNotifications = {};
@ -140,6 +141,8 @@ function processGeneralCommand(cmd, apiClient) {
function onMessageReceived(e, msg) { function onMessageReceived(e, msg) {
const apiClient = this; const apiClient = this;
const SyncPlay = pluginManager.firstOfType(PluginType.SyncPlay)?.instance;
if (msg.MessageType === 'Play') { if (msg.MessageType === 'Play') {
notifyApp(); notifyApp();
const serverId = apiClient.serverInfo().Id; const serverId = apiClient.serverInfo().Id;
@ -186,9 +189,9 @@ function onMessageReceived(e, msg) {
} }
} }
} else if (msg.MessageType === 'SyncPlayCommand') { } else if (msg.MessageType === 'SyncPlayCommand') {
SyncPlay.Manager.processCommand(msg.Data, apiClient); SyncPlay?.Manager.processCommand(msg.Data, apiClient);
} else if (msg.MessageType === 'SyncPlayGroupUpdate') { } else if (msg.MessageType === 'SyncPlayGroupUpdate') {
SyncPlay.Manager.processGroupUpdate(msg.Data, apiClient); SyncPlay?.Manager.processGroupUpdate(msg.Data, apiClient);
} else { } else {
Events.trigger(serverNotifications, msg.MessageType, [apiClient, msg.Data]); Events.trigger(serverNotifications, msg.MessageType, [apiClient, msg.Data]);
} }

19
src/strings/bn.json Normal file
View file

@ -0,0 +1,19 @@
{
"Favorites": "পছন্দসমূহ",
"Albums": "অ্যালবামসমূহ",
"Artists": "শিল্পীগণ",
"Books": "পুস্তকসমূহ",
"Channels": "চ্যানেলসমূহ",
"Collections": "সংগ্রহশালা",
"Folders": "ফোল্ডারসমূহ",
"Genres": "শৈলীধারাসমূহ",
"HeaderAlbumArtists": "অ্যালবাম শিল্পীবৃন্দ",
"HeaderContinueWatching": "দেখতে থাকুন",
"Movies": "চলচ্চিত্রসমূহ",
"MusicVideos": "সঙ্গীত ভিডিয়ো সমূহ",
"Photos": "চিত্রসমূহ",
"Playlists": "প্লে লিস্ট সমূহ",
"Songs": "সঙ্গীতসমূহ",
"Sync": "সমলয় স্থাপন",
"ValueSpecialEpisodeName": "বিশেষ পর্ব - {0}"
}

View file

@ -14,10 +14,10 @@
"AspectRatio": "Relació d'aspecte", "AspectRatio": "Relació d'aspecte",
"Audio": "Àudio", "Audio": "Àudio",
"MessageBrowsePluginCatalog": "Consulteu el nostre catàleg per veure els complements disponibles.", "MessageBrowsePluginCatalog": "Consulteu el nostre catàleg per veure els complements disponibles.",
"ButtonAddMediaLibrary": "Afegir Biblioteca Multimèdia", "ButtonAddMediaLibrary": "Afegir biblioteca de mitjans",
"ButtonAddScheduledTaskTrigger": "Afegir Disparador", "ButtonAddScheduledTaskTrigger": "Afegir Disparador",
"ButtonAddServer": "Afegeix Servidor", "ButtonAddServer": "Afegeix Servidor",
"ButtonAddUser": "Afegir Usuari", "ButtonAddUser": "Afegir usuari",
"ButtonArrowLeft": "Esquerra", "ButtonArrowLeft": "Esquerra",
"ButtonArrowRight": "Dreta", "ButtonArrowRight": "Dreta",
"ButtonBack": "Darrera", "ButtonBack": "Darrera",
@ -38,7 +38,7 @@
"ButtonQuickStartGuide": "Guia d'inici ràpid", "ButtonQuickStartGuide": "Guia d'inici ràpid",
"ButtonRefreshGuideData": "Actualitza les dades de la guia", "ButtonRefreshGuideData": "Actualitza les dades de la guia",
"ButtonRemove": "Elimina", "ButtonRemove": "Elimina",
"ButtonResetEasyPassword": "Reinicia el codi PIN senzill", "ButtonResetEasyPassword": "Restabliu el codi Easy PIN",
"ButtonResume": "Reprèn", "ButtonResume": "Reprèn",
"ButtonSelectDirectory": "Selecciona el directori", "ButtonSelectDirectory": "Selecciona el directori",
"ButtonSend": "Envia", "ButtonSend": "Envia",
@ -61,7 +61,7 @@
"DeleteImage": "Esborra Imatge", "DeleteImage": "Esborra Imatge",
"DeleteImageConfirmation": "Esteu segur que voleu suprimir aquesta imatge?", "DeleteImageConfirmation": "Esteu segur que voleu suprimir aquesta imatge?",
"DeleteMedia": "Esborra", "DeleteMedia": "Esborra",
"DeleteUser": "Esborra Usuari", "DeleteUser": "Esborrar usuari",
"Desktop": "Escriptori", "Desktop": "Escriptori",
"DeviceAccessHelp": "Això només s'aplica a dispositius que poden ser identificats i no previndrà l'accés des del navegador. Filtrant l'accés de dispositius a l'usuari previndrà l'ús de nous dispositius fins que hagin estat aprovats aquí.", "DeviceAccessHelp": "Això només s'aplica a dispositius que poden ser identificats i no previndrà l'accés des del navegador. Filtrant l'accés de dispositius a l'usuari previndrà l'ús de nous dispositius fins que hagin estat aprovats aquí.",
"Disconnect": "Desconnecta", "Disconnect": "Desconnecta",
@ -233,7 +233,7 @@
"LabelDay": "Dia de la setmana:", "LabelDay": "Dia de la setmana:",
"LabelDeathDate": "Data de defunció:", "LabelDeathDate": "Data de defunció:",
"LabelDefaultUser": "Usuari per defecte:", "LabelDefaultUser": "Usuari per defecte:",
"LabelDefaultUserHelp": "Determinar quina biblioteca d'usuari s'hauria de mostrar als dispositius connectats. Es pot anul·lar per a cada dispositiu emprant perfils.", "LabelDefaultUserHelp": "Determina quina biblioteca d'usuari s'hauria de mostrar als dispositius connectats. Es pot anul·lar per a cada dispositiu emprant perfils.",
"LabelDeviceDescription": "Descripció del dispositiu:", "LabelDeviceDescription": "Descripció del dispositiu:",
"LabelDiscNumber": "Disc:", "LabelDiscNumber": "Disc:",
"LabelDisplayLanguage": "Idioma de visualització:", "LabelDisplayLanguage": "Idioma de visualització:",
@ -300,7 +300,7 @@
"LabelModelDescription": "Descripció del model:", "LabelModelDescription": "Descripció del model:",
"LabelModelName": "Nom del model:", "LabelModelName": "Nom del model:",
"LabelModelNumber": "Nombre de model:", "LabelModelNumber": "Nombre de model:",
"LabelMonitorUsers": "Supervisar activitat de:", "LabelMonitorUsers": "Supervisar l'activitat de:",
"LabelMovieRecordingPath": "Directori de gravació de pel·lícules:", "LabelMovieRecordingPath": "Directori de gravació de pel·lícules:",
"LabelName": "Nom:", "LabelName": "Nom:",
"LabelNewName": "Nou nom:", "LabelNewName": "Nou nom:",
@ -371,7 +371,7 @@
"Live": "Directe", "Live": "Directe",
"MarkPlayed": "Marca com a reproduït", "MarkPlayed": "Marca com a reproduït",
"MarkUnplayed": "Marca com a no reproduït", "MarkUnplayed": "Marca com a no reproduït",
"MaxParentalRatingHelp": "El contingut amb una valoració superior no serà mostrat a l'usuari.", "MaxParentalRatingHelp": "El contingut amb una classificació superior no serà mostrat a l'usuari.",
"MediaInfoAspectRatio": "Relació d'aspecte", "MediaInfoAspectRatio": "Relació d'aspecte",
"MediaInfoChannels": "Canals", "MediaInfoChannels": "Canals",
"MediaInfoDefault": "Per defecte", "MediaInfoDefault": "Per defecte",
@ -402,7 +402,7 @@
"Mobile": "Mòbil", "Mobile": "Mòbil",
"Monday": "Dilluns", "Monday": "Dilluns",
"MoreFromValue": "Més de {0}", "MoreFromValue": "Més de {0}",
"MoreUsersCanBeAddedLater": "Podeu afegir més usuaris des del tauler de control després.", "MoreUsersCanBeAddedLater": "Es poden afegir més usuaris des del Tauler de control.",
"MoveLeft": "Moure a l'esquerra", "MoveLeft": "Moure a l'esquerra",
"MoveRight": "Moure a la dreta", "MoveRight": "Moure a la dreta",
"Mute": "Silencia", "Mute": "Silencia",
@ -431,7 +431,7 @@
"OptionAllowRemoteControlOthers": "Permetre el control remot d'altres usuaris", "OptionAllowRemoteControlOthers": "Permetre el control remot d'altres usuaris",
"OptionAllowRemoteSharedDevices": "Permetre el control remot dels dispositius compartits", "OptionAllowRemoteSharedDevices": "Permetre el control remot dels dispositius compartits",
"OptionAllowRemoteSharedDevicesHelp": "Els dispositius DLNA es consideren compartits fins que un usuari comença a controlar-los.", "OptionAllowRemoteSharedDevicesHelp": "Els dispositius DLNA es consideren compartits fins que un usuari comença a controlar-los.",
"OptionAllowUserToManageServer": "Permet aquest usuari gestionar el servidor", "OptionAllowUserToManageServer": "Permet a aquest usuari gestionar el servidor",
"OptionCommunityRating": "Valoració de la Comunitat", "OptionCommunityRating": "Valoració de la Comunitat",
"OptionCriticRating": "Valoració dels Crítics", "OptionCriticRating": "Valoració dels Crítics",
"OptionDaily": "Diari", "OptionDaily": "Diari",
@ -439,7 +439,7 @@
"OptionDateAddedImportTime": "Empra la data d'escaneig", "OptionDateAddedImportTime": "Empra la data d'escaneig",
"OptionDatePlayed": "Data de Reproducció", "OptionDatePlayed": "Data de Reproducció",
"OptionDisableUser": "Desactiva aquest usuari", "OptionDisableUser": "Desactiva aquest usuari",
"OptionDisableUserHelp": "El servidor no permetrà cap connexió daquest usuari. Les connexions existents es tancaran bruscament.", "OptionDisableUserHelp": "El servidor no permetrà cap connexió daquest usuari. Les connexions existents es tancaran immediatament.",
"OptionDislikes": "No m'agrada", "OptionDislikes": "No m'agrada",
"OptionEmbedSubtitles": "Incrusta dins el contenidor", "OptionEmbedSubtitles": "Incrusta dins el contenidor",
"OptionEnableAccessFromAllDevices": "Habilita l'accés des de tots els dispositius", "OptionEnableAccessFromAllDevices": "Habilita l'accés des de tots els dispositius",
@ -647,7 +647,7 @@
"BoxRear": "Caixa (posterior)", "BoxRear": "Caixa (posterior)",
"BoxSet": "Col·leció", "BoxSet": "Col·leció",
"Box": "Caixa", "Box": "Caixa",
"BookLibraryHelp": "L'àudio i els llibres de text són compatibles. Reviseu la {0} guia de denominació de llibres {1}.", "BookLibraryHelp": "Els audiollibres i els llibres son compatibles. Reviseu la {0} guia de denominació de llibres {1}.",
"Backdrops": "Fons", "Backdrops": "Fons",
"Backdrop": "Fons", "Backdrop": "Fons",
"Artist": "Artista", "Artist": "Artista",
@ -663,14 +663,14 @@
"CopyStreamURL": "Copia l'URL de reproducció", "CopyStreamURL": "Copia l'URL de reproducció",
"ContinueWatching": "Continuar mirant", "ContinueWatching": "Continuar mirant",
"ConfirmEndPlayerSession": "Vols tancar Jellyfin a {0}?", "ConfirmEndPlayerSession": "Vols tancar Jellyfin a {0}?",
"ConfirmDeleteItems": "L'esborrat d'aquests elements els eliminarà del sistema de fitxers i de la biblioteca multimèdia. Estàs segur que vols continuar?", "ConfirmDeleteItems": "L'esborrat d'aquests elements els eliminarà del sistema de fitxers i de la biblioteca de mitjans. Esteu segurs que voleu continuar?",
"ConfirmDeleteItem": "L'esborrat d'aquest element l'eliminarà del sistema de fitxers i de la biblioteca multimèdia. Estàs segur que vols continuar?", "ConfirmDeleteItem": "L'esborrat d'aquest element l'eliminarà del sistema de fitxers i de la biblioteca multimèdia. Esteu segurs que voleu continuar?",
"ConfigureDateAdded": "Configureu com es determinen les metadades de la \"Data d'afegit\" al Tauler > Biblioteques > Configuració de l'NFO", "ConfigureDateAdded": "Configureu com es determinen les metadades de la \"Data d'afegit\" al Tauler > Biblioteques > Configuració de l'NFO",
"CommunityRating": "Ràting comunitari", "CommunityRating": "Ràting comunitari",
"ColorTransfer": "Transferència de color", "ColorTransfer": "Transferència de color",
"ColorSpace": "Espai de color", "ColorSpace": "Espai de color",
"ColorPrimaries": "Colors primaris", "ColorPrimaries": "Colors primaris",
"DefaultMetadataLangaugeDescription": "Aquests són els teus valors per defecte i poden ser personalitats per cada biblioteca.", "DefaultMetadataLangaugeDescription": "Aquests son els vostres valors per defecte i poden ser personalitzats per a cada biblioteca.",
"Default": "Per defecte", "Default": "Per defecte",
"DatePlayed": "Data reproduït", "DatePlayed": "Data reproduït",
"DateAdded": "Data d'addició", "DateAdded": "Data d'addició",
@ -716,7 +716,7 @@
"EnableBackdropsHelp": "Mostra imatges al fons d'algunes pàgines mentre navegueu per la biblioteca.", "EnableBackdropsHelp": "Mostra imatges al fons d'algunes pàgines mentre navegueu per la biblioteca.",
"EnableAutoCast": "Establir com a defecte", "EnableAutoCast": "Establir com a defecte",
"EditMetadata": "Edita les metadades", "EditMetadata": "Edita les metadades",
"EasyPasswordHelp": "El vostre codi PIN fàcil s'utilitza per accedir fora de línia als clients compatibles i també es pot utilitzar per iniciar la sessió a la xarxa fàcilment.", "EasyPasswordHelp": "El vostre codi Easy PIN s'utilitza per accedir fora de línia als clients compatibles i també es pot utilitzar per iniciar la sessió a la xarxa fàcilment.",
"DrmChannelsNotImported": "Els canals amb DRM no simportaran.", "DrmChannelsNotImported": "Els canals amb DRM no simportaran.",
"DownloadsValue": "{0} descàrregues", "DownloadsValue": "{0} descàrregues",
"DisplayMissingEpisodesWithinSeasonsHelp": "Això també s'ha d'activar per a les biblioteques de TV a la configuració del servidor.", "DisplayMissingEpisodesWithinSeasonsHelp": "Això també s'ha d'activar per a les biblioteques de TV a la configuració del servidor.",
@ -731,7 +731,7 @@
"DirectPlaying": "Reproducció directe", "DirectPlaying": "Reproducció directe",
"DetectingDevices": "Detectant dispositius", "DetectingDevices": "Detectant dispositius",
"Descending": "Descendent", "Descending": "Descendent",
"DeleteUserConfirmation": "Esteu segur que voleu eliminar aquest usuari?", "DeleteUserConfirmation": "Esteu segurs que voleu eliminar aquest usuari?",
"DeleteDeviceConfirmation": "Esteu segurs que voleu suprimir aquest dispositiu? Tornarà a aparèixer la propera vegada que un usuari iniciï la sessió amb ell.", "DeleteDeviceConfirmation": "Esteu segurs que voleu suprimir aquest dispositiu? Tornarà a aparèixer la propera vegada que un usuari iniciï la sessió amb ell.",
"Data": "Dades", "Data": "Dades",
"ButtonUseQuickConnect": "Utilitzar Quick Connect", "ButtonUseQuickConnect": "Utilitzar Quick Connect",
@ -770,7 +770,7 @@
"EnablePlugin": "Activar", "EnablePlugin": "Activar",
"DirectStreamHelp1": "El flux de vídeo és compatible amb el dispositiu, però té un format d'àudio incompatible (DTS, Dolby TrueHD, etc.) o un nombre de canals d'àudio. El flux de vídeo es tornarà a empaquetar sense pèrdues sobre la marxa abans d'enviar-lo al dispositiu. Només es transcodificarà el flux d'àudio.", "DirectStreamHelp1": "El flux de vídeo és compatible amb el dispositiu, però té un format d'àudio incompatible (DTS, Dolby TrueHD, etc.) o un nombre de canals d'àudio. El flux de vídeo es tornarà a empaquetar sense pèrdues sobre la marxa abans d'enviar-lo al dispositiu. Només es transcodificarà el flux d'àudio.",
"DirectPlayHelp": "El fitxer font és totalment compatible amb aquest client i la sessió rep el fitxer sense modificacions.", "DirectPlayHelp": "El fitxer font és totalment compatible amb aquest client i la sessió rep el fitxer sense modificacions.",
"DeleteDevicesConfirmation": "Esteu segurs que voleu suprimir tots els dispositius? Es tancarà la sessió de la resta de sessions. Els dispositius tornaran a aparèixer la pròxima vegada que un usuari iniciï la sessió.", "DeleteDevicesConfirmation": "Esteu segurs que voleu suprimir tots els dispositius? Es tancaran la sessió de la resta de sessions. Els dispositius tornaran a aparèixer la pròxima vegada que un usuari iniciï la sessió.",
"DeleteAll": "Eliminar tots", "DeleteAll": "Eliminar tots",
"DeinterlaceMethodHelp": "Seleccioneu el mètode de desentrellaçat que voleu utilitzar quan transcodifiqueu el programari de contingut entrellaçat. Quan està activada l'acceleració de maquinari que admet el desentrellaçat de maquinari, s'utilitzarà el desentrellaçador de maquinari en lloc d'aquesta configuració.", "DeinterlaceMethodHelp": "Seleccioneu el mètode de desentrellaçat que voleu utilitzar quan transcodifiqueu el programari de contingut entrellaçat. Quan està activada l'acceleració de maquinari que admet el desentrellaçat de maquinari, s'utilitzarà el desentrellaçador de maquinari en lloc d'aquesta configuració.",
"HeaderDirectPlayProfileHelp": "Afegiu perfils de reproducció directa per indicar quins formats pot gestionar el dispositiu de forma nativa.", "HeaderDirectPlayProfileHelp": "Afegiu perfils de reproducció directa per indicar quins formats pot gestionar el dispositiu de forma nativa.",
@ -922,7 +922,7 @@
"TabLogs": "Registres", "TabLogs": "Registres",
"SystemDlnaProfilesHelp": "Perfils de el sistema són de només lectura. Els canvis en un perfil de sistema seran emmagatzemades a un nou perfil personalitzat.", "SystemDlnaProfilesHelp": "Perfils de el sistema són de només lectura. Els canvis en un perfil de sistema seran emmagatzemades a un nou perfil personalitzat.",
"SyncPlayGroupDefaultTitle": "Grup {0}'s", "SyncPlayGroupDefaultTitle": "Grup {0}'s",
"SyncPlayAccessHelp": "La funció SyncPlay permet sincronitzar la reproducció amb altres dispositius. Seleccioneu el nivell d'accés que té aquest usuari a SyncPlay.", "SyncPlayAccessHelp": "La funció SyncPlay permet sincronitzar la reproducció amb altres dispositius. Seleccioneu el nivell d'accés a SyncPlay que té aquest usuari.",
"SubtitleVerticalPositionHelp": "Número de línia on apareix el text. Els nombres positius indiquen dalt a baix. Els nombres negatius indiquen dalt a baix.", "SubtitleVerticalPositionHelp": "Número de línia on apareix el text. Els nombres positius indiquen dalt a baix. Els nombres negatius indiquen dalt a baix.",
"SubtitleOffset": "Subtítol Offset", "SubtitleOffset": "Subtítol Offset",
"SubtitleDownloadersHelp": "Activa i classificar les seves descarregadors de subtítols preferits en ordre de prioritat.", "SubtitleDownloadersHelp": "Activa i classificar les seves descarregadors de subtítols preferits en ordre de prioritat.",
@ -989,7 +989,7 @@
"MessageUnableToConnectToServer": "No es pot connectar amb el servidor seleccionat en aquest moment. Assegureu-vos que està funcionant i torni a intentar-ho.", "MessageUnableToConnectToServer": "No es pot connectar amb el servidor seleccionat en aquest moment. Assegureu-vos que està funcionant i torni a intentar-ho.",
"MessageTheFollowingLocationWillBeRemovedFromLibrary": "Les ubicacions següents mitjans de comunicació seran eliminats de la biblioteca:", "MessageTheFollowingLocationWillBeRemovedFromLibrary": "Les ubicacions següents mitjans de comunicació seran eliminats de la biblioteca:",
"MessageSyncPlayUserLeft": "{0} ha deixat el grup.", "MessageSyncPlayUserLeft": "{0} ha deixat el grup.",
"MessageSyncPlayUserJoined": "{0} s'ha unit a el grup.", "MessageSyncPlayUserJoined": "{0} s'ha unit al grup.",
"MessageSyncPlayPlaybackPermissionRequired": "Permís de reproducció requerit.", "MessageSyncPlayPlaybackPermissionRequired": "Permís de reproducció requerit.",
"MessageSyncPlayNoGroupsAvailable": "No hi ha grups disponibles. Comença a jugar alguna cosa primer.", "MessageSyncPlayNoGroupsAvailable": "No hi ha grups disponibles. Comença a jugar alguna cosa primer.",
"MessageSyncPlayLibraryAccessDenied": "L'accés a aquest contingut està restringit.", "MessageSyncPlayLibraryAccessDenied": "L'accés a aquest contingut està restringit.",
@ -1012,13 +1012,13 @@
"MessagePluginConfigurationRequiresLocalAccess": "Connecteu-vos amb el servidor local directament per configurar aquest complement.", "MessagePluginConfigurationRequiresLocalAccess": "Connecteu-vos amb el servidor local directament per configurar aquest complement.",
"MessagePleaseWait": "Si us plau, espereu. Això pot trigar un minut.", "MessagePleaseWait": "Si us plau, espereu. Això pot trigar un minut.",
"MessagePlayAccessRestricted": "La reproducció d'aquest contingut està restringit actualment. Poseu-vos en contacte amb l'administrador de servidor per obtenir més informació.", "MessagePlayAccessRestricted": "La reproducció d'aquest contingut està restringit actualment. Poseu-vos en contacte amb l'administrador de servidor per obtenir més informació.",
"MessagePasswordResetForUsers": "Els següents usuaris han tingut restablir les seves contrasenyes. Ara poden accedir als codis PIN que es van utilitzar per realitzar el restabliment.", "MessagePasswordResetForUsers": "S'han restablert contrasenyes dels següents usuaris. Ara poden accedir amb codis Easy PIN que van utilitzar per realitzar el restabliment.",
"MessageNoServersAvailable": "No hi ha servidors han estat trobats usant el descobriment automàtic de servidor.", "MessageNoServersAvailable": "No hi ha servidors han estat trobats usant el descobriment automàtic de servidor.",
"MessageNoRepositories": "No hi ha repositoris.", "MessageNoRepositories": "No hi ha repositoris.",
"MessageNoGenresAvailable": "Permetre alguns proveïdors de metadades per tirar dels gèneres a través d'Internet.", "MessageNoGenresAvailable": "Permetre alguns proveïdors de metadades per tirar dels gèneres a través d'Internet.",
"MessageNoCollectionsAvailable": "Les col·leccions us permeten gaudir d'agrupacions personalitzades de pel·lícules, sèries i àlbums. Feu clic al botó '+' per començar a crear col·leccions.", "MessageNoCollectionsAvailable": "Les col·leccions us permeten gaudir d'agrupacions personalitzades de pel·lícules, sèries i àlbums. Feu clic al botó '+' per començar a crear col·leccions.",
"MessageLeaveEmptyToInherit": "Deixar en blanc per Heretar configuració d'un element principal o el valor predeterminat global.", "MessageLeaveEmptyToInherit": "Deixar en blanc per Heretar configuració d'un element principal o el valor predeterminat global.",
"MessageInvalidUser": "Nom d'usuari o contrasenya incorrectes. Torni-ho a provar.", "MessageInvalidUser": "Nom d'usuari o contrasenya incorrectes. Torneu-ho a provar.",
"MessageInvalidForgotPasswordPin": "S'ha introduït un codi PIN no vàlid o caducat. Torni-ho a provar.", "MessageInvalidForgotPasswordPin": "S'ha introduït un codi PIN no vàlid o caducat. Torni-ho a provar.",
"MessageImageTypeNotSelected": "Seleccioneu un tipus d'imatge al menú desplegable.", "MessageImageTypeNotSelected": "Seleccioneu un tipus d'imatge al menú desplegable.",
"MessageImageFileTypeAllowed": "Només els arxius JPEG i PNG són compatibles.", "MessageImageFileTypeAllowed": "Només els arxius JPEG i PNG són compatibles.",
@ -1026,7 +1026,7 @@
"MessageForgotPasswordInNetworkRequired": "Torneu a iniciar el procés de restabliment de contrasenya des de dins de la seva xarxa domèstica.", "MessageForgotPasswordInNetworkRequired": "Torneu a iniciar el procés de restabliment de contrasenya des de dins de la seva xarxa domèstica.",
"MessageForgotPasswordFileCreated": "El següent arxiu s'ha creat en el seu servidor i conté instruccions sobre com procedir:", "MessageForgotPasswordFileCreated": "El següent arxiu s'ha creat en el seu servidor i conté instruccions sobre com procedir:",
"MessageFileReadError": "Hi ha hagut un error a llegint l'arxiu. Torni-ho a provar.", "MessageFileReadError": "Hi ha hagut un error a llegint l'arxiu. Torni-ho a provar.",
"MessageDirectoryPickerLinuxInstruction": "Per a Linux amb Arch Linux, CentOS, Debian, Fedora, openSUSE, o Ubuntu, ha de concedir a l'usuari del servei al menys l'accés de lectura als llocs d'emmagatzematge.", "MessageDirectoryPickerLinuxInstruction": "Per a Linux amb Arch Linux, CentOS, Debian, Fedora, openSUSE, o Ubuntu, ha de concedir a l'usuari del servei com a mínim l'accés de lectura als llocs d'emmagatzematge.",
"MessageDirectoryPickerBSDInstruction": "Per BSD, pot ser que hagi de configurar l'emmagatzematge dins del seu presó FreeNAS pel Jellyfin pot accedir als mitjans de comunicació.", "MessageDirectoryPickerBSDInstruction": "Per BSD, pot ser que hagi de configurar l'emmagatzematge dins del seu presó FreeNAS pel Jellyfin pot accedir als mitjans de comunicació.",
"MessageDeleteTaskTrigger": "Esteu segur que voleu eliminar aquest disparador tasca?", "MessageDeleteTaskTrigger": "Esteu segur que voleu eliminar aquest disparador tasca?",
"MessageCreateAccountAt": "Crear un compte a {0}", "MessageCreateAccountAt": "Crear un compte a {0}",
@ -1090,9 +1090,9 @@
"LabelVaapiDeviceHelp": "Aquest és el \"render node\" que s'utilitza per a l'acceleració de maquinari.", "LabelVaapiDeviceHelp": "Aquest és el \"render node\" que s'utilitza per a l'acceleració de maquinari.",
"LabelVaapiDevice": "Dispositiu VA-API:", "LabelVaapiDevice": "Dispositiu VA-API:",
"LabelUserRemoteClientBitrateLimitHelp": "Substituir el valor global predeterminat establert a la configuració del servidor, vegeu Tauler de control > Reproducció > Streaming.", "LabelUserRemoteClientBitrateLimitHelp": "Substituir el valor global predeterminat establert a la configuració del servidor, vegeu Tauler de control > Reproducció > Streaming.",
"LabelUserMaxActiveSessions": "nombre màxim de sessions simultànies d'usuaris:", "LabelUserMaxActiveSessions": "Nombre màxim de sessions simultànies d'usuaris:",
"LabelUserLoginAttemptsBeforeLockout": "Intents de connexió fallits abans que l'usuari està bloquejat:", "LabelUserLoginAttemptsBeforeLockout": "Intents de connexió fallits abans que l'usuari sigui bloquejat:",
"LabelUserLibraryHelp": "Seleccioneu el qual la biblioteca d'usuaris per visualitzar al dispositiu. Deixar en blanc per heretar la configuració predeterminada.", "LabelUserLibraryHelp": "Seleccioneu quina biblioteca d'usuari es visualitza al dispositiu. Deixeu-ho en blanc per heretar la configuració predeterminada.",
"LabelUserAgent": "Agent d'usuari:", "LabelUserAgent": "Agent d'usuari:",
"LabelUnstable": "Inestable", "LabelUnstable": "Inestable",
"LabelUDPPortRangeHelp": "Restringir Jellyfin utilitzar aquest rang de ports a fer les connexions UDP. (Per defecte és 1024-65535) Nota <br/>: Certes funcions requereixen ports que poden estar fora d'aquest rang fix ..", "LabelUDPPortRangeHelp": "Restringir Jellyfin utilitzar aquest rang de ports a fer les connexions UDP. (Per defecte és 1024-65535) Nota <br/>: Certes funcions requereixen ports que poden estar fora d'aquest rang fix ..",
@ -1135,7 +1135,7 @@
"LabelSyncPlayLeaveGroup": "Marxar del grup", "LabelSyncPlayLeaveGroup": "Marxar del grup",
"LabelSyncPlayHaltPlaybackDescription": "I ignorar les actualitzacions de llista de reproducció actual", "LabelSyncPlayHaltPlaybackDescription": "I ignorar les actualitzacions de llista de reproducció actual",
"LabelSyncPlayHaltPlayback": "Aturar la reproducció local", "LabelSyncPlayHaltPlayback": "Aturar la reproducció local",
"LabelSyncPlayAccessNone": "Desactivat per aquest usuari", "LabelSyncPlayAccessNone": "Desactivat per a aquest usuari",
"LabelSyncPlayAccessJoinGroups": "Permetre als usuaris a unir-se als grups", "LabelSyncPlayAccessJoinGroups": "Permetre als usuaris a unir-se als grups",
"LabelSyncPlayAccessCreateAndJoinGroups": "Permetre a l'usuari crear i unir-se a grups", "LabelSyncPlayAccessCreateAndJoinGroups": "Permetre a l'usuari crear i unir-se a grups",
"LabelSyncPlayAccess": "Accés SyncPlay:", "LabelSyncPlayAccess": "Accés SyncPlay:",
@ -1237,8 +1237,8 @@
"LabelLibraryPageSizeHelp": "Estableix la quantitat d'elements a mostrar en una pàgina de la biblioteca. Es posa a 0 per tal de desactivar la paginació.", "LabelLibraryPageSizeHelp": "Estableix la quantitat d'elements a mostrar en una pàgina de la biblioteca. Es posa a 0 per tal de desactivar la paginació.",
"LabelLibraryPageSize": "Mida de pàgina de la biblioteca:", "LabelLibraryPageSize": "Mida de pàgina de la biblioteca:",
"LabelLanNetworks": "Xarxes LAN:", "LabelLanNetworks": "Xarxes LAN:",
"LabelKodiMetadataUserHelp": "Guardar dades de visionat als arxius NFO de manera que altres aplicacions les puguin utilitzar.", "LabelKodiMetadataUserHelp": "Guarda les dades de visionat en arxius NFO de manera que altres aplicacions les puguin utilitzar.",
"LabelKodiMetadataUser": "Guardar les dades de vigilància d'usuari a arxius NFO per:", "LabelKodiMetadataUser": "Guardar les dades de visualització d'usuari en arxius NFO per a:",
"LabelKodiMetadataSaveImagePathsHelp": "Això es recomana si vostè té els noms d'arxiu d'imatge que no s'ajusten a les directrius de Kodi.", "LabelKodiMetadataSaveImagePathsHelp": "Això es recomana si vostè té els noms d'arxiu d'imatge que no s'ajusten a les directrius de Kodi.",
"LabelKodiMetadataEnableExtraThumbsHelp": "Quan es descarreguin imatges, es poden guardar tant a \"extrafanart\" i \"extrathumbs\" per assegurar la màxima compatibilitat amb els skins del Kodi.", "LabelKodiMetadataEnableExtraThumbsHelp": "Quan es descarreguin imatges, es poden guardar tant a \"extrafanart\" i \"extrathumbs\" per assegurar la màxima compatibilitat amb els skins del Kodi.",
"LabelKodiMetadataEnableExtraThumbs": "Còpia extrafanart a el camp extrathumbs", "LabelKodiMetadataEnableExtraThumbs": "Còpia extrafanart a el camp extrathumbs",
@ -1262,7 +1262,7 @@
"LabelH265Crf": "H.265 codifica CRF:", "LabelH265Crf": "H.265 codifica CRF:",
"LabelH264Crf": "H.264 codifica CRF:", "LabelH264Crf": "H.264 codifica CRF:",
"LabelFormat": "Format:", "LabelFormat": "Format:",
"LabelForgotPasswordUsernameHelp": "Introdueix el nom d'usuari, si ho recordi.", "LabelForgotPasswordUsernameHelp": "Introduïu el nom d'usuari, si el recordeu.",
"LabelFont": "Font:", "LabelFont": "Font:",
"LabelFolder": "Carpeta:", "LabelFolder": "Carpeta:",
"LabelFileOrUrl": "Arxiu o URL:", "LabelFileOrUrl": "Arxiu o URL:",
@ -1453,7 +1453,7 @@
"OptionMaxActiveSessionsHelp": "Un valor de 0 desactivarà la funció.", "OptionMaxActiveSessionsHelp": "Un valor de 0 desactivarà la funció.",
"OptionMaxActiveSessions": "Establir el nombre màxim de sessions simultànies d'usuaris.", "OptionMaxActiveSessions": "Establir el nombre màxim de sessions simultànies d'usuaris.",
"OptionMax": "Max", "OptionMax": "Max",
"OptionLoginAttemptsBeforeLockoutHelp": "Un valor de 0 significa que hereten el valor per defecte de 3 intents per a usuaris normals i 5 pels administradors. Establir a -1 desactiva la funció.", "OptionLoginAttemptsBeforeLockoutHelp": "Un valor de 0 significa que s'hereten els valors per defecte: 3 intents per als usuaris normals i 5 per als administradors. Establir a -1 desactiva la funció.",
"OptionLoginAttemptsBeforeLockout": "Determina el nombre d'intents d'inici de sessió incorrectes que es poden fer abans que es bloquegi.", "OptionLoginAttemptsBeforeLockout": "Determina el nombre d'intents d'inici de sessió incorrectes que es poden fer abans que es bloquegi.",
"OptionIsSD": "SD", "OptionIsSD": "SD",
"OptionIsHD": "HD", "OptionIsHD": "HD",
@ -1480,7 +1480,7 @@
"OptionAllowVideoPlaybackRemuxing": "Permet la reproducció de vídeo que requereix una conversió sense recodificació", "OptionAllowVideoPlaybackRemuxing": "Permet la reproducció de vídeo que requereix una conversió sense recodificació",
"OptionAllowSyncTranscoding": "Permet la descàrrega i la sincronització dels mitjans que requereixen transcodificació", "OptionAllowSyncTranscoding": "Permet la descàrrega i la sincronització dels mitjans que requereixen transcodificació",
"OptionAllowMediaPlaybackTranscodingHelp": "La restricció de l'accés a la transcodificació pot provocar errors de reproducció en els clients a causa dels formats de mitjans compatibles.", "OptionAllowMediaPlaybackTranscodingHelp": "La restricció de l'accés a la transcodificació pot provocar errors de reproducció en els clients a causa dels formats de mitjans compatibles.",
"OptionAllowContentDownloadHelp": "Els usuaris poden descarregar els mitjans de comunicació i emmagatzemar-la en els seus dispositius. Això no és el mateix que una funció de sincronització. biblioteques de llibres requereixen aquesta habilitat per funcionar.", "OptionAllowContentDownloadHelp": "Els usuaris poden descarregar els mitjans i emmagatzemar-los als seus dispositius. Això no és el mateix que una funció de sincronització. Les biblioteques de llibres ho requereixen per funcionar.",
"OptionAllowContentDownload": "Permetre la descàrrega dels mitjans", "OptionAllowContentDownload": "Permetre la descàrrega dels mitjans",
"OptionAllowAudioPlaybackTranscoding": "Permet la reproducció d'àudio que requereix la transcodificació", "OptionAllowAudioPlaybackTranscoding": "Permet la reproducció d'àudio que requereix la transcodificació",
"Option3D": "3D", "Option3D": "3D",
@ -1715,5 +1715,6 @@
"SubtitleRed": "Vermell", "SubtitleRed": "Vermell",
"SubtitleYellow": "Groc", "SubtitleYellow": "Groc",
"StereoDownmixAlgorithmHelp": "Algoritme utilitzat per barrejar àudio multicanal a estèreo.", "StereoDownmixAlgorithmHelp": "Algoritme utilitzat per barrejar àudio multicanal a estèreo.",
"DownloadAll": "Descarrega-ho tot" "DownloadAll": "Descarrega-ho tot",
"LabelEnableAudioVbr": "Activar la codificació d'àudio VBR"
} }

View file

@ -1719,5 +1719,7 @@
"Short": "Krátký film", "Short": "Krátký film",
"HeaderPerformance": "Výkon", "HeaderPerformance": "Výkon",
"LabelParallelImageEncodingLimit": "Počet paralelních kódování obrázků", "LabelParallelImageEncodingLimit": "Počet paralelních kódování obrázků",
"LabelParallelImageEncodingLimitHelp": "Maximální počet kódování obrázků, které mohou běžet zároveň. Nastavením na 0 bude limit nastaven dle parametrů systému." "LabelParallelImageEncodingLimitHelp": "Maximální počet kódování obrázků, které mohou běžet zároveň. Nastavením na 0 bude limit nastaven dle parametrů systému.",
"LabelEnableAudioVbr": "Povolit kódování zvuku VBR",
"LabelEnableAudioVbrHelp": "Proměnlivý bitový tok (VBR) nabízí lepší poměr mezi kvalitou a průměrným bitovým tokem, ale někdy může způsobit dodatečné načítání či problémy s kompatibilitou."
} }

View file

@ -80,8 +80,8 @@
"Composer": "Komponist", "Composer": "Komponist",
"ConfigureDateAdded": "Konfigurer hvordan metadata for 'tilføjet' dato bestemmes, under Kontrolpanel > Biblioteker > NFO indstillinger", "ConfigureDateAdded": "Konfigurer hvordan metadata for 'tilføjet' dato bestemmes, under Kontrolpanel > Biblioteker > NFO indstillinger",
"ConfirmDeleteImage": "Slet billede?", "ConfirmDeleteImage": "Slet billede?",
"ConfirmDeleteItem": "Hvis dette element slettes, fjernes det både fra dit filsystem samt din mediebibliotek. Er du sikker på du ønsker at fortsætte?", "ConfirmDeleteItem": "Hvis dette element slettes, fjernes det fra både dit filsystem og dit mediebibliotek. Er du sikker på at fortsætte?",
"ConfirmDeleteItems": "Sletning af disse emner vil både fjerne dem fra filsystemet og dit mediebibliotek. Er du sikker på at du vil fortsætte?", "ConfirmDeleteItems": "Sletning af disse emner vil fjerne dem fra både filsystemet og dit mediebibliotek. Er du sikker på at du vil fortsætte?",
"ConfirmDeletion": "Bekræft sletning", "ConfirmDeletion": "Bekræft sletning",
"Connect": "Forbind", "Connect": "Forbind",
"Continuing": "Forsættes", "Continuing": "Forsættes",
@ -136,7 +136,7 @@
"FileReadError": "Der opstod en fejl i forsøget på at læse filen.", "FileReadError": "Der opstod en fejl i forsøget på at læse filen.",
"Friday": "Fredag", "Friday": "Fredag",
"Fullscreen": "Fuldskærm", "Fullscreen": "Fuldskærm",
"General": "Generel", "General": "Generelt",
"Genres": "Genrer", "Genres": "Genrer",
"GroupVersions": "Grupér versioner", "GroupVersions": "Grupér versioner",
"GuestStar": "Gæsteskuespiller", "GuestStar": "Gæsteskuespiller",
@ -272,7 +272,7 @@
"HeaderSendMessage": "Send besked", "HeaderSendMessage": "Send besked",
"HeaderSeriesOptions": "Serieindstillinger", "HeaderSeriesOptions": "Serieindstillinger",
"HeaderServerSettings": "Serverindstillinger", "HeaderServerSettings": "Serverindstillinger",
"HeaderSetupLibrary": "Opsæt dine mediebiblioteker", "HeaderSetupLibrary": "Konfigurer dine mediebiblioteker",
"HeaderSortBy": "Sorter Efter", "HeaderSortBy": "Sorter Efter",
"HeaderSortOrder": "Sorteringsorden", "HeaderSortOrder": "Sorteringsorden",
"HeaderSpecialEpisodeInfo": "Information om specialepisoder", "HeaderSpecialEpisodeInfo": "Information om specialepisoder",
@ -404,7 +404,7 @@
"LabelFriendlyName": "System venligt navn:", "LabelFriendlyName": "System venligt navn:",
"LabelServerNameHelp": "Dette navn bruges til at identificere serveren. Som udgangspunkt anvendes computerens navn.", "LabelServerNameHelp": "Dette navn bruges til at identificere serveren. Som udgangspunkt anvendes computerens navn.",
"LabelGroupMoviesIntoCollections": "Grupper film i samlinger", "LabelGroupMoviesIntoCollections": "Grupper film i samlinger",
"LabelGroupMoviesIntoCollectionsHelp": "Film i samlinger vil blive vist som en samlet enhed i filmlister.", "LabelGroupMoviesIntoCollectionsHelp": "Film i samlinger vil blive vist som en samlet visning i filmlister.",
"LabelH264Crf": "H.264-kodning CRF:", "LabelH264Crf": "H.264-kodning CRF:",
"LabelEncoderPreset": "Forudindstilling for kodning:", "LabelEncoderPreset": "Forudindstilling for kodning:",
"LabelHardwareAccelerationType": "Hardwareacceleration:", "LabelHardwareAccelerationType": "Hardwareacceleration:",
@ -451,9 +451,9 @@
"LabelMessageText": "Beskedtekst:", "LabelMessageText": "Beskedtekst:",
"LabelMessageTitle": "Titel på besked:", "LabelMessageTitle": "Titel på besked:",
"LabelMetadataDownloadLanguage": "Foretrukket sprog for nedhentning:", "LabelMetadataDownloadLanguage": "Foretrukket sprog for nedhentning:",
"LabelMetadataDownloadersHelp": "Aktiver og ranger dine fortrukne metadata downloadere i en prioriteret rækkefølge. Lavt rangerende downloadere bliver kun benyttet til at udfylde manglende information.", "LabelMetadataDownloadersHelp": "Aktiver og ranger dine foretrukne metadata kilder i prioriteret rækkefølge. Lavt rangerende kilder vil kun blive benyttet til at udfylde manglende information.",
"LabelMetadataPath": "Metadatasti:", "LabelMetadataPath": "Metadatasti:",
"LabelMetadataPathHelp": "Angiv en brugerdefineret lokation til downloadet grafik og metadata.", "LabelMetadataPathHelp": "Angiv en brugerdefineret lokation til hentet grafik og metadata.",
"LabelMetadataReaders": "Metadata aflæsere:", "LabelMetadataReaders": "Metadata aflæsere:",
"LabelMetadataReadersHelp": "Ranger dine fortrukne lokale metadatakilder i prioriteret rækkefølge. Den først fundne fil vil blive aflæst.", "LabelMetadataReadersHelp": "Ranger dine fortrukne lokale metadatakilder i prioriteret rækkefølge. Den først fundne fil vil blive aflæst.",
"LabelMetadataSavers": "Metadata-gemmer:", "LabelMetadataSavers": "Metadata-gemmer:",
@ -546,7 +546,7 @@
"LabelStartWhenPossible": "Start når muligt:", "LabelStartWhenPossible": "Start når muligt:",
"LabelStopWhenPossible": "Stop når muligt:", "LabelStopWhenPossible": "Stop når muligt:",
"LabelStopping": "Standser", "LabelStopping": "Standser",
"LabelSubtitleDownloaders": "undertekst downloadere:", "LabelSubtitleDownloaders": "Kilder til undertekster:",
"LabelSubtitleFormatHelp": "F. eks: srt", "LabelSubtitleFormatHelp": "F. eks: srt",
"LabelSubtitlePlaybackMode": "Underteksttilstand:", "LabelSubtitlePlaybackMode": "Underteksttilstand:",
"LabelSupportedMediaTypes": "Understøttede medieformater:", "LabelSupportedMediaTypes": "Understøttede medieformater:",
@ -561,7 +561,7 @@
"LabelTriggerType": "Udløsertype:", "LabelTriggerType": "Udløsertype:",
"LabelTunerIpAddress": "IP-adresse for Tuner:", "LabelTunerIpAddress": "IP-adresse for Tuner:",
"LabelTunerType": "Tunertype:", "LabelTunerType": "Tunertype:",
"LabelTypeMetadataDownloaders": "Metadata downloadere ({0}):", "LabelTypeMetadataDownloaders": "Kilder for metadata ({0}):",
"LabelTypeText": "Tekst", "LabelTypeText": "Tekst",
"LabelUseNotificationServices": "Brug følgende tjenester:", "LabelUseNotificationServices": "Brug følgende tjenester:",
"LabelUser": "Bruger:", "LabelUser": "Bruger:",
@ -622,7 +622,7 @@
"MessageDeleteTaskTrigger": "Er du sikker på du ønsker at slette denne task trigger?", "MessageDeleteTaskTrigger": "Er du sikker på du ønsker at slette denne task trigger?",
"MessageDirectoryPickerBSDInstruction": "For BSD skal du muligvis konfigurere lager i dit 'FreeNAS Jail', så Jellyfin kan tilgå dine medie filer.", "MessageDirectoryPickerBSDInstruction": "For BSD skal du muligvis konfigurere lager i dit 'FreeNAS Jail', så Jellyfin kan tilgå dine medie filer.",
"MessageDirectoryPickerLinuxInstruction": "For Linux på Arch Linux, CentOS, Debian, Fedora, openSUSE eller Ubuntu, skal du give servicebrugeren mindst læseadgang til dine lagerpladser.", "MessageDirectoryPickerLinuxInstruction": "For Linux på Arch Linux, CentOS, Debian, Fedora, openSUSE eller Ubuntu, skal du give servicebrugeren mindst læseadgang til dine lagerpladser.",
"MessageDownloadQueued": "Download sat i kø.", "MessageDownloadQueued": "Hent sat i kø.",
"MessageEnablingOptionLongerScans": "Aktivering af denne indstilling kan resultere i væsentlig længere biblioteks skan.", "MessageEnablingOptionLongerScans": "Aktivering af denne indstilling kan resultere i væsentlig længere biblioteks skan.",
"MessageFileReadError": "Der opstod en fejl i forsøget på at læse filen.", "MessageFileReadError": "Der opstod en fejl i forsøget på at læse filen.",
"MessageForgotPasswordFileCreated": "Den følgende fil er blevet oprettet på din server og indeholder instruktioner vedrørende hvordan du skal fortsætte:", "MessageForgotPasswordFileCreated": "Den følgende fil er blevet oprettet på din server og indeholder instruktioner vedrørende hvordan du skal fortsætte:",
@ -638,7 +638,7 @@
"MessageNoTrailersFound": "Installer forfilm kanalen for at tilføje et bibliotek med forfilm hentet fra internettet.", "MessageNoTrailersFound": "Installer forfilm kanalen for at tilføje et bibliotek med forfilm hentet fra internettet.",
"MessageNothingHere": "Her er ingenting.", "MessageNothingHere": "Her er ingenting.",
"MessagePasswordResetForUsers": "Følgende brugere har fået nulstillet deres adgangskoder. De kan nu logge på med de pinkoder, der blev brugt til at udføre nulstillingen.", "MessagePasswordResetForUsers": "Følgende brugere har fået nulstillet deres adgangskoder. De kan nu logge på med de pinkoder, der blev brugt til at udføre nulstillingen.",
"MessagePleaseEnsureInternetMetadata": "Sørg venligst for at hentning af metadata fra internettet er aktiveret.", "MessagePleaseEnsureInternetMetadata": "Venligst sikre at hentning af metadata fra internettet er aktiveret.",
"MessagePleaseWait": "Vent venligst. Dette kan tage et minut.", "MessagePleaseWait": "Vent venligst. Dette kan tage et minut.",
"MessagePluginConfigurationRequiresLocalAccess": "For at opsætte dette plugin log da venligst direkte ind på din lokale server.", "MessagePluginConfigurationRequiresLocalAccess": "For at opsætte dette plugin log da venligst direkte ind på din lokale server.",
"MessagePluginInstallDisclaimer": "Plugins fremstillet af medlemmer fra fællesskabet er en alle tiders måde at forbedre din oplevelse med yderligere features og fordele. Før installation, bedes du venligst være opmærksom på de effekter de kan have på din server; så som lange scantider på biblioteker, yderligere baggrundsbehandling og forringet systemstabilitet.", "MessagePluginInstallDisclaimer": "Plugins fremstillet af medlemmer fra fællesskabet er en alle tiders måde at forbedre din oplevelse med yderligere features og fordele. Før installation, bedes du venligst være opmærksom på de effekter de kan have på din server; så som lange scantider på biblioteker, yderligere baggrundsbehandling og forringet systemstabilitet.",
@ -688,7 +688,7 @@
"OptionAllowRemoteControlOthers": "Tillad fjernstyring af andre brugere", "OptionAllowRemoteControlOthers": "Tillad fjernstyring af andre brugere",
"OptionAllowRemoteSharedDevices": "Tillad fjernstyring af delte enheder", "OptionAllowRemoteSharedDevices": "Tillad fjernstyring af delte enheder",
"OptionAllowRemoteSharedDevicesHelp": "DLNA-enheder betragtes som delt, indtil en bruger begynder at kontrollere dem.", "OptionAllowRemoteSharedDevicesHelp": "DLNA-enheder betragtes som delt, indtil en bruger begynder at kontrollere dem.",
"OptionAllowSyncTranscoding": "Tillad medie hentning og synkronisering der kræver omkodning", "OptionAllowSyncTranscoding": "Tillad at hente medier og synkronisering der kræver omkodning",
"OptionAllowUserToManageServer": "Tillad denne bruger at administrere serveren", "OptionAllowUserToManageServer": "Tillad denne bruger at administrere serveren",
"OptionAllowVideoPlaybackRemuxing": "Tillad videoafspilning som kræver konvertering uden omkodning", "OptionAllowVideoPlaybackRemuxing": "Tillad videoafspilning som kræver konvertering uden omkodning",
"OptionAllowVideoPlaybackTranscoding": "Tillad videoafspilning der kræver transkodning", "OptionAllowVideoPlaybackTranscoding": "Tillad videoafspilning der kræver transkodning",
@ -706,7 +706,7 @@
"OptionDisableUserHelp": "Serveren vil ikke tillade forbindelser fra denne bruger. Eksisterende forbindelser vil blive afbrudt øjeblikkeligt.", "OptionDisableUserHelp": "Serveren vil ikke tillade forbindelser fra denne bruger. Eksisterende forbindelser vil blive afbrudt øjeblikkeligt.",
"OptionDislikes": "Ikke-Lide", "OptionDislikes": "Ikke-Lide",
"OptionDisplayFolderView": "Få vist en mappevisning til at se enkle mediemapper", "OptionDisplayFolderView": "Få vist en mappevisning til at se enkle mediemapper",
"OptionDisplayFolderViewHelp": "Vis mapper sammen med dine andre mediebiblioteker. Dette kan være nyttigt, hvis du gerne vil have en almindelig mappevisning.", "OptionDisplayFolderViewHelp": "Vis mapper sammen med dine andre mediebiblioteker. Dette kan være nyttigt, hvis du gerne vil have en simpel mappevisning.",
"OptionDownloadImagesInAdvance": "Download billeder på forhånd", "OptionDownloadImagesInAdvance": "Download billeder på forhånd",
"OptionDownloadImagesInAdvanceHelp": "Som standard downloades de fleste billeder kun, når de anmodes fra en Jellyfin-app. Aktivér denne mulighed for at downloade alle billeder på forhånd, da nye medier importeres. Dette kan forårsage betydeligt længere biblioteksscanninger.", "OptionDownloadImagesInAdvanceHelp": "Som standard downloades de fleste billeder kun, når de anmodes fra en Jellyfin-app. Aktivér denne mulighed for at downloade alle billeder på forhånd, da nye medier importeres. Dette kan forårsage betydeligt længere biblioteksscanninger.",
"OptionDvd": "DVD", "OptionDvd": "DVD",
@ -746,7 +746,7 @@
"OptionReleaseDate": "Udgivelsesdato", "OptionReleaseDate": "Udgivelsesdato",
"OptionReportByteRangeSeekingWhenTranscoding": "Angiv at serveren understøtter bytes øgning nrdeå r transkodes", "OptionReportByteRangeSeekingWhenTranscoding": "Angiv at serveren understøtter bytes øgning nrdeå r transkodes",
"OptionReportByteRangeSeekingWhenTranscodingHelp": "Dette er krævet for nogle enheder der ikke er særligt gode til tidssøgning.", "OptionReportByteRangeSeekingWhenTranscodingHelp": "Dette er krævet for nogle enheder der ikke er særligt gode til tidssøgning.",
"OptionRequirePerfectSubtitleMatch": "Download kun undertekster der er perfekte matches for videofiler", "OptionRequirePerfectSubtitleMatch": "Hent kun undertekster der er perfekte matches for videofiler",
"OptionResumable": "Kan genoptages", "OptionResumable": "Kan genoptages",
"OptionSaveMetadataAsHidden": "Gem metadata og billeder som skjulte filer", "OptionSaveMetadataAsHidden": "Gem metadata og billeder som skjulte filer",
"OptionSaveMetadataAsHiddenHelp": "Ændring af dette vil blive anvendt på nyt metadata gemt fremadrettet. Allerede eksisterende metadata-filer opdateres næste gang de gemmes af serveren.", "OptionSaveMetadataAsHiddenHelp": "Ændring af dette vil blive anvendt på nyt metadata gemt fremadrettet. Allerede eksisterende metadata-filer opdateres næste gang de gemmes af serveren.",
@ -835,7 +835,7 @@
"ServerNameIsRestarting": "Serveren bag {0} genstarter.", "ServerNameIsRestarting": "Serveren bag {0} genstarter.",
"ServerNameIsShuttingDown": "Serveren bag {0} lukker ned.", "ServerNameIsShuttingDown": "Serveren bag {0} lukker ned.",
"ServerRestartNeededAfterPluginInstall": "Jellyfin skal genstartes efter installation af en tilføjelse.", "ServerRestartNeededAfterPluginInstall": "Jellyfin skal genstartes efter installation af en tilføjelse.",
"ServerUpdateNeeded": "Denne server bør opdateres. For at hente den nyeste version besøg venligst {0}", "ServerUpdateNeeded": "Denne server bør opdateres. For at hente den nyeste version, besøg venligst {0}",
"Settings": "Indstillinger", "Settings": "Indstillinger",
"SettingsSaved": "Indstillinger er gemt.", "SettingsSaved": "Indstillinger er gemt.",
"SettingsWarning": "Ændring af disse værdier kan resultere i instabilitet eller forbindelsesfejl. Hvis du oplever fejl, anbefaler vi at du skifter til standardværdier.", "SettingsWarning": "Ændring af disse værdier kan resultere i instabilitet eller forbindelsesfejl. Hvis du oplever fejl, anbefaler vi at du skifter til standardværdier.",
@ -851,16 +851,16 @@
"Sports": "Sport", "Sports": "Sport",
"StopRecording": "Stop optagelse", "StopRecording": "Stop optagelse",
"Studios": "Studier", "Studios": "Studier",
"SubtitleDownloadersHelp": "Aktiver og ranger dine prefererede undertekst hentere i priotets orden.", "SubtitleDownloadersHelp": "Aktiver og ranger dine foretrukne kilder for undertekster i prioriteret rækkefølge.",
"Subtitles": "Undertekster", "Subtitles": "Undertekster",
"Sunday": "Søndag", "Sunday": "Søndag",
"Sync": "Synk", "Sync": "Synkroniser",
"SystemDlnaProfilesHelp": "Systemprofiler kan ikke overskrives. Ændringer i en systemprofil vil blive gemt i en ny brugerdefineret profil.", "SystemDlnaProfilesHelp": "Systemprofiler kan ikke overskrives. Ændringer i en systemprofil vil blive gemt i en ny brugerdefineret profil.",
"TabAccess": "Adgang", "TabAccess": "Adgang",
"TabAdvanced": "Avanceret", "TabAdvanced": "Avanceret",
"TabCatalog": "Katalog", "TabCatalog": "Katalog",
"TabContainers": "Containere", "TabContainers": "Containere",
"TabDashboard": "Betjeningspanel", "TabDashboard": "Dashboard",
"TabDirectPlay": "Direkte afspilning", "TabDirectPlay": "Direkte afspilning",
"TabLatest": "Nyligt tilføjet", "TabLatest": "Nyligt tilføjet",
"TabMusic": "Musik", "TabMusic": "Musik",
@ -920,13 +920,13 @@
"XmlTvSportsCategoriesHelp": "Programmer med disse kategorier bliver vist som sportsprogrammer. Adskil flere med '|'.", "XmlTvSportsCategoriesHelp": "Programmer med disse kategorier bliver vist som sportsprogrammer. Adskil flere med '|'.",
"Yesterday": "I går", "Yesterday": "I går",
"AirDate": "Udgivelsesdato", "AirDate": "Udgivelsesdato",
"Albums": "Albummer", "Albums": "Album",
"Artists": "Kunstnere", "Artists": "Kunstnere",
"Books": "Bøger", "Books": "Bøger",
"Collections": "Samlinger", "Collections": "Samlinger",
"Favorites": "Favoritter", "Favorites": "Favoritter",
"Folders": "Mapper", "Folders": "Mapper",
"HeaderAlbumArtists": "Albumkunstner", "HeaderAlbumArtists": "Albums kunstnere",
"Absolute": "Absolut", "Absolute": "Absolut",
"AccessRestrictedTryAgainLater": "Adgang er begrænset lige nu. Prøv venligst igen senere.", "AccessRestrictedTryAgainLater": "Adgang er begrænset lige nu. Prøv venligst igen senere.",
"Aired": "Udgivet", "Aired": "Udgivet",
@ -1057,7 +1057,7 @@
"LabelMetadata": "Metadata:", "LabelMetadata": "Metadata:",
"LabelModelUrl": "Model URL:", "LabelModelUrl": "Model URL:",
"LabelPreferredSubtitleLanguage": "Foretrukket undertekst sprog:", "LabelPreferredSubtitleLanguage": "Foretrukket undertekst sprog:",
"LabelProfileCodecs": "Codecs:", "LabelProfileCodecs": "Kodeks:",
"LabelProfileContainer": "Beholder:", "LabelProfileContainer": "Beholder:",
"LabelProfileVideoCodecs": "Video Codec:", "LabelProfileVideoCodecs": "Video Codec:",
"LabelReasonForTranscoding": "Grund til omkodning:", "LabelReasonForTranscoding": "Grund til omkodning:",
@ -1121,10 +1121,10 @@
"OptionProtocolHls": "HTTP Live Streaming (HLS)", "OptionProtocolHls": "HTTP Live Streaming (HLS)",
"OptionProtocolHttp": "Web", "OptionProtocolHttp": "Web",
"OptionRegex": "Regex", "OptionRegex": "Regex",
"OptionRequirePerfectSubtitleMatchHelp": "At påkræve en perfekt match vil filtrere undertekster så kun dem der er testet og tjekket der passer nøjagtigt til din video fil vil blive inkluderet. At fravælge denne vil forøge chancerne for at undertekster bliver hentet, men vil også forøge risikoen for ikke-passende og ukorrekte undertekster.", "OptionRequirePerfectSubtitleMatchHelp": "At påkræve et perfekt match, vil filtrere undertekster så kun dem der er testet og tjekket at de passer nøjagtigt til din video fil, vil blive inkluderet. Hvis du fravælger vil det forøge chancerne for at undertekster bliver hentet, men vil også forøge risikoen for ikke-passende og ukorrekte undertekster.",
"OptionResElement": "'res' element", "OptionResElement": "'res' element",
"PerfectMatch": "Perfekt match", "PerfectMatch": "Perfekt match",
"Photos": "Fotoer", "Photos": "Fotos",
"PlayCount": "Afspilninger", "PlayCount": "Afspilninger",
"PlayNext": "Afspil næste", "PlayNext": "Afspil næste",
"PlayNextEpisodeAutomatically": "Afspil næste afsnit automatisk", "PlayNextEpisodeAutomatically": "Afspil næste afsnit automatisk",
@ -1233,8 +1233,8 @@
"DashboardServerName": "Server: {0}", "DashboardServerName": "Server: {0}",
"DashboardVersionNumber": "Version: {0}", "DashboardVersionNumber": "Version: {0}",
"LabelTranscodingProgress": "Transkodnings forløb:", "LabelTranscodingProgress": "Transkodnings forløb:",
"LabelTranscodingFramerate": "Transcoding framerate:", "LabelTranscodingFramerate": "Omkodnings opdateringshastighed:",
"LabelTranscodes": "Transcodes:", "LabelTranscodes": "Omkodede filer:",
"LabelTranscodePath": "Transkodnings sti:", "LabelTranscodePath": "Transkodnings sti:",
"LabelStreamType": "Streamtype:", "LabelStreamType": "Streamtype:",
"LabelSonyAggregationFlags": "Sony aggregering flag:", "LabelSonyAggregationFlags": "Sony aggregering flag:",
@ -1325,7 +1325,7 @@
"HeaderPortRanges": "Brandmur og Proxy indstillinger", "HeaderPortRanges": "Brandmur og Proxy indstillinger",
"HeaderNewRepository": "Nyt arkiv", "HeaderNewRepository": "Nyt arkiv",
"HeaderNetworking": "IP Protokoller", "HeaderNetworking": "IP Protokoller",
"HeaderDVR": "Digital optager", "HeaderDVR": "DVR",
"HeaderDeleteDevices": "Fjern alle enheder", "HeaderDeleteDevices": "Fjern alle enheder",
"HeaderDebugging": "Fejlfinding og sporing", "HeaderDebugging": "Fejlfinding og sporing",
"HeaderAutoDiscovery": "Netværksopdagelse", "HeaderAutoDiscovery": "Netværksopdagelse",
@ -1381,8 +1381,8 @@
"Other": "Andet", "Other": "Andet",
"OptionMaxActiveSessionsHelp": "En værdi på 0 vil deaktivere denne funktion.", "OptionMaxActiveSessionsHelp": "En værdi på 0 vil deaktivere denne funktion.",
"OptionMaxActiveSessions": "Angiv det maksimale antal samtidige bruger sessioner.", "OptionMaxActiveSessions": "Angiv det maksimale antal samtidige bruger sessioner.",
"OptionAllowContentDownloadHelp": "Brugere kan hente media og gemme det på deres enheder. Dette er ikke det samme som en sync funktion. Bog biblioteker kræver dette aktiveres for at fungere ordentlig.", "OptionAllowContentDownloadHelp": "Brugere kan hente materiale og gemme det på deres enheder. Dette er ikke det samme som en synk funktion. Bog biblioteker kræver at dette er aktiveret for at fungere korrekt.",
"OptionAllowContentDownload": "Tillad hentning af media", "OptionAllowContentDownload": "Tillad at hente media",
"NextTrack": "Spring til næste", "NextTrack": "Spring til næste",
"MusicVideos": "Musikvideoer", "MusicVideos": "Musikvideoer",
"MillisecondsUnit": "ms", "MillisecondsUnit": "ms",
@ -1609,7 +1609,7 @@
"AllowEmbeddedSubtitlesAllowImageOption": "Tillad billede", "AllowEmbeddedSubtitlesAllowImageOption": "Tillad billede",
"AllowEmbeddedSubtitlesAllowNoneOption": "Tillad ingen", "AllowEmbeddedSubtitlesAllowNoneOption": "Tillad ingen",
"AllowEmbeddedSubtitlesAllowAllOption": "Tillad alle", "AllowEmbeddedSubtitlesAllowAllOption": "Tillad alle",
"AllowEmbeddedSubtitlesHelp": "Deaktiver undertekster som er pakket i medie. Kræver en komplet biblioteksopdatering.", "AllowEmbeddedSubtitlesHelp": "Deaktiver undertekster som er pakket i mediet. Kræver en komplet biblioteksopdatering.",
"OtherArtist": "Anden artist", "OtherArtist": "Anden artist",
"OriginalAirDate": "Original sendedato", "OriginalAirDate": "Original sendedato",
"NextChapter": "Næste kapitel", "NextChapter": "Næste kapitel",
@ -1665,5 +1665,40 @@
"SubtitleGreen": "Grøn", "SubtitleGreen": "Grøn",
"SubtitleLightGray": "lysegrå", "SubtitleLightGray": "lysegrå",
"SubtitleRed": "Rød", "SubtitleRed": "Rød",
"Short": "Kort" "Short": "Kort",
"Featurette": "Klip",
"PreferEmbeddedExtrasTitlesOverFileNamesHelp": "Ekstramateriale har ofte det samme indlejrede navn som det oprindelige materiale. Brug denne for at bruge den indlejrede titel alligevel.",
"MediaInfoDoViTitle": "DV titel",
"OptionDateEpisodeAdded": "Dato episoden blev tilføjet",
"PreferEmbeddedExtrasTitlesOverFileNames": "Foretræk indlejrede titler fremfor filnavne på ekstramateriale",
"LabelTextWeight": "Tekst vægt:",
"RememberSubtitleSelectionsHelp": "Forsøg at vælge undertekst ud fra tætteste match af foregående video.",
"SaveRecordingImages": "Gem optagelsens EPG billeder",
"HomeVideosPhotos": "Hjemmevideoer og -billeder",
"IgnoreDtsHelp": "Deaktivering af denne indstilling kan muligvis løse udfordringer såsom manglende lydkanal med separate lyd- og videospor.",
"EnableSplashScreen": "Vis opstarts skærm",
"LabelStereoDownmixAlgorithm": "",
"LabelMaxVideoResolution": "Max opløsning af video omkodnings opløsning",
"HeaderRecordingMetadataSaving": "Optager metadata",
"LabelChapterImageResolutionHelp": "Opløsningen af det udtrukne kapitelbillede.",
"MessageRenameMediaFolder": "Omdøbning af et mediebibliotek sletter al tilhørende metadata. Fortsæt med forsigtighed.",
"StereoDownmixAlgorithmHelp": "Algoritme brugt til at nedskalere flerkanals lyd til stereo.",
"IgnoreDts": "Ignorer DTS (afkodning af tidsstempel)",
"LabelDummyChapterDuration": "Interval:",
"LabelDummyChapterDurationHelp": "Interval i sekunder for udtræk af kapitelbilleder.",
"LabelDummyChapterCount": "Begrænsning:",
"LabelDummyChapterCountHelp": "Det maksimum antal kapitelbilleder der udtrækkes for hver mediefil.",
"MediaInfoDvProfile": "DV profil",
"LabelParallelImageEncodingLimit": "Parallel billedkodning grænese",
"LabelParallelImageEncodingLimitHelp": "Max antal af billedkodninger, som er tilladt at køre parallelt. Ved at sætte denne til 0, vil der blive valgt et max ud fra dit system.",
"MessageNoItemsAvailable": "Ingen elementer er tilgængelige i øjeblikket.",
"MessageNoFavoritesAvailable": "Ingen favoritter er tilgængelige i øjeblikket.",
"OptionDateShowAdded": "Dato serien blev tilføjet",
"RememberAudioSelections": "Vælg lydspor baseret på foregående element",
"RememberAudioSelectionsHelp": "Forsøg at vælge lydspor ud fra tætteste match ud fra foregående video.",
"RememberSubtitleSelections": "Vælg undertekst baseret på foregående element",
"EnableCardLayout": "Vis visuel CardBox",
"ResolutionMatchSource": "Match kilde",
"SubtitleCyan": "Cyan",
"SubtitleMagenta": "Magenta"
} }

View file

@ -637,6 +637,8 @@
"LabelEasyPinCode": "Easy PIN code:", "LabelEasyPinCode": "Easy PIN code:",
"LabelEmbedAlbumArtDidl": "Embed album art in DIDL", "LabelEmbedAlbumArtDidl": "Embed album art in DIDL",
"LabelEmbedAlbumArtDidlHelp": "Some devices prefer this method for getting the album art. Others may fail to play with this option enabled.", "LabelEmbedAlbumArtDidlHelp": "Some devices prefer this method for getting the album art. Others may fail to play with this option enabled.",
"LabelEnableAudioVbr": "Enable VBR audio encoding",
"LabelEnableAudioVbrHelp": "Variable bitrate offers better quality to average bitrate ratio, but in some rare cases may cause buffering and compatibility issues.",
"LabelEnableAutomaticPortMap": "Enable automatic port mapping", "LabelEnableAutomaticPortMap": "Enable automatic port mapping",
"LabelEnableAutomaticPortMapHelp": "Automatically forward public ports on your router to local ports on your server via UPnP. This may not work with some router models or network configurations. Changes will not apply until after a server restart.", "LabelEnableAutomaticPortMapHelp": "Automatically forward public ports on your router to local ports on your server via UPnP. This may not work with some router models or network configurations. Changes will not apply until after a server restart.",
"LabelEnableBlastAliveMessages": "Blast alive messages", "LabelEnableBlastAliveMessages": "Blast alive messages",

View file

@ -1719,5 +1719,7 @@
"Short": "Court-métrage", "Short": "Court-métrage",
"HeaderPerformance": "Performance", "HeaderPerformance": "Performance",
"LabelParallelImageEncodingLimit": "Limite de parallélisation de l'encodage d'image", "LabelParallelImageEncodingLimit": "Limite de parallélisation de l'encodage d'image",
"LabelParallelImageEncodingLimitHelp": "Nombre maximal dencodages dimage autorisés à sexécuter en parallèle. Si vous définissez cette valeur sur 0, vous choisirez une limite en fonction des spécifications de votre système." "LabelParallelImageEncodingLimitHelp": "Nombre maximal dencodages dimage autorisés à sexécuter en parallèle. Si vous définissez cette valeur sur 0, vous choisirez une limite en fonction des spécifications de votre système.",
"LabelEnableAudioVbr": "Activer lencodage audio VBR",
"LabelEnableAudioVbrHelp": "Le débit binaire variable offre une qualité supérieure à la moyenne mais peut, dans de rares cas, causer des problèmes de mise en mémoire tampon et de compatibilité."
} }

View file

@ -148,5 +148,6 @@
"Songs": "गाने", "Songs": "गाने",
"Larger": "और बड़ा", "Larger": "और बड़ा",
"ListPaging": "{2} का {0}-{1}", "ListPaging": "{2} का {0}-{1}",
"Shows": "शो" "Shows": "शो",
"ValueSpecialEpisodeName": "विशेष"
} }

View file

@ -1614,7 +1614,7 @@
"ContainerBitrateExceedsLimit": "A videó bitrátája meghaladja a limitet", "ContainerBitrateExceedsLimit": "A videó bitrátája meghaladja a limitet",
"SelectAll": "Összes kiválasztása", "SelectAll": "Összes kiválasztása",
"ButtonExitApp": "Kilépés az alkalmazásból", "ButtonExitApp": "Kilépés az alkalmazásból",
"Clip": "Rövidfilm", "Clip": "Klip",
"ThemeVideo": "Téma Videó", "ThemeVideo": "Téma Videó",
"ThemeSong": "Főcímdal", "ThemeSong": "Főcímdal",
"Sample": "Minta", "Sample": "Minta",
@ -1711,5 +1711,10 @@
"LabelDummyChapterCount": "Határvonal:", "LabelDummyChapterCount": "Határvonal:",
"LabelChapterImageResolution": "Felbontás:", "LabelChapterImageResolution": "Felbontás:",
"LabelChapterImageResolutionHelp": "A kinyert fejezetképek felbontása.", "LabelChapterImageResolutionHelp": "A kinyert fejezetképek felbontása.",
"HeaderPerformance": "Teljesítmény" "HeaderPerformance": "Teljesítmény",
"Short": "Rövidfilm",
"Featurette": "Mellékfilm",
"LabelParallelImageEncodingLimitHelp": "Maximálisan engedélyezett egyidejűleg futó képkódolások száma. 0-ra állítva a rendszer specifikációja alapján lesz kiválasztva a limit.",
"ResolutionMatchSource": "Forrásnak megfelelő",
"LabelParallelImageEncodingLimit": "Egyidejű képkódolási limit"
} }

View file

@ -127,7 +127,7 @@
"Sunday": "Duminică", "Sunday": "Duminică",
"TabAccess": "Acces", "TabAccess": "Acces",
"TabAdvanced": "Avansat", "TabAdvanced": "Avansat",
"TabLatest": "Cele mai recente", "TabLatest": "Adăugate recent",
"TabMusic": "Muzică", "TabMusic": "Muzică",
"TabMyPlugins": "Plugin-urile mele", "TabMyPlugins": "Plugin-urile mele",
"TabNetworks": "Trusturi TV", "TabNetworks": "Trusturi TV",
@ -946,7 +946,7 @@
"List": "Listă", "List": "Listă",
"LeaveBlankToNotSetAPassword": "Puteți lăsa acest câmp necompletat pentru a nu seta o parolă.", "LeaveBlankToNotSetAPassword": "Puteți lăsa acest câmp necompletat pentru a nu seta o parolă.",
"LearnHowYouCanContribute": "Aflați cum puteți contribui.", "LearnHowYouCanContribute": "Aflați cum puteți contribui.",
"LatestFromLibrary": "Ultimele {0}", "LatestFromLibrary": "Ultimele adăugate {0}",
"Large": "Mare", "Large": "Mare",
"LanNetworksHelp": "Lista separată de virgule a adreselor IP sau a intrărilor de tip IP/mască de rețea pentru rețelele care vor fi luate în considerare în rețeaua locală atunci când se aplică restricțiile de lățime de bandă. Dacă este setat, toate celelalte adrese IP vor fi considerate a fi în rețeaua externă și vor fi supuse restricțiilor de lățime de bandă externe. Dacă este lăsat necompletat, numai subnetul serverului este considerat a fi în rețeaua locală.", "LanNetworksHelp": "Lista separată de virgule a adreselor IP sau a intrărilor de tip IP/mască de rețea pentru rețelele care vor fi luate în considerare în rețeaua locală atunci când se aplică restricțiile de lățime de bandă. Dacă este setat, toate celelalte adrese IP vor fi considerate a fi în rețeaua externă și vor fi supuse restricțiilor de lățime de bandă externe. Dacă este lăsat necompletat, numai subnetul serverului este considerat a fi în rețeaua locală.",
"LabelffmpegPathHelp": "Calea către executabilul FFmpeg sau dosarul care conține FFmpeg.", "LabelffmpegPathHelp": "Calea către executabilul FFmpeg sau dosarul care conține FFmpeg.",
@ -1614,7 +1614,7 @@
"DeletedScene": "Scene șterse", "DeletedScene": "Scene șterse",
"BehindTheScenes": "În spatele scenei", "BehindTheScenes": "În spatele scenei",
"Trailer": "Trailer", "Trailer": "Trailer",
"Clip": "Featurette", "Clip": "Clip",
"SelectAll": "Selectează Tot", "SelectAll": "Selectează Tot",
"DirectPlayError": "A apărut o eroare la pornirea redării directe", "DirectPlayError": "A apărut o eroare la pornirea redării directe",
"UnknownAudioStreamInfo": "Informațiile fluxului audio sunt necunoscute", "UnknownAudioStreamInfo": "Informațiile fluxului audio sunt necunoscute",
@ -1663,7 +1663,7 @@
"IgnoreDts": "Ignoră DTS (marca de timp a decodării)", "IgnoreDts": "Ignoră DTS (marca de timp a decodării)",
"DownloadAll": "Descărcați tot", "DownloadAll": "Descărcați tot",
"MessageNoItemsAvailable": "Niciun articol nu este valabil în momentul actual.", "MessageNoItemsAvailable": "Niciun articol nu este valabil în momentul actual.",
"MessageRenameMediaFolder": "Redenumirea unei biblioteci va cauza toate metadatele să fie pierdute, continuați cu grijă.", "MessageRenameMediaFolder": "Redenumirea unei biblioteci va șterge toate fisierele metadata, continuați cu grijă.",
"OptionDateEpisodeAdded": "Dată Adăugare Episod", "OptionDateEpisodeAdded": "Dată Adăugare Episod",
"OptionDateShowAdded": "Dată Adăugare Serial", "OptionDateShowAdded": "Dată Adăugare Serial",
"MessageNoFavoritesAvailable": "Niciun favorit nu este valabil în momentul actual.", "MessageNoFavoritesAvailable": "Niciun favorit nu este valabil în momentul actual.",
@ -1680,5 +1680,6 @@
"LabelParallelImageEncodingLimit": "Limita encodărilor simultane", "LabelParallelImageEncodingLimit": "Limita encodărilor simultane",
"LabelParallelImageEncodingLimitHelp": "Numărul maxim de encodări ale imaginilor care sunt permise să ruleze simultan. Setarea acestei valori la 0 va alege automat o limită bazată pe specificațiile tehnice ale sistemului.", "LabelParallelImageEncodingLimitHelp": "Numărul maxim de encodări ale imaginilor care sunt permise să ruleze simultan. Setarea acestei valori la 0 va alege automat o limită bazată pe specificațiile tehnice ale sistemului.",
"HeaderDummyChapter": "Imaginile Capitolelor", "HeaderDummyChapter": "Imaginile Capitolelor",
"HeaderRecordingMetadataSaving": "Înregistrarea Metadatelor" "HeaderRecordingMetadataSaving": "Înregistrarea Metadatelor",
"EnableSplashScreen": "Activează ecranul splash"
} }

View file

@ -1662,7 +1662,7 @@
"RememberAudioSelectionsHelp": "Cố gắng đặt bản âm thanh phù hợp nhất với video cuối cùng.", "RememberAudioSelectionsHelp": "Cố gắng đặt bản âm thanh phù hợp nhất với video cuối cùng.",
"RememberAudioSelections": "Đặt bản nhạc dựa trên mục trước đó", "RememberAudioSelections": "Đặt bản nhạc dựa trên mục trước đó",
"LabelMaxVideoResolution": "Độ Phân Giải Chuyển Mã Video Tối Đa Được Phép", "LabelMaxVideoResolution": "Độ Phân Giải Chuyển Mã Video Tối Đa Được Phép",
"VideoRangeTypeNotSupported": "Loại phạm vi của video không được hỗ trợ", "VideoRangeTypeNotSupported": "Không hỗ trợ loại dải động của video",
"Interview": "Phỏng vấn", "Interview": "Phỏng vấn",
"Sample": "Mẫu", "Sample": "Mẫu",
"Trailer": "", "Trailer": "",
@ -1709,5 +1709,8 @@
"LabelParallelImageEncodingLimitHelp": "Lượng mã hóa hình ảnh tối đa được phép chạy song song. Đặt giá trị này thành 0 sẽ chọn giới hạn dựa trên thông số kỹ thuật hệ thống của bạn.", "LabelParallelImageEncodingLimitHelp": "Lượng mã hóa hình ảnh tối đa được phép chạy song song. Đặt giá trị này thành 0 sẽ chọn giới hạn dựa trên thông số kỹ thuật hệ thống của bạn.",
"SecondarySubtitles": "Phụ đề phụ", "SecondarySubtitles": "Phụ đề phụ",
"HeaderPerformance": "Hiệu suất", "HeaderPerformance": "Hiệu suất",
"LabelParallelImageEncodingLimit": "Giới hạn mã hóa hình ảnh song song" "LabelParallelImageEncodingLimit": "Giới hạn mã hóa hình ảnh song song",
"MediaInfoDvBlSignalCompatibilityId": "Id tương thích tính hiệu DV bl",
"LabelEnableAudioVbr": "Bật mã hóa âm thanh VBR",
"LabelEnableAudioVbrHelp": "Tốc độ bit thay đổi mang lại chất lượng tốt hơn so với tỷ lệ bit trung bình, nhưng trong một số trường hợp hiếm gặp, có thể gây ra sự cố về khả năng tương thích và bộ đệm."
} }

View file

@ -1380,10 +1380,10 @@
"Preview": "预览", "Preview": "预览",
"SubtitleVerticalPositionHelp": "文字出现的行号。正数表示由上到下,负数表示由下到上。", "SubtitleVerticalPositionHelp": "文字出现的行号。正数表示由上到下,负数表示由下到上。",
"LabelSubtitleVerticalPosition": "垂直位置:", "LabelSubtitleVerticalPosition": "垂直位置:",
"PreviousTrack": "上一", "PreviousTrack": "上一",
"MessageGetInstalledPluginsError": "获取已安装插件列表时出现错误。", "MessageGetInstalledPluginsError": "获取已安装插件列表时出现错误。",
"MessagePluginInstallError": "安装插件时出现错误。", "MessagePluginInstallError": "安装插件时出现错误。",
"NextTrack": "下一", "NextTrack": "下一",
"LabelUnstable": "不稳定", "LabelUnstable": "不稳定",
"PlaybackRate": "播放速度", "PlaybackRate": "播放速度",
"LabelMaxMuxingQueueSize": "最大混合器队列大小:", "LabelMaxMuxingQueueSize": "最大混合器队列大小:",
@ -1719,5 +1719,7 @@
"Short": "短片", "Short": "短片",
"LabelParallelImageEncodingLimitHelp": "允许并行运行的图像编码的最大数量。设为 0 以根据您的系统配置自动设置。", "LabelParallelImageEncodingLimitHelp": "允许并行运行的图像编码的最大数量。设为 0 以根据您的系统配置自动设置。",
"HeaderPerformance": "性能", "HeaderPerformance": "性能",
"LabelParallelImageEncodingLimit": "并行图像编码限制" "LabelParallelImageEncodingLimit": "并行图像编码限制",
"LabelEnableAudioVbr": "启用 VBR 音频编码",
"LabelEnableAudioVbrHelp": "可变比特率VBR相比平均比特率ABR可以提供更好的质量但在少见情况中可能造成缓冲和兼容性问题。"
} }

View file

@ -9,5 +9,5 @@ export interface Plugin {
name: string name: string
id: string id: string
type: PluginType | string type: PluginType | string
priority: number priority?: number
} }