diff --git a/src/NzbDrone.Core/Localization/Core/en.json b/src/NzbDrone.Core/Localization/Core/en.json index 7424dd391..8d6e2af5c 100644 --- a/src/NzbDrone.Core/Localization/Core/en.json +++ b/src/NzbDrone.Core/Localization/Core/en.json @@ -1085,8 +1085,178 @@ "NotificationStatusSingleClientHealthCheckMessage": "Notifications unavailable due to failures: {notificationNames}", "NotificationTriggers": "Notification Triggers", "NotificationTriggersHelpText": "Select which events should trigger this notification", + "NotificationsAppriseSettingsConfigurationKey": "Apprise Configuration Key", + "NotificationsAppriseSettingsConfigurationKeyHelpText": "Configuration Key for the Persistent Storage Solution. Leave empty if Stateless URLs is used.", + "NotificationsAppriseSettingsNotificationType": "Apprise Notification Type", + "NotificationsAppriseSettingsPasswordHelpText": "HTTP Basic Auth Password", + "NotificationsAppriseSettingsServerUrl": "Apprise Server URL", + "NotificationsAppriseSettingsServerUrlHelpText": "Apprise server URL, including http(s):// and port if needed", + "NotificationsAppriseSettingsStatelessUrls": "Apprise Stateless URLs", + "NotificationsAppriseSettingsStatelessUrlsHelpText": "One or more URLs separated by commas identifying where the notification should be sent to. Leave empty if Persistent Storage is used.", + "NotificationsAppriseSettingsTags": "Apprise Tags", + "NotificationsAppriseSettingsTagsHelpText": "Optionally notify only those tagged accordingly.", + "NotificationsAppriseSettingsUsernameHelpText": "HTTP Basic Auth Username", + "NotificationsCustomScriptSettingsArguments": "Arguments", + "NotificationsCustomScriptSettingsArgumentsHelpText": "Arguments to pass to the script", + "NotificationsCustomScriptSettingsName": "Custom Script", + "NotificationsCustomScriptSettingsProviderMessage": "Testing will execute the script with the EventType set to {eventTypeTest}, ensure your script handles this correctly", + "NotificationsCustomScriptValidationFileDoesNotExist": "File does not exist", + "NotificationsDiscordSettingsAuthor": "Author", + "NotificationsDiscordSettingsAuthorHelpText": "Override the embed author that shows for this notification. Blank is instance name", + "NotificationsDiscordSettingsAvatar": "Avatar", + "NotificationsDiscordSettingsAvatarHelpText": "Change the avatar that is used for messages from this integration", + "NotificationsDiscordSettingsOnGrabFields": "On Grab Fields", + "NotificationsDiscordSettingsOnGrabFieldsHelpText": "Change the fields that are passed in for this 'on grab' notification", + "NotificationsDiscordSettingsOnImportFields": "On Import Fields", + "NotificationsDiscordSettingsOnImportFieldsHelpText": "Change the fields that are passed in for this 'on import' notification", + "NotificationsDiscordSettingsOnManualInteractionFields": "On Manual Interaction Fields", + "NotificationsDiscordSettingsOnManualInteractionFieldsHelpText": "Change the fields that are passed in for this 'on manual interation' notification", + "NotificationsDiscordSettingsUsernameHelpText": "The username to post as, defaults to Discord webhook default", + "NotificationsDiscordSettingsWebhookUrlHelpText": "Discord channel webhook url", + "NotificationsEmailSettingsBccAddress": "BCC Address(es)", + "NotificationsEmailSettingsBccAddressHelpText": "Comma separated list of email bcc recipients", + "NotificationsEmailSettingsCcAddress": "CC Address(es)", + "NotificationsEmailSettingsCcAddressHelpText": "Comma separated list of email cc recipients", + "NotificationsEmailSettingsFromAddress": "From Address", + "NotificationsEmailSettingsName": "Email", + "NotificationsEmailSettingsRecipientAddress": "Recipient Address(es)", + "NotificationsEmailSettingsRecipientAddressHelpText": "Comma separated list of email recipients", + "NotificationsEmailSettingsRequireEncryption": "Require Encryption", + "NotificationsEmailSettingsRequireEncryptionHelpText": "Require SSL (Port 465 only) or StartTLS (any other port)", + "NotificationsEmailSettingsServer": "Server", + "NotificationsEmailSettingsServerHelpText": "Hostname or IP of Email server", + "NotificationsEmbySettingsSendNotifications": "Send Notifications", + "NotificationsEmbySettingsSendNotificationsHelpText": "Have MediaBrowser send notifications to configured providers", + "NotificationsEmbySettingsUpdateLibraryHelpText": "Update Library on Import, Rename, or Delete?", + "NotificationsGotifySettingIncludeSeriesPoster": "Include Series Poster", + "NotificationsGotifySettingIncludeSeriesPosterHelpText": "Include series poster in message", + "NotificationsGotifySettingsAppToken": "App Token", + "NotificationsGotifySettingsAppTokenHelpText": "The Application Token generated by Gotify", + "NotificationsGotifySettingsPriorityHelpText": "Priority of the notification", + "NotificationsGotifySettingsServer": "Gotify Server", + "NotificationsGotifySettingsServerHelpText": "Gotify server URL, including http(s):// and port if needed", + "NotificationsJoinSettingsApiKeyHelpText": "The API Key from your Join account settings (click Join API button).", + "NotificationsJoinSettingsDeviceIds": "Device IDs", + "NotificationsJoinSettingsDeviceIdsHelpText": "Deprecated, use Device Names instead. Comma separated list of Device IDs you'd like to send notifications to. If unset, all devices will receive notifications.", + "NotificationsJoinSettingsDeviceNames": "Device Names", + "NotificationsJoinSettingsDeviceNamesHelpText": "Comma separated list of full or partial device names you'd like to send notifications to. If unset, all devices will receive notifications.", + "NotificationsJoinSettingsNotificationPriority": "Notification Priority", + "NotificationsJoinValidationInvalidDeviceId": "Device IDs appear invalid.", + "NotificationsKodiSettingAlwaysUpdate": "Always Update", + "NotificationsKodiSettingAlwaysUpdateHelpText": "Update library even when a video is playing?", + "NotificationsKodiSettingsCleanLibrary": "Clean Library", + "NotificationsKodiSettingsCleanLibraryHelpText": "Clean library after update", + "NotificationsKodiSettingsDisplayTime": "Display Time", + "NotificationsKodiSettingsDisplayTimeHelpText": "How long the notification will be displayed for (In seconds)", + "NotificationsKodiSettingsGuiNotification": "GUI Notification", + "NotificationsKodiSettingsUpdateLibraryHelpText": "Update library on Import & Rename?", "NotificationsLoadError": "Unable to load Notifications", + "NotificationsMailgunSettingsApiKeyHelpText": "The API key generated from MailGun", + "NotificationsMailgunSettingsSenderDomain": "Sender Domain", + "NotificationsMailgunSettingsUseEuEndpoint": "Use EU Endpoint", + "NotificationsMailgunSettingsUseEuEndpointHelpText": "Enable to use the EU MailGun endpoint", + "NotificationsNotifiarrSettingsApiKeyHelpText": "Your API key from your profile", + "NotificationsNtfySettingsAccessToken": "Access Token", + "NotificationsNtfySettingsAccessTokenHelpText": "Optional token-based authorization. Takes priority over username/password", + "NotificationsNtfySettingsClickUrl": "Click Url", + "NotificationsNtfySettingsClickUrlHelpText": "Optional link when user clicks notification", + "NotificationsNtfySettingsPasswordHelpText": "Optional password", + "NotificationsNtfySettingsServerUrl": "Server URL", + "NotificationsNtfySettingsServerUrlHelpText": "Leave blank to use public server ({url})", + "NotificationsNtfySettingsTagsEmojis": "Ntfy Tags and Emojis", + "NotificationsNtfySettingsTagsEmojisHelpText": "Optional list of tags or emojis to use", + "NotificationsNtfySettingsTopics": "Topics", + "NotificationsNtfySettingsTopicsHelpText": "List of Topics to send notifications to", + "NotificationsNtfySettingsUsernameHelpText": "Optional username", + "NotificationsNtfyValidationAuthorizationRequired": "Authorization is required", + "NotificationsPlexSettingsAuthToken": "Auth Token", + "NotificationsPlexSettingsAuthenticateWithPlexTv": "Authenticate with Plex.tv", + "NotificationsPlexValidationNoTvLibraryFound": "At least one TV library is required", + "NotificationsPushBulletSettingSenderId": "Sender ID", + "NotificationsPushBulletSettingSenderIdHelpText": "The device ID to send notifications from, use device_iden in the device's URL on pushbullet.com (leave blank to send from yourself)", + "NotificationsPushBulletSettingsAccessToken": "Access Token", + "NotificationsPushBulletSettingsChannelTags": "Channel Tags", + "NotificationsPushBulletSettingsChannelTagsHelpText": "List of Channel Tags to send notifications to", + "NotificationsPushBulletSettingsDeviceIds": "Device IDs", + "NotificationsPushBulletSettingsDeviceIdsHelpText": "List of device IDs (leave blank to send to all devices)", + "NotificationsPushcutSettingsApiKeyHelpText": "API Keys can be managed in the Account view of the Pushcut app", + "NotificationsPushcutSettingsNotificationName": "Notification Name", + "NotificationsPushcutSettingsNotificationNameHelpText": "Notification name from Notifications tab of the Pushcut app", + "NotificationsPushcutSettingsTimeSensitive": "Time Sensitive", + "NotificationsPushcutSettingsTimeSensitiveHelpText": "Enable to mark the notification as \"Time Sensitive\"", + "NotificationsPushoverSettingsDevices": "Devices", + "NotificationsPushoverSettingsDevicesHelpText": "List of device names (leave blank to send to all devices)", + "NotificationsPushoverSettingsExpire": "Expire", + "NotificationsPushoverSettingsExpireHelpText": "Maximum time to retry Emergency alerts, maximum 86400 seconds\"", + "NotificationsPushoverSettingsRetry": "Retry", + "NotificationsPushoverSettingsRetryHelpText": "Interval to retry Emergency alerts, minimum 30 seconds", + "NotificationsPushoverSettingsSound": "Sound", + "NotificationsPushoverSettingsSoundHelpText": "Notification sound, leave blank to use the default", + "NotificationsPushoverSettingsUserKey": "User Key", + "NotificationsSendGridSettingsApiKeyHelpText": "The API Key generated by SendGrid", + "NotificationsSettingsUpdateLibrary": "Update Library", + "NotificationsSettingsUpdateMapPathsFrom": "Map Paths From", + "NotificationsSettingsUpdateMapPathsFromHelpText": "{appName} path, used to modify series paths when {serviceName} sees library path location differently from {appName} (Requires 'Update Library')", + "NotificationsSettingsUpdateMapPathsTo": "Map Paths To", + "NotificationsSettingsUpdateMapPathsToHelpText": "{serviceName} path, used to modify series paths when {serviceName} sees library path location differently from {appName} (Requires 'Update Library')", + "NotificationsSettingsUseSslHelpText": "Connect to {serviceName} over HTTPS instead of HTTP", + "NotificationsSettingsWebhookMethod": "Method", + "NotificationsSettingsWebhookMethodHelpText": "Which HTTP method to use submit to the Webservice", + "NotificationsSettingsWebhookUrl": "Webhook URL", + "NotificationsSignalSettingsGroupIdPhoneNumber": "Group ID / Phone Number", + "NotificationsSignalSettingsGroupIdPhoneNumberHelpText": "Group ID / Phone Number of the receiver", + "NotificationsSignalSettingsPasswordHelpText": "Password used to authenticate requests toward signal-api", + "NotificationsSignalSettingsSenderNumber": "Sender Number", + "NotificationsSignalSettingsSenderNumberHelpText": "Phone number of the sender register in signal-api", + "NotificationsSignalSettingsUsernameHelpText": "Username used to authenticate requests toward signal-api", + "NotificationsSignalValidationSslRequired": "SSL seems to be required", + "NotificationsSimplepushSettingsEvent": "Event", + "NotificationsSimplepushSettingsEventHelpText": "Customize the behavior of push notifications", + "NotificationsSimplepushSettingsKey": "Key", + "NotificationsSlackSettingsChannel": "Channel", + "NotificationsSlackSettingsChannelHelpText": "Overrides the default channel for the incoming webhook (#other-channel)", + "NotificationsSlackSettingsIcon": "Icon", + "NotificationsSlackSettingsIconHelpText": "Change the icon that is used for messages posted to Slack (Emoji or URL)", + "NotificationsSlackSettingsUsernameHelpText": "Username to post to Slack as", + "NotificationsSlackSettingsWebhookUrlHelpText": "Slack channel webhook url", + "NotificationsSynologySettingsUpdateLibraryHelpText": "Call synoindex on localhost to update a library file", + "NotificationsSynologyValidationInvalidOs": "Must be a Synology", + "NotificationsSynologyValidationTestFailed": "Not a Synology or synoindex not available", "NotificationsTagsSeriesHelpText": "Only send notifications for series with at least one matching tag", + "NotificationsTelegramSettingsBotToken": "Bot Token", + "NotificationsTelegramSettingsChatId": "Chat ID", + "NotificationsTelegramSettingsChatIdHelpText": "You must start a conversation with the bot or add it to your group to receive messages", + "NotificationsTelegramSettingsSendSilently": "Send Silently", + "NotificationsTelegramSettingsSendSilentlyHelpText": "Sends the message silently. Users will receive a notification with no sound", + "NotificationsTelegramSettingsTopicId": "Topic ID", + "NotificationsTelegramSettingsTopicIdHelpText": "Specify a Topic ID to send notifications to that topic. Leave blank to use the general topic (Supergroups only)", + "NotificationsTraktSettingsAccessToken": "Access Token", + "NotificationsTraktSettingsAuthUser": "Auth User", + "NotificationsTraktSettingsAuthenticateWithTrakt": "Authenticate with Trakt", + "NotificationsTraktSettingsExpires": "Expires", + "NotificationsTraktSettingsRefreshToken": "Refresh Token", + "NotificationsTwitterSettingsAccessToken": "Access Token", + "NotificationsTwitterSettingsAccessTokenSecret": "Access Token Secret", + "NotificationsTwitterSettingsConnectToTwitter": "Connect to Twitter / X", + "NotificationsTwitterSettingsConsumerKey": "Consumer Key", + "NotificationsTwitterSettingsConsumerKeyHelpText": "Consumer key from a Twitter application", + "NotificationsTwitterSettingsConsumerSecret": "Consumer Secret", + "NotificationsTwitterSettingsConsumerSecretHelpText": "Consumer secret from a Twitter application", + "NotificationsTwitterSettingsDirectMessage": "Direct Message", + "NotificationsTwitterSettingsDirectMessageHelpText": "Send a direct message instead of a public message", + "NotificationsTwitterSettingsMention": "Mention", + "NotificationsTwitterSettingsMentionHelpText": "Mention this user in sent tweets", + "NotificationsValidationInvalidAccessToken": "Access Token is invalid", + "NotificationsValidationInvalidApiKey": "API Key is invalid", + "NotificationsValidationInvalidApiKeyExceptionMessage": "API Key is invalid: {exceptionMessage}", + "NotificationsValidationInvalidAuthenticationToken": "Authentication Token is invalid", + "NotificationsValidationInvalidHttpCredentials": "HTTP Auth credentials are invalid: {exceptionMessage}", + "NotificationsValidationInvalidUsernamePassword": "Invalid username or password", + "NotificationsValidationUnableToConnect": "Unable to connect: {exceptionMessage}", + "NotificationsValidationUnableToConnectToApi": "Unable to connect to {service} API. Server connection failed: ({responseCode}) {exceptionMessage}", + "NotificationsValidationUnableToConnectToService": "Unable to connect to {serviceName}", + "NotificationsValidationUnableToSendTestMessage": "Unable to send test message: {exceptionMessage}", + "NotificationsValidationUnableToSendTestMessageApiResponse": "Unable to send test message. Response from API: {error}", "NzbgetHistoryItemMessage": "PAR Status: {parStatus} - Unpack Status: {unpackStatus} - Move Status: {moveStatus} - Script Status: {scriptStatus} - Delete Status: {deleteStatus} - Mark Status: {markStatus}", "Ok": "Ok", "OnApplicationUpdate": "On Application Update", diff --git a/src/NzbDrone.Core/Notifications/Apprise/AppriseProxy.cs b/src/NzbDrone.Core/Notifications/Apprise/AppriseProxy.cs index 02acfb5aa..18f004863 100644 --- a/src/NzbDrone.Core/Notifications/Apprise/AppriseProxy.cs +++ b/src/NzbDrone.Core/Notifications/Apprise/AppriseProxy.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Net; using FluentValidation.Results; @@ -6,6 +7,7 @@ using NLog; using NzbDrone.Common.Extensions; using NzbDrone.Common.Http; using NzbDrone.Common.Serializer; +using NzbDrone.Core.Localization; namespace NzbDrone.Core.Notifications.Apprise { @@ -18,11 +20,13 @@ namespace NzbDrone.Core.Notifications.Apprise public class AppriseProxy : IAppriseProxy { private readonly IHttpClient _httpClient; + private readonly ILocalizationService _localizationService; private readonly Logger _logger; - public AppriseProxy(IHttpClient httpClient, Logger logger) + public AppriseProxy(IHttpClient httpClient, ILocalizationService localizationService, Logger logger) { _httpClient = httpClient; + _localizationService = localizationService; _logger = logger; } @@ -92,7 +96,7 @@ namespace NzbDrone.Core.Notifications.Apprise if (httpException.Response.StatusCode == HttpStatusCode.Unauthorized) { _logger.Error(ex, $"HTTP Auth credentials are invalid: {0}", ex.Message); - return new ValidationFailure("AuthUsername", $"HTTP Auth credentials are invalid: {ex.Message}"); + return new ValidationFailure("AuthUsername", _localizationService.GetLocalizedString("NotificationsValidationInvalidHttpCredentials", new Dictionary { { "exceptionMessage", ex.Message } })); } if (httpException.Response.Content.IsNotNullOrWhiteSpace()) @@ -100,16 +104,16 @@ namespace NzbDrone.Core.Notifications.Apprise var error = Json.Deserialize(httpException.Response.Content); _logger.Error(ex, $"Unable to send test message. Response from API: {0}", error.Error); - return new ValidationFailure(string.Empty, $"Unable to send test message. Response from API: {error.Error}"); + return new ValidationFailure(string.Empty, _localizationService.GetLocalizedString("NotificationsValidationUnableToSendTestMessageApiResponse", new Dictionary { { "error", error.Error } })); } _logger.Error(ex, "Unable to send test message. Server connection failed: ({0}) {1}", httpException.Response.StatusCode, ex.Message); - return new ValidationFailure("Url", $"Unable to connect to Apprise API. Server connection failed: ({httpException.Response.StatusCode}) {ex.Message}"); + return new ValidationFailure("Url", _localizationService.GetLocalizedString("NotificationsValidationUnableToConnectToApi", new Dictionary { { "service", "Apprise" }, { "responseCode", httpException.Response.StatusCode }, { "exceptionMessage", ex.Message } })); } catch (Exception ex) { _logger.Error(ex, "Unable to send test message: {0}", ex.Message); - return new ValidationFailure("Url", $"Unable to send test message: {ex.Message}"); + return new ValidationFailure("Url", _localizationService.GetLocalizedString("NotificationsValidationUnableToSendTestMessage", new Dictionary { { "exceptionMessage", ex.Message } })); } return null; diff --git a/src/NzbDrone.Core/Notifications/Apprise/AppriseSettings.cs b/src/NzbDrone.Core/Notifications/Apprise/AppriseSettings.cs index 31c709253..d33a3f4ec 100644 --- a/src/NzbDrone.Core/Notifications/Apprise/AppriseSettings.cs +++ b/src/NzbDrone.Core/Notifications/Apprise/AppriseSettings.cs @@ -45,25 +45,25 @@ namespace NzbDrone.Core.Notifications.Apprise Tags = Array.Empty(); } - [FieldDefinition(1, Label = "Apprise Server URL", Type = FieldType.Url, Placeholder = "http://localhost:8000", HelpText = "Apprise server URL, including http(s):// and port if needed", HelpLink = "https://github.com/caronc/apprise-api")] + [FieldDefinition(1, Label = "NotificationsAppriseSettingsServerUrl", Type = FieldType.Url, Placeholder = "http://localhost:8000", HelpText = "NotificationsAppriseSettingsServerUrlHelpText", HelpLink = "https://github.com/caronc/apprise-api")] public string ServerUrl { get; set; } - [FieldDefinition(2, Label = "Apprise Configuration Key", Type = FieldType.Textbox, HelpText = "Configuration Key for the Persistent Storage Solution. Leave empty if Stateless URLs is used.", HelpLink = "https://github.com/caronc/apprise-api#persistent-storage-solution")] + [FieldDefinition(2, Label = "NotificationsAppriseSettingsConfigurationKey", Type = FieldType.Textbox, HelpText = "NotificationsAppriseSettingsConfigurationKeyHelpText", HelpLink = "https://github.com/caronc/apprise-api#persistent-storage-solution")] public string ConfigurationKey { get; set; } - [FieldDefinition(3, Label = "Apprise Stateless URLs", Type = FieldType.Textbox, HelpText = "One or more URLs separated by commas identifying where the notification should be sent to. Leave empty if Persistent Storage is used.", HelpLink = "https://github.com/caronc/apprise#productivity-based-notifications")] + [FieldDefinition(3, Label = "NotificationsAppriseSettingsStatelessUrls", Type = FieldType.Textbox, HelpText = "NotificationsAppriseSettingsStatelessUrlsHelpText", HelpLink = "https://github.com/caronc/apprise#productivity-based-notifications")] public string StatelessUrls { get; set; } - [FieldDefinition(4, Label = "Apprise Notification Type", Type = FieldType.Select, SelectOptions = typeof(AppriseNotificationType))] + [FieldDefinition(4, Label = "NotificationsAppriseSettingsNotificationType", Type = FieldType.Select, SelectOptions = typeof(AppriseNotificationType))] public int NotificationType { get; set; } - [FieldDefinition(5, Label = "Apprise Tags", Type = FieldType.Tag, HelpText = "Optionally notify only those tagged accordingly.")] + [FieldDefinition(5, Label = "NotificationsAppriseSettingsTags", Type = FieldType.Tag, HelpText = "")] public IEnumerable Tags { get; set; } - [FieldDefinition(6, Label = "Username", Type = FieldType.Textbox, HelpText = "HTTP Basic Auth Username", Privacy = PrivacyLevel.UserName)] + [FieldDefinition(6, Label = "Username", Type = FieldType.Textbox, HelpText = "NotificationsAppriseSettingsUsernameHelpText", Privacy = PrivacyLevel.UserName)] public string AuthUsername { get; set; } - [FieldDefinition(7, Label = "Password", Type = FieldType.Password, HelpText = "HTTP Basic Auth Password", Privacy = PrivacyLevel.Password)] + [FieldDefinition(7, Label = "Password", Type = FieldType.Password, HelpText = "NotificationsAppriseSettingsPasswordHelpText", Privacy = PrivacyLevel.Password)] public string AuthPassword { get; set; } public NzbDroneValidationResult Validate() diff --git a/src/NzbDrone.Core/Notifications/CustomScript/CustomScript.cs b/src/NzbDrone.Core/Notifications/CustomScript/CustomScript.cs index e085b4165..2a6483e18 100644 --- a/src/NzbDrone.Core/Notifications/CustomScript/CustomScript.cs +++ b/src/NzbDrone.Core/Notifications/CustomScript/CustomScript.cs @@ -10,6 +10,7 @@ using NzbDrone.Common.Extensions; using NzbDrone.Common.Processes; using NzbDrone.Core.Configuration; using NzbDrone.Core.HealthCheck; +using NzbDrone.Core.Localization; using NzbDrone.Core.MediaFiles; using NzbDrone.Core.MediaFiles.MediaInfo; using NzbDrone.Core.Parser; @@ -27,6 +28,7 @@ namespace NzbDrone.Core.Notifications.CustomScript private readonly IDiskProvider _diskProvider; private readonly IProcessProvider _processProvider; private readonly ITagRepository _tagRepository; + private readonly ILocalizationService _localizationService; private readonly Logger _logger; public CustomScript(IConfigFileProvider configFileProvider, @@ -34,6 +36,7 @@ namespace NzbDrone.Core.Notifications.CustomScript IDiskProvider diskProvider, IProcessProvider processProvider, ITagRepository tagRepository, + ILocalizationService localizationService, Logger logger) { _configFileProvider = configFileProvider; @@ -41,14 +44,15 @@ namespace NzbDrone.Core.Notifications.CustomScript _diskProvider = diskProvider; _processProvider = processProvider; _tagRepository = tagRepository; + _localizationService = localizationService; _logger = logger; } - public override string Name => "Custom Script"; + public override string Name => _localizationService.GetLocalizedString("NotificationsCustomScriptSettingsName"); public override string Link => "https://wiki.servarr.com/sonarr/settings#connections"; - public override ProviderMessage Message => new ProviderMessage("Testing will execute the script with the EventType set to Test, ensure your script handles this correctly", ProviderMessageType.Warning); + public override ProviderMessage Message => new ProviderMessage(_localizationService.GetLocalizedString("NotificationsCustomScriptSettingsProviderMessage", new Dictionary { { "eventTypeTest", "Test" } }), ProviderMessageType.Warning); public override void OnGrab(GrabMessage message) { @@ -360,7 +364,7 @@ namespace NzbDrone.Core.Notifications.CustomScript if (!_diskProvider.FileExists(Settings.Path)) { - failures.Add(new NzbDroneValidationFailure("Path", "File does not exist")); + failures.Add(new NzbDroneValidationFailure("Path", _localizationService.GetLocalizedString("NotificationsCustomScriptValidationFileDoesNotExist"))); } if (failures.Empty()) diff --git a/src/NzbDrone.Core/Notifications/CustomScript/CustomScriptSettings.cs b/src/NzbDrone.Core/Notifications/CustomScript/CustomScriptSettings.cs index ce5a398ed..8c52308e5 100644 --- a/src/NzbDrone.Core/Notifications/CustomScript/CustomScriptSettings.cs +++ b/src/NzbDrone.Core/Notifications/CustomScript/CustomScriptSettings.cs @@ -23,7 +23,7 @@ namespace NzbDrone.Core.Notifications.CustomScript [FieldDefinition(0, Label = "Path", Type = FieldType.FilePath)] public string Path { get; set; } - [FieldDefinition(1, Label = "Arguments", HelpText = "Arguments to pass to the script", Hidden = HiddenType.HiddenIfNotSet)] + [FieldDefinition(1, Label = "NotificationsCustomScriptSettingsArguments", HelpText = "NotificationsCustomScriptSettingsArgumentsHelpText", Hidden = HiddenType.HiddenIfNotSet)] public string Arguments { get; set; } public NzbDroneValidationResult Validate() diff --git a/src/NzbDrone.Core/Notifications/Discord/Discord.cs b/src/NzbDrone.Core/Notifications/Discord/Discord.cs index 335605143..0f32c1f86 100644 --- a/src/NzbDrone.Core/Notifications/Discord/Discord.cs +++ b/src/NzbDrone.Core/Notifications/Discord/Discord.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using FluentValidation.Results; using NzbDrone.Common.Extensions; +using NzbDrone.Core.Localization; using NzbDrone.Core.MediaCover; using NzbDrone.Core.MediaFiles; using NzbDrone.Core.MediaFiles.MediaInfo; @@ -15,10 +16,12 @@ namespace NzbDrone.Core.Notifications.Discord public class Discord : NotificationBase { private readonly IDiscordProxy _proxy; + private readonly ILocalizationService _localizationService; - public Discord(IDiscordProxy proxy) + public Discord(IDiscordProxy proxy, ILocalizationService localizationService) { _proxy = proxy; + _localizationService = localizationService; } public override string Name => "Discord"; @@ -538,7 +541,7 @@ namespace NzbDrone.Core.Notifications.Discord } catch (DiscordException ex) { - return new NzbDroneValidationFailure("Unable to post", ex.Message); + return new NzbDroneValidationFailure(string.Empty, _localizationService.GetLocalizedString("NotificationsValidationUnableToSendTestMessage", new Dictionary { { "exceptionMessage", ex.Message } })); } return null; diff --git a/src/NzbDrone.Core/Notifications/Discord/DiscordSettings.cs b/src/NzbDrone.Core/Notifications/Discord/DiscordSettings.cs index 459fdaa2d..8dbb68ba4 100644 --- a/src/NzbDrone.Core/Notifications/Discord/DiscordSettings.cs +++ b/src/NzbDrone.Core/Notifications/Discord/DiscordSettings.cs @@ -68,25 +68,25 @@ namespace NzbDrone.Core.Notifications.Discord private static readonly DiscordSettingsValidator Validator = new (); - [FieldDefinition(0, Label = "Webhook URL", HelpText = "Discord channel webhook url")] + [FieldDefinition(0, Label = "NotificationsSettingsWebhookUrl", HelpText = "NotificationsDiscordSettingsWebhookUrlHelpText")] public string WebHookUrl { get; set; } - [FieldDefinition(1, Label = "Username", Privacy = PrivacyLevel.UserName, HelpText = "The username to post as, defaults to Discord webhook default")] + [FieldDefinition(1, Label = "Username", Privacy = PrivacyLevel.UserName, HelpText = "NotificationsDiscordSettingsUsernameHelpText")] public string Username { get; set; } - [FieldDefinition(2, Label = "Avatar", HelpText = "Change the avatar that is used for messages from this integration", Type = FieldType.Textbox)] + [FieldDefinition(2, Label = "NotificationsDiscordSettingsAvatar", HelpText = "NotificationsDiscordSettingsAvatarHelpText", Type = FieldType.Textbox)] public string Avatar { get; set; } - [FieldDefinition(3, Label = "Author", Advanced = true, HelpText = "Override the embed author that shows for this notification, Blank is instance name", Type = FieldType.Textbox)] + [FieldDefinition(3, Label = "NotificationsDiscordSettingsAuthor", Advanced = true, HelpText = "NotificationsDiscordSettingsAuthorHelpText", Type = FieldType.Textbox)] public string Author { get; set; } - [FieldDefinition(4, Label = "On Grab Fields", Advanced = true, SelectOptions = typeof(DiscordGrabFieldType), HelpText = "Change the fields that are passed in for this 'on grab' notification", Type = FieldType.Select)] + [FieldDefinition(4, Label = "NotificationsDiscordSettingsOnGrabFields", Advanced = true, SelectOptions = typeof(DiscordGrabFieldType), HelpText = "NotificationsDiscordSettingsOnGrabFieldsHelpText", Type = FieldType.Select)] public IEnumerable GrabFields { get; set; } - [FieldDefinition(5, Label = "On Import Fields", Advanced = true, SelectOptions = typeof(DiscordImportFieldType), HelpText = "Change the fields that are passed for this 'on import' notification", Type = FieldType.Select)] + [FieldDefinition(5, Label = "NotificationsDiscordSettingsOnImportFields", Advanced = true, SelectOptions = typeof(DiscordImportFieldType), HelpText = "NotificationsDiscordSettingsOnImportFieldsHelpText", Type = FieldType.Select)] public IEnumerable ImportFields { get; set; } - [FieldDefinition(6, Label = "On Manual Interaction Fields", Advanced = true, SelectOptions = typeof(DiscordManualInteractionFieldType), HelpText = "Change the fields that are passed for this 'on manual interaction' notification", Type = FieldType.Select)] + [FieldDefinition(6, Label = "NotificationsDiscordSettingsOnManualInteractionFields", Advanced = true, SelectOptions = typeof(DiscordManualInteractionFieldType), HelpText = "NotificationsDiscordSettingsOnManualInteractionFieldsHelpText", Type = FieldType.Select)] public IEnumerable ManualInteractionFields { get; set; } public NzbDroneValidationResult Validate() diff --git a/src/NzbDrone.Core/Notifications/Email/Email.cs b/src/NzbDrone.Core/Notifications/Email/Email.cs index 567738c09..f8d3646ad 100644 --- a/src/NzbDrone.Core/Notifications/Email/Email.cs +++ b/src/NzbDrone.Core/Notifications/Email/Email.cs @@ -8,19 +8,22 @@ using MimeKit; using NLog; using NzbDrone.Common.Extensions; using NzbDrone.Common.Http.Dispatchers; +using NzbDrone.Core.Localization; namespace NzbDrone.Core.Notifications.Email { public class Email : NotificationBase { private readonly ICertificateValidationService _certificateValidationService; + private readonly ILocalizationService _localizationService; private readonly Logger _logger; - public override string Name => "Email"; + public override string Name => _localizationService.GetLocalizedString("NotificationsEmailSettingsName"); - public Email(ICertificateValidationService certificateValidationService, Logger logger) + public Email(ICertificateValidationService certificateValidationService, ILocalizationService localizationService, Logger logger) { _certificateValidationService = certificateValidationService; + _localizationService = localizationService; _logger = logger; } @@ -180,7 +183,7 @@ namespace NzbDrone.Core.Notifications.Email catch (Exception ex) { _logger.Error(ex, "Unable to send test email"); - return new ValidationFailure("Server", "Unable to send test email"); + return new ValidationFailure("Server", _localizationService.GetLocalizedString("NotificationsValidationUnableToSendTestMessage", new Dictionary { { "exceptionMessage", ex.Message } })); } return null; diff --git a/src/NzbDrone.Core/Notifications/Email/EmailSettings.cs b/src/NzbDrone.Core/Notifications/Email/EmailSettings.cs index eb9f6dea2..69ffaa60f 100644 --- a/src/NzbDrone.Core/Notifications/Email/EmailSettings.cs +++ b/src/NzbDrone.Core/Notifications/Email/EmailSettings.cs @@ -39,13 +39,13 @@ namespace NzbDrone.Core.Notifications.Email Bcc = Array.Empty(); } - [FieldDefinition(0, Label = "Server", HelpText = "Hostname or IP of Email server")] + [FieldDefinition(0, Label = "NotificationsEmailSettingsServer", HelpText = "NotificationsEmailSettingsServerHelpText")] public string Server { get; set; } [FieldDefinition(1, Label = "Port")] public int Port { get; set; } - [FieldDefinition(2, Label = "Require Encryption", HelpText = "Require SSL (Port 465 only) or StartTLS (any other port)", Type = FieldType.Checkbox)] + [FieldDefinition(2, Label = "NotificationsEmailSettingsRequireEncryption", HelpText = "NotificationsEmailSettingsRequireEncryptionHelpText", Type = FieldType.Checkbox)] public bool RequireEncryption { get; set; } [FieldDefinition(3, Label = "Username", Privacy = PrivacyLevel.UserName)] @@ -54,16 +54,16 @@ namespace NzbDrone.Core.Notifications.Email [FieldDefinition(4, Label = "Password", Type = FieldType.Password, Privacy = PrivacyLevel.Password)] public string Password { get; set; } - [FieldDefinition(5, Label = "From Address")] + [FieldDefinition(5, Label = "NotificationsEmailSettingsFromAddress")] public string From { get; set; } - [FieldDefinition(6, Label = "Recipient Address(es)", HelpText = "Comma separated list of email recipients")] + [FieldDefinition(6, Label = "NotificationsEmailSettingsRecipientAddress", HelpText = "NotificationsEmailSettingsRecipientAddressHelpText")] public IEnumerable To { get; set; } - [FieldDefinition(7, Label = "CC Address(es)", HelpText = "Comma separated list of email cc recipients", Advanced = true)] + [FieldDefinition(7, Label = "NotificationsEmailSettingsCcAddress", HelpText = "NotificationsEmailSettingsCcAddressHelpText", Advanced = true)] public IEnumerable Cc { get; set; } - [FieldDefinition(8, Label = "BCC Address(es)", HelpText = "Comma separated list of email bcc recipients", Advanced = true)] + [FieldDefinition(8, Label = "NotificationsEmailSettingsBccAddress", HelpText = "NotificationsEmailSettingsBccAddressHelpText", Advanced = true)] public IEnumerable Bcc { get; set; } public NzbDroneValidationResult Validate() diff --git a/src/NzbDrone.Core/Notifications/Gotify/Gotify.cs b/src/NzbDrone.Core/Notifications/Gotify/Gotify.cs index af6401573..b315ec352 100644 --- a/src/NzbDrone.Core/Notifications/Gotify/Gotify.cs +++ b/src/NzbDrone.Core/Notifications/Gotify/Gotify.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using FluentValidation.Results; using NLog; +using NzbDrone.Core.Localization; using NzbDrone.Core.MediaCover; using NzbDrone.Core.Tv; @@ -12,11 +13,13 @@ namespace NzbDrone.Core.Notifications.Gotify public class Gotify : NotificationBase { private readonly IGotifyProxy _proxy; + private readonly ILocalizationService _localizationService; private readonly Logger _logger; - public Gotify(IGotifyProxy proxy, Logger logger) + public Gotify(IGotifyProxy proxy, ILocalizationService localizationService, Logger logger) { _proxy = proxy; + _localizationService = localizationService; _logger = logger; } @@ -101,7 +104,7 @@ namespace NzbDrone.Core.Notifications.Gotify catch (Exception ex) { _logger.Error(ex, "Unable to send test message"); - failures.Add(new ValidationFailure("", "Unable to send test message")); + failures.Add(new ValidationFailure(string.Empty, _localizationService.GetLocalizedString("NotificationsValidationUnableToSendTestMessage", new Dictionary { { "exceptionMessage", ex.Message } }))); } return new ValidationResult(failures); diff --git a/src/NzbDrone.Core/Notifications/Gotify/GotifySettings.cs b/src/NzbDrone.Core/Notifications/Gotify/GotifySettings.cs index 48f4aa7e8..08c4ecbfd 100644 --- a/src/NzbDrone.Core/Notifications/Gotify/GotifySettings.cs +++ b/src/NzbDrone.Core/Notifications/Gotify/GotifySettings.cs @@ -23,16 +23,16 @@ namespace NzbDrone.Core.Notifications.Gotify Priority = 5; } - [FieldDefinition(0, Label = "Gotify Server", HelpText = "Gotify server URL, including http(s):// and port if needed")] + [FieldDefinition(0, Label = "NotificationsGotifySettingsServer", HelpText = "")] public string Server { get; set; } - [FieldDefinition(1, Label = "App Token", Privacy = PrivacyLevel.ApiKey, HelpText = "The Application Token generated by Gotify")] + [FieldDefinition(1, Label = "NotificationsGotifySettingsAppToken", Privacy = PrivacyLevel.ApiKey, HelpText = "NotificationsGotifySettingsAppTokenHelpText")] public string AppToken { get; set; } - [FieldDefinition(2, Label = "Priority", Type = FieldType.Select, SelectOptions = typeof(GotifyPriority), HelpText = "Priority of the notification")] + [FieldDefinition(2, Label = "Priority", Type = FieldType.Select, SelectOptions = typeof(GotifyPriority), HelpText = "NotificationsGotifySettingsPriorityHelpText")] public int Priority { get; set; } - [FieldDefinition(3, Label = "Include Series Poster", Type = FieldType.Checkbox, HelpText = "Include series poster in message")] + [FieldDefinition(3, Label = "NotificationsGotifySettingIncludeSeriesPoster", Type = FieldType.Checkbox, HelpText = "NotificationsGotifySettingIncludeSeriesPosterHelpText")] public bool IncludeSeriesPoster { get; set; } public NzbDroneValidationResult Validate() diff --git a/src/NzbDrone.Core/Notifications/Join/JoinProxy.cs b/src/NzbDrone.Core/Notifications/Join/JoinProxy.cs index 516dda173..fa017543f 100644 --- a/src/NzbDrone.Core/Notifications/Join/JoinProxy.cs +++ b/src/NzbDrone.Core/Notifications/Join/JoinProxy.cs @@ -1,10 +1,12 @@ using System; +using System.Collections.Generic; using System.Net.Http; using FluentValidation.Results; using NLog; using NzbDrone.Common.Extensions; using NzbDrone.Common.Http; using NzbDrone.Common.Serializer; +using NzbDrone.Core.Localization; namespace NzbDrone.Core.Notifications.Join { @@ -19,11 +21,13 @@ namespace NzbDrone.Core.Notifications.Join private const string URL = "https://joinjoaomgcd.appspot.com/_ah/api/messaging/v1/sendPush?"; private readonly IHttpClient _httpClient; + private readonly ILocalizationService _localizationService; private readonly Logger _logger; - public JoinProxy(IHttpClient httpClient, Logger logger) + public JoinProxy(IHttpClient httpClient, ILocalizationService localizationService, Logger logger) { _httpClient = httpClient; + _localizationService = localizationService; _logger = logger; } @@ -55,22 +59,22 @@ namespace NzbDrone.Core.Notifications.Join catch (JoinInvalidDeviceException ex) { _logger.Error(ex, "Unable to send test Join message. Invalid Device IDs supplied."); - return new ValidationFailure("DeviceIds", "Device IDs appear invalid."); + return new ValidationFailure("DeviceIds", _localizationService.GetLocalizedString("NotificationsJoinValidationInvalidDeviceId")); } catch (JoinException ex) { _logger.Error(ex, "Unable to send test Join message."); - return new ValidationFailure("ApiKey", ex.Message); + return new ValidationFailure("ApiKey", _localizationService.GetLocalizedString("NotificationsValidationUnableToSendTestMessage", new Dictionary { { "exceptionMessage", ex.Message } })); } catch (HttpException ex) { _logger.Error(ex, "Unable to send test Join message. Server connection failed."); - return new ValidationFailure("ApiKey", "Unable to connect to Join API. Please try again later."); + return new ValidationFailure("ApiKey", _localizationService.GetLocalizedString("NotificationsValidationUnableToSendTestMessage", new Dictionary { { "service", "Join" }, { "responseCode", ex.Response.StatusCode }, { "exceptionMessage", ex.Message } })); } catch (Exception ex) { _logger.Error(ex, "Unable to send test Join message. Unknown error."); - return new ValidationFailure("ApiKey", ex.Message); + return new ValidationFailure("ApiKey", _localizationService.GetLocalizedString("NotificationsValidationUnableToSendTestMessage", new Dictionary { { "exceptionMessage", ex.Message } })); } } diff --git a/src/NzbDrone.Core/Notifications/Join/JoinSettings.cs b/src/NzbDrone.Core/Notifications/Join/JoinSettings.cs index db5c8550a..bd3046240 100644 --- a/src/NzbDrone.Core/Notifications/Join/JoinSettings.cs +++ b/src/NzbDrone.Core/Notifications/Join/JoinSettings.cs @@ -23,16 +23,16 @@ namespace NzbDrone.Core.Notifications.Join private static readonly JoinSettingsValidator Validator = new JoinSettingsValidator(); - [FieldDefinition(0, Label = "API Key", HelpText = "The API Key from your Join account settings (click Join API button).", HelpLink = "https://joinjoaomgcd.appspot.com/")] + [FieldDefinition(0, Label = "ApiKey", HelpText = "NotificationsJoinSettingsApiKeyHelpText", HelpLink = "https://joinjoaomgcd.appspot.com/")] public string ApiKey { get; set; } - [FieldDefinition(1, Label = "Device IDs", HelpText = "Deprecated, use Device Names instead. Comma separated list of Device IDs you'd like to send notifications to. If unset, all devices will receive notifications.")] + [FieldDefinition(1, Label = "NotificationsJoinSettingsDeviceIds", HelpText = "NotificationsJoinSettingsDeviceIdsHelpText", Hidden = HiddenType.HiddenIfNotSet)] public string DeviceIds { get; set; } - [FieldDefinition(2, Label = "Device Names", HelpText = "Comma separated list of full or partial device names you'd like to send notifications to. If unset, all devices will receive notifications.", HelpLink = "https://joaoapps.com/join/api/")] + [FieldDefinition(2, Label = "NotificationsJoinSettingsDeviceNames", HelpText = "NotificationsJoinSettingsDeviceNamesHelpText", HelpLink = "https://joaoapps.com/join/api/")] public string DeviceNames { get; set; } - [FieldDefinition(3, Label = "Notification Priority", Type = FieldType.Select, SelectOptions = typeof(JoinPriority))] + [FieldDefinition(3, Label = "NotificationsJoinSettingsNotificationPriority", Type = FieldType.Select, SelectOptions = typeof(JoinPriority))] public int Priority { get; set; } public NzbDroneValidationResult Validate() diff --git a/src/NzbDrone.Core/Notifications/Mailgun/Mailgun.cs b/src/NzbDrone.Core/Notifications/Mailgun/Mailgun.cs index 9498e06e9..9706d8ebb 100644 --- a/src/NzbDrone.Core/Notifications/Mailgun/Mailgun.cs +++ b/src/NzbDrone.Core/Notifications/Mailgun/Mailgun.cs @@ -2,17 +2,20 @@ using System; using System.Collections.Generic; using FluentValidation.Results; using NLog; +using NzbDrone.Core.Localization; namespace NzbDrone.Core.Notifications.Mailgun { public class MailGun : NotificationBase { private readonly IMailgunProxy _proxy; + private readonly ILocalizationService _localizationService; private readonly Logger _logger; - public MailGun(IMailgunProxy proxy, Logger logger) + public MailGun(IMailgunProxy proxy, ILocalizationService localizationService, Logger logger) { _proxy = proxy; + _localizationService = localizationService; _logger = logger; } @@ -85,7 +88,7 @@ namespace NzbDrone.Core.Notifications.Mailgun catch (Exception ex) { _logger.Error(ex, "Unable to send test message though Mailgun."); - failures.Add(new ValidationFailure("", "Unable to send test message though Mailgun.")); + failures.Add(new ValidationFailure(string.Empty, _localizationService.GetLocalizedString("NotificationsValidationUnableToSendTestMessage", new Dictionary { { "exceptionMessage", ex.Message } }))); } return new ValidationResult(failures); diff --git a/src/NzbDrone.Core/Notifications/Mailgun/MailgunSettings.cs b/src/NzbDrone.Core/Notifications/Mailgun/MailgunSettings.cs index 181de5faa..42802abc0 100644 --- a/src/NzbDrone.Core/Notifications/Mailgun/MailgunSettings.cs +++ b/src/NzbDrone.Core/Notifications/Mailgun/MailgunSettings.cs @@ -26,19 +26,19 @@ namespace NzbDrone.Core.Notifications.Mailgun Recipients = Array.Empty(); } - [FieldDefinition(0, Label = "API Key", HelpText = "The API key generated from MailGun")] + [FieldDefinition(0, Label = "ApiKey", HelpText = "NotificationsMailgunSettingsApiKeyHelpText")] public string ApiKey { get; set; } - [FieldDefinition(1, Label = "Use EU Endpoint?", HelpText = "You can choose to use the EU MailGun endpoint with this", Type = FieldType.Checkbox)] + [FieldDefinition(1, Label = "NotificationsMailgunSettingsUseEuEndpoint", HelpText = "NotificationsMailgunSettingsUseEuEndpointHelpText", Type = FieldType.Checkbox)] public bool UseEuEndpoint { get; set; } - [FieldDefinition(2, Label = "From Address")] + [FieldDefinition(2, Label = "NotificationsEmailSettingsFromAddress")] public string From { get; set; } - [FieldDefinition(3, Label = "Sender Domain")] + [FieldDefinition(3, Label = "NotificationsMailgunSettingsSenderDomain")] public string SenderDomain { get; set; } - [FieldDefinition(4, Label = "Recipient Address(es)", Type = FieldType.Tag)] + [FieldDefinition(4, Label = "NotificationsEmailSettingsRecipientAddress", Type = FieldType.Tag)] public IEnumerable Recipients { get; set; } public NzbDroneValidationResult Validate() diff --git a/src/NzbDrone.Core/Notifications/MediaBrowser/MediaBrowserService.cs b/src/NzbDrone.Core/Notifications/MediaBrowser/MediaBrowserService.cs index 1f997dfd2..a89c2180f 100644 --- a/src/NzbDrone.Core/Notifications/MediaBrowser/MediaBrowserService.cs +++ b/src/NzbDrone.Core/Notifications/MediaBrowser/MediaBrowserService.cs @@ -6,6 +6,7 @@ using NLog; using NzbDrone.Common.Disk; using NzbDrone.Common.Extensions; using NzbDrone.Common.Http; +using NzbDrone.Core.Localization; using NzbDrone.Core.Tv; namespace NzbDrone.Core.Notifications.Emby @@ -20,11 +21,13 @@ namespace NzbDrone.Core.Notifications.Emby public class MediaBrowserService : IMediaBrowserService { private readonly MediaBrowserProxy _proxy; + private readonly ILocalizationService _localizationService; private readonly Logger _logger; - public MediaBrowserService(MediaBrowserProxy proxy, Logger logger) + public MediaBrowserService(MediaBrowserProxy proxy, ILocalizationService localizationService, Logger logger) { _proxy = proxy; + _localizationService = localizationService; _logger = logger; } @@ -66,13 +69,13 @@ namespace NzbDrone.Core.Notifications.Emby { if (ex.Response.StatusCode == HttpStatusCode.Unauthorized) { - return new ValidationFailure("ApiKey", "API Key is incorrect"); + return new ValidationFailure("ApiKey", _localizationService.GetLocalizedString("NotificationsValidationInvalidApiKey")); } } catch (Exception ex) { _logger.Error(ex, "Unable to send test message"); - return new ValidationFailure("Host", "Unable to send test message: " + ex.Message); + return new ValidationFailure("Host", _localizationService.GetLocalizedString("NotificationsValidationUnableToSendTestMessage", new Dictionary { { "exceptionMessage", ex.Message } })); } return null; diff --git a/src/NzbDrone.Core/Notifications/MediaBrowser/MediaBrowserSettings.cs b/src/NzbDrone.Core/Notifications/MediaBrowser/MediaBrowserSettings.cs index a09fe71b0..237ac9998 100644 --- a/src/NzbDrone.Core/Notifications/MediaBrowser/MediaBrowserSettings.cs +++ b/src/NzbDrone.Core/Notifications/MediaBrowser/MediaBrowserSettings.cs @@ -33,22 +33,25 @@ namespace NzbDrone.Core.Notifications.Emby [FieldDefinition(1, Label = "Port")] public int Port { get; set; } - [FieldDefinition(2, Label = "Use SSL", Type = FieldType.Checkbox, HelpText = "Connect to Emby/Jellyfin over HTTPS instead of HTTP")] + [FieldDefinition(2, Label = "UseSsl", Type = FieldType.Checkbox, HelpText = "NotificationsSettingsUseSslHelpText")] + [FieldToken(TokenField.HelpText, "UseSsl", "serviceName", "Emby/Jellyfin")] public bool UseSsl { get; set; } - [FieldDefinition(3, Label = "API Key", Privacy = PrivacyLevel.ApiKey)] + [FieldDefinition(3, Label = "ApiKey", Privacy = PrivacyLevel.ApiKey)] public string ApiKey { get; set; } - [FieldDefinition(4, Label = "Send Notifications", HelpText = "Have MediaBrowser send notifications to configured providers", Type = FieldType.Checkbox)] + [FieldDefinition(4, Label = "NotificationsEmbySettingsSendNotifications", HelpText = "NotificationsEmbySettingsSendNotificationsHelpText", Type = FieldType.Checkbox)] public bool Notify { get; set; } - [FieldDefinition(5, Label = "Update Library", HelpText = "Update Library on Import, Rename, or Delete?", Type = FieldType.Checkbox)] + [FieldDefinition(5, Label = "NotificationsSettingsUpdateLibrary", HelpText = "NotificationsEmbySettingsUpdateLibraryHelpText", Type = FieldType.Checkbox)] public bool UpdateLibrary { get; set; } - [FieldDefinition(6, Label = "Map Paths From", HelpText = "Sonarr path, used to modify series paths when Emby/Jellyfin sees library path location differently from Sonarr(Requires 'UpdateLibrary')", Type = FieldType.Textbox, Advanced = true)] + [FieldDefinition(6, Label = "NotificationsSettingsUpdateMapPathsFrom", HelpText = "NotificationsSettingsUpdateMapPathsFromHelpText", Type = FieldType.Textbox, Advanced = true)] + [FieldToken(TokenField.HelpText, "NotificationsSettingsUpdateMapPathsFrom", "serviceName", "Emby/Jellyfin")] public string MapFrom { get; set; } - [FieldDefinition(7, Label = "Map Paths To", HelpText = "Emby/Jellyfin path, used to modify series paths when Emby/Jellyfin sees library path location differently from Sonarr(Requires 'UpdateLibrary')", Type = FieldType.Textbox, Advanced = true)] + [FieldDefinition(7, Label = "NotificationsSettingsUpdateMapPathsTo", HelpText = "NotificationsSettingsUpdateMapPathsToHelpText", Type = FieldType.Textbox, Advanced = true)] + [FieldToken(TokenField.HelpText, "NotificationsSettingsUpdateMapPathsTo", "serviceName", "Emby/Jellyfin")] public string MapTo { get; set; } [JsonIgnore] diff --git a/src/NzbDrone.Core/Notifications/Notifiarr/Notifiarr.cs b/src/NzbDrone.Core/Notifications/Notifiarr/Notifiarr.cs index 63044763d..cc3c9b7b7 100644 --- a/src/NzbDrone.Core/Notifications/Notifiarr/Notifiarr.cs +++ b/src/NzbDrone.Core/Notifications/Notifiarr/Notifiarr.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using FluentValidation.Results; using NzbDrone.Common.Extensions; using NzbDrone.Core.Configuration; +using NzbDrone.Core.Localization; using NzbDrone.Core.MediaFiles; using NzbDrone.Core.Notifications.Webhook; using NzbDrone.Core.Tv; @@ -13,8 +14,8 @@ namespace NzbDrone.Core.Notifications.Notifiarr { private readonly INotifiarrProxy _proxy; - public Notifiarr(INotifiarrProxy proxy, IConfigFileProvider configFileProvider, IConfigService configService) - : base(configFileProvider, configService) + public Notifiarr(INotifiarrProxy proxy, IConfigFileProvider configFileProvider, IConfigService configService, ILocalizationService localizationService) + : base(configFileProvider, configService, localizationService) { _proxy = proxy; } @@ -89,7 +90,7 @@ namespace NzbDrone.Core.Notifications.Notifiarr } catch (NotifiarrException ex) { - return new NzbDroneValidationFailure("APIKey", ex.Message); + return new NzbDroneValidationFailure("APIKey", _localizationService.GetLocalizedString("NotificationsValidationUnableToSendTestMessage", new Dictionary { { "exceptionMessage", ex.Message } })); } return null; diff --git a/src/NzbDrone.Core/Notifications/Notifiarr/NotifiarrSettings.cs b/src/NzbDrone.Core/Notifications/Notifiarr/NotifiarrSettings.cs index f391e8a77..dd610b3ba 100644 --- a/src/NzbDrone.Core/Notifications/Notifiarr/NotifiarrSettings.cs +++ b/src/NzbDrone.Core/Notifications/Notifiarr/NotifiarrSettings.cs @@ -17,7 +17,7 @@ namespace NzbDrone.Core.Notifications.Notifiarr { private static readonly NotifiarrSettingsValidator Validator = new NotifiarrSettingsValidator(); - [FieldDefinition(0, Label = "API Key", Privacy = PrivacyLevel.ApiKey, HelpText = "Your API key from your profile", HelpLink = "https://notifiarr.com")] + [FieldDefinition(0, Label = "ApiKey", Privacy = PrivacyLevel.ApiKey, HelpText = "NotificationsNotifiarrSettingsApiKeyHelpText", HelpLink = "https://notifiarr.com")] public string ApiKey { get; set; } public NzbDroneValidationResult Validate() diff --git a/src/NzbDrone.Core/Notifications/Ntfy/NtfyProxy.cs b/src/NzbDrone.Core/Notifications/Ntfy/NtfyProxy.cs index 0afa524c8..4198ce38c 100644 --- a/src/NzbDrone.Core/Notifications/Ntfy/NtfyProxy.cs +++ b/src/NzbDrone.Core/Notifications/Ntfy/NtfyProxy.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Net; @@ -6,6 +7,7 @@ using FluentValidation.Results; using NLog; using NzbDrone.Common.Extensions; using NzbDrone.Common.Http; +using NzbDrone.Core.Localization; namespace NzbDrone.Core.Notifications.Ntfy { @@ -21,12 +23,13 @@ namespace NzbDrone.Core.Notifications.Ntfy private const string DEFAULT_PUSH_URL = "https://ntfy.sh"; private readonly IHttpClient _httpClient; - + private readonly ILocalizationService _localizationService; private readonly Logger _logger; - public NtfyProxy(IHttpClient httpClient, Logger logger) + public NtfyProxy(IHttpClient httpClient, ILocalizationService localizationService, Logger logger) { _httpClient = httpClient; + _localizationService = localizationService; _logger = logger; } @@ -83,26 +86,26 @@ namespace NzbDrone.Core.Notifications.Ntfy if (!settings.AccessToken.IsNullOrWhiteSpace()) { _logger.Error(ex, "Invalid token"); - return new ValidationFailure("AccessToken", "Invalid token"); + return new ValidationFailure("AccessToken", _localizationService.GetLocalizedString("NotificationsValidationInvalidAccessToken")); } if (!settings.UserName.IsNullOrWhiteSpace() && !settings.Password.IsNullOrWhiteSpace()) { _logger.Error(ex, "Invalid username or password"); - return new ValidationFailure("UserName", "Invalid username or password"); + return new ValidationFailure("UserName", _localizationService.GetLocalizedString("NotificationsValidationInvalidUsernamePassword")); } _logger.Error(ex, "Authorization is required"); - return new ValidationFailure("AccessToken", "Authorization is required"); + return new ValidationFailure("AccessToken", _localizationService.GetLocalizedString("NotificationsNtfyValidationAuthorizationRequired")); } _logger.Error(ex, "Unable to send test message"); - return new ValidationFailure("ServerUrl", "Unable to send test message"); + return new ValidationFailure("ServerUrl", _localizationService.GetLocalizedString("NotificationsValidationUnableToSendTestMessage", new Dictionary { { "exceptionMessage", ex.Message } })); } catch (Exception ex) { _logger.Error(ex, "Unable to send test message"); - return new ValidationFailure("", "Unable to send test message"); + return new ValidationFailure(string.Empty, _localizationService.GetLocalizedString("NotificationsValidationUnableToSendTestMessage", new Dictionary { { "exceptionMessage", ex.Message } })); } return null; diff --git a/src/NzbDrone.Core/Notifications/Ntfy/NtfySettings.cs b/src/NzbDrone.Core/Notifications/Ntfy/NtfySettings.cs index 1c1cedec3..d7273b1ef 100644 --- a/src/NzbDrone.Core/Notifications/Ntfy/NtfySettings.cs +++ b/src/NzbDrone.Core/Notifications/Ntfy/NtfySettings.cs @@ -34,28 +34,29 @@ namespace NzbDrone.Core.Notifications.Ntfy Priority = 3; } - [FieldDefinition(0, Label = "Server Url", Type = FieldType.Url, HelpLink = "https://ntfy.sh/docs/install/", HelpText = "Leave blank to use public server (https://ntfy.sh)")] + [FieldDefinition(0, Label = "NotificationsNtfySettingsServerUrl", Type = FieldType.Url, HelpLink = "https://ntfy.sh/docs/install/", HelpText = "NotificationsNtfySettingsServerUrlHelpText")] + [FieldToken(TokenField.HelpText, "NotificationsNtfySettingsServerUrl", "url", "https://ntfy.sh")] public string ServerUrl { get; set; } - [FieldDefinition(1, Label = "Access Token", Type = FieldType.Password, Privacy = PrivacyLevel.ApiKey, HelpText = "Optional token-based authorization. Takes priority over username/password", HelpLink = "https://docs.ntfy.sh/config/#access-tokens")] + [FieldDefinition(1, Label = "NotificationsNtfySettingsAccessToken", Type = FieldType.Password, Privacy = PrivacyLevel.ApiKey, HelpText = "NotificationsNtfySettingsAccessTokenHelpText", HelpLink = "https://docs.ntfy.sh/config/#access-tokens")] public string AccessToken { get; set; } - [FieldDefinition(2, Label = "User Name", HelpText = "Optional Authorization", Privacy = PrivacyLevel.UserName)] + [FieldDefinition(2, Label = "Username", HelpText = "NotificationsNtfySettingsUsernameHelpText", Privacy = PrivacyLevel.UserName)] public string UserName { get; set; } - [FieldDefinition(3, Label = "Password", Type = FieldType.Password, HelpText = "Optional Password", Privacy = PrivacyLevel.Password)] + [FieldDefinition(3, Label = "Password", Type = FieldType.Password, HelpText = "NotificationsNtfySettingsPasswordHelpText", Privacy = PrivacyLevel.Password)] public string Password { get; set; } [FieldDefinition(4, Label = "Priority", Type = FieldType.Select, SelectOptions = typeof(NtfyPriority))] public int Priority { get; set; } - [FieldDefinition(5, Label = "Topics", HelpText = "List of Topics to send notifications to", Type = FieldType.Tag)] + [FieldDefinition(5, Label = "NotificationsNtfySettingsTopics", HelpText = "NotificationsNtfySettingsTopicsHelpText", Type = FieldType.Tag)] public IEnumerable Topics { get; set; } - [FieldDefinition(6, Label = "Ntfy Tags and Emojis", Type = FieldType.Tag, HelpText = "Optional list of tags or emojis to use", HelpLink = "https://ntfy.sh/docs/emojis/")] + [FieldDefinition(6, Label = "NotificationsNtfySettingsTagsEmojis", Type = FieldType.Tag, HelpText = "", HelpLink = "https://ntfy.sh/docs/emojis/")] public IEnumerable Tags { get; set; } - [FieldDefinition(7, Label = "Click URL", Type = FieldType.Url, HelpText = "Optional link when user clicks notification")] + [FieldDefinition(7, Label = "NotificationsNtfySettingsClickUrl", Type = FieldType.Url, HelpText = "NotificationsNtfySettingsClickUrlHelpText")] public string ClickUrl { get; set; } public NzbDroneValidationResult Validate() diff --git a/src/NzbDrone.Core/Notifications/Plex/Server/PlexServerService.cs b/src/NzbDrone.Core/Notifications/Plex/Server/PlexServerService.cs index ec85434fd..ceff60865 100644 --- a/src/NzbDrone.Core/Notifications/Plex/Server/PlexServerService.cs +++ b/src/NzbDrone.Core/Notifications/Plex/Server/PlexServerService.cs @@ -8,6 +8,7 @@ using NLog; using NzbDrone.Common.Cache; using NzbDrone.Common.Disk; using NzbDrone.Common.Extensions; +using NzbDrone.Core.Localization; using NzbDrone.Core.RootFolders; using NzbDrone.Core.Tv; using NzbDrone.Core.Validation; @@ -26,13 +27,15 @@ namespace NzbDrone.Core.Notifications.Plex.Server private readonly ICached _versionCache; private readonly IPlexServerProxy _plexServerProxy; private readonly IRootFolderService _rootFolderService; + private readonly ILocalizationService _localizationService; private readonly Logger _logger; - public PlexServerService(ICacheManager cacheManager, IPlexServerProxy plexServerProxy, IRootFolderService rootFolderService, Logger logger) + public PlexServerService(ICacheManager cacheManager, IPlexServerProxy plexServerProxy, IRootFolderService rootFolderService, ILocalizationService localizationService, Logger logger) { _versionCache = cacheManager.GetCache(GetType(), "versionCache"); _plexServerProxy = plexServerProxy; _rootFolderService = rootFolderService; + _localizationService = localizationService; _logger = logger; } @@ -154,23 +157,23 @@ namespace NzbDrone.Core.Notifications.Plex.Server if (sections.Empty()) { - return new ValidationFailure("Host", "At least one TV library is required"); + return new ValidationFailure("Host", _localizationService.GetLocalizedString("NotificationsPlexValidationNoTvLibraryFound")); } } catch (PlexAuthenticationException ex) { _logger.Error(ex, "Unable to connect to Plex Media Server"); - return new ValidationFailure("AuthToken", "Invalid authentication token"); + return new ValidationFailure("AuthToken", _localizationService.GetLocalizedString("NotificationsValidationInvalidAuthenticationToken")); } catch (PlexException ex) { - return new NzbDroneValidationFailure("Host", ex.Message); + return new NzbDroneValidationFailure("Host", _localizationService.GetLocalizedString("NotificationsValidationUnableToConnect", new Dictionary { { "exceptionMessage", ex.Message } })); } catch (Exception ex) { _logger.Error(ex, "Unable to connect to Plex Media Server"); - return new NzbDroneValidationFailure("Host", "Unable to connect to Plex Media Server") + return new NzbDroneValidationFailure("Host", _localizationService.GetLocalizedString("NotificationsValidationUnableToConnectToService", new Dictionary { { "serviceName", "Plex Media Server" } })) { DetailedDescription = ex.Message }; diff --git a/src/NzbDrone.Core/Notifications/Plex/Server/PlexServerSettings.cs b/src/NzbDrone.Core/Notifications/Plex/Server/PlexServerSettings.cs index ef23de07f..ff6fd7789 100644 --- a/src/NzbDrone.Core/Notifications/Plex/Server/PlexServerSettings.cs +++ b/src/NzbDrone.Core/Notifications/Plex/Server/PlexServerSettings.cs @@ -34,22 +34,25 @@ namespace NzbDrone.Core.Notifications.Plex.Server [FieldDefinition(1, Label = "Port")] public int Port { get; set; } - [FieldDefinition(2, Label = "Use SSL", Type = FieldType.Checkbox, HelpText = "Connect to Plex over HTTPS instead of HTTP")] + [FieldDefinition(2, Label = "UseSsl", Type = FieldType.Checkbox, HelpText = "NotificationsSettingsUseSslHelpText")] + [FieldToken(TokenField.HelpText, "UseSsl", "serviceName", "Plex")] public bool UseSsl { get; set; } - [FieldDefinition(3, Label = "Auth Token", Type = FieldType.Textbox, Privacy = PrivacyLevel.ApiKey, Advanced = true)] + [FieldDefinition(3, Label = "NotificationsPlexSettingsAuthToken", Type = FieldType.Textbox, Privacy = PrivacyLevel.ApiKey, Advanced = true)] public string AuthToken { get; set; } - [FieldDefinition(4, Label = "Authenticate with Plex.tv", Type = FieldType.OAuth)] + [FieldDefinition(4, Label = "NotificationsPlexSettingsAuthenticateWithPlexTv", Type = FieldType.OAuth)] public string SignIn { get; set; } - [FieldDefinition(5, Label = "Update Library", Type = FieldType.Checkbox)] + [FieldDefinition(5, Label = "NotificationsSettingsUpdateLibrary", Type = FieldType.Checkbox)] public bool UpdateLibrary { get; set; } - [FieldDefinition(6, Label = "Map Paths From", Type = FieldType.Textbox, Advanced = true, HelpText = "Sonarr path, used to modify series paths when Plex sees library path location differently from Sonarr")] + [FieldDefinition(6, Label = "NotificationsSettingsUpdateMapPathsFrom", Type = FieldType.Textbox, Advanced = true, HelpText = "NotificationsSettingsUpdateMapPathsFromHelpText")] + [FieldToken(TokenField.HelpText, "NotificationsSettingsUpdateMapPathsFrom", "serviceName", "Plex")] public string MapFrom { get; set; } - [FieldDefinition(7, Label = "Map Paths To", Type = FieldType.Textbox, Advanced = true, HelpText = "Plex path, used to modify series paths when Plex sees library path location differently from Sonarr")] + [FieldDefinition(7, Label = "NotificationsSettingsUpdateMapPathsTo", Type = FieldType.Textbox, Advanced = true, HelpText = "NotificationsSettingsUpdateMapPathsToHelpText")] + [FieldToken(TokenField.HelpText, "NotificationsSettingsUpdateMapPathsTo", "serviceName", "Plex")] public string MapTo { get; set; } public bool IsValid => !string.IsNullOrWhiteSpace(Host); diff --git a/src/NzbDrone.Core/Notifications/Prowl/ProwlProxy.cs b/src/NzbDrone.Core/Notifications/Prowl/ProwlProxy.cs index e51b73bd0..92cadb79d 100644 --- a/src/NzbDrone.Core/Notifications/Prowl/ProwlProxy.cs +++ b/src/NzbDrone.Core/Notifications/Prowl/ProwlProxy.cs @@ -1,9 +1,11 @@ using System; +using System.Collections.Generic; using System.Net; using FluentValidation.Results; using NLog; using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.Http; +using NzbDrone.Core.Localization; namespace NzbDrone.Core.Notifications.Prowl { @@ -17,11 +19,13 @@ namespace NzbDrone.Core.Notifications.Prowl { private const string PUSH_URL = "https://api.prowlapp.com/publicapi/add"; private readonly IHttpClient _httpClient; + private readonly ILocalizationService _localizationService; private readonly Logger _logger; - public ProwlProxy(IHttpClient httpClient, Logger logger) + public ProwlProxy(IHttpClient httpClient, ILocalizationService localizationService, Logger logger) { _httpClient = httpClient; + _localizationService = localizationService; _logger = logger; } @@ -68,7 +72,7 @@ namespace NzbDrone.Core.Notifications.Prowl } catch (Exception ex) { - return new ValidationFailure("ApiKey", ex.Message); + return new ValidationFailure("ApiKey", _localizationService.GetLocalizedString("NotificationsValidationUnableToSendTestMessage", new Dictionary { { "exceptionMessage", ex.Message } })); } return null; diff --git a/src/NzbDrone.Core/Notifications/Prowl/ProwlSettings.cs b/src/NzbDrone.Core/Notifications/Prowl/ProwlSettings.cs index aaacdf469..4add832cb 100644 --- a/src/NzbDrone.Core/Notifications/Prowl/ProwlSettings.cs +++ b/src/NzbDrone.Core/Notifications/Prowl/ProwlSettings.cs @@ -17,7 +17,7 @@ namespace NzbDrone.Core.Notifications.Prowl { private static readonly ProwlSettingsValidator Validator = new ProwlSettingsValidator(); - [FieldDefinition(0, Label = "API Key", Privacy = PrivacyLevel.ApiKey, HelpLink = "https://www.prowlapp.com/api_settings.php")] + [FieldDefinition(0, Label = "ApiKey", Privacy = PrivacyLevel.ApiKey, HelpLink = "https://www.prowlapp.com/api_settings.php")] public string ApiKey { get; set; } [FieldDefinition(1, Label = "Priority", Type = FieldType.Select, SelectOptions = typeof(ProwlPriority))] diff --git a/src/NzbDrone.Core/Notifications/PushBullet/PushBulletProxy.cs b/src/NzbDrone.Core/Notifications/PushBullet/PushBulletProxy.cs index fadd10188..4ec711167 100644 --- a/src/NzbDrone.Core/Notifications/PushBullet/PushBulletProxy.cs +++ b/src/NzbDrone.Core/Notifications/PushBullet/PushBulletProxy.cs @@ -8,6 +8,7 @@ using NLog; using NzbDrone.Common.Extensions; using NzbDrone.Common.Http; using NzbDrone.Common.Serializer; +using NzbDrone.Core.Localization; namespace NzbDrone.Core.Notifications.PushBullet { @@ -23,11 +24,13 @@ namespace NzbDrone.Core.Notifications.PushBullet private const string PUSH_URL = "https://api.pushbullet.com/v2/pushes"; private const string DEVICE_URL = "https://api.pushbullet.com/v2/devices"; private readonly IHttpClient _httpClient; + private readonly ILocalizationService _localizationService; private readonly Logger _logger; - public PushBulletProxy(IHttpClient httpClient, Logger logger) + public PushBulletProxy(IHttpClient httpClient, ILocalizationService localizationService, Logger logger) { _httpClient = httpClient; + _localizationService = localizationService; _logger = logger; } @@ -134,16 +137,16 @@ namespace NzbDrone.Core.Notifications.PushBullet if (ex.Response.StatusCode == HttpStatusCode.Unauthorized) { _logger.Error(ex, "API Key is invalid"); - return new ValidationFailure("ApiKey", "API Key is invalid"); + return new ValidationFailure("ApiKey", _localizationService.GetLocalizedString("NotificationsValidationInvalidApiKey")); } _logger.Error(ex, "Unable to send test message"); - return new ValidationFailure("ApiKey", "Unable to send test message"); + return new ValidationFailure("ApiKey", _localizationService.GetLocalizedString("NotificationsValidationUnableToSendTestMessage", new Dictionary { { "exceptionMessage", ex.Message } })); } catch (Exception ex) { _logger.Error(ex, "Unable to send test message"); - return new ValidationFailure("", "Unable to send test message"); + return new ValidationFailure("", _localizationService.GetLocalizedString("NotificationsValidationUnableToSendTestMessage", new Dictionary { { "exceptionMessage", ex.Message } })); } return null; diff --git a/src/NzbDrone.Core/Notifications/PushBullet/PushBulletSettings.cs b/src/NzbDrone.Core/Notifications/PushBullet/PushBulletSettings.cs index d4e9d0661..a50aee65d 100644 --- a/src/NzbDrone.Core/Notifications/PushBullet/PushBulletSettings.cs +++ b/src/NzbDrone.Core/Notifications/PushBullet/PushBulletSettings.cs @@ -25,16 +25,16 @@ namespace NzbDrone.Core.Notifications.PushBullet ChannelTags = Array.Empty(); } - [FieldDefinition(0, Label = "Access Token", Privacy = PrivacyLevel.ApiKey, HelpLink = "https://www.pushbullet.com/#settings/account")] + [FieldDefinition(0, Label = "NotificationsPushBulletSettingsAccessToken", Privacy = PrivacyLevel.ApiKey, HelpLink = "https://www.pushbullet.com/#settings/account")] public string ApiKey { get; set; } - [FieldDefinition(1, Label = "Device IDs", HelpText = "List of device IDs (leave blank to send to all devices)", Type = FieldType.Device)] + [FieldDefinition(1, Label = "NotificationsPushBulletSettingsDeviceIds", HelpText = "NotificationsPushBulletSettingsDeviceIdsHelpText", Type = FieldType.Device)] public IEnumerable DeviceIds { get; set; } - [FieldDefinition(2, Label = "Channel Tags", HelpText = "List of Channel Tags to send notifications to", Type = FieldType.Tag)] + [FieldDefinition(2, Label = "NotificationsPushBulletSettingsChannelTags", HelpText = "NotificationsPushBulletSettingsChannelTagsHelpText", Type = FieldType.Tag)] public IEnumerable ChannelTags { get; set; } - [FieldDefinition(3, Label = "Sender ID", HelpText = "The device ID to send notifications from, use device_iden in the device's URL on pushbullet.com (leave blank to send from yourself)")] + [FieldDefinition(3, Label = "NotificationsPushBulletSettingSenderId", HelpText = "NotificationsPushBulletSettingSenderIdHelpText")] public string SenderId { get; set; } public NzbDroneValidationResult Validate() diff --git a/src/NzbDrone.Core/Notifications/Pushcut/PushcutProxy.cs b/src/NzbDrone.Core/Notifications/Pushcut/PushcutProxy.cs index ddae1319a..1629854bb 100644 --- a/src/NzbDrone.Core/Notifications/Pushcut/PushcutProxy.cs +++ b/src/NzbDrone.Core/Notifications/Pushcut/PushcutProxy.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using System.Net; using System.Net.Http; using FluentValidation.Results; @@ -5,6 +6,7 @@ using NLog; using NzbDrone.Common.Extensions; using NzbDrone.Common.Http; using NzbDrone.Common.Serializer; +using NzbDrone.Core.Localization; namespace NzbDrone.Core.Notifications.Pushcut { @@ -17,11 +19,13 @@ namespace NzbDrone.Core.Notifications.Pushcut public class PushcutProxy : IPushcutProxy { private readonly IHttpClient _httpClient; + private readonly ILocalizationService _localizationService; private readonly Logger _logger; - public PushcutProxy(IHttpClient httpClient, Logger logger) + public PushcutProxy(IHttpClient httpClient, ILocalizationService localizationService, Logger logger) { _httpClient = httpClient; + _localizationService = localizationService; _logger = logger; } @@ -67,7 +71,7 @@ namespace NzbDrone.Core.Notifications.Pushcut if (httpException.Response.StatusCode == HttpStatusCode.Forbidden) { _logger.Error(pushcutException, "API Key is invalid: {0}", pushcutException.Message); - return new ValidationFailure("API Key", $"API Key is invalid: {pushcutException.Message}"); + return new ValidationFailure("API Key", _localizationService.GetLocalizedString("NotificationsValidationInvalidApiKeyExceptionMessage", new Dictionary { { "exceptionMessage", pushcutException.Message } })); } if (httpException.Response.Content.IsNotNullOrWhiteSpace()) @@ -75,11 +79,11 @@ namespace NzbDrone.Core.Notifications.Pushcut var response = Json.Deserialize(httpException.Response.Content); _logger.Error(pushcutException, "Unable to send test notification. Response from Pushcut: {0}", response.Error); - return new ValidationFailure("Url", $"Unable to send test notification. Response from Pushcut: {response.Error}"); + return new ValidationFailure("Url", _localizationService.GetLocalizedString("NotificationsValidationUnableToSendTestMessageApiResponse", new Dictionary { { "error", response.Error } })); } _logger.Error(pushcutException, "Unable to connect to Pushcut API. Server connection failed: ({0}) {1}", httpException.Response.StatusCode, pushcutException.Message); - return new ValidationFailure("Host", $"Unable to connect to Pushcut API. Server connection failed: ({httpException.Response.StatusCode}) {pushcutException.Message}"); + return new ValidationFailure("Host", _localizationService.GetLocalizedString("NotificationsValidationUnableToConnectToApi", new Dictionary { { "responseCode", httpException.Response.StatusCode }, { "exceptionMessage", pushcutException.Message } })); } return null; diff --git a/src/NzbDrone.Core/Notifications/Pushcut/PushcutSettings.cs b/src/NzbDrone.Core/Notifications/Pushcut/PushcutSettings.cs index 625bca01e..87ee342b2 100644 --- a/src/NzbDrone.Core/Notifications/Pushcut/PushcutSettings.cs +++ b/src/NzbDrone.Core/Notifications/Pushcut/PushcutSettings.cs @@ -18,13 +18,13 @@ namespace NzbDrone.Core.Notifications.Pushcut { private static readonly PushcutSettingsValidator Validator = new (); - [FieldDefinition(0, Label = "Notification name", Type = FieldType.Textbox, HelpText = "Notification name from Notifications tab of the Pushcut app.")] + [FieldDefinition(0, Label = "NotificationsPushcutSettingsNotificationName", Type = FieldType.Textbox, HelpText = "")] public string NotificationName { get; set; } - [FieldDefinition(1, Label = "API Key", Type = FieldType.Textbox, Privacy = PrivacyLevel.ApiKey, HelpText = "API Keys can be managed in the Account view of the Pushcut app.")] + [FieldDefinition(1, Label = "ApiKey", Type = FieldType.Textbox, Privacy = PrivacyLevel.ApiKey, HelpText = "NotificationsPushcutSettingsApiKeyHelpText")] public string ApiKey { get; set; } - [FieldDefinition(2, Label = "Time sensitive", Type = FieldType.Checkbox, HelpText = "Check to mark the notification as \"Time-Sensitive\"")] + [FieldDefinition(2, Label = "NotificationsPushcutSettingsTimeSensitive", Type = FieldType.Checkbox, HelpText = "NotificationsPushcutSettingsTimeSensitiveHelpText")] public bool TimeSensitive { get; set; } public NzbDroneValidationResult Validate() diff --git a/src/NzbDrone.Core/Notifications/Pushover/PushoverProxy.cs b/src/NzbDrone.Core/Notifications/Pushover/PushoverProxy.cs index 91e1f4444..758290c2f 100644 --- a/src/NzbDrone.Core/Notifications/Pushover/PushoverProxy.cs +++ b/src/NzbDrone.Core/Notifications/Pushover/PushoverProxy.cs @@ -1,8 +1,10 @@ using System; +using System.Collections.Generic; using FluentValidation.Results; using NLog; using NzbDrone.Common.Extensions; using NzbDrone.Common.Http; +using NzbDrone.Core.Localization; namespace NzbDrone.Core.Notifications.Pushover { @@ -17,11 +19,13 @@ namespace NzbDrone.Core.Notifications.Pushover private const string URL = "https://api.pushover.net/1/messages.json"; private readonly IHttpClient _httpClient; + private readonly ILocalizationService _localizationService; private readonly Logger _logger; - public PushoverProxy(IHttpClient httpClient, Logger logger) + public PushoverProxy(IHttpClient httpClient, ILocalizationService localizationService, Logger logger) { _httpClient = httpClient; + _localizationService = localizationService; _logger = logger; } @@ -64,7 +68,7 @@ namespace NzbDrone.Core.Notifications.Pushover catch (Exception ex) { _logger.Error(ex, "Unable to send test message"); - return new ValidationFailure("ApiKey", "Unable to send test message"); + return new ValidationFailure("ApiKey", _localizationService.GetLocalizedString("NotificationsValidationUnableToSendTestMessage", new Dictionary { { "exceptionMessage", ex.Message } })); } return null; diff --git a/src/NzbDrone.Core/Notifications/Pushover/PushoverSettings.cs b/src/NzbDrone.Core/Notifications/Pushover/PushoverSettings.cs index d84f4873c..7b6c78953 100644 --- a/src/NzbDrone.Core/Notifications/Pushover/PushoverSettings.cs +++ b/src/NzbDrone.Core/Notifications/Pushover/PushoverSettings.cs @@ -28,25 +28,25 @@ namespace NzbDrone.Core.Notifications.Pushover } // TODO: Get Pushover to change our app name (or create a new app) when we have a new logo - [FieldDefinition(0, Label = "API Key", Privacy = PrivacyLevel.ApiKey, HelpLink = "https://pushover.net/apps/clone/sonarr")] + [FieldDefinition(0, Label = "ApiKey", Privacy = PrivacyLevel.ApiKey, HelpLink = "https://pushover.net/apps/clone/sonarr")] public string ApiKey { get; set; } - [FieldDefinition(1, Label = "User Key", Privacy = PrivacyLevel.UserName, HelpLink = "https://pushover.net/")] + [FieldDefinition(1, Label = "NotificationsPushoverSettingsUserKey", Privacy = PrivacyLevel.UserName, HelpLink = "https://pushover.net/")] public string UserKey { get; set; } - [FieldDefinition(2, Label = "Devices", HelpText = "List of device names (leave blank to send to all devices)", Type = FieldType.Tag)] + [FieldDefinition(2, Label = "NotificationsPushoverSettingsDevices", HelpText = "NotificationsPushoverSettingsDevicesHelpText", Type = FieldType.Tag)] public IEnumerable Devices { get; set; } [FieldDefinition(3, Label = "Priority", Type = FieldType.Select, SelectOptions = typeof(PushoverPriority))] public int Priority { get; set; } - [FieldDefinition(4, Label = "Retry", Type = FieldType.Textbox, HelpText = "Interval to retry Emergency alerts, minimum 30 seconds")] + [FieldDefinition(4, Label = "NotificationsPushoverSettingsRetry", Type = FieldType.Textbox, HelpText = "NotificationsPushoverSettingsRetryHelpText")] public int Retry { get; set; } - [FieldDefinition(5, Label = "Expire", Type = FieldType.Textbox, HelpText = "Maximum time to retry Emergency alerts, maximum 86400 seconds")] + [FieldDefinition(5, Label = "NotificationsPushoverSettingsExpire", Type = FieldType.Textbox, HelpText = "NotificationsPushoverSettingsExpireHelpText")] public int Expire { get; set; } - [FieldDefinition(6, Label = "Sound", Type = FieldType.Textbox, HelpText = "Notification sound, leave blank to use the default", HelpLink = "https://pushover.net/api#sounds")] + [FieldDefinition(6, Label = "NotificationsPushoverSettingsSound", Type = FieldType.Textbox, HelpText = "NotificationsPushoverSettingsSoundHelpText", HelpLink = "https://pushover.net/api#sounds")] public string Sound { get; set; } public bool IsValid => !string.IsNullOrWhiteSpace(UserKey) && Priority >= -1 && Priority <= 2; diff --git a/src/NzbDrone.Core/Notifications/SendGrid/SendGrid.cs b/src/NzbDrone.Core/Notifications/SendGrid/SendGrid.cs index 5e707c33a..d05672d24 100644 --- a/src/NzbDrone.Core/Notifications/SendGrid/SendGrid.cs +++ b/src/NzbDrone.Core/Notifications/SendGrid/SendGrid.cs @@ -2,17 +2,20 @@ using System; using System.Collections.Generic; using FluentValidation.Results; using NLog; +using NzbDrone.Core.Localization; namespace NzbDrone.Core.Notifications.SendGrid { public class SendGrid : NotificationBase { private readonly ISendGridProxy _proxy; + private readonly ILocalizationService _localizationService; private readonly Logger _logger; - public SendGrid(ISendGridProxy proxy, Logger logger) + public SendGrid(ISendGridProxy proxy, ILocalizationService localizationService, Logger logger) { _proxy = proxy; + _localizationService = localizationService; _logger = logger; } @@ -78,7 +81,7 @@ namespace NzbDrone.Core.Notifications.SendGrid catch (Exception ex) { _logger.Error(ex, "Unable to send test message"); - failures.Add(new ValidationFailure("", "Unable to send test message")); + failures.Add(new ValidationFailure("", _localizationService.GetLocalizedString("NotificationsValidationUnableToSendTestMessage", new Dictionary { { "exceptionMessage", ex.Message } }))); } return new ValidationResult(failures); diff --git a/src/NzbDrone.Core/Notifications/SendGrid/SendGridSettings.cs b/src/NzbDrone.Core/Notifications/SendGrid/SendGridSettings.cs index cfd65987c..0add1e793 100644 --- a/src/NzbDrone.Core/Notifications/SendGrid/SendGridSettings.cs +++ b/src/NzbDrone.Core/Notifications/SendGrid/SendGridSettings.cs @@ -30,13 +30,13 @@ namespace NzbDrone.Core.Notifications.SendGrid public string BaseUrl { get; set; } - [FieldDefinition(1, Label = "API Key", HelpText = "The API Key generated by SendGrid", HelpLink = "https://sendgrid.com/docs/ui/account-and-settings/api-keys/#creating-an-api-key")] + [FieldDefinition(1, Label = "ApiKey", HelpText = "NotificationsSendGridSettingsApiKeyHelpText", HelpLink = "https://sendgrid.com/docs/ui/account-and-settings/api-keys/#creating-an-api-key")] public string ApiKey { get; set; } - [FieldDefinition(2, Label = "From Address")] + [FieldDefinition(2, Label = "NotificationsEmailSettingsFromAddress")] public string From { get; set; } - [FieldDefinition(3, Label = "Recipient Address(es)", Type = FieldType.Tag)] + [FieldDefinition(3, Label = "NotificationsEmailSettingsRecipientAddress", Type = FieldType.Tag)] public IEnumerable Recipients { get; set; } public NzbDroneValidationResult Validate() diff --git a/src/NzbDrone.Core/Notifications/Signal/SignalProxy.cs b/src/NzbDrone.Core/Notifications/Signal/SignalProxy.cs index e41de7a32..ae5d328ef 100644 --- a/src/NzbDrone.Core/Notifications/Signal/SignalProxy.cs +++ b/src/NzbDrone.Core/Notifications/Signal/SignalProxy.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Net; using System.Text; using FluentValidation.Results; @@ -6,6 +7,7 @@ using NLog; using NzbDrone.Common.Extensions; using NzbDrone.Common.Http; using NzbDrone.Common.Serializer; +using NzbDrone.Core.Localization; namespace NzbDrone.Core.Notifications.Signal { @@ -18,11 +20,13 @@ namespace NzbDrone.Core.Notifications.Signal public class SignalProxy : ISignalProxy { private readonly IHttpClient _httpClient; + private readonly ILocalizationService _localizationService; private readonly Logger _logger; - public SignalProxy(IHttpClient httpClient, Logger logger) + public SignalProxy(IHttpClient httpClient, ILocalizationService localizationService, Logger logger) { _httpClient = httpClient; + _localizationService = localizationService; _logger = logger; } @@ -71,7 +75,7 @@ namespace NzbDrone.Core.Notifications.Signal catch (WebException ex) { _logger.Error(ex, "Unable to send test message: {0}", ex.Message); - return new ValidationFailure("Host", $"Unable to send test message: {ex.Message}"); + return new ValidationFailure("Host", _localizationService.GetLocalizedString("NotificationsValidationUnableToSendTestMessage", new Dictionary { { "exceptionMessage", ex.Message } })); } catch (HttpException ex) { @@ -81,7 +85,7 @@ namespace NzbDrone.Core.Notifications.Signal { if (ex.Response.Content.ContainsIgnoreCase("400 The plain HTTP request was sent to HTTPS port")) { - return new ValidationFailure("UseSsl", "SSL seems to be required"); + return new ValidationFailure("UseSsl", _localizationService.GetLocalizedString("NotificationsSignalValidationSslRequired")); } var error = Json.Deserialize(ex.Response.Content); @@ -97,20 +101,20 @@ namespace NzbDrone.Core.Notifications.Signal property = "SenderNumber"; } - return new ValidationFailure(property, $"Unable to send test message: {error.Error}"); + return new ValidationFailure(property, _localizationService.GetLocalizedString("NotificationsValidationUnableToSendTestMessage", new Dictionary { { "exceptionMessage", error.Error } })); } if (ex.Response.StatusCode == HttpStatusCode.Unauthorized) { - return new ValidationFailure("AuthUsername", "Login/Password invalid"); + return new ValidationFailure("AuthUsername", _localizationService.GetLocalizedString("NotificationsValidationInvalidUsernamePassword")); } - return new ValidationFailure("Host", $"Unable to send test message: {ex.Message}"); + return new ValidationFailure("Host", _localizationService.GetLocalizedString("NotificationsValidationUnableToSendTestMessage", new Dictionary { { "exceptionMessage", ex.Message } })); } catch (Exception ex) { _logger.Error(ex, "Unable to send test message: {0}", ex.Message); - return new ValidationFailure("Host", $"Unable to send test message: {ex.Message}"); + return new ValidationFailure("Host", _localizationService.GetLocalizedString("NotificationsValidationUnableToSendTestMessage", new Dictionary { { "exceptionMessage", ex.Message } })); } return null; diff --git a/src/NzbDrone.Core/Notifications/Signal/SignalSettings.cs b/src/NzbDrone.Core/Notifications/Signal/SignalSettings.cs index 8906a45e3..500215730 100644 --- a/src/NzbDrone.Core/Notifications/Signal/SignalSettings.cs +++ b/src/NzbDrone.Core/Notifications/Signal/SignalSettings.cs @@ -20,25 +20,26 @@ namespace NzbDrone.Core.Notifications.Signal { private static readonly SignalSettingsValidator Validator = new (); - [FieldDefinition(0, Label = "Host", Type = FieldType.Textbox, HelpText = "localhost")] + [FieldDefinition(0, Label = "Host", Type = FieldType.Textbox, Placeholder = "localhost")] public string Host { get; set; } - [FieldDefinition(1, Label = "Port", Type = FieldType.Textbox, HelpText = "8080")] + [FieldDefinition(1, Label = "Port", Type = FieldType.Textbox, Placeholder = "8080")] public int Port { get; set; } - [FieldDefinition(2, Label = "Use SSL", Type = FieldType.Checkbox, HelpText = "Use a secure connection.")] + [FieldDefinition(2, Label = "UseSsl", Type = FieldType.Checkbox, HelpText = "NotificationsSettingsUseSslHelpText")] + [FieldToken(TokenField.HelpText, "UseSsl", "serviceName", "Signal")] public bool UseSsl { get; set; } - [FieldDefinition(3, Label = "Sender Number", Privacy = PrivacyLevel.ApiKey, HelpText = "Phone number of the sender register in signal-api")] + [FieldDefinition(3, Label = "NotificationsSignalSettingsSenderNumber", Privacy = PrivacyLevel.ApiKey, HelpText = "NotificationsSignalSettingsSenderNumberHelpText")] public string SenderNumber { get; set; } - [FieldDefinition(4, Label = "Group ID / PhoneNumber", HelpText = "GroupID / PhoneNumber of the receiver")] + [FieldDefinition(4, Label = "NotificationsSignalSettingsGroupIdPhoneNumber", HelpText = "NotificationsSignalSettingsGroupIdPhoneNumberHelpText")] public string ReceiverId { get; set; } - [FieldDefinition(5, Label = "Login", Privacy = PrivacyLevel.UserName, HelpText = "Username used to authenticate requests toward signal-api")] + [FieldDefinition(5, Label = "Username", Privacy = PrivacyLevel.UserName, HelpText = "NotificationsSignalSettingsUsernameHelpText")] public string AuthUsername { get; set; } - [FieldDefinition(6, Label = "Password", Type = FieldType.Password, Privacy = PrivacyLevel.Password, HelpText = "Password used to authenticate requests toward signal-api")] + [FieldDefinition(6, Label = "Password", Type = FieldType.Password, Privacy = PrivacyLevel.Password, HelpText = "NotificationsSignalSettingsPasswordHelpText")] public string AuthPassword { get; set; } public NzbDroneValidationResult Validate() diff --git a/src/NzbDrone.Core/Notifications/Simplepush/SimplepushProxy.cs b/src/NzbDrone.Core/Notifications/Simplepush/SimplepushProxy.cs index 457cafb9e..22022f462 100644 --- a/src/NzbDrone.Core/Notifications/Simplepush/SimplepushProxy.cs +++ b/src/NzbDrone.Core/Notifications/Simplepush/SimplepushProxy.cs @@ -1,7 +1,9 @@ using System; +using System.Collections.Generic; using FluentValidation.Results; using NLog; using NzbDrone.Common.Http; +using NzbDrone.Core.Localization; namespace NzbDrone.Core.Notifications.Simplepush { @@ -15,11 +17,13 @@ namespace NzbDrone.Core.Notifications.Simplepush { private const string URL = "https://api.simplepush.io/send"; private readonly IHttpClient _httpClient; + private readonly ILocalizationService _localizationService; private readonly Logger _logger; - public SimplepushProxy(IHttpClient httpClient, Logger logger) + public SimplepushProxy(IHttpClient httpClient, ILocalizationService localizationService, Logger logger) { _httpClient = httpClient; + _localizationService = localizationService; _logger = logger; } @@ -49,7 +53,7 @@ namespace NzbDrone.Core.Notifications.Simplepush catch (Exception ex) { _logger.Error(ex, "Unable to send test message"); - return new ValidationFailure("ApiKey", "Unable to send test message"); + return new ValidationFailure("ApiKey", _localizationService.GetLocalizedString("NotificationsValidationUnableToSendTestMessage", new Dictionary { { "exceptionMessage", ex.Message } })); } return null; diff --git a/src/NzbDrone.Core/Notifications/Simplepush/SimplepushSettings.cs b/src/NzbDrone.Core/Notifications/Simplepush/SimplepushSettings.cs index af8b211ef..2e285aeed 100644 --- a/src/NzbDrone.Core/Notifications/Simplepush/SimplepushSettings.cs +++ b/src/NzbDrone.Core/Notifications/Simplepush/SimplepushSettings.cs @@ -17,10 +17,10 @@ namespace NzbDrone.Core.Notifications.Simplepush { private static readonly SimplepushSettingsValidator Validator = new SimplepushSettingsValidator(); - [FieldDefinition(0, Label = "Key", Privacy = PrivacyLevel.ApiKey, HelpLink = "https://simplepush.io/features")] + [FieldDefinition(0, Label = "NotificationsSimplepushSettingsKey", Privacy = PrivacyLevel.ApiKey, HelpLink = "https://simplepush.io/features")] public string Key { get; set; } - [FieldDefinition(1, Label = "Event", HelpText = "Customize the behavior of push notifications", HelpLink = "https://simplepush.io/features")] + [FieldDefinition(1, Label = "NotificationsSimplepushSettingsEvent", HelpText = "NotificationsSimplepushSettingsEventHelpText", HelpLink = "https://simplepush.io/features")] public string Event { get; set; } public bool IsValid => !string.IsNullOrWhiteSpace(Key); diff --git a/src/NzbDrone.Core/Notifications/Slack/Slack.cs b/src/NzbDrone.Core/Notifications/Slack/Slack.cs index e341f924e..2fe412f2b 100644 --- a/src/NzbDrone.Core/Notifications/Slack/Slack.cs +++ b/src/NzbDrone.Core/Notifications/Slack/Slack.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using FluentValidation.Results; using NzbDrone.Common.Extensions; +using NzbDrone.Core.Localization; using NzbDrone.Core.MediaFiles; using NzbDrone.Core.Notifications.Slack.Payloads; using NzbDrone.Core.Tv; @@ -13,10 +14,12 @@ namespace NzbDrone.Core.Notifications.Slack public class Slack : NotificationBase { private readonly ISlackProxy _proxy; + private readonly ILocalizationService _localizationService; - public Slack(ISlackProxy proxy) + public Slack(ISlackProxy proxy, ILocalizationService localizationService) { _proxy = proxy; + _localizationService = localizationService; } public override string Name => "Slack"; @@ -205,7 +208,7 @@ namespace NzbDrone.Core.Notifications.Slack } catch (SlackExeption ex) { - return new NzbDroneValidationFailure("Unable to post", ex.Message); + return new NzbDroneValidationFailure("Unable to post", _localizationService.GetLocalizedString("NotificationsValidationUnableToSendTestMessage", new Dictionary { { "exceptionMessage", ex.Message } })); } return null; diff --git a/src/NzbDrone.Core/Notifications/Slack/SlackSettings.cs b/src/NzbDrone.Core/Notifications/Slack/SlackSettings.cs index 399a1ae46..bd7f10c33 100644 --- a/src/NzbDrone.Core/Notifications/Slack/SlackSettings.cs +++ b/src/NzbDrone.Core/Notifications/Slack/SlackSettings.cs @@ -18,16 +18,16 @@ namespace NzbDrone.Core.Notifications.Slack { private static readonly SlackSettingsValidator Validator = new SlackSettingsValidator(); - [FieldDefinition(0, Label = "Webhook URL", HelpText = "Slack channel webhook url", Type = FieldType.Url, HelpLink = "https://my.slack.com/services/new/incoming-webhook/")] + [FieldDefinition(0, Label = "NotificationsSettingsWebhookUrl", HelpText = "NotificationsSlackSettingsWebhookUrlHelpText", Type = FieldType.Url, HelpLink = "https://my.slack.com/services/new/incoming-webhook/")] public string WebHookUrl { get; set; } - [FieldDefinition(1, Label = "Username", Privacy = PrivacyLevel.UserName, HelpText = "Choose the username that this integration will post as", Type = FieldType.Textbox)] + [FieldDefinition(1, Label = "Username", Privacy = PrivacyLevel.UserName, HelpText = "NotificationsSlackSettingsUsernameHelpText", Type = FieldType.Textbox)] public string Username { get; set; } - [FieldDefinition(2, Label = "Icon", HelpText = "Change the icon that is used for messages from this integration (Emoji or URL)", Type = FieldType.Textbox, HelpLink = "http://www.emoji-cheat-sheet.com/")] + [FieldDefinition(2, Label = "NotificationsSlackSettingsIcon", HelpText = "NotificationsSlackSettingsIconHelpText", Type = FieldType.Textbox, HelpLink = "http://www.emoji-cheat-sheet.com/")] public string Icon { get; set; } - [FieldDefinition(3, Label = "Channel", HelpText = "Overrides the default channel for the incoming webhook (#other-channel)", Type = FieldType.Textbox)] + [FieldDefinition(3, Label = "NotificationsSlackSettingsChannel", HelpText = "NotificationsSlackSettingsChannelHelpText", Type = FieldType.Textbox)] public string Channel { get; set; } public NzbDroneValidationResult Validate() diff --git a/src/NzbDrone.Core/Notifications/Synology/SynologyIndexer.cs b/src/NzbDrone.Core/Notifications/Synology/SynologyIndexer.cs index b14a94c5f..23e576b47 100644 --- a/src/NzbDrone.Core/Notifications/Synology/SynologyIndexer.cs +++ b/src/NzbDrone.Core/Notifications/Synology/SynologyIndexer.cs @@ -3,6 +3,7 @@ using System.IO; using FluentValidation.Results; using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.Extensions; +using NzbDrone.Core.Localization; using NzbDrone.Core.MediaFiles; using NzbDrone.Core.Tv; @@ -11,10 +12,12 @@ namespace NzbDrone.Core.Notifications.Synology public class SynologyIndexer : NotificationBase { private readonly ISynologyIndexerProxy _indexerProxy; + private readonly ILocalizationService _localizationService; - public SynologyIndexer(ISynologyIndexerProxy indexerProxy) + public SynologyIndexer(ISynologyIndexerProxy indexerProxy, ILocalizationService localizationService) { _indexerProxy = indexerProxy; + _localizationService = localizationService; } public override string Link => "https://www.synology.com"; @@ -88,12 +91,12 @@ namespace NzbDrone.Core.Notifications.Synology { if (!OsInfo.IsLinux) { - return new ValidationFailure(null, "Must be a Synology"); + return new ValidationFailure(string.Empty, _localizationService.GetLocalizedString("NotificationsSynologyValidationInvalidOs")); } if (!_indexerProxy.Test()) { - return new ValidationFailure(null, "Not a Synology or synoindex not available"); + return new ValidationFailure(string.Empty, _localizationService.GetLocalizedString("NotificationsSynologyValidationTestFailed")); } return null; diff --git a/src/NzbDrone.Core/Notifications/Synology/SynologyIndexerSettings.cs b/src/NzbDrone.Core/Notifications/Synology/SynologyIndexerSettings.cs index 58b4322e8..8bad70a04 100644 --- a/src/NzbDrone.Core/Notifications/Synology/SynologyIndexerSettings.cs +++ b/src/NzbDrone.Core/Notifications/Synology/SynologyIndexerSettings.cs @@ -18,7 +18,7 @@ namespace NzbDrone.Core.Notifications.Synology UpdateLibrary = true; } - [FieldDefinition(0, Label = "Update Library", Type = FieldType.Checkbox, HelpText = "Call synoindex on localhost to update a library file")] + [FieldDefinition(0, Label = "NotificationsSettingsUpdateLibrary", Type = FieldType.Checkbox, HelpText = "NotificationsSynologySettingsUpdateLibraryHelpText")] public bool UpdateLibrary { get; set; } public NzbDroneValidationResult Validate() diff --git a/src/NzbDrone.Core/Notifications/Telegram/TelegramProxy.cs b/src/NzbDrone.Core/Notifications/Telegram/TelegramProxy.cs index f4ce00f74..fbeb625df 100644 --- a/src/NzbDrone.Core/Notifications/Telegram/TelegramProxy.cs +++ b/src/NzbDrone.Core/Notifications/Telegram/TelegramProxy.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Net; using System.Web; using FluentValidation.Results; @@ -6,6 +7,7 @@ using NLog; using NzbDrone.Common.Extensions; using NzbDrone.Common.Http; using NzbDrone.Common.Serializer; +using NzbDrone.Core.Localization; namespace NzbDrone.Core.Notifications.Telegram { @@ -20,11 +22,13 @@ namespace NzbDrone.Core.Notifications.Telegram private const string URL = "https://api.telegram.org"; private readonly IHttpClient _httpClient; + private readonly ILocalizationService _localizationService; private readonly Logger _logger; - public TelegramProxy(IHttpClient httpClient, Logger logger) + public TelegramProxy(IHttpClient httpClient, ILocalizationService localizationService, Logger logger) { _httpClient = httpClient; + _localizationService = localizationService; _logger = logger; } @@ -61,7 +65,7 @@ namespace NzbDrone.Core.Notifications.Telegram if (ex is WebException webException) { - return new ValidationFailure("Connection", $"{webException.Status.ToString()}: {webException.Message}"); + return new ValidationFailure("Connection", _localizationService.GetLocalizedString("NotificationsValidationUnableToConnectToApi", new Dictionary { { "service", "Telegram" }, { "responseCode", webException.Status.ToString() }, { "exceptionMessage", webException.Message } })); } else if (ex is Common.Http.HttpException restException && restException.Response.StatusCode == HttpStatusCode.BadRequest) { @@ -77,10 +81,10 @@ namespace NzbDrone.Core.Notifications.Telegram property = "TopicId"; } - return new ValidationFailure(property, error.Description); + return new ValidationFailure(property, _localizationService.GetLocalizedString("NotificationsValidationUnableToConnect", new Dictionary { { "exceptionMessage", error.Description } })); } - return new ValidationFailure("BotToken", "Unable to send test message"); + return new ValidationFailure("BotToken", _localizationService.GetLocalizedString("NotificationsValidationUnableToConnect", new Dictionary { { "exceptionMessage", ex.Message } })); } return null; diff --git a/src/NzbDrone.Core/Notifications/Telegram/TelegramSettings.cs b/src/NzbDrone.Core/Notifications/Telegram/TelegramSettings.cs index 774fd4ca0..ede7b3ad3 100644 --- a/src/NzbDrone.Core/Notifications/Telegram/TelegramSettings.cs +++ b/src/NzbDrone.Core/Notifications/Telegram/TelegramSettings.cs @@ -20,16 +20,16 @@ namespace NzbDrone.Core.Notifications.Telegram { private static readonly TelegramSettingsValidator Validator = new TelegramSettingsValidator(); - [FieldDefinition(0, Label = "Bot Token", Privacy = PrivacyLevel.ApiKey, HelpLink = "https://core.telegram.org/bots")] + [FieldDefinition(0, Label = "NotificationsTelegramSettingsBotToken", Privacy = PrivacyLevel.ApiKey, HelpLink = "https://core.telegram.org/bots")] public string BotToken { get; set; } - [FieldDefinition(1, Label = "Chat ID", HelpLink = "http://stackoverflow.com/a/37396871/882971", HelpText = "You must start a conversation with the bot or add it to your group to receive messages")] + [FieldDefinition(1, Label = "NotificationsTelegramSettingsChatId", HelpLink = "http://stackoverflow.com/a/37396871/882971", HelpText = "NotificationsTelegramSettingsChatIdHelpText")] public string ChatId { get; set; } - [FieldDefinition(2, Label = "Topic ID", HelpLink = "https://stackoverflow.com/a/75178418", HelpText = "Specify a Topic ID to send notifications to that topic. Leave blank to use the general topic (Supergroups only)")] + [FieldDefinition(2, Label = "NotificationsTelegramSettingsTopicId", HelpLink = "https://stackoverflow.com/a/75178418", HelpText = "NotificationsTelegramSettingsTopicIdHelpText")] public int? TopicId { get; set; } - [FieldDefinition(3, Label = "Send Silently", Type = FieldType.Checkbox, HelpText = "Sends the message silently. Users will receive a notification with no sound")] + [FieldDefinition(3, Label = "NotificationsTelegramSettingsSendSilently", Type = FieldType.Checkbox, HelpText = "NotificationsTelegramSettingsSendSilentlyHelpText")] public bool SendSilently { get; set; } public NzbDroneValidationResult Validate() diff --git a/src/NzbDrone.Core/Notifications/Trakt/Trakt.cs b/src/NzbDrone.Core/Notifications/Trakt/Trakt.cs index c30631c74..9a4362e2f 100644 --- a/src/NzbDrone.Core/Notifications/Trakt/Trakt.cs +++ b/src/NzbDrone.Core/Notifications/Trakt/Trakt.cs @@ -5,6 +5,7 @@ using FluentValidation.Results; using NLog; using NzbDrone.Common.Extensions; using NzbDrone.Common.Http; +using NzbDrone.Core.Localization; using NzbDrone.Core.MediaFiles; using NzbDrone.Core.MediaFiles.MediaInfo; using NzbDrone.Core.Notifications.Trakt.Resource; @@ -18,12 +19,14 @@ namespace NzbDrone.Core.Notifications.Trakt { private readonly ITraktProxy _proxy; private readonly INotificationRepository _notificationRepository; + private readonly ILocalizationService _localizationService; private readonly Logger _logger; - public Trakt(ITraktProxy proxy, INotificationRepository notificationRepository, Logger logger) + public Trakt(ITraktProxy proxy, INotificationRepository notificationRepository, ILocalizationService localizationService, Logger logger) { _proxy = proxy; _notificationRepository = notificationRepository; + _localizationService = localizationService; _logger = logger; } @@ -70,20 +73,20 @@ namespace NzbDrone.Core.Notifications.Trakt { _logger.Error(ex, "Access Token is invalid: " + ex.Message); - failures.Add(new ValidationFailure("Token", "Access Token is invalid")); + failures.Add(new ValidationFailure("Token", _localizationService.GetLocalizedString("NotificationsValidationInvalidAccessToken"))); } else { _logger.Error(ex, "Unable to send test message: " + ex.Message); - failures.Add(new ValidationFailure("Token", "Unable to send test message")); + failures.Add(new ValidationFailure("Token", _localizationService.GetLocalizedString("NotificationsValidationUnableToSendTestMessage", new Dictionary { { "exceptionMessage", ex.Message } }))); } } catch (Exception ex) { _logger.Error(ex, "Unable to send test message: " + ex.Message); - failures.Add(new ValidationFailure("", "Unable to send test message")); + failures.Add(new ValidationFailure("", _localizationService.GetLocalizedString("NotificationsValidationUnableToSendTestMessage", new Dictionary { { "exceptionMessage", ex.Message } }))); } return new ValidationResult(failures); diff --git a/src/NzbDrone.Core/Notifications/Trakt/TraktSettings.cs b/src/NzbDrone.Core/Notifications/Trakt/TraktSettings.cs index 99dfaf9fc..0be5677da 100644 --- a/src/NzbDrone.Core/Notifications/Trakt/TraktSettings.cs +++ b/src/NzbDrone.Core/Notifications/Trakt/TraktSettings.cs @@ -25,19 +25,19 @@ namespace NzbDrone.Core.Notifications.Trakt SignIn = "startOAuth"; } - [FieldDefinition(0, Label = "Access Token", Type = FieldType.Textbox, Hidden = HiddenType.Hidden)] + [FieldDefinition(0, Label = "NotificationsTraktSettingsAccessToken", Type = FieldType.Textbox, Hidden = HiddenType.Hidden)] public string AccessToken { get; set; } - [FieldDefinition(1, Label = "Refresh Token", Type = FieldType.Textbox, Hidden = HiddenType.Hidden)] + [FieldDefinition(1, Label = "NotificationsTraktSettingsRefreshToken", Type = FieldType.Textbox, Hidden = HiddenType.Hidden)] public string RefreshToken { get; set; } - [FieldDefinition(2, Label = "Expires", Type = FieldType.Textbox, Hidden = HiddenType.Hidden)] + [FieldDefinition(2, Label = "NotificationsTraktSettingsExpires", Type = FieldType.Textbox, Hidden = HiddenType.Hidden)] public DateTime Expires { get; set; } - [FieldDefinition(3, Label = "Auth User", Type = FieldType.Textbox, Hidden = HiddenType.Hidden)] + [FieldDefinition(3, Label = "NotificationsTraktSettingsAuthUser", Type = FieldType.Textbox, Hidden = HiddenType.Hidden)] public string AuthUser { get; set; } - [FieldDefinition(4, Label = "Authenticate with Trakt", Type = FieldType.OAuth)] + [FieldDefinition(4, Label = "NotificationsTraktSettingsAuthenticateWithTrakt", Type = FieldType.OAuth)] public string SignIn { get; set; } public NzbDroneValidationResult Validate() diff --git a/src/NzbDrone.Core/Notifications/Twitter/TwitterService.cs b/src/NzbDrone.Core/Notifications/Twitter/TwitterService.cs index a04b384b6..d8f282f54 100644 --- a/src/NzbDrone.Core/Notifications/Twitter/TwitterService.cs +++ b/src/NzbDrone.Core/Notifications/Twitter/TwitterService.cs @@ -1,9 +1,11 @@ using System; +using System.Collections.Generic; using System.IO; using System.Net; using FluentValidation.Results; using NLog; using NzbDrone.Common.Extensions; +using NzbDrone.Core.Localization; namespace NzbDrone.Core.Notifications.Twitter { @@ -18,11 +20,13 @@ namespace NzbDrone.Core.Notifications.Twitter public class TwitterService : ITwitterService { private readonly ITwitterProxy _twitterProxy; + private readonly ILocalizationService _localizationService; private readonly Logger _logger; - public TwitterService(ITwitterProxy twitterProxy, Logger logger) + public TwitterService(ITwitterProxy twitterProxy, ILocalizationService localizationService, Logger logger) { _twitterProxy = twitterProxy; + _localizationService = localizationService; _logger = logger; } @@ -96,7 +100,7 @@ namespace NzbDrone.Core.Notifications.Twitter catch (Exception ex) { _logger.Error(ex, "Unable to send test message"); - return new ValidationFailure("Host", "Unable to send test message"); + return new ValidationFailure("Host", _localizationService.GetLocalizedString("NotificationsValidationUnableToSendTestMessage", new Dictionary { { "exceptionMessage", ex.Message } })); } return null; diff --git a/src/NzbDrone.Core/Notifications/Twitter/TwitterSettings.cs b/src/NzbDrone.Core/Notifications/Twitter/TwitterSettings.cs index 50c3744ab..448c0976e 100644 --- a/src/NzbDrone.Core/Notifications/Twitter/TwitterSettings.cs +++ b/src/NzbDrone.Core/Notifications/Twitter/TwitterSettings.cs @@ -38,25 +38,25 @@ namespace NzbDrone.Core.Notifications.Twitter AuthorizeNotification = "startOAuth"; } - [FieldDefinition(0, Label = "Consumer Key", Privacy = PrivacyLevel.ApiKey, HelpText = "Consumer key from a Twitter application", HelpLink = "https://wiki.servarr.com/useful-tools#twitter-connect")] + [FieldDefinition(0, Label = "NotificationsTwitterSettingsConsumerKey", Privacy = PrivacyLevel.ApiKey, HelpText = "NotificationsTwitterSettingsConsumerKeyHelpText", HelpLink = "https://wiki.servarr.com/useful-tools#twitter-connect")] public string ConsumerKey { get; set; } - [FieldDefinition(1, Label = "Consumer Secret", Privacy = PrivacyLevel.ApiKey, HelpText = "Consumer secret from a Twitter application", HelpLink = "https://wiki.servarr.com/useful-tools#twitter-connect")] + [FieldDefinition(1, Label = "NotificationsTwitterSettingsConsumerSecret", Privacy = PrivacyLevel.ApiKey, HelpText = "NotificationsTwitterSettingsConsumerSecretHelpText", HelpLink = "https://wiki.servarr.com/useful-tools#twitter-connect")] public string ConsumerSecret { get; set; } - [FieldDefinition(2, Label = "Access Token", Privacy = PrivacyLevel.ApiKey, Advanced = true)] + [FieldDefinition(2, Label = "NotificationsTwitterSettingsAccessToken", Privacy = PrivacyLevel.ApiKey, Advanced = true)] public string AccessToken { get; set; } - [FieldDefinition(3, Label = "Access Token Secret", Privacy = PrivacyLevel.ApiKey, Advanced = true)] + [FieldDefinition(3, Label = "NotificationsTwitterSettingsAccessTokenSecret", Privacy = PrivacyLevel.ApiKey, Advanced = true)] public string AccessTokenSecret { get; set; } - [FieldDefinition(4, Label = "Mention", HelpText = "Mention this user in sent tweets")] + [FieldDefinition(4, Label = "NotificationsTwitterSettingsMention", HelpText = "NotificationsTwitterSettingsMentionHelpText")] public string Mention { get; set; } - [FieldDefinition(5, Label = "Direct Message", Type = FieldType.Checkbox, HelpText = "Send a direct message instead of a public message")] + [FieldDefinition(5, Label = "NotificationsTwitterSettingsDirectMessage", Type = FieldType.Checkbox, HelpText = "NotificationsTwitterSettingsDirectMessageHelpText")] public bool DirectMessage { get; set; } - [FieldDefinition(6, Label = "Connect to Twitter", Type = FieldType.OAuth)] + [FieldDefinition(6, Label = "NotificationsTwitterSettingsConnectToTwitter", Type = FieldType.OAuth)] public string AuthorizeNotification { get; set; } public NzbDroneValidationResult Validate() diff --git a/src/NzbDrone.Core/Notifications/Webhook/Webhook.cs b/src/NzbDrone.Core/Notifications/Webhook/Webhook.cs index bfd7b0399..b7cf6379d 100644 --- a/src/NzbDrone.Core/Notifications/Webhook/Webhook.cs +++ b/src/NzbDrone.Core/Notifications/Webhook/Webhook.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using FluentValidation.Results; using NzbDrone.Common.Extensions; using NzbDrone.Core.Configuration; +using NzbDrone.Core.Localization; using NzbDrone.Core.MediaFiles; using NzbDrone.Core.Tv; using NzbDrone.Core.Validation; @@ -12,8 +13,8 @@ namespace NzbDrone.Core.Notifications.Webhook { private readonly IWebhookProxy _proxy; - public Webhook(IWebhookProxy proxy, IConfigFileProvider configFileProvider, IConfigService configService) - : base(configFileProvider, configService) + public Webhook(IWebhookProxy proxy, IConfigFileProvider configFileProvider, IConfigService configService, ILocalizationService localizationService) + : base(configFileProvider, configService, localizationService) { _proxy = proxy; } @@ -89,7 +90,7 @@ namespace NzbDrone.Core.Notifications.Webhook } catch (WebhookException ex) { - return new NzbDroneValidationFailure("Url", ex.Message); + return new NzbDroneValidationFailure("Url", _localizationService.GetLocalizedString("NotificationsValidationUnableToSendTestMessage", new Dictionary { { "exceptionMessage", ex.Message } })); } return null; diff --git a/src/NzbDrone.Core/Notifications/Webhook/WebhookBase.cs b/src/NzbDrone.Core/Notifications/Webhook/WebhookBase.cs index 90baedeb8..22375baa7 100644 --- a/src/NzbDrone.Core/Notifications/Webhook/WebhookBase.cs +++ b/src/NzbDrone.Core/Notifications/Webhook/WebhookBase.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using NzbDrone.Core.Configuration; +using NzbDrone.Core.Localization; using NzbDrone.Core.MediaFiles; using NzbDrone.Core.ThingiProvider; using NzbDrone.Core.Tv; @@ -13,11 +14,13 @@ namespace NzbDrone.Core.Notifications.Webhook { private readonly IConfigFileProvider _configFileProvider; private readonly IConfigService _configService; + protected readonly ILocalizationService _localizationService; - protected WebhookBase(IConfigFileProvider configFileProvider, IConfigService configService) + protected WebhookBase(IConfigFileProvider configFileProvider, IConfigService configService, ILocalizationService localizationService) { _configFileProvider = configFileProvider; _configService = configService; + _localizationService = localizationService; } protected WebhookGrabPayload BuildOnGrabPayload(GrabMessage message) diff --git a/src/NzbDrone.Core/Notifications/Webhook/WebhookSettings.cs b/src/NzbDrone.Core/Notifications/Webhook/WebhookSettings.cs index 128a95587..f244c7d88 100644 --- a/src/NzbDrone.Core/Notifications/Webhook/WebhookSettings.cs +++ b/src/NzbDrone.Core/Notifications/Webhook/WebhookSettings.cs @@ -23,10 +23,10 @@ namespace NzbDrone.Core.Notifications.Webhook Method = Convert.ToInt32(WebhookMethod.POST); } - [FieldDefinition(0, Label = "URL", Type = FieldType.Url)] + [FieldDefinition(0, Label = "NotificationsSettingsWebhookUrl", Type = FieldType.Url)] public string Url { get; set; } - [FieldDefinition(1, Label = "Method", Type = FieldType.Select, SelectOptions = typeof(WebhookMethod), HelpText = "Which HTTP method to use submit to the Webservice")] + [FieldDefinition(1, Label = "NotificationsSettingsWebhookMethod", Type = FieldType.Select, SelectOptions = typeof(WebhookMethod), HelpText = "NotificationsSettingsWebhookMethodHelpText")] public int Method { get; set; } [FieldDefinition(2, Label = "Username", Privacy = PrivacyLevel.UserName)] diff --git a/src/NzbDrone.Core/Notifications/Xbmc/XbmcService.cs b/src/NzbDrone.Core/Notifications/Xbmc/XbmcService.cs index 7b0b7ca97..a79ff7002 100644 --- a/src/NzbDrone.Core/Notifications/Xbmc/XbmcService.cs +++ b/src/NzbDrone.Core/Notifications/Xbmc/XbmcService.cs @@ -1,7 +1,9 @@ using System; +using System.Collections.Generic; using System.Linq; using FluentValidation.Results; using NLog; +using NzbDrone.Core.Localization; using NzbDrone.Core.Tv; namespace NzbDrone.Core.Notifications.Xbmc @@ -17,12 +19,13 @@ namespace NzbDrone.Core.Notifications.Xbmc public class XbmcService : IXbmcService { private readonly IXbmcJsonApiProxy _proxy; + private readonly ILocalizationService _localizationService; private readonly Logger _logger; - public XbmcService(IXbmcJsonApiProxy proxy, - Logger logger) + public XbmcService(IXbmcJsonApiProxy proxy, ILocalizationService localizationService, Logger logger) { _proxy = proxy; + _localizationService = localizationService; _logger = logger; } @@ -130,7 +133,7 @@ namespace NzbDrone.Core.Notifications.Xbmc catch (Exception ex) { _logger.Error(ex, "Unable to send test message"); - return new ValidationFailure("Host", "Unable to send test message"); + return new ValidationFailure("Host", _localizationService.GetLocalizedString("NotificationsValidationUnableToSendTestMessage", new Dictionary { { "exceptionMessage", ex.Message } })); } return null; diff --git a/src/NzbDrone.Core/Notifications/Xbmc/XbmcSettings.cs b/src/NzbDrone.Core/Notifications/Xbmc/XbmcSettings.cs index 9fd4010cc..94652a587 100644 --- a/src/NzbDrone.Core/Notifications/Xbmc/XbmcSettings.cs +++ b/src/NzbDrone.Core/Notifications/Xbmc/XbmcSettings.cs @@ -33,7 +33,8 @@ namespace NzbDrone.Core.Notifications.Xbmc [FieldDefinition(1, Label = "Port")] public int Port { get; set; } - [FieldDefinition(2, Label = "Use SSL", Type = FieldType.Checkbox, HelpText = "Connect to Kodi over HTTPS instead of HTTP")] + [FieldDefinition(2, Label = "UseSsl", Type = FieldType.Checkbox, HelpText = "NotificationsSettingsUseSslHelpText")] + [FieldToken(TokenField.HelpText, "UseSsl", "serviceName", "Kodi")] public bool UseSsl { get; set; } [FieldDefinition(3, Label = "Username", Privacy = PrivacyLevel.UserName)] @@ -43,19 +44,19 @@ namespace NzbDrone.Core.Notifications.Xbmc public string Password { get; set; } [DefaultValue(5)] - [FieldDefinition(5, Label = "Display Time", HelpText = "How long the notification will be displayed for (In seconds)")] + [FieldDefinition(5, Label = "NotificationsKodiSettingsDisplayTime", HelpText = "NotificationsKodiSettingsDisplayTimeHelpText")] public int DisplayTime { get; set; } - [FieldDefinition(6, Label = "GUI Notification", Type = FieldType.Checkbox)] + [FieldDefinition(6, Label = "NotificationsKodiSettingsGuiNotification", Type = FieldType.Checkbox)] public bool Notify { get; set; } - [FieldDefinition(7, Label = "Update Library", HelpText = "Update Library on Import & Rename?", Type = FieldType.Checkbox)] + [FieldDefinition(7, Label = "NotificationsSettingsUpdateLibrary", HelpText = "NotificationsKodiSettingsUpdateLibraryHelpText", Type = FieldType.Checkbox)] public bool UpdateLibrary { get; set; } - [FieldDefinition(8, Label = "Clean Library", HelpText = "Clean Library after update?", Type = FieldType.Checkbox)] + [FieldDefinition(8, Label = "NotificationsKodiSettingsCleanLibrary", HelpText = "NotificationsKodiSettingsCleanLibraryHelpText", Type = FieldType.Checkbox)] public bool CleanLibrary { get; set; } - [FieldDefinition(9, Label = "Always Update", HelpText = "Update Library even when a video is playing?", Type = FieldType.Checkbox)] + [FieldDefinition(9, Label = "NotificationsKodiSettingAlwaysUpdate", HelpText = "NotificationsKodiSettingAlwaysUpdateHelpText", Type = FieldType.Checkbox)] public bool AlwaysUpdate { get; set; } [JsonIgnore]