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)
This commit is contained in:
Mark McDowall 2023-01-04 21:23:57 -08:00 committed by Bogdan
parent 933d9e074c
commit e50abd276e
7 changed files with 86 additions and 28 deletions

View File

@ -1,6 +1,7 @@
import _ from 'lodash'; import _ from 'lodash';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
import getLanguageName from 'Utilities/String/getLanguageName';
import * as mediaInfoTypes from './mediaInfoTypes'; import * as mediaInfoTypes from './mediaInfoTypes';
function formatLanguages(languages) { function formatLanguages(languages) {
@ -8,7 +9,7 @@ function formatLanguages(languages) {
return null; return null;
} }
const splitLanguages = _.uniq(languages.split(' / ')); const splitLanguages = _.uniq(languages.split('/')).map((l) => getLanguageName(l));
if (splitLanguages.length > 3) { if (splitLanguages.length > 3) {
return ( return (
@ -39,18 +40,15 @@ function MediaInfo(props) {
return ( return (
<span> <span>
{ {
!!audioCodec && audioCodec ? audioCodec : ''
audioCodec
} }
{ {
!!audioCodec && !!audioChannels && audioCodec && audioChannels ? ' - ' : ''
' - '
} }
{ {
!!audioChannels && audioChannels ? audioChannels.toFixed(1) : ''
audioChannels.toFixed(1)
} }
</span> </span>
); );

View File

@ -4,30 +4,34 @@ import { connect } from 'react-redux';
import { createSelector } from 'reselect'; import { createSelector } from 'reselect';
import { clearPendingChanges } from 'Store/Actions/baseActions'; import { clearPendingChanges } from 'Store/Actions/baseActions';
import { fetchUISettings, saveUISettings, setUISettingsValue } from 'Store/Actions/settingsActions'; import { fetchUISettings, saveUISettings, setUISettingsValue } from 'Store/Actions/settingsActions';
import createLanguagesSelector from 'Store/Selectors/createLanguagesSelector';
import createSettingsSectionSelector from 'Store/Selectors/createSettingsSectionSelector'; import createSettingsSectionSelector from 'Store/Selectors/createSettingsSectionSelector';
import UISettings from './UISettings'; import UISettings from './UISettings';
const SECTION = 'ui'; const SECTION = 'ui';
const FILTER_LANGUAGES = ['Any', 'Unknown', 'Original'];
function createLanguagesSelector() { function createFilteredLanguagesSelector() {
return createSelector( return createSelector(
(state) => state.settings.languages, createLanguagesSelector(),
(languages) => { (languages) => {
const items = languages.items; if (!languages || !languages.items) {
const filterItems = ['Any', 'Unknown'];
if (!items) {
return []; return [];
} }
const newItems = items.filter((lang) => !filterItems.includes(lang.name)).map((item) => { const newItems = languages.items
return { .filter((lang) => !FILTER_LANGUAGES.includes(lang.name))
key: item.id, .map((item) => {
value: item.name return {
}; key: item.id,
}); value: item.name
};
});
return newItems; return {
...languages,
items: newItems
};
} }
); );
} }
@ -36,12 +40,15 @@ function createMapStateToProps() {
return createSelector( return createSelector(
(state) => state.settings.advancedSettings, (state) => state.settings.advancedSettings,
createSettingsSectionSelector(SECTION), createSettingsSectionSelector(SECTION),
createLanguagesSelector(), createFilteredLanguagesSelector(),
(advancedSettings, sectionSettings, languages) => { (advancedSettings, sectionSettings, languages) => {
return { return {
advancedSettings, advancedSettings,
languages, languages: languages.items,
...sectionSettings isLanguagesPopulated: languages.isPopulated,
...sectionSettings,
isFetching: sectionSettings.isFetching || languages.isFetching,
error: sectionSettings.error || languages.error
}; };
} }
); );

View File

@ -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;
}

View File

@ -20,6 +20,7 @@ namespace NzbDrone.Core.Localization
Dictionary<string, string> GetLocalizationDictionary(); Dictionary<string, string> GetLocalizationDictionary();
string GetLocalizedString(string phrase); string GetLocalizedString(string phrase);
string GetLocalizedString(string phrase, string language); string GetLocalizedString(string phrase, string language);
string GetLanguageIdentifier();
} }
public class LocalizationService : ILocalizationService, IHandleAsync<ConfigSavedEvent> public class LocalizationService : ILocalizationService, IHandleAsync<ConfigSavedEvent>
@ -45,14 +46,14 @@ namespace NzbDrone.Core.Localization
public Dictionary<string, string> GetLocalizationDictionary() public Dictionary<string, string> GetLocalizationDictionary()
{ {
var language = GetSetLanguageFileName(); var language = GetLanguageFileName();
return GetLocalizationDictionary(language); return GetLocalizationDictionary(language);
} }
public string GetLocalizedString(string phrase) public string GetLocalizedString(string phrase)
{ {
var language = GetSetLanguageFileName(); var language = GetLanguageFileName();
return GetLocalizedString(phrase, language); return GetLocalizedString(phrase, language);
} }
@ -66,7 +67,7 @@ namespace NzbDrone.Core.Localization
if (language.IsNullOrWhiteSpace()) if (language.IsNullOrWhiteSpace())
{ {
language = GetSetLanguageFileName(); language = GetLanguageFileName();
} }
if (language == null) if (language == null)
@ -84,19 +85,24 @@ namespace NzbDrone.Core.Localization
return phrase; return phrase;
} }
private string GetSetLanguageFileName() public string GetLanguageIdentifier()
{ {
var isoLanguage = IsoLanguages.Get((Language)_configService.UILanguage); var isoLanguage = IsoLanguages.Get((Language)_configService.UILanguage);
var language = isoLanguage.TwoLetterCode; var language = isoLanguage.TwoLetterCode;
if (isoLanguage.CountryCode.IsNotNullOrWhiteSpace()) if (isoLanguage.CountryCode.IsNotNullOrWhiteSpace())
{ {
language = string.Format("{0}_{1}", language, isoLanguage.CountryCode); language = $"{language}-{isoLanguage.CountryCode.ToUpperInvariant()}";
} }
return language; return language;
} }
private string GetLanguageFileName()
{
return GetLanguageIdentifier().Replace("-", "_").ToLowerInvariant();
}
private Dictionary<string, string> GetLocalizationDictionary(string language) private Dictionary<string, string> GetLocalizationDictionary(string language)
{ {
if (string.IsNullOrEmpty(language)) if (string.IsNullOrEmpty(language))

View File

@ -9,6 +9,7 @@ namespace NzbDrone.Core.Parser
public string CountryCode { get; set; } public string CountryCode { get; set; }
public string EnglishName { get; set; } public string EnglishName { get; set; }
public Language Language { get; set; } public Language Language { get; set; }
public string CountyCodeLower => CountryCode?.ToLower();
public IsoLanguage(string twoLetterCode, string countryCode, string threeLetterCode, string englishName, Language language) public IsoLanguage(string twoLetterCode, string countryCode, string threeLetterCode, string englishName, Language language)
{ {

View File

@ -25,5 +25,17 @@ namespace Radarr.Api.V3.Localization
{ {
return JsonSerializer.Serialize(_localizationService.GetLocalizationDictionary().ToResource(), _serializerSettings); return JsonSerializer.Serialize(_localizationService.GetLocalizationDictionary().ToResource(), _serializerSettings);
} }
[HttpGet("language")]
[Produces("application/json")]
public LocalizationLanguageResource GetLanguage()
{
var identifier = _localizationService.GetLanguageIdentifier();
return new LocalizationLanguageResource
{
Identifier = identifier
};
}
} }
} }

View File

@ -0,0 +1,7 @@
namespace Radarr.Api.V3.Localization
{
public class LocalizationLanguageResource
{
public string Identifier { get; set; }
}
}