diff --git a/frontend/src/InteractiveImport/Language/SelectLanguageModalContentConnector.js b/frontend/src/InteractiveImport/Language/SelectLanguageModalContentConnector.js
index 1eda0b176..f4b6796a3 100644
--- a/frontend/src/InteractiveImport/Language/SelectLanguageModalContentConnector.js
+++ b/frontend/src/InteractiveImport/Language/SelectLanguageModalContentConnector.js
@@ -11,7 +11,22 @@ function createMapStateToProps() {
return createSelector(
createLanguagesSelector(),
(languages) => {
- return languages;
+ const {
+ isFetching,
+ isPopulated,
+ error,
+ items
+ } = languages;
+
+ const filterItems = ['Any', 'Original'];
+ const filteredLanguages = items.filter((lang) => !filterItems.includes(lang.name));
+
+ return {
+ isFetching,
+ isPopulated,
+ error,
+ items: filteredLanguages
+ };
}
);
}
diff --git a/frontend/src/Series/Index/Menus/SeriesIndexSortMenu.js b/frontend/src/Series/Index/Menus/SeriesIndexSortMenu.js
index 018a4c8eb..7ea5ea75b 100644
--- a/frontend/src/Series/Index/Menus/SeriesIndexSortMenu.js
+++ b/frontend/src/Series/Index/Menus/SeriesIndexSortMenu.js
@@ -46,6 +46,15 @@ function SeriesIndexSortMenu(props) {
Network
+
+ Original Language
+
+
+ {originalLanguage.name}
+
+ );
+ }
+
if (name === 'qualityProfileId') {
return (
{
+ if (series.originalLanguage) {
+ acc.push({
+ id: series.originalLanguage.name,
+ name: series.originalLanguage.name
+ });
+ }
+
+ return acc;
+ }, []);
+
+ return languageList.sort(sortByName);
+ }
+ },
{
name: 'releaseGroups',
label: 'Release Groups',
diff --git a/frontend/src/Store/Actions/seriesIndexActions.js b/frontend/src/Store/Actions/seriesIndexActions.js
index 0e1c4d9e5..8cdadba95 100644
--- a/frontend/src/Store/Actions/seriesIndexActions.js
+++ b/frontend/src/Store/Actions/seriesIndexActions.js
@@ -95,6 +95,12 @@ export const defaultState = {
isSortable: true,
isVisible: false
},
+ {
+ name: 'originalLanguage',
+ label: 'Original Language',
+ isSortable: true,
+ isVisible: false
+ },
{
name: 'added',
label: 'Added',
@@ -249,6 +255,12 @@ export const defaultState = {
return statistics.seasonCount;
},
+ originalLanguage: function(item) {
+ const { originalLanguage = {} } = item;
+
+ return originalLanguage.name;
+ },
+
ratings: function(item) {
const { ratings = {} } = item;
diff --git a/src/NzbDrone.Core.Test/MediaFiles/EpisodeImport/Aggregation/Aggregators/AggregateLanguageFixture.cs b/src/NzbDrone.Core.Test/MediaFiles/EpisodeImport/Aggregation/Aggregators/AggregateLanguageFixture.cs
index 833b76b42..2d13d6792 100644
--- a/src/NzbDrone.Core.Test/MediaFiles/EpisodeImport/Aggregation/Aggregators/AggregateLanguageFixture.cs
+++ b/src/NzbDrone.Core.Test/MediaFiles/EpisodeImport/Aggregation/Aggregators/AggregateLanguageFixture.cs
@@ -18,6 +18,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Aggregation.Aggregators
public class AggregateLanguageFixture : CoreTest
{
private LocalEpisode _localEpisode;
+ private Series _series;
private string _simpleReleaseTitle = "Series.Title.S01E01.xyz-RlsGroup";
[SetUp]
@@ -26,11 +27,16 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Aggregation.Aggregators
var episodes = Builder.CreateListOfSize(1)
.BuildList();
+ _series = Builder.CreateNew()
+ .With(m => m.OriginalLanguage = Language.English)
+ .Build();
+
_localEpisode = Builder.CreateNew()
.With(l => l.DownloadClientEpisodeInfo = null)
.With(l => l.FolderEpisodeInfo = null)
.With(l => l.FileEpisodeInfo = null)
.With(l => l.Episodes = episodes)
+ .With(l => l.Series = _series)
.Build();
}
@@ -72,7 +78,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Aggregation.Aggregators
{
var result = Subject.Aggregate(_localEpisode, null);
- result.Languages.Should().Contain(Language.English);
+ result.Languages.Should().Contain(_series.OriginalLanguage);
}
[Test]
@@ -120,13 +126,13 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Aggregation.Aggregators
[Test]
public void should_return_file_language_when_file_language_is_higher_than_others()
{
- _localEpisode.DownloadClientEpisodeInfo = GetParsedEpisodeInfo(new List { Language.English }, _simpleReleaseTitle);
- _localEpisode.FolderEpisodeInfo = GetParsedEpisodeInfo(new List { Language.English }, _simpleReleaseTitle);
+ _localEpisode.DownloadClientEpisodeInfo = GetParsedEpisodeInfo(new List { Language.Unknown }, _simpleReleaseTitle);
+ _localEpisode.FolderEpisodeInfo = GetParsedEpisodeInfo(new List { Language.Unknown }, _simpleReleaseTitle);
_localEpisode.FileEpisodeInfo = GetParsedEpisodeInfo(new List { Language.French }, _simpleReleaseTitle);
GivenAugmenters(new List { Language.French },
- new List { Language.English },
- new List { Language.English },
+ new List { Language.Unknown },
+ new List { Language.Unknown },
null);
Subject.Aggregate(_localEpisode, null).Languages.Should().Contain(_localEpisode.FileEpisodeInfo.Languages);
@@ -135,9 +141,9 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Aggregation.Aggregators
[Test]
public void should_return_multi_language()
{
- GivenAugmenters(new List { Language.English },
+ GivenAugmenters(new List { Language.Unknown },
new List { Language.French, Language.German },
- new List { Language.English },
+ new List { Language.Unknown },
null);
Subject.Aggregate(_localEpisode, null).Languages.Should().Equal(new List { Language.French, Language.German });
diff --git a/src/NzbDrone.Core.Test/MediaFiles/EpisodeImport/Specifications/UpgradeSpecificationFixture.cs b/src/NzbDrone.Core.Test/MediaFiles/EpisodeImport/Specifications/UpgradeSpecificationFixture.cs
index 1bc867448..0cb595dd0 100644
--- a/src/NzbDrone.Core.Test/MediaFiles/EpisodeImport/Specifications/UpgradeSpecificationFixture.cs
+++ b/src/NzbDrone.Core.Test/MediaFiles/EpisodeImport/Specifications/UpgradeSpecificationFixture.cs
@@ -260,46 +260,6 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeFalse();
}
- [Test]
- public void should_return_false_if_it_is_a_preferred_word_downgrade_and_equal_language_and_quality()
- {
- var lowFormat = new List { new CustomFormat("Bad Format", new ResolutionSpecification { Value = (int)Resolution.R1080p }) { Id = 2 } };
-
- CustomFormatsFixture.GivenCustomFormats(lowFormat.First());
-
- _series.QualityProfile.Value.FormatItems = CustomFormatsFixture.GetSampleFormatItems();
-
- Mocker.GetMock()
- .Setup(s => s.DownloadPropersAndRepacks)
- .Returns(ProperDownloadTypes.DoNotPrefer);
-
- Mocker.GetMock()
- .Setup(s => s.ParseCustomFormat(It.IsAny()))
- .Returns(new List());
-
- Mocker.GetMock()
- .Setup(s => s.ParseCustomFormat(It.IsAny()))
- .Returns(lowFormat);
-
- _localEpisode.Quality = new QualityModel(Quality.Bluray1080p);
-
- _localEpisode.Episodes = Builder.CreateListOfSize(1)
- .All()
- .With(e => e.EpisodeFileId = 1)
- .With(e => e.EpisodeFile = new LazyLoaded(
- new EpisodeFile
- {
- Quality = new QualityModel(Quality.Bluray1080p),
- Languages = new List { Language.Spanish }
- }))
- .Build()
- .ToList();
-
- _localEpisode.FileEpisodeInfo = Builder.CreateNew().Build();
-
- Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeFalse();
- }
-
[Test]
public void should_return_true_if_it_is_a_preferred_word_downgrade_and_language_downgrade_and_a_quality_upgrade()
{
diff --git a/src/NzbDrone.Core.Test/ParserTests/LanguageParserFixture.cs b/src/NzbDrone.Core.Test/ParserTests/LanguageParserFixture.cs
index 40baa32ad..47c50014d 100644
--- a/src/NzbDrone.Core.Test/ParserTests/LanguageParserFixture.cs
+++ b/src/NzbDrone.Core.Test/ParserTests/LanguageParserFixture.cs
@@ -11,21 +11,27 @@ namespace NzbDrone.Core.Test.ParserTests
public class LanguageParserFixture : CoreTest
{
[TestCase("Title.the.Series.2009.S01E14.English.HDTV.XviD-LOL")]
+ [TestCase("Series Title - S01E01 - Pilot.English.sub")]
+ [TestCase("Series Title - S01E01 - Pilot.english.sub")]
+ public void should_parse_language_english(string postTitle)
+ {
+ var result = LanguageParser.ParseLanguages(postTitle);
+ result.First().Should().Be(Language.English);
+ }
+
+ [TestCase("Spanish Killroy was Here S02E02 Flodden 720p AMZN WEB-DL DDP5 1 H 264-NTb")]
+ [TestCase("Title.the.Spanish.Series.S02E02.1080p.WEB.H264-CAKES")]
+ [TestCase("Title.the.Spanish.Series.S02E06.Field.of.Cloth.of.Gold.1080p.AMZN.WEBRip.DDP5.1.x264-NTb")]
[TestCase("Title.the.Series.2009.S01E14.Germany.HDTV.XviD-LOL")]
[TestCase("Title.the.Series.2009.S01E14.HDTV.XviD-LOL")]
[TestCase("Title.the.Italian.Series.S01E01.The.Family.720p.HDTV.x264-FTP")]
[TestCase("Title.the.Italy.Series.S02E01.720p.HDTV.x264-TLA")]
[TestCase("Series Title - S01E01 - Pilot.en.sub")]
[TestCase("Series Title - S01E01 - Pilot.eng.sub")]
- [TestCase("Series Title - S01E01 - Pilot.English.sub")]
- [TestCase("Series Title - S01E01 - Pilot.english.sub")]
- [TestCase("Spanish Killroy was Here S02E02 Flodden 720p AMZN WEB-DL DDP5 1 H 264-NTb")]
- [TestCase("Title.the.Spanish.Series.S02E02.1080p.WEB.H264-CAKES")]
- [TestCase("Title.the.Spanish.Series.S02E06.Field.of.Cloth.of.Gold.1080p.AMZN.WEBRip.DDP5.1.x264-NTb")]
- public void should_parse_language_english(string postTitle)
+ public void should_parse_language_unknown(string postTitle)
{
var result = LanguageParser.ParseLanguages(postTitle);
- result.First().Should().Be(Language.English);
+ result.First().Should().Be(Language.Unknown);
}
[TestCase("Series Title - S01E01 - Pilot.sub")]
@@ -314,7 +320,7 @@ namespace NzbDrone.Core.Test.ParserTests
public void should_not_parse_series_or_episode_title(string postTitle)
{
var result = LanguageParser.ParseLanguages(postTitle);
- result.First().Name.Should().Be(Language.English.Name);
+ result.First().Name.Should().Be(Language.Unknown.Name);
}
}
}
diff --git a/src/NzbDrone.Core.Test/ParserTests/ParsingServiceTests/GetEpisodesFixture.cs b/src/NzbDrone.Core.Test/ParserTests/ParsingServiceTests/GetEpisodesFixture.cs
index e86092f6c..1dd3940c5 100644
--- a/src/NzbDrone.Core.Test/ParserTests/ParsingServiceTests/GetEpisodesFixture.cs
+++ b/src/NzbDrone.Core.Test/ParserTests/ParsingServiceTests/GetEpisodesFixture.cs
@@ -7,6 +7,7 @@ using Moq;
using NUnit.Framework;
using NzbDrone.Core.DataAugmentation.Scene;
using NzbDrone.Core.IndexerSearch.Definitions;
+using NzbDrone.Core.Languages;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Tv;
@@ -41,7 +42,8 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
SeriesTitle = _series.Title,
SeasonNumber = 1,
EpisodeNumbers = new[] { 1 },
- AbsoluteEpisodeNumbers = new int[0]
+ AbsoluteEpisodeNumbers = new int[0],
+ Languages = new List { Language.English }
};
_singleEpisodeSearchCriteria = new SingleEpisodeSearchCriteria
diff --git a/src/NzbDrone.Core.Test/ParserTests/ParsingServiceTests/MapFixture.cs b/src/NzbDrone.Core.Test/ParserTests/ParsingServiceTests/MapFixture.cs
index 5249af1aa..d8c6fbb8d 100644
--- a/src/NzbDrone.Core.Test/ParserTests/ParsingServiceTests/MapFixture.cs
+++ b/src/NzbDrone.Core.Test/ParserTests/ParsingServiceTests/MapFixture.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using FizzWare.NBuilder;
@@ -7,6 +7,7 @@ using Moq;
using NUnit.Framework;
using NzbDrone.Core.DataAugmentation.Scene;
using NzbDrone.Core.IndexerSearch.Definitions;
+using NzbDrone.Core.Languages;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Tv;
@@ -41,7 +42,8 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
SeriesTitle = _series.Title,
SeriesTitleInfo = new SeriesTitleInfo(),
SeasonNumber = 1,
- EpisodeNumbers = new[] { 1 }
+ EpisodeNumbers = new[] { 1 },
+ Languages = new List { Language.English }
};
_singleEpisodeSearchCriteria = new SingleEpisodeSearchCriteria
diff --git a/src/NzbDrone.Core/CustomFormats/CustomFormatCalculationService.cs b/src/NzbDrone.Core/CustomFormats/CustomFormatCalculationService.cs
index 6b7546db0..b1b6eec29 100644
--- a/src/NzbDrone.Core/CustomFormats/CustomFormatCalculationService.cs
+++ b/src/NzbDrone.Core/CustomFormats/CustomFormatCalculationService.cs
@@ -84,7 +84,8 @@ namespace NzbDrone.Core.CustomFormats
ExtraInfo = new Dictionary
{
{ "Size", episodeFile.Size },
- { "Filename", Path.GetFileName(episodeFile.RelativePath) }
+ { "Filename", Path.GetFileName(episodeFile.RelativePath) },
+ { "OriginalLanguage", episodeFile.Series.Value.OriginalLanguage }
}
};
diff --git a/src/NzbDrone.Core/CustomFormats/Specifications/LanguageSpecification.cs b/src/NzbDrone.Core/CustomFormats/Specifications/LanguageSpecification.cs
index 341fb4d62..42950a407 100644
--- a/src/NzbDrone.Core/CustomFormats/Specifications/LanguageSpecification.cs
+++ b/src/NzbDrone.Core/CustomFormats/Specifications/LanguageSpecification.cs
@@ -34,7 +34,11 @@ namespace NzbDrone.Core.CustomFormats
protected override bool IsSatisfiedByWithoutNegate(ParsedEpisodeInfo episodeInfo)
{
- return episodeInfo?.Languages?.Contains((Language)Value) ?? false;
+ var comparedLanguage = episodeInfo != null && Value == Language.Original.Id && episodeInfo.ExtraInfo.ContainsKey("OriginalLanguage")
+ ? (Language)episodeInfo.ExtraInfo["OriginalLanguage"]
+ : (Language)Value;
+
+ return episodeInfo?.Languages?.Contains(comparedLanguage) ?? false;
}
public override NzbDroneValidationResult Validate()
diff --git a/src/NzbDrone.Core/Datastore/Migration/176_original_language.cs b/src/NzbDrone.Core/Datastore/Migration/176_original_language.cs
new file mode 100644
index 000000000..91250d26d
--- /dev/null
+++ b/src/NzbDrone.Core/Datastore/Migration/176_original_language.cs
@@ -0,0 +1,16 @@
+using FluentMigrator;
+using NzbDrone.Core.Datastore.Migration.Framework;
+using NzbDrone.Core.Languages;
+
+namespace NzbDrone.Core.Datastore.Migration
+{
+ [Migration(176)]
+ public class original_language : NzbDroneMigrationBase
+ {
+ protected override void MainDbUpgrade()
+ {
+ Alter.Table("Series")
+ .AddColumn("OriginalLanguage").AsInt32().WithDefaultValue((int)Language.English);
+ }
+ }
+}
diff --git a/src/NzbDrone.Core/Languages/Language.cs b/src/NzbDrone.Core/Languages/Language.cs
index ab400fc01..2e6bb638f 100644
--- a/src/NzbDrone.Core/Languages/Language.cs
+++ b/src/NzbDrone.Core/Languages/Language.cs
@@ -102,6 +102,7 @@ namespace NzbDrone.Core.Languages
public static Language Malayalam => new Language(29, "Malayalam");
public static Language Ukrainian => new Language(30, "Ukrainian");
public static Language Slovak => new Language(31, "Slovak");
+ public static Language Original => new Language(-2, "Original");
public static List All
{
@@ -140,7 +141,8 @@ namespace NzbDrone.Core.Languages
Bulgarian,
Malayalam,
Ukrainian,
- Slovak
+ Slovak,
+ Original
};
}
}
diff --git a/src/NzbDrone.Core/MediaFiles/EpisodeImport/Aggregation/Aggregators/AggregateLanguage.cs b/src/NzbDrone.Core/MediaFiles/EpisodeImport/Aggregation/Aggregators/AggregateLanguage.cs
index 06b96e87c..07c0dd34e 100644
--- a/src/NzbDrone.Core/MediaFiles/EpisodeImport/Aggregation/Aggregators/AggregateLanguage.cs
+++ b/src/NzbDrone.Core/MediaFiles/EpisodeImport/Aggregation/Aggregators/AggregateLanguage.cs
@@ -22,7 +22,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Aggregation.Aggregators
public LocalEpisode Aggregate(LocalEpisode localEpisode, DownloadClientItem downloadClientItem)
{
- var languages = new List { Language.English };
+ var languages = new List { localEpisode.Series?.OriginalLanguage ?? Language.Unknown };
var languagesConfidence = Confidence.Default;
foreach (var augmentLanguage in _augmentLanguages)
@@ -37,7 +37,6 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Aggregation.Aggregators
if (augmentedLanguage?.Languages != null &&
augmentedLanguage.Languages.Count > 0 &&
- !(augmentedLanguage.Languages.Count == 1 && augmentedLanguage.Languages.Contains(Language.English)) &&
!(augmentedLanguage.Languages.Count == 1 && augmentedLanguage.Languages.Contains(Language.Unknown)))
{
languages = augmentedLanguage.Languages;
diff --git a/src/NzbDrone.Core/MediaFiles/EpisodeImport/Aggregation/Aggregators/Augmenters/Language/AugmentLanguageFromDownloadClientItem.cs b/src/NzbDrone.Core/MediaFiles/EpisodeImport/Aggregation/Aggregators/Augmenters/Language/AugmentLanguageFromDownloadClientItem.cs
index 6ef6d5d60..906d2ff7f 100644
--- a/src/NzbDrone.Core/MediaFiles/EpisodeImport/Aggregation/Aggregators/Augmenters/Language/AugmentLanguageFromDownloadClientItem.cs
+++ b/src/NzbDrone.Core/MediaFiles/EpisodeImport/Aggregation/Aggregators/Augmenters/Language/AugmentLanguageFromDownloadClientItem.cs
@@ -23,7 +23,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Aggregation.Aggregators.Augment
foreach (var episode in localEpisode.Episodes)
{
- var episodeTitleLanguage = LanguageParser.ParseLanguages(episode.Title, false);
+ var episodeTitleLanguage = LanguageParser.ParseLanguages(episode.Title);
languages = languages.Except(episodeTitleLanguage).ToList();
}
diff --git a/src/NzbDrone.Core/MediaFiles/EpisodeImport/Aggregation/Aggregators/Augmenters/Language/AugmentLanguageFromFileName.cs b/src/NzbDrone.Core/MediaFiles/EpisodeImport/Aggregation/Aggregators/Augmenters/Language/AugmentLanguageFromFileName.cs
index 7bdb8c31d..04384a27a 100644
--- a/src/NzbDrone.Core/MediaFiles/EpisodeImport/Aggregation/Aggregators/Augmenters/Language/AugmentLanguageFromFileName.cs
+++ b/src/NzbDrone.Core/MediaFiles/EpisodeImport/Aggregation/Aggregators/Augmenters/Language/AugmentLanguageFromFileName.cs
@@ -21,7 +21,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Aggregation.Aggregators.Augment
foreach (var episode in localEpisode.Episodes)
{
- var episodeTitleLanguage = LanguageParser.ParseLanguages(episode.Title, false);
+ var episodeTitleLanguage = LanguageParser.ParseLanguages(episode.Title);
languages = languages.Except(episodeTitleLanguage).ToList();
}
diff --git a/src/NzbDrone.Core/MediaFiles/EpisodeImport/Aggregation/Aggregators/Augmenters/Language/AugmentLanguageFromFolder.cs b/src/NzbDrone.Core/MediaFiles/EpisodeImport/Aggregation/Aggregators/Augmenters/Language/AugmentLanguageFromFolder.cs
index 39c079f19..3ce9b431c 100644
--- a/src/NzbDrone.Core/MediaFiles/EpisodeImport/Aggregation/Aggregators/Augmenters/Language/AugmentLanguageFromFolder.cs
+++ b/src/NzbDrone.Core/MediaFiles/EpisodeImport/Aggregation/Aggregators/Augmenters/Language/AugmentLanguageFromFolder.cs
@@ -21,7 +21,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Aggregation.Aggregators.Augment
foreach (var episode in localEpisode.Episodes)
{
- var episodeTitleLanguage = LanguageParser.ParseLanguages(episode.Title, false);
+ var episodeTitleLanguage = LanguageParser.ParseLanguages(episode.Title);
languages = languages.Except(episodeTitleLanguage).ToList();
}
diff --git a/src/NzbDrone.Core/MediaFiles/EpisodeImport/Manual/ManualImportService.cs b/src/NzbDrone.Core/MediaFiles/EpisodeImport/Manual/ManualImportService.cs
index 6b6c50871..5ba365cd2 100644
--- a/src/NzbDrone.Core/MediaFiles/EpisodeImport/Manual/ManualImportService.cs
+++ b/src/NzbDrone.Core/MediaFiles/EpisodeImport/Manual/ManualImportService.cs
@@ -139,6 +139,14 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
var rootFolder = Path.GetDirectoryName(path);
var series = _seriesService.GetSeries(seriesId);
+ var languageParse = LanguageParser.ParseLanguages(path);
+
+ if (languageParse.Count <= 1 && languageParse.First() == Language.Unknown && series != null)
+ {
+ languageParse = new List { series.OriginalLanguage };
+ _logger.Debug("Language couldn't be parsed from release, falling back to series original language: {0}", series.OriginalLanguage.Name);
+ }
+
if (episodeIds.Any())
{
var downloadClientItem = GetTrackedDownload(downloadId)?.DownloadItem;
@@ -153,7 +161,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
localEpisode.ExistingFile = series.Path.IsParentPath(path);
localEpisode.Size = _diskProvider.GetFileSize(path);
localEpisode.ReleaseGroup = releaseGroup.IsNullOrWhiteSpace() ? Parser.Parser.ParseReleaseGroup(path) : releaseGroup;
- localEpisode.Languages = (languages?.SingleOrDefault() ?? Language.Unknown) == Language.Unknown ? LanguageParser.ParseLanguages(path) : languages;
+ localEpisode.Languages = (languages?.SingleOrDefault() ?? Language.Unknown) == Language.Unknown ? languageParse : languages;
localEpisode.Quality = quality.Quality == Quality.Unknown ? QualityParser.ParseQuality(path) : quality;
return MapItem(_importDecisionMaker.GetDecision(localEpisode, downloadClientItem), rootFolder, downloadId, null);
diff --git a/src/NzbDrone.Core/MediaFiles/EpisodeImport/Specifications/UpgradeSpecification.cs b/src/NzbDrone.Core/MediaFiles/EpisodeImport/Specifications/UpgradeSpecification.cs
index ae7f5d9af..4f1ddaf0e 100644
--- a/src/NzbDrone.Core/MediaFiles/EpisodeImport/Specifications/UpgradeSpecification.cs
+++ b/src/NzbDrone.Core/MediaFiles/EpisodeImport/Specifications/UpgradeSpecification.cs
@@ -5,9 +5,7 @@ using NzbDrone.Core.Configuration;
using NzbDrone.Core.CustomFormats;
using NzbDrone.Core.DecisionEngine;
using NzbDrone.Core.Download;
-using NzbDrone.Core.Languages;
using NzbDrone.Core.Parser.Model;
-using NzbDrone.Core.Profiles.Releases;
using NzbDrone.Core.Qualities;
namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications
@@ -43,7 +41,6 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications
}
var qualityCompare = qualityComparer.Compare(localEpisode.Quality.Quality, episodeFile.Quality.Quality);
- var customFormatScore = GetCustomFormatScore(localEpisode);
if (qualityCompare < 0)
{
@@ -62,46 +59,9 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications
_logger.Debug("This file isn't a quality revision upgrade for all episodes. Skipping {0}", localEpisode.Path);
return Decision.Reject("Not a quality revision upgrade for existing episode file(s)");
}
-
- var customFormats = _customFormatCalculationService.ParseCustomFormat(episodeFile);
- var episodeFileCustomFormatScore = localEpisode.Series.QualityProfile.Value.CalculateCustomFormatScore(customFormats);
-
- if (qualityCompare == 0 && customFormatScore < episodeFileCustomFormatScore)
- {
- _logger.Debug("This file isn't a custom format upgrade for episode. Skipping {0}", localEpisode.Path);
- return Decision.Reject("Not a custom format upgrade for existing episode file(s)");
- }
}
return Decision.Accept();
}
-
- private int GetCustomFormatScore(LocalEpisode localEpisode)
- {
- var series = localEpisode.Series;
- var scores = new List();
- var fileFormats = new List();
- var folderFormats = new List();
- var clientFormats = new List();
-
- if (localEpisode.FileEpisodeInfo != null)
- {
- fileFormats = _customFormatCalculationService.ParseCustomFormat(localEpisode.FileEpisodeInfo);
- }
-
- if (localEpisode.FolderEpisodeInfo != null)
- {
- folderFormats = _customFormatCalculationService.ParseCustomFormat(localEpisode.FolderEpisodeInfo);
- }
-
- if (localEpisode.DownloadClientEpisodeInfo != null)
- {
- clientFormats = _customFormatCalculationService.ParseCustomFormat(localEpisode.DownloadClientEpisodeInfo);
- }
-
- var formats = fileFormats.Union(folderFormats.Union(clientFormats)).ToList();
-
- return series.QualityProfile.Value.CalculateCustomFormatScore(formats);
- }
}
}
diff --git a/src/NzbDrone.Core/MetadataSource/SkyHook/Resource/ShowResource.cs b/src/NzbDrone.Core/MetadataSource/SkyHook/Resource/ShowResource.cs
index 76fc0ecd9..4672241c5 100644
--- a/src/NzbDrone.Core/MetadataSource/SkyHook/Resource/ShowResource.cs
+++ b/src/NzbDrone.Core/MetadataSource/SkyHook/Resource/ShowResource.cs
@@ -1,4 +1,4 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
{
@@ -29,6 +29,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
public string Network { get; set; }
public string ImdbId { get; set; }
+ public string OriginalLanguage { get; set; }
public List Actors { get; set; }
public List Genres { get; set; }
diff --git a/src/NzbDrone.Core/MetadataSource/SkyHook/SkyHookProxy.cs b/src/NzbDrone.Core/MetadataSource/SkyHook/SkyHookProxy.cs
index 331a93027..4d4448287 100644
--- a/src/NzbDrone.Core/MetadataSource/SkyHook/SkyHookProxy.cs
+++ b/src/NzbDrone.Core/MetadataSource/SkyHook/SkyHookProxy.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
@@ -9,8 +9,10 @@ using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Core.DataAugmentation.DailySeries;
using NzbDrone.Core.Exceptions;
+using NzbDrone.Core.Languages;
using NzbDrone.Core.MediaCover;
using NzbDrone.Core.MetadataSource.SkyHook.Resource;
+using NzbDrone.Core.Parser;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.MetadataSource.SkyHook
@@ -158,6 +160,8 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
series.CleanTitle = Parser.Parser.CleanSeriesTitle(show.Title);
series.SortTitle = SeriesTitleNormalizer.Normalize(show.Title, show.TvdbId);
+ series.OriginalLanguage = IsoLanguages.Find(show.OriginalLanguage.ToLower())?.Language ?? Language.English;
+
if (show.FirstAired != null)
{
series.FirstAired = DateTime.ParseExact(show.FirstAired, "yyyy-MM-dd", DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
diff --git a/src/NzbDrone.Core/Parser/LanguageParser.cs b/src/NzbDrone.Core/Parser/LanguageParser.cs
index 2549b6974..7e1e76f5d 100644
--- a/src/NzbDrone.Core/Parser/LanguageParser.cs
+++ b/src/NzbDrone.Core/Parser/LanguageParser.cs
@@ -27,7 +27,7 @@ namespace NzbDrone.Core.Parser
private static readonly Regex SubtitleLanguageRegex = new Regex(".+?[-_. ](?[a-z]{2,3})([-_. ](?full|forced|foreign|default|cc|psdh|sdh))*$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
- public static List ParseLanguages(string title, bool defaultToEnglish = true)
+ public static List ParseLanguages(string title)
{
foreach (var regex in CleanSeriesTitleRegex)
{
@@ -175,7 +175,7 @@ namespace NzbDrone.Core.Parser
if (!languages.Any())
{
- languages.Add(defaultToEnglish ? Language.English : Language.Unknown);
+ languages.Add(Language.Unknown);
}
return languages.DistinctBy(l => (int)l).ToList();
diff --git a/src/NzbDrone.Core/Parser/ParsingService.cs b/src/NzbDrone.Core/Parser/ParsingService.cs
index bbdc76156..4deed93c4 100644
--- a/src/NzbDrone.Core/Parser/ParsingService.cs
+++ b/src/NzbDrone.Core/Parser/ParsingService.cs
@@ -6,6 +6,8 @@ using NzbDrone.Common.Extensions;
using NzbDrone.Common.Instrumentation.Extensions;
using NzbDrone.Core.DataAugmentation.Scene;
using NzbDrone.Core.IndexerSearch.Definitions;
+using NzbDrone.Core.Languages;
+using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Tv;
@@ -182,6 +184,29 @@ namespace NzbDrone.Core.Parser
{
remoteEpisode.Episodes = GetEpisodes(parsedEpisodeInfo, series, remoteEpisode.MappedSeasonNumber, sceneSource, searchCriteria);
}
+
+ parsedEpisodeInfo.ExtraInfo["OriginalLanguage"] = series.OriginalLanguage;
+ }
+
+ // Use series language as fallback if we could't parse a language (more accurate than just using English)
+ if (parsedEpisodeInfo.Languages.Count <= 1 && parsedEpisodeInfo.Languages.First() == Language.Unknown && series != null)
+ {
+ parsedEpisodeInfo.Languages = new List { series.OriginalLanguage };
+ _logger.Debug("Language couldn't be parsed from release, fallback to series original language: {0}", series.OriginalLanguage.Name);
+ }
+
+ if (parsedEpisodeInfo.Languages.Contains(Language.Original))
+ {
+ parsedEpisodeInfo.Languages.Remove(Language.Original);
+
+ if (series != null && !parsedEpisodeInfo.Languages.Contains(series.OriginalLanguage))
+ {
+ parsedEpisodeInfo.Languages.Add(series.OriginalLanguage);
+ }
+ else
+ {
+ parsedEpisodeInfo.Languages.Add(Language.Unknown);
+ }
}
if (remoteEpisode.Episodes == null)
diff --git a/src/NzbDrone.Core/Tv/RefreshSeriesService.cs b/src/NzbDrone.Core/Tv/RefreshSeriesService.cs
index f34ae0c21..64467ddb1 100644
--- a/src/NzbDrone.Core/Tv/RefreshSeriesService.cs
+++ b/src/NzbDrone.Core/Tv/RefreshSeriesService.cs
@@ -91,6 +91,7 @@ namespace NzbDrone.Core.Tv
series.ImdbId = seriesInfo.ImdbId;
series.AirTime = seriesInfo.AirTime;
series.Overview = seriesInfo.Overview;
+ series.OriginalLanguage = seriesInfo.OriginalLanguage;
series.Status = seriesInfo.Status;
series.CleanTitle = seriesInfo.CleanTitle;
series.SortTitle = seriesInfo.SortTitle;
diff --git a/src/NzbDrone.Core/Tv/Series.cs b/src/NzbDrone.Core/Tv/Series.cs
index cf398cab2..b10ac3de5 100644
--- a/src/NzbDrone.Core/Tv/Series.cs
+++ b/src/NzbDrone.Core/Tv/Series.cs
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Datastore;
+using NzbDrone.Core.Languages;
using NzbDrone.Core.Profiles.Qualities;
namespace NzbDrone.Core.Tv
@@ -15,6 +16,7 @@ namespace NzbDrone.Core.Tv
Actors = new List();
Seasons = new List();
Tags = new HashSet();
+ OriginalLanguage = Language.English;
}
public int TvdbId { get; set; }
@@ -47,6 +49,7 @@ namespace NzbDrone.Core.Tv
public DateTime Added { get; set; }
public DateTime? FirstAired { get; set; }
public LazyLoaded QualityProfile { get; set; }
+ public Language OriginalLanguage { get; set; }
public List Seasons { get; set; }
public HashSet Tags { get; set; }
diff --git a/src/Sonarr.Api.V3/Series/SeriesResource.cs b/src/Sonarr.Api.V3/Series/SeriesResource.cs
index f7efc9f37..e5e672a0b 100644
--- a/src/Sonarr.Api.V3/Series/SeriesResource.cs
+++ b/src/Sonarr.Api.V3/Series/SeriesResource.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using NzbDrone.Core.Languages;
using NzbDrone.Core.MediaCover;
using NzbDrone.Core.Tv;
using Sonarr.Http.REST;
@@ -30,7 +31,7 @@ namespace Sonarr.Api.V3.Series
public string Network { get; set; }
public string AirTime { get; set; }
public List Images { get; set; }
-
+ public Language OriginalLanguage { get; set; }
public string RemotePoster { get; set; }
public List Seasons { get; set; }
public int Year { get; set; }
@@ -100,6 +101,7 @@ namespace Sonarr.Api.V3.Series
Seasons = model.Seasons.ToResource(includeSeasonImages),
Year = model.Year,
+ OriginalLanguage = model.OriginalLanguage,
Path = model.Path,
QualityProfileId = model.QualityProfileId,
@@ -161,6 +163,7 @@ namespace Sonarr.Api.V3.Series
Seasons = resource.Seasons?.ToModel() ?? new List(),
Year = resource.Year,
+ OriginalLanguage = resource.OriginalLanguage,
Path = resource.Path,
QualityProfileId = resource.QualityProfileId,