mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-05-04 07:46:32 +01:00
Compare commits
1 Commits
master
...
allow-tmdb
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
86804686a4 |
@@ -3,7 +3,7 @@
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"dotnet-ef": {
|
||||
"version": "10.0.7",
|
||||
"version": "10.0.5",
|
||||
"commands": [
|
||||
"dotnet-ef"
|
||||
]
|
||||
|
||||
8
.github/ISSUE_TEMPLATE/issue report.yml
vendored
8
.github/ISSUE_TEMPLATE/issue report.yml
vendored
@@ -87,9 +87,13 @@ body:
|
||||
label: Jellyfin Server version
|
||||
description: What version of Jellyfin are you using?
|
||||
options:
|
||||
- 10.11.8
|
||||
- 10.11.7
|
||||
- 10.11.6
|
||||
- 10.11.5
|
||||
- 10.11.4
|
||||
- 10.11.3
|
||||
- 10.11.2
|
||||
- 10.11.1
|
||||
- 10.11.0
|
||||
- Master
|
||||
- Unstable
|
||||
- Older*
|
||||
|
||||
10
.github/workflows/ci-codeql-analysis.yml
vendored
10
.github/workflows/ci-codeql-analysis.yml
vendored
@@ -8,10 +8,6 @@ on:
|
||||
schedule:
|
||||
- cron: '24 2 * * 4'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
@@ -32,13 +28,13 @@ jobs:
|
||||
dotnet-version: '10.0.x'
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3
|
||||
uses: github/codeql-action/init@b1bff81932f5cdfc8695c7752dcee935dcd061c8 # v4.33.0
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
queries: +security-extended
|
||||
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3
|
||||
uses: github/codeql-action/autobuild@b1bff81932f5cdfc8695c7752dcee935dcd061c8 # v4.33.0
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3
|
||||
uses: github/codeql-action/analyze@b1bff81932f5cdfc8695c7752dcee935dcd061c8 # v4.33.0
|
||||
|
||||
4
.github/workflows/ci-compat.yml
vendored
4
.github/workflows/ci-compat.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
dotnet build Jellyfin.Server -o ./out
|
||||
|
||||
- name: Upload Head
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: abi-head
|
||||
retention-days: 14
|
||||
@@ -65,7 +65,7 @@ jobs:
|
||||
dotnet build Jellyfin.Server -o ./out
|
||||
|
||||
- name: Upload Head
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: abi-base
|
||||
retention-days: 14
|
||||
|
||||
@@ -1,28 +1,118 @@
|
||||
name: OpenAPI Publish
|
||||
name: OpenAPI
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
tags:
|
||||
- 'v*'
|
||||
pull_request:
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
publish-openapi:
|
||||
name: OpenAPI - Publish Artifact
|
||||
uses: ./.github/workflows/openapi-generate.yml
|
||||
openapi-head:
|
||||
name: OpenAPI - HEAD
|
||||
runs-on: ubuntu-latest
|
||||
permissions: read-all
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
repository: ${{ github.event.pull_request.head.repo.full_name }}
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0
|
||||
with:
|
||||
dotnet-version: '10.0.x'
|
||||
- name: Generate openapi.json
|
||||
run: dotnet test tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj -c Release --filter "Jellyfin.Server.Integration.Tests.OpenApiSpecTests"
|
||||
|
||||
- name: Upload openapi.json
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: openapi-head
|
||||
retention-days: 14
|
||||
if-no-files-found: error
|
||||
path: tests/Jellyfin.Server.Integration.Tests/bin/Release/net10.0/openapi.json
|
||||
|
||||
openapi-base:
|
||||
name: OpenAPI - BASE
|
||||
if: ${{ github.base_ref != '' }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions: read-all
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
repository: ${{ github.event.pull_request.head.repo.full_name }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Checkout common ancestor
|
||||
env:
|
||||
HEAD_REF: ${{ github.head_ref }}
|
||||
run: |
|
||||
git remote add upstream https://github.com/${{ github.event.pull_request.base.repo.full_name }}
|
||||
git -c protocol.version=2 fetch --prune --progress --no-recurse-submodules upstream +refs/heads/*:refs/remotes/upstream/* +refs/tags/*:refs/tags/*
|
||||
ANCESTOR_REF=$(git merge-base upstream/${{ github.base_ref }} origin/$HEAD_REF)
|
||||
git checkout --progress --force $ANCESTOR_REF
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0
|
||||
with:
|
||||
dotnet-version: '10.0.x'
|
||||
- name: Generate openapi.json
|
||||
run: dotnet test tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj -c Release --filter "Jellyfin.Server.Integration.Tests.OpenApiSpecTests"
|
||||
|
||||
- name: Upload openapi.json
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: openapi-base
|
||||
retention-days: 14
|
||||
if-no-files-found: error
|
||||
path: tests/Jellyfin.Server.Integration.Tests/bin/Release/net10.0/openapi.json
|
||||
|
||||
openapi-diff:
|
||||
permissions:
|
||||
contents: read
|
||||
with:
|
||||
ref: ${{ github.sha }}
|
||||
repository: ${{ github.repository }}
|
||||
artifact: openapi-head
|
||||
pull-requests: write
|
||||
|
||||
name: OpenAPI - Difference
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- openapi-head
|
||||
- openapi-base
|
||||
steps:
|
||||
- name: Download openapi-head
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: openapi-head
|
||||
path: openapi-head
|
||||
|
||||
- name: Download openapi-base
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: openapi-base
|
||||
path: openapi-base
|
||||
|
||||
- name: Detect OpenAPI changes
|
||||
id: openapi-diff
|
||||
uses: jellyfin/openapi-diff-action@9274f6bda9d01ab091942a4a8334baa53692e8a4 # v1.0.0
|
||||
with:
|
||||
old-spec: openapi-base/openapi.json
|
||||
new-spec: openapi-head/openapi.json
|
||||
markdown: openapi-changelog.md
|
||||
add-pr-comment: true
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
|
||||
publish-unstable:
|
||||
name: OpenAPI - Publish Unstable Spec
|
||||
if: ${{ github.event_name != 'pull_request' && !startsWith(github.ref, 'refs/tags/v') && contains(github.repository_owner, 'jellyfin') }}
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- publish-openapi
|
||||
- openapi-head
|
||||
steps:
|
||||
- name: Set unstable dated version
|
||||
id: version
|
||||
@@ -83,7 +173,7 @@ jobs:
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/v') && contains(github.repository_owner, 'jellyfin') }}
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- publish-openapi
|
||||
- openapi-head
|
||||
steps:
|
||||
- name: Set version number
|
||||
id: version
|
||||
2
.github/workflows/ci-tests.yml
vendored
2
.github/workflows/ci-tests.yml
vendored
@@ -35,7 +35,7 @@ jobs:
|
||||
--verbosity minimal
|
||||
|
||||
- name: Merge code coverage results
|
||||
uses: danielpalme/ReportGenerator-GitHub-Action@c31aa4ed4f12f147061186cf2a029f307b5c3636 # v5.5.9
|
||||
uses: danielpalme/ReportGenerator-GitHub-Action@cf6fe1b38ed5becc89ffe056c1f240825993be5b # v5.5.4
|
||||
with:
|
||||
reports: "**/coverage.cobertura.xml"
|
||||
targetdir: "merged/"
|
||||
|
||||
2
.github/workflows/commands.yml
vendored
2
.github/workflows/commands.yml
vendored
@@ -36,7 +36,7 @@ jobs:
|
||||
|
||||
rename:
|
||||
name: Rename
|
||||
if: contains(github.event.comment.body, '@jellyfin-bot rename')
|
||||
if: contains(github.event.comment.body, '@jellyfin-bot rename') && github.event.comment.author_association == 'MEMBER'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: pull in script
|
||||
|
||||
44
.github/workflows/openapi-generate.yml
vendored
44
.github/workflows/openapi-generate.yml
vendored
@@ -1,44 +0,0 @@
|
||||
name: OpenAPI Generate
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
ref:
|
||||
required: true
|
||||
type: string
|
||||
repository:
|
||||
required: true
|
||||
type: string
|
||||
artifact:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
main:
|
||||
name: Main
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
ref: ${{ inputs.ref }}
|
||||
repository: ${{ inputs.repository }}
|
||||
|
||||
- name: Configure .NET
|
||||
uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0
|
||||
with:
|
||||
dotnet-version: '10.0.x'
|
||||
|
||||
- name: Create File
|
||||
run: dotnet test tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj -c Release --filter Jellyfin.Server.Integration.Tests.OpenApiSpecTests
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: ${{ inputs.artifact }}
|
||||
path: tests/Jellyfin.Server.Integration.Tests/bin/Release/net10.0/openapi.json
|
||||
retention-days: 14
|
||||
if-no-files-found: error
|
||||
80
.github/workflows/openapi-pull-request.yml
vendored
80
.github/workflows/openapi-pull-request.yml
vendored
@@ -1,80 +0,0 @@
|
||||
name: OpenAPI Check
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
ancestor:
|
||||
name: Common Ancestor
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
base_ref: ${{ steps.ancestor.outputs.base_ref }}
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
repository: ${{ github.event.pull_request.head.repo.full_name }}
|
||||
fetch-depth: 0
|
||||
- name: Search History
|
||||
id: ancestor
|
||||
run: |
|
||||
git remote add upstream https://github.com/${{ github.event.pull_request.base.repo.full_name }}
|
||||
git fetch --prune --progress --no-recurse-submodules upstream +refs/heads/*:refs/remotes/upstream/* +refs/tags/*:refs/tags/*
|
||||
|
||||
ANCESTOR_REF=$(git merge-base upstream/${{ github.base_ref }} HEAD)
|
||||
|
||||
echo "ref: ${ANCESTOR_REF}"
|
||||
|
||||
echo "base_ref=${ANCESTOR_REF}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
head:
|
||||
name: Head Artifact
|
||||
uses: ./.github/workflows/openapi-generate.yml
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
repository: ${{ github.event.pull_request.head.repo.full_name }}
|
||||
artifact: openapi-head
|
||||
|
||||
base:
|
||||
name: Base Artifact
|
||||
uses: ./.github/workflows/openapi-generate.yml
|
||||
needs:
|
||||
- ancestor
|
||||
with:
|
||||
ref: ${{ needs.ancestor.outputs.base_ref }}
|
||||
repository: ${{ github.event.pull_request.base.repo.full_name }}
|
||||
artifact: openapi-base
|
||||
|
||||
diff:
|
||||
name: Generate Report
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- head
|
||||
- base
|
||||
steps:
|
||||
- name: Download Head
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: openapi-head
|
||||
path: openapi-head
|
||||
- name: Download Base
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: openapi-base
|
||||
path: openapi-base
|
||||
- name: Detect Changes
|
||||
id: openapi-diff
|
||||
run: |
|
||||
sed -i 's:allOf:oneOf:g' openapi-head/openapi.json
|
||||
sed -i 's:allOf:oneOf:g' openapi-base/openapi.json
|
||||
|
||||
mkdir -p /tmp/openapi-report
|
||||
mv openapi-head/openapi.json /tmp/openapi-report/head.json
|
||||
mv openapi-base/openapi.json /tmp/openapi-report/base.json
|
||||
|
||||
docker run -v /tmp/openapi-report:/data openapitools/openapi-diff:2.1.6 /data/base.json /data/head.json --state -l ERROR --markdown /data/openapi-report.md
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: openapi-report
|
||||
path: /tmp/openapi-report/openapi-report.md
|
||||
59
.github/workflows/openapi-workflow-run.yml
vendored
59
.github/workflows/openapi-workflow-run.yml
vendored
@@ -1,59 +0,0 @@
|
||||
name: OpenAPI Report
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows:
|
||||
- OpenAPI Check
|
||||
types:
|
||||
- completed
|
||||
|
||||
jobs:
|
||||
metadata:
|
||||
name: Generate Metadata
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||
outputs:
|
||||
pr_number: ${{ steps.pr_number.outputs.pr_number }}
|
||||
steps:
|
||||
- name: Get Pull Request Number
|
||||
id: pr_number
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
|
||||
run: |
|
||||
API_RESPONSE=$(gh pr list --repo "${GITHUB_REPOSITORY}" --search "${HEAD_SHA}" --state open --json number)
|
||||
PR_NUMBER=$(echo "${API_RESPONSE}" | jq '.[0].number')
|
||||
|
||||
echo "repository: ${GITHUB_REPOSITORY}"
|
||||
echo "sha: ${HEAD_SHA}"
|
||||
echo "response: ${API_RESPONSE}"
|
||||
echo "pr: ${PR_NUMBER}"
|
||||
|
||||
echo "pr_number=${PR_NUMBER}" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
comment:
|
||||
name: Pull Request Comment
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||
needs:
|
||||
- metadata
|
||||
permissions:
|
||||
pull-requests: write
|
||||
actions: read
|
||||
contents: read
|
||||
steps:
|
||||
- name: Download OpenAPI Report
|
||||
id: download_report
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: openapi-report
|
||||
path: openapi-report
|
||||
run-id: ${{ github.event.workflow_run.id }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Push Comment
|
||||
uses: thollander/actions-comment-pull-request@24bffb9b452ba05a4f3f77933840a6a841d1b32b # v3.0.1
|
||||
with:
|
||||
github-token: ${{ secrets.JF_BOT_TOKEN }}
|
||||
file-path: ${{ steps.download_report.outputs.download-path }}/openapi-report.md
|
||||
pr-number: ${{ needs.metadata.outputs.pr_number }}
|
||||
comment-tag: openapi-report
|
||||
2
.github/workflows/release-bump-version.yaml
vendored
2
.github/workflows/release-bump-version.yaml
vendored
@@ -28,7 +28,7 @@ jobs:
|
||||
timeoutSeconds: 3600
|
||||
|
||||
- name: Setup YQ
|
||||
uses: chrisdickinson/setup-yq@fa3192edd79d6eb0e4e12de8dde3a0c26f2b853b # latest
|
||||
uses: chrisdickinson/setup-yq@latest
|
||||
with:
|
||||
yq-version: v4.9.8
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
# Jellyfin Contributors
|
||||
|
||||
- [0x25CBFC4F](https://github.com/0x25CBFC4F)
|
||||
- [1337joe](https://github.com/1337joe)
|
||||
- [97carmine](https://github.com/97carmine)
|
||||
- [Abbe98](https://github.com/Abbe98)
|
||||
@@ -15,7 +14,7 @@
|
||||
- [bilde2910](https://github.com/bilde2910)
|
||||
- [bfayers](https://github.com/bfayers)
|
||||
- [BnMcG](https://github.com/BnMcG)
|
||||
- [Bond_009](https://github.com/Bond-009)
|
||||
- [Bond-009](https://github.com/Bond-009)
|
||||
- [brianjmurrell](https://github.com/brianjmurrell)
|
||||
- [bugfixin](https://github.com/bugfixin)
|
||||
- [chaosinnovator](https://github.com/chaosinnovator)
|
||||
@@ -32,7 +31,6 @@
|
||||
- [DaveChild](https://github.com/DaveChild)
|
||||
- [DavidFair](https://github.com/DavidFair)
|
||||
- [Delgan](https://github.com/Delgan)
|
||||
- [DerMaddis](https://github.com/dermaddis)
|
||||
- [Derpipose](https://github.com/Derpipose)
|
||||
- [dcrdev](https://github.com/dcrdev)
|
||||
- [dhartung](https://github.com/dhartung)
|
||||
@@ -56,7 +54,6 @@
|
||||
- [geilername](https://github.com/geilername)
|
||||
- [GermanCoding](https://github.com/GermanCoding)
|
||||
- [gnattu](https://github.com/gnattu)
|
||||
- [gnuyent](https://github.com/gnuyent)
|
||||
- [GodTamIt](https://github.com/GodTamIt)
|
||||
- [grafixeyehero](https://github.com/grafixeyehero)
|
||||
- [h1nk](https://github.com/h1nk)
|
||||
@@ -64,7 +61,6 @@
|
||||
- [HelloWorld017](https://github.com/HelloWorld017)
|
||||
- [ikomhoog](https://github.com/ikomhoog)
|
||||
- [iwalton3](https://github.com/iwalton3)
|
||||
- [Jakob Kukla](https://github.com/jakobkukla)
|
||||
- [jftuga](https://github.com/jftuga)
|
||||
- [jkhsjdhjs](https://github.com/jkhsjdhjs)
|
||||
- [jmshrv](https://github.com/jmshrv)
|
||||
@@ -73,10 +69,8 @@
|
||||
- [JustAMan](https://github.com/JustAMan)
|
||||
- [justinfenn](https://github.com/justinfenn)
|
||||
- [JPVenson](https://github.com/JPVenson)
|
||||
- [JPUC1143](https://github.com/Jpuc1143/)
|
||||
- [KerryRJ](https://github.com/KerryRJ)
|
||||
- [Larvitar](https://github.com/Larvitar)
|
||||
- [lbenini](https://github.com/lbenini)
|
||||
- [LeoVerto](https://github.com/LeoVerto)
|
||||
- [Liggy](https://github.com/Liggy)
|
||||
- [lmaonator](https://github.com/lmaonator)
|
||||
@@ -89,19 +83,15 @@
|
||||
- [marius-luca-87](https://github.com/marius-luca-87)
|
||||
- [mark-monteiro](https://github.com/mark-monteiro)
|
||||
- [MarkCiliaVincenti](https://github.com/MarkCiliaVincenti)
|
||||
- [Martin Reuter](https://github.com/reuterma24)
|
||||
- [Matt07211](https://github.com/Matt07211)
|
||||
- [Matthew Jones](https://github.com/matthew-jones-uk)
|
||||
- [Maxr1998](https://github.com/Maxr1998)
|
||||
- [mcarlton00](https://github.com/mcarlton00)
|
||||
- [Michael McElroy](https://github.com/mcmcelro)
|
||||
- [mitchfizz05](https://github.com/mitchfizz05)
|
||||
- [mohd-akram](https://github.com/mohd-akram)
|
||||
- [MrTimscampi](https://github.com/MrTimscampi)
|
||||
- [n8225](https://github.com/n8225)
|
||||
- [Nalsai](https://github.com/Nalsai)
|
||||
- [Narfinger](https://github.com/Narfinger)
|
||||
- [Nathan McCrina](https://github.com/nfmccrina)
|
||||
- [NathanPickard](https://github.com/NathanPickard)
|
||||
- [neilsb](https://github.com/neilsb)
|
||||
- [nevado](https://github.com/nevado)
|
||||
@@ -112,7 +102,6 @@
|
||||
- [OancaAndrei](https://github.com/OancaAndrei)
|
||||
- [obradovichv](https://github.com/obradovichv)
|
||||
- [oddstr13](https://github.com/oddstr13)
|
||||
- [olsh](https://github.com/olsh)
|
||||
- [orryverducci](https://github.com/orryverducci)
|
||||
- [petermcneil](https://github.com/petermcneil)
|
||||
- [Phlogi](https://github.com/Phlogi)
|
||||
@@ -123,7 +112,6 @@
|
||||
- [RazeLighter777](https://github.com/RazeLighter777)
|
||||
- [redSpoutnik](https://github.com/redSpoutnik)
|
||||
- [ringmatter](https://github.com/ringmatter)
|
||||
- [Robert Lützner](https://github.com/rluetzner)
|
||||
- [ryan-hartzell](https://github.com/ryan-hartzell)
|
||||
- [s0urcelab](https://github.com/s0urcelab)
|
||||
- [sachk](https://github.com/sachk)
|
||||
@@ -139,7 +127,6 @@
|
||||
- [sl1288](https://github.com/sl1288)
|
||||
- [Smith00101010](https://github.com/Smith00101010)
|
||||
- [sorinyo2004](https://github.com/sorinyo2004)
|
||||
- [Soumyadip Auddy](https://github.com/SoumyadipAuddy)
|
||||
- [sparky8251](https://github.com/sparky8251)
|
||||
- [spookbits](https://github.com/spookbits)
|
||||
- [ssenart](https://github.com/ssenart)
|
||||
@@ -162,7 +149,6 @@
|
||||
- [twinkybot](https://github.com/twinkybot)
|
||||
- [Ullmie02](https://github.com/Ullmie02)
|
||||
- [Unhelpful](https://github.com/Unhelpful)
|
||||
- [Utku Özdemir](https://github.com/utkuozdemir)
|
||||
- [viaregio](https://github.com/viaregio)
|
||||
- [vitorsemeano](https://github.com/vitorsemeano)
|
||||
- [voodoos](https://github.com/voodoos)
|
||||
@@ -178,7 +164,6 @@
|
||||
- [XVicarious](https://github.com/XVicarious)
|
||||
- [YouKnowBlom](https://github.com/YouKnowBlom)
|
||||
- [ZachPhelan](https://github.com/ZachPhelan)
|
||||
- [ZeusCraft10](https://github.com/ZeusCraft10)
|
||||
- [KristupasSavickas](https://github.com/KristupasSavickas)
|
||||
- [Pusta](https://github.com/pusta)
|
||||
- [nielsvanvelzen](https://github.com/nielsvanvelzen)
|
||||
@@ -226,9 +211,6 @@
|
||||
- [martenumberto](https://github.com/martenumberto)
|
||||
- [ZeusCraft10](https://github.com/ZeusCraft10)
|
||||
- [MarcoCoreDuo](https://github.com/MarcoCoreDuo)
|
||||
- [LiHRaM](https://github.com/LiHRaM)
|
||||
- [MSalman5230](https://github.com/MSalman5230)
|
||||
- [dwandw](https://github.com/dwandw)
|
||||
|
||||
# Emby Contributors
|
||||
|
||||
@@ -292,3 +274,17 @@
|
||||
- [tikuf](https://github.com/tikuf/)
|
||||
- [Tim Hobbs](https://github.com/timhobbs)
|
||||
- [SvenVandenbrande](https://github.com/SvenVandenbrande)
|
||||
- [olsh](https://github.com/olsh)
|
||||
- [lbenini](https://github.com/lbenini)
|
||||
- [gnuyent](https://github.com/gnuyent)
|
||||
- [Matthew Jones](https://github.com/matthew-jones-uk)
|
||||
- [Jakob Kukla](https://github.com/jakobkukla)
|
||||
- [Utku Özdemir](https://github.com/utkuozdemir)
|
||||
- [JPUC1143](https://github.com/Jpuc1143/)
|
||||
- [0x25CBFC4F](https://github.com/0x25CBFC4F)
|
||||
- [Robert Lützner](https://github.com/rluetzner)
|
||||
- [Nathan McCrina](https://github.com/nfmccrina)
|
||||
- [Martin Reuter](https://github.com/reuterma24)
|
||||
- [Michael McElroy](https://github.com/mcmcelro)
|
||||
- [Soumyadip Auddy](https://github.com/SoumyadipAuddy)
|
||||
- [DerMaddis](https://github.com/dermaddis)
|
||||
|
||||
@@ -6,48 +6,48 @@
|
||||
<ItemGroup Label="Package Dependencies">
|
||||
<PackageVersion Include="AsyncKeyedLock" Version="8.0.2" />
|
||||
<PackageVersion Include="AutoFixture.AutoMoq" Version="4.18.1" />
|
||||
<PackageVersion Include="AutoFixture.Xunit3" Version="4.19.0" />
|
||||
<PackageVersion Include="AutoFixture.Xunit2" Version="4.18.1" />
|
||||
<PackageVersion Include="AutoFixture" Version="4.18.1" />
|
||||
<PackageVersion Include="BDInfo" Version="0.8.0" />
|
||||
<PackageVersion Include="BitFaster.Caching" Version="2.5.4" />
|
||||
<PackageVersion Include="BlurHashSharp.SkiaSharp" Version="1.4.0-pre.1" />
|
||||
<PackageVersion Include="BlurHashSharp" Version="1.4.0-pre.1" />
|
||||
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
|
||||
<PackageVersion Include="coverlet.collector" Version="10.0.0" />
|
||||
<PackageVersion Include="Diacritics" Version="4.1.8" />
|
||||
<PackageVersion Include="coverlet.collector" Version="8.0.1" />
|
||||
<PackageVersion Include="Diacritics" Version="4.1.4" />
|
||||
<PackageVersion Include="DiscUtils.Udf" Version="0.16.13" />
|
||||
<PackageVersion Include="DotNet.Glob" Version="3.1.3" />
|
||||
<PackageVersion Include="FsCheck.Xunit.v3" Version="3.3.3" />
|
||||
<PackageVersion Include="FsCheck.Xunit" Version="3.3.2" />
|
||||
<PackageVersion Include="HarfBuzzSharp.NativeAssets.Linux" Version="8.3.1.1" />
|
||||
<PackageVersion Include="ICU4N.Transliterator" Version="60.1.0-alpha.356" />
|
||||
<PackageVersion Include="IDisposableAnalyzers" Version="4.0.8" />
|
||||
<PackageVersion Include="Ignore" Version="0.2.1" />
|
||||
<PackageVersion Include="Jellyfin.XmlTv" Version="10.12.0-pre1" />
|
||||
<PackageVersion Include="Jellyfin.XmlTv" Version="10.8.0" />
|
||||
<PackageVersion Include="libse" Version="4.0.12" />
|
||||
<PackageVersion Include="LrcParser" Version="2025.623.0" />
|
||||
<PackageVersion Include="MetaBrainz.MusicBrainz" Version="8.0.1" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Authorization" Version="10.0.7" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.7" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Authorization" Version="10.0.5" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.5" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="4.14.0" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.Common" Version="5.3.0" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="5.3.0" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="5.3.0" />
|
||||
<PackageVersion Include="Microsoft.Data.Sqlite" Version="10.0.7" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.7" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.7" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.7" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.7" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="10.0.7" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="10.0.7" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.7" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="10.0.7" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.7" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="10.0.7" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="10.0.7" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Http" Version="10.0.7" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="10.0.7" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Options" Version="10.0.7" />
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.5.1" />
|
||||
<PackageVersion Include="Microsoft.Data.Sqlite" Version="10.0.5" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.5" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.5" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.5" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.5" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="10.0.5" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="10.0.5" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.5" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="10.0.5" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.5" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="10.0.5" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="10.0.5" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Http" Version="10.0.5" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="10.0.5" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Options" Version="10.0.5" />
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
|
||||
<PackageVersion Include="MimeTypes" Version="2.5.2" />
|
||||
<PackageVersion Include="Morestachio" Version="5.0.1.631" />
|
||||
<PackageVersion Include="Moq" Version="4.18.4" />
|
||||
@@ -75,15 +75,16 @@
|
||||
<PackageVersion Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" />
|
||||
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
|
||||
<PackageVersion Include="Svg.Skia" Version="3.4.1" />
|
||||
<PackageVersion Include="Swashbuckle.AspNetCore.ReDoc" Version="10.1.7" />
|
||||
<PackageVersion Include="Swashbuckle.AspNetCore" Version="10.1.7" />
|
||||
<PackageVersion Include="System.Text.Json" Version="10.0.7" />
|
||||
<PackageVersion Include="Swashbuckle.AspNetCore.ReDoc" Version="10.1.5" />
|
||||
<PackageVersion Include="Swashbuckle.AspNetCore" Version="10.1.5" />
|
||||
<PackageVersion Include="System.Text.Json" Version="10.0.5" />
|
||||
<PackageVersion Include="TagLibSharp" Version="2.3.0" />
|
||||
<PackageVersion Include="z440.atl.core" Version="7.13.0" />
|
||||
<PackageVersion Include="z440.atl.core" Version="7.11.0" />
|
||||
<PackageVersion Include="TMDbLib" Version="3.0.0" />
|
||||
<PackageVersion Include="UTF.Unknown" Version="2.6.0" />
|
||||
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
|
||||
<PackageVersion Include="xunit.v3" Version="3.2.2" />
|
||||
<PackageVersion Include="Xunit.v3.Priority" Version="1.1.18" />
|
||||
<PackageVersion Include="Xunit.Priority" Version="1.1.6" />
|
||||
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||
<PackageVersion Include="Xunit.SkippableFact" Version="1.5.61" />
|
||||
<PackageVersion Include="xunit" Version="2.9.3" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -152,8 +152,8 @@ namespace Emby.Naming.Common
|
||||
|
||||
CleanStrings =
|
||||
[
|
||||
@"^\s*(?<cleaned>.+?)[ _\,\.\(\)\[\]\-](3d|sbs|tab|hsbs|htab|mvc|HDR|HDC|UHD|UltraHD|4k|ac3|dts|custom|dc|divx|divx5|dsr|dsrip|dutch|dvd|dvdrip|dvdscr|dvdscreener|screener|dvdivx|cam|fragment|fs|hdtv|hdrip|hdtvrip|internal|limited|multi|subs|ntsc|ogg|ogm|pal|pdtv|proper|repack|rerip|retail|cd[1-9]|r5|bd5|bd|se|svcd|swedish|german|read.nfo|nfofix|unrated|ws|telesync|ts|telecine|tc|brrip|bdrip|480p|480i|576p|576i|720p|720i|1080p|1080i|2160p|hrhd|hrhdtv|hddvd|bluray|blu-ray|x264|x265|h264|h265|xvid|xvidvd|xxx|www.www|AAC|DTS)(?=[ _\,\.\(\)\[\]\-]|$)",
|
||||
@"^\s*(?<cleaned>.+?)((\s*\[[^\]]+\]\s*)+)(\.[^\s]+)?$",
|
||||
@"^\s*(?<cleaned>.+?)[ _\,\.\(\)\[\]\-](3d|sbs|tab|hsbs|htab|mvc|HDR|HDC|UHD|UltraHD|4k|ac3|dts|custom|dc|divx|divx5|dsr|dsrip|dutch|dvd|dvdrip|dvdscr|dvdscreener|screener|dvdivx|cam|fragment|fs|hdtv|hdrip|hdtvrip|internal|limited|multi|subs|ntsc|ogg|ogm|pal|pdtv|proper|repack|rerip|retail|cd[1-9]|r5|bd5|bd|se|svcd|swedish|german|read.nfo|nfofix|unrated|ws|telesync|ts|telecine|tc|brrip|bdrip|480p|480i|576p|576i|720p|720i|1080p|1080i|2160p|hrhd|hrhdtv|hddvd|bluray|blu-ray|x264|x265|h264|h265|xvid|xvidvd|xxx|www.www|AAC|DTS|\[.*\])([ _\,\.\(\)\[\]\-]|$)",
|
||||
@"^(?<cleaned>.+?)(\[.*\])",
|
||||
@"^\s*(?<cleaned>.+?)\WE[0-9]+(-|~)E?[0-9]+(\W|$)",
|
||||
@"^\s*\[[^\]]+\](?!\.\w+$)\s*(?<cleaned>.+)",
|
||||
@"^\s*(?<cleaned>.+?)\s+-\s+[0-9]+\s*$",
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace Emby.Naming.Video
|
||||
var match = expression.Match(name);
|
||||
if (match.Success && match.Groups.TryGetValue("cleaned", out var cleaned))
|
||||
{
|
||||
newName = cleaned.Value.Trim();
|
||||
newName = cleaned.Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -217,8 +217,6 @@ namespace Emby.Naming.Video
|
||||
// The CleanStringParser should have removed common keywords etc.
|
||||
return testFilename.IsEmpty
|
||||
|| testFilename[0] == '-'
|
||||
|| testFilename[0] == '_'
|
||||
|| testFilename[0] == '.'
|
||||
|| CheckMultiVersionRegex().IsMatch(testFilename);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -507,13 +507,7 @@ namespace Emby.Server.Implementations
|
||||
|
||||
serviceCollection.AddSingleton<IUserDataManager, UserDataManager>();
|
||||
|
||||
serviceCollection.AddSingleton<BaseItemRepository>();
|
||||
serviceCollection.AddSingleton<IItemRepository>(sp => sp.GetRequiredService<BaseItemRepository>());
|
||||
serviceCollection.AddSingleton<IItemQueryHelpers>(sp => sp.GetRequiredService<BaseItemRepository>());
|
||||
serviceCollection.AddSingleton<IItemPersistenceService, ItemPersistenceService>();
|
||||
serviceCollection.AddSingleton<INextUpService, NextUpService>();
|
||||
serviceCollection.AddSingleton<IItemCountService, ItemCountService>();
|
||||
serviceCollection.AddSingleton<ILinkedChildrenService, LinkedChildrenService>();
|
||||
serviceCollection.AddSingleton<IItemRepository, BaseItemRepository>();
|
||||
serviceCollection.AddSingleton<IPeopleRepository, PeopleRepository>();
|
||||
serviceCollection.AddSingleton<IChapterRepository, ChapterRepository>();
|
||||
serviceCollection.AddSingleton<IMediaAttachmentRepository, MediaAttachmentRepository>();
|
||||
@@ -647,7 +641,6 @@ namespace Emby.Server.Implementations
|
||||
BaseItem.ConfigurationManager = ConfigurationManager;
|
||||
BaseItem.FileSystem = Resolve<IFileSystem>();
|
||||
BaseItem.ItemRepository = Resolve<IItemRepository>();
|
||||
BaseItem.ItemCountService = Resolve<IItemCountService>();
|
||||
BaseItem.LibraryManager = Resolve<ILibraryManager>();
|
||||
BaseItem.LocalizationManager = Resolve<ILocalizationManager>();
|
||||
BaseItem.Logger = Resolve<ILogger<BaseItem>>();
|
||||
|
||||
@@ -7,7 +7,6 @@ using System.Threading.Tasks;
|
||||
using Jellyfin.Extensions;
|
||||
using MediaBrowser.Controller.Chapters;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.MediaEncoding;
|
||||
@@ -233,22 +232,12 @@ public class ChapterManager : IChapterManager
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Supports(BaseItem item)
|
||||
=> item is Video or Audio;
|
||||
|
||||
/// <inheritdoc />
|
||||
public void SaveChapters(BaseItem item, IReadOnlyList<ChapterInfo> chapters)
|
||||
public void SaveChapters(Video video, IReadOnlyList<ChapterInfo> chapters)
|
||||
{
|
||||
if (!Supports(item))
|
||||
{
|
||||
_logger.LogWarning("Attempted to save chapters for unsupported item type {Type}: {Name} ({Id})", item.GetType().Name, item.Name, item.Id);
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove any chapters that are outside of the runtime of the item
|
||||
var validChapters = chapters.Where(c => c.StartPositionTicks < item.RunTimeTicks).ToList();
|
||||
_chapterRepository.SaveChapters(item.Id, validChapters);
|
||||
}
|
||||
// Remove any chapters that are outside of the runtime of the video
|
||||
var validChapters = chapters.Where(c => c.StartPositionTicks < video.RunTimeTicks).ToList();
|
||||
_chapterRepository.SaveChapters(video.Id, validChapters);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ChapterInfo? GetChapter(Guid baseItemId, int index)
|
||||
|
||||
@@ -272,7 +272,7 @@ namespace Emby.Server.Implementations.Collections
|
||||
{
|
||||
var childItem = _libraryManager.GetItemById(guidId);
|
||||
|
||||
var child = collection.LinkedChildren.FirstOrDefault(i => i.ItemId.HasValue && i.ItemId.Value.Equals(guidId));
|
||||
var child = collection.LinkedChildren.FirstOrDefault(i => (i.ItemId.HasValue && i.ItemId.Value.Equals(guidId)) || (childItem is not null && string.Equals(childItem.Path, i.Path, StringComparison.OrdinalIgnoreCase)));
|
||||
|
||||
if (child is null)
|
||||
{
|
||||
@@ -342,7 +342,7 @@ namespace Emby.Server.Implementations.Collections
|
||||
// this is kind of a performance hack because only Video has alternate versions that should be in a box set?
|
||||
if (item is Video video)
|
||||
{
|
||||
foreach (var childId in _libraryManager.GetLocalAlternateVersionIds(video))
|
||||
foreach (var childId in video.GetLocalAlternateVersionIds())
|
||||
{
|
||||
if (!results.ContainsKey(childId))
|
||||
{
|
||||
|
||||
@@ -5,12 +5,10 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Jellyfin.Data.Enums;
|
||||
using Jellyfin.Database.Implementations;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Playlists;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
@@ -37,11 +35,7 @@ public class CleanDatabaseScheduledTask : ILibraryPostScanTask
|
||||
|
||||
public async Task Run(IProgress<double> progress, CancellationToken cancellationToken)
|
||||
{
|
||||
var deadItemsProgress = new Progress<double>(val => progress.Report(val * 0.8));
|
||||
await CleanDeadItems(cancellationToken, deadItemsProgress).ConfigureAwait(false);
|
||||
|
||||
var playlistProgress = new Progress<double>(val => progress.Report(80 + (val * 0.2)));
|
||||
await CleanOrphanedFilePlaylistsAsync(cancellationToken, playlistProgress).ConfigureAwait(false);
|
||||
await CleanDeadItems(cancellationToken, progress).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task CleanDeadItems(CancellationToken cancellationToken, IProgress<double> progress)
|
||||
@@ -122,32 +116,4 @@ public class CleanDatabaseScheduledTask : ILibraryPostScanTask
|
||||
|
||||
progress.Report(100);
|
||||
}
|
||||
|
||||
private async Task CleanOrphanedFilePlaylistsAsync(CancellationToken cancellationToken, IProgress<double> progress)
|
||||
{
|
||||
var playlists = _libraryManager.GetItemList(new InternalItemsQuery
|
||||
{
|
||||
IncludeItemTypes = [BaseItemKind.Playlist],
|
||||
Recursive = true
|
||||
}).OfType<Playlist>().ToList();
|
||||
|
||||
var numComplete = 0;
|
||||
var numItems = Math.Max(playlists.Count, 1);
|
||||
|
||||
foreach (var playlist in playlists)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (playlist.IsFile && !File.Exists(playlist.Path))
|
||||
{
|
||||
_logger.LogInformation("Removing file-based playlist {Name} because source file {Path} no longer exists", playlist.Name, playlist.Path);
|
||||
_libraryManager.DeleteItem(playlist, new DeleteOptions { DeleteFileLocation = false });
|
||||
}
|
||||
|
||||
numComplete++;
|
||||
progress.Report((double)numComplete / numItems * 100);
|
||||
}
|
||||
|
||||
progress.Report(100);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,68 +153,17 @@ namespace Emby.Server.Implementations.Dto
|
||||
private ILiveTvManager LivetvManager => _livetvManagerFactory.Value;
|
||||
|
||||
/// <inheritdoc />
|
||||
public IReadOnlyList<BaseItemDto> GetBaseItemDtos(
|
||||
IReadOnlyList<BaseItem> items,
|
||||
DtoOptions options,
|
||||
User? user = null,
|
||||
BaseItem? owner = null,
|
||||
bool skipVisibilityCheck = false)
|
||||
public IReadOnlyList<BaseItemDto> GetBaseItemDtos(IReadOnlyList<BaseItem> items, DtoOptions options, User? user = null, BaseItem? owner = null)
|
||||
{
|
||||
var accessibleItems = skipVisibilityCheck || user is null ? items : items.Where(x => x.IsVisible(user)).ToList();
|
||||
var accessibleItems = user is null ? items : items.Where(x => x.IsVisible(user)).ToList();
|
||||
var returnItems = new BaseItemDto[accessibleItems.Count];
|
||||
List<(BaseItem, BaseItemDto)>? programTuples = null;
|
||||
List<(BaseItemDto, LiveTvChannel)>? channelTuples = null;
|
||||
|
||||
// Batch-fetch user data for all items
|
||||
Dictionary<Guid, UserItemData>? userDataBatch = null;
|
||||
if (user is not null && options.EnableUserData)
|
||||
{
|
||||
userDataBatch = _userDataRepository.GetUserDataBatch(accessibleItems, user);
|
||||
}
|
||||
|
||||
// Pre-compute collection folders once to avoid N+1 queries in CanDelete
|
||||
List<Folder>? allCollectionFolders = null;
|
||||
if (user is not null && options.ContainsField(ItemFields.CanDelete))
|
||||
{
|
||||
allCollectionFolders = _libraryManager.GetUserRootFolder().Children.OfType<Folder>().ToList();
|
||||
}
|
||||
|
||||
// Batch-fetch child counts for all folders to avoid N+1 queries
|
||||
Dictionary<Guid, int>? childCountBatch = null;
|
||||
if (options.ContainsField(ItemFields.ChildCount))
|
||||
{
|
||||
var folderIds = accessibleItems.OfType<Folder>().Select(f => f.Id).ToList();
|
||||
if (folderIds.Count > 0)
|
||||
{
|
||||
childCountBatch = _libraryManager.GetChildCountBatch(folderIds, user?.Id);
|
||||
}
|
||||
}
|
||||
|
||||
// Batch-fetch played/total counts for all folders to avoid N+1 queries
|
||||
Dictionary<Guid, (int Played, int Total)>? playedCountBatch = null;
|
||||
if (user is not null && options.EnableUserData)
|
||||
{
|
||||
var folderIds = accessibleItems.OfType<Folder>()
|
||||
.Where(f => f.SupportsUserDataFromChildren && (f.SupportsPlayedStatus || options.ContainsField(ItemFields.RecursiveItemCount)))
|
||||
.Select(f => f.Id).ToList();
|
||||
if (folderIds.Count > 0)
|
||||
{
|
||||
playedCountBatch = _libraryManager.GetPlayedAndTotalCountBatch(folderIds, user);
|
||||
}
|
||||
}
|
||||
|
||||
for (int index = 0; index < accessibleItems.Count; index++)
|
||||
{
|
||||
var item = accessibleItems[index];
|
||||
var dto = GetBaseItemDtoInternal(
|
||||
item,
|
||||
options,
|
||||
user,
|
||||
owner,
|
||||
userDataBatch?.GetValueOrDefault(item.Id),
|
||||
allCollectionFolders,
|
||||
childCountBatch,
|
||||
playedCountBatch);
|
||||
var dto = GetBaseItemDtoInternal(item, options, user, owner);
|
||||
|
||||
if (item is LiveTvChannel tvChannel)
|
||||
{
|
||||
@@ -248,7 +197,7 @@ namespace Emby.Server.Implementations.Dto
|
||||
|
||||
public BaseItemDto GetBaseItemDto(BaseItem item, DtoOptions options, User? user = null, BaseItem? owner = null)
|
||||
{
|
||||
var dto = GetBaseItemDtoInternal(item, options, user, owner, null);
|
||||
var dto = GetBaseItemDtoInternal(item, options, user, owner);
|
||||
if (item is LiveTvChannel tvChannel)
|
||||
{
|
||||
LivetvManager.AddChannelInfo(new[] { (dto, tvChannel) }, options, user);
|
||||
@@ -266,15 +215,7 @@ namespace Emby.Server.Implementations.Dto
|
||||
return dto;
|
||||
}
|
||||
|
||||
private BaseItemDto GetBaseItemDtoInternal(
|
||||
BaseItem item,
|
||||
DtoOptions options,
|
||||
User? user = null,
|
||||
BaseItem? owner = null,
|
||||
UserItemData? userData = null,
|
||||
List<Folder>? allCollectionFolders = null,
|
||||
Dictionary<Guid, int>? childCountBatch = null,
|
||||
Dictionary<Guid, (int Played, int Total)>? playedCountBatch = null)
|
||||
private BaseItemDto GetBaseItemDtoInternal(BaseItem item, DtoOptions options, User? user = null, BaseItem? owner = null)
|
||||
{
|
||||
var dto = new BaseItemDto
|
||||
{
|
||||
@@ -311,14 +252,7 @@ namespace Emby.Server.Implementations.Dto
|
||||
|
||||
if (user is not null)
|
||||
{
|
||||
AttachUserSpecificInfo(
|
||||
dto,
|
||||
item,
|
||||
user,
|
||||
options,
|
||||
userData,
|
||||
childCountBatch,
|
||||
playedCountBatch);
|
||||
AttachUserSpecificInfo(dto, item, user, options);
|
||||
}
|
||||
|
||||
if (item is IHasMediaSources
|
||||
@@ -340,9 +274,7 @@ namespace Emby.Server.Implementations.Dto
|
||||
{
|
||||
dto.CanDelete = user is null
|
||||
? item.CanDelete()
|
||||
: allCollectionFolders is not null
|
||||
? item.CanDelete(user, allCollectionFolders)
|
||||
: item.CanDelete(user);
|
||||
: item.CanDelete(user);
|
||||
}
|
||||
|
||||
if (options.ContainsField(ItemFields.CanDownload))
|
||||
@@ -446,7 +378,37 @@ namespace Emby.Server.Implementations.Dto
|
||||
return;
|
||||
}
|
||||
|
||||
var counts = _libraryManager.GetItemCountsForNameItem(dto.Type, dto.Id, relatedItemKinds, user);
|
||||
var query = new InternalItemsQuery(user)
|
||||
{
|
||||
Recursive = true,
|
||||
DtoOptions = new DtoOptions(false) { EnableImages = false },
|
||||
IncludeItemTypes = relatedItemKinds
|
||||
};
|
||||
|
||||
switch (dto.Type)
|
||||
{
|
||||
case BaseItemKind.Genre:
|
||||
case BaseItemKind.MusicGenre:
|
||||
query.GenreIds = [dto.Id];
|
||||
break;
|
||||
case BaseItemKind.MusicArtist:
|
||||
query.ArtistIds = [dto.Id];
|
||||
break;
|
||||
case BaseItemKind.Person:
|
||||
query.PersonIds = [dto.Id];
|
||||
break;
|
||||
case BaseItemKind.Studio:
|
||||
query.StudioIds = [dto.Id];
|
||||
break;
|
||||
case BaseItemKind.Year
|
||||
when int.TryParse(dto.Name, NumberStyles.Integer, CultureInfo.InvariantCulture, out var year):
|
||||
query.Years = [year];
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
var counts = _libraryManager.GetItemCounts(query);
|
||||
|
||||
dto.AlbumCount = counts.AlbumCount;
|
||||
dto.ArtistCount = counts.ArtistCount;
|
||||
@@ -496,14 +458,7 @@ namespace Emby.Server.Implementations.Dto
|
||||
/// <summary>
|
||||
/// Attaches the user specific info.
|
||||
/// </summary>
|
||||
private void AttachUserSpecificInfo(
|
||||
BaseItemDto dto,
|
||||
BaseItem item,
|
||||
User user,
|
||||
DtoOptions options,
|
||||
UserItemData? userData = null,
|
||||
Dictionary<Guid, int>? childCountBatch = null,
|
||||
Dictionary<Guid, (int Played, int Total)>? playedCountBatch = null)
|
||||
private void AttachUserSpecificInfo(BaseItemDto dto, BaseItem item, User user, DtoOptions options)
|
||||
{
|
||||
if (item.IsFolder)
|
||||
{
|
||||
@@ -511,19 +466,7 @@ namespace Emby.Server.Implementations.Dto
|
||||
|
||||
if (options.EnableUserData)
|
||||
{
|
||||
if (userData is not null)
|
||||
{
|
||||
// Use pre-fetched user data
|
||||
dto.UserData = GetUserItemDataDto(userData, item.Id);
|
||||
(int Played, int Total)? precomputed = playedCountBatch is not null
|
||||
&& playedCountBatch.TryGetValue(item.Id, out var counts) ? counts : null;
|
||||
item.FillUserDataDtoValues(dto.UserData, userData, dto, user, options, precomputed);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fall back to individual fetch
|
||||
dto.UserData = _userDataRepository.GetUserDataDto(item, dto, user, options);
|
||||
}
|
||||
dto.UserData = _userDataRepository.GetUserDataDto(item, dto, user, options);
|
||||
}
|
||||
|
||||
if (!dto.ChildCount.HasValue && item.SourceType == SourceType.Library)
|
||||
@@ -542,7 +485,7 @@ namespace Emby.Server.Implementations.Dto
|
||||
|
||||
if (options.ContainsField(ItemFields.ChildCount))
|
||||
{
|
||||
dto.ChildCount ??= GetChildCount(folder, user, childCountBatch);
|
||||
dto.ChildCount ??= GetChildCount(folder, user);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -560,17 +503,7 @@ namespace Emby.Server.Implementations.Dto
|
||||
{
|
||||
if (options.EnableUserData)
|
||||
{
|
||||
if (userData is not null)
|
||||
{
|
||||
// Use pre-fetched user data
|
||||
dto.UserData = GetUserItemDataDto(userData, item.Id);
|
||||
item.FillUserDataDtoValues(dto.UserData, userData, dto, user, options);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fall back to individual fetch
|
||||
dto.UserData = _userDataRepository.GetUserDataDto(item, user);
|
||||
}
|
||||
dto.UserData = _userDataRepository.GetUserDataDto(item, user);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -580,25 +513,7 @@ namespace Emby.Server.Implementations.Dto
|
||||
}
|
||||
}
|
||||
|
||||
private static UserItemDataDto GetUserItemDataDto(UserItemData data, Guid itemId)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(data);
|
||||
|
||||
return new UserItemDataDto
|
||||
{
|
||||
IsFavorite = data.IsFavorite,
|
||||
Likes = data.Likes,
|
||||
PlaybackPositionTicks = data.PlaybackPositionTicks,
|
||||
PlayCount = data.PlayCount,
|
||||
Rating = data.Rating,
|
||||
Played = data.Played,
|
||||
LastPlayedDate = data.LastPlayedDate,
|
||||
ItemId = itemId,
|
||||
Key = data.Key
|
||||
};
|
||||
}
|
||||
|
||||
private static int GetChildCount(Folder folder, User user, Dictionary<Guid, int>? childCountBatch)
|
||||
private static int GetChildCount(Folder folder, User user)
|
||||
{
|
||||
// Right now this is too slow to calculate for top level folders on a per-user basis
|
||||
// Just return something so that apps that are expecting a value won't think the folders are empty
|
||||
@@ -607,13 +522,6 @@ namespace Emby.Server.Implementations.Dto
|
||||
return Random.Shared.Next(1, 10);
|
||||
}
|
||||
|
||||
// Use pre-fetched batch data if available
|
||||
if (childCountBatch is not null && childCountBatch.TryGetValue(folder.Id, out var count))
|
||||
{
|
||||
return count;
|
||||
}
|
||||
|
||||
// Fall back to individual query for special cases (Series, Season, etc.)
|
||||
return folder.GetChildCount(user);
|
||||
}
|
||||
|
||||
@@ -1111,15 +1019,6 @@ namespace Emby.Server.Implementations.Dto
|
||||
{
|
||||
dto.AlbumId = albumParent.Id;
|
||||
dto.AlbumPrimaryImageTag = GetTagAndFillBlurhash(dto, albumParent, ImageType.Primary);
|
||||
if (albumParent.LUFS.HasValue)
|
||||
{
|
||||
// -18 LUFS reference, same as ReplayGain 2.0, compatible with ReplayGain 1.0
|
||||
dto.AlbumNormalizationGain = -18f - albumParent.LUFS;
|
||||
}
|
||||
else if (albumParent.NormalizationGain.HasValue)
|
||||
{
|
||||
dto.AlbumNormalizationGain = albumParent.NormalizationGain;
|
||||
}
|
||||
}
|
||||
|
||||
// if (options.ContainsField(ItemFields.MediaSourceCount))
|
||||
@@ -1224,6 +1123,11 @@ namespace Emby.Server.Implementations.Dto
|
||||
}
|
||||
}
|
||||
|
||||
if (options.ContainsField(ItemFields.Chapters))
|
||||
{
|
||||
dto.Chapters = _chapterManager.GetChapters(item.Id).ToList();
|
||||
}
|
||||
|
||||
if (options.ContainsField(ItemFields.Trickplay))
|
||||
{
|
||||
var trickplay = _trickplayManager.GetTrickplayManifest(item).GetAwaiter().GetResult();
|
||||
@@ -1237,11 +1141,6 @@ namespace Emby.Server.Implementations.Dto
|
||||
dto.ExtraType = video.ExtraType;
|
||||
}
|
||||
|
||||
if (options.ContainsField(ItemFields.Chapters))
|
||||
{
|
||||
dto.Chapters = _chapterManager.GetChapters(item.Id).ToList();
|
||||
}
|
||||
|
||||
if (options.ContainsField(ItemFields.MediaStreams))
|
||||
{
|
||||
// Add VideoInfo
|
||||
|
||||
@@ -60,7 +60,6 @@ namespace Emby.Server.Implementations.IO
|
||||
_fileSystem = fileSystem;
|
||||
|
||||
appLifetime.ApplicationStarted.Register(Start);
|
||||
appLifetime.ApplicationStopping.Register(Stop);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -586,12 +586,6 @@ namespace Emby.Server.Implementations.IO
|
||||
/// <inheritdoc />
|
||||
public virtual IEnumerable<FileSystemMetadata> GetFiles(string path, string searchPattern, IReadOnlyList<string>? extensions, bool enableCaseSensitiveExtensions, bool recursive = false)
|
||||
{
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
_logger.LogWarning("Directory does not exist: {Path}", path);
|
||||
return [];
|
||||
}
|
||||
|
||||
var enumerationOptions = GetEnumerationOptions(recursive);
|
||||
|
||||
// On linux and macOS the search pattern is case-sensitive
|
||||
|
||||
@@ -31,20 +31,6 @@ namespace Emby.Server.Implementations.Library
|
||||
"**/*.sample.?????",
|
||||
"**/sample/*",
|
||||
|
||||
// Avoid adding Hungarian sample files
|
||||
// https://github.com/jellyfin/jellyfin/issues/16237
|
||||
"**/minta.?",
|
||||
"**/minta.??",
|
||||
"**/minta.???", // Matches minta.mkv
|
||||
"**/minta.????", // Matches minta.webm
|
||||
"**/minta.?????",
|
||||
"**/*.minta.?",
|
||||
"**/*.minta.??",
|
||||
"**/*.minta.???",
|
||||
"**/*.minta.????",
|
||||
"**/*.minta.?????",
|
||||
"**/minta/*",
|
||||
|
||||
// Directories
|
||||
"**/metadata/**",
|
||||
"**/metadata",
|
||||
|
||||
@@ -34,11 +34,14 @@ using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.LiveTv;
|
||||
using MediaBrowser.Controller.MediaEncoding;
|
||||
using MediaBrowser.Controller.MediaSegments;
|
||||
using MediaBrowser.Controller.Persistence;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Controller.Resolvers;
|
||||
using MediaBrowser.Controller.Sorting;
|
||||
using MediaBrowser.Controller.Trickplay;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using MediaBrowser.Model.Dlna;
|
||||
using MediaBrowser.Model.Drawing;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Entities;
|
||||
@@ -74,10 +77,6 @@ namespace Emby.Server.Implementations.Library
|
||||
private readonly IMediaEncoder _mediaEncoder;
|
||||
private readonly IFileSystem _fileSystem;
|
||||
private readonly IItemRepository _itemRepository;
|
||||
private readonly IItemPersistenceService _persistenceService;
|
||||
private readonly INextUpService _nextUpService;
|
||||
private readonly IItemCountService _countService;
|
||||
private readonly ILinkedChildrenService _linkedChildrenService;
|
||||
private readonly IImageProcessor _imageProcessor;
|
||||
private readonly NamingOptions _namingOptions;
|
||||
private readonly IPeopleRepository _peopleRepository;
|
||||
@@ -116,10 +115,6 @@ namespace Emby.Server.Implementations.Library
|
||||
/// <param name="userViewManagerFactory">The user view manager.</param>
|
||||
/// <param name="mediaEncoder">The media encoder.</param>
|
||||
/// <param name="itemRepository">The item repository.</param>
|
||||
/// <param name="persistenceService">The item persistence service.</param>
|
||||
/// <param name="nextUpService">The next up service.</param>
|
||||
/// <param name="countService">The item count service.</param>
|
||||
/// <param name="linkedChildrenService">The linked children service.</param>
|
||||
/// <param name="imageProcessor">The image processor.</param>
|
||||
/// <param name="namingOptions">The naming options.</param>
|
||||
/// <param name="directoryService">The directory service.</param>
|
||||
@@ -138,10 +133,6 @@ namespace Emby.Server.Implementations.Library
|
||||
Lazy<IUserViewManager> userViewManagerFactory,
|
||||
IMediaEncoder mediaEncoder,
|
||||
IItemRepository itemRepository,
|
||||
IItemPersistenceService persistenceService,
|
||||
INextUpService nextUpService,
|
||||
IItemCountService countService,
|
||||
ILinkedChildrenService linkedChildrenService,
|
||||
IImageProcessor imageProcessor,
|
||||
NamingOptions namingOptions,
|
||||
IDirectoryService directoryService,
|
||||
@@ -160,10 +151,6 @@ namespace Emby.Server.Implementations.Library
|
||||
_userViewManagerFactory = userViewManagerFactory;
|
||||
_mediaEncoder = mediaEncoder;
|
||||
_itemRepository = itemRepository;
|
||||
_persistenceService = persistenceService;
|
||||
_nextUpService = nextUpService;
|
||||
_countService = countService;
|
||||
_linkedChildrenService = linkedChildrenService;
|
||||
_imageProcessor = imageProcessor;
|
||||
|
||||
_cache = new FastConcurrentLru<Guid, BaseItem>(_configurationManager.Configuration.CacheSize);
|
||||
@@ -340,17 +327,9 @@ namespace Emby.Server.Implementations.Library
|
||||
DeleteItem(item, options, parent, notifyParentItem);
|
||||
}
|
||||
|
||||
public void DeleteItemsUnsafeFast(IReadOnlyCollection<BaseItem> items, bool deleteSourceFiles = false)
|
||||
public void DeleteItemsUnsafeFast(IEnumerable<BaseItem> items)
|
||||
{
|
||||
if (items.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var pathMaps = items.Select(e =>
|
||||
(Item: e,
|
||||
InternalPath: GetInternalMetadataPaths(e),
|
||||
DeletePaths: deleteSourceFiles ? e.GetDeletePaths() : [])).ToArray();
|
||||
var pathMaps = items.Select(e => (Item: e, InternalPath: GetInternalMetadataPaths(e), DeletePaths: e.GetDeletePaths())).ToArray();
|
||||
|
||||
foreach (var (item, internalPaths, pathsToDelete) in pathMaps)
|
||||
{
|
||||
@@ -384,7 +363,7 @@ namespace Emby.Server.Implementations.Library
|
||||
}
|
||||
}
|
||||
|
||||
_persistenceService.DeleteItem([.. pathMaps.Select(f => f.Item.Id)]);
|
||||
_itemRepository.DeleteItem([.. pathMaps.Select(f => f.Item.Id)]);
|
||||
}
|
||||
|
||||
public void DeleteItem(BaseItem item, DeleteOptions options, BaseItem parent, bool notifyParentItem)
|
||||
@@ -427,99 +406,6 @@ namespace Emby.Server.Implementations.Library
|
||||
item.Id);
|
||||
}
|
||||
|
||||
// If deleting a primary version video, clear PrimaryVersionId from alternate versions
|
||||
// OwnerId check: items with OwnerId set are alternate versions or extras, not primaries
|
||||
if (item is Video video && !video.PrimaryVersionId.HasValue && video.OwnerId.IsEmpty())
|
||||
{
|
||||
var localAlternateIds = GetLocalAlternateVersionIds(video).ToHashSet();
|
||||
var allAlternateVersions = localAlternateIds
|
||||
.Concat(GetLinkedAlternateVersions(video).Select(v => v.Id))
|
||||
.Distinct()
|
||||
.Select(id => GetItemById(id))
|
||||
.OfType<Video>()
|
||||
.ToList();
|
||||
|
||||
// Partition alternates by whether their files still exist on disk
|
||||
var alternateVersions = new List<Video>();
|
||||
var missingAlternates = new List<Video>();
|
||||
foreach (var alt in allAlternateVersions)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(alt.Path) && !_fileSystem.FileExists(alt.Path))
|
||||
{
|
||||
missingAlternates.Add(alt);
|
||||
}
|
||||
else
|
||||
{
|
||||
alternateVersions.Add(alt);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete alternates whose files no longer exist to avoid ghost items.
|
||||
// Clear PrimaryVersionId first so DeleteItem doesn't try to update the primary being deleted.
|
||||
foreach (var missing in missingAlternates)
|
||||
{
|
||||
_logger.LogInformation(
|
||||
"Deleting missing alternate version {Name} ({Path})",
|
||||
missing.Name ?? "Unknown name",
|
||||
missing.Path ?? string.Empty);
|
||||
missing.SetPrimaryVersionId(null);
|
||||
missing.OwnerId = Guid.Empty;
|
||||
missing.LocalAlternateVersions = [];
|
||||
missing.LinkedAlternateVersions = [];
|
||||
DeleteItem(missing, new DeleteOptions { DeleteFileLocation = false }, false);
|
||||
}
|
||||
|
||||
if (alternateVersions.Count > 0)
|
||||
{
|
||||
_logger.LogInformation(
|
||||
"Clearing PrimaryVersionId from {Count} alternate versions of {Name}",
|
||||
alternateVersions.Count,
|
||||
item.Name ?? "Unknown name");
|
||||
|
||||
// Promote the first alternate version to be the new primary
|
||||
var newPrimary = alternateVersions[0];
|
||||
newPrimary.SetPrimaryVersionId(null);
|
||||
newPrimary.OwnerId = Guid.Empty;
|
||||
|
||||
// Transfer alternate version arrays from old primary to new primary
|
||||
// so UpdateToRepositoryAsync creates correct LinkedChildren entries
|
||||
newPrimary.LocalAlternateVersions = video.LocalAlternateVersions
|
||||
.Where(p => !string.Equals(p, newPrimary.Path, StringComparison.OrdinalIgnoreCase))
|
||||
.ToArray();
|
||||
newPrimary.LinkedAlternateVersions = video.LinkedAlternateVersions
|
||||
.Where(lc => !lc.ItemId.HasValue || !lc.ItemId.Value.Equals(newPrimary.Id))
|
||||
.ToArray();
|
||||
|
||||
newPrimary.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).GetAwaiter().GetResult();
|
||||
|
||||
// Re-route playlist/collection references from deleted primary to new primary
|
||||
RerouteLinkedChildReferencesAsync(video.Id, newPrimary.Id).GetAwaiter().GetResult();
|
||||
|
||||
// Update remaining alternates to point to new primary
|
||||
foreach (var alternate in alternateVersions.Skip(1))
|
||||
{
|
||||
alternate.SetPrimaryVersionId(newPrimary.Id);
|
||||
// Only set OwnerId for local alternates; linked alternates are independent items
|
||||
alternate.OwnerId = localAlternateIds.Contains(alternate.Id) ? newPrimary.Id : Guid.Empty;
|
||||
alternate.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).GetAwaiter().GetResult();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (item is Video alternateVideo && alternateVideo.PrimaryVersionId.HasValue)
|
||||
{
|
||||
// If deleting an alternate version, re-route references to its primary
|
||||
RerouteLinkedChildReferencesAsync(alternateVideo.Id, alternateVideo.PrimaryVersionId.Value).GetAwaiter().GetResult();
|
||||
|
||||
// Remove deleted alternate from primary's LinkedAlternateVersions
|
||||
if (GetItemById(alternateVideo.PrimaryVersionId.Value) is Video primaryVideo)
|
||||
{
|
||||
primaryVideo.LinkedAlternateVersions = primaryVideo.LinkedAlternateVersions
|
||||
.Where(lc => !lc.ItemId.HasValue || !lc.ItemId.Value.Equals(alternateVideo.Id))
|
||||
.ToArray();
|
||||
primaryVideo.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).GetAwaiter().GetResult();
|
||||
}
|
||||
}
|
||||
|
||||
var children = item.IsFolder
|
||||
? ((Folder)item).GetRecursiveChildren(false)
|
||||
: [];
|
||||
@@ -564,7 +450,7 @@ namespace Emby.Server.Implementations.Library
|
||||
|
||||
item.SetParent(null);
|
||||
|
||||
_persistenceService.DeleteItem([item.Id, .. children.Select(f => f.Id)]);
|
||||
_itemRepository.DeleteItem([item.Id, .. children.Select(f => f.Id)]);
|
||||
_cache.TryRemove(item.Id, out _);
|
||||
foreach (var child in children)
|
||||
{
|
||||
@@ -690,9 +576,6 @@ namespace Emby.Server.Implementations.Library
|
||||
// Trickplay
|
||||
list.Add(_pathManager.GetTrickplayDirectory(video));
|
||||
|
||||
// Chapter Images
|
||||
list.Add(_pathManager.GetChapterImageFolderPath(video));
|
||||
|
||||
// Subtitles and attachments
|
||||
foreach (var mediaSource in item.GetMediaSources(false))
|
||||
{
|
||||
@@ -774,63 +657,8 @@ namespace Emby.Server.Implementations.Library
|
||||
return key.GetMD5();
|
||||
}
|
||||
|
||||
public BaseItem? ResolvePath(
|
||||
FileSystemMetadata fileInfo,
|
||||
Folder? parent = null,
|
||||
IDirectoryService? directoryService = null,
|
||||
CollectionType? collectionType = null)
|
||||
=> ResolvePath(fileInfo, directoryService ?? new DirectoryService(_fileSystem), null, parent, collectionType);
|
||||
|
||||
/// <inheritdoc />
|
||||
public Video? ResolveAlternateVersion(string path, Type expectedVideoType, Folder? parent, CollectionType? collectionType)
|
||||
{
|
||||
// Clean up any existing item saved with wrong type (e.g. Video instead of Movie).
|
||||
// This happens when items were previously resolved without proper type context
|
||||
// in mixed-content libraries where collectionType is null.
|
||||
var expectedId = GetNewItemId(path, expectedVideoType);
|
||||
if (expectedVideoType != typeof(Video))
|
||||
{
|
||||
var wrongTypeId = GetNewItemId(path, typeof(Video));
|
||||
if (!wrongTypeId.Equals(expectedId) && GetItemById(wrongTypeId) is Video wrongTypeItem)
|
||||
{
|
||||
_logger.LogInformation(
|
||||
"Removing alternate version with wrong type {WrongType}, expected {ExpectedType}: {Path}",
|
||||
wrongTypeItem.GetType().Name,
|
||||
expectedVideoType.Name,
|
||||
path);
|
||||
DeleteItem(wrongTypeItem, new DeleteOptions { DeleteFileLocation = false });
|
||||
}
|
||||
}
|
||||
|
||||
var resolved = ResolvePath(
|
||||
_fileSystem.GetFileSystemInfo(path),
|
||||
parent,
|
||||
collectionType: collectionType) as Video;
|
||||
|
||||
if (resolved is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Ensure the alternate version has the same concrete type as the primary video.
|
||||
// ResolvePath may return a generic Video for files in mixed-content libraries
|
||||
// where collectionType is null, even though the primary is a Movie/Episode/etc.
|
||||
if (resolved.GetType() != expectedVideoType)
|
||||
{
|
||||
if (Activator.CreateInstance(expectedVideoType) is Video correctVideo)
|
||||
{
|
||||
correctVideo.Path = resolved.Path;
|
||||
correctVideo.Name = resolved.Name;
|
||||
correctVideo.VideoType = resolved.VideoType;
|
||||
correctVideo.ProductionYear = resolved.ProductionYear;
|
||||
correctVideo.ExtraType = resolved.ExtraType;
|
||||
resolved = correctVideo;
|
||||
}
|
||||
}
|
||||
|
||||
resolved.Id = expectedId;
|
||||
return resolved;
|
||||
}
|
||||
public BaseItem? ResolvePath(FileSystemMetadata fileInfo, Folder? parent = null, IDirectoryService? directoryService = null)
|
||||
=> ResolvePath(fileInfo, directoryService ?? new DirectoryService(_fileSystem), null, parent);
|
||||
|
||||
private BaseItem? ResolvePath(
|
||||
FileSystemMetadata fileInfo,
|
||||
@@ -1213,7 +1041,7 @@ namespace Emby.Server.Implementations.Library
|
||||
|
||||
public IReadOnlyDictionary<string, MusicArtist[]> GetArtists(IReadOnlyList<string> names)
|
||||
{
|
||||
return _linkedChildrenService.FindArtists(names);
|
||||
return _itemRepository.FindArtists(names);
|
||||
}
|
||||
|
||||
public MusicArtist GetArtist(string name, DtoOptions options)
|
||||
@@ -1358,7 +1186,7 @@ namespace Emby.Server.Implementations.Library
|
||||
|
||||
if (toDelete.Count > 0)
|
||||
{
|
||||
_persistenceService.DeleteItem(toDelete.ToArray());
|
||||
_itemRepository.DeleteItem(toDelete.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1434,7 +1262,7 @@ namespace Emby.Server.Implementations.Library
|
||||
progress.Report(percent * 100);
|
||||
}
|
||||
|
||||
_persistenceService.UpdateInheritedValues();
|
||||
_itemRepository.UpdateInheritedValues();
|
||||
|
||||
progress.Report(100);
|
||||
}
|
||||
@@ -1593,7 +1421,14 @@ namespace Emby.Server.Implementations.Library
|
||||
AddUserToQuery(query, query.User, allowExternalContent);
|
||||
}
|
||||
|
||||
return _itemRepository.GetItemList(query);
|
||||
var itemList = _itemRepository.GetItemList(query);
|
||||
var user = query.User;
|
||||
if (user is not null)
|
||||
{
|
||||
return itemList.Where(i => i.IsVisible(user)).ToList();
|
||||
}
|
||||
|
||||
return itemList;
|
||||
}
|
||||
|
||||
public IReadOnlyList<BaseItem> GetItemList(InternalItemsQuery query)
|
||||
@@ -1617,7 +1452,7 @@ namespace Emby.Server.Implementations.Library
|
||||
AddUserToQuery(query, query.User);
|
||||
}
|
||||
|
||||
return _countService.GetCount(query);
|
||||
return _itemRepository.GetCount(query);
|
||||
}
|
||||
|
||||
public ItemCounts GetItemCounts(InternalItemsQuery query)
|
||||
@@ -1636,30 +1471,7 @@ namespace Emby.Server.Implementations.Library
|
||||
AddUserToQuery(query, query.User);
|
||||
}
|
||||
|
||||
return _countService.GetItemCounts(query);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ItemCounts GetItemCountsForNameItem(BaseItemKind kind, Guid id, BaseItemKind[] relatedItemKinds, User? user)
|
||||
{
|
||||
var query = new InternalItemsQuery(user);
|
||||
if (user is not null)
|
||||
{
|
||||
AddUserToQuery(query, user);
|
||||
}
|
||||
|
||||
return _countService.GetItemCountsForNameItem(kind, id, relatedItemKinds, query);
|
||||
}
|
||||
|
||||
public Dictionary<Guid, int> GetChildCountBatch(IReadOnlyList<Guid> parentIds, Guid? userId)
|
||||
{
|
||||
return _countService.GetChildCountBatch(parentIds, userId);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Dictionary<Guid, (int Played, int Total)> GetPlayedAndTotalCountBatch(IReadOnlyList<Guid> folderIds, User user)
|
||||
{
|
||||
return _countService.GetPlayedAndTotalCountBatch(folderIds, user);
|
||||
return _itemRepository.GetItemCounts(query);
|
||||
}
|
||||
|
||||
public IReadOnlyList<BaseItem> GetItemList(InternalItemsQuery query, List<BaseItem> parents)
|
||||
@@ -1704,17 +1516,7 @@ namespace Emby.Server.Implementations.Library
|
||||
}
|
||||
}
|
||||
|
||||
return _nextUpService.GetNextUpSeriesKeys(query, dateCutoff);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IReadOnlyDictionary<string, MediaBrowser.Controller.Persistence.NextUpEpisodeBatchResult> GetNextUpEpisodesBatch(
|
||||
InternalItemsQuery query,
|
||||
IReadOnlyList<string> seriesKeys,
|
||||
bool includeSpecials,
|
||||
bool includeWatchedForRewatching)
|
||||
{
|
||||
return _nextUpService.GetNextUpEpisodesBatch(query, seriesKeys, includeSpecials, includeWatchedForRewatching);
|
||||
return _itemRepository.GetNextUpSeriesKeys(query, dateCutoff);
|
||||
}
|
||||
|
||||
public QueryResult<BaseItem> QueryItems(InternalItemsQuery query)
|
||||
@@ -1898,11 +1700,6 @@ namespace Emby.Server.Implementations.Library
|
||||
|
||||
private void AddUserToQuery(InternalItemsQuery query, User user, bool allowExternalContent = true)
|
||||
{
|
||||
if (query.User is null)
|
||||
{
|
||||
query.SetUser(user);
|
||||
}
|
||||
|
||||
if (query.AncestorIds.Length == 0 &&
|
||||
query.ParentId.IsEmpty() &&
|
||||
query.ChannelIds.Count == 0 &&
|
||||
@@ -1928,15 +1725,6 @@ namespace Emby.Server.Implementations.Library
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void ConfigureUserAccess(InternalItemsQuery query, User user)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(query);
|
||||
ArgumentNullException.ThrowIfNull(user);
|
||||
|
||||
AddUserToQuery(query, user);
|
||||
}
|
||||
|
||||
private IEnumerable<Guid> GetTopParentIdsForQuery(BaseItem item, User? user)
|
||||
{
|
||||
if (item is UserView view)
|
||||
@@ -2101,44 +1889,6 @@ namespace Emby.Server.Implementations.Library
|
||||
return video;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<Guid> GetLocalAlternateVersionIds(Video video)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(video);
|
||||
|
||||
var linkedIds = _linkedChildrenService.GetLinkedChildrenIds(video.Id, (int)MediaBrowser.Controller.Entities.LinkedChildType.LocalAlternateVersion);
|
||||
if (linkedIds.Count > 0)
|
||||
{
|
||||
return linkedIds;
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<Video> GetLinkedAlternateVersions(Video video)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(video);
|
||||
|
||||
var linkedIds = _linkedChildrenService.GetLinkedChildrenIds(video.Id, (int)MediaBrowser.Controller.Entities.LinkedChildType.LinkedAlternateVersion);
|
||||
if (linkedIds.Count > 0)
|
||||
{
|
||||
return linkedIds
|
||||
.Select(id => GetItemById(id))
|
||||
.Where(i => i is not null)
|
||||
.OfType<Video>()
|
||||
.OrderBy(i => i.SortName);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void UpsertLinkedChild(Guid parentId, Guid childId, MediaBrowser.Controller.Entities.LinkedChildType childType)
|
||||
{
|
||||
_linkedChildrenService.UpsertLinkedChild(parentId, childId, childType);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<BaseItem> Sort(IEnumerable<BaseItem> items, User? user, IEnumerable<ItemSortBy> sortBy, SortOrder sortOrder)
|
||||
{
|
||||
@@ -2243,44 +1993,9 @@ namespace Emby.Server.Implementations.Library
|
||||
/// <inheritdoc />
|
||||
public void CreateItems(IReadOnlyList<BaseItem> items, BaseItem? parent, CancellationToken cancellationToken)
|
||||
{
|
||||
// Resolve and add any local alternate version items that don't exist yet
|
||||
// This ensures they exist in the database when LinkedChildren are processed
|
||||
var allItems = new List<BaseItem>(items);
|
||||
var parentFolder = parent as Folder;
|
||||
var parentCollectionType = parent is not null ? GetTopFolderContentType(parent) : null;
|
||||
_itemRepository.SaveItems(items, cancellationToken);
|
||||
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (item is Video video && video.LocalAlternateVersions.Length > 0)
|
||||
{
|
||||
var videoType = video.GetType();
|
||||
foreach (var path in video.LocalAlternateVersions)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Use the primary video's type for ID calculation to ensure consistency
|
||||
var altId = GetNewItemId(path, videoType);
|
||||
if (GetItemById(altId) is null && !allItems.Any(i => i.Id.Equals(altId)))
|
||||
{
|
||||
// Alternate version doesn't exist, resolve and create it
|
||||
// ensuring it has the same type as the primary video
|
||||
var altVideo = ResolveAlternateVersion(path, videoType, parentFolder, parentCollectionType);
|
||||
if (altVideo is not null)
|
||||
{
|
||||
altVideo.OwnerId = video.Id;
|
||||
altVideo.SetPrimaryVersionId(video.Id);
|
||||
allItems.Add(altVideo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_persistenceService.SaveItems(allItems, cancellationToken);
|
||||
|
||||
foreach (var item in allItems)
|
||||
{
|
||||
RegisterItem(item);
|
||||
}
|
||||
@@ -2429,7 +2144,7 @@ namespace Emby.Server.Implementations.Library
|
||||
|
||||
item.ValidateImages();
|
||||
|
||||
await _persistenceService.SaveImagesAsync(item).ConfigureAwait(false);
|
||||
await _itemRepository.SaveImagesAsync(item).ConfigureAwait(false);
|
||||
|
||||
RegisterItem(item);
|
||||
}
|
||||
@@ -2446,50 +2161,7 @@ namespace Emby.Server.Implementations.Library
|
||||
item.DateLastSaved = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
// Resolve and add any local alternate version items that don't exist yet
|
||||
// This ensures they exist in the database when LinkedChildren are processed
|
||||
var allItems = new List<BaseItem>(items);
|
||||
var parentFolder = parent as Folder;
|
||||
var parentCollectionType = GetTopFolderContentType(parent);
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (item is Video video && video.LocalAlternateVersions.Length > 0)
|
||||
{
|
||||
var videoType = video.GetType();
|
||||
foreach (var path in video.LocalAlternateVersions)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Use the primary video's type for ID calculation to ensure consistency
|
||||
var altId = GetNewItemId(path, videoType);
|
||||
if (GetItemById(altId) is null && !allItems.Any(i => i.Id.Equals(altId)))
|
||||
{
|
||||
// Alternate version doesn't exist, resolve and create it
|
||||
// ensuring it has the same type as the primary video
|
||||
var altVideo = ResolveAlternateVersion(path, videoType, parentFolder, parentCollectionType);
|
||||
if (altVideo is not null)
|
||||
{
|
||||
altVideo.OwnerId = video.Id;
|
||||
altVideo.SetPrimaryVersionId(video.Id);
|
||||
allItems.Add(altVideo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_persistenceService.SaveItems(allItems, cancellationToken);
|
||||
|
||||
foreach (var item in allItems)
|
||||
{
|
||||
if (!items.Contains(item))
|
||||
{
|
||||
RegisterItem(item);
|
||||
}
|
||||
}
|
||||
_itemRepository.SaveItems(items, cancellationToken);
|
||||
|
||||
if (parent is Folder folder)
|
||||
{
|
||||
@@ -2533,7 +2205,7 @@ namespace Emby.Server.Implementations.Library
|
||||
/// <inheritdoc />
|
||||
public async Task ReattachUserDataAsync(BaseItem item, CancellationToken cancellationToken)
|
||||
{
|
||||
await _persistenceService.ReattachUserDataAsync(item, cancellationToken).ConfigureAwait(false);
|
||||
await _itemRepository.ReattachUserDataAsync(item, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task RunMetadataSavers(BaseItem item, ItemUpdateType updateReason)
|
||||
@@ -3162,8 +2834,7 @@ namespace Emby.Server.Implementations.Library
|
||||
{
|
||||
// Apply .ignore rules
|
||||
var filtered = fileSystemChildren.Where(c => !DotIgnoreIgnoreRule.IsIgnored(c, owner)).ToList();
|
||||
var isFolder = owner.IsFolder || (owner is Video video && (video.VideoType == VideoType.BluRay || video.VideoType == VideoType.Dvd));
|
||||
var ownerVideoInfo = VideoResolver.Resolve(owner.Path, isFolder, _namingOptions, libraryRoot: owner.ContainingFolderPath);
|
||||
var ownerVideoInfo = VideoResolver.Resolve(owner.Path, owner.IsFolder, _namingOptions, libraryRoot: owner.ContainingFolderPath);
|
||||
if (ownerVideoInfo is null)
|
||||
{
|
||||
yield break;
|
||||
@@ -3225,16 +2896,10 @@ namespace Emby.Server.Implementations.Library
|
||||
extra.ExtraType = extraType;
|
||||
}
|
||||
|
||||
// Only return items that are actual extras (have ExtraType set)
|
||||
// Note: OwnerId and ParentId are set by RefreshExtras, not here,
|
||||
// so that RefreshExtras can detect when they need updating and set ForceSave.
|
||||
if (extra.ExtraType is not null)
|
||||
{
|
||||
extra.IsInMixedFolder = isInMixedFolder;
|
||||
return extra;
|
||||
}
|
||||
|
||||
return null;
|
||||
extra.ParentId = Guid.Empty;
|
||||
extra.OwnerId = owner.Id;
|
||||
extra.IsInMixedFolder = isInMixedFolder;
|
||||
return extra;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3720,40 +3385,5 @@ namespace Emby.Server.Implementations.Library
|
||||
_fileSystem.CreateShortcut(lnk, _appHost.ReverseVirtualPath(path));
|
||||
RemoveContentTypeOverrides(path);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task RerouteLinkedChildReferencesAsync(Guid fromChildId, Guid toChildId)
|
||||
{
|
||||
var affectedParentIds = _linkedChildrenService.RerouteLinkedChildren(fromChildId, toChildId);
|
||||
|
||||
// Update in-memory LinkedChildren and re-save metadata (NFO) for affected parents
|
||||
foreach (var parentId in affectedParentIds)
|
||||
{
|
||||
if (GetItemById(parentId) is Folder parent)
|
||||
{
|
||||
foreach (var lc in parent.LinkedChildren)
|
||||
{
|
||||
if (lc.ItemId.HasValue && lc.ItemId.Value.Equals(fromChildId))
|
||||
{
|
||||
lc.ItemId = toChildId;
|
||||
}
|
||||
}
|
||||
|
||||
await RunMetadataSavers(parent, ItemUpdateType.MetadataEdit).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public QueryFiltersLegacy GetQueryFiltersLegacy(InternalItemsQuery query)
|
||||
{
|
||||
if (query.User is not null)
|
||||
{
|
||||
AddUserToQuery(query, query.User);
|
||||
}
|
||||
|
||||
SetTopParentOrAncestorIds(query);
|
||||
return _itemRepository.GetQueryFiltersLegacy(query);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +70,12 @@ namespace Emby.Server.Implementations.Library
|
||||
return match ? imdbId.ToString() : null;
|
||||
}
|
||||
|
||||
// Allow tmdb as an alias for tmdbid
|
||||
if (attribute.Equals("tmdbid", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return str.GetAttributeValue("tmdb");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -177,74 +177,53 @@ namespace Emby.Server.Implementations.Library
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Dictionary<Guid, UserItemData> GetUserDataBatch(IReadOnlyList<BaseItem> items, User user)
|
||||
private UserItemData? GetUserData(User user, Guid itemId, List<string> keys)
|
||||
{
|
||||
var result = new Dictionary<Guid, UserItemData>(items.Count);
|
||||
var itemsNeedingQuery = new List<(BaseItem Item, List<string> Keys)>();
|
||||
var cacheKey = GetCacheKey(user.InternalId, itemId);
|
||||
|
||||
foreach (var item in items)
|
||||
if (_cache.TryGet(cacheKey, out var data))
|
||||
{
|
||||
var cacheKey = GetCacheKey(user.InternalId, item.Id);
|
||||
if (_cache.TryGet(cacheKey, out var cachedData))
|
||||
{
|
||||
result[item.Id] = cachedData;
|
||||
}
|
||||
else
|
||||
{
|
||||
var userData = item.UserData?.Where(e => e.UserId.Equals(user.Id)).Select(Map).FirstOrDefault();
|
||||
if (userData is not null)
|
||||
{
|
||||
result[item.Id] = userData;
|
||||
_cache.AddOrUpdate(cacheKey, userData);
|
||||
}
|
||||
else
|
||||
{
|
||||
var keys = item.GetUserDataKeys();
|
||||
itemsNeedingQuery.Add((item, keys));
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
if (itemsNeedingQuery.Count == 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
data = GetUserDataInternal(user.Id, itemId, keys);
|
||||
|
||||
// Build a single query for all missing items
|
||||
var allItemIds = itemsNeedingQuery.Select(x => x.Item.Id).ToList();
|
||||
var allKeys = itemsNeedingQuery.SelectMany(x => x.Keys).Distinct().ToList();
|
||||
if (allKeys.Count > 0)
|
||||
if (data is null)
|
||||
{
|
||||
using var context = _repository.CreateDbContext();
|
||||
var userDataArray = context.UserData
|
||||
.AsNoTracking()
|
||||
.Where(e => e.UserId.Equals(user.Id))
|
||||
.WhereOneOrMany(allItemIds, e => e.ItemId)
|
||||
.WhereOneOrMany(allKeys, e => e.CustomDataKey)
|
||||
.ToArray();
|
||||
|
||||
var userDataByItem = userDataArray.GroupBy(e => e.ItemId).ToDictionary(g => g.Key, g => g.ToArray());
|
||||
foreach (var (item, keys) in itemsNeedingQuery)
|
||||
return new UserItemData()
|
||||
{
|
||||
UserItemData userData;
|
||||
if (userDataByItem.TryGetValue(item.Id, out var itemUserData) && itemUserData.Length > 0)
|
||||
{
|
||||
var directDataReference = itemUserData.FirstOrDefault(e => e.CustomDataKey == item.Id.ToString("N"));
|
||||
userData = directDataReference is not null ? Map(directDataReference) : Map(itemUserData.First());
|
||||
}
|
||||
else
|
||||
{
|
||||
userData = new UserItemData { Key = keys.Count > 0 ? keys[0] : string.Empty };
|
||||
}
|
||||
|
||||
result[item.Id] = userData;
|
||||
var cacheKey = GetCacheKey(user.InternalId, item.Id);
|
||||
_cache.AddOrUpdate(cacheKey, userData);
|
||||
}
|
||||
Key = keys[0],
|
||||
};
|
||||
}
|
||||
|
||||
return result;
|
||||
return _cache.GetOrAdd(cacheKey, _ => data);
|
||||
}
|
||||
|
||||
private UserItemData? GetUserDataInternal(Guid userId, Guid itemId, List<string> keys)
|
||||
{
|
||||
if (keys.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
using var context = _repository.CreateDbContext();
|
||||
var userData = context.UserData.AsNoTracking().Where(e => e.ItemId == itemId && keys.Contains(e.CustomDataKey) && e.UserId.Equals(userId)).ToArray();
|
||||
|
||||
if (userData.Length > 0)
|
||||
{
|
||||
var directDataReference = userData.FirstOrDefault(e => e.CustomDataKey == itemId.ToString("N"));
|
||||
if (directDataReference is not null)
|
||||
{
|
||||
return Map(directDataReference);
|
||||
}
|
||||
|
||||
return Map(userData.First());
|
||||
}
|
||||
|
||||
return new UserItemData
|
||||
{
|
||||
Key = keys.Last()!
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -59,8 +59,8 @@ namespace Emby.Server.Implementations.Library
|
||||
var collectionFolder = folder as ICollectionFolder;
|
||||
var folderViewType = collectionFolder?.CollectionType;
|
||||
|
||||
// Playlist and BoxSet libraries require special handling because the folder only references linked items
|
||||
if (folderViewType == CollectionType.playlists || folderViewType == CollectionType.boxsets)
|
||||
// Playlist library requires special handling because the folder only references user playlists
|
||||
if (folderViewType == CollectionType.playlists)
|
||||
{
|
||||
var items = folder.GetItemList(new InternalItemsQuery(user)
|
||||
{
|
||||
@@ -138,7 +138,7 @@ namespace Emby.Server.Implementations.Library
|
||||
list = list.Where(i => !user.GetPreferenceValues<Guid>(PreferenceKind.MyMediaExcludes).Contains(i.Id)).ToList();
|
||||
}
|
||||
|
||||
var sorted = _libraryManager.Sort(list, user, [ItemSortBy.SortName], SortOrder.Ascending).ToList();
|
||||
var sorted = _libraryManager.Sort(list, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending).ToList();
|
||||
var orders = user.GetPreferenceValues<Guid>(PreferenceKind.OrderedViews);
|
||||
|
||||
return list
|
||||
@@ -205,7 +205,7 @@ namespace Emby.Server.Implementations.Library
|
||||
var libraryItems = GetItemsForLatestItems(request.User, request, options);
|
||||
|
||||
var list = new List<Tuple<BaseItem, List<BaseItem>>>();
|
||||
var containerIndexMap = new Dictionary<Guid, int>();
|
||||
|
||||
foreach (var item in libraryItems)
|
||||
{
|
||||
// Only grab the index container for media
|
||||
@@ -213,16 +213,20 @@ namespace Emby.Server.Implementations.Library
|
||||
|
||||
if (container is null)
|
||||
{
|
||||
list.Add(new Tuple<BaseItem, List<BaseItem>>(null!, new List<BaseItem> { item }));
|
||||
}
|
||||
else if (containerIndexMap.TryGetValue(container.Id, out var existingIndex))
|
||||
{
|
||||
list[existingIndex].Item2.Add(item);
|
||||
list.Add(new Tuple<BaseItem, List<BaseItem>>(null, new List<BaseItem> { item }));
|
||||
}
|
||||
else
|
||||
{
|
||||
containerIndexMap[container.Id] = list.Count;
|
||||
list.Add(new Tuple<BaseItem, List<BaseItem>>(container, new List<BaseItem> { item }));
|
||||
var current = list.FirstOrDefault(i => i.Item1 is not null && i.Item1.Id.Equals(container.Id));
|
||||
|
||||
if (current is not null)
|
||||
{
|
||||
current.Item2.Add(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
list.Add(new Tuple<BaseItem, List<BaseItem>>(container, new List<BaseItem> { item }));
|
||||
}
|
||||
}
|
||||
|
||||
if (list.Count >= request.Limit)
|
||||
@@ -251,7 +255,7 @@ namespace Emby.Server.Implementations.Library
|
||||
return _channelManager.GetLatestChannelItemsInternal(
|
||||
new InternalItemsQuery(user)
|
||||
{
|
||||
ChannelIds = [parentId],
|
||||
ChannelIds = new[] { parentId },
|
||||
IsPlayed = request.IsPlayed,
|
||||
StartIndex = request.StartIndex,
|
||||
Limit = request.Limit,
|
||||
@@ -297,11 +301,11 @@ namespace Emby.Server.Implementations.Library
|
||||
{
|
||||
if (hasCollectionType.All(i => i.CollectionType == CollectionType.movies))
|
||||
{
|
||||
includeItemTypes = [BaseItemKind.Movie];
|
||||
includeItemTypes = new[] { BaseItemKind.Movie };
|
||||
}
|
||||
else if (hasCollectionType.All(i => i.CollectionType == CollectionType.tvshows))
|
||||
{
|
||||
includeItemTypes = [BaseItemKind.Episode];
|
||||
includeItemTypes = new[] { BaseItemKind.Episode };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -340,29 +344,29 @@ namespace Emby.Server.Implementations.Library
|
||||
}
|
||||
|
||||
var excludeItemTypes = includeItemTypes.Length == 0 && mediaTypes.Length == 0
|
||||
?
|
||||
[
|
||||
? new[]
|
||||
{
|
||||
BaseItemKind.Person,
|
||||
BaseItemKind.Studio,
|
||||
BaseItemKind.Year,
|
||||
BaseItemKind.MusicGenre,
|
||||
BaseItemKind.Genre
|
||||
]
|
||||
}
|
||||
: Array.Empty<BaseItemKind>();
|
||||
|
||||
var query = new InternalItemsQuery(user)
|
||||
{
|
||||
IncludeItemTypes = includeItemTypes,
|
||||
OrderBy =
|
||||
[
|
||||
OrderBy = new[]
|
||||
{
|
||||
(ItemSortBy.DateCreated, SortOrder.Descending),
|
||||
(ItemSortBy.SortName, SortOrder.Descending),
|
||||
(ItemSortBy.ProductionYear, SortOrder.Descending)
|
||||
],
|
||||
},
|
||||
IsFolder = includeItemTypes.Length == 0 ? false : null,
|
||||
ExcludeItemTypes = excludeItemTypes,
|
||||
IsVirtualItem = false,
|
||||
Limit = limit * 2,
|
||||
Limit = limit * 5,
|
||||
IsPlayed = isPlayed,
|
||||
DtoOptions = options,
|
||||
MediaTypes = mediaTypes
|
||||
@@ -390,12 +394,6 @@ namespace Emby.Server.Implementations.Library
|
||||
query.Limit = limit;
|
||||
return _libraryManager.GetLatestItemList(query, parents, CollectionType.music);
|
||||
}
|
||||
|
||||
if (collectionType == CollectionType.movies)
|
||||
{
|
||||
query.Limit = limit;
|
||||
return _libraryManager.GetLatestItemList(query, parents, CollectionType.movies);
|
||||
}
|
||||
}
|
||||
|
||||
return _libraryManager.GetItemList(query, parents);
|
||||
|
||||
@@ -50,40 +50,21 @@ public class ArtistsValidator
|
||||
public async Task Run(IProgress<double> progress, CancellationToken cancellationToken)
|
||||
{
|
||||
var names = _itemRepo.GetAllArtistNames();
|
||||
var existingArtistIds = _libraryManager.GetItemIds(new InternalItemsQuery
|
||||
{
|
||||
IncludeItemTypes = [BaseItemKind.MusicArtist]
|
||||
}).ToHashSet();
|
||||
|
||||
var existingArtists = _libraryManager.GetArtists(names);
|
||||
|
||||
var numComplete = 0;
|
||||
var count = names.Count;
|
||||
var refreshed = 0;
|
||||
|
||||
foreach (var name in names)
|
||||
{
|
||||
try
|
||||
{
|
||||
MusicArtist? item = null;
|
||||
if (existingArtists.TryGetValue(name, out var artists) && artists.Length > 0)
|
||||
{
|
||||
item = artists.OrderBy(i => i.IsAccessedByName ? 1 : 0).First();
|
||||
}
|
||||
var item = _libraryManager.GetArtist(name);
|
||||
|
||||
// Fall back to GetArtist if not found (creates new item if needed)
|
||||
item ??= _libraryManager.GetArtist(name);
|
||||
var isNew = !existingArtistIds.Contains(item.Id);
|
||||
var neverRefreshed = item.DateLastRefreshed == default;
|
||||
|
||||
if (isNew || neverRefreshed)
|
||||
{
|
||||
await item.RefreshMetadata(cancellationToken).ConfigureAwait(false);
|
||||
refreshed++;
|
||||
}
|
||||
await item.RefreshMetadata(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// Don't clutter the log
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -99,23 +80,30 @@ public class ArtistsValidator
|
||||
progress.Report(percent);
|
||||
}
|
||||
|
||||
_logger.LogInformation("Refreshed metadata for {RefreshedCount} new artists out of {TotalCount} total", refreshed, count);
|
||||
|
||||
var deadEntities = _libraryManager.GetItemList(new InternalItemsQuery
|
||||
{
|
||||
IncludeItemTypes = [BaseItemKind.MusicArtist],
|
||||
IsDeadArtist = true,
|
||||
IsLocked = false
|
||||
}).Cast<MusicArtist>()
|
||||
.Where(item => item.IsAccessedByName)
|
||||
.ToList();
|
||||
}).Cast<MusicArtist>().ToList();
|
||||
|
||||
foreach (var item in deadEntities)
|
||||
{
|
||||
_logger.LogInformation("Deleting dead {ItemType} {ItemId} {ItemName}", item.GetType().Name, item.Id.ToString("N", CultureInfo.InvariantCulture), item.Name);
|
||||
}
|
||||
if (!item.IsAccessedByName)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
_libraryManager.DeleteItemsUnsafeFast(deadEntities, deleteSourceFiles: true);
|
||||
_logger.LogInformation("Deleting dead {ItemType} {ItemId} {ItemName}", item.GetType().Name, item.Id.ToString("N", CultureInfo.InvariantCulture), item.Name);
|
||||
|
||||
_libraryManager.DeleteItem(
|
||||
item,
|
||||
new DeleteOptions
|
||||
{
|
||||
DeleteFileLocation = false
|
||||
},
|
||||
false);
|
||||
}
|
||||
|
||||
progress.Report(100);
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ public class CollectionPostScanTask : ILibraryPostScanTask
|
||||
|
||||
foreach (var m in movies)
|
||||
{
|
||||
if (m is Movie movie && !string.IsNullOrEmpty(movie.CollectionName) && !movie.PrimaryVersionId.HasValue)
|
||||
if (m is Movie movie && !string.IsNullOrEmpty(movie.CollectionName))
|
||||
{
|
||||
if (collectionNameMoviesMap.TryGetValue(movie.CollectionName, out var movieList))
|
||||
{
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Jellyfin.Data.Enums;
|
||||
@@ -49,40 +48,17 @@ public class GenresValidator
|
||||
public async Task Run(IProgress<double> progress, CancellationToken cancellationToken)
|
||||
{
|
||||
var names = _itemRepo.GetGenreNames();
|
||||
var existingGenreIds = _libraryManager.GetItemIds(new InternalItemsQuery
|
||||
{
|
||||
IncludeItemTypes = [BaseItemKind.Genre]
|
||||
}).ToHashSet();
|
||||
|
||||
var existingGenres = _libraryManager.GetItemList(new InternalItemsQuery
|
||||
{
|
||||
IncludeItemTypes = [BaseItemKind.Genre]
|
||||
}).Cast<Genre>()
|
||||
.GroupBy(g => g.Name, StringComparer.OrdinalIgnoreCase)
|
||||
.ToDictionary(g => g.Key, g => g.First(), StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
var numComplete = 0;
|
||||
var count = names.Count;
|
||||
var refreshed = 0;
|
||||
|
||||
foreach (var name in names)
|
||||
{
|
||||
try
|
||||
{
|
||||
Genre? item = null;
|
||||
if (existingGenres.TryGetValue(name, out var existingGenre))
|
||||
{
|
||||
item = existingGenre;
|
||||
}
|
||||
var item = _libraryManager.GetGenre(name);
|
||||
|
||||
// Fall back to GetGenre if not found (creates new item if needed)
|
||||
item ??= _libraryManager.GetGenre(name);
|
||||
|
||||
if (!existingGenreIds.Contains(item.Id))
|
||||
{
|
||||
await item.RefreshMetadata(cancellationToken).ConfigureAwait(false);
|
||||
refreshed++;
|
||||
}
|
||||
await item.RefreshMetadata(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
@@ -102,8 +78,6 @@ public class GenresValidator
|
||||
progress.Report(percent);
|
||||
}
|
||||
|
||||
_logger.LogInformation("Refreshed metadata for {RefreshedCount} new genres out of {TotalCount} total", refreshed, count);
|
||||
|
||||
var deadEntities = _libraryManager.GetItemList(new InternalItemsQuery
|
||||
{
|
||||
IncludeItemTypes = [BaseItemKind.Genre, BaseItemKind.MusicGenre],
|
||||
@@ -114,9 +88,15 @@ public class GenresValidator
|
||||
foreach (var item in deadEntities)
|
||||
{
|
||||
_logger.LogInformation("Deleting dead {ItemType} {ItemId} {ItemName}", item.GetType().Name, item.Id.ToString("N", CultureInfo.InvariantCulture), item.Name);
|
||||
}
|
||||
|
||||
_libraryManager.DeleteItemsUnsafeFast(deadEntities, deleteSourceFiles: true);
|
||||
_libraryManager.DeleteItem(
|
||||
item,
|
||||
new DeleteOptions
|
||||
{
|
||||
DeleteFileLocation = false
|
||||
},
|
||||
false);
|
||||
}
|
||||
|
||||
progress.Report(100);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Jellyfin.Data.Enums;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Persistence;
|
||||
using Microsoft.Extensions.Logging;
|
||||
@@ -48,25 +45,17 @@ public class MusicGenresValidator
|
||||
public async Task Run(IProgress<double> progress, CancellationToken cancellationToken)
|
||||
{
|
||||
var names = _itemRepo.GetMusicGenreNames();
|
||||
var existingMusicGenreIds = _libraryManager.GetItemIds(new InternalItemsQuery
|
||||
{
|
||||
IncludeItemTypes = [BaseItemKind.MusicGenre]
|
||||
}).ToHashSet();
|
||||
|
||||
var numComplete = 0;
|
||||
var count = names.Count;
|
||||
var refreshed = 0;
|
||||
|
||||
foreach (var name in names)
|
||||
{
|
||||
try
|
||||
{
|
||||
var item = _libraryManager.GetMusicGenre(name);
|
||||
if (!existingMusicGenreIds.Contains(item.Id))
|
||||
{
|
||||
await item.RefreshMetadata(cancellationToken).ConfigureAwait(false);
|
||||
refreshed++;
|
||||
}
|
||||
|
||||
await item.RefreshMetadata(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
@@ -86,8 +75,6 @@ public class MusicGenresValidator
|
||||
progress.Report(percent);
|
||||
}
|
||||
|
||||
_logger.LogInformation("Refreshed metadata for {RefreshedCount} new music genres out of {TotalCount} total", refreshed, count);
|
||||
|
||||
progress.Report(100);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ public class PeopleValidator
|
||||
var i = 0;
|
||||
foreach (var item in deadEntities.Chunk(500))
|
||||
{
|
||||
_libraryManager.DeleteItemsUnsafeFast(item, true);
|
||||
_libraryManager.DeleteItemsUnsafeFast(item);
|
||||
subProgress.Report(100f / deadEntities.Count * (i++ * 100));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Jellyfin.Data.Enums;
|
||||
@@ -50,40 +49,17 @@ public class StudiosValidator
|
||||
public async Task Run(IProgress<double> progress, CancellationToken cancellationToken)
|
||||
{
|
||||
var names = _itemRepo.GetStudioNames();
|
||||
var existingStudioIds = _libraryManager.GetItemIds(new InternalItemsQuery
|
||||
{
|
||||
IncludeItemTypes = [BaseItemKind.Studio]
|
||||
}).ToHashSet();
|
||||
|
||||
var existingStudios = _libraryManager.GetItemList(new InternalItemsQuery
|
||||
{
|
||||
IncludeItemTypes = [BaseItemKind.Studio]
|
||||
}).Cast<Studio>()
|
||||
.GroupBy(s => s.Name, StringComparer.OrdinalIgnoreCase)
|
||||
.ToDictionary(g => g.Key, g => g.First(), StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
var numComplete = 0;
|
||||
var count = names.Count;
|
||||
var refreshed = 0;
|
||||
|
||||
foreach (var name in names)
|
||||
{
|
||||
try
|
||||
{
|
||||
Studio? item = null;
|
||||
if (existingStudios.TryGetValue(name, out var existingStudio))
|
||||
{
|
||||
item = existingStudio;
|
||||
}
|
||||
var item = _libraryManager.GetStudio(name);
|
||||
|
||||
// Fall back to GetStudio if not found (creates new item if needed)
|
||||
item ??= _libraryManager.GetStudio(name);
|
||||
|
||||
if (!existingStudioIds.Contains(item.Id))
|
||||
{
|
||||
await item.RefreshMetadata(cancellationToken).ConfigureAwait(false);
|
||||
refreshed++;
|
||||
}
|
||||
await item.RefreshMetadata(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
@@ -103,8 +79,6 @@ public class StudiosValidator
|
||||
progress.Report(percent);
|
||||
}
|
||||
|
||||
_logger.LogInformation("Refreshed metadata for {RefreshedCount} new studios out of {TotalCount} total", refreshed, count);
|
||||
|
||||
var deadEntities = _libraryManager.GetItemList(new InternalItemsQuery
|
||||
{
|
||||
IncludeItemTypes = [BaseItemKind.Studio],
|
||||
@@ -115,9 +89,15 @@ public class StudiosValidator
|
||||
foreach (var item in deadEntities)
|
||||
{
|
||||
_logger.LogInformation("Deleting dead {ItemType} {ItemId} {ItemName}", item.GetType().Name, item.Id.ToString("N", CultureInfo.InvariantCulture), item.Name);
|
||||
}
|
||||
|
||||
_libraryManager.DeleteItemsUnsafeFast(deadEntities, deleteSourceFiles: true);
|
||||
_libraryManager.DeleteItem(
|
||||
item,
|
||||
new DeleteOptions
|
||||
{
|
||||
DeleteFileLocation = false
|
||||
},
|
||||
false);
|
||||
}
|
||||
|
||||
progress.Report(100);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
{
|
||||
"Albums": "аальбомқәа",
|
||||
"AppDeviceValues": "Апп: {0}, Априбор: {1}",
|
||||
"Application": "Апрограмма"
|
||||
"Albums": "аальбомқәа"
|
||||
}
|
||||
|
||||
@@ -128,6 +128,8 @@
|
||||
"TaskRefreshTrickplayImagesDescription": "Skep fopspeel voorskou vir videos in aangeskakelde media versameling.",
|
||||
"TaskAudioNormalizationDescription": "Skandeer lêers vir oudio-normaliseringsdata.",
|
||||
"TaskAudioNormalization": "Odio Normalisering",
|
||||
"TaskCleanCollectionsAndPlaylists": "Maak versamelings en snitlyste skoon",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Verwyder items uit versamelings en snitlyste wat nie meer bestaan nie.",
|
||||
"TaskDownloadMissingLyrics": "Laai tekorte lirieke af",
|
||||
"TaskDownloadMissingLyricsDescription": "Laai lirieke af vir liedjies",
|
||||
"TaskExtractMediaSegments": "Media Segment Skandeer",
|
||||
|
||||
@@ -1,139 +1,141 @@
|
||||
{
|
||||
"Albums": "الألبومات",
|
||||
"AppDeviceValues": "التطبيق: {0}، الجهاز: {1}",
|
||||
"Application": "التطبيق",
|
||||
"Artists": "الفنانون",
|
||||
"AuthenticationSucceededWithUserName": "تمت مصادقة {0} بنجاح",
|
||||
"Albums": "ألبومات",
|
||||
"AppDeviceValues": "تطبيق: {0}, جهاز: {1}",
|
||||
"Application": "تطبيق",
|
||||
"Artists": "فنانون",
|
||||
"AuthenticationSucceededWithUserName": "نجحت عملية التوثيق بـ {0}",
|
||||
"Books": "الكتب",
|
||||
"CameraImageUploadedFrom": "تم رفع صورة كاميرا جديدة من {0}",
|
||||
"CameraImageUploadedFrom": "رُفعت صورة الكاميرا الجديدة من {0}",
|
||||
"Channels": "القنوات",
|
||||
"ChapterNameValue": "الفصل {0}",
|
||||
"Collections": "المجموعات",
|
||||
"DeviceOfflineWithName": "انقطع اتصال {0}",
|
||||
"Collections": "مجموعات",
|
||||
"DeviceOfflineWithName": "قُطِع الاتصال ب{0}",
|
||||
"DeviceOnlineWithName": "{0} متصل",
|
||||
"FailedLoginAttemptWithUserName": "محاولة تسجيل دخول فاشلة من {0}",
|
||||
"FailedLoginAttemptWithUserName": "محاولة تسجيل الدخول فاشلة من {0}",
|
||||
"Favorites": "المفضلة",
|
||||
"Folders": "المجلدات",
|
||||
"Genres": "الأنواع",
|
||||
"HeaderAlbumArtists": "فنانو الألبوم",
|
||||
"Genres": "التصنيفات",
|
||||
"HeaderAlbumArtists": "فناني الألبوم",
|
||||
"HeaderContinueWatching": "متابعة المشاهدة",
|
||||
"HeaderFavoriteAlbums": "الألبومات المفضلة",
|
||||
"HeaderFavoriteArtists": "الفنانون المفضلون",
|
||||
"HeaderFavoriteEpisodes": "الحلقات المفضلة",
|
||||
"HeaderFavoriteShows": "المسلسلات المفضلة",
|
||||
"HeaderFavoriteSongs": "الأغاني المفضلة",
|
||||
"HeaderLiveTV": "البث التلفزيوني المباشر",
|
||||
"HeaderLiveTV": "التلفاز المباشر",
|
||||
"HeaderNextUp": "التالي",
|
||||
"HeaderRecordingGroups": "مجموعات التسجيل",
|
||||
"HomeVideos": "فيديوهات منزلية",
|
||||
"Inherit": "وراثة",
|
||||
"ItemAddedWithName": "تمت إضافة {0} إلى المكتبة",
|
||||
"ItemRemovedWithName": "تمت إزالة {0} من المكتبة",
|
||||
"LabelIpAddressValue": "عنوان IP: {0}",
|
||||
"HomeVideos": "الفيديوهات الشخصية",
|
||||
"Inherit": "توريث",
|
||||
"ItemAddedWithName": "أُضيف {0} للمكتبة",
|
||||
"ItemRemovedWithName": "أُزيل {0} من المكتبة",
|
||||
"LabelIpAddressValue": "عنوان الآي بي: {0}",
|
||||
"LabelRunningTimeValue": "مدة التشغيل: {0}",
|
||||
"Latest": "الأحدث",
|
||||
"MessageApplicationUpdated": "تم تحديث خادم Jellyfin",
|
||||
"MessageApplicationUpdatedTo": "تم تحديث خادم Jellyfin إلى {0}",
|
||||
"MessageNamedServerConfigurationUpdatedWithValue": "تم تحديث قسم إعدادات الخادم {0}",
|
||||
"MessageServerConfigurationUpdated": "تم تحديث إعدادات الخادم",
|
||||
"MessageApplicationUpdated": "حُدث خادم Jellyfin",
|
||||
"MessageApplicationUpdatedTo": "حُدث خادم Jellyfin إلى {0}",
|
||||
"MessageNamedServerConfigurationUpdatedWithValue": "حُدثت إعدادات الخادم في قسم {0}",
|
||||
"MessageServerConfigurationUpdated": "حُدثت إعدادات الخادم",
|
||||
"MixedContent": "محتوى مختلط",
|
||||
"Movies": "الأفلام",
|
||||
"Music": "الموسيقى",
|
||||
"MusicVideos": "الفيديوهات الموسيقية",
|
||||
"NameInstallFailed": "فشل تثبيت {0}",
|
||||
"NameSeasonNumber": "الموسم {0}",
|
||||
"NameSeasonUnknown": "موسم غير معروف",
|
||||
"NewVersionIsAvailable": "يتوفر إصدار جديد من خادم Jellyfin للتنزيل.",
|
||||
"NotificationOptionApplicationUpdateAvailable": "تحديث التطبيق متاح",
|
||||
"NotificationOptionApplicationUpdateInstalled": "تم تثبيت تحديث التطبيق",
|
||||
"NotificationOptionAudioPlayback": "بدأ تشغيل الصوت",
|
||||
"NotificationOptionAudioPlaybackStopped": "توقف تشغيل الصوت",
|
||||
"NotificationOptionCameraImageUploaded": "تم رفع صورة كاميرا",
|
||||
"NotificationOptionInstallationFailed": "فشل التثبيت",
|
||||
"NotificationOptionNewLibraryContent": "تمت إضافة محتوى جديد",
|
||||
"NotificationOptionPluginError": "خطأ في الملحق",
|
||||
"NotificationOptionPluginInstalled": "تم تثبيت الملحق",
|
||||
"NameSeasonUnknown": "الموسم غير معروف",
|
||||
"NewVersionIsAvailable": "نسخة جديدة من خادم Jellyfin متوفرة للتحميل.",
|
||||
"NotificationOptionApplicationUpdateAvailable": "يوجد تحديث للتطبيق",
|
||||
"NotificationOptionApplicationUpdateInstalled": "نُصب تحديث التطبيق",
|
||||
"NotificationOptionAudioPlayback": "بدأ تشغيل المقطع الصوتي",
|
||||
"NotificationOptionAudioPlaybackStopped": "أُوقف تشغيل المقطع الصوتي",
|
||||
"NotificationOptionCameraImageUploaded": "رُفعت صورة الكاميرا",
|
||||
"NotificationOptionInstallationFailed": "فشل في التثبيت",
|
||||
"NotificationOptionNewLibraryContent": "أُضيف محتوى جديدا",
|
||||
"NotificationOptionPluginError": "فشل في الملحق",
|
||||
"NotificationOptionPluginInstalled": "ثُبتت الملحق",
|
||||
"NotificationOptionPluginUninstalled": "تمت إزالة الملحق",
|
||||
"NotificationOptionPluginUpdateInstalled": "تم تحديث الملحق",
|
||||
"NotificationOptionServerRestartRequired": "مطلوب إعادة تشغيل الخادم",
|
||||
"NotificationOptionTaskFailed": "فشل المهمة المجدولة",
|
||||
"NotificationOptionUserLockedOut": "تم قفل حساب المستخدم",
|
||||
"NotificationOptionPluginUpdateInstalled": "تم تثبيت تحديثات الملحق",
|
||||
"NotificationOptionServerRestartRequired": "يجب إعادة تشغيل الخادم",
|
||||
"NotificationOptionTaskFailed": "فشل في المهمة المجدولة",
|
||||
"NotificationOptionUserLockedOut": "تم إقفال حساب المستخدم",
|
||||
"NotificationOptionVideoPlayback": "بدأ تشغيل الفيديو",
|
||||
"NotificationOptionVideoPlaybackStopped": "توقف تشغيل الفيديو",
|
||||
"NotificationOptionVideoPlaybackStopped": "تم إيقاف تشغيل الفيديو",
|
||||
"Photos": "الصور",
|
||||
"Playlists": "قوائم التشغيل",
|
||||
"Plugin": "الملحق",
|
||||
"PluginInstalledWithName": "تم تثبيت {0}",
|
||||
"PluginUninstalledWithName": "تمت إزالة {0}",
|
||||
"PluginUpdatedWithName": "تم تحديث {0}",
|
||||
"ProviderValue": "المزوّد: {0}",
|
||||
"ScheduledTaskFailedWithName": "فشلت {0}",
|
||||
"ScheduledTaskStartedWithName": "بدأت {0}",
|
||||
"ServerNameNeedsToBeRestarted": "يحتاج {0} إلى إعادة التشغيل",
|
||||
"Shows": "المسلسلات",
|
||||
"ProviderValue": "المزود: {0}",
|
||||
"ScheduledTaskFailedWithName": "فشلت العملية {0}",
|
||||
"ScheduledTaskStartedWithName": "تم بدء العملية {0}",
|
||||
"ServerNameNeedsToBeRestarted": "يحتاج {0} لإعادة التشغيل",
|
||||
"Shows": "العروض",
|
||||
"Songs": "الأغاني",
|
||||
"StartupEmbyServerIsLoading": "يتم الآن تحميل خادم Jellyfin. يرجى المحاولة مرة أخرى بعد قليل.",
|
||||
"SubtitleDownloadFailureFromForItem": "فشل تنزيل الترجمات من {0} لـ {1}",
|
||||
"StartupEmbyServerIsLoading": "يتم تحميل خادم Jellyfin . الرجاء المحاولة بعد قليل.",
|
||||
"SubtitleDownloadFailureFromForItem": "فشل تحميل الترجمات من {0} ل {1}",
|
||||
"Sync": "مزامنة",
|
||||
"System": "النظام",
|
||||
"TvShows": "البرامج التلفزيونية",
|
||||
"User": "المستخدم",
|
||||
"UserCreatedWithName": "تم إنشاء المستخدم {0}",
|
||||
"UserDeletedWithName": "تم حذف المستخدم {0}",
|
||||
"UserDownloadingItemWithValues": "{0} يقوم بتنزيل {1}",
|
||||
"UserLockedOutWithName": "تم قفل حساب المستخدم {0}",
|
||||
"UserOfflineFromDevice": "انقطع اتصال {0} من {1}",
|
||||
"UserOnlineFromDevice": "{0} متصل من {1}",
|
||||
"UserPasswordChangedWithName": "تم تغيير كلمة المرور للمستخدم {0}",
|
||||
"UserPolicyUpdatedWithName": "تم تحديث سياسة المستخدم لـ {0}",
|
||||
"UserStartedPlayingItemWithValues": "{0} يقوم بتشغيل {1} على {2}",
|
||||
"UserStoppedPlayingItemWithValues": "أنهى {0} تشغيل {1} على {2}",
|
||||
"ValueHasBeenAddedToLibrary": "تمت إضافة {0} إلى مكتبة المحتوى الخاصة بك",
|
||||
"ValueSpecialEpisodeName": "خاص - {0}",
|
||||
"UserDownloadingItemWithValues": "يقوم {0} بتنزيل {1}",
|
||||
"UserLockedOutWithName": "تم منع المستخدم {0} من الدخول",
|
||||
"UserOfflineFromDevice": "تم قطع اتصال {0} من {1}",
|
||||
"UserOnlineFromDevice": "{0} متصل عبر {1}",
|
||||
"UserPasswordChangedWithName": "تم تغيير كلمة السر للمستخدم {0}",
|
||||
"UserPolicyUpdatedWithName": "تم تحديث سياسة المستخدم {0}",
|
||||
"UserStartedPlayingItemWithValues": "قام {0} ببدء تشغيل {1} على {2}",
|
||||
"UserStoppedPlayingItemWithValues": "قام {0} بإيقاف تشغيل {1} على {2}",
|
||||
"ValueHasBeenAddedToLibrary": "تمت اضافت {0} إلى مكتبة الوسائط",
|
||||
"ValueSpecialEpisodeName": "حلقة خاصه - {0}",
|
||||
"VersionNumber": "الإصدار {0}",
|
||||
"TaskCleanCacheDescription": "يحذف ملفات ذاكرة التخزين المؤقت التي لم يعد النظام بحاجة إليها.",
|
||||
"TaskCleanCache": "تنظيف مجلد ذاكرة التخزين المؤقت",
|
||||
"TaskCleanCacheDescription": "يحذف الملفات المؤقتة التي لم يعد النظام بحاجة إليها.",
|
||||
"TaskCleanCache": "حذف الملفات المؤقتة",
|
||||
"TasksChannelsCategory": "قنوات الإنترنت",
|
||||
"TasksLibraryCategory": "المكتبة",
|
||||
"TasksMaintenanceCategory": "الصيانة",
|
||||
"TaskRefreshLibraryDescription": "يفحص مكتبة المحتوى الخاصة بك بحثاً عن ملفات جديدة ويحدّث البيانات الوصفية.",
|
||||
"TaskRefreshLibrary": "فحص مكتبة المحتوى",
|
||||
"TaskRefreshChapterImagesDescription": "ينشئ صوراً مصغرة للفيديوهات التي تحتوي على فصول.",
|
||||
"TaskRefreshChapterImages": "استخراج صور الفصول",
|
||||
"TasksApplicationCategory": "التطبيق",
|
||||
"TaskDownloadMissingSubtitlesDescription": "يبحث في الإنترنت عن الترجمات المفقودة بناءً على إعدادات البيانات الوصفية.",
|
||||
"TaskDownloadMissingSubtitles": "تنزيل الترجمات المفقودة",
|
||||
"TaskRefreshChannelsDescription": "يحدّث معلومات قنوات الإنترنت.",
|
||||
"TaskRefreshChannels": "تحديث القنوات",
|
||||
"TaskCleanTranscodeDescription": "يحذف ملفات تحويل الترميز التي مر عليها أكثر من يوم واحد.",
|
||||
"TaskCleanTranscode": "تنظيف مجلد تحويل الترميز",
|
||||
"TaskUpdatePluginsDescription": "ينزّل ويثبّت التحديثات للملحقات المهيأة للتحديث التلقائي.",
|
||||
"TaskUpdatePlugins": "تحديث الملحقات",
|
||||
"TaskRefreshPeopleDescription": "يحدّث البيانات الوصفية للممثلين والمخرجين في مكتبة المحتوى الخاصة بك.",
|
||||
"TaskRefreshPeople": "تحديث الأشخاص",
|
||||
"TaskCleanLogsDescription": "يحذف ملفات السجل التي يزيد عمرها عن {0} أيام.",
|
||||
"TaskCleanLogs": "تنظيف مجلد السجلات",
|
||||
"TaskCleanActivityLogDescription": "يحذف إدخالات سجل النشاط الأقدم من العمر المحدد.",
|
||||
"TaskCleanActivityLog": "تنظيف سجل النشاط",
|
||||
"Default": "الافتراضي",
|
||||
"Undefined": "غير محدد",
|
||||
"Forced": "إجباري",
|
||||
"TaskOptimizeDatabaseDescription": "يضغط قاعدة البيانات ويقلل المساحة الحرة. قد يؤدي تشغيل هذه المهمة بعد فحص المكتبة أو إجراء تغييرات أخرى تتضمن تعديلات على قاعدة البيانات إلى تحسين الأداء.",
|
||||
"TasksLibraryCategory": "مكتبة",
|
||||
"TasksMaintenanceCategory": "صيانة",
|
||||
"TaskRefreshLibraryDescription": "يفحص مكتبة الوسائط الخاصة بك باحثا عن ملفات جديدة، ومن ثم يُحدث البيانات الوصفية.",
|
||||
"TaskRefreshLibrary": "افحص مكتبة الوسائط",
|
||||
"TaskRefreshChapterImagesDescription": "يُنشئ صور مصغرة لمقاطع الفيديو التي تحتوي على فصول.",
|
||||
"TaskRefreshChapterImages": "استخراج صور الفصل",
|
||||
"TasksApplicationCategory": "تطبيق",
|
||||
"TaskDownloadMissingSubtitlesDescription": "يبحث في الإنترنت على الترجمات الناقصة استنادا على البيانات الوصفية.",
|
||||
"TaskDownloadMissingSubtitles": "تحميل الترجمات الناقصة",
|
||||
"TaskRefreshChannelsDescription": "يحدث معلومات قنوات الإنترنت.",
|
||||
"TaskRefreshChannels": "إعادة تحديث القنوات",
|
||||
"TaskCleanTranscodeDescription": "يحذف ملفات الترميز الأقدم من يوم واحد.",
|
||||
"TaskCleanTranscode": "حذف ما بمجلد الترميز",
|
||||
"TaskUpdatePluginsDescription": "تحميل وتثبيت الإضافات التي تم تفعيل التحديث التلقائي لها.",
|
||||
"TaskUpdatePlugins": "تحديث الإضافات",
|
||||
"TaskRefreshPeopleDescription": "يقوم بتحديث البيانات الوصفية للممثلين والمخرجين في مكتبة الوسائط الخاصة بك.",
|
||||
"TaskRefreshPeople": "إعادة تحميل الأشخاص",
|
||||
"TaskCleanLogsDescription": "يحذف السجلات الأقدم من {0} يوم.",
|
||||
"TaskCleanLogs": "حذف مسار السجل",
|
||||
"TaskCleanActivityLogDescription": "يحذف سجل الأنشطة الأقدم من الوقت الذي تم تحديده.",
|
||||
"TaskCleanActivityLog": "حذف سجل الأنشطة",
|
||||
"Default": "افتراضي",
|
||||
"Undefined": "غير معرف",
|
||||
"Forced": "ملحقة",
|
||||
"TaskOptimizeDatabaseDescription": "يضغط قاعدة البيانات ويقتطع المساحة الحرة. تشغيل هذه المهمة بعد فحص المكتبة أو إجراء تغييرات أخرى تتضمن تعديلات في قاعدة البيانات قد تؤدي إلى تحسين الأداء.",
|
||||
"TaskOptimizeDatabase": "تحسين قاعدة البيانات",
|
||||
"TaskKeyframeExtractorDescription": "يستخرج الإطارات الرئيسية من ملفات الفيديو لإنشاء قوائم تشغيل HLS أكثر دقة. قد يستغرق تشغيل هذه المهمة وقتاً طويلاً.",
|
||||
"TaskKeyframeExtractor": "مستخرج الإطارات الرئيسية",
|
||||
"TaskKeyframeExtractorDescription": "يستخرج الإطارات الرئيسية من ملفات الفيديو لكي ينشئ قوائم تشغيل بث HTTP المباشر. قد تستمر هذه العملية لوقت طويل.",
|
||||
"TaskKeyframeExtractor": "مستخرج الإطار الرئيسي",
|
||||
"External": "خارجي",
|
||||
"HearingImpaired": "لضعاف السمع",
|
||||
"TaskRefreshTrickplayImages": "إنشاء صور معاينات التنقل (Trickplay)",
|
||||
"TaskRefreshTrickplayImagesDescription": "ينشئ صور معاينات التنقل السريع للفيديوهات في المكتبات المفعّلة.",
|
||||
"TaskAudioNormalization": "تطبيع الصوت",
|
||||
"TaskAudioNormalizationDescription": "يفحص الملفات لجمع بيانات تطبيع الصوت.",
|
||||
"TaskDownloadMissingLyrics": "تنزيل الكلمات المفقودة",
|
||||
"TaskDownloadMissingLyricsDescription": "ينزّل الكلمات للأغاني.",
|
||||
"TaskExtractMediaSegments": "فحص مقاطع المحتوى",
|
||||
"TaskExtractMediaSegmentsDescription": "يستخرج أو يحصل على مقاطع المحتوى من الملحقات المفعّلة لمقاطع المحتوى (MediaSegment).",
|
||||
"TaskMoveTrickplayImages": "نقل موقع صور معاينات التنقل",
|
||||
"TaskMoveTrickplayImagesDescription": "ينقل ملفات معاينات التنقل الحالية وفقاً لإعدادات المكتبة.",
|
||||
"HearingImpaired": "ضعاف السمع",
|
||||
"TaskRefreshTrickplayImages": "توليد صور المعاينة السريعة",
|
||||
"TaskRefreshTrickplayImagesDescription": "يُولّد معاينات تنقل سريع لمقاطع الفيديو ضمن المكتبات المفعّلة.",
|
||||
"TaskCleanCollectionsAndPlaylists": "حذف المجموعات وقوائم التشغيل",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "حذف عناصر من المجموعات وقوائم التشغيل التي لم تعد موجودة.",
|
||||
"TaskAudioNormalization": "تسوية الصوت",
|
||||
"TaskAudioNormalizationDescription": "مسح الملفات لتطبيع بيانات الصوت.",
|
||||
"TaskDownloadMissingLyrics": "تنزيل عبارات القصيدة",
|
||||
"TaskDownloadMissingLyricsDescription": "كلمات",
|
||||
"TaskExtractMediaSegments": "فحص مقاطع الوسائط",
|
||||
"TaskExtractMediaSegmentsDescription": "يستخرج مقاطع وسائط من إضافات MediaSegment المُفعّلة.",
|
||||
"TaskMoveTrickplayImages": "تغيير مكان صور المعاينة السريعة",
|
||||
"TaskMoveTrickplayImagesDescription": "تُنقل ملفات التشغيل السريع الحالية بناءً على إعدادات المكتبة.",
|
||||
"CleanupUserDataTask": "مهمة تنظيف بيانات المستخدم",
|
||||
"CleanupUserDataTaskDescription": "ينظف جميع بيانات المستخدم (مثل حالة المشاهدة وحالة المفضلة وغيرها) للمحتوى الذي لم يعد موجوداً لمدة 90 يوماً على الأقل."
|
||||
"CleanupUserDataTaskDescription": "مسح جميع بيانات المستخدم (حالة المشاهدة، والحالة المفضلة وما إلى ذلك) من الوسائط التي لم تعد موجودة لمدة 90 يومًا على الأقل."
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
{}
|
||||
@@ -126,6 +126,8 @@
|
||||
"TaskKeyframeExtractorDescription": "Выдае ключавыя кадры з відэафайлаў для стварэння больш дакладных плэй-лістоў HLS. Гэта задача можа выконвацца доўга.",
|
||||
"TaskRefreshTrickplayImages": "Стварыць выявы Trickplay",
|
||||
"TaskRefreshTrickplayImagesDescription": "Стварае перадпрагляды відэаролікаў для Trickplay у падключаных бібліятэках.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Ачысціць калекцыі і плэй-лісты",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Выдаляе элементы з калекцый і плэй-лістоў, якія больш не існуюць.",
|
||||
"TaskAudioNormalizationDescription": "Скануе файлы на прадмет нармалізацыі гуку.",
|
||||
"TaskAudioNormalization": "Нармалізацыя гуку",
|
||||
"TaskExtractMediaSegmentsDescription": "Выдае або атрымлівае медыясегменты з убудоў з падтрымкай MediaSegment.",
|
||||
|
||||
@@ -128,6 +128,8 @@
|
||||
"TaskRefreshTrickplayImagesDescription": "Създава прегледи на Trickplay за видеа в активирани библиотеки.",
|
||||
"TaskDownloadMissingLyrics": "Свали липсващи текстове",
|
||||
"TaskDownloadMissingLyricsDescription": "Свали текстове за песни",
|
||||
"TaskCleanCollectionsAndPlaylists": "Изчисти колекциите и плейлистите",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Премахни несъществуващи файлове в колекциите и плейлистите.",
|
||||
"TaskAudioNormalization": "Нормализиране на звука",
|
||||
"TaskAudioNormalizationDescription": "Сканирай файловете за нормализация на звука.",
|
||||
"TaskExtractMediaSegmentsDescription": "Изважда медиини сегменти от MediaSegment плъгини.",
|
||||
|
||||
@@ -127,6 +127,8 @@
|
||||
"TaskRefreshTrickplayImages": "ট্রিকপ্লে ইমেজ তৈরি",
|
||||
"TaskRefreshTrickplayImagesDescription": "সক্ষম লাইব্রেরিতে ভিডিওর জন্য ট্রিকপ্লে প্রিভিউ তৈরি করে।",
|
||||
"TaskDownloadMissingLyricsDescription": "গানের জন্য লিরিকস ডাউনলোড করুন",
|
||||
"TaskCleanCollectionsAndPlaylists": "কালেকশন এবং প্লেলিস্ট পরিষ্কার করুন",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "কালেকশন এবং প্লেলিস্ট থেকে আইটেমগুলি সরিয়ে দেয় যা আর বিদ্যমান নেই।",
|
||||
"TaskExtractMediaSegments": "মিডিয়া সেগমেন্ট স্ক্যান",
|
||||
"TaskExtractMediaSegmentsDescription": "মিডিয়া সেগমেন্ট সক্ষম প্লাগইনগুলি থেকে মিডিয়া সেগমেন্ট বের করে বা অর্জন করে।",
|
||||
"TaskDownloadMissingLyrics": "অনুপস্থিত গান ডাউনলোড করুন",
|
||||
|
||||
@@ -1,139 +0,0 @@
|
||||
{
|
||||
"Albums": "Albumi",
|
||||
"Artists": "Umjetnici",
|
||||
"Books": "Knjige",
|
||||
"Channels": "Kanalima",
|
||||
"Collections": "Zbirke",
|
||||
"Default": "Zadano",
|
||||
"Favorites": "Omiljeni",
|
||||
"Folders": "Mape",
|
||||
"Genres": "Žanrovi",
|
||||
"HeaderAlbumArtists": "Umjetnici albuma",
|
||||
"HeaderContinueWatching": "Nastavi gledati",
|
||||
"Movies": "Filmovi",
|
||||
"MusicVideos": "Muzički spotovi",
|
||||
"Photos": "Slike",
|
||||
"Playlists": "Plejliste",
|
||||
"Shows": "Pokazuje",
|
||||
"Songs": "Pjesme",
|
||||
"ValueSpecialEpisodeName": "Posebno - {0}",
|
||||
"AppDeviceValues": "Aplikacija: {0}, Uređaj: {1}",
|
||||
"Application": "Prijava",
|
||||
"AuthenticationSucceededWithUserName": "{0} uspješno autentificirano",
|
||||
"CameraImageUploadedFrom": "Nova slika s kamere je postavljena sa {0}",
|
||||
"ChapterNameValue": "Poglavlje {0}",
|
||||
"DeviceOfflineWithName": "{0} se odspojio",
|
||||
"DeviceOnlineWithName": "{0} je povezan",
|
||||
"External": "Vanjsko",
|
||||
"FailedLoginAttemptWithUserName": "Neuspjeli pokušaj prijave sa {0}",
|
||||
"Forced": "Prisilno",
|
||||
"HeaderFavoriteAlbums": "Omiljeni albumi",
|
||||
"HeaderFavoriteArtists": "Omiljeni umjetnici",
|
||||
"HeaderFavoriteEpisodes": "Omiljene epizode",
|
||||
"HeaderFavoriteShows": "Omiljene emisije",
|
||||
"HeaderFavoriteSongs": "Omiljene pjesme",
|
||||
"HeaderLiveTV": "TV uživo",
|
||||
"HeaderNextUp": "Slijedi",
|
||||
"HeaderRecordingGroups": "Grupe za snimanje",
|
||||
"HearingImpaired": "Oštećen sluh",
|
||||
"HomeVideos": "Kućni videozapisi",
|
||||
"Inherit": "Nasljedi",
|
||||
"ItemAddedWithName": "{0} je dodan u biblioteku",
|
||||
"ItemRemovedWithName": "{0} je uklonjen iz biblioteke",
|
||||
"LabelIpAddressValue": "IP adresa: {0}",
|
||||
"LabelRunningTimeValue": "Trajanje: {0}",
|
||||
"Latest": "Posljednje dodano",
|
||||
"MessageApplicationUpdated": "Jellyfin Server je ažuriran",
|
||||
"MessageApplicationUpdatedTo": "Jellyfin Server je ažuriran na {0}",
|
||||
"MessageNamedServerConfigurationUpdatedWithValue": "Sekcija za konfiguraciju servera {0} je ažurirana",
|
||||
"MessageServerConfigurationUpdated": "Konfiguracija servera je ažurirana",
|
||||
"MixedContent": "Miješani sadržaj",
|
||||
"Music": "Muzika",
|
||||
"NameInstallFailed": "{0} instalacija je propala",
|
||||
"NameSeasonNumber": "Sezona {0}",
|
||||
"NameSeasonUnknown": "Sezona nepoznata",
|
||||
"NewVersionIsAvailable": "Dostupna je nova verzija Jellyfin Servera za preuzimanje.",
|
||||
"NotificationOptionApplicationUpdateAvailable": "Dostupno ažuriranje aplikacije",
|
||||
"NotificationOptionApplicationUpdateInstalled": "Ažuriranje aplikacije instalirano",
|
||||
"NotificationOptionAudioPlayback": "Pokrenuto je reproduciranje zvuka",
|
||||
"NotificationOptionAudioPlaybackStopped": "Zaustavljeno je reproduciranje zvuka",
|
||||
"NotificationOptionCameraImageUploaded": "Učitana slika s kamere",
|
||||
"NotificationOptionInstallationFailed": "Neuspjeh instalacije",
|
||||
"NotificationOptionNewLibraryContent": "Dodan novi sadržaj",
|
||||
"NotificationOptionPluginError": "Neuspjeh dodatka",
|
||||
"NotificationOptionPluginInstalled": "Dodatak je instaliran",
|
||||
"NotificationOptionPluginUninstalled": "Dodatak je deinstaliran",
|
||||
"NotificationOptionPluginUpdateInstalled": "Ažuriranje dodatka je instalirano",
|
||||
"NotificationOptionServerRestartRequired": "Potreban je ponovni pokret servera",
|
||||
"NotificationOptionTaskFailed": "Neuspjeh zakazane zadatke",
|
||||
"NotificationOptionUserLockedOut": "Korisnik je zaključan",
|
||||
"NotificationOptionVideoPlayback": "Pokrenuto je reproduciranje videa",
|
||||
"NotificationOptionVideoPlaybackStopped": "Reprodukcija videa je zaustavljena",
|
||||
"Plugin": "Plugin",
|
||||
"PluginInstalledWithName": "{0} je instaliran",
|
||||
"PluginUninstalledWithName": "{0} je deinstaliran",
|
||||
"PluginUpdatedWithName": "{0} je ažurirano",
|
||||
"ProviderValue": "Pružatelj: {0}",
|
||||
"ScheduledTaskFailedWithName": "{0} nije uspjelo",
|
||||
"ScheduledTaskStartedWithName": "{0} počelo",
|
||||
"ServerNameNeedsToBeRestarted": "{0} treba ponovo pokrenuti",
|
||||
"StartupEmbyServerIsLoading": "Jellyfin Server se učitava. Molimo pokušajte ponovo za kratko vrijeme.",
|
||||
"SubtitleDownloadFailureFromForItem": "Podtitlovi nisu uspjeli preuzeti sa {0} za {1}",
|
||||
"Sync": "Sinkronizacija",
|
||||
"System": "Sistem",
|
||||
"TvShows": "TV serije",
|
||||
"Undefined": "Nedefinirano",
|
||||
"User": "Korisnik",
|
||||
"UserCreatedWithName": "Korisnik {0} je kreiran",
|
||||
"UserDeletedWithName": "Korisnik {0} je izbrisan",
|
||||
"UserDownloadingItemWithValues": "{0} preuzima {1}",
|
||||
"UserLockedOutWithName": "Korisnik {0} je zaključan",
|
||||
"UserOfflineFromDevice": "{0} se odspojio od {1}",
|
||||
"UserOnlineFromDevice": "{0} je online od {1}",
|
||||
"UserPasswordChangedWithName": "Lozinka je promijenjena za korisnika {0}",
|
||||
"UserPolicyUpdatedWithName": "Pravila za korisnike su ažurirana za {0}",
|
||||
"UserStartedPlayingItemWithValues": "{0} igra protiv {1} na {2}",
|
||||
"UserStoppedPlayingItemWithValues": "{0} je završio igru protiv {1} na {2}",
|
||||
"ValueHasBeenAddedToLibrary": "{0} je dodan u vašu medijsku biblioteku",
|
||||
"VersionNumber": "Verzija {0}",
|
||||
"TasksMaintenanceCategory": "Održavanje",
|
||||
"TasksLibraryCategory": "Biblioteka",
|
||||
"TasksApplicationCategory": "Prijava",
|
||||
"TasksChannelsCategory": "Internetski kanali",
|
||||
"TaskCleanActivityLog": "Očisti dnevnik aktivnosti",
|
||||
"TaskCleanActivityLogDescription": "Brisanje unosa u dnevnik aktivnosti starijih od konfigurisane starosti.",
|
||||
"TaskCleanCache": "Očistite direktorij keša",
|
||||
"TaskCleanCacheDescription": "Brisanje keš datoteka koje sistemu više nisu potrebne.",
|
||||
"TaskRefreshChapterImages": "Izvadi slike iz poglavlja",
|
||||
"TaskRefreshChapterImagesDescription": "Stvara minijature za videozapise koji imaju poglavlja.",
|
||||
"TaskAudioNormalization": "Normalizacija zvuka",
|
||||
"TaskAudioNormalizationDescription": "Skeneriše datoteke radi podataka za normalizaciju zvuka.",
|
||||
"TaskRefreshLibrary": "Skenerisati medijsku biblioteku",
|
||||
"TaskRefreshLibraryDescription": "Skenerira vašu medijsku biblioteku na nove datoteke i osvježava metapodatke.",
|
||||
"TaskCleanLogs": "Očisti direktorij dnevnika",
|
||||
"TaskCleanLogsDescription": "Brisanje dnevničkih datoteka starijih od {0} dana.",
|
||||
"TaskRefreshPeople": "Osvježite ljude",
|
||||
"TaskRefreshPeopleDescription": "Ažurira metapodatke za glumce i režisere u vašoj medijskoj biblioteci.",
|
||||
"TaskRefreshTrickplayImages": "Generirajte Trickplay slike",
|
||||
"TaskRefreshTrickplayImagesDescription": "Stvara pregled trik-igara za videozapise u omogućenim bibliotekama.",
|
||||
"TaskUpdatePlugins": "Ažuriraj dodatke",
|
||||
"TaskUpdatePluginsDescription": "Preuzima i instalira ažuriranja dodataka koji su konfigurisani da se automatski ažuriraju.",
|
||||
"TaskCleanTranscode": "Očisti Transcode direktorij",
|
||||
"TaskCleanTranscodeDescription": "Brisanje transkodiranih datoteka starijih od jednog dana.",
|
||||
"TaskRefreshChannels": "Osvježi kanale",
|
||||
"TaskRefreshChannelsDescription": "Osvježava informacije o internetskom kanalu.",
|
||||
"TaskDownloadMissingLyrics": "Preuzmi nedostajuće tekstove",
|
||||
"TaskDownloadMissingLyricsDescription": "Preuzmi tekstove pjesama",
|
||||
"TaskDownloadMissingSubtitles": "Preuzmite nedostajuće titlove",
|
||||
"TaskDownloadMissingSubtitlesDescription": "Pretražuje internet u potrazi za nedostajućim titlovima na osnovu konfiguracije metapodataka.",
|
||||
"TaskOptimizeDatabase": "Optimizirajte bazu podataka",
|
||||
"TaskOptimizeDatabaseDescription": "Komprimira bazu podataka i čisti slobodan prostor. Pokretanje ovog zadatka nakon skeniranja biblioteke ili izvođenja drugih promjena koje podrazumijevaju izmjene baze podataka može poboljšati performanse.",
|
||||
"TaskKeyframeExtractor": "Izvađač ključnih sličica",
|
||||
"TaskKeyframeExtractorDescription": "Izvlači ključne okvire iz video datoteka kako bi kreirao preciznije HLS playliste. Ovaj zadatak može trajati dugo.",
|
||||
"TaskExtractMediaSegments": "Analiza medijskog segmenta",
|
||||
"TaskExtractMediaSegmentsDescription": "Izvlači ili dobija medijske segmente iz dodataka koji podržavaju MediaSegment.",
|
||||
"TaskMoveTrickplayImages": "Migracija lokacije slike Trickplay",
|
||||
"TaskMoveTrickplayImagesDescription": "Premješta postojeće datoteke trik-igara prema postavkama biblioteke.",
|
||||
"CleanupUserDataTask": "Zadatak čišćenja korisničkih podataka",
|
||||
"CleanupUserDataTaskDescription": "Čisti sve korisničke podatke (stanje praćenja, status omiljenog itd.) sa medija koji više nije prisutan najmanje 90 dana."
|
||||
}
|
||||
@@ -63,8 +63,8 @@
|
||||
"Photos": "Fotos",
|
||||
"Playlists": "Llistes de reproducció",
|
||||
"Plugin": "Complement",
|
||||
"PluginInstalledWithName": "S'ha instal·lat {0}",
|
||||
"PluginUninstalledWithName": "S'ha desinstal·lat {0}",
|
||||
"PluginInstalledWithName": "{0} ha estat instal·lat",
|
||||
"PluginUninstalledWithName": "S'ha instal·lat {0}",
|
||||
"PluginUpdatedWithName": "S'ha actualitzat {0}",
|
||||
"ProviderValue": "Proveïdor: {0}",
|
||||
"ScheduledTaskFailedWithName": "{0} ha fallat",
|
||||
@@ -126,6 +126,8 @@
|
||||
"HearingImpaired": "Discapacitat auditiva",
|
||||
"TaskRefreshTrickplayImages": "Generació d'imatges de previsualització",
|
||||
"TaskRefreshTrickplayImagesDescription": "Creació d'imatges de previsualització per a vídeos en les mediateques habilitades.",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Esborra elements de col·leccions i llistes de reproducció que ja no existeixen.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Neteja de les col·leccions i llistes de reproducció",
|
||||
"TaskAudioNormalization": "Estabilització de l'àudio",
|
||||
"TaskAudioNormalizationDescription": "Escaneja els fitxer per a obtenir dades de normalització de l'àudio.",
|
||||
"TaskDownloadMissingLyricsDescription": "Descàrrega de les lletres de les cançons",
|
||||
|
||||
@@ -126,6 +126,8 @@
|
||||
"HearingImpaired": "Sluchově postižení",
|
||||
"TaskRefreshTrickplayImages": "Generovat obrázky pro Trickplay",
|
||||
"TaskRefreshTrickplayImagesDescription": "Obrázky Trickplay se používají k zobrazení náhledů u videí v knihovnách, kde je to povoleno.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Pročistit kolekce a seznamy přehrávání",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Odstraní neexistující položky z kolekcí a seznamů přehrávání.",
|
||||
"TaskAudioNormalization": "Normalizace zvuku",
|
||||
"TaskAudioNormalizationDescription": "Skenovat soubory za účelem normalizace zvuku.",
|
||||
"TaskDownloadMissingLyrics": "Stáhnout chybějící texty k písni",
|
||||
|
||||
@@ -130,5 +130,7 @@
|
||||
"TaskRefreshTrickplayImagesDescription": "Creu rhagolygon Trickplay ar gyfer fideos mewn llyfrgelloedd gweithredol.",
|
||||
"TaskDownloadMissingLyrics": "Lawrlwytho geiriau coll",
|
||||
"TaskDownloadMissingLyricsDescription": "Lawrlwytho geiriau caneuon",
|
||||
"TaskCleanCollectionsAndPlaylists": "Glanhau casgliadau a rhestrau chwarae",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Dileu eitemau o gasgliadau a rhestrau chwarae sydd ddim yn bodoli bellach.",
|
||||
"TaskExtractMediaSegments": "Sganio Darnau Cyfryngau"
|
||||
}
|
||||
|
||||
@@ -126,6 +126,8 @@
|
||||
"HearingImpaired": "Hørehæmmet",
|
||||
"TaskRefreshTrickplayImages": "Generer trickplay-billeder",
|
||||
"TaskRefreshTrickplayImagesDescription": "Laver trickplay-billeder for videoer i aktiverede biblioteker.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Ryd op i samlinger og afspilningslister",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Fjerner elementer fra samlinger og afspilningslister der ikke eksisterer længere.",
|
||||
"TaskAudioNormalizationDescription": "Skanner filer for data vedrørende lydnormalisering.",
|
||||
"TaskAudioNormalization": "Lydnormalisering",
|
||||
"TaskDownloadMissingLyricsDescription": "Søger på internettet efter manglende sangtekster baseret på metadata-konfigurationen",
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
"HeaderContinueWatching": "Weiterschauen",
|
||||
"HeaderFavoriteAlbums": "Lieblingsalben",
|
||||
"HeaderFavoriteArtists": "Lieblingsinterpreten",
|
||||
"HeaderFavoriteEpisodes": "Lieblingsfolgen",
|
||||
"HeaderFavoriteEpisodes": "Lieblingsepisoden",
|
||||
"HeaderFavoriteShows": "Lieblingsserien",
|
||||
"HeaderFavoriteSongs": "Lieblingssongs",
|
||||
"HeaderLiveTV": "Live TV",
|
||||
@@ -126,6 +126,8 @@
|
||||
"HearingImpaired": "Hörgeschädigt",
|
||||
"TaskRefreshTrickplayImages": "Trickplay-Bilder generieren",
|
||||
"TaskRefreshTrickplayImagesDescription": "Erstellt ein Trickplay-Vorschauen für Videos in aktivierten Bibliotheken.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Sammlungen und Playlisten aufräumen",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Löscht nicht mehr vorhandene Einträge aus den Sammlungen und Playlisten.",
|
||||
"TaskAudioNormalization": "Audio Normalisierung",
|
||||
"TaskAudioNormalizationDescription": "Durchsucht Dateien nach Audionormalisierungsdaten.",
|
||||
"TaskDownloadMissingLyricsDescription": "Lädt Songtexte herunter",
|
||||
|
||||
@@ -128,6 +128,8 @@
|
||||
"TaskRefreshTrickplayImagesDescription": "Δημιουργεί προεπισκοπήσεις trickplay για βίντεο σε ενεργοποιημένες βιβλιοθήκες.",
|
||||
"TaskAudioNormalization": "Ομοιομορφία ήχου",
|
||||
"TaskAudioNormalizationDescription": "Ανίχνευση αρχείων για δεδομένα ομοιομορφίας ήχου.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Καθαρισμός συλλογών και λιστών αναπαραγωγής",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Αφαιρούνται στοιχεία από τις συλλογές και τις λίστες αναπαραγωγής που δεν υπάρχουν πλέον.",
|
||||
"TaskMoveTrickplayImages": "Αλλαγή τοποθεσίας εικόνων Trickplay",
|
||||
"TaskDownloadMissingLyrics": "Λήψη στίχων που λείπουν",
|
||||
"TaskMoveTrickplayImagesDescription": "Μετακινεί τα υπάρχοντα αρχεία trickplay σύμφωνα με τις ρυθμίσεις της βιβλιοθήκης.",
|
||||
|
||||
@@ -126,6 +126,8 @@
|
||||
"HearingImpaired": "Hearing Impaired",
|
||||
"TaskRefreshTrickplayImages": "Generate Trickplay Images",
|
||||
"TaskRefreshTrickplayImagesDescription": "Creates trickplay previews for videos in enabled libraries.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Clean up collections and playlists",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Removes items from collections and playlists that no longer exist.",
|
||||
"TaskAudioNormalization": "Audio Normalisation",
|
||||
"TaskAudioNormalizationDescription": "Scans files for audio normalisation data.",
|
||||
"TaskDownloadMissingLyrics": "Download missing lyrics",
|
||||
|
||||
@@ -130,6 +130,8 @@
|
||||
"TaskOptimizeDatabaseDescription": "Compacts database and truncates free space. Running this task after scanning the library or doing other changes that imply database modifications might improve performance.",
|
||||
"TaskKeyframeExtractor": "Keyframe Extractor",
|
||||
"TaskKeyframeExtractorDescription": "Extracts keyframes from video files to create more precise HLS playlists. This task may run for a long time.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Clean up collections and playlists",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Removes items from collections and playlists that no longer exist.",
|
||||
"TaskExtractMediaSegments": "Media Segment Scan",
|
||||
"TaskExtractMediaSegmentsDescription": "Extracts or obtains media segments from MediaSegment enabled plugins.",
|
||||
"TaskMoveTrickplayImages": "Migrate Trickplay Image Location",
|
||||
|
||||
@@ -128,6 +128,8 @@
|
||||
"TaskRefreshTrickplayImagesDescription": "Crea vistas previas de reproducción engañosa para videos en bibliotecas habilitadas.",
|
||||
"TaskAudioNormalization": "Normalización de audio",
|
||||
"TaskAudioNormalizationDescription": "Escanea archivos en busca de datos de normalización de audio.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Limpiar colecciones y listas de reproducción",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Elimina elementos de colecciones y listas de reproducción que ya no existen.",
|
||||
"TaskDownloadMissingLyrics": "Descargar letra faltante",
|
||||
"TaskDownloadMissingLyricsDescription": "Descarga letras de canciones",
|
||||
"TaskExtractMediaSegments": "Escanear Segmentos de Media",
|
||||
|
||||
@@ -128,6 +128,8 @@
|
||||
"TaskRefreshTrickplayImages": "Generar imágenes de la barra de reproducción",
|
||||
"TaskAudioNormalization": "Normalización de audio",
|
||||
"TaskAudioNormalizationDescription": "Analiza los archivos para normalizar el audio.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Limpieza de colecciones y listas de reproducción",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Quita elementos que ya no existen de colecciones y listas de reproducción.",
|
||||
"TaskDownloadMissingLyrics": "descargar letras que faltan",
|
||||
"TaskDownloadMissingLyricsDescription": "Descargar letras de canciones",
|
||||
"TaskExtractMediaSegments": "Escaneo de segmentos de medios",
|
||||
|
||||
@@ -126,6 +126,8 @@
|
||||
"HearingImpaired": "Discapacidad Auditiva",
|
||||
"TaskRefreshTrickplayImages": "Generar miniaturas de línea de tiempo",
|
||||
"TaskRefreshTrickplayImagesDescription": "Crear miniaturas de tiempo para videos en las librerías habilitadas.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Limpiar colecciones y listas de reproducción",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Elimina elementos de colecciones y listas de reproducción que ya no existen.",
|
||||
"TaskAudioNormalization": "Normalización de audio",
|
||||
"TaskAudioNormalizationDescription": "Escanear archivos para obtener datos de normalización.",
|
||||
"TaskDownloadMissingLyricsDescription": "Descargar letras para las canciones",
|
||||
|
||||
@@ -127,7 +127,9 @@
|
||||
"TaskRefreshTrickplayImagesDescription": "Crea previsualizaciones para la barra de reproducción en las bibliotecas habilitadas.",
|
||||
"TaskRefreshTrickplayImages": "Generar imágenes de la barra de reproducción",
|
||||
"TaskAudioNormalization": "Normalización de audio",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Quita elementos que ya no existen de colecciones y listas de reproducción.",
|
||||
"TaskAudioNormalizationDescription": "Analiza los archivos para normalizar el audio.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Limpieza de colecciones y listas de reproducción",
|
||||
"TaskDownloadMissingLyrics": "Descargar letra faltante",
|
||||
"TaskDownloadMissingLyricsDescription": "Descarga letras de canciones",
|
||||
"TaskExtractMediaSegmentsDescription": "Extrae u obtiene segmentos de medios de complementos habilitados para MediaSegment.",
|
||||
|
||||
@@ -41,6 +41,8 @@
|
||||
"TaskKeyframeExtractorDescription": "Extrae Fotogramas Clave de los archivos de vídeo para crear Listas de Reproducción HLS más precisas. Esta tarea puede durar mucho tiempo.",
|
||||
"TaskAudioNormalization": "Normalización de audio",
|
||||
"TaskAudioNormalizationDescription": "Escanear archivos para la normalización de data.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Limpiar colecciones y listas de reproducción",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Remover elementos de colecciones y listas de reproducción que no existen.",
|
||||
"TvShows": "Series de TV",
|
||||
"UserStartedPlayingItemWithValues": "{0} está reproduciendo {1} en {2}",
|
||||
"TaskRefreshChannels": "Actualizar canales",
|
||||
|
||||
@@ -128,11 +128,13 @@
|
||||
"TaskRefreshTrickplayImagesDescription": "Loob trickplay eelvaated videotele lubatud meediakogudes.",
|
||||
"TaskAudioNormalization": "Normaliseeri helitugevus",
|
||||
"TaskAudioNormalizationDescription": "Otsib failidest helitugevuse normaliseerimise teavet.",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Eemaldab kogumikest ja esitusloenditest üksused, mida enam ei eksisteeri.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Puhasta kogumikud ja esitusloendid",
|
||||
"TaskDownloadMissingLyrics": "Hangi puuduvad laulusõnad",
|
||||
"TaskDownloadMissingLyricsDescription": "Laulusõnade allalaadimine",
|
||||
"TaskMoveTrickplayImagesDescription": "Liigutab trickplay pildid meediakogu sätete kohaselt.",
|
||||
"TaskExtractMediaSegments": "Skaneeri meedialõike",
|
||||
"TaskExtractMediaSegmentsDescription": "Eraldab või võtab meedialõigud MediaSegment'i toega pluginatest.",
|
||||
"TaskExtractMediaSegments": "Skaneeri meediasegmente",
|
||||
"TaskExtractMediaSegmentsDescription": "Eraldab või võtab meediasegmendid MediaSegment'i lubavatest pluginatest.",
|
||||
"TaskMoveTrickplayImages": "Muuda trickplay piltide asukoht",
|
||||
"CleanupUserDataTask": "Puhasta kasutajaandmed",
|
||||
"CleanupUserDataTaskDescription": "Puhastab kõik kasutajaandmed (vaatamise olek, lemmikute olek jne) meediast, mida pole enam vähemalt 90 päeva saadaval olnud."
|
||||
|
||||
@@ -130,6 +130,8 @@
|
||||
"TaskDownloadMissingLyrics": "Deskargatu falta diren letrak",
|
||||
"TaskDownloadMissingLyricsDescription": "Deskargatu abestientzako letrak",
|
||||
"TaskExtractMediaSegments": "Multimedia segmentuen eskaneoa",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Jada existitzen ez diren bildumak eta erreprodukzio-zerrendak kentzen ditu.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Garbitu bildumak eta erreprodukzio-zerrendak",
|
||||
"TaskExtractMediaSegmentsDescription": "Media segmentuak atera edo lortzen ditu MediaSegment gaituta duten pluginetik.",
|
||||
"TaskMoveTrickplayImages": "Aldatu Trickplay irudien kokalekua",
|
||||
"TaskMoveTrickplayImagesDescription": "Lehendik dauden trickplay fitxategiak liburutegiaren ezarpenen arabera mugitzen dira.",
|
||||
|
||||
@@ -126,6 +126,8 @@
|
||||
"HearingImpaired": "مشکل شنوایی",
|
||||
"TaskRefreshTrickplayImages": "تولید تصاویر Trickplay",
|
||||
"TaskRefreshTrickplayImagesDescription": "تولید پیشنمایش های trickplay برای ویدیو های فعال شده در کتابخانه.",
|
||||
"TaskCleanCollectionsAndPlaylists": "پاکسازی مجموعه ها و لیست پخش",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "موارد را از مجموعه ها و لیست پخش هایی که دیگر وجود ندارند حذف میکند.",
|
||||
"TaskAudioNormalizationDescription": "بررسی فایل برای دادههای نرمال کردن صدا.",
|
||||
"TaskDownloadMissingLyrics": "دانلود متنهای ناموجود",
|
||||
"TaskDownloadMissingLyricsDescription": "دانلود متن شعرها",
|
||||
|
||||
@@ -39,8 +39,8 @@
|
||||
"Channels": "Kanavat",
|
||||
"CameraImageUploadedFrom": "Uusi kameran kuva on sirretty lähteestä {0}",
|
||||
"Books": "Kirjat",
|
||||
"AuthenticationSucceededWithUserName": "{0} todennus onnistunut",
|
||||
"Artists": "Artistit",
|
||||
"AuthenticationSucceededWithUserName": "{0} on todennettu",
|
||||
"Artists": "Esittäjät",
|
||||
"Application": "Sovellus",
|
||||
"AppDeviceValues": "Sovellus: {0}, Laite: {1}",
|
||||
"Albums": "Albumit",
|
||||
@@ -126,6 +126,8 @@
|
||||
"HearingImpaired": "Kuulorajoitteinen",
|
||||
"TaskRefreshTrickplayImages": "Luo Trickplay-kuvat",
|
||||
"TaskRefreshTrickplayImagesDescription": "Luo Trickplay-esikatselut käytössä olevien kirjastojen videoista.",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Poistaa kohteet kokoelmista ja soittolistoista joita ei ole enää olemassa.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Puhdista kokoelmat ja soittolistat",
|
||||
"TaskAudioNormalization": "Äänenvoimakkuuden normalisointi",
|
||||
"TaskAudioNormalizationDescription": "Etsii tiedostoista äänenvoimakkuuden normalisointitietoja.",
|
||||
"TaskDownloadMissingLyrics": "Lataa puuttuva lyriikka",
|
||||
|
||||
@@ -14,9 +14,5 @@
|
||||
"DeviceOnlineWithName": "{0} er sambundið",
|
||||
"Favorites": "Yndis",
|
||||
"Folders": "Mappur",
|
||||
"Forced": "Kravt",
|
||||
"FailedLoginAttemptWithUserName": "Miseydnað innritanarroynd frá {0}",
|
||||
"HeaderFavoriteEpisodes": "Yndispartar",
|
||||
"HeaderFavoriteSongs": "Yndissangir",
|
||||
"LabelIpAddressValue": "IP atsetur: {0}"
|
||||
"Forced": "Kravt"
|
||||
}
|
||||
|
||||
@@ -126,6 +126,8 @@
|
||||
"HearingImpaired": "Malentendants",
|
||||
"TaskRefreshTrickplayImages": "Générer des images Trickplay",
|
||||
"TaskRefreshTrickplayImagesDescription": "Crée des aperçus Trickplay pour les vidéos dans les médiathèques activées.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Nettoyer les collections et les listes de lecture",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Supprime les éléments des collections et des listes de lecture qui n'existent plus.",
|
||||
"TaskAudioNormalization": "Normalisation audio",
|
||||
"TaskAudioNormalizationDescription": "Analyse les fichiers à la recherche de données de normalisation audio.",
|
||||
"TaskExtractMediaSegments": "Analyse des segments de média",
|
||||
|
||||
@@ -126,6 +126,8 @@
|
||||
"HearingImpaired": "Malentendants",
|
||||
"TaskRefreshTrickplayImages": "Générer des images Trickplay",
|
||||
"TaskRefreshTrickplayImagesDescription": "Crée des aperçus Trickplay pour les vidéos dans les médiathèques activées.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Nettoyer les collections et les listes de lecture",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Supprime les éléments des collections et des listes de lecture qui n'existent plus.",
|
||||
"TaskAudioNormalization": "Normalisation audio",
|
||||
"TaskAudioNormalizationDescription": "Analyse les fichiers à la recherche de données de normalisation audio.",
|
||||
"TaskDownloadMissingLyricsDescription": "Téléchargement des paroles des chansons",
|
||||
|
||||
@@ -29,10 +29,12 @@
|
||||
"TaskRefreshChannelsDescription": "Athnuachan eolas faoi chainéil idirlín.",
|
||||
"TaskOptimizeDatabase": "Bunachar sonraí a bharrfheabhsú",
|
||||
"TaskKeyframeExtractorDescription": "Baintear eochairfhrámaí as comhaid físe chun seinmliostaí HLS níos cruinne a chruthú. Féadfaidh an tasc seo a bheith ar siúl ar feadh i bhfad.",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Baintear míreanna as bailiúcháin agus seinmliostaí nach ann dóibh a thuilleadh.",
|
||||
"TaskDownloadMissingLyricsDescription": "Íosluchtaigh liricí do na hamhráin",
|
||||
"TaskUpdatePluginsDescription": "Íoslódálann agus suiteálann nuashonruithe do bhreiseáin atá cumraithe le nuashonrú go huathoibríoch.",
|
||||
"TaskDownloadMissingSubtitlesDescription": "Déanann sé cuardach ar an idirlíon le haghaidh fotheidil atá ar iarraidh bunaithe ar chumraíocht meiteashonraí.",
|
||||
"TaskExtractMediaSegmentsDescription": "Sliocht nó faigheann codanna meán ó bhreiseáin chumasaithe MediaSegment.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Glan suas bailiúcháin agus seinmliostaí",
|
||||
"TaskOptimizeDatabaseDescription": "Comhdhlúthaíonn bunachar sonraí agus gearrtar spás saor in aisce. Má ritheann tú an tasc seo tar éis scanadh a dhéanamh ar an leabharlann nó athruithe eile a dhéanamh a thugann le tuiscint gur cheart go bhfeabhsófaí an fheidhmíocht.",
|
||||
"TaskMoveTrickplayImagesDescription": "Bogtar comhaid trickplay atá ann cheana de réir socruithe na leabharlainne.",
|
||||
"AppDeviceValues": "Aip: {0}, Gléas: {1}",
|
||||
|
||||
@@ -128,6 +128,8 @@
|
||||
"TaskRefreshTrickplayImagesDescription": "Crea miniaturas de previsualización para os vídeos nas bibliotecas habilitadas.",
|
||||
"TaskDownloadMissingLyrics": "Descargar letras que faltan",
|
||||
"TaskDownloadMissingLyricsDescription": "Descarga as letras das cancións",
|
||||
"TaskCleanCollectionsAndPlaylists": "Limpar coleccións e listas de reprodución",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Quita ítems que xa non existen das coleccións e listas de reprodución.",
|
||||
"TaskExtractMediaSegmentsDescription": "Procura segmentos de medios cos plugins habilitados.",
|
||||
"TaskExtractMediaSegments": "Escaneo de segmentos de medios",
|
||||
"TaskMoveTrickplayImages": "Migrar as miniaturas de previsualización a outra ubicación",
|
||||
|
||||
@@ -127,7 +127,9 @@
|
||||
"TaskRefreshTrickplayImages": "יצירת תמונות Trickplay",
|
||||
"TaskRefreshTrickplayImagesDescription": "יוצר תמונות Trickplay לסרטונים בספריות הפעילות.",
|
||||
"TaskAudioNormalization": "נרמול שמע",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "מנקה פריטים לא קיימים מאוספים ורשימות השמעה.",
|
||||
"TaskAudioNormalizationDescription": "מחפש קבצי נורמליזציה של שמע.",
|
||||
"TaskCleanCollectionsAndPlaylists": "מנקה אוספים ורשימות השמעה",
|
||||
"TaskDownloadMissingLyrics": "הורדת מילים חסרות",
|
||||
"TaskDownloadMissingLyricsDescription": "הורדת מילים לשירים",
|
||||
"TaskMoveTrickplayImages": "העברת מיקום של תמונות Trickplay",
|
||||
|
||||
@@ -127,12 +127,14 @@
|
||||
"TaskRefreshTrickplayImages": "ट्रिकप्लै चित्रों को सृजन करे",
|
||||
"TaskRefreshTrickplayImagesDescription": "नियत संग्रहों में चलचित्रों का ट्रीकप्लै दर्शनों को सृजन करे.",
|
||||
"TaskAudioNormalization": "श्रव्य सामान्यीकरण",
|
||||
"TaskAudioNormalizationDescription": "श्रव्य सामान्यीकरण के लिए फाइलें अन्वेषण करें।",
|
||||
"TaskAudioNormalizationDescription": "श्रव्य सामान्यीकरण के लिए फाइलें अन्वेषण करें",
|
||||
"TaskDownloadMissingLyrics": "लापता गानों के बोल डाउनलोड करेँ",
|
||||
"TaskDownloadMissingLyricsDescription": "गानों के बोल डाउनलोड करता है",
|
||||
"TaskExtractMediaSegments": "मीडिया सेगमेंट स्कैन",
|
||||
"TaskExtractMediaSegmentsDescription": "मीडियासेगमेंट सक्षम प्लगइन्स से मीडिया सेगमेंट निकालता है या प्राप्त करता है।",
|
||||
"TaskMoveTrickplayImages": "ट्रिकप्ले छवि स्थान माइग्रेट करें",
|
||||
"TaskMoveTrickplayImagesDescription": "लाइब्रेरी सेटिंग्स के अनुसार मौजूदा ट्रिकप्ले फ़ाइलों को स्थानांतरित करता है।",
|
||||
"CleanupUserDataTask": "यूज़र डेटा सफाई कार्य"
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "संग्रहों और प्लेलिस्टों से उन आइटमों को हटाता है जो अब मौजूद नहीं हैं।",
|
||||
"TaskCleanCollectionsAndPlaylists": "संग्रह और प्लेलिस्ट साफ़ करें",
|
||||
"CleanupUserDataTask": "यूज़र डेटा की सफाई करता है।"
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
"HeaderFavoriteShows": "Omiljene serije",
|
||||
"HeaderFavoriteSongs": "Omiljene pjesme",
|
||||
"HeaderLiveTV": "TV uživo",
|
||||
"HeaderNextUp": "Sljedeće na redu",
|
||||
"HeaderNextUp": "Slijedi",
|
||||
"HeaderRecordingGroups": "Grupa snimka",
|
||||
"HomeVideos": "Kućni video",
|
||||
"Inherit": "Naslijedi",
|
||||
@@ -73,10 +73,10 @@
|
||||
"Shows": "Emisije",
|
||||
"Songs": "Pjesme",
|
||||
"StartupEmbyServerIsLoading": "Jellyfin server se učitava. Pokušajte ponovo uskoro.",
|
||||
"SubtitleDownloadFailureFromForItem": "Titlovi nisu uspješno preuzeti od {0} za {1}",
|
||||
"SubtitleDownloadFailureFromForItem": "Prijevod nije uspješno preuzet od {0} za {1}",
|
||||
"Sync": "Sinkronizacija",
|
||||
"System": "Sustav",
|
||||
"TvShows": "TV emisije",
|
||||
"TvShows": "Serije",
|
||||
"User": "Korisnik",
|
||||
"UserCreatedWithName": "Korisnik {0} je kreiran",
|
||||
"UserDeletedWithName": "Korisnik {0} je obrisan",
|
||||
@@ -88,26 +88,26 @@
|
||||
"UserPolicyUpdatedWithName": "Pravila za korisnika ažurirana su za {0}",
|
||||
"UserStartedPlayingItemWithValues": "{0} je pokrenuo reprodukciju {1} na {2}",
|
||||
"UserStoppedPlayingItemWithValues": "{0} je završio reprodukciju {1} na {2}",
|
||||
"ValueHasBeenAddedToLibrary": "{0} je dodano u biblioteku medija",
|
||||
"ValueSpecialEpisodeName": "Posebno – {0}",
|
||||
"ValueHasBeenAddedToLibrary": "{0} je dodano u medijsku biblioteku",
|
||||
"ValueSpecialEpisodeName": "Posebno - {0}",
|
||||
"VersionNumber": "Verzija {0}",
|
||||
"TaskRefreshLibraryDescription": "Skenira biblioteku medija radi novih datoteka i osvježava metapodatke.",
|
||||
"TaskRefreshLibrary": "Skeniraj biblioteku medija",
|
||||
"TaskRefreshLibraryDescription": "Skenira medijsku biblioteku radi novih datoteka i osvježava metapodatke.",
|
||||
"TaskRefreshLibrary": "Skeniraj medijsku biblioteku",
|
||||
"TaskRefreshChapterImagesDescription": "Kreira sličice za videozapise koji imaju poglavlja.",
|
||||
"TaskRefreshChapterImages": "Izdvoji slike poglavlja",
|
||||
"TaskCleanCacheDescription": "Briše nepotrebne datoteke iz predmemorije.",
|
||||
"TaskCleanCache": "Očisti mapu predmemorije",
|
||||
"TasksApplicationCategory": "Aplikacija",
|
||||
"TasksMaintenanceCategory": "Održavanje",
|
||||
"TaskDownloadMissingSubtitlesDescription": "Pretraži internet za nedsotajućim titlovima ne osnovi konfiguracije metapodataka.",
|
||||
"TaskDownloadMissingSubtitles": "Preuzmi nedostajuće titlove",
|
||||
"TaskDownloadMissingSubtitlesDescription": "Pretraži Internet za prijevodima koji nedostaju prema konfiguraciji metapodataka.",
|
||||
"TaskDownloadMissingSubtitles": "Preuzmi prijevod koji nedostaje",
|
||||
"TaskRefreshChannelsDescription": "Osvježava informacije Internet kanala.",
|
||||
"TaskRefreshChannels": "Osvježi kanale",
|
||||
"TaskCleanTranscodeDescription": "Briše transkodirane datoteke starije od jednog dana.",
|
||||
"TaskCleanTranscode": "Očisti mapu transkodiranja",
|
||||
"TaskUpdatePluginsDescription": "Preuzima i instalira ažuriranja za dodatke koji su konfigurirani da se ažuriraju automatski.",
|
||||
"TaskUpdatePlugins": "Ažuriraj dodatke",
|
||||
"TaskRefreshPeopleDescription": "Ažurira metapodatke za glumce i redatelje u biblioteci medija.",
|
||||
"TaskRefreshPeopleDescription": "Ažurira metapodatke za glumce i redatelje u medijskoj biblioteci.",
|
||||
"TaskRefreshPeople": "Osvježi osobe",
|
||||
"TaskCleanLogsDescription": "Briše zapise dnevnika koji su stariji od {0} dana.",
|
||||
"TaskCleanLogs": "Očisti mapu dnevnika zapisa",
|
||||
@@ -119,7 +119,7 @@
|
||||
"Forced": "Forsirani",
|
||||
"Default": "Zadano",
|
||||
"TaskOptimizeDatabase": "Optimiziraj bazu podataka",
|
||||
"External": "Eksterni",
|
||||
"External": "Vanjski",
|
||||
"TaskKeyframeExtractorDescription": "Izvlačenje ključnih okvira iz videozapisa za stvaranje objektivnije HLS liste za reprodukciju. Pokretanje ovog zadatka može potrajati.",
|
||||
"TaskKeyframeExtractor": "Izvoditelj ključnog okvira",
|
||||
"TaskOptimizeDatabaseDescription": "Sažima bazu podataka i uklanja prazan prostor. Pokretanje ovog zadatka, može poboljšati performanse nakon provođenja indeksiranja biblioteke ili provođenja drugih promjena koje utječu na bazu podataka.",
|
||||
@@ -128,12 +128,14 @@
|
||||
"TaskRefreshTrickplayImagesDescription": "Stvara preglede brzog pregledavanja za videa u aktiviranim bibliotekama.",
|
||||
"TaskAudioNormalization": "Normalizacija zvuka",
|
||||
"TaskAudioNormalizationDescription": "Skenira datoteke u potrazi za podacima o normalizaciji zvuka.",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Uklanja stavke iz zbirki i popisa za reprodukciju koje više ne postoje.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Očisti zbirke i popise za reprodukciju",
|
||||
"TaskExtractMediaSegments": "Skeniranje dijelova medija",
|
||||
"TaskDownloadMissingLyrics": "Preuzmi tekstove koji nedostaju",
|
||||
"TaskDownloadMissingLyricsDescription": "Preuzmi tekstove pjesama",
|
||||
"TaskExtractMediaSegmentsDescription": "Izvlači ili pribavlja dijelove medija iz omogućenih media pluginova.",
|
||||
"TaskMoveTrickplayImages": "Premjesti mjesto slika brzog pregledavanja",
|
||||
"TaskMoveTrickplayImagesDescription": "Premješta postojeće datoteke brzog pregledavanja u postavke biblioteke.",
|
||||
"TaskMoveTrickplayImagesDescription": "Premješta postojeće datoteke brzog pregledavanja prema postavkama biblioteke.",
|
||||
"CleanupUserDataTask": "Zadatak čišćenja korisničkih podataka",
|
||||
"CleanupUserDataTaskDescription": "Briše sve korisničke podatke (stanje gledanja, status favorita itd.) s medija koji više nisu prisutni najmanje 90 dana."
|
||||
}
|
||||
|
||||
@@ -58,8 +58,5 @@
|
||||
"ValueSpecialEpisodeName": "Spesyal - {0}",
|
||||
"VersionNumber": "Vesyon {0}",
|
||||
"TasksApplicationCategory": "Aplikasyon",
|
||||
"TasksMaintenanceCategory": "Antretyen",
|
||||
"AppDeviceValues": "Aplikasyon: {0}, Aparèy: {1}",
|
||||
"AuthenticationSucceededWithUserName": "{0} otantifye avèk siksè",
|
||||
"CameraImageUploadedFrom": "Une nouvelle image de la caméra a été téléchargée depuis {0}"
|
||||
"TasksMaintenanceCategory": "Antretyen"
|
||||
}
|
||||
|
||||
@@ -127,7 +127,9 @@
|
||||
"TaskRefreshTrickplayImages": "Trickplay képek előállítása",
|
||||
"TaskRefreshTrickplayImagesDescription": "Trickplay előnézetet készít az engedélyezett könyvtárakban lévő videókhoz.",
|
||||
"TaskAudioNormalization": "Hangerő-normalizálás",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Nem létező elemek törlése a gyűjteményekből és lejátszási listákról.",
|
||||
"TaskAudioNormalizationDescription": "Hangerő-normalizálási adatok keresése.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Gyűjtemények és lejátszási listák optimalizálása",
|
||||
"TaskExtractMediaSegments": "Médiaszegmens felismerése",
|
||||
"TaskDownloadMissingLyrics": "Hiányzó szöveg letöltése",
|
||||
"TaskDownloadMissingLyricsDescription": "Zenék szövegének letöltése",
|
||||
|
||||
@@ -128,6 +128,8 @@
|
||||
"TaskRefreshTrickplayImagesDescription": "Buat pratinjau trickplay untuk video di perpustakaan yang diaktifkan.",
|
||||
"TaskAudioNormalizationDescription": "Pindai file untuk data normalisasi audio.",
|
||||
"TaskAudioNormalization": "Normalisasi Audio",
|
||||
"TaskCleanCollectionsAndPlaylists": "Bersihkan koleksi dan daftar putar",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Menghapus item dari koleksi dan daftar putar yang sudah tidak ada.",
|
||||
"TaskDownloadMissingLyricsDescription": "Unduh lirik untuk lagu",
|
||||
"TaskExtractMediaSegmentsDescription": "Mengekstrak atau memperoleh segmen media dari plugin yang mendukung MediaSegment.",
|
||||
"TaskMoveTrickplayImagesDescription": "Memindahkan file trickplay yang sudah ada sesuai dengan pengaturan pustaka.",
|
||||
|
||||
@@ -128,6 +128,8 @@
|
||||
"TaskRefreshTrickplayImages": "Búa til hraðspilunarmyndir",
|
||||
"TaskAudioNormalization": "Hljóðstöðlun",
|
||||
"TaskAudioNormalizationDescription": "Leitar að hljóðstöðlunargögnum í skrám.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Hreinsa söfn og spilunarlista",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Fjarlægir hluti úr söfnum og spilalistum sem eru ekki lengur til.",
|
||||
"TaskDownloadMissingLyricsDescription": "Sækja söngtexta fyrir lög",
|
||||
"TaskDownloadMissingLyrics": "Sækja söngtexta sem vantar",
|
||||
"TaskExtractMediaSegments": "Skönnun efnishluta",
|
||||
|
||||
@@ -126,6 +126,8 @@
|
||||
"HearingImpaired": "Non udenti",
|
||||
"TaskRefreshTrickplayImages": "Genera immagini Trickplay",
|
||||
"TaskRefreshTrickplayImagesDescription": "Crea anteprime trickplay per i video nelle librerie abilitate.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Ripulisci le collezioni e le scalette",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Rimuove gli elementi dalle collezioni e dalle scalette che non esistono più.",
|
||||
"TaskAudioNormalization": "Normalizzazione dell'audio",
|
||||
"TaskAudioNormalizationDescription": "Scansiona i file alla ricerca dei dati per la normalizzazione dell'audio.",
|
||||
"TaskDownloadMissingLyricsDescription": "Scarica testi per le canzoni",
|
||||
|
||||
@@ -126,8 +126,10 @@
|
||||
"HearingImpaired": "聴覚障害の方",
|
||||
"TaskRefreshTrickplayImages": "トリックプレー画像を生成",
|
||||
"TaskRefreshTrickplayImagesDescription": "有効なライブラリ内のビデオをもとにトリックプレーのプレビューを生成します。",
|
||||
"TaskCleanCollectionsAndPlaylists": "コレクションとプレイリストをクリーンアップ",
|
||||
"TaskAudioNormalization": "音声の正規化",
|
||||
"TaskAudioNormalizationDescription": "音声の正規化データのためにファイルをスキャンします。",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "在しなくなったコレクションやプレイリストからアイテムを削除します。",
|
||||
"TaskDownloadMissingLyricsDescription": "歌詞をダウンロード",
|
||||
"TaskExtractMediaSegments": "メディアセグメントを読み取る",
|
||||
"TaskMoveTrickplayImages": "Trickplayの画像を移動",
|
||||
|
||||
@@ -9,46 +9,46 @@
|
||||
"Artists": "არტისტი",
|
||||
"AuthenticationSucceededWithUserName": "{0} -ის ავთენტიკაცია წარმატებულია",
|
||||
"Books": "წიგნები",
|
||||
"Forced": "იძულებითი",
|
||||
"Forced": "ძალით",
|
||||
"Inherit": "მემკვიდრეობით",
|
||||
"Latest": "უახლესი",
|
||||
"Movies": "ფილმები",
|
||||
"Music": "მუსიკა",
|
||||
"Photos": "ფოტოები",
|
||||
"Playlists": "დასაკრავი სიები",
|
||||
"Plugin": "მოდული",
|
||||
"Plugin": "დამატება",
|
||||
"Shows": "სერიალები",
|
||||
"Songs": "სიმღერები",
|
||||
"Sync": "სინქრონიზაცია",
|
||||
"System": "სისტემა",
|
||||
"Undefined": "განუსაზღვრელი",
|
||||
"Undefined": "აღუწერელი",
|
||||
"User": "მომხმარებელი",
|
||||
"TasksMaintenanceCategory": "რემონტი",
|
||||
"TasksLibraryCategory": "ბიბლიოთეკა",
|
||||
"ChapterNameValue": "თავი {0}",
|
||||
"HeaderContinueWatching": "ყურების გაგრძელება",
|
||||
"HeaderFavoriteArtists": "რჩეული შემსრულებლები",
|
||||
"DeviceOfflineWithName": "{0} გამოეთიშა",
|
||||
"DeviceOfflineWithName": "{0} გაითიშა",
|
||||
"External": "გარე",
|
||||
"HeaderFavoriteEpisodes": "რჩეული ეპიზოდები",
|
||||
"HeaderFavoriteSongs": "რჩეული სიმღერები",
|
||||
"HeaderRecordingGroups": "ჩამწერი ჯგუფები",
|
||||
"HearingImpaired": "სმენადაქვეითებული",
|
||||
"LabelRunningTimeValue": "ხანგრძლივობა: {0}",
|
||||
"LabelRunningTimeValue": "გაშვებულობის დრო: {0}",
|
||||
"MessageApplicationUpdatedTo": "Jellyfin-ის სერვერი განახლდა {0}-ზე",
|
||||
"MessageNamedServerConfigurationUpdatedWithValue": "სერვერის კონფიგურაციის სექცია {0} განახლდა",
|
||||
"MixedContent": "შერეული შემცველობა",
|
||||
"MusicVideos": "მუსიკალური ვიდეოები",
|
||||
"MusicVideos": "მუსიკის ვიდეოები",
|
||||
"NotificationOptionInstallationFailed": "დაყენების შეცდომა",
|
||||
"NotificationOptionApplicationUpdateInstalled": "აპლიკაციის განახლება დაყენებულია",
|
||||
"NotificationOptionAudioPlayback": "აუდიოს დაკვრა დაწყებულია",
|
||||
"NotificationOptionCameraImageUploaded": "კამერის გამოსახულება ატვირთულია",
|
||||
"NotificationOptionVideoPlaybackStopped": "ვიდეოს დაკვრა გაჩერებულია",
|
||||
"PluginUninstalledWithName": "{0} წაიშალა",
|
||||
"ScheduledTaskStartedWithName": "{0} დაიწყო",
|
||||
"ScheduledTaskStartedWithName": "{0} გაეშვა",
|
||||
"VersionNumber": "ვერსია {0}",
|
||||
"TasksChannelsCategory": "ინტერნეტ-არხები",
|
||||
"ValueSpecialEpisodeName": "დამატებითი - {0}",
|
||||
"ValueSpecialEpisodeName": "სპეციალური - {0}",
|
||||
"TaskRefreshChannelsDescription": "ინტერნეტ-არხის ინფორმაციის განახლება.",
|
||||
"Channels": "არხები",
|
||||
"Collections": "კოლექციები",
|
||||
@@ -56,31 +56,31 @@
|
||||
"Favorites": "რჩეულები",
|
||||
"Folders": "საქაღალდეები",
|
||||
"HeaderFavoriteShows": "რჩეული სერიალები",
|
||||
"HeaderLiveTV": "ლაივ ტელევიზია",
|
||||
"HeaderNextUp": "შემდეგი",
|
||||
"HeaderLiveTV": "ცოცხალი TV",
|
||||
"HeaderNextUp": "შემდეგი ზემოთ",
|
||||
"HomeVideos": "სახლის ვიდეოები",
|
||||
"NameSeasonNumber": "სეზონი {0}",
|
||||
"NameSeasonUnknown": "სეზონი უცნობია",
|
||||
"NotificationOptionPluginError": "მოდულის შეცდომა",
|
||||
"NotificationOptionPluginInstalled": "მოდული დაყენებულია",
|
||||
"NotificationOptionPluginUninstalled": "მოდული წაიშალა",
|
||||
"NotificationOptionPluginError": "დამატების შეცდომა",
|
||||
"NotificationOptionPluginInstalled": "დამატება დაყენებულია",
|
||||
"NotificationOptionPluginUninstalled": "დამატება წაიშალა",
|
||||
"ProviderValue": "მომწოდებელი: {0}",
|
||||
"ScheduledTaskFailedWithName": "{0} ვერ შესრულდა",
|
||||
"TvShows": "სატელევიზიო სერიალები",
|
||||
"ScheduledTaskFailedWithName": "{0} ავარიულია",
|
||||
"TvShows": "TV სერიალები",
|
||||
"TaskRefreshPeople": "ხალხის განახლება",
|
||||
"TaskUpdatePlugins": "მოდულების განახლება",
|
||||
"TaskUpdatePlugins": "დამატებების განახლება",
|
||||
"TaskRefreshChannels": "არხების განახლება",
|
||||
"TaskOptimizeDatabase": "მონაცემთა ბაზის ოპტიმიზაცია",
|
||||
"TaskOptimizeDatabase": "ბაზების ოპტიმიზაცია",
|
||||
"TaskKeyframeExtractor": "საკვანძო კადრის გამომღები",
|
||||
"DeviceOnlineWithName": "{0} დაკავშირდა",
|
||||
"DeviceOnlineWithName": "{0} შეერთებულია",
|
||||
"LabelIpAddressValue": "IP მისამართი: {0}",
|
||||
"NameInstallFailed": "{0}-ის დაყენების შეცდომა",
|
||||
"NotificationOptionApplicationUpdateAvailable": "ხელმისაწვდომია აპლიკაციის განახლება",
|
||||
"NotificationOptionAudioPlaybackStopped": "აუდიოს დაკვრა გაჩერებულია",
|
||||
"NotificationOptionNewLibraryContent": "ახალი შემცველობა დამატებულია",
|
||||
"NotificationOptionPluginUpdateInstalled": "მოდულიs განახლება დაყენებულია",
|
||||
"NotificationOptionServerRestartRequired": "საჭიროა სერვერის გადატვირთვა",
|
||||
"NotificationOptionTaskFailed": "გეგმიური დავალების შეცდომა",
|
||||
"NotificationOptionPluginUpdateInstalled": "დამატების განახლება დაყენებულია",
|
||||
"NotificationOptionServerRestartRequired": "სერვერის გადატვირთვა აუცილებელია",
|
||||
"NotificationOptionTaskFailed": "დაგეგმილი ამოცანის შეცდომა",
|
||||
"NotificationOptionUserLockedOut": "მომხმარებელი დაიბლოკა",
|
||||
"NotificationOptionVideoPlayback": "ვიდეოს დაკვრა დაწყებულია",
|
||||
"PluginInstalledWithName": "{0} დაყენებულია",
|
||||
@@ -91,49 +91,39 @@
|
||||
"TaskRefreshLibrary": "მედიის ბიბლიოთეკის სკანირება",
|
||||
"TaskCleanLogs": "ჟურნალის საქაღალდის გასუფთავება",
|
||||
"TaskCleanTranscode": "ტრანსკოდირების საქაღალდის გასუფთავება",
|
||||
"TaskDownloadMissingSubtitles": "მიუწვდომელი სუბტიტრების გადმოწერა",
|
||||
"UserDownloadingItemWithValues": "{0} -ი {1}-ს იწერს",
|
||||
"FailedLoginAttemptWithUserName": "შესვლის წარუმატებელი მცდელობა {0}-დან",
|
||||
"TaskDownloadMissingSubtitles": "ნაკლული სუბტიტრების გადმოწერა",
|
||||
"UserDownloadingItemWithValues": "{0} -ი {0}-ს იწერს",
|
||||
"FailedLoginAttemptWithUserName": "{0}-დან შემოსვლის შეცდომა",
|
||||
"MessageApplicationUpdated": "Jellyfin-ის სერვერი განახლდა",
|
||||
"MessageServerConfigurationUpdated": "სერვერის კონფიგურაცია განახლდა",
|
||||
"ServerNameNeedsToBeRestarted": "საჭიროა {0}-ის გადატვირთვა",
|
||||
"UserCreatedWithName": "მომხმარებელი {0} შეიქმნა",
|
||||
"UserDeletedWithName": "მომხმარებელი {0} წაშლილია",
|
||||
"UserOnlineFromDevice": "{0}-ი დაკავშირდა {1}-დან",
|
||||
"UserOfflineFromDevice": "{0}-ი {1}-დან გაეთიშა",
|
||||
"UserOnlineFromDevice": "{0}-ი ხაზზეა {1}-დან",
|
||||
"UserOfflineFromDevice": "{0}-ი {1}-დან გაითიშა",
|
||||
"ItemAddedWithName": "{0} ჩამატებულია ბიბლიოთეკაში",
|
||||
"ItemRemovedWithName": "{0} წაშლილია ბიბლიოთეკიდან",
|
||||
"UserLockedOutWithName": "მომხმარებელი {0} დაბლოკილია",
|
||||
"UserStartedPlayingItemWithValues": "{0} უყურებს {1}-ს {2}-ზე",
|
||||
"UserPasswordChangedWithName": "მომხმარებელი {0}-სთვის პაროლი შეიცვალა",
|
||||
"UserStartedPlayingItemWithValues": "{0} თამაშობს {1}-ს {2}-ზე",
|
||||
"UserPasswordChangedWithName": "მომხმარებლისთვის {0} პაროლი შეცვლილია",
|
||||
"UserPolicyUpdatedWithName": "{0}-ის მომხმარებლის პოლიტიკა განახლდა",
|
||||
"UserStoppedPlayingItemWithValues": "{0}-მა დაასრულა {1}-ის ყურება {2}-ზე",
|
||||
"UserStoppedPlayingItemWithValues": "{0}-მა დაამთავრა {1}-ის დაკვრა {2}-ზე",
|
||||
"TaskRefreshChapterImagesDescription": "თავების მქონე ვიდეოებისთვის მინიატურების შექმნა.",
|
||||
"TaskKeyframeExtractorDescription": "უფრო ზუსტი HLS დასაკრავი სიებისითვის ვიდეოდან საკვანძო გადრების ამოღება. შეიძლება საკმაო დრო დასჭირდეს.",
|
||||
"NewVersionIsAvailable": "გადმოსაწერად ხელმისაწვდომია Jellyfin -ის ახალი ვერსია.",
|
||||
"CameraImageUploadedFrom": "ახალი კამერის გამოსახულება ატვირთულია {0}-დან",
|
||||
"StartupEmbyServerIsLoading": "Jellyfin სერვერი იტვირთება. მოგვიანებით სცადეთ.",
|
||||
"SubtitleDownloadFailureFromForItem": "{0}-დან {1}-სთვის სუბტიტრების გადმოწერა ვერ შესრულდა",
|
||||
"SubtitleDownloadFailureFromForItem": "{0}-დან {1}-სთვის სუბტიტრების გადმოწერის შეცდომა",
|
||||
"ValueHasBeenAddedToLibrary": "{0} დაემატა თქვენს მედიის ბიბლიოთეკას",
|
||||
"TaskCleanActivityLogDescription": "შლის მითითებულ ასაკზე ძველ ჟურნალის ჩანაწერებს.",
|
||||
"TaskCleanCacheDescription": "შლის სისტემისთვის არასაჭირო ქეშის ფაილებს.",
|
||||
"TaskRefreshLibraryDescription": "ეძებს ახალ ფაილებს თქვენს მედიის ბიბლიოთეკაში და ანახლებს მეტამონაცემებს.",
|
||||
"TaskCleanActivityLogDescription": "მითითებულ ასაკზე ძველი ჟურნალის ჩანაწერების წაშლა.",
|
||||
"TaskCleanCacheDescription": "სისტემისთვის არასაჭირო ქეშის ფაილების წაშლა.",
|
||||
"TaskRefreshLibraryDescription": "თქვენი მედია ბიბლიოთეკაში ახალი ფაილების ძებნა და მეტამონაცემების განახლება.",
|
||||
"TaskCleanLogsDescription": "{0} დღეზე ძველი ჟურნალის ფაილების წაშლა.",
|
||||
"TaskRefreshPeopleDescription": "თქვენს მედიის ბიბლიოთეკაში მსახიობების და რეჟისორების მეტამონაცემების განახლება.",
|
||||
"TaskUpdatePluginsDescription": "ავტომატურად განახლებადად მონიშნული მოდულების განახლებების გადმოწერა და დაყენება.",
|
||||
"TaskUpdatePluginsDescription": "ავტომატურად განახლებადად მონიშნული დამატებების განახლებების გადმოწერა და დაყენება.",
|
||||
"TaskCleanTranscodeDescription": "ერთ დღეზე უფრო ძველი ტრანსკოდირების ფაილების წაშლა.",
|
||||
"TaskDownloadMissingSubtitlesDescription": "ეძებს ბიბლიოთეკაში მიუწვდომელ სუბტიტრებს ინტერნეტში მეტამონაცემებზე დაყრდნობით.",
|
||||
"TaskOptimizeDatabaseDescription": "კუმშავს მონაცემთა ბაზას ადგილის გათავისუფლებლად. ამ ამოცანის ბიბლიოთეკის სკანირების ან ნებისმიერი ცვლილების, რომელიც ბაზაში რამეს აკეთებს, გაშვებას შეუძლია ბაზის წარმადობა გაზარდოს.",
|
||||
"TaskRefreshTrickplayImagesDescription": "ქმნის trickplay წინასწარ ხედებს ვიდეოებისთვის დაშვებულ ბიბლიოთეკებში.",
|
||||
"TaskRefreshTrickplayImages": "Trickplay სურათების გენერირება",
|
||||
"TaskAudioNormalization": "აუდიოს ნორმალიზება",
|
||||
"TaskAudioNormalizationDescription": "აანალიზებს ფაილებს აუდიოს ნორმალიზაციისთვის.",
|
||||
"TaskDownloadMissingLyrics": "მიუწვდომელი ლირიკების ჩამოტვირთვა",
|
||||
"TaskDownloadMissingLyricsDescription": "ჩამოტვირთავს ამჟამად ბიბლიოთეკაში არარსებულ ლირიკებს სიმღერებისთვის",
|
||||
"TaskExtractMediaSegments": "მედია სეგმენტების სკანირება",
|
||||
"TaskExtractMediaSegmentsDescription": "მედია სეგმენტების სკანირება მხარდაჭერილი მოდულებისთვის.",
|
||||
"TaskMoveTrickplayImages": "Trickplay სურათების მიგრაცია",
|
||||
"TaskMoveTrickplayImagesDescription": "გადააქვს trickplay ფაილები ბიბლიოთეკის პარამეტრებზე დაყრდნობით.",
|
||||
"CleanupUserDataTask": "მომხმარებლების მონაცემების გასუფთავება",
|
||||
"CleanupUserDataTaskDescription": "ასუფთავებს მომხმარებლების მონაცემებს (ყურების სტატუსი, ფავორიტები ანდ ა.შ) მედია ელემენტებისთვის რომლების 90 დღეზე მეტია აღარ არსებობენ."
|
||||
"TaskDownloadMissingSubtitlesDescription": "მეტამონაცემებზე დაყრდნობით ინტერნეტში ნაკლული სუბტიტრების ძებნა.",
|
||||
"TaskOptimizeDatabaseDescription": "ბაზს შეკუშვა და ადგილის გათავისუფლება. ამ ამოცანის ბიბლიოთეკის სკანირების ან ნებისმიერი ცვლილების, რომელიც ბაზაში რამეს აკეთებს, გაშვებას შეუძლია ბაზის წარმადობა გაზარდოს.",
|
||||
"TaskRefreshTrickplayImagesDescription": "ქმნის trickplay წინასწარ ხედებს ვიდეოებისთვის ჩართულ ბიბლიოთეკებში.",
|
||||
"TaskRefreshTrickplayImages": "Trickplay სურათების გენერირება"
|
||||
}
|
||||
|
||||
@@ -127,5 +127,7 @@
|
||||
"TaskUpdatePluginsDescription": "ទាញយក និងដំឡើងបច្ចុប្បន្នភាពសម្រាប់Plugins ដែលត្រូវបាន Config ដើម្បីធ្វើបច្ចុប្បន្នភាពដោយស្វ័យប្រវត្តិ.",
|
||||
"TaskCleanTranscodeDescription": "លុបឯកសារ Transcode ដែលលើសពីមួយថ្ងៃ.",
|
||||
"TaskDownloadMissingSubtitlesDescription": "ស្វែងរកតាមអ៊ីនធឺណិត សម្រាប់សាប់ថាយថល ដែលបាត់ដោយផ្អែកលើ metadata.",
|
||||
"TaskOptimizeDatabase": "ធ្វើឱ្យ Database ប្រសើរឡើង"
|
||||
"TaskOptimizeDatabase": "ធ្វើឱ្យ Database ប្រសើរឡើង",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "លុបរបស់របរចេញពីបណ្តុំ និងបញ្ជីចាក់ដែលលែងមាន.",
|
||||
"TaskCleanCollectionsAndPlaylists": "សម្អាតបណ្តុំ និងបញ្ជីចាក់"
|
||||
}
|
||||
|
||||
@@ -129,5 +129,7 @@
|
||||
"TaskExtractMediaSegments": "ಮಾಧ್ಯಮ ವಿಭಾಗದ ಹುಡುಕು",
|
||||
"TaskDownloadMissingLyrics": "ಇಲ್ಲದ ಸಾಹಿತ್ಯವನ್ನು ಪಡೆಯಿರಿ",
|
||||
"TaskAudioNormalization": "ಧ್ವನಿ ಸಾಮಾನ್ಯೀಕರಣ",
|
||||
"TaskRefreshTrickplayImages": "ಟ್ರಿಕ್ಪ್ಲೇ ಚಿತ್ರಗಳನ್ನು ರಚಿಸಿ"
|
||||
"TaskRefreshTrickplayImages": "ಟ್ರಿಕ್ಪ್ಲೇ ಚಿತ್ರಗಳನ್ನು ರಚಿಸಿ",
|
||||
"TaskCleanCollectionsAndPlaylists": "ಸಂಗ್ರಹಗಳು ಮತ್ತು ಪ್ಲೇಪಟ್ಟಿಗಳನ್ನು ಸ್ವಚ್ಛಗೊಳಿಸಿ",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "ಇಲ್ಲದ ಸಂಗ್ರಹಗಳು ಮತ್ತು ಪ್ಲೇಪಟ್ಟಿಗಳಿಂದ ವಸ್ತುಗಳನ್ನು ತೆಗೆದುಹಾಕುತ್ತದೆ."
|
||||
}
|
||||
|
||||
@@ -124,10 +124,12 @@
|
||||
"TaskKeyframeExtractor": "키프레임 추출",
|
||||
"External": "외부",
|
||||
"HearingImpaired": "청각 장애",
|
||||
"TaskCleanCollectionsAndPlaylists": "컬렉션과 재생목록 정리",
|
||||
"TaskAudioNormalization": "오디오의 볼륨 수준을 일정하게 조정",
|
||||
"TaskAudioNormalizationDescription": "오디오의 볼륨 수준을 일정하게 조정하기 위해 파일을 스캔합니다.",
|
||||
"TaskRefreshTrickplayImages": "비디오 탐색용 미리보기 썸네일 생성",
|
||||
"TaskRefreshTrickplayImagesDescription": "활성화된 라이브러리에서 비디오의 트릭플레이 미리보기를 생성합니다.",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "더 이상 존재하지 않는 컬렉션 및 재생 목록에서 항목을 제거합니다.",
|
||||
"TaskExtractMediaSegments": "미디어 세그먼트 스캔",
|
||||
"TaskExtractMediaSegmentsDescription": "MediaSegment를 지원하는 플러그인에서 미디어 세그먼트를 추출하거나 가져옵니다.",
|
||||
"TaskMoveTrickplayImages": "트릭플레이 이미지 위치 마이그레이션",
|
||||
|
||||
@@ -128,7 +128,9 @@
|
||||
"TaskOptimizeDatabaseDescription": "Y hwra kesstrotha ha berrhe efander rydh. Martesen y hwra gwellhe gwryth mar kwre'ta an oberen ma wosa ty dhe arhwilas an lyverva, po neb chanj aral neb a brof chanjyansow selvanylyon.",
|
||||
"TaskAudioNormalizationDescription": "Y hwra arhwilas restrennow rag manylyon normalheans klewans.",
|
||||
"TaskRefreshLibraryDescription": "Y hwra arhwilas dha lyverva media rag restrennow nowydh ha disegha metamanylyon.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Glanhe kuntellow ha rolyow-gwari",
|
||||
"TaskKeyframeExtractor": "Estennell Framalhwedh",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Y hwra dilea taklow a-dhyworth kuntellow ha rolyow-gwari na vos na moy.",
|
||||
"TaskKeyframeExtractorDescription": "Y hwra kuntel framyowalhwedh a-dhyworth restrennow gwydhyowyow rag gul rolyow-gwari HLS moy poran. Martesen y hwra an oberen ma ow ponya rag termyn hir.",
|
||||
"TaskExtractMediaSegments": "Arhwilas Rann Media",
|
||||
"TaskExtractMediaSegmentsDescription": "Kavos rannow media a-dhyworth ystynansow gallosegys MediaSegment.",
|
||||
|
||||
@@ -104,6 +104,8 @@
|
||||
"TaskDownloadMissingSubtitles": "Fehlend Ënnertitelen eroflueden",
|
||||
"TaskOptimizeDatabase": "Datebank optiméieren",
|
||||
"TaskKeyframeExtractor": "Schlësselbild Extrakter",
|
||||
"TaskCleanCollectionsAndPlaylists": "Sammlungen a Playlisten botzen",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Ewechhuele vun Elementer aus Sammlungen a Playlisten, déi net méi existéieren.",
|
||||
"TaskExtractMediaSegments": "Mediesegment-Scan",
|
||||
"NewVersionIsAvailable": "Nei Versioun fir Jellyfin Server ass verfügbar.",
|
||||
"CameraImageUploadedFrom": "En neit Kamera Bild gouf vu {0} eropgelueden",
|
||||
|
||||
@@ -126,6 +126,8 @@
|
||||
"HearingImpaired": "Su klausos sutrikimais",
|
||||
"TaskRefreshTrickplayImages": "Generuoti Trickplay atvaizdus",
|
||||
"TaskRefreshTrickplayImagesDescription": "Sukuria trickplay peržiūras vaizdo įrašams įgalintose bibliotekose.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Išvalo duomenis rinkiniuose ir grojaraščiuose",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Pašalina neegzistuojančius elementus iš rinkinių ir grojaraščių.",
|
||||
"TaskAudioNormalization": "Garso normalizavimas",
|
||||
"TaskAudioNormalizationDescription": "Skenuoja failus, ieškant garso normalizavimo duomenų.",
|
||||
"TaskExtractMediaSegments": "Medijos segmentų nuskaitymas",
|
||||
|
||||
@@ -127,7 +127,9 @@
|
||||
"TaskRefreshTrickplayImages": "Ģenerēt partīšanas attēlus",
|
||||
"TaskRefreshTrickplayImagesDescription": "Izveido priekšskatījumus videoklipu pārtīšanai iespējotajās bibliotēkās.",
|
||||
"TaskAudioNormalization": "Audio normalizācija",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Noņem vairs neeksistējošus vienumus no kolekcijām un atskaņošanas sarakstiem.",
|
||||
"TaskAudioNormalizationDescription": "Skanē failus priekš audio normālizācijas informācijas.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Notīrīt kolekcijas un atskaņošanas sarakstus",
|
||||
"TaskExtractMediaSegments": "Multivides segmenta skenēšana",
|
||||
"TaskExtractMediaSegmentsDescription": "Izvelk vai iegūst multivides segmentus no MediaSegment iespējotiem spraudņiem.",
|
||||
"TaskMoveTrickplayImages": "Trickplay attēlu pārvietošana",
|
||||
|
||||
@@ -124,15 +124,13 @@
|
||||
"TaskCleanActivityLog": "Избриши Лог на Активности",
|
||||
"External": "Надворешен",
|
||||
"HearingImpaired": "Оштетен слух",
|
||||
"TaskCleanCollectionsAndPlaylists": "Исчисти ги колекциите и плејлистите",
|
||||
"TaskAudioNormalizationDescription": "Скенирање датотеки за податоци за нормализација на звукот.",
|
||||
"TaskDownloadMissingLyrics": "Преземи стихови кои недостасуваат",
|
||||
"TaskDownloadMissingLyricsDescription": "Преземи стихови/текстови за песни",
|
||||
"TaskRefreshTrickplayImages": "Генерирај слики за прегледување (Trickplay)",
|
||||
"TaskAudioNormalization": "Нормализација на звукот",
|
||||
"TaskRefreshTrickplayImagesDescription": "Креира трикплеј прегледи за видеа во овозможените библиотеки.",
|
||||
"TaskExtractMediaSegments": "Скенирање на сегменти на содржина",
|
||||
"TaskMoveTrickplayImages": "Мигрирај ја локацијата на сликата од Trickplay",
|
||||
"TaskMoveTrickplayImagesDescription": "Ги преместува постоечките датотеки за трикплеј според поставките на библиотеката.",
|
||||
"CleanupUserDataTask": "Задача за чистење на кориснички податоци",
|
||||
"CleanupUserDataTaskDescription": "Ги чисти сите кориснички податоци (состојба на гледање, статус на омилени итн.) од медиуми што повеќе не се присутни најмалку 90 дена."
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Отстранува ставки од колекциите и плејлистите што веќе не постојат.",
|
||||
"TaskExtractMediaSegments": "Скенирање на сегменти на содржина"
|
||||
}
|
||||
|
||||
@@ -124,6 +124,8 @@
|
||||
"External": "പുറമേയുള്ള",
|
||||
"TaskKeyframeExtractorDescription": "കൂടുതൽ കൃത്യമായ HLS പ്ലേലിസ്റ്റുകൾ സൃഷ്ടിക്കുന്നതിന് വീഡിയോ ഫയലുകളിൽ നിന്ന് കീഫ്രെയിമുകൾ എക്സ്ട്രാക്റ്റ് ചെയ്യുന്നു. ഈ പ്രവർത്തനം പൂർത്തിയാവാൻ കുറച്ചധികം സമയം എടുത്തേക്കാം.",
|
||||
"TaskKeyframeExtractor": "കീഫ്രെയിം എക്സ്ട്രാക്റ്റർ",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "നിലവിലില്ലാത്ത ശേഖരങ്ങളിൽ നിന്നും പ്ലേലിസ്റ്റുകളിൽ നിന്നും ഇനങ്ങൾ നീക്കംചെയ്യുന്നു.",
|
||||
"TaskCleanCollectionsAndPlaylists": "ശേഖരങ്ങളും പ്ലേലിസ്റ്റുകളും വൃത്തിയാക്കുക",
|
||||
"TaskAudioNormalization": "സാധാരണ ശബ്ദ നിലയിലെത്തിലെത്തിക്കുക",
|
||||
"TaskAudioNormalizationDescription": "സാധാരണ ശബ്ദ നിലയിലെത്തിലെത്തിക്കുന്ന ഡാറ്റയ്ക്കായി ഫയലുകൾ സ്കാൻ ചെയ്യുക.",
|
||||
"TaskRefreshTrickplayImages": "ട്രിക്ക് പ്ലേ ചിത്രങ്ങൾ സൃഷ്ടിക്കുക",
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
"NotificationOptionServerRestartRequired": "Server-г дахин асаана уу",
|
||||
"NotificationOptionVideoPlaybackStopped": "Бичлэгийг зогсоов",
|
||||
"UserPasswordChangedWithName": "Хэрэглэгч {0}-н нууц үгийг өөрчиллөө",
|
||||
"TaskCleanCollectionsAndPlaylists": "Цуглуулга ба тоглуулах жагсаалтыг цэвэрлэх",
|
||||
"ScheduledTaskFailedWithName": "{0} амжилтгүй",
|
||||
"StartupEmbyServerIsLoading": "Jellyfin Server ачааллаж байна. Хэсэг хугацааны дараа дахин оролдоно уу.",
|
||||
"TaskCleanActivityLog": "Үйл ажиллагааны бүртгэлийг цэвэрлэх",
|
||||
@@ -43,6 +44,7 @@
|
||||
"NotificationOptionAudioPlayback": "Дууг тоглууллаа",
|
||||
"TaskRefreshTrickplayImages": "Трикплэй зургуудыг үүсгэх",
|
||||
"TaskUpdatePlugins": "Plugin-уудыг шинэчлэх",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Одоо байхгүй болсон зүйлсийг цуглуулга ба тоглуулах жагсаалтаас устгана.",
|
||||
"TaskAudioNormalization": "Аудиог хэвшүүлэх",
|
||||
"TaskAudioNormalizationDescription": "Файлуудаас дууны хэвийн хэмжээсийн мэдээллийг шалгана.",
|
||||
"TaskRefreshTrickplayImagesDescription": "Идэвхжсэн сангуудад байгаа видеонуудын трикплэй урьдчилсан харагдацыг үүсгэнэ.",
|
||||
|
||||
@@ -126,6 +126,7 @@
|
||||
"HearingImpaired": "कर्णबधीर",
|
||||
"TaskRefreshTrickplayImages": "ट्रिकप्ले प्रतिमा तयार करा",
|
||||
"TaskRefreshTrickplayImagesDescription": "सक्षम लायब्ररीमधील व्हिडिओंसाठी ट्रिकप्ले पूर्वावलोकन तयार करते.",
|
||||
"TaskCleanCollectionsAndPlaylists": "संग्रह आणि प्लेलिस्ट व्यवस्थित करा",
|
||||
"TaskExtractMediaSegments": "मिडिया विभाग तपासणी",
|
||||
"TaskMoveTrickplayImages": "ट्रिकप्ले प्रतिमेचे स्थान स्थलांतर करा",
|
||||
"TaskDownloadMissingLyrics": "उपलब्ध नसलेली गीतपट्टी (Lyrics) डाउनलोड करा",
|
||||
@@ -134,6 +135,7 @@
|
||||
"TaskDownloadMissingLyricsDescription": "गाण्यांची गीतपट्टी (Lyrics) डाउनलोड करतो",
|
||||
"TaskExtractMediaSegmentsDescription": "सक्रिय असलेल्या प्लगिनमधून मीडिया विभाग प्राप्त करते.",
|
||||
"TaskMoveTrickplayImagesDescription": "लायब्ररीच्या सेटिंग्जप्रमाणे आधीपासून अस्तित्वात असलेल्या ट्रिकप्ले फाइल्सचे स्थान बदलते.",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "जे संग्रह आणि प्लेलिस्ट आता अस्तित्वात नाहीत, त्यांमधील घटक हटवते.",
|
||||
"CleanupUserDataTask": "वापरकर्ता डेटाची स्वच्छता प्रक्रिया",
|
||||
"CleanupUserDataTaskDescription": "९० दिवसांहून अधिक काळ अनुपस्थित असलेल्या माध्यमांवरील सर्व वापरकर्ता माहिती (जसे पाहण्याची स्थिती, आवडी इ.) हटवते."
|
||||
}
|
||||
|
||||
@@ -132,8 +132,10 @@
|
||||
"TaskDownloadMissingLyrics": "Muat turun lirik yang hilang",
|
||||
"TaskDownloadMissingLyricsDescription": "Memuat turun lirik-lirik untuk lagu-lagu",
|
||||
"TaskMoveTrickplayImages": "Alih Lokasi Imej Trickplay",
|
||||
"TaskCleanCollectionsAndPlaylists": "Bersihkan koleksi dan senarai audio video",
|
||||
"TaskAudioNormalization": "Normalisasi Audio",
|
||||
"TaskAudioNormalizationDescription": "Mengimbas fail-fail untuk data normalisasi audio.",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Mengalih keluar item daripada koleksi dan senarai audio video yang tidak wujud lagi.",
|
||||
"CleanupUserDataTaskDescription": "Membersihkan semua data pengguna (keadaan tontonan, status kegemaran, dan sebagainya) daripada media yang tidak lagi wujud sekurang-kurangnya selama 90 hari.",
|
||||
"CleanupUserDataTask": "Tugas pembersihan data pengguna"
|
||||
}
|
||||
|
||||
@@ -128,6 +128,8 @@
|
||||
"TaskOptimizeDatabase": "Ottimiżża d-database",
|
||||
"TaskKeyframeExtractor": "Estrattur ta' Keyframes",
|
||||
"TaskKeyframeExtractorDescription": "Jiġbed il-keyframes mill-fajls tal-videos biex jagħmel playlists HLS aktar preċiżi. Dan it-task jista' jdum żmien twil biex ilesti.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Naddaf il-kollezzjonijiet u l-playlists",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Ineħħi oġġetti minn kollezzjonijiet u playlists li m'għadhomx jeżistu.",
|
||||
"TaskDownloadMissingLyrics": "Niżżel il-lirika nieqsa",
|
||||
"TaskDownloadMissingLyricsDescription": "Iniżżel il-lirika għal-kanzunetti",
|
||||
"TaskExtractMediaSegments": "Scan tas-Sezzjoni tal-Midja",
|
||||
|
||||
@@ -122,8 +122,10 @@
|
||||
"AppDeviceValues": "အက်ပ်- {0}၊ စက်- {1}",
|
||||
"External": "ပြင်ပ",
|
||||
"TaskKeyframeExtractorDescription": "ပိုမိုတိကျသည့် အိတ်ချ်အယ်လ်အက်စ် အစဉ်လိုက်ပြသမှုများ ဖန်တီးနိုင်ရန်အတွက် ဗီဒီယိုဖိုင်များမှ ကီးဖရိန်များကို ထုတ်နှုတ်ယူမည် ဖြစ်သည်။ ဤလုပ်ဆောင်မှုသည် အချိန်ကြာရှည်နိုင်သည်။",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "စုစည်းမှုများနှင့် အစဉ်လိုက်ပြသမှုများမှ မရှိတော့သည်များကို ဖယ်ရှားမည်။",
|
||||
"TaskRefreshTrickplayImages": "ထရစ်ခ်ပလေး ပုံများကို ထုတ်မည်",
|
||||
"TaskKeyframeExtractor": "ကီးဖရိန်များကို ထုတ်နုတ်ခြင်း",
|
||||
"TaskCleanCollectionsAndPlaylists": "စုစည်းမှုများနှင့် အစဉ်လိုက်ပြသမှုများကို ရှင်းလင်းမည်",
|
||||
"HearingImpaired": "အကြားအာရုံ ချို့တဲ့သူ",
|
||||
"TaskDownloadMissingLyrics": "ကျန်နေသောသီချင်းစာသားများအား ဒေါင်းလုတ်ဆွဲပါ",
|
||||
"TaskDownloadMissingLyricsDescription": "သီချင်းများအတွက် သီချင်းစာသား ဒေါင်းလုတ်ဆွဲပါ"
|
||||
|
||||
@@ -126,8 +126,10 @@
|
||||
"HearingImpaired": "Hørselshemmet",
|
||||
"TaskRefreshTrickplayImages": "Generer Trickplay bilder",
|
||||
"TaskRefreshTrickplayImagesDescription": "Oppretter trickplay-forhåndsvisninger for videoer i aktiverte biblioteker.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Rydd kolleksjoner og spillelister",
|
||||
"TaskAudioNormalization": "Lydnormalisering",
|
||||
"TaskAudioNormalizationDescription": "Skan filer for lydnormaliserende data.",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Fjerner elementer fra kolleksjoner og spillelister som ikke lengere finnes.",
|
||||
"TaskDownloadMissingLyrics": "Last ned manglende tekster",
|
||||
"TaskDownloadMissingLyricsDescription": "Last ned sangtekster",
|
||||
"TaskExtractMediaSegments": "Skann mediasegment",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"Albums": "Albums",
|
||||
"AppDeviceValues": "App: {0}, Apparaat: {1}",
|
||||
"Application": "Applicatie",
|
||||
"Artists": "Artiesten",
|
||||
@@ -13,6 +14,7 @@
|
||||
"FailedLoginAttemptWithUserName": "Mislukte aanmeldpoging van {0}",
|
||||
"Favorites": "Favorieten",
|
||||
"Folders": "Mappen",
|
||||
"Genres": "Genres",
|
||||
"HeaderAlbumArtists": "Albumartiesten",
|
||||
"HeaderContinueWatching": "Verderkijken",
|
||||
"HeaderFavoriteAlbums": "Favoriete albums",
|
||||
@@ -21,10 +23,10 @@
|
||||
"HeaderFavoriteShows": "Favoriete series",
|
||||
"HeaderFavoriteSongs": "Favoriete nummers",
|
||||
"HeaderLiveTV": "Live-tv",
|
||||
"HeaderNextUp": "Volgende",
|
||||
"HeaderNextUp": "Als volgende",
|
||||
"HeaderRecordingGroups": "Opnamegroepen",
|
||||
"HomeVideos": "Homevideo's",
|
||||
"Inherit": "Overnemen",
|
||||
"Inherit": "Erven",
|
||||
"ItemAddedWithName": "{0} is toegevoegd aan de bibliotheek",
|
||||
"ItemRemovedWithName": "{0} is verwijderd uit de bibliotheek",
|
||||
"LabelIpAddressValue": "IP-adres: {0}",
|
||||
@@ -114,7 +116,7 @@
|
||||
"TaskCleanActivityLogDescription": "Verwijdert activiteitenlogs ouder dan de ingestelde leeftijd.",
|
||||
"TaskCleanActivityLog": "Activiteitenlogboek legen",
|
||||
"Undefined": "Niet gedefinieerd",
|
||||
"Forced": "Geforceerd",
|
||||
"Forced": "Gedwongen",
|
||||
"Default": "Standaard",
|
||||
"TaskOptimizeDatabaseDescription": "Comprimeert de database en trimt vrije ruimte. Het uitvoeren van deze taak kan de prestaties verbeteren, na het scannen van de bibliotheek of andere aanpassingen die invloed hebben op de database.",
|
||||
"TaskOptimizeDatabase": "Database optimaliseren",
|
||||
@@ -124,6 +126,8 @@
|
||||
"HearingImpaired": "Slechthorenden",
|
||||
"TaskRefreshTrickplayImages": "Trickplay-afbeeldingen genereren",
|
||||
"TaskRefreshTrickplayImagesDescription": "Creëert trickplay-voorvertoningen voor video's in bibliotheken waarvoor dit is ingeschakeld.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Collecties en afspeellijsten opruimen",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Verwijdert niet langer bestaande items uit collecties en afspeellijsten.",
|
||||
"TaskAudioNormalization": "Geluidsnormalisatie",
|
||||
"TaskAudioNormalizationDescription": "Scant bestanden op gegevens voor geluidsnormalisatie.",
|
||||
"TaskDownloadMissingLyrics": "Ontbrekende liedteksten downloaden",
|
||||
@@ -133,7 +137,5 @@
|
||||
"TaskMoveTrickplayImagesDescription": "Verplaatst bestaande trickplay-bestanden op basis van de bibliotheekinstellingen.",
|
||||
"TaskExtractMediaSegments": "Scannen op mediasegmenten",
|
||||
"CleanupUserDataTaskDescription": "Wist alle gebruikersgegevens (kijkstatus, favorieten, etc.) van media die al minstens 90 dagen niet meer aanwezig zijn.",
|
||||
"CleanupUserDataTask": "Opruimtaak gebruikersdata",
|
||||
"Albums": "Albums",
|
||||
"Genres": "Genres"
|
||||
"CleanupUserDataTask": "Opruimtaak gebruikersdata"
|
||||
}
|
||||
|
||||
@@ -131,6 +131,8 @@
|
||||
"TaskDownloadMissingLyrics": "ਅਧੂਰੇ ਬੋਲ ਡਾਊਨਲੋਡ ਕਰੋ",
|
||||
"TaskDownloadMissingLyricsDescription": "ਗੀਤਾਂ ਲਈ ਡਾਊਨਲੋਡ ਕਿਤੇ ਬੋਲ",
|
||||
"TaskKeyframeExtractor": "ਕੀ-ਫ੍ਰੇਮ ਐਕਸਟ੍ਰੈਕਟਰ",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "ਕਲੈਕਸ਼ਨਾਂ ਅਤੇ ਪਲੇਲਿਸਟਾਂ ਵਿੱਚੋਂ ਉਹ ਆਈਟਮ ਹਟਾਉਂਦਾ ਹੈ ਜੋ ਹੁਣ ਮੌਜੂਦ ਨਹੀਂ ਹਨ।",
|
||||
"TaskCleanCollectionsAndPlaylists": "ਕਲੈਕਸ਼ਨਾਂ ਅਤੇ ਪਲੇਲਿਸਟਾਂ ਨੂੰ ਸਾਫ ਕਰੋ",
|
||||
"TaskAudioNormalization": "ਆਵਾਜ਼ ਸਧਾਰਣੀਕਰਨ",
|
||||
"TaskRefreshTrickplayImagesDescription": "ਵੀਡੀਓ ਲਈ ਟ੍ਰਿਕਪਲੇ ਪ੍ਰੀਵਿਊ ਬਣਾਉਂਦਾ ਹੈ (ਜੇ ਲਾਇਬ੍ਰੇਰੀ ਵਿੱਚ ਚੁਣਿਆ ਗਿਆ ਹੈ)।",
|
||||
"TaskKeyframeExtractorDescription": "ਕੀ-ਫ੍ਰੇਮਜ਼ ਨੂੰ ਵੀਡੀਓ ਫਾਈਲਾਂ ਵਿੱਚੋਂ ਨਿਕਾਲਦਾ ਹੈ ਤਾਂ ਜੋ ਹੋਰ ਜ਼ਿਆਦਾ ਸਟਿਕ ਹੋਣ ਵਾਲੀਆਂ HLS ਪਲੇਲਿਸਟਾਂ ਬਣਾਈਆਂ ਜਾ ਸਕਣ। ਇਹ ਕੰਮ ਲੰਬੇ ਸਮੇਂ ਤੱਕ ਚੱਲ ਸਕਦਾ ਹੈ।",
|
||||
|
||||
@@ -126,6 +126,8 @@
|
||||
"HearingImpaired": "Niedosłyszący",
|
||||
"TaskRefreshTrickplayImages": "Generuj obrazy Trickplay",
|
||||
"TaskRefreshTrickplayImagesDescription": "Tworzy podglądy Trickplay dla filmów we włączonych bibliotekach.",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Usuwa elementy z kolekcji i list odtwarzania, które już nie istnieją.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Oczyść kolekcje i listy odtwarzania",
|
||||
"TaskAudioNormalization": "Normalizacja dźwięku",
|
||||
"TaskAudioNormalizationDescription": "Skanuje pliki w poszukiwaniu danych normalizacji dźwięku.",
|
||||
"TaskDownloadMissingLyrics": "Pobierz brakujące słowa",
|
||||
|
||||
@@ -126,6 +126,8 @@
|
||||
"HearingImpaired": "Deficiência Auditiva",
|
||||
"TaskRefreshTrickplayImages": "Gerar imagens Trickplay",
|
||||
"TaskRefreshTrickplayImagesDescription": "Cria prévias Trickplay para vídeos em bibliotecas em que o recurso está habilitado.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Limpe coleções e playlists",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Remove itens de coleções e playlists que não existem mais.",
|
||||
"TaskAudioNormalization": "Normalização de áudio",
|
||||
"TaskAudioNormalizationDescription": "Examina os ficheiros em busca de dados de normalização de áudio.",
|
||||
"TaskDownloadMissingLyricsDescription": "Baixar letras para músicas",
|
||||
|
||||
@@ -126,6 +126,8 @@
|
||||
"HearingImpaired": "Surdo",
|
||||
"TaskRefreshTrickplayImages": "Gerar imagens de trickplay",
|
||||
"TaskRefreshTrickplayImagesDescription": "Cria pré-visualizações de trickplay para vídeos nas bibliotecas ativadas.",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Remove itens de coleções e listas de reprodução que já não existem.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Limpar coleções e listas de reprodução",
|
||||
"TaskAudioNormalizationDescription": "Analisa os ficheiros para obter dados de normalização de áudio.",
|
||||
"TaskAudioNormalization": "Normalização de áudio",
|
||||
"TaskExtractMediaSegments": "Analisar segmentos de multimédia",
|
||||
|
||||
@@ -126,6 +126,8 @@
|
||||
"TaskKeyframeExtractorDescription": "Retira frames chave do video para criar listas HLS precisas. Esta tarefa pode correr durante algum tempo.",
|
||||
"TaskRefreshTrickplayImages": "Gerar imagens de trickplay",
|
||||
"TaskRefreshTrickplayImagesDescription": "Cria pré-visualizações de trickplay para vídeos nas bibliotecas ativadas.",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Remove itens de coleções e listas de reprodução que já não existem.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Limpar coleções e listas de reprodução",
|
||||
"TaskAudioNormalizationDescription": "Analisa os ficheiros para obter dados de normalização de áudio.",
|
||||
"TaskAudioNormalization": "Normalização de áudio",
|
||||
"TaskDownloadMissingLyrics": "Transferir letra em falta",
|
||||
|
||||
@@ -128,6 +128,8 @@
|
||||
"TaskRefreshTrickplayImagesDescription": "Generează previzualizările trickplay pentru videourile din librăriile selectate.",
|
||||
"TaskAudioNormalizationDescription": "Scanează fișiere pentru date necesare normalizării sunetului.",
|
||||
"TaskAudioNormalization": "Normalizare sunet",
|
||||
"TaskCleanCollectionsAndPlaylists": "Curăță colecțiile și listele de redare",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Elimină elementele care nu mai există din colecții și liste de redare.",
|
||||
"TaskExtractMediaSegments": "Scanează segmentele media",
|
||||
"TaskMoveTrickplayImagesDescription": "Mută fișierele trickplay existente conform setărilor librăriei.",
|
||||
"TaskExtractMediaSegmentsDescription": "Extrage sau obține segmentele media de la pluginurile MediaSegment activate.",
|
||||
|
||||
@@ -126,6 +126,8 @@
|
||||
"HearingImpaired": "Для слабослышащих",
|
||||
"TaskRefreshTrickplayImages": "Сгенерировать изображения для Trickplay",
|
||||
"TaskRefreshTrickplayImagesDescription": "Создает предпросмотры для Trickplay для видео в библиотеках, где эта функция включена.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Очистка коллекций и списков воспроизведения",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Удаляет элементы из коллекций и списков воспроизведения, которые больше не существуют.",
|
||||
"TaskAudioNormalization": "Нормализация звука",
|
||||
"TaskAudioNormalizationDescription": "Сканирует файлы на наличие данных о нормализации звука.",
|
||||
"TaskDownloadMissingLyrics": "Загрузить недостающий текст",
|
||||
|
||||
@@ -126,6 +126,8 @@
|
||||
"HearingImpaired": "Sluchovo postihnutí",
|
||||
"TaskRefreshTrickplayImages": "Generovanie obrázkov Trickplay",
|
||||
"TaskRefreshTrickplayImagesDescription": "Vytvára trickplay náhľady pre videá v povolených knižniciach.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Vyčistiť kolekcie a playlisty",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Odstráni položky z kolekcií a playlistov, ktoré už neexistujú.",
|
||||
"TaskAudioNormalization": "Normalizácia zvuku",
|
||||
"TaskAudioNormalizationDescription": "Skenovať súbory za účelom normalizácie zvuku.",
|
||||
"TaskExtractMediaSegments": "Skenovanie segmentov médií",
|
||||
|
||||
@@ -132,8 +132,10 @@
|
||||
"TaskMoveTrickplayImages": "Preseli lokacijo Trickplay slik",
|
||||
"TaskDownloadMissingLyrics": "Prenesi manjkajoča besedila pesmi",
|
||||
"TaskDownloadMissingLyricsDescription": "Prenesi besedila za pesmi",
|
||||
"TaskCleanCollectionsAndPlaylists": "Počisti zbirke in sezname predvajanja",
|
||||
"TaskAudioNormalization": "Normalizacija zvoka",
|
||||
"TaskAudioNormalizationDescription": "Pregled datotek za podatke o normalizaciji zvoka.",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Odstrani elemente iz zbirk in seznamov predvajanja, ki ne obstajajo več.",
|
||||
"CleanupUserDataTask": "Čiščenje uporabniških podatkov",
|
||||
"CleanupUserDataTaskDescription": "Izbriše vse uporabniške podatke (stanje ogleda, priljubljene itd.) za vsebine, ki že več kot 90 dni niso na voljo."
|
||||
}
|
||||
|
||||
@@ -132,6 +132,8 @@
|
||||
"TaskMoveTrickplayImagesDescription": "Zhvendos skedarët ekzistues të trickplay sipas cilësimeve të bibliotekës.",
|
||||
"TaskDownloadMissingLyrics": "Shkarko tekstet e këngëve që mungojnë",
|
||||
"TaskDownloadMissingLyricsDescription": "Shkarkon tekstet e këngëve",
|
||||
"TaskCleanCollectionsAndPlaylists": "Pastron koleksionet dhe listat e këngëve",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Heq elementet nga koleksionet dhe listat e këngëve që nuk ekzistojnë më.",
|
||||
"TaskAudioNormalization": "Normalizimi i audios",
|
||||
"TaskAudioNormalizationDescription": "Skannon skedarët për të dhëna të normalizimit të audios.",
|
||||
"CleanupUserDataTaskDescription": "Pastron të gjitha të dhënat e përdorueseve (gjendja e shikimit, statusi i të preferuarave etj.) nga mediat që nuk janë më të pranishme për të paktën 90 ditë.",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user