From 8c10f8b55cdb495ccd63b48b86f3f1052c81edd6 Mon Sep 17 00:00:00 2001 From: Qstick Date: Tue, 5 Jul 2022 21:22:54 -0500 Subject: [PATCH] Cleanup Language and Localization code --- frontend/src/Components/Page/PageConnector.js | 15 +- frontend/src/Settings/UI/UISettings.js | 4 +- .../src/Settings/UI/UISettingsConnector.js | 17 +- .../src/Store/Actions/Settings/languages.js | 48 ---- frontend/src/Store/Actions/index.js | 2 + .../src/Store/Actions/localizationActions.js | 39 +++ frontend/src/Store/Actions/settingsActions.js | 5 - .../Languages/LanguageFixture.cs | 85 ------ .../LocalizationServiceFixture.cs | 3 +- .../Configuration/ConfigService.cs | 5 +- .../Configuration/IConfigService.cs | 2 +- .../Converters/LanguageIntConverter.cs | 48 ---- .../021_localization_setting_to_string.cs | 82 ++++++ src/NzbDrone.Core/Datastore/TableMapping.cs | 3 - src/NzbDrone.Core/Languages/Language.cs | 193 ------------- .../Languages/LanguageExtensions.cs | 13 - .../Languages/LanguageFieldConverter.cs | 13 - .../Languages/LanguagesComparer.cs | 53 ---- .../Languages/RealLanguageFieldConverter.cs | 17 -- .../Localization/LocalizationOption.cs | 14 + .../Localization/LocalizationService.cs | 55 +++- src/NzbDrone.Core/Parser/IsoLanguage.cs | 22 -- src/NzbDrone.Core/Parser/IsoLanguages.cs | 85 ------ src/NzbDrone.Core/Parser/LanguageParser.cs | 272 ------------------ src/NzbDrone.Core/Parser/Model/ReleaseInfo.cs | 1 - .../Config/UiConfigResource.cs | 2 +- .../Languages/LanguageController.cs | 37 --- .../Languages/LanguageResource.cs | 13 - .../Localization/LocalizationController.cs | 8 + 29 files changed, 204 insertions(+), 952 deletions(-) delete mode 100644 frontend/src/Store/Actions/Settings/languages.js create mode 100644 frontend/src/Store/Actions/localizationActions.js delete mode 100644 src/NzbDrone.Core.Test/Languages/LanguageFixture.cs delete mode 100644 src/NzbDrone.Core/Datastore/Converters/LanguageIntConverter.cs create mode 100644 src/NzbDrone.Core/Datastore/Migration/021_localization_setting_to_string.cs delete mode 100644 src/NzbDrone.Core/Languages/Language.cs delete mode 100644 src/NzbDrone.Core/Languages/LanguageExtensions.cs delete mode 100644 src/NzbDrone.Core/Languages/LanguageFieldConverter.cs delete mode 100644 src/NzbDrone.Core/Languages/LanguagesComparer.cs delete mode 100644 src/NzbDrone.Core/Languages/RealLanguageFieldConverter.cs create mode 100644 src/NzbDrone.Core/Localization/LocalizationOption.cs delete mode 100644 src/NzbDrone.Core/Parser/IsoLanguage.cs delete mode 100644 src/NzbDrone.Core/Parser/IsoLanguages.cs delete mode 100644 src/NzbDrone.Core/Parser/LanguageParser.cs delete mode 100644 src/Prowlarr.Api.V1/Languages/LanguageController.cs delete mode 100644 src/Prowlarr.Api.V1/Languages/LanguageResource.cs diff --git a/frontend/src/Components/Page/PageConnector.js b/frontend/src/Components/Page/PageConnector.js index 0f826fd68..647fdcf7b 100644 --- a/frontend/src/Components/Page/PageConnector.js +++ b/frontend/src/Components/Page/PageConnector.js @@ -7,7 +7,7 @@ import { saveDimensions, setIsSidebarVisible } from 'Store/Actions/appActions'; import { fetchCustomFilters } from 'Store/Actions/customFilterActions'; import { fetchIndexers } from 'Store/Actions/indexerActions'; import { fetchIndexerStatus } from 'Store/Actions/indexerStatusActions'; -import { fetchAppProfiles, fetchGeneralSettings, fetchIndexerCategories, fetchLanguages, fetchUISettings } from 'Store/Actions/settingsActions'; +import { fetchAppProfiles, fetchGeneralSettings, fetchIndexerCategories, fetchUISettings } from 'Store/Actions/settingsActions'; import { fetchStatus } from 'Store/Actions/systemActions'; import { fetchTags } from 'Store/Actions/tagActions'; import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector'; @@ -48,7 +48,6 @@ const selectIsPopulated = createSelector( (state) => state.tags.isPopulated, (state) => state.settings.ui.isPopulated, (state) => state.settings.general.isPopulated, - (state) => state.settings.languages.isPopulated, (state) => state.settings.appProfiles.isPopulated, (state) => state.indexers.isPopulated, (state) => state.indexerStatus.isPopulated, @@ -59,7 +58,6 @@ const selectIsPopulated = createSelector( tagsIsPopulated, uiSettingsIsPopulated, generalSettingsIsPopulated, - languagesIsPopulated, appProfilesIsPopulated, indexersIsPopulated, indexerStatusIsPopulated, @@ -71,7 +69,6 @@ const selectIsPopulated = createSelector( tagsIsPopulated && uiSettingsIsPopulated && generalSettingsIsPopulated && - languagesIsPopulated && appProfilesIsPopulated && indexersIsPopulated && indexerStatusIsPopulated && @@ -86,7 +83,6 @@ const selectErrors = createSelector( (state) => state.tags.error, (state) => state.settings.ui.error, (state) => state.settings.general.error, - (state) => state.settings.languages.error, (state) => state.settings.appProfiles.error, (state) => state.indexers.error, (state) => state.indexerStatus.error, @@ -97,7 +93,6 @@ const selectErrors = createSelector( tagsError, uiSettingsError, generalSettingsError, - languagesError, appProfilesError, indexersError, indexerStatusError, @@ -109,7 +104,6 @@ const selectErrors = createSelector( tagsError || uiSettingsError || generalSettingsError || - languagesError || appProfilesError || indexersError || indexerStatusError || @@ -123,7 +117,6 @@ const selectErrors = createSelector( tagsError, uiSettingsError, generalSettingsError, - languagesError, appProfilesError, indexersError, indexerStatusError, @@ -166,9 +159,6 @@ function createMapDispatchToProps(dispatch, props) { dispatchFetchTags() { dispatch(fetchTags()); }, - dispatchFetchLanguages() { - dispatch(fetchLanguages()); - }, dispatchFetchIndexers() { dispatch(fetchIndexers()); }, @@ -216,7 +206,6 @@ class PageConnector extends Component { if (!this.props.isPopulated) { this.props.dispatchFetchCustomFilters(); this.props.dispatchFetchTags(); - this.props.dispatchFetchLanguages(); this.props.dispatchFetchAppProfiles(); this.props.dispatchFetchIndexers(); this.props.dispatchFetchIndexerStatus(); @@ -242,7 +231,6 @@ class PageConnector extends Component { isPopulated, hasError, dispatchFetchTags, - dispatchFetchLanguages, dispatchFetchAppProfiles, dispatchFetchIndexers, dispatchFetchIndexerStatus, @@ -283,7 +271,6 @@ PageConnector.propTypes = { isSidebarVisible: PropTypes.bool.isRequired, dispatchFetchCustomFilters: PropTypes.func.isRequired, dispatchFetchTags: PropTypes.func.isRequired, - dispatchFetchLanguages: PropTypes.func.isRequired, dispatchFetchAppProfiles: PropTypes.func.isRequired, dispatchFetchIndexers: PropTypes.func.isRequired, dispatchFetchIndexerStatus: PropTypes.func.isRequired, diff --git a/frontend/src/Settings/UI/UISettings.js b/frontend/src/Settings/UI/UISettings.js index 7b395225b..83443cd72 100644 --- a/frontend/src/Settings/UI/UISettings.js +++ b/frontend/src/Settings/UI/UISettings.js @@ -62,8 +62,6 @@ class UISettings extends Component { ...otherProps } = this.props; - const uiLanguages = languages.filter((item) => item.value !== 'Original'); - const themeOptions = Object.keys(themes) .map((theme) => ({ key: theme, value: titleCase(theme) })); @@ -172,7 +170,7 @@ class UISettings extends Component { state.settings.languages, - (languages) => { - const items = languages.items; - const filterItems = ['Any', 'Unknown']; + (state) => state.localization, + (localization) => { + console.log(localization); + + const items = localization.items; if (!items) { return []; } - const newItems = items.filter((lang) => !filterItems.includes(lang.name)).map((item) => { + const newItems = items.filter((lang) => !items.includes(lang.name)).map((item) => { return { - key: item.id, + key: item.value, value: item.name }; }); @@ -51,6 +53,7 @@ const mapDispatchToProps = { setUISettingsValue, saveUISettings, fetchUISettings, + fetchLocalizationOptions, clearPendingChanges }; @@ -61,6 +64,7 @@ class UISettingsConnector extends Component { componentDidMount() { this.props.fetchUISettings(); + this.props.fetchLocalizationOptions(); } componentWillUnmount() { @@ -96,6 +100,7 @@ UISettingsConnector.propTypes = { setUISettingsValue: PropTypes.func.isRequired, saveUISettings: PropTypes.func.isRequired, fetchUISettings: PropTypes.func.isRequired, + fetchLocalizationOptions: PropTypes.func.isRequired, clearPendingChanges: PropTypes.func.isRequired }; diff --git a/frontend/src/Store/Actions/Settings/languages.js b/frontend/src/Store/Actions/Settings/languages.js deleted file mode 100644 index a0b62fc49..000000000 --- a/frontend/src/Store/Actions/Settings/languages.js +++ /dev/null @@ -1,48 +0,0 @@ -import createFetchHandler from 'Store/Actions/Creators/createFetchHandler'; -import { createThunk } from 'Store/thunks'; - -// -// Variables - -const section = 'settings.languages'; - -// -// Actions Types - -export const FETCH_LANGUAGES = 'settings/languages/fetchLanguages'; - -// -// Action Creators - -export const fetchLanguages = createThunk(FETCH_LANGUAGES); - -// -// Details - -export default { - - // - // State - - defaultState: { - isFetching: false, - isPopulated: false, - error: null, - items: [] - }, - - // - // Action Handlers - - actionHandlers: { - [FETCH_LANGUAGES]: createFetchHandler(section, '/language') - }, - - // - // Reducers - - reducers: { - - } - -}; diff --git a/frontend/src/Store/Actions/index.js b/frontend/src/Store/Actions/index.js index 1f0eccd71..98db37faf 100644 --- a/frontend/src/Store/Actions/index.js +++ b/frontend/src/Store/Actions/index.js @@ -7,6 +7,7 @@ import * as indexers from './indexerActions'; import * as indexerIndex from './indexerIndexActions'; import * as indexerStats from './indexerStatsActions'; import * as indexerStatus from './indexerStatusActions'; +import * as localization from './localizationActions'; import * as oAuth from './oAuthActions'; import * as paths from './pathActions'; import * as providerOptions from './providerOptionActions'; @@ -25,6 +26,7 @@ export default [ paths, providerOptions, releases, + localization, indexers, indexerIndex, indexerStats, diff --git a/frontend/src/Store/Actions/localizationActions.js b/frontend/src/Store/Actions/localizationActions.js new file mode 100644 index 000000000..f7928fc63 --- /dev/null +++ b/frontend/src/Store/Actions/localizationActions.js @@ -0,0 +1,39 @@ +import createFetchHandler from 'Store/Actions/Creators/createFetchHandler'; +import { createThunk, handleThunks } from 'Store/thunks'; +import createHandleActions from './Creators/createHandleActions'; + +// +// Variables + +export const section = 'localization'; + +// +// State + +export const defaultState = { + isFetching: false, + isPopulated: false, + error: null, + items: [] +}; + +// +// Actions Types + +export const FETCH_LOCALIZATION_OPTIONS = 'localization/fetchLocalizationOptions'; + +// +// Action Creators + +export const fetchLocalizationOptions = createThunk(FETCH_LOCALIZATION_OPTIONS); + +// +// Action Handlers +export const actionHandlers = handleThunks({ + + [FETCH_LOCALIZATION_OPTIONS]: createFetchHandler(section, '/localization/options') +}); + +// +// Reducers +export const reducers = createHandleActions({}, defaultState, section); diff --git a/frontend/src/Store/Actions/settingsActions.js b/frontend/src/Store/Actions/settingsActions.js index e7fe7247a..6aa4ad6be 100644 --- a/frontend/src/Store/Actions/settingsActions.js +++ b/frontend/src/Store/Actions/settingsActions.js @@ -8,7 +8,6 @@ import downloadClients from './Settings/downloadClients'; import general from './Settings/general'; import indexerCategories from './Settings/indexerCategories'; import indexerProxies from './Settings/indexerProxies'; -import languages from './Settings/languages'; import notifications from './Settings/notifications'; import ui from './Settings/ui'; @@ -16,7 +15,6 @@ export * from './Settings/downloadClients'; export * from './Settings/general'; export * from './Settings/indexerCategories'; export * from './Settings/indexerProxies'; -export * from './Settings/languages'; export * from './Settings/notifications'; export * from './Settings/applications'; export * from './Settings/appProfiles'; @@ -38,7 +36,6 @@ export const defaultState = { general: general.defaultState, indexerCategories: indexerCategories.defaultState, indexerProxies: indexerProxies.defaultState, - languages: languages.defaultState, notifications: notifications.defaultState, applications: applications.defaultState, appProfiles: appProfiles.defaultState, @@ -68,7 +65,6 @@ export const actionHandlers = handleThunks({ ...general.actionHandlers, ...indexerCategories.actionHandlers, ...indexerProxies.actionHandlers, - ...languages.actionHandlers, ...notifications.actionHandlers, ...applications.actionHandlers, ...appProfiles.actionHandlers, @@ -89,7 +85,6 @@ export const reducers = createHandleActions({ ...general.reducers, ...indexerCategories.reducers, ...indexerProxies.reducers, - ...languages.reducers, ...notifications.reducers, ...applications.reducers, ...appProfiles.reducers, diff --git a/src/NzbDrone.Core.Test/Languages/LanguageFixture.cs b/src/NzbDrone.Core.Test/Languages/LanguageFixture.cs deleted file mode 100644 index 706c36541..000000000 --- a/src/NzbDrone.Core.Test/Languages/LanguageFixture.cs +++ /dev/null @@ -1,85 +0,0 @@ -using FluentAssertions; -using NUnit.Framework; -using NzbDrone.Core.Languages; -using NzbDrone.Core.Test.Framework; - -namespace NzbDrone.Core.Test.Languages -{ - [TestFixture] - public class LanguageFixture : CoreTest - { - public static object[] FromIntCases = - { - new object[] { 1, Language.English }, - new object[] { 2, Language.French }, - new object[] { 3, Language.Spanish }, - new object[] { 4, Language.German }, - new object[] { 5, Language.Italian }, - new object[] { 6, Language.Danish }, - new object[] { 7, Language.Dutch }, - new object[] { 8, Language.Japanese }, - new object[] { 9, Language.Icelandic }, - new object[] { 10, Language.Chinese }, - new object[] { 11, Language.Russian }, - new object[] { 12, Language.Polish }, - new object[] { 13, Language.Vietnamese }, - new object[] { 14, Language.Swedish }, - new object[] { 15, Language.Norwegian }, - new object[] { 16, Language.Finnish }, - new object[] { 17, Language.Turkish }, - new object[] { 18, Language.Portuguese }, - new object[] { 19, Language.Flemish }, - new object[] { 20, Language.Greek }, - new object[] { 21, Language.Korean }, - new object[] { 22, Language.Hungarian }, - new object[] { 23, Language.Hebrew }, - new object[] { 24, Language.Lithuanian }, - new object[] { 25, Language.Czech } - }; - - public static object[] ToIntCases = - { - new object[] { Language.English, 1 }, - new object[] { Language.French, 2 }, - new object[] { Language.Spanish, 3 }, - new object[] { Language.German, 4 }, - new object[] { Language.Italian, 5 }, - new object[] { Language.Danish, 6 }, - new object[] { Language.Dutch, 7 }, - new object[] { Language.Japanese, 8 }, - new object[] { Language.Icelandic, 9 }, - new object[] { Language.Chinese, 10 }, - new object[] { Language.Russian, 11 }, - new object[] { Language.Polish, 12 }, - new object[] { Language.Vietnamese, 13 }, - new object[] { Language.Swedish, 14 }, - new object[] { Language.Norwegian, 15 }, - new object[] { Language.Finnish, 16 }, - new object[] { Language.Turkish, 17 }, - new object[] { Language.Portuguese, 18 }, - new object[] { Language.Flemish, 19 }, - new object[] { Language.Greek, 20 }, - new object[] { Language.Korean, 21 }, - new object[] { Language.Hungarian, 22 }, - new object[] { Language.Hebrew, 23 }, - new object[] { Language.Lithuanian, 24 }, - new object[] { Language.Czech, 25 } - }; - - [Test] - [TestCaseSource("FromIntCases")] - public void should_be_able_to_convert_int_to_languageTypes(int source, Language expected) - { - var language = (Language)source; - language.Should().Be(expected); - } - - [Test] - [TestCaseSource("ToIntCases")] - public void should_be_able_to_convert_languageTypes_to_int(Language source, int expected) - { - var i = (int)source; - i.Should().Be(expected); - } - } -} diff --git a/src/NzbDrone.Core.Test/Localization/LocalizationServiceFixture.cs b/src/NzbDrone.Core.Test/Localization/LocalizationServiceFixture.cs index 9998bb8ee..e49b0592d 100644 --- a/src/NzbDrone.Core.Test/Localization/LocalizationServiceFixture.cs +++ b/src/NzbDrone.Core.Test/Localization/LocalizationServiceFixture.cs @@ -3,7 +3,6 @@ using FluentAssertions; using NUnit.Framework; using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Core.Configuration; -using NzbDrone.Core.Languages; using NzbDrone.Core.Localization; using NzbDrone.Core.Test.Framework; using NzbDrone.Test.Common; @@ -16,7 +15,7 @@ namespace NzbDrone.Core.Test.Localization [SetUp] public void Setup() { - Mocker.GetMock().Setup(m => m.UILanguage).Returns((int)Language.English); + Mocker.GetMock().Setup(m => m.UILanguage).Returns("en"); Mocker.GetMock().Setup(m => m.StartUpFolder).Returns(TestContext.CurrentContext.TestDirectory); } diff --git a/src/NzbDrone.Core/Configuration/ConfigService.cs b/src/NzbDrone.Core/Configuration/ConfigService.cs index 8cedd7b26..269847f33 100644 --- a/src/NzbDrone.Core/Configuration/ConfigService.cs +++ b/src/NzbDrone.Core/Configuration/ConfigService.cs @@ -6,7 +6,6 @@ using NLog; using NzbDrone.Common.EnsureThat; using NzbDrone.Common.Http.Proxy; using NzbDrone.Core.Configuration.Events; -using NzbDrone.Core.Languages; using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Security; @@ -139,9 +138,9 @@ namespace NzbDrone.Core.Configuration set { SetValue("EnableColorImpairedMode", value); } } - public int UILanguage + public string UILanguage { - get { return GetValueInt("UILanguage", (int)Language.English); } + get { return GetValue("UILanguage", "en"); } set { SetValue("UILanguage", value); } } diff --git a/src/NzbDrone.Core/Configuration/IConfigService.cs b/src/NzbDrone.Core/Configuration/IConfigService.cs index 8da617821..4f37b8d51 100644 --- a/src/NzbDrone.Core/Configuration/IConfigService.cs +++ b/src/NzbDrone.Core/Configuration/IConfigService.cs @@ -22,7 +22,7 @@ namespace NzbDrone.Core.Configuration string TimeFormat { get; set; } bool ShowRelativeDates { get; set; } bool EnableColorImpairedMode { get; set; } - int UILanguage { get; set; } + string UILanguage { get; set; } //Internal string PlexClientIdentifier { get; } diff --git a/src/NzbDrone.Core/Datastore/Converters/LanguageIntConverter.cs b/src/NzbDrone.Core/Datastore/Converters/LanguageIntConverter.cs deleted file mode 100644 index b7981367f..000000000 --- a/src/NzbDrone.Core/Datastore/Converters/LanguageIntConverter.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Data; -using System.Text.Json; -using System.Text.Json.Serialization; -using Dapper; -using NzbDrone.Core.Languages; - -namespace NzbDrone.Core.Datastore.Converters -{ - public class DapperLanguageIntConverter : SqlMapper.TypeHandler - { - public override void SetValue(IDbDataParameter parameter, Language value) - { - if (value == null) - { - throw new InvalidOperationException("Attempted to save a language that isn't really a language"); - } - else - { - parameter.Value = (int)value; - } - } - - public override Language Parse(object value) - { - if (value == null || value is DBNull) - { - return Language.Unknown; - } - - return (Language)Convert.ToInt32(value); - } - } - - public class LanguageIntConverter : JsonConverter - { - public override Language Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - var item = reader.GetInt32(); - return (Language)item; - } - - public override void Write(Utf8JsonWriter writer, Language value, JsonSerializerOptions options) - { - writer.WriteNumberValue((int)value); - } - } -} diff --git a/src/NzbDrone.Core/Datastore/Migration/021_localization_setting_to_string.cs b/src/NzbDrone.Core/Datastore/Migration/021_localization_setting_to_string.cs new file mode 100644 index 000000000..3cd0cc4c6 --- /dev/null +++ b/src/NzbDrone.Core/Datastore/Migration/021_localization_setting_to_string.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using System.Data; +using FluentMigrator; +using NzbDrone.Core.Datastore.Migration.Framework; + +namespace NzbDrone.Core.Datastore.Migration +{ + [Migration(021)] + public class localization_setting_to_string : NzbDroneMigrationBase + { + protected override void MainDbUpgrade() + { + Execute.WithConnection(FixLocalizationConfig); + } + + private void FixLocalizationConfig(IDbConnection conn, IDbTransaction tran) + { + string uiLanguage; + string uiCulture; + + using (var cmd = conn.CreateCommand()) + { + cmd.Transaction = tran; + cmd.CommandText = "SELECT \"Value\" FROM \"Config\" WHERE \"Key\" = 'uilanguage'"; + + uiLanguage = (string)cmd.ExecuteScalar(); + } + + if (uiLanguage != null && int.TryParse(uiLanguage, out var uiLanguageInt)) + { + uiCulture = _uiMapping.GetValueOrDefault(uiLanguageInt) ?? "en"; + + using (var insertCmd = conn.CreateCommand()) + { + insertCmd.Transaction = tran; + insertCmd.CommandText = string.Format("UPDATE \"Config\" SET \"Value\" = '{0}' WHERE \"Key\" = 'uilanguage'", uiCulture); + insertCmd.ExecuteNonQuery(); + } + } + } + + private readonly Dictionary _uiMapping = new Dictionary() + { + { 1, "en" }, + { 2, "fr" }, + { 3, "es" }, + { 4, "de" }, + { 5, "it" }, + { 6, "da" }, + { 7, "nl" }, + { 8, "ja" }, + { 9, "is" }, + { 10, "zh_CN" }, + { 11, "ru" }, + { 12, "pl" }, + { 13, "vi" }, + { 14, "sv" }, + { 15, "nb_NO" }, + { 16, "fi" }, + { 17, "tr" }, + { 18, "pt" }, + { 19, "en" }, + { 20, "el" }, + { 21, "ko" }, + { 22, "hu" }, + { 23, "he" }, + { 24, "lt" }, + { 25, "cs" }, + { 26, "hi" }, + { 27, "ro" }, + { 28, "th" }, + { 29, "bg" }, + { 30, "pt_BR" }, + { 31, "ar" }, + { 32, "uk" }, + { 33, "fa" }, + { 34, "be" }, + { 35, "zh_TW" }, + }; + } +} diff --git a/src/NzbDrone.Core/Datastore/TableMapping.cs b/src/NzbDrone.Core/Datastore/TableMapping.cs index 126c02740..566dba21e 100644 --- a/src/NzbDrone.Core/Datastore/TableMapping.cs +++ b/src/NzbDrone.Core/Datastore/TableMapping.cs @@ -14,7 +14,6 @@ using NzbDrone.Core.Indexers; using NzbDrone.Core.IndexerVersions; using NzbDrone.Core.Instrumentation; using NzbDrone.Core.Jobs; -using NzbDrone.Core.Languages; using NzbDrone.Core.Messaging.Commands; using NzbDrone.Core.Notifications; using NzbDrone.Core.Parser.Model; @@ -113,8 +112,6 @@ namespace NzbDrone.Core.Datastore SqlMapper.AddTypeHandler(new EmbeddedDocumentConverter>()); SqlMapper.AddTypeHandler(new EmbeddedDocumentConverter>>()); SqlMapper.AddTypeHandler(new EmbeddedDocumentConverter>()); - SqlMapper.AddTypeHandler(new DapperLanguageIntConverter()); - SqlMapper.AddTypeHandler(new EmbeddedDocumentConverter>(new LanguageIntConverter())); SqlMapper.AddTypeHandler(new EmbeddedDocumentConverter>()); SqlMapper.AddTypeHandler(new EmbeddedDocumentConverter()); SqlMapper.AddTypeHandler(new EmbeddedDocumentConverter>()); diff --git a/src/NzbDrone.Core/Languages/Language.cs b/src/NzbDrone.Core/Languages/Language.cs deleted file mode 100644 index 0265858e0..000000000 --- a/src/NzbDrone.Core/Languages/Language.cs +++ /dev/null @@ -1,193 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using NzbDrone.Core.Datastore; - -namespace NzbDrone.Core.Languages -{ - public class Language : IEmbeddedDocument, IEquatable - { - public int Id { get; set; } - public string Name { get; set; } - - public Language() - { - } - - private Language(int id, string name) - { - Id = id; - Name = name; - } - - public override string ToString() - { - return Name; - } - - public override int GetHashCode() - { - return Id.GetHashCode(); - } - - public bool Equals(Language other) - { - if (ReferenceEquals(null, other)) - { - return false; - } - - if (ReferenceEquals(this, other)) - { - return true; - } - - return Id.Equals(other.Id); - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) - { - return false; - } - - if (ReferenceEquals(this, obj)) - { - return true; - } - - return Equals(obj as Language); - } - - public static bool operator ==(Language left, Language right) - { - return Equals(left, right); - } - - public static bool operator !=(Language left, Language right) - { - return !Equals(left, right); - } - - public static Language Unknown => new Language(0, "Unknown"); - public static Language English => new Language(1, "English"); - public static Language French => new Language(2, "French"); - public static Language Spanish => new Language(3, "Spanish"); - public static Language German => new Language(4, "German"); - public static Language Italian => new Language(5, "Italian"); - public static Language Danish => new Language(6, "Danish"); - public static Language Dutch => new Language(7, "Dutch"); - public static Language Japanese => new Language(8, "Japanese"); - public static Language Icelandic => new Language(9, "Icelandic"); - public static Language Chinese => new Language(10, "Chinese (Simplified)"); - public static Language Russian => new Language(11, "Russian"); - public static Language Polish => new Language(12, "Polish"); - public static Language Vietnamese => new Language(13, "Vietnamese"); - public static Language Swedish => new Language(14, "Swedish"); - public static Language Norwegian => new Language(15, "Norwegian"); - public static Language Finnish => new Language(16, "Finnish"); - public static Language Turkish => new Language(17, "Turkish"); - public static Language Portuguese => new Language(18, "Portuguese"); - public static Language Flemish => new Language(19, "Flemish"); - public static Language Greek => new Language(20, "Greek"); - public static Language Korean => new Language(21, "Korean"); - public static Language Hungarian => new Language(22, "Hungarian"); - public static Language Hebrew => new Language(23, "Hebrew"); - public static Language Lithuanian => new Language(24, "Lithuanian"); - public static Language Czech => new Language(25, "Czech"); - public static Language Hindi => new Language(26, "Hindi"); - public static Language Romanian => new Language(27, "Romanian"); - public static Language Thai => new Language(28, "Thai"); - public static Language Bulgarian => new Language(29, "Bulgarian"); - public static Language PortugueseBR => new Language(30, "Portuguese (Brazil)"); - public static Language Arabic => new Language(31, "Arabic"); - public static Language Ukrainian => new Language(32, "Ukrainian"); - public static Language Persian => new Language(33, "Persian"); - public static Language Bengali => new Language(34, "Bengali"); - public static Language ChineseTW => new Language(35, "Chinese (Traditional)"); - public static Language Any => new Language(-1, "Any"); - public static Language Original => new Language(-2, "Original"); - - public static List All - { - get - { - return new List - { - Unknown, - English, - French, - Spanish, - German, - Italian, - Danish, - Dutch, - Japanese, - Icelandic, - Chinese, - Russian, - Polish, - Vietnamese, - Swedish, - Norwegian, - Finnish, - Turkish, - Portuguese, - Flemish, - Greek, - Korean, - Hungarian, - Hebrew, - Lithuanian, - Czech, - Romanian, - Hindi, - Thai, - Bulgarian, - Any, - Original - }; - } - } - - public static Language FindById(int id) - { - if (id == 0) - { - return Unknown; - } - - Language language = All.FirstOrDefault(v => v.Id == id); - - if (language == null) - { - throw new ArgumentException("ID does not match a known language", nameof(id)); - } - - return language; - } - - public static explicit operator Language(int id) - { - return FindById(id); - } - - public static explicit operator int(Language language) - { - return language.Id; - } - - public static explicit operator Language(string lang) - { - var language = All.FirstOrDefault(v => v.Name.Equals(lang, StringComparison.InvariantCultureIgnoreCase)); - - if (language == null) - { - throw new ArgumentException("Language does not match a known language", nameof(lang)); - } - - return language; - } - } -} diff --git a/src/NzbDrone.Core/Languages/LanguageExtensions.cs b/src/NzbDrone.Core/Languages/LanguageExtensions.cs deleted file mode 100644 index f9c42b078..000000000 --- a/src/NzbDrone.Core/Languages/LanguageExtensions.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Collections.Generic; -using System.Linq; - -namespace NzbDrone.Core.Languages -{ - public static class LanguageExtensions - { - public static string ToExtendedString(this IEnumerable languages) - { - return string.Join(", ", languages.Select(l => l.ToString())); - } - } -} diff --git a/src/NzbDrone.Core/Languages/LanguageFieldConverter.cs b/src/NzbDrone.Core/Languages/LanguageFieldConverter.cs deleted file mode 100644 index 801a251ac..000000000 --- a/src/NzbDrone.Core/Languages/LanguageFieldConverter.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Collections.Generic; -using NzbDrone.Core.Annotations; - -namespace NzbDrone.Core.Languages -{ - public class LanguageFieldConverter : ISelectOptionsConverter - { - public List GetSelectOptions() - { - return Language.All.ConvertAll(v => new SelectOption { Value = v.Id, Name = v.Name }); - } - } -} diff --git a/src/NzbDrone.Core/Languages/LanguagesComparer.cs b/src/NzbDrone.Core/Languages/LanguagesComparer.cs deleted file mode 100644 index 02a9dd3d6..000000000 --- a/src/NzbDrone.Core/Languages/LanguagesComparer.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System.Collections.Generic; -using System.Linq; - -namespace NzbDrone.Core.Languages -{ - public class LanguagesComparer : IComparer> - { - public int Compare(List x, List y) - { - if (!x.Any() && !y.Any()) - { - return 0; - } - - if (!x.Any() && y.Any()) - { - return 1; - } - - if (x.Any() && !y.Any()) - { - return -1; - } - - if (x.Count > 1 && y.Count > 1 && x.Count > y.Count) - { - return 1; - } - - if (x.Count > 1 && y.Count > 1 && x.Count < y.Count) - { - return -1; - } - - if (x.Count > 1 && y.Count == 1) - { - return 1; - } - - if (x.Count == 1 && y.Count > 1) - { - return -1; - } - - if (x.Count == 1 && y.Count == 1) - { - return x.First().Name.CompareTo(y.First().Name); - } - - return 0; - } - } -} diff --git a/src/NzbDrone.Core/Languages/RealLanguageFieldConverter.cs b/src/NzbDrone.Core/Languages/RealLanguageFieldConverter.cs deleted file mode 100644 index 12c5df289..000000000 --- a/src/NzbDrone.Core/Languages/RealLanguageFieldConverter.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using NzbDrone.Core.Annotations; - -namespace NzbDrone.Core.Languages -{ - public class RealLanguageFieldConverter : ISelectOptionsConverter - { - public List GetSelectOptions() - { - return Language.All - .Where(l => l != Language.Unknown && l != Language.Any) - .ToList() - .ConvertAll(v => new SelectOption { Value = v.Id, Name = v.Name }); - } - } -} diff --git a/src/NzbDrone.Core/Localization/LocalizationOption.cs b/src/NzbDrone.Core/Localization/LocalizationOption.cs new file mode 100644 index 000000000..85426ef39 --- /dev/null +++ b/src/NzbDrone.Core/Localization/LocalizationOption.cs @@ -0,0 +1,14 @@ +namespace NzbDrone.Core.Localization +{ + public class LocalizationOption + { + public LocalizationOption(string name, string value) + { + Name = name; + Value = value; + } + + public string Name { get; set; } + public string Value { get; set; } + } +} diff --git a/src/NzbDrone.Core/Localization/LocalizationService.cs b/src/NzbDrone.Core/Localization/LocalizationService.cs index 66fda0b60..94e1a9924 100644 --- a/src/NzbDrone.Core/Localization/LocalizationService.cs +++ b/src/NzbDrone.Core/Localization/LocalizationService.cs @@ -9,7 +9,6 @@ using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.Extensions; using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration.Events; -using NzbDrone.Core.Languages; using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Parser; @@ -20,6 +19,7 @@ namespace NzbDrone.Core.Localization Dictionary GetLocalizationDictionary(); string GetLocalizedString(string phrase); string GetLocalizedString(string phrase, string language); + IEnumerable GetLocalizationOptions(); } public class LocalizationService : ILocalizationService, IHandleAsync @@ -45,14 +45,14 @@ namespace NzbDrone.Core.Localization public Dictionary GetLocalizationDictionary() { - var language = GetSetLanguageFileName(); + var language = _configService.UILanguage; return GetLocalizationDictionary(language); } public string GetLocalizedString(string phrase) { - var language = GetSetLanguageFileName(); + var language = _configService.UILanguage; return GetLocalizedString(phrase, language); } @@ -66,7 +66,7 @@ namespace NzbDrone.Core.Localization if (language.IsNullOrWhiteSpace()) { - language = GetSetLanguageFileName(); + language = _configService.UILanguage; } if (language == null) @@ -84,17 +84,44 @@ namespace NzbDrone.Core.Localization return phrase; } - private string GetSetLanguageFileName() + public IEnumerable GetLocalizationOptions() { - var isoLanguage = IsoLanguages.Get((Language)_configService.UILanguage); - var language = isoLanguage.TwoLetterCode; - - if (isoLanguage.CountryCode.IsNotNullOrWhiteSpace()) - { - language = string.Format("{0}_{1}", language, isoLanguage.CountryCode); - } - - return language; + yield return new LocalizationOption("العربية", "ar"); + yield return new LocalizationOption("Български", "bg"); + yield return new LocalizationOption("বাংলা (বাংলাদেশ)", "bn"); + yield return new LocalizationOption("Català", "ca"); + yield return new LocalizationOption("Čeština", "cs"); + yield return new LocalizationOption("Dansk", "da"); + yield return new LocalizationOption("Deutsch", "de"); + yield return new LocalizationOption("English", "en"); + yield return new LocalizationOption("Ελληνικά", "el"); + yield return new LocalizationOption("Español", "es"); + yield return new LocalizationOption("فارسی", "fa"); + yield return new LocalizationOption("Suomi", "fi"); + yield return new LocalizationOption("Français", "fr"); + yield return new LocalizationOption("עִבְרִית", "he"); + yield return new LocalizationOption("हिन्दी", "hi"); + yield return new LocalizationOption("Magyar", "hu"); + yield return new LocalizationOption("Íslenska", "is"); + yield return new LocalizationOption("Italiano", "it"); + yield return new LocalizationOption("日本語", "ja"); + yield return new LocalizationOption("한국어", "ko"); + yield return new LocalizationOption("Lietuvių", "lt"); + yield return new LocalizationOption("Norsk bokmål", "nb_NO"); + yield return new LocalizationOption("Nederlands", "nl"); + yield return new LocalizationOption("Polski", "pl"); + yield return new LocalizationOption("Português", "pt"); + yield return new LocalizationOption("Português (Brasil)", "pt_BR"); + yield return new LocalizationOption("Românește", "ro"); + yield return new LocalizationOption("Русский", "ru"); + yield return new LocalizationOption("Slovenčina", "sk"); + yield return new LocalizationOption("Svenska", "sv"); + yield return new LocalizationOption("ภาษาไทย", "th"); + yield return new LocalizationOption("Türkçe", "tr"); + yield return new LocalizationOption("Українська", "uk"); + yield return new LocalizationOption("Tiếng Việt", "vi"); + yield return new LocalizationOption("汉语 (简化字)", "zh_CN"); + yield return new LocalizationOption("漢語 (繁体字)", "zh_TW"); } private Dictionary GetLocalizationDictionary(string language) diff --git a/src/NzbDrone.Core/Parser/IsoLanguage.cs b/src/NzbDrone.Core/Parser/IsoLanguage.cs deleted file mode 100644 index 6f919c572..000000000 --- a/src/NzbDrone.Core/Parser/IsoLanguage.cs +++ /dev/null @@ -1,22 +0,0 @@ -using NzbDrone.Core.Languages; - -namespace NzbDrone.Core.Parser -{ - public class IsoLanguage - { - public string TwoLetterCode { get; set; } - public string ThreeLetterCode { get; set; } - public string CountryCode { get; set; } - public string EnglishName { get; set; } - public Language Language { get; set; } - - public IsoLanguage(string twoLetterCode, string countryCode, string threeLetterCode, string englishName, Language language) - { - TwoLetterCode = twoLetterCode; - ThreeLetterCode = threeLetterCode; - CountryCode = countryCode; - EnglishName = englishName; - Language = language; - } - } -} diff --git a/src/NzbDrone.Core/Parser/IsoLanguages.cs b/src/NzbDrone.Core/Parser/IsoLanguages.cs deleted file mode 100644 index 141075c31..000000000 --- a/src/NzbDrone.Core/Parser/IsoLanguages.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using NzbDrone.Core.Languages; - -namespace NzbDrone.Core.Parser -{ - public static class IsoLanguages - { - private static readonly HashSet All = new HashSet - { - new IsoLanguage("en", "", "eng", "English", Language.English), - new IsoLanguage("fr", "fr", "fra", "French", Language.French), - new IsoLanguage("es", "", "spa", "Spanish", Language.Spanish), - new IsoLanguage("de", "", "deu", "German", 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 (Simplified)", Language.Chinese), - new IsoLanguage("zh", "tw", "zho", "Chinese (Traditional)", Language.ChineseTW), - new IsoLanguage("ru", "", "rus", "Russian", Language.Russian), - new IsoLanguage("pl", "", "pol", "Polish", Language.Polish), - new IsoLanguage("vi", "", "vie", "Vietnamese", Language.Vietnamese), - new IsoLanguage("sv", "", "swe", "Swedish", Language.Swedish), - new IsoLanguage("no", "", "nor", "Norwegian", Language.Norwegian), - new IsoLanguage("nb", "", "nob", "Norwegian Bokmal", Language.Norwegian), - new IsoLanguage("fi", "", "fin", "Finnish", Language.Finnish), - new IsoLanguage("tr", "", "tur", "Turkish", Language.Turkish), - new IsoLanguage("pt", "pt", "por", "Portuguese", Language.Portuguese), - new IsoLanguage("el", "", "ell", "Greek", Language.Greek), - new IsoLanguage("ko", "", "kor", "Korean", Language.Korean), - new IsoLanguage("hu", "", "hun", "Hungarian", Language.Hungarian), - new IsoLanguage("he", "", "heb", "Hebrew", Language.Hebrew), - new IsoLanguage("cs", "", "ces", "Czech", Language.Czech), - new IsoLanguage("hi", "", "hin", "Hindi", Language.Hindi), - new IsoLanguage("th", "", "tha", "Thai", Language.Thai), - new IsoLanguage("bg", "", "bul", "Bulgarian", Language.Bulgarian), - new IsoLanguage("ro", "", "ron", "Romanian", Language.Romanian), - new IsoLanguage("pt", "br", "", "Portuguese (Brazil)", Language.PortugueseBR), - new IsoLanguage("ar", "", "ara", "Arabic", Language.Arabic), - new IsoLanguage("uk", "", "ukr", "Ukrainian", Language.Ukrainian), - new IsoLanguage("fa", "", "fas", "Persian", Language.Persian), - new IsoLanguage("be", "", "ben", "Bengali", Language.Bengali) - }; - - public static IsoLanguage Find(string isoCode) - { - var isoArray = isoCode.Split('-'); - - var langCode = isoArray[0].ToLower(); - - if (langCode.Length == 2) - { - //Lookup ISO639-1 code - var isoLanguages = All.Where(l => l.TwoLetterCode == langCode).ToList(); - - if (isoArray.Length > 1) - { - isoLanguages = isoLanguages.Any(l => l.CountryCode == isoArray[1].ToLower()) ? - isoLanguages.Where(l => l.CountryCode == isoArray[1].ToLower()).ToList() : isoLanguages.Where(l => string.IsNullOrEmpty(l.CountryCode)).ToList(); - } - - return isoLanguages.FirstOrDefault(); - } - else if (langCode.Length == 3) - { - //Lookup ISO639-2T code - return All.FirstOrDefault(l => l.ThreeLetterCode == langCode); - } - - return null; - } - - public static IsoLanguage FindByName(string name) - { - return All.FirstOrDefault(l => l.EnglishName == name.Trim()); - } - - public static IsoLanguage Get(Language language) - { - return All.FirstOrDefault(l => l.Language == language); - } - } -} diff --git a/src/NzbDrone.Core/Parser/LanguageParser.cs b/src/NzbDrone.Core/Parser/LanguageParser.cs deleted file mode 100644 index e7c262fc8..000000000 --- a/src/NzbDrone.Core/Parser/LanguageParser.cs +++ /dev/null @@ -1,272 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text.RegularExpressions; -using NLog; -using NzbDrone.Common.Extensions; -using NzbDrone.Common.Instrumentation; -using NzbDrone.Core.Languages; - -namespace NzbDrone.Core.Parser -{ - public static class LanguageParser - { - private static readonly Logger Logger = NzbDroneLogger.GetLogger(typeof(LanguageParser)); - - private static readonly Regex LanguageRegex = new Regex(@"(?:\W|_|^)(?\b(?:ita|italian)\b)|(?\b(?:german|videomann|ger)\b)|(?flemish)|(?bgaudio)|(?greek)|(?(?:\W|_)(?:FR|VO|VFF|VFQ|VFI|VF2|TRUEFRENCH)(?:\W|_))|(?\brus\b)|(?\beng\b)|(?\b(?:HUNDUB|HUN)\b)|(?\bHebDub\b)|(?\[(?:CH[ST]|BIG5|GB)\]|简|繁|字幕)", - RegexOptions.IgnoreCase | RegexOptions.Compiled); - - private static readonly Regex CaseSensitiveLanguageRegex = new Regex(@"(?\bLT\b)|(?\bCZ\b)", - RegexOptions.Compiled); - - private static readonly Regex SubtitleLanguageRegex = new Regex(".+?[-_. ](?[a-z]{2,3})(?:[-_. ]forced)?$", RegexOptions.Compiled | RegexOptions.IgnoreCase); - - public static List ParseLanguages(string title) - { - var lowerTitle = title.ToLower(); - var languages = new List(); - - if (lowerTitle.Contains("english")) - { - languages.Add(Language.English); - } - - if (lowerTitle.Contains("french")) - { - languages.Add(Language.French); - } - - if (lowerTitle.Contains("spanish")) - { - languages.Add(Language.Spanish); - } - - if (lowerTitle.Contains("danish")) - { - languages.Add(Language.Danish); - } - - if (lowerTitle.Contains("dutch")) - { - languages.Add(Language.Dutch); - } - - if (lowerTitle.Contains("japanese")) - { - languages.Add(Language.Japanese); - } - - if (lowerTitle.Contains("icelandic")) - { - languages.Add(Language.Icelandic); - } - - if (lowerTitle.Contains("mandarin") || lowerTitle.Contains("cantonese") || lowerTitle.Contains("chinese")) - { - languages.Add(Language.Chinese); - } - - if (lowerTitle.Contains("korean")) - { - languages.Add(Language.Korean); - } - - if (lowerTitle.Contains("russian")) - { - languages.Add(Language.Russian); - } - - if (lowerTitle.Contains("romanian")) - { - languages.Add(Language.Romanian); - } - - if (lowerTitle.Contains("hindi")) - { - languages.Add(Language.Hindi); - } - - if (lowerTitle.Contains("thai")) - { - languages.Add(Language.Thai); - } - - if (lowerTitle.Contains("bulgarian")) - { - languages.Add(Language.Bulgarian); - } - - if (lowerTitle.Contains("polish")) - { - languages.Add(Language.Polish); - } - - if (lowerTitle.Contains("vietnamese")) - { - languages.Add(Language.Vietnamese); - } - - if (lowerTitle.Contains("swedish")) - { - languages.Add(Language.Swedish); - } - - if (lowerTitle.Contains("norwegian")) - { - languages.Add(Language.Norwegian); - } - - if (lowerTitle.Contains("finnish")) - { - languages.Add(Language.Finnish); - } - - if (lowerTitle.Contains("turkish")) - { - languages.Add(Language.Turkish); - } - - if (lowerTitle.Contains("portuguese")) - { - languages.Add(Language.Portuguese); - } - - if (lowerTitle.Contains("hungarian")) - { - languages.Add(Language.Hungarian); - } - - if (lowerTitle.Contains("hebrew")) - { - languages.Add(Language.Hebrew); - } - - // Case sensitive - var caseSensitiveMatch = CaseSensitiveLanguageRegex.Match(title); - - if (caseSensitiveMatch.Groups["lithuanian"].Captures.Cast().Any()) - { - languages.Add(Language.Lithuanian); - } - - if (caseSensitiveMatch.Groups["czech"].Captures.Cast().Any()) - { - languages.Add(Language.Czech); - } - - var matches = LanguageRegex.Matches(title); - - foreach (Match match in matches) - { - if (match.Groups["italian"].Captures.Cast().Any()) - { - languages.Add(Language.Italian); - } - - if (match.Groups["german"].Captures.Cast().Any()) - { - languages.Add(Language.German); - } - - if (match.Groups["flemish"].Captures.Cast().Any()) - { - languages.Add(Language.Flemish); - } - - if (match.Groups["greek"].Captures.Cast().Any()) - { - languages.Add(Language.Greek); - } - - if (match.Groups["french"].Success) - { - languages.Add(Language.French); - } - - if (match.Groups["russian"].Success) - { - languages.Add(Language.Russian); - } - - if (match.Groups["english"].Success) - { - languages.Add(Language.English); - } - - if (match.Groups["bulgarian"].Success) - { - languages.Add(Language.Bulgarian); - } - - if (match.Groups["dutch"].Success) - { - languages.Add(Language.Dutch); - } - - if (match.Groups["hungarian"].Success) - { - languages.Add(Language.Hungarian); - } - - if (match.Groups["hebrew"].Success) - { - languages.Add(Language.Hebrew); - } - - if (match.Groups["chinese"].Success) - { - languages.Add(Language.Chinese); - } - } - - if (title.ToLower().Contains("multi")) - { - //Let's add english language to multi release as a safe guard. - if (!languages.Contains(Language.English) && languages.Count < 2) - { - languages.Add(Language.English); - } - } - - if (!languages.Any()) - { - languages.Add(Language.Unknown); - } - - return languages.DistinctBy(l => (int)l).ToList(); - } - - public static Language ParseSubtitleLanguage(string fileName) - { - try - { -#if !LIBRARY - Logger.Debug("Parsing language from subtitle file: {0}", fileName); -#endif - - var simpleFilename = Path.GetFileNameWithoutExtension(fileName); - var languageMatch = SubtitleLanguageRegex.Match(simpleFilename); - - if (languageMatch.Success) - { - var isoCode = languageMatch.Groups["iso_code"].Value; - var isoLanguage = IsoLanguages.Find(isoCode); - - return isoLanguage?.Language ?? Language.Unknown; - } -#if !LIBRARY - Logger.Debug("Unable to parse langauge from subtitle file: {0}", fileName); -#endif - } - catch (Exception) - { -#if !LIBRARY - Logger.Debug("Failed parsing langauge from subtitle file: {0}", fileName); -#endif - } - - return Language.Unknown; - } - } -} diff --git a/src/NzbDrone.Core/Parser/Model/ReleaseInfo.cs b/src/NzbDrone.Core/Parser/Model/ReleaseInfo.cs index f76e36747..fe1815483 100644 --- a/src/NzbDrone.Core/Parser/Model/ReleaseInfo.cs +++ b/src/NzbDrone.Core/Parser/Model/ReleaseInfo.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq; using System.Text; using NzbDrone.Core.Indexers; -using NzbDrone.Core.Languages; namespace NzbDrone.Core.Parser.Model { diff --git a/src/Prowlarr.Api.V1/Config/UiConfigResource.cs b/src/Prowlarr.Api.V1/Config/UiConfigResource.cs index ae63a6d43..55f532f98 100644 --- a/src/Prowlarr.Api.V1/Config/UiConfigResource.cs +++ b/src/Prowlarr.Api.V1/Config/UiConfigResource.cs @@ -16,7 +16,7 @@ namespace Prowlarr.Api.V1.Config public bool ShowRelativeDates { get; set; } public bool EnableColorImpairedMode { get; set; } - public int UILanguage { get; set; } + public string UILanguage { get; set; } public string Theme { get; set; } } diff --git a/src/Prowlarr.Api.V1/Languages/LanguageController.cs b/src/Prowlarr.Api.V1/Languages/LanguageController.cs deleted file mode 100644 index de7a2c4e7..000000000 --- a/src/Prowlarr.Api.V1/Languages/LanguageController.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Microsoft.AspNetCore.Mvc; -using NzbDrone.Core.Languages; -using Prowlarr.Http; -using Prowlarr.Http.REST; - -namespace Prowlarr.Api.V1.Languages -{ - [V1ApiController()] - public class LanguageController : RestController - { - public override LanguageResource GetResourceById(int id) - { - var language = (Language)id; - - return new LanguageResource - { - Id = (int)language, - Name = language.ToString() - }; - } - - [HttpGet] - [Produces("application/json")] - public List GetAll() - { - return Language.All.Select(l => new LanguageResource - { - Id = (int)l, - Name = l.ToString() - }) - .OrderBy(l => l.Name) - .ToList(); - } - } -} diff --git a/src/Prowlarr.Api.V1/Languages/LanguageResource.cs b/src/Prowlarr.Api.V1/Languages/LanguageResource.cs deleted file mode 100644 index 6bb325049..000000000 --- a/src/Prowlarr.Api.V1/Languages/LanguageResource.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Newtonsoft.Json; -using Prowlarr.Http.REST; - -namespace Prowlarr.Api.V1.Languages -{ - public class LanguageResource : RestResource - { - [JsonProperty(DefaultValueHandling = DefaultValueHandling.Include)] - public new int Id { get; set; } - public string Name { get; set; } - public string NameLower => Name.ToLowerInvariant(); - } -} diff --git a/src/Prowlarr.Api.V1/Localization/LocalizationController.cs b/src/Prowlarr.Api.V1/Localization/LocalizationController.cs index 67d3f53b5..e544936b1 100644 --- a/src/Prowlarr.Api.V1/Localization/LocalizationController.cs +++ b/src/Prowlarr.Api.V1/Localization/LocalizationController.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using System.Text.Json; using Microsoft.AspNetCore.Mvc; using NzbDrone.Common.Serializer; @@ -26,5 +27,12 @@ namespace Prowlarr.Api.V1.Localization { return Json(_localizationService.GetLocalizationDictionary().ToResource(), _serializerSettings); } + + [HttpGet("Options")] + [Produces("application/json")] + public ActionResult> GetLocalizationOptions() + { + return Ok(_localizationService.GetLocalizationOptions()); + } } }