diff --git a/.copr/Makefile b/.copr/Makefile new file mode 120000 index 000000000..ec3c90dfd --- /dev/null +++ b/.copr/Makefile @@ -0,0 +1 @@ +../fedora/Makefile \ No newline at end of file diff --git a/.editorconfig b/.editorconfig index 81eba8ccc..92cf9dc59 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,3 +7,6 @@ charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true end_of_line = lf + +[json] +indent_size = 2 diff --git a/.eslintignore b/.eslintignore index 52369be1e..8e3aee83f 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1 +1,5 @@ -libraries/ +node_modules +dist +.idea +.vscode +src/libraries diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 000000000..6a01fe5bf --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,190 @@ +module.exports = { + root: true, + plugins: [ + 'promise', + 'import', + 'eslint-comments' + ], + env: { + node: true, + es6: true, + es2017: true, + es2020: true + }, + parserOptions: { + ecmaVersion: 2020, + sourceType: 'module', + ecmaFeatures: { + impliedStrict: true + } + }, + extends: [ + 'eslint:recommended', + // 'plugin:promise/recommended', + 'plugin:import/errors', + 'plugin:import/warnings', + 'plugin:eslint-comments/recommended', + 'plugin:compat/recommended' + ], + rules: { + 'block-spacing': ["error"], + 'brace-style': ["error"], + 'comma-dangle': ["error", "never"], + 'comma-spacing': ["error"], + 'eol-last': ["error"], + 'indent': ["error", 4, { "SwitchCase": 1 }], + 'keyword-spacing': ["error"], + 'max-statements-per-line': ["error"], + 'no-floating-decimal': ["error"], + 'no-multi-spaces': ["error"], + 'no-multiple-empty-lines': ["error", { "max": 1 }], + 'no-trailing-spaces': ["error"], + 'one-var': ["error", "never"], + 'semi': ["error"], + 'space-before-blocks': ["error"] + }, + overrides: [ + { + files: [ + './src/**/*.js' + ], + env: { + node: false, + amd: true, + browser: true, + es6: true, + es2017: true, + es2020: true + }, + globals: { + // Browser globals + 'MediaMetadata': 'readonly', + // Tizen globals + 'tizen': 'readonly', + 'webapis': 'readonly', + // WebOS globals + 'webOS': 'readonly', + // Dependency globals + '$': 'readonly', + 'jQuery': 'readonly', + 'requirejs': 'readonly', + // Jellyfin globals + 'ApiClient': 'writable', + 'AppInfo': 'writable', + 'chrome': 'writable', + 'ConnectionManager': 'writable', + 'DlnaProfilePage': 'writable', + 'Dashboard': 'writable', + 'DashboardPage': 'writable', + 'Emby': 'readonly', + 'Events': 'writable', + 'getParameterByName': 'writable', + 'getWindowLocationSearch': 'writable', + 'Globalize': 'writable', + 'Hls': 'writable', + 'dfnshelper': 'writable', + 'LibraryMenu': 'writable', + 'LinkParser': 'writable', + 'LiveTvHelpers': 'writable', + 'MetadataEditor': 'writable', + 'pageClassOn': 'writable', + 'pageIdOn': 'writable', + 'PlaylistViewer': 'writable', + 'UserParentalControlPage': 'writable', + 'Windows': 'readonly' + }, + rules: { + // TODO: Fix warnings and remove these rules + 'no-redeclare': ["warn"], + 'no-unused-vars': ["warn"], + 'no-useless-escape': ["warn"], + // TODO: Remove after ES6 migration is complete + 'import/no-unresolved': ["off"] + }, + settings: { + polyfills: [ + // Native Promises Only + 'Promise', + // whatwg-fetch + 'fetch', + // document-register-element + 'document.registerElement', + // resize-observer-polyfill + 'ResizeObserver', + // fast-text-encoding + 'TextEncoder', + // intersection-observer + 'IntersectionObserver', + // Core-js + 'Object.assign', + 'Object.is', + 'Object.setPrototypeOf', + 'Object.toString', + 'Object.freeze', + 'Object.seal', + 'Object.preventExtensions', + 'Object.isFrozen', + 'Object.isSealed', + 'Object.isExtensible', + 'Object.getOwnPropertyDescriptor', + 'Object.getPrototypeOf', + 'Object.keys', + 'Object.getOwnPropertyNames', + 'Function.name', + 'Function.hasInstance', + 'Array.from', + 'Array.arrayOf', + 'Array.copyWithin', + 'Array.fill', + 'Array.find', + 'Array.findIndex', + 'Array.iterator', + 'String.fromCodePoint', + 'String.raw', + 'String.iterator', + 'String.codePointAt', + 'String.endsWith', + 'String.includes', + 'String.repeat', + 'String.startsWith', + 'String.trim', + 'String.anchor', + 'String.big', + 'String.blink', + 'String.bold', + 'String.fixed', + 'String.fontcolor', + 'String.fontsize', + 'String.italics', + 'String.link', + 'String.small', + 'String.strike', + 'String.sub', + 'String.sup', + 'RegExp', + 'Number', + 'Math', + 'Date', + 'async', + 'Symbol', + 'Map', + 'Set', + 'WeakMap', + 'WeakSet', + 'ArrayBuffer', + 'DataView', + 'Int8Array', + 'Uint8Array', + 'Uint8ClampedArray', + 'Int16Array', + 'Uint16Array', + 'Int32Array', + 'Uint32Array', + 'Float32Array', + 'Float64Array', + 'Reflect' + ] + } + } + ] +} diff --git a/.eslintrc.yml b/.eslintrc.yml deleted file mode 100644 index 0b92c0c9b..000000000 --- a/.eslintrc.yml +++ /dev/null @@ -1,171 +0,0 @@ -env: - amd: true - browser: true - es6: true - es2017: true - es2020: true - -parserOptions: - ecmaVersion: 2020 - sourceType: module - ecmaFeatures: - impliedStrict: true - -plugins: - - promise - - import - - eslint-comments - -extends: - - eslint:recommended - - plugin:promise/recommended - - plugin:import/errors - - plugin:import/warnings - - plugin:eslint-comments/recommended - - plugin:compat/recommended - -globals: - # Browser globals - MediaMetadata: readonly - # Tizen globals - tizen: readonly - webapis: readonly - # WebOS globals - webOS: readonly - # Dependency globals - $: readonly - jQuery: readonly - requirejs: readonly - # Jellyfin globals - ApiClient: writable - AppInfo: writable - chrome: writable - ConnectionManager: writable - DlnaProfilePage: writable - Dashboard: writable - DashboardPage: writable - Emby: readonly - Events: writable - getParameterByName: writable - getWindowLocationSearch: writable - Globalize: writable - Hls: writable - dfnshelper: writable - LibraryMenu: writable - LinkParser: writable - LiveTvHelpers: writable - MetadataEditor: writable - pageClassOn: writable - pageIdOn: writable - PlaylistViewer: writable - UserParentalControlPage: writable - Windows: readonly - -rules: - block-spacing: ["error"] - brace-style: ["error"] - comma-dangle: ["error", "never"] - comma-spacing: ["error"] - eol-last: ["error"] - indent: ["error", 4, { "SwitchCase": 1 }] - keyword-spacing: ["error"] - max-statements-per-line: ["error"] - no-floating-decimal: ["error"] - no-multi-spaces: ["error"] - no-multiple-empty-lines: ["error", { "max": 1 }] - no-trailing-spaces: ["error"] - one-var: ["error", "never"] - semi: ["error"] - space-before-blocks: ["error"] - # TODO: Fix warnings and remove these rules - no-redeclare: ["warn"] - no-unused-vars: ["warn"] - no-useless-escape: ["warn"] - promise/catch-or-return: ["warn"] - promise/always-return: ["warn"] - promise/no-return-wrap: ["warn"] - # TODO: Remove after ES6 migration is complete - import/no-unresolved: ["warn"] - -settings: - polyfills: - # Native Promises Only - - Promise - # whatwg-fetch - - fetch - # document-register-element - - document.registerElement - # resize-observer-polyfill - - ResizeObserver - # fast-text-encoding - - TextEncoder - # intersection-observer - - IntersectionObserver - # Core-js - - Object.assign - - Object.is - - Object.setPrototypeOf - - Object.toString - - Object.freeze - - Object.seal - - Object.preventExtensions - - Object.isFrozen - - Object.isSealed - - Object.isExtensible - - Object.getOwnPropertyDescriptor - - Object.getPrototypeOf - - Object.keys - - Object.getOwnPropertyNames - - Function.name - - Function.hasInstance - - Array.from - - Array.arrayOf - - Array.copyWithin - - Array.fill - - Array.find - - Array.findIndex - - Array.iterator - - String.fromCodePoint - - String.raw - - String.iterator - - String.codePointAt - - String.endsWith - - String.includes - - String.repeat - - String.startsWith - - String.trim - - String.anchor - - String.big - - String.blink - - String.bold - - String.fixed - - String.fontcolor - - String.fontsize - - String.italics - - String.link - - String.small - - String.strike - - String.sub - - String.sup - - RegExp - - Number - - Math - - Date - - async - - Symbol - - Map - - Set - - WeakMap - - WeakSet - - ArrayBuffer - - DataView - - Int8Array - - Uint8Array - - Uint8ClampedArray - - Int16Array - - Uint16Array - - Int32Array - - Uint32Array - - Float32Array - - Float64Array - - Reflect diff --git a/.gitattributes b/.gitattributes index 80f9bc36e..9e495a4df 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,35 @@ -/CONTRIBUTORS.md merge=union +* text=auto + +CONTRIBUTORS.md merge=union +README.md text +LICENSE text + +*.css text +*.eot binary +*.gif binary +*.html text diff=html +*.ico binary +*.*ignore text +*.jpg binary +*.js text +*.json text +*.lock text -diff +*.map text -diff +*.md text +*.otf binary +*.png binary +*.py text diff=python +*.svg binary +*.ts text +*.ttf binary +*.sass text +*.vue text +*.webp binary +*.woff binary +*.woff2 binary + +.editorconfig text +.gitattributes export-ignore +.gitignore export-ignore + +*.gitattributes linguist-language=gitattributes diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..e902dc712 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,3 @@ +# Joshua must review all changes to deployment and build.sh +deployment/* @joshuaboniface +build.sh @joshuaboniface diff --git a/.gitignore b/.gitignore index 2bb5bc64d..4adf9558b 100644 --- a/.gitignore +++ b/.gitignore @@ -3,8 +3,9 @@ config.json # npm dist +web node_modules # ide .idea -.vscode +.vscode \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100755 index 000000000..9f5fa6022 --- /dev/null +++ b/build.sh @@ -0,0 +1,110 @@ +#!/usr/bin/env bash + +# build.sh - Build Jellyfin binary packages +# Part of the Jellyfin Project + +set -o errexit +set -o pipefail + +usage() { + echo -e "build.sh - Build Jellyfin binary packages" + echo -e "Usage:" + echo -e " $0 -t/--type -p/--platform [-k/--keep-artifacts] [-l/--list-platforms]" + echo -e "Notes:" + echo -e " * BUILD_TYPE can be one of: [native, docker] and must be specified" + echo -e " * native: Build using the build script in the host OS" + echo -e " * docker: Build using the build script in a standardized Docker container" + echo -e " * PLATFORM can be any platform shown by -l/--list-platforms and must be specified" + echo -e " * If -k/--keep-artifacts is specified, transient artifacts (e.g. Docker containers) will be" + echo -e " retained after the build is finished; the source directory will still be cleaned" + echo -e " * If -l/--list-platforms is specified, all other arguments are ignored; the script will print" + echo -e " the list of supported platforms and exit" +} + +list_platforms() { + declare -a platforms + platforms=( + $( find deployment -maxdepth 1 -mindepth 1 -name "build.*" | awk -F'.' '{ $1=""; printf $2; if ($3 != ""){ printf "." $3; }; if ($4 != ""){ printf "." $4; }; print ""; }' | sort ) + ) + echo -e "Valid platforms:" + echo + for platform in ${platforms[@]}; do + echo -e "* ${platform} : $( grep '^#=' deployment/build.${platform} | sed 's/^#= //' )" + done +} + +do_build_native() { + export IS_DOCKER=NO + deployment/build.${PLATFORM} +} + +do_build_docker() { + if ! dpkg --print-architecture | grep -q 'amd64'; then + echo "Docker-based builds only support amd64-based cross-building; use a 'native' build instead." + exit 1 + fi + if [[ ! -f deployment/Dockerfile.${PLATFORM} ]]; then + echo "Missing Dockerfile for platform ${PLATFORM}" + exit 1 + fi + if [[ ${KEEP_ARTIFACTS} == YES ]]; then + docker_args="" + else + docker_args="--rm" + fi + + docker build . -t "jellyfin-builder.${PLATFORM}" -f deployment/Dockerfile.${PLATFORM} + mkdir -p ${ARTIFACT_DIR} + docker run $docker_args -v "${SOURCE_DIR}:/jellyfin" -v "${ARTIFACT_DIR}:/dist" "jellyfin-builder.${PLATFORM}" +} + +while [[ $# -gt 0 ]]; do + key="$1" + case $key in + -t|--type) + BUILD_TYPE="$2" + shift + shift + ;; + -p|--platform) + PLATFORM="$2" + shift + shift + ;; + -k|--keep-artifacts) + KEEP_ARTIFACTS=YES + shift + ;; + -l|--list-platforms) + list_platforms + exit 0 + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown option $1" + usage + exit 1 + ;; + esac +done + +if [[ -z ${BUILD_TYPE} || -z ${PLATFORM} ]]; then + usage + exit 1 +fi + +export SOURCE_DIR="$( pwd )" +export ARTIFACT_DIR="${SOURCE_DIR}/../bin/${PLATFORM}" + +# Determine build type +case ${BUILD_TYPE} in + native) + do_build_native + ;; + docker) + do_build_docker + ;; +esac diff --git a/build.yaml b/build.yaml new file mode 100644 index 000000000..fe1633fae --- /dev/null +++ b/build.yaml @@ -0,0 +1,9 @@ +--- +# We just wrap `build` so this is really it +name: "jellyfin-web" +version: "10.6.0" +packages: + - debian.all + - fedora.all + - centos.all + - portable diff --git a/bump_version b/bump_version new file mode 100755 index 000000000..bc8288b82 --- /dev/null +++ b/bump_version @@ -0,0 +1,96 @@ +#!/usr/bin/env bash + +# bump_version - increase the shared version and generate changelogs + +set -o errexit +set -o pipefail + +usage() { + echo -e "bump_version - increase the shared version and generate changelogs" + echo -e "" + echo -e "Usage:" + echo -e " $ bump_version " +} + +if [[ -z $1 ]]; then + usage + exit 1 +fi + +shared_version_file="src/components/apphost.js" +build_file="./build.yaml" + +new_version="$1" + +# Parse the version from shared version file +old_version="$( + grep "appVersion" ${shared_version_file} | head -1 \ + | sed -E 's/var appVersion = "([0-9\.]+)";/\1/' +)" +echo "Old version in appHost is: $old_version" + +# Set the shared version to the specified new_version +old_version_sed="$( sed 's/\./\\./g' <<<"${old_version}" )" # Escape the '.' chars +new_version_sed="$( cut -f1 -d'-' <<<"${new_version}" )" +sed -i "s/${old_version_sed}/${new_version_sed}/g" ${shared_version_file} + +old_version="$( + grep "version:" ${build_file} \ + | sed -E 's/version: "([0-9\.]+[-a-z0-9]*)"/\1/' +)" +echo "Old version in ${build_file}: $old_version`" + +# Set the build.yaml version to the specified new_version +old_version_sed="$( sed 's/\./\\./g' <<<"${old_version}" )" # Escape the '.' chars +sed -i "s/${old_version_sed}/${new_version}/g" ${build_file} + +if [[ ${new_version} == *"-"* ]]; then + new_version_deb="$( sed 's/-/~/g' <<<"${new_version}" )" +else + new_version_deb="${new_version}-1" +fi + +# Write out a temporary Debian changelog with our new stuff appended and some templated formatting +debian_changelog_file="debian/changelog" +debian_changelog_temp="$( mktemp )" +# Create new temp file with our changelog +echo -e "jellyfin (${new_version_deb}) unstable; urgency=medium + + * New upstream version ${new_version}; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v${new_version} + + -- Jellyfin Packaging Team $( date --rfc-2822 ) +" >> ${debian_changelog_temp} +cat ${debian_changelog_file} >> ${debian_changelog_temp} +# Move into place +mv ${debian_changelog_temp} ${debian_changelog_file} + +# Write out a temporary Yum changelog with our new stuff prepended and some templated formatting +fedora_spec_file="fedora/jellyfin.spec" +fedora_changelog_temp="$( mktemp )" +fedora_spec_temp_dir="$( mktemp -d )" +fedora_spec_temp="${fedora_spec_temp_dir}/jellyfin.spec.tmp" +# Make a copy of our spec file for hacking +cp ${fedora_spec_file} ${fedora_spec_temp_dir}/ +pushd ${fedora_spec_temp_dir} +# Split out the stuff before and after changelog +csplit jellyfin.spec "/^%changelog/" # produces xx00 xx01 +# Update the version in xx00 +sed -i "s/${old_version_sed}/${new_version_sed}/g" xx00 +# Remove the header from xx01 +sed -i '/^%changelog/d' xx01 +# Create new temp file with our changelog +echo -e "%changelog +* $( LANG=C date '+%a %b %d %Y' ) Jellyfin Packaging Team +- New upstream version ${new_version}; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v${new_version}" >> ${fedora_changelog_temp} +cat xx01 >> ${fedora_changelog_temp} +# Reassembble +cat xx00 ${fedora_changelog_temp} > ${fedora_spec_temp} +popd +# Move into place +mv ${fedora_spec_temp} ${fedora_spec_file} +# Clean up +rm -rf ${fedora_changelog_temp} ${fedora_spec_temp_dir} + +# Stage the changed files for commit +git add ${shared_version_file} ${build_file} ${debian_changelog_file} ${fedora_spec_file} Dockerfile* +git status diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 000000000..50966c3a0 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,5 @@ +jellyfin-web (10.6.0-1) unstable; urgency=medium + + * New upstream version 10.6.0; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.6.0 + + -- Jellyfin Packaging Team Mon, 16 Mar 2020 11:15:00 -0400 diff --git a/debian/compat b/debian/compat new file mode 100644 index 000000000..45a4fb75d --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +8 diff --git a/debian/control b/debian/control new file mode 100644 index 000000000..ce7b130ef --- /dev/null +++ b/debian/control @@ -0,0 +1,16 @@ +Source: jellyfin-web +Section: misc +Priority: optional +Maintainer: Jellyfin Team +Build-Depends: debhelper (>= 9), + npm | nodejs +Standards-Version: 3.9.4 +Homepage: https://jellyfin.org/ +Vcs-Git: https://github.org/jellyfin/jellyfin-web.git +Vcs-Browser: https://github.org/jellyfin/jellyfin-web + +Package: jellyfin-web +Recommends: jellyfin-server +Architecture: all +Description: Jellyfin is the Free Software Media System. + This package provides the Jellyfin web client. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 000000000..85548075e --- /dev/null +++ b/debian/copyright @@ -0,0 +1,28 @@ +Format: http://dep.debian.net/deps/dep5 +Upstream-Name: jellyfin-web +Source: https://github.com/jellyfin/jellyfin-web + +Files: * +Copyright: 2018-2020 Jellyfin Team +License: GPL-3.0 + +Files: debian/* +Copyright: 2020 Joshua Boniface +License: GPL-3.0 + +License: GPL-3.0 + This package is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + . + This package is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + . + You should have received a copy of the GNU General Public License + along with this program. If not, see + . + On Debian systems, the complete text of the GNU General + Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". diff --git a/debian/gbp.conf b/debian/gbp.conf new file mode 100644 index 000000000..60b3d2872 --- /dev/null +++ b/debian/gbp.conf @@ -0,0 +1,6 @@ +[DEFAULT] +pristine-tar = False +cleaner = fakeroot debian/rules clean + +[import-orig] +filter = [ ".git*", ".hg*", ".vs*", ".vscode*" ] diff --git a/debian/install b/debian/install new file mode 100644 index 000000000..584fe06a1 --- /dev/null +++ b/debian/install @@ -0,0 +1 @@ +web usr/share/jellyfin/ diff --git a/debian/po/POTFILES.in b/debian/po/POTFILES.in new file mode 100644 index 000000000..cef83a340 --- /dev/null +++ b/debian/po/POTFILES.in @@ -0,0 +1 @@ +[type: gettext/rfc822deb] templates diff --git a/debian/po/templates.pot b/debian/po/templates.pot new file mode 100644 index 000000000..2cdcae417 --- /dev/null +++ b/debian/po/templates.pot @@ -0,0 +1,57 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: jellyfin-server\n" +"Report-Msgid-Bugs-To: jellyfin-server@packages.debian.org\n" +"POT-Creation-Date: 2015-06-12 20:51-0600\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#. Type: note +#. Description +#: ../templates:1001 +msgid "Jellyfin permission info:" +msgstr "" + +#. Type: note +#. Description +#: ../templates:1001 +msgid "" +"Jellyfin by default runs under a user named \"jellyfin\". Please ensure that the " +"user jellyfin has read and write access to any folders you wish to add to your " +"library. Otherwise please run jellyfin under a different user." +msgstr "" + +#. Type: string +#. Description +#: ../templates:2001 +msgid "Username to run Jellyfin as:" +msgstr "" + +#. Type: string +#. Description +#: ../templates:2001 +msgid "The user that jellyfin will run as." +msgstr "" + +#. Type: note +#. Description +#: ../templates:3001 +msgid "Jellyfin still running" +msgstr "" + +#. Type: note +#. Description +#: ../templates:3001 +msgid "Jellyfin is currently running. Please close it and try again." +msgstr "" diff --git a/debian/rules b/debian/rules new file mode 100755 index 000000000..f3e568225 --- /dev/null +++ b/debian/rules @@ -0,0 +1,20 @@ +#! /usr/bin/make -f +export DH_VERBOSE=1 + +%: + dh $@ + +# disable "make check" +override_dh_auto_test: + +# disable stripping debugging symbols +override_dh_clistrip: + +override_dh_auto_build: + npx yarn install + mv $(CURDIR)/dist $(CURDIR)/web + +override_dh_auto_clean: + test -d $(CURDIR)/dist && rm -rf '$(CURDIR)/dist' || true + test -d $(CURDIR)/web && rm -rf '$(CURDIR)/web' || true + test -d $(CURDIR)/node_modules && rm -rf '$(CURDIR)/node_modules' || true diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 000000000..d3827e75a --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +1.0 diff --git a/debian/source/options b/debian/source/options new file mode 100644 index 000000000..b7adf56c6 --- /dev/null +++ b/debian/source/options @@ -0,0 +1,7 @@ +tar-ignore='.git*' +tar-ignore='**/.git' +tar-ignore='**/.hg' +tar-ignore='**/.vs' +tar-ignore='**/.vscode' +tar-ignore='deployment' +tar-ignore='*.deb' diff --git a/deployment/Dockerfile.centos.all b/deployment/Dockerfile.centos.all new file mode 100644 index 000000000..93bf8d698 --- /dev/null +++ b/deployment/Dockerfile.centos.all @@ -0,0 +1,27 @@ +FROM centos:7 +# Docker build arguments +ARG SOURCE_DIR=/jellyfin +ARG ARTIFACT_DIR=/dist +# Docker run environment +ENV SOURCE_DIR=/jellyfin +ENV ARTIFACT_DIR=/dist +ENV IS_DOCKER=YES + +# Prepare CentOS environment +RUN yum update -y \ + && yum install -y epel-release \ + && yum install -y @buildsys-build rpmdevtools git yum-plugins-core nodejs-yarn autoconf automake glibc-devel + +# Install recent NodeJS and Yarn +RUN curl -fSsLo /etc/yum.repos.d/yarn.repo https://dl.yarnpkg.com/rpm/yarn.repo \ + && rpm -i https://rpm.nodesource.com/pub_10.x/el/7/x86_64/nodesource-release-el7-1.noarch.rpm \ + && yum install -y yarn + +# Link to build script +RUN ln -sf ${SOURCE_DIR}/deployment/build.centos.all /build.sh + +VOLUME ${SOURCE_DIR}/ + +VOLUME ${ARTIFACT_DIR}/ + +ENTRYPOINT ["/build.sh"] diff --git a/deployment/Dockerfile.debian.all b/deployment/Dockerfile.debian.all new file mode 100644 index 000000000..54281a5eb --- /dev/null +++ b/deployment/Dockerfile.debian.all @@ -0,0 +1,25 @@ +FROM debian:10 +# Docker build arguments +ARG SOURCE_DIR=/jellyfin +ARG ARTIFACT_DIR=/dist +# Docker run environment +ENV SOURCE_DIR=/jellyfin +ENV ARTIFACT_DIR=/dist +ENV DEB_BUILD_OPTIONS=noddebs +ENV IS_DOCKER=YES + +# Prepare Debian build environment +RUN apt-get update \ + && apt-get install -y debhelper mmv npm git + +# Prepare Yarn +RUN npm install -g yarn + +# Link to build script +RUN ln -sf ${SOURCE_DIR}/deployment/build.debian.all /build.sh + +VOLUME ${SOURCE_DIR}/ + +VOLUME ${ARTIFACT_DIR}/ + +ENTRYPOINT ["/build.sh"] diff --git a/deployment/Dockerfile.fedora.all b/deployment/Dockerfile.fedora.all new file mode 100644 index 000000000..d47f4ff4d --- /dev/null +++ b/deployment/Dockerfile.fedora.all @@ -0,0 +1,21 @@ +FROM fedora:31 +# Docker build arguments +ARG SOURCE_DIR=/jellyfin +ARG ARTIFACT_DIR=/dist +# Docker run environment +ENV SOURCE_DIR=/jellyfin +ENV ARTIFACT_DIR=/dist +ENV IS_DOCKER=YES + +# Prepare Fedora environment +RUN dnf update -y \ + && dnf install -y @buildsys-build rpmdevtools git dnf-plugins-core nodejs-yarn autoconf automake glibc-devel + +# Link to build script +RUN ln -sf ${SOURCE_DIR}/deployment/build.fedora.all /build.sh + +VOLUME ${SOURCE_DIR}/ + +VOLUME ${ARTIFACT_DIR}/ + +ENTRYPOINT ["/build.sh"] diff --git a/deployment/Dockerfile.portable b/deployment/Dockerfile.portable new file mode 100644 index 000000000..e0d1f4526 --- /dev/null +++ b/deployment/Dockerfile.portable @@ -0,0 +1,25 @@ +FROM debian:10 +# Docker build arguments +ARG SOURCE_DIR=/jellyfin +ARG ARTIFACT_DIR=/dist +# Docker run environment +ENV SOURCE_DIR=/jellyfin +ENV ARTIFACT_DIR=/dist +ENV DEB_BUILD_OPTIONS=noddebs +ENV IS_DOCKER=YES + +# Prepare Debian build environment +RUN apt-get update \ + && apt-get install -y mmv npm git + +# Prepare Yarn +RUN npm install -g yarn + +# Link to build script +RUN ln -sf ${SOURCE_DIR}/deployment/build.portable /build.sh + +VOLUME ${SOURCE_DIR}/ + +VOLUME ${ARTIFACT_DIR}/ + +ENTRYPOINT ["/build.sh"] diff --git a/deployment/build.centos.all b/deployment/build.centos.all new file mode 100755 index 000000000..8c2cec6d3 --- /dev/null +++ b/deployment/build.centos.all @@ -0,0 +1,27 @@ +#!/bin/bash + +#= CentOS 7 all .rpm + +set -o errexit +set -o xtrace + +# Move to source directory +pushd ${SOURCE_DIR} + +cp -a yarn.lock /tmp/yarn.lock + +# Build RPM +make -f fedora/Makefile srpm outdir=/root/rpmbuild/SRPMS +rpmbuild --rebuild -bb /root/rpmbuild/SRPMS/jellyfin-*.src.rpm + +# Move the artifacts out +mv /root/rpmbuild/RPMS/noarch/jellyfin-*.rpm /root/rpmbuild/SRPMS/jellyfin-*.src.rpm ${ARTIFACT_DIR}/ + +if [[ ${IS_DOCKER} == YES ]]; then + chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR} +fi + +rm -f fedora/jellyfin*.tar.gz +cp -a /tmp/yarn.lock yarn.lock + +popd diff --git a/deployment/build.debian.all b/deployment/build.debian.all new file mode 100755 index 000000000..8d617a288 --- /dev/null +++ b/deployment/build.debian.all @@ -0,0 +1,25 @@ +#!/bin/bash + +#= Debian/Ubuntu all .deb + +set -o errexit +set -o xtrace + +# Move to source directory +pushd ${SOURCE_DIR} + +cp -a yarn.lock /tmp/yarn.lock + +# Build DEB +dpkg-buildpackage -us -uc --pre-clean --post-clean + +mkdir -p ${ARTIFACT_DIR}/ +mv ../jellyfin*.{deb,dsc,tar.gz,buildinfo,changes} ${ARTIFACT_DIR}/ + +cp -a /tmp/yarn.lock yarn.lock + +if [[ ${IS_DOCKER} == YES ]]; then + chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR} +fi + +popd diff --git a/deployment/build.fedora.all b/deployment/build.fedora.all new file mode 100755 index 000000000..4ba12f35e --- /dev/null +++ b/deployment/build.fedora.all @@ -0,0 +1,27 @@ +#!/bin/bash + +#= Fedora 29+ all .rpm + +set -o errexit +set -o xtrace + +# Move to source directory +pushd ${SOURCE_DIR} + +cp -a yarn.lock /tmp/yarn.lock + +# Build RPM +make -f fedora/Makefile srpm outdir=/root/rpmbuild/SRPMS +rpmbuild -rb /root/rpmbuild/SRPMS/jellyfin-*.src.rpm + +# Move the artifacts out +mv /root/rpmbuild/RPMS/noarch/jellyfin-*.rpm /root/rpmbuild/SRPMS/jellyfin-*.src.rpm ${ARTIFACT_DIR}/ + +if [[ ${IS_DOCKER} == YES ]]; then + chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR} +fi + +rm -f fedora/jellyfin*.tar.gz +cp -a /tmp/yarn.lock yarn.lock + +popd diff --git a/deployment/build.portable b/deployment/build.portable new file mode 100755 index 000000000..c4cbe927e --- /dev/null +++ b/deployment/build.portable @@ -0,0 +1,28 @@ +#!/bin/bash + +#= Portable .NET DLL .tar.gz + +set -o errexit +set -o xtrace + +# Move to source directory +pushd ${SOURCE_DIR} + +# Get version +version="$( grep "version:" ./build.yaml | sed -E 's/version: "([0-9\.]+.*)"/\1/' )" + +# Build archives +npx yarn install +mv dist/ jellyfin-web_${version} +tar -czf jellyfin-web_${version}_portable.tar.gz jellyfin-web_${version} +rm -rf dist/ + +# Move the artifacts out +mkdir -p ${ARTIFACT_DIR}/ +mv jellyfin[-_]*.tar.gz ${ARTIFACT_DIR}/ + +if [[ ${IS_DOCKER} == YES ]]; then + chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR} +fi + +popd diff --git a/fedora/Makefile b/fedora/Makefile new file mode 100644 index 000000000..1d3e39ac8 --- /dev/null +++ b/fedora/Makefile @@ -0,0 +1,21 @@ +VERSION := $(shell sed -ne '/^Version:/s/.* *//p' fedora/jellyfin-web.spec) + +srpm: + cd fedora/; \ + SOURCE_DIR=.. \ + WORKDIR="$${PWD}"; \ + tar \ + --transform "s,^\.,jellyfin-web-$(VERSION)," \ + --exclude='.git*' \ + --exclude='**/.git' \ + --exclude='**/.hg' \ + --exclude='deployment' \ + --exclude='*.deb' \ + --exclude='*.rpm' \ + --exclude='jellyfin-web-$(VERSION).tar.gz' \ + -czf "jellyfin-web-$(VERSION).tar.gz" \ + -C $${SOURCE_DIR} ./ + cd fedora/; \ + rpmbuild -bs jellyfin-web.spec \ + --define "_sourcedir $$PWD/" \ + --define "_srcrpmdir $(outdir)" diff --git a/fedora/jellyfin-web.spec b/fedora/jellyfin-web.spec new file mode 100644 index 000000000..dbc0bd0ef --- /dev/null +++ b/fedora/jellyfin-web.spec @@ -0,0 +1,43 @@ +%global debug_package %{nil} + +Name: jellyfin-web +Version: 10.6.0 +Release: 1%{?dist} +Summary: The Free Software Media System web client +License: GPLv3 +URL: https://jellyfin.org +# Jellyfin Server tarball created by `make -f .copr/Makefile srpm`, real URL ends with `v%{version}.tar.gz` +Source0: jellyfin-web-%{version}.tar.gz + +%if 0%{?centos} +BuildRequires: yarn +%else +BuildRequires nodejs-yarn +%endif +BuildArch: noarch + +# Disable Automatic Dependency Processing +AutoReqProv: no + +%description +Jellyfin is a free software media system that puts you in control of managing and streaming your media. + + +%prep +%autosetup -n jellyfin-web-%{version} -b 0 + +%build + +%install +yarn install +%{__mkdir} -p %{buildroot}%{_datadir} +mv dist %{buildroot}%{_datadir}/jellyfin-web +%{__install} -D -m 0644 LICENSE %{buildroot}%{_datadir}/licenses/jellyfin/LICENSE + +%files +%attr(755,root,root) %{_datadir}/jellyfin-web +%{_datadir}/licenses/jellyfin/LICENSE + +%changelog +* Mon Mar 23 2020 Jellyfin Packaging Team +- Forthcoming stable release diff --git a/gulpfile.js b/gulpfile.js index 4556e71bc..0e9732455 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,5 +1,3 @@ -'use strict'; - const { src, dest, series, parallel, watch } = require('gulp'); const browserSync = require('browser-sync').create(); const del = require('del'); diff --git a/package.json b/package.json index 4e79ea3c3..c22437bfc 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "@babel/plugin-transform-modules-amd": "^7.8.3", "@babel/polyfill": "^7.8.7", "@babel/preset-env": "^7.8.6", - "autoprefixer": "^9.7.4", + "autoprefixer": "^9.7.6", "babel-loader": "^8.0.6", "browser-sync": "^2.26.7", "clean-webpack-plugin": "^3.0.0", @@ -90,10 +90,10 @@ "test": [ "src/components/autoFocuser.js", "src/components/cardbuilder/cardBuilder.js", - "src/components/dom.js", + "src/scripts/dom.js", "src/components/filedownloader.js", "src/components/filesystem.js", - "src/components/input/keyboardnavigation.js", + "src/scripts/keyboardnavigation.js", "src/components/sanatizefilename.js", "src/components/scrollManager.js", "src/scripts/settings/appSettings.js", @@ -130,7 +130,7 @@ "build:development": "gulp --development", "build:production": "gulp --production", "build:standalone": "gulp standalone --development", - "lint": "eslint \"src\"", + "lint": "eslint \".\"", "stylelint": "stylelint \"src/**/*.css\"" } } diff --git a/postcss.config.js b/postcss.config.js index 23159fd29..9ce2e16af 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -1,11 +1,13 @@ const postcssPresetEnv = require('postcss-preset-env'); +const autoprefixer = require('autoprefixer'); const cssnano = require('cssnano'); const config = () => ({ - plugins: [ - postcssPresetEnv(), - cssnano() - ] + plugins: [ + postcssPresetEnv(), + autoprefixer(), + cssnano() + ] }); -module.exports = config +module.exports = config; diff --git a/src/addplugin.html b/src/addplugin.html index 83640033b..30e42a2c5 100644 --- a/src/addplugin.html +++ b/src/addplugin.html @@ -8,9 +8,8 @@ ${Help} -

-

-

+

+

@@ -28,7 +27,6 @@
${ServerRestartNeededAfterPluginInstall}
-

@@ -37,9 +35,6 @@ diff --git a/src/components/accessschedule/accessschedule.js b/src/components/accessschedule/accessschedule.js index 2f4be8b2a..28b09b893 100644 --- a/src/components/accessschedule/accessschedule.js +++ b/src/components/accessschedule/accessschedule.js @@ -1,4 +1,4 @@ -define(["dialogHelper", "datetime", "emby-select", "paper-icon-button-light", "formDialogStyle"], function (dialogHelper, datetime) { +define(["dialogHelper", "datetime", "globalize", "emby-select", "paper-icon-button-light", "formDialogStyle"], function (dialogHelper, datetime, globalize) { "use strict"; function getDisplayTime(hours) { @@ -38,7 +38,7 @@ define(["dialogHelper", "datetime", "emby-select", "paper-icon-button-light", "f }; if (parseFloat(updatedSchedule.StartHour) >= parseFloat(updatedSchedule.EndHour)) { - return void alert(Globalize.translate("ErrorMessageStartHourGreaterThanEnd")); + return void alert(globalize.translate("ErrorMessageStartHourGreaterThanEnd")); } context.submitted = true; @@ -60,7 +60,7 @@ define(["dialogHelper", "datetime", "emby-select", "paper-icon-button-light", "f }); dlg.classList.add("formDialog"); var html = ""; - html += Globalize.translateDocument(template); + html += globalize.translateDocument(template); dlg.innerHTML = html; populateHours(dlg); loadSchedule(dlg, options.schedule); diff --git a/src/components/apphost.js b/src/components/apphost.js index 7c2c59a5e..2240aff52 100644 --- a/src/components/apphost.js +++ b/src/components/apphost.js @@ -1,4 +1,4 @@ -define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], function (appSettings, browser, events, htmlMediaHelper, webSettings) { +define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings", "globalize"], function (appSettings, browser, events, htmlMediaHelper, webSettings, globalize) { "use strict"; function getBaseProfileOptions(item) { @@ -328,10 +328,10 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f require(["actionsheet"], function (actionsheet) { exitPromise = actionsheet.show({ - title: Globalize.translate("MessageConfirmAppExit"), + title: globalize.translate("MessageConfirmAppExit"), items: [ - {id: "yes", name: Globalize.translate("Yes")}, - {id: "no", name: Globalize.translate("No")} + {id: "yes", name: globalize.translate("Yes")}, + {id: "no", name: globalize.translate("No")} ] }).then(function (value) { if (value === "yes") { @@ -346,7 +346,7 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f var deviceId; var deviceName; var appName = "Jellyfin Web"; - var appVersion = "10.5.0"; + var appVersion = "10.6.0"; var appHost = { getWindowState: function () { diff --git a/src/components/directorybrowser/directorybrowser.js b/src/components/directorybrowser/directorybrowser.js index fc976068e..65fe34df1 100644 --- a/src/components/directorybrowser/directorybrowser.js +++ b/src/components/directorybrowser/directorybrowser.js @@ -1,4 +1,4 @@ -define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper-icon-button-light', 'css!./directorybrowser', 'formDialogStyle', 'emby-button'], function(loading, dialogHelper, dom) { +define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-input', 'paper-icon-button-light', 'css!./directorybrowser', 'formDialogStyle', 'emby-button'], function(loading, dialogHelper, dom, globalize) { 'use strict'; function getSystemInfo() { @@ -53,7 +53,7 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper- } if (!path) { - html += getItem("lnkPath lnkDirectory", "", "Network", Globalize.translate("ButtonNetwork")); + html += getItem("lnkPath lnkDirectory", "", "Network", globalize.translate("ButtonNetwork")); } page.querySelector(".results").innerHTML = html; @@ -89,16 +89,16 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper- var instruction = options.instruction ? options.instruction + "

" : ""; html += '
'; html += instruction; - html += Globalize.translate("MessageDirectoryPickerInstruction", "\\\\server", "\\\\192.168.1.101"); + html += globalize.translate("MessageDirectoryPickerInstruction", "\\\\server", "\\\\192.168.1.101"); if ("bsd" === systemInfo.OperatingSystem.toLowerCase()) { html += "
"; html += "
"; - html += Globalize.translate("MessageDirectoryPickerBSDInstruction"); + html += globalize.translate("MessageDirectoryPickerBSDInstruction"); html += "
"; } else if ("linux" === systemInfo.OperatingSystem.toLowerCase()) { html += "
"; html += "
"; - html += Globalize.translate("MessageDirectoryPickerLinuxInstruction"); + html += globalize.translate("MessageDirectoryPickerLinuxInstruction"); html += "
"; } html += "
"; @@ -113,10 +113,10 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper- labelKey = "LabelPath"; } var readOnlyAttribute = options.pathReadOnly ? " readonly" : ""; - html += ''; + html += ''; html += ""; if (!readOnlyAttribute) { - html += ''; + html += ''; } html += ""; if (!readOnlyAttribute) { @@ -124,14 +124,14 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper- } if (options.enableNetworkSharePath) { html += '
'; - html += ''; + html += ''; html += '
'; - html += Globalize.translate("LabelOptionalNetworkPathHelp"); + html += globalize.translate("LabelOptionalNetworkPathHelp"); html += "
"; html += "
"; } html += '
'; - html += '"; + html += '"; html += "
"; html += ""; html += ""; @@ -164,14 +164,14 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper- }).catch(function(response) { if (response) { if (response.status === 404) { - alertText(Globalize.translate("PathNotFound")); + alertText(globalize.translate("PathNotFound")); return Promise.reject(); } if (response.status === 500) { if (validateWriteable) { - alertText(Globalize.translate("WriteAccessRequired")); + alertText(globalize.translate("WriteAccessRequired")); } else { - alertText(Globalize.translate("PathNotFound")); + alertText(globalize.translate("PathNotFound")); } return Promise.reject(); } @@ -266,7 +266,7 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper- html += '
'; html += ''; html += '

'; - html += options.header || Globalize.translate("HeaderSelectPath"); + html += options.header || globalize.translate("HeaderSelectPath"); html += "

"; html += "
"; html += getEditorHtml(options, systemInfo); diff --git a/src/components/homesections/homesections.js b/src/components/homesections/homesections.js index cb4866a1c..894cf0bdb 100644 --- a/src/components/homesections/homesections.js +++ b/src/components/homesections/homesections.js @@ -64,13 +64,13 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la } else { var noLibDescription; if (user['Policy'] && user['Policy']['IsAdministrator']) { - noLibDescription = Globalize.translate("NoCreatedLibraries", '', ''); + noLibDescription = globalize.translate("NoCreatedLibraries", '
', ''); } else { - noLibDescription = Globalize.translate("AskAdminToCreateLibrary"); + noLibDescription = globalize.translate("AskAdminToCreateLibrary"); } html += '
'; - html += '

' + Globalize.translate("MessageNothingHere") + '

'; + html += '

' + globalize.translate("MessageNothingHere") + '

'; html += '

' + noLibDescription + '

'; html += '
'; elem.innerHTML = html; @@ -243,9 +243,9 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la return function (items) { var cardLayout = false; var shape; - if (itemType === 'Channel' || viewType === 'movies' || viewType === 'books') { + if (itemType === 'Channel' || viewType === 'movies' || viewType === 'books' || viewType === 'tvshows') { shape = getPortraitShape(); - } else if (viewType === 'music') { + } else if (viewType === 'music' || viewType === 'homevideos') { shape = getSquareShape(); } else { shape = getThumbShape(); diff --git a/src/components/htmlvideoplayer/plugin.js b/src/components/htmlvideoplayer/plugin.js index fa0c02237..d3e3b3640 100644 --- a/src/components/htmlvideoplayer/plugin.js +++ b/src/components/htmlvideoplayer/plugin.js @@ -795,7 +795,9 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa dlg.parentNode.removeChild(dlg); } - screenfull.exit(); + if (screenfull.isEnabled) { + screenfull.exit(); + } }; function onEnded() { diff --git a/src/components/itemcontextmenu.js b/src/components/itemcontextmenu.js index 5f95714d3..eec46899a 100644 --- a/src/components/itemcontextmenu.js +++ b/src/components/itemcontextmenu.js @@ -218,7 +218,7 @@ define(["apphost", "globalize", "connectionManager", "itemHelper", "appRouter", if (item.Type === "Program" && options.record !== false) { if (item.TimerId) { commands.push({ - name: Globalize.translate("ManageRecording"), + name: globalize.translate("ManageRecording"), id: "record", icon: "fiber_manual_record" }); @@ -228,7 +228,7 @@ define(["apphost", "globalize", "connectionManager", "itemHelper", "appRouter", if (item.Type === "Program" && options.record !== false) { if (!item.TimerId) { commands.push({ - name: Globalize.translate("Record"), + name: globalize.translate("Record"), id: "record", icon: "fiber_manual_record" }); @@ -283,7 +283,7 @@ define(["apphost", "globalize", "connectionManager", "itemHelper", "appRouter", if (options.openAlbum !== false && item.AlbumId && item.MediaType !== "Photo") { commands.push({ - name: Globalize.translate("ViewAlbum"), + name: globalize.translate("ViewAlbum"), id: "album", icon: "album" }); @@ -291,7 +291,7 @@ define(["apphost", "globalize", "connectionManager", "itemHelper", "appRouter", if (options.openArtist !== false && item.ArtistItems && item.ArtistItems.length) { commands.push({ - name: Globalize.translate("ViewArtist"), + name: globalize.translate("ViewArtist"), id: "artist", icon: "person" }); diff --git a/src/components/medialibrarycreator/medialibrarycreator.js b/src/components/medialibrarycreator/medialibrarycreator.js index 0a8741387..1665efe27 100644 --- a/src/components/medialibrarycreator/medialibrarycreator.js +++ b/src/components/medialibrarycreator/medialibrarycreator.js @@ -1,4 +1,4 @@ -define(["loading", "dialogHelper", "dom", "jQuery", "components/libraryoptionseditor/libraryoptionseditor", "emby-toggle", "emby-input", "emby-select", "paper-icon-button-light", "listViewStyle", "formDialogStyle", "emby-button", "flexStyles"], function (loading, dialogHelper, dom, $, libraryoptionseditor) { +define(["loading", "dialogHelper", "dom", "jQuery", "components/libraryoptionseditor/libraryoptionseditor", "globalize", "emby-toggle", "emby-input", "emby-select", "paper-icon-button-light", "listViewStyle", "formDialogStyle", "emby-button", "flexStyles"], function (loading, dialogHelper, dom, $, libraryoptionseditor, globalize) { "use strict"; function onAddLibrary() { @@ -9,7 +9,7 @@ define(["loading", "dialogHelper", "dom", "jQuery", "components/libraryoptionsed if (pathInfos.length == 0) { require(["alert"], function (alert) { alert({ - text: Globalize.translate("PleaseAddAtLeastOneFolder"), + text: globalize.translate("PleaseAddAtLeastOneFolder"), type: "error" }); }); @@ -36,7 +36,7 @@ define(["loading", "dialogHelper", "dom", "jQuery", "components/libraryoptionsed dialogHelper.close(dlg); }, function () { require(["toast"], function (toast) { - toast(Globalize.translate("ErrorAddingMediaPathToVirtualFolder")); + toast(globalize.translate("ErrorAddingMediaPathToVirtualFolder")); }); isCreating = false; @@ -196,7 +196,7 @@ define(["loading", "dialogHelper", "dom", "jQuery", "components/libraryoptionsed dlg.classList.add("background-theme-a"); dlg.classList.add("dlg-librarycreator"); dlg.classList.add("formDialog"); - dlg.innerHTML = Globalize.translateDocument(template); + dlg.innerHTML = globalize.translateDocument(template); initEditor(dlg, options.collectionTypeOptions); dlg.addEventListener("close", onDialogClosed); dialogHelper.open(dlg); diff --git a/src/components/medialibraryeditor/medialibraryeditor.js b/src/components/medialibraryeditor/medialibraryeditor.js index 7c5c8d408..6a0f955b2 100644 --- a/src/components/medialibraryeditor/medialibraryeditor.js +++ b/src/components/medialibraryeditor/medialibraryeditor.js @@ -1,4 +1,4 @@ -define(["jQuery", "loading", "dialogHelper", "dom", "components/libraryoptionseditor/libraryoptionseditor", "emby-button", "listViewStyle", "paper-icon-button-light", "formDialogStyle", "emby-toggle", "flexStyles"], function (jQuery, loading, dialogHelper, dom, libraryoptionseditor) { +define(["jQuery", "loading", "dialogHelper", "dom", "components/libraryoptionseditor/libraryoptionseditor", "globalize", "emby-button", "listViewStyle", "paper-icon-button-light", "formDialogStyle", "emby-toggle", "flexStyles"], function (jQuery, loading, dialogHelper, dom, libraryoptionseditor, globalize) { "use strict"; function onEditLibrary() { @@ -31,7 +31,7 @@ define(["jQuery", "loading", "dialogHelper", "dom", "components/libraryoptionsed refreshLibraryFromServer(page); }, function () { require(["toast"], function (toast) { - toast(Globalize.translate("ErrorAddingMediaPathToVirtualFolder")); + toast(globalize.translate("ErrorAddingMediaPathToVirtualFolder")); }); }); } @@ -46,7 +46,7 @@ define(["jQuery", "loading", "dialogHelper", "dom", "components/libraryoptionsed refreshLibraryFromServer(page); }, function () { require(["toast"], function (toast) { - toast(Globalize.translate("ErrorAddingMediaPathToVirtualFolder")); + toast(globalize.translate("ErrorAddingMediaPathToVirtualFolder")); }); }); } @@ -57,9 +57,9 @@ define(["jQuery", "loading", "dialogHelper", "dom", "components/libraryoptionsed require(["confirm"], function (confirm) { confirm({ - title: Globalize.translate("HeaderRemoveMediaLocation"), - text: Globalize.translate("MessageConfirmRemoveMediaLocation"), - confirmText: Globalize.translate("ButtonDelete"), + title: globalize.translate("HeaderRemoveMediaLocation"), + text: globalize.translate("MessageConfirmRemoveMediaLocation"), + confirmText: globalize.translate("ButtonDelete"), primary: "delete" }).then(function () { var refreshAfterChange = currentOptions.refresh; @@ -68,7 +68,7 @@ define(["jQuery", "loading", "dialogHelper", "dom", "components/libraryoptionsed refreshLibraryFromServer(dom.parentWithClass(button, "dlg-libraryeditor")); }, function () { require(["toast"], function (toast) { - toast(Globalize.translate("DefaultErrorMessage")); + toast(globalize.translate("DefaultErrorMessage")); }); }); }); @@ -213,7 +213,7 @@ define(["jQuery", "loading", "dialogHelper", "dom", "components/libraryoptionsed dlg.classList.add("ui-body-a"); dlg.classList.add("background-theme-a"); dlg.classList.add("formDialog"); - dlg.innerHTML = Globalize.translateDocument(template); + dlg.innerHTML = globalize.translateDocument(template); dlg.querySelector(".formDialogHeaderTitle").innerHTML = options.library.Name; initEditor(dlg, options); dlg.addEventListener("close", onDialogClosed); diff --git a/src/components/multiselect/multiselect.js b/src/components/multiselect/multiselect.js index 8a41e86af..53c3b4cf5 100644 --- a/src/components/multiselect/multiselect.js +++ b/src/components/multiselect/multiselect.js @@ -212,7 +212,7 @@ define(["browser", "appStorage", "apphost", "loading", "connectionManager", "glo if (user.Policy.EnableContentDownloading && appHost.supports("filedownload")) { menuItems.push({ - name: Globalize.translate("ButtonDownload"), + name: globalize.translate("ButtonDownload"), id: "download", icon: "file_download" }); diff --git a/src/components/playback/playbackmanager.js b/src/components/playback/playbackmanager.js index f323d3609..031231285 100644 --- a/src/components/playback/playbackmanager.js +++ b/src/components/playback/playbackmanager.js @@ -20,9 +20,11 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla } function bindToFullscreenChange(player) { - screenfull.on('change', function () { - events.trigger(player, 'fullscreenchange'); - }); + if (screenfull.isEnabled) { + screenfull.on('change', function () { + events.trigger(player, 'fullscreenchange'); + }); + } } function triggerPlayerChange(playbackManagerInstance, newPlayer, newTarget, previousPlayer, previousTargetInfo) { diff --git a/src/components/polyfills/objectassign.js b/src/components/polyfills/objectassign.js deleted file mode 100644 index 85f55aa14..000000000 --- a/src/components/polyfills/objectassign.js +++ /dev/null @@ -1,24 +0,0 @@ -if (typeof Object.assign != 'function') { - (function () { - Object.assign = function (target) { - 'use strict'; - if (target === undefined || target === null) { - throw new TypeError('Cannot convert undefined or null to object'); - } - - var output = Object(target); - for (var index = 1; index < arguments.length; index++) { - var source = arguments[index]; - if (source !== undefined && source !== null) { - for (var nextKey in source) { - // eslint-disable-next-line no-prototype-builtins - if (source.hasOwnProperty(nextKey)) { - output[nextKey] = source[nextKey]; - } - } - } - } - return output; - }; - })(); -} diff --git a/src/components/remotecontrol/remotecontrol.js b/src/components/remotecontrol/remotecontrol.js index 8e2a382d1..327cd1dcf 100644 --- a/src/components/remotecontrol/remotecontrol.js +++ b/src/components/remotecontrol/remotecontrol.js @@ -672,18 +672,6 @@ define(["browser", "datetime", "backdrop", "libraryBrowser", "listView", "imageL playbackManager.setVolume(this.value, currentPlayer); } - var contextmenuHtml = ''; - var volumecontrolHtml = '
'; - volumecontrolHtml += ''; - volumecontrolHtml += '
'; - volumecontrolHtml += '
'; - if (!layoutManager.mobile) { - context.querySelector(".nowPlayingSecondaryButtons").innerHTML += volumecontrolHtml; - context.querySelector(".playlistSectionButton").innerHTML += contextmenuHtml; - } else { - context.querySelector(".playlistSectionButton").innerHTML += volumecontrolHtml + contextmenuHtml; - } - context.querySelector(".nowPlayingVolumeSlider").addEventListener("change", setVolume); context.querySelector(".nowPlayingVolumeSlider").addEventListener("mousemove", setVolume); context.querySelector(".nowPlayingVolumeSlider").addEventListener("touchmove", setVolume); @@ -767,6 +755,18 @@ define(["browser", "datetime", "backdrop", "libraryBrowser", "listView", "imageL } function init(ownerView, context) { + let contextmenuHtml = ``; + let volumecontrolHtml = '
'; + volumecontrolHtml += ``; + volumecontrolHtml += '
'; + volumecontrolHtml += '
'; + if (!layoutManager.mobile) { + context.querySelector('.nowPlayingSecondaryButtons').innerHTML += volumecontrolHtml; + context.querySelector('.playlistSectionButton').innerHTML += contextmenuHtml; + } else { + context.querySelector('.playlistSectionButton').innerHTML += volumecontrolHtml + contextmenuHtml; + } + bindEvents(context); context.querySelector(".sendMessageForm").addEventListener("submit", onMessageSubmit); context.querySelector(".typeTextForm").addEventListener("submit", onSendStringSubmit); diff --git a/src/components/subtitleeditor/subtitleeditor.js b/src/components/subtitleeditor/subtitleeditor.js index 1ff30712f..123b4ba20 100644 --- a/src/components/subtitleeditor/subtitleeditor.js +++ b/src/components/subtitleeditor/subtitleeditor.js @@ -397,7 +397,7 @@ define(['dialogHelper', 'require', 'layoutManager', 'globalize', 'userSettings', var items = []; items.push({ - name: Globalize.translate('Download'), + name: globalize.translate('Download'), id: 'download' }); diff --git a/src/components/tvproviders/schedulesdirect.js b/src/components/tvproviders/schedulesdirect.js index cf11e5736..649ac5017 100644 --- a/src/components/tvproviders/schedulesdirect.js +++ b/src/components/tvproviders/schedulesdirect.js @@ -1,4 +1,4 @@ -define(["jQuery", "loading", "emby-checkbox", "listViewStyle", "emby-input", "emby-select", "emby-button", "flexStyles"], function ($, loading) { +define(["jQuery", "loading", "globalize", "emby-checkbox", "listViewStyle", "emby-input", "emby-select", "emby-button", "flexStyles"], function ($, loading, globalize) { "use strict"; return function (page, providerId, options) { @@ -69,7 +69,7 @@ define(["jQuery", "loading", "emby-checkbox", "listViewStyle", "emby-input", "em $(page.querySelector(".txtZipCode")).trigger("change"); }, function () { // ApiClient.getJSON() error handler Dashboard.alert({ - message: Globalize.translate("ErrorGettingTvLineups") + message: globalize.translate("ErrorGettingTvLineups") }); }); loading.hide(); @@ -130,7 +130,7 @@ define(["jQuery", "loading", "emby-checkbox", "listViewStyle", "emby-input", "em reload(); }, function () { Dashboard.alert({ // ApiClient.ajax() error handler - message: Globalize.translate("ErrorSavingTvProvider") + message: globalize.translate("ErrorSavingTvProvider") }); }); }); @@ -141,7 +141,7 @@ define(["jQuery", "loading", "emby-checkbox", "listViewStyle", "emby-input", "em if (!selectedListingsId) { return void Dashboard.alert({ - message: Globalize.translate("ErrorPleaseSelectLineup") + message: globalize.translate("ErrorPleaseSelectLineup") }); } @@ -178,7 +178,7 @@ define(["jQuery", "loading", "emby-checkbox", "listViewStyle", "emby-input", "em }, function () { loading.hide(); Dashboard.alert({ - message: Globalize.translate("ErrorAddingListingsToSchedulesDirect") + message: globalize.translate("ErrorAddingListingsToSchedulesDirect") }); }); }); @@ -210,7 +210,7 @@ define(["jQuery", "loading", "emby-checkbox", "listViewStyle", "emby-input", "em loading.hide(); }, function (result) { Dashboard.alert({ - message: Globalize.translate("ErrorGettingTvLineups") + message: globalize.translate("ErrorGettingTvLineups") }); refreshListings(""); loading.hide(); @@ -290,7 +290,7 @@ define(["jQuery", "loading", "emby-checkbox", "listViewStyle", "emby-input", "em page.querySelector(".selectTunersSection").classList.remove("hide"); } }); - $(".createAccountHelp", page).html(Globalize.translate("MessageCreateAccountAt", 'http://www.schedulesdirect.org')); + $(".createAccountHelp", page).html(globalize.translate("MessageCreateAccountAt", 'http://www.schedulesdirect.org')); reload(); }; }; diff --git a/src/components/tvproviders/xmltv.js b/src/components/tvproviders/xmltv.js index 7e7d381f0..991ed49a4 100644 --- a/src/components/tvproviders/xmltv.js +++ b/src/components/tvproviders/xmltv.js @@ -1,4 +1,4 @@ -define(["jQuery", "loading", "emby-checkbox", "emby-input", "listViewStyle", "paper-icon-button-light"], function ($, loading) { +define(["jQuery", "loading", "globalize", "emby-checkbox", "emby-input", "listViewStyle", "paper-icon-button-light"], function ($, loading, globalize) { "use strict"; return function (page, providerId, options) { @@ -92,7 +92,7 @@ define(["jQuery", "loading", "emby-checkbox", "emby-input", "listViewStyle", "pa }, function () { loading.hide(); Dashboard.alert({ - message: Globalize.translate("ErrorAddingXmlTvFile") + message: globalize.translate("ErrorAddingXmlTvFile") }); }); }); diff --git a/src/controllers/auth/addserver.js b/src/controllers/auth/addserver.js index a55ba3066..8cead5abf 100644 --- a/src/controllers/auth/addserver.js +++ b/src/controllers/auth/addserver.js @@ -1,4 +1,4 @@ -define(["appSettings", "loading", "browser", "emby-button"], function(appSettings, loading, browser) { +define(["appSettings", "loading", "browser", "globalize", "emby-button"], function(appSettings, loading, browser, globalize) { "use strict"; function handleConnectionResult(page, result) { @@ -17,13 +17,13 @@ define(["appSettings", "loading", "browser", "emby-button"], function(appSetting break; case "ServerUpdateNeeded": Dashboard.alert({ - message: Globalize.translate("ServerUpdateNeeded", 'https://github.com/jellyfin/jellyfin') + message: globalize.translate("ServerUpdateNeeded", 'https://github.com/jellyfin/jellyfin') }); break; case "Unavailable": Dashboard.alert({ - message: Globalize.translate("MessageUnableToConnectToServer"), - title: Globalize.translate("HeaderConnectionFailure") + message: globalize.translate("MessageUnableToConnectToServer"), + title: globalize.translate("HeaderConnectionFailure") }); } } diff --git a/src/controllers/auth/forgotpassword.js b/src/controllers/auth/forgotpassword.js index e0f8ea4ef..32052d1f7 100644 --- a/src/controllers/auth/forgotpassword.js +++ b/src/controllers/auth/forgotpassword.js @@ -1,23 +1,23 @@ -define([], function () { +define(["globalize"], function (globalize) { "use strict"; function processForgotPasswordResult(result) { if ("ContactAdmin" == result.Action) { return void Dashboard.alert({ - message: Globalize.translate("MessageContactAdminToResetPassword"), - title: Globalize.translate("HeaderForgotPassword") + message: globalize.translate("MessageContactAdminToResetPassword"), + title: globalize.translate("HeaderForgotPassword") }); } if ("InNetworkRequired" == result.Action) { return void Dashboard.alert({ - message: Globalize.translate("MessageForgotPasswordInNetworkRequired"), - title: Globalize.translate("HeaderForgotPassword") + message: globalize.translate("MessageForgotPasswordInNetworkRequired"), + title: globalize.translate("HeaderForgotPassword") }); } if ("PinCode" == result.Action) { - var msg = Globalize.translate("MessageForgotPasswordFileCreated"); + var msg = globalize.translate("MessageForgotPasswordFileCreated"); msg += "
"; msg += "
"; msg += "Enter PIN here to finish Password Reset
"; @@ -26,7 +26,7 @@ define([], function () { msg += "
"; return void Dashboard.alert({ message: msg, - title: Globalize.translate("HeaderForgotPassword"), + title: globalize.translate("HeaderForgotPassword"), callback: function () { Dashboard.navigate("forgotpasswordpin.html"); } diff --git a/src/controllers/auth/forgotpasswordpin.js b/src/controllers/auth/forgotpasswordpin.js index 47b1c899b..f88f57ad7 100644 --- a/src/controllers/auth/forgotpasswordpin.js +++ b/src/controllers/auth/forgotpasswordpin.js @@ -1,15 +1,15 @@ -define([], function () { +define(["globalize"], function (globalize) { "use strict"; function processForgotPasswordResult(result) { if (result.Success) { - var msg = Globalize.translate("MessagePasswordResetForUsers"); + var msg = globalize.translate("MessagePasswordResetForUsers"); msg += "
"; msg += "
"; msg += result.UsersReset.join("
"); return void Dashboard.alert({ message: msg, - title: Globalize.translate("HeaderPasswordReset"), + title: globalize.translate("HeaderPasswordReset"), callback: function () { window.location.href = "index.html"; } @@ -17,8 +17,8 @@ define([], function () { } Dashboard.alert({ - message: Globalize.translate("MessageInvalidForgotPasswordPin"), - title: Globalize.translate("HeaderPasswordReset") + message: globalize.translate("MessageInvalidForgotPasswordPin"), + title: globalize.translate("HeaderPasswordReset") }); } diff --git a/src/controllers/auth/login.js b/src/controllers/auth/login.js index 4b679bbbd..05075efe5 100644 --- a/src/controllers/auth/login.js +++ b/src/controllers/auth/login.js @@ -1,4 +1,4 @@ -define(["apphost", "appSettings", "dom", "connectionManager", "loading", "layoutManager", "browser", "cardStyle", "emby-checkbox"], function (appHost, appSettings, dom, connectionManager, loading, layoutManager, browser) { +define(["apphost", "appSettings", "dom", "connectionManager", "loading", "layoutManager", "browser", "globalize", "cardStyle", "emby-checkbox"], function (appHost, appSettings, dom, connectionManager, loading, layoutManager, browser, globalize) { "use strict"; var enableFocusTransform = !browser.slow && !browser.edge; @@ -28,12 +28,12 @@ define(["apphost", "appSettings", "dom", "connectionManager", "loading", "layout if (UnauthorizedOrForbidden.includes(response.status)) { require(["toast"], function (toast) { const messageKey = response.status === 401 ? "MessageInvalidUser" : "MessageUnauthorizedUser"; - toast(Globalize.translate(messageKey)); + toast(globalize.translate(messageKey)); }); } else { Dashboard.alert({ - message: Globalize.translate("MessageUnableToConnectToServer"), - title: Globalize.translate("HeaderConnectionFailure") + message: globalize.translate("MessageUnableToConnectToServer"), + title: globalize.translate("HeaderConnectionFailure") }); } }); diff --git a/src/controllers/apikeys.js b/src/controllers/dashboard/apikeys.js similarity index 100% rename from src/controllers/apikeys.js rename to src/controllers/dashboard/apikeys.js diff --git a/src/controllers/device.js b/src/controllers/dashboard/devices/device.js similarity index 100% rename from src/controllers/device.js rename to src/controllers/dashboard/devices/device.js diff --git a/src/controllers/devices.js b/src/controllers/dashboard/devices/devices.js similarity index 100% rename from src/controllers/devices.js rename to src/controllers/dashboard/devices/devices.js diff --git a/src/controllers/dlnaprofile.js b/src/controllers/dashboard/dlna/dlnaprofile.js similarity index 96% rename from src/controllers/dlnaprofile.js rename to src/controllers/dashboard/dlna/dlnaprofile.js index ca0d3afdb..f4d5704a2 100644 --- a/src/controllers/dlnaprofile.js +++ b/src/controllers/dashboard/dlna/dlnaprofile.js @@ -1,4 +1,4 @@ -define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-input", "emby-checkbox", "listViewStyle", "emby-button"], function ($, loading) { +define(["jQuery", "loading", "globalize", "fnchecked", "emby-select", "emby-button", "emby-input", "emby-checkbox", "listViewStyle", "emby-button"], function ($, loading, globalize) { "use strict"; function loadProfile(page) { @@ -258,14 +258,14 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in html += "
"; html += ''; - html += "

" + Globalize.translate("ValueContainer", profile.Container || allText) + "

"; + html += "

" + globalize.translate("ValueContainer", profile.Container || allText) + "

"; if ("Video" == profile.Type) { - html += "

" + Globalize.translate("ValueVideoCodec", profile.VideoCodec || allText) + "

"; - html += "

" + Globalize.translate("ValueAudioCodec", profile.AudioCodec || allText) + "

"; + html += "

" + globalize.translate("ValueVideoCodec", profile.VideoCodec || allText) + "

"; + html += "

" + globalize.translate("ValueAudioCodec", profile.AudioCodec || allText) + "

"; } else { if ("Audio" == profile.Type) { - html += "

" + Globalize.translate("ValueCodec", profile.AudioCodec || allText) + "

"; + html += "

" + globalize.translate("ValueCodec", profile.AudioCodec || allText) + "

"; } } @@ -319,14 +319,14 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in html += "
"; html += ''; html += "

Protocol: " + (profile.Protocol || "Http") + "

"; - html += "

" + Globalize.translate("ValueContainer", profile.Container || allText) + "

"; + html += "

" + globalize.translate("ValueContainer", profile.Container || allText) + "

"; if ("Video" == profile.Type) { - html += "

" + Globalize.translate("ValueVideoCodec", profile.VideoCodec || allText) + "

"; - html += "

" + Globalize.translate("ValueAudioCodec", profile.AudioCodec || allText) + "

"; + html += "

" + globalize.translate("ValueVideoCodec", profile.VideoCodec || allText) + "

"; + html += "

" + globalize.translate("ValueAudioCodec", profile.AudioCodec || allText) + "

"; } else { if ("Audio" == profile.Type) { - html += "

" + Globalize.translate("ValueCodec", profile.AudioCodec || allText) + "

"; + html += "

" + globalize.translate("ValueCodec", profile.AudioCodec || allText) + "

"; } } @@ -404,11 +404,11 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in html += "
"; html += ''; - html += "

" + Globalize.translate("ValueContainer", profile.Container || allText) + "

"; + html += "

" + globalize.translate("ValueContainer", profile.Container || allText) + "

"; if (profile.Conditions && profile.Conditions.length) { html += "

"; - html += Globalize.translate("ValueConditions", profile.Conditions.map(function (c) { + html += globalize.translate("ValueConditions", profile.Conditions.map(function (c) { return c.Property; }).join(", ")); html += "

"; @@ -476,11 +476,11 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in html += "
"; html += ''; - html += "

" + Globalize.translate("ValueCodec", profile.Codec || allText) + "

"; + html += "

" + globalize.translate("ValueCodec", profile.Codec || allText) + "

"; if (profile.Conditions && profile.Conditions.length) { html += "

"; - html += Globalize.translate("ValueConditions", profile.Conditions.map(function (c) { + html += globalize.translate("ValueConditions", profile.Conditions.map(function (c) { return c.Property; }).join(", ")); html += "

"; @@ -547,20 +547,20 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in html += "
"; html += ''; - html += "

" + Globalize.translate("ValueContainer", profile.Container || allText) + "

"; + html += "

" + globalize.translate("ValueContainer", profile.Container || allText) + "

"; if ("Video" == profile.Type) { - html += "

" + Globalize.translate("ValueVideoCodec", profile.VideoCodec || allText) + "

"; - html += "

" + Globalize.translate("ValueAudioCodec", profile.AudioCodec || allText) + "

"; + html += "

" + globalize.translate("ValueVideoCodec", profile.VideoCodec || allText) + "

"; + html += "

" + globalize.translate("ValueAudioCodec", profile.AudioCodec || allText) + "

"; } else { if ("Audio" == profile.Type) { - html += "

" + Globalize.translate("ValueCodec", profile.AudioCodec || allText) + "

"; + html += "

" + globalize.translate("ValueCodec", profile.AudioCodec || allText) + "

"; } } if (profile.Conditions && profile.Conditions.length) { html += "

"; - html += Globalize.translate("ValueConditions", profile.Conditions.map(function (c) { + html += globalize.translate("ValueConditions", profile.Conditions.map(function (c) { return c.Property; }).join(", ")); html += "

"; @@ -690,7 +690,7 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in var currentProfile; var currentSubProfile; var isSubProfileNew; - var allText = Globalize.translate("LabelAll"); + var allText = globalize.translate("LabelAll"); $(document).on("pageinit", "#dlnaProfilePage", function () { var page = this; diff --git a/src/controllers/dlnaprofiles.js b/src/controllers/dashboard/dlna/dlnaprofiles.js similarity index 100% rename from src/controllers/dlnaprofiles.js rename to src/controllers/dashboard/dlna/dlnaprofiles.js diff --git a/src/controllers/dlnasettings.js b/src/controllers/dashboard/dlna/dlnasettings.js similarity index 91% rename from src/controllers/dlnasettings.js rename to src/controllers/dashboard/dlna/dlnasettings.js index fbb3af120..dd71b9ed1 100644 --- a/src/controllers/dlnasettings.js +++ b/src/controllers/dashboard/dlna/dlnasettings.js @@ -1,4 +1,4 @@ -define(["jQuery", "loading", "libraryMenu", "fnchecked"], function ($, loading, libraryMenu) { +define(["jQuery", "loading", "libraryMenu", "globalize", "fnchecked"], function ($, loading, libraryMenu, globalize) { "use strict"; function loadPage(page, config, users) { @@ -34,10 +34,10 @@ define(["jQuery", "loading", "libraryMenu", "fnchecked"], function ($, loading, function getTabs() { return [{ href: "dlnasettings.html", - name: Globalize.translate("TabSettings") + name: globalize.translate("TabSettings") }, { href: "dlnaprofiles.html", - name: Globalize.translate("TabProfiles") + name: globalize.translate("TabProfiles") }]; } diff --git a/src/controllers/encodingsettings.js b/src/controllers/dashboard/encodingsettings.js similarity index 98% rename from src/controllers/encodingsettings.js rename to src/controllers/dashboard/encodingsettings.js index 1b2718866..9820d7401 100644 --- a/src/controllers/encodingsettings.js +++ b/src/controllers/dashboard/encodingsettings.js @@ -116,13 +116,13 @@ define(["jQuery", "loading", "globalize", "dom", "libraryMenu"], function ($, lo function getTabs() { return [{ href: "encodingsettings.html", - name: Globalize.translate("Transcoding") + name: globalize.translate("Transcoding") }, { href: "playbackconfiguration.html", - name: Globalize.translate("TabResumeSettings") + name: globalize.translate("TabResumeSettings") }, { href: "streamingsettings.html", - name: Globalize.translate("TabStreaming") + name: globalize.translate("TabStreaming") }]; } diff --git a/src/controllers/dashboard/general.js b/src/controllers/dashboard/general.js index a434e4624..68d72d432 100644 --- a/src/controllers/dashboard/general.js +++ b/src/controllers/dashboard/general.js @@ -1,4 +1,4 @@ -define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emby-input", "emby-select", "emby-button"], function ($, loading) { +define(["jQuery", "loading", "globalize", "fnchecked", "emby-checkbox", "emby-textarea", "emby-input", "emby-select", "emby-button"], function ($, loading, globalize) { "use strict"; function loadPage(page, config, languageOptions, systemInfo) { @@ -58,7 +58,7 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emb }); }, function () { require(["alert"], function (alert) { - alert(Globalize.translate("DefaultErrorMessage")); + alert(globalize.translate("DefaultErrorMessage")); }); Dashboard.processServerConfigurationUpdateResult(); @@ -83,8 +83,8 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emb picker.close(); }, validateWriteable: true, - header: Globalize.translate("HeaderSelectServerCachePath"), - instruction: Globalize.translate("HeaderSelectServerCachePathHelp") + header: globalize.translate("HeaderSelectServerCachePath"), + instruction: globalize.translate("HeaderSelectServerCachePathHelp") }); }); }); @@ -106,8 +106,8 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emb picker.close(); }, validateWriteable: true, - header: Globalize.translate("HeaderSelectMetadataPath"), - instruction: Globalize.translate("HeaderSelectMetadataPathHelp"), + header: globalize.translate("HeaderSelectMetadataPath"), + instruction: globalize.translate("HeaderSelectMetadataPathHelp"), enableNetworkSharePath: true }); }); diff --git a/src/controllers/librarydisplay.js b/src/controllers/dashboard/librarydisplay.js similarity index 93% rename from src/controllers/librarydisplay.js rename to src/controllers/dashboard/librarydisplay.js index 78294f440..603ab1ee6 100644 --- a/src/controllers/librarydisplay.js +++ b/src/controllers/dashboard/librarydisplay.js @@ -4,16 +4,16 @@ define(["globalize", "loading", "libraryMenu", "emby-checkbox", "emby-button", " function getTabs() { return [{ href: "library.html", - name: Globalize.translate("HeaderLibraries") + name: globalize.translate("HeaderLibraries") }, { href: "librarydisplay.html", - name: Globalize.translate("TabDisplay") + name: globalize.translate("TabDisplay") }, { href: "metadataimages.html", - name: Globalize.translate("TabMetadata") + name: globalize.translate("TabMetadata") }, { href: "metadatanfo.html", - name: Globalize.translate("TabNfoSettings") + name: globalize.translate("TabNfoSettings") }]; } diff --git a/src/controllers/medialibrarypage.js b/src/controllers/dashboard/medialibrarypage.js similarity index 100% rename from src/controllers/medialibrarypage.js rename to src/controllers/dashboard/medialibrarypage.js diff --git a/src/controllers/metadataimagespage.js b/src/controllers/dashboard/metadataimagespage.js similarity index 87% rename from src/controllers/metadataimagespage.js rename to src/controllers/dashboard/metadataimagespage.js index 39b4ca6fe..42d751a24 100644 --- a/src/controllers/metadataimagespage.js +++ b/src/controllers/dashboard/metadataimagespage.js @@ -1,4 +1,4 @@ -define(["jQuery", "dom", "loading", "libraryMenu", "listViewStyle"], function($, dom, loading, libraryMenu) { +define(["jQuery", "dom", "loading", "libraryMenu", "globalize", "listViewStyle"], function($, dom, loading, libraryMenu, globalize) { "use strict"; function populateLanguages(select) { @@ -43,16 +43,16 @@ define(["jQuery", "dom", "loading", "libraryMenu", "listViewStyle"], function($, function getTabs() { return [{ href: "library.html", - name: Globalize.translate("HeaderLibraries") + name: globalize.translate("HeaderLibraries") }, { href: "librarydisplay.html", - name: Globalize.translate("TabDisplay") + name: globalize.translate("TabDisplay") }, { href: "metadataimages.html", - name: Globalize.translate("TabMetadata") + name: globalize.translate("TabMetadata") }, { href: "metadatanfo.html", - name: Globalize.translate("TabNfoSettings") + name: globalize.translate("TabNfoSettings") }]; } diff --git a/src/controllers/metadatanfo.js b/src/controllers/dashboard/metadatanfo.js similarity index 85% rename from src/controllers/metadatanfo.js rename to src/controllers/dashboard/metadatanfo.js index 20049837d..586663218 100644 --- a/src/controllers/metadatanfo.js +++ b/src/controllers/dashboard/metadatanfo.js @@ -1,8 +1,8 @@ -define(["jQuery", "loading", "libraryMenu"], function ($, loading, libraryMenu) { +define(["jQuery", "loading", "libraryMenu", "globalize"], function ($, loading, libraryMenu, globalize) { "use strict"; function loadPage(page, config, users) { - var html = '"; + var html = '"; html += users.map(function (user) { return '"; }).join(""); @@ -33,7 +33,7 @@ define(["jQuery", "loading", "libraryMenu"], function ($, loading, libraryMenu) function showConfirmMessage(config) { var msg = []; - msg.push(Globalize.translate("MetadataSettingChangeHelp")); + msg.push(globalize.translate("MetadataSettingChangeHelp")); require(["alert"], function (alert) { alert({ @@ -45,16 +45,16 @@ define(["jQuery", "loading", "libraryMenu"], function ($, loading, libraryMenu) function getTabs() { return [{ href: "library.html", - name: Globalize.translate("HeaderLibraries") + name: globalize.translate("HeaderLibraries") }, { href: "librarydisplay.html", - name: Globalize.translate("TabDisplay") + name: globalize.translate("TabDisplay") }, { href: "metadataimages.html", - name: Globalize.translate("TabMetadata") + name: globalize.translate("TabMetadata") }, { href: "metadatanfo.html", - name: Globalize.translate("TabNfoSettings") + name: globalize.translate("TabNfoSettings") }]; } diff --git a/src/controllers/playbackconfiguration.js b/src/controllers/dashboard/playbackconfiguration.js similarity index 84% rename from src/controllers/playbackconfiguration.js rename to src/controllers/dashboard/playbackconfiguration.js index cd2136cea..a4ba6bb62 100644 --- a/src/controllers/playbackconfiguration.js +++ b/src/controllers/dashboard/playbackconfiguration.js @@ -1,4 +1,4 @@ -define(["jQuery", "loading", "libraryMenu"], function ($, loading, libraryMenu) { +define(["jQuery", "loading", "libraryMenu", "globalize"], function ($, loading, libraryMenu, globalize) { "use strict"; function loadPage(page, config) { @@ -25,13 +25,13 @@ define(["jQuery", "loading", "libraryMenu"], function ($, loading, libraryMenu) function getTabs() { return [{ href: "encodingsettings.html", - name: Globalize.translate("Transcoding") + name: globalize.translate("Transcoding") }, { href: "playbackconfiguration.html", - name: Globalize.translate("TabResumeSettings") + name: globalize.translate("TabResumeSettings") }, { href: "streamingsettings.html", - name: Globalize.translate("TabStreaming") + name: globalize.translate("TabStreaming") }]; } diff --git a/src/controllers/dashboard/plugins/add.js b/src/controllers/dashboard/plugins/add.js index a05cac461..3b2bf9e76 100644 --- a/src/controllers/dashboard/plugins/add.js +++ b/src/controllers/dashboard/plugins/add.js @@ -7,8 +7,8 @@ define(["jQuery", "loading", "libraryMenu", "globalize", "connectionManager", "e for (var i = 0; i < length; i++) { var version = packageInfo.versions[i]; - html += '

' + version.versionStr + " (" + version.classification + ")

"; - html += '
' + version.description + "
"; + html += '

' + version.version + "

"; + html += '
' + version.changelog + "
"; } $("#revisionHistory", page).html(html); @@ -19,7 +19,7 @@ define(["jQuery", "loading", "libraryMenu", "globalize", "connectionManager", "e for (var i = 0; i < packageInfo.versions.length; i++) { var version = packageInfo.versions[i]; - html += '"; + html += '"; } var selectmenu = $("#selectVersion", page).html(html); @@ -28,16 +28,9 @@ define(["jQuery", "loading", "libraryMenu", "globalize", "connectionManager", "e $("#pCurrentVersion", page).hide().html(""); } - var packageVersion = packageInfo.versions.filter(function (current) { - return "Release" == current.classification; - })[0]; - packageVersion = packageVersion || packageInfo.versions.filter(function (current) { - return "Beta" == current.classification; - })[0]; - + var packageVersion = packageInfo.versions[0]; if (packageVersion) { - var val = packageVersion.versionStr + "|" + packageVersion.classification; - selectmenu.val(val); + selectmenu.val(packageVersion.version); } } @@ -45,44 +38,23 @@ define(["jQuery", "loading", "libraryMenu", "globalize", "connectionManager", "e var installedPlugin = installedPlugins.filter(function (ip) { return ip.Name == pkg.name; })[0]; + populateVersions(pkg, page, installedPlugin); populateHistory(pkg, page); + $(".pluginName", page).html(pkg.name); + $("#btnInstallDiv", page).removeClass("hide"); + $("#pSelectVersion", page).removeClass("hide"); - if ("Server" == pkg.targetSystem) { - $("#btnInstallDiv", page).removeClass("hide"); - $("#nonServerMsg", page).hide(); - $("#pSelectVersion", page).removeClass("hide"); + if (pkg.overview) { + $("#overview", page).show().html(pkg.overview); } else { - $("#btnInstallDiv", page).addClass("hide"); - $("#pSelectVersion", page).addClass("hide"); - var msg = globalize.translate("MessageInstallPluginFromApp"); - $("#nonServerMsg", page).html(msg).show(); + $("#overview", page).hide(); } - if (pkg.shortDescription) { - $("#tagline", page).show().html(pkg.shortDescription); - } else { - $("#tagline", page).hide(); - } - - $("#overview", page).html(pkg.overview || ""); + $("#description", page).html(pkg.description); $("#developer", page).html(pkg.owner); - if (pkg.richDescUrl) { - $("#pViewWebsite", page).show(); - $("#pViewWebsite a", page).attr("href", pkg.richDescUrl); - } else { - $("#pViewWebsite", page).hide(); - } - - if (pkg.previewImage || pkg.thumbImage) { - var img = pkg.previewImage ? pkg.previewImage : pkg.thumbImage; - $("#pPreviewImage", page).show().html(""); - } else { - $("#pPreviewImage", page).hide().html(""); - } - if (installedPlugin) { var currentVersionText = globalize.translate("MessageYouHaveVersionInstalled", "" + installedPlugin.Version + ""); $("#pCurrentVersion", page).show().html(currentVersionText); diff --git a/src/controllers/dashboard/plugins/available.js b/src/controllers/dashboard/plugins/available.js index adccfa393..aff9b89ed 100644 --- a/src/controllers/dashboard/plugins/available.js +++ b/src/controllers/dashboard/plugins/available.js @@ -98,21 +98,14 @@ define(["loading", "libraryMenu", "globalize", "cardStyle", "emby-button", "emby html += '
"; html += '
'; html += "
"; html += plugin.name; html += "
"; - var installedPlugin = plugin.isApp ? null : installedPlugins.filter(function (ip) { + var installedPlugin = installedPlugins.filter(function (ip) { return ip.Id == plugin.guid; })[0]; html += "
"; diff --git a/src/controllers/dashboard/plugins/installed.js b/src/controllers/dashboard/plugins/installed.js index d87413bb5..826996516 100644 --- a/src/controllers/dashboard/plugins/installed.js +++ b/src/controllers/dashboard/plugins/installed.js @@ -42,14 +42,7 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button" html += '"; html += '
'; @@ -57,7 +50,7 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button" html += ''; html += "
"; html += "
"; - html += configPage ? configPage.DisplayName || plugin.Name : plugin.Name; + html += configPage.DisplayName || plugin.Name; html += "
"; html += "
"; html += plugin.Version; diff --git a/src/controllers/serveractivity.js b/src/controllers/dashboard/serveractivity.js similarity index 100% rename from src/controllers/serveractivity.js rename to src/controllers/dashboard/serveractivity.js diff --git a/src/controllers/streamingsettings.js b/src/controllers/dashboard/streamingsettings.js similarity index 82% rename from src/controllers/streamingsettings.js rename to src/controllers/dashboard/streamingsettings.js index 14e5e028a..dcd0dcba1 100644 --- a/src/controllers/streamingsettings.js +++ b/src/controllers/dashboard/streamingsettings.js @@ -1,4 +1,4 @@ -define(["jQuery", "libraryMenu", "loading"], function ($, libraryMenu, loading) { +define(["jQuery", "libraryMenu", "loading", "globalize"], function ($, libraryMenu, loading, globalize) { "use strict"; function loadPage(page, config) { @@ -20,13 +20,13 @@ define(["jQuery", "libraryMenu", "loading"], function ($, libraryMenu, loading) function getTabs() { return [{ href: "encodingsettings.html", - name: Globalize.translate("Transcoding") + name: globalize.translate("Transcoding") }, { href: "playbackconfiguration.html", - name: Globalize.translate("TabResumeSettings") + name: globalize.translate("TabResumeSettings") }, { href: "streamingsettings.html", - name: Globalize.translate("TabStreaming") + name: globalize.translate("TabStreaming") }]; } diff --git a/src/controllers/livetvguideprovider.js b/src/controllers/livetvguideprovider.js index a58917f22..b58000adc 100644 --- a/src/controllers/livetvguideprovider.js +++ b/src/controllers/livetvguideprovider.js @@ -1,4 +1,4 @@ -define(["events", "loading"], function (events, loading) { +define(["events", "loading", "globalize"], function (events, loading, globalize) { "use strict"; function onListingsSubmitted() { @@ -17,7 +17,7 @@ define(["events", "loading"], function (events, loading) { function loadTemplate(page, type, providerId) { require(["text!./components/tvproviders/" + type + ".template.html"], function (html) { - page.querySelector(".providerTemplate").innerHTML = Globalize.translateDocument(html); + page.querySelector(".providerTemplate").innerHTML = globalize.translateDocument(html); init(page, type, providerId); }); } diff --git a/src/controllers/livetvsettings.js b/src/controllers/livetvsettings.js index 2b11071c7..e86f08ca6 100644 --- a/src/controllers/livetvsettings.js +++ b/src/controllers/livetvsettings.js @@ -1,4 +1,4 @@ -define(["jQuery", "loading", "fnchecked", "emby-button"], function ($, loading) { +define(["jQuery", "loading", "globalize", "fnchecked", "emby-button"], function ($, loading, globalize) { "use strict"; function loadPage(page, config) { @@ -44,7 +44,7 @@ define(["jQuery", "loading", "fnchecked", "emby-button"], function ($, loading) var msg = ""; if (recordingPathChanged) { - msg += Globalize.translate("RecordingPathChangeMessage"); + msg += globalize.translate("RecordingPathChangeMessage"); } if (msg) { diff --git a/src/controllers/movies/moviecollections.js b/src/controllers/movies/moviecollections.js index 84ceec6a1..4dfe23e7a 100644 --- a/src/controllers/movies/moviecollections.js +++ b/src/controllers/movies/moviecollections.js @@ -1,4 +1,4 @@ -define(["loading", "events", "libraryBrowser", "imageLoader", "listView", "cardBuilder", "userSettings", "emby-itemscontainer"], function (loading, events, libraryBrowser, imageLoader, listView, cardBuilder, userSettings) { +define(["loading", "events", "libraryBrowser", "imageLoader", "listView", "cardBuilder", "userSettings", "globalize", "emby-itemscontainer"], function (loading, events, libraryBrowser, imageLoader, listView, cardBuilder, userSettings, globalize) { "use strict"; return function (view, params, tabContent) { @@ -171,7 +171,7 @@ define(["loading", "events", "libraryBrowser", "imageLoader", "listView", "cardB } if (!result.Items.length) { - html = '

' + Globalize.translate("MessageNoCollectionsAvailable") + "

"; + html = '

' + globalize.translate("MessageNoCollectionsAvailable") + "

"; } var itemsContainer = tabContent.querySelector(".itemsContainer"); @@ -199,19 +199,19 @@ define(["loading", "events", "libraryBrowser", "imageLoader", "listView", "cardB tabContent.querySelector(".btnSort").addEventListener("click", function (e) { libraryBrowser.showSortMenu({ items: [{ - name: Globalize.translate("OptionNameSort"), + name: globalize.translate("OptionNameSort"), id: "SortName" }, { - name: Globalize.translate("OptionImdbRating"), + name: globalize.translate("OptionImdbRating"), id: "CommunityRating,SortName" }, { - name: Globalize.translate("OptionDateAdded"), + name: globalize.translate("OptionDateAdded"), id: "DateCreated,SortName" }, { - name: Globalize.translate("OptionParentalRating"), + name: globalize.translate("OptionParentalRating"), id: "OfficialRating,SortName" }, { - name: Globalize.translate("OptionReleaseDate"), + name: globalize.translate("OptionReleaseDate"), id: "PremiereDate,SortName" }], callback: function () { diff --git a/src/controllers/movies/movies.js b/src/controllers/movies/movies.js index 38985fb4d..9748da62d 100644 --- a/src/controllers/movies/movies.js +++ b/src/controllers/movies/movies.js @@ -1,4 +1,4 @@ -define(["loading", "layoutManager", "userSettings", "events", "libraryBrowser", "alphaPicker", "listView", "cardBuilder", "emby-itemscontainer"], function (loading, layoutManager, userSettings, events, libraryBrowser, alphaPicker, listView, cardBuilder) { +define(["loading", "layoutManager", "userSettings", "events", "libraryBrowser", "alphaPicker", "listView", "cardBuilder", "globalize", "emby-itemscontainer"], function (loading, layoutManager, userSettings, events, libraryBrowser, alphaPicker, listView, cardBuilder, globalize) { "use strict"; return function (view, params, tabContent, options) { @@ -191,31 +191,31 @@ define(["loading", "layoutManager", "userSettings", "events", "libraryBrowser", btnSort.addEventListener("click", function (e) { libraryBrowser.showSortMenu({ items: [{ - name: Globalize.translate("OptionNameSort"), + name: globalize.translate("OptionNameSort"), id: "SortName,ProductionYear" }, { - name: Globalize.translate("OptionImdbRating"), + name: globalize.translate("OptionImdbRating"), id: "CommunityRating,SortName,ProductionYear" }, { - name: Globalize.translate("OptionCriticRating"), + name: globalize.translate("OptionCriticRating"), id: "CriticRating,SortName,ProductionYear" }, { - name: Globalize.translate("OptionDateAdded"), + name: globalize.translate("OptionDateAdded"), id: "DateCreated,SortName,ProductionYear" }, { - name: Globalize.translate("OptionDatePlayed"), + name: globalize.translate("OptionDatePlayed"), id: "DatePlayed,SortName,ProductionYear" }, { - name: Globalize.translate("OptionParentalRating"), + name: globalize.translate("OptionParentalRating"), id: "OfficialRating,SortName,ProductionYear" }, { - name: Globalize.translate("OptionPlayCount"), + name: globalize.translate("OptionPlayCount"), id: "PlayCount,SortName,ProductionYear" }, { - name: Globalize.translate("OptionReleaseDate"), + name: globalize.translate("OptionReleaseDate"), id: "PremiereDate,SortName,ProductionYear" }, { - name: Globalize.translate("OptionRuntime"), + name: globalize.translate("OptionRuntime"), id: "Runtime,SortName,ProductionYear" }], callback: function () { diff --git a/src/controllers/movies/moviesrecommended.js b/src/controllers/movies/moviesrecommended.js index 98e087147..5f341d3e3 100644 --- a/src/controllers/movies/moviesrecommended.js +++ b/src/controllers/movies/moviesrecommended.js @@ -1,4 +1,4 @@ -define(["events", "layoutManager", "inputManager", "userSettings", "libraryMenu", "mainTabsManager", "cardBuilder", "dom", "imageLoader", "playbackManager", "emby-scroller", "emby-itemscontainer", "emby-tabs", "emby-button"], function (events, layoutManager, inputManager, userSettings, libraryMenu, mainTabsManager, cardBuilder, dom, imageLoader, playbackManager) { +define(["events", "layoutManager", "inputManager", "userSettings", "libraryMenu", "mainTabsManager", "cardBuilder", "dom", "imageLoader", "playbackManager", "globalize", "emby-scroller", "emby-itemscontainer", "emby-tabs", "emby-button"], function (events, layoutManager, inputManager, userSettings, libraryMenu, mainTabsManager, cardBuilder, dom, imageLoader, playbackManager, globalize) { "use strict"; function enableScrollX() { @@ -91,21 +91,21 @@ define(["events", "layoutManager", "inputManager", "userSettings", "libraryMenu" switch (recommendation.RecommendationType) { case "SimilarToRecentlyPlayed": - title = Globalize.translate("RecommendationBecauseYouWatched", recommendation.BaselineItemName); + title = globalize.translate("RecommendationBecauseYouWatched", recommendation.BaselineItemName); break; case "SimilarToLikedItem": - title = Globalize.translate("RecommendationBecauseYouLike", recommendation.BaselineItemName); + title = globalize.translate("RecommendationBecauseYouLike", recommendation.BaselineItemName); break; case "HasDirectorFromRecentlyPlayed": case "HasLikedDirector": - title = Globalize.translate("RecommendationDirectedBy", recommendation.BaselineItemName); + title = globalize.translate("RecommendationDirectedBy", recommendation.BaselineItemName); break; case "HasActorFromRecentlyPlayed": case "HasLikedActor": - title = Globalize.translate("RecommendationStarring", recommendation.BaselineItemName); + title = globalize.translate("RecommendationStarring", recommendation.BaselineItemName); break; } @@ -211,19 +211,19 @@ define(["events", "layoutManager", "inputManager", "userSettings", "libraryMenu" function getTabs() { return [{ - name: Globalize.translate("Movies") + name: globalize.translate("Movies") }, { - name: Globalize.translate("TabSuggestions") + name: globalize.translate("TabSuggestions") }, { - name: Globalize.translate("TabTrailers") + name: globalize.translate("TabTrailers") }, { - name: Globalize.translate("TabFavorites") + name: globalize.translate("TabFavorites") }, { - name: Globalize.translate("TabCollections") + name: globalize.translate("TabCollections") }, { - name: Globalize.translate("TabGenres") + name: globalize.translate("TabGenres") }, { - name: Globalize.translate("ButtonSearch"), + name: globalize.translate("ButtonSearch"), cssClass: "searchTabButton" }]; } @@ -398,8 +398,8 @@ define(["events", "layoutManager", "inputManager", "userSettings", "libraryMenu" libraryMenu.setTitle(item.Name); }); } else { - view.setAttribute("data-title", Globalize.translate("TabMovies")); - libraryMenu.setTitle(Globalize.translate("TabMovies")); + view.setAttribute("data-title", globalize.translate("TabMovies")); + libraryMenu.setTitle(globalize.translate("TabMovies")); } } diff --git a/src/controllers/movies/movietrailers.js b/src/controllers/movies/movietrailers.js index e839d29b1..590b204b2 100644 --- a/src/controllers/movies/movietrailers.js +++ b/src/controllers/movies/movietrailers.js @@ -1,4 +1,4 @@ -define(["layoutManager", "loading", "events", "libraryBrowser", "imageLoader", "alphaPicker", "listView", "cardBuilder", "userSettings", "emby-itemscontainer"], function (layoutManager, loading, events, libraryBrowser, imageLoader, alphaPicker, listView, cardBuilder, userSettings) { +define(["layoutManager", "loading", "events", "libraryBrowser", "imageLoader", "alphaPicker", "listView", "cardBuilder", "userSettings", "globalize", "emby-itemscontainer"], function (layoutManager, loading, events, libraryBrowser, imageLoader, alphaPicker, listView, cardBuilder, userSettings, globalize) { "use strict"; return function (view, params, tabContent) { @@ -158,7 +158,7 @@ define(["layoutManager", "loading", "events", "libraryBrowser", "imageLoader", " } if (!result.Items.length) { - html = '

' + Globalize.translate("MessageNoTrailersFound") + "

"; + html = '

' + globalize.translate("MessageNoTrailersFound") + "

"; } var itemsContainer = tabContent.querySelector(".itemsContainer"); @@ -223,25 +223,25 @@ define(["layoutManager", "loading", "events", "libraryBrowser", "imageLoader", " tabContent.querySelector(".btnSort").addEventListener("click", function (e) { libraryBrowser.showSortMenu({ items: [{ - name: Globalize.translate("OptionNameSort"), + name: globalize.translate("OptionNameSort"), id: "SortName" }, { - name: Globalize.translate("OptionImdbRating"), + name: globalize.translate("OptionImdbRating"), id: "CommunityRating,SortName" }, { - name: Globalize.translate("OptionDateAdded"), + name: globalize.translate("OptionDateAdded"), id: "DateCreated,SortName" }, { - name: Globalize.translate("OptionDatePlayed"), + name: globalize.translate("OptionDatePlayed"), id: "DatePlayed,SortName" }, { - name: Globalize.translate("OptionParentalRating"), + name: globalize.translate("OptionParentalRating"), id: "OfficialRating,SortName" }, { - name: Globalize.translate("OptionPlayCount"), + name: globalize.translate("OptionPlayCount"), id: "PlayCount,SortName" }, { - name: Globalize.translate("OptionReleaseDate"), + name: globalize.translate("OptionReleaseDate"), id: "PremiereDate,SortName" }], callback: function () { diff --git a/src/controllers/music/musicalbums.js b/src/controllers/music/musicalbums.js index a3c362d35..580f30bce 100644 --- a/src/controllers/music/musicalbums.js +++ b/src/controllers/music/musicalbums.js @@ -1,4 +1,4 @@ -define(["layoutManager", "playbackManager", "loading", "events", "libraryBrowser", "imageLoader", "alphaPicker", "listView", "cardBuilder", "userSettings", "emby-itemscontainer"], function (layoutManager, playbackManager, loading, events, libraryBrowser, imageLoader, alphaPicker, listView, cardBuilder, userSettings) { +define(["layoutManager", "playbackManager", "loading", "events", "libraryBrowser", "imageLoader", "alphaPicker", "listView", "cardBuilder", "userSettings", "globalize", "emby-itemscontainer"], function (layoutManager, playbackManager, loading, events, libraryBrowser, imageLoader, alphaPicker, listView, cardBuilder, userSettings, globalize) { "use strict"; return function (view, params, tabContent) { @@ -230,25 +230,25 @@ define(["layoutManager", "playbackManager", "loading", "events", "libraryBrowser tabContent.querySelector(".btnSort").addEventListener("click", function (e) { libraryBrowser.showSortMenu({ items: [{ - name: Globalize.translate("OptionNameSort"), + name: globalize.translate("OptionNameSort"), id: "SortName" }, { - name: Globalize.translate("OptionAlbumArtist"), + name: globalize.translate("OptionAlbumArtist"), id: "AlbumArtist,SortName" }, { - name: Globalize.translate("OptionCommunityRating"), + name: globalize.translate("OptionCommunityRating"), id: "CommunityRating,SortName" }, { - name: Globalize.translate("OptionCriticRating"), + name: globalize.translate("OptionCriticRating"), id: "CriticRating,SortName" }, { - name: Globalize.translate("OptionDateAdded"), + name: globalize.translate("OptionDateAdded"), id: "DateCreated,SortName" }, { - name: Globalize.translate("OptionReleaseDate"), + name: globalize.translate("OptionReleaseDate"), id: "ProductionYear,PremiereDate,SortName" }, { - name: Globalize.translate("OptionRandom"), + name: globalize.translate("OptionRandom"), id: "Random,SortName" }], callback: function () { diff --git a/src/controllers/music/musicrecommended.js b/src/controllers/music/musicrecommended.js index 8b87dff26..14a231a34 100644 --- a/src/controllers/music/musicrecommended.js +++ b/src/controllers/music/musicrecommended.js @@ -1,4 +1,4 @@ -define(["browser", "layoutManager", "userSettings", "inputManager", "loading", "cardBuilder", "dom", "apphost", "imageLoader", "libraryMenu", "playbackManager", "mainTabsManager", "scrollStyles", "emby-itemscontainer", "emby-tabs", "emby-button", "flexStyles"], function (browser, layoutManager, userSettings, inputManager, loading, cardBuilder, dom, appHost, imageLoader, libraryMenu, playbackManager, mainTabsManager) { +define(["browser", "layoutManager", "userSettings", "inputManager", "loading", "cardBuilder", "dom", "apphost", "imageLoader", "libraryMenu", "playbackManager", "mainTabsManager", "globalize", "scrollStyles", "emby-itemscontainer", "emby-tabs", "emby-button", "flexStyles"], function (browser, layoutManager, userSettings, inputManager, loading, cardBuilder, dom, appHost, imageLoader, libraryMenu, playbackManager, mainTabsManager, globalize) { "use strict"; function itemsPerRow() { @@ -167,21 +167,21 @@ define(["browser", "layoutManager", "userSettings", "inputManager", "loading", " function getTabs() { return [{ - name: Globalize.translate("TabSuggestions") + name: globalize.translate("TabSuggestions") }, { - name: Globalize.translate("TabAlbums") + name: globalize.translate("TabAlbums") }, { - name: Globalize.translate("TabAlbumArtists") + name: globalize.translate("TabAlbumArtists") }, { - name: Globalize.translate("TabArtists") + name: globalize.translate("TabArtists") }, { - name: Globalize.translate("TabPlaylists") + name: globalize.translate("TabPlaylists") }, { - name: Globalize.translate("TabSongs") + name: globalize.translate("TabSongs") }, { - name: Globalize.translate("TabGenres") + name: globalize.translate("TabGenres") }, { - name: Globalize.translate("ButtonSearch"), + name: globalize.translate("ButtonSearch"), cssClass: "searchTabButton" }]; } @@ -388,8 +388,8 @@ define(["browser", "layoutManager", "userSettings", "inputManager", "loading", " libraryMenu.setTitle(item.Name); }); } else { - view.setAttribute("data-title", Globalize.translate("TabMusic")); - libraryMenu.setTitle(Globalize.translate("TabMusic")); + view.setAttribute("data-title", globalize.translate("TabMusic")); + libraryMenu.setTitle(globalize.translate("TabMusic")); } } diff --git a/src/controllers/music/songs.js b/src/controllers/music/songs.js index aaa71395e..29d21b077 100644 --- a/src/controllers/music/songs.js +++ b/src/controllers/music/songs.js @@ -1,4 +1,4 @@ -define(["events", "libraryBrowser", "imageLoader", "listView", "loading", "userSettings", "emby-itemscontainer"], function (events, libraryBrowser, imageLoader, listView, loading, userSettings) { +define(["events", "libraryBrowser", "imageLoader", "listView", "loading", "userSettings", "globalize", "emby-itemscontainer"], function (events, libraryBrowser, imageLoader, listView, loading, userSettings, globalize) { "use strict"; return function (view, params, tabContent) { @@ -149,31 +149,31 @@ define(["events", "libraryBrowser", "imageLoader", "listView", "loading", "userS tabContent.querySelector(".btnSort").addEventListener("click", function (e) { libraryBrowser.showSortMenu({ items: [{ - name: Globalize.translate("OptionTrackName"), + name: globalize.translate("OptionTrackName"), id: "Name" }, { - name: Globalize.translate("OptionAlbum"), + name: globalize.translate("OptionAlbum"), id: "Album,SortName" }, { - name: Globalize.translate("OptionAlbumArtist"), + name: globalize.translate("OptionAlbumArtist"), id: "AlbumArtist,Album,SortName" }, { - name: Globalize.translate("OptionArtist"), + name: globalize.translate("OptionArtist"), id: "Artist,Album,SortName" }, { - name: Globalize.translate("OptionDateAdded"), + name: globalize.translate("OptionDateAdded"), id: "DateCreated,SortName" }, { - name: Globalize.translate("OptionDatePlayed"), + name: globalize.translate("OptionDatePlayed"), id: "DatePlayed,SortName" }, { - name: Globalize.translate("OptionPlayCount"), + name: globalize.translate("OptionPlayCount"), id: "PlayCount,SortName" }, { - name: Globalize.translate("OptionReleaseDate"), + name: globalize.translate("OptionReleaseDate"), id: "PremiereDate,AlbumArtist,Album,SortName" }, { - name: Globalize.translate("OptionRuntime"), + name: globalize.translate("OptionRuntime"), id: "Runtime,AlbumArtist,Album,SortName" }], callback: function () { diff --git a/src/controllers/shows/episodes.js b/src/controllers/shows/episodes.js index 792eab88a..bd7823d40 100644 --- a/src/controllers/shows/episodes.js +++ b/src/controllers/shows/episodes.js @@ -1,4 +1,4 @@ -define(["loading", "events", "libraryBrowser", "imageLoader", "listView", "cardBuilder", "userSettings", "emby-itemscontainer"], function (loading, events, libraryBrowser, imageLoader, listView, cardBuilder, userSettings) { +define(["loading", "events", "libraryBrowser", "imageLoader", "listView", "cardBuilder", "userSettings", "globalize", "emby-itemscontainer"], function (loading, events, libraryBrowser, imageLoader, listView, cardBuilder, userSettings, globalize) { "use strict"; return function (view, params, tabContent) { @@ -188,28 +188,28 @@ define(["loading", "events", "libraryBrowser", "imageLoader", "listView", "cardB tabContent.querySelector(".btnSort").addEventListener("click", function (e) { libraryBrowser.showSortMenu({ items: [{ - name: Globalize.translate("OptionNameSort"), + name: globalize.translate("OptionNameSort"), id: "SeriesSortName,SortName" }, { - name: Globalize.translate("OptionTvdbRating"), + name: globalize.translate("OptionTvdbRating"), id: "CommunityRating,SeriesSortName,SortName" }, { - name: Globalize.translate("OptionDateAdded"), + name: globalize.translate("OptionDateAdded"), id: "DateCreated,SeriesSortName,SortName" }, { - name: Globalize.translate("OptionPremiereDate"), + name: globalize.translate("OptionPremiereDate"), id: "PremiereDate,SeriesSortName,SortName" }, { - name: Globalize.translate("OptionDatePlayed"), + name: globalize.translate("OptionDatePlayed"), id: "DatePlayed,SeriesSortName,SortName" }, { - name: Globalize.translate("OptionParentalRating"), + name: globalize.translate("OptionParentalRating"), id: "OfficialRating,SeriesSortName,SortName" }, { - name: Globalize.translate("OptionPlayCount"), + name: globalize.translate("OptionPlayCount"), id: "PlayCount,SeriesSortName,SortName" }, { - name: Globalize.translate("OptionRuntime"), + name: globalize.translate("OptionRuntime"), id: "Runtime,SeriesSortName,SortName" }], callback: function () { diff --git a/src/controllers/shows/tvrecommended.js b/src/controllers/shows/tvrecommended.js index d1adb0434..4427d3fa7 100644 --- a/src/controllers/shows/tvrecommended.js +++ b/src/controllers/shows/tvrecommended.js @@ -1,23 +1,23 @@ -define(["events", "inputManager", "libraryMenu", "layoutManager", "loading", "dom", "userSettings", "cardBuilder", "playbackManager", "mainTabsManager", "scrollStyles", "emby-itemscontainer", "emby-button"], function (events, inputManager, libraryMenu, layoutManager, loading, dom, userSettings, cardBuilder, playbackManager, mainTabsManager) { +define(["events", "inputManager", "libraryMenu", "layoutManager", "loading", "dom", "userSettings", "cardBuilder", "playbackManager", "mainTabsManager", "globalize", "scrollStyles", "emby-itemscontainer", "emby-button"], function (events, inputManager, libraryMenu, layoutManager, loading, dom, userSettings, cardBuilder, playbackManager, mainTabsManager, globalize) { "use strict"; function getTabs() { return [{ - name: Globalize.translate("TabShows") + name: globalize.translate("TabShows") }, { - name: Globalize.translate("TabSuggestions") + name: globalize.translate("TabSuggestions") }, { - name: Globalize.translate("TabLatest") + name: globalize.translate("TabLatest") }, { - name: Globalize.translate("TabUpcoming") + name: globalize.translate("TabUpcoming") }, { - name: Globalize.translate("TabGenres") + name: globalize.translate("TabGenres") }, { - name: Globalize.translate("TabNetworks") + name: globalize.translate("TabNetworks") }, { - name: Globalize.translate("TabEpisodes") + name: globalize.translate("TabEpisodes") }, { - name: Globalize.translate("ButtonSearch"), + name: globalize.translate("ButtonSearch"), cssClass: "searchTabButton" }]; } @@ -314,8 +314,8 @@ define(["events", "inputManager", "libraryMenu", "layoutManager", "loading", "do libraryMenu.setTitle(item.Name); }); } else { - view.setAttribute("data-title", Globalize.translate("TabShows")); - libraryMenu.setTitle(Globalize.translate("TabShows")); + view.setAttribute("data-title", globalize.translate("TabShows")); + libraryMenu.setTitle(globalize.translate("TabShows")); } } diff --git a/src/controllers/shows/tvshows.js b/src/controllers/shows/tvshows.js index 95d027d77..0f992fe8d 100644 --- a/src/controllers/shows/tvshows.js +++ b/src/controllers/shows/tvshows.js @@ -1,4 +1,4 @@ -define(["layoutManager", "loading", "events", "libraryBrowser", "imageLoader", "listView", "cardBuilder", "alphaPicker", "userSettings", "emby-itemscontainer"], function (layoutManager, loading, events, libraryBrowser, imageLoader, listView, cardBuilder, alphaPicker, userSettings) { +define(["layoutManager", "loading", "events", "libraryBrowser", "imageLoader", "listView", "cardBuilder", "alphaPicker", "userSettings", "globalize", "emby-itemscontainer"], function (layoutManager, loading, events, libraryBrowser, imageLoader, listView, cardBuilder, alphaPicker, userSettings, globalize) { "use strict"; return function (view, params, tabContent) { @@ -241,22 +241,22 @@ define(["layoutManager", "loading", "events", "libraryBrowser", "imageLoader", " tabContent.querySelector(".btnSort").addEventListener("click", function (e) { libraryBrowser.showSortMenu({ items: [{ - name: Globalize.translate("OptionNameSort"), + name: globalize.translate("OptionNameSort"), id: "SortName" }, { - name: Globalize.translate("OptionImdbRating"), + name: globalize.translate("OptionImdbRating"), id: "CommunityRating,SortName" }, { - name: Globalize.translate("OptionDateAdded"), + name: globalize.translate("OptionDateAdded"), id: "DateCreated,SortName" }, { - name: Globalize.translate("OptionDatePlayed"), + name: globalize.translate("OptionDatePlayed"), id: "DatePlayed,SortName" }, { - name: Globalize.translate("OptionParentalRating"), + name: globalize.translate("OptionParentalRating"), id: "OfficialRating,SortName" }, { - name: Globalize.translate("OptionReleaseDate"), + name: globalize.translate("OptionReleaseDate"), id: "PremiereDate,SortName" }], callback: function () { diff --git a/src/controllers/shows/tvupcoming.js b/src/controllers/shows/tvupcoming.js index 249d932d3..816717edf 100644 --- a/src/controllers/shows/tvupcoming.js +++ b/src/controllers/shows/tvupcoming.js @@ -1,4 +1,4 @@ -define(["layoutManager", "loading", "datetime", "libraryBrowser", "cardBuilder", "apphost", "imageLoader", "scrollStyles", "emby-itemscontainer"], function (layoutManager, loading, datetime, libraryBrowser, cardBuilder, appHost, imageLoader) { +define(["layoutManager", "loading", "datetime", "libraryBrowser", "cardBuilder", "apphost", "imageLoader", "globalize", "scrollStyles", "emby-itemscontainer"], function (layoutManager, loading, datetime, libraryBrowser, cardBuilder, appHost, imageLoader, globalize) { "use strict"; function getUpcomingPromise(context, params) { @@ -52,7 +52,7 @@ define(["layoutManager", "loading", "datetime", "libraryBrowser", "cardBuilder", if (item.PremiereDate) { try { var premiereDate = datetime.parseISO8601Date(item.PremiereDate, true); - dateText = datetime.isRelativeDay(premiereDate, -1) ? Globalize.translate("Yesterday") : datetime.toLocaleDateString(premiereDate, { + dateText = datetime.isRelativeDay(premiereDate, -1) ? globalize.translate("Yesterday") : datetime.toLocaleDateString(premiereDate, { weekday: "long", month: "short", day: "numeric" diff --git a/src/controllers/user/profile.js b/src/controllers/user/profile.js index 3b85cb1d8..d0ff4edd0 100644 --- a/src/controllers/user/profile.js +++ b/src/controllers/user/profile.js @@ -1,4 +1,4 @@ -define(["controllers/userpasswordpage", "loading", "libraryMenu", "apphost", "emby-button"], function (UserPasswordPage, loading, libraryMenu, appHost) { +define(["controllers/userpasswordpage", "loading", "libraryMenu", "apphost", "globalize", "emby-button"], function (UserPasswordPage, loading, libraryMenu, appHost, globalize) { "use strict"; function reloadUser(page) { @@ -37,7 +37,7 @@ define(["controllers/userpasswordpage", "loading", "libraryMenu", "apphost", "em switch (evt.target.error.code) { case evt.target.error.NOT_FOUND_ERR: require(["toast"], function (toast) { - toast(Globalize.translate("FileNotFound")); + toast(globalize.translate("FileNotFound")); }); break; case evt.target.error.ABORT_ERR: @@ -46,7 +46,7 @@ define(["controllers/userpasswordpage", "loading", "libraryMenu", "apphost", "em case evt.target.error.NOT_READABLE_ERR: default: require(["toast"], function (toast) { - toast(Globalize.translate("FileReadError")); + toast(globalize.translate("FileReadError")); }); } } @@ -54,7 +54,7 @@ define(["controllers/userpasswordpage", "loading", "libraryMenu", "apphost", "em function onFileReaderAbort(evt) { loading.hide(); require(["toast"], function (toast) { - toast(Globalize.translate("FileReadCancelled")); + toast(globalize.translate("FileReadCancelled")); }); } @@ -86,7 +86,7 @@ define(["controllers/userpasswordpage", "loading", "libraryMenu", "apphost", "em new UserPasswordPage(view, params); view.querySelector("#btnDeleteImage").addEventListener("click", function () { require(["confirm"], function (confirm) { - confirm(Globalize.translate("DeleteImageConfirmation"), Globalize.translate("DeleteImage")).then(function () { + confirm(globalize.translate("DeleteImageConfirmation"), globalize.translate("DeleteImage")).then(function () { loading.show(); var userId = getParameterByName("userId"); ApiClient.deleteUserImage(userId, "primary").then(function () { diff --git a/src/controllers/useredit.js b/src/controllers/useredit.js index f6a5aaf00..45a8798e4 100644 --- a/src/controllers/useredit.js +++ b/src/controllers/useredit.js @@ -1,4 +1,4 @@ -define(["jQuery", "loading", "libraryMenu", "fnchecked"], function ($, loading, libraryMenu) { +define(["jQuery", "loading", "libraryMenu", "globalize", "fnchecked"], function ($, loading, libraryMenu, globalize) { "use strict"; function loadDeleteFolders(page, user, mediaFolders) { @@ -112,7 +112,7 @@ define(["jQuery", "loading", "libraryMenu", "fnchecked"], function ($, loading, loading.hide(); require(["toast"], function (toast) { - toast(Globalize.translate("SettingsSaved")); + toast(globalize.translate("SettingsSaved")); }); } @@ -176,7 +176,7 @@ define(["jQuery", "loading", "libraryMenu", "fnchecked"], function ($, loading, var currentUser; $(document).on("pageinit", "#editUserPage", function () { $(".editUserProfileForm").off("submit", onSubmit).on("submit", onSubmit); - this.querySelector(".sharingHelp").innerHTML = Globalize.translate("OptionAllowLinkSharingHelp", 30); + this.querySelector(".sharingHelp").innerHTML = globalize.translate("OptionAllowLinkSharingHelp", 30); var page = this; $("#chkEnableDeleteAllFolders", this).on("change", function () { if (this.checked) { diff --git a/src/controllers/userlibraryaccess.js b/src/controllers/userlibraryaccess.js index 38418f519..0965e9189 100644 --- a/src/controllers/userlibraryaccess.js +++ b/src/controllers/userlibraryaccess.js @@ -1,4 +1,4 @@ -define(["jQuery", "loading", "libraryMenu", "fnchecked"], function ($, loading, libraryMenu) { +define(["jQuery", "loading", "libraryMenu", "globalize", "fnchecked"], function ($, loading, libraryMenu, globalize) { "use strict"; function triggerChange(select) { @@ -9,7 +9,7 @@ define(["jQuery", "loading", "libraryMenu", "fnchecked"], function ($, loading, function loadMediaFolders(page, user, mediaFolders) { var html = ""; - html += '

' + Globalize.translate("HeaderLibraries") + "

"; + html += '

' + globalize.translate("HeaderLibraries") + "

"; html += '
'; for (var i = 0, length = mediaFolders.length; i < length; i++) { @@ -28,7 +28,7 @@ define(["jQuery", "loading", "libraryMenu", "fnchecked"], function ($, loading, function loadChannels(page, user, channels) { var html = ""; - html += '

' + Globalize.translate("HeaderChannels") + "

"; + html += '

' + globalize.translate("HeaderChannels") + "

"; html += '
'; for (var i = 0, length = channels.length; i < length; i++) { @@ -52,7 +52,7 @@ define(["jQuery", "loading", "libraryMenu", "fnchecked"], function ($, loading, function loadDevices(page, user, devices) { var html = ""; - html += '

' + Globalize.translate("HeaderDevices") + "

"; + html += '

' + globalize.translate("HeaderDevices") + "

"; html += '
'; for (var i = 0, length = devices.length; i < length; i++) { @@ -85,7 +85,7 @@ define(["jQuery", "loading", "libraryMenu", "fnchecked"], function ($, loading, loading.hide(); require(["toast"], function (toast) { - toast(Globalize.translate("SettingsSaved")); + toast(globalize.translate("SettingsSaved")); }); } diff --git a/src/controllers/usernew.js b/src/controllers/usernew.js index ec80679f8..b93d1d662 100644 --- a/src/controllers/usernew.js +++ b/src/controllers/usernew.js @@ -1,9 +1,9 @@ -define(["jQuery", "loading", "fnchecked", "emby-checkbox"], function ($, loading) { +define(["jQuery", "loading", "globalize", "fnchecked", "emby-checkbox"], function ($, loading, globalize) { "use strict"; function loadMediaFolders(page, mediaFolders) { var html = ""; - html += '

' + Globalize.translate("HeaderLibraries") + "

"; + html += '

' + globalize.translate("HeaderLibraries") + "

"; html += '
'; for (var i = 0; i < mediaFolders.length; i++) { @@ -18,7 +18,7 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox"], function ($, loading function loadChannels(page, channels) { var html = ""; - html += '

' + Globalize.translate("HeaderChannels") + "

"; + html += '

' + globalize.translate("HeaderChannels") + "

"; html += '
'; for (var i = 0; i < channels.length; i++) { @@ -85,7 +85,7 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox"], function ($, loading }); }, function (response) { require(["toast"], function (toast) { - toast(Globalize.translate("DefaultErrorMessage")); + toast(globalize.translate("DefaultErrorMessage")); }); loading.hide(); diff --git a/src/controllers/userparentalcontrol.js b/src/controllers/userparentalcontrol.js index 333c09f26..54f5a8a94 100644 --- a/src/controllers/userparentalcontrol.js +++ b/src/controllers/userparentalcontrol.js @@ -1,4 +1,4 @@ -define(["jQuery", "datetime", "loading", "libraryMenu", "listViewStyle", "paper-icon-button-light"], function ($, datetime, loading, libraryMenu) { +define(["jQuery", "datetime", "loading", "libraryMenu", "globalize", "listViewStyle", "paper-icon-button-light"], function ($, datetime, loading, libraryMenu, globalize) { "use strict"; function populateRatings(allParentalRatings, page) { @@ -35,29 +35,29 @@ define(["jQuery", "datetime", "loading", "libraryMenu", "listViewStyle", "paper- function loadUnratedItems(page, user) { var items = [{ - name: Globalize.translate("OptionBlockBooks"), + name: globalize.translate("OptionBlockBooks"), value: "Book" }, { - name: Globalize.translate("OptionBlockChannelContent"), + name: globalize.translate("OptionBlockChannelContent"), value: "ChannelContent" }, { - name: Globalize.translate("OptionBlockLiveTvChannels"), + name: globalize.translate("OptionBlockLiveTvChannels"), value: "LiveTvChannel" }, { - name: Globalize.translate("OptionBlockMovies"), + name: globalize.translate("OptionBlockMovies"), value: "Movie" }, { - name: Globalize.translate("OptionBlockMusic"), + name: globalize.translate("OptionBlockMusic"), value: "Music" }, { - name: Globalize.translate("OptionBlockTrailers"), + name: globalize.translate("OptionBlockTrailers"), value: "Trailer" }, { - name: Globalize.translate("OptionBlockTvShows"), + name: globalize.translate("OptionBlockTvShows"), value: "Series" }]; var html = ""; - html += '

' + Globalize.translate("HeaderBlockItemsWithNoRating") + "

"; + html += '

' + globalize.translate("HeaderBlockItemsWithNoRating") + "

"; html += '
'; for (var i = 0, length = items.length; i < length; i++) { @@ -139,7 +139,7 @@ define(["jQuery", "datetime", "loading", "libraryMenu", "listViewStyle", "paper- itemHtml += '
'; itemHtml += '
'; itemHtml += '

'; - itemHtml += Globalize.translate("Option" + a.DayOfWeek); + itemHtml += globalize.translate("Option" + a.DayOfWeek); itemHtml += "

"; itemHtml += '
' + getDisplayTime(a.StartHour) + " - " + getDisplayTime(a.EndHour) + "
"; itemHtml += "
"; @@ -159,7 +159,7 @@ define(["jQuery", "datetime", "loading", "libraryMenu", "listViewStyle", "paper- loading.hide(); require(["toast"], function (toast) { - toast(Globalize.translate("SettingsSaved")); + toast(globalize.translate("SettingsSaved")); }); } @@ -226,7 +226,7 @@ define(["jQuery", "datetime", "loading", "libraryMenu", "listViewStyle", "paper- function showBlockedTagPopup(page) { require(["prompt"], function (prompt) { prompt({ - label: Globalize.translate("LabelTag") + label: globalize.translate("LabelTag") }).then(function (value) { var tags = getBlockedTagsFromPage(page); diff --git a/src/controllers/userpasswordpage.js b/src/controllers/userpasswordpage.js index eeb9b25e3..8ceb46c5e 100644 --- a/src/controllers/userpasswordpage.js +++ b/src/controllers/userpasswordpage.js @@ -1,4 +1,4 @@ -define(["loading", "libraryMenu", "emby-button"], function (loading, libraryMenu) { +define(["loading", "libraryMenu", "globalize", "emby-button"], function (loading, libraryMenu, globalize) { "use strict"; function loadUser(page, params) { @@ -79,7 +79,7 @@ define(["loading", "libraryMenu", "emby-button"], function (loading, libraryMenu loading.hide(); require(["toast"], function (toast) { - toast(Globalize.translate("MessageSettingsSaved")); + toast(globalize.translate("MessageSettingsSaved")); }); loadUser(view, params); @@ -102,15 +102,15 @@ define(["loading", "libraryMenu", "emby-button"], function (loading, libraryMenu loading.hide(); require(["toast"], function (toast) { - toast(Globalize.translate("PasswordSaved")); + toast(globalize.translate("PasswordSaved")); }); loadUser(view, params); }, function () { loading.hide(); Dashboard.alert({ - title: Globalize.translate("HeaderLoginFailure"), - message: Globalize.translate("MessageInvalidUser") + title: globalize.translate("HeaderLoginFailure"), + message: globalize.translate("MessageInvalidUser") }); }); } @@ -120,7 +120,7 @@ define(["loading", "libraryMenu", "emby-button"], function (loading, libraryMenu if (form.querySelector("#txtNewPassword").value != form.querySelector("#txtNewPasswordConfirm").value) { require(["toast"], function (toast) { - toast(Globalize.translate("PasswordMatchError")); + toast(globalize.translate("PasswordMatchError")); }); } else { loading.show(); @@ -139,17 +139,17 @@ define(["loading", "libraryMenu", "emby-button"], function (loading, libraryMenu } function resetPassword() { - var msg = Globalize.translate("PasswordResetConfirmation"); + var msg = globalize.translate("PasswordResetConfirmation"); require(["confirm"], function (confirm) { - confirm(msg, Globalize.translate("PasswordResetHeader")).then(function () { + confirm(msg, globalize.translate("PasswordResetHeader")).then(function () { var userId = params.userId; loading.show(); ApiClient.resetUserPassword(userId).then(function () { loading.hide(); Dashboard.alert({ - message: Globalize.translate("PasswordResetComplete"), - title: Globalize.translate("PasswordResetHeader") + message: globalize.translate("PasswordResetComplete"), + title: globalize.translate("PasswordResetHeader") }); loadUser(view, params); }); @@ -158,17 +158,17 @@ define(["loading", "libraryMenu", "emby-button"], function (loading, libraryMenu } function resetEasyPassword() { - var msg = Globalize.translate("PinCodeResetConfirmation"); + var msg = globalize.translate("PinCodeResetConfirmation"); require(["confirm"], function (confirm) { - confirm(msg, Globalize.translate("HeaderPinCodeReset")).then(function () { + confirm(msg, globalize.translate("HeaderPinCodeReset")).then(function () { var userId = params.userId; loading.show(); ApiClient.resetEasyPassword(userId).then(function () { loading.hide(); Dashboard.alert({ - message: Globalize.translate("PinCodeResetComplete"), - title: Globalize.translate("HeaderPinCodeReset") + message: globalize.translate("PinCodeResetComplete"), + title: globalize.translate("HeaderPinCodeReset") }); loadUser(view, params); }); diff --git a/src/controllers/wizard/user.js b/src/controllers/wizard/user.js index 270953b24..32f2bf933 100644 --- a/src/controllers/wizard/user.js +++ b/src/controllers/wizard/user.js @@ -33,7 +33,7 @@ define(["loading", "globalize", "dashboardcss", "emby-input", "emby-button", "em if (form.querySelector("#txtManualPassword").value != form.querySelector("#txtPasswordConfirm").value) { require(["toast"], function (toast) { - toast(Globalize.translate("PasswordMatchError")); + toast(globalize.translate("PasswordMatchError")); }); } else { submit(form); diff --git a/src/elements/emby-button/emby-button.css b/src/elements/emby-button/emby-button.css index a19ce571e..b3ee4db15 100644 --- a/src/elements/emby-button/emby-button.css +++ b/src/elements/emby-button/emby-button.css @@ -49,6 +49,7 @@ .button-link { background: transparent; + cursor: pointer; margin: 0; padding: 0; vertical-align: initial; diff --git a/src/components/polyfills/focusPreventScroll.js b/src/legacy/focusPreventScroll.js similarity index 100% rename from src/components/polyfills/focusPreventScroll.js rename to src/legacy/focusPreventScroll.js diff --git a/src/components/navdrawer/navdrawer.css b/src/libraries/navdrawer/navdrawer.css similarity index 100% rename from src/components/navdrawer/navdrawer.css rename to src/libraries/navdrawer/navdrawer.css diff --git a/src/components/navdrawer/navdrawer.js b/src/libraries/navdrawer/navdrawer.js similarity index 100% rename from src/components/navdrawer/navdrawer.js rename to src/libraries/navdrawer/navdrawer.js diff --git a/src/components/screensavermanager.js b/src/libraries/screensavermanager.js similarity index 100% rename from src/components/screensavermanager.js rename to src/libraries/screensavermanager.js diff --git a/src/components/scroller.js b/src/libraries/scroller.js similarity index 100% rename from src/components/scroller.js rename to src/libraries/scroller.js diff --git a/src/components/visibleinviewport.js b/src/libraries/visibleinviewport.js similarity index 100% rename from src/components/visibleinviewport.js rename to src/libraries/visibleinviewport.js diff --git a/src/nowplaying.html b/src/nowplaying.html index 0f34e5ba3..6eaf0252f 100644 --- a/src/nowplaying.html +++ b/src/nowplaying.html @@ -26,9 +26,9 @@
-
+
-
+
"; + html += '"; html += "
"; html += '
'; html += "
"; diff --git a/src/components/input/keyboardnavigation.js b/src/scripts/keyboardnavigation.js similarity index 98% rename from src/components/input/keyboardnavigation.js rename to src/scripts/keyboardnavigation.js index 3c80063f4..a95b750b1 100644 --- a/src/components/input/keyboardnavigation.js +++ b/src/scripts/keyboardnavigation.js @@ -155,7 +155,7 @@ export function enable() { function attachGamepadScript(e) { console.log("Gamepad connected! Attaching gamepadtokey.js script"); window.removeEventListener("gamepadconnected", attachGamepadScript); - require(["components/input/gamepadtokey"]); + require(["scripts/gamepadtokey"]); } // No need to check for gamepads manually at load time, the eventhandler will be fired for that diff --git a/src/scripts/librarybrowser.js b/src/scripts/librarybrowser.js index bc8908fe6..9f8ec00ad 100644 --- a/src/scripts/librarybrowser.js +++ b/src/scripts/librarybrowser.js @@ -1,4 +1,4 @@ -define(["userSettings"], function (userSettings) { +define(["userSettings", "globalize"], function (userSettings, globalize) { "use strict"; var libraryBrowser = { @@ -45,7 +45,7 @@ define(["userSettings"], function (userSettings) { var menuItems = views.map(function (v) { return { - name: Globalize.translate("Option" + v), + name: globalize.translate("Option" + v), id: v, selected: currentLayout == v }; @@ -83,7 +83,7 @@ define(["userSettings"], function (userSettings) { if (html += '
', showControls) { html += ''; - html += Globalize.translate("ListPaging", (totalRecordCount ? startIndex + 1 : 0), recordsEnd, totalRecordCount); + html += globalize.translate("ListPaging", (totalRecordCount ? startIndex + 1 : 0), recordsEnd, totalRecordCount); html += ""; } @@ -96,15 +96,15 @@ define(["userSettings"], function (userSettings) { } if (options.addLayoutButton) { - html += ''; + html += ''; } if (options.sortButton) { - html += ''; + html += ''; } if (options.filterButton) { - html += ''; + html += ''; } html += "
"; @@ -154,7 +154,7 @@ define(["userSettings"], function (userSettings) { var html = ""; html += '
'; html += '

'; - html += Globalize.translate("HeaderSortBy"); + html += globalize.translate("HeaderSortBy"); html += "

"; var i; var length; @@ -169,13 +169,13 @@ define(["userSettings"], function (userSettings) { html += "
"; html += '

'; - html += Globalize.translate("HeaderSortOrder"); + html += globalize.translate("HeaderSortOrder"); html += "

"; html += "
"; isChecked = "Ascending" == options.query.SortOrder ? " checked" : ""; - html += '"; + html += '"; isChecked = "Descending" == options.query.SortOrder ? " checked" : ""; - html += '"; + html += '"; html += "
"; html += "
"; dlg.innerHTML = html; diff --git a/src/components/input/mouseManager.js b/src/scripts/mouseManager.js similarity index 100% rename from src/components/input/mouseManager.js rename to src/scripts/mouseManager.js diff --git a/src/scripts/routes.js b/src/scripts/routes.js index 9c3db58a7..72c67e5b7 100644 --- a/src/scripts/routes.js +++ b/src/scripts/routes.js @@ -23,6 +23,35 @@ define([ console.debug("defining core routes"); + defineRoute({ + path: "/addserver.html", + autoFocus: false, + anonymous: true, + startup: true, + controller: "auth/addserver" + }); + defineRoute({ + path: "/selectserver.html", + autoFocus: false, + anonymous: true, + startup: true, + controller: "auth/selectserver", + type: "selectserver" + }); + defineRoute({ + path: "/forgotpassword.html", + anonymous: true, + startup: true, + controller: "auth/forgotpassword" + }); + defineRoute({ + path: "/forgotpasswordpin.html", + autoFocus: false, + anonymous: true, + startup: true, + controller: "auth/forgotpasswordpin" + }); + defineRoute({ path: "/addplugin.html", autoFocus: false, @@ -41,13 +70,6 @@ define([ transition: "fade", controller: "user/profile" }); - defineRoute({ - path: "/addserver.html", - autoFocus: false, - anonymous: true, - startup: true, - controller: "auth/addserver" - }); defineRoute({ path: "/mypreferencesdisplay.html", autoFocus: false, @@ -95,31 +117,31 @@ define([ path: "/devices.html", autoFocus: false, roles: "admin", - controller: "devices" + controller: "dashboard/devices/devices" }); defineRoute({ path: "/device.html", autoFocus: false, roles: "admin", - controller: "device" + controller: "dashboard/devices/device" }); defineRoute({ path: "/dlnaprofile.html", autoFocus: false, roles: "admin", - controller: "dlnaprofile" + controller: "dashboard/dlna/dlnaprofile" }); defineRoute({ path: "/dlnaprofiles.html", autoFocus: false, roles: "admin", - controller: "dlnaprofiles" + controller: "dashboard/dlna/dlnaprofiles" }); defineRoute({ path: "/dlnasettings.html", autoFocus: false, roles: "admin", - controller: "dlnasettings" + controller: "dashboard/dlna/dlnasettings" }); defineRoute({ path: "/edititemmetadata.html", @@ -130,20 +152,7 @@ define([ path: "/encodingsettings.html", autoFocus: false, roles: "admin", - controller: "encodingsettings" - }); - defineRoute({ - path: "/forgotpassword.html", - anonymous: true, - startup: true, - controller: "auth/forgotpassword" - }); - defineRoute({ - path: "/forgotpasswordpin.html", - autoFocus: false, - anonymous: true, - startup: true, - controller: "auth/forgotpasswordpin" + controller: "dashboard/encodingsettings" }); defineRoute({ path: "/home.html", @@ -158,11 +167,6 @@ define([ controller: "list", transition: "fade" }); - defineRoute({ - path: "/index.html", - autoFocus: false, - isDefaultRoute: true - }); defineRoute({ path: "/itemdetails.html", controller: "itemdetailpage", @@ -173,19 +177,13 @@ define([ path: "/library.html", autoFocus: false, roles: "admin", - controller: "medialibrarypage" + controller: "dashboard/medialibrarypage" }); defineRoute({ path: "/librarydisplay.html", autoFocus: false, roles: "admin", - controller: "librarydisplay" - }); - defineRoute({ - path: "/librarysettings.html", - autoFocus: false, - roles: "admin", - controller: "librarysettings" + controller: "dashboard/librarydisplay" }); defineRoute({ path: "/livetv.html", @@ -233,13 +231,13 @@ define([ path: "/metadataimages.html", autoFocus: false, roles: "admin", - controller: "metadataimagespage" + controller: "dashboard/metadataimagespage" }); defineRoute({ path: "/metadatanfo.html", autoFocus: false, roles: "admin", - controller: "metadatanfo" + controller: "dashboard/metadatanfo" }); defineRoute({ path: "/movies.html", @@ -265,20 +263,11 @@ define([ autoFocus: false, roles: "admin" }); - defineRoute({ - path: "/nowplaying.html", - controller: "playback/nowplaying", - autoFocus: false, - transition: "fade", - fullscreen: true, - supportsThemeMedia: true, - enableMediaControl: false - }); defineRoute({ path: "/playbackconfiguration.html", autoFocus: false, roles: "admin", - controller: "playbackconfiguration" + controller: "dashboard/playbackconfiguration" }); defineRoute({ path: "/availableplugins.html", @@ -308,31 +297,23 @@ define([ path: "/search.html", controller: "searchpage" }); - defineRoute({ - path: "/selectserver.html", - autoFocus: false, - anonymous: true, - startup: true, - controller: "auth/selectserver", - type: "selectserver" - }); defineRoute({ path: "/serveractivity.html", autoFocus: false, roles: "admin", - controller: "serveractivity" + controller: "dashboard/serveractivity" }); defineRoute({ path: "/apikeys.html", autoFocus: false, roles: "admin", - controller: "apikeys" + controller: "dashboard/apikeys" }); defineRoute({ path: "/streamingsettings.html", autoFocus: false, roles: "admin", - controller: "streamingsettings" + controller: "dashboard/streamingsettings" }); defineRoute({ path: "/tv.html", @@ -423,6 +404,15 @@ define([ fullscreen: true, enableMediaControl: false }); + defineRoute({ + path: "/nowplaying.html", + controller: "playback/nowplaying", + autoFocus: false, + transition: "fade", + fullscreen: true, + supportsThemeMedia: true, + enableMediaControl: false + }); defineRoute({ path: "/configurationpage", autoFocus: false, @@ -436,4 +426,9 @@ define([ isDefaultRoute: true, autoFocus: false }); + defineRoute({ + path: "/index.html", + autoFocus: false, + isDefaultRoute: true + }); }); diff --git a/src/scripts/settings/appSettings.js b/src/scripts/settings/appSettings.js index 03ceb346a..6f0975e98 100644 --- a/src/scripts/settings/appSettings.js +++ b/src/scripts/settings/appSettings.js @@ -12,7 +12,7 @@ import events from 'events'; } export function enableAutoLogin(val) { - if (val != null) { + if (val !== undefined) { this.set('enableAutoLogin', val.toString()); } @@ -20,7 +20,7 @@ import events from 'events'; } export function enableSystemExternalPlayers(val) { - if (val !== null) { + if (val !== undefined) { this.set('enableSystemExternalPlayers', val.toString()); } @@ -29,7 +29,7 @@ import events from 'events'; export function enableAutomaticBitrateDetection(isInNetwork, mediaType, val) { var key = 'enableautobitratebitrate-' + mediaType + '-' + isInNetwork; - if (val != null) { + if (val !== undefined) { if (isInNetwork && mediaType === 'Audio') { val = true; } @@ -46,7 +46,7 @@ import events from 'events'; export function maxStreamingBitrate(isInNetwork, mediaType, val) { var key = 'maxbitrate-' + mediaType + '-' + isInNetwork; - if (val != null) { + if (val !== undefined) { if (isInNetwork && mediaType === 'Audio') { // nothing to do, this is always a max value } else { @@ -72,7 +72,7 @@ import events from 'events'; } export function maxChromecastBitrate(val) { - if (val != null) { + if (val !== undefined) { this.set('chromecastBitrate1', val); } @@ -81,7 +81,7 @@ import events from 'events'; } export function syncOnlyOnWifi(val) { - if (val != null) { + if (val !== undefined) { this.set('syncOnlyOnWifi', val.toString()); } @@ -89,7 +89,7 @@ import events from 'events'; } export function syncPath(val) { - if (val != null) { + if (val !== undefined) { this.set('syncPath', val); } @@ -97,7 +97,7 @@ import events from 'events'; } export function cameraUploadServers(val) { - if (val != null) { + if (val !== undefined) { this.set('cameraUploadServers', val.join(',')); } @@ -110,7 +110,7 @@ import events from 'events'; } export function runAtStartup(val) { - if (val != null) { + if (val !== undefined) { this.set('runatstartup', val.toString()); } diff --git a/src/scripts/settings/userSettings.js b/src/scripts/settings/userSettings.js index 6f115eeff..12748eac2 100644 --- a/src/scripts/settings/userSettings.js +++ b/src/scripts/settings/userSettings.js @@ -84,7 +84,7 @@ import events from 'events'; } export function enableCinemaMode(val) { - if (val != null) { + if (val !== undefined) { return this.set('enableCinemaMode', val.toString(), false); } @@ -93,7 +93,7 @@ import events from 'events'; } export function enableNextVideoInfoOverlay(val) { - if (val != null) { + if (val !== undefined) { return this.set('enableNextVideoInfoOverlay', val.toString()); } @@ -102,7 +102,7 @@ import events from 'events'; } export function enableThemeSongs(val) { - if (val != null) { + if (val !== undefined) { return this.set('enableThemeSongs', val.toString(), false); } @@ -111,7 +111,7 @@ import events from 'events'; } export function enableThemeVideos(val) { - if (val != null) { + if (val !== undefined) { return this.set('enableThemeVideos', val.toString(), false); } @@ -120,7 +120,7 @@ import events from 'events'; } export function enableFastFadein(val) { - if (val != null) { + if (val !== undefined) { return this.set('fastFadein', val.toString(), false); } @@ -129,7 +129,7 @@ import events from 'events'; } export function enableBackdrops(val) { - if (val != null) { + if (val !== undefined) { return this.set('enableBackdrops', val.toString(), false); } @@ -138,7 +138,7 @@ import events from 'events'; } export function language(val) { - if (val != null) { + if (val !== undefined) { return this.set('language', val.toString(), false); } @@ -146,7 +146,7 @@ import events from 'events'; } export function dateTimeLocale(val) { - if (val != null) { + if (val !== undefined) { return this.set('datetimelocale', val.toString(), false); } @@ -154,7 +154,7 @@ import events from 'events'; } export function skipBackLength(val) { - if (val != null) { + if (val !== undefined) { return this.set('skipBackLength', val.toString()); } @@ -162,7 +162,7 @@ import events from 'events'; } export function skipForwardLength(val) { - if (val != null) { + if (val !== undefined) { return this.set('skipForwardLength', val.toString()); } @@ -170,7 +170,7 @@ import events from 'events'; } export function dashboardTheme(val) { - if (val != null) { + if (val !== undefined) { return this.set('dashboardTheme', val); } @@ -178,7 +178,7 @@ import events from 'events'; } export function skin(val) { - if (val != null) { + if (val !== undefined) { return this.set('skin', val, false); } @@ -186,7 +186,7 @@ import events from 'events'; } export function theme(val) { - if (val != null) { + if (val !== undefined) { return this.set('appTheme', val, false); } @@ -194,7 +194,7 @@ import events from 'events'; } export function screensaver(val) { - if (val != null) { + if (val !== undefined) { return this.set('screensaver', val, false); } @@ -202,7 +202,7 @@ import events from 'events'; } export function libraryPageSize(val) { - if (val != null) { + if (val !== undefined) { return this.set('libraryPageSize', parseInt(val, 10), false); } @@ -216,7 +216,7 @@ import events from 'events'; } export function soundEffects(val) { - if (val != null) { + if (val !== undefined) { return this.set('soundeffects', val, false); } diff --git a/src/scripts/site.js b/src/scripts/site.js index 9641409eb..df9bd4495 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -371,8 +371,9 @@ var AppInfo = {}; function initRequireWithBrowser(browser) { var bowerPath = getBowerPath(); var componentsPath = getComponentsPath(); + var scriptsPath = getScriptsPath(); - define("filesystem", [componentsPath + "/filesystem"], returnFirstDependency); + define("filesystem", [scriptsPath + "/filesystem"], returnFirstDependency); if (window.IntersectionObserver && !browser.edge) { define("lazyLoader", [componentsPath + "/lazyloader/lazyloader-intersectionobserver"], returnFirstDependency); @@ -425,9 +426,6 @@ var AppInfo = {}; if (!window.fetch) { promises.push(require(["fetch"])); } - if ("function" != typeof Object.assign) { - promises.push(require(["objectassign"])); - } Promise.all(promises).then(function () { createConnectionManager().then(function () { @@ -565,7 +563,7 @@ var AppInfo = {}; require(["playerSelectionMenu", "components/playback/remotecontrolautoplay"]); } - require(["components/screensavermanager"]); + require(["libraries/screensavermanager"]); if (!appHost.supports("physicalvolumecontrol") || browser.touch) { require(["components/playback/volumeosd"]); @@ -657,7 +655,7 @@ var AppInfo = {}; medialibraryeditor: componentsPath + "/medialibraryeditor/medialibraryeditor", imageoptionseditor: componentsPath + "/imageoptionseditor/imageoptionseditor", apphost: componentsPath + "/apphost", - visibleinviewport: componentsPath + "/visibleinviewport", + visibleinviewport: bowerPath + "/visibleinviewport", qualityoptions: componentsPath + "/qualityoptions", focusManager: componentsPath + "/focusManager", itemHelper: componentsPath + "/itemhelper", @@ -762,8 +760,8 @@ var AppInfo = {}; // TODO remove these libraries // all of these have been modified so we need to fix that first - define("scroller", [componentsPath + "/scroller"], returnFirstDependency); - define("navdrawer", [componentsPath + "/navdrawer/navdrawer"], returnFirstDependency); + define("scroller", [bowerPath + "/scroller"], returnFirstDependency); + define("navdrawer", [bowerPath + "/navdrawer/navdrawer"], returnFirstDependency); define("emby-button", [elementsPath + "/emby-button/emby-button"], returnFirstDependency); define("paper-icon-button-light", [elementsPath + "/emby-button/paper-icon-button-light"], returnFirstDependency); @@ -803,7 +801,7 @@ var AppInfo = {}; define("playerSettingsMenu", [componentsPath + "/playback/playersettingsmenu"], returnFirstDependency); define("playMethodHelper", [componentsPath + "/playback/playmethodhelper"], returnFirstDependency); define("brightnessOsd", [componentsPath + "/playback/brightnessosd"], returnFirstDependency); - define("alphaNumericShortcuts", [componentsPath + "/alphanumericshortcuts/alphanumericshortcuts"], returnFirstDependency); + define("alphaNumericShortcuts", [scriptsPath + "/alphanumericshortcuts"], returnFirstDependency); define("multiSelect", [componentsPath + "/multiselect/multiselect"], returnFirstDependency); define("alphaPicker", [componentsPath + "/alphapicker/alphapicker"], returnFirstDependency); define("tabbedView", [componentsPath + "/tabbedview/tabbedview"], returnFirstDependency); @@ -825,7 +823,7 @@ var AppInfo = {}; define("itemContextMenu", [componentsPath + "/itemcontextmenu"], returnFirstDependency); define("imageEditor", [componentsPath + "/imageeditor/imageeditor"], returnFirstDependency); define("imageDownloader", [componentsPath + "/imagedownloader/imagedownloader"], returnFirstDependency); - define("dom", [componentsPath + "/dom"], returnFirstDependency); + define("dom", [scriptsPath + "/dom"], returnFirstDependency); define("playerStats", [componentsPath + "/playerstats/playerstats"], returnFirstDependency); define("searchFields", [componentsPath + "/search/searchfields"], returnFirstDependency); define("searchResults", [componentsPath + "/search/searchresults"], returnFirstDependency); @@ -855,8 +853,7 @@ var AppInfo = {}; return viewManager; }); define("slideshow", [componentsPath + "/slideshow/slideshow"], returnFirstDependency); - define("objectassign", [componentsPath + "/polyfills/objectassign"], returnFirstDependency); - define("focusPreventScroll", [componentsPath + "/polyfills/focusPreventScroll"], returnFirstDependency); + define("focusPreventScroll", ["legacy/focusPreventScroll"], returnFirstDependency); define("userdataButtons", [componentsPath + "/userdatabuttons/userdatabuttons"], returnFirstDependency); define("listView", [componentsPath + "/listview/listview"], returnFirstDependency); define("indicators", [componentsPath + "/indicators/indicators"], returnFirstDependency); @@ -874,8 +871,8 @@ var AppInfo = {}; define("dialogHelper", [componentsPath + "/dialogHelper/dialogHelper"], returnFirstDependency); define("serverNotifications", [componentsPath + "/serverNotifications"], returnFirstDependency); define("skinManager", [componentsPath + "/skinManager"], returnFirstDependency); - define("keyboardnavigation", [componentsPath + "/input/keyboardnavigation"], returnFirstDependency); - define("mouseManager", [componentsPath + "/input/mouseManager"], returnFirstDependency); + define("keyboardnavigation", [scriptsPath + "/keyboardnavigation"], returnFirstDependency); + define("mouseManager", [scriptsPath + "/mouseManager"], returnFirstDependency); define("scrollManager", [componentsPath + "/scrollManager"], returnFirstDependency); define("autoFocuser", [componentsPath + "/autoFocuser"], returnFirstDependency); define("connectionManager", [], function () { diff --git a/src/scripts/taskbutton.js b/src/scripts/taskbutton.js index f9774167c..6159ad9fe 100644 --- a/src/scripts/taskbutton.js +++ b/src/scripts/taskbutton.js @@ -1,4 +1,4 @@ -define(["events", "userSettings", "serverNotifications", "connectionManager", "emby-button"], function (events, userSettings, serverNotifications, connectionManager) { +define(["events", "userSettings", "serverNotifications", "connectionManager", "globalize", "emby-button"], function (events, userSettings, serverNotifications, connectionManager, globalize) { "use strict"; return function (options) { @@ -48,11 +48,11 @@ define(["events", "userSettings", "serverNotifications", "connectionManager", "e var lastResult = task.LastExecutionResult ? task.LastExecutionResult.Status : ''; if (lastResult == "Failed") { - options.lastResultElem.html('(' + Globalize.translate('LabelFailed') + ')'); + options.lastResultElem.html('(' + globalize.translate('LabelFailed') + ')'); } else if (lastResult == "Cancelled") { - options.lastResultElem.html('(' + Globalize.translate('LabelCancelled') + ')'); + options.lastResultElem.html('(' + globalize.translate('LabelCancelled') + ')'); } else if (lastResult == "Aborted") { - options.lastResultElem.html('' + Globalize.translate('LabelAbortedByServerShutdown') + ''); + options.lastResultElem.html('' + globalize.translate('LabelAbortedByServerShutdown') + ''); } else { options.lastResultElem.html(lastResult); } diff --git a/src/strings/bg-bg.json b/src/strings/bg-bg.json index ab4cfcb93..7cfc56bb2 100644 --- a/src/strings/bg-bg.json +++ b/src/strings/bg-bg.json @@ -86,10 +86,10 @@ "ChannelAccessHelp": "Изберете каналите, които да споделите с потребителя. Администраторите ще могат да редактират всички канали, използвайки управлението на метаданни.", "Collections": "Колекции", "ColorSpace": "Цветово пространство", - "CommunityRating": "Обществена ощенка", + "CommunityRating": "Рейтинг на общността", "Composer": "Съчинител", "ConfirmDeleteImage": "Изтриване на изображението?", - "ContinueWatching": "Продължаване на гледането", + "ContinueWatching": "Продължи гледането", "Continuing": "Продължаващо", "CriticRating": "Оценка на критиците", "DateAdded": "Дата на добавяне", @@ -305,7 +305,7 @@ "LabelCustomCertificatePath": "Път към потребителския сертификат:", "LabelCustomCertificatePathHelp": "Път до файл с шифровъчен стандарт №12 (PKCS #12), съдържащ сертификат и частен ключ за поддръжка на протокол TLS на собствен домейн.", "LabelCustomCss": "CSS по избор:", - "LabelCustomCssHelp": "Добавете собствен стил за Уеб-интерфейса.", + "LabelCustomCssHelp": "Добавете собствен стил към уеб-интерфейса.", "LabelCustomDeviceDisplayName": "Показвано име:", "LabelCustomRating": "Оценка по избор:", "LabelDashboardTheme": "Облик на сървърното табло:", @@ -836,7 +836,7 @@ "AddItemToCollectionHelp": "Добавяне към колекция чрез търсенето им и използване на дясно-щракване с мишката или контекстното меню.", "Absolute": "Aбсолютен", "LabelLanNetworks": "Локални мрежи:", - "LabelKodiMetadataSaveImagePathsHelp": "Това е препоръчително ако имате изображения, пътят към които не е съобразен с изискванията на Kodi", + "LabelKodiMetadataSaveImagePathsHelp": "Това е препоръчително, ако наименованието на изображенията не са съобразени с изискванията на Kodi.", "LabelKodiMetadataSaveImagePaths": "Записване на пътеките към изображенията в nfo файловете", "LabelChannels": "Канали:", "DropShadow": "Сянка", @@ -878,5 +878,24 @@ "BoxRear": "Комплект (стар)", "BoxSet": "Комплект", "AuthProviderHelp": "Избор на доставчик на услуга за Автентификация, която ще се използва за автентификация на потребителската парола.", - "AllowedRemoteAddressesHelp": "Списък с IP адреси или IP/маска записи, разделени със запетая, които ще имат отдалечен достъп. Ако полето не е попълнено всички адреси ще имат отдалечен достъп." + "AllowedRemoteAddressesHelp": "Списък с IP адреси или IP/маска записи, разделени със запетая, които ще имат отдалечен достъп. Ако полето не е попълнено всички адреси ще имат отдалечен достъп.", + "BurnSubtitlesHelp": "Определя дали сървърът трябва да записва субтитри във видеоклиповете припрекодиране. Избягването на това значително ще подобри производителността. Изберете Auto, за да запишете формати, базирани на изображения (VOBSUB, PGS, SUB, IDX) и някои ASS или SSA субтитри.", + "AllowFfmpegThrottlingHelp": "Когато прекодирането или запазването на видео стигне достатъчно далеч напред от текущата позиция за възпроизвеждане, поставете на пауза процеса, така ще се изразходват по-малко ресурси. Това е най-полезно, когато се гледа, без да се търси често из видеото. Изключете това, ако имате проблеми с възпроизвеждането.", + "AllowOnTheFlySubtitleExtractionHelp": "Вградените субтитри могат да бъдат извлечени от видеоклиповете и прехвърлени към клиентите като обикновен текст, за да се предотврати транскодирането на видеото. В някои системи това може да отнеме много време и да спре възпроизвеждането на видео по време на процеса на извличане. Деактивирайте това, за да има вградени субтитри, записани с видео кодиране, когато те не се поддържат от клиентското устройство.", + "CinemaModeConfigurationHelp": "Режимът на кино носи театрално изживяване направо във вашата всекидневна с възможност за пускане на трейлъри и персонализирани интродукции преди основния филм.", + "ChangingMetadataImageSettingsNewContent": "Промените в настройките за изтегляне на метаданни или изображения ще се прилагат само за ново съдържание, добавено към вашата библиотека. За да приложите промените към съществуващите заглавия, ще трябва да обновите метаданните им ръчно.", + "DefaultMetadataLangaugeDescription": "Това са настройки по подразбиране и могат да се променят на база библиотека.", + "DefaultErrorMessage": "Възникна грешка при изпълнение на заявката. Моля опитайте по-късно.", + "CustomDlnaProfilesHelp": "Създаване на персонализиран профил за целево устройство или заменяне на системния профил.", + "CopyStreamURL": "Копиране URL на стрийма", + "CopyStreamURLError": "Възникна грешка при копиране на URL.", + "CopyStreamURLSuccess": "URL се копира успешно.", + "Connect": "Свързване", + "ConfirmEndPlayerSession": "Искате ли да изключите Jellyfin на {0}?", + "ConfirmDeletion": "Потвърждаване на изтриването", + "ConfirmDeleteItem": "Изтриването на елемента ще го премахне едновременно от файловата система и библиотеката. Сигурни ли сте, че искате да продължите?", + "ConfigureDateAdded": "Конфигурацията на добавянето на датата се определя в панела на Jellyfin сървъра в секцията за настройка на библиотека", + "ConfirmDeleteItems": "Изтриването на елементите ще ги премахне едновременно от файловата система и библиотеката. Сигурни ли сте, че искате да продължите?", + "ColorTransfer": "Предаване на цвета", + "ColorPrimaries": "Основни цветове" } diff --git a/src/strings/cs.json b/src/strings/cs.json index fc6abce2e..b7f2f7b9d 100644 --- a/src/strings/cs.json +++ b/src/strings/cs.json @@ -1603,5 +1603,6 @@ "LabelLibraryPageSize": "Velikost stránky knihovny:", "LabelDeinterlaceMethod": "Metoda odstranění prokládání:", "DeinterlaceMethodHelp": "Vyberte metodu odstranění prokládání obrazu při překódování obsahu.", - "UnsupportedPlayback": "Jellyfin nemůže dešifrovat obsah chráněný technologií DRM, ale pokusí se zobrazit o veškerý obsah, včetně chráněných titulů. Některé soubory se mohou zdát úplně černé kvůli šifrování nebo jiným nepodporovaným funkcím, jako jsou například interaktivní funkce." + "UnsupportedPlayback": "Jellyfin nemůže dešifrovat obsah chráněný technologií DRM, ale pokusí se zobrazit o veškerý obsah, včetně chráněných titulů. Některé soubory se mohou zdát úplně černé kvůli šifrování nebo jiným nepodporovaným funkcím, jako jsou například interaktivní funkce.", + "MessageUnauthorizedUser": "Momentálně nemáte oprávnění k přístupu na server. Další informace získáte od správce serveru." } diff --git a/src/strings/da.json b/src/strings/da.json index 3b8f4f13d..a2b4cb6a4 100644 --- a/src/strings/da.json +++ b/src/strings/da.json @@ -12,7 +12,7 @@ "AllChannels": "Alle kanaler", "AllEpisodes": "Alle episoder", "AllLibraries": "Alle biblioteker", - "AllowHWTranscodingHelp": "Lader tuneren omkode streams on-the-fly. Dette kan hjælpe med at reducere omkodning der kræves af serveren.", + "AllowHWTranscodingHelp": "Tillader tuneren at omkode streaming on-the-fly. Dette kan hjælpe med at reducere belastning af serveren på grund af yderligere omkodning.", "AllowMediaConversion": "Tillad media konvertering", "AllowMediaConversionHelp": "Giv eller nægt adgang til Konvertér Media featuren.", "AllowOnTheFlySubtitleExtraction": "Tillad udtræk af undertekster on-the-fly", @@ -1539,7 +1539,7 @@ "Album": "Album", "EveryHour": "Hver time", "EveryXMinutes": "Hvert {0} minut", - "OnWakeFromSleep": "Når du vågner fra søvn", + "OnWakeFromSleep": "Ved vækning fra dvale", "WeeklyAt": "{0}s ved {1}", "DailyAt": "Dagligt kl. {0}", "LastSeen": "Sidst set {0}", @@ -1585,7 +1585,7 @@ "MediaInfoStreamTypeEmbeddedImage": "Indlejret billede", "MediaInfoStreamTypeAudio": "Lyd", "LaunchWebAppOnStartupHelp": "Åben web klienten i den standard web browser når serveren starter første gang. Dette vil ikke ske når restart server funktionen benyttes.", - "LaunchWebAppOnStartup": "Åben webinterfacet når serveren startes", + "LaunchWebAppOnStartup": "Åben webinterfacet når serveren startes", "LabelWeb": "Web:", "LabelVideoResolution": "Videoopløsning:", "LabelVideoBitrate": "Video bitrate:", @@ -1633,9 +1633,11 @@ "ClientSettings": "Klient Indstillinger", "ButtonSplit": "Opdel", "BoxSet": "Box Set", - "AuthProviderHelp": "Vælg en godkendelse udbyder, der skal bruges til at godkende denne brugers adgangskode.", + "AuthProviderHelp": "Vælg en godkendelses udbyder, der kan bruges til at godkende denne brugers adgangskode.", "AskAdminToCreateLibrary": "Spørg en administrator om at oprette et bibliotek.", "Artist": "Artist", "EveryXHours": "Hver {0} time", - "OnApplicationStartup": "Ved programstart" + "OnApplicationStartup": "Ved programstart", + "UnsupportedPlayback": "Jellyfin kan ikke dekryptere indhold, der er beskyttet af DRM, men alt indhold vil blive forsøgt afspillet uanset, inklusive beskyttede titler. Nogle filer kan eventuelt vises med sort skærm på grund af kryptering eller andre funktioner, der ikke understøttes, såsom interaktive titler.", + "MessageUnauthorizedUser": "Du har ikke tilladelse til at tilgå serveren på dette tidspunkt. Kontakt din serveradministrator for mere information." } diff --git a/src/strings/el.json b/src/strings/el.json index 3856480fd..480492836 100644 --- a/src/strings/el.json +++ b/src/strings/el.json @@ -10,7 +10,7 @@ "AdditionalNotificationServices": "Περιηγηθείτε στον κατάλογο plugin για να εγκαταστήσετε πρόσθετες υπηρεσίες ειδοποίησης.", "AirDate": "Ημερομηνία προβολής", "Aired": "Προβλήθηκε", - "Albums": "Άλμπουμ", + "Albums": "Άλμπουμς", "All": "Όλα", "AllChannels": "Όλα τα κανάλια", "AllComplexFormats": "Όλες οι σύνθετες μορφές (ASS, SSA, VOBSUB, PGS, SUB / IDX κ.λπ.)", @@ -19,7 +19,7 @@ "AllLibraries": "Όλες οι βιβλιοθήκες", "AllowRemoteAccess": "Να επιτρέπονται οι απομακρυσμένες συνδέσεις σε αυτόν το διακομιστή Jellyfin.", "AllowRemoteAccessHelp": "Εάν δεν επιλεχθεί, όλες οι απομακρυσμένες συνδέσεις θα αποκλειστούν.", - "AlwaysPlaySubtitles": "Πάντα αναπαραγωγή Υποτίτλων", + "AlwaysPlaySubtitles": "Παίξτε πάντα", "AlwaysPlaySubtitlesHelp": "Οι υπότιτλοι που ταιριάζουν με τις προτιμήσεις γλώσσας θα φορτωθούν ανεξάρτητα από τη γλώσσα του ήχου.", "AnyLanguage": "Οποιαδήποτε γλώσσα", "Anytime": "Οποτεδήποτε", @@ -28,7 +28,7 @@ "Artists": "Καλλιτέχνες", "AsManyAsPossible": "Οσο το δυνατον περισσοτερα", "Ascending": "Αύξουσα", - "AspectRatio": "Αρχικός λόγος διαστάσεων", + "AspectRatio": "Αναλογία απεικόνισης", "AttributeNew": "Νέο", "Audio": "Ήχος", "Auto": "Αυτόματο", @@ -1224,6 +1224,14 @@ "LabelServerName": "Όνομα Διακομιστή:", "ButtonAddImage": "Προσθήκη Εικόνας", "BoxRear": "Κουτί(πίσω)", - "BookLibraryHelp": "Ήχος και βιβλία υποστηρίζονται.Ελέγξτε τον {0}ονομαστικό οδηγό βιβλίων{1}.", - "AuthProviderHelp": "Επιλέξτε ένα Πάροχο Επαλήθευσης για να επαληθεύσετε το κωδικό αυτού του χρήστη." + "BookLibraryHelp": "Υποστήριξη ήχου και βιβλίων κειμένου. Εξετάστε τον {0}οδηγό ονομάτων βιβλίου{1}.", + "AuthProviderHelp": "Επιλέξτε ένα Πάροχο Επαλήθευσης για να επαληθεύσετε το κωδικό αυτού του χρήστη.", + "AllowFfmpegThrottling": "Επιτάχυνση Διακωδικοποιησής", + "AlbumArtist": "Άλμπουμ Καλλιτέχνη", + "Album": "Άλμπουμ", + "BoxSet": "Σετ Κουτιού", + "AskAdminToCreateLibrary": "Ζητήστε από έναν διαχειριστή να δημιουργήσει μια βιβλιοθήκη.", + "Artist": "Καλλιτέχνης", + "AllowedRemoteAddressesHelp": "Λίστα διαχωρισμένων διευθύνσεων IP ή καταχωρίσεων IP / netmask για δίκτυα που θα επιτρέπεται η σύνδεση εξ αποστάσεως. Εάν αφεθεί κενό, όλες οι απομακρυσμένες διευθύνσεις θα επιτρέπονται.", + "AllowFfmpegThrottlingHelp": "Όταν ένας διακωδικοποιητής ή remux φτάσει αρκετά μπροστά από την τρέχουσα θέση αναπαραγωγής, διακόψτε τη διαδικασία ώστε να καταναλώσει λιγότερους πόρους. Αυτό είναι πιο χρήσιμο όταν παρακολουθείτε χωρίς να αναζητάτε συχνά. Απενεργοποιήστε το εάν αντιμετωπίζετε προβλήματα αναπαραγωγής." } diff --git a/src/strings/en-us.json b/src/strings/en-us.json index a44dece13..344753c74 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -137,6 +137,8 @@ "ButtonSplit": "Split", "ButtonSubmit": "Submit", "ButtonSubtitles": "Subtitles", + "ButtonToggleContextMenu": "More", + "ButtonTogglePlaylist": "Playlist", "ButtonTrailer": "Trailer", "ButtonUninstall": "Uninstall", "ButtonUp": "Up", diff --git a/src/strings/es-ar.json b/src/strings/es-ar.json index 44ddbbf30..69c571a57 100644 --- a/src/strings/es-ar.json +++ b/src/strings/es-ar.json @@ -499,5 +499,6 @@ "HeaderDeleteItems": "Eliminar ítems", "HeaderDeleteItem": "Eliminar ítem", "HeaderDeleteDevice": "Eliminar dispositivo", - "HeaderDefaultRecordingSettings": "Ajustes de grabación por defecto" + "HeaderDefaultRecordingSettings": "Ajustes de grabación por defecto", + "UnsupportedPlayback": "Jellyfin no puede descifrar contenido protegido por DRM pero a pesar de esto lo intentará con todo el contenido, incluyendo títulos protegidos. Algunos archivos pueden aparecer completamente en negro por estar cifrados o por otras características no soportadas, como títulos interactivos." } diff --git a/src/strings/es.json b/src/strings/es.json index 5a2ad1ea9..4b090997d 100644 --- a/src/strings/es.json +++ b/src/strings/es.json @@ -1508,5 +1508,7 @@ "UnsupportedPlayback": "No es posible desencriptar contenido protegido mediante DRM; sin embargo se intentará su reproducción. Algunos archivos pueden aparecer completamente negros debido a encriptación u otras características no soportadas, como títulos interactivos.", "YadifBob": "YADIF Bob", "Yadif": "YADIF", - "MessageUnauthorizedUser": "No tiene autorización para acceder al servidor en este momento. Póngase en contacto con el administrador del servidor para obtener más información." + "MessageUnauthorizedUser": "No tiene autorización para acceder al servidor en este momento. Póngase en contacto con el administrador del servidor para obtener más información.", + "ButtonTogglePlaylist": "Lista de reproducción", + "ButtonToggleContextMenu": "Más" } diff --git a/src/strings/fa.json b/src/strings/fa.json index 192257bf9..f244a2587 100644 --- a/src/strings/fa.json +++ b/src/strings/fa.json @@ -106,7 +106,7 @@ "TabProfiles": "پروفایل ها", "TabShows": "سریال ها", "TabSongs": "آهنگ ها", - "TabSuggestions": "پیشنهادات", + "TabSuggestions": "پیشنهادها", "TabUpcoming": "بزودی", "TellUsAboutYourself": "در مورد خودتان به ما بگویید", "ThisWizardWillGuideYou": "این عمل برای انجام تنظیمات به شما کمک می‌کند. برای شروع، لطفا زبان مورد نظر خود را انتخاب کنید.", @@ -641,5 +641,34 @@ "OptionPlainStorageFolders": "نمایش همه پوشه‌ها به عنوان پوشه‌های ذخیره سازی ساده", "OptionParentalRating": "رتبه بندی والدین", "OptionOnInterval": "در یک فاصله", - "BookLibraryHelp": "کتاب‌های صوتی و متنی پشتیبانی می‌شوند. {0}راهنمای نامگذاری کتاب{1} را مرور کنید." + "BookLibraryHelp": "کتاب‌های صوتی و متنی پشتیبانی می‌شوند. {0}راهنمای نامگذاری کتاب{1} را مرور کنید.", + "TabInfo": "اطلاعات", + "TabGuide": "راهنما", + "TabFavorites": "مورد علاقه‌ها", + "TabDisplay": "نمایش", + "TabDirectPlay": "پخش مستقیم", + "TabDevices": "دستگاه‌ها", + "TabDashboard": "داشبورد", + "TabCollections": "مجموعه‌ها", + "TabCodecs": "کدک‌ها", + "TabChannels": "کانال‌ها", + "TabCatalog": "فهرست", + "TV": "تلویزیون", + "Sunday": "یکشنبه", + "TabTranscoding": "کدگذاری", + "TabTrailers": "تریلرها", + "Suggestions": "پیشنهادها", + "Subtitles": "زیرنویس‌ها", + "Studios": "استودیو‌ها", + "StopRecording": "توقف ضبط", + "Sports": "ورزش‌ها", + "SortName": "مرتب سازی نام", + "SortChannelsBy": "مرتب سازی کانال‌ها بر اساس:", + "SortByValue": "مرتب شده بر اساس {0}", + "Sort": "مرتب سازی", + "Smart": "باهوش", + "Smaller": "کوچکتر", + "Small": "کوچک", + "ButtonTogglePlaylist": "لیست پخش", + "ButtonToggleContextMenu": "بیشتر" } diff --git a/src/strings/fr.json b/src/strings/fr.json index 72ff37513..63483821a 100644 --- a/src/strings/fr.json +++ b/src/strings/fr.json @@ -23,11 +23,11 @@ "AllowMediaConversion": "Autoriser la conversion des médias", "AllowMediaConversionHelp": "Autoriser ou refuser l'accès à la fonctionnalité de conversion des médias.", "AllowOnTheFlySubtitleExtraction": "Autoriser l'extraction des sous-titres à la volée", - "AllowOnTheFlySubtitleExtractionHelp": "Les sous-titres intégrés peuvent être extraits des vidéos et distribués aux clients au format texte pour éviter le transcodage. Sur certains systèmes, cela peut prendre du temps et arrêter la lecture de la vidéo pendant le processus d'extraction. Désactivez cette option pour graver les sous-titres avec un transcodage quand l'appareil ne les prend pas en charge nativement.", + "AllowOnTheFlySubtitleExtractionHelp": "Les sous-titres intégrés peuvent être extraits des vidéos et distribués aux clients au format texte pour éviter le transcodage. Sur certains systèmes, cela peut prendre du temps et arrêter la lecture de la vidéo pendant le processus d'extraction. Désactivez cette option pour graver les sous-titres avec un transcodage quand l'appareil client ne les prend pas en charge nativement.", "AllowRemoteAccess": "Autoriser les connexions distantes à ce serveur Jellyfin.", "AllowRemoteAccessHelp": "Si l'option est désactivée, toutes les connexions distantes seront bloquées.", "AllowedRemoteAddressesHelp": "Liste d'adresses IP ou d'IP/masque de sous-réseau séparées par des virgules qui seront autorisées à se connecter à distance. Si la liste est vide, toutes les adresses distantes seront autorisées.", - "AlwaysPlaySubtitles": "Toujours lancer les sous-titres", + "AlwaysPlaySubtitles": "Toujours afficher les sous-titres", "AlwaysPlaySubtitlesHelp": "Les sous-titres correspondant à la préférence linguistique seront chargés indépendamment de la langue de l'audio.", "AnyLanguage": "N'importe quel langage", "Anytime": "N'importe quand", @@ -100,7 +100,7 @@ "ButtonRemove": "Supprimer", "ButtonRename": "Renommer", "ButtonRepeat": "Répéter", - "ButtonResetEasyPassword": "Réinitialiser le code Easy PIN", + "ButtonResetEasyPassword": "Réinitialiser le code easy PIN", "ButtonResetPassword": "Réinitialiser le mot de passe", "ButtonRestart": "Redémarrer", "ButtonResume": "Reprendre", @@ -130,7 +130,7 @@ "CancelRecording": "Annuler l'enregistrement", "CancelSeries": "Annuler la série", "Categories": "Catégories", - "ChangingMetadataImageSettingsNewContent": "Les modifications des réglages de téléchargement des métadonnées et des illustrations ne seront appliquées qu'au nouveau contenu ajouté à votre médiathèque. Pour appliquer ces changements aux titres existants, vous devrez actualiser leurs métadonnées manuellement.", + "ChangingMetadataImageSettingsNewContent": "Les modifications des paramètres de téléchargement des métadonnées et des illustrations ne seront appliquées qu'au contenu nouvellement ajouté à votre médiathèque. Pour appliquer ces changements aux titres pré-existants, vous devrez actualiser leurs métadonnées manuellement.", "ChannelAccessHelp": "Sélectionnez les chaînes à partager avec cet utilisateur. Les administrateurs pourront modifier toutes les chaînes en utilisant le gestionnaire de métadonnées.", "ChannelNameOnly": "Seulement la chaîne {0}", "ChannelNumber": "Numéro de chaîne", @@ -1399,7 +1399,7 @@ "AuthProviderHelp": "Sélectionner un fournisseur d'authentification pour authentifier le mot de passe de cet utilisateur.", "PasswordResetProviderHelp": "Choisissez un Fournisseur de réinitialisation de mot de passe à utiliser lorsqu'un utilisateur demande la réinitialisation de son mot de passe", "HeaderHome": "Accueil", - "LabelUserLoginAttemptsBeforeLockout": "Tentatives de connexion échouées avant que l'utilisateur ne soit verrouillé:", + "LabelUserLoginAttemptsBeforeLockout": "Tentatives de connexion échouées avant que l'utilisateur ne soit verrouillé :", "DashboardOperatingSystem": "Système d'Exploitation: {0}", "DashboardArchitecture": "Architecture : {0}", "LaunchWebAppOnStartup": "Démarrer l'interface web dans mon navigateur quand le serveur est démarré", @@ -1465,7 +1465,7 @@ "LabelCorruptedFrames": "Images corrompues :", "CopyStreamURLError": "Une erreur est survenue lors de la copie de l'URL.", "AskAdminToCreateLibrary": "Demander à un administrateur de créer une médiathèque.", - "AllowFfmpegThrottlingHelp": "Quand le transcodage ou le remultiplexage est suffisamment loin de la position de lecture, le processus se mettra en pause afin d’économiser des ressources. Plus utile lors d’une lecture continue. À désactiver en cas de problèmes de lecture.", + "AllowFfmpegThrottlingHelp": "Quand le transcodage ou le remultiplexage est suffisamment en avant de la position de lecture, le processus se mettra en pause afin d’économiser des ressources. Plus utile lors d’une lecture continue. À désactiver en cas de problèmes de lecture.", "AllowFfmpegThrottling": "Adapter la vitesse du transcodage", "NoCreatedLibraries": "Il semble que vous n'ayez pas encore créé de bibliothèques. {0}Voulez-vous en créer une maintenant ?{1}", "PlaybackErrorNoCompatibleStream": "Ce client n'est pas compatible avec le média et le serveur n'envoie pas de format compatible.", @@ -1502,5 +1502,7 @@ "LabelLibraryPageSize": "Taille de la page de la médiathèque :", "LabelLibraryPageSizeHelp": "Définit la quantité d'éléments à afficher sur une page de médiathèque. Définir à 0 afin de désactiver la pagination.", "UnsupportedPlayback": "Jellyfin ne peut pas décoder du contenu protégé par un système de gestion des droits numériques, mais une tentative de lecture sera effectuée sur tout le contenu, y compris les titres protégés. Certains fichiers peuvent apparaître complètement noir, du fait de protections ou de fonctionnalités non supportées, comme les titres interactifs.", - "MessageUnauthorizedUser": "Vous n'êtes pas autorisé à accéder au serveur pour le moment. Veuillez contacter l'administrateur de votre serveur pour plus d'informations." + "MessageUnauthorizedUser": "Vous n'êtes pas autorisé à accéder au serveur pour le moment. Veuillez contacter l'administrateur de votre serveur pour plus d'informations.", + "ButtonTogglePlaylist": "Liste de lecture", + "ButtonToggleContextMenu": "Plus" } diff --git a/src/strings/hu.json b/src/strings/hu.json index a8f35831a..8dd5d4d85 100644 --- a/src/strings/hu.json +++ b/src/strings/hu.json @@ -1506,5 +1506,7 @@ "YadifBob": "YADIF Bob", "Yadif": "YADIF", "ReleaseGroup": "Kiadócsoport", - "MessageUnauthorizedUser": "Jelenleg nincs jogosultságod a szerverhez való hozzáféréshez. Kérjük, lépj kapcsolatba az adminisztrátorral további információkért!" + "MessageUnauthorizedUser": "Jelenleg nincs jogosultságod a szerverhez való hozzáféréshez. Kérjük, lépj kapcsolatba az adminisztrátorral további információkért!", + "ButtonTogglePlaylist": "Lejátszási listák", + "ButtonToggleContextMenu": "Továbbiak" } diff --git a/src/strings/ko.json b/src/strings/ko.json index 7e6f36b84..9e0bd4260 100644 --- a/src/strings/ko.json +++ b/src/strings/ko.json @@ -976,7 +976,7 @@ "OptionEnableForAllTuners": "모든 튜너 장치 활성화", "OptionBanner": "배너", "Option3D": "3D", - "OnlyImageFormats": "이미지 포맷만 (VOBSUB, PGS, SUB 등)", + "OnlyImageFormats": "이미지 포맷만 (VOBSUB, PGS, SUB)", "Off": "끄기", "NumLocationsValue": "{0} 폴더", "Normal": "보통", @@ -1378,7 +1378,7 @@ "LabelDefaultScreen": "기본 화면:", "LabelDateTimeLocale": "날짜/시간 로케일:", "XmlTvPathHelp": "XMLTV 파일을 저장할 경로를 설정합니다. Jellyfin은 이 파일을 읽어 주기적으로 변경 사항을 확인합니다. 파일 생성 및 파일 업데이트는 사용자가 수동으로 해야 합니다.", - "MessageTheFollowingLocationWillBeRemovedFromLibrary": "다음과 같은 미디어 장소들을 라이브러리에서 제거합니다:", + "MessageTheFollowingLocationWillBeRemovedFromLibrary": "다음과 같은 미디어 저장소들을 라이브러리에서 제거합니다:", "MessageReenableUser": "재활성화는 아래를 참조하십시오", "MessagePluginConfigurationRequiresLocalAccess": "이 플러그인을 구성하려면 로컬 서버에 직접 로그인하십시오.", "MessageNoCollectionsAvailable": "컬렉션을 사용하면 영화, 시리즈 및 앨범의 개인화 된 그룹을 즐길 수 있습니다. + 버튼을 클릭하여 컬렉션 만들기를 시작합니다.", @@ -1398,16 +1398,34 @@ "Artist": "아티스트", "AlbumArtist": "앨범 아티스트", "Album": "앨범", - "NoCreatedLibraries": "라이브러리가 없는 것 같습니다. {0}지금 당장 하나 만드시겠습니까?{1}", - "NewCollectionHelp": "컬렉션을 통해 사용자 정의로 영화와 같은 콘텐츠들을 묶어놓을 수 있습니다.", - "Never": "절대 아님", + "NoCreatedLibraries": "라이브러리가 없습니다. {0}지금 생성하겠습니까?{1}", + "NewCollectionHelp": "영화 및 다른 라이브러리 콘텐츠들을 묶어 개인화된 컬렉션을 구성할 수 있습니다.", + "Never": "항상 안 함", "Movie": "영화", "MoveRight": "오른쪽으로 이동", "MoveLeft": "왼쪽으로 이동", - "MoreFromValue": "{0} 에서", - "MetadataSettingChangeHelp": "변환된 메타데이터 설정은 새롭게 들어오는 콘텐츠에 적용이 됩니다. 기존의 콘텐츠에도 적용을 하려면 상세 스크린을 열어 새로 고침 버튼을 누르거나 메타데이터 메니저를 통해 대량으로 새로 고침을 하면 됩니다.", - "MessagePluginInstallDisclaimer": "Jellyfin 커뮤니티에서 만들어진 플러그인들은 Jellyfin의 기능들과 편리성을 향상시켜줄 수 있습니다. 하지만 설치하기 전에 이런 플러그인들은 라이브러리 스켄 속도 저하, 추가된 백그라운드 프로세싱 그리고 시스템의 불안정성같은 문제점들을 Jellyfin 서버에 일으킬 수도 있다는 것을 유념하시기 바람니다.", - "LabelLibraryPageSizeHelp": "라이브러리 페이지에 표시될 아이템들의 수를 조절합니다. 0 으로 지정시 페이징을 비활성화 합니다.", + "MoreFromValue": "{0} 에서 더 자세히", + "MetadataSettingChangeHelp": "변경된 메타데이터 설정은 새 콘텐츠에 적용됩니다. 기존의 콘텐츠에 적용하려면 상세 화면에서 새로 고침 버튼을 누르거나 메타데이터 매니저를 통해 일괄적으로 새로 고침을 수행하십시오.", + "MessagePluginInstallDisclaimer": "Jellyfin 커뮤니티에서 만들어진 플러그인은 Jellyfin의 기능과 편의성을 향상시킬 수 있습니다. 다만 이러한 플러그인은 라이브러리 스캔 속도 저하, 추가 백그라운드 프로세싱, 시스템 불안정과 같은 문제를 야기할 수 있다는 것을 유념하시기 바랍니다.", + "LabelLibraryPageSizeHelp": "라이브러리 페이지에 표시될 항목 수를 조절합니다. 0으로 지정 시 페이징을 비활성화합니다.", "LabelLibraryPageSize": "라이브러리 페이지 크기:", - "LabelEnableBlastAliveMessages": "서버 활성화 메세지" + "LabelEnableBlastAliveMessages": "서버 활성화 메세지", + "OptionEnableExternalContentInSuggestionsHelp": "제안 항목에 인터넷 예고편과 라이브 TV 프로그램이 포함되도록 허용합니다.", + "OptionEnableExternalContentInSuggestions": "제안 항목에 외부 콘텐츠 허용", + "OptionDownloadImagesInAdvanceHelp": "기본적으로 대부분의 이미지는 Jellyfin 앱에서 요청할 때에만 다운로드됩니다. 새 미디어를 추가할 때 모든 이미지를 미리 다운로드하려면 이 옵션을 활성화하십시오. 라이브러리 스캔이 심각하게 지연될 수도 있습니다.", + "OptionDownloadImagesInAdvance": "미리 이미지 다운로드", + "OptionDisplayFolderView": "일반적인 미디어 폴더를 볼 수 있는 폴더 보기를 표시합니다", + "OptionAutomaticallyGroupSeriesHelp": "활성화하면 라이브러리 내의 여러 폴더에 분산된 시리즈를 하나의 시리즈로 병합합니다.", + "OptionAutomaticallyGroupSeries": "여러 폴더에 분산된 시리즈를 자동으로 병합합니다", + "OptionAllowVideoPlaybackRemuxing": "변환이 필요한 비디오를 재인코딩하지 않고 재생하는 것을 허용", + "OptionAllowSyncTranscoding": "트랜스코딩이 필요한 미디어의 다운로드 및 싱크 허용", + "OptionAllowMediaPlaybackTranscodingHelp": "트랜스코딩 접근을 제한하면 Jellyfin 앱에서 지원되지 않는 미디어 형식을 재생할 때 문제가 발생할 수 있습니다.", + "OptionForceRemoteSourceTranscoding": "원격 미디어 소스를 강제 트랜스코딩 (라이브 TV 등)", + "OnlyForcedSubtitlesHelp": "'강제'로 표시된 자막만 불러옵니다.", + "OnlyForcedSubtitles": "강제로 설정한 자막만", + "OneChannel": "단채널", + "NoSubtitlesHelp": "자막을 자동으로 불러오지 않습니다. 재생 중에 수동으로 켤 수 있습니다.", + "MusicLibraryHelp": "{0}음악 이름 지정 규칙{1}을 확인하십시오.", + "MovieLibraryHelp": "{0}영화 이름 지정 규칙{1}을 확인하십시오.", + "MessageUnauthorizedUser": "현재 서버에 접속할 권한이 없습니다. 자세한 정보는 서버 관리자에게 문의하십시오." } diff --git a/src/strings/pl.json b/src/strings/pl.json index 32e9a9798..431ea3feb 100644 --- a/src/strings/pl.json +++ b/src/strings/pl.json @@ -1467,5 +1467,8 @@ "LabelVideoResolution": "Rozdzielczość wideo:", "LabelStreamType": "Typ transmisji:", "EnableFastImageFadeInHelp": "Włącz szybszą animację pojawiania się dla załadowanych obrazów", - "EnableFastImageFadeIn": "Szybkie pojawianie się obrazów" + "EnableFastImageFadeIn": "Szybkie pojawianie się obrazów", + "Artist": "Artysta", + "AlbumArtist": "Album artysty", + "Album": "Album" } diff --git a/src/strings/ro.json b/src/strings/ro.json index 4da3ddde4..c27996ec4 100644 --- a/src/strings/ro.json +++ b/src/strings/ro.json @@ -1499,5 +1499,8 @@ "DeinterlaceMethodHelp": "Selectați metoda de intercalat pe care să o utilizați la transcodarea conținutului intercalat.", "UnsupportedPlayback": "Jellyfin nu poate decripta conținut protejat de DRM, dar tot conținutul va fi încercat indiferent de titlurile protejate. Unele fișiere pot părea complet negre din cauza criptării sau a altor funcții neacceptate, cum ar fi titluri interactive.", "LabelLibraryPageSizeHelp": "Setează cantitatea de elemente de afișat pe o pagină a bibliotecii. Setați la 0 pentru a dezactiva paginarea.", - "LabelLibraryPageSize": "Mărimea paginii Bibliotecă:" + "LabelLibraryPageSize": "Mărimea paginii Bibliotecă:", + "MessageUnauthorizedUser": "Nu sunteți autorizat să accesați serverul în acest moment. Vă rugăm să contactați administratorul serverului pentru mai multe informații.", + "ButtonTogglePlaylist": "Listă de redare", + "ButtonToggleContextMenu": "Mai mult" } diff --git a/src/strings/ru.json b/src/strings/ru.json index 6d88e3ea8..33169c555 100644 --- a/src/strings/ru.json +++ b/src/strings/ru.json @@ -83,7 +83,7 @@ "ButtonGuide": "Телегид", "ButtonHelp": "Справка", "ButtonHome": "Главное", - "ButtonInfo": "Инфо...", + "ButtonInfo": "Инфо", "ButtonLearnMore": "Подробнее", "ButtonLibraryAccess": "Доступ к медиатеке", "ButtonManualLogin": "Войти вручную", @@ -96,7 +96,7 @@ "ButtonOpen": "Открыть", "ButtonParentalControl": "Родительский контроль", "ButtonPause": "Пауза", - "ButtonPlay": "Воспр.", + "ButtonPlay": "Воспроизведение", "ButtonPreviousTrack": "Предыдущая дорожка", "ButtonProfile": "Профиль", "ButtonQuickStartGuide": "Руководство по запуску", @@ -127,6 +127,8 @@ "ButtonStop": "Остановить", "ButtonSubmit": "Подтвердить", "ButtonSubtitles": "Субтитры", + "ButtonToggleContextMenu": "Ещё", + "ButtonTogglePlaylist": "Плей-лист", "ButtonTrailer": "Трейлер", "ButtonUninstall": "Удалить", "ButtonUp": "Вверх", @@ -203,8 +205,8 @@ "EditImages": "Править изображения", "EditMetadata": "Править метаданные", "EditSubtitles": "Править субтитры", - "EnableBackdrops": "Задники", - "EnableBackdropsHelp": "Задники будут отображаются фоном на некоторых страницах при просмотре медиатеки.", + "EnableBackdrops": "Фоны", + "EnableBackdropsHelp": "Фоны будут отображаются на заднем плане на некоторых страницах при просмотре медиатеки.", "EnableCinemaMode": "Режим кинозала", "EnableColorCodedBackgrounds": "Обозначеннные цветом фоны", "EnableDisplayMirroring": "Дублирование отображения", @@ -215,7 +217,7 @@ "EnableNextVideoInfoOverlayHelp": "В конце видео отображать информацию о последующем видео в текущем плей-листе.", "EnablePhotos": "Отображать фотографии", "EnablePhotosHelp": "Изображения будут обнаруживаться и отображаться наряду с другими медиафайлами.", - "EnableStreamLooping": "Автоциклирование трансляций", + "EnableStreamLooping": "Зацикливание трансляций", "EnableStreamLoopingHelp": "Включайте, если трансляции содержат данные только на несколько секунд и необходимо непрерывно их запрашивать. Включение этого без необходимости может породить проблемы.", "EnableThemeSongs": "Тематические композиции", "EnableThemeSongsHelp": "Воспроизведение тематических композиций в фоновом режиме при навигации по медиатеке.", @@ -263,11 +265,11 @@ "Genres": "Жанры", "GroupBySeries": "Группирование по сериалам", "GroupVersions": "Сгруппировать версии", - "GuestStar": "Пригл. актёр", + "GuestStar": "Приглашенный актёр", "Guide": "Телегид", "GuideProviderLogin": "Вход", "GuideProviderSelectListings": "Выбор перечней", - "H264CrfHelp": "Постоянное значение оценки (Constant Rate Factor, CRF) - параметр качества по умолчанию для кодёра x264. Возможно задавать значения от 0 до 51, где меньшие значения привели бы к улучшению качества (за счёт бо́льших размеров файлов). Разумными являются значения от 18 до 28. Стандартно для x264 - 23, так что вы можете использовать это в качестве отправной точки.", + "H264CrfHelp": "Постоянное значение оценки (Constant Rate Factor, CRF) - параметр качества по умолчанию для кодека x264. Возможно задавать значения от 0 до 51, где меньшие значения привели бы к улучшению качества (за счёт увеличения размеров файлов). Разумными являются значения от 18 до 28. Стандартно для x264 - 23, так что вы можете использовать это в качестве отправной точки.", "EncoderPresetHelp": "Выберите значение быстрее для улучшения производительности, или значение медленнее для улучшения качества.", "HDPrograms": "HD-передачи", "HandledByProxy": "Обрабатывается обратным прокси", @@ -404,7 +406,7 @@ "HeaderPeople": "Люди", "HeaderPhotoAlbums": "Фотоальбомы", "HeaderPinCodeReset": "Сброс PIN-кода", - "HeaderPlayAll": "Воспр. все", + "HeaderPlayAll": "Воспроизвести все", "HeaderPlayOn": "Воспроизведение", "HeaderPlayback": "Воспроизведение медиаданных", "HeaderPlaybackError": "Ошибка воспроизведения", @@ -660,7 +662,7 @@ "LabelManufacturer": "Производитель:", "LabelManufacturerUrl": "URL производителя", "LabelMatchType": "Тип соответствия:", - "LabelMaxBackdropsPerItem": "Макс. число задников на элемент:", + "LabelMaxBackdropsPerItem": "Максимальное число фонов на элемент:", "LabelMaxChromecastBitrate": "Качество трансляции Chromecast:", "LabelMaxParentalRating": "Макс. допустимая возрастная категория:", "LabelMaxResumePercentage": "Макс. доля для возобновления, %:", @@ -680,12 +682,12 @@ "LabelMetadataSavers": "Хранители метаданных:", "LabelMetadataSaversHelp": "Выберите форматы файлов, куда будут сохраняться метаданные.", "LabelMethod": "Метод:", - "LabelMinBackdropDownloadWidth": "Мин. ширина загружаемого задника:", - "LabelMinResumeDuration": "Мин. длительность для возобновления:", + "LabelMinBackdropDownloadWidth": "Минимальная ширина загружаемого фона:", + "LabelMinResumeDuration": "Минимальная длительность для возобновления:", "LabelMinResumeDurationHelp": "Наименьшая длительность видео в секундах, при которой сохраняется позиция воспроизведения и позволяется возобновление.", - "LabelMinResumePercentage": "Мин. доля для возобновления, %:", + "LabelMinResumePercentage": "Минимальная доля для возобновления, %:", "LabelMinResumePercentageHelp": "Произведения предполагаются не воспроизведёнными, при остановке до данного момента.", - "LabelMinScreenshotDownloadWidth": "Мин. ширина загружаемого снимка экрана:", + "LabelMinScreenshotDownloadWidth": "Минимальная ширина загружаемого снимка экрана:", "LabelModelDescription": "Описание модели", "LabelModelName": "Наименование модели", "LabelModelNumber": "Номер модели", @@ -709,7 +711,7 @@ "LabelNumberOfGuideDaysHelp": "Больше дней загрузки данных телегида обеспечивает возможность заблаговременно назначать расписание и просматривать больше перечней, однако это займёт больше времени для загрузки. При значении «Авто» выбор определяется числом каналов.", "LabelOptionalNetworkPath": "(Необязательно) Общедоступная сетевая папка:", "LabelOptionalNetworkPathHelp": "Если данная папка общедоступна в своей сети, предоставление пути к сетевой папке может позволить Jellyfin-приложениям на других устройствах получить прямой доступ к медиафайлам.", - "LabelOriginalAspectRatio": "Исходное соот-ие сторон:", + "LabelOriginalAspectRatio": "Исходное соотношение сторон:", "LabelOriginalTitle": "Оригинальное название:", "LabelOverview": "Обзор:", "LabelParentNumber": "Родительский номер:", @@ -833,7 +835,7 @@ "LabelVideo": "Видео", "LabelXDlnaCap": "Свойства X-Dlna:", "LabelXDlnaCapHelp": "Определяется содержание из элемента X_DLNACAP во пространстве имён urn:schemas-dlna-org:device-1-0.", - "LabelXDlnaDoc": "Схема X-Dlna:", + "LabelXDlnaDoc": "Схема X-DLNA:", "LabelXDlnaDocHelp": "Определяется содержание из элемента X_DLNADOC во пространстве имён urn:schemas-dlna-org:device-1-0.", "LabelYear": "Год:", "LabelYourFirstName": "Ваше имя:", @@ -856,11 +858,11 @@ "ManageLibrary": "Управление медиатекой", "ManageRecording": "Управлять записью", "MapChannels": "Сопоставить каналы", - "MarkPlayed": "Отметить как воспр-ое", - "MarkUnplayed": "Отметить как невоспр-ое", + "MarkPlayed": "Отметить как воспроизведенное", + "MarkUnplayed": "Отметить как невоспроизведенное", "MaxParentalRatingHelp": "Содержание с более высокой возр. категорией будет скрыто от этого пользователя.", "MediaInfoAnamorphic": "Анаморфность", - "MediaInfoAspectRatio": "Соот-ие сторон", + "MediaInfoAspectRatio": "Соотношение сторон", "MediaInfoBitDepth": "Глубина цвета", "MediaInfoBitrate": "Поток. ск-ть", "MediaInfoChannels": "Каналы", @@ -880,7 +882,7 @@ "MediaInfoProfile": "Профиль", "MediaInfoRefFrames": "Опорные кадры", "MediaInfoResolution": "Разрешение", - "MediaInfoSampleRate": "Ч-та дискр-ии", + "MediaInfoSampleRate": "Частота дискретизации", "MediaInfoSize": "Размер", "MediaInfoTimestamp": "Метка времени", "MediaIsBeingConverted": "Медиаданные преобразуются в формат, совместимый с устройством, которое воспроизводит эти медиаданные.", @@ -1003,7 +1005,7 @@ "OptionBlockMusic": "Музыка", "OptionBlockTrailers": "Трейлеры", "OptionBlockTvShows": "ТВ-передачи", - "OptionBluray": "BluRay", + "OptionBluray": "Blu-ray", "OptionCommunityRating": "Пользовательский рейтинг", "OptionContinuing": "Продолжающееся", "OptionCriticRating": "Оценка критиков", @@ -1020,7 +1022,7 @@ "OptionDisplayFolderView": "Отображать аспект Папки для просмотра обычных медиапапок", "OptionDisplayFolderViewHelp": "Отображение аспекта \"Папки\" рядом с другими вашими медиатеками. Это может быть полезно, если вы хотите вид обычных папок.", "OptionDownloadArtImage": "Виньетка", - "OptionDownloadBackImage": "Задник", + "OptionDownloadBackImage": "Фон", "OptionDownloadBannerImage": "Баннер", "OptionDownloadBoxImage": "DVD-бокс", "OptionDownloadDiscImage": "Диск", @@ -1113,7 +1115,7 @@ "PackageInstallCancelled": "Установка {0} (версия {1}) отменена.", "PackageInstallCompleted": "Установка {0} (версия {1}) завершена.", "PackageInstallFailed": "Установка {0} (версия {1}) неудачна.", - "ParentalRating": "Возр. кат-ия", + "ParentalRating": "Возрастная категория", "PasswordMatchError": "Пароль и подтверждение пароля должны совпадать.", "PasswordResetComplete": "Пароль был сброшен.", "PasswordResetConfirmation": "Вы действительно хотите сбросить пароль?", @@ -1126,10 +1128,10 @@ "PinCodeResetComplete": "PIN-код был сброшен.", "PinCodeResetConfirmation": "Вы действительно хотите сбросить PIN-код?", "PlaceFavoriteChannelsAtBeginning": "Разместить избранные каналы в начале", - "Play": "Воспр.", - "PlayAllFromHere": "Воспр. все отсюда", + "Play": "Воспроизведение", + "PlayAllFromHere": "Воспроизвести все отсюда", "PlayCount": "Кол. воспроизведений", - "PlayFromBeginning": "Воспр. с начала", + "PlayFromBeginning": "Воспроизвести с начала", "PlayNext": "Воспроизвести следующее", "PlayNextEpisodeAutomatically": "Воспроизводить последующий эпизод автоматически", "Played": "Воспроизведено", @@ -1258,7 +1260,7 @@ "TabContainers": "Контейнеры", "TabDashboard": "Панель", "TabDevices": "Устройства", - "TabDirectPlay": "Прямое воспр-ие", + "TabDirectPlay": "Прямое воспроизведение", "TabDisplay": "Отображение", "TabEpisodes": "Эпизоды", "TabFavorites": "Избранное", @@ -1436,7 +1438,7 @@ "LabelPlayMethod": "Метод воспроизведения:", "LabelFolder": "Папка:", "LabelBaseUrl": "Базовый URL:", - "LabelBitrate": "Поток. ск-ть:", + "LabelBitrate": "Битрейт:", "LabelAudioSampleRate": "Частота дискретизации аудио:", "LabelAudioCodec": "Аудио кодек:", "LabelAudioChannels": "Аудио каналы:", @@ -1500,5 +1502,6 @@ "LabelLibraryPageSizeHelp": "Устанавливается количество элементов для отображения на странице медиатеки. Установите 0 для отключения нумерации страниц.", "LabelDeinterlaceMethod": "Метод устранения гребёнки:", "DeinterlaceMethodHelp": "Выберите метод устранения гребёнки, который будет использоваться при перекодировании чересстрочного содержания.", - "UnsupportedPlayback": "Jellyfin не может расшифровать содержимое, защищенное DRM, но в любом случае будет предпринята попытка расшифровки всего содержимого, включая защищенные заголовки. Некоторые файлы могут выглядеть полностью черными из-за шифрования или других неподдерживаемых функций, таких как интерактивные заголовки." + "UnsupportedPlayback": "Jellyfin не может расшифровать содержимое, защищенное DRM, но в любом случае будет предпринята попытка расшифровки всего содержимого, включая защищенные заголовки. Некоторые файлы могут выглядеть полностью черными из-за шифрования или других неподдерживаемых функций, таких как интерактивные заголовки.", + "MessageUnauthorizedUser": "В настоящее время у вас нет доступа к серверу. Пожалуйста, свяжитесь с администратором сервера для получения дополнительной информации." } diff --git a/webpack.dev.js b/webpack.dev.js index beca8ea4f..78bdb5486 100644 --- a/webpack.dev.js +++ b/webpack.dev.js @@ -28,7 +28,7 @@ module.exports = merge(common, { { test: /\.(woff|woff2|eot|ttf|otf)$/, use: [ - 'file-loader', + 'file-loader' ] } ] diff --git a/webpack.prod.js b/webpack.prod.js index 80d40f345..c2d5e9791 100644 --- a/webpack.prod.js +++ b/webpack.prod.js @@ -21,7 +21,7 @@ module.exports = merge(common, { { test: /\.(woff|woff2|eot|ttf|otf)$/, use: [ - 'file-loader', + 'file-loader' ] } ] diff --git a/yarn.lock b/yarn.lock index 55d6a104d..47485dd25 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1553,6 +1553,19 @@ autoprefixer@^9.0.0, autoprefixer@^9.6.1, autoprefixer@^9.7.4: postcss "^7.0.27" postcss-value-parser "^4.0.3" +autoprefixer@^9.7.6: + version "9.7.6" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.7.6.tgz#63ac5bbc0ce7934e6997207d5bb00d68fa8293a4" + integrity sha512-F7cYpbN7uVVhACZTeeIeealwdGM6wMtfWARVLTy5xmKtgVdBNJvbDRoCK3YO1orcs7gv/KwYlb3iXwu9Ug9BkQ== + dependencies: + browserslist "^4.11.1" + caniuse-lite "^1.0.30001039" + chalk "^2.4.2" + normalize-range "^0.1.2" + num2fraction "^1.2.2" + postcss "^7.0.27" + postcss-value-parser "^4.0.3" + aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" @@ -1970,6 +1983,16 @@ browserslist@^4.0.0, browserslist@^4.11.0, browserslist@^4.6.4, browserslist@^4. node-releases "^1.1.52" pkg-up "^3.1.0" +browserslist@^4.11.1: + version "4.12.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.12.0.tgz#06c6d5715a1ede6c51fc39ff67fd647f740b656d" + integrity sha512-UH2GkcEDSI0k/lRkuDSzFl9ZZ87skSy9w2XAn1MsZnL+4c4rqbBd3e82UWHbYDpztABrPBhZsTEeuxVfHppqDg== + dependencies: + caniuse-lite "^1.0.30001043" + electron-to-chromium "^1.3.413" + node-releases "^1.1.53" + pkg-up "^2.0.0" + browserslist@^4.8.2: version "4.11.1" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.11.1.tgz#92f855ee88d6e050e7e7311d987992014f1a1f1b" @@ -2240,6 +2263,11 @@ caniuse-lite@^1.0.30001038: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001039.tgz#b3814a1c38ffeb23567f8323500c09526a577bbe" integrity sha512-SezbWCTT34eyFoWHgx8UWso7YtvtM7oosmFoXbCkdC6qJzRfBTeTgE9REtKtiuKXuMwWTZEvdnFNGAyVMorv8Q== +caniuse-lite@^1.0.30001039, caniuse-lite@^1.0.30001043: + version "1.0.30001046" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001046.tgz#7a06d3e8fd8aa7f4d21c9a2e313f35f2d06b013e" + integrity sha512-CsGjBRYWG6FvgbyGy+hBbaezpwiqIOLkxQPY4A4Ea49g1eNsnQuESB+n4QM0BKii1j80MyJ26Ir5ywTQkbRE4g== + caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" @@ -3667,6 +3695,11 @@ electron-to-chromium@^1.3.390: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.397.tgz#db640c2e67b08d590a504c20b56904537aa2bafa" integrity sha512-zcUd1p/7yzTSdWkCTrqGvbnEOASy96d0RJL/lc5BDJoO23Z3G/VHd0yIPbguDU9n8QNUTCigLO7oEdtOb7fp2A== +electron-to-chromium@^1.3.413: + version "1.3.418" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.418.tgz#840021191f466b803a873e154113620c9f53cec6" + integrity sha512-i2QrQtHes5fK/F9QGG5XacM5WKEuR322fxTYF9e8O9Gu0mc0WmjjwGpV8c7Htso6Zf2Di18lc3SIPxmMeRFBug== + elliptic@^6.0.0: version "6.5.2" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.2.tgz#05c5678d7173c049d8ca433552224a495d0e3762"