mirror of
https://github.com/Sonarr/Sonarr.git
synced 2026-04-16 21:15:28 -04:00
Compare commits
57 Commits
v4.0.4.169
...
v4.0.7.186
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6afd3bd344 | ||
|
|
acaf5cd353 | ||
|
|
e97e5bfe8f | ||
|
|
678872b879 | ||
|
|
10e9735c1c | ||
|
|
293a1bc618 | ||
|
|
0c883f7886 | ||
|
|
46c7de379c | ||
|
|
a83b521766 | ||
|
|
1d06e40acb | ||
|
|
bfcdc89f6a | ||
|
|
67943edfbc | ||
|
|
04f8595498 | ||
|
|
81ac73299a | ||
|
|
a779a5fad2 | ||
|
|
bfe6a740fa | ||
|
|
c9ea40b874 | ||
|
|
4ee0ae1418 | ||
|
|
ac1da45ecd | ||
|
|
5c327d5be3 | ||
|
|
55c1ce2e3d | ||
|
|
fd7f0ea973 | ||
|
|
d5dff8e8d6 | ||
|
|
8099ba10af | ||
|
|
143ccb1e2a | ||
|
|
29480d9544 | ||
|
|
6de536a7ad | ||
|
|
bce848facf | ||
|
|
ea4fe392a0 | ||
|
|
45fe585944 | ||
|
|
a0d2933134 | ||
|
|
4c622fd412 | ||
|
|
fb060730c7 | ||
|
|
6d5ff9c4d6 | ||
|
|
63bed3e670 | ||
|
|
e684c10432 | ||
|
|
d2509798e9 | ||
|
|
6c39855ebe | ||
|
|
a30e9da767 | ||
|
|
f8e81396d4 | ||
|
|
7fccf590a8 | ||
|
|
e1b937e8d5 | ||
|
|
c331c8bd11 | ||
|
|
52b72925f9 | ||
|
|
378fedcd9d | ||
|
|
a90ab1a8fd | ||
|
|
0edc5ba99a | ||
|
|
ea54ade9bf | ||
|
|
e07eb05e8b | ||
|
|
d9b771ab0b | ||
|
|
6b08e849b8 | ||
|
|
9c1f48ebc9 | ||
|
|
fd3dd1ab7d | ||
|
|
11e5c5a11b | ||
|
|
48f0291884 | ||
|
|
af0e55aef4 | ||
|
|
39a439eb4c |
242
.github/workflows/build.yml
vendored
242
.github/workflows/build.yml
vendored
@@ -6,13 +6,13 @@ on:
|
||||
- develop
|
||||
- main
|
||||
paths-ignore:
|
||||
- 'src/Sonarr.Api.*/openapi.json'
|
||||
- "src/Sonarr.Api.*/openapi.json"
|
||||
pull_request:
|
||||
branches:
|
||||
- develop
|
||||
paths-ignore:
|
||||
- 'src/NzbDrone.Core/Localization/Core/**'
|
||||
- 'src/Sonarr.Api.*/openapi.json'
|
||||
- "src/NzbDrone.Core/Localization/Core/**"
|
||||
- "src/Sonarr.Api.*/openapi.json"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
@@ -22,7 +22,7 @@ env:
|
||||
FRAMEWORK: net6.0
|
||||
RAW_BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
|
||||
SONARR_MAJOR_VERSION: 4
|
||||
VERSION: 4.0.4
|
||||
VERSION: 4.0.7
|
||||
|
||||
jobs:
|
||||
backend:
|
||||
@@ -32,105 +32,105 @@ jobs:
|
||||
major_version: ${{ steps.variables.outputs.major_version }}
|
||||
version: ${{ steps.variables.outputs.version }}
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v4
|
||||
- name: Check out
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
|
||||
- name: Setup Environment Variables
|
||||
id: variables
|
||||
shell: bash
|
||||
run: |
|
||||
# Add 800 to the build number because GitHub won't let us pick an arbitrary starting point
|
||||
SONARR_VERSION="${{ env.VERSION }}.$((${{ github.run_number }}+800))"
|
||||
DOTNET_VERSION=$(jq -r '.sdk.version' global.json)
|
||||
- name: Setup Environment Variables
|
||||
id: variables
|
||||
shell: bash
|
||||
run: |
|
||||
# Add 800 to the build number because GitHub won't let us pick an arbitrary starting point
|
||||
SONARR_VERSION="${{ env.VERSION }}.$((${{ github.run_number }}+800))"
|
||||
DOTNET_VERSION=$(jq -r '.sdk.version' global.json)
|
||||
|
||||
echo "SDK_PATH=${{ env.DOTNET_ROOT }}/sdk/${DOTNET_VERSION}" >> "$GITHUB_ENV"
|
||||
echo "SONARR_VERSION=$SONARR_VERSION" >> "$GITHUB_ENV"
|
||||
echo "BRANCH=${RAW_BRANCH_NAME//\//-}" >> "$GITHUB_ENV"
|
||||
echo "SDK_PATH=${{ env.DOTNET_ROOT }}/sdk/${DOTNET_VERSION}" >> "$GITHUB_ENV"
|
||||
echo "SONARR_VERSION=$SONARR_VERSION" >> "$GITHUB_ENV"
|
||||
echo "BRANCH=${RAW_BRANCH_NAME//\//-}" >> "$GITHUB_ENV"
|
||||
|
||||
echo "framework=${{ env.FRAMEWORK }}" >> "$GITHUB_OUTPUT"
|
||||
echo "major_version=${{ env.SONARR_MAJOR_VERSION }}" >> "$GITHUB_OUTPUT"
|
||||
echo "version=$SONARR_VERSION" >> "$GITHUB_OUTPUT"
|
||||
echo "framework=${{ env.FRAMEWORK }}" >> "$GITHUB_OUTPUT"
|
||||
echo "major_version=${{ env.SONARR_MAJOR_VERSION }}" >> "$GITHUB_OUTPUT"
|
||||
echo "version=$SONARR_VERSION" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Enable Extra Platforms In SDK
|
||||
shell: bash
|
||||
run: ./build.sh --enable-extra-platforms-in-sdk
|
||||
- name: Enable Extra Platforms In SDK
|
||||
shell: bash
|
||||
run: ./build.sh --enable-extra-platforms-in-sdk
|
||||
|
||||
- name: Build Backend
|
||||
shell: bash
|
||||
run: ./build.sh --backend --enable-extra-platforms --packages
|
||||
- name: Build Backend
|
||||
shell: bash
|
||||
run: ./build.sh --backend --enable-extra-platforms --packages
|
||||
|
||||
# Test Artifacts
|
||||
# Test Artifacts
|
||||
|
||||
- name: Publish win-x64 Test Artifact
|
||||
uses: ./.github/actions/publish-test-artifact
|
||||
with:
|
||||
framework: ${{ env.FRAMEWORK }}
|
||||
runtime: win-x64
|
||||
- name: Publish win-x64 Test Artifact
|
||||
uses: ./.github/actions/publish-test-artifact
|
||||
with:
|
||||
framework: ${{ env.FRAMEWORK }}
|
||||
runtime: win-x64
|
||||
|
||||
- name: Publish linux-x64 Test Artifact
|
||||
uses: ./.github/actions/publish-test-artifact
|
||||
with:
|
||||
framework: ${{ env.FRAMEWORK }}
|
||||
runtime: linux-x64
|
||||
- name: Publish linux-x64 Test Artifact
|
||||
uses: ./.github/actions/publish-test-artifact
|
||||
with:
|
||||
framework: ${{ env.FRAMEWORK }}
|
||||
runtime: linux-x64
|
||||
|
||||
- name: Publish osx-arm64 Test Artifact
|
||||
uses: ./.github/actions/publish-test-artifact
|
||||
with:
|
||||
framework: ${{ env.FRAMEWORK }}
|
||||
runtime: osx-arm64
|
||||
- name: Publish osx-arm64 Test Artifact
|
||||
uses: ./.github/actions/publish-test-artifact
|
||||
with:
|
||||
framework: ${{ env.FRAMEWORK }}
|
||||
runtime: osx-arm64
|
||||
|
||||
# Build Artifacts (grouped by OS)
|
||||
|
||||
- name: Publish FreeBSD Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build_freebsd
|
||||
path: _artifacts/freebsd-*/**/*
|
||||
- name: Publish Linux Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build_linux
|
||||
path: _artifacts/linux-*/**/*
|
||||
- name: Publish macOS Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build_macos
|
||||
path: _artifacts/osx-*/**/*
|
||||
- name: Publish Windows Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build_windows
|
||||
path: _artifacts/win-*/**/*
|
||||
# Build Artifacts (grouped by OS)
|
||||
|
||||
- name: Publish FreeBSD Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build_freebsd
|
||||
path: _artifacts/freebsd-*/**/*
|
||||
- name: Publish Linux Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build_linux
|
||||
path: _artifacts/linux-*/**/*
|
||||
- name: Publish macOS Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build_macos
|
||||
path: _artifacts/osx-*/**/*
|
||||
- name: Publish Windows Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build_windows
|
||||
path: _artifacts/win-*/**/*
|
||||
|
||||
frontend:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v4
|
||||
- name: Check out
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Volta
|
||||
uses: volta-cli/action@v4
|
||||
- name: Volta
|
||||
uses: volta-cli/action@v4
|
||||
|
||||
- name: Yarn Install
|
||||
run: yarn install
|
||||
- name: Yarn Install
|
||||
run: yarn install
|
||||
|
||||
- name: Lint
|
||||
run: yarn lint
|
||||
- name: Lint
|
||||
run: yarn lint
|
||||
|
||||
- name: Stylelint
|
||||
run: yarn stylelint -f github
|
||||
- name: Stylelint
|
||||
run: yarn stylelint -f github
|
||||
|
||||
- name: Build
|
||||
run: yarn build --env production
|
||||
- name: Build
|
||||
run: yarn build --env production
|
||||
|
||||
- name: Publish UI Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build_ui
|
||||
path: _output/UI/**/*
|
||||
- name: Publish UI Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build_ui
|
||||
path: _output/UI/**/*
|
||||
|
||||
unit_test:
|
||||
needs: backend
|
||||
@@ -150,32 +150,32 @@ jobs:
|
||||
filter: TestCategory!=ManualTest&TestCategory!=LINUX&TestCategory!=IntegrationTest&TestCategory!=AutomationTest
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v4
|
||||
- name: Check out
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Test
|
||||
uses: ./.github/actions/test
|
||||
with:
|
||||
os: ${{ matrix.os }}
|
||||
artifact: ${{ matrix.artifact }}
|
||||
pattern: Sonarr.*.Test.dll
|
||||
filter: ${{ matrix.filter }}
|
||||
- name: Test
|
||||
uses: ./.github/actions/test
|
||||
with:
|
||||
os: ${{ matrix.os }}
|
||||
artifact: ${{ matrix.artifact }}
|
||||
pattern: Sonarr.*.Test.dll
|
||||
filter: ${{ matrix.filter }}
|
||||
|
||||
unit_test_postgres:
|
||||
needs: backend
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v4
|
||||
- name: Check out
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Test
|
||||
uses: ./.github/actions/test
|
||||
with:
|
||||
os: ubuntu-latest
|
||||
artifact: tests-linux-x64
|
||||
pattern: Sonarr.*.Test.dll
|
||||
filter: TestCategory!=ManualTest&TestCategory!=WINDOWS&TestCategory!=IntegrationTest&TestCategory!=AutomationTest
|
||||
use_postgres: true
|
||||
- name: Test
|
||||
uses: ./.github/actions/test
|
||||
with:
|
||||
os: ubuntu-latest
|
||||
artifact: tests-linux-x64
|
||||
pattern: Sonarr.*.Test.dll
|
||||
filter: TestCategory!=ManualTest&TestCategory!=WINDOWS&TestCategory!=IntegrationTest&TestCategory!=AutomationTest
|
||||
use_postgres: true
|
||||
|
||||
integration_test:
|
||||
needs: backend
|
||||
@@ -201,19 +201,19 @@ jobs:
|
||||
binary_path: win-x64/${{ needs.backend.outputs.framework }}/Sonarr
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v4
|
||||
- name: Check out
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Test
|
||||
uses: ./.github/actions/test
|
||||
with:
|
||||
os: ${{ matrix.os }}
|
||||
artifact: ${{ matrix.artifact }}
|
||||
pattern: Sonarr.*.Test.dll
|
||||
filter: ${{ matrix.filter }}
|
||||
integration_tests: true
|
||||
binary_artifact: ${{ matrix.binary_artifact }}
|
||||
binary_path: ${{ matrix.binary_path }}
|
||||
- name: Test
|
||||
uses: ./.github/actions/test
|
||||
with:
|
||||
os: ${{ matrix.os }}
|
||||
artifact: ${{ matrix.artifact }}
|
||||
pattern: Sonarr.*.Test.dll
|
||||
filter: ${{ matrix.filter }}
|
||||
integration_tests: true
|
||||
binary_artifact: ${{ matrix.binary_artifact }}
|
||||
binary_path: ${{ matrix.binary_path }}
|
||||
|
||||
deploy:
|
||||
if: ${{ github.ref_name == 'develop' || github.ref_name == 'main' }}
|
||||
@@ -228,7 +228,15 @@ jobs:
|
||||
|
||||
notify:
|
||||
name: Discord Notification
|
||||
needs: [backend, frontend, unit_test, unit_test_postgres, integration_test, deploy]
|
||||
needs:
|
||||
[
|
||||
backend,
|
||||
frontend,
|
||||
unit_test,
|
||||
unit_test_postgres,
|
||||
integration_test,
|
||||
deploy,
|
||||
]
|
||||
if: ${{ !cancelled() && (github.ref_name == 'develop' || github.ref_name == 'main') }}
|
||||
env:
|
||||
STATUS: ${{ contains(needs.*.result, 'failure') && 'failure' || 'success' }}
|
||||
@@ -239,10 +247,10 @@ jobs:
|
||||
uses: tsickert/discord-webhook@v6.0.0
|
||||
with:
|
||||
webhook-url: ${{ secrets.DISCORD_WEBHOOK_URL }}
|
||||
username: 'GitHub Actions'
|
||||
avatar-url: 'https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png'
|
||||
username: "GitHub Actions"
|
||||
avatar-url: "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png"
|
||||
embed-title: "${{ github.workflow }}: ${{ env.STATUS == 'success' && 'Success' || 'Failure' }}"
|
||||
embed-url: 'https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}'
|
||||
embed-url: "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
||||
embed-description: |
|
||||
**Branch** ${{ github.ref }}
|
||||
**Build** ${{ needs.backend.outputs.version }}
|
||||
|
||||
12
docs.sh
12
docs.sh
@@ -25,17 +25,23 @@ slnFile=src/Sonarr.sln
|
||||
|
||||
platform=Posix
|
||||
|
||||
if [ "$PLATFORM" = "Windows" ]; then
|
||||
application=Sonarr.Console.dll
|
||||
else
|
||||
application=Sonarr.dll
|
||||
fi
|
||||
|
||||
dotnet clean $slnFile -c Debug
|
||||
dotnet clean $slnFile -c Release
|
||||
|
||||
dotnet msbuild -restore $slnFile -p:Configuration=Debug -p:Platform=$platform -p:RuntimeIdentifiers=$RUNTIME -t:PublishAllRids
|
||||
|
||||
dotnet new tool-manifest
|
||||
dotnet tool install --version 6.5.0 Swashbuckle.AspNetCore.Cli
|
||||
dotnet tool install --version 6.6.2 Swashbuckle.AspNetCore.Cli
|
||||
|
||||
dotnet tool run swagger tofile --output ./src/Sonarr.Api.V3/openapi.json "$outputFolder/$FRAMEWORK/$RUNTIME/Sonarr.dll" v3 &
|
||||
dotnet tool run swagger tofile --output ./src/Sonarr.Api.V3/openapi.json "$outputFolder/$FRAMEWORK/$RUNTIME/$application" v3 &
|
||||
|
||||
sleep 30
|
||||
sleep 45
|
||||
|
||||
kill %1
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ class HistoryRow extends Component {
|
||||
onMarkAsFailedPress
|
||||
} = this.props;
|
||||
|
||||
if (!episode) {
|
||||
if (!series || !episode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -217,6 +217,7 @@ class Queue extends Component {
|
||||
>
|
||||
<TableOptionsModalWrapper
|
||||
columns={columns}
|
||||
maxPageSize={200}
|
||||
{...otherProps}
|
||||
optionsComponent={QueueOptionsConnector}
|
||||
>
|
||||
|
||||
@@ -70,6 +70,11 @@ function QueueStatus(props) {
|
||||
iconName = icons.DOWNLOADED;
|
||||
title = translate('Downloaded');
|
||||
|
||||
if (trackedDownloadState === 'importBlocked') {
|
||||
title += ` - ${translate('UnableToImportAutomatically')}`;
|
||||
iconKind = kinds.WARNING;
|
||||
}
|
||||
|
||||
if (trackedDownloadState === 'importPending') {
|
||||
title += ` - ${translate('WaitingToImport')}`;
|
||||
iconKind = kinds.PURPLE;
|
||||
|
||||
@@ -118,6 +118,7 @@ function RemoveQueueItemModal(props: RemoveQueueItemModalProps) {
|
||||
{
|
||||
key: 'blocklistAndSearch',
|
||||
value: translate('BlocklistAndSearch'),
|
||||
isDisabled: isPending,
|
||||
hint: multipleSelected
|
||||
? translate('BlocklistAndSearchMultipleHint')
|
||||
: translate('BlocklistAndSearchHint'),
|
||||
@@ -130,7 +131,7 @@ function RemoveQueueItemModal(props: RemoveQueueItemModalProps) {
|
||||
: translate('BlocklistOnlyHint'),
|
||||
},
|
||||
];
|
||||
}, [multipleSelected]);
|
||||
}, [isPending, multipleSelected]);
|
||||
|
||||
const handleRemovalMethodChange = useCallback(
|
||||
({ value }: { value: RemovalMethod }) => {
|
||||
|
||||
@@ -271,26 +271,32 @@ class EnhancedSelectInput extends Component {
|
||||
this.setState({ isOpen: !this.state.isOpen });
|
||||
};
|
||||
|
||||
onSelect = (value) => {
|
||||
if (Array.isArray(this.props.value)) {
|
||||
let newValue = null;
|
||||
const index = this.props.value.indexOf(value);
|
||||
onSelect = (newValue) => {
|
||||
const { name, value, values, onChange } = this.props;
|
||||
const additionalProperties = values.find((v) => v.key === newValue)?.additionalProperties;
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
let arrayValue = null;
|
||||
const index = value.indexOf(newValue);
|
||||
|
||||
if (index === -1) {
|
||||
newValue = this.props.values.map((v) => v.key).filter((v) => (v === value) || this.props.value.includes(v));
|
||||
arrayValue = values.map((v) => v.key).filter((v) => (v === newValue) || value.includes(v));
|
||||
} else {
|
||||
newValue = [...this.props.value];
|
||||
newValue.splice(index, 1);
|
||||
arrayValue = [...value];
|
||||
arrayValue.splice(index, 1);
|
||||
}
|
||||
this.props.onChange({
|
||||
name: this.props.name,
|
||||
value: newValue
|
||||
onChange({
|
||||
name,
|
||||
value: arrayValue,
|
||||
additionalProperties
|
||||
});
|
||||
} else {
|
||||
this.setState({ isOpen: false });
|
||||
|
||||
this.props.onChange({
|
||||
name: this.props.name,
|
||||
value
|
||||
onChange({
|
||||
name,
|
||||
value: newValue,
|
||||
additionalProperties
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -485,7 +491,7 @@ class EnhancedSelectInput extends Component {
|
||||
values.map((v, index) => {
|
||||
const hasParent = v.parentKey !== undefined;
|
||||
const depth = hasParent ? 1 : 0;
|
||||
const parentSelected = hasParent && value.includes(v.parentKey);
|
||||
const parentSelected = hasParent && Array.isArray(value) && value.includes(v.parentKey);
|
||||
return (
|
||||
<OptionComponent
|
||||
key={v.key}
|
||||
|
||||
@@ -9,7 +9,8 @@ import EnhancedSelectInput from './EnhancedSelectInput';
|
||||
const importantFieldNames = [
|
||||
'baseUrl',
|
||||
'apiPath',
|
||||
'apiKey'
|
||||
'apiKey',
|
||||
'authToken'
|
||||
];
|
||||
|
||||
function getProviderDataKey(providerData) {
|
||||
@@ -34,7 +35,9 @@ function getSelectOptions(items) {
|
||||
key: option.value,
|
||||
value: option.name,
|
||||
hint: option.hint,
|
||||
parentKey: option.parentValue
|
||||
parentKey: option.parentValue,
|
||||
isDisabled: option.isDisabled,
|
||||
additionalProperties: option.additionalProperties
|
||||
};
|
||||
});
|
||||
}
|
||||
@@ -147,7 +150,7 @@ EnhancedSelectInputConnector.propTypes = {
|
||||
provider: PropTypes.string.isRequired,
|
||||
providerData: PropTypes.object.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
value: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.number, PropTypes.string])).isRequired,
|
||||
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.arrayOf(PropTypes.string), PropTypes.arrayOf(PropTypes.number)]).isRequired,
|
||||
values: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
selectOptionsProviderAction: PropTypes.string,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
|
||||
@@ -88,6 +88,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
.purple {
|
||||
border-color: var(--purple);
|
||||
background-color: var(--purple);
|
||||
|
||||
&.outline {
|
||||
color: var(--purple);
|
||||
}
|
||||
}
|
||||
|
||||
/** Sizes **/
|
||||
|
||||
.small {
|
||||
|
||||
1
frontend/src/Components/Label.css.d.ts
vendored
1
frontend/src/Components/Label.css.d.ts
vendored
@@ -11,6 +11,7 @@ interface CssExports {
|
||||
'medium': string;
|
||||
'outline': string;
|
||||
'primary': string;
|
||||
'purple': string;
|
||||
'small': string;
|
||||
'success': string;
|
||||
'warning': string;
|
||||
|
||||
@@ -21,6 +21,7 @@ function createCleanSeriesSelector() {
|
||||
tvdbId,
|
||||
tvMazeId,
|
||||
imdbId,
|
||||
tmdbId,
|
||||
tags = []
|
||||
} = series;
|
||||
|
||||
@@ -33,6 +34,7 @@ function createCleanSeriesSelector() {
|
||||
tvdbId,
|
||||
tvMazeId,
|
||||
imdbId,
|
||||
tmdbId,
|
||||
firstCharacter: title.charAt(0).toLowerCase(),
|
||||
tags: tags.reduce((acc, id) => {
|
||||
const matchingTag = allTags.find((tag) => tag.id === id);
|
||||
|
||||
@@ -14,6 +14,7 @@ function SeriesSearchResult(props) {
|
||||
tvdbId,
|
||||
tvMazeId,
|
||||
imdbId,
|
||||
tmdbId,
|
||||
tags
|
||||
} = props;
|
||||
|
||||
@@ -73,6 +74,14 @@ function SeriesSearchResult(props) {
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
match.key === 'tmdbId' && tmdbId ?
|
||||
<div className={styles.alternateTitle}>
|
||||
TmdbId: {tmdbId}
|
||||
</div> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
tag ?
|
||||
<div className={styles.tagContainer}>
|
||||
@@ -97,6 +106,7 @@ SeriesSearchResult.propTypes = {
|
||||
tvdbId: PropTypes.number,
|
||||
tvMazeId: PropTypes.number,
|
||||
imdbId: PropTypes.string,
|
||||
tmdbId: PropTypes.number,
|
||||
tags: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
match: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
@@ -13,6 +13,7 @@ const fuseOptions = {
|
||||
'tvdbId',
|
||||
'tvMazeId',
|
||||
'imdbId',
|
||||
'tmdbId',
|
||||
'tags.label'
|
||||
]
|
||||
};
|
||||
|
||||
@@ -49,11 +49,12 @@ class TableOptionsModal extends Component {
|
||||
|
||||
onPageSizeChange = ({ value }) => {
|
||||
let pageSizeError = null;
|
||||
const maxPageSize = this.props.maxPageSize ?? 250;
|
||||
|
||||
if (value < 5) {
|
||||
pageSizeError = translate('TablePageSizeMinimum', { minimumValue: '5' });
|
||||
} else if (value > 250) {
|
||||
pageSizeError = translate('TablePageSizeMaximum', { maximumValue: '250' });
|
||||
} else if (value > maxPageSize) {
|
||||
pageSizeError = translate('TablePageSizeMaximum', { maximumValue: `${maxPageSize}` });
|
||||
} else {
|
||||
this.props.onTableOptionChange({ pageSize: value });
|
||||
}
|
||||
@@ -248,6 +249,7 @@ TableOptionsModal.propTypes = {
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
pageSize: PropTypes.number,
|
||||
maxPageSize: PropTypes.number,
|
||||
canModifyColumns: PropTypes.bool.isRequired,
|
||||
optionsComponent: PropTypes.elementType,
|
||||
onTableOptionChange: PropTypes.func.isRequired,
|
||||
|
||||
@@ -14,4 +14,9 @@
|
||||
.deleteFilesMessage {
|
||||
margin-top: 20px;
|
||||
color: var(--dangerColor);
|
||||
|
||||
.deleteCount {
|
||||
margin-top: 20px;
|
||||
color: var(--warningColor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// This file is automatically generated.
|
||||
// Please do not change this file!
|
||||
interface CssExports {
|
||||
'deleteCount': string;
|
||||
'deleteFilesMessage': string;
|
||||
'folderPath': string;
|
||||
'pathContainer': string;
|
||||
|
||||
@@ -50,15 +50,15 @@ class DeleteSeriesModalContent extends Component {
|
||||
const {
|
||||
title,
|
||||
path,
|
||||
statistics,
|
||||
statistics = {},
|
||||
deleteOptions,
|
||||
onModalClose,
|
||||
onDeleteOptionChange
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
episodeFileCount,
|
||||
sizeOnDisk
|
||||
episodeFileCount = 0,
|
||||
sizeOnDisk = 0
|
||||
} = statistics;
|
||||
|
||||
const deleteFiles = this.state.deleteFiles;
|
||||
@@ -108,16 +108,20 @@ class DeleteSeriesModalContent extends Component {
|
||||
</FormGroup>
|
||||
|
||||
{
|
||||
deleteFiles &&
|
||||
deleteFiles ?
|
||||
<div className={styles.deleteFilesMessage}>
|
||||
<div><InlineMarkdown data={translate('DeleteSeriesFolderConfirmation', { path })} blockClassName={styles.folderPath} /></div>
|
||||
{
|
||||
!!episodeFileCount &&
|
||||
<div>{translate('DeleteSeriesFolderEpisodeCount', { episodeFileCount, size: formatBytes(sizeOnDisk) })}</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
{
|
||||
episodeFileCount ?
|
||||
<div className={styles.deleteCount}>
|
||||
{translate('DeleteSeriesFolderEpisodeCount', { episodeFileCount, size: formatBytes(sizeOnDisk) })}
|
||||
</div> :
|
||||
null
|
||||
}
|
||||
</div> :
|
||||
null
|
||||
}
|
||||
</ModalBody>
|
||||
|
||||
<ModalFooter>
|
||||
|
||||
69
frontend/src/Series/Details/SeasonProgressLabel.tsx
Normal file
69
frontend/src/Series/Details/SeasonProgressLabel.tsx
Normal file
@@ -0,0 +1,69 @@
|
||||
import React from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import Label from 'Components/Label';
|
||||
import { kinds, sizes } from 'Helpers/Props';
|
||||
import createSeriesQueueItemsDetailsSelector, {
|
||||
SeriesQueueDetails,
|
||||
} from 'Series/Index/createSeriesQueueDetailsSelector';
|
||||
|
||||
function getEpisodeCountKind(
|
||||
monitored: boolean,
|
||||
episodeFileCount: number,
|
||||
episodeCount: number,
|
||||
isDownloading: boolean
|
||||
) {
|
||||
if (isDownloading) {
|
||||
return kinds.PURPLE;
|
||||
}
|
||||
|
||||
if (episodeFileCount === episodeCount && episodeCount > 0) {
|
||||
return kinds.SUCCESS;
|
||||
}
|
||||
|
||||
if (!monitored) {
|
||||
return kinds.WARNING;
|
||||
}
|
||||
|
||||
return kinds.DANGER;
|
||||
}
|
||||
|
||||
interface SeasonProgressLabelProps {
|
||||
seriesId: number;
|
||||
seasonNumber: number;
|
||||
monitored: boolean;
|
||||
episodeCount: number;
|
||||
episodeFileCount: number;
|
||||
}
|
||||
|
||||
function SeasonProgressLabel({
|
||||
seriesId,
|
||||
seasonNumber,
|
||||
monitored,
|
||||
episodeCount,
|
||||
episodeFileCount,
|
||||
}: SeasonProgressLabelProps) {
|
||||
const queueDetails: SeriesQueueDetails = useSelector(
|
||||
createSeriesQueueItemsDetailsSelector(seriesId, seasonNumber)
|
||||
);
|
||||
|
||||
const newDownloads = queueDetails.count - queueDetails.episodesWithFiles;
|
||||
const text = newDownloads
|
||||
? `${episodeFileCount} + ${newDownloads} / ${episodeCount}`
|
||||
: `${episodeFileCount} / ${episodeCount}`;
|
||||
|
||||
return (
|
||||
<Label
|
||||
kind={getEpisodeCountKind(
|
||||
monitored,
|
||||
episodeFileCount,
|
||||
episodeCount,
|
||||
queueDetails.count > 0
|
||||
)}
|
||||
size={sizes.LARGE}
|
||||
>
|
||||
<span>{text}</span>
|
||||
</Label>
|
||||
);
|
||||
}
|
||||
|
||||
export default SeasonProgressLabel;
|
||||
@@ -175,6 +175,7 @@ class SeriesDetails extends Component {
|
||||
tvdbId,
|
||||
tvMazeId,
|
||||
imdbId,
|
||||
tmdbId,
|
||||
title,
|
||||
runtime,
|
||||
ratings,
|
||||
@@ -566,6 +567,7 @@ class SeriesDetails extends Component {
|
||||
tvdbId={tvdbId}
|
||||
tvMazeId={tvMazeId}
|
||||
imdbId={imdbId}
|
||||
tmdbId={tmdbId}
|
||||
/>
|
||||
}
|
||||
kind={kinds.INVERSE}
|
||||
@@ -719,6 +721,7 @@ SeriesDetails.propTypes = {
|
||||
tvdbId: PropTypes.number.isRequired,
|
||||
tvMazeId: PropTypes.number,
|
||||
imdbId: PropTypes.string,
|
||||
tmdbId: PropTypes.number,
|
||||
title: PropTypes.string.isRequired,
|
||||
runtime: PropTypes.number.isRequired,
|
||||
ratings: PropTypes.object.isRequired,
|
||||
|
||||
@@ -9,7 +9,8 @@ function SeriesDetailsLinks(props) {
|
||||
const {
|
||||
tvdbId,
|
||||
tvMazeId,
|
||||
imdbId
|
||||
imdbId,
|
||||
tmdbId
|
||||
} = props;
|
||||
|
||||
return (
|
||||
@@ -71,6 +72,22 @@ function SeriesDetailsLinks(props) {
|
||||
</Label>
|
||||
</Link>
|
||||
}
|
||||
|
||||
{
|
||||
!!tmdbId &&
|
||||
<Link
|
||||
className={styles.link}
|
||||
to={`https://www.themoviedb.org/tv/${tmdbId}`}
|
||||
>
|
||||
<Label
|
||||
className={styles.linkLabel}
|
||||
kind={kinds.INFO}
|
||||
size={sizes.LARGE}
|
||||
>
|
||||
TMDB
|
||||
</Label>
|
||||
</Link>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -78,7 +95,8 @@ function SeriesDetailsLinks(props) {
|
||||
SeriesDetailsLinks.propTypes = {
|
||||
tvdbId: PropTypes.number.isRequired,
|
||||
tvMazeId: PropTypes.number,
|
||||
imdbId: PropTypes.string
|
||||
imdbId: PropTypes.string,
|
||||
tmdbId: PropTypes.number
|
||||
};
|
||||
|
||||
export default SeriesDetailsLinks;
|
||||
|
||||
@@ -2,7 +2,6 @@ import _ from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import Icon from 'Components/Icon';
|
||||
import Label from 'Components/Label';
|
||||
import IconButton from 'Components/Link/IconButton';
|
||||
import Link from 'Components/Link/Link';
|
||||
import SpinnerIconButton from 'Components/Link/SpinnerIconButton';
|
||||
@@ -15,7 +14,7 @@ import SpinnerIcon from 'Components/SpinnerIcon';
|
||||
import Table from 'Components/Table/Table';
|
||||
import TableBody from 'Components/Table/TableBody';
|
||||
import Popover from 'Components/Tooltip/Popover';
|
||||
import { align, icons, kinds, sizes, sortDirections, tooltipPositions } from 'Helpers/Props';
|
||||
import { align, icons, sortDirections, tooltipPositions } from 'Helpers/Props';
|
||||
import InteractiveImportModal from 'InteractiveImport/InteractiveImportModal';
|
||||
import OrganizePreviewModalConnector from 'Organize/OrganizePreviewModalConnector';
|
||||
import SeriesHistoryModal from 'Series/History/SeriesHistoryModal';
|
||||
@@ -27,6 +26,7 @@ import translate from 'Utilities/String/translate';
|
||||
import getToggledRange from 'Utilities/Table/getToggledRange';
|
||||
import EpisodeRowConnector from './EpisodeRowConnector';
|
||||
import SeasonInfo from './SeasonInfo';
|
||||
import SeasonProgressLabel from './SeasonProgressLabel';
|
||||
import styles from './SeriesDetailsSeason.css';
|
||||
|
||||
function getSeasonStatistics(episodes) {
|
||||
@@ -64,18 +64,6 @@ function getSeasonStatistics(episodes) {
|
||||
};
|
||||
}
|
||||
|
||||
function getEpisodeCountKind(monitored, episodeFileCount, episodeCount) {
|
||||
if (episodeFileCount === episodeCount && episodeCount > 0) {
|
||||
return kinds.SUCCESS;
|
||||
}
|
||||
|
||||
if (!monitored) {
|
||||
return kinds.WARNING;
|
||||
}
|
||||
|
||||
return kinds.DANGER;
|
||||
}
|
||||
|
||||
class SeriesDetailsSeason extends Component {
|
||||
|
||||
//
|
||||
@@ -265,12 +253,13 @@ class SeriesDetailsSeason extends Component {
|
||||
className={styles.episodeCountTooltip}
|
||||
canFlip={true}
|
||||
anchor={
|
||||
<Label
|
||||
kind={getEpisodeCountKind(monitored, episodeFileCount, episodeCount)}
|
||||
size={sizes.LARGE}
|
||||
>
|
||||
<span>{episodeFileCount} / {episodeCount}</span>
|
||||
</Label>
|
||||
<SeasonProgressLabel
|
||||
seriesId={seriesId}
|
||||
seasonNumber={seasonNumber}
|
||||
monitored={monitored}
|
||||
episodeCount={episodeCount}
|
||||
episodeFileCount={episodeFileCount}
|
||||
/>
|
||||
}
|
||||
title={translate('SeasonInformation')}
|
||||
body={
|
||||
|
||||
@@ -10,4 +10,15 @@
|
||||
.path {
|
||||
margin-left: 5px;
|
||||
color: var(--dangerColor);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.statistics {
|
||||
margin-left: 5px;
|
||||
color: var(--warningColor);
|
||||
}
|
||||
|
||||
.deleteFilesMessage {
|
||||
margin-top: 20px;
|
||||
color: var(--warningColor);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
// This file is automatically generated.
|
||||
// Please do not change this file!
|
||||
interface CssExports {
|
||||
'deleteFilesMessage': string;
|
||||
'message': string;
|
||||
'path': string;
|
||||
'pathContainer': string;
|
||||
'statistics': string;
|
||||
}
|
||||
export const cssExports: CssExports;
|
||||
export default cssExports;
|
||||
|
||||
@@ -16,6 +16,7 @@ import Series from 'Series/Series';
|
||||
import { bulkDeleteSeries, setDeleteOption } from 'Store/Actions/seriesActions';
|
||||
import createAllSeriesSelector from 'Store/Selectors/createAllSeriesSelector';
|
||||
import { CheckInputChanged } from 'typings/inputs';
|
||||
import formatBytes from 'Utilities/Number/formatBytes';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './DeleteSeriesModalContent.css';
|
||||
|
||||
@@ -85,6 +86,23 @@ function DeleteSeriesModalContent(props: DeleteSeriesModalContentProps) {
|
||||
onModalClose,
|
||||
]);
|
||||
|
||||
const { totalEpisodeFileCount, totalSizeOnDisk } = useMemo(() => {
|
||||
return series.reduce(
|
||||
(acc, { statistics = {} }) => {
|
||||
const { episodeFileCount = 0, sizeOnDisk = 0 } = statistics;
|
||||
|
||||
acc.totalEpisodeFileCount += episodeFileCount;
|
||||
acc.totalSizeOnDisk += sizeOnDisk;
|
||||
|
||||
return acc;
|
||||
},
|
||||
{
|
||||
totalEpisodeFileCount: 0,
|
||||
totalSizeOnDisk: 0,
|
||||
}
|
||||
);
|
||||
}, [series]);
|
||||
|
||||
return (
|
||||
<ModalContent onModalClose={onModalClose}>
|
||||
<ModalHeader>{translate('DeleteSelectedSeries')}</ModalHeader>
|
||||
@@ -136,20 +154,44 @@ function DeleteSeriesModalContent(props: DeleteSeriesModalContentProps) {
|
||||
</div>
|
||||
|
||||
<ul>
|
||||
{series.map((s) => {
|
||||
{series.map(({ title, path, statistics = {} }) => {
|
||||
const { episodeFileCount = 0, sizeOnDisk = 0 } = statistics;
|
||||
|
||||
return (
|
||||
<li key={s.title}>
|
||||
<span>{s.title}</span>
|
||||
<li key={title}>
|
||||
<span>{title}</span>
|
||||
|
||||
{deleteFiles && (
|
||||
<span className={styles.pathContainer}>
|
||||
-<span className={styles.path}>{s.path}</span>
|
||||
<span>
|
||||
<span className={styles.pathContainer}>
|
||||
-<span className={styles.path}>{path}</span>
|
||||
</span>
|
||||
|
||||
{!!episodeFileCount && (
|
||||
<span className={styles.statistics}>
|
||||
(
|
||||
{translate('DeleteSeriesFolderEpisodeCount', {
|
||||
episodeFileCount,
|
||||
size: formatBytes(sizeOnDisk),
|
||||
})}
|
||||
)
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
)}
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
|
||||
{deleteFiles && !!totalEpisodeFileCount ? (
|
||||
<div className={styles.deleteFilesMessage}>
|
||||
{translate('DeleteSeriesFolderEpisodeCount', {
|
||||
episodeFileCount: totalEpisodeFileCount,
|
||||
size: formatBytes(totalSizeOnDisk),
|
||||
})}
|
||||
</div>
|
||||
) : null}
|
||||
</ModalBody>
|
||||
|
||||
<ModalFooter>
|
||||
|
||||
@@ -70,6 +70,7 @@ interface Series extends ModelBase {
|
||||
tvdbId: number;
|
||||
tvMazeId: number;
|
||||
tvRageId: number;
|
||||
tmdbId: number;
|
||||
useSceneNumbering: boolean;
|
||||
year: number;
|
||||
isSaving?: boolean;
|
||||
|
||||
@@ -138,7 +138,8 @@ class Naming extends Component {
|
||||
{ key: 1, value: translate('ReplaceWithDash') },
|
||||
{ key: 2, value: translate('ReplaceWithSpaceDash') },
|
||||
{ key: 3, value: translate('ReplaceWithSpaceDashSpace') },
|
||||
{ key: 4, value: translate('SmartReplace'), hint: translate('SmartReplaceHint') }
|
||||
{ key: 4, value: translate('SmartReplace'), hint: translate('SmartReplaceHint') },
|
||||
{ key: 5, value: translate('Custom'), hint: translate('CustomColonReplacementFormatHint') }
|
||||
];
|
||||
|
||||
const standardEpisodeFormatHelpTexts = [];
|
||||
@@ -262,6 +263,22 @@ class Naming extends Component {
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
replaceIllegalCharacters && settings.colonReplacementFormat.value === 5 ?
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('ColonReplacement')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.TEXT}
|
||||
name="customColonReplacementFormat"
|
||||
helpText={translate('CustomColonReplacementFormatHelpText')}
|
||||
onChange={onInputChange}
|
||||
{...settings.customColonReplacementFormat}
|
||||
/>
|
||||
</FormGroup> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
renameEpisodes &&
|
||||
<div>
|
||||
|
||||
@@ -99,6 +99,7 @@ const seriesTokens = [
|
||||
const seriesIdTokens = [
|
||||
{ token: '{ImdbId}', example: 'tt12345' },
|
||||
{ token: '{TvdbId}', example: '12345' },
|
||||
{ token: '{TmdbId}', example: '11223' },
|
||||
{ token: '{TvMazeId}', example: '54321' }
|
||||
];
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import {
|
||||
saveNotification,
|
||||
setNotificationFieldValue,
|
||||
setNotificationFieldValues,
|
||||
setNotificationValue,
|
||||
testNotification,
|
||||
toggleAdvancedSettings
|
||||
@@ -27,7 +27,7 @@ function createMapStateToProps() {
|
||||
|
||||
const mapDispatchToProps = {
|
||||
setNotificationValue,
|
||||
setNotificationFieldValue,
|
||||
setNotificationFieldValues,
|
||||
saveNotification,
|
||||
testNotification,
|
||||
toggleAdvancedSettings
|
||||
@@ -51,8 +51,8 @@ class EditNotificationModalContentConnector extends Component {
|
||||
this.props.setNotificationValue({ name, value });
|
||||
};
|
||||
|
||||
onFieldChange = ({ name, value }) => {
|
||||
this.props.setNotificationFieldValue({ name, value });
|
||||
onFieldChange = ({ name, value, additionalProperties = {} }) => {
|
||||
this.props.setNotificationFieldValues({ properties: { ...additionalProperties, [name]: value } });
|
||||
};
|
||||
|
||||
onSavePress = () => {
|
||||
@@ -91,7 +91,7 @@ EditNotificationModalContentConnector.propTypes = {
|
||||
saveError: PropTypes.object,
|
||||
item: PropTypes.object.isRequired,
|
||||
setNotificationValue: PropTypes.func.isRequired,
|
||||
setNotificationFieldValue: PropTypes.func.isRequired,
|
||||
setNotificationFieldValues: PropTypes.func.isRequired,
|
||||
saveNotification: PropTypes.func.isRequired,
|
||||
testNotification: PropTypes.func.isRequired,
|
||||
toggleAdvancedSettings: PropTypes.func.isRequired,
|
||||
|
||||
@@ -59,6 +59,7 @@ class Notification extends Component {
|
||||
onGrab,
|
||||
onDownload,
|
||||
onUpgrade,
|
||||
onImportComplete,
|
||||
onRename,
|
||||
onSeriesAdd,
|
||||
onSeriesDelete,
|
||||
@@ -71,6 +72,7 @@ class Notification extends Component {
|
||||
supportsOnGrab,
|
||||
supportsOnDownload,
|
||||
supportsOnUpgrade,
|
||||
supportsOnImportComplete,
|
||||
supportsOnRename,
|
||||
supportsOnSeriesAdd,
|
||||
supportsOnSeriesDelete,
|
||||
@@ -105,7 +107,7 @@ class Notification extends Component {
|
||||
{
|
||||
supportsOnDownload && onDownload ?
|
||||
<Label kind={kinds.SUCCESS}>
|
||||
{translate('OnImport')}
|
||||
{translate('OnFileImport')}
|
||||
</Label> :
|
||||
null
|
||||
}
|
||||
@@ -118,6 +120,14 @@ class Notification extends Component {
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
supportsOnImportComplete && onImportComplete ?
|
||||
<Label kind={kinds.SUCCESS}>
|
||||
{translate('OnImportComplete')}
|
||||
</Label> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
supportsOnRename && onRename ?
|
||||
<Label kind={kinds.SUCCESS}>
|
||||
@@ -191,7 +201,7 @@ class Notification extends Component {
|
||||
}
|
||||
|
||||
{
|
||||
!onGrab && !onDownload && !onRename && !onHealthIssue && !onHealthRestored && !onApplicationUpdate && !onSeriesAdd && !onSeriesDelete && !onEpisodeFileDelete && !onManualInteractionRequired ?
|
||||
!onGrab && !onDownload && !onRename && !onImportComplete && !onHealthIssue && !onHealthRestored && !onApplicationUpdate && !onSeriesAdd && !onSeriesDelete && !onEpisodeFileDelete && !onManualInteractionRequired ?
|
||||
<Label
|
||||
kind={kinds.DISABLED}
|
||||
outline={true}
|
||||
@@ -233,6 +243,7 @@ Notification.propTypes = {
|
||||
onGrab: PropTypes.bool.isRequired,
|
||||
onDownload: PropTypes.bool.isRequired,
|
||||
onUpgrade: PropTypes.bool.isRequired,
|
||||
onImportComplete: PropTypes.bool.isRequired,
|
||||
onRename: PropTypes.bool.isRequired,
|
||||
onSeriesAdd: PropTypes.bool.isRequired,
|
||||
onSeriesDelete: PropTypes.bool.isRequired,
|
||||
@@ -244,6 +255,7 @@ Notification.propTypes = {
|
||||
onManualInteractionRequired: PropTypes.bool.isRequired,
|
||||
supportsOnGrab: PropTypes.bool.isRequired,
|
||||
supportsOnDownload: PropTypes.bool.isRequired,
|
||||
supportsOnImportComplete: PropTypes.bool.isRequired,
|
||||
supportsOnSeriesAdd: PropTypes.bool.isRequired,
|
||||
supportsOnSeriesDelete: PropTypes.bool.isRequired,
|
||||
supportsOnEpisodeFileDelete: PropTypes.bool.isRequired,
|
||||
|
||||
@@ -18,6 +18,7 @@ function NotificationEventItems(props) {
|
||||
onGrab,
|
||||
onDownload,
|
||||
onUpgrade,
|
||||
onImportComplete,
|
||||
onRename,
|
||||
onSeriesAdd,
|
||||
onSeriesDelete,
|
||||
@@ -30,6 +31,7 @@ function NotificationEventItems(props) {
|
||||
supportsOnGrab,
|
||||
supportsOnDownload,
|
||||
supportsOnUpgrade,
|
||||
supportsOnImportComplete,
|
||||
supportsOnRename,
|
||||
supportsOnSeriesAdd,
|
||||
supportsOnSeriesDelete,
|
||||
@@ -66,7 +68,7 @@ function NotificationEventItems(props) {
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="onDownload"
|
||||
helpText={translate('OnImport')}
|
||||
helpText={translate('OnFileImport')}
|
||||
isDisabled={!supportsOnDownload.value}
|
||||
{...onDownload}
|
||||
onChange={onInputChange}
|
||||
@@ -87,6 +89,17 @@ function NotificationEventItems(props) {
|
||||
</div>
|
||||
}
|
||||
|
||||
<div>
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="onImportComplete"
|
||||
helpText={translate('OnImportComplete')}
|
||||
isDisabled={!supportsOnImportComplete.value}
|
||||
{...onImportComplete}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import getSectionState from 'Utilities/State/getSectionState';
|
||||
import updateSectionState from 'Utilities/State/updateSectionState';
|
||||
|
||||
function createSetProviderFieldValuesReducer(section) {
|
||||
return (state, { payload }) => {
|
||||
if (section === payload.section) {
|
||||
const { properties } = payload;
|
||||
const newState = getSectionState(state, section);
|
||||
newState.pendingChanges = Object.assign({}, newState.pendingChanges);
|
||||
const fields = Object.assign({}, newState.pendingChanges.fields || {});
|
||||
|
||||
Object.keys(properties).forEach((name) => {
|
||||
fields[name] = properties[name];
|
||||
});
|
||||
|
||||
newState.pendingChanges.fields = fields;
|
||||
|
||||
return updateSectionState(state, section, newState);
|
||||
}
|
||||
|
||||
return state;
|
||||
};
|
||||
}
|
||||
|
||||
export default createSetProviderFieldValuesReducer;
|
||||
@@ -5,6 +5,7 @@ import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHand
|
||||
import createSaveProviderHandler, { createCancelSaveProviderHandler } from 'Store/Actions/Creators/createSaveProviderHandler';
|
||||
import createTestProviderHandler, { createCancelTestProviderHandler } from 'Store/Actions/Creators/createTestProviderHandler';
|
||||
import createSetProviderFieldValueReducer from 'Store/Actions/Creators/Reducers/createSetProviderFieldValueReducer';
|
||||
import createSetProviderFieldValuesReducer from 'Store/Actions/Creators/Reducers/createSetProviderFieldValuesReducer';
|
||||
import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
|
||||
import { createThunk } from 'Store/thunks';
|
||||
import selectProviderSchema from 'Utilities/State/selectProviderSchema';
|
||||
@@ -22,6 +23,7 @@ export const FETCH_NOTIFICATION_SCHEMA = 'settings/notifications/fetchNotificati
|
||||
export const SELECT_NOTIFICATION_SCHEMA = 'settings/notifications/selectNotificationSchema';
|
||||
export const SET_NOTIFICATION_VALUE = 'settings/notifications/setNotificationValue';
|
||||
export const SET_NOTIFICATION_FIELD_VALUE = 'settings/notifications/setNotificationFieldValue';
|
||||
export const SET_NOTIFICATION_FIELD_VALUES = 'settings/notifications/setNotificationFieldValues';
|
||||
export const SAVE_NOTIFICATION = 'settings/notifications/saveNotification';
|
||||
export const CANCEL_SAVE_NOTIFICATION = 'settings/notifications/cancelSaveNotification';
|
||||
export const DELETE_NOTIFICATION = 'settings/notifications/deleteNotification';
|
||||
@@ -55,6 +57,13 @@ export const setNotificationFieldValue = createAction(SET_NOTIFICATION_FIELD_VAL
|
||||
};
|
||||
});
|
||||
|
||||
export const setNotificationFieldValues = createAction(SET_NOTIFICATION_FIELD_VALUES, (payload) => {
|
||||
return {
|
||||
section,
|
||||
...payload
|
||||
};
|
||||
});
|
||||
|
||||
//
|
||||
// Details
|
||||
|
||||
@@ -99,6 +108,7 @@ export default {
|
||||
reducers: {
|
||||
[SET_NOTIFICATION_VALUE]: createSetSettingValueReducer(section),
|
||||
[SET_NOTIFICATION_FIELD_VALUE]: createSetProviderFieldValueReducer(section),
|
||||
[SET_NOTIFICATION_FIELD_VALUES]: createSetProviderFieldValuesReducer(section),
|
||||
|
||||
[SELECT_NOTIFICATION_SCHEMA]: (state, { payload }) => {
|
||||
return selectProviderSchema(state, section, payload, (selectedSchema) => {
|
||||
@@ -106,6 +116,7 @@ export default {
|
||||
selectedSchema.onGrab = selectedSchema.supportsOnGrab;
|
||||
selectedSchema.onDownload = selectedSchema.supportsOnDownload;
|
||||
selectedSchema.onUpgrade = selectedSchema.supportsOnUpgrade;
|
||||
selectedSchema.onImportComplete = selectedSchema.supportsOnImportComplete;
|
||||
selectedSchema.onRename = selectedSchema.supportsOnRename;
|
||||
selectedSchema.onSeriesAdd = selectedSchema.supportsOnSeriesAdd;
|
||||
selectedSchema.onSeriesDelete = selectedSchema.supportsOnSeriesDelete;
|
||||
|
||||
@@ -153,7 +153,11 @@ namespace NzbDrone.Common.Disk
|
||||
{
|
||||
Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs);
|
||||
|
||||
return Directory.EnumerateDirectories(path);
|
||||
return Directory.EnumerateDirectories(path, "*", new EnumerationOptions
|
||||
{
|
||||
AttributesToSkip = FileAttributes.System,
|
||||
IgnoreInaccessible = true
|
||||
});
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetFiles(string path, bool recursive)
|
||||
|
||||
@@ -71,6 +71,10 @@ namespace NzbDrone.Core.Test.Download.CompletedDownloadServiceTests
|
||||
Mocker.GetMock<IProvideImportItemService>()
|
||||
.Setup(s => s.ProvideImportItem(It.IsAny<DownloadClientItem>(), It.IsAny<DownloadClientItem>()))
|
||||
.Returns<DownloadClientItem, DownloadClientItem>((i, p) => i);
|
||||
|
||||
Mocker.GetMock<IEpisodeService>()
|
||||
.Setup(s => s.GetEpisodes(It.IsAny<IEnumerable<int>>()))
|
||||
.Returns(new List<Episode>());
|
||||
}
|
||||
|
||||
private RemoteEpisode BuildRemoteEpisode()
|
||||
@@ -366,7 +370,7 @@ namespace NzbDrone.Core.Test.Download.CompletedDownloadServiceTests
|
||||
Mocker.GetMock<IEventAggregator>()
|
||||
.Verify(v => v.PublishEvent(It.IsAny<DownloadCompletedEvent>()), Times.Never());
|
||||
|
||||
_trackedDownload.State.Should().Be(TrackedDownloadState.ImportPending);
|
||||
_trackedDownload.State.Should().Be(TrackedDownloadState.ImportBlocked);
|
||||
}
|
||||
|
||||
private void AssertImported()
|
||||
|
||||
@@ -608,5 +608,47 @@ namespace NzbDrone.Core.Test.IndexerSearchTests
|
||||
allCriteria.Last().As<SingleEpisodeSearchCriteria>().SeasonNumber.Should().Be(2);
|
||||
allCriteria.Last().As<SingleEpisodeSearchCriteria>().EpisodeNumber.Should().Be(3);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task episode_search_should_include_series_title_when_not_a_direct_title_match()
|
||||
{
|
||||
_xemSeries.Title = "Sonarr's Title";
|
||||
_xemSeries.CleanTitle = "sonarrstitle";
|
||||
|
||||
WithEpisode(1, 12, 2, 3);
|
||||
|
||||
Mocker.GetMock<ISceneMappingService>()
|
||||
.Setup(s => s.FindByTvdbId(It.IsAny<int>()))
|
||||
.Returns(new List<SceneMapping>
|
||||
{
|
||||
new SceneMapping
|
||||
{
|
||||
TvdbId = _xemSeries.TvdbId,
|
||||
SearchTerm = "Sonarrs Title",
|
||||
ParseTerm = _xemSeries.CleanTitle,
|
||||
SeasonNumber = 1,
|
||||
SceneSeasonNumber = 1,
|
||||
SceneOrigin = "tvdb",
|
||||
Type = "ServicesProvider"
|
||||
}
|
||||
});
|
||||
|
||||
var allCriteria = WatchForSearchCriteria();
|
||||
|
||||
await Subject.EpisodeSearch(_xemEpisodes.First(), false, false);
|
||||
|
||||
Mocker.GetMock<ISceneMappingService>()
|
||||
.Verify(v => v.FindByTvdbId(_xemSeries.Id), Times.Once());
|
||||
|
||||
allCriteria.Should().HaveCount(2);
|
||||
|
||||
allCriteria.First().Should().BeOfType<SingleEpisodeSearchCriteria>();
|
||||
allCriteria.First().As<SingleEpisodeSearchCriteria>().SeasonNumber.Should().Be(1);
|
||||
allCriteria.First().As<SingleEpisodeSearchCriteria>().EpisodeNumber.Should().Be(12);
|
||||
|
||||
allCriteria.Last().Should().BeOfType<SingleEpisodeSearchCriteria>();
|
||||
allCriteria.Last().As<SingleEpisodeSearchCriteria>().SeasonNumber.Should().Be(2);
|
||||
allCriteria.Last().As<SingleEpisodeSearchCriteria>().EpisodeNumber.Should().Be(3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
|
||||
|
||||
_singleEpisodeSearchCriteria = new SingleEpisodeSearchCriteria
|
||||
{
|
||||
Series = new Tv.Series { TvRageId = 10, TvdbId = 20, TvMazeId = 30, ImdbId = "t40" },
|
||||
Series = new Tv.Series { TvRageId = 10, TvdbId = 20, TvMazeId = 30, ImdbId = "t40", TmdbId = 50 },
|
||||
SceneTitles = new List<string> { "Monkey Island" },
|
||||
SeasonNumber = 1,
|
||||
EpisodeNumber = 2
|
||||
@@ -44,14 +44,14 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
|
||||
|
||||
_seasonSearchCriteria = new SeasonSearchCriteria
|
||||
{
|
||||
Series = new Tv.Series { TvRageId = 10, TvdbId = 20, TvMazeId = 30, ImdbId = "t40" },
|
||||
Series = new Tv.Series { TvRageId = 10, TvdbId = 20, TvMazeId = 30, ImdbId = "t40", TmdbId = 50 },
|
||||
SceneTitles = new List<string> { "Monkey Island" },
|
||||
SeasonNumber = 1,
|
||||
};
|
||||
|
||||
_animeSearchCriteria = new AnimeEpisodeSearchCriteria()
|
||||
{
|
||||
Series = new Tv.Series { TvRageId = 10, TvdbId = 20, TvMazeId = 30, ImdbId = "t40" },
|
||||
Series = new Tv.Series { TvRageId = 10, TvdbId = 20, TvMazeId = 30, ImdbId = "t40", TmdbId = 50 },
|
||||
SceneTitles = new List<string>() { "Monkey+Island" },
|
||||
AbsoluteEpisodeNumber = 100,
|
||||
SeasonNumber = 5,
|
||||
@@ -60,7 +60,7 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
|
||||
|
||||
_animeSeasonSearchCriteria = new AnimeSeasonSearchCriteria()
|
||||
{
|
||||
Series = new Tv.Series { TvRageId = 10, TvdbId = 20, TvMazeId = 30, ImdbId = "t40" },
|
||||
Series = new Tv.Series { TvRageId = 10, TvdbId = 20, TvMazeId = 30, ImdbId = "t40", TmdbId = 50 },
|
||||
SceneTitles = new List<string> { "Monkey Island" },
|
||||
SeasonNumber = 3,
|
||||
};
|
||||
@@ -268,6 +268,19 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
|
||||
page.Url.Query.Should().Contain("imdbid=t40");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_search_by_tmdb_if_supported()
|
||||
{
|
||||
_capabilities.SupportedTvSearchParameters = new[] { "q", "tmdbid", "season", "ep" };
|
||||
|
||||
var results = Subject.GetSearchRequests(_singleEpisodeSearchCriteria);
|
||||
results.GetTier(0).Should().HaveCount(1);
|
||||
|
||||
var page = results.GetAllTiers().First().First();
|
||||
|
||||
page.Url.Query.Should().Contain("tmdbid=50");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_prefer_search_by_tvdbid_if_rid_supported()
|
||||
{
|
||||
|
||||
@@ -107,7 +107,7 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo
|
||||
[TestCase(10, "", "", "", null, HdrFormat.None)]
|
||||
[TestCase(10, "bt709", "bt709", "", null, HdrFormat.None)]
|
||||
[TestCase(8, "bt2020", "smpte2084", "", null, HdrFormat.None)]
|
||||
[TestCase(10, "bt2020", "bt2020-10", "", null, HdrFormat.Hlg10)]
|
||||
[TestCase(10, "bt2020", "bt2020-10", "", null, HdrFormat.None)]
|
||||
[TestCase(10, "bt2020", "arib-std-b67", "", null, HdrFormat.Hlg10)]
|
||||
[TestCase(10, "bt2020", "smpte2084", "", null, HdrFormat.Pq10)]
|
||||
[TestCase(10, "bt2020", "smpte2084", "FFMpegCore.SideData", null, HdrFormat.Pq10)]
|
||||
|
||||
@@ -34,6 +34,7 @@ namespace NzbDrone.Core.Test.NotificationTests.Xbmc
|
||||
Subject.Definition = new NotificationDefinition();
|
||||
Subject.Definition.Settings = new XbmcSettings
|
||||
{
|
||||
Host = "localhost",
|
||||
UpdateLibrary = true
|
||||
};
|
||||
}
|
||||
@@ -49,6 +50,7 @@ namespace NzbDrone.Core.Test.NotificationTests.Xbmc
|
||||
|
||||
Subject.Definition.Settings = new XbmcSettings
|
||||
{
|
||||
Host = "localhost",
|
||||
UpdateLibrary = true,
|
||||
CleanLibrary = true
|
||||
};
|
||||
@@ -58,6 +60,7 @@ namespace NzbDrone.Core.Test.NotificationTests.Xbmc
|
||||
public void should_not_clean_if_no_episode_was_replaced()
|
||||
{
|
||||
Subject.OnDownload(_downloadMessage);
|
||||
Subject.ProcessQueue();
|
||||
|
||||
Mocker.GetMock<IXbmcService>().Verify(v => v.Clean(It.IsAny<XbmcSettings>()), Times.Never());
|
||||
}
|
||||
@@ -67,6 +70,7 @@ namespace NzbDrone.Core.Test.NotificationTests.Xbmc
|
||||
{
|
||||
GivenOldFiles();
|
||||
Subject.OnDownload(_downloadMessage);
|
||||
Subject.ProcessQueue();
|
||||
|
||||
Mocker.GetMock<IXbmcService>().Verify(v => v.Clean(It.IsAny<XbmcSettings>()), Times.Once());
|
||||
}
|
||||
|
||||
@@ -90,5 +90,18 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
|
||||
Subject.BuildFileName(new List<Episode> { _episode1 }, _series, _episodeFile)
|
||||
.Should().Be(expected);
|
||||
}
|
||||
|
||||
[TestCase("Series: Title", ColonReplacementFormat.Custom, "\ua789", "Series\ua789 Title")]
|
||||
[TestCase("Series: Title", ColonReplacementFormat.Custom, "∶", "Series∶ Title")]
|
||||
public void should_replace_colon_with_custom_format(string seriesName, ColonReplacementFormat replacementFormat, string customFormat, string expected)
|
||||
{
|
||||
_series.Title = seriesName;
|
||||
_namingConfig.StandardEpisodeFormat = "{Series Title}";
|
||||
_namingConfig.ColonReplacementFormat = replacementFormat;
|
||||
_namingConfig.CustomColonReplacementFormat = customFormat;
|
||||
|
||||
Subject.BuildFileName(new List<Episode> { _episode1 }, _series, _episodeFile)
|
||||
.Should().Be(expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,5 +56,14 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
|
||||
Subject.GetSeriesFolder(_series)
|
||||
.Should().Be($"Series Title ({_series.TvMazeId})");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_add_tmdb_id()
|
||||
{
|
||||
_namingConfig.SeriesFolderFormat = "{Series Title} ({TmdbId})";
|
||||
|
||||
Subject.GetSeriesFolder(_series)
|
||||
.Should().Be($"Series Title ({_series.TmdbId})");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,13 @@ namespace NzbDrone.Core.Test.ParserTests
|
||||
ExceptionVerification.IgnoreWarns();
|
||||
}
|
||||
|
||||
[TestCase("علم نف) أ.دعادل الأبيض ٢٠٢٤ ٣ ٣")]
|
||||
[TestCase("ror-240618_1007-1022-")]
|
||||
public void should_parse_unknown_formats_without_error(string title)
|
||||
{
|
||||
Parser.Parser.ParseTitle(title).Should().NotBeNull();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_parse_md5()
|
||||
{
|
||||
|
||||
@@ -64,6 +64,7 @@ namespace NzbDrone.Core.Test.ParserTests
|
||||
[TestCase("Title.S01.720p.VFF.WEB-DL.AAC2.0.H.264-BTN")]
|
||||
[TestCase("Title.S01.720p.VFQ.WEB-DL.AAC2.0.H.264-BTN")]
|
||||
[TestCase("Title.S01.720p.TRUEFRENCH.WEB-DL.AAC2.0.H.264-BTN")]
|
||||
[TestCase("Series In The Middle S01 Multi VFI VO 1080p WEB x265 HEVC AAC 5.1-Papaya")]
|
||||
public void should_parse_language_french(string postTitle)
|
||||
{
|
||||
var result = LanguageParser.ParseLanguages(postTitle);
|
||||
|
||||
@@ -254,6 +254,7 @@ namespace NzbDrone.Core.Test.ParserTests
|
||||
[TestCase("Series Title Season 2 (WEB 1080p HEVC Opus) [Netaro]", false)]
|
||||
[TestCase("Series.Title.S01E01.Erste.Begegnungen.German.DD51.Synced.DL.1080p.HBOMaxHD.AVC-TVS", false)]
|
||||
[TestCase("Series.Title.S01E05.Tavora.greift.an.German.DL.1080p.DisneyHD.h264-4SF", false)]
|
||||
[TestCase("Series.Title.S02E04.German.Dubbed.DL.AAC.1080p.WEB.AVC-GROUP", false)]
|
||||
public void should_parse_webdl1080p_quality(string title, bool proper)
|
||||
{
|
||||
ParseAndVerifyQuality(title, Quality.WEBDL1080p, proper);
|
||||
@@ -279,6 +280,7 @@ namespace NzbDrone.Core.Test.ParserTests
|
||||
[TestCase("[HorribleSubs] Series Title! S01 [Web][MKV][h264][2160p][AAC 2.0][Softsubs (HorribleSubs)]", false)]
|
||||
[TestCase("Series Title S02 2013 WEB-DL 4k H265 AAC 2Audio-HDSWEB", false)]
|
||||
[TestCase("Series.Title.S02E02.This.Year.Will.Be.Different.2160p.WEB.H.265", false)]
|
||||
[TestCase("Series.Title.S02E04.German.Dubbed.DL.AAC.2160p.DV.HDR.WEB.HEVC-GROUP", false)]
|
||||
public void should_parse_webdl2160p_quality(string title, bool proper)
|
||||
{
|
||||
ParseAndVerifyQuality(title, Quality.WEBDL2160p, proper);
|
||||
|
||||
@@ -33,6 +33,9 @@ namespace NzbDrone.Core.Test.ParserTests
|
||||
[TestCase("Series No More S01 2023 1080p WEB-DL AVC AC3 2.0 Dual Audio -ZR-", "Series No More", 1)]
|
||||
[TestCase("Series Title / S1E1-8 of 8 [2024, WEB-DL 1080p] + Original + RUS", "Series Title", 1)]
|
||||
[TestCase("Series Title / S2E1-16 of 16 [2022, WEB-DL] RUS", "Series Title", 2)]
|
||||
[TestCase("[hchcsen] Mobile Series 00 S01 [BD Remux Dual Audio 1080p AVC 2xFLAC] (Kidou Senshi Gundam 00 Season 1)", "Mobile Series 00", 1)]
|
||||
[TestCase("[HorribleRips] Mobile Series 00 S1 [1080p]", "Mobile Series 00", 1)]
|
||||
[TestCase("[Zoombie] Zom 100: Bucket List of the Dead S01 [Web][MKV][h265 10-bit][1080p][AC3 2.0][Softsubs (Zoombie)]", "Zom 100: Bucket List of the Dead", 1)]
|
||||
public void should_parse_full_season_release(string postTitle, string title, int season)
|
||||
{
|
||||
var result = Parser.Parser.ParseTitle(postTitle);
|
||||
|
||||
@@ -168,6 +168,10 @@ namespace NzbDrone.Core.Test.ParserTests
|
||||
[TestCase("Босх: Спадок / Series: Legacy / S2E1 of 10 (2023) WEB-DL 1080p Ukr/Eng | sub Eng", "Series: Legacy", 2, 1)]
|
||||
[TestCase("Titles.s06e01.1999.BDRip.1080p.Ukr.Eng.AC3.Hurtom.TNU.Tenax555", "Titles", 6, 1)]
|
||||
[TestCase("Titles.s06.01.1999.BDRip.1080p.Ukr.Eng.AC3.Hurtom.TNU.Tenax555", "Titles", 6, 1)]
|
||||
[TestCase("[Judas] Series Title (2024) - S01E14", "Series Title (2024)", 1, 14)]
|
||||
[TestCase("[ReleaseGroup] SeriesTitle S01E1 Webdl 1080p", "SeriesTitle", 1, 1)]
|
||||
[TestCase("[SubsPlus+] Series no Chill - S02E01 (NF WEB 1080p AVC AAC)", "Series no Chill", 2, 1)]
|
||||
[TestCase("[SubsPlus+] Series no Chill - S02E01v2 (NF WEB 1080p AVC AAC)", "Series no Chill", 2, 1)]
|
||||
|
||||
// [TestCase("", "", 0, 0)]
|
||||
public void should_parse_single_episode(string postTitle, string title, int seasonNumber, int episodeNumber)
|
||||
|
||||
@@ -23,6 +23,7 @@ namespace NzbDrone.Core.Test.ParserTests
|
||||
[TestCase("[www.test-hyphen.ca] - Series (2011) S01", "Series (2011)")]
|
||||
[TestCase("test123.ca - Series Time S02 720p HDTV x264 CRON", "Series Time")]
|
||||
[TestCase("[www.test-hyphen123.co.za] - Series Title S01E01", "Series Title")]
|
||||
[TestCase("(seriesawake.com) Series Super - 57 [720p] [English Subbed]", "Series Super")]
|
||||
|
||||
public void should_not_parse_url_in_name(string postTitle, string title)
|
||||
{
|
||||
|
||||
@@ -44,6 +44,7 @@ namespace NzbDrone.Core.Test.QueueTests
|
||||
|
||||
_trackedDownloads = Builder<TrackedDownload>.CreateListOfSize(1)
|
||||
.All()
|
||||
.With(v => v.IsTrackable = true)
|
||||
.With(v => v.DownloadItem = downloadItem)
|
||||
.With(v => v.RemoteEpisode = remoteEpisode)
|
||||
.Build()
|
||||
|
||||
@@ -137,6 +137,20 @@ namespace NzbDrone.Core.Test.TvTests
|
||||
.Verify(v => v.UpdateSeries(It.Is<Series>(s => s.TvMazeId == newSeriesInfo.TvMazeId), It.IsAny<bool>(), It.IsAny<bool>()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_update_tmdb_id_if_changed()
|
||||
{
|
||||
var newSeriesInfo = _series.JsonClone();
|
||||
newSeriesInfo.TmdbId = _series.TmdbId + 1;
|
||||
|
||||
GivenNewSeriesInfo(newSeriesInfo);
|
||||
|
||||
Subject.Execute(new RefreshSeriesCommand(new List<int> { _series.Id }));
|
||||
|
||||
Mocker.GetMock<ISeriesService>()
|
||||
.Verify(v => v.UpdateSeries(It.Is<Series>(s => s.TmdbId == newSeriesInfo.TmdbId), It.IsAny<bool>(), It.IsAny<bool>()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_log_error_if_tvdb_id_not_found()
|
||||
{
|
||||
|
||||
@@ -5,6 +5,7 @@ using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.AutoTagging;
|
||||
using NzbDrone.Core.Organizer;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Tv;
|
||||
@@ -28,6 +29,10 @@ namespace NzbDrone.Core.Test.TvTests.SeriesServiceTests
|
||||
.With(s => s.Path = @"C:\Test\name".AsOsAgnostic())
|
||||
.With(s => s.RootFolderPath = "")
|
||||
.Build().ToList();
|
||||
|
||||
Mocker.GetMock<IAutoTaggingService>()
|
||||
.Setup(s => s.GetTagChanges(It.IsAny<Series>()))
|
||||
.Returns(new AutoTaggingChanges());
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -79,5 +84,23 @@ namespace NzbDrone.Core.Test.TvTests.SeriesServiceTests
|
||||
|
||||
Subject.UpdateSeries(series, false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_add_and_remove_tags()
|
||||
{
|
||||
_series[0].Tags = new HashSet<int> { 1, 2 };
|
||||
|
||||
Mocker.GetMock<IAutoTaggingService>()
|
||||
.Setup(s => s.GetTagChanges(_series[0]))
|
||||
.Returns(new AutoTaggingChanges
|
||||
{
|
||||
TagsToAdd = new HashSet<int> { 3 },
|
||||
TagsToRemove = new HashSet<int> { 1 }
|
||||
});
|
||||
|
||||
var result = Subject.UpdateSeries(_series, false);
|
||||
|
||||
result[0].Tags.Should().BeEquivalentTo(new[] { 2, 3 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.AutoTagging;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
@@ -31,6 +33,14 @@ namespace NzbDrone.Core.Test.TvTests.SeriesServiceTests
|
||||
new Season { SeasonNumber = 1, Monitored = true },
|
||||
new Season { SeasonNumber = 2, Monitored = true }
|
||||
};
|
||||
|
||||
Mocker.GetMock<IAutoTaggingService>()
|
||||
.Setup(s => s.GetTagChanges(It.IsAny<Series>()))
|
||||
.Returns(new AutoTaggingChanges());
|
||||
|
||||
Mocker.GetMock<ISeriesRepository>()
|
||||
.Setup(s => s.Update(It.IsAny<Series>()))
|
||||
.Returns<Series>(r => r);
|
||||
}
|
||||
|
||||
private void GivenExistingSeries()
|
||||
@@ -68,5 +78,28 @@ namespace NzbDrone.Core.Test.TvTests.SeriesServiceTests
|
||||
Mocker.GetMock<IEpisodeService>()
|
||||
.Verify(v => v.SetEpisodeMonitoredBySeason(_fakeSeries.Id, It.IsAny<int>(), It.IsAny<bool>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_add_and_remove_tags()
|
||||
{
|
||||
GivenExistingSeries();
|
||||
var seasonNumber = 1;
|
||||
var monitored = false;
|
||||
|
||||
_fakeSeries.Tags = new HashSet<int> { 1, 2 };
|
||||
_fakeSeries.Seasons.Single(s => s.SeasonNumber == seasonNumber).Monitored = monitored;
|
||||
|
||||
Mocker.GetMock<IAutoTaggingService>()
|
||||
.Setup(s => s.GetTagChanges(_fakeSeries))
|
||||
.Returns(new AutoTaggingChanges
|
||||
{
|
||||
TagsToAdd = new HashSet<int> { 3 },
|
||||
TagsToRemove = new HashSet<int> { 1 }
|
||||
});
|
||||
|
||||
var result = Subject.UpdateSeries(_fakeSeries);
|
||||
|
||||
result.Tags.Should().BeEquivalentTo(new[] { 2, 3 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,11 +48,11 @@ namespace NzbDrone.Core.Test.UpdateTests
|
||||
{
|
||||
const string branch = "main";
|
||||
UseRealHttp();
|
||||
var recent = Subject.GetRecentUpdates(branch, new Version(3, 0), null);
|
||||
var recent = Subject.GetRecentUpdates(branch, new Version(4, 0), null);
|
||||
|
||||
recent.Should().NotBeEmpty();
|
||||
recent.Should().OnlyContain(c => c.Hash.IsNotNullOrWhiteSpace());
|
||||
recent.Should().OnlyContain(c => c.FileName.Contains($"Sonarr.{c.Branch}.3."));
|
||||
recent.Should().OnlyContain(c => c.FileName.Contains($"Sonarr.{c.Branch}.4."));
|
||||
recent.Should().OnlyContain(c => c.ReleaseDate.Year >= 2014);
|
||||
recent.Where(c => c.Changes != null).Should().OnlyContain(c => c.Changes.New != null);
|
||||
recent.Where(c => c.Changes != null).Should().OnlyContain(c => c.Changes.Fixed != null);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace NzbDrone.Core.Annotations
|
||||
@@ -59,13 +60,27 @@ namespace NzbDrone.Core.Annotations
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class FieldSelectOption
|
||||
public class FieldSelectOption<T>
|
||||
where T : struct
|
||||
{
|
||||
public int Value { get; set; }
|
||||
public T Value { get; set; }
|
||||
public string Name { get; set; }
|
||||
public int Order { get; set; }
|
||||
public string Hint { get; set; }
|
||||
public int? ParentValue { get; set; }
|
||||
public T? ParentValue { get; set; }
|
||||
public bool? IsDisabled { get; set; }
|
||||
public Dictionary<string, object> AdditionalProperties { get; set; }
|
||||
}
|
||||
|
||||
public class FieldSelectStringOption
|
||||
{
|
||||
public string Value { get; set; }
|
||||
public string Name { get; set; }
|
||||
public int Order { get; set; }
|
||||
public string Hint { get; set; }
|
||||
public string ParentValue { get; set; }
|
||||
public bool? IsDisabled { get; set; }
|
||||
public Dictionary<string, object> AdditionalProperties { get; set; }
|
||||
}
|
||||
|
||||
public enum FieldType
|
||||
|
||||
@@ -419,13 +419,21 @@ namespace NzbDrone.Core.Configuration
|
||||
throw new InvalidConfigFileException($"{_configFile} is corrupt. Please delete the config file and Sonarr will recreate it.");
|
||||
}
|
||||
|
||||
return XDocument.Parse(_diskProvider.ReadAllText(_configFile));
|
||||
var xDoc = XDocument.Parse(_diskProvider.ReadAllText(_configFile));
|
||||
var config = xDoc.Descendants(CONFIG_ELEMENT_NAME).ToList();
|
||||
|
||||
if (config.Count != 1)
|
||||
{
|
||||
throw new InvalidConfigFileException($"{_configFile} is invalid. Please delete the config file and Sonarr will recreate it.");
|
||||
}
|
||||
|
||||
return xDoc;
|
||||
}
|
||||
|
||||
var xDoc = new XDocument(new XDeclaration("1.0", "utf-8", "yes"));
|
||||
xDoc.Add(new XElement(CONFIG_ELEMENT_NAME));
|
||||
var newXDoc = new XDocument(new XDeclaration("1.0", "utf-8", "yes"));
|
||||
newXDoc.Add(new XElement(CONFIG_ELEMENT_NAME));
|
||||
|
||||
return xDoc;
|
||||
return newXDoc;
|
||||
}
|
||||
}
|
||||
catch (XmlException ex)
|
||||
|
||||
15
src/NzbDrone.Core/Datastore/Migration/206_add_tmdbid.cs
Normal file
15
src/NzbDrone.Core/Datastore/Migration/206_add_tmdbid.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using FluentMigrator;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(206)]
|
||||
public class add_tmdbid : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Alter.Table("Series").AddColumn("TmdbId").AsInt32().WithDefaultValue(0);
|
||||
Create.Index().OnTable("Series").OnColumn("TmdbId");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using FluentMigrator;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(209)]
|
||||
public class add_on_import_complete_to_notifications : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Alter.Table("Notifications").AddColumn("OnImportComplete").AsBoolean().WithDefaultValue(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using FluentMigrator;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(211)]
|
||||
public class add_custom_colon_replacement_to_naming_config : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Alter.Table("NamingConfig").AddColumn("CustomColonReplacementFormat").AsString().WithDefaultValue("");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,6 +89,7 @@ namespace NzbDrone.Core.Datastore
|
||||
.Ignore(x => x.ImplementationName)
|
||||
.Ignore(i => i.SupportsOnGrab)
|
||||
.Ignore(i => i.SupportsOnDownload)
|
||||
.Ignore(i => i.SupportsOnImportComplete)
|
||||
.Ignore(i => i.SupportsOnUpgrade)
|
||||
.Ignore(i => i.SupportsOnRename)
|
||||
.Ignore(i => i.SupportsOnSeriesAdd)
|
||||
|
||||
@@ -25,6 +25,11 @@ namespace NzbDrone.Core.Download.Aggregation
|
||||
|
||||
public RemoteEpisode Augment(RemoteEpisode remoteEpisode)
|
||||
{
|
||||
if (remoteEpisode == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach (var augmenter in _augmenters)
|
||||
{
|
||||
try
|
||||
|
||||
@@ -124,14 +124,23 @@ namespace NzbDrone.Core.Download.Clients.Deluge
|
||||
}
|
||||
|
||||
var items = new List<DownloadClientItem>();
|
||||
var ignoredCount = 0;
|
||||
|
||||
foreach (var torrent in torrents)
|
||||
{
|
||||
if (torrent.Hash == null)
|
||||
// Silently ignore torrents with no hash
|
||||
if (torrent.Hash.IsNullOrWhiteSpace())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore torrents without a name, but track to log a single warning for all invalid torrents.
|
||||
if (torrent.Name.IsNullOrWhiteSpace())
|
||||
{
|
||||
ignoredCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
var item = new DownloadClientItem();
|
||||
item.DownloadId = torrent.Hash.ToUpper();
|
||||
item.Title = torrent.Name;
|
||||
@@ -189,6 +198,11 @@ namespace NzbDrone.Core.Download.Clients.Deluge
|
||||
items.Add(item);
|
||||
}
|
||||
|
||||
if (ignoredCount > 0)
|
||||
{
|
||||
_logger.Warn("{0} torrent(s) were ignored becuase they did not have a title, check Deluge and remove any invalid torrents");
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@ namespace NzbDrone.Core.Download
|
||||
private readonly IParsingService _parsingService;
|
||||
private readonly ISeriesService _seriesService;
|
||||
private readonly ITrackedDownloadAlreadyImported _trackedDownloadAlreadyImported;
|
||||
private readonly IEpisodeService _episodeService;
|
||||
private readonly IMediaFileService _mediaFileService;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public CompletedDownloadService(IEventAggregator eventAggregator,
|
||||
@@ -43,6 +45,8 @@ namespace NzbDrone.Core.Download
|
||||
IParsingService parsingService,
|
||||
ISeriesService seriesService,
|
||||
ITrackedDownloadAlreadyImported trackedDownloadAlreadyImported,
|
||||
IEpisodeService episodeService,
|
||||
IMediaFileService mediaFileService,
|
||||
Logger logger)
|
||||
{
|
||||
_eventAggregator = eventAggregator;
|
||||
@@ -52,6 +56,8 @@ namespace NzbDrone.Core.Download
|
||||
_parsingService = parsingService;
|
||||
_seriesService = seriesService;
|
||||
_trackedDownloadAlreadyImported = trackedDownloadAlreadyImported;
|
||||
_episodeService = episodeService;
|
||||
_mediaFileService = mediaFileService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
@@ -64,8 +70,8 @@ namespace NzbDrone.Core.Download
|
||||
|
||||
SetImportItem(trackedDownload);
|
||||
|
||||
// Only process tracked downloads that are still downloading
|
||||
if (trackedDownload.State != TrackedDownloadState.Downloading)
|
||||
// Only process tracked downloads that are still downloading or have been blocked for importing due to an issue with matching
|
||||
if (trackedDownload.State != TrackedDownloadState.Downloading && trackedDownload.State != TrackedDownloadState.ImportBlocked)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -96,7 +102,7 @@ namespace NzbDrone.Core.Download
|
||||
if (series == null)
|
||||
{
|
||||
trackedDownload.Warn("Series title mismatch; automatic import is not possible. Check the download troubleshooting entry on the wiki for common causes.");
|
||||
SendManualInteractionRequiredNotification(trackedDownload);
|
||||
SetStateToImportBlocked(trackedDownload);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -108,7 +114,7 @@ namespace NzbDrone.Core.Download
|
||||
if (seriesMatchType == SeriesMatchType.Id && releaseSource != ReleaseSourceType.InteractiveSearch)
|
||||
{
|
||||
trackedDownload.Warn("Found matching series via grab history, but release was matched to series by ID. Automatic import is not possible. See the FAQ for details.");
|
||||
SendManualInteractionRequiredNotification(trackedDownload);
|
||||
SetStateToImportBlocked(trackedDownload);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -129,7 +135,7 @@ namespace NzbDrone.Core.Download
|
||||
if (trackedDownload.RemoteEpisode == null)
|
||||
{
|
||||
trackedDownload.Warn("Unable to parse download, automatic import is not possible.");
|
||||
SendManualInteractionRequiredNotification(trackedDownload);
|
||||
SetStateToImportBlocked(trackedDownload);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -187,7 +193,7 @@ namespace NzbDrone.Core.Download
|
||||
if (statusMessages.Any())
|
||||
{
|
||||
trackedDownload.Warn(statusMessages.ToArray());
|
||||
SendManualInteractionRequiredNotification(trackedDownload);
|
||||
SetStateToImportBlocked(trackedDownload);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,11 +204,23 @@ namespace NzbDrone.Core.Download
|
||||
.Count() >= Math.Max(1,
|
||||
trackedDownload.RemoteEpisode.Episodes.Count);
|
||||
|
||||
var historyItems = _historyService.FindByDownloadId(trackedDownload.DownloadItem.DownloadId)
|
||||
.OrderByDescending(h => h.Date)
|
||||
.ToList();
|
||||
|
||||
var grabbedHistory = historyItems.Where(h => h.EventType == EpisodeHistoryEventType.Grabbed).ToList();
|
||||
var releaseInfo = grabbedHistory.Count > 0 ? new GrabbedReleaseInfo(grabbedHistory) : null;
|
||||
|
||||
if (allEpisodesImported)
|
||||
{
|
||||
_logger.Debug("All episodes were imported for {0}", trackedDownload.DownloadItem.Title);
|
||||
trackedDownload.State = TrackedDownloadState.Imported;
|
||||
_eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload, trackedDownload.RemoteEpisode.Series.Id));
|
||||
|
||||
_eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload,
|
||||
trackedDownload.RemoteEpisode.Series.Id,
|
||||
importResults.Where(c => c.Result == ImportResultType.Imported).Select(c => c.EpisodeFile).ToList(),
|
||||
releaseInfo));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -216,12 +234,9 @@ namespace NzbDrone.Core.Download
|
||||
// safe, but commenting for future benefit.
|
||||
|
||||
var atLeastOneEpisodeImported = importResults.Any(c => c.Result == ImportResultType.Imported);
|
||||
|
||||
var historyItems = _historyService.FindByDownloadId(trackedDownload.DownloadItem.DownloadId)
|
||||
.OrderByDescending(h => h.Date)
|
||||
.ToList();
|
||||
|
||||
var allEpisodesImportedInHistory = _trackedDownloadAlreadyImported.IsImported(trackedDownload, historyItems);
|
||||
var episodes = _episodeService.GetEpisodes(trackedDownload.RemoteEpisode.Episodes.Select(e => e.Id));
|
||||
var files = _mediaFileService.GetFiles(episodes.Select(e => e.EpisodeFileId).Distinct());
|
||||
|
||||
if (allEpisodesImportedInHistory)
|
||||
{
|
||||
@@ -245,7 +260,7 @@ namespace NzbDrone.Core.Download
|
||||
}
|
||||
|
||||
trackedDownload.State = TrackedDownloadState.Imported;
|
||||
_eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload, trackedDownload.RemoteEpisode.Series.Id));
|
||||
_eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload, trackedDownload.RemoteEpisode.Series.Id, files, releaseInfo));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -254,8 +269,10 @@ namespace NzbDrone.Core.Download
|
||||
return false;
|
||||
}
|
||||
|
||||
private void SendManualInteractionRequiredNotification(TrackedDownload trackedDownload)
|
||||
private void SetStateToImportBlocked(TrackedDownload trackedDownload)
|
||||
{
|
||||
trackedDownload.State = TrackedDownloadState.ImportBlocked;
|
||||
|
||||
if (!trackedDownload.HasNotifiedManualInteractionRequired)
|
||||
{
|
||||
var grabbedHistories = _historyService.FindByDownloadId(trackedDownload.DownloadItem.DownloadId).Where(h => h.EventType == EpisodeHistoryEventType.Grabbed).ToList();
|
||||
|
||||
@@ -1,17 +1,24 @@
|
||||
using NzbDrone.Common.Messaging;
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Common.Messaging;
|
||||
using NzbDrone.Core.Download.TrackedDownloads;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.Download
|
||||
{
|
||||
public class DownloadCompletedEvent : IEvent
|
||||
{
|
||||
public TrackedDownload TrackedDownload { get; private set; }
|
||||
public int SeriesId { get; set; }
|
||||
public int SeriesId { get; private set; }
|
||||
public List<EpisodeFile> EpisodeFiles { get; private set; }
|
||||
public GrabbedReleaseInfo Release { get; private set; }
|
||||
|
||||
public DownloadCompletedEvent(TrackedDownload trackedDownload, int seriesId)
|
||||
public DownloadCompletedEvent(TrackedDownload trackedDownload, int seriesId, List<EpisodeFile> episodeFiles, GrabbedReleaseInfo release)
|
||||
{
|
||||
TrackedDownload = trackedDownload;
|
||||
SeriesId = seriesId;
|
||||
EpisodeFiles = episodeFiles;
|
||||
Release = release;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,8 +73,8 @@ namespace NzbDrone.Core.Download
|
||||
|
||||
public void Check(TrackedDownload trackedDownload)
|
||||
{
|
||||
// Only process tracked downloads that are still downloading
|
||||
if (trackedDownload.State != TrackedDownloadState.Downloading)
|
||||
// Only process tracked downloads that are still downloading or import is blocked (if they fail after attempting to be processed)
|
||||
if (trackedDownload.State != TrackedDownloadState.Downloading && trackedDownload.State != TrackedDownloadState.ImportBlocked)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ namespace NzbDrone.Core.Download.TrackedDownloads
|
||||
_trackedDownloadService.TrackDownload((DownloadClientDefinition)downloadClient.Definition,
|
||||
downloadItem);
|
||||
|
||||
if (trackedDownload != null && trackedDownload.State == TrackedDownloadState.Downloading)
|
||||
if (trackedDownload is { State: TrackedDownloadState.Downloading or TrackedDownloadState.ImportBlocked })
|
||||
{
|
||||
_failedDownloadService.Check(trackedDownload);
|
||||
_completedDownloadService.Check(trackedDownload);
|
||||
|
||||
@@ -40,6 +40,7 @@ namespace NzbDrone.Core.Download.TrackedDownloads
|
||||
public enum TrackedDownloadState
|
||||
{
|
||||
Downloading,
|
||||
ImportBlocked,
|
||||
ImportPending,
|
||||
Importing,
|
||||
Imported,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
|
||||
@@ -28,6 +28,7 @@ namespace NzbDrone.Core.Download.TrackedDownloads
|
||||
|
||||
public class TrackedDownloadService : ITrackedDownloadService,
|
||||
IHandle<EpisodeInfoRefreshedEvent>,
|
||||
IHandle<SeriesAddedEvent>,
|
||||
IHandle<SeriesDeletedEvent>
|
||||
{
|
||||
private readonly IParsingService _parsingService;
|
||||
@@ -278,12 +279,29 @@ namespace NzbDrone.Core.Download.TrackedDownloads
|
||||
}
|
||||
}
|
||||
|
||||
public void Handle(SeriesAddedEvent message)
|
||||
{
|
||||
var cachedItems = _cache.Values
|
||||
.Where(t =>
|
||||
t.RemoteEpisode?.Series == null ||
|
||||
message.Series?.TvdbId == t.RemoteEpisode.Series.TvdbId)
|
||||
.ToList();
|
||||
|
||||
if (cachedItems.Any())
|
||||
{
|
||||
cachedItems.ForEach(UpdateCachedItem);
|
||||
|
||||
_eventAggregator.PublishEvent(new TrackedDownloadRefreshedEvent(GetTrackedDownloads()));
|
||||
}
|
||||
}
|
||||
|
||||
public void Handle(SeriesDeletedEvent message)
|
||||
{
|
||||
var cachedItems = _cache.Values.Where(t =>
|
||||
t.RemoteEpisode?.Series != null &&
|
||||
message.Series.Any(s => s.Id == t.RemoteEpisode.Series.Id))
|
||||
.ToList();
|
||||
var cachedItems = _cache.Values
|
||||
.Where(t =>
|
||||
t.RemoteEpisode?.Series != null &&
|
||||
message.Series.Any(s => s.Id == t.RemoteEpisode.Series.Id || s.TvdbId == t.RemoteEpisode.Series.TvdbId))
|
||||
.ToList();
|
||||
|
||||
if (cachedItems.Any())
|
||||
{
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Common.Messaging;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.Download
|
||||
{
|
||||
public class UntrackedDownloadCompletedEvent : IEvent
|
||||
{
|
||||
public Series Series { get; private set; }
|
||||
public List<Episode> Episodes { get; private set; }
|
||||
public List<EpisodeFile> EpisodeFiles { get; private set; }
|
||||
public ParsedEpisodeInfo ParsedEpisodeInfo { get; private set; }
|
||||
public string SourcePath { get; private set; }
|
||||
|
||||
public UntrackedDownloadCompletedEvent(Series series, List<Episode> episodes, List<EpisodeFile> episodeFiles, ParsedEpisodeInfo parsedEpisodeInfo, string sourcePath)
|
||||
{
|
||||
Series = series;
|
||||
Episodes = episodes;
|
||||
EpisodeFiles = episodeFiles;
|
||||
ParsedEpisodeInfo = parsedEpisodeInfo;
|
||||
SourcePath = sourcePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,7 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
|
||||
Tvdb = series.TvdbId.ToString();
|
||||
TvMaze = series.TvMazeId > 0 ? series.TvMazeId.ToString() : null;
|
||||
TvRage = series.TvRageId > 0 ? series.TvMazeId.ToString() : null;
|
||||
Tmdb = series.TmdbId > 0 ? series.TmdbId.ToString() : null;
|
||||
Imdb = series.ImdbId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,26 @@
|
||||
using NzbDrone.Core.Instrumentation;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Instrumentation;
|
||||
|
||||
namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
{
|
||||
public class TrimLogDatabase : IHousekeepingTask
|
||||
{
|
||||
private readonly ILogRepository _logRepo;
|
||||
private readonly IConfigFileProvider _configFileProvider;
|
||||
|
||||
public TrimLogDatabase(ILogRepository logRepo)
|
||||
public TrimLogDatabase(ILogRepository logRepo, IConfigFileProvider configFileProvider)
|
||||
{
|
||||
_logRepo = logRepo;
|
||||
_configFileProvider = configFileProvider;
|
||||
}
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
if (!_configFileProvider.LogDbEnabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_logRepo.Trim();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ namespace NzbDrone.Core.ImportLists.Custom
|
||||
{
|
||||
public class CustomSeries
|
||||
{
|
||||
public string Title { get; set; }
|
||||
public int TvdbId { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ namespace NzbDrone.Core.ImportLists.Custom
|
||||
{
|
||||
series.Add(new ImportListItemInfo
|
||||
{
|
||||
Title = item.Title.IsNullOrWhiteSpace() ? $"TvdbId: {item.TvdbId}" : item.Title,
|
||||
TvdbId = item.TvdbId
|
||||
});
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace NzbDrone.Core.ImportLists.Imdb
|
||||
// Parse TSV response from IMDB export
|
||||
var rows = importResponse.Content.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
series = rows.Skip(1).SelectList(m => m.Split(',')).Where(m => m.Length > 1).SelectList(i => new ImportListItemInfo { ImdbId = i[1] });
|
||||
series = rows.Skip(1).SelectList(m => m.Split(',')).Where(m => m.Length > 5).SelectList(i => new ImportListItemInfo { ImdbId = i[1], Title = i[5] });
|
||||
|
||||
return series;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace NzbDrone.Core.IndexerSearch.Definitions
|
||||
public virtual bool UserInvokedSearch { get; set; }
|
||||
public virtual bool InteractiveSearch { get; set; }
|
||||
|
||||
public List<string> AllSceneTitles => SceneTitles.Concat(CleanSceneTitles).Distinct().ToList();
|
||||
public List<string> CleanSceneTitles => SceneTitles.Select(GetCleanSceneTitle).Distinct().ToList();
|
||||
|
||||
public static string GetCleanSceneTitle(string title)
|
||||
|
||||
@@ -265,7 +265,7 @@ namespace NzbDrone.Core.IndexerSearch
|
||||
}
|
||||
}
|
||||
|
||||
if (sceneMapping.ParseTerm == series.CleanTitle && sceneMapping.FilterRegex.IsNullOrWhiteSpace())
|
||||
if (sceneMapping.SearchTerm == series.Title && sceneMapping.FilterRegex.IsNullOrWhiteSpace())
|
||||
{
|
||||
// Disable the implied mapping if we have an explicit mapping by the same name
|
||||
includeGlobal = false;
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace NzbDrone.Core.Indexers.Newznab
|
||||
{
|
||||
public static class NewznabCategoryFieldOptionsConverter
|
||||
{
|
||||
public static List<FieldSelectOption> GetFieldSelectOptions(List<NewznabCategory> categories)
|
||||
public static List<FieldSelectOption<int>> GetFieldSelectOptions(List<NewznabCategory> categories)
|
||||
{
|
||||
// Categories not relevant for Sonarr
|
||||
var ignoreCategories = new[] { 1000, 3000, 4000, 6000, 7000 };
|
||||
@@ -14,7 +14,7 @@ namespace NzbDrone.Core.Indexers.Newznab
|
||||
// And maybe relevant for specific users
|
||||
var unimportantCategories = new[] { 0, 2000 };
|
||||
|
||||
var result = new List<FieldSelectOption>();
|
||||
var result = new List<FieldSelectOption<int>>();
|
||||
|
||||
if (categories == null)
|
||||
{
|
||||
@@ -41,7 +41,7 @@ namespace NzbDrone.Core.Indexers.Newznab
|
||||
|
||||
foreach (var category in categories.Where(cat => !ignoreCategories.Contains(cat.Id)).OrderBy(cat => unimportantCategories.Contains(cat.Id)).ThenBy(cat => cat.Id))
|
||||
{
|
||||
result.Add(new FieldSelectOption
|
||||
result.Add(new FieldSelectOption<int>
|
||||
{
|
||||
Value = category.Id,
|
||||
Name = category.Name,
|
||||
@@ -52,7 +52,7 @@ namespace NzbDrone.Core.Indexers.Newznab
|
||||
{
|
||||
foreach (var subcat in category.Subcategories.OrderBy(cat => cat.Id))
|
||||
{
|
||||
result.Add(new FieldSelectOption
|
||||
result.Add(new FieldSelectOption<int>
|
||||
{
|
||||
Value = subcat.Id,
|
||||
Name = subcat.Name,
|
||||
|
||||
@@ -119,12 +119,23 @@ namespace NzbDrone.Core.Indexers.Newznab
|
||||
}
|
||||
}
|
||||
|
||||
private bool SupportsTmdbSearch
|
||||
{
|
||||
get
|
||||
{
|
||||
var capabilities = _capabilitiesProvider.GetCapabilities(Settings);
|
||||
|
||||
return capabilities.SupportedTvSearchParameters != null &&
|
||||
capabilities.SupportedTvSearchParameters.Contains("tmdbid");
|
||||
}
|
||||
}
|
||||
|
||||
// Combines all ID based searches
|
||||
private bool SupportsTvIdSearches
|
||||
{
|
||||
get
|
||||
{
|
||||
return SupportsTvdbSearch || SupportsImdbSearch || SupportsTvRageSearch || SupportsTvMazeSearch;
|
||||
return SupportsTvdbSearch || SupportsImdbSearch || SupportsTvRageSearch || SupportsTvMazeSearch || SupportsTmdbSearch;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -410,7 +421,7 @@ namespace NzbDrone.Core.Indexers.Newznab
|
||||
$"&season={NewznabifySeasonNumber(searchCriteria.SeasonNumber)}&ep={searchCriteria.EpisodeNumber}");
|
||||
}
|
||||
|
||||
var queryTitles = TextSearchEngine == "raw" ? searchCriteria.SceneTitles : searchCriteria.CleanSceneTitles;
|
||||
var queryTitles = TextSearchEngine == "raw" ? searchCriteria.AllSceneTitles : searchCriteria.CleanSceneTitles;
|
||||
|
||||
foreach (var queryTitle in queryTitles)
|
||||
{
|
||||
@@ -484,8 +495,9 @@ namespace NzbDrone.Core.Indexers.Newznab
|
||||
var includeImdbSearch = SupportsImdbSearch && searchCriteria.Series.ImdbId.IsNotNullOrWhiteSpace();
|
||||
var includeTvRageSearch = SupportsTvRageSearch && searchCriteria.Series.TvRageId > 0;
|
||||
var includeTvMazeSearch = SupportsTvMazeSearch && searchCriteria.Series.TvMazeId > 0;
|
||||
var includeTmdbSearch = SupportsTmdbSearch && searchCriteria.Series.TmdbId > 0;
|
||||
|
||||
if (SupportsAggregatedIdSearch && (includeTvdbSearch || includeTvRageSearch || includeTvMazeSearch))
|
||||
if (SupportsAggregatedIdSearch && (includeTvdbSearch || includeTvRageSearch || includeTvMazeSearch || includeTmdbSearch))
|
||||
{
|
||||
var ids = "";
|
||||
|
||||
@@ -509,6 +521,11 @@ namespace NzbDrone.Core.Indexers.Newznab
|
||||
ids += "&tvmazeid=" + searchCriteria.Series.TvMazeId;
|
||||
}
|
||||
|
||||
if (includeTmdbSearch)
|
||||
{
|
||||
ids += "&tmdbid=" + searchCriteria.Series.TmdbId;
|
||||
}
|
||||
|
||||
chain.Add(GetPagedRequests(MaxPages, categories, "tvsearch", ids + parameters));
|
||||
}
|
||||
else
|
||||
@@ -541,6 +558,13 @@ namespace NzbDrone.Core.Indexers.Newznab
|
||||
"tvsearch",
|
||||
$"&tvmazeid={searchCriteria.Series.TvMazeId}{parameters}"));
|
||||
}
|
||||
else if (includeTmdbSearch)
|
||||
{
|
||||
chain.Add(GetPagedRequests(MaxPages,
|
||||
categories,
|
||||
"tvsearch",
|
||||
$"&tmdbid={searchCriteria.Series.TmdbId}{parameters}"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -68,16 +68,17 @@ namespace NzbDrone.Core.Indexers.Newznab
|
||||
protected override bool PostProcess(IndexerResponse indexerResponse, List<XElement> items, List<ReleaseInfo> releases)
|
||||
{
|
||||
var enclosureTypes = items.SelectMany(GetEnclosures).Select(v => v.Type).Distinct().ToArray();
|
||||
|
||||
if (enclosureTypes.Any() && enclosureTypes.Intersect(PreferredEnclosureMimeTypes).Empty())
|
||||
{
|
||||
if (enclosureTypes.Intersect(TorrentEnclosureMimeTypes).Any())
|
||||
{
|
||||
_logger.Warn("{0} does not contain {1}, found {2}, did you intend to add a Torznab indexer?", indexerResponse.Request.Url, NzbEnclosureMimeType, enclosureTypes[0]);
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Warn("{1} does not contain {1}, found {2}.", indexerResponse.Request.Url, NzbEnclosureMimeType, enclosureTypes[0]);
|
||||
}
|
||||
|
||||
_logger.Warn("{0} does not contain {1}, found {2}.", indexerResponse.Request.Url, NzbEnclosureMimeType, enclosureTypes[0]);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -262,26 +262,26 @@ namespace NzbDrone.Core.Indexers
|
||||
protected virtual RssEnclosure[] GetEnclosures(XElement item)
|
||||
{
|
||||
var enclosures = item.Elements("enclosure")
|
||||
.Select(v =>
|
||||
{
|
||||
try
|
||||
{
|
||||
return new RssEnclosure
|
||||
{
|
||||
Url = v.Attribute("url")?.Value,
|
||||
Type = v.Attribute("type")?.Value,
|
||||
Length = v.Attribute("length")?.Value?.ParseInt64() ?? 0
|
||||
};
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Warn(e, "Failed to get enclosure for: {0}", item.Title());
|
||||
}
|
||||
.Select(v =>
|
||||
{
|
||||
try
|
||||
{
|
||||
return new RssEnclosure
|
||||
{
|
||||
Url = v.Attribute("url")?.Value,
|
||||
Type = v.Attribute("type")?.Value,
|
||||
Length = v.Attribute("length")?.Value?.ParseInt64() ?? 0
|
||||
};
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Warn(ex, "Failed to get enclosure for: {0}", item.Title());
|
||||
}
|
||||
|
||||
return null;
|
||||
})
|
||||
.Where(v => v != null)
|
||||
.ToArray();
|
||||
return null;
|
||||
})
|
||||
.Where(v => v != null)
|
||||
.ToArray();
|
||||
|
||||
return enclosures;
|
||||
}
|
||||
|
||||
@@ -59,16 +59,17 @@ namespace NzbDrone.Core.Indexers.Torznab
|
||||
protected override bool PostProcess(IndexerResponse indexerResponse, List<XElement> items, List<ReleaseInfo> releases)
|
||||
{
|
||||
var enclosureTypes = items.SelectMany(GetEnclosures).Select(v => v.Type).Distinct().ToArray();
|
||||
|
||||
if (enclosureTypes.Any() && enclosureTypes.Intersect(PreferredEnclosureMimeTypes).Empty())
|
||||
{
|
||||
if (enclosureTypes.Intersect(UsenetEnclosureMimeTypes).Any())
|
||||
{
|
||||
_logger.Warn("{0} does not contain {1}, found {2}, did you intend to add a Newznab indexer?", indexerResponse.Request.Url, TorrentEnclosureMimeType, enclosureTypes[0]);
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Warn("{1} does not contain {1}, found {2}.", indexerResponse.Request.Url, TorrentEnclosureMimeType, enclosureTypes[0]);
|
||||
}
|
||||
|
||||
_logger.Warn("{0} does not contain {1}, found {2}.", indexerResponse.Request.Url, TorrentEnclosureMimeType, enclosureTypes[0]);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -209,7 +209,7 @@
|
||||
"CountSeasons": "{count} Řad",
|
||||
"CustomFormat": "Vlastní formát",
|
||||
"CustomFormats": "Vlastní formáty",
|
||||
"CutoffUnmet": "Vynechat nevyhovující",
|
||||
"CutoffUnmet": "Mezní hodnota nesplněna",
|
||||
"Cutoff": "Odříznout",
|
||||
"DailyEpisodeFormat": "Formát denní epizody",
|
||||
"DailyEpisodeTypeDescription": "Epizody vydávané denně nebo méně často, které používají rok-měsíc-den (2023-08-04)",
|
||||
@@ -219,7 +219,7 @@
|
||||
"CreateGroup": "Vytvořit skupinu",
|
||||
"Custom": "Vlastní",
|
||||
"CustomFormatUnknownCondition": "Neznámá podmínka vlastního formátu „{implementation}“",
|
||||
"CustomFormatUnknownConditionOption": "Neznámá možnost '{key}' pro podmínku '{implementation}'",
|
||||
"CustomFormatUnknownConditionOption": "Neznámá možnost „{key}“ pro podmínku „{implementation}“",
|
||||
"CustomFormatsLoadError": "Nelze načíst vlastní formáty",
|
||||
"CustomFormatsSettingsSummary": "Vlastní formáty a nastavení",
|
||||
"CopyUsingHardlinksSeriesHelpText": "Pevné odkazy umožňují aplikaci {appName} importovat odesílané torrenty do složky seriálu, aniž by zabíraly další místo na disku nebo kopírovaly celý obsah souboru. Hardlinky budou fungovat pouze v případě, že zdrojový a cílový soubor jsou na stejném svazku",
|
||||
@@ -319,5 +319,17 @@
|
||||
"EditSelectedImportLists": "Upravit vybrané seznamy k importu",
|
||||
"FormatDateTime": "{formattedDate} {formattedTime}",
|
||||
"AddRootFolderError": "Nepodařilo se přidat kořenový adresář",
|
||||
"DownloadClientRemovesCompletedDownloadsHealthCheckMessage": "Klient stahování {downloadClientName} je nastaven na odstranění dokončených stahování. To může vést k tomu, že stahování budou z klienta odstraněna dříve, než je bude moci importovat {appName}."
|
||||
"DownloadClientRemovesCompletedDownloadsHealthCheckMessage": "Klient stahování {downloadClientName} je nastaven na odstranění dokončených stahování. To může vést k tomu, že stahování budou z klienta odstraněna dříve, než je bude moci importovat {appName}.",
|
||||
"ConnectionSettingsUrlBaseHelpText": "Přidá předponu do {connectionName} url, jako např. {url}",
|
||||
"CustomFormatsSpecificationRegularExpressionHelpText": "Vlastní formát RegEx nerozlišuje velká a malá písmena",
|
||||
"CustomFormatsSpecificationFlag": "Vlajka",
|
||||
"BlackholeFolderHelpText": "Složka do které {appName} uloží {extension} soubor",
|
||||
"BlackholeWatchFolder": "Složka sledování",
|
||||
"Category": "Kategorie",
|
||||
"BlocklistAndSearch": "Seznam blokovaných a vyhledávání",
|
||||
"BlackholeWatchFolderHelpText": "Složka ze které {appName} má importovat stažené soubory",
|
||||
"BlocklistReleaseHelpText": "Zabránit {appName} v opětovném sebrání tohoto vydání pomocí RSS nebo automatického vyhledávání",
|
||||
"BlocklistMultipleOnlyHint": "Blokovat a nehledat náhradu",
|
||||
"CustomFormatsSettingsTriggerInfo": "Vlastní formát se použije na vydání nebo soubor, pokud odpovídá alespoň jednomu z různých typů zvolených podmínek.",
|
||||
"ChangeCategory": "Změnit kategorii"
|
||||
}
|
||||
|
||||
@@ -34,5 +34,9 @@
|
||||
"AddImportListImplementation": "Tilføj importliste - {implementationName}",
|
||||
"AddRootFolderError": "Kunne ikke tilføje rodmappe",
|
||||
"Table": "Tabel",
|
||||
"AddIndexer": "Tilføj indekser"
|
||||
"AddIndexer": "Tilføj indekser",
|
||||
"AddDownloadClient": "Tilføj downloadklient",
|
||||
"AddImportListExclusion": "Tilføj ekslusion til importeringslisten",
|
||||
"AddDelayProfileError": "Kan ikke tilføje en ny forsinkelsesprofil. Prøv venligst igen.",
|
||||
"AddDownloadClientError": "Ikke muligt at tilføje en ny downloadklient. Prøv venligst igen."
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@
|
||||
"AddConnectionImplementation": "Verbindung hinzufügen - {implementationName}",
|
||||
"AddDownloadClientImplementation": "Download-Client hinzufügen - {implementationName}",
|
||||
"AddIndexerImplementation": "Indexer hinzufügen - {implementationName}",
|
||||
"AddNotificationError": "Neue Benachrichtigung konnte nicht hinzugefügt werden, bitte versuchen Sie es erneut.",
|
||||
"AddNotificationError": "Die neue Benachrichtigung konnte nicht hinzugefügt werden, bitte erneut probieren.",
|
||||
"AddQualityProfileError": "Qualitätsprofil konnte nicht hinzugefügt werden. Bitte versuchen Sie es erneut.",
|
||||
"AddNewSeriesRootFolderHelpText": "Unterordner '{folder}' wird automatisch erstellt",
|
||||
"AddNewSeriesSearchForMissingEpisodes": "Suche für fehlende Episoden starten",
|
||||
@@ -144,7 +144,7 @@
|
||||
"AuthenticationRequiredPasswordHelpTextWarning": "Gib ein neues Passwort ein",
|
||||
"AuthenticationRequiredUsernameHelpTextWarning": "Gib einen neuen Benutzernamen ein",
|
||||
"AuthenticationRequiredHelpText": "Ändern, welche anfragen Authentifizierung benötigen. Ändere nichts wenn du dir nicht des Risikos bewusst bist.",
|
||||
"AnalyseVideoFilesHelpText": "Videoinformationen wie Auflösung, Laufzeit und Codec-Informationen aus Dateien extrahieren. Dies erfordert, dass {appName} Teile der Datei liest, was bei Scans zu hoher Festplatten- oder Netzwerkaktivität führen kann.",
|
||||
"AnalyseVideoFilesHelpText": "Videoinformationen wie Auflösung, Laufzeit und Codec aus Datien erkennen. Dazu ist es erforderlich, dass {appName} Teile der Datei liest, was zu hoher Festplatten- oder Netzwerkaktivität während der Scans führen kann.",
|
||||
"AnalyticsEnabledHelpText": "Senden Sie anonyme Nutzungs- und Fehlerinformationen an die Server von {appName}. Dazu gehören Informationen zu Ihrem Browser, welche {appName}-WebUI-Seiten Sie verwenden, Fehlerberichte sowie Betriebssystem- und Laufzeitversion. Wir werden diese Informationen verwenden, um Funktionen und Fehlerbehebungen zu priorisieren.",
|
||||
"AutoTaggingNegateHelpText": "Falls aktiviert wird die Auto Tagging Regel nicht angewendet, solange diese Bedingung {implementationName} zutrifft.",
|
||||
"CopyUsingHardlinksSeriesHelpText": "Mithilfe von Hardlinks kann {appName} Seeding-Torrents in den Serienordner importieren, ohne zusätzlichen Speicherplatz zu beanspruchen oder den gesamten Inhalt der Datei zu kopieren. Hardlinks funktionieren nur, wenn sich Quelle und Ziel auf demselben Volume befinden",
|
||||
@@ -164,7 +164,7 @@
|
||||
"RestartReloadNote": "Hinweis: {appName} startet während des Wiederherstellungsvorgangs automatisch neu und lädt die Benutzeroberfläche neu.",
|
||||
"AutoRedownloadFailedHelpText": "Suchen Sie automatisch nach einer anderen Version und versuchen Sie, sie herunterzuladen",
|
||||
"AirDate": "Ausstrahlungsdatum",
|
||||
"AgeWhenGrabbed": "Alter (zum Zeitpunkt der Entführung)",
|
||||
"AgeWhenGrabbed": "Alter (bei Erfassung)",
|
||||
"ApplyTagsHelpTextHowToApplySeries": "So wenden Sie Tags auf die ausgewählte Serie an",
|
||||
"ApiKey": "API-Schlüssel",
|
||||
"AutoTaggingLoadError": "Automatisches Tagging konnte nicht geladen werden",
|
||||
@@ -272,7 +272,7 @@
|
||||
"ContinuingOnly": "Nur fortlaufend",
|
||||
"ContinuingSeriesDescription": "Weitere Episoden/eine weitere Staffel werden erwartet",
|
||||
"CopyToClipboard": "In die Zwischenablage kopieren",
|
||||
"CouldNotFindResults": "Es konnten keine Ergebnisse für „{term}“ gefunden werden.",
|
||||
"CouldNotFindResults": "Es konnten keine Ergebnisse für „{term}“ gefunden werden",
|
||||
"CountSeriesSelected": "{count} Serie ausgewählt",
|
||||
"CreateEmptySeriesFoldersHelpText": "Erstellen Sie beim Festplatten-Scan Ordner für fehlende Serien",
|
||||
"CreateGroup": "Gruppe erstellen",
|
||||
@@ -416,7 +416,7 @@
|
||||
"DownloadClientSabnzbdValidationEnableDisableDateSorting": "Deaktivieren Sie die Datumssortierung",
|
||||
"DownloadClientSabnzbdValidationEnableDisableDateSortingDetail": "Sie müssen die Datumssortierung für die von {appName} verwendete Kategorie deaktivieren, um Importprobleme zu vermeiden. Gehen Sie zu Sabnzbd, um das Problem zu beheben.",
|
||||
"DownloadClientSabnzbdValidationEnableDisableMovieSorting": "Deaktivieren Sie die Filmsortierung",
|
||||
"AllResultsAreHiddenByTheAppliedFilter": "Alle Resultate werden wegen des angewandten Filters nicht angezeigt",
|
||||
"AllResultsAreHiddenByTheAppliedFilter": "Alle Ergebnisse werden durch den angewendeten Filter ausgeblendet",
|
||||
"RegularExpressionsCanBeTested": "Reguläre Ausdrücke können [hier] getestet werden ({url}).",
|
||||
"ReleaseSceneIndicatorUnknownSeries": "Unbekannte Folge oder Serie.",
|
||||
"RemoveFilter": "Filter entfernen",
|
||||
@@ -549,7 +549,7 @@
|
||||
"CountImportListsSelected": "{count} Importliste(n) ausgewählt",
|
||||
"CountIndexersSelected": "{count} Indexer ausgewählt",
|
||||
"CountSelectedFiles": "{selectedCount} ausgewählte Dateien",
|
||||
"CustomFormatUnknownConditionOption": "Unbekannte Option „{key}“ für Bedingung „{implementation}“",
|
||||
"CustomFormatUnknownConditionOption": "Unbekannte Option '{key}' für die Bedingung '{implementation}'",
|
||||
"CustomFormatsSettings": "Einstellungen für eigene Formate",
|
||||
"Daily": "Täglich",
|
||||
"Dash": "Bindestrich",
|
||||
@@ -580,7 +580,7 @@
|
||||
"SslCertPassword": "SSL-Zertifikatskennwort",
|
||||
"SpecialsFolderFormat": "Specials-Ordnerformat",
|
||||
"SourceTitle": "Quellentitel",
|
||||
"Agenda": "Tagesordnung",
|
||||
"Agenda": "Agenda",
|
||||
"AnEpisodeIsDownloading": "Eine Episode wird heruntergeladen",
|
||||
"CollapseMultipleEpisodesHelpText": "Reduzieren Sie mehrere Episoden, die am selben Tag ausgestrahlt werden",
|
||||
"Connect": "Verbinden",
|
||||
@@ -792,5 +792,86 @@
|
||||
"MediaManagement": "Medienverwaltung",
|
||||
"StartupDirectory": "Start-Verzeichnis",
|
||||
"OnRename": "Bei Umbenennung",
|
||||
"MaintenanceRelease": "Maintenance Release: Fehlerbehebungen und andere Verbesserungen. Siehe Github Commit Verlauf für weitere Details"
|
||||
"MaintenanceRelease": "Maintenance Release: Fehlerbehebungen und andere Verbesserungen. Siehe Github Commit Verlauf für weitere Details",
|
||||
"BlocklistRelease": "Release sperren",
|
||||
"BranchUpdateMechanism": "Git-Branch für den externen Updateablauf",
|
||||
"AutoTaggingSpecificationGenre": "Genre(s)",
|
||||
"AutoTaggingSpecificationOriginalLanguage": "Sprache",
|
||||
"AutoTaggingSpecificationQualityProfile": "Qualitätsprofil",
|
||||
"AutoTaggingSpecificationRootFolder": "Stammverzeichnis",
|
||||
"AutoTaggingSpecificationStatus": "Status",
|
||||
"ConnectionSettingsUrlBaseHelpText": "Fügt ein Präfix zur {connectionName} URL hinzu, z. B. {url}",
|
||||
"DeleteImportListExclusion": "Importlisten Ausschluss löschen",
|
||||
"DeleteTag": "Tag löschen",
|
||||
"DoNotBlocklistHint": "Entfernen ohne Sperren",
|
||||
"DownloadClientPriorityHelpText": "Download-Client-Priorität von 1 (Höchste) bis 50 (Niedrigste). Standard: 1. Round-Robin wird für Clients mit der gleichen Priorität verwendet.",
|
||||
"DownloadClientSettingsRecentPriority": "Neueste Priorität",
|
||||
"DownloadClientValidationApiKeyIncorrect": "API-Key fehlerhaft",
|
||||
"ClientPriority": "Priorität",
|
||||
"Cutoff": "Schwelle",
|
||||
"DownloadClient": "Downloader",
|
||||
"DownloadClientSabnzbdValidationUnknownVersion": "Unbekannte Version: {rawVersion}",
|
||||
"CutoffUnmet": "Schwelle nicht erreicht",
|
||||
"DownloadClientSettingsInitialState": "Ausgangszustand",
|
||||
"DownloadClientValidationApiKeyRequired": "API-Key benötigt",
|
||||
"CustomFormatsSpecificationRegularExpressionHelpText": "Benutzerdefiniertes Format RegEx ist nicht groß-/kleinschreibungssensitiv",
|
||||
"CustomFormatsSpecificationMinimumSize": "Mindestgröße",
|
||||
"CustomFormatsSpecificationRegularExpression": "Regulären Ausdruck",
|
||||
"CustomFormatsSpecificationReleaseGroup": "Release-Gruppe",
|
||||
"CustomFormatsSpecificationResolution": "Auflösung",
|
||||
"DeleteImportListExclusionMessageText": "Bist du sicher, dass du diesen Importlisten Ausschluss löschen willst?",
|
||||
"DownloadClientSabnzbdValidationEnableDisableTvSorting": "TV-Sortierung deaktivieren",
|
||||
"CustomFormatUnknownCondition": "Unbekannte Eigene Formatbedingung '{implementation}'",
|
||||
"ReleaseGroups": "Release Gruppen",
|
||||
"DownloadClientSettingsUseSslHelpText": "Sichere Verbindung verwenden, wenn Verbindung zu {clientName} hergestellt wird",
|
||||
"ReleaseRejected": "Release abgelehnt",
|
||||
"Clear": "Leeren",
|
||||
"DownloadClientValidationCategoryMissing": "Kategorie existiert nicht",
|
||||
"DownloadClientValidationAuthenticationFailure": "Authentifizierung fehlgeschlagen",
|
||||
"DownloadClientValidationErrorVersion": "{clientName} Version sollte mindestens {requiredVersion} sein. Die gemeldete Version ist {reportedVersion}",
|
||||
"DownloadClientValidationGroupMissing": "Gruppe existiert nicht",
|
||||
"DownloadClientValidationSslConnectFailure": "Verbindung über SSL nicht möglich",
|
||||
"ReleaseProfilesLoadError": "Release-Profile können nicht geladen werden",
|
||||
"DownloadClientDelugeSettingsDirectory": "Download Verzeichnis",
|
||||
"DownloadClientDelugeSettingsDirectoryCompleted": "Verschieben, wenn Verzeichnis abgeschlossen",
|
||||
"DownloadClientSettings": "Downloader Einstellungen",
|
||||
"IgnoreDownloadHint": "Hält {appName} von der weiteren Verarbeitung dieses Downloads ab",
|
||||
"ClearBlocklist": "Sperrliste leeren",
|
||||
"CleanLibraryLevel": "Mediathek aufräumen",
|
||||
"CloneAutoTag": "Automatische Tags kopieren",
|
||||
"DownloadClientSettingsOlderPriorityEpisodeHelpText": "Priorität beim Abrufen von Episoden, die vor mehr als 14 Tagen ausgestrahlt wurden",
|
||||
"DownloadClientSettingsInitialStateHelpText": "Anfangszustand für zu {clientName} hinzugefügte Torrents",
|
||||
"DownloadClientSettingsOlderPriority": "Ältere Priorität",
|
||||
"IgnoreDownload": "Download ignorieren",
|
||||
"CustomFormatsSettingsTriggerInfo": "Ein Eigenes Format wird auf eine Veröffentlichung oder Datei angewandt, wenn sie mindestens einer der verschiedenen ausgewählten Bedingungen entspricht.",
|
||||
"DatabaseMigration": "DB Migration",
|
||||
"DownloadClientSettingsDestinationHelpText": "Legt das Ziel für den Download manuell fest; lassen Sie es leer, um die Standardeinstellung zu verwenden",
|
||||
"DownloadClientSettingsCategorySubFolderHelpText": "Das Hinzufügen einer spezifischen Kategorie für {appName} vermeidet Konflikte mit nicht verwandten Downloads, die nicht {appName} sind. Die Verwendung einer Kategorie ist optional, wird aber dringend empfohlen. Erzeugt ein Unterverzeichnis [category] im Ausgabeverzeichnis.",
|
||||
"BlocklistReleases": "Release sperren",
|
||||
"DownloadClientQbittorrentTorrentStateMissingFiles": "qBittorrent meldet fehlende Dateien",
|
||||
"ChangeCategoryHint": "Änderung des Downloads in die 'Post-Import-Kategorie' vom Download-Client",
|
||||
"ChangeCategoryMultipleHint": "Änderung der Downloads in die 'Post-Import-Kategorie' vom Download-Client",
|
||||
"CustomFormatsSpecificationSource": "Quelle",
|
||||
"BlocklistFilterHasNoItems": "Ausgewählter Blocklistenfilter enthält keine Elemente",
|
||||
"CustomFilter": "Benutzerdefinierter Filter",
|
||||
"CustomFormatsSpecificationFlag": "Markierung",
|
||||
"CustomFormatScore": "Eigenes Format Bewertungspunkte",
|
||||
"CustomFormatsSpecificationLanguage": "Sprache",
|
||||
"CustomFormatsSpecificationMaximumSize": "Maximale Größe",
|
||||
"AutoTaggingSpecificationTag": "Tag",
|
||||
"BindAddress": "Adresse binden",
|
||||
"DownloadClientSettingsRecentPriorityEpisodeHelpText": "Priorität beim Abrufen von Episoden, die innerhalb der letzten 14 Tage ausgestrahlt wurden",
|
||||
"DownloadClientSettingsUrlBaseHelpText": "Fügt ein Präfix zur {clientName} Url hinzu, z.B. {url}",
|
||||
"DownloadClientTransmissionSettingsDirectoryHelpText": "Optionaler Speicherort für Downloads; leer lassen, um den Standardspeicherort für Übertragungen zu verwenden",
|
||||
"DownloadClientUTorrentTorrentStateError": "uTorrent meldet einen Fehler",
|
||||
"DoNotBlocklist": "Nicht Sperren",
|
||||
"ReleaseHash": "Release Hash",
|
||||
"DownloadClientAriaSettingsDirectoryHelpText": "Optionaler Speicherort für Downloads. Lassen Sie das Feld leer, um den standardmäßigen rTorrent-Speicherort zu verwenden",
|
||||
"DownloadClientSeriesTagHelpText": "Verwenden Sie diesen Downloader nur für Serien mit mindestens einem passenden Tag. Lassen Sie ihn leer, um ihn für alle Serien zu verwenden.",
|
||||
"DownloadClientSettingsCategoryHelpText": "Das Hinzufügen einer spezifischen Kategorie für {appName} vermeidet Konflikte mit nicht verwandten Downloads, die nicht {appName} sind. Die Verwendung einer Kategorie ist optional, wird aber dringend empfohlen.",
|
||||
"DownloadClientSettingsPostImportCategoryHelpText": "Kategorie für {appName}, die nach dem Importieren des Downloads festgelegt wird. {appName} wird Torrents in dieser Kategorie nicht entfernen, auch wenn das Seeding beendet ist. Leer lassen, um dieselbe Kategorie beizubehalten.",
|
||||
"DownloadClientValidationCategoryMissingDetail": "Die von Ihnen eingegebene Kategorie existiert nicht in {clientName}. Erstellen Sie sie zuerst in {clientName}.",
|
||||
"DownloadClientValidationGroupMissingDetail": "Die von Ihnen eingegebene Gruppe existiert nicht in {clientName}. Erstellen Sie sie zuerst in {clientName}.",
|
||||
"IgnoreDownloads": "Downloads ignorieren",
|
||||
"IgnoreDownloadsHint": "Hindert {appName}, diese Downloads weiter zu verarbeiten"
|
||||
}
|
||||
|
||||
@@ -270,6 +270,9 @@
|
||||
"CreateGroup": "Create Group",
|
||||
"CurrentlyInstalled": "Currently Installed",
|
||||
"Custom": "Custom",
|
||||
"CustomColonReplacement": "Custom Colon Replacement",
|
||||
"CustomColonReplacementFormatHelpText": "Characters to be used as a replacement for colons",
|
||||
"CustomColonReplacementFormatHint": "Valid file system character such as Colon (Letter)",
|
||||
"CustomFilter": "Custom Filter",
|
||||
"CustomFilters": "Custom Filters",
|
||||
"CustomFormat": "Custom Format",
|
||||
@@ -1361,6 +1364,8 @@
|
||||
"NotificationsNtfyValidationAuthorizationRequired": "Authorization is required",
|
||||
"NotificationsPlexSettingsAuthToken": "Auth Token",
|
||||
"NotificationsPlexSettingsAuthenticateWithPlexTv": "Authenticate with Plex.tv",
|
||||
"NotificationsPlexSettingsServer": "Server",
|
||||
"NotificationsPlexSettingsServerHelpText": "Select server from plex.tv account after authenticating",
|
||||
"NotificationsPlexValidationNoTvLibraryFound": "At least one TV library is required",
|
||||
"NotificationsPushBulletSettingSenderId": "Sender ID",
|
||||
"NotificationsPushBulletSettingSenderIdHelpText": "The device ID to send notifications from, use device_iden in the device's URL on pushbullet.com (leave blank to send from yourself)",
|
||||
@@ -1454,10 +1459,11 @@
|
||||
"OnApplicationUpdate": "On Application Update",
|
||||
"OnEpisodeFileDelete": "On Episode File Delete",
|
||||
"OnEpisodeFileDeleteForUpgrade": "On Episode File Delete For Upgrade",
|
||||
"OnFileImport": "On File Import",
|
||||
"OnGrab": "On Grab",
|
||||
"OnHealthIssue": "On Health Issue",
|
||||
"OnHealthRestored": "On Health Restored",
|
||||
"OnImport": "On Import",
|
||||
"OnImportComplete": "On Import Complete",
|
||||
"OnLatestVersion": "The latest version of {appName} is already installed",
|
||||
"OnManualInteractionRequired": "On Manual Interaction Required",
|
||||
"OnRename": "On Rename",
|
||||
@@ -1992,6 +1998,7 @@
|
||||
"Umask770Description": "{octal} - Owner & Group write",
|
||||
"Umask775Description": "{octal} - Owner & Group write, Other read",
|
||||
"Umask777Description": "{octal} - Everyone write",
|
||||
"UnableToImportAutomatically": "Unable to Import Automatically",
|
||||
"UnableToLoadAutoTagging": "Unable to load auto tagging",
|
||||
"UnableToLoadBackups": "Unable to load backups",
|
||||
"UnableToUpdateSonarrDirectly": "Unable to update {appName} directly,",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"Added": "Añadido",
|
||||
"ApplyChanges": "Aplicar Cambios",
|
||||
"AuthBasic": "Básico (ventana emergente del navegador)",
|
||||
"AuthBasic": "Básica (Ventana emergente del navegador)",
|
||||
"BackupFolderHelpText": "Las rutas relativas estarán en el directorio AppData de {appName}",
|
||||
"BackupsLoadError": "No se pudieron cargar las copias de seguridad",
|
||||
"Enable": "Habilitar",
|
||||
@@ -36,22 +36,22 @@
|
||||
"AddNewRestriction": "Añadir nueva restricción",
|
||||
"AddRemotePathMapping": "Añadir Asignación de Ruta Remota",
|
||||
"Analytics": "Analíticas",
|
||||
"ApiKey": "Clave de API",
|
||||
"ApiKey": "Clave API",
|
||||
"AnimeEpisodeFormat": "Formato de Episodio de Anime",
|
||||
"ApplicationUrlHelpText": "La URL externa de la aplicación incluyendo http(s)://, puerto y URL base",
|
||||
"ApplyTagsHelpTextReplace": "Reemplazar: Sustituye las etiquetas por las introducidas (introduce \"no tags\" para borrar todas las etiquetas)",
|
||||
"ApplicationURL": "URL de la aplicación",
|
||||
"Authentication": "Autenticación",
|
||||
"AuthForm": "Formularios (Página de inicio de sesión)",
|
||||
"AuthenticationMethodHelpText": "Requerir nombre de usuario y contraseña para acceder {appName}",
|
||||
"AuthenticationMethodHelpText": "Requiere usuario y contraseña para acceder a {appName}",
|
||||
"AuthenticationRequired": "Autenticación requerida",
|
||||
"AutoTaggingLoadError": "No se pudo cargar el etiquetado automático",
|
||||
"AutoRedownloadFailedHelpText": "Buscar e intentar descargar automáticamente una versión diferente",
|
||||
"AutoRedownloadFailedHelpText": "Busca e intenta descargar automáticamente una versión diferente",
|
||||
"Backup": "Copia de seguridad",
|
||||
"AutomaticSearch": "Búsqueda Automática",
|
||||
"Automatic": "Automático",
|
||||
"BindAddressHelpText": "Dirección IP4 válida, localhost o '*' para todas las interfaces",
|
||||
"BindAddress": "Dirección de Ligado",
|
||||
"BindAddress": "Dirección de enlace",
|
||||
"Branch": "Rama",
|
||||
"BuiltIn": "Integrado",
|
||||
"Condition": "Condición",
|
||||
@@ -65,7 +65,7 @@
|
||||
"Duplicate": "Duplicar",
|
||||
"Error": "Error",
|
||||
"Episodes": "Episodios",
|
||||
"External": "Externo",
|
||||
"External": "Externa",
|
||||
"Extend": "Extender",
|
||||
"Restore": "Restaurar",
|
||||
"Security": "Seguridad",
|
||||
@@ -78,10 +78,10 @@
|
||||
"Torrents": "Torrents",
|
||||
"Ui": "Interfaz",
|
||||
"Underscore": "Guion bajo",
|
||||
"UpdateMechanismHelpText": "Usar el actualizador integrado de {appName} o un script",
|
||||
"UpdateMechanismHelpText": "Usa el actualizador integrado de {appName} o un script",
|
||||
"Warn": "Advertencia",
|
||||
"AutoTagging": "Etiquetado Automático",
|
||||
"AddAutoTag": "Añadir Etiqueta Automática",
|
||||
"AddAutoTag": "Añadir etiqueta automática",
|
||||
"AddCondition": "Añadir Condición",
|
||||
"AbsoluteEpisodeNumbers": "Número(s) de Episodio Absoluto(s)",
|
||||
"AirDate": "Fecha de Emisión",
|
||||
@@ -128,7 +128,7 @@
|
||||
"AudioLanguages": "Idiomas de Audio",
|
||||
"Episode": "Episodio",
|
||||
"Activity": "Actividad",
|
||||
"AddNew": "Añadir Nuevo",
|
||||
"AddNew": "Añadir nuevo",
|
||||
"ApplyTagsHelpTextAdd": "Añadir: Añade las etiquetas a la lista de etiquetas existente",
|
||||
"ApplyTagsHelpTextRemove": "Eliminar: Elimina las etiquetas introducidas",
|
||||
"Blocklist": "Lista de bloqueos",
|
||||
@@ -165,7 +165,7 @@
|
||||
"AddRemotePathMappingError": "No se pudo añadir una nueva asignación de ruta remota, inténtelo de nuevo.",
|
||||
"AgeWhenGrabbed": "Antigüedad (cuando se añadió)",
|
||||
"AllResultsAreHiddenByTheAppliedFilter": "Todos los resultados están ocultos por el filtro aplicado",
|
||||
"AnalyseVideoFilesHelpText": "Extraer información de video como la resolución, el tiempo de ejecución y la información del códec de los archivos. Esto requiere que {appName} lea partes del archivo lo cual puede causar una alta actividad en el disco o en la red durante los escaneos.",
|
||||
"AnalyseVideoFilesHelpText": "Extrae información de video como la resolución, el tiempo de ejecución y la información del códec de los archivos. Esto requiere que {appName} lea partes del archivo lo cual puede causar una alta actividad en el disco o en la red durante los escaneos.",
|
||||
"AnimeEpisodeTypeDescription": "Episodios lanzados usando un número de episodio absoluto",
|
||||
"ApiKeyValidationHealthCheckMessage": "Por favor actualiza tu clave API para que tenga de longitud al menos {length} caracteres. Puedes hacerlo en los ajustes o en el archivo de configuración",
|
||||
"AppDataLocationHealthCheckMessage": "No será posible actualizar para evitar la eliminación de AppData al actualizar",
|
||||
@@ -174,7 +174,7 @@
|
||||
"Clone": "Clonar",
|
||||
"Connections": "Conexiones",
|
||||
"Dash": "Guion",
|
||||
"AnalyticsEnabledHelpText": "Envíe información anónima de uso y error a los servidores de {appName}. Esto incluye información sobre su navegador, qué páginas de {appName} WebUI utiliza, informes de errores, así como el sistema operativo y la versión en tiempo de ejecución. Usaremos esta información para priorizar funciones y correcciones de errores.",
|
||||
"AnalyticsEnabledHelpText": "Envía información anónima de uso y error a los servidores de {appName}. Esto incluye información sobre tu navegador, qué páginas de interfaz web de {appName} utilizas, informes de errores, así como el sistema operativo y la versión en tiempo de ejecución. Usaremos esta información para priorizar funciones y correcciones de errores.",
|
||||
"BackupIntervalHelpText": "Intervalo entre copias de seguridad automáticas",
|
||||
"BackupRetentionHelpText": "Las copias de seguridad automáticas anteriores al período de retención serán borradas automáticamente",
|
||||
"AddNewSeries": "Añadir Nueva Serie",
|
||||
@@ -182,7 +182,7 @@
|
||||
"AddNewSeriesHelpText": "Es fácil añadir una nueva serie, empiece escribiendo el nombre de la serie que desea añadir.",
|
||||
"AddNewSeriesRootFolderHelpText": "La subcarpeta '{folder}' será creada automáticamente",
|
||||
"AddNewSeriesSearchForCutoffUnmetEpisodes": "Empezar la búsqueda de episodios con límites no alcanzados",
|
||||
"AddNewSeriesSearchForMissingEpisodes": "Empezar búsqueda de episodios faltantes",
|
||||
"AddNewSeriesSearchForMissingEpisodes": "Empezar la búsqueda de episodios faltantes",
|
||||
"AddQualityProfile": "Añadir Perfil de Calidad",
|
||||
"AddQualityProfileError": "No se pudo añadir un nuevo perfil de calidad, inténtelo de nuevo.",
|
||||
"AddReleaseProfile": "Añadir perfil de lanzamiento",
|
||||
@@ -199,7 +199,7 @@
|
||||
"EditSelectedDownloadClients": "Editar Clientes de Descarga Seleccionados",
|
||||
"DeleteRemotePathMappingMessageText": "¿Está seguro de querer eliminar esta asignación de ruta remota?",
|
||||
"Implementation": "Implementación",
|
||||
"ImportUsingScript": "Importar Script de Uso",
|
||||
"ImportUsingScript": "Importar usando un script",
|
||||
"CloneAutoTag": "Clonar Etiquetado Automático",
|
||||
"ManageIndexers": "Gestionar Indexadores",
|
||||
"DeleteAutoTag": "Eliminar Etiquetado Automático",
|
||||
@@ -219,15 +219,15 @@
|
||||
"AddConditionImplementation": "Añadir condición - {implementationName}",
|
||||
"AppUpdated": "{appName} Actualizado",
|
||||
"AutomaticUpdatesDisabledDocker": "Las actualizaciones automáticas no están soportadas directamente cuando se utiliza el mecanismo de actualización de Docker. Tendrá que actualizar la imagen del contenedor fuera de {appName} o utilizar un script",
|
||||
"AuthenticationRequiredHelpText": "Cambiar para que las solicitudes requieran autenticación. No lo cambie a menos que entienda los riesgos.",
|
||||
"AuthenticationRequiredWarning": "Para evitar el acceso remoto sin autenticación, {appName} ahora requiere que la autenticación esté habilitada. Opcionalmente puede desactivar la autenticación desde una dirección local.",
|
||||
"AuthenticationRequiredPasswordHelpTextWarning": "Introduzca una nueva contraseña",
|
||||
"AuthenticationRequiredUsernameHelpTextWarning": "Introduzca un nuevo nombre de usuario",
|
||||
"AuthenticationRequiredHelpText": "Cambia para qué solicitudes se requiere autenticación. No cambiar a menos que entiendas los riesgos.",
|
||||
"AuthenticationRequiredWarning": "Para evitar el acceso remoto sin autenticación, {appName} ahora requiere que la autenticación sea habilitada. Opcionalmente puedes deshabilitar la autenticación desde direcciones locales.",
|
||||
"AuthenticationRequiredPasswordHelpTextWarning": "Introduce una nueva contraseña",
|
||||
"AuthenticationRequiredUsernameHelpTextWarning": "Introduce un nuevo usuario",
|
||||
"AuthenticationMethod": "Método de autenticación",
|
||||
"AddConnectionImplementation": "Añadir Conexión - {implementationName}",
|
||||
"AddDownloadClientImplementation": "Añadir Cliente de Descarga - {implementationName}",
|
||||
"VideoDynamicRange": "Video de Rango Dinámico",
|
||||
"AuthenticationMethodHelpTextWarning": "Por favor selecciona un método válido de autenticación",
|
||||
"AuthenticationMethodHelpTextWarning": "Por favor selecciona un método de autenticación válido",
|
||||
"AddCustomFilter": "Añadir Filtro Personalizado",
|
||||
"BypassDelayIfAboveCustomFormatScoreMinimumScore": "Puntuación mínima de formato personalizado",
|
||||
"CountIndexersSelected": "{count} indexador(es) seleccionado(s)",
|
||||
@@ -266,12 +266,12 @@
|
||||
"DeleteSelectedImportListsMessageText": "¿Estás seguro que quieres eliminar {count} lista(s) de importación seleccionada(s)?",
|
||||
"DeletedReasonUpgrade": "Se ha borrado el archivo para importar una versión mejorada",
|
||||
"DeleteTagMessageText": "¿Está seguro de querer eliminar la etiqueta '{label}'?",
|
||||
"DisabledForLocalAddresses": "Deshabilitado para Direcciones Locales",
|
||||
"DisabledForLocalAddresses": "Deshabilitada para direcciones locales",
|
||||
"DeletedReasonManual": "El archivo fue eliminado usando {appName}, o bien manualmente o por otra herramienta a través de la API",
|
||||
"ClearBlocklist": "Limpiar lista de bloqueos",
|
||||
"AuthenticationRequiredPasswordConfirmationHelpTextWarning": "Confirma la nueva contraseña",
|
||||
"MonitorPilotEpisode": "Episodio Piloto",
|
||||
"MonitorRecentEpisodesDescription": "Monitorizar episodios emitidos en los últimos 90 días y los episodios futuros",
|
||||
"MonitorRecentEpisodesDescription": "Monitoriza episodios emitidos en los últimos 90 días y los episodios futuros",
|
||||
"MonitorSelected": "Monitorizar seleccionados",
|
||||
"MonitorSeries": "Monitorizar Series",
|
||||
"NoHistory": "Sin historial",
|
||||
@@ -287,8 +287,8 @@
|
||||
"History": "Historial",
|
||||
"MonitorNoNewSeasonsDescription": "No monitorizar automáticamente ninguna temporada nueva",
|
||||
"HistoryLoadError": "No se pudo cargar el historial",
|
||||
"LibraryImport": "Importar Librería",
|
||||
"RescanSeriesFolderAfterRefresh": "Re-escanear la Carpeta de Series tras Actualizar",
|
||||
"LibraryImport": "Importar biblioteca",
|
||||
"RescanSeriesFolderAfterRefresh": "Volver a escanear la carpeta de series tras actualizar",
|
||||
"Wanted": "Buscado",
|
||||
"MonitorPilotEpisodeDescription": "Sólo monitorizar el primer episodio de la primera temporada",
|
||||
"MonitorRecentEpisodes": "Episodios Recientes",
|
||||
@@ -300,14 +300,14 @@
|
||||
"MonitorSpecialEpisodes": "Monitorizar Especiales",
|
||||
"Queue": "Cola",
|
||||
"RescanAfterRefreshHelpTextWarning": "{appName} no detectará automáticamente cambios en los archivos si no se elige 'Siempre'",
|
||||
"RescanAfterRefreshSeriesHelpText": "Re-escanear la carpeta de series tras actualizar las series",
|
||||
"RescanAfterRefreshSeriesHelpText": "Vuelve a escanear la carpeta de series tras actualizar las series",
|
||||
"MonitorNoNewSeasons": "Sin Nuevas Temporadas",
|
||||
"MonitorSpecialEpisodesDescription": "Monitorizar todos los episodios especiales sin cambiar el estado de monitorizado de otros episodios",
|
||||
"MonitorSpecialEpisodesDescription": "Monitoriza todos los episodios especiales sin cambiar el estado de monitorizado de otros episodios",
|
||||
"Calendar": "Calendario",
|
||||
"BlocklistRelease": "Lista de bloqueos de lanzamiento",
|
||||
"CountSeasons": "{count} Temporadas",
|
||||
"BranchUpdate": "Rama a usar para actualizar {appName}",
|
||||
"ChmodFolder": "Carpeta chmod",
|
||||
"ChmodFolder": "chmod de la carpeta",
|
||||
"CheckDownloadClientForDetails": "Revisar el cliente de descarga para más detalles",
|
||||
"ChooseAnotherFolder": "Elige otra Carpeta",
|
||||
"ClientPriority": "Prioridad del Cliente",
|
||||
@@ -317,7 +317,7 @@
|
||||
"CalendarLoadError": "Incapaz de cargar el calendario",
|
||||
"CertificateValidation": "Validacion de certificado",
|
||||
"BypassProxyForLocalAddresses": "Omitir Proxy para Direcciones Locales",
|
||||
"ChangeFileDateHelpText": "Cambiar la fecha del archivo al importar/rescan",
|
||||
"ChangeFileDateHelpText": "Cambia la fecha del archivo al importar/volver a escanear",
|
||||
"ChownGroupHelpText": "Nombre del grupo o gid. Utilice gid para sistemas de archivos remotos.",
|
||||
"CloneProfile": "Clonar Perfil",
|
||||
"CollectionsLoadError": "No se han podido cargar las colecciones",
|
||||
@@ -355,7 +355,7 @@
|
||||
"Agenda": "Agenda",
|
||||
"Cancel": "Cancelar",
|
||||
"ChangeFileDate": "Cambiar fecha de archivo",
|
||||
"CertificateValidationHelpText": "Cambiar como es la validacion de la certificacion estricta de HTTPS. No cambiar a menos que entiendas las consecuencias.",
|
||||
"CertificateValidationHelpText": "Cambia cómo de estricta es la validación de certificación de HTTPS. No cambiar a menos que entiendas los riesgos.",
|
||||
"AddListExclusion": "Añadir lista de exclusión",
|
||||
"AddedDate": "Agregado: {date}",
|
||||
"AllSeriesAreHiddenByTheAppliedFilter": "Todos los resultados estan ocultos por el filtro aplicado",
|
||||
@@ -422,7 +422,7 @@
|
||||
"FailedToFetchUpdates": "Fallo al buscar las actualizaciones",
|
||||
"FailedToUpdateSettings": "Fallo al actualizar los ajustes",
|
||||
"MaintenanceRelease": "Lanzamiento de mantenimiento: Corrección de errores y otras mejoras. Ver historial de commits de Github para mas detalle",
|
||||
"CreateEmptySeriesFoldersHelpText": "Cree carpetas de series faltantes durante el análisis del disco",
|
||||
"CreateEmptySeriesFoldersHelpText": "Crea carpetas de series faltantes durante el análisis del disco",
|
||||
"DefaultCase": "Caso predeterminado",
|
||||
"Daily": "Diario",
|
||||
"CollapseMultipleEpisodesHelpText": "Contraer varios episodios que se emiten el mismo día",
|
||||
@@ -465,7 +465,7 @@
|
||||
"InteractiveImportNoQuality": "La calidad debe elegirse para cada archivo seleccionado",
|
||||
"InteractiveSearchModalHeader": "Búsqueda interactiva",
|
||||
"InvalidUILanguage": "Su interfaz de usuario está configurada en un idioma no válido, corríjalo y guarde la configuración",
|
||||
"ChownGroup": "chown grupo",
|
||||
"ChownGroup": "chown del grupo",
|
||||
"DelayProfileProtocol": "Protocolo: {preferredProtocol}",
|
||||
"DelayProfilesLoadError": "Incapaz de cargar Perfiles de Retardo",
|
||||
"ContinuingSeriesDescription": "Se esperan más episodios u otra temporada",
|
||||
@@ -598,7 +598,7 @@
|
||||
"DownloadClientNzbgetValidationKeepHistoryZero": "La configuración KeepHistory de NzbGet debería ser mayor de 0",
|
||||
"DownloadClientNzbgetValidationKeepHistoryZeroDetail": "La configuración KeepHistory de NzbGet está establecida a 0. Esto evita que {appName} vea las descargas completadas.",
|
||||
"DownloadClientDownloadStationValidationSharedFolderMissing": "La carpeta compartida no existe",
|
||||
"DownloadPropersAndRepacksHelpText": "Decidir si automáticamente actualizar a Propers/Repacks",
|
||||
"DownloadPropersAndRepacksHelpText": "Actualiza automáticamente o no a Propers/Repacks",
|
||||
"EditListExclusion": "Editar exclusión de lista",
|
||||
"EnableAutomaticAdd": "Habilitar añadido automático",
|
||||
"EditQualityProfile": "Editar perfil de calidad",
|
||||
@@ -737,7 +737,7 @@
|
||||
"DownloadClientQbittorrentSettingsInitialStateHelpText": "Estado inicial para los torrents añadidos a qBittorrent. Ten en cuenta que Forzar torrents no cumple las restricciones de semilla",
|
||||
"DownloadClientQbittorrentSettingsSequentialOrderHelpText": "Descarga en orden secuencial (qBittorrent 4.1.0+)",
|
||||
"DownloadClientDownloadStationValidationSharedFolderMissingDetail": "El Diskstation no tiene una carpeta compartida con el nombre '{sharedFolder}'. ¿Estás seguro que lo has especificado correctamente?",
|
||||
"EnableCompletedDownloadHandlingHelpText": "Importar automáticamente las descargas completas del gestor de descargas",
|
||||
"EnableCompletedDownloadHandlingHelpText": "Importa automáticamente las descargas completas del gestor de descargas",
|
||||
"EnableInteractiveSearchHelpTextWarning": "Buscar no está soportado por este indexador",
|
||||
"EnableRss": "Habilitar RSS",
|
||||
"Ended": "Terminado",
|
||||
@@ -783,7 +783,7 @@
|
||||
"FilterDoesNotEndWith": "no termina en",
|
||||
"Fixed": "Arreglado",
|
||||
"Global": "Global",
|
||||
"Enabled": "Habilitado",
|
||||
"Enabled": "Habilitada",
|
||||
"EpisodeHistoryLoadError": "No se puede cargar el historial del episodio",
|
||||
"EpisodeIsDownloading": "El episodio se está descargando",
|
||||
"EpisodeHasNotAired": "El episodio no está en emisión",
|
||||
@@ -801,7 +801,7 @@
|
||||
"GeneralSettings": "Opciones generales",
|
||||
"GeneralSettingsLoadError": "No se pueden cargar las opciones generales",
|
||||
"Grab": "Capturar",
|
||||
"GrabReleaseUnknownSeriesOrEpisodeMessageText": "{appName} no pudo determinar para qué serie y episodio era este lanzamiento. {appName} no pudo automáticamente importar este lanzamiento. ¿Te gustaría capturar '{title}'?",
|
||||
"GrabReleaseUnknownSeriesOrEpisodeMessageText": "{appName} no pudo determinar para qué serie y episodio era este lanzamiento. {appName} no pudo importar automáticamente este lanzamiento. ¿Te gustaría capturar '{title}'?",
|
||||
"HasMissingSeason": "Tiene temporadas faltantes",
|
||||
"ImportListSearchForMissingEpisodesHelpText": "Una vez se añada la serie a {appName}, buscar automáticamente episodios faltantes",
|
||||
"ImportListsSonarrValidationInvalidUrl": "La URL de {appName} es inválida. ¿Te falta la URL base?",
|
||||
@@ -989,7 +989,7 @@
|
||||
"ImportListsValidationInvalidApiKey": "La clave API es inválida",
|
||||
"ImportListsValidationTestFailed": "El test fue abortado debido a un error: {exceptionMessage}",
|
||||
"ImportScriptPathHelpText": "La ruta al script a usar para importar",
|
||||
"ImportUsingScriptHelpText": "Copiar archivos para importar usando un script (p. ej. para transcodificación)",
|
||||
"ImportUsingScriptHelpText": "Copia archivos para importar usando un script (p. ej. para transcodificación)",
|
||||
"Importing": "Importando",
|
||||
"IncludeUnmonitored": "Incluir no monitorizadas",
|
||||
"IndexerLongTermStatusAllUnavailableHealthCheckMessage": "Ningún indexador está disponible debido a errores durante más de 6 horas",
|
||||
@@ -1040,7 +1040,7 @@
|
||||
"ImportMechanismHandlingDisabledHealthCheckMessage": "Habilitar Gestión de descargas completadas",
|
||||
"ImportedTo": "Importar a",
|
||||
"IncludeCustomFormatWhenRenaming": "Incluir formato personalizado cuando se renombra",
|
||||
"CleanLibraryLevel": "Limpiar el nivel de la librería",
|
||||
"CleanLibraryLevel": "Limpiar nivel de biblioteca",
|
||||
"SearchForCutoffUnmetEpisodes": "Buscar todos los episodios con límites no alcanzados",
|
||||
"IconForSpecials": "Icono para Especiales",
|
||||
"ImportListExclusions": "Importar lista de exclusiones",
|
||||
@@ -1067,7 +1067,7 @@
|
||||
"IndexerSearchNoAutomaticHealthCheckMessage": "No hay indexadores disponibles con Búsqueda Automática activada, {appName} no proporcionará ningún resultado de búsquedas automáticas",
|
||||
"IndexerSearchNoAvailableIndexersHealthCheckMessage": "Todos los indexadores con capacidad de búsqueda no están disponibles temporalmente debido a errores recientes del indexadores",
|
||||
"IndexerSearchNoInteractiveHealthCheckMessage": "No hay indexadores disponibles con Búsqueda Interactiva activada, {appName} no proporcionará ningún resultado de búsquedas interactivas",
|
||||
"PasswordConfirmation": "Confirmación de Contraseña",
|
||||
"PasswordConfirmation": "Confirmación de contraseña",
|
||||
"IndexerSettingsAdditionalParameters": "Parámetros adicionales",
|
||||
"IndexerSettingsAllowZeroSizeHelpText": "Activar esta opción le permitirá utilizar fuentes que no especifiquen el tamaño del lanzamiento, pero tenga cuidado, no se realizarán comprobaciones relacionadas con el tamaño.",
|
||||
"IndexerSettingsAllowZeroSize": "Permitir Tamaño Cero",
|
||||
@@ -1189,7 +1189,7 @@
|
||||
"ListSyncTag": "Etiqueta de Sincronización de Lista",
|
||||
"ListSyncTagHelpText": "Esta etiqueta se añadirá cuando una serie desaparezca o ya no esté en su(s) lista(s)",
|
||||
"MetadataLoadError": "No se puede cargar Metadatos",
|
||||
"MetadataSourceSettingsSeriesSummary": "Información de dónde {appName} obtiene información de series y episodio",
|
||||
"MetadataSourceSettingsSeriesSummary": "Fuente de información de donde {appName} obtiene información de series y episodios",
|
||||
"Max": "Máximo",
|
||||
"MaximumSizeHelpText": "Tamaño máximo en MB para que un lanzamiento sea capturado. Establece a cero para establecer a ilimitado",
|
||||
"MatchedToEpisodes": "Ajustado a Episodios",
|
||||
@@ -1486,7 +1486,7 @@
|
||||
"RemoveQueueItemConfirmation": "¿Estás seguro que quieres eliminar '{sourceTitle}' de la cola?",
|
||||
"RemoveRootFolder": "Eliminar la carpeta raíz",
|
||||
"RemoveSelectedItem": "Eliminar elemento seleccionado",
|
||||
"RemoveTagsAutomaticallyHelpText": "Eliminar etiquetas automáticamente si las condiciones no se cumplen",
|
||||
"RemoveTagsAutomaticallyHelpText": "Elimina etiquetas automáticamente si las condiciones no se cumplen",
|
||||
"RemovedFromTaskQueue": "Eliminar de la cola de tareas",
|
||||
"RemovedSeriesMultipleRemovedHealthCheckMessage": "Las series {series} fueron eliminadas de TheTVDB",
|
||||
"RenameFiles": "Renombrar archivos",
|
||||
@@ -1526,7 +1526,6 @@
|
||||
"ShowQualityProfile": "Mostrar perfil de calidad",
|
||||
"ShowQualityProfileHelpText": "Muestra el perfil de calidad bajo el póster",
|
||||
"ShowRelativeDates": "Mostrar fechas relativas",
|
||||
"OnImport": "Al importar",
|
||||
"Other": "Otro",
|
||||
"ShowRelativeDatesHelpText": "Muestra fechas absolutas o relativas (Hoy/Ayer/etc)",
|
||||
"Proxy": "Proxy",
|
||||
@@ -1595,7 +1594,7 @@
|
||||
"TestAllIndexers": "Probar todos los indexadores",
|
||||
"TestAllLists": "Probar todas las listas",
|
||||
"TestParsing": "Probar análisis",
|
||||
"ThemeHelpText": "Cambiar el tema de la interfaz de la aplicación, el tema 'Auto' usará el tema de tu sistema para establecer el modo luminoso u oscuro. Inspirado por Theme.Park",
|
||||
"ThemeHelpText": "Cambia el tema de la interfaz de la aplicación, el tema 'Auto' usará el tema de tu sistema para establecer el modo luminoso u oscuro. Inspirado por Theme.Park",
|
||||
"TimeLeft": "Tiempo restante",
|
||||
"ToggleMonitoredSeriesUnmonitored ": "No se puede conmutar el estado monitorizado cuando la serie no está monitorizada",
|
||||
"Tomorrow": "Mañana",
|
||||
@@ -1621,7 +1620,7 @@
|
||||
"Upcoming": "Próximamente",
|
||||
"UpcomingSeriesDescription": "Series que han sido anunciadas pero aún no hay fecha de emisión exacta",
|
||||
"ReleaseSceneIndicatorUnknownSeries": "Episodio o serie desconocido.",
|
||||
"RemoveDownloadsAlert": "Las opciones de Eliminar fueron movidas a las opciones del cliente de descarga individual en la table anterior.",
|
||||
"RemoveDownloadsAlert": "Las opciones de eliminación fueron trasladadas a las opciones del cliente de descarga individual en la tabla anterior.",
|
||||
"RestartRequiredHelpTextWarning": "Requiere reiniciar para que tenga efecto",
|
||||
"SelectFolder": "Seleccionar carpeta",
|
||||
"TestAllClients": "Probar todos los clientes",
|
||||
@@ -1894,7 +1893,7 @@
|
||||
"UiLanguage": "Idioma de interfaz",
|
||||
"UiLanguageHelpText": "Idioma que {appName} usará en la interfaz",
|
||||
"UiSettingsSummary": "Opciones de calendario, fecha y color alterado",
|
||||
"UpdateAutomaticallyHelpText": "Descargar e instalar actualizaciones automáticamente. Todavía puedes instalar desde Sistema: Actualizaciones",
|
||||
"UpdateAutomaticallyHelpText": "Descarga e instala actualizaciones automáticamente. Podrás seguir instalándolas desde Sistema: Actualizaciones",
|
||||
"TotalRecords": "Total de registros: {totalRecords}",
|
||||
"WantMoreControlAddACustomFormat": "¿Quieres más control sobre qué descargas son preferidas? Añade un [formato personalizado](/opciones/formatospersonalizados)",
|
||||
"OrganizeModalHeader": "Organizar y renombrar",
|
||||
@@ -1916,7 +1915,7 @@
|
||||
"SelectEpisodesModalTitle": "{modalTitle} - Seleccionar episodio(s)",
|
||||
"DownloadClientDelugeSettingsDirectory": "Directorio de descarga",
|
||||
"DownloadClientDelugeSettingsDirectoryHelpText": "Ubicación opcional en la que poner las descargas, dejar en blanco para usar la ubicación predeterminada de Deluge",
|
||||
"UnmonitorSpecialsEpisodesDescription": "Dejar de monitorizar todos los episodios especiales sin cambiar el estado monitorizado de otros episodios",
|
||||
"UnmonitorSpecialsEpisodesDescription": "Deja de monitorizar todos los episodios especiales sin cambiar el estado monitorizado de otros episodios",
|
||||
"DownloadClientDelugeSettingsDirectoryCompletedHelpText": "Ubicación opcional a la que mover las descargas completadas, dejar en blanco para usar la ubicación predeterminada de Deluge",
|
||||
"DownloadClientDelugeSettingsDirectoryCompleted": "Directorio al que mover cuando se complete",
|
||||
"NotificationsDiscordSettingsWebhookUrlHelpText": "URL de canal webhook de Discord",
|
||||
@@ -2078,5 +2077,13 @@
|
||||
"TomorrowAt": "Mañana a las {time}",
|
||||
"YesterdayAt": "Ayer a las {time}",
|
||||
"TodayAt": "Hoy a las {time}",
|
||||
"DayOfWeekAt": "{day} a las {time}"
|
||||
"DayOfWeekAt": "{day} a las {time}",
|
||||
"UnableToImportAutomatically": "No se pudo importar automáticamente",
|
||||
"NotificationsPlexSettingsServer": "Servidor",
|
||||
"NotificationsPlexSettingsServerHelpText": "Selecciona el servidor desde una cuenta de plex.tv después de autenticarse",
|
||||
"CustomColonReplacement": "Reemplazo personalizado de dos puntos",
|
||||
"CustomColonReplacementFormatHelpText": "Caracteres que serán usados como reemplazo para los dos puntos",
|
||||
"CustomColonReplacementFormatHint": "Caracteres válidos del sistema de archivos como dos puntos (letra)",
|
||||
"OnFileImport": "Al importar un archivo",
|
||||
"OnImportComplete": "Al completar la importación"
|
||||
}
|
||||
|
||||
@@ -961,7 +961,7 @@
|
||||
"Global": "Yleiset",
|
||||
"GeneralSettings": "Yleiset asetukset",
|
||||
"ImportListsLoadError": "Tuontilistojen lataus epäonnistui",
|
||||
"Importing": "Tuonti",
|
||||
"Importing": "Tuodaan",
|
||||
"IndexerDownloadClientHealthCheckMessage": "Tietolähteet virheellisillä lataustyökaluilla: {indexerNames}.",
|
||||
"Indexer": "Tietolähde",
|
||||
"Location": "Sijainti",
|
||||
|
||||
@@ -299,7 +299,7 @@
|
||||
"SkipFreeSpaceCheck": "Ignorer la vérification de l'espace libre",
|
||||
"Sunday": "Dimanche",
|
||||
"TorrentDelay": "Retard du torrent",
|
||||
"DownloadClients": "Clients de téléchargement",
|
||||
"DownloadClients": "Clients de télécharg.",
|
||||
"CustomFormats": "Formats perso.",
|
||||
"NoIndexersFound": "Aucun indexeur n'a été trouvé",
|
||||
"Profiles": "Profils",
|
||||
@@ -550,7 +550,7 @@
|
||||
"LastWriteTime": "Heure de la dernière écriture",
|
||||
"LatestSeason": "Dernière saison",
|
||||
"LibraryImportTipsDontUseDownloadsFolder": "Ne l'utilisez pas pour importer des téléchargements à partir de votre client de téléchargement, cela concerne uniquement les bibliothèques organisées existantes, pas les fichiers non triés.",
|
||||
"ListWillRefreshEveryInterval": "La liste sera actualisée tous les {refreshInterval}",
|
||||
"ListWillRefreshEveryInterval": "La liste se rafraîchira toutes les {refreshInterval}",
|
||||
"ListsLoadError": "Impossible de charger les listes",
|
||||
"Local": "Locale",
|
||||
"LocalPath": "Chemin local",
|
||||
@@ -616,7 +616,7 @@
|
||||
"OnSeriesDelete": "Lors de la suppression de la série",
|
||||
"OnlyTorrent": "Uniquement Torrent",
|
||||
"OpenBrowserOnStart": "Ouvrir le navigateur au démarrage",
|
||||
"OpenSeries": "Série ouverte",
|
||||
"OpenSeries": "Ouvrir la série",
|
||||
"Options": "Options",
|
||||
"Organize": "Organiser",
|
||||
"OrganizeLoadError": "Erreur lors du chargement des aperçus",
|
||||
@@ -849,7 +849,7 @@
|
||||
"MinimumFreeSpaceHelpText": "Empêcher l'importation si elle laisse moins d'espace disque disponible",
|
||||
"MinimumLimits": "Limites minimales",
|
||||
"MinutesFortyFive": "45 Minutes : {fortyFive}",
|
||||
"Monitor": "Surveillé",
|
||||
"Monitor": "Surveiller",
|
||||
"MonitorAllEpisodesDescription": "Surveillez tous les épisodes sauf les spéciaux",
|
||||
"MonitorExistingEpisodes": "Épisodes existants",
|
||||
"MonitorExistingEpisodesDescription": "Surveiller les épisodes contenant des fichiers ou qui n'ont pas encore été diffusés",
|
||||
@@ -946,7 +946,6 @@
|
||||
"MatchedToEpisodes": "Adapté aux épisodes",
|
||||
"NoEpisodesFoundForSelectedSeason": "Aucun épisode n'a été trouvé pour la saison sélectionnée",
|
||||
"OnHealthRestored": "Sur la santé restaurée",
|
||||
"OnImport": "À l'importation",
|
||||
"OnLatestVersion": "La dernière version de {appName} est déjà installée",
|
||||
"PreferAndUpgrade": "Préférer et mettre à niveau",
|
||||
"RejectionCount": "Nombre de rejets",
|
||||
@@ -1131,7 +1130,7 @@
|
||||
"NotSeasonPack": "Pas de pack saisonnier",
|
||||
"NotificationTriggersHelpText": "Sélectionnez les événements qui doivent déclencher cette notification",
|
||||
"NotificationsTagsSeriesHelpText": "N'envoyer des notifications que pour les séries avec au moins une balise correspondante",
|
||||
"OnApplicationUpdate": "Sur la mise à jour de l'application",
|
||||
"OnApplicationUpdate": "Lors de la mise à jour de l'application",
|
||||
"OnEpisodeFileDelete": "Lors de la suppression du fichier de l'épisode",
|
||||
"OnHealthIssue": "Sur la question de la santé",
|
||||
"OnManualInteractionRequired": "Sur l'interaction manuelle requise",
|
||||
@@ -1344,7 +1343,7 @@
|
||||
"DeleteDelayProfile": "Supprimer le profil de retard",
|
||||
"DeleteDelayProfileMessageText": "Êtes-vous sûr de vouloir supprimer ce profil de retard ?",
|
||||
"DeleteEpisodeFile": "Supprimer le fichier de l'épisode",
|
||||
"DeleteEpisodeFileMessage": "Supprimer le fichier de l'épisode '{path}'?",
|
||||
"DeleteEpisodeFileMessage": "Êtes-vous sûr de vouloir supprimer « {path} » ?",
|
||||
"DeleteEpisodeFromDisk": "Supprimer l'épisode du disque",
|
||||
"DeleteImportListMessageText": "Êtes-vous sûr de vouloir supprimer la liste « {name} » ?",
|
||||
"DeleteSelectedEpisodeFiles": "Supprimer les fichiers d'épisode sélectionnés",
|
||||
@@ -1779,7 +1778,7 @@
|
||||
"NotificationsPushoverSettingsDevicesHelpText": "Liste des noms des appareils (laisser vide pour envoyer à tous les appareils)",
|
||||
"NotificationsPushoverSettingsDevices": "Appareils",
|
||||
"NotificationsPushcutSettingsTimeSensitiveHelpText": "Activer pour marquer la notification comme « Time Sensitive »",
|
||||
"NotificationsPushcutSettingsTimeSensitive": "Time Sensitive",
|
||||
"NotificationsPushcutSettingsTimeSensitive": "Sensible au temps",
|
||||
"NotificationsPushcutSettingsNotificationNameHelpText": "Nom de la notification de l'onglet Notifications de l'app Pushcut",
|
||||
"NotificationsPushcutSettingsNotificationName": "Nom de la notification",
|
||||
"NotificationsPushcutSettingsApiKeyHelpText": "Les clés API peuvent être gérées dans la vue Compte de l'app Pushcut",
|
||||
@@ -2071,5 +2070,13 @@
|
||||
"NotificationsTelegramSettingsIncludeAppName": "Inclure {appName} dans le Titre",
|
||||
"NotificationsTelegramSettingsIncludeAppNameHelpText": "Préfixer éventuellement le titre du message par {appName} pour différencier les notifications des différentes applications",
|
||||
"IndexerSettingsMultiLanguageRelease": "Multilingue",
|
||||
"IndexerSettingsMultiLanguageReleaseHelpText": "Quelles langues sont normalement présentes dans une version multiple de l'indexeur ?"
|
||||
"IndexerSettingsMultiLanguageReleaseHelpText": "Quelles langues sont normalement présentes dans une version multiple de l'indexeur ?",
|
||||
"DownloadClientQbittorrentTorrentStateMissingFiles": "qBittorrent signale des fichiers manquants",
|
||||
"BlocklistFilterHasNoItems": "La liste de blocage sélectionnée ne contient aucun élément",
|
||||
"HasUnmonitoredSeason": "A une saison non surveillée",
|
||||
"YesterdayAt": "Hier à {time}",
|
||||
"UnableToImportAutomatically": "Impossible d'importer automatiquement",
|
||||
"DayOfWeekAt": "{day} à {time}",
|
||||
"TomorrowAt": "Demain à {time}",
|
||||
"TodayAt": "Aujourd'hui à {time}"
|
||||
}
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
{}
|
||||
{
|
||||
"About": "के बारे में",
|
||||
"Absolute": "पूर्ण"
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
"ApplyChanges": "Applica Cambiamenti",
|
||||
"ApplyTags": "Applica Etichette",
|
||||
"BackupNow": "Esegui backup ora",
|
||||
"Backups": "Backups",
|
||||
"Backups": "Backup",
|
||||
"Blocklist": "Lista dei Blocchi",
|
||||
"Activity": "Attività",
|
||||
"About": "Info",
|
||||
@@ -59,12 +59,12 @@
|
||||
"AppUpdated": "{appName} Aggiornato",
|
||||
"AppUpdatedVersion": "{appName} è stato aggiornato alla versione `{version}`, per vedere le modifiche devi ricaricare {appName} ",
|
||||
"ApplicationURL": "URL Applicazione",
|
||||
"AuthenticationMethodHelpText": "Inserisci Username e Password per accedere a {appName}",
|
||||
"AuthenticationMethodHelpText": "Utilizza nome utente e password per accedere a {appName}",
|
||||
"BindAddressHelpText": "Indirizzi IP validi, localhost o '*' per tutte le interfacce",
|
||||
"BeforeUpdate": "Prima dell'aggiornamento",
|
||||
"CalendarFeed": "Feed calendario {appName}",
|
||||
"CalendarOptions": "Opzioni del Calendario",
|
||||
"ChooseImportMode": "Selezionare Metodo di Importazione",
|
||||
"ChooseImportMode": "Seleziona Metodo di Importazione",
|
||||
"CollapseMultipleEpisodes": "Collassa Episodi Multipli",
|
||||
"Conditions": "Condizioni",
|
||||
"Continuing": "In Corso",
|
||||
@@ -147,7 +147,7 @@
|
||||
"CreateGroup": "Crea gruppo",
|
||||
"DeleteEmptyFolders": "Cancella le cartelle vuote",
|
||||
"Enabled": "Abilitato",
|
||||
"UpdateMechanismHelpText": "Usa il sistema di aggiornamento interno di {appName} o uno script",
|
||||
"UpdateMechanismHelpText": "Usa il sistema di aggiornamento incorporato di {appName} o uno script",
|
||||
"AllResultsAreHiddenByTheAppliedFilter": "Tutti i risultati sono nascosti dal filtro applicato",
|
||||
"EditSelectedDownloadClients": "Modifica i Client di Download Selezionati",
|
||||
"EditSelectedImportLists": "Modifica le Liste di Importazione Selezionate",
|
||||
@@ -250,5 +250,682 @@
|
||||
"AutoRedownloadFailed": "Download fallito",
|
||||
"AddDelayProfileError": "Impossibile aggiungere un nuovo profilo di ritardo, riprova.",
|
||||
"Cutoff": "Taglio",
|
||||
"AddListExclusion": "Aggiungi elenco esclusioni"
|
||||
"AddListExclusion": "Aggiungi Lista esclusioni",
|
||||
"DownloadClientValidationApiKeyRequired": "API Key Richiesta",
|
||||
"Donate": "Dona",
|
||||
"DownloadClientDownloadStationValidationNoDefaultDestination": "Nessuna destinazione predefinita",
|
||||
"ImportListSettings": "Impostazioni delle Liste",
|
||||
"DownloadClientFreeboxSettingsAppId": "ID App",
|
||||
"DownloadClientFreeboxSettingsAppToken": "Token App",
|
||||
"DownloadClientPneumaticSettingsNzbFolderHelpText": "Questa cartella dovrà essere raggiungibile da XBMC",
|
||||
"DownloadClientPneumaticSettingsNzbFolder": "Cartella Nzb",
|
||||
"DownloadClientSabnzbdValidationEnableDisableDateSorting": "Disattiva ordinamento per data",
|
||||
"DownloadClientQbittorrentValidationCategoryUnsupported": "Categoria non è supportata",
|
||||
"DownloadClientValidationCategoryMissing": "Categoria non esiste",
|
||||
"DownloadClientRTorrentSettingsUrlPath": "Percorso Url",
|
||||
"Default": "Predefinito",
|
||||
"DownloadClientFreeboxSettingsApiUrl": "API URL",
|
||||
"DownloadClientQbittorrentValidationCategoryRecommended": "Categoria è raccomandata",
|
||||
"Discord": "Discord",
|
||||
"DownloadClientDownloadStationValidationFolderMissing": "Cartella non esiste",
|
||||
"DownloadClientValidationAuthenticationFailure": "Autenticazione Fallita",
|
||||
"DownloadClientDownloadStationValidationFolderMissingDetail": "La cartella '{downloadDir}' non esiste, deve essere creata manualmente all'interno della Cartella Condivisa '{sharedFolder}'.",
|
||||
"DownloadClientSabnzbdValidationUnknownVersion": "Versione sconosciuta: {rawVersion}",
|
||||
"DownloadClientValidationVerifySsl": "Verifica impostazioni SSL",
|
||||
"ChangeCategory": "Cambia Categoria",
|
||||
"DownloadClientPneumaticSettingsStrmFolder": "Cartella Strm",
|
||||
"Destination": "Destinazione",
|
||||
"DownloadClientDownloadStationValidationSharedFolderMissing": "Cartella condivisa non esiste",
|
||||
"DownloadClientQbittorrentValidationCategoryRecommendedDetail": "{appName} non tenterà di importare i download completati senza una categoria.",
|
||||
"DownloadClientValidationGroupMissing": "Gruppo non esistente",
|
||||
"DownloadWarning": "Avviso di download: {warningMessage}",
|
||||
"IndexerSettingsAdditionalParameters": "Parametri Addizionali",
|
||||
"IndexerSettingsCookie": "Cookie",
|
||||
"BlackholeWatchFolderHelpText": "Cartella da cui {appName} dovrebbe importare i download completati",
|
||||
"NotificationsEmailSettingsServer": "Server",
|
||||
"NotificationsNtfySettingsPasswordHelpText": "Password opzionale",
|
||||
"NotificationsPlexSettingsAuthenticateWithPlexTv": "Autentica con Plex.tv",
|
||||
"NotificationsPushcutSettingsNotificationName": "Nome Notifica",
|
||||
"NotificationsTraktSettingsExpires": "Scadenze",
|
||||
"NotificationsTraktSettingsAuthenticateWithTrakt": "Autentica con Trakt",
|
||||
"NotificationsValidationUnableToConnectToApi": "Impossibile connettersi alle API di {service}. Connessione al server fallita: ({responseCode}) {exceptionMessage}",
|
||||
"InteractiveImportNoFilesFound": "Nessun video trovato nella castella selezionata",
|
||||
"Or": "o",
|
||||
"ManageLists": "Gestisci Liste",
|
||||
"OriginalLanguage": "Lingua Originale",
|
||||
"OverrideGrabNoQuality": "Qualità deve essere selezionata",
|
||||
"XmlRpcPath": "Percorso XML RPC",
|
||||
"WouldYouLikeToRestoreBackup": "Vuoi ripristinare il backup '{name}'?",
|
||||
"PendingDownloadClientUnavailable": "In Attesa - Client di Download in attesa",
|
||||
"PreviouslyInstalled": "Precedentemente Installato",
|
||||
"MissingLoadError": "Errore caricando elementi mancanti",
|
||||
"MonitorSelected": "Monitora Selezionati",
|
||||
"Period": "Periodo",
|
||||
"RemoveFailedDownloads": "Rimuovi Download Falliti",
|
||||
"RemoveMultipleFromDownloadClientHint": "Rimuovi i download e i file dal client di download",
|
||||
"RemoveSelectedItemQueueMessageText": "Sei sicuro di voler rimuovere 1 elemento dalla coda?",
|
||||
"TagDetails": "Dettagli Etichetta - {label}",
|
||||
"BranchUpdate": "Branca da usare per aggiornare {appName}",
|
||||
"DefaultNotFoundMessage": "Ti devi essere perso, non c'è nulla da vedere qui.",
|
||||
"DeleteIndexerMessageText": "Sicuro di voler eliminare l'indicizzatore '{name}'?",
|
||||
"Socks5": "Socks5 (Supporto TOR)",
|
||||
"DeleteEpisodeFileMessage": "Sei sicuro di volere eliminare '{path}'?",
|
||||
"NotificationsKodiSettingsCleanLibraryHelpText": "Pulisci libreria dopo l'aggiornamento",
|
||||
"PreferProtocol": "Preferisci {preferredProtocol}",
|
||||
"RetryingDownloadOn": "Riprovando il download il {date} alle {time}",
|
||||
"DeleteNotificationMessageText": "Sei sicuro di voler eliminare la notifica '{name}'?",
|
||||
"RemoveCompletedDownloads": "Rimuovi Download Completati",
|
||||
"DownloadClientFloodSettingsAdditionalTags": "Tag addizionali",
|
||||
"DelayingDownloadUntil": "Ritardare il download fino al {date} alle {time}",
|
||||
"DeleteDownloadClientMessageText": "Sei sicuro di voler eliminare il client di download '{name}'?",
|
||||
"NoHistoryFound": "Nessun storico trovato",
|
||||
"OneMinute": "1 Minuto",
|
||||
"OptionalName": "Nome opzionale",
|
||||
"DeleteSelectedIndexers": "Elimina Indicizzatore/i",
|
||||
"Branch": "Branca",
|
||||
"Debug": "Debug",
|
||||
"Never": "Mai",
|
||||
"UsenetDelayTime": "Ritardo Usenet: {usenetDelay}",
|
||||
"OrganizeModalHeader": "Organizza & Rinomina",
|
||||
"Parse": "Analizza",
|
||||
"RemoveFromDownloadClient": "Rimuovi dal client di download",
|
||||
"RemoveQueueItemConfirmation": "Sei sicuro di voler rimuovere '{sourceTitle}' dalla coda?",
|
||||
"NoIndexersFound": "Nessun indicizzatore trovato",
|
||||
"DeleteImportListMessageText": "Sei sicuro di volere eliminare la lista '{name}'?",
|
||||
"DeleteDelayProfile": "Elimina Profilo di Ritardo",
|
||||
"DeleteTagMessageText": "Sei sicuro di voler eliminare l'etichetta '{label}'?",
|
||||
"MinutesSixty": "60 Minuti: {sixty}",
|
||||
"NotificationsCustomScriptSettingsName": "Script personalizzato",
|
||||
"NotificationsCustomScriptValidationFileDoesNotExist": "File non esiste",
|
||||
"Database": "Database",
|
||||
"NotificationsPushoverSettingsExpire": "Scadenza",
|
||||
"NotificationsSettingsWebhookMethod": "Metodo",
|
||||
"NotificationsSynologyValidationInvalidOs": "Deve essere un Synology",
|
||||
"NotificationsTraktSettingsRefreshToken": "Refresh Token",
|
||||
"CouldNotFindResults": "Nessun risultato trovato per '{term}'",
|
||||
"IndexerSettingsApiPath": "Percorso API",
|
||||
"AutoTaggingSpecificationMaximumYear": "Anno Massimo",
|
||||
"AutoTaggingSpecificationGenre": "Genere/i",
|
||||
"AutoTaggingSpecificationMinimumYear": "Anno Minimo",
|
||||
"AutoTaggingSpecificationOriginalLanguage": "Lingua",
|
||||
"AutoTaggingSpecificationQualityProfile": "Profilo Qualità",
|
||||
"AutoTaggingSpecificationRootFolder": "Cartella Radice",
|
||||
"AutoTaggingSpecificationStatus": "Stato",
|
||||
"CustomFormatsSpecificationLanguage": "Linguaggio",
|
||||
"CustomFormatsSpecificationMaximumSize": "Dimensione Massima",
|
||||
"CustomFormatsSpecificationMinimumSize": "Dimensione Minima",
|
||||
"DelayProfile": "Profilo di Ritardo",
|
||||
"DeleteBackupMessageText": "Sei sicuro di voler cancellare il backup '{name}'?",
|
||||
"DeleteDelayProfileMessageText": "Sei sicuro di volere eliminare questo profilo di ritardo?",
|
||||
"NotificationsTelegramSettingsSendSilentlyHelpText": "Invia il messaggio silenziosamente. L'utente riceverà una notifica senza suono",
|
||||
"NotificationsPushoverSettingsRetry": "Riprova",
|
||||
"NotificationsSettingsWebhookUrl": "URL Webhook",
|
||||
"PackageVersionInfo": "{packageVersion} di {packageAuthor}",
|
||||
"RemoveQueueItem": "Rimuovi - {sourceTitle}",
|
||||
"ParseModalErrorParsing": "Errore durante l'analisi, per favore prova di nuovo.",
|
||||
"OverrideGrabNoLanguage": "Almeno una lingua deve essere selezionata",
|
||||
"PasswordConfirmation": "Conferma Password",
|
||||
"RemoveSelectedItemsQueueMessageText": "Sei sicuro di voler rimuovere {selectedCount} elementi dalla coda?",
|
||||
"ConnectionLostToBackend": "{appName} ha perso la connessione al backend e dovrà essere ricaricato per ripristinare la funzionalità.",
|
||||
"CountIndexersSelected": "{count} indicizzatore(i) selezionato(i)",
|
||||
"CountDownloadClientsSelected": "{count} client di download selezionato/i",
|
||||
"PrioritySettings": "Priorità: {priority}",
|
||||
"OverrideAndAddToDownloadQueue": "Sovrascrivi e aggiungi alla coda di download",
|
||||
"NotificationsSettingsUseSslHelpText": "Connetti a {serviceName} tramite HTTPS indece di HTTP",
|
||||
"OrganizeRelativePaths": "Tutti i percorsi sono relativi a: `{path}`",
|
||||
"CurrentlyInstalled": "Attualmente Installato",
|
||||
"NotificationsEmailSettingsName": "Email",
|
||||
"NotificationsNtfySettingsServerUrl": "URL Server",
|
||||
"NotificationsPushoverSettingsSound": "Suono",
|
||||
"NotificationsSignalValidationSslRequired": "SSL sembra essere richiesto",
|
||||
"TorrentDelayTime": "Ritardo torrent: {torrentDelay}",
|
||||
"NotificationsTwitterSettingsMention": "Menziona",
|
||||
"NotificationsPushoverSettingsDevices": "Dispositivi",
|
||||
"NotificationsTelegramSettingsSendSilently": "Invia Silenziosamente",
|
||||
"DatabaseMigration": "Migrazione Database",
|
||||
"AutoTaggingSpecificationTag": "Etichetta",
|
||||
"CustomFormatUnknownConditionOption": "Opzione sconosciuta '{key}' per la condizione '{implementation}'",
|
||||
"CustomFormatsSpecificationResolution": "Risoluzione",
|
||||
"CustomFormatsSpecificationSource": "Fonte",
|
||||
"BlocklistAndSearch": "Lista dei Blocchi e Ricerca",
|
||||
"NotificationsEmbySettingsSendNotifications": "Invia Notifiche",
|
||||
"IndexerHDBitsSettingsMediumsHelpText": "Se non specificato, saranno utilizzate tutte le opzioni.",
|
||||
"DeleteQualityProfile": "Elimina Profilo Qualità",
|
||||
"DeleteSelectedEpisodeFiles": "Elimina i File degli Episodi Selezionati",
|
||||
"DeleteEpisodesFiles": "Elimina i File di {episodeFileCount} Episodi",
|
||||
"CustomFilter": "Filtro Personalizzato",
|
||||
"NotificationsTelegramSettingsIncludeAppName": "Includi {appName} nel Titolo",
|
||||
"IndexerHDBitsSettingsCodecsHelpText": "Se non specificato, saranno utilizzate tutte le opzioni.",
|
||||
"NotificationsGotifySettingsAppToken": "App Token",
|
||||
"InfoUrl": "URL Info",
|
||||
"ConnectionLostReconnect": "{appName} cercherà di connettersi automaticamente, oppure clicca su ricarica qui sotto.",
|
||||
"ListWillRefreshEveryInterval": "Le liste verranno aggiornate ogni {refreshInterval}",
|
||||
"NotificationsNtfySettingsServerUrlHelpText": "Lascia vuoto per usare il server pubblico {url}",
|
||||
"NotificationsTwitterSettingsMentionHelpText": "Menziona questo utente nei tweet inviati",
|
||||
"NotificationsValidationUnableToSendTestMessageApiResponse": "Impossibile inviare messaggio di prova. Risposta dalle API: {error}",
|
||||
"RemoveFromDownloadClientHint": "Rimuovi il download e i file dal client di download",
|
||||
"DayOfWeekAt": "{day} alle {time}",
|
||||
"DeleteRootFolder": "Elimina Cartella Radice",
|
||||
"DeleteRootFolderMessageText": "Sei sicuro di volere eliminare la cartella radice '{path}'?",
|
||||
"ManageIndexers": "Gestisci Indicizzatori",
|
||||
"MissingNoItems": "Nessun elemento mancante",
|
||||
"NotificationsKodiSettingsCleanLibrary": "Pulisci Libreria",
|
||||
"NotificationsNtfySettingsUsernameHelpText": "Nome utente opzionale",
|
||||
"NotificationsSettingsUpdateLibrary": "Aggiorna Libreria",
|
||||
"NotificationsSlackSettingsChannel": "Canale",
|
||||
"NotificationsSlackSettingsIcon": "Icona",
|
||||
"NotificationsTelegramSettingsBotToken": "Token Bot",
|
||||
"NotificationsTwitterSettingsAccessToken": "Access Token",
|
||||
"NotificationsTwitterSettingsConnectToTwitter": "Connetti a Twitter / X",
|
||||
"NotificationsTwitterSettingsDirectMessage": "Messaggio Diretto",
|
||||
"NotificationsValidationInvalidUsernamePassword": "Nome Utente o password non validi",
|
||||
"NotificationsValidationUnableToConnect": "Impossibile connettersi: {exceptionMessage}",
|
||||
"NotificationsValidationUnableToConnectToService": "Impossibile connettersi a {serviceName}",
|
||||
"NotificationsValidationUnableToSendTestMessage": "Impossibile inviare messaggio di prova: {exceptionMessage}",
|
||||
"ThemeHelpText": "Cambia il Tema dell'interfaccia dell’applicazione, il Tema 'Auto' userà il suo Tema di Sistema per impostare la modalità Chiara o Scura. Ispirato da Theme.Park",
|
||||
"Torrents": "Torrents",
|
||||
"Upcoming": "In arrivo",
|
||||
"DownloadClientUTorrentTorrentStateError": "uTorrent sta segnalando un errore",
|
||||
"DownloadClientValidationSslConnectFailure": "Impossibile connettersi tramite SSL",
|
||||
"ErrorLoadingContent": "Si è verificato un errore caricando questo contenuto",
|
||||
"FilterDoesNotStartWith": "non inizia con",
|
||||
"Filters": "Filtri",
|
||||
"IgnoreDownloads": "Ignora Download",
|
||||
"IndexerSettingsApiPathHelpText": "Percorso API, solitamente {url}",
|
||||
"BlackholeFolderHelpText": "Cartella nella quale {appName} salverà i file di tipo {extension}",
|
||||
"UseSeasonFolder": "Usa Cartella Stagione",
|
||||
"Monday": "Lunedì",
|
||||
"DetailedProgressBarHelpText": "Mostra testo sulla barra di avanzamento",
|
||||
"DownloadClientValidationUnknownException": "Eccezione sconosciuta: {exception}",
|
||||
"OnlyTorrent": "Solo Torrent",
|
||||
"OpenBrowserOnStart": "Apri browser all'avvio",
|
||||
"OnlyUsenet": "Solo Usenet",
|
||||
"OpenSeries": "Apri Serie",
|
||||
"Organize": "Organizza",
|
||||
"Other": "Altri",
|
||||
"Yesterday": "Ieri",
|
||||
"Paused": "In Pausa",
|
||||
"Priority": "Priorità",
|
||||
"Metadata": "Metadati",
|
||||
"Quality": "Qualità",
|
||||
"MidseasonFinale": "Finale di Metà Stagione",
|
||||
"QualityProfile": "Profilo Qualità",
|
||||
"MinimumAge": "Età Minima",
|
||||
"ShowAdvanced": "Mostra Avanzate",
|
||||
"MonitorFirstSeason": "Prima Stagione",
|
||||
"MonitoredOnly": "Solo Monitorati",
|
||||
"MoreInfo": "Ulteriori Informazioni",
|
||||
"FormatRuntimeMinutes": "{minutes}m",
|
||||
"Options": "Opzioni",
|
||||
"PartialSeason": "Stagione Parziale",
|
||||
"Port": "Porta",
|
||||
"PreferTorrent": "Preferisci Torrent",
|
||||
"Reset": "Reimposta",
|
||||
"RssIsNotSupportedWithThisIndexer": "RSS non è supportato con questo indicizzatore",
|
||||
"PublishedDate": "Data Pubblicazione",
|
||||
"SeriesDetailsGoTo": "Vai a {title}",
|
||||
"Security": "Sicurezza",
|
||||
"Settings": "Impostazioni",
|
||||
"ShowDateAdded": "Mostra Data Aggiunta",
|
||||
"Reason": "Ragione",
|
||||
"RecyclingBin": "Cestino",
|
||||
"SpecialEpisode": "Episodio Speciale",
|
||||
"Space": "Spazio",
|
||||
"SslPort": "Porta SSL",
|
||||
"StartImport": "Inizia Importazione",
|
||||
"Test": "Prova",
|
||||
"Titles": "Titoli",
|
||||
"Result": "Risultato",
|
||||
"Unavailable": "Non disponibile",
|
||||
"SearchSelected": "Ricerca Selezionate",
|
||||
"SeasonCount": "Conteggio Stagioni",
|
||||
"Season": "Stagione",
|
||||
"SeriesType": "Tipo Serie",
|
||||
"ShowNetwork": "Mostra Rete",
|
||||
"MoveSeriesFoldersMoveFiles": "Sì, Sposta i File",
|
||||
"Negated": "Negato",
|
||||
"SizeOnDisk": "Dimensione sul disco",
|
||||
"Sort": "Ordina",
|
||||
"FilterSeriesPlaceholder": "Filtra serie",
|
||||
"FormatShortTimeSpanHours": "{hours} ora/e",
|
||||
"Monitoring": "Monitorando",
|
||||
"Month": "Mese",
|
||||
"MonitoredEpisodesHelpText": "Scarica gli episodi monitorati in questa serie",
|
||||
"NoChanges": "Nessun Cambiamento",
|
||||
"NotificationsNtfyValidationAuthorizationRequired": "Autorizzazione richiesta",
|
||||
"PreferredProtocol": "Protocollo Preferito",
|
||||
"QualitiesHelpText": "Qualità più alte nella lista sono quelle preferite. Qualità all'interno dello stesso gruppo sono equivalenti. Solo le qualità selezionate saranno ricercate",
|
||||
"Real": "Reale",
|
||||
"RefreshAndScanTooltip": "Aggiorna informazioni e scansiona disco",
|
||||
"SeriesIndexFooterMissingMonitored": "Episodi Mancanti (Serie monitorate)",
|
||||
"SingleEpisode": "Episodio Singolo",
|
||||
"Shutdown": "Spegnimento",
|
||||
"Wiki": "Wiki",
|
||||
"True": "Vero",
|
||||
"WhatsNew": "Cosa c'è di nuovo?",
|
||||
"SelectQuality": "Seleziona Qualità",
|
||||
"SelectLanguages": "Seleziona Lingue",
|
||||
"TableOptions": "Opzioni Tabella",
|
||||
"Tba": "TBA",
|
||||
"TablePageSizeMinimum": "La dimensione della pagina deve essere almeno {minimumValue}",
|
||||
"Theme": "Tema",
|
||||
"Updates": "Aggiornamenti",
|
||||
"VersionNumber": "Versione {version}",
|
||||
"EditSelectedIndexers": "Modifica Indicizzatori Selezionati",
|
||||
"Example": "Esempio",
|
||||
"FilterContains": "contiene",
|
||||
"FilterDoesNotContain": "non contiene",
|
||||
"FilterIsAfter": "è dopo",
|
||||
"FilterIsBefore": "è prima",
|
||||
"FilterIs": "è",
|
||||
"FilterLessThanOrEqual": "meno o uguale di",
|
||||
"FilterNotEqual": "non uguale",
|
||||
"DownloadClientFreeboxApiError": "Le API di Freebox hanno segnalato un errore: {errorDescription}",
|
||||
"DailyEpisodeFormat": "Formato Episodi Giornalieri",
|
||||
"FileManagement": "Gestione File",
|
||||
"MissingEpisodes": "Episodi Mancanti",
|
||||
"Mode": "Modalità",
|
||||
"MonitorAllEpisodesDescription": "Monitora tutti gli episodi esclusi gli speciali",
|
||||
"MonitorAllEpisodes": "Tutti gli Episodi",
|
||||
"MonitorExistingEpisodes": "Episodi Esistenti",
|
||||
"Preferred": "Preferito",
|
||||
"Scene": "Scene",
|
||||
"SizeLimit": "Limite Dimensione",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "Tipo",
|
||||
"DownloadClientNzbgetSettingsAddPausedHelpText": "Questa opzione richiede almeno la versione 16.0 di NzbGet",
|
||||
"System": "Sistema",
|
||||
"CollectionsLoadError": "Impossibile caricare le collezioni",
|
||||
"ConnectSettingsSummary": "Notifiche, connessioni a media servers/players, e script personalizzati",
|
||||
"Folders": "Cartelle",
|
||||
"PreferredSize": "Dimensione Preferita",
|
||||
"Proxy": "Proxy",
|
||||
"DownloadClientQbittorrentSettingsUseSslHelpText": "Usa una connessione sicura. Vedi Opzioni -> Web UI -> 'Usa HTTPS invece di HTTP' in qBittorrent.",
|
||||
"DownloadClientQbittorrentTorrentStateError": "qBittorrent sta segnalando un errore",
|
||||
"TimeLeft": "Tempo Rimasto",
|
||||
"Unlimited": "Illimitato",
|
||||
"Title": "Titolo",
|
||||
"Original": "Originale",
|
||||
"Path": "Percorso",
|
||||
"MaximumSize": "Dimensione Massima",
|
||||
"ProgressBarProgress": "Barra Progressi al {progress}%",
|
||||
"RootFolderSelectFreeSpace": "{freeSpace} Libero",
|
||||
"RssSync": "Sincronizza RSS",
|
||||
"SaveSettings": "Salva Impostazioni",
|
||||
"Search": "Ricerca",
|
||||
"SearchForMissing": "Ricerca dei Mancanti",
|
||||
"SearchForMonitoredEpisodes": "Ricerca degli episodi monitorati",
|
||||
"SeasonFolder": "Cartella della Stagione",
|
||||
"SeasonNumber": "Numero Stagione",
|
||||
"SelectLanguageModalTitle": "{modalTitle} - Seleziona Lingua",
|
||||
"SeriesDetailsRuntime": "{runtime} Minuti",
|
||||
"SeriesIsUnmonitored": "Serie non monitorata",
|
||||
"SeriesProgressBarText": "{episodeFileCount} / {episodeCount} (Totale: {totalEpisodeCount}, Scaricando: {downloadingCount})",
|
||||
"ShowEpisodes": "Mostra Episodi",
|
||||
"ShowEpisodeInformationHelpText": "Mostra titolo e numero dell'episodio",
|
||||
"Source": "Fonte",
|
||||
"Unknown": "Sconosciuto",
|
||||
"UseSsl": "Usa SSL",
|
||||
"DownloadClientSettingsDestinationHelpText": "Specifica manualmente la destinazione dei download, lascia vuoti per usare la predefinita",
|
||||
"DownloadClientSettingsInitialState": "Stato Iniziale",
|
||||
"Folder": "Cartella",
|
||||
"TorrentBlackholeSaveMagnetFilesReadOnly": "Solo Lettura",
|
||||
"Ui": "Interfaccia",
|
||||
"UiLanguage": "Lingua Interfaccia",
|
||||
"UiSettingsLoadError": "Impossibile caricare le impostazioni interfaccia",
|
||||
"MustNotContain": "Non Deve Contenere",
|
||||
"Network": "Rete",
|
||||
"ReadTheWikiForMoreInformation": "Leggi la Wiki per più informazioni",
|
||||
"RecentChanges": "Cambiamenti Recenti",
|
||||
"Refresh": "Aggiorna",
|
||||
"DownloadClientSettingsUseSslHelpText": "Usa connessione sicura quando connetti a {clientName}",
|
||||
"SelectEpisodes": "Seleziona Episodio/i",
|
||||
"TestAll": "Prova Tutto",
|
||||
"SelectFolder": "Seleziona Cartella",
|
||||
"DownloadStationStatusExtracting": "Estrazione: {progress}&",
|
||||
"DownloadClientQbittorrentSettingsSequentialOrder": "Ordine Sequenziale",
|
||||
"DownloadClientQbittorrentValidationCategoryAddFailureDetail": "{appName} non è stato in grado di aggiungere l'etichetta a qBittorrent.",
|
||||
"DownloadClientQbittorrentSettingsSequentialOrderHelpText": "Scarica in ordine sequenziale (qBittorrent 4.1.0+)",
|
||||
"MegabytesPerMinute": "Megabyte Per Minuto",
|
||||
"MonitorFirstSeasonDescription": "Monitora tutti gli episodi delle prima stagione. Tutte le altre stagioni saranno ignorate",
|
||||
"MustContain": "Deve Contenere",
|
||||
"PreferUsenet": "Preferisci Usenet",
|
||||
"NoChange": "Nessun Cambio",
|
||||
"RestoreBackup": "Ripristina Backup",
|
||||
"SelectAll": "Seleziona Tutto",
|
||||
"SelectSeries": "Seleziona Serie",
|
||||
"SeriesTitle": "Titolo Serie",
|
||||
"ShowPath": "Mostra Percorso",
|
||||
"Table": "Tabella",
|
||||
"TheTvdb": "TheTVDB",
|
||||
"Total": "Totale",
|
||||
"TotalFileSize": "Totale Dimensione File",
|
||||
"DownloadClientQbittorrentTorrentStateMetadata": "qBittorrent sta scaricando i metadati",
|
||||
"DownloadClientQbittorrentTorrentStateUnknown": "Stato di download sconosciuto: {state}",
|
||||
"External": "Esterno",
|
||||
"Failed": "Fallito",
|
||||
"FilterLessThan": "meno di",
|
||||
"FilterDoesNotEndWith": "non termina con",
|
||||
"FilterEqual": "uguale",
|
||||
"FormatDateTimeRelative": "{relativeDay}, {formattedDate} {formattedTime}",
|
||||
"FormatShortTimeSpanMinutes": "{minutes} minuto/i",
|
||||
"InvalidUILanguage": "L'interfaccia è impostata in una lingua non valida, correggi e salva le tue impostazioni",
|
||||
"Max": "Massimo",
|
||||
"MinutesFortyFive": "45 Minuti: {fortyFive}",
|
||||
"NoDownloadClientsFound": "Nessun client di download trovato",
|
||||
"MassSearchCancelWarning": "Questo non può essere cancellato una volta avviato senza riavviare {appName} o disattivando tutti i tuoi indicizzatori.",
|
||||
"Profiles": "Profili",
|
||||
"Qualities": "Qualità",
|
||||
"QualityProfilesLoadError": "Impossibile caricare Profili Qualità",
|
||||
"QueueLoadError": "Impossibile caricare la Coda",
|
||||
"Queued": "In Coda",
|
||||
"SaveChanges": "Salva Cambiamenti",
|
||||
"Seasons": "Stagioni",
|
||||
"Series": "Serie",
|
||||
"MonitorRecentEpisodes": "Episodi Recenti",
|
||||
"MoreDetails": "Ulteriore dettagli",
|
||||
"MonitorSpecialEpisodes": "Monitora Speciali",
|
||||
"TimeFormat": "Formato Orario",
|
||||
"UsenetDisabled": "Usenet Disabilitato",
|
||||
"Version": "Versione",
|
||||
"WithFiles": "Con i File",
|
||||
"Username": "Nome Utente",
|
||||
"YesCancel": "Sì, Cancella",
|
||||
"Yes": "Sì",
|
||||
"DownloadClientRTorrentSettingsAddStopped": "Aggiungi Fermato",
|
||||
"Restart": "Riavvia",
|
||||
"Rss": "RSS",
|
||||
"ProxyBadRequestHealthCheckMessage": "Test del proxy fallito: Status Code: {statusCode}",
|
||||
"ProxyBypassFilterHelpText": "Usa ',' come separatore, e '*.' come wildcard per i sottodomini",
|
||||
"RestartRequiredToApplyChanges": "{appName} richiede un riavvio per applicare i cambiamenti, vuoi riavviare ora?",
|
||||
"SearchMonitored": "Ricerca Monitorate",
|
||||
"SeasonDetails": "Dettagli Stagione",
|
||||
"SelectDownloadClientModalTitle": "{modalTitle} - Seleziona Client di Download",
|
||||
"SelectDropdown": "Seleziona...",
|
||||
"SeriesIsMonitored": "Serie monitorata",
|
||||
"Special": "Speciale",
|
||||
"TablePageSizeMaximum": "La dimensione della pagina non deve superare {maximumValue}",
|
||||
"TablePageSize": "Dimensione Pagina",
|
||||
"UnknownDownloadState": "Stato download sconosciuto: {state}",
|
||||
"UsenetBlackholeNzbFolder": "Cartella Nzb",
|
||||
"From": "Da",
|
||||
"QualityProfiles": "Profili Qualità",
|
||||
"RecyclingBinCleanupHelpText": "Imposta a 0 per disattivare la pulizia automatica",
|
||||
"RefreshAndScan": "Aggiorna & Scansiona",
|
||||
"HourShorthand": "h",
|
||||
"InteractiveImportNoImportMode": "Una modalità di importazione deve essere selezionata",
|
||||
"MyComputer": "Mio Computer",
|
||||
"Posters": "Locandine",
|
||||
"SeasonNumberToken": "Stagione {seasonNumber}",
|
||||
"ShowTitle": "Mostra Titolo",
|
||||
"TorrentBlackholeTorrentFolder": "Cartella Torrent",
|
||||
"UiLanguageHelpText": "Lingua che {appName} userà per l'interfaccia",
|
||||
"DownloadIgnored": "Download Ignorato",
|
||||
"CustomFormatsSpecificationMaximumSizeHelpText": "La release deve essere minore o uguale a questa dimensione",
|
||||
"CustomFormatsSpecificationMinimumSizeHelpText": "La release deve essere maggiore di questa dimensione",
|
||||
"CustomFormatsSpecificationRegularExpression": "Espressione Regolare",
|
||||
"DefaultDelayProfileSeries": "Questo è il profilo di default. Viene Applicato a tutte le serie che non hanno in profilo esplicito.",
|
||||
"DownloadClientDelugeTorrentStateError": "Deluge sta segnalando un errore",
|
||||
"DownloadClientDelugeSettingsUrlBaseHelpText": "Aggiungi un prefisso all'url del json di deluge, vedi {url}",
|
||||
"FilterEpisodesPlaceholder": "Filtra episodi per titolo o numero",
|
||||
"FilterGreaterThanOrEqual": "più grande o uguale di",
|
||||
"FilterIsNot": "non è",
|
||||
"FilterGreaterThan": "più grande di",
|
||||
"Formats": "Formati",
|
||||
"FormatRuntimeHours": "{hours}h",
|
||||
"FirstDayOfWeek": "Primo Giorno della Settimana",
|
||||
"FreeSpace": "Spazio Libero",
|
||||
"FormatDateTime": "{formattedDate} {formattedTime}",
|
||||
"FormatTimeSpanDays": "{days}d {time}",
|
||||
"MetadataSettingsSeriesImages": "Immagini della Serie",
|
||||
"MetadataSettingsSeriesMetadata": "Metadati della Serie",
|
||||
"MetadataSettingsSeasonImages": "Immagini della Stagione",
|
||||
"NotificationsEmailSettingsBccAddress": "Indirizzo/i BCC",
|
||||
"OrganizeLoadError": "Errore caricando le anteprime",
|
||||
"OrganizeSelectedSeriesModalHeader": "Organizza Serie Selezionate",
|
||||
"Today": "Oggi",
|
||||
"Specials": "Speciali",
|
||||
"NotificationsLoadError": "Impossibile caricare Notifiche",
|
||||
"SeasonPassTruncated": "Solo le ultime 25 stagione sono mostrate, vai ai dettagli per vedere tutte le stagioni",
|
||||
"SeriesCannotBeFound": "Scusa, quella serie non può essere trovata.",
|
||||
"Style": "Stile",
|
||||
"NotificationsEmailSettingsCcAddress": "Indirizzo/i CC",
|
||||
"NotificationsMailgunSettingsUseEuEndpoint": "Usa Endpoint EU",
|
||||
"Pending": "In Attesa",
|
||||
"PendingChangesStayReview": "Rimani e rivedi i cambiamenti",
|
||||
"FormatAgeDays": "giorni",
|
||||
"FormatAgeHour": "ora",
|
||||
"FormatAgeHours": "ore",
|
||||
"FormatAgeMinute": "minuto",
|
||||
"FormatAgeMinutes": "minuti",
|
||||
"FormatAgeDay": "giorno",
|
||||
"MetadataPlexSettingsSeriesPlexMatchFileHelpText": "Crea un file .plexmatch nella cartella della serie",
|
||||
"MonitorMissingEpisodes": "Episodi Mancanti",
|
||||
"New": "Nuovo",
|
||||
"NoBackupsAreAvailable": "Nessun backup disponibile",
|
||||
"MetadataSettingsEpisodeImages": "Immagini dell'Episodio",
|
||||
"PosterSize": "Dimensioni Locandina",
|
||||
"Restore": "Ripristina",
|
||||
"RestartReloadNote": "Nota: {appName} si riavvierà automaticamente e ricaricherà l'interfaccia durante il processo di ripristino.",
|
||||
"SeasonPassEpisodesDownloaded": "{episodeFileCount}/{totalEpisodeCount} episodi scaricati",
|
||||
"SelectLanguage": "Seleziona Lingua",
|
||||
"SeriesIndexFooterDownloading": "Scaricando (Uno o più episodi)",
|
||||
"SeriesTypes": "Tipi Serie",
|
||||
"SetPermissions": "Imposta Permessi",
|
||||
"StartupDirectory": "Cartella di Avvio",
|
||||
"Tomorrow": "Domani",
|
||||
"UnknownEventTooltip": "Evento sconosciuto",
|
||||
"UseProxy": "Usa Proxy",
|
||||
"InteractiveImportNoQuality": "Una qualità deve essere scelta per ogni file selezionato",
|
||||
"PortNumber": "Numero Porta",
|
||||
"MonitorAllSeasons": "Tutte le Stagioni",
|
||||
"DownloadClientValidationUnableToConnect": "Impossibile connettersi a {clientName}",
|
||||
"DownloadClientValidationVerifySslDetail": "Per favore verifica la tua configurazione SSL su entrambi {clientName} e {appName}",
|
||||
"IndexerDownloadClientHealthCheckMessage": "Indicizzatori con client di download non validi: {indexerNames}.",
|
||||
"MonitorAllSeasonsDescription": "Monitora tutte le nuove stagioni automaticamente",
|
||||
"MonitorFutureEpisodes": "Episodi Futuri",
|
||||
"No": "No",
|
||||
"MonitorLastSeason": "Ultima Stagione",
|
||||
"NoEpisodesInThisSeason": "Nessun episodio in questa stagione",
|
||||
"OrganizeModalHeaderSeason": "Organizza & Rinomina - {season}",
|
||||
"Save": "Salva",
|
||||
"More": "Altro",
|
||||
"MonitorLastSeasonDescription": "Monitora tutti gli episodi della ultima stagione",
|
||||
"RestartSonarr": "Riavvia {appName}",
|
||||
"SeasonFinale": "Finale di Stagione",
|
||||
"RestartNow": "Riavvia ora",
|
||||
"TablePageSizeHelpText": "Numero di elementi da mostrare in ogni pagina",
|
||||
"UiSettings": "Impostazioni Interfaccia",
|
||||
"TvdbId": "ID TVDB",
|
||||
"Wanted": "Ricercato",
|
||||
"CustomFormatsLoadError": "Impossibile a caricare Formati Personalizzati",
|
||||
"FilterEndsWith": "termina con",
|
||||
"MetadataSource": "Fonte Metadati",
|
||||
"Monitored": "Monitorato",
|
||||
"MoveSeriesFoldersDontMoveFiles": "No, Sposterò i File da Solo",
|
||||
"RemoveQueueItemRemovalMethod": "Metodo di Rimozione",
|
||||
"SecretToken": "Secret Token",
|
||||
"UrlBase": "Base Url",
|
||||
"NotificationsEmailSettingsFromAddress": "Dall'Indirizzo",
|
||||
"NotificationsGotifySettingsServer": "Server Gotify",
|
||||
"NotificationsGotifySettingsPriorityHelpText": "Priorità della notifica",
|
||||
"Score": "Punteggio",
|
||||
"SelectSeasonModalTitle": "{modalTitle} - Seleziona Stagione",
|
||||
"UpdateAvailableHealthCheckMessage": "Nuovo aggiornamento disponibile",
|
||||
"Permissions": "Permessi",
|
||||
"Scheduled": "Pianificato",
|
||||
"SearchAll": "Ricerca tutto",
|
||||
"VisitTheWikiForMoreDetails": "Visita la wiki per ulteriori dettagli: ",
|
||||
"Week": "Settimana",
|
||||
"DownloadClientValidationSslConnectFailureDetail": "{appName} non è in grado di connettersi a {clientName} usando SSL. Questo problema potrebbe essere legato al computer. Prova a configurare entrambi {appName} e {clientName} senza usare SSL.",
|
||||
"LogFilesLocation": "File di Log localizzati in: {location}",
|
||||
"PendingChangesMessage": "Hai dei cambiamenti non salvati, sei sicuro di volere lasciare questa pagina?",
|
||||
"NotificationsEmailSettingsUseEncryption": "Usa Crittografia",
|
||||
"DailyEpisodeTypeDescription": "Episodi rilasciati giornalmente o meno frequentemente che usano anno-mese-giorno (2023-08-04)",
|
||||
"DownloadClientQbittorrentTorrentStateMissingFiles": "qBittorrent sta segnalando dei file mancanti",
|
||||
"NoEventsFound": "Nessun evento trovato",
|
||||
"SearchIsNotSupportedWithThisIndexer": "Ricerca non supportata con questo indicizzatore",
|
||||
"SelectReleaseType": "Seleziona Tipo Release",
|
||||
"Uppercase": "Maiuscolo",
|
||||
"False": "Falso",
|
||||
"Files": "File",
|
||||
"Filter": "Filtro",
|
||||
"OverrideGrabNoEpisode": "Almeno un episodio deve essere selezionato",
|
||||
"FilterStartsWith": "inizia con",
|
||||
"FinaleTooltip": "Serie o finale di stagione",
|
||||
"QualitySettings": "Impostazioni Qualità",
|
||||
"Queue": "Coda",
|
||||
"QueueIsEmpty": "La coda è vuota",
|
||||
"QuickSearch": "Ricerca Veloce",
|
||||
"RefreshSeries": "Aggiorna Serie",
|
||||
"Year": "Anno",
|
||||
"LanguagesLoadError": "Impossibile caricare le lingue",
|
||||
"MetadataLoadError": "Impossibile caricare i Metadati",
|
||||
"MetadataSettings": "Impostazioni Metadati",
|
||||
"MetadataSettingsEpisodeMetadata": "Metadati dell'Episodio",
|
||||
"Status": "Stato",
|
||||
"DeleteQualityProfileMessageText": "Sicuro di voler cancellare il profilo di qualità '{name}'?",
|
||||
"NotificationsGotifySettingsServerHelpText": "URL server Gotify, includendo http(s):// e porta se necessario",
|
||||
"Time": "Orario",
|
||||
"Password": "Password",
|
||||
"OrganizeNothingToRename": "Successo! Il mio lavoro è finito, nessun file da rinominare.",
|
||||
"PosterOptions": "Opzioni Locandina",
|
||||
"Progress": "Progressi",
|
||||
"Protocol": "Protocollo",
|
||||
"ProxyFailedToTestHealthCheckMessage": "Test del proxy fallito: {url}",
|
||||
"ProxyType": "Tipo Proxy",
|
||||
"QualitiesLoadError": "Impossibile caricare qualità",
|
||||
"RecyclingBinCleanup": "Pulizia Cestino",
|
||||
"SelectFolderModalTitle": "{modalTitle} - Seleziona Cartella",
|
||||
"ResetTitles": "Reimposta Titoli",
|
||||
"RestartLater": "Lo riavvierò dopo",
|
||||
"RssSyncInterval": "Intervallo Sincronizzazione RSS",
|
||||
"Runtime": "Tempo di esecuzione",
|
||||
"SearchByTvdbId": "Puoi anche ricercare usando l'ID TVDB di uno show. Es. tvdb:71663",
|
||||
"SearchForMonitoredEpisodesSeason": "Ricerca degli episodi monitorati in questa stagione",
|
||||
"SelectEpisodesModalTitle": "{modalTitle} - Seleziona Episodio/i",
|
||||
"SelectSeason": "Seleziona Stagione",
|
||||
"SeriesIndexFooterMissingUnmonitored": "Episodi Mancanti (Serie non monitorate)",
|
||||
"ShowEpisodeInformation": "Mostra Informazioni Episodio",
|
||||
"Size": "Dimensione",
|
||||
"YesterdayAt": "Ieri alle {time}",
|
||||
"UnableToImportAutomatically": "Impossibile Importare Automaticamente",
|
||||
"Small": "Piccolo",
|
||||
"Socks4": "Socks4",
|
||||
"Standard": "Standard",
|
||||
"Started": "Iniziato",
|
||||
"TorrentsDisabled": "Torrent Disattivati",
|
||||
"UnsavedChanges": "Cambiamenti Non Salvati",
|
||||
"UnselectAll": "Deseleziona Tutto",
|
||||
"UpdateAll": "Aggiorna Tutto",
|
||||
"UpdateSonarrDirectlyLoadError": "Impossibile aggiornare {appName} direttamente,",
|
||||
"UseSeasonFolderHelpText": "Ordina episodi dentro all cartella della stagione",
|
||||
"VideoCodec": "Codec Video",
|
||||
"DownloadClientValidationCategoryMissingDetail": "La categoria che ha inserito non esiste in {clientName}. Crealo prima su {clientName}.",
|
||||
"RestrictionsLoadError": "Impossibile caricare le Restrizioni",
|
||||
"SearchFailedError": "Ricerca fallita, per favore riprova nuovamente dopo.",
|
||||
"DownloadClientDelugeValidationLabelPluginFailureDetail": "{appName} non è stato in grado di aggiungere l'etichetta a {clientName}.",
|
||||
"DownloadClientFreeboxAuthenticationError": "Autenticazione alle API di Freebox fallita. Ragione: {errorDescription}",
|
||||
"DownloadClientQbittorrentValidationCategoryUnsupportedDetail": "Categorie non supportate fino alla versione 3.3.0 di qBittorrent. Per favore aggiorna o prova con una Categoria vuota.",
|
||||
"DownloadClientSettingsInitialStateHelpText": "Stato iniziale per i torrent aggiunti a {clientName}",
|
||||
"DeleteSelectedDownloadClientsMessageText": "Sei sicuro di voler eliminare i '{count}' client di download selezionato/i?",
|
||||
"DownloadClientSettingsAddPaused": "Aggiungi In Pausa",
|
||||
"DownloadClientValidationUnableToConnectDetail": "Per favore verifica nome host e porta.",
|
||||
"FormatShortTimeSpanSeconds": "{seconds} secondo/i",
|
||||
"IgnoreDownload": "Ignora Download",
|
||||
"Implementation": "Implementazione",
|
||||
"File": "File",
|
||||
"LabelIsRequired": "Etichetta richiesta",
|
||||
"IndexerSettingsSeedRatio": "Rapporto Seed",
|
||||
"ManageClients": "Gestisci Clients",
|
||||
"ManageDownloadClients": "Gestisci Clients di Download",
|
||||
"Message": "Messaggio",
|
||||
"Min": "Min",
|
||||
"MinutesThirty": "30 Minuti: {thirty}",
|
||||
"Missing": "Mancante",
|
||||
"MonitorNewItems": "Monitora Nuovi Elementi",
|
||||
"MonitorNewSeasons": "Monitora Nuove Stagioni",
|
||||
"MonitorNewSeasonsHelpText": "Quali nuove stagioni devono essere monitorati automaticamente",
|
||||
"MonitorNoEpisodes": "Nessuno",
|
||||
"MonitorNoEpisodesDescription": "Nessun episodio sarà monitorato",
|
||||
"NotificationsDiscordSettingsAvatar": "Avatar",
|
||||
"NotificationsMailgunSettingsUseEuEndpointHelpText": "Abilita per usare l'endpoint EU di MailGun",
|
||||
"MonitorNoNewSeasonsDescription": "Non monitorare nessuna nuova stagione automaticamente",
|
||||
"MonitorPilotEpisode": "Episodio Pilota",
|
||||
"MonitorPilotEpisodeDescription": "Monitora solo il primo episodio della prima stagione",
|
||||
"MonitorSeries": "Monitora Serie",
|
||||
"MonitoredStatus": "Monitorato/Stato",
|
||||
"MoveFiles": "Sposta File",
|
||||
"Name": "Nome",
|
||||
"Negate": "Nega",
|
||||
"SubtitleLanguages": "Lingua Sottotitoli",
|
||||
"Sunday": "Domenica",
|
||||
"TableColumns": "Colonne",
|
||||
"TodayAt": "Oggi alle {time}",
|
||||
"TomorrowAt": "Domani alle {time}",
|
||||
"TotalSpace": "Totale Spazio",
|
||||
"EnableRss": "Abilita RSS",
|
||||
"DownloadFailedEpisodeTooltip": "Download dell'episodio fallito",
|
||||
"Downloading": "Scaricando",
|
||||
"Edit": "Modifica",
|
||||
"EditCustomFormat": "Modifica Formato Personalizzato",
|
||||
"Error": "Errore",
|
||||
"EpisodeDownloaded": "Episodio Scaricato",
|
||||
"ImportListsSonarrSettingsFullUrl": "URL Completo",
|
||||
"ImportListsTraktSettingsLimit": "Limite",
|
||||
"DownloadClient": "Client di Download",
|
||||
"EditConditionImplementation": "Modifica Condizione - {implementationName}",
|
||||
"EpisodeFileMissingTooltip": "File dell'episodio mancante",
|
||||
"EpisodeInfo": "Info Episodio",
|
||||
"DockerUpdater": "Aggiorna il container di docker per ricevere l'aggiornamento",
|
||||
"DownloadFailed": "Download Fallito",
|
||||
"EpisodeFileRenamedTooltip": "Episodio del file rinominato",
|
||||
"EpisodeTitleRequired": "Titolo Episodio Richiesto",
|
||||
"Existing": "Esistente",
|
||||
"Episode": "Episodio",
|
||||
"ImportSeries": "Importa Serie",
|
||||
"Donations": "Donazioni",
|
||||
"EditDelayProfile": "Modifica Profilo di Ritardo",
|
||||
"EnableInteractiveSearchHelpTextWarning": "Ricerca non supportata con questo indicizzatore",
|
||||
"EnableProfile": "Abilita Profilo",
|
||||
"Exception": "Eccezione",
|
||||
"EditGroups": "Modifica Gruppi",
|
||||
"EditDownloadClientImplementation": "Modifica Client di Download - {implementationName}",
|
||||
"EditSelectedSeries": "Modifica Serie Selezionate",
|
||||
"DotNetVersion": ".NET",
|
||||
"DiskSpace": "Spazio sul Disco",
|
||||
"EpisodeFileRenamed": "File dell'Episodio Rinominato",
|
||||
"Events": "Eventi",
|
||||
"Episodes": "Episodi",
|
||||
"NotificationsDiscordSettingsAuthor": "Autore",
|
||||
"EpisodeTitle": "Titolo Episodio",
|
||||
"Imported": "Importato",
|
||||
"EpisodeImported": "Episodio Importato",
|
||||
"EditConnectionImplementation": "Modifica Connessione - {implementationName}",
|
||||
"Enable": "Abilita",
|
||||
"EnableAutomaticAdd": "Abilita Aggiunta Automatica",
|
||||
"EnableAutomaticAddSeriesHelpText": "Aggiungi serie da questa lista a {appName} quando la sincronizzazione è effettuata tramite UI o da {appName}",
|
||||
"EditIndexerImplementation": "Modifica Indicizzatore - {implementationName}",
|
||||
"ImportListsTraktSettingsAuthenticateWithTrakt": "Autentica con Trakt",
|
||||
"ImportListsTraktSettingsGenres": "Generi",
|
||||
"ImportListsTraktSettingsListName": "Nome Lista",
|
||||
"ImportListsTraktSettingsAdditionalParameters": "Parametri Addizionali",
|
||||
"ImportListsTraktSettingsListType": "Tipo Lista",
|
||||
"ImportListsTraktSettingsRating": "Valutazione",
|
||||
"Docker": "Docker",
|
||||
"IndexerHDBitsSettingsCategories": "Categorie",
|
||||
"EditSeries": "Modifica Serie",
|
||||
"Duration": "Durata",
|
||||
"EnableCompletedDownloadHandlingHelpText": "Importa automaticamente i download completati dal client di download",
|
||||
"SeriesIndexFooterEnded": "Terminata (Tutti gli episodi scaricati)",
|
||||
"EpisodeFileDeletedTooltip": "File dell'episodio eliminato",
|
||||
"Downloaded": "Scaricato",
|
||||
"EditQualityProfile": "Modifica Profilo Qualità",
|
||||
"EditSeriesModalHeader": "Modifica - {title}",
|
||||
"EpisodeRequested": "Episodio Richiesto",
|
||||
"DownloadIgnoredEpisodeTooltip": "Download dell'Episodio Ignorato",
|
||||
"EditRestriction": "Modifica Restrizione",
|
||||
"EnableSsl": "Abilita SSL",
|
||||
"EpisodeFileDeleted": "File dell'Episodio Eliminato",
|
||||
"Importing": "Importando"
|
||||
}
|
||||
|
||||
@@ -205,5 +205,7 @@
|
||||
"Category": "Categorie",
|
||||
"BlocklistReleaseHelpText": "Voorkom dat deze release opnieuw wordt gedownload door {appName} door een RSS lijst of een automatische zoekopdracht",
|
||||
"ChangeCategory": "Verander categorie",
|
||||
"ChownGroup": "chown groep"
|
||||
"ChownGroup": "chown groep",
|
||||
"AutoTaggingSpecificationTag": "Tag",
|
||||
"AddDelayProfileError": "Mislukt om vertragingsprofiel toe te voegen, probeer het later nog eens."
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@
|
||||
"Calendar": "Calendário",
|
||||
"Connect": "Conectar",
|
||||
"CustomFormats": "Formatos personalizados",
|
||||
"CutoffUnmet": "Corte não alcançado",
|
||||
"CutoffUnmet": "Corte Não Alcançado",
|
||||
"DownloadClients": "Clientes de download",
|
||||
"Events": "Eventos",
|
||||
"General": "Geral",
|
||||
@@ -205,7 +205,7 @@
|
||||
"SeasonNumber": "Número da Temporada",
|
||||
"SeriesTitle": "Título da Série",
|
||||
"Special": "Especial",
|
||||
"TestParsing": "Testar Análise",
|
||||
"TestParsing": "Análise de teste",
|
||||
"About": "Sobre",
|
||||
"Actions": "Ações",
|
||||
"AppDataDirectory": "Diretório AppData",
|
||||
@@ -432,7 +432,7 @@
|
||||
"AuthBasic": "Básico (pop-up do navegador)",
|
||||
"AuthForm": "Formulário (página de login)",
|
||||
"Authentication": "Autenticação",
|
||||
"AuthenticationMethodHelpText": "Exigir nome de usuário e senha para acessar o {appName}",
|
||||
"AuthenticationMethodHelpText": "Exigir Nome de Usuário e Senha para acessar {appName}",
|
||||
"AuthenticationRequired": "Autenticação exigida",
|
||||
"AutoRedownloadFailedHelpText": "Procurar automaticamente e tente baixar uma versão diferente",
|
||||
"AutoTaggingLoadError": "Não foi possível carregar tagging automática",
|
||||
@@ -493,7 +493,7 @@
|
||||
"CustomFormatsLoadError": "Não foi possível carregar Formatos Personalizados",
|
||||
"CustomFormatsSettings": "Configurações de Formatos Personalizados",
|
||||
"CustomFormatsSettingsSummary": "Configurações e Formatos Personalizados",
|
||||
"DailyEpisodeFormat": "Formato do Episódio Diário",
|
||||
"DailyEpisodeFormat": "Formato do episódio diário",
|
||||
"Cutoff": "Corte",
|
||||
"Dash": "Traço",
|
||||
"Dates": "Datas",
|
||||
@@ -686,7 +686,6 @@
|
||||
"OnGrab": "Ao obter",
|
||||
"OnHealthIssue": "Ao Problema de Saúde",
|
||||
"OnHealthRestored": "Com a Saúde Restaurada",
|
||||
"OnImport": "Ao Importar",
|
||||
"OnRename": "Ao Renomear",
|
||||
"OnSeriesAdd": "Ao Adicionar Série",
|
||||
"OnSeriesDelete": "Ao Excluir Série",
|
||||
@@ -891,7 +890,7 @@
|
||||
"UnmonitorDeletedEpisodes": "Cancelar Monitoramento de Episódios Excluídos",
|
||||
"UnsavedChanges": "Alterações Não Salvas",
|
||||
"UpdateAutomaticallyHelpText": "Baixe e instale atualizações automaticamente. Você ainda poderá instalar a partir do Sistema: Atualizações",
|
||||
"UpdateMechanismHelpText": "Use o atualizador integrado do {appName} ou um script",
|
||||
"UpdateMechanismHelpText": "Usar o atualizador integrado do {appName} ou um script",
|
||||
"UpdateSonarrDirectlyLoadError": "Incapaz de atualizar o {appName} diretamente,",
|
||||
"UpdateUiNotWritableHealthCheckMessage": "Não é possível instalar a atualização porque a pasta de IU '{uiFolder}' não pode ser salva pelo usuário '{userName}'.",
|
||||
"UpgradeUntil": "Atualizar Até",
|
||||
@@ -1262,7 +1261,7 @@
|
||||
"OverrideGrabNoQuality": "A qualidade deve ser selecionada",
|
||||
"OverrideGrabNoSeries": "A série deve ser selecionada",
|
||||
"Parse": "Analisar",
|
||||
"ParseModalHelpTextDetails": "{appName} tentará analisar o título e mostrar detalhes sobre ele",
|
||||
"ParseModalHelpTextDetails": "O {appName} tentará analisar o título e mostrar detalhes sobre ele",
|
||||
"RecentChanges": "Mudanças Recentes",
|
||||
"ReleaseRejected": "Lançamento Rejeitado",
|
||||
"ReleaseSceneIndicatorAssumingScene": "Assumindo a Numeração da Scene.",
|
||||
@@ -1448,11 +1447,11 @@
|
||||
"MissingNoItems": "Nenhum item ausente",
|
||||
"SearchAll": "Pesquisar Todos",
|
||||
"UnmonitorSelected": "Não Monitorar os Selecionados",
|
||||
"CutoffUnmetNoItems": "Nenhum item com corte não atingido",
|
||||
"CutoffUnmetNoItems": "Nenhum item com limite não atingido",
|
||||
"MonitorSelected": "Monitorar Selecionados",
|
||||
"SearchForAllMissingEpisodesConfirmationCount": "Tem certeza de que deseja pesquisar todos os episódios ausentes de {totalRecords}?",
|
||||
"SearchSelected": "Pesquisar Selecionado",
|
||||
"CutoffUnmetLoadError": "Erro ao carregar itens de corte não atingidos",
|
||||
"CutoffUnmetLoadError": "Erro ao carregar itens de limite não atingido",
|
||||
"MassSearchCancelWarning": "Isso não pode ser cancelado depois de iniciado sem reiniciar {appName} ou desabilitar todos os seus indexadores.",
|
||||
"SearchForAllMissingEpisodes": "Pesquisar por todos os episódios ausentes",
|
||||
"SearchForCutoffUnmetEpisodes": "Pesquise todos os episódios que o corte não foi atingido",
|
||||
@@ -2016,7 +2015,7 @@
|
||||
"BlocklistReleaseHelpText": "Impede que esta versão seja baixada novamente por {appName} via RSS ou Pesquisa Automática",
|
||||
"ChangeCategoryHint": "Altera o download para a \"Categoria pós-importação\" do cliente de download",
|
||||
"ChangeCategoryMultipleHint": "Altera os downloads para a \"Categoria pós-importação' do cliente de download",
|
||||
"DatabaseMigration": "Migração de Banco de Dados",
|
||||
"DatabaseMigration": "Migração de banco de dados",
|
||||
"DoNotBlocklistHint": "Remover sem colocar na lista de bloqueio",
|
||||
"ChangeCategory": "Alterar categoria",
|
||||
"DoNotBlocklist": "Não coloque na lista de bloqueio",
|
||||
@@ -2078,5 +2077,13 @@
|
||||
"TodayAt": "Hoje às {time}",
|
||||
"TomorrowAt": "Amanhã às {time}",
|
||||
"HasUnmonitoredSeason": "Tem Temporada Não Monitorada",
|
||||
"YesterdayAt": "Ontem às {time}"
|
||||
"YesterdayAt": "Ontem às {time}",
|
||||
"UnableToImportAutomatically": "Não foi possível importar automaticamente",
|
||||
"CustomColonReplacement": "Substituto de Dois Pontos Personalizado",
|
||||
"CustomColonReplacementFormatHint": "Caractere válido do sistema de arquivos, como dois pontos (letra)",
|
||||
"NotificationsPlexSettingsServerHelpText": "Selecione o servidor da conta plex.tv após a autenticação",
|
||||
"OnFileImport": "Ao Importar o Arquivo",
|
||||
"OnImportComplete": "Ao Completar Importação",
|
||||
"CustomColonReplacementFormatHelpText": "Caracteres a serem usados em substituição aos dois pontos",
|
||||
"NotificationsPlexSettingsServer": "Servidor"
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
"AppUpdated": "{appName} Güncellendi",
|
||||
"ApplicationURL": "Uygulama URL'si",
|
||||
"ApplyTagsHelpTextAdd": "Ekle: Etiketleri mevcut etiket listesine ekleyin",
|
||||
"ApplyTagsHelpTextHowToApplyIndexers": "Seçilen indeksleyicilere etiketler nasıl uygulanır?",
|
||||
"ApplyTagsHelpTextHowToApplyIndexers": "Seçilen indeksleyicilere etiketler nasıl uygulanır",
|
||||
"ApplyTagsHelpTextRemove": "Kaldır: Girilen etiketleri kaldırın",
|
||||
"AuthenticationRequiredPasswordHelpTextWarning": "Yeni şifre girin",
|
||||
"AuthenticationRequiredUsernameHelpTextWarning": "Yeni kullanıcı adınızı girin",
|
||||
@@ -88,8 +88,8 @@
|
||||
"CustomFormatUnknownConditionOption": "'{implementation}' koşulu için bilinmeyen seçenek '{key}'",
|
||||
"AutoTagging": "Otomatik Etiketleme",
|
||||
"AutoTaggingNegateHelpText": "İşaretlenirse, {implementationName} koşulu eşleştiğinde otomatik etiketleme kuralı uygulanmayacaktır.",
|
||||
"ApplyTagsHelpTextHowToApplyDownloadClients": "Seçilen indirme istemcilerine etiketler nasıl uygulanır?",
|
||||
"ApplyTagsHelpTextHowToApplyImportLists": "Seçilen içe aktarma listelerine etiketler nasıl uygulanır?",
|
||||
"ApplyTagsHelpTextHowToApplyDownloadClients": "Seçilen indirme istemcilerine etiketler nasıl uygulanır",
|
||||
"ApplyTagsHelpTextHowToApplyImportLists": "Seçilen içe aktarma listelerine etiketler nasıl uygulanır",
|
||||
"AuthenticationRequiredHelpText": "İstekler için Kimlik doğrulamanın gereklilik ayarını değiştirin. Riskleri anlamadığınız sürece değiştirmeyin.",
|
||||
"AutoTaggingLoadError": "Otomatik etiketleme yüklenemiyor",
|
||||
"BypassDelayIfAboveCustomFormatScore": "Özel Format Koşullarının Üstündeyse Baypas Et",
|
||||
@@ -837,5 +837,15 @@
|
||||
"UpdateAutomaticallyHelpText": "Güncelleştirmeleri otomatik olarak indirip yükleyin. Sistem: Güncellemeler'den yükleme yapmaya devam edebileceksiniz",
|
||||
"Wanted": "Arananlar",
|
||||
"Cutoff": "Kesinti",
|
||||
"Required": "Gerekli"
|
||||
"Required": "Gerekli",
|
||||
"AirsTbaOn": "Daha sonra duyurulacak {networkLabel}'de",
|
||||
"AllFiles": "Tüm dosyalar",
|
||||
"AllSeriesAreHiddenByTheAppliedFilter": "Tüm sonuçlar, uygulanan filtre tarafından gizlenir",
|
||||
"Always": "Her zaman",
|
||||
"AirsDateAtTimeOn": "{date} saat {time} {networkLabel}'de",
|
||||
"AllResultsAreHiddenByTheAppliedFilter": "Tüm sonuçlar, uygulanan filtre tarafından gizlenir",
|
||||
"AllSeriesInRootFolderHaveBeenImported": "{path} içerisindeki tüm diziler içeri aktarıldı",
|
||||
"AlternateTitles": "Alternatif Başlıklar",
|
||||
"AnEpisodeIsDownloading": "Bir bölüm indiriliyor",
|
||||
"UnableToImportAutomatically": "Otomatikman İçe Aktarılamıyor"
|
||||
}
|
||||
|
||||
@@ -345,5 +345,27 @@
|
||||
"DownloadClientDelugeValidationLabelPluginInactive": "Плагін міток не активовано",
|
||||
"DownloadClientAriaSettingsDirectoryHelpText": "Додаткове розташування для розміщення завантажень. Залиште поле порожнім, щоб використовувати стандартне розташування Aria2",
|
||||
"CustomFormatHelpText": "{appName} оцінює кожен випуск, використовуючи суму балів для відповідності користувацьких форматів. Якщо новий випуск покращить оцінку, з такою ж або кращою якістю, {appName} схопить його.",
|
||||
"DownloadClientDownloadStationSettingsDirectoryHelpText": "Додаткова спільна папка для розміщення завантажень. Залиште поле порожнім, щоб використовувати стандартне розташування Download Station"
|
||||
"DownloadClientDownloadStationSettingsDirectoryHelpText": "Додаткова спільна папка для розміщення завантажень. Залиште поле порожнім, щоб використовувати стандартне розташування Download Station",
|
||||
"ClickToChangeIndexerFlags": "Натисніть, щоб змінити прапорці індексатора",
|
||||
"AutoTaggingLoadError": "Не вдалося завантажити автоматичне маркування",
|
||||
"CountDownloadClientsSelected": "Вибрано {count} клієнтів завантажувача",
|
||||
"CountImportListsSelected": "Вибрано {count} списків імпорту",
|
||||
"AutoTagging": "Автоматичне маркування",
|
||||
"CloneCondition": "Клонування умови",
|
||||
"AutomaticAdd": "Автоматичне додавання",
|
||||
"BypassDelayIfAboveCustomFormatScoreMinimumScoreHelpText": "Мінімальна оцінка користувацького формату, необхідна для обходу затримки для обраного протоколу",
|
||||
"ChownGroup": "chown Група",
|
||||
"BlocklistMultipleOnlyHint": "Додати до чорного списку без пошуку замін",
|
||||
"BlocklistOnly": "Тільки чорний список",
|
||||
"BlocklistOnlyHint": "Додати до чорного списку без пошуку заміни",
|
||||
"ChangeCategoryHint": "Змінює завантаження на «Категорію після імпорту» з клієнта завантажувача",
|
||||
"ChangeCategoryMultipleHint": "Змінює завантаження на «Категорію після імпорту» з клієнта завантажувача",
|
||||
"BlocklistAndSearchHint": "Розпочати пошук заміни після додавання до чорного списку",
|
||||
"BlocklistAndSearchMultipleHint": "Розпочати пошук замін після додавання до чорного списку",
|
||||
"AutoRedownloadFailedFromInteractiveSearchHelpText": "Автоматично шукати та намагатися завантажити інший реліз, якщо обраний реліз не вдалось завантажити з інтерактивного пошуку.",
|
||||
"BlackholeWatchFolder": "Папка для спостереження",
|
||||
"BypassDelayIfAboveCustomFormatScore": "Пропустити, якщо перевищено оцінку користувацького формату",
|
||||
"Clone": "Клонування",
|
||||
"BlocklistFilterHasNoItems": "Вибраний фільтр чорного списку не містить елементів",
|
||||
"BypassDelayIfAboveCustomFormatScoreHelpText": "Увімкнути обхід, якщо реліз має оцінку вищу за встановлений мінімальний бал користувацького формату"
|
||||
}
|
||||
|
||||
@@ -5,5 +5,7 @@
|
||||
"ApiKeyValidationHealthCheckMessage": "Hãy cập nhật mã API để dài ít nhất {length} kí tự. Bạn có thể làm điều này trong cài đặt hoặc trong tập config",
|
||||
"AppDataLocationHealthCheckMessage": "Việc cập nhật sẽ không xảy ra để tránh xóa AppData khi cập nhật",
|
||||
"ApplyChanges": "Áp dụng thay đổi",
|
||||
"AutomaticAdd": "Tự động thêm"
|
||||
"AutomaticAdd": "Tự động thêm",
|
||||
"CalendarOptions": "Tùy chọn lịch",
|
||||
"UpdateMechanismHelpText": "Sử dụng trình cập nhật tích hợp của {appName} hoặc một tập lệnh"
|
||||
}
|
||||
|
||||
@@ -550,7 +550,7 @@
|
||||
"AutoRedownloadFailedHelpText": "自动搜索并尝试下载不同的版本",
|
||||
"AutoTaggingLoadError": "无法加载自动标记",
|
||||
"Automatic": "自动化",
|
||||
"AutoTaggingRequiredHelpText": "这个{implementationName}条件必须匹配自动标记规则才能应用。否则,一个{implementationName}匹配就足够了。",
|
||||
"AutoTaggingRequiredHelpText": "这个{0}条件必须匹配自动标记规则才能应用。否则,一个{0}匹配就足够了。",
|
||||
"AutoTaggingNegateHelpText": "如果选中,当 {implementationName} 条件匹配时,自动标记不会应用。",
|
||||
"BackupRetentionHelpText": "超过保留期限的自动备份将被自动清理",
|
||||
"BackupsLoadError": "无法加载备份",
|
||||
@@ -1309,7 +1309,6 @@
|
||||
"OnApplicationUpdate": "程序更新时",
|
||||
"OnHealthIssue": "健康度异常",
|
||||
"OnHealthRestored": "健康度恢复",
|
||||
"OnImport": "导入中",
|
||||
"Password": "密码",
|
||||
"PendingDownloadClientUnavailable": "挂起 - 下载客户端不可用",
|
||||
"QueueLoadError": "加载队列失败",
|
||||
|
||||
@@ -171,7 +171,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||
}
|
||||
|
||||
episodeFile = _mediaFileService.Add(episodeFile);
|
||||
importResults.Add(new ImportResult(importDecision));
|
||||
importResults.Add(new ImportResult(importDecision, episodeFile));
|
||||
|
||||
if (newDownload)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Common.EnsureThat;
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||
public class ImportResult
|
||||
{
|
||||
public ImportDecision ImportDecision { get; private set; }
|
||||
public EpisodeFile EpisodeFile { get; private set; }
|
||||
public List<string> Errors { get; private set; }
|
||||
|
||||
public ImportResultType Result
|
||||
@@ -34,5 +35,14 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||
ImportDecision = importDecision;
|
||||
Errors = errors.ToList();
|
||||
}
|
||||
|
||||
public ImportResult(ImportDecision importDecision, EpisodeFile episodeFile)
|
||||
{
|
||||
Ensure.That(importDecision, () => importDecision).IsNotNull();
|
||||
|
||||
ImportDecision = importDecision;
|
||||
EpisodeFile = episodeFile;
|
||||
Errors = new List<string>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -395,14 +395,6 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
|
||||
item.Name = Path.GetFileNameWithoutExtension(decision.LocalEpisode.Path);
|
||||
item.DownloadId = downloadId;
|
||||
|
||||
if (decision.LocalEpisode.Series != null)
|
||||
{
|
||||
item.Series = decision.LocalEpisode.Series;
|
||||
|
||||
item.CustomFormats = _formatCalculator.ParseCustomFormat(decision.LocalEpisode);
|
||||
item.CustomFormatScore = item.Series.QualityProfile?.Value.CalculateCustomFormatScore(item.CustomFormats) ?? 0;
|
||||
}
|
||||
|
||||
if (decision.LocalEpisode.Episodes.Any() && decision.LocalEpisode.Episodes.Select(c => c.SeasonNumber).Distinct().Count() == 1)
|
||||
{
|
||||
var seasons = decision.LocalEpisode.Episodes.Select(c => c.SeasonNumber).Distinct().ToList();
|
||||
@@ -430,6 +422,14 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
|
||||
item.IndexerFlags = (int)decision.LocalEpisode.IndexerFlags;
|
||||
item.ReleaseType = decision.LocalEpisode.ReleaseType;
|
||||
|
||||
if (decision.LocalEpisode.Series != null)
|
||||
{
|
||||
item.Series = decision.LocalEpisode.Series;
|
||||
|
||||
item.CustomFormats = _formatCalculator.ParseCustomFormat(decision.LocalEpisode);
|
||||
item.CustomFormatScore = item.Series.QualityProfile?.Value.CalculateCustomFormatScore(item.CustomFormats) ?? 0;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
@@ -506,8 +506,6 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
|
||||
|
||||
// Augment episode file so imported files have all additional information an automatic import would
|
||||
localEpisode = _aggregationService.Augment(localEpisode, trackedDownload?.DownloadItem);
|
||||
localEpisode.CustomFormats = _formatCalculator.ParseCustomFormat(localEpisode);
|
||||
localEpisode.CustomFormatScore = localEpisode.Series.QualityProfile?.Value.CalculateCustomFormatScore(localEpisode.CustomFormats) ?? 0;
|
||||
|
||||
// Apply the user-chosen values.
|
||||
localEpisode.Series = series;
|
||||
@@ -518,6 +516,9 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
|
||||
localEpisode.IndexerFlags = (IndexerFlags)file.IndexerFlags;
|
||||
localEpisode.ReleaseType = file.ReleaseType;
|
||||
|
||||
localEpisode.CustomFormats = _formatCalculator.ParseCustomFormat(localEpisode);
|
||||
localEpisode.CustomFormatScore = localEpisode.Series.QualityProfile?.Value.CalculateCustomFormatScore(localEpisode.CustomFormats) ?? 0;
|
||||
|
||||
// TODO: Cleanup non-tracked downloads
|
||||
|
||||
var importDecision = new ImportDecision(localEpisode);
|
||||
@@ -545,6 +546,24 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
|
||||
_logger.ProgressTrace("Manually imported {0} files", imported.Count);
|
||||
}
|
||||
|
||||
var untrackedImports = imported.Where(i => importedTrackedDownload.FirstOrDefault(t => t.ImportResult != i) == null).ToList();
|
||||
|
||||
if (untrackedImports.Any())
|
||||
{
|
||||
foreach (var groupedUntrackedImport in untrackedImports.GroupBy(i => new { i.EpisodeFile.SeriesId, i.EpisodeFile.SeasonNumber }))
|
||||
{
|
||||
var localEpisodes = groupedUntrackedImport.Select(u => u.ImportDecision.LocalEpisode).ToList();
|
||||
var episodeFiles = groupedUntrackedImport.Select(u => u.EpisodeFile).ToList();
|
||||
var localEpisode = localEpisodes.First();
|
||||
var series = localEpisode.Series;
|
||||
var sourcePath = localEpisodes.Select(l => l.Path).ToList().GetLongestCommonPath();
|
||||
var episodes = localEpisodes.SelectMany(l => l.Episodes).ToList();
|
||||
var parsedEpisodeInfo = localEpisode.FolderEpisodeInfo ?? localEpisode.FileEpisodeInfo;
|
||||
|
||||
_eventAggregator.PublishEvent(new UntrackedDownloadCompletedEvent(series, episodes, episodeFiles, parsedEpisodeInfo, sourcePath));
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var groupedTrackedDownload in importedTrackedDownload.GroupBy(i => i.TrackedDownload.DownloadItem.DownloadId).ToList())
|
||||
{
|
||||
var trackedDownload = groupedTrackedDownload.First().TrackedDownload;
|
||||
@@ -561,15 +580,20 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
|
||||
}
|
||||
}
|
||||
|
||||
var allEpisodesImported = groupedTrackedDownload.Select(c => c.ImportResult)
|
||||
.Where(c => c.Result == ImportResultType.Imported)
|
||||
var importedResults = groupedTrackedDownload.Select(c => c.ImportResult)
|
||||
.Where(c => c.Result == ImportResultType.Imported)
|
||||
.ToList();
|
||||
|
||||
var allEpisodesImported = importedResults
|
||||
.SelectMany(c => c.ImportDecision.LocalEpisode.Episodes).Count() >=
|
||||
Math.Max(1, trackedDownload.RemoteEpisode?.Episodes?.Count ?? 1);
|
||||
|
||||
if (allEpisodesImported)
|
||||
{
|
||||
var episodeFiles = importedResults.Select(i => i.EpisodeFile).ToList();
|
||||
|
||||
trackedDownload.State = TrackedDownloadState.Imported;
|
||||
_eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload, importedSeries.Id));
|
||||
_eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload, importedSeries.Id, episodeFiles, importedResults.First().ImportDecision.LocalEpisode.Release));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,10 +22,10 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
|
||||
private readonly List<FFProbePixelFormat> _pixelFormats;
|
||||
|
||||
public const int MINIMUM_MEDIA_INFO_SCHEMA_REVISION = 8;
|
||||
public const int CURRENT_MEDIA_INFO_SCHEMA_REVISION = 10;
|
||||
public const int CURRENT_MEDIA_INFO_SCHEMA_REVISION = 11;
|
||||
|
||||
private static readonly string[] ValidHdrColourPrimaries = { "bt2020" };
|
||||
private static readonly string[] HlgTransferFunctions = { "bt2020-10", "arib-std-b67" };
|
||||
private static readonly string[] HlgTransferFunctions = { "arib-std-b67" };
|
||||
private static readonly string[] PqTransferFunctions = { "smpte2084" };
|
||||
private static readonly string[] ValidHdrTransferFunctions = HlgTransferFunctions.Concat(PqTransferFunctions).ToArray();
|
||||
|
||||
|
||||
@@ -137,6 +137,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||
environmentVariables.Add("Sonarr_Series_Path", series.Path);
|
||||
environmentVariables.Add("Sonarr_Series_TvdbId", series.TvdbId.ToString());
|
||||
environmentVariables.Add("Sonarr_Series_TvMazeId", series.TvMazeId.ToString());
|
||||
environmentVariables.Add("Sonarr_Series_TmdbId", series.TmdbId.ToString());
|
||||
environmentVariables.Add("Sonarr_Series_ImdbId", series.ImdbId ?? string.Empty);
|
||||
environmentVariables.Add("Sonarr_Series_Type", series.SeriesType.ToString());
|
||||
environmentVariables.Add("Sonarr_Series_OriginalLanguage", IsoLanguages.Get(series.OriginalLanguage).ThreeLetterCode);
|
||||
|
||||
@@ -23,6 +23,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
|
||||
public string LastAired { get; set; }
|
||||
public int? TvRageId { get; set; }
|
||||
public int? TvMazeId { get; set; }
|
||||
public int? TmdbId { get; set; }
|
||||
|
||||
public string Status { get; set; }
|
||||
public int? Runtime { get; set; }
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user