From e50abd276e22c68761619e0f135221565ba67bf0 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Wed, 4 Jan 2023 21:23:57 -0800 Subject: [PATCH] Fixed: Displaying audio and subtitle languages in UI (cherry picked from commit 139412284276479921632ee5ef1dabe76c5388b4) Rename LocalizationLanguageResource to avoid collision with LanguageResource (cherry picked from commit d2cd3f77169887086980feac3bab1f16301d189e) --- frontend/src/MovieFile/MediaInfo.js | 12 +++--- .../src/Settings/UI/UISettingsConnector.js | 39 +++++++++++-------- .../src/Utilities/String/getLanguageName.js | 27 +++++++++++++ .../Localization/LocalizationService.cs | 16 +++++--- src/NzbDrone.Core/Parser/IsoLanguage.cs | 1 + .../Localization/LocalizationController.cs | 12 ++++++ .../LocalizationLanguageResource.cs | 7 ++++ 7 files changed, 86 insertions(+), 28 deletions(-) create mode 100644 frontend/src/Utilities/String/getLanguageName.js create mode 100644 src/Radarr.Api.V3/Localization/LocalizationLanguageResource.cs diff --git a/frontend/src/MovieFile/MediaInfo.js b/frontend/src/MovieFile/MediaInfo.js index fa6f87f04..9aa4d1d7f 100644 --- a/frontend/src/MovieFile/MediaInfo.js +++ b/frontend/src/MovieFile/MediaInfo.js @@ -1,6 +1,7 @@ import _ from 'lodash'; import PropTypes from 'prop-types'; import React from 'react'; +import getLanguageName from 'Utilities/String/getLanguageName'; import * as mediaInfoTypes from './mediaInfoTypes'; function formatLanguages(languages) { @@ -8,7 +9,7 @@ function formatLanguages(languages) { return null; } - const splitLanguages = _.uniq(languages.split(' / ')); + const splitLanguages = _.uniq(languages.split('/')).map((l) => getLanguageName(l)); if (splitLanguages.length > 3) { return ( @@ -39,18 +40,15 @@ function MediaInfo(props) { return ( { - !!audioCodec && - audioCodec + audioCodec ? audioCodec : '' } { - !!audioCodec && !!audioChannels && - ' - ' + audioCodec && audioChannels ? ' - ' : '' } { - !!audioChannels && - audioChannels.toFixed(1) + audioChannels ? audioChannels.toFixed(1) : '' } ); diff --git a/frontend/src/Settings/UI/UISettingsConnector.js b/frontend/src/Settings/UI/UISettingsConnector.js index ea9194f8c..0f891dd7d 100644 --- a/frontend/src/Settings/UI/UISettingsConnector.js +++ b/frontend/src/Settings/UI/UISettingsConnector.js @@ -4,30 +4,34 @@ import { connect } from 'react-redux'; import { createSelector } from 'reselect'; import { clearPendingChanges } from 'Store/Actions/baseActions'; import { fetchUISettings, saveUISettings, setUISettingsValue } from 'Store/Actions/settingsActions'; +import createLanguagesSelector from 'Store/Selectors/createLanguagesSelector'; import createSettingsSectionSelector from 'Store/Selectors/createSettingsSectionSelector'; import UISettings from './UISettings'; const SECTION = 'ui'; +const FILTER_LANGUAGES = ['Any', 'Unknown', 'Original']; -function createLanguagesSelector() { +function createFilteredLanguagesSelector() { return createSelector( - (state) => state.settings.languages, + createLanguagesSelector(), (languages) => { - const items = languages.items; - const filterItems = ['Any', 'Unknown']; - - if (!items) { + if (!languages || !languages.items) { return []; } - const newItems = items.filter((lang) => !filterItems.includes(lang.name)).map((item) => { - return { - key: item.id, - value: item.name - }; - }); + const newItems = languages.items + .filter((lang) => !FILTER_LANGUAGES.includes(lang.name)) + .map((item) => { + return { + key: item.id, + value: item.name + }; + }); - return newItems; + return { + ...languages, + items: newItems + }; } ); } @@ -36,12 +40,15 @@ function createMapStateToProps() { return createSelector( (state) => state.settings.advancedSettings, createSettingsSectionSelector(SECTION), - createLanguagesSelector(), + createFilteredLanguagesSelector(), (advancedSettings, sectionSettings, languages) => { return { advancedSettings, - languages, - ...sectionSettings + languages: languages.items, + isLanguagesPopulated: languages.isPopulated, + ...sectionSettings, + isFetching: sectionSettings.isFetching || languages.isFetching, + error: sectionSettings.error || languages.error }; } ); diff --git a/frontend/src/Utilities/String/getLanguageName.js b/frontend/src/Utilities/String/getLanguageName.js new file mode 100644 index 000000000..db957e643 --- /dev/null +++ b/frontend/src/Utilities/String/getLanguageName.js @@ -0,0 +1,27 @@ +import createAjaxRequest from 'Utilities/createAjaxRequest'; + +function getTranslations() { + return createAjaxRequest({ + global: false, + dataType: 'json', + url: '/localization/language' + }).request; +} + +let languageNames = new Intl.DisplayNames(['en'], { type: 'language' }); + +getTranslations().then((data) => { + const names = new Intl.DisplayNames([data.identifier], { type: 'language' }); + + if (names) { + languageNames = names; + } +}); + +export default function getLanguageName(code) { + if (!languageNames) { + return code; + } + + return languageNames.of(code) ?? code; +} diff --git a/src/NzbDrone.Core/Localization/LocalizationService.cs b/src/NzbDrone.Core/Localization/LocalizationService.cs index 38a2c0a69..8633ea45c 100644 --- a/src/NzbDrone.Core/Localization/LocalizationService.cs +++ b/src/NzbDrone.Core/Localization/LocalizationService.cs @@ -20,6 +20,7 @@ public interface ILocalizationService Dictionary GetLocalizationDictionary(); string GetLocalizedString(string phrase); string GetLocalizedString(string phrase, string language); + string GetLanguageIdentifier(); } public class LocalizationService : ILocalizationService, IHandleAsync @@ -45,14 +46,14 @@ public LocalizationService(IConfigService configService, public Dictionary GetLocalizationDictionary() { - var language = GetSetLanguageFileName(); + var language = GetLanguageFileName(); return GetLocalizationDictionary(language); } public string GetLocalizedString(string phrase) { - var language = GetSetLanguageFileName(); + var language = GetLanguageFileName(); return GetLocalizedString(phrase, language); } @@ -66,7 +67,7 @@ public string GetLocalizedString(string phrase, string language) if (language.IsNullOrWhiteSpace()) { - language = GetSetLanguageFileName(); + language = GetLanguageFileName(); } if (language == null) @@ -84,19 +85,24 @@ public string GetLocalizedString(string phrase, string language) return phrase; } - private string GetSetLanguageFileName() + public string GetLanguageIdentifier() { var isoLanguage = IsoLanguages.Get((Language)_configService.UILanguage); var language = isoLanguage.TwoLetterCode; if (isoLanguage.CountryCode.IsNotNullOrWhiteSpace()) { - language = string.Format("{0}_{1}", language, isoLanguage.CountryCode); + language = $"{language}-{isoLanguage.CountryCode.ToUpperInvariant()}"; } return language; } + private string GetLanguageFileName() + { + return GetLanguageIdentifier().Replace("-", "_").ToLowerInvariant(); + } + private Dictionary GetLocalizationDictionary(string language) { if (string.IsNullOrEmpty(language)) diff --git a/src/NzbDrone.Core/Parser/IsoLanguage.cs b/src/NzbDrone.Core/Parser/IsoLanguage.cs index 6f919c572..c9d0f740e 100644 --- a/src/NzbDrone.Core/Parser/IsoLanguage.cs +++ b/src/NzbDrone.Core/Parser/IsoLanguage.cs @@ -9,6 +9,7 @@ public class IsoLanguage public string CountryCode { get; set; } public string EnglishName { get; set; } public Language Language { get; set; } + public string CountyCodeLower => CountryCode?.ToLower(); public IsoLanguage(string twoLetterCode, string countryCode, string threeLetterCode, string englishName, Language language) { diff --git a/src/Radarr.Api.V3/Localization/LocalizationController.cs b/src/Radarr.Api.V3/Localization/LocalizationController.cs index b12f074b5..9fb330f72 100644 --- a/src/Radarr.Api.V3/Localization/LocalizationController.cs +++ b/src/Radarr.Api.V3/Localization/LocalizationController.cs @@ -25,5 +25,17 @@ public string GetLocalizationDictionary() { return JsonSerializer.Serialize(_localizationService.GetLocalizationDictionary().ToResource(), _serializerSettings); } + + [HttpGet("language")] + [Produces("application/json")] + public LocalizationLanguageResource GetLanguage() + { + var identifier = _localizationService.GetLanguageIdentifier(); + + return new LocalizationLanguageResource + { + Identifier = identifier + }; + } } } diff --git a/src/Radarr.Api.V3/Localization/LocalizationLanguageResource.cs b/src/Radarr.Api.V3/Localization/LocalizationLanguageResource.cs new file mode 100644 index 000000000..e331022f9 --- /dev/null +++ b/src/Radarr.Api.V3/Localization/LocalizationLanguageResource.cs @@ -0,0 +1,7 @@ +namespace Radarr.Api.V3.Localization +{ + public class LocalizationLanguageResource + { + public string Identifier { get; set; } + } +}