mirror of
https://github.com/Radarr/Radarr
synced 2026-01-23 16:04:18 +01:00
New: Add regional translation support (fr-CA, en-CA, es-MX, pt-BR)
Adds the ability to fetch regional translation titles from TMDb and use them in indexer searches. This addresses requests for supporting regional language variants like French Canadian (fr-CA) which have different movie titles than the base language (fr). Changes: - Add config settings: FetchRegionalTranslations, RegionalTranslationVariants, and RegionalTranslationRateLimit in Media Management - Add UI settings in Media Management page for configuring regional variants - Extend TranslationResource to parse TMDb API format (iso_639_1, iso_3166_1) - Implement FetchRegionalTranslationsFromTMDb in SkyHookProxy - Fix MovieTranslationService to use DistinctBy(CleanTitle) instead of DistinctBy(Language) allowing multiple translations for the same language with different titles (e.g., fr 'À nous quatre' and fr-CA 'L'attrape-parents') Closes #10482 Related: #7788, #4612, #2644
This commit is contained in:
parent
89110c2cc8
commit
bd52c075a5
16 changed files with 418 additions and 7 deletions
|
|
@ -461,6 +461,124 @@ function MediaManagement() {
|
|||
</FormGroup>
|
||||
</FieldSet>
|
||||
|
||||
<FieldSet legend={translate('MovieInfo')}>
|
||||
<FormGroup
|
||||
advancedSettings={showAdvancedSettings}
|
||||
isAdvanced={true}
|
||||
size={sizes.MEDIUM}
|
||||
>
|
||||
<FormLabel>{translate('FetchRegionalTranslations')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="fetchRegionalTranslations"
|
||||
helpText={translate('FetchRegionalTranslationsHelpText')}
|
||||
onChange={handleInputChange}
|
||||
{...settings.fetchRegionalTranslations}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
{settings.fetchRegionalTranslations.value ? (
|
||||
<>
|
||||
<FormGroup
|
||||
advancedSettings={showAdvancedSettings}
|
||||
isAdvanced={true}
|
||||
>
|
||||
<FormLabel>{translate('RegionalTranslationVariants')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.TEXT}
|
||||
name="regionalTranslationVariants"
|
||||
helpTexts={[
|
||||
translate('RegionalTranslationVariantsHelpText'),
|
||||
translate('RegionalTranslationVariantsHelpTextExamples'),
|
||||
]}
|
||||
onChange={handleInputChange}
|
||||
{...settings.regionalTranslationVariants}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup
|
||||
advancedSettings={showAdvancedSettings}
|
||||
isAdvanced={true}
|
||||
size={sizes.MEDIUM}
|
||||
>
|
||||
<FormLabel>{translate('RegionalTranslationRateLimit')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.NUMBER}
|
||||
unit="ms"
|
||||
name="regionalTranslationRateLimit"
|
||||
helpText={translate('RegionalTranslationRateLimitHelpText')}
|
||||
min={100}
|
||||
max={5000}
|
||||
onChange={handleInputChange}
|
||||
{...settings.regionalTranslationRateLimit}
|
||||
/>
|
||||
</FormGroup>
|
||||
</>
|
||||
) : null}
|
||||
</FieldSet>
|
||||
|
||||
<FieldSet legend={translate('MovieInfo')}>
|
||||
<FormGroup
|
||||
advancedSettings={showAdvancedSettings}
|
||||
isAdvanced={true}
|
||||
size={sizes.MEDIUM}
|
||||
>
|
||||
<FormLabel>{translate('FetchRegionalTranslations')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="fetchRegionalTranslations"
|
||||
helpText={translate('FetchRegionalTranslationsHelpText')}
|
||||
onChange={handleInputChange}
|
||||
{...settings.fetchRegionalTranslations}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
{settings.fetchRegionalTranslations.value ? (
|
||||
<>
|
||||
<FormGroup
|
||||
advancedSettings={showAdvancedSettings}
|
||||
isAdvanced={true}
|
||||
>
|
||||
<FormLabel>{translate('RegionalTranslationVariants')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.TEXT}
|
||||
name="regionalTranslationVariants"
|
||||
helpTexts={[
|
||||
translate('RegionalTranslationVariantsHelpText'),
|
||||
translate('RegionalTranslationVariantsHelpTextExamples'),
|
||||
]}
|
||||
onChange={handleInputChange}
|
||||
{...settings.regionalTranslationVariants}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup
|
||||
advancedSettings={showAdvancedSettings}
|
||||
isAdvanced={true}
|
||||
size={sizes.MEDIUM}
|
||||
>
|
||||
<FormLabel>{translate('RegionalTranslationRateLimit')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.NUMBER}
|
||||
unit="ms"
|
||||
name="regionalTranslationRateLimit"
|
||||
helpText={translate('RegionalTranslationRateLimitHelpText')}
|
||||
min={100}
|
||||
max={5000}
|
||||
onChange={handleInputChange}
|
||||
{...settings.regionalTranslationRateLimit}
|
||||
/>
|
||||
</FormGroup>
|
||||
</>
|
||||
) : null}
|
||||
</FieldSet>
|
||||
|
||||
{showAdvancedSettings && !isWindows ? (
|
||||
<FieldSet legend={translate('Permissions')}>
|
||||
<FormGroup
|
||||
|
|
|
|||
|
|
@ -18,4 +18,7 @@ export default interface MediaManagement {
|
|||
importExtraFiles: boolean;
|
||||
extraFileExtensions: string;
|
||||
enableMediaInfo: boolean;
|
||||
fetchRegionalTranslations: boolean;
|
||||
regionalTranslationVariants: string;
|
||||
regionalTranslationRateLimit: number;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"sdk": {
|
||||
"version": "8.0.405"
|
||||
"version": "8.0.122"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -156,5 +156,6 @@
|
|||
"volta": {
|
||||
"node": "20.11.1",
|
||||
"yarn": "1.22.19"
|
||||
}
|
||||
},
|
||||
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
|
||||
}
|
||||
|
|
|
|||
BIN
radarr-title-search-walkthrough.pdf
Normal file
BIN
radarr-title-search-walkthrough.pdf
Normal file
Binary file not shown.
|
|
@ -121,5 +121,23 @@ public void should_ignore_null_properties()
|
|||
|
||||
Mocker.GetMock<IConfigRepository>().Verify(c => c.Upsert("downloadedepisodesfolder", It.IsAny<string>()), Times.Never());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FetchRegionalTranslations_should_default_to_true()
|
||||
{
|
||||
Subject.FetchRegionalTranslations.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RegionalTranslationVariants_should_have_default_value()
|
||||
{
|
||||
Subject.RegionalTranslationVariants.Should().Be("fr-CA,en-CA,es-MX,pt-BR");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RegionalTranslationRateLimit_should_default_to_500()
|
||||
{
|
||||
Subject.RegionalTranslationRateLimit.Should().Be(500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ public void should_return_iso_language_for_English(string isoCode)
|
|||
[TestCase("enus")]
|
||||
[TestCase("enusa")]
|
||||
[TestCase("wo")]
|
||||
[TestCase("fr-CA")]
|
||||
public void unknown_or_invalid_code_should_return_null(string isoCode)
|
||||
{
|
||||
var result = IsoLanguages.Find(isoCode);
|
||||
|
|
@ -129,5 +128,83 @@ public void should_return_georgian(string isoCode)
|
|||
var result = IsoLanguages.Find(isoCode);
|
||||
result.Language.Should().Be(Language.Georgian);
|
||||
}
|
||||
|
||||
[TestCase("fr-CA")]
|
||||
[TestCase("fr-ca")]
|
||||
[TestCase("FR-CA")]
|
||||
public void should_return_french_for_french_canadian(string isoCode)
|
||||
{
|
||||
var result = IsoLanguages.Find(isoCode);
|
||||
result.Should().NotBeNull();
|
||||
result.Language.Should().Be(Language.French);
|
||||
}
|
||||
|
||||
[TestCase("en-CA")]
|
||||
[TestCase("en-ca")]
|
||||
[TestCase("EN-CA")]
|
||||
public void should_return_english_for_english_canadian(string isoCode)
|
||||
{
|
||||
var result = IsoLanguages.Find(isoCode);
|
||||
result.Should().NotBeNull();
|
||||
result.Language.Should().Be(Language.English);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void french_canadian_should_map_to_same_language_as_french()
|
||||
{
|
||||
var frCA = IsoLanguages.Find("fr-CA");
|
||||
var fr = IsoLanguages.Find("fr");
|
||||
|
||||
frCA.Should().NotBeNull();
|
||||
fr.Should().NotBeNull();
|
||||
frCA.Language.Should().Be(fr.Language);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void english_canadian_should_map_to_same_language_as_english()
|
||||
{
|
||||
var enCA = IsoLanguages.Find("en-CA");
|
||||
var en = IsoLanguages.Find("en");
|
||||
|
||||
enCA.Should().NotBeNull();
|
||||
en.Should().NotBeNull();
|
||||
enCA.Language.Should().Be(en.Language);
|
||||
}
|
||||
|
||||
[TestCase("de-AT")]
|
||||
[TestCase("de-at")]
|
||||
public void should_return_german_for_german_austria(string isoCode)
|
||||
{
|
||||
var result = IsoLanguages.Find(isoCode);
|
||||
result.Should().NotBeNull();
|
||||
result.Language.Should().Be(Language.German);
|
||||
}
|
||||
|
||||
[TestCase("de-CH")]
|
||||
[TestCase("de-ch")]
|
||||
public void should_return_german_for_german_switzerland(string isoCode)
|
||||
{
|
||||
var result = IsoLanguages.Find(isoCode);
|
||||
result.Should().NotBeNull();
|
||||
result.Language.Should().Be(Language.German);
|
||||
}
|
||||
|
||||
[TestCase("zh-TW")]
|
||||
[TestCase("zh-tw")]
|
||||
public void should_return_chinese_for_chinese_taiwan(string isoCode)
|
||||
{
|
||||
var result = IsoLanguages.Find(isoCode);
|
||||
result.Should().NotBeNull();
|
||||
result.Language.Should().Be(Language.Chinese);
|
||||
}
|
||||
|
||||
[TestCase("zh-HK")]
|
||||
[TestCase("zh-hk")]
|
||||
public void should_return_chinese_for_chinese_hong_kong(string isoCode)
|
||||
{
|
||||
var result = IsoLanguages.Find(isoCode);
|
||||
result.Should().NotBeNull();
|
||||
result.Language.Should().Be(Language.Chinese);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -135,6 +135,24 @@ public TMDbCountryCode CertificationCountry
|
|||
set { SetValue("CertificationCountry", value); }
|
||||
}
|
||||
|
||||
public bool FetchRegionalTranslations
|
||||
{
|
||||
get { return GetValueBoolean("FetchRegionalTranslations", false); }
|
||||
set { SetValue("FetchRegionalTranslations", value); }
|
||||
}
|
||||
|
||||
public string RegionalTranslationVariants
|
||||
{
|
||||
get { return GetValue("RegionalTranslationVariants", "fr-CA,en-CA,es-MX,pt-BR"); }
|
||||
set { SetValue("RegionalTranslationVariants", value); }
|
||||
}
|
||||
|
||||
public int RegionalTranslationRateLimit
|
||||
{
|
||||
get { return GetValueInt("RegionalTranslationRateLimit", 500); }
|
||||
set { SetValue("RegionalTranslationRateLimit", value); }
|
||||
}
|
||||
|
||||
public int MaximumSize
|
||||
{
|
||||
get { return GetValueInt("MaximumSize", 0); }
|
||||
|
|
|
|||
|
|
@ -65,6 +65,9 @@ public interface IConfigService
|
|||
|
||||
// Metadata Provider
|
||||
TMDbCountryCode CertificationCountry { get; set; }
|
||||
bool FetchRegionalTranslations { get; set; }
|
||||
string RegionalTranslationVariants { get; set; }
|
||||
int RegionalTranslationRateLimit { get; set; }
|
||||
|
||||
// UI
|
||||
int FirstDayOfWeek { get; set; }
|
||||
|
|
|
|||
|
|
@ -1150,6 +1150,14 @@
|
|||
"MovieInfoLanguage": "Movie Info Language",
|
||||
"MovieInfoLanguageHelpText": "Language that {appName} will use for Movie Information in UI",
|
||||
"MovieInfoLanguageHelpTextWarning": "Browser Reload Required",
|
||||
"MovieInfo": "Movie Info",
|
||||
"FetchRegionalTranslations": "Fetch Regional Translations",
|
||||
"FetchRegionalTranslationsHelpText": "Automatically fetch regional language variants (fr-CA, en-CA, etc.) from TMDb to include in indexer searches. Regional variants map to their base language (fr-CA → French, en-CA → English).",
|
||||
"RegionalTranslationVariants": "Regional Translation Variants",
|
||||
"RegionalTranslationVariantsHelpText": "Comma-separated list of regional language variants to fetch from TMDb (e.g., fr-CA, en-CA, es-MX, pt-BR). These will be included in searches when the base language is selected in quality profiles.",
|
||||
"RegionalTranslationVariantsHelpTextExamples": "Examples: 'fr-CA,en-CA' or 'fr-CA, en-CA, es-MX, pt-BR'",
|
||||
"RegionalTranslationRateLimit": "Regional Translation Rate Limit",
|
||||
"RegionalTranslationRateLimitHelpText": "Delay in milliseconds between regional translation requests to TMDb API. This coordinates with all other TMDb requests to prevent rate limiting. Default: 500ms.",
|
||||
"MovieInvalidFormat": "Movie: Invalid Format",
|
||||
"MovieIsDownloading": "Movie is downloading",
|
||||
"MovieIsMonitored": "Movie is monitored",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
|
||||
{
|
||||
public class TMDbTranslationsResponse
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public TranslationResource[] Translations { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
using Newtonsoft.Json;
|
||||
|
||||
namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
|
||||
{
|
||||
public class TranslationResource
|
||||
|
|
@ -5,5 +7,24 @@ public class TranslationResource
|
|||
public string Title { get; set; }
|
||||
public string Overview { get; set; }
|
||||
public string Language { get; set; }
|
||||
|
||||
// For TMDb direct API response (iso codes + nested data)
|
||||
[JsonProperty("iso_639_1")]
|
||||
public string Iso6391 { get; set; }
|
||||
|
||||
[JsonProperty("iso_3166_1")]
|
||||
public string Iso31661 { get; set; }
|
||||
|
||||
[JsonProperty("data")]
|
||||
public TranslationDataResource Data { get; set; }
|
||||
}
|
||||
|
||||
public class TranslationDataResource
|
||||
{
|
||||
[JsonProperty("title")]
|
||||
public string Title { get; set; }
|
||||
|
||||
[JsonProperty("overview")]
|
||||
public string Overview { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ public class SkyHookProxy : IProvideMovieInfo, ISearchForNewMovie
|
|||
private readonly Logger _logger;
|
||||
|
||||
private readonly IHttpRequestBuilderFactory _radarrMetadata;
|
||||
private readonly IHttpRequestBuilderFactory _tmdb;
|
||||
private readonly IConfigService _configService;
|
||||
private readonly IMovieService _movieService;
|
||||
private readonly IMovieMetadataService _movieMetadataService;
|
||||
|
|
@ -44,6 +45,7 @@ public SkyHookProxy(IHttpClient httpClient,
|
|||
{
|
||||
_httpClient = httpClient;
|
||||
_radarrMetadata = requestBuilder.RadarrMetadata;
|
||||
_tmdb = requestBuilder.TMDB;
|
||||
_configService = configService;
|
||||
_movieService = movieService;
|
||||
_movieMetadataService = movieMetadataService;
|
||||
|
|
@ -241,6 +243,11 @@ public MovieMetadata MapMovie(MovieResource resource)
|
|||
|
||||
movie.Translations.AddRange(resource.Translations.Select(MapTranslation));
|
||||
|
||||
// Fetch additional regional translations from TMDb (fr-CA, en-CA, etc.)
|
||||
// Add these as Translations so they are used for indexer searches
|
||||
var regionalTranslations = FetchRegionalTranslationsFromTMDb(resource.TmdbId);
|
||||
movie.Translations.AddRange(regionalTranslations);
|
||||
|
||||
movie.OriginalLanguage = IsoLanguages.Find(resource.OriginalLanguage.ToLower())?.Language ?? Language.English;
|
||||
|
||||
movie.Website = resource.Homepage;
|
||||
|
|
@ -638,6 +645,121 @@ private static MovieTranslation MapTranslation(TranslationResource arg)
|
|||
return newAlternativeTitle;
|
||||
}
|
||||
|
||||
private List<MovieTranslation> FetchRegionalTranslationsFromTMDb(int tmdbId)
|
||||
{
|
||||
// Check if feature is enabled
|
||||
if (!_configService.FetchRegionalTranslations)
|
||||
{
|
||||
return new List<MovieTranslation>();
|
||||
}
|
||||
|
||||
// Parse configured variants
|
||||
var wantedVariants = _configService.RegionalTranslationVariants
|
||||
.Split(',')
|
||||
.Select(v => v.Trim().ToLower())
|
||||
.Where(v => !string.IsNullOrEmpty(v))
|
||||
.ToHashSet();
|
||||
|
||||
if (!wantedVariants.Any())
|
||||
{
|
||||
_logger.Debug("No regional translation variants configured, skipping fetch");
|
||||
return new List<MovieTranslation>();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var request = _tmdb.Create()
|
||||
.SetSegment("api", "3")
|
||||
.SetSegment("route", "movie")
|
||||
.SetSegment("id", tmdbId.ToString())
|
||||
.SetSegment("secondaryRoute", "/translations")
|
||||
.Build();
|
||||
|
||||
// Use configured rate limit with coordination across all TMDb requests
|
||||
request.RateLimit = TimeSpan.FromMilliseconds(_configService.RegionalTranslationRateLimit);
|
||||
request.RateLimitKey = "regional-translations";
|
||||
|
||||
_logger.Info("Fetching regional translations for TMDb ID {0}", tmdbId);
|
||||
|
||||
var response = _httpClient.Get<TMDbTranslationsResponse>(request);
|
||||
|
||||
// Filter for configured regional variants and create MovieTranslations
|
||||
var regionalTranslations = new List<MovieTranslation>();
|
||||
_logger.Info("TMDb returned {0} translations, wanted variants: {1}", response.Resource.Translations?.Length ?? 0, string.Join(",", wantedVariants));
|
||||
foreach (var translation in response.Resource.Translations)
|
||||
{
|
||||
// Build full regional code from iso_639_1 (language) and iso_3166_1 (country)
|
||||
// e.g., "fr" + "CA" = "fr-ca"
|
||||
var languageCode = translation.Iso6391?.ToLower();
|
||||
var countryCode = translation.Iso31661?.ToLower();
|
||||
|
||||
if (string.IsNullOrEmpty(languageCode))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create regional variant code (e.g., "fr-ca")
|
||||
var regionalCode = !string.IsNullOrEmpty(countryCode)
|
||||
? $"{languageCode}-{countryCode}"
|
||||
: languageCode;
|
||||
|
||||
// Check if this is a wanted regional variant
|
||||
if (wantedVariants.Contains(regionalCode))
|
||||
{
|
||||
// Get title and overview from nested data object (TMDb API format)
|
||||
var title = translation.Data?.Title ?? translation.Title;
|
||||
var overview = translation.Data?.Overview ?? translation.Overview;
|
||||
|
||||
if (string.IsNullOrEmpty(title))
|
||||
{
|
||||
_logger.Info("Matched {0} but title is empty, skipping", regionalCode);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Map the language code to Radarr's Language enum
|
||||
var language = IsoLanguages.Find(languageCode)?.Language;
|
||||
if (language == null)
|
||||
{
|
||||
_logger.Info("Could not map language code {0} to Radarr language for regional translation", languageCode);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create a MovieTranslation so it's used in indexer searches
|
||||
var movieTranslation = new MovieTranslation
|
||||
{
|
||||
Title = title,
|
||||
Overview = overview,
|
||||
CleanTitle = title.CleanMovieTitle(),
|
||||
Language = language
|
||||
};
|
||||
|
||||
regionalTranslations.Add(movieTranslation);
|
||||
_logger.Info("Added regional translation {0} ({1}) for movie {2}", regionalCode, title, tmdbId);
|
||||
}
|
||||
}
|
||||
|
||||
_logger.Info("Fetched {0} regional translations for TMDb ID {1}", regionalTranslations.Count, tmdbId);
|
||||
return regionalTranslations;
|
||||
}
|
||||
catch (TooManyRequestsException ex)
|
||||
{
|
||||
_logger.Warn("Rate limit hit fetching regional translations for TMDb ID {0}. Will retry on next refresh. Retry after: {1}", tmdbId, ex.RetryAfter);
|
||||
return new List<MovieTranslation>();
|
||||
}
|
||||
catch (HttpException ex)
|
||||
{
|
||||
_logger.Debug(ex, "HTTP error fetching regional translations for TMDb ID {0}", tmdbId);
|
||||
return new List<MovieTranslation>();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "Unexpected error fetching regional translations for TMDb ID {0}", tmdbId);
|
||||
return new List<MovieTranslation>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static Ratings MapRatings(RatingResource ratings)
|
||||
{
|
||||
if (ratings == null)
|
||||
|
|
|
|||
|
|
@ -51,8 +51,10 @@ public List<MovieTranslation> UpdateTranslations(List<MovieTranslation> translat
|
|||
// Then throw out any we don't have languages for
|
||||
translations = translations.Where(t => t.Language != null).ToList();
|
||||
|
||||
// Then make sure they are all distinct languages
|
||||
translations = translations.DistinctBy(t => t.Language).ToList();
|
||||
// Make sure translations are distinct by their CleanTitle
|
||||
// This allows multiple translations for the same language with different titles
|
||||
// (e.g., fr="À nous quatre" and fr-CA="L'attrape-parents" both map to Language.French)
|
||||
translations = translations.DistinctBy(t => t.CleanTitle).ToList();
|
||||
|
||||
// Now find translations to delete, update and insert
|
||||
var existingTranslations = _translationRepo.FindByMovieMetadataId(movieMetadataId);
|
||||
|
|
|
|||
|
|
@ -11,15 +11,21 @@ public static class IsoLanguages
|
|||
private static readonly HashSet<IsoLanguage> All = new HashSet<IsoLanguage>
|
||||
{
|
||||
new IsoLanguage("en", "", "eng", "English", Language.English),
|
||||
new IsoLanguage("en", "ca", "eng", "English (Canada)", Language.English),
|
||||
new IsoLanguage("fr", "fr", "fra", "French", Language.French),
|
||||
new IsoLanguage("fr", "ca", "fra", "French (Canada)", Language.French),
|
||||
new IsoLanguage("es", "", "spa", "Spanish", Language.Spanish),
|
||||
new IsoLanguage("de", "de", "deu", "German", Language.German),
|
||||
new IsoLanguage("de", "at", "deu", "German (Austria)", Language.German),
|
||||
new IsoLanguage("de", "ch", "deu", "German (Switzerland)", Language.German),
|
||||
new IsoLanguage("it", "", "ita", "Italian", Language.Italian),
|
||||
new IsoLanguage("da", "", "dan", "Danish", Language.Danish),
|
||||
new IsoLanguage("nl", "", "nld", "Dutch", Language.Dutch),
|
||||
new IsoLanguage("ja", "", "jpn", "Japanese", Language.Japanese),
|
||||
new IsoLanguage("is", "", "isl", "Icelandic", Language.Icelandic),
|
||||
new IsoLanguage("zh", "cn", "zho", "Chinese", Language.Chinese),
|
||||
new IsoLanguage("zh", "tw", "zho", "Chinese (Taiwan)", Language.Chinese),
|
||||
new IsoLanguage("zh", "hk", "zho", "Chinese (Hong Kong)", Language.Chinese),
|
||||
new IsoLanguage("ru", "", "rus", "Russian", Language.Russian),
|
||||
new IsoLanguage("pl", "", "pol", "Polish", Language.Polish),
|
||||
new IsoLanguage("vi", "", "vie", "Vietnamese", Language.Vietnamese),
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@ public class MediaManagementConfigResource : RestResource
|
|||
public bool ImportExtraFiles { get; set; }
|
||||
public string ExtraFileExtensions { get; set; }
|
||||
public bool EnableMediaInfo { get; set; }
|
||||
public bool FetchRegionalTranslations { get; set; }
|
||||
public string RegionalTranslationVariants { get; set; }
|
||||
public int RegionalTranslationRateLimit { get; set; }
|
||||
}
|
||||
|
||||
public static class MediaManagementConfigResourceMapper
|
||||
|
|
@ -59,7 +62,10 @@ public static MediaManagementConfigResource ToResource(IConfigService model)
|
|||
ScriptImportPath = model.ScriptImportPath,
|
||||
ImportExtraFiles = model.ImportExtraFiles,
|
||||
ExtraFileExtensions = model.ExtraFileExtensions,
|
||||
EnableMediaInfo = model.EnableMediaInfo
|
||||
EnableMediaInfo = model.EnableMediaInfo,
|
||||
FetchRegionalTranslations = model.FetchRegionalTranslations,
|
||||
RegionalTranslationVariants = model.RegionalTranslationVariants,
|
||||
RegionalTranslationRateLimit = model.RegionalTranslationRateLimit
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue